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

📄 reload.c

📁 这是完整的gcc源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
  register char *fmt;  int success_2;        if (x == y)    return 1;  if ((code == REG || (code == SUBREG && GET_CODE (SUBREG_REG (x)) == REG))      && (GET_CODE (y) == REG || (GET_CODE (y) == SUBREG				  && GET_CODE (SUBREG_REG (y)) == REG)))    {      register int j;      if (code == SUBREG)	{	  i = REGNO (SUBREG_REG (x));	  if (i >= FIRST_PSEUDO_REGISTER)	    goto slow;	  i += SUBREG_WORD (x);	}      else	i = REGNO (x);      if (GET_CODE (y) == SUBREG)	{	  j = REGNO (SUBREG_REG (y));	  if (j >= FIRST_PSEUDO_REGISTER)	    goto slow;	  j += SUBREG_WORD (y);	}      else	j = REGNO (y);      return i == j;    }  /* If two operands must match, because they are really a single     operand of an assembler insn, then two postincrements are invalid     because the assembler insn would increment only once.     On the other hand, an postincrement matches ordinary indexing     if the postincrement is the output operand.  */  if (code == POST_DEC || code == POST_INC)    return operands_match_p (XEXP (x, 0), y);  /* Two preincrements are invalid     because the assembler insn would increment only once.     On the other hand, an preincrement matches ordinary indexing     if the preincrement is the input operand.     In this case, return 2, since some callers need to do special     things when this happens.  */  if (GET_CODE (y) == PRE_DEC || GET_CODE (y) == PRE_INC)    return operands_match_p (x, XEXP (y, 0)) ? 2 : 0; slow:  /* Now we have disposed of all the cases      in which different rtx codes can match.  */  if (code != GET_CODE (y))    return 0;  if (code == LABEL_REF)    return XEXP (x, 0) == XEXP (y, 0);  if (code == SYMBOL_REF)    return XSTR (x, 0) == XSTR (y, 0);  /* (MULT:SI x y) and (MULT:HI x y) are NOT equivalent.  */  if (GET_MODE (x) != GET_MODE (y))    return 0;  /* Compare the elements.  If any pair of corresponding elements     fail to match, return 0 for the whole things.  */  success_2 = 0;  fmt = GET_RTX_FORMAT (code);  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)    {      int val;      switch (fmt[i])	{	case 'i':	  if (XINT (x, i) != XINT (y, i))	    return 0;	  break;	case 'e':	  val = operands_match_p (XEXP (x, i), XEXP (y, i));	  if (val == 0)	    return 0;	  /* If any subexpression returns 2,	     we should return 2 if we are successful.  */	  if (val == 2)	    success_2 = 1;	  break;	case '0':	  break;	  /* It is believed that rtx's at this level will never	     contain anything but integers and other rtx's,	     except for within LABEL_REFs and SYMBOL_REFs.  */	default:	  abort ();	}    }  return 1 + success_2;}/* Return the number of times character C occurs in string S.  */static intn_occurrences (c, s)     char c;     char *s;{  int n = 0;  while (*s)    n += (*s++ == c);  return n;}struct decomposition{  int reg_flag;  int safe;  rtx base;  int start;  int end;};/* Describe the range of registers or memory referenced by X.   If X is a register, set REG_FLAG and put the first register    number into START and the last plus one into END.   If X is a memory reference, put a base address into BASE    and a range of integer offsets into START and END.   If X is pushing on the stack, we can assume it causes no trouble,    so we set the SAFE field.  */static struct decompositiondecompose (x)     rtx x;{  struct decomposition val;  int all_const = 0;  val.reg_flag = 0;  val.safe = 0;  if (GET_CODE (x) == MEM)    {      rtx base, offset = 0;      rtx addr = XEXP (x, 0);      if (GET_CODE (addr) == PRE_DEC || GET_CODE (addr) == PRE_INC	  || GET_CODE (addr) == POST_DEC || GET_CODE (addr) == POST_INC)	{	  val.base = XEXP (addr, 0);	  val.start = - GET_MODE_SIZE (GET_MODE (x));	  val.end = GET_MODE_SIZE (GET_MODE (x));	  val.safe = REGNO (val.base) == STACK_POINTER_REGNUM;	  return val;	}      if (GET_CODE (addr) == CONST)	{	  addr = XEXP (addr, 0);	  all_const = 1;	}      if (GET_CODE (addr) == PLUS)	{	  if (CONSTANT_P (XEXP (addr, 0)))	    {	      base = XEXP (addr, 1);	      offset = XEXP (addr, 0);	    }	  else if (CONSTANT_P (XEXP (addr, 1)))	    {	      base = XEXP (addr, 0);	      offset = XEXP (addr, 1);	    }	}      if (offset == 0)	{	  base = addr;	  offset = const0_rtx;	}       if (GET_CODE (offset) == CONST)	offset = XEXP (offset, 0);      if (GET_CODE (offset) == PLUS)	{	  if (GET_CODE (XEXP (offset, 0)) == CONST_INT)	    {	      base = gen_rtx (PLUS, GET_MODE (base), base, XEXP (offset, 1));	      offset = XEXP (offset, 0);	    }	  else if (GET_CODE (XEXP (offset, 1)) == CONST_INT)	    {	      base = gen_rtx (PLUS, GET_MODE (base), base, XEXP (offset, 0));	      offset = XEXP (offset, 1);	    }	  else	    {	      base = gen_rtx (PLUS, GET_MODE (base), base, offset);	      offset = const0_rtx;	    }	}      else if (GET_CODE (offset) != CONST_INT)	{	  base = gen_rtx (PLUS, GET_MODE (base), base, offset);	  offset = const0_rtx;	}      if (all_const && GET_CODE (base) == PLUS)	base = gen_rtx (CONST, GET_MODE (base), base);      if (GET_CODE (offset) != CONST_INT)	abort ();      val.start = INTVAL (offset);      val.end = val.start + GET_MODE_SIZE (GET_MODE (x));      val.base = base;      return val;    }  else if (GET_CODE (x) == REG)    {      val.reg_flag = 1;      val.start = true_regnum (x);       if (val.start < 0)	{	  /* A pseudo with no hard reg.  */	  val.start = REGNO (x);	  val.end = val.start + 1;	}      else	/* A hard reg.  */	val.end = val.start + HARD_REGNO_NREGS (val.start, GET_MODE (x));    }  else if (GET_CODE (x) == SUBREG)    {      if (GET_CODE (SUBREG_REG (x)) != REG)	/* This could be more precise, but it's good enough.  */	return decompose (SUBREG_REG (x));      val.reg_flag = 1;      val.start = true_regnum (x);       if (val.start < 0)	return decompose (SUBREG_REG (x));      else	/* A hard reg.  */	val.end = val.start + HARD_REGNO_NREGS (val.start, GET_MODE (x));    }  else    abort ();  return val;}/* Return 1 if altering Y will not modify the value of X.   Y is also described by YDATA, which should be decompose (Y).  */static intimmune_p (x, y, ydata)     rtx x, y;     struct decomposition ydata;{  struct decomposition xdata;  if (ydata.reg_flag)    return !refers_to_regno_p (ydata.start, ydata.end, x, 0);  if (ydata.safe)    return 1;  if (GET_CODE (y) != MEM)    abort ();  /* If Y is memory and X is not, Y can't affect X.  */  if (GET_CODE (x) != MEM)    return 1;  xdata =  decompose (x);  if (! rtx_equal_p (xdata.base, ydata.base))    {      /* If bases are distinct symbolic constants, there is no overlap.  */      if (CONSTANT_P (xdata.base) && CONSTANT_P (ydata.base))	return 1;      /* Constants and stack slots never overlap.  */      if (CONSTANT_P (xdata.base)	  && (ydata.base == frame_pointer_rtx	      || ydata.base == stack_pointer_rtx))	return 1;      if (CONSTANT_P (ydata.base)	  && (xdata.base == frame_pointer_rtx	      || xdata.base == stack_pointer_rtx))	return 1;      /* If either base is variable, we don't know anything.  */      return 0;    }  return (xdata.start >= ydata.end || ydata.start >= xdata.end);}/* Main entry point of this file: search the body of INSN   for values that need reloading and record them with push_reload.   REPLACE nonzero means record also where the values occur   so that subst_reloads can be used.   IND_OK says that a memory reference is a valid memory address.   LIVE_KNOWN says we have valid information about which hard   regs are live at each point in the program; this is true when   we are called from global_alloc but false when stupid register   allocation has been done.   RELOAD_REG_P if nonzero is a vector indexed by hard reg number   which is nonnegative if the reg has been commandeered for reloading into.   It is copied into STATIC_RELOAD_REG_P and referenced from there   by various subroutines.  */voidfind_reloads (insn, replace, ind_ok, live_known, reload_reg_p)     rtx insn;     int replace, ind_ok;     int live_known;     short *reload_reg_p;{#ifdef REGISTER_CONSTRAINTS  enum reload_modified { RELOAD_NOTHING, RELOAD_READ, RELOAD_READ_WRITE, RELOAD_WRITE };  register int insn_code_number;  register int i;  int noperands;  /* These are the constraints for the insn.  We don't change them.  */  char *constraints1[MAX_RECOG_OPERANDS];  /* These start out as the constraints for the insn     and they are chewed up as we consider alternatives.  */  char *constraints[MAX_RECOG_OPERANDS];  /* Nonzero for a MEM operand whose entire address needs a reload.  */  int address_reloaded[MAX_RECOG_OPERANDS];  int n_alternatives;  int this_alternative[MAX_RECOG_OPERANDS];  char this_alternative_win[MAX_RECOG_OPERANDS];  char this_alternative_offmemok[MAX_RECOG_OPERANDS];  char this_alternative_earlyclobber[MAX_RECOG_OPERANDS];  int this_alternative_matches[MAX_RECOG_OPERANDS];  int swapped;  int goal_alternative[MAX_RECOG_OPERANDS];  int this_alternative_number;  int goal_alternative_number;  int operand_reloadnum[MAX_RECOG_OPERANDS];  int goal_alternative_matches[MAX_RECOG_OPERANDS];  int goal_alternative_matched[MAX_RECOG_OPERANDS];  char goal_alternative_win[MAX_RECOG_OPERANDS];  char goal_alternative_offmemok[MAX_RECOG_OPERANDS];  char goal_alternative_earlyclobber[MAX_RECOG_OPERANDS];  int goal_alternative_swapped;  enum reload_modified modified[MAX_RECOG_OPERANDS];  int best;  int commutative;  char operands_match[MAX_RECOG_OPERANDS][MAX_RECOG_OPERANDS];  rtx substed_operand[MAX_RECOG_OPERANDS];  rtx body = PATTERN (insn);  int goal_earlyclobber, this_earlyclobber;  enum machine_mode operand_mode[MAX_RECOG_OPERANDS];  this_insn = insn;  this_insn_is_asm = 0;		/* Tentative.  */  n_reloads = 0;  n_replacements = 0;  n_memlocs = 0;  n_earlyclobbers = 0;  replace_reloads = replace;  indirect_ok = ind_ok;  hard_regs_live_known = live_known;  static_reload_reg_p = reload_reg_p;  /* Find what kind of insn this is.  NOPERANDS gets number of operands.     Make OPERANDS point to a vector of operand values.     Make OPERAND_LOCS point to a vector of pointers to     where the operands were found.     Fill CONSTRAINTS and CONSTRAINTS1 with pointers to the     constraint-strings for this insn.     Return if the insn needs no reload processing.  */  switch (GET_CODE (body))    {    case USE:    case CLOBBER:    case ASM_INPUT:    case ADDR_VEC:    case ADDR_DIFF_VEC:      return;    case SET:      /* Dispose quickly of (set (reg..) (reg..)) if both have hard regs.  */      if (GET_CODE (SET_DEST (body)) == REG	  && REGNO (SET_DEST (body)) < FIRST_PSEUDO_REGISTER	  && GET_CODE (SET_SRC (body)) == REG	  && REGNO (SET_SRC (body)) < FIRST_PSEUDO_REGISTER)	return;    case PARALLEL:    case ASM_OPERANDS:      noperands = asm_noperands (body);      if (noperands >= 0)	{	  /* This insn is an `asm' with operands.  */	  insn_code_number = -1;	  this_insn_is_asm = 1;	  /* expand_asm_operands makes sure there aren't too many operands.  */	  if (noperands > MAX_RECOG_OPERANDS)	    abort ();

⌨️ 快捷键说明

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