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

📄 reload.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 5 页
字号:
    secondary_type = type;  else    secondary_type = in_p ? RELOAD_FOR_INPUT_ADDRESS : RELOAD_FOR_OUTPUT_ADDRESS;  *picode = CODE_FOR_nothing;  /* If X is a paradoxical SUBREG, use the inner value to determine both the     mode and object being reloaded.  */  if (GET_CODE (x) == SUBREG      && (GET_MODE_SIZE (GET_MODE (x))	  > GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))))    {      x = SUBREG_REG (x);      reload_mode = GET_MODE (x);    }  /* If X is a pseudo-register that has an equivalent MEM (actually, if it     is still a pseudo-register by now, it *must* have an equivalent MEM     but we don't want to assume that), use that equivalent when seeing if     a secondary reload is needed since whether or not a reload is needed     might be sensitive to the form of the MEM.  */  if (GET_CODE (x) == REG && REGNO (x) >= FIRST_PSEUDO_REGISTER      && reg_equiv_mem[REGNO (x)] != 0)    x = reg_equiv_mem[REGNO (x)];#ifdef SECONDARY_INPUT_RELOAD_CLASS  if (in_p)    class = SECONDARY_INPUT_RELOAD_CLASS (reload_class, reload_mode, x);#endif#ifdef SECONDARY_OUTPUT_RELOAD_CLASS  if (! in_p)    class = SECONDARY_OUTPUT_RELOAD_CLASS (reload_class, reload_mode, x);#endif  /* If we don't need any secondary registers, done.  */  if (class == NO_REGS)    return -1;  /* Get a possible insn to use.  If the predicate doesn't accept X, don't     use the insn.  */  icode = (in_p ? reload_in_optab[(int) reload_mode]	   : reload_out_optab[(int) reload_mode]);  if (icode != CODE_FOR_nothing      && insn_operand_predicate[(int) icode][in_p]      && (! (insn_operand_predicate[(int) icode][in_p]) (x, reload_mode)))    icode = CODE_FOR_nothing;  /* If we will be using an insn, see if it can directly handle the reload     register we will be using.  If it can, the secondary reload is for a     scratch register.  If it can't, we will use the secondary reload for     an intermediate register and require a tertiary reload for the scratch     register.  */  if (icode != CODE_FOR_nothing)    {      /* If IN_P is non-zero, the reload register will be the output in 	 operand 0.  If IN_P is zero, the reload register will be the input	 in operand 1.  Outputs should have an initial "=", which we must	 skip.  */      char insn_letter = insn_operand_constraint[(int) icode][!in_p][in_p];      enum reg_class insn_class	= (insn_letter == 'r' ? GENERAL_REGS	   : REG_CLASS_FROM_LETTER (insn_letter));      if (insn_class == NO_REGS	  || (in_p && insn_operand_constraint[(int) icode][!in_p][0] != '=')	  /* The scratch register's constraint must start with "=&".  */	  || insn_operand_constraint[(int) icode][2][0] != '='	  || insn_operand_constraint[(int) icode][2][1] != '&')	abort ();      if (reg_class_subset_p (reload_class, insn_class))	mode = insn_operand_mode[(int) icode][2];      else	{	  char t_letter = insn_operand_constraint[(int) icode][2][2];	  class = insn_class;	  t_mode = insn_operand_mode[(int) icode][2];	  t_class = (t_letter == 'r' ? GENERAL_REGS		     : REG_CLASS_FROM_LETTER (t_letter));	  t_icode = icode;	  icode = CODE_FOR_nothing;	}    }  /* This case isn't valid, so fail.  Reload is allowed to use the same     register for RELOAD_FOR_INPUT_ADDRESS and RELOAD_FOR_INPUT reloads, but     in the case of a secondary register, we actually need two different     registers for correct code.  We fail here to prevent the possibility of     silently generating incorrect code later.     The convention is that secondary input reloads are valid only if the     secondary_class is different from class.  If you have such a case, you     can not use secondary reloads, you must work around the problem some     other way.     Allow this when MODE is not reload_mode and assume that the generated     code handles this case (it does on the Alpha, which is the only place     this currently happens).  */  if (in_p && class == reload_class && mode == reload_mode)    abort ();  /* If we need a tertiary reload, see if we have one we can reuse or else     make a new one.  */  if (t_class != NO_REGS)    {      for (t_reload = 0; t_reload < n_reloads; t_reload++)	if (reload_secondary_p[t_reload]	    && (reg_class_subset_p (t_class, reload_reg_class[t_reload])		|| reg_class_subset_p (reload_reg_class[t_reload], t_class))	    && ((in_p && reload_inmode[t_reload] == t_mode)		|| (! in_p && reload_outmode[t_reload] == t_mode))	    && ((in_p && (reload_secondary_in_icode[t_reload]			  == CODE_FOR_nothing))		|| (! in_p &&(reload_secondary_out_icode[t_reload]			      == CODE_FOR_nothing)))	    && (reg_class_size[(int) t_class] == 1#ifdef SMALL_REGISTER_CLASSES		|| 1#endif		)	    && MERGABLE_RELOADS (secondary_type,				 reload_when_needed[t_reload],				 opnum, reload_opnum[t_reload]))	  {	    if (in_p)	      reload_inmode[t_reload] = t_mode;	    if (! in_p)	      reload_outmode[t_reload] = t_mode;	    if (reg_class_subset_p (t_class, reload_reg_class[t_reload]))	      reload_reg_class[t_reload] = t_class;	    reload_opnum[t_reload] = MIN (reload_opnum[t_reload], opnum);	    reload_optional[t_reload] &= optional;	    reload_secondary_p[t_reload] = 1;	    if (MERGE_TO_OTHER (secondary_type, reload_when_needed[t_reload],				opnum, reload_opnum[t_reload]))	      reload_when_needed[t_reload] = RELOAD_OTHER;	  }      if (t_reload == n_reloads)	{	  /* We need to make a new tertiary reload for this register class.  */	  reload_in[t_reload] = reload_out[t_reload] = 0;	  reload_reg_class[t_reload] = t_class;	  reload_inmode[t_reload] = in_p ? t_mode : VOIDmode;	  reload_outmode[t_reload] = ! in_p ? t_mode : VOIDmode;	  reload_reg_rtx[t_reload] = 0;	  reload_optional[t_reload] = optional;	  reload_inc[t_reload] = 0;	  /* Maybe we could combine these, but it seems too tricky.  */	  reload_nocombine[t_reload] = 1;	  reload_in_reg[t_reload] = 0;	  reload_opnum[t_reload] = opnum;	  reload_when_needed[t_reload] = secondary_type;	  reload_secondary_in_reload[t_reload] = -1;	  reload_secondary_out_reload[t_reload] = -1;	  reload_secondary_in_icode[t_reload] = CODE_FOR_nothing;	  reload_secondary_out_icode[t_reload] = CODE_FOR_nothing;	  reload_secondary_p[t_reload] = 1;	  n_reloads++;	}    }  /* See if we can reuse an existing secondary reload.  */  for (s_reload = 0; s_reload < n_reloads; s_reload++)    if (reload_secondary_p[s_reload]	&& (reg_class_subset_p (class, reload_reg_class[s_reload])	    || reg_class_subset_p (reload_reg_class[s_reload], class))	&& ((in_p && reload_inmode[s_reload] == mode)	    || (! in_p && reload_outmode[s_reload] == mode))	&& ((in_p && reload_secondary_in_reload[s_reload] == t_reload)	    || (! in_p && reload_secondary_out_reload[s_reload] == t_reload))	&& ((in_p && reload_secondary_in_icode[s_reload] == t_icode)	    || (! in_p && reload_secondary_out_icode[s_reload] == t_icode))	&& (reg_class_size[(int) class] == 1#ifdef SMALL_REGISTER_CLASSES	    || 1#endif	    )	&& MERGABLE_RELOADS (secondary_type, reload_when_needed[s_reload],			     opnum, reload_opnum[s_reload]))      {	if (in_p)	  reload_inmode[s_reload] = mode;	if (! in_p)	  reload_outmode[s_reload] = mode;	if (reg_class_subset_p (class, reload_reg_class[s_reload]))	  reload_reg_class[s_reload] = class;	reload_opnum[s_reload] = MIN (reload_opnum[s_reload], opnum);	reload_optional[s_reload] &= optional;	reload_secondary_p[s_reload] = 1;	if (MERGE_TO_OTHER (secondary_type, reload_when_needed[s_reload],			    opnum, reload_opnum[s_reload]))	  reload_when_needed[s_reload] = RELOAD_OTHER;      }  if (s_reload == n_reloads)    {      /* We need to make a new secondary reload for this register class.  */      reload_in[s_reload] = reload_out[s_reload] = 0;      reload_reg_class[s_reload] = class;      reload_inmode[s_reload] = in_p ? mode : VOIDmode;      reload_outmode[s_reload] = ! in_p ? mode : VOIDmode;      reload_reg_rtx[s_reload] = 0;      reload_optional[s_reload] = optional;      reload_inc[s_reload] = 0;      /* Maybe we could combine these, but it seems too tricky.  */      reload_nocombine[s_reload] = 1;      reload_in_reg[s_reload] = 0;      reload_opnum[s_reload] = opnum;      reload_when_needed[s_reload] = secondary_type;      reload_secondary_in_reload[s_reload] = in_p ? t_reload : -1;      reload_secondary_out_reload[s_reload] = ! in_p ? t_reload : -1;      reload_secondary_in_icode[s_reload] = in_p ? t_icode : CODE_FOR_nothing;       reload_secondary_out_icode[s_reload]	= ! in_p ? t_icode : CODE_FOR_nothing;      reload_secondary_p[s_reload] = 1;      n_reloads++;#ifdef SECONDARY_MEMORY_NEEDED      /* If we need a memory location to copy between the two reload regs,	 set it up now.  */      if (in_p && icode == CODE_FOR_nothing	  && SECONDARY_MEMORY_NEEDED (class, reload_class, reload_mode))	get_secondary_mem (x, reload_mode, opnum, type);      if (! in_p && icode == CODE_FOR_nothing	  && SECONDARY_MEMORY_NEEDED (reload_class, class, reload_mode))	get_secondary_mem (x, reload_mode, opnum, type);#endif    }  *picode = icode;  return s_reload;}#endif /* HAVE_SECONDARY_RELOADS */#ifdef SECONDARY_MEMORY_NEEDED/* Return a memory location that will be used to copy X in mode MODE.     If we haven't already made a location for this mode in this insn,   call find_reloads_address on the location being returned.  */rtxget_secondary_mem (x, mode, opnum, type)     rtx x;     enum machine_mode mode;     int opnum;     enum reload_type type;{  rtx loc;  int mem_valid;  /* By default, if MODE is narrower than a word, widen it to a word.     This is required because most machines that require these memory     locations do not support short load and stores from all registers     (e.g., FP registers).  */#ifdef SECONDARY_MEMORY_NEEDED_MODE  mode = SECONDARY_MEMORY_NEEDED_MODE (mode);#else  if (GET_MODE_BITSIZE (mode) < BITS_PER_WORD)    mode = mode_for_size (BITS_PER_WORD, GET_MODE_CLASS (mode), 0);#endif  /* If we already have made a MEM for this operand in MODE, return it.  */  if (secondary_memlocs_elim[(int) mode][opnum] != 0)    return secondary_memlocs_elim[(int) mode][opnum];  /* If this is the first time we've tried to get a MEM for this mode,      allocate a new one.  `something_changed' in reload will get set     by noticing that the frame size has changed.  */  if (secondary_memlocs[(int) mode] == 0)    {#ifdef SECONDARY_MEMORY_NEEDED_RTX      secondary_memlocs[(int) mode] = SECONDARY_MEMORY_NEEDED_RTX (mode);#else      secondary_memlocs[(int) mode]	= assign_stack_local (mode, GET_MODE_SIZE (mode), 0);#endif    }  /* Get a version of the address doing any eliminations needed.  If that     didn't give us a new MEM, make a new one if it isn't valid.  */  loc = eliminate_regs (secondary_memlocs[(int) mode], VOIDmode, NULL_RTX);  mem_valid = strict_memory_address_p (mode, XEXP (loc, 0));  if (! mem_valid && loc == secondary_memlocs[(int) mode])    loc = copy_rtx (loc);  /* The only time the call below will do anything is if the stack     offset is too large.  In that case IND_LEVELS doesn't matter, so we     can just pass a zero.  Adjust the type to be the address of the     corresponding object.  If the address was valid, save the eliminated     address.  If it wasn't valid, we need to make a reload each time, so     don't save it.  */  if (! mem_valid)    {      type =  (type == RELOAD_FOR_INPUT ? RELOAD_FOR_INPUT_ADDRESS	       : type == RELOAD_FOR_OUTPUT ? RELOAD_FOR_OUTPUT_ADDRESS	       : RELOAD_OTHER);      find_reloads_address (mode, NULL_PTR, XEXP (loc, 0), &XEXP (loc, 0),			    opnum, type, 0);    }  secondary_memlocs_elim[(int) mode][opnum] = loc;  return loc;}/* Clear any secondary memory locations we've made.  */voidclear_secondary_mem (){  bzero ((char *) secondary_memlocs, sizeof secondary_memlocs);}#endif /* SECONDARY_MEMORY_NEEDED *//* 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.

⌨️ 快捷键说明

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