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

📄 reload1.c

📁 这是完整的gcc源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
  n_spills++;  return val;}/* Scan all insns, computing the stack depth, and convert all   frame-pointer-relative references to stack-pointer-relative references.  */static voideliminate_frame_pointer (first)     rtx first;{  int depth = 0;  int max_uid = get_max_uid ();  int *label_depth = (int *) alloca ((max_uid + 1) * sizeof (int));  int i;  rtx insn;  for (i = 0; i <= max_uid; i++)    label_depth[i] = -1;  /* In this loop, for each forward branch we record the stack     depth of the label it jumps to.  We take advantage of the fact     that the stack depth at a label reached by a backward branch     is always, in GCC output, equal to the stack depth of the preceding     unconditional jump, because it was either a loop statement or     statement label.  */  for (insn = first; insn; insn = NEXT_INSN (insn))    {      rtx pattern = PATTERN (insn);      switch (GET_CODE (insn))	{	case INSN:	  frame_pointer_address_altered = 0;	  alter_frame_pointer_addresses (pattern, depth);	  /* Rerecognize insn if changed.  */	  if (frame_pointer_address_altered)	    {	      int old_code = INSN_CODE (insn);	      INSN_CODE (insn) = -1;	      /* It can happen that we fail to recognize the insn now		 because a pseudoreg inside an address got allocated		 to a hard reg that isn't valid for the address.		 When this happens, chances are it really still fits the		 same pattern as before.		 This is not a real fix for the bug, but it is safer than		 any real fix, and it should hold things till version 2		 comes out.  */	      if (recog_memoized (insn) < 0)		INSN_CODE (insn) = old_code;	    }	  /* Notice pushes and pops; update DEPTH.  */	  if (GET_CODE (pattern) == SET)	    {#ifdef PUSH_ROUNDING	      if (push_operand (SET_DEST (pattern),				GET_MODE (SET_DEST (pattern))))		depth += PUSH_ROUNDING (GET_MODE_SIZE (GET_MODE (SET_DEST (pattern))));#endif	      if (GET_CODE (SET_DEST (pattern)) == REG		  && REGNO (SET_DEST (pattern)) == STACK_POINTER_REGNUM)		{		  int delta;		  if (GET_CODE (SET_SRC (pattern)) == PLUS		      && GET_CODE (XEXP (SET_SRC (pattern), 0)) == REG		      && REGNO (XEXP (SET_SRC (pattern), 0)) == STACK_POINTER_REGNUM)		    delta = INTVAL (XEXP (SET_SRC (pattern), 1));		  else if (GET_CODE (SET_SRC (pattern)) == MINUS			   && GET_CODE (XEXP (SET_SRC (pattern), 0)) == REG			   && REGNO (XEXP (SET_SRC (pattern), 0)) == STACK_POINTER_REGNUM)		    delta = -INTVAL (XEXP (SET_SRC (pattern), 1));		  else abort ();#ifdef STACK_GROWS_DOWNWARD		  depth -= delta;#else		  depth += delta;#endif		}	    }	  break;	case JUMP_INSN:	  frame_pointer_address_altered = 0;	  alter_frame_pointer_addresses (pattern, depth);	  /* Rerecognize insn if changed.  */	  if (frame_pointer_address_altered)	    INSN_CODE (insn) = -1;	  if (GET_CODE (pattern) == ADDR_VEC)	    for (i = 0; i < XVECLEN (pattern, 0); i++)	      label_depth[INSN_UID (XEXP (XVECEXP (pattern, 0, i), 0))] = depth;	  else if (GET_CODE (pattern) == ADDR_DIFF_VEC)	    {	      label_depth[INSN_UID (XEXP (XEXP (pattern, 0), 0))] = depth;	      for (i = 0; i < XVECLEN (pattern, 1); i++)		label_depth[INSN_UID (XEXP (XVECEXP (pattern, 1, i), 0))] = depth;	    }	  else if (JUMP_LABEL (insn))	    label_depth[INSN_UID (JUMP_LABEL (insn))] = depth;	  else	  break;	case CODE_LABEL:	  if (label_depth [INSN_UID (insn)] >= 0)	    depth = label_depth [INSN_UID (insn)];	  break;	case CALL_INSN:	  frame_pointer_address_altered = 0;	  alter_frame_pointer_addresses (pattern, depth);	  /* Rerecognize insn if changed.  */	  if (frame_pointer_address_altered)	    INSN_CODE (insn) = -1;	  break;	}    }}/* Walk the rtx X, converting all frame-pointer refs to stack-pointer refs   on the assumption that the current temporary stack depth is DEPTH.   (The size of saved registers must be added to DEPTH   to get the actual offset between the logical frame-pointer and the   stack pointer.  FIX_FRAME_POINTER_ADDRESS takes care of that.)  */static rtxalter_frame_pointer_addresses (x, depth)     register rtx x;     int depth;{  register int i;  register char *fmt;  register enum rtx_code code = GET_CODE (x);  switch (code)    {    case CONST_INT:    case CONST:    case SYMBOL_REF:    case LABEL_REF:    case CONST_DOUBLE:    case CC0:    case PC:      return x;    case REG:      /* Frame ptr can occur outside a PLUS if a stack slot	 can occur with offset 0.  */      if (x == frame_pointer_rtx)	{	  rtx oldx = x;	  FIX_FRAME_POINTER_ADDRESS (x, depth);	  if (x != oldx)	    frame_pointer_address_altered = 1;	}      return x;    case MEM:      {	rtx addr = XEXP (x, 0);	rtx mem;	rtx old_addr = addr;	FIX_FRAME_POINTER_ADDRESS (addr, depth);	if (addr != old_addr)	  frame_pointer_address_altered = 1;	/* These MEMs are normally shared.  Make a changed copy;	   don't alter the shared MEM, since it needs to be altered	   differently each time it occurs (since DEPTH varies).  */	mem = gen_rtx (MEM, GET_MODE (x), addr);	MEM_VOLATILE_P (mem) = MEM_VOLATILE_P (x);	return mem;      }    case PLUS:      {	rtx oldx = x;	/* Handle addresses being loaded or pushed, etc.,	   rather than referenced.  */	FIX_FRAME_POINTER_ADDRESS (x, depth);	if (x != oldx)	  frame_pointer_address_altered = 1;	code = GET_CODE (x);	break;      }    }  fmt = GET_RTX_FORMAT (code);  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)    {      if (fmt[i] == 'e')	XEXP (x, i) = alter_frame_pointer_addresses (XEXP (x, i), depth);      else if (fmt[i] == 'E')	{	  register int j;	  for (j = XVECLEN (x, i) - 1; j >=0; j--)	    XVECEXP (x, i, j)	      = alter_frame_pointer_addresses (XVECEXP (x, i, j), depth);	}    }  return x;}/* Modify the home of pseudo-reg I.   The new home is present in reg_renumber[I].   FROM_REG may be the hard reg that the pseudo-reg is being spilled from;   or it may be -1, meaning there is none or it is not relevant.   This is used so that all pseudos spilled from a given hard reg   can share one stack slot.  */static voidalter_reg (i, from_reg)     register int i;     int from_reg;{  /* When outputting an inline function, this can happen     for a reg that isn't actually used.  */  if (regno_reg_rtx[i] == 0)    return;  /* If the reg got changed to a MEM at rtl-generation time,     ignore it.  */  if (GET_CODE (regno_reg_rtx[i]) != REG)    return;  /* Modify the reg-rtx to contain the new hard reg     number or else to contain its pseudo reg number.  */  REGNO (regno_reg_rtx[i])    = reg_renumber[i] >= 0 ? reg_renumber[i] : i;  if (reg_renumber[i] < 0 && reg_equiv_init[i])    {      /* Delete the insn that loads the pseudo register.  */      PUT_CODE (reg_equiv_init[i], NOTE);      NOTE_LINE_NUMBER (reg_equiv_init[i])	= NOTE_INSN_DELETED;      NOTE_SOURCE_FILE (reg_equiv_init[i]) = 0;    }  /* If we have a pseudo that is needed but has no hard reg or equivalent,     allocate a stack slot for it.  */  if (reg_renumber[i] < 0      && reg_n_refs[i] > 0      && reg_equiv_constant[i] == 0      && reg_equiv_mem[i] == 0      && reg_equiv_address[i] == 0)    {      register rtx x, addr;      int inherent_size = PSEUDO_REGNO_BYTES (i);      int total_size = max (inherent_size, reg_max_ref_width[i]);      /* Each pseudo reg has an inherent size which comes from its own mode,	 and a total size which provides room for paradoxical subregs	 which refer to the pseudo reg in wider modes.	 We can use a slot already allocated if it provides both	 enough inherent space and enough total space.	 Otherwise, we allocate a new slot, making sure that it has no less	 inherent space, and no less total space, then the previous slot.  */      if (from_reg == -1)	{	  /* No known place to spill from => no slot to reuse.  */	  x = assign_stack_local (GET_MODE (regno_reg_rtx[i]), total_size);#ifdef BYTES_BIG_ENDIAN	  /* Cancel the  big-endian correction done in assign_stack_local.	     Get the address of the beginning of the slot.	     This is so we can do a big-endian correction unconditionally	     below.  */	  x = gen_rtx (MEM, GET_MODE (regno_reg_rtx[i]),		       plus_constant (XEXP (x, 0),				      inherent_size - total_size));#endif	}      /* Reuse a stack slot if possible.  */      else if (spill_stack_slot[from_reg] != 0	       && spill_stack_slot_width[from_reg] >= total_size	       && (GET_MODE_SIZE (GET_MODE (spill_stack_slot[from_reg]))		   >= inherent_size))	x = spill_stack_slot[from_reg];      /* Allocate a new or bigger slot.  */      else	{	  /* Compute maximum size needed, both for inherent size	     and for total size.  */	  enum machine_mode mode = GET_MODE (regno_reg_rtx[i]);	  if (spill_stack_slot[from_reg])	    {	      if (GET_MODE_SIZE (GET_MODE (spill_stack_slot[from_reg]))		  > inherent_size)		mode = GET_MODE (spill_stack_slot[from_reg]);	      if (spill_stack_slot_width[from_reg] > total_size)		total_size = spill_stack_slot_width[from_reg];	    }	  /* Make a slot with that size.  */	  x = assign_stack_local (mode, total_size);#ifdef BYTES_BIG_ENDIAN	  /* Cancel the  big-endian correction done in assign_stack_local.	     Get the address of the beginning of the slot.	     This is so we can do a big-endian correction unconditionally	     below.  */	  x = gen_rtx (MEM, mode,		       plus_constant (XEXP (x, 0),				      GET_MODE_SIZE (mode) - total_size));#endif	  spill_stack_slot[from_reg] = x;	  spill_stack_slot_width[from_reg] = total_size;	}#ifdef BYTES_BIG_ENDIAN      /* On a big endian machine, the "address" of the slot	 is the address of the low part that fits its inherent mode.  */      if (inherent_size < total_size)	x = gen_rtx (MEM, GET_MODE (regno_reg_rtx[i]),		     plus_constant (XEXP (x, 0),				    total_size - inherent_size));#endif /* BYTES_BIG_ENDIAN */      addr = XEXP (x, 0);      /* If the stack slot is directly addressable, substitute	 the MEM we just got directly for the old REG.	 Otherwise, record the address; we will generate hairy code	 to compute the address in a register each time it is needed.  */      if (memory_address_p (GET_MODE (regno_reg_rtx[i]), addr))	reg_equiv_mem[i] = x;      else	reg_equiv_address[i] = XEXP (x, 0);    }}/* Mark the slots in regs_ever_live for the hard regs   used by pseudo-reg number REGNO.  */voidmark_home_live (regno)     int regno;{  register int i, lim;  i = reg_renumber[regno];  if (i < 0)    return;  lim = i + HARD_REGNO_NREGS (i, PSEUDO_REGNO_MODE (regno));  while (i < lim)    regs_ever_live[i++] = 1;}/* Kick all pseudos out of hard register REGNO.   If GLOBAL is nonzero, try to find someplace else to put them.   If DUMPFILE is nonzero, log actions taken on that file.   Return nonzero if any pseudos needed to be kicked out   or if this hard reg may appear explicitly in some instructions.  */static intspill_hard_reg (regno, global, dumpfile)     register int regno;     int global;     FILE *dumpfile;{  int something_changed = 0;  register int i;  /* Spill every pseudo reg that was allocated to this reg     or to something that overlaps this reg.  */  for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)    if (reg_renumber[i] >= 0	&& reg_renumber[i] <= regno	&& (reg_renumber[i] 	    + HARD_REGNO_NREGS (reg_renumber[i],				PSEUDO_REGNO_MODE (i))	    > regno))      {	/* If this register belongs solely to a basic block	   which needed no spilling, leave it be.  */	if (regno != FRAME_POINTER_REGNUM	    && basic_block_needs	    && reg_basic_block[i] >= 0	    && basic_block_needs[reg_basic_block[i]] == 0)	  continue;	/* Mark it as no longer having a hard register home.  */	reg_renumber[i] = -1;	/* We will need to scan everything again.  */	something_changed = 1;	if (global)	  {	    retry_global_alloc (i, forbidden_regs);	    /* Update regs_ever_live for new home (if any).  */	    mark_home_live (i);	    /* If something gets spilled to the stack,	       we must have a frame pointer, so spill the frame pointer.  */	    if (reg_renumber[i] == -1 && ! frame_pointer_needed)	      {		frame_pointer_needed = 1;		forbidden_regs[FRAME_POINTER_REGNUM] = 1;		spill_hard_reg (FRAME_POINTER_REGNUM, global, dumpfile);	      }

⌨️ 快捷键说明

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