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

📄 jump.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
		    if (total_pushed < 0)		      {			emit_insn_before (gen_add2_insn (stack_pointer_rtx,							 GEN_INT (- total_pushed)),					  p);			break;		      }		    XEXP (dest, 0)		      = plus_constant (stack_pointer_rtx, total_pushed);		  }	      }#endif	    /* Detect and delete no-op move instructions	       resulting from not allocating a parameter in a register.  */	    if (GET_CODE (body) == SET		&& (SET_DEST (body) == SET_SRC (body)		    || (GET_CODE (SET_DEST (body)) == MEM			&& GET_CODE (SET_SRC (body)) == MEM			&& rtx_equal_p (SET_SRC (body), SET_DEST (body))))		&& ! (GET_CODE (SET_DEST (body)) == MEM		      && MEM_VOLATILE_P (SET_DEST (body)))		&& ! (GET_CODE (SET_SRC (body)) == MEM		      && MEM_VOLATILE_P (SET_SRC (body))))	      delete_insn (insn);	    /* Detect and ignore no-op move instructions	       resulting from smart or fortuitous register allocation.  */	    else if (GET_CODE (body) == SET)	      {		int sreg = true_regnum (SET_SRC (body));		int dreg = true_regnum (SET_DEST (body));		if (sreg == dreg && sreg >= 0)		  delete_insn (insn);		else if (sreg >= 0 && dreg >= 0)		  {		    rtx trial;		    rtx tem = find_equiv_reg (NULL_RTX, insn, 0,					      sreg, NULL_PTR, dreg,					      GET_MODE (SET_SRC (body)));#ifdef PRESERVE_DEATH_INFO_REGNO_P		    /* Deleting insn could lose a death-note for SREG or DREG		       so don't do it if final needs accurate death-notes.  */		    if (! PRESERVE_DEATH_INFO_REGNO_P (sreg)			&& ! PRESERVE_DEATH_INFO_REGNO_P (dreg))#endif		      {			/* DREG may have been the target of a REG_DEAD note in			   the insn which makes INSN redundant.  If so, reorg			   would still think it is dead.  So search for such a			   note and delete it if we find it.  */			for (trial = prev_nonnote_insn (insn);			     trial && GET_CODE (trial) != CODE_LABEL;			     trial = prev_nonnote_insn (trial))			  if (find_regno_note (trial, REG_DEAD, dreg))			    {			      remove_death (dreg, trial);			      break;			    }			if (tem != 0			    && GET_MODE (tem) == GET_MODE (SET_DEST (body)))			  delete_insn (insn);		      }		  }		else if (dreg >= 0 && CONSTANT_P (SET_SRC (body))			 && find_equiv_reg (SET_SRC (body), insn, 0, dreg,					    NULL_PTR, 0,					    GET_MODE (SET_DEST (body))))		  {		    /* This handles the case where we have two consecutive		       assignments of the same constant to pseudos that didn't		       get a hard reg.  Each SET from the constant will be		       converted into a SET of the spill register and an		       output reload will be made following it.  This produces		       two loads of the same constant into the same spill		       register.  */		    rtx in_insn = insn;		    /* Look back for a death note for the first reg.		       If there is one, it is no longer accurate.  */		    while (in_insn && GET_CODE (in_insn) != CODE_LABEL)		      {			if ((GET_CODE (in_insn) == INSN			     || GET_CODE (in_insn) == JUMP_INSN)			    && find_regno_note (in_insn, REG_DEAD, dreg))			  {			    remove_death (dreg, in_insn);			    break;			  }			in_insn = PREV_INSN (in_insn);		      }		    /* Delete the second load of the value.  */		    delete_insn (insn);		  }	      }	    else if (GET_CODE (body) == PARALLEL)	      {		/* If each part is a set between two identical registers or		   a USE or CLOBBER, delete the insn. */		int i, sreg, dreg;		rtx tem;		for (i = XVECLEN (body, 0) - 1; i >= 0; i--)		  {		    tem = XVECEXP (body, 0, i);		    if (GET_CODE (tem) == USE || GET_CODE (tem) == CLOBBER)		      continue;		    if (GET_CODE (tem) != SET		    	|| (sreg = true_regnum (SET_SRC (tem))) < 0		    	|| (dreg = true_regnum (SET_DEST (tem))) < 0		    	|| dreg != sreg)		      break;		  }		  		if (i < 0)		  delete_insn (insn);	      }#if !BYTES_BIG_ENDIAN /* Not worth the hair to detect this			 in the big-endian case.  */	    /* Also delete insns to store bit fields if they are no-ops.  */	    else if (GET_CODE (body) == SET		     && GET_CODE (SET_DEST (body)) == ZERO_EXTRACT		     && XEXP (SET_DEST (body), 2) == const0_rtx		     && XEXP (SET_DEST (body), 0) == SET_SRC (body)		     && ! (GET_CODE (SET_SRC (body)) == MEM			   && MEM_VOLATILE_P (SET_SRC (body))))	      delete_insn (insn);#endif /* not BYTES_BIG_ENDIAN */	  }      insn = next;    }  /* If we haven't yet gotten to reload and we have just run regscan,     delete any insn that sets a register that isn't used elsewhere.     This helps some of the optimizations below by having less insns     being jumped around.  */  if (! reload_completed && after_regscan)    for (insn = f; insn; insn = next)      {	rtx set = single_set (insn);	next = NEXT_INSN (insn);	if (set && GET_CODE (SET_DEST (set)) == REG	    && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER	    && regno_first_uid[REGNO (SET_DEST (set))] == INSN_UID (insn)	    && regno_last_uid[REGNO (SET_DEST (set))] == INSN_UID (insn)	    && ! side_effects_p (SET_SRC (set)))	  delete_insn (insn);      }  /* Now iterate optimizing jumps until nothing changes over one pass.  */  changed = 1;  while (changed)    {      changed = 0;      for (insn = f; insn; insn = next)	{	  rtx reallabelprev;	  rtx temp, temp1, temp2, temp3, temp4, temp5, temp6;	  rtx nlabel;	  int this_is_simplejump, this_is_condjump, reversep;#if 0	  /* If NOT the first iteration, if this is the last jump pass	     (just before final), do the special peephole optimizations.	     Avoiding the first iteration gives ordinary jump opts	     a chance to work before peephole opts.  */	  if (reload_completed && !first && !flag_no_peephole)	    if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN)	      peephole (insn);#endif	  /* That could have deleted some insns after INSN, so check now	     what the following insn is.  */	  next = NEXT_INSN (insn);	  /* See if this is a NOTE_INSN_LOOP_BEG followed by an unconditional	     jump.  Try to optimize by duplicating the loop exit test if so.	     This is only safe immediately after regscan, because it uses	     the values of regno_first_uid and regno_last_uid.  */	  if (after_regscan && GET_CODE (insn) == NOTE	      && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG	      && (temp1 = next_nonnote_insn (insn)) != 0	      && simplejump_p (temp1))	    {	      temp = PREV_INSN (insn);	      if (duplicate_loop_exit_test (insn))		{		  changed = 1;		  next = NEXT_INSN (temp);		  continue;		}	    }	  if (GET_CODE (insn) != JUMP_INSN)	    continue;	  this_is_simplejump = simplejump_p (insn);	  this_is_condjump = condjump_p (insn);	  /* Tension the labels in dispatch tables.  */	  if (GET_CODE (PATTERN (insn)) == ADDR_VEC)	    changed |= tension_vector_labels (PATTERN (insn), 0);	  if (GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)	    changed |= tension_vector_labels (PATTERN (insn), 1);	  /* If a dispatch table always goes to the same place,	     get rid of it and replace the insn that uses it.  */	  if (GET_CODE (PATTERN (insn)) == ADDR_VEC	      || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)	    {	      int i;	      rtx pat = PATTERN (insn);	      int diff_vec_p = GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC;	      int len = XVECLEN (pat, diff_vec_p);	      rtx dispatch = prev_real_insn (insn);	      for (i = 0; i < len; i++)		if (XEXP (XVECEXP (pat, diff_vec_p, i), 0)		    != XEXP (XVECEXP (pat, diff_vec_p, 0), 0))		  break;	      if (i == len		  && dispatch != 0		  && GET_CODE (dispatch) == JUMP_INSN		  && JUMP_LABEL (dispatch) != 0		  /* Don't mess with a casesi insn.  */		  && !(GET_CODE (PATTERN (dispatch)) == SET		       && (GET_CODE (SET_SRC (PATTERN (dispatch)))			   == IF_THEN_ELSE))		  && next_real_insn (JUMP_LABEL (dispatch)) == insn)		{		  redirect_tablejump (dispatch,				      XEXP (XVECEXP (pat, diff_vec_p, 0), 0));		  changed = 1;		}	    }	  reallabelprev = prev_active_insn (JUMP_LABEL (insn));	  /* If a jump references the end of the function, try to turn	     it into a RETURN insn, possibly a conditional one.  */	  if (JUMP_LABEL (insn)	      && next_active_insn (JUMP_LABEL (insn)) == 0)	    changed |= redirect_jump (insn, NULL_RTX);	  /* Detect jump to following insn.  */	  if (reallabelprev == insn && condjump_p (insn))	    {	      delete_jump (insn);	      changed = 1;	      continue;	    }	  /* If we have an unconditional jump preceded by a USE, try to put	     the USE before the target and jump there.  This simplifies many	     of the optimizations below since we don't have to worry about	     dealing with these USE insns.  We only do this if the label	     being branch to already has the identical USE or if code	     never falls through to that label.  */	  if (this_is_simplejump	      && (temp = prev_nonnote_insn (insn)) != 0	      && GET_CODE (temp) == INSN && GET_CODE (PATTERN (temp)) == USE	      && (temp1 = prev_nonnote_insn (JUMP_LABEL (insn))) != 0	      && (GET_CODE (temp1) == BARRIER		  || (GET_CODE (temp1) == INSN		      && rtx_equal_p (PATTERN (temp), PATTERN (temp1)))))	    {	      if (GET_CODE (temp1) == BARRIER)		{		  emit_insn_after (PATTERN (temp), temp1);		  temp1 = NEXT_INSN (temp1);		}	      delete_insn (temp);	      redirect_jump (insn, get_label_before (temp1));	      reallabelprev = prev_real_insn (temp1);	      changed = 1;	    }	  /* Simplify   if (...) x = a; else x = b; by converting it	     to         x = b; if (...) x = a;	     if B is sufficiently simple, the test doesn't involve X,	     and nothing in the test modifies B or X.	     If we have small register classes, we also can't do this if X	     is a hard register.	     If the "x = b;" insn has any REG_NOTES, we don't do this because	     of the possibility that we are running after CSE and there is a	     REG_EQUAL note that is only valid if the branch has already been	     taken.  If we move the insn with the REG_EQUAL note, we may	     fold the comparison to always be false in a later CSE pass.	     (We could also delete the REG_NOTES when moving the insn, but it	     seems simpler to not move it.)  An exception is that we can move	     the insn if the only note is a REG_EQUAL or REG_EQUIV whose	     value is the same as "b".	     INSN is the branch over the `else' part. 	     We set:	     TEMP to the jump insn preceding "x = a;"	     TEMP1 to X	     TEMP2 to the insn that sets "x = b;"	     TEMP3 to the insn that sets "x = a;"	     TEMP4 to the set of "x = b";  */	  if (this_is_simplejump	      && (temp3 = prev_active_insn (insn)) != 0	      && GET_CODE (temp3) == INSN	      && (temp4 = single_set (temp3)) != 0	      && GET_CODE (temp1 = SET_DEST (temp4)) == REG#ifdef SMALL_REGISTER_CLASSES	      && REGNO (temp1) >= FIRST_PSEUDO_REGISTER#endif	      && (temp2 = next_active_insn (insn)) != 0	      && GET_CODE (temp2) == INSN	      && (temp4 = single_set (temp2)) != 0	      && rtx_equal_p (SET_DEST (temp4), temp1)	      && (GET_CODE (SET_SRC (temp4)) == REG		  || GET_CODE (SET_SRC (temp4)) == SUBREG		  || CONSTANT_P (SET_SRC (temp4)))	      && (REG_NOTES (temp2) == 0		  || ((REG_NOTE_KIND (REG_NOTES (temp2)) == REG_EQUAL		       || REG_NOTE_KIND (REG_NOTES (temp2)) == REG_EQUIV)		      && XEXP (REG_NOTES (temp2), 1) == 0		      && rtx_equal_p (XEXP (REG_NOTES (temp2), 0),				      SET_SRC (temp4))))	      && (temp = prev_active_insn (temp3)) != 0	      && condjump_p (temp) && ! simplejump_p (temp)	      /* TEMP must skip over the "x = a;" insn */	      && prev_real_insn (JUMP_LABEL (temp)) == insn	      && no_labels_between_p (insn, JUMP_LABEL (temp))	      /* There must be no other entries to the "x = b;" insn.  */	      && no_labels_between_p (JUMP_LABEL (temp), temp2)	      /* INSN must either branch to the insn after TEMP2 or the insn		 after TEMP2 must branch to the same place as INSN.  */	      && (reallabelprev == temp2		  || ((temp5 = next_active_insn (temp2)) != 0		      && simplejump_p (temp5)		      && JUMP_LABEL (temp5) == JUMP_LABEL (insn))))	    {	      /* The test expression, X, may be a complicated test with		 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.  */

⌨️ 快捷键说明

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