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

📄 combine.c

📁 这是完整的gcc源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	 now supposed to appear.  */      if (((was_replaced[0] && GET_CODE (XEXP (x, 1)) == PLUS)	   || (was_replaced[1] && GET_CODE (XEXP (x, 0)) == PLUS))	  ||	  ((was_replaced[0] || was_replaced[1])	   && GET_CODE (to) == PLUS))	{	  rtx offset = 0, base, index;	  if (GET_CODE (to) != PLUS)	    {	      index = to;	      base = was_replaced[0] ? XEXP (x, 1) : XEXP (x, 0);	    }	  else	    {	      index = was_replaced[0] ? XEXP (x, 1) : XEXP (x, 0);	      base = to;	    }	  if (CONSTANT_ADDRESS_P (XEXP (base, 0)))	    {	      offset = XEXP (base, 0);	      base = XEXP (base, 1);	    }	  else if (CONSTANT_ADDRESS_P (XEXP (base, 1)))	    {	      offset = XEXP (base, 1);	      base = XEXP (base, 0);	    }	  if (offset != 0)	    {	      if (!undobuf.storage)		undobuf.storage = (char *) oballoc (0);	      if (GET_CODE (offset) == CONST_INT)		return plus_constant (gen_rtx (PLUS, GET_MODE (index),					       base, index),				      INTVAL (offset));	      if (GET_CODE (index) == CONST_INT)		return plus_constant (gen_rtx (PLUS, GET_MODE (offset),					       base, offset),				      INTVAL (index));	      return gen_rtx (PLUS, GET_MODE (index),			      gen_rtx (PLUS, GET_MODE (index),				       base, index),			      offset);	    }	}      break;    case EQ:    case NE:      /* If comparing a subreg against zero, discard the subreg.  */      if (was_replaced[0]	  && GET_CODE (to) == SUBREG	  && SUBREG_WORD (to) == 0	  && XEXP (x, 1) == const0_rtx)	SUBST (XEXP (x, 0), SUBREG_REG (to));      /* If comparing a ZERO_EXTRACT against zero,	 canonicalize to a SIGN_EXTRACT,	 since the two are equivalent here.  */      if (was_replaced[0]	  && GET_CODE (to) == ZERO_EXTRACT	  && XEXP (x, 1) == const0_rtx)	{	  if (!undobuf.storage)	    undobuf.storage = (char *) oballoc (0);	  SUBST (XEXP (x, 0),		 gen_rtx (SIGN_EXTRACT, GET_MODE (to),			  XEXP (to, 0), XEXP (to, 1),			  XEXP (to, 2)));	}#ifndef BITS_BIG_ENDIAN      /* If we are putting (ASHIFT 1 x) into (EQ (AND ... y) 0),	 arrange to return (EQ (SIGN_EXTRACT y 1 x) 0),	 which is what jump-on-bit instructions are written with.  */      else if (XEXP (x, 1) == const0_rtx	       && GET_CODE (XEXP (x, 0)) == AND	       && (XEXP (XEXP (x, 0), 0) == to		   || XEXP (XEXP (x, 0), 1) == to)	       && GET_CODE (to) == ASHIFT	       && XEXP (to, 0) == const1_rtx)	{	  register rtx y = XEXP (XEXP (x, 0),				 XEXP (XEXP (x, 0), 0) == to);	  if (!undobuf.storage)	    undobuf.storage = (char *) oballoc (0);	  SUBST (XEXP (x, 0),		 gen_rtx (SIGN_EXTRACT, GET_MODE (to),			  y,			  const1_rtx, XEXP (to, 1)));	}#endif /* not BITS_BIG_ENDIAN */      /* Negation is a no-op before equality test against zero.  */      if (GET_CODE (XEXP (x, 0)) == NEG && XEXP (x, 1) == const0_rtx)	{	  SUBST (XEXP (x, 0), XEXP (XEXP (x, 0), 0));	}      if (GET_CODE (XEXP (x, 1)) == NEG && XEXP (x, 0) == const0_rtx)	{	  SUBST (XEXP (x, 1), XEXP (XEXP (x, 1), 0));	}      break;    case ZERO_EXTEND:      /* Nested zero-extends are equivalent to just one.  */      if (was_replaced[0]	  && GET_CODE (to) == ZERO_EXTEND)	SUBST (XEXP (x, 0), XEXP (to, 0));      /* Zero extending a constant int can be replaced	 by a zero-extended constant.  */      if (was_replaced[0]	  && HOST_BITS_PER_INT >= GET_MODE_BITSIZE (GET_MODE (from))	  && GET_CODE (to) == CONST_INT)	{	  int intval = INTVAL (to) & GET_MODE_MASK (GET_MODE (from));	  if (!undobuf.storage)	    undobuf.storage = (char *) oballoc (0);	  return gen_rtx (CONST_INT, VOIDmode, intval);	}      /* Zero-extending the result of an and with a constant can be done	 with a wider and.  */      if (was_replaced[0]	  && GET_CODE (to) == AND	  && GET_CODE (XEXP (to, 1)) == CONST_INT	  && FAKE_EXTEND_SAFE_P (GET_MODE (x), XEXP (to, 0))	  /* Avoid getting wrong result if the constant has high bits set	     that are irrelevant in the narrow mode where it is being used.  */	  && 0 == (INTVAL (XEXP (to, 1))		   & ~ GET_MODE_MASK (GET_MODE (to))))	{	  if (!undobuf.storage)	    undobuf.storage = (char *) oballoc (0);	  return gen_rtx (AND, GET_MODE (x),			  gen_lowpart_for_combine (GET_MODE (x), XEXP (to, 0)),			  XEXP (to, 1));	}       /* Change (zero_extend:M (subreg:N (zero_extract:M ...) 0))	 to (zero_extract:M ...) if the field extracted fits in mode N.  */      if (GET_CODE (XEXP (x, 0)) == SUBREG	  && GET_CODE (XEXP (XEXP (x, 0), 0)) == ZERO_EXTRACT	  && GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)) == CONST_INT	  && (INTVAL (XEXP (XEXP (XEXP (x, 0), 0), 1))	      <= GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0)))))	{	  return XEXP (XEXP (x, 0), 0);	}      /* Change (zero_extend:M (subreg:N (and:M ... <const>) 0))	 to (and:M ...) if the significant bits fit in mode N.  */      if (GET_CODE (XEXP (x, 0)) == SUBREG	  && SUBREG_REG (XEXP (x, 0)) == to	  && SUBREG_WORD (XEXP (x, 0)) == 0	  && GET_CODE (to) == AND	  && GET_CODE (XEXP (to, 1)) == CONST_INT	  && FAKE_EXTEND_SAFE_P (GET_MODE (x), XEXP (to, 0))	  /* Avoid getting wrong result if the constant has high bits set	     that are irrelevant in the narrow mode where it is being used.  */	  && 0 == (INTVAL (XEXP (to, 1))		   & ~ GET_MODE_MASK (GET_MODE (to))))	{	  if (!undobuf.storage)	    undobuf.storage = (char *) oballoc (0);	  return gen_rtx (AND, GET_MODE (x),			  gen_lowpart_for_combine (GET_MODE (x), XEXP (to, 0)),			  XEXP (to, 1));	}      /* In (zero_extend:M (subreg:N (lshiftrt:M REG))),	 where REG was assigned from (zero_extend:M (any:N ...)),	 remove the outer zero extension.  */      if (GET_CODE (XEXP (x, 0)) == SUBREG	  && SUBREG_REG (XEXP (x, 0)) == to	  && SUBREG_WORD (XEXP (x, 0)) == 0	  && GET_CODE (to) == LSHIFTRT)	{	  rtx tmp = XEXP (to, 0);	  /* See if arg of LSHIFTRT is a register whose value we can find.  */	  if (GET_CODE (tmp) == REG)	    if (reg_n_sets[REGNO (tmp)] == 1		&& reg_last_set[REGNO (tmp)] != 0		&& SET_DEST (PATTERN (reg_last_set[REGNO (tmp)])) == tmp)	      tmp = SET_SRC (PATTERN (reg_last_set[REGNO (tmp)]));	    else	      break;	  if (GET_CODE (tmp) == ZERO_EXTEND	      && GET_MODE (tmp) == GET_MODE (x)	      && GET_MODE (XEXP (tmp, 0)) == GET_MODE (XEXP (x, 0)))	    return SUBREG_REG (XEXP (x, 0));	}      break;    case SIGN_EXTEND:      /* Nested sign-extends are equivalent to just one.  */      if (was_replaced[0]	  && GET_CODE (to) == SIGN_EXTEND)	SUBST (XEXP (x, 0), XEXP (to, 0));      /* Sign extending a constant int can be replaced	 by a sign-extended constant.  */      if (was_replaced[0]	  && HOST_BITS_PER_INT >= GET_MODE_BITSIZE (GET_MODE (from))	  && GET_CODE (to) == CONST_INT)	{	  int intval = INTVAL (to);	  if (!undobuf.storage)	    undobuf.storage = (char *) oballoc (0);	  if (intval > 0	      && (intval & (1 << (GET_MODE_BITSIZE (GET_MODE (from)) - 1))))	    intval |= ~ GET_MODE_MASK (GET_MODE (from));	  return gen_rtx (CONST_INT, VOIDmode, intval);	}      /* Sign-extending the result of an and with a constant can be done	 with a wider and, provided the high bit of the constant is 0.  */      if (was_replaced[0]	  && GET_CODE (to) == AND	  && GET_CODE (XEXP (to, 1)) == CONST_INT	  && FAKE_EXTEND_SAFE_P (GET_MODE (x), XEXP (to, 0))	  && ((INTVAL (XEXP (to, 1))	       & (-1 << (GET_MODE_BITSIZE (GET_MODE (to)) - 1)))	      == 0))	{	  if (!undobuf.storage)	    undobuf.storage = (char *) oballoc (0);	  return gen_rtx (AND, GET_MODE (x),			  gen_lowpart_for_combine (GET_MODE (x), XEXP (to, 0)),			  XEXP (to, 1));	 }       /* hacks added by tiemann.  */      /* Change (sign_extend:M (subreg:N (and:M ... <const>) 0))	 to (and:M ...), provided the result fits in mode N,	 and the high bit of the constant is 0 in mode N.  */      if (GET_CODE (XEXP (x, 0)) == SUBREG	  && SUBREG_REG (XEXP (x, 0)) == to	  && SUBREG_WORD (XEXP (x, 0)) == 0	  && GET_CODE (to) == AND	  && GET_CODE (XEXP (to, 1)) == CONST_INT	  && FAKE_EXTEND_SAFE_P (GET_MODE (x), XEXP (to, 0))	  && ((INTVAL (XEXP (to, 1))	       & (-1 << (GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0))) - 1)))	      == 0))	{	  if (!undobuf.storage)	    undobuf.storage = (char *) oballoc (0);	  return gen_rtx (AND, GET_MODE (x),			  gen_lowpart_for_combine (GET_MODE (x), XEXP (to, 0)),			  XEXP (to, 1));	}       /* In (sign_extend:M (subreg:N (ashiftrt:M REG))),	 where REG was assigned from (sign_extend:M (any:N ...)),	 remove the outer sign extension.  */      if (GET_CODE (XEXP (x, 0)) == SUBREG	  && SUBREG_REG (XEXP (x, 0)) == to	  && SUBREG_WORD (XEXP (x, 0)) == 0	  && GET_CODE (to) == ASHIFTRT)	{	  rtx tmp = XEXP (to, 0);	  /* See if arg of LSHIFTRT is a register whose value we can find.  */	  if (GET_CODE (tmp) == REG)	    if (reg_n_sets[REGNO (tmp)] == 1		&& reg_last_set[REGNO (tmp)] != 0		&& SET_DEST (PATTERN (reg_last_set[REGNO (tmp)])) == tmp)	      tmp = SET_SRC (PATTERN (reg_last_set[REGNO (tmp)]));	    else	      break;	  if (GET_CODE (tmp) == SIGN_EXTEND	      && GET_MODE (tmp) == GET_MODE (x)	      && GET_MODE (XEXP (tmp, 0)) == GET_MODE (XEXP (x, 0)))	    return SUBREG_REG (XEXP (x, 0));	}      break;    case SET:      /* In (set (zero-extract <x> <n> <y>) (and <foo> <(2**n-1) | anything>))	 the `and' can be deleted.  This can happen when storing a bit	 that came from a set-flag insn followed by masking to one bit.  */      if (GET_CODE (XEXP (x, 0)) == ZERO_EXTRACT	  && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT	  && was_replaced[1]	  && GET_CODE (to) == AND	  && GET_CODE (XEXP (to, 1)) == CONST_INT	  && 0 == (((1 << INTVAL (XEXP (XEXP (x, 0), 1))) - 1)		   & ~ INTVAL (XEXP (to, 1))))	{	  SUBST (XEXP (x, 1), XEXP (to, 0));	}       /* In (set (zero-extract <x> <n> <y>)		 (subreg (and <foo> <(2**n-1) | anything>)))	 the `and' can be deleted.  */      if (GET_CODE (XEXP (x, 0)) == ZERO_EXTRACT	  && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT	  && GET_CODE (XEXP (x, 1)) == SUBREG	  && SUBREG_WORD (XEXP (x, 1)) == 0	  && GET_CODE (SUBREG_REG (XEXP (x, 1))) == AND	  && GET_CODE (XEXP (SUBREG_REG (XEXP (x, 1)), 1)) == CONST_INT	  && 0 == (((1 << INTVAL (XEXP (XEXP (x, 0), 1))) - 1)		   & ~ INTVAL (XEXP (SUBREG_REG (XEXP (x, 1)), 1))))	{	  SUBST (SUBREG_REG (XEXP (x, 1)), XEXP (SUBREG_REG (XEXP (x, 1)), 0));	}       /* (set (zero_extract ...) (and/or/xor (zero_extract ...) const)),	 if both zero_extracts have the same location, size and position,	 can be changed to avoid the byte extracts.  */      if ((GET_CODE (XEXP (x, 0)) == ZERO_EXTRACT	   || GET_CODE (XEXP (x, 0)) == SIGN_EXTRACT)	  && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT	  && (GET_CODE (XEXP (x, 1)) == AND	      || GET_CODE (XEXP (x, 1)) == IOR	      || GET_CODE (XEXP (x, 1)) == XOR)	  && rtx_equal_p (XEXP (x, 0), XEXP (XEXP (x, 1), 0))	  && GET_CODE (XEXP (XEXP (x, 1), 0)) == GET_CODE (XEXP (x, 0))	  && GET_CODE (XEXP (XEXP (x, 1), 1)) == CONST_INT	  /* zero_extract can apply to a QImode even if the bits extracted	     don't fit inside that byte.  In such a case, we may not do this	     optimization, since the OR or AND insn really would need	     to fit in a byte.  */	  && (INTVAL (XEXP (XEXP (x, 0), 1)) + INTVAL (XEXP (XEXP (x, 0), 2))	      < GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (x, 0), 0)))))	{	  int shiftcount;	  int fieldsize;	  int newmask;#ifdef BITS_BIG_ENDIAN	  shiftcount	    = GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (x, 0), 0)))	      - INTVAL (XEXP (XEXP (x, 0), 1)) - INTVAL (XEXP (XEXP (x, 0), 2));#else	  shiftcount	    = INTVAL (XEXP (XEXP (x, 0), 2));#endif	  fieldsize = INTVAL (XEXP (XEXP (x, 0), 1));	  newmask = ((INTVAL (XEXP (XEXP (x, 1), 1)) << shiftcount)		     + (GET_CODE (XEXP (x, 1)) == AND			/* For AND, preserve the bits outside this field.  */			? ((1 << shiftcount) - 1			   + (-1 << (shiftcount + fieldsize)))			: 0));	  if (GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (x, 0), 0)))	      < HOST_BITS_PER_INT)	    newmask &= (1 << GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (x, 0), 0)))) - 1;	  if (!undobuf.storage)	    undobuf.storage = (char *) oballoc (0);	  return	    gen_rtx (SET, VOIDmode,		     XEXP (XEXP (x, 0), 0),		     gen_rtx (GET_CODE (XEXP (x, 1)),			      GET_MODE (XEXP (XEXP (x, 0), 0)),			      XEXP (XEXP (XEXP (x, 1), 0), 0),			      gen_rtx (CONST_INT, VOIDmode, newmask)));	}      /* Can simplify (set (cc0) (compare (zero/sign_extend FOO) CONST))	 to (set (cc0) (compare FOO CONST)) if CONST fits in FOO's mode	 and we are only testing equality.	 In fact, this is valid for zero_extend if what follows is an	 unsigned comparison, and for sign_extend with a signed comparison.  */      if (SET_DEST (x) == cc0_rtx	  && GET_CODE (SET_SRC (x)) == COMPARE	  && (GET_CODE (XEXP (SET_SRC (x), 0)) == ZERO_EXTEND	      || GET_CODE (XEXP (SET_SRC (x), 0)) == SIGN_EXTEND)	  && next_insn_tests_no_inequality (subst_insn)	  && GET_CODE (XEXP (SET_SRC (x), 1)) == CONST_INT	  /* This is overly cautious by one bit, but saves worrying about	     whether it is zero-extension or sign extension.  */	  && ((unsigned) INTVAL (XEXP (SET_SRC (x), 1))	      < (1 << (GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (SET_SRC (x), 0), 0))) - 1))))	SUBST (XEXP (SET_SRC (x), 0), XEXP (XEXP (SET_SRC (x), 0), 0));      break;    case AND:      if (GET_CODE (XEXP (x, 1)) == CONST_INT)	{	  rtx tem = simplify_and_const_int (x, to);	  if (tem)	    return tem;	}      break;    case IOR:    case XOR:      /* (ior (ior x c1) c2) => (ior x c1|c2); likewise for xor.  */      if (GET_CODE (XEXP (x, 1)) == CONST_INT	  && GET_CODE (XEXP (x, 0)) == code

⌨️ 快捷键说明

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