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

📄 reload.c

📁 GCC编译器源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
  return loc;}/* Clear any secondary memory locations we've made.  */voidclear_secondary_mem (){  bzero ((char *) secondary_memlocs, sizeof secondary_memlocs);}#endif /* SECONDARY_MEMORY_NEEDED *//* Find the largest class for which every register number plus N is valid in   M1 (if in range).  Abort if no such class exists.  */static enum reg_classfind_valid_class (m1, n)     enum machine_mode  m1;     int n;{  int class;  int regno;  enum reg_class best_class;  int best_size = 0;  for (class = 1; class < N_REG_CLASSES; class++)    {      int bad = 0;      for (regno = 0; regno < FIRST_PSEUDO_REGISTER && ! bad; regno++)	if (TEST_HARD_REG_BIT (reg_class_contents[class], regno)	    && TEST_HARD_REG_BIT (reg_class_contents[class], regno + n)	    && ! HARD_REGNO_MODE_OK (regno + n, m1))	  bad = 1;      if (! bad && reg_class_size[class] > best_size)	best_class = class, best_size = reg_class_size[class];    }  if (best_size == 0)    abort ();  return best_class;}/* Record one reload that needs to be performed.   IN is an rtx saying where the data are to be found before this instruction.   OUT says where they must be stored after the instruction.   (IN is zero for data not read, and OUT is zero for data not written.)   INLOC and OUTLOC point to the places in the instructions where   IN and OUT were found.   If IN and OUT are both non-zero, it means the same register must be used   to reload both IN and OUT.   CLASS is a register class required for the reloaded data.   INMODE is the machine mode that the instruction requires   for the reg that replaces IN and OUTMODE is likewise for OUT.   If IN is zero, then OUT's location and mode should be passed as   INLOC and INMODE.   STRICT_LOW is the 1 if there is a containing STRICT_LOW_PART rtx.   OPTIONAL nonzero means this reload does not need to be performed:   it can be discarded if that is more convenient.   OPNUM and TYPE say what the purpose of this reload is.   The return value is the reload-number for this reload.   If both IN and OUT are nonzero, in some rare cases we might   want to make two separate reloads.  (Actually we never do this now.)   Therefore, the reload-number for OUT is stored in   output_reloadnum when we return; the return value applies to IN.   Usually (presently always), when IN and OUT are nonzero,   the two reload-numbers are equal, but the caller should be careful to   distinguish them.  */static intpush_reload (in, out, inloc, outloc, class,	     inmode, outmode, strict_low, optional, opnum, type)     register rtx in, out;     rtx *inloc, *outloc;     enum reg_class class;     enum machine_mode inmode, outmode;     int strict_low;     int optional;     int opnum;     enum reload_type type;{  register int i;  int dont_share = 0;  int dont_remove_subreg = 0;  rtx *in_subreg_loc = 0, *out_subreg_loc = 0;  int secondary_in_reload = -1, secondary_out_reload = -1;  enum insn_code secondary_in_icode = CODE_FOR_nothing;  enum insn_code secondary_out_icode = CODE_FOR_nothing;  /* INMODE and/or OUTMODE could be VOIDmode if no mode     has been specified for the operand.  In that case,     use the operand's mode as the mode to reload.  */  if (inmode == VOIDmode && in != 0)    inmode = GET_MODE (in);  if (outmode == VOIDmode && out != 0)    outmode = GET_MODE (out);  /* If IN is a pseudo register everywhere-equivalent to a constant, and      it is not in a hard register, reload straight from the constant,     since we want to get rid of such pseudo registers.     Often this is done earlier, but not always in find_reloads_address.  */  if (in != 0 && GET_CODE (in) == REG)    {      register int regno = REGNO (in);      if (regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] < 0	  && reg_equiv_constant[regno] != 0)	in = reg_equiv_constant[regno];    }  /* Likewise for OUT.  Of course, OUT will never be equivalent to     an actual constant, but it might be equivalent to a memory location     (in the case of a parameter).  */  if (out != 0 && GET_CODE (out) == REG)    {      register int regno = REGNO (out);      if (regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] < 0	  && reg_equiv_constant[regno] != 0)	out = reg_equiv_constant[regno];    }  /* If we have a read-write operand with an address side-effect,     change either IN or OUT so the side-effect happens only once.  */  if (in != 0 && out != 0 && GET_CODE (in) == MEM && rtx_equal_p (in, out))    {      if (GET_CODE (XEXP (in, 0)) == POST_INC	  || GET_CODE (XEXP (in, 0)) == POST_DEC)	in = gen_rtx (MEM, GET_MODE (in), XEXP (XEXP (in, 0), 0));      if (GET_CODE (XEXP (in, 0)) == PRE_INC	  || GET_CODE (XEXP (in, 0)) == PRE_DEC)	out = gen_rtx (MEM, GET_MODE (out), XEXP (XEXP (out, 0), 0));    }  /* If we are reloading a (SUBREG constant ...), really reload just the     inside expression in its own mode.  Similarly for (SUBREG (PLUS ...)).     If we have (SUBREG:M1 (MEM:M2 ...) ...) (or an inner REG that is still     a pseudo and hence will become a MEM) with M1 wider than M2 and the     register is a pseudo, also reload the inside expression.     For machines that extend byte loads, do this for any SUBREG of a pseudo     where both M1 and M2 are a word or smaller, M1 is wider than M2, and     M2 is an integral mode that gets extended when loaded.     Similar issue for (SUBREG:M1 (REG:M2 ...) ...) for a hard register R where     either M1 is not valid for R or M2 is wider than a word but we only     need one word to store an M2-sized quantity in R.     (However, if OUT is nonzero, we need to reload the reg *and*     the subreg, so do nothing here, and let following statement handle it.)     Note that the case of (SUBREG (CONST_INT...)...) is handled elsewhere;     we can't handle it here because CONST_INT does not indicate a mode.     Similarly, we must reload the inside expression if we have a     STRICT_LOW_PART (presumably, in == out in the cas).     Also reload the inner expression if it does not require a secondary     reload but the SUBREG does.     Finally, reload the inner expression if it is a register that is in     the class whose registers cannot be referenced in a different size     and M1 is not the same size as M2.  If SUBREG_WORD is nonzero, we     cannot reload just the inside since we might end up with the wrong     register class.  */  if (in != 0 && GET_CODE (in) == SUBREG && SUBREG_WORD (in) == 0#ifdef CLASS_CANNOT_CHANGE_SIZE      && class != CLASS_CANNOT_CHANGE_SIZE#endif      && (CONSTANT_P (SUBREG_REG (in))	  || GET_CODE (SUBREG_REG (in)) == PLUS	  || strict_low	  || (((GET_CODE (SUBREG_REG (in)) == REG		&& REGNO (SUBREG_REG (in)) >= FIRST_PSEUDO_REGISTER)	       || GET_CODE (SUBREG_REG (in)) == MEM)	      && ((GET_MODE_SIZE (inmode)		   > GET_MODE_SIZE (GET_MODE (SUBREG_REG (in))))#ifdef LOAD_EXTEND_OP		  || (GET_MODE_SIZE (inmode) <= UNITS_PER_WORD		      && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (in)))			  <= UNITS_PER_WORD)		      && (GET_MODE_SIZE (inmode)			  > GET_MODE_SIZE (GET_MODE (SUBREG_REG (in))))		      && INTEGRAL_MODE_P (GET_MODE (SUBREG_REG (in)))		      && LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (in))) != NIL)#endif		  ))	  || (GET_CODE (SUBREG_REG (in)) == REG	      && REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER	      /* The case where out is nonzero		 is handled differently in the following statement.  */	      && (out == 0 || SUBREG_WORD (in) == 0)	      && ((GET_MODE_SIZE (inmode) <= UNITS_PER_WORD		   && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (in)))		       > UNITS_PER_WORD)		   && ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (in)))			/ UNITS_PER_WORD)		       != HARD_REGNO_NREGS (REGNO (SUBREG_REG (in)),					    GET_MODE (SUBREG_REG (in)))))		  || ! HARD_REGNO_MODE_OK ((REGNO (SUBREG_REG (in))					    + SUBREG_WORD (in)),					   inmode)))#ifdef SECONDARY_INPUT_RELOAD_CLASS	  || (SECONDARY_INPUT_RELOAD_CLASS (class, inmode, in) != NO_REGS	      && (SECONDARY_INPUT_RELOAD_CLASS (class,						GET_MODE (SUBREG_REG (in)),						SUBREG_REG (in))		  == NO_REGS))#endif#ifdef CLASS_CANNOT_CHANGE_SIZE	  || (GET_CODE (SUBREG_REG (in)) == REG	      && REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER	      && (TEST_HARD_REG_BIT		  (reg_class_contents[(int) CLASS_CANNOT_CHANGE_SIZE],		   REGNO (SUBREG_REG (in))))	      && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (in)))		  != GET_MODE_SIZE (inmode)))#endif	  ))    {      in_subreg_loc = inloc;      inloc = &SUBREG_REG (in);      in = *inloc;#ifndef LOAD_EXTEND_OP      if (GET_CODE (in) == MEM)	/* This is supposed to happen only for paradoxical subregs made by	   combine.c.  (SUBREG (MEM)) isn't supposed to occur other ways.  */	if (GET_MODE_SIZE (GET_MODE (in)) > GET_MODE_SIZE (inmode))	  abort ();#endif      inmode = GET_MODE (in);    }  /* Similar issue for (SUBREG:M1 (REG:M2 ...) ...) for a hard register R where     either M1 is not valid for R or M2 is wider than a word but we only     need one word to store an M2-sized quantity in R.     However, we must reload the inner reg *as well as* the subreg in     that case.  */  /* Similar issue for (SUBREG constant ...) if it was not handled by the     code above.  This can happen if SUBREG_WORD != 0.  */  if (in != 0 && GET_CODE (in) == SUBREG      && (CONSTANT_P (SUBREG_REG (in))	  || (GET_CODE (SUBREG_REG (in)) == REG	      && REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER	      && (! HARD_REGNO_MODE_OK (REGNO (SUBREG_REG (in))					+ SUBREG_WORD (in),					inmode)		  || (GET_MODE_SIZE (inmode) <= UNITS_PER_WORD		      && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (in)))			  > UNITS_PER_WORD)		      && ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (in)))			   / UNITS_PER_WORD)			  != HARD_REGNO_NREGS (REGNO (SUBREG_REG (in)),					       GET_MODE (SUBREG_REG (in)))))))))    {      /* This relies on the fact that emit_reload_insns outputs the	 instructions for input reloads of type RELOAD_OTHER in the same	 order as the reloads.  Thus if the outer reload is also of type	 RELOAD_OTHER, we are guaranteed that this inner reload will be	 output before the outer reload.  */      push_reload (SUBREG_REG (in), NULL_RTX, &SUBREG_REG (in), NULL_PTR,		   find_valid_class (inmode, SUBREG_WORD (in)),		   VOIDmode, VOIDmode, 0, 0, opnum, type);      dont_remove_subreg = 1;    }  /* Similarly for paradoxical and problematical SUBREGs on the output.     Note that there is no reason we need worry about the previous value     of SUBREG_REG (out); even if wider than out,     storing in a subreg is entitled to clobber it all     (except in the case of STRICT_LOW_PART,     and in that case the constraint should label it input-output.)  */  if (out != 0 && GET_CODE (out) == SUBREG && SUBREG_WORD (out) == 0#ifdef CLASS_CANNOT_CHANGE_SIZE      && class != CLASS_CANNOT_CHANGE_SIZE#endif      && (CONSTANT_P (SUBREG_REG (out))	  || strict_low	  || (((GET_CODE (SUBREG_REG (out)) == REG		&& REGNO (SUBREG_REG (out)) >= FIRST_PSEUDO_REGISTER)	       || GET_CODE (SUBREG_REG (out)) == MEM)	      && ((GET_MODE_SIZE (outmode)		   > GET_MODE_SIZE (GET_MODE (SUBREG_REG (out))))))	  || (GET_CODE (SUBREG_REG (out)) == REG	      && REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER	      && ((GET_MODE_SIZE (outmode) <= UNITS_PER_WORD		   && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (out)))		       > UNITS_PER_WORD)		   && ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (out)))			/ UNITS_PER_WORD)		       != HARD_REGNO_NREGS (REGNO (SUBREG_REG (out)),					    GET_MODE (SUBREG_REG (out)))))		  || ! HARD_REGNO_MODE_OK ((REGNO (SUBREG_REG (out))					    + SUBREG_WORD (out)),					   outmode)))#ifdef SECONDARY_OUTPUT_RELOAD_CLASS	  || (SECONDARY_OUTPUT_RELOAD_CLASS (class, outmode, out) != NO_REGS	      && (SECONDARY_OUTPUT_RELOAD_CLASS (class,						 GET_MODE (SUBREG_REG (out)),						 SUBREG_REG (out))		  == NO_REGS))#endif#ifdef CLASS_CANNOT_CHANGE_SIZE	  || (GET_CODE (SUBREG_REG (out)) == REG	      && REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER	      && (TEST_HARD_REG_BIT		  (reg_class_contents[(int) CLASS_CANNOT_CHANGE_SIZE],		   REGNO (SUBREG_REG (out))))	      && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (out)))		  != GET_MODE_SIZE (outmode)))#endif	  ))    {      out_subreg_loc = outloc;      outloc = &SUBREG_REG (out);      out = *outloc; #ifndef LOAD_EXTEND_OP     if (GET_CODE (out) == MEM	  && GET_MODE_SIZE (GET_MODE (out)) > GET_MODE_SIZE (outmode))	abort ();#endif      outmode = GET_MODE (out);    }  /* Similar issue for (SUBREG:M1 (REG:M2 ...) ...) for a hard register R where     either M1 is not valid for R or M2 is wider than a word but we only     need one word to store an M2-sized quantity in R.     However, we must reload the inner reg *as well as* the subreg in     that case.  In this case, the inner reg is an in-out reload.  */  if (out != 0 && GET_CODE (out) == SUBREG      && GET_CODE (SUBREG_REG (out)) == REG      && REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER      && (! HARD_REGNO_MODE_OK (REGNO (SUBREG_REG (out)) + SUBREG_WORD (out),				outmode)	  || (GET_MODE_SIZE (outmode) <= UNITS_PER_WORD	      && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (out)))		  > UNITS_PER_WORD)

⌨️ 快捷键说明

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