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

📄 fold-const.c

📁 这是完整的gcc源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
		}	    }	  mul_double (int1l, int1h, int2l, int2h, &low, &hi);	  t = build_int_2 (low, hi);	  break;	case TRUNC_DIV_EXPR: case ROUND_DIV_EXPR: 	case FLOOR_DIV_EXPR: case CEIL_DIV_EXPR:	case EXACT_DIV_EXPR:	  if (int2h == 0 && int2l == 1)	    {	      t = build_int_2 (int1l, int1h);	      break;	    }	  if (int1l == int2l && int1h == int2h)	    {	      if ((int1l | int1h) == 0)		abort ();	      t = build_int_2 (1, 0);	      break;	    }	  div_and_round_double (code, uns, int1l, int1h, int2l, int2h,				&low, &hi, &garbagel, &garbageh);	  t = build_int_2 (low, hi);	  break;	case TRUNC_MOD_EXPR: case ROUND_MOD_EXPR: 	case FLOOR_MOD_EXPR: case CEIL_MOD_EXPR:	  div_and_round_double (code, uns, int1l, int1h, int2l, int2h,				&garbagel, &garbageh, &low, &hi);	  t = build_int_2 (low, hi);	  break;	case MIN_EXPR:	case MAX_EXPR:	  if (uns)	    {	      low = (((unsigned) int1h < (unsigned) int2h)		     || (((unsigned) int1h == (unsigned) int2h)			 && ((unsigned) int1l < (unsigned) int2l)));	    }	  else	    {	      low = ((int1h < int2h)		     || ((int1h == int2h)			 && ((unsigned) int1l < (unsigned) int2l)));	    }	  if (low == (code == MIN_EXPR))	    t = build_int_2 (int1l, int1h);	  else	    t = build_int_2 (int2l, int2h);	  break;	default:	  abort ();	}    got_it:      TREE_TYPE (t) = TREE_TYPE (arg1);      force_fit_type (t);      return t;    }#if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)  if (TREE_CODE (arg1) == REAL_CST)    {      register REAL_VALUE_TYPE d1 = TREE_REAL_CST (arg1);      register REAL_VALUE_TYPE d2 = TREE_REAL_CST (arg2);      register REAL_VALUE_TYPE value;      if (setjmp (combine_error))	{	  warning ("floating overflow in constant folding");	  return build (code, TREE_TYPE (arg1), arg1, arg2);	}      set_float_handler (combine_error);#ifdef REAL_ARITHMETIC      REAL_ARITHMETIC (value, code, d1, d2);#else      switch (code)	{	case PLUS_EXPR:	  value = d1 + d2;	  break;	case MINUS_EXPR:	  value = d1 - d2;	  break;	case MULT_EXPR:	  value = d1 * d2;	  break;	case RDIV_EXPR:	  if (d2 == 0)	    abort ();	  value = d1 / d2;	  break;	case MIN_EXPR:	  value = d1 < d2 ? d1 : d2;	  break;	case MAX_EXPR:	  value = d1 > d2 ? d1 : d2;	  break;	default:	  abort ();	}#endif /* no REAL_ARITHMETIC */      set_float_handler (0);      if (TYPE_MODE (TREE_TYPE (arg1)) == SFmode)	value = REAL_VALUE_TRUNCATE (value);      return build_real (TREE_TYPE (arg1), value);    }#endif /* not REAL_IS_NOT_DOUBLE, or REAL_ARITHMETIC */  if (TREE_CODE (arg1) == COMPLEX_CST)    {      register tree r1 = TREE_REALPART (arg1);      register tree i1 = TREE_IMAGPART (arg1);      register tree r2 = TREE_REALPART (arg2);      register tree i2 = TREE_IMAGPART (arg2);      register tree t;      switch (code)	{	case PLUS_EXPR:	  t = build_complex (combine (PLUS_EXPR, r1, r2),			     combine (PLUS_EXPR, i1, i2));	  break;	case MINUS_EXPR:	  t = build_complex (combine (MINUS_EXPR, r1, r2),			     combine (MINUS_EXPR, i1, i2));	  break;	case MULT_EXPR:	  t = build_complex (combine (MINUS_EXPR,				      combine (MULT_EXPR, r1, r2),				      combine (MULT_EXPR, i1, i2)),			     combine (PLUS_EXPR,				      combine (MULT_EXPR, r1, i2),				      combine (MULT_EXPR, i1, r2)));	  break;	case RDIV_EXPR:	  {	    register tree magsquared	      = combine (PLUS_EXPR,			 combine (MULT_EXPR, r2, r2),			 combine (MULT_EXPR, i2, i2));	    t = build_complex (combine (RDIV_EXPR,					combine (PLUS_EXPR,						 combine (MULT_EXPR, r1, r2),						 combine (MULT_EXPR, i1, i2)),					magsquared),			       combine (RDIV_EXPR,					combine (MINUS_EXPR,						 combine (MULT_EXPR, i1, r2),						 combine (MULT_EXPR, r1, i2)),					magsquared));	  }	  break;	default:	  abort ();	}      TREE_TYPE (t) = TREE_TYPE (arg1);      return t;    }  return 0;}/* Given T, a tree representing type conversion of a constant,   return a constant tree representing the result of conversion.  */static treefold_convert (t)     register tree t;{  register tree arg1 = TREE_OPERAND (t, 0);  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));	  TREE_TYPE (t) = type;	  force_fit_type (t);	}#if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)      else if (TREE_CODE (arg1) == REAL_CST)	{	  if (REAL_VALUES_LESS (real_value_from_int_cst (TYPE_MAX_VALUE (type)),				TREE_REAL_CST (arg1))	      || REAL_VALUES_LESS (TREE_REAL_CST (arg1),				   real_value_from_int_cst (TYPE_MIN_VALUE (type))))	    {	      warning ("real constant out of range for integer conversion");	      return t;	    }#ifndef REAL_ARITHMETIC	  {	    REAL_VALUE_TYPE d;	    int low, high;	    int half_word = 1 << (HOST_BITS_PER_INT / 2);	    d = TREE_REAL_CST (arg1);	    if (d < 0)	      d = -d;	    high = (int) (d / half_word / half_word);	    d -= (REAL_VALUE_TYPE) high * half_word * half_word;	    low = (unsigned) d;	    if (TREE_REAL_CST (arg1) < 0)	      neg_double (low, high, &low, &high);	    t = build_int_2 (low, high);	  }#else	  {	    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)	{	  REAL_VALUE_TYPE r = TREE_REAL_CST (arg1);	  /* This handles conversion from double to float,	     which is the only nontrivial float conversion now supported.  */	  if (TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (arg1)))	    r = REAL_VALUE_TRUNCATE (r);	  return build_real (type, r);	}    }  TREE_LITERAL (t) = 1;  return t;}/* Return nonzero if two constants (that are not manifest constants)   are necessarily equal.  It detects only the easiest, common case of   equality.  */static intoperand_equal_p (arg0, arg1)     tree arg0, arg1;{  while ((TREE_CODE (arg0) == NOP_EXPR	  || TREE_CODE (arg0) == CONVERT_EXPR)	 && TYPE_MODE (TREE_TYPE (arg0)) == TYPE_MODE (TREE_TYPE (TREE_OPERAND (arg0, 0))))    arg0 = TREE_OPERAND (arg0, 0);  while ((TREE_CODE (arg1) == NOP_EXPR	  || TREE_CODE (arg1) == CONVERT_EXPR)	 && TYPE_MODE (TREE_TYPE (arg1)) == TYPE_MODE (TREE_TYPE (TREE_OPERAND (arg1, 0))))    arg1 = TREE_OPERAND (arg1, 0);  if (TREE_CODE (arg0) == TREE_CODE (arg1)      && TREE_CODE (arg0) == ADDR_EXPR      && TREE_OPERAND (arg0, 0) == TREE_OPERAND (arg1, 0))    return 1;  return 0;}#if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)/* Return 1 if ARG is a real constant with value zero.   This function is not defined in the case where it is impossible   to tell whether a real constant is zero (for cross-compilation).  */static intreal_zerop (arg)     tree arg;{#ifdef REAL_IS_NOT_DOUBLE  tree t1 = build_real_from_int_cst (TREE_TYPE (arg), integer_zero_node);  return REAL_VALUES_EQUAL (TREE_REAL_CST (arg), TREE_REAL_CST (t1));#else  return TREE_REAL_CST (arg) == 0;#endif}#endif /* not REAL_IS_NOT_DOUBLE, or REAL_ARITHMETIC *//* Perform constant folding and related simplification of EXPR.   The related simplifications include x*1 => x, x*0 => 0, etc.,   and application of the associative law.   NOP_EXPR conversions may be removed freely (as long as we   are careful not to change the C type of the overall expression)   We cannot simplify through a CONVERT_EXPR, FIX_EXPR or FLOAT_EXPR,   but we can constant-fold them if they have constant operands.  */treefold (expr)      tree expr;{  register tree t = expr;  tree type = TREE_TYPE (expr);  register tree arg0, arg1;  register enum tree_code code = TREE_CODE (t);  register int kind;  /* WINS will be nonzero when the switch is done     if all operands are constant.     LOSES will be nonzero when the switch is done     if any operand is volatile.     This inhibits optimizations such as  (foo () * 0) => 0.     But identity-element optimizations such as     (foo () * 1) => (foo ()) can be done even if LOSES is set.  */  int wins = 1;  int loses = 0;  /* Return right away if already constant.  */  if (TREE_LITERAL (t))    {      if (code == CONST_DECL)	return DECL_INITIAL (t);      return t;    }    kind = *tree_code_type[(int) code];  if (kind == 'e' || kind == 'r')    {      register int len = tree_code_length[(int) code];      register int i;      for (i = 0; i < len; i++)	{	  if (TREE_OPERAND (t, i) == 0)	    continue;		/* Valid for CALL_EXPR, at least.  */	  if (TREE_CODE (TREE_OPERAND (t, i)) != INTEGER_CST#if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)	      && TREE_CODE (TREE_OPERAND (t, i)) != REAL_CST#endif /* not REAL_IS_NOT_DOUBLE, or REAL_ARITHMETIC */	      )	    /* Note that TREE_LITERAL isn't enough:	       static var addresses are constant but we can't	       do arithmetic on them.  */	    wins = 0;	  if (TREE_VOLATILE (TREE_OPERAND (t, i)))	    loses = 1;	}      arg0 = TREE_OPERAND (t, 0);      if (len > 1)	arg1 = TREE_OPERAND (t, 1);    }  /* Now WINS and LOSES are set as described above,     ARG0 is the first operand of EXPR,     and ARG1 is the second operand (if it has more than one operand).  */  switch (code)    {    case INTEGER_CST:    case REAL_CST:    case STRING_CST:    case COMPLEX_CST:    case CONSTRUCTOR:      return t;    case CONST_DECL:      return fold (DECL_INITIAL (t));    case NOP_EXPR:    case FLOAT_EXPR:    case CONVERT_EXPR:    case FIX_TRUNC_EXPR:      /* Other kinds of FIX are not handled properly by fold_convert.  */      if (!wins)	{	  TREE_LITERAL (t) = TREE_LITERAL (arg0);	  return t;	}      return fold_convert (t);#if 0  /* This loses on &"foo"[0].  */    case ARRAY_REF:	{	  int i;	  /* Fold an expression like: "foo"[2] */	  if (TREE_CODE (arg0) == STRING_CST	      && TREE_CODE (arg1) == INTEGER_CST	      && !TREE_INT_CST_HIGH (arg1)	      && (i = TREE_INT_CST_LOW (arg1)) < TREE_STRING_LENGTH (arg0))	    {	      t = build_int_2 (TREE_STRING_POINTER (arg0)[i], 0);	      TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (arg0));	      force_fit_type (t);	    }	}      return t;#endif /* 0 */    case RANGE_EXPR:      TREE_LITERAL (t) = wins;      return t;    case NEGATE_EXPR:      if (wins)	{	  if (TREE_CODE (arg0) == INTEGER_CST)	    {	      if (TREE_INT_CST_LOW (arg0) == 0)		t = build_int_2 (0, - TREE_INT_CST_HIGH (arg0));	      else		t = build_int_2 (- TREE_INT_CST_LOW (arg0),				 ~ TREE_INT_CST_HIGH (arg0));	      TREE_TYPE (t) = type;	      force_fit_type (t);	    }	  else if (TREE_CODE (arg0) == REAL_CST)	    t = build_real (type, REAL_VALUE_NEGATE (TREE_REAL_CST (arg0)));	  TREE_TYPE (t) = type;	}      return t;    case ABS_EXPR:      if (wins)	{	  if (TREE_CODE (arg0) == INTEGER_CST)	    {	      if (! TREE_UNSIGNED (type)		  && TREE_INT_CST_HIGH (arg0) < 0)		{		  if (TREE_INT_CST_LOW (arg0) == 0)		    t = build_int_2 (0, - TREE_INT_CST_HIGH (arg0));		  else		    t = build_int_2 (- TREE_INT_CST_LOW (arg0),				     ~ TREE_INT_CST_HIGH (arg0));		}	    }	  else if (TREE_CODE (arg0) == REAL_CST)	    {	      if (#if defined (REAL_IS_NOT_DOUBLE)		  REAL_VALUES_LESS (TREE_REAL_CST (arg0),				    REAL_VALUE_ATOF ("0.0"))#else		  REAL_VALUES_LESS (TREE_REAL_CST (arg0), 0)#endif		  )		t = build_real (type,				REAL_VALUE_NEGATE (TREE_REAL_CST (arg0)));	    }	  TREE_TYPE (t) = type;	}      return t;    case BIT_NOT_EXPR:      if (wins)

⌨️ 快捷键说明

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