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

📄 reload.c

📁 这是完整的gcc源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		   || GET_CODE (in) == POST_DEC		   || GET_CODE (in) == PRE_INC		   || GET_CODE (in) == PRE_DEC)	       && MATCHES (XEXP (in, 0), reload_in[i]))))	{	  /* Make sure reload_in ultimately has the increment,	     not the plain register.  */	  if (GET_CODE (in) == REG)	    in = reload_in[i];	  break;	}  if (i == n_reloads)    {      /* We found no existing reload suitable for re-use.	 So add an additional reload.  */      reload_in[i] = in;      reload_out[i] = out;      reload_reg_class[i] = class;      reload_inmode[i] = inmode;      reload_outmode[i] = outmode;      reload_reg_rtx[i] = 0;      reload_optional[i] = optional;      reload_inc[i] = 0;      reload_strict_low[i] = strict_low;      reload_nocombine[i] = 0;      reload_in_reg[i] = *inloc;      reload_needed_for[i] = needed_for;      reload_needed_for_multiple[i] = 0;      n_reloads++;    }  else    {      /* We are reusing an existing reload,	 but we may have additional information for it.	 For example, we may now have both IN and OUT	 while the old one may have just one of them.	 If we have had two different inmodes or two different outmodes,	 use the wider one.  */      if (inmode != VOIDmode	  && (reload_inmode[i] == VOIDmode	      || GET_MODE_SIZE (inmode) > GET_MODE_SIZE (reload_inmode[i])))	reload_inmode[i] = inmode;      if (outmode != VOIDmode	  && (reload_outmode[i] == VOIDmode	      || GET_MODE_SIZE (outmode) > GET_MODE_SIZE (reload_outmode[i])))	reload_outmode[i] = outmode;      if (in != 0)	reload_in[i] = in;      if (out != 0)	reload_out[i] = out;      reload_optional[i] &= optional;      if (reload_needed_for[i] != needed_for)	reload_needed_for_multiple[i] = 1;    }  /* If the ostensible rtx being reload differs from the rtx found     in the location to substitute, this reload is not safe to combine     because we cannot reliably tell whether it appears in the insn.  */  if (in != 0 && in != *inloc)    reload_nocombine[i] = 1;#if 0  /* This was replaced by changes in find_reloads_address_1 and the new     function inc_for_reload, which go with a new meaning of reload_inc.  */  /* If this is an IN/OUT reload in an insn that sets the CC,     it must be for an autoincrement.  It doesn't work to store     the incremented value after the insn because that would clobber the CC.     So we must do the increment of the value reloaded from,     increment it, store it back, then decrement again.  */  if (out != 0 && sets_cc0_p (PATTERN (this_insn)))    {      out = 0;      reload_out[i] = 0;      reload_inc[i] = find_inc_amount (PATTERN (this_insn), in);      /* If we did not find a nonzero amount-to-increment-by,	 that contradicts the belief that IN is being incremented	 in an address in this insn.  */      if (reload_inc[i] == 0)	abort ();    }#endif  /* If we will replace IN and OUT with the reload-reg,     record where they are located so that substitution need     not do a tree walk.  */  if (replace_reloads)    {      if (inloc != 0)	{	  register struct replacement *r = &replacements[n_replacements++];	  r->what = i;	  r->where = inloc;	  r->mode = inmode;	}      if (outloc != 0 && outloc != inloc)	{	  register struct replacement *r = &replacements[n_replacements++];	  r->what = i;	  r->where = outloc;	  r->mode = outmode;	}    }  /* If this reload is just being introduced and it has both     an incoming quantity and an outgoing quantity that are     supposed to be made to match, see if either one of the two     can serve as the place to reload into.     If one of them is acceptable, set reload_reg_rtx[i]     to that one.  */  if (in != 0 && out != 0 && in != out && reload_reg_rtx[i] == 0)    {      reload_reg_rtx[i] = find_dummy_reload (in, out, inloc, outloc,					     reload_reg_class[i], i);      /* If the outgoing register already contains the same value	 as the incoming one, we can dispense with loading it.	 The easiest way to tell the caller that is to give a phony	 value for the incoming operand (same as outgoing one).  */      if (reload_reg_rtx[i] == out	  && (GET_CODE (in) == REG || CONSTANT_P (in))	  && 0 != find_equiv_reg (in, this_insn, 0, REGNO (out),				  static_reload_reg_p, i, inmode))	reload_in[i] = out;    }  if (out)    output_reloadnum = i;  return i;}/* Record an additional place we must replace a value   for which we have already recorded a reload.   RELOADNUM is the value returned by push_reload   when the reload was recorded.   This is used in insn patterns that use match_dup.  */static voidpush_replacement (loc, reloadnum, mode)     rtx *loc;     int reloadnum;     enum machine_mode mode;{  if (replace_reloads)    {      register struct replacement *r = &replacements[n_replacements++];      r->what = reloadnum;      r->where = loc;      r->mode = mode;    }}/* If there is only one output reload, try to combine it   with a (logically unrelated) input reload   to reduce the number of reload registers needed.   This is safe if the input reload does not appear in   the value being output-reloaded, because this implies   it is not needed any more once the original insn completes.  */static voidcombine_reloads (){  int i;  int output_reload = -1;  /* Find the output reload; return unless there is exactly one     and that one is mandatory.  */  for (i = 0; i < n_reloads; i++)    if (reload_out[i] != 0)      {	if (output_reload >= 0)	  return;	output_reload = i;      }  if (output_reload < 0 || reload_optional[output_reload])    return;  /* An input-output reload isn't combinable.  */  if (reload_in[output_reload] != 0)    return;  /* Check each input reload; can we combine it?  */  for (i = 0; i < n_reloads; i++)    if (reload_in[i] && ! reload_optional[i] && ! reload_nocombine[i]	/* Life span of this reload must not extend past main insn.  */	&& reload_when_needed[i] != RELOAD_FOR_OUTPUT_RELOAD_ADDRESS	&& reload_inmode[i] == reload_outmode[output_reload]	&& reload_inc[i] == 0	&& reload_reg_rtx[i] == 0	&& reload_strict_low[i] == 0	&& reload_reg_class[i] == reload_reg_class[output_reload]	&& ! reg_overlap_mentioned_p (reload_in[i], reload_out[output_reload]))      {	int j;	/* We have found a reload to combine with!  */	reload_out[i] = reload_out[output_reload];	reload_outmode[i] = reload_outmode[output_reload];	/* Mark the old output reload as inoperative.  */	reload_out[output_reload] = 0;	/* The combined reload is needed for the entire insn.  */	reload_needed_for_multiple[i] = 1;	reload_when_needed[i] = RELOAD_OTHER;	/* Transfer all replacements from the old reload to the combined.  */	for (j = 0; j < n_replacements; j++)	  if (replacements[j].what == output_reload)	    replacements[j].what = i;	return;      }}/* Try to find a reload register for an in-out reload (expressions IN and OUT).   See if one of IN and OUT is a register that may be used;   this is desirable since a spill-register won't be needed.   If so, return the register rtx that proves acceptable.   INLOC and OUTLOC are locations where IN and OUT appear in the insn.   CLASS is the register class required for the reload.   If FOR_REAL is >= 0, it is the number of the reload,   and in some cases when it can be discovered that OUT doesn't need   to be computed, clear out reload_out[FOR_REAL].   If FOR_REAL is -1, this should not be done, because this call   is just to see if a register can be found, not to find and install it.  */static rtxfind_dummy_reload (in, out, inloc, outloc, class, for_real)     rtx in, out;     rtx *inloc, *outloc;     enum reg_class class;     int for_real;{  rtx value = 0;  rtx orig_in = in;  while (GET_CODE (out) == SUBREG)    out = SUBREG_REG (out);  while (GET_CODE (in) == SUBREG)    in = SUBREG_REG (in);  /* If operands exceed a word, we can't use either of them     unless they have the same size.  */  if (GET_MODE_SIZE (GET_MODE (out)) != GET_MODE_SIZE (GET_MODE (in))      && (GET_MODE_SIZE (GET_MODE (out)) > UNITS_PER_WORD	  || GET_MODE_SIZE (GET_MODE (in)) > UNITS_PER_WORD))    return 0;  /* See if OUT will do.  */  if (GET_CODE (out) == REG)    {      register int regno = REGNO (out);      /* When we consider whether the insn uses OUT,	 ignore references within IN.  They don't prevent us	 from copying IN into OUT, because those refs would	 move into the insn that reloads IN.	 However, we only ignore IN in its role as this operand.	 If the insn uses IN elsewhere and it contains OUT,	 that counts.  We can't be sure it's the "same" operand	 so it might not go through this reload.  */      *inloc = const0_rtx;      if (reg_renumber[regno] >= 0)	regno = reg_renumber[regno];      if (regno < FIRST_PSEUDO_REGISTER	  /* A fixed reg that can overlap other regs better not be used	     for reloading in any way.  */#ifdef OVERLAPPING_REGNO_P	  && ! (fixed_regs[regno] && OVERLAPPING_REGNO_P (regno))#endif	  && ! refers_to_regno_p (regno, regno + HARD_REGNO_NREGS (regno, GET_MODE (out)),				  PATTERN (this_insn), outloc)	  && TEST_HARD_REG_BIT (reg_class_contents[(int) class], regno))	value = out;      *inloc = orig_in;    }  /* Consider using IN if OUT was not acceptable     or if OUT dies in this insn (like the quotient in a divmod insn).     We can't use IN unless it is free after this insn,     which means we must know accurately which hard regs are live.     Also, the result can't go in IN if IN is used within OUT.  */  if (hard_regs_live_known      && GET_CODE (in) == REG      && ! find_reg_note (this_insn, REG_UNSET, in)      && (value == 0	  || find_regno_note (this_insn, REG_DEAD, REGNO (value))))    {      register int regno = REGNO (in);      if (find_regno_note (this_insn, REG_DEAD, regno))	{	  if (reg_renumber[regno] >= 0)	    regno = reg_renumber[regno];	  if (regno < FIRST_PSEUDO_REGISTER	      && ! refers_to_regno_p (regno,				      regno + HARD_REGNO_NREGS (regno, GET_MODE (in)),				      out, 0)	      && ! hard_reg_set_here_p (regno, PATTERN (this_insn))	      && TEST_HARD_REG_BIT (reg_class_contents[(int) class], regno))	    {	      /* If we were going to use OUT as the reload reg		 and changed our mind, it means OUT is a dummy that		 dies here.  So don't bother copying value to it.  */	      if (for_real >= 0 && value == out)		reload_out[for_real] = 0;	      value = in;	    }	}    }  return value;}/* This page contains subroutines used mainly for determining   whether the IN or an OUT of a reload can serve as the   reload register.  *//* Return 1 if hard reg number REGNO is stored in by expression X,   either explicitly or in the guise of a pseudo-reg allocated to REGNO.   X should be the body of an instruction.  */static inthard_reg_set_here_p (regno, x)     register int regno;     rtx x;{  if (GET_CODE (x) == SET || GET_CODE (x) == CLOBBER)    {      register rtx op0 = SET_DEST (x);      while (GET_CODE (op0) == SUBREG)	op0 = SUBREG_REG (op0);      if (GET_CODE (op0) == REG)	{	  register int r = REGNO (op0);	  /* See if this reg includes the specified one.  */	  if (r <= regno && r + HARD_REGNO_NREGS (r, GET_MODE (op0)) > regno)	    return 1;	}    }  else if (GET_CODE (x) == PARALLEL)    {      register int i = XVECLEN (x, 0) - 1;      for (; i >= 0; i--)	if (hard_reg_set_here_p (regno, XVECEXP (x, 0, i)))	  return 1;    }  return 0;}/* Return 1 if ADDR is a valid memory address for mode MODE,   and check that each pseudo reg has the proper kind of   hard reg.  */intstrict_memory_address_p (mode, addr)     enum machine_mode mode;     register rtx addr;{  GO_IF_LEGITIMATE_ADDRESS (mode, addr, win);  return 0; win:  return 1;}/* Like rtx_equal_p except that it allows a REG and a SUBREG to match   if they are the same hard reg, and has special hacks for   autoincrement and autodecrement.   This is specifically intended for find_reloads to use   in determining whether two operands match.   X is the operand whose number is the lower of the two.   The value is 2 if Y contains a pre-increment that matches   a non-incrementing address in X.  *//* ??? To be completely correct, we should arrange to pass   for X the output operand and for Y the input operand.   For now, we assume that the output operand has the lower number   because that is natural in (SET output (... input ...)).  */intoperands_match_p (x, y)     register rtx x, y;{  register int i;  register RTX_CODE code = GET_CODE (x);

⌨️ 快捷键说明

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