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

📄 jump.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
		  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_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);	      ++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 (--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;			/* Include in each range any line number before it.  */			while (PREV_INSN (range1beg)			       && GET_CODE (PREV_INSN (range1beg)) == NOTE			       && NOTE_LINE_NUMBER (PREV_INSN (range1beg)) > 0)			  range1beg = PREV_INSN (range1beg);			while (PREV_INSN (range2beg)			       && GET_CODE (PREV_INSN (range2beg)) == NOTE			       && NOTE_LINE_NUMBER (PREV_INSN (range2beg)) > 0)			  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;			changed = 1;			continue;		      }		  }	      }	      /* Now that the jump has been tensioned,		 try cross jumping: check for identical code		 before the jump and before its target label. */	      /* First, cross jumping of conditional jumps:  */	      if (cross_jump && condjump_p (insn))		{		  rtx newjpos, newlpos;		  rtx x = prev_real_insn (JUMP_LABEL (insn));		  /* A conditional jump may be crossjumped		     only if the place it jumps to follows		     an opposing jump that comes back here.  */		  if (x != 0 && ! jump_back_p (x, insn))		    /* We have no opposing jump;		       cannot cross jump this insn.  */		    x = 0;		  newjpos = 0;		  /* TARGET is nonzero if it is ok to cross jump		     to code before TARGET.  If so, see if matches.  */		  if (x != 0)		    find_cross_jump (insn, x, 2,				     &newjpos, &newlpos);		  if (newjpos != 0)		    {		      do_cross_jump (insn, newjpos, newlpos);		      /* Make the old conditional jump			 into an unconditional one.  */		      SET_SRC (PATTERN (insn))			= gen_rtx (LABEL_REF, VOIDmode, JUMP_LABEL (insn));		      INSN_CODE (insn) = -1;		      emit_barrier_after (insn);		      /* Add to jump_chain unless this is a new label			 whose UID is too large. */		      if (INSN_UID (JUMP_LABEL (insn)) < max_jump_chain)			{			  jump_chain[INSN_UID (insn)]			    = jump_chain[INSN_UID (JUMP_LABEL (insn))];			  jump_chain[INSN_UID (JUMP_LABEL (insn))] = insn;			}		      changed = 1;		      next = insn;		    }		}	      /* Cross jumping of unconditional jumps:		 a few differences.  */	      if (cross_jump && simplejump_p (insn))		{		  rtx newjpos, newlpos;		  rtx target;		  newjpos = 0;		  /* TARGET is nonzero if it is ok to cross jump		     to code before TARGET.  If so, see if matches.  */		  find_cross_jump (insn, JUMP_LABEL (insn), 1,				   &newjpos, &newlpos);		  /* If cannot cross jump to code before the label,		     see if we can cross jump to another jump to		     the same label.  */		  /* Try each other jump to this label.  */		  if (INSN_UID (JUMP_LABEL (insn)) < max_uid)		    for (target = jump_chain[INSN_UID (JUMP_LABEL (insn))];			 target != 0 && newjpos == 0;			 target = jump_chain[INSN_UID (target)])		      if (target != insn			  && JUMP_LABEL (target) == JUMP_LABEL (insn)			  /* Ignore TARGET if it's deleted.  */			  && ! INSN_DELETED_P (target))			find_cross_jump (insn, target, 2,					 &newjpos, &newlpos);		  if (newjpos != 0)		    {		      do_cross_jump (insn, newjpos, newlpos);		      changed = 1;		      next = insn;		    }		}	      /* This code was dead in the previous jump.c!  */	      if (cross_jump && GET_CODE (PATTERN (insn)) == RETURN)		{		  /* Return insns all "jump to the same place"		     so we can cross-jump between any two of them.  */		  rtx newjpos, newlpos, target;		  newjpos = 0;		  /* If cannot cross jump to code before the label,		     see if we can cross jump to another jump to		     the same label.  */		  /* Try each other jump to this label.  */		  for (target = jump_chain[0];		       target != 0 && newjpos == 0;		       target = jump_chain[INSN_UID (target)])		    if (target != insn			&& ! INSN_DELETED_P (target)			&& GET_CODE (PATTERN (target)) == RETURN)		      find_cross_jump (insn, target, 2,				       &newjpos, &newlpos);		  if (newjpos != 0)		    {		      do_cross_jump (insn, newjpos, newlpos);		      changed = 1;		      next = insn;		    }		}	    }	}      first = 0;    }  /* Delete extraneous line number notes.     Note that two consecutive notes for different lines are not really     extraneous.  There should be some indication where that line belonged,     even if it became empty.  */  {    rtx last_note = 0;    for (insn = f; insn; insn = NEXT_INSN (insn))      if (GET_CODE (insn) == NOTE && NOTE_LINE_NUMBER (insn) >= 0)	{	  /* Delete this note if it is identical to previous note.  */	  if (last_note	      && NOTE_SOURCE_FILE (insn) == NOTE_SOURCE_FILE (last_note)	      && NOTE_LINE_NUMBER (insn) == NOTE_LINE_NUMBER (last_note))	    {	      delete_insn (insn);	      continue;	    }	  last_note = insn;	}  }  /* See if there is still a NOTE_INSN_FUNCTION_END in this function.     If so, delete it, and record that this function can drop off the end.  */  insn = last_insn;  {    int n_labels = 1;    while (insn	   /* One label can follow the end-note: the return label.  */	   && ((GET_CODE (insn) == CODE_LABEL && n_labels-- > 0)	       /* Ordinary insns can follow it if returning a structure.  */	       || GET_CODE (insn) == INSN	       /* If machine uses explicit RETURN insns, no epilogue,		  then one of them follows the note.  */	       || (GET_CODE (insn) == JUMP_INSN		   && GET_CODE (PATTERN (insn)) == RETURN)	       /* Other kinds of notes can follow also.  */	       || (GET_CODE (insn) == NOTE		   && NOTE_LINE_NUMBER (insn) != NOTE_INSN_FUNCTION_END)))      insn = PREV_INSN (insn);  }  /* Report if control can fall through at the end of the function.  */  if (insn && GET_CODE (insn) == NOTE      && NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_END)    {      can_reach_end = 1;      delete_insn (insn);    }  /* Show JUMP_CHAIN no longer valid.  */  jump_chain = 0;}/* LOOP_START is a NOTE_INSN_LOOP_BEG note that is followed by an unconditional   jump.  Assume that this unconditional jump is to the exit test code.  If   the code is sufficiently simple, make a copy of it before INSN,   followed by a jump to the exit of the loop.  Then delete the unconditional   jump after INSN.   Note that it is possible we can get confused here if the jump immediately   after the loop start branches outside the loop but within an outer loop.   If we are near the exit of that loop, we will copy its exit test.  This   will not generate incorrec

⌨️ 快捷键说明

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