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

📄 reload.c

📁 GUN开源阻止下的编译器GCC
💻 C
📖 第 1 页 / 共 5 页
字号:
	mode = inmode;      else	mode = outmode;      if (mode == VOIDmode)	{	  error_for_asm (this_insn, "cannot reload integer constant operand in `asm'");	  mode = word_mode;	  if (in != 0)	    inmode = word_mode;	  if (out != 0)	    outmode = word_mode;	}      for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)	if (HARD_REGNO_MODE_OK (i, mode)	    && TEST_HARD_REG_BIT (reg_class_contents[(int) class], i))	  {	    int nregs = HARD_REGNO_NREGS (i, mode);	    int j;	    for (j = 1; j < nregs; j++)	      if (! TEST_HARD_REG_BIT (reg_class_contents[(int) class], i + j))		break;	    if (j == nregs)	      break;	  }      if (i == FIRST_PSEUDO_REGISTER)	{	  error_for_asm (this_insn, "impossible register constraint in `asm'");	  class = ALL_REGS;	}    }  if (class == NO_REGS)    abort ();  /* We can use an existing reload if the class is right     and at least one of IN and OUT is a match     and the other is at worst neutral.     (A zero compared against anything is neutral.)      If SMALL_REGISTER_CLASSES, don't use existing reloads unless they are     for the same thing since that can cause us to need more reload registers     than we otherwise would.  */  for (i = 0; i < n_reloads; i++)    if ((reg_class_subset_p (class, reload_reg_class[i])	 || reg_class_subset_p (reload_reg_class[i], class))	/* If the existing reload has a register, it must fit our class.  */	&& (reload_reg_rtx[i] == 0	    || TEST_HARD_REG_BIT (reg_class_contents[(int) class],				  true_regnum (reload_reg_rtx[i])))	&& ((in != 0 && MATCHES (reload_in[i], in) && ! dont_share	     && (out == 0 || reload_out[i] == 0 || MATCHES (reload_out[i], out)))	    ||	    (out != 0 && MATCHES (reload_out[i], out)	     && (in == 0 || reload_in[i] == 0 || MATCHES (reload_in[i], in))))	&& (reg_class_size[(int) class] == 1#ifdef SMALL_REGISTER_CLASSES	    || 1#endif	    )	&& MERGABLE_RELOADS (type, reload_when_needed[i],			     opnum, reload_opnum[i]))      break;  /* Reloading a plain reg for input can match a reload to postincrement     that reg, since the postincrement's value is the right value.     Likewise, it can match a preincrement reload, since we regard     the preincrementation as happening before any ref in this insn     to that register.  */  if (i == n_reloads)    for (i = 0; i < n_reloads; i++)      if ((reg_class_subset_p (class, reload_reg_class[i])	   || reg_class_subset_p (reload_reg_class[i], class))	  /* If the existing reload has a register, it must fit our class.  */	  && (reload_reg_rtx[i] == 0	      || TEST_HARD_REG_BIT (reg_class_contents[(int) class],				    true_regnum (reload_reg_rtx[i])))	  && out == 0 && reload_out[i] == 0 && reload_in[i] != 0	  && ((GET_CODE (in) == REG	       && (GET_CODE (reload_in[i]) == POST_INC		   || GET_CODE (reload_in[i]) == POST_DEC		   || GET_CODE (reload_in[i]) == PRE_INC		   || GET_CODE (reload_in[i]) == PRE_DEC)	       && MATCHES (XEXP (reload_in[i], 0), in))	      ||	      (GET_CODE (reload_in[i]) == REG	       && (GET_CODE (in) == POST_INC		   || GET_CODE (in) == POST_DEC		   || GET_CODE (in) == PRE_INC		   || GET_CODE (in) == PRE_DEC)	       && MATCHES (XEXP (in, 0), reload_in[i])))	  && (reg_class_size[(int) class] == 1#ifdef SMALL_REGISTER_CLASSES	      || 1#endif	      )	  && MERGABLE_RELOADS (type, reload_when_needed[i],			       opnum, reload_opnum[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)    {      /* See if we need a secondary reload register to move between CLASS	 and IN or CLASS and OUT.  Get the icode and push any required reloads	 needed for each of them if so.  */#ifdef SECONDARY_INPUT_RELOAD_CLASS      if (in != 0)	secondary_in_reload	  = push_secondary_reload (1, in, opnum, optional, class, inmode, type,				   &secondary_in_icode);#endif#ifdef SECONDARY_OUTPUT_RELOAD_CLASS      if (out != 0 && GET_CODE (out) != SCRATCH)	secondary_out_reload	  = push_secondary_reload (0, out, opnum, optional, class, outmode,				   type, &secondary_out_icode);#endif      /* We found no existing reload suitable for re-use.	 So add an additional reload.  */      i = n_reloads;      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_nocombine[i] = 0;      reload_in_reg[i] = inloc ? *inloc : 0;      reload_opnum[i] = opnum;      reload_when_needed[i] = type;      reload_secondary_in_reload[i] = secondary_in_reload;      reload_secondary_out_reload[i] = secondary_out_reload;      reload_secondary_in_icode[i] = secondary_in_icode;      reload_secondary_out_icode[i] = secondary_out_icode;      reload_secondary_p[i] = 0;      n_reloads++;#ifdef SECONDARY_MEMORY_NEEDED      /* If a memory location is needed for the copy, make one.  */      if (in != 0 && GET_CODE (in) == REG	  && REGNO (in) < FIRST_PSEUDO_REGISTER	  && SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (REGNO (in)),				     class, inmode))	get_secondary_mem (in, inmode, opnum, type);      if (out != 0 && GET_CODE (out) == REG	  && REGNO (out) < FIRST_PSEUDO_REGISTER	  && SECONDARY_MEMORY_NEEDED (class, REGNO_REG_CLASS (REGNO (out)),				      outmode))	get_secondary_mem (out, outmode, opnum, type);#endif    }  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 (inmode != VOIDmode)	reload_inmode[i] = inmode;      if (outmode != VOIDmode)	reload_outmode[i] = outmode;      if (in != 0)	reload_in[i] = in;      if (out != 0)	reload_out[i] = out;      if (reg_class_subset_p (class, reload_reg_class[i]))	reload_reg_class[i] = class;      reload_optional[i] &= optional;      if (MERGE_TO_OTHER (type, reload_when_needed[i],			  opnum, reload_opnum[i]))	reload_when_needed[i] = RELOAD_OTHER;      reload_opnum[i] = MIN (reload_opnum[i], opnum);    }  /* 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->subreg_loc = in_subreg_loc;	  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->subreg_loc = out_subreg_loc;	  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,					     inmode, outmode,					     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 this is an input reload and the operand contains a register that     dies in this insn and is used nowhere else, see if it is the right class     to be used for this reload.  Use it if so.  (This occurs most commonly     in the case of paradoxical SUBREGs and in-out reloads).  We cannot do     this if it is also an output reload that mentions the register unless     the output is a SUBREG that clobbers an entire register.     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;    }}

⌨️ 快捷键说明

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