aboutsummaryrefslogtreecommitdiff
path: root/gcc/fold-const.c
diff options
context:
space:
mode:
authorAnatoly Sokolov <aesok@post.ru>2010-06-18 19:58:48 +0400
committerAnatoly Sokolov <aesok@gcc.gnu.org>2010-06-18 19:58:48 +0400
commitfd7de64cee04fd08c9a849a20e9cf0fd8d6906e1 (patch)
tree43dbfc5a3de6b7b8c559675266ac518bbcabd39a /gcc/fold-const.c
parentbc87224e9341b186905d8ac849aeb59463ae4f6b (diff)
downloadgcc-fd7de64cee04fd08c9a849a20e9cf0fd8d6906e1.zip
gcc-fd7de64cee04fd08c9a849a20e9cf0fd8d6906e1.tar.gz
gcc-fd7de64cee04fd08c9a849a20e9cf0fd8d6906e1.tar.bz2
double-int.h (double_int_to_shwi, [...]): Implement as static inline.
* double-int.h (double_int_to_shwi, double_int_to_uhwi, double_int_fits_in_uhwi_p): Implement as static inline. (double_int_xor): New inline function. (double_int_lrotate, double_int_rrotate, double_int_max, double_int_umax, double_int_smax, double_int_min, double_int_umin, double_int_smin): Declare. (lrotate_double, rrotate_double): Remove declaration. * double-int.c (double_int_fits_in_uhwi_p, double_int_to_shwi, double_int_to_uhwi, lrotate_double, rrotate_double): Remove function. (double_int_lrotate, double_int_rrotate, double_int_max, double_int_umax, double_int_smax, double_int_min, double_int_umin, double_int_smin): New function. * fold-const.c (int_const_binop): Clean up, use double_int_* functions. * simplify-rtx.c (simplify_const_binary_operation): Clean up, use double_int_* and immed_double_int_const functions. From-SVN: r161002
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r--gcc/fold-const.c119
1 files changed, 57 insertions, 62 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 9abc94e..a1cd5520 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -924,145 +924,140 @@ int_binop_types_match_p (enum tree_code code, const_tree type1, const_tree type2
tree
int_const_binop (enum tree_code code, const_tree arg1, const_tree arg2, int notrunc)
{
- unsigned HOST_WIDE_INT int1l, int2l;
- HOST_WIDE_INT int1h, int2h;
- unsigned HOST_WIDE_INT low;
- HOST_WIDE_INT hi;
- unsigned HOST_WIDE_INT garbagel;
- HOST_WIDE_INT garbageh;
+ double_int op1, op2, res, tmp;
tree t;
tree type = TREE_TYPE (arg1);
- int uns = TYPE_UNSIGNED (type);
- int is_sizetype
+ bool uns = TYPE_UNSIGNED (type);
+ bool is_sizetype
= (TREE_CODE (type) == INTEGER_TYPE && TYPE_IS_SIZETYPE (type));
- int overflow = 0;
+ bool overflow = false;
- int1l = TREE_INT_CST_LOW (arg1);
- int1h = TREE_INT_CST_HIGH (arg1);
- int2l = TREE_INT_CST_LOW (arg2);
- int2h = TREE_INT_CST_HIGH (arg2);
+ op1 = tree_to_double_int (arg1);
+ op2 = tree_to_double_int (arg2);
switch (code)
{
case BIT_IOR_EXPR:
- low = int1l | int2l, hi = int1h | int2h;
+ res = double_int_ior (op1, op2);
break;
case BIT_XOR_EXPR:
- low = int1l ^ int2l, hi = int1h ^ int2h;
+ res = double_int_xor (op1, op2);
break;
case BIT_AND_EXPR:
- low = int1l & int2l, hi = int1h & int2h;
+ res = double_int_and (op1, op2);
break;
case RSHIFT_EXPR:
- int2l = -int2l;
+ res = double_int_rshift (op1, double_int_to_shwi (op2),
+ TYPE_PRECISION (type), !uns);
+ break;
+
case LSHIFT_EXPR:
/* It's unclear from the C standard whether shifts can overflow.
The following code ignores overflow; perhaps a C standard
interpretation ruling is needed. */
- lshift_double (int1l, int1h, int2l, TYPE_PRECISION (type),
- &low, &hi, !uns);
+ res = double_int_lshift (op1, double_int_to_shwi (op2),
+ TYPE_PRECISION (type), !uns);
break;
case RROTATE_EXPR:
- int2l = - int2l;
+ res = double_int_rrotate (op1, double_int_to_shwi (op2),
+ TYPE_PRECISION (type));
+ break;
+
case LROTATE_EXPR:
- lrotate_double (int1l, int1h, int2l, TYPE_PRECISION (type),
- &low, &hi);
+ res = double_int_lrotate (op1, double_int_to_shwi (op2),
+ TYPE_PRECISION (type));
break;
case PLUS_EXPR:
- overflow = add_double (int1l, int1h, int2l, int2h, &low, &hi);
+ overflow = add_double (op1.low, op1.high, op2.low, op2.high,
+ &res.low, &res.high);
break;
case MINUS_EXPR:
- neg_double (int2l, int2h, &low, &hi);
- add_double (int1l, int1h, low, hi, &low, &hi);
- overflow = OVERFLOW_SUM_SIGN (hi, int2h, int1h);
+ neg_double (op2.low, op2.high, &res.low, &res.high);
+ add_double (op1.low, op1.high, res.low, res.high,
+ &res.low, &res.high);
+ overflow = OVERFLOW_SUM_SIGN (res.high, op2.high, op1.high);
break;
case MULT_EXPR:
- overflow = mul_double (int1l, int1h, int2l, int2h, &low, &hi);
+ overflow = mul_double (op1.low, op1.high, op2.low, op2.high,
+ &res.low, &res.high);
break;
case TRUNC_DIV_EXPR:
case FLOOR_DIV_EXPR: case CEIL_DIV_EXPR:
case EXACT_DIV_EXPR:
/* This is a shortcut for a common special case. */
- if (int2h == 0 && (HOST_WIDE_INT) int2l > 0
+ if (op2.high == 0 && (HOST_WIDE_INT) op2.low > 0
&& !TREE_OVERFLOW (arg1)
&& !TREE_OVERFLOW (arg2)
- && int1h == 0 && (HOST_WIDE_INT) int1l >= 0)
+ && op1.high == 0 && (HOST_WIDE_INT) op1.low >= 0)
{
if (code == CEIL_DIV_EXPR)
- int1l += int2l - 1;
+ op1.low += op2.low - 1;
- low = int1l / int2l, hi = 0;
+ res.low = op1.low / op2.low, res.high = 0;
break;
}
/* ... fall through ... */
case ROUND_DIV_EXPR:
- if (int2h == 0 && int2l == 0)
+ if (double_int_zero_p (op2))
return NULL_TREE;
- if (int2h == 0 && int2l == 1)
+ if (double_int_one_p (op2))
{
- low = int1l, hi = int1h;
+ res = op1;
break;
}
- if (int1l == int2l && int1h == int2h
- && ! (int1l == 0 && int1h == 0))
+ if (double_int_equal_p (op1, op2)
+ && ! double_int_zero_p (op1))
{
- low = 1, hi = 0;
+ res = double_int_one;
break;
}
- overflow = div_and_round_double (code, uns, int1l, int1h, int2l, int2h,
- &low, &hi, &garbagel, &garbageh);
+ overflow = div_and_round_double (code, uns,
+ op1.low, op1.high, op2.low, op2.high,
+ &res.low, &res.high,
+ &tmp.low, &tmp.high);
break;
case TRUNC_MOD_EXPR:
case FLOOR_MOD_EXPR: case CEIL_MOD_EXPR:
/* This is a shortcut for a common special case. */
- if (int2h == 0 && (HOST_WIDE_INT) int2l > 0
+ if (op2.high == 0 && (HOST_WIDE_INT) op2.low > 0
&& !TREE_OVERFLOW (arg1)
&& !TREE_OVERFLOW (arg2)
- && int1h == 0 && (HOST_WIDE_INT) int1l >= 0)
+ && op1.high == 0 && (HOST_WIDE_INT) op1.low >= 0)
{
if (code == CEIL_MOD_EXPR)
- int1l += int2l - 1;
- low = int1l % int2l, hi = 0;
+ op1.low += op2.low - 1;
+ res.low = op1.low % op2.low, res.high = 0;
break;
}
/* ... fall through ... */
case ROUND_MOD_EXPR:
- if (int2h == 0 && int2l == 0)
+ if (double_int_zero_p (op2))
return NULL_TREE;
overflow = div_and_round_double (code, uns,
- int1l, int1h, int2l, int2h,
- &garbagel, &garbageh, &low, &hi);
+ op1.low, op1.high, op2.low, op2.high,
+ &tmp.low, &tmp.high,
+ &res.low, &res.high);
break;
case MIN_EXPR:
- case MAX_EXPR:
- if (uns)
- low = (((unsigned HOST_WIDE_INT) int1h
- < (unsigned HOST_WIDE_INT) int2h)
- || (((unsigned HOST_WIDE_INT) int1h
- == (unsigned HOST_WIDE_INT) int2h)
- && int1l < int2l));
- else
- low = (int1h < int2h
- || (int1h == int2h && int1l < int2l));
+ res = double_int_min (op1, op2, uns);
+ break;
- if (low == (code == MIN_EXPR))
- low = int1l, hi = int1h;
- else
- low = int2l, hi = int2h;
+ case MAX_EXPR:
+ res = double_int_max (op1, op2, uns);
break;
default:
@@ -1071,7 +1066,7 @@ int_const_binop (enum tree_code code, const_tree arg1, const_tree arg2, int notr
if (notrunc)
{
- t = build_int_cst_wide (TREE_TYPE (arg1), low, hi);
+ t = build_int_cst_wide (TREE_TYPE (arg1), res.low, res.high);
/* Propagate overflow flags ourselves. */
if (((!uns || is_sizetype) && overflow)
@@ -1082,7 +1077,7 @@ int_const_binop (enum tree_code code, const_tree arg1, const_tree arg2, int notr
}
}
else
- t = force_fit_type_double (TREE_TYPE (arg1), low, hi, 1,
+ t = force_fit_type_double (TREE_TYPE (arg1), res.low, res.high, 1,
((!uns || is_sizetype) && overflow)
| TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2));