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

📄 reload.c

📁 GCC编译器源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
     Note that the operand might be one of the spill regs, if it is a     pseudo reg and we are in a block where spilling has not taken place.     But if there is no spilling in this block, that is OK.     An explicitly used hard reg cannot be a spill reg.  */  if (reload_reg_rtx[i] == 0 && in != 0)    {      rtx note;      int regno;      for (note = REG_NOTES (this_insn); note; note = XEXP (note, 1))	if (REG_NOTE_KIND (note) == REG_DEAD	    && GET_CODE (XEXP (note, 0)) == REG	    && (regno = REGNO (XEXP (note, 0))) < FIRST_PSEUDO_REGISTER	    && reg_mentioned_p (XEXP (note, 0), in)	    && ! refers_to_regno_for_reload_p (regno,					       (regno						+ HARD_REGNO_NREGS (regno,								    inmode)),					       PATTERN (this_insn), inloc)	    /* If this is also an output reload, IN cannot be used as	       the reload register if it is set in this insn unless IN	       is also OUT.  */	    && (out == 0 || in == out		|| ! hard_reg_set_here_p (regno,					  (regno					   + HARD_REGNO_NREGS (regno,							       inmode)),					  PATTERN (this_insn)))	    /* ??? Why is this code so different from the previous?	       Is there any simple coherent way to describe the two together?	       What's going on here.  */	    && (in != out		|| (GET_CODE (in) == SUBREG		    && (((GET_MODE_SIZE (GET_MODE (in)) + (UNITS_PER_WORD - 1))			 / UNITS_PER_WORD)			== ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (in)))			     + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD))))	    /* Make sure the operand fits in the reg that dies.  */	    && GET_MODE_SIZE (inmode) <= GET_MODE_SIZE (GET_MODE (XEXP (note, 0)))	    && HARD_REGNO_MODE_OK (regno, inmode)	    && GET_MODE_SIZE (outmode) <= GET_MODE_SIZE (GET_MODE (XEXP (note, 0)))	    && HARD_REGNO_MODE_OK (regno, outmode)	    && TEST_HARD_REG_BIT (reg_class_contents[(int) class], regno)	    && !fixed_regs[regno])	  {	    reload_reg_rtx[i] = gen_rtx (REG, inmode, regno);	    break;	  }    }  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->subreg_loc = 0;      r->mode = mode;    }}/* Transfer all replacements that used to be in reload FROM to be in   reload TO.  */voidtransfer_replacements (to, from)     int to, from;{  int i;  for (i = 0; i < n_replacements; i++)    if (replacements[i].what == from)      replacements[i].what = to;}/* If there is only one output reload, and it is not for an earlyclobber   operand, 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.   If that doesn't work, see we can use any of the registers that   die in this insn as a reload register.  We can if it is of the right   class and does not appear in the value being output-reloaded.  */static voidcombine_reloads (){  int i;  int output_reload = -1;  int secondary_out = -1;  rtx note;  /* 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;  /* If this reload is for an earlyclobber operand, we can't do anything.  */  if (earlyclobber_operand_p (reload_out[output_reload]))    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_ADDRESS	&& reload_when_needed[i] != RELOAD_FOR_OUTADDR_ADDRESS	&& reload_when_needed[i] != RELOAD_OTHER	&& (CLASS_MAX_NREGS (reload_reg_class[i], reload_inmode[i])	    == CLASS_MAX_NREGS (reload_reg_class[output_reload],				reload_outmode[output_reload]))	&& reload_inc[i] == 0	&& reload_reg_rtx[i] == 0#ifdef SECONDARY_MEMORY_NEEDED	/* Don't combine two reloads with different secondary	   memory locations.  */	&& (secondary_memlocs_elim[(int) reload_outmode[output_reload]][reload_opnum[i]] == 0	    || secondary_memlocs_elim[(int) reload_outmode[output_reload]][reload_opnum[output_reload]] == 0	    || rtx_equal_p (secondary_memlocs_elim[(int) reload_outmode[output_reload]][reload_opnum[i]],			    secondary_memlocs_elim[(int) reload_outmode[output_reload]][reload_opnum[output_reload]]))#endif	&& (SMALL_REGISTER_CLASSES	    ? (reload_reg_class[i] == reload_reg_class[output_reload])	    : (reg_class_subset_p (reload_reg_class[i],				   reload_reg_class[output_reload])	       || reg_class_subset_p (reload_reg_class[output_reload],				      reload_reg_class[i])))	&& (MATCHES (reload_in[i], reload_out[output_reload])	    /* Args reversed because the first arg seems to be	       the one that we imagine being modified	       while the second is the one that might be affected.  */	    || (! reg_overlap_mentioned_for_reload_p (reload_out[output_reload],						      reload_in[i])		/* However, if the input is a register that appears inside		   the output, then we also can't share.		   Imagine (set (mem (reg 69)) (plus (reg 69) ...)).		   If the same reload reg is used for both reg 69 and the		   result to be stored in memory, then that result		   will clobber the address of the memory ref.  */		&& ! (GET_CODE (reload_in[i]) == REG		      && reg_overlap_mentioned_for_reload_p (reload_in[i],							     reload_out[output_reload]))))	&& (reg_class_size[(int) reload_reg_class[i]]	    || SMALL_REGISTER_CLASSES)	/* We will allow making things slightly worse by combining an	   input and an output, but no worse than that.  */	&& (reload_when_needed[i] == RELOAD_FOR_INPUT	    || reload_when_needed[i] == RELOAD_FOR_OUTPUT))      {	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_when_needed[i] = RELOAD_OTHER;	/* If the output reload had a secondary reload, copy it.  */	if (reload_secondary_out_reload[output_reload] != -1)	  {	    reload_secondary_out_reload[i]	      = reload_secondary_out_reload[output_reload];	    reload_secondary_out_icode[i]	      = reload_secondary_out_icode[output_reload];	  }#ifdef SECONDARY_MEMORY_NEEDED	/* Copy any secondary MEM.  */	if (secondary_memlocs_elim[(int) reload_outmode[output_reload]][reload_opnum[output_reload]] != 0)	  secondary_memlocs_elim[(int) reload_outmode[output_reload]][reload_opnum[i]]	    = secondary_memlocs_elim[(int) reload_outmode[output_reload]][reload_opnum[output_reload]];#endif	/* If required, minimize the register class.  */	if (reg_class_subset_p (reload_reg_class[output_reload],				reload_reg_class[i]))	  reload_reg_class[i] = reload_reg_class[output_reload];	/* 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;      }  /* If this insn has only one operand that is modified or written (assumed     to be the first),  it must be the one corresponding to this reload.  It     is safe to use anything that dies in this insn for that output provided     that it does not occur in the output (we already know it isn't an     earlyclobber.  If this is an asm insn, give up.  */  if (INSN_CODE (this_insn) == -1)    return;  for (i = 1; i < insn_n_operands[INSN_CODE (this_insn)]; i++)    if (insn_operand_constraint[INSN_CODE (this_insn)][i][0] == '='	|| insn_operand_constraint[INSN_CODE (this_insn)][i][0] == '+')      return;  /* See if some hard register that dies in this insn and is not used in     the output is the right class.  Only works if the register we pick     up can fully hold our output reload.  */  for (note = REG_NOTES (this_insn); note; note = XEXP (note, 1))    if (REG_NOTE_KIND (note) == REG_DEAD	&& GET_CODE (XEXP (note, 0)) == REG	&& ! reg_overlap_mentioned_for_reload_p (XEXP (note, 0),						 reload_out[output_reload])	&& REGNO (XEXP (note, 0)) < FIRST_PSEUDO_REGISTER	&& HARD_REGNO_MODE_OK (REGNO (XEXP (note, 0)), reload_outmode[output_reload])	&& TEST_HARD_REG_BIT (reg_class_contents[(int) reload_reg_class[output_reload]],			      REGNO (XEXP (note, 0)))	&& (HARD_REGNO_NREGS (REGNO (XEXP (note, 0)), reload_outmode[output_reload])	    <= HARD_REGNO_NREGS (REGNO (XEXP (note, 0)), GET_MODE (XEXP (note, 0))))	/* Ensure that a secondary or tertiary reload for this output	   won't want this register.  */        && ((secondary_out = reload_secondary_out_reload[output_reload]) == -1            || (! (TEST_HARD_REG_BIT		    (reg_class_contents[(int) reload_reg_class[secondary_out]],		     REGNO (XEXP (note, 0))))		&& ((secondary_out = reload_secondary_out_reload[secondary_out]) == -1		    ||  ! (TEST_HARD_REG_BIT			   (reg_class_contents[(int) reload_reg_class[secondary_out]],			    REGNO (XEXP (note, 0)))))))	&& ! fixed_regs[REGNO (XEXP (note, 0))])      {	reload_reg_rtx[output_reload] = gen_rtx (REG,						 reload_outmode[output_reload],						 REGNO (XEXP (note, 0)));	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.   EARLYCLOBBER is non-zero if OUT is an earlyclobber operand.  This   puts an additional constraint on being able to use IN for OUT since   IN must not appear elsewhere in the insn (it is assumed that IN itself   is safe from the earlyclobber).  */static rtxfind_dummy_reload (real_in, real_out, inloc, outloc,		   inmode, outmode, class, for_real, earlyclobber)     rtx real_in, real_out;     rtx *inloc, *outloc;     enum machine_mode inmode, outmode;     enum reg_class class;     int for_real;     int earlyclobber;{  rtx in = real_in;  rtx out = real_out;  int in_offset = 0;  int out_offset = 0;  rtx value = 0;  /* If operands exceed a word, we can't use either of them     unless they have the same size.  */  if (GET_MODE_SIZE (outmode) != GET_MODE_SIZE (inmode)      && (GET_MODE_SIZE (outmode) > UNITS_PER_WORD	  || GET_MODE_SIZE (inmode) > UNITS_PER_WORD))    return 0;  /* Find the inside of any subregs.  */  while (GET_CODE (out) == SUBREG)    {      out_offset = SUBREG_WORD (out);      out = SUBREG_REG (out);    }  while (GET_CODE (in) == SUBREG)    {      in_offset = SUBREG_WORD (in);      in = SUBREG_REG (in);    }  /* Narrow down the reg class, the same way push_reload will;     otherwise we might find a dummy now, but push_reload won't.  */  class = PREFERRED_RELOAD_CLASS (in, class);  /* See if OUT will do.  */  if (GET_CODE (out) == REG      && REGNO (out) < FIRST_PSEUDO_REGISTER)    {      register int regno = REGNO (out) + out_offset;      int nwords = HARD_REGNO_NREGS (regno, outmode);      rtx saved_rtx;      /* 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 reload.	 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 throug

⌨️ 快捷键说明

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