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

📄 fold-const.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
  if (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST)    {      /* And some specific cases even faster than that.  */      if (code == PLUS_EXPR	  && TREE_INT_CST_LOW (arg0) == 0	  && TREE_INT_CST_HIGH (arg0) == 0)	return arg1;      if (code == MINUS_EXPR	  && TREE_INT_CST_LOW (arg1) == 0	  && TREE_INT_CST_HIGH (arg1) == 0)	return arg0;      if (code == MULT_EXPR	  && TREE_INT_CST_LOW (arg0) == 1	  && TREE_INT_CST_HIGH (arg0) == 0)	return arg1;      /* Handle general case of two integer constants.  */      return const_binop (code, arg0, arg1);    }  if (arg0 == error_mark_node || arg1 == error_mark_node)    return error_mark_node;  return fold (build (code, sizetype, arg0, arg1));}/* Given T, a tree representing type conversion of ARG1, a constant,   return a constant tree representing the result of conversion.  */static treefold_convert (t, arg1)     register tree t;     register tree arg1;{  register tree type = TREE_TYPE (t);  if (TREE_CODE (type) == POINTER_TYPE      || TREE_CODE (type) == INTEGER_TYPE      || TREE_CODE (type) == ENUMERAL_TYPE)    {      if (TREE_CODE (arg1) == INTEGER_CST)	{	  /* Given an integer constant, make new constant with new type,	     appropriately sign-extended or truncated.  */	  t = build_int_2 (TREE_INT_CST_LOW (arg1),			   TREE_INT_CST_HIGH (arg1));	  /* Carry forward overflow indication unless truncating.  */	  if (TYPE_PRECISION (type) >= TYPE_PRECISION (TREE_TYPE (t)))	    TREE_CONSTANT_OVERFLOW (t) = TREE_CONSTANT_OVERFLOW (arg1);	  TREE_TYPE (t) = type;	  force_fit_type (t);	}#if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)      else if (TREE_CODE (arg1) == REAL_CST)	{	  REAL_VALUE_TYPE	    l = real_value_from_int_cst (TYPE_MIN_VALUE (type)),	    x = TREE_REAL_CST (arg1),	    u = real_value_from_int_cst (TYPE_MAX_VALUE (type));	  /* See if X will be in range after truncation towards 0.	     To compensate for truncation, move the bounds away from 0,	     but reject if X exactly equals the adjusted bounds.  */#ifdef REAL_ARITHMETIC	  REAL_ARITHMETIC (l, MINUS_EXPR, l, dconst1);	  REAL_ARITHMETIC (u, PLUS_EXPR, u, dconst1);#else	  l--;	  u++;#endif	  if (! (REAL_VALUES_LESS (l, x) && REAL_VALUES_LESS (x, u)))	    {	      pedwarn ("real constant out of range for integer conversion");	      return t;	    }#ifndef REAL_ARITHMETIC	  {	    REAL_VALUE_TYPE d;	    HOST_WIDE_INT low, high;	    HOST_WIDE_INT half_word	      = (HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT / 2);	    d = TREE_REAL_CST (arg1);	    if (d < 0)	      d = -d;	    high = (HOST_WIDE_INT) (d / half_word / half_word);	    d -= (REAL_VALUE_TYPE) high * half_word * half_word;	    if (d >= (REAL_VALUE_TYPE) half_word * half_word / 2)	      {		low = d - (REAL_VALUE_TYPE) half_word * half_word / 2;		low |= (HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1);	      }	    else	      low = (HOST_WIDE_INT) d;	    if (TREE_REAL_CST (arg1) < 0)	      neg_double (low, high, &low, &high);	    t = build_int_2 (low, high);	  }#else	  {	    HOST_WIDE_INT low, high;	    REAL_VALUE_TO_INT (low, high, TREE_REAL_CST (arg1));	    t = build_int_2 (low, high);	  }#endif	  TREE_TYPE (t) = type;	  force_fit_type (t);	}#endif /* not REAL_IS_NOT_DOUBLE, or REAL_ARITHMETIC */      TREE_TYPE (t) = type;    }  else if (TREE_CODE (type) == REAL_TYPE)    {#if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)      if (TREE_CODE (arg1) == INTEGER_CST)	return build_real_from_int_cst (type, arg1);#endif /* not REAL_IS_NOT_DOUBLE, or REAL_ARITHMETIC */      if (TREE_CODE (arg1) == REAL_CST)	{	  if (setjmp (float_error))	    {	      pedwarn ("floating overflow in constant expression");	      return t;	    }	  set_float_handler (float_error);	  t = build_real (type, real_value_truncate (TYPE_MODE (type),						     TREE_REAL_CST (arg1)));	  set_float_handler (NULL_PTR);	  return t;	}    }  TREE_CONSTANT (t) = 1;  return t;}/* Return an expr equal to X but certainly not valid as an lvalue.  */treenon_lvalue (x)     tree x;{  tree result;  /* These things are certainly not lvalues.  */  if (TREE_CODE (x) == NON_LVALUE_EXPR      || TREE_CODE (x) == INTEGER_CST      || TREE_CODE (x) == REAL_CST      || TREE_CODE (x) == STRING_CST      || TREE_CODE (x) == ADDR_EXPR)    return x;  result = build1 (NON_LVALUE_EXPR, TREE_TYPE (x), x);  TREE_CONSTANT (result) = TREE_CONSTANT (x);  return result;}/* Given a tree comparison code, return the code that is the logical inverse   of the given code.  It is not safe to do this for floating-point   comparisons, except for NE_EXPR and EQ_EXPR.  */static enum tree_codeinvert_tree_comparison (code)     enum tree_code code;{  switch (code)    {    case EQ_EXPR:      return NE_EXPR;    case NE_EXPR:      return EQ_EXPR;    case GT_EXPR:      return LE_EXPR;    case GE_EXPR:      return LT_EXPR;    case LT_EXPR:      return GE_EXPR;    case LE_EXPR:      return GT_EXPR;    default:      abort ();    }}/* Similar, but return the comparison that results if the operands are   swapped.  This is safe for floating-point.  */static enum tree_codeswap_tree_comparison (code)     enum tree_code code;{  switch (code)    {    case EQ_EXPR:    case NE_EXPR:      return code;    case GT_EXPR:      return LT_EXPR;    case GE_EXPR:      return LE_EXPR;    case LT_EXPR:      return GT_EXPR;    case LE_EXPR:      return GE_EXPR;    default:      abort ();    }}/* Return nonzero if two operands are necessarily equal.   If ONLY_CONST is non-zero, only return non-zero for constants.   This function tests whether the operands are indistinguishable;   it does not test whether they are equal using C's == operation.   The distinction is important for IEEE floating point, because   (1) -0.0 and 0.0 are distinguishable, but -0.0==0.0, and   (2) two NaNs may be indistinguishable, but NaN!=NaN.  */intoperand_equal_p (arg0, arg1, only_const)     tree arg0, arg1;     int only_const;{  /* If both types don't have the same signedness, then we can't consider     them equal.  We must check this before the STRIP_NOPS calls     because they may change the signedness of the arguments.  */  if (TREE_UNSIGNED (TREE_TYPE (arg0)) != TREE_UNSIGNED (TREE_TYPE (arg1)))    return 0;  STRIP_NOPS (arg0);  STRIP_NOPS (arg1);  /* If ARG0 and ARG1 are the same SAVE_EXPR, they are necessarily equal.     We don't care about side effects in that case because the SAVE_EXPR     takes care of that for us.  */  if (TREE_CODE (arg0) == SAVE_EXPR && arg0 == arg1)    return ! only_const;  if (TREE_SIDE_EFFECTS (arg0) || TREE_SIDE_EFFECTS (arg1))    return 0;  if (TREE_CODE (arg0) == TREE_CODE (arg1)      && TREE_CODE (arg0) == ADDR_EXPR      && TREE_OPERAND (arg0, 0) == TREE_OPERAND (arg1, 0))    return 1;  if (TREE_CODE (arg0) == TREE_CODE (arg1)      && TREE_CODE (arg0) == INTEGER_CST      && TREE_INT_CST_LOW (arg0) == TREE_INT_CST_LOW (arg1)      && TREE_INT_CST_HIGH (arg0) == TREE_INT_CST_HIGH (arg1))    return 1;  /* Detect when real constants are equal.  */  if (TREE_CODE (arg0) == TREE_CODE (arg1)      && TREE_CODE (arg0) == REAL_CST)    return !bcmp (&TREE_REAL_CST (arg0), &TREE_REAL_CST (arg1),		  sizeof (REAL_VALUE_TYPE));  if (only_const)    return 0;  if (arg0 == arg1)    return 1;  if (TREE_CODE (arg0) != TREE_CODE (arg1))    return 0;  /* This is needed for conversions and for COMPONENT_REF.     Might as well play it safe and always test this.  */  if (TYPE_MODE (TREE_TYPE (arg0)) != TYPE_MODE (TREE_TYPE (arg1)))    return 0;  switch (TREE_CODE_CLASS (TREE_CODE (arg0)))    {    case '1':      /* Two conversions are equal only if signedness and modes match.  */      if ((TREE_CODE (arg0) == NOP_EXPR || TREE_CODE (arg0) == CONVERT_EXPR)	  && (TREE_UNSIGNED (TREE_TYPE (arg0))	      != TREE_UNSIGNED (TREE_TYPE (arg1))))	return 0;      return operand_equal_p (TREE_OPERAND (arg0, 0),			      TREE_OPERAND (arg1, 0), 0);    case '<':    case '2':      return (operand_equal_p (TREE_OPERAND (arg0, 0),			       TREE_OPERAND (arg1, 0), 0)	      && operand_equal_p (TREE_OPERAND (arg0, 1),				  TREE_OPERAND (arg1, 1), 0));    case 'r':      switch (TREE_CODE (arg0))	{	case INDIRECT_REF:	  return operand_equal_p (TREE_OPERAND (arg0, 0),				  TREE_OPERAND (arg1, 0), 0);	case COMPONENT_REF:	case ARRAY_REF:	  return (operand_equal_p (TREE_OPERAND (arg0, 0),				   TREE_OPERAND (arg1, 0), 0)		  && operand_equal_p (TREE_OPERAND (arg0, 1),				      TREE_OPERAND (arg1, 1), 0));	case BIT_FIELD_REF:	  return (operand_equal_p (TREE_OPERAND (arg0, 0),				   TREE_OPERAND (arg1, 0), 0)		  && operand_equal_p (TREE_OPERAND (arg0, 1),				      TREE_OPERAND (arg1, 1), 0)		  && operand_equal_p (TREE_OPERAND (arg0, 2),				      TREE_OPERAND (arg1, 2), 0));	}      break;    }  return 0;}/* Similar to operand_equal_p, but see if ARG0 might have been made by   shorten_compare from ARG1 when ARG1 was being compared with OTHER.    When in doubt, return 0.  */static int operand_equal_for_comparison_p (arg0, arg1, other)     tree arg0, arg1;     tree other;{  int unsignedp1, unsignedpo;  tree primarg1, primother;  int correct_width;  if (operand_equal_p (arg0, arg1, 0))    return 1;  if (TREE_CODE (TREE_TYPE (arg0)) != INTEGER_TYPE)    return 0;  /* Duplicate what shorten_compare does to ARG1 and see if that gives the     actual comparison operand, ARG0.     First throw away any conversions to wider types     already present in the operands.  */  primarg1 = get_narrower (arg1, &unsignedp1);  primother = get_narrower (other, &unsignedpo);  correct_width = TYPE_PRECISION (TREE_TYPE (arg1));  if (unsignedp1 == unsignedpo      && TYPE_PRECISION (TREE_TYPE (primarg1)) < correct_width      && TYPE_PRECISION (TREE_TYPE (primother)) < correct_width)    {      tree type = TREE_TYPE (arg0);      /* Make sure shorter operand is extended the right way	 to match the longer operand.  */      primarg1 = convert (signed_or_unsigned_type (unsignedp1,						  TREE_TYPE (primarg1)),			 primarg1);      if (operand_equal_p (arg0, convert (type, primarg1), 0))	return 1;    }  return 0;}/* See if ARG is an expression that is either a comparison or is performing   arithmetic on comparisons.  The comparisons must only be comparing   two different values, which will be stored in *CVAL1 and *CVAL2; if   they are non-zero it means that some operands have already been found.   No variables may be used anywhere else in the expression except in the   comparisons.   If this is true, return 1.  Otherwise, return zero.  */static inttwoval_comparison_p (arg, cval1, cval2)     tree arg;     tree *cval1, *cval2;{  enum tree_code code = TREE_CODE (arg);  char class = TREE_CODE_CLASS (code);  /* We can handle some of the 'e' cases here.  */  if (class == 'e'      && (code == TRUTH_NOT_EXPR	  || (code == SAVE_EXPR && SAVE_EXPR_RTL (arg) == 0)))    class = '1';  else if (class == 'e'	   && (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR	       || code == COMPOUND_EXPR))    class = '2';  switch (class)    {    case '1':      return twoval_comparison_p (TREE_OPERAND (arg, 0), cval1, cval2);    case '2':      return (twoval_comparison_p (TREE_OPERAND (arg, 0), cval1, cval2)	      && twoval_comparison_p (TREE_OPERAND (arg, 1), cval1, cval2));    case 'c':      return 1;    case 'e':      if (code == COND_EXPR)	return (twoval_comparison_p (TREE_OPERAND (arg, 0), cval1, cval2)		&& twoval_comparison_p (TREE_OPERAND (arg, 1), cval1, cval2)		&& twoval_comparison_p (TREE_OPERAND (arg, 2),					cval1, cval2));      return 0;	      case '<':      /* First see if we can handle the first operand, then the second.  For	 the second operand, we know *CVAL1 can't be zero.  It must be that	 one side of the comparison is each of the values; test for the	 case where this isn't true by failing if the two operands	 are the same.  */      if (operand_equal_p (TREE_OPERAND (arg, 0),			   TREE_OPERAND (arg, 1), 0))	return 0;      if (*cval1 == 0)	*cval1 = TREE_OPERAND (arg, 0);      else if (operand_equal_p (*cval1, TREE_OPERAND (arg, 0), 0))	;      else if (*cval2 == 0)	*cval2 = TREE_OPERAND (arg, 0);      else if (operand_equal_p (*cval2, TREE_OPERAND (arg, 0), 0))	;      else	return 0;      if (operand_equal_p (*cval1, TREE_OPERAND (arg, 1), 0))	;      else if (*cval2 == 0)	*cval2 = TREE_OPERAND (arg, 1);      else if (operand_equal_p (*cval2, TREE_OPERAND (arg, 1), 0))	;      else	return 0;      return 1;    }  return 0;}/* ARG is a tree that is known to contain just arithmetic operations and   comparisons.  Evaluate the operations in the tree substituting NEW0 for   any occurrence of OLD0 as an operand of a comparison and likewise for   NEW1 and OLD1.  */static treeeval_subst (arg, old0, new0, old1, new1)     tree arg;     tree old0, new0, old1, new1;{  tree type = TREE_TYPE (arg);  enum tree_code code = TREE_CODE (arg);  char class = TREE_CODE_CLASS (code);  /* We can handle some of the 'e' cases here.  */  if (class == 'e' && code == TRUTH_NOT_EXPR)    class = '1';  else if (class == 'e'	   && (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR))    class = '2';  switch (class)    {    case '1':      return fold (build1 (code, type,			   eval_subst (TREE_OPERAND (arg, 0),				       old0, new0, old1, new1)));    case '2':

⌨️ 快捷键说明

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