rtlanal.c

来自「GCC编译器源代码」· C语言 代码 · 共 1,983 行 · 第 1/4 页

C
1,983
字号
 /* case TRAP_IF: This isn't clear yet.  */      return 1;    case MEM:    case ASM_OPERANDS:      if (MEM_VOLATILE_P (x))	return 1;    default:      break;    }  /* 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;    default:      break;    }  /* 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))	  || GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)	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;      break;    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;          default:      break;    }  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;          default:      break;    }  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;}/* Return 1 if X, the SRC_SRC of  SET of (pc) contain a REG or MEM that is   not in the constant pool and not in the condition of an IF_THEN_ELSE.  */static intjmp_uses_reg_or_mem (x)     rtx x;{  enum rtx_code code = GET_CODE (x);  int i, j;  char *fmt;  switch (code)    {    case CONST:    case LABEL_REF:    case PC:      return 0;    case REG:      return 1;    case MEM:      return ! (GET_CODE (XEXP (x, 0)) == SYMBOL_REF		&& CONSTANT_POOL_ADDRESS_P (XEXP (x, 0)));    case IF_THEN_ELSE:      return (jmp_uses_reg_or_mem (XEXP (x, 1))	      || jmp_uses_reg_or_mem (XEXP (x, 2)));    case PLUS:  case MINUS:  case MULT:      return (jmp_uses_reg_or_mem (XEXP (x, 0))	      || jmp_uses_reg_or_mem (XEXP (x, 1)));    }  fmt = GET_RTX_FORMAT (code);  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)    {      if (fmt[i] == 'e'	  && jmp_uses_reg_or_mem (XEXP (x, i)))	return 1;      if (fmt[i] == 'E')	for (j = 0; j < XVECLEN (x, i); j++)	  if (jmp_uses_reg_or_mem (XVECEXP (x, i, j)))	    return 1;    }  return 0;}/* Return nonzero if INSN is an indirect jump (aka computed jump).   Tablejumps and casesi insns are not considered indirect jumps;   we can recognize them by a (use (lael_ref)).  */intcomputed_jump_p (insn)     rtx insn;{  int i;  if (GET_CODE (insn) == JUMP_INSN)    {      rtx pat = PATTERN (insn);      int computed_jump = 0;      if (GET_CODE (pat) == PARALLEL)	{	  int len = XVECLEN (pat, 0);	  int has_use_labelref = 0;	  for (i = len - 1; i >= 0; i--)	    if (GET_CODE (XVECEXP (pat, 0, i)) == USE		&& (GET_CODE (XEXP (XVECEXP (pat, 0, i), 0))		    == LABEL_REF))	      has_use_labelref = 1;	  if (! has_use_labelref)	    for (i = len - 1; i >= 0; i--)	      if (GET_CODE (XVECEXP (pat, 0, i)) == SET		  && SET_DEST (XVECEXP (pat, 0, i)) == pc_rtx		  && jmp_uses_reg_or_mem (SET_SRC (XVECEXP (pat, 0, i))))		return 1;	}      else if (GET_CODE (pat) == SET	       && SET_DEST (pat) == pc_rtx	       && jmp_uses_reg_or_mem (SET_SRC (pat)))	return 1;    }  return 0;}

⌨️ 快捷键说明

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