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

📄 jump.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 5 页
字号:
	     <  == converts to >  ==	     <  != converts to ==  >	     etc.	     If the code is written to only accept an '==' test for the second	     compare, then all that needs to be done is to swap the condition	     of the first branch.	     It is questionable whether we want this optimization anyways,	     since if the user wrote code like this because he/she knew that	     the jump to label1 is taken most of the time, then rewriting	     this gives slower code.  */	  /* @@ This should call get_condition to find the values being	     compared, instead of looking for a COMPARE insn when HAVE_cc0	     is not defined.  This would allow it to work on the m88k.  */	  /* @@ This optimization is only safe before cse is run if HAVE_cc0	     is not defined and the condition is tested by a separate compare	     insn.  This is because the code below assumes that the result	     of the compare dies in the following branch.  */	  /* Simplify  test a ~= b		       condjump label1;		       test a == b		       condjump label2;		       jump label3;		       label1:	     rewriting as		       test a ~~= b		       condjump label3		       test a == b		       condjump label2		       label1:	     where ~= is an inequality, e.g. >, and ~~= is the swapped	     inequality, e.g. <.	     We recognize this case scanning backwards.	     TEMP is the conditional jump to `label2';	     TEMP1 is the test for `a == b';	     TEMP2 is the conditional jump to `label1';	     TEMP3 is the test for `a ~= b'.  */	  else if (this_is_simplejump		   && (temp = prev_active_insn (insn))		   && no_labels_between_p (temp, insn)		   && condjump_p (temp)		   && (temp1 = prev_active_insn (temp))		   && no_labels_between_p (temp1, temp)		   && GET_CODE (temp1) == INSN		   && GET_CODE (PATTERN (temp1)) == SET#ifdef HAVE_cc0		   && sets_cc0_p (PATTERN (temp1)) == 1#else		   && GET_CODE (SET_SRC (PATTERN (temp1))) == COMPARE		   && GET_CODE (SET_DEST (PATTERN (temp1))) == REG		   && (temp == find_next_ref (SET_DEST (PATTERN (temp1)), temp1))#endif		   && (temp2 = prev_active_insn (temp1))		   && no_labels_between_p (temp2, temp1)		   && condjump_p (temp2)		   && JUMP_LABEL (temp2) == next_nonnote_insn (NEXT_INSN (insn))		   && (temp3 = prev_active_insn (temp2))		   && no_labels_between_p (temp3, temp2)		   && GET_CODE (PATTERN (temp3)) == SET		   && rtx_equal_p (SET_DEST (PATTERN (temp3)),				   SET_DEST (PATTERN (temp1)))		   && rtx_equal_p (SET_SRC (PATTERN (temp1)),				   SET_SRC (PATTERN (temp3)))		   && ! inequality_comparisons_p (PATTERN (temp))		   && inequality_comparisons_p (PATTERN (temp2)))	    {	      rtx fallthrough_label = JUMP_LABEL (temp2);	      ++LABEL_NUSES (fallthrough_label);	      if (swap_jump (temp2, JUMP_LABEL (insn)))		{		  delete_insn (insn);		  changed = 1;		}	      if (--LABEL_NUSES (fallthrough_label) == 0)		delete_insn (fallthrough_label);	    }#endif	  /* Simplify  if (...) {... x = 1;} if (x) ...	     We recognize this case backwards.	     TEMP is the test of `x';	     TEMP1 is the assignment to `x' at the end of the	     previous statement.  */	  /* @@ This should call get_condition to find the values being	     compared, instead of looking for a COMPARE insn when HAVE_cc0	     is not defined.  This would allow it to work on the m88k.  */	  /* @@ This optimization is only safe before cse is run if HAVE_cc0	     is not defined and the condition is tested by a separate compare	     insn.  This is because the code below assumes that the result	     of the compare dies in the following branch.  */	  /* ??? This has to be turned off.  The problem is that the	     unconditional jump might indirectly end up branching to the	     label between TEMP1 and TEMP.  We can't detect this, in general,	     since it may become a jump to there after further optimizations.	     If that jump is done, it will be deleted, so we will retry	     this optimization in the next pass, thus an infinite loop.	     The present code prevents this by putting the jump after the	     label, but this is not logically correct.  */#if 0	  else if (this_is_condjump		   /* Safe to skip USE and CLOBBER insns here		      since they will not be deleted.  */		   && (temp = prev_active_insn (insn))		   && no_labels_between_p (temp, insn)		   && GET_CODE (temp) == INSN		   && GET_CODE (PATTERN (temp)) == SET#ifdef HAVE_cc0		   && sets_cc0_p (PATTERN (temp)) == 1		   && GET_CODE (SET_SRC (PATTERN (temp))) == REG#else		   /* Temp must be a compare insn, we can not accept a register		      to register move here, since it may not be simply a		      tst insn.  */		   && GET_CODE (SET_SRC (PATTERN (temp))) == COMPARE		   && XEXP (SET_SRC (PATTERN (temp)), 1) == const0_rtx		   && GET_CODE (XEXP (SET_SRC (PATTERN (temp)), 0)) == REG		   && GET_CODE (SET_DEST (PATTERN (temp))) == REG		   && insn == find_next_ref (SET_DEST (PATTERN (temp)), temp)#endif		   /* May skip USE or CLOBBER insns here		      for checking for opportunity, since we		      take care of them later.  */		   && (temp1 = prev_active_insn (temp))		   && GET_CODE (temp1) == INSN		   && GET_CODE (PATTERN (temp1)) == SET#ifdef HAVE_cc0		   && SET_SRC (PATTERN (temp)) == SET_DEST (PATTERN (temp1))#else		   && (XEXP (SET_SRC (PATTERN (temp)), 0)		       == SET_DEST (PATTERN (temp1)))#endif		   && CONSTANT_P (SET_SRC (PATTERN (temp1)))		   /* If this isn't true, cse will do the job.  */		   && ! no_labels_between_p (temp1, temp))	    {	      /* Get the if_then_else from the condjump.  */	      rtx choice = SET_SRC (PATTERN (insn));	      if (GET_CODE (choice) == IF_THEN_ELSE		  && (GET_CODE (XEXP (choice, 0)) == EQ		      || GET_CODE (XEXP (choice, 0)) == NE))		{		  int want_nonzero = (GET_CODE (XEXP (choice, 0)) == NE);		  rtx last_insn;		  rtx ultimate;		  rtx p;		  /* Get the place that condjump will jump to		     if it is reached from here.  */		  if ((SET_SRC (PATTERN (temp1)) != const0_rtx)		      == want_nonzero)		    ultimate = XEXP (choice, 1);		  else		    ultimate = XEXP (choice, 2);		  /* Get it as a CODE_LABEL.  */		  if (ultimate == pc_rtx)		    ultimate = get_label_after (insn);		  else		    /* Get the label out of the LABEL_REF.  */		    ultimate = XEXP (ultimate, 0);		  /* Insert the jump immediately before TEMP, specifically		     after the label that is between TEMP1 and TEMP.  */		  last_insn = PREV_INSN (temp);		  /* If we would be branching to the next insn, the jump		     would immediately be deleted and the re-inserted in		     a subsequent pass over the code.  So don't do anything		     in that case.  */		  if (next_active_insn (last_insn)		      != next_active_insn (ultimate))		    {		      emit_barrier_after (last_insn);		      p = emit_jump_insn_after (gen_jump (ultimate),						last_insn);		      JUMP_LABEL (p) = ultimate;		      ++LABEL_NUSES (ultimate);		      if (INSN_UID (ultimate) < max_jump_chain			  && INSN_CODE (p) < max_jump_chain)			{			  jump_chain[INSN_UID (p)]			    = jump_chain[INSN_UID (ultimate)];			  jump_chain[INSN_UID (ultimate)] = p;			}		      changed = 1;		      continue;		    }		}	    }#endif	  /* Detect a conditional jump going to the same place	     as an immediately following unconditional jump.  */	  else if (this_is_condjump		   && (temp = next_active_insn (insn)) != 0		   && simplejump_p (temp)		   && (next_active_insn (JUMP_LABEL (insn))		       == next_active_insn (JUMP_LABEL (temp))))	    {	      delete_jump (insn);	      changed = 1;	      continue;	    }	  /* Detect a conditional jump jumping over an unconditional jump.  */	  else if ((this_is_condjump || this_is_condjump_in_parallel)		   && ! this_is_simplejump		   && reallabelprev != 0		   && GET_CODE (reallabelprev) == JUMP_INSN		   && prev_active_insn (reallabelprev) == insn		   && no_labels_between_p (insn, reallabelprev)		   && simplejump_p (reallabelprev))	    {	      /* When we invert the unconditional jump, we will be		 decrementing the usage count of its old label.		 Make sure that we don't delete it now because that		 might cause the following code to be deleted.  */	      rtx prev_uses = prev_nonnote_insn (reallabelprev);	      rtx prev_label = JUMP_LABEL (insn);	      if (prev_label)		++LABEL_NUSES (prev_label);	      if (invert_jump (insn, JUMP_LABEL (reallabelprev)))		{		  /* It is very likely that if there are USE insns before		     this jump, they hold REG_DEAD notes.  These REG_DEAD		     notes are no longer valid due to this optimization,		     and will cause the life-analysis that following passes		     (notably delayed-branch scheduling) to think that		     these registers are dead when they are not.		     To prevent this trouble, we just remove the USE insns		     from the insn chain.  */		  while (prev_uses && GET_CODE (prev_uses) == INSN			 && GET_CODE (PATTERN (prev_uses)) == USE)		    {		      rtx useless = prev_uses;		      prev_uses = prev_nonnote_insn (prev_uses);		      delete_insn (useless);		    }		  delete_insn (reallabelprev);		  next = insn;		  changed = 1;		}	      /* We can now safely delete the label if it is unreferenced		 since the delete_insn above has deleted the BARRIER.  */	      if (prev_label && --LABEL_NUSES (prev_label) == 0)		delete_insn (prev_label);	      continue;	    }	  else	    {	      /* Detect a jump to a jump.  */	      nlabel = follow_jumps (JUMP_LABEL (insn));	      if (nlabel != JUMP_LABEL (insn)		  && redirect_jump (insn, nlabel))		{		  changed = 1;		  next = insn;		}	      /* Look for   if (foo) bar; else break;  */	      /* The insns look like this:		 insn = condjump label1;		 ...range1 (some insns)...		 jump label2;		 label1:		 ...range2 (some insns)...		 jump somewhere unconditionally		 label2:  */	      {		rtx label1 = next_label (insn);		rtx range1end = label1 ? prev_active_insn (label1) : 0;		/* Don't do this optimization on the first round, so that		   jump-around-a-jump gets simplified before we ask here		   whether a jump is unconditional.		   Also don't do it when we are called after reload since		   it will confuse reorg.  */		if (! first		    && (reload_completed ? ! flag_delayed_branch : 1)		    /* Make sure INSN is something we can invert.  */		    && condjump_p (insn)		    && label1 != 0		    && JUMP_LABEL (insn) == label1		    && LABEL_NUSES (label1) == 1		    && GET_CODE (range1end) == JUMP_INSN		    && simplejump_p (range1end))		  {		    rtx label2 = next_label (label1);		    rtx range2end = label2 ? prev_active_insn (label2) : 0;		    if (range1end != range2end			&& JUMP_LABEL (range1end) == label2			&& GET_CODE (range2end) == JUMP_INSN			&& GET_CODE (NEXT_INSN (range2end)) == BARRIER			/* Invert the jump condition, so we			   still execute the same insns in each case.  */			&& invert_jump (insn, label1))		      {			rtx range1beg = next_active_insn (insn);			rtx range2beg = next_active_insn (label1);			rtx range1after, range2after;			rtx range1before, range2before;			rtx rangenext;			/* Include in each range any notes before it, to be			   sure that we get the line number note if any, even			   if there are other notes here.  */			while (PREV_INSN (range1beg)			       && GET_CODE (PREV_INSN (range1beg)) == NOTE)			  range1beg = PREV_INSN (range1beg);			while (PREV_INSN (range2beg)			       && GET_CODE (PREV_INSN (range2beg)) == NOTE)			  range2beg = PREV_INSN (range2beg);			/* Don't move NOTEs for blocks or loops; shift them			   outside the ranges, where they'll stay put.  */			range1beg = squeeze_notes (range1beg, range1end);			range2beg = squeeze_notes (range2beg, range2end);			/* Get current surrounds of the 2 ranges.  */			range1before = PREV_INSN (range1beg);			range2before = PREV_INSN (range2beg);			range1after = NEXT_INSN (range1end);			range2after = NEXT_INSN (range2end);			/* Splice range2 where range1 was.  */			NEXT_INSN (range1before) = range2beg;			PREV_INSN (range2beg) = range1before;			NEXT_INSN (range2end) = range1after;			PREV_INSN (range1after) = range2end;			/* Splice range1 where range2 was.  */			NEXT_INSN (range2before) = range1beg;			PREV_INSN (range1beg) = range2before;			NEXT_INSN (range1end) = range2after;			PREV_INSN (range2after) = range1end;			/* Check for a loop end note between the end of			   range2, and the next code label.  If there is one,			   then what we have really seen is			   if (foo) break; end_of_loop;			   and moved the break sequence outside the loop.			   We must move the LOOP_END note to where the			   loop really ends now, or we will confuse loop			   optimization.  Stop if we find a LOOP_BEG note			   first, since we don't want to move the LOOP_END			   note in that case.  */			for (;range2after != label2; range2after = rangenext)			  {			    rangenext = NEXT_INSN (range2after);			    if (GET_CODE (range2after) == NOTE)			      {				if (NOTE_LINE_NUMBER (range2after)				    == NOTE_INSN_LOOP_END)				  {				    NEXT_INSN (PREV_INSN (range2after))				      = rangenext;				    PREV_INSN (rangenext)				      = PREV_INSN (range2after);				    PREV_INSN (range2after) 				      = PREV_INSN (range1beg);				    NEXT_INSN (range2after) = range1beg;

⌨️ 快捷键说明

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