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

📄 reload.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
      for (; i >= 0; i--)	if (hard_reg_set_here_p (beg_regno, end_regno, XVECEXP (x, 0, i)))	  return 1;    }  return 0;}/* Return 1 if ADDR is a valid memory address for mode MODE,   and check that each pseudo reg has the proper kind of   hard reg.  */intstrict_memory_address_p (mode, addr)     enum machine_mode mode;     register rtx addr;{  GO_IF_LEGITIMATE_ADDRESS (mode, addr, win);  return 0; win:  return 1;}/* Like rtx_equal_p except that it allows a REG and a SUBREG to match   if they are the same hard reg, and has special hacks for   autoincrement and autodecrement.   This is specifically intended for find_reloads to use   in determining whether two operands match.   X is the operand whose number is the lower of the two.   The value is 2 if Y contains a pre-increment that matches   a non-incrementing address in X.  *//* ??? To be completely correct, we should arrange to pass   for X the output operand and for Y the input operand.   For now, we assume that the output operand has the lower number   because that is natural in (SET output (... input ...)).  */intoperands_match_p (x, y)     register rtx x, y;{  register int i;  register RTX_CODE code = GET_CODE (x);  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 'w':	  if (XWINT (x, i) != XWINT (y, i))	    return 0;	  break;	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.  */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;  HOST_WIDE_INT start;  HOST_WIDE_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 if (CONSTANT_P (x)	   /* This hasn't been assigned yet, so it can't conflict yet.  */	   || GET_CODE (x) == SCRATCH)    val.safe = 1;  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_for_reload_p (ydata.start, ydata.end, x, NULL_PTR);  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);}/* Similar, but calls decompose.  */intsafe_from_earlyclobber (op, clobber)     rtx op, clobber;{  struct decomposition early_data;  early_data = decompose (clobber);  return immune_p (op, clobber, early_data);}/* 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_LEVELS says how many levels of indirection are supported by this   machine; a value of zero means that a memory reference is not 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

⌨️ 快捷键说明

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