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

📄 reload1.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
#ifdef SMALL_REGISTER_CLASSES  CLEAR_HARD_REG_SET (forbidden_regs);#else  COPY_HARD_REG_SET (forbidden_regs, bad_spill_regs);#endif  /* Spill any hard regs that we know we can't eliminate.  */  for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)    if (! ep->can_eliminate)      {	spill_hard_reg (ep->from, global, dumpfile, 1);	regs_ever_live[ep->from] = 1;      }  if (global)    for (i = 0; i < N_REG_CLASSES; i++)      {	basic_block_needs[i] = (char *)alloca (n_basic_blocks);	bzero (basic_block_needs[i], n_basic_blocks);      }  /* 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 ();      static char *reg_class_names[] = REG_CLASS_NAMES;      something_changed = 0;      bzero (max_needs, sizeof max_needs);      bzero (max_groups, sizeof max_groups);      bzero (max_nongroups, sizeof max_nongroups);      bzero (max_needs_insn, sizeof max_needs_insn);      bzero (max_groups_insn, sizeof max_groups_insn);      bzero (max_nongroups_insn, sizeof max_nongroups_insn);      bzero (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 (&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.	 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)) == 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;	      /* Initially, count RELOAD_OTHER reloads.		 Later, merge in the other kinds.  */	      int insn_needs[N_REG_CLASSES];	      int insn_groups[N_REG_CLASSES];	      int insn_total_groups = 0;	      /* Count RELOAD_FOR_INPUT_RELOAD_ADDRESS reloads.  */	      int insn_needs_for_inputs[N_REG_CLASSES];	      int insn_groups_for_inputs[N_REG_CLASSES];	      int insn_total_groups_for_inputs = 0;	      /* Count RELOAD_FOR_OUTPUT_RELOAD_ADDRESS reloads.  */	      int insn_needs_for_outputs[N_REG_CLASSES];	      int insn_groups_for_outputs[N_REG_CLASSES];	      int insn_total_groups_for_outputs = 0;	      /* Count RELOAD_FOR_OPERAND_ADDRESS reloads.  */	      int insn_needs_for_operands[N_REG_CLASSES];	      int insn_groups_for_operands[N_REG_CLASSES];	      int insn_total_groups_for_operands = 0;#if 0  /* This wouldn't work nowadays, since optimize_bit_field	  looks for non-strict memory addresses.  */	      /* Optimization: a bit-field instruction whose field		 happens to be a byte or halfword in memory		 can be changed to a move instruction.  */	      if (GET_CODE (PATTERN (insn)) == SET)		{		  rtx dest = SET_DEST (PATTERN (insn));		  rtx src = SET_SRC (PATTERN (insn));		  if (GET_CODE (dest) == ZERO_EXTRACT		      || GET_CODE (dest) == SIGN_EXTRACT)		    optimize_bit_field (PATTERN (insn), insn, reg_equiv_mem);		  if (GET_CODE (src) == ZERO_EXTRACT		      || GET_CODE (src) == SIGN_EXTRACT)		    optimize_bit_field (PATTERN (insn), insn, reg_equiv_mem);		}#endif	      /* 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_mentioned_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			       : 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;	      for (i = 0; i < N_REG_CLASSES; i++)		{		  insn_needs[i] = 0, insn_groups[i] = 0;		  insn_needs_for_inputs[i] = 0, insn_groups_for_inputs[i] = 0;		  insn_needs_for_outputs[i] = 0, insn_groups_for_outputs[i] = 0;		  insn_needs_for_operands[i] = 0, insn_groups_for_operands[i] = 0;		}	      /* 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 *this_groups;		  int *this_needs;		  int *this_total_groups;		  /* 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;		    }		  /* Decide which time-of-use to count this reload for.  */		  switch (reload_when_needed[i])

⌨️ 快捷键说明

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