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

📄 rtlanal.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 3 页
字号:
find_regno_note (insn, kind, regno)     rtx insn;     enum reg_note kind;     int regno;{  register rtx link;  for (link = REG_NOTES (insn); link; link = XEXP (link, 1))    if (REG_NOTE_KIND (link) == kind	/* Verify that it is a register, so that scratch and MEM won't cause a	   problem here.  */	&& GET_CODE (XEXP (link, 0)) == REG	&& REGNO (XEXP (link, 0)) <= regno	&& ((REGNO (XEXP (link, 0))	     + (REGNO (XEXP (link, 0)) >= FIRST_PSEUDO_REGISTER ? 1		: HARD_REGNO_NREGS (REGNO (XEXP (link, 0)),				    GET_MODE (XEXP (link, 0)))))	    > regno))      return link;  return 0;}/* Return true if DATUM, or any overlap of DATUM, of kind CODE is found   in the CALL_INSN_FUNCTION_USAGE information of INSN.  */intfind_reg_fusage (insn, code, datum)     rtx insn;     enum rtx_code code;     rtx datum;{  /* If it's not a CALL_INSN, it can't possibly have a     CALL_INSN_FUNCTION_USAGE field, so don't bother checking.  */  if (GET_CODE (insn) != CALL_INSN)    return 0;  if (! datum)    abort();  if (GET_CODE (datum) != REG)    {      register rtx link;      for (link = CALL_INSN_FUNCTION_USAGE (insn);           link;	   link = XEXP (link, 1))        if (GET_CODE (XEXP (link, 0)) == code	    && rtx_equal_p (datum, SET_DEST (XEXP (link, 0))))          return 1;    }  else    {      register int regno = REGNO (datum);      /* CALL_INSN_FUNCTION_USAGE information cannot contain references	 to pseudo registers, so don't bother checking.  */      if (regno < FIRST_PSEUDO_REGISTER)        {	  int end_regno = regno + HARD_REGNO_NREGS (regno, GET_MODE (datum));	  int i;	  for (i = regno; i < end_regno; i++)	    if (find_regno_fusage (insn, code, i))	      return 1;        }    }  return 0;}/* Return true if REGNO, or any overlap of REGNO, of kind CODE is found   in the CALL_INSN_FUNCTION_USAGE information of INSN.  */intfind_regno_fusage (insn, code, regno)     rtx insn;     enum rtx_code code;     int regno;{  register rtx link;  /* CALL_INSN_FUNCTION_USAGE information cannot contain references     to pseudo registers, so don't bother checking.  */  if (regno >= FIRST_PSEUDO_REGISTER      || GET_CODE (insn) != CALL_INSN )    return 0;  for (link = CALL_INSN_FUNCTION_USAGE (insn); link; link = XEXP (link, 1))   {    register int regnote;    register rtx op;    if (GET_CODE (op = XEXP (link, 0)) == code	&& GET_CODE (SET_DEST (op)) == REG	&& (regnote = REGNO (SET_DEST (op))) <= regno	&& regnote		+ HARD_REGNO_NREGS (regnote, GET_MODE (SET_DEST (op)))	    > regno)      return 1;   }  return 0;}/* Remove register note NOTE from the REG_NOTES of INSN.  */voidremove_note (insn, note)     register rtx note;     register rtx insn;{  register rtx link;  if (REG_NOTES (insn) == note)    {      REG_NOTES (insn) = XEXP (note, 1);      return;    }  for (link = REG_NOTES (insn); link; link = XEXP (link, 1))    if (XEXP (link, 1) == note)      {	XEXP (link, 1) = XEXP (note, 1);	return;      }  abort ();}/* Nonzero if X contains any volatile instructions.  These are instructions   which may cause unpredictable machine state instructions, and thus no   instructions should be moved or combined across them.  This includes   only volatile asms and UNSPEC_VOLATILE instructions.  */intvolatile_insn_p (x)     rtx x;{  register RTX_CODE code;  code = GET_CODE (x);  switch (code)    {    case LABEL_REF:    case SYMBOL_REF:    case CONST_INT:    case CONST:    case CONST_DOUBLE:    case CC0:    case PC:    case REG:    case SCRATCH:    case CLOBBER:    case ASM_INPUT:    case ADDR_VEC:    case ADDR_DIFF_VEC:    case CALL:    case MEM:      return 0;    case UNSPEC_VOLATILE: /* case TRAP_IF: This isn't clear yet.  */      return 1;    case ASM_OPERANDS:      if (MEM_VOLATILE_P (x))	return 1;    }  /* Recursively scan the operands of this expression.  */  {    register char *fmt = GET_RTX_FORMAT (code);    register int i;        for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)      {	if (fmt[i] == 'e')	  {	    if (volatile_insn_p (XEXP (x, i)))	      return 1;	  }	if (fmt[i] == 'E')	  {	    register int j;	    for (j = 0; j < XVECLEN (x, i); j++)	      if (volatile_insn_p (XVECEXP (x, i, j)))		return 1;	  }      }  }  return 0;}/* Nonzero if X contains any volatile memory references   UNSPEC_VOLATILE operations or volatile ASM_OPERANDS expressions.  */intvolatile_refs_p (x)     rtx x;{  register RTX_CODE code;  code = GET_CODE (x);  switch (code)    {    case LABEL_REF:    case SYMBOL_REF:    case CONST_INT:    case CONST:    case CONST_DOUBLE:    case CC0:    case PC:    case REG:    case SCRATCH:    case CLOBBER:    case ASM_INPUT:    case ADDR_VEC:    case ADDR_DIFF_VEC:      return 0;    case CALL:    case UNSPEC_VOLATILE: /* case TRAP_IF: This isn't clear yet.  */      return 1;    case MEM:    case ASM_OPERANDS:      if (MEM_VOLATILE_P (x))	return 1;    }  /* Recursively scan the operands of this expression.  */  {    register char *fmt = GET_RTX_FORMAT (code);    register int i;        for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)      {	if (fmt[i] == 'e')	  {	    if (volatile_refs_p (XEXP (x, i)))	      return 1;	  }	if (fmt[i] == 'E')	  {	    register int j;	    for (j = 0; j < XVECLEN (x, i); j++)	      if (volatile_refs_p (XVECEXP (x, i, j)))		return 1;	  }      }  }  return 0;}/* Similar to above, except that it also rejects register pre- and post-   incrementing.  */intside_effects_p (x)     rtx x;{  register RTX_CODE code;  code = GET_CODE (x);  switch (code)    {    case LABEL_REF:    case SYMBOL_REF:    case CONST_INT:    case CONST:    case CONST_DOUBLE:    case CC0:    case PC:    case REG:    case SCRATCH:    case ASM_INPUT:    case ADDR_VEC:    case ADDR_DIFF_VEC:      return 0;    case CLOBBER:      /* Reject CLOBBER with a non-VOID mode.  These are made by combine.c	 when some combination can't be done.  If we see one, don't think	 that we can simplify the expression.  */      return (GET_MODE (x) != VOIDmode);    case PRE_INC:    case PRE_DEC:    case POST_INC:    case POST_DEC:    case CALL:    case UNSPEC_VOLATILE: /* case TRAP_IF: This isn't clear yet.  */      return 1;    case MEM:    case ASM_OPERANDS:      if (MEM_VOLATILE_P (x))	return 1;    }  /* Recursively scan the operands of this expression.  */  {    register char *fmt = GET_RTX_FORMAT (code);    register int i;        for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)      {	if (fmt[i] == 'e')	  {	    if (side_effects_p (XEXP (x, i)))	      return 1;	  }	if (fmt[i] == 'E')	  {	    register int j;	    for (j = 0; j < XVECLEN (x, i); j++)	      if (side_effects_p (XVECEXP (x, i, j)))		return 1;	  }      }  }  return 0;}/* Return nonzero if evaluating rtx X might cause a trap.  */intmay_trap_p (x)     rtx x;{  int i;  enum rtx_code code;  char *fmt;  if (x == 0)    return 0;  code = GET_CODE (x);  switch (code)    {      /* Handle these cases quickly.  */    case CONST_INT:    case CONST_DOUBLE:    case SYMBOL_REF:    case LABEL_REF:    case CONST:    case PC:    case CC0:    case REG:    case SCRATCH:      return 0;      /* Conditional trap can trap!  */    case UNSPEC_VOLATILE:    case TRAP_IF:      return 1;      /* Memory ref can trap unless it's a static var or a stack slot.  */    case MEM:      return rtx_addr_can_trap_p (XEXP (x, 0));      /* Division by a non-constant might trap.  */    case DIV:    case MOD:    case UDIV:    case UMOD:      if (! CONSTANT_P (XEXP (x, 1)))	return 1;      /* This was const0_rtx, but by not using that,	 we can link this file into other programs.  */      if (GET_CODE (XEXP (x, 1)) == CONST_INT && INTVAL (XEXP (x, 1)) == 0)	return 1;    case EXPR_LIST:      /* An EXPR_LIST is used to represent a function call.  This	 certainly may trap.  */      return 1;    default:      /* Any floating arithmetic may trap.  */      if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)	return 1;    }  fmt = GET_RTX_FORMAT (code);  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)    {      if (fmt[i] == 'e')	{	  if (may_trap_p (XEXP (x, i)))	    return 1;	}      else if (fmt[i] == 'E')	{	  register int j;	  for (j = 0; j < XVECLEN (x, i); j++)	    if (may_trap_p (XVECEXP (x, i, j)))	      return 1;	}    }  return 0;}/* Return nonzero if X contains a comparison that is not either EQ or NE,   i.e., an inequality.  */intinequality_comparisons_p (x)     rtx x;{  register char *fmt;  register int len, i;  register enum rtx_code code = GET_CODE (x);  switch (code)    {    case REG:    case SCRATCH:    case PC:    case CC0:    case CONST_INT:    case CONST_DOUBLE:    case CONST:    case LABEL_REF:    case SYMBOL_REF:      return 0;    case LT:    case LTU:    case GT:    case GTU:    case LE:    case LEU:    case GE:    case GEU:      return 1;    }  len = GET_RTX_LENGTH (code);  fmt = GET_RTX_FORMAT (code);  for (i = 0; i < len; i++)    {      if (fmt[i] == 'e')	{	  if (inequality_comparisons_p (XEXP (x, i)))	    return 1;	}      else if (fmt[i] == 'E')	{	  register int j;	  for (j = XVECLEN (x, i) - 1; j >= 0; j--)	    if (inequality_comparisons_p (XVECEXP (x, i, j)))	      return 1;	}    }	      return 0;}/* Replace any occurrence of FROM in X with TO.   Note that copying is not done so X must not be shared unless all copies   are to be modified.  */rtxreplace_rtx (x, from, to)     rtx x, from, to;{  register int i, j;  register char *fmt;  if (x == from)    return to;  /* Allow this function to make replacements in EXPR_LISTs.  */  if (x == 0)    return 0;  fmt = GET_RTX_FORMAT (GET_CODE (x));  for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)    {      if (fmt[i] == 'e')	XEXP (x, i) = replace_rtx (XEXP (x, i), from, to);      else if (fmt[i] == 'E')	for (j = XVECLEN (x, i) - 1; j >= 0; j--)	  XVECEXP (x, i, j) = replace_rtx (XVECEXP (x, i, j), from, to);    }  return x;}  /* Throughout the rtx X, replace many registers according to REG_MAP.   Return the replacement for X (which may be X with altered contents).   REG_MAP[R] is the replacement for register R, or 0 for don't replace.   NREGS is the length of REG_MAP; regs >= NREGS are not mapped.     We only support REG_MAP entries of REG or SUBREG.  Also, hard registers   should not be mapped to pseudos or vice versa since validate_change   is not called.   If REPLACE_DEST is 1, replacements are also done in destinations;   otherwise, only sources are replaced.  */rtxreplace_regs (x, reg_map, nregs, replace_dest)     rtx x;     rtx *reg_map;     int nregs;     int replace_dest;{  register enum rtx_code code;  register int i;  register char *fmt;  if (x == 0)    return x;  code = GET_CODE (x);  switch (code)    {    case SCRATCH:    case PC:    case CC0:    case CONST_INT:    case CONST_DOUBLE:    case CONST:    case SYMBOL_REF:    case LABEL_REF:      return x;    case REG:      /* Verify that the register has an entry before trying to access it.  */      if (REGNO (x) < nregs && reg_map[REGNO (x)] != 0)	{	  /* SUBREGs can't be shared.  Always return a copy to ensure that if	     this replacement occurs more than once then each instance will	     get distinct rtx.  */	  if (GET_CODE (reg_map[REGNO (x)]) == SUBREG)	    return copy_rtx (reg_map[REGNO (x)]);	  return reg_map[REGNO (x)];	}      return x;    case SUBREG:      /* Prevent making nested SUBREGs.  */      if (GET_CODE (SUBREG_REG (x)) == REG && REGNO (SUBREG_REG (x)) < nregs	  && reg_map[REGNO (SUBREG_REG (x))] != 0	  && GET_CODE (reg_map[REGNO (SUBREG_REG (x))]) == SUBREG)	{	  rtx map_val = reg_map[REGNO (SUBREG_REG (x))];	  rtx map_inner = SUBREG_REG (map_val);	  if (GET_MODE (x) == GET_MODE (map_inner))	    return map_inner;	  else	    {	      /* We cannot call gen_rtx here since we may be linked with		 genattrtab.c.  */	      /* Let's try clobbering the incoming SUBREG and see		 if this is really safe.  */	      SUBREG_REG (x) = map_inner;	      SUBREG_WORD (x) += SUBREG_WORD (map_val);	      return x;#if 0	      rtx new = rtx_alloc (SUBREG);	      PUT_MODE (new, GET_MODE (x));	      SUBREG_REG (new) = map_inner;	      SUBREG_WORD (new) = SUBREG_WORD (x) + SUBREG_WORD (map_val);#endif	    }	}      break;    case SET:      if (replace_dest)	SET_DEST (x) = replace_regs (SET_DEST (x), reg_map, nregs, 0);      else if (GET_CODE (SET_DEST (x)) == MEM	       || GET_CODE (SET_DEST (x)) == STRICT_LOW_PART)	/* Even if we are not to replace destinations, replace register if it	   is CONTAINED in destination (destination is memory or	   STRICT_LOW_PART).  */	XEXP (SET_DEST (x), 0) = replace_regs (XEXP (SET_DEST (x), 0),					       reg_map, nregs, 0);      else if (GET_CODE (SET_DEST (x)) == ZERO_EXTRACT)	/* Similarly, for ZERO_EXTRACT we replace all operands.  */	break;      SET_SRC (x) = replace_regs (SET_SRC (x), reg_map, nregs, 0);      return x;    }  fmt = GET_RTX_FORMAT (code);  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)    {      if (fmt[i] == 'e')	XEXP (x, i) = replace_regs (XEXP (x, i), reg_map, nregs, replace_dest);      if (fmt[i] == 'E')	{	  register int j;	  for (j = 0; j < XVECLEN (x, i); j++)	    XVECEXP (x, i, j) = replace_regs (XVECEXP (x, i, j), reg_map,					      nregs, replace_dest);	}    }  return x;}

⌨️ 快捷键说明

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