⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jump.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 5 页
字号:
		 multiple branches.  See if we can find all the uses of		 the label that TEMP branches to without hitting a CALL_INSN		 or a jump to somewhere else.  */	      rtx target = JUMP_LABEL (temp);	      int nuses = LABEL_NUSES (target);	      rtx p, q;	      /* Set P to the first jump insn that goes around "x = a;".  */	      for (p = temp; nuses && p; p = prev_nonnote_insn (p))		{		  if (GET_CODE (p) == JUMP_INSN)		    {		      if (condjump_p (p) && ! simplejump_p (p)			  && JUMP_LABEL (p) == target)			{			  nuses--;			  if (nuses == 0)			    break;			}		      else			break;		    }		  else if (GET_CODE (p) == CALL_INSN)		    break;		}#ifdef HAVE_cc0	      /* We cannot insert anything between a set of cc and its use		 so if P uses cc0, we must back up to the previous insn.  */	      q = prev_nonnote_insn (p);	      if (q && GET_RTX_CLASS (GET_CODE (q)) == 'i'		  && sets_cc0_p (PATTERN (q)))		p = q;#endif	      if (p)		p = PREV_INSN (p);	      /* If we found all the uses and there was no data conflict, we		 can move the assignment unless we can branch into the middle		 from somewhere.  */	      if (nuses == 0 && p		  && no_labels_between_p (p, insn)		  && ! reg_referenced_between_p (temp1, p, NEXT_INSN (temp3))		  && ! reg_set_between_p (temp1, p, temp3)		  && (GET_CODE (SET_SRC (temp4)) == CONST_INT		      || ! reg_set_between_p (SET_SRC (temp4), p, temp2)))		{		  emit_insn_after_with_line_notes (PATTERN (temp2), p, temp2);		  delete_insn (temp2);		  /* Set NEXT to an insn that we know won't go away.  */		  next = next_active_insn (insn);		  /* Delete the jump around the set.  Note that we must do		     this before we redirect the test jumps so that it won't		     delete the code immediately following the assignment		     we moved (which might be a jump).  */		  delete_insn (insn);		  /* We either have two consecutive labels or a jump to		     a jump, so adjust all the JUMP_INSNs to branch to where		     INSN branches to.  */		  for (p = NEXT_INSN (p); p != next; p = NEXT_INSN (p))		    if (GET_CODE (p) == JUMP_INSN)		      redirect_jump (p, target);		  changed = 1;		  continue;		}	    }#ifndef HAVE_cc0	  /* If we have if (...) x = exp;  and branches are expensive,	     EXP is a single insn, does not have any side effects, cannot	     trap, and is not too costly, convert this to	     t = exp; if (...) x = t;	     Don't do this when we have CC0 because it is unlikely to help	     and we'd need to worry about where to place the new insn and	     the potential for conflicts.  We also can't do this when we have	     notes on the insn for the same reason as above.	     We set:	     TEMP to the "x = exp;" insn.	     TEMP1 to the single set in the "x = exp; insn.	     TEMP2 to "x".  */	  if (! reload_completed	      && this_is_condjump && ! this_is_simplejump	      && BRANCH_COST >= 3	      && (temp = next_nonnote_insn (insn)) != 0	      && GET_CODE (temp) == INSN	      && REG_NOTES (temp) == 0	      && (reallabelprev == temp		  || ((temp2 = next_active_insn (temp)) != 0		      && simplejump_p (temp2)		      && JUMP_LABEL (temp2) == JUMP_LABEL (insn)))	      && (temp1 = single_set (temp)) != 0	      && (temp2 = SET_DEST (temp1), GET_CODE (temp2) == REG)	      && GET_MODE_CLASS (GET_MODE (temp2)) == MODE_INT#ifdef SMALL_REGISTER_CLASSES	      && REGNO (temp2) >= FIRST_PSEUDO_REGISTER#endif	      && GET_CODE (SET_SRC (temp1)) != REG	      && GET_CODE (SET_SRC (temp1)) != SUBREG	      && GET_CODE (SET_SRC (temp1)) != CONST_INT	      && ! side_effects_p (SET_SRC (temp1))	      && ! may_trap_p (SET_SRC (temp1))	      && rtx_cost (SET_SRC (temp1), SET) < 10)	    {	      rtx new = gen_reg_rtx (GET_MODE (temp2));	      if (validate_change (temp, &SET_DEST (temp1), new, 0))		{		  next = emit_insn_after (gen_move_insn (temp2, new), insn);		  emit_insn_after_with_line_notes (PATTERN (temp), 						   PREV_INSN (insn), temp);		  delete_insn (temp);		  reallabelprev = prev_active_insn (JUMP_LABEL (insn));		}	    }	  /* Similarly, if it takes two insns to compute EXP but they	     have the same destination.  Here TEMP3 will be the second	     insn and TEMP4 the SET from that insn.  */	  if (! reload_completed	      && this_is_condjump && ! this_is_simplejump	      && BRANCH_COST >= 4	      && (temp = next_nonnote_insn (insn)) != 0	      && GET_CODE (temp) == INSN	      && REG_NOTES (temp) == 0	      && (temp3 = next_nonnote_insn (temp)) != 0	      && GET_CODE (temp3) == INSN	      && REG_NOTES (temp3) == 0	      && (reallabelprev == temp3		  || ((temp2 = next_active_insn (temp3)) != 0		      && simplejump_p (temp2)		      && JUMP_LABEL (temp2) == JUMP_LABEL (insn)))	      && (temp1 = single_set (temp)) != 0	      && (temp2 = SET_DEST (temp1), GET_CODE (temp2) == REG)	      && GET_MODE_CLASS (GET_MODE (temp2)) == MODE_INT#ifdef SMALL_REGISTER_CLASSES	      && REGNO (temp2) >= FIRST_PSEUDO_REGISTER#endif	      && ! side_effects_p (SET_SRC (temp1))	      && ! may_trap_p (SET_SRC (temp1))	      && rtx_cost (SET_SRC (temp1), SET) < 10	      && (temp4 = single_set (temp3)) != 0	      && rtx_equal_p (SET_DEST (temp4), temp2)	      && ! side_effects_p (SET_SRC (temp4))	      && ! may_trap_p (SET_SRC (temp4))	      && rtx_cost (SET_SRC (temp4), SET) < 10)	    {	      rtx new = gen_reg_rtx (GET_MODE (temp2));	      if (validate_change (temp, &SET_DEST (temp1), new, 0))		{		  next = emit_insn_after (gen_move_insn (temp2, new), insn);		  emit_insn_after_with_line_notes (PATTERN (temp),						   PREV_INSN (insn), temp);		  emit_insn_after_with_line_notes		    (replace_rtx (PATTERN (temp3), temp2, new),		     PREV_INSN (insn), temp3);		  delete_insn (temp);		  delete_insn (temp3);		  reallabelprev = prev_active_insn (JUMP_LABEL (insn));		}	    }	  /* Finally, handle the case where two insns are used to 	     compute EXP but a temporary register is used.  Here we must	     ensure that the temporary register is not used anywhere else. */	  if (! reload_completed	      && after_regscan	      && this_is_condjump && ! this_is_simplejump	      && BRANCH_COST >= 4	      && (temp = next_nonnote_insn (insn)) != 0	      && GET_CODE (temp) == INSN	      && REG_NOTES (temp) == 0	      && (temp3 = next_nonnote_insn (temp)) != 0	      && GET_CODE (temp3) == INSN	      && REG_NOTES (temp3) == 0	      && (reallabelprev == temp3		  || ((temp2 = next_active_insn (temp3)) != 0		      && simplejump_p (temp2)		      && JUMP_LABEL (temp2) == JUMP_LABEL (insn)))	      && (temp1 = single_set (temp)) != 0	      && (temp5 = SET_DEST (temp1),		  (GET_CODE (temp5) == REG		   || (GET_CODE (temp5) == SUBREG		       && (temp5 = SUBREG_REG (temp5),			   GET_CODE (temp5) == REG))))	      && REGNO (temp5) >= FIRST_PSEUDO_REGISTER	      && regno_first_uid[REGNO (temp5)] == INSN_UID (temp)	      && regno_last_uid[REGNO (temp5)] == INSN_UID (temp3)	      && ! side_effects_p (SET_SRC (temp1))	      && ! may_trap_p (SET_SRC (temp1))	      && rtx_cost (SET_SRC (temp1), SET) < 10	      && (temp4 = single_set (temp3)) != 0	      && (temp2 = SET_DEST (temp4), GET_CODE (temp2) == REG)	      && GET_MODE_CLASS (GET_MODE (temp2)) == MODE_INT#ifdef SMALL_REGISTER_CLASSES	      && REGNO (temp2) >= FIRST_PSEUDO_REGISTER#endif	      && rtx_equal_p (SET_DEST (temp4), temp2)	      && ! side_effects_p (SET_SRC (temp4))	      && ! may_trap_p (SET_SRC (temp4))	      && rtx_cost (SET_SRC (temp4), SET) < 10)	    {	      rtx new = gen_reg_rtx (GET_MODE (temp2));	      if (validate_change (temp3, &SET_DEST (temp4), new, 0))		{		  next = emit_insn_after (gen_move_insn (temp2, new), insn);		  emit_insn_after_with_line_notes (PATTERN (temp),						   PREV_INSN (insn), temp);		  emit_insn_after_with_line_notes (PATTERN (temp3),						   PREV_INSN (insn), temp3);		  delete_insn (temp);		  delete_insn (temp3);		  reallabelprev = prev_active_insn (JUMP_LABEL (insn));		}	    }#endif /* HAVE_cc0 */	  /* Try to use a conditional move (if the target has them), or a	     store-flag insn.  The general case is:	     1) x = a; if (...) x = b; and	     2) if (...) x = b;	     If the jump would be faster, the machine should not have defined	     the movcc or scc insns!.  These cases are often made by the	     previous optimization.	     The second case is treated as  x = x; if (...) x = b;.	     INSN here is the jump around the store.  We set:	     TEMP to the "x = b;" insn.	     TEMP1 to X.	     TEMP2 to B.	     TEMP3 to A (X in the second case).	     TEMP4 to the condition being tested.	     TEMP5 to the earliest insn used to find the condition.  */	  if (/* We can't do this after reload has completed.  */	      ! reload_completed	      && this_is_condjump && ! this_is_simplejump	      /* Set TEMP to the "x = b;" insn.  */	      && (temp = next_nonnote_insn (insn)) != 0	      && GET_CODE (temp) == INSN	      && GET_CODE (PATTERN (temp)) == SET	      && GET_CODE (temp1 = SET_DEST (PATTERN (temp))) == REG#ifdef SMALL_REGISTER_CLASSES	      && REGNO (temp1) >= FIRST_PSEUDO_REGISTER#endif	      && (GET_CODE (temp2 = SET_SRC (PATTERN (temp))) == REG		  || GET_CODE (temp2) == SUBREG		  /* ??? How about floating point constants?  */		  || GET_CODE (temp2) == CONST_INT)	      /* Allow either form, but prefer the former if both apply. 		 There is no point in using the old value of TEMP1 if		 it is a register, since cse will alias them.  It can		 lose if the old value were a hard register since CSE		 won't replace hard registers.  */	      && (((temp3 = reg_set_last (temp1, insn)) != 0)		  /* Make the latter case look like  x = x; if (...) x = b;  */		  || (temp3 = temp1, 1))	      /* INSN must either branch to the insn after TEMP or the insn		 after TEMP must branch to the same place as INSN.  */	      && (reallabelprev == temp		  || ((temp4 = next_active_insn (temp)) != 0		      && simplejump_p (temp4)		      && JUMP_LABEL (temp4) == JUMP_LABEL (insn)))	      && (temp4 = get_condition (insn, &temp5)) != 0	      /* We must be comparing objects whose modes imply the size.		 We could handle BLKmode if (1) emit_store_flag could		 and (2) we could find the size reliably.  */	      && GET_MODE (XEXP (temp4, 0)) != BLKmode	      /* No point in doing any of this if branches are cheap or we		 don't have conditional moves.  */	      && (BRANCH_COST >= 2#ifdef HAVE_conditional_move		  || 1#endif		  )#ifdef HAVE_cc0	      /* If the previous insn sets CC0 and something else, we can't		 do this since we are going to delete that insn.  */	      && ! ((temp6 = prev_nonnote_insn (insn)) != 0		    && GET_CODE (temp6) == INSN		    && (sets_cc0_p (PATTERN (temp6)) == -1			|| (sets_cc0_p (PATTERN (temp6)) == 1			    && FIND_REG_INC_NOTE (temp6, NULL_RTX))))#endif	      )	    {#ifdef HAVE_conditional_move	      /* First try a conditional move.  */	      {		enum rtx_code code = GET_CODE (temp4);		rtx var = temp1;		rtx cond0, cond1, aval, bval;		rtx target;		/* Copy the compared variables into cond0 and cond1, so that		   any side effects performed in or after the old comparison,		   will not affect our compare which will come later.  */		/* ??? Is it possible to just use the comparison in the jump		   insn?  After all, we're going to delete it.  We'd have		   to modify emit_conditional_move to take a comparison rtx		   instead or write a new function.  */		cond0 = gen_reg_rtx (GET_MODE (XEXP (temp4, 0)));		/* We want the target to be able to simplify comparisons with		   zero (and maybe other constants as well), so don't create		   pseudos for them.  There's no need to either.  */		if (GET_CODE (XEXP (temp4, 1)) == CONST_INT		    || GET_CODE (XEXP (temp4, 1)) == CONST_DOUBLE)		  cond1 = XEXP (temp4, 1);		else		  cond1 = gen_reg_rtx (GET_MODE (XEXP (temp4, 1)));		aval = temp3;		bval = temp2;		start_sequence ();		target = emit_conditional_move (var, code,						cond0, cond1, VOIDmode,						aval, bval, GET_MODE (var),						(code == LTU || code == GEU						 || code == LEU || code == GTU));		if (target)		  {		    rtx seq1,seq2;		    /* Save the conditional move sequence but don't emit it		       yet.  On some machines, like the alpha, it is possible		       that temp5 == insn, so next generate the sequence that		       saves the compared values and then emit both		       sequences ensuring seq1 occurs before seq2.  */		    seq2 = get_insns ();		    end_sequence ();		    /* Now that we can't fail, generate the copy insns that		       preserve the compared values.  */		    start_sequence ();		    emit_move_insn (cond0, XEXP (temp4, 0));		    if (cond1 != XEXP (temp4, 1))		      emit_move_insn (cond1, XEXP (temp4, 1));		    seq1 = get_insns ();		    end_sequence ();		    emit_insns_before (seq1, temp5);		    emit_insns_before (seq2, insn);		    /* ??? We can also delete the insn that sets X to A.		       Flow will do it too though.  */		    delete_insn (temp);		    next = NEXT_INSN (insn);		    delete_jump (insn);		    changed = 1;		    continue;		  }		else		  end_sequence ();	      }#endif	      /* That didn't work, try a store-flag insn.		 We further divide the cases into:		 1) x = a; if (...) x = b; and either A or B is zero,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -