diff options
author | aesok <aesok@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-06-18 15:58:48 +0000 |
---|---|---|
committer | aesok <aesok@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-06-18 15:58:48 +0000 |
commit | 90739616821228b8d42607fdd1fcddcb23919574 (patch) | |
tree | 43dbfc5a3de6b7b8c559675266ac518bbcabd39a /gcc | |
parent | aef48c9a82fae9bcda3e3da058f9a4447d293301 (diff) | |
download | gcc-90739616821228b8d42607fdd1fcddcb23919574.tar.gz |
* 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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@161002 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 19 | ||||
-rw-r--r-- | gcc/double-int.c | 152 | ||||
-rw-r--r-- | gcc/double-int.h | 62 | ||||
-rw-r--r-- | gcc/fold-const.c | 119 | ||||
-rw-r--r-- | gcc/simplify-rtx.c | 129 |
5 files changed, 264 insertions, 217 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0e723ef02ac..14bdc453e98 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,22 @@ +2010-06-18 Anatoly Sokolov <aesok@post.ru> + + * 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. + 2010-06-18 Nathan Froyd <froydnj@codesourcery.com> * function.h (types_used_by_cur_var_decl): Change type to a VEC. diff --git a/gcc/double-int.c b/gcc/double-int.c index 000be2bf7b0..7bdda7da212 100644 --- a/gcc/double-int.c +++ b/gcc/double-int.c @@ -432,51 +432,6 @@ rshift_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1, } } -/* Rotate the doubleword integer in L1, H1 left by COUNT places - keeping only PREC bits of result. - Rotate right if COUNT is negative. - Store the value as two `HOST_WIDE_INT' pieces in *LV and *HV. */ - -void -lrotate_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1, - HOST_WIDE_INT count, unsigned int prec, - unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv) -{ - unsigned HOST_WIDE_INT s1l, s2l; - HOST_WIDE_INT s1h, s2h; - - count %= prec; - if (count < 0) - count += prec; - - lshift_double (l1, h1, count, prec, &s1l, &s1h, 0); - rshift_double (l1, h1, prec - count, prec, &s2l, &s2h, 0); - *lv = s1l | s2l; - *hv = s1h | s2h; -} - -/* Rotate the doubleword integer in L1, H1 left by COUNT places - keeping only PREC bits of result. COUNT must be positive. - Store the value as two `HOST_WIDE_INT' pieces in *LV and *HV. */ - -void -rrotate_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1, - HOST_WIDE_INT count, unsigned int prec, - unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv) -{ - unsigned HOST_WIDE_INT s1l, s2l; - HOST_WIDE_INT s1h, s2h; - - count %= prec; - if (count < 0) - count += prec; - - rshift_double (l1, h1, count, prec, &s1l, &s1h, 0); - lshift_double (l1, h1, prec - count, prec, &s2l, &s2h, 0); - *lv = s1l | s2l; - *hv = s1h | s2h; -} - /* Divide doubleword integer LNUM, HNUM by doubleword integer LDEN, HDEN for a quotient (stored in *LQUO, *HQUO) and remainder (in *LREM, *HREM). CODE is a tree code for a kind of division, one of @@ -842,14 +797,6 @@ double_int_sext (double_int cst, unsigned prec) return r; } -/* Returns true if CST fits in unsigned HOST_WIDE_INT. */ - -bool -double_int_fits_in_uhwi_p (double_int cst) -{ - return cst.high == 0; -} - /* Returns true if CST fits in signed HOST_WIDE_INT. */ bool @@ -875,24 +822,6 @@ double_int_fits_in_hwi_p (double_int cst, bool uns) return double_int_fits_in_shwi_p (cst); } -/* Returns value of CST as a signed number. CST must satisfy - double_int_fits_in_shwi_p. */ - -HOST_WIDE_INT -double_int_to_shwi (double_int cst) -{ - return (HOST_WIDE_INT) cst.low; -} - -/* Returns value of CST as an unsigned number. CST must satisfy - double_int_fits_in_uhwi_p. */ - -unsigned HOST_WIDE_INT -double_int_to_uhwi (double_int cst) -{ - return cst.low; -} - /* Returns A * B. */ double_int @@ -1049,6 +978,42 @@ double_int_rshift (double_int a, HOST_WIDE_INT count, unsigned int prec, bool ar return ret; } +/* Rotate A left by COUNT places keeping only PREC bits of result. + Rotate right if COUNT is negative. */ + +double_int +double_int_lrotate (double_int a, HOST_WIDE_INT count, unsigned int prec) +{ + double_int t1, t2; + + count %= prec; + if (count < 0) + count += prec; + + t1 = double_int_lshift (a, count, prec, false); + t2 = double_int_rshift (a, prec - count, prec, false); + + return double_int_ior (t1, t2); +} + +/* Rotate A rigth by COUNT places keeping only PREC bits of result. + Rotate right if COUNT is negative. */ + +double_int +double_int_rrotate (double_int a, HOST_WIDE_INT count, unsigned int prec) +{ + double_int t1, t2; + + count %= prec; + if (count < 0) + count += prec; + + t1 = double_int_rshift (a, count, prec, false); + t2 = double_int_lshift (a, prec - count, prec, false); + + return double_int_ior (t1, t2); +} + /* Returns -1 if A < B, 0 if A == B and 1 if A > B. Signedness of the comparison is given by UNS. */ @@ -1097,6 +1062,51 @@ double_int_scmp (double_int a, double_int b) return 0; } +/* Compares two values A and B. Returns max value. Signedness of the + comparison is given by UNS. */ + +double_int +double_int_max (double_int a, double_int b, bool uns) +{ + return (double_int_cmp (a, b, uns) == 1) ? a : b; +} + +/* Compares two signed values A and B. Returns max value. */ + +double_int double_int_smax (double_int a, double_int b) +{ + return (double_int_scmp (a, b) == 1) ? a : b; +} + +/* Compares two unsigned values A and B. Returns max value. */ + +double_int double_int_umax (double_int a, double_int b) +{ + return (double_int_ucmp (a, b) == 1) ? a : b; +} + +/* Compares two values A and B. Returns mix value. Signedness of the + comparison is given by UNS. */ + +double_int double_int_min (double_int a, double_int b, bool uns) +{ + return (double_int_cmp (a, b, uns) == -1) ? a : b; +} + +/* Compares two signed values A and B. Returns min value. */ + +double_int double_int_smin (double_int a, double_int b) +{ + return (double_int_scmp (a, b) == -1) ? a : b; +} + +/* Compares two unsigned values A and B. Returns min value. */ + +double_int double_int_umin (double_int a, double_int b) +{ + return (double_int_ucmp (a, b) == -1) ? a : b; +} + /* Splits last digit of *CST (taken as unsigned) in BASE and returns it. */ static unsigned diff --git a/gcc/double-int.h b/gcc/double-int.h index c13b112d496..250951d57f9 100644 --- a/gcc/double-int.h +++ b/gcc/double-int.h @@ -97,6 +97,35 @@ uhwi_to_double_int (unsigned HOST_WIDE_INT cst) return r; } +/* Returns value of CST as a signed number. CST must satisfy + double_int_fits_in_shwi_p. */ + +static inline HOST_WIDE_INT +double_int_to_shwi (double_int cst) +{ + return (HOST_WIDE_INT) cst.low; +} + +/* Returns value of CST as an unsigned number. CST must satisfy + double_int_fits_in_uhwi_p. */ + +static inline unsigned HOST_WIDE_INT +double_int_to_uhwi (double_int cst) +{ + return cst.low; +} + +bool double_int_fits_in_hwi_p (double_int, bool); +bool double_int_fits_in_shwi_p (double_int); + +/* Returns true if CST fits in unsigned HOST_WIDE_INT. */ + +static inline bool +double_int_fits_in_uhwi_p (double_int cst) +{ + return cst.high == 0; +} + /* The following operations perform arithmetics modulo 2^precision, so you do not need to call double_int_ext between them, even if you are representing numbers with precision less than @@ -109,11 +138,6 @@ double_int double_int_neg (double_int); /* You must ensure that double_int_ext is called on the operands of the following operations, if the precision of the numbers is less than 2 * HOST_BITS_PER_WIDE_INT bits. */ -bool double_int_fits_in_hwi_p (double_int, bool); -bool double_int_fits_in_shwi_p (double_int); -bool double_int_fits_in_uhwi_p (double_int); -HOST_WIDE_INT double_int_to_shwi (double_int); -unsigned HOST_WIDE_INT double_int_to_uhwi (double_int); double_int double_int_div (double_int, double_int, bool, unsigned); double_int double_int_sdiv (double_int, double_int, unsigned); double_int double_int_udiv (double_int, double_int, unsigned); @@ -157,9 +181,22 @@ double_int_and (double_int a, double_int b) return a; } +/* Returns A ^ B. */ + +static inline double_int +double_int_xor (double_int a, double_int b) +{ + a.low ^= b.low; + a.high ^= b.high; + return a; +} + + /* Shift operations. */ double_int double_int_lshift (double_int, HOST_WIDE_INT, unsigned int, bool); double_int double_int_rshift (double_int, HOST_WIDE_INT, unsigned int, bool); +double_int double_int_lrotate (double_int, HOST_WIDE_INT, unsigned int); +double_int double_int_rrotate (double_int, HOST_WIDE_INT, unsigned int); /* Returns true if CST is negative. Of course, CST is considered to be signed. */ @@ -173,6 +210,15 @@ double_int_negative_p (double_int cst) int double_int_cmp (double_int, double_int, bool); int double_int_scmp (double_int, double_int); int double_int_ucmp (double_int, double_int); + +double_int double_int_max (double_int, double_int, bool); +double_int double_int_smax (double_int, double_int); +double_int double_int_umax (double_int, double_int); + +double_int double_int_min (double_int, double_int, bool); +double_int double_int_smin (double_int, double_int); +double_int double_int_umin (double_int, double_int); + void dump_double_int (FILE *, double_int, bool); /* Zero and sign extension of numbers in smaller precisions. */ @@ -248,12 +294,6 @@ extern void lshift_double (unsigned HOST_WIDE_INT, HOST_WIDE_INT, extern void rshift_double (unsigned HOST_WIDE_INT, HOST_WIDE_INT, HOST_WIDE_INT, unsigned int, unsigned HOST_WIDE_INT *, HOST_WIDE_INT *, bool); -extern void lrotate_double (unsigned HOST_WIDE_INT, HOST_WIDE_INT, - HOST_WIDE_INT, unsigned int, - unsigned HOST_WIDE_INT *, HOST_WIDE_INT *); -extern void rrotate_double (unsigned HOST_WIDE_INT, HOST_WIDE_INT, - HOST_WIDE_INT, unsigned int, - unsigned HOST_WIDE_INT *, HOST_WIDE_INT *); extern int div_and_round_double (unsigned, int, unsigned HOST_WIDE_INT, HOST_WIDE_INT, unsigned HOST_WIDE_INT, HOST_WIDE_INT, unsigned HOST_WIDE_INT *, diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 9abc94e8457..a1cd552014c 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)); diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index b38ab2e5991..be63198e442 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -3268,141 +3268,124 @@ simplify_const_binary_operation (enum rtx_code code, enum machine_mode mode, /* We can fold some multi-word operations. */ if (GET_MODE_CLASS (mode) == MODE_INT - && width == HOST_BITS_PER_WIDE_INT * 2 - && (GET_CODE (op0) == CONST_DOUBLE || CONST_INT_P (op0)) - && (GET_CODE (op1) == CONST_DOUBLE || CONST_INT_P (op1))) + && width == HOST_BITS_PER_DOUBLE_INT + && (CONST_DOUBLE_P (op0) || CONST_INT_P (op0)) + && (CONST_DOUBLE_P (op1) || CONST_INT_P (op1))) { - unsigned HOST_WIDE_INT l1, l2, lv, lt; - HOST_WIDE_INT h1, h2, hv, ht; + double_int o0, o1, res, tmp; - if (GET_CODE (op0) == CONST_DOUBLE) - l1 = CONST_DOUBLE_LOW (op0), h1 = CONST_DOUBLE_HIGH (op0); - else - l1 = INTVAL (op0), h1 = HWI_SIGN_EXTEND (l1); - - if (GET_CODE (op1) == CONST_DOUBLE) - l2 = CONST_DOUBLE_LOW (op1), h2 = CONST_DOUBLE_HIGH (op1); - else - l2 = INTVAL (op1), h2 = HWI_SIGN_EXTEND (l2); + o0 = rtx_to_double_int (op0); + o1 = rtx_to_double_int (op1); switch (code) { case MINUS: /* A - B == A + (-B). */ - neg_double (l2, h2, &lv, &hv); - l2 = lv, h2 = hv; + o1 = double_int_neg (o1); /* Fall through.... */ case PLUS: - add_double (l1, h1, l2, h2, &lv, &hv); + res = double_int_add (o0, o1); break; case MULT: - mul_double (l1, h1, l2, h2, &lv, &hv); + res = double_int_mul (o0, o1); break; case DIV: - if (div_and_round_double (TRUNC_DIV_EXPR, 0, l1, h1, l2, h2, - &lv, &hv, <, &ht)) + if (div_and_round_double (TRUNC_DIV_EXPR, 0, + o0.low, o0.high, o1.low, o1.high, + &res.low, &res.high, + &tmp.low, &tmp.high)) return 0; break; case MOD: - if (div_and_round_double (TRUNC_DIV_EXPR, 0, l1, h1, l2, h2, - <, &ht, &lv, &hv)) + if (div_and_round_double (TRUNC_DIV_EXPR, 0, + o0.low, o0.high, o1.low, o1.high, + &tmp.low, &tmp.high, + &res.low, &res.high)) return 0; break; case UDIV: - if (div_and_round_double (TRUNC_DIV_EXPR, 1, l1, h1, l2, h2, - &lv, &hv, <, &ht)) + if (div_and_round_double (TRUNC_DIV_EXPR, 1, + o0.low, o0.high, o1.low, o1.high, + &res.low, &res.high, + &tmp.low, &tmp.high)) return 0; break; case UMOD: - if (div_and_round_double (TRUNC_DIV_EXPR, 1, l1, h1, l2, h2, - <, &ht, &lv, &hv)) + if (div_and_round_double (TRUNC_DIV_EXPR, 1, + o0.low, o0.high, o1.low, o1.high, + &tmp.low, &tmp.high, + &res.low, &res.high)) return 0; break; case AND: - lv = l1 & l2, hv = h1 & h2; + res = double_int_and (o0, o1); break; case IOR: - lv = l1 | l2, hv = h1 | h2; + res = double_int_ior (o0, o1); break; case XOR: - lv = l1 ^ l2, hv = h1 ^ h2; + res = double_int_xor (o0, o1); break; case SMIN: - if (h1 < h2 - || (h1 == h2 - && ((unsigned HOST_WIDE_INT) l1 - < (unsigned HOST_WIDE_INT) l2))) - lv = l1, hv = h1; - else - lv = l2, hv = h2; + res = double_int_smin (o0, o1); break; case SMAX: - if (h1 > h2 - || (h1 == h2 - && ((unsigned HOST_WIDE_INT) l1 - > (unsigned HOST_WIDE_INT) l2))) - lv = l1, hv = h1; - else - lv = l2, hv = h2; + res = double_int_smax (o0, o1); break; case UMIN: - if ((unsigned HOST_WIDE_INT) h1 < (unsigned HOST_WIDE_INT) h2 - || (h1 == h2 - && ((unsigned HOST_WIDE_INT) l1 - < (unsigned HOST_WIDE_INT) l2))) - lv = l1, hv = h1; - else - lv = l2, hv = h2; + res = double_int_umin (o0, o1); break; case UMAX: - if ((unsigned HOST_WIDE_INT) h1 > (unsigned HOST_WIDE_INT) h2 - || (h1 == h2 - && ((unsigned HOST_WIDE_INT) l1 - > (unsigned HOST_WIDE_INT) l2))) - lv = l1, hv = h1; - else - lv = l2, hv = h2; + res = double_int_umax (o0, o1); break; case LSHIFTRT: case ASHIFTRT: case ASHIFT: case ROTATE: case ROTATERT: - if (SHIFT_COUNT_TRUNCATED) - l2 &= (GET_MODE_BITSIZE (mode) - 1), h2 = 0; - - if (h2 != 0 || l2 >= GET_MODE_BITSIZE (mode)) - return 0; - - if (code == LSHIFTRT || code == ASHIFTRT) - rshift_double (l1, h1, l2, GET_MODE_BITSIZE (mode), &lv, &hv, - code == ASHIFTRT); - else if (code == ASHIFT) - lshift_double (l1, h1, l2, GET_MODE_BITSIZE (mode), &lv, &hv, 1); - else if (code == ROTATE) - lrotate_double (l1, h1, l2, GET_MODE_BITSIZE (mode), &lv, &hv); - else /* code == ROTATERT */ - rrotate_double (l1, h1, l2, GET_MODE_BITSIZE (mode), &lv, &hv); + { + unsigned HOST_WIDE_INT cnt; + + if (SHIFT_COUNT_TRUNCATED) + o1 = double_int_zext (o1, GET_MODE_BITSIZE (mode)); + + if (!double_int_fits_in_uhwi_p (o1) + || double_int_to_uhwi (o1) >= GET_MODE_BITSIZE (mode)) + return 0; + + cnt = double_int_to_uhwi (o1); + + if (code == LSHIFTRT || code == ASHIFTRT) + res = double_int_rshift (o0, cnt, GET_MODE_BITSIZE (mode), + code == ASHIFTRT); + else if (code == ASHIFT) + res = double_int_lshift (o0, cnt, GET_MODE_BITSIZE (mode), + true); + else if (code == ROTATE) + res = double_int_lrotate (o0, cnt, GET_MODE_BITSIZE (mode)); + else /* code == ROTATERT */ + res = double_int_rrotate (o0, cnt, GET_MODE_BITSIZE (mode)); + } break; default: return 0; } - return immed_double_const (lv, hv, mode); + return immed_double_int_const (res, mode); } if (CONST_INT_P (op0) && CONST_INT_P (op1) |