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

📄 reload1.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 5 页
字号:
  /* From now on, we need to emit any moves without making new pseudos.  */  reload_in_progress = 1;  /* This loop scans the entire function each go-round     and repeats until one repetition spills no additional hard regs.  */  /* This flag is set when a pseudo reg is spilled,     to require another pass.  Note that getting an additional reload     reg does not necessarily imply any pseudo reg was spilled;     sometimes we find a reload reg that no pseudo reg was allocated in.  */  something_changed = 1;  /* This flag is set if there are any insns that require reloading.  */  something_needs_reloads = 0;  /* This flag is set if there are any insns that require register     eliminations.  */  something_needs_elimination = 0;  while (something_changed)    {      rtx after_call = 0;      /* For each class, number of reload regs needed in that class.	 This is the maximum over all insns of the needs in that class	 of the individual insn.  */      int max_needs[N_REG_CLASSES];      /* For each class, size of group of consecutive regs	 that is needed for the reloads of this class.  */      int group_size[N_REG_CLASSES];      /* For each class, max number of consecutive groups needed.	 (Each group contains group_size[CLASS] consecutive registers.)  */      int max_groups[N_REG_CLASSES];      /* For each class, max number needed of regs that don't belong	 to any of the groups.  */      int max_nongroups[N_REG_CLASSES];      /* For each class, the machine mode which requires consecutive	 groups of regs of that class.	 If two different modes ever require groups of one class,	 they must be the same size and equally restrictive for that class,	 otherwise we can't handle the complexity.  */      enum machine_mode group_mode[N_REG_CLASSES];      /* Record the insn where each maximum need is first found.  */      rtx max_needs_insn[N_REG_CLASSES];      rtx max_groups_insn[N_REG_CLASSES];      rtx max_nongroups_insn[N_REG_CLASSES];      rtx x;      int starting_frame_size = get_frame_size ();      int previous_frame_pointer_needed = frame_pointer_needed;      static char *reg_class_names[] = REG_CLASS_NAMES;      something_changed = 0;      bzero ((char *) max_needs, sizeof max_needs);      bzero ((char *) max_groups, sizeof max_groups);      bzero ((char *) max_nongroups, sizeof max_nongroups);      bzero ((char *) max_needs_insn, sizeof max_needs_insn);      bzero ((char *) max_groups_insn, sizeof max_groups_insn);      bzero ((char *) max_nongroups_insn, sizeof max_nongroups_insn);      bzero ((char *) group_size, sizeof group_size);      for (i = 0; i < N_REG_CLASSES; i++)	group_mode[i] = VOIDmode;      /* Keep track of which basic blocks are needing the reloads.  */      this_block = 0;      /* Remember whether any element of basic_block_needs	 changes from 0 to 1 in this pass.  */      new_basic_block_needs = 0;      /* Reset all offsets on eliminable registers to their initial values.  */#ifdef ELIMINABLE_REGS      for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)	{	  INITIAL_ELIMINATION_OFFSET (ep->from, ep->to, ep->initial_offset);	  ep->previous_offset = ep->offset	    = ep->max_offset = ep->initial_offset;	}#else#ifdef INITIAL_FRAME_POINTER_OFFSET      INITIAL_FRAME_POINTER_OFFSET (reg_eliminate[0].initial_offset);#else      if (!FRAME_POINTER_REQUIRED)	abort ();      reg_eliminate[0].initial_offset = 0;#endif      reg_eliminate[0].previous_offset = reg_eliminate[0].max_offset	= reg_eliminate[0].offset = reg_eliminate[0].initial_offset;#endif      num_not_at_initial_offset = 0;      bzero ((char *) &offsets_known_at[get_first_label_num ()], num_labels);      /* Set a known offset for each forced label to be at the initial offset	 of each elimination.  We do this because we assume that all	 computed jumps occur from a location where each elimination is	 at its initial offset.  */      for (x = forced_labels; x; x = XEXP (x, 1))	if (XEXP (x, 0))	  set_label_offsets (XEXP (x, 0), NULL_RTX, 1);      /* For each pseudo register that has an equivalent location defined,	 try to eliminate any eliminable registers (such as the frame pointer)	 assuming initial offsets for the replacement register, which	 is the normal case.	 If the resulting location is directly addressable, substitute	 the MEM we just got directly for the old REG.	 If it is not addressable but is a constant or the sum of a hard reg	 and constant, it is probably not addressable because the constant is	 out of range, in that case record the address; we will generate	 hairy code to compute the address in a register each time it is	 needed.  Similarly if it is a hard register, but one that is not	 valid as an address register.	 If the location is not addressable, but does not have one of the	 above forms, assign a stack slot.  We have to do this to avoid the	 potential of producing lots of reloads if, e.g., a location involves	 a pseudo that didn't get a hard register and has an equivalent memory	 location that also involves a pseudo that didn't get a hard register.	 Perhaps at some point we will improve reload_when_needed handling	 so this problem goes away.  But that's very hairy.  */      for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)	if (reg_renumber[i] < 0 && reg_equiv_memory_loc[i])	  {	    rtx x = eliminate_regs (reg_equiv_memory_loc[i], 0, NULL_RTX);	    if (strict_memory_address_p (GET_MODE (regno_reg_rtx[i]),					 XEXP (x, 0)))	      reg_equiv_mem[i] = x, reg_equiv_address[i] = 0;	    else if (CONSTANT_P (XEXP (x, 0))		     || (GET_CODE (XEXP (x, 0)) == REG			 && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER)		     || (GET_CODE (XEXP (x, 0)) == PLUS			 && GET_CODE (XEXP (XEXP (x, 0), 0)) == REG			 && (REGNO (XEXP (XEXP (x, 0), 0))			     < FIRST_PSEUDO_REGISTER)			 && CONSTANT_P (XEXP (XEXP (x, 0), 1))))	      reg_equiv_address[i] = XEXP (x, 0), reg_equiv_mem[i] = 0;	    else	      {		/* Make a new stack slot.  Then indicate that something		   changed so we go back and recompute offsets for		   eliminable registers because the allocation of memory		   below might change some offset.  reg_equiv_{mem,address}		   will be set up for this pseudo on the next pass around		   the loop.  */		reg_equiv_memory_loc[i] = 0;		reg_equiv_init[i] = 0;		alter_reg (i, -1);		something_changed = 1;	      }	  }      /* If we allocated another pseudo to the stack, redo elimination	 bookkeeping.  */      if (something_changed)	continue;      /* If caller-saves needs a group, initialize the group to include	 the size and mode required for caller-saves.  */      if (caller_save_group_size > 1)	{	  group_mode[(int) caller_save_spill_class] = Pmode;	  group_size[(int) caller_save_spill_class] = caller_save_group_size;	}      /* Compute the most additional registers needed by any instruction.	 Collect information separately for each class of regs.  */      for (insn = first; insn; insn = NEXT_INSN (insn))	{	  if (global && this_block + 1 < n_basic_blocks	      && insn == basic_block_head[this_block+1])	    ++this_block;	  /* If this is a label, a JUMP_INSN, or has REG_NOTES (which	     might include REG_LABEL), we need to see what effects this	     has on the known offsets at labels.  */	  if (GET_CODE (insn) == CODE_LABEL || GET_CODE (insn) == JUMP_INSN	      || (GET_RTX_CLASS (GET_CODE (insn)) == 'i'		  && REG_NOTES (insn) != 0))	    set_label_offsets (insn, insn, 0);	  if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')	    {	      /* Nonzero means don't use a reload reg that overlaps		 the place where a function value can be returned.  */	      rtx avoid_return_reg = 0;	      rtx old_body = PATTERN (insn);	      int old_code = INSN_CODE (insn); 	      rtx old_notes = REG_NOTES (insn);	      int did_elimination = 0;	      /* To compute the number of reload registers of each class 		 needed for an insn, we must simulate what choose_reload_regs		 can do.  We do this by splitting an insn into an "input" and		 an "output" part.  RELOAD_OTHER reloads are used in both. 		 The input part uses those reloads, RELOAD_FOR_INPUT reloads,		 which must be live over the entire input section of reloads,		 and the maximum of all the RELOAD_FOR_INPUT_ADDRESS and		 RELOAD_FOR_OPERAND_ADDRESS reloads, which conflict with the		 inputs.		 The registers needed for output are RELOAD_OTHER and		 RELOAD_FOR_OUTPUT, which are live for the entire output		 portion, and the maximum of all the RELOAD_FOR_OUTPUT_ADDRESS		 reloads for each operand.		 The total number of registers needed is the maximum of the		 inputs and outputs.  */	      struct needs		{		  /* [0] is normal, [1] is nongroup.  */		  int regs[2][N_REG_CLASSES];		  int groups[N_REG_CLASSES];		};	      /* Each `struct needs' corresponds to one RELOAD_... type.  */	      struct {		struct needs other;		struct needs input;		struct needs output;		struct needs insn;		struct needs other_addr;		struct needs op_addr;		struct needs op_addr_reload;		struct needs in_addr[MAX_RECOG_OPERANDS];		struct needs out_addr[MAX_RECOG_OPERANDS];	      } insn_needs;	      /* If needed, eliminate any eliminable registers.  */	      if (num_eliminable)		did_elimination = eliminate_regs_in_insn (insn, 0);#ifdef SMALL_REGISTER_CLASSES	      /* Set avoid_return_reg if this is an insn		 that might use the value of a function call.  */	      if (GET_CODE (insn) == CALL_INSN)		{		  if (GET_CODE (PATTERN (insn)) == SET)		    after_call = SET_DEST (PATTERN (insn));		  else if (GET_CODE (PATTERN (insn)) == PARALLEL			   && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == SET)		    after_call = SET_DEST (XVECEXP (PATTERN (insn), 0, 0));		  else		    after_call = 0;		}	      else if (after_call != 0		       && !(GET_CODE (PATTERN (insn)) == SET			    && SET_DEST (PATTERN (insn)) == stack_pointer_rtx))		{		  if (reg_referenced_p (after_call, PATTERN (insn)))		    avoid_return_reg = after_call;		  after_call = 0;		}#endif /* SMALL_REGISTER_CLASSES */	      /* Analyze the instruction.  */	      find_reloads (insn, 0, spill_indirect_levels, global,			    spill_reg_order);	      /* Remember for later shortcuts which insns had any reloads or		 register eliminations.		 One might think that it would be worthwhile to mark insns		 that need register replacements but not reloads, but this is		 not safe because find_reloads may do some manipulation of		 the insn (such as swapping commutative operands), which would		 be lost when we restore the old pattern after register		 replacement.  So the actions of find_reloads must be redone in		 subsequent passes or in reload_as_needed.		 However, it is safe to mark insns that need reloads		 but not register replacement.  */	      PUT_MODE (insn, (did_elimination ? QImode			       : n_reloads ? HImode			       : GET_MODE (insn) == DImode ? DImode			       : VOIDmode));	      /* Discard any register replacements done.  */	      if (did_elimination)		{		  obstack_free (&reload_obstack, reload_firstobj);		  PATTERN (insn) = old_body;		  INSN_CODE (insn) = old_code; 		  REG_NOTES (insn) = old_notes;		  something_needs_elimination = 1;		}	      /* If this insn has no reloads, we need not do anything except		 in the case of a CALL_INSN when we have caller-saves and		 caller-save needs reloads.  */	      if (n_reloads == 0		  && ! (GET_CODE (insn) == CALL_INSN			&& caller_save_spill_class != NO_REGS))		continue;	      something_needs_reloads = 1;	      bzero ((char *) &insn_needs, sizeof insn_needs);	      /* Count each reload once in every class		 containing the reload's own class.  */	      for (i = 0; i < n_reloads; i++)		{		  register enum reg_class *p;		  enum reg_class class = reload_reg_class[i];		  int size;		  enum machine_mode mode;		  int nongroup_need;		  struct needs *this_needs;		  /* Don't count the dummy reloads, for which one of the		     regs mentioned in the insn can be used for reloading.		     Don't count optional reloads.		     Don't count reloads that got combined with others.  */		  if (reload_reg_rtx[i] != 0		      || reload_optional[i] != 0		      || (reload_out[i] == 0 && reload_in[i] == 0			  && ! reload_secondary_p[i]))  		    continue;		  /* Show that a reload register of this class is needed		     in this basic block.  We do not use insn_needs and		     insn_groups because they are overly conservative for		     this purpose.  */		  if (global && ! basic_block_needs[(int) class][this_block])		    {		      basic_block_needs[(int) class][this_block] = 1;		      new_basic_block_needs = 1;		    }		  mode = reload_inmode[i];		  if (GET_MODE_SIZE (reload_outmode[i]) > GET_MODE_SIZE (mode))		    mode = reload_outmode[i];		  size = CLASS_MAX_NREGS (class, mode);		  /* If this class doesn't want a group, determine if we have		     a nongroup need or a regular need.  We have a nongroup		     need if this reload conflicts with a group reload whose		     class intersects with this reload's class.  */		  nongroup_need = 0;		  if (size == 1)		    for (j = 0; j < n_reloads; j++)		      if ((CLASS_MAX_NREGS (reload_reg_class[j],					    (GET_MODE_SIZE (reload_outmode[j])					     > GET_MODE_SIZE (reload_inmode[j]))					    ? reload_outmode[j]					    : reload_inmode[j])			   > 1)			  && (!reload_optional[j])			  && (reload_in[j] != 0 || reload_out[j] != 0			      || reload_secondary_p[j])			  && reloads_conflict (i, j)

⌨️ 快捷键说明

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