From: Eric Botcazou Date: Thu, 19 Oct 2006 20:25:18 +0000 (+0000) Subject: fold-const.c (add_double): Rename to add_double_with_sign. X-Git-Tag: releases/gcc-4.0.4~270 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bcb1d3ce7a50768edb280244ff80d840f994907b;p=thirdparty%2Fgcc.git fold-const.c (add_double): Rename to add_double_with_sign. * fold-const.c (add_double): Rename to add_double_with_sign. Add 'unsigned_p' parameter and take it into account for the overflow. (mul_double): Rename to mul_double_with_sign. Add 'unsigned_p' parameter and take it into account for the overflow. (fold_div_compare): Call add_double_with_sign instead of add_double and mul_double_with_sign instead of mul_double, passing them the unsignedness of the type. * tree.h (add_double): Macroize. (add_double_with_sign): New prototype. (mul_double): Macroize. (mul_double_with_sign): New prototype. From-SVN: r117889 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0f66fe1dd420..93afce20f70d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +2006-10-19 Eric Botcazou + + * fold-const.c (add_double): Rename to add_double_with_sign. + Add 'unsigned_p' parameter and take it into account for the overflow. + (mul_double): Rename to mul_double_with_sign. + Add 'unsigned_p' parameter and take it into account for the overflow. + (fold_div_compare): Call add_double_with_sign instead of add_double + and mul_double_with_sign instead of mul_double, passing them the + unsignedness of the type. + * tree.h (add_double): Macroize. + (add_double_with_sign): New prototype. + (mul_double): Macroize. + (mul_double_with_sign): New prototype. + 2006-10-16 Richard Guenther PR target/25519 diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 180fb35c6624..b254a9d79fc5 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -285,14 +285,16 @@ force_fit_type (tree t, int overflowable, } /* Add two doubleword integers with doubleword result. + Return nonzero if the operation overflows according to UNSIGNED_P. Each argument is given as two `HOST_WIDE_INT' pieces. One argument is L1 and H1; the other, L2 and H2. The value is stored as two `HOST_WIDE_INT' pieces in *LV and *HV. */ int -add_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1, - unsigned HOST_WIDE_INT l2, HOST_WIDE_INT h2, - unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv) +add_double_with_sign (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1, + unsigned HOST_WIDE_INT l2, HOST_WIDE_INT h2, + unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv, + bool unsigned_p) { unsigned HOST_WIDE_INT l; HOST_WIDE_INT h; @@ -302,7 +304,11 @@ add_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1, *lv = l; *hv = h; - return OVERFLOW_SUM_SIGN (h1, h2, h); + + if (unsigned_p) + return (unsigned HOST_WIDE_INT) h < (unsigned HOST_WIDE_INT) h1; + else + return OVERFLOW_SUM_SIGN (h1, h2, h); } /* Negate a doubleword integer with doubleword result. @@ -329,15 +335,16 @@ neg_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1, } /* Multiply two doubleword integers with doubleword result. - Return nonzero if the operation overflows, assuming it's signed. + Return nonzero if the operation overflows according to UNSIGNED_P. Each argument is given as two `HOST_WIDE_INT' pieces. One argument is L1 and H1; the other, L2 and H2. The value is stored as two `HOST_WIDE_INT' pieces in *LV and *HV. */ int -mul_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1, - unsigned HOST_WIDE_INT l2, HOST_WIDE_INT h2, - unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv) +mul_double_with_sign (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1, + unsigned HOST_WIDE_INT l2, HOST_WIDE_INT h2, + unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv, + bool unsigned_p) { HOST_WIDE_INT arg1[4]; HOST_WIDE_INT arg2[4]; @@ -368,11 +375,15 @@ mul_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1, prod[i + 4] = carry; } - decode (prod, lv, hv); /* This ignores prod[4] through prod[4*2-1] */ - - /* Check for overflow by calculating the top half of the answer in full; - it should agree with the low half's sign bit. */ + decode (prod, lv, hv); decode (prod + 4, &toplow, &tophigh); + + /* Unsigned overflow is immediate. */ + if (unsigned_p) + return (toplow | tophigh) != 0; + + /* Check for signed overflow by calculating the signed representation of the + top half of the result; it should agree with the low half's sign bit. */ if (h1 < 0) { neg_double (l2, h2, &neglow, &neghigh); @@ -5802,28 +5813,30 @@ fold_div_compare (enum tree_code code, tree type, tree arg0, tree arg1) tree arg01 = TREE_OPERAND (arg0, 1); unsigned HOST_WIDE_INT lpart; HOST_WIDE_INT hpart; + bool unsigned_p = TYPE_UNSIGNED (TREE_TYPE (arg0)); int overflow; /* We have to do this the hard way to detect unsigned overflow. prod = int_const_binop (MULT_EXPR, arg01, arg1, 0); */ - overflow = mul_double (TREE_INT_CST_LOW (arg01), - TREE_INT_CST_HIGH (arg01), - TREE_INT_CST_LOW (arg1), - TREE_INT_CST_HIGH (arg1), &lpart, &hpart); + overflow = mul_double_with_sign (TREE_INT_CST_LOW (arg01), + TREE_INT_CST_HIGH (arg01), + TREE_INT_CST_LOW (arg1), + TREE_INT_CST_HIGH (arg1), + &lpart, &hpart, unsigned_p); prod = build_int_cst_wide (TREE_TYPE (arg00), lpart, hpart); prod = force_fit_type (prod, -1, overflow, false); - if (TYPE_UNSIGNED (TREE_TYPE (arg0))) + if (unsigned_p) { tmp = int_const_binop (MINUS_EXPR, arg01, integer_one_node, 0); lo = prod; /* Likewise hi = int_const_binop (PLUS_EXPR, prod, tmp, 0). */ - overflow = add_double (TREE_INT_CST_LOW (prod), - TREE_INT_CST_HIGH (prod), - TREE_INT_CST_LOW (tmp), - TREE_INT_CST_HIGH (tmp), - &lpart, &hpart); + overflow = add_double_with_sign (TREE_INT_CST_LOW (prod), + TREE_INT_CST_HIGH (prod), + TREE_INT_CST_LOW (tmp), + TREE_INT_CST_HIGH (tmp), + &lpart, &hpart, unsigned_p); hi = build_int_cst_wide (TREE_TYPE (arg00), lpart, hpart); hi = force_fit_type (hi, -1, overflow | TREE_OVERFLOW (prod), TREE_CONSTANT_OVERFLOW (prod)); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 6f8a5e515748..4ee9b5c732c3 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2006-10-19 Eric Botcazou + + * gcc.dg/div-compare-1.c: New test. + 2006-10-16 Kaveh R. Ghazi Backport: diff --git a/gcc/testsuite/gcc.dg/div-compare-1.c b/gcc/testsuite/gcc.dg/div-compare-1.c new file mode 100644 index 000000000000..61adafe140d1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/div-compare-1.c @@ -0,0 +1,21 @@ +/* { dg-do run } */ +/* { dg-options "-std=c99" } */ + +extern void abort(void); + +typedef unsigned long long uint64; + +int very_large_value (uint64 t) +{ + return (t / 1000000000ULL) > 9223372037ULL; +} + +int main(void) +{ + uint64 t = 0xC000000000000000ULL; + + if (!very_large_value (t)) + abort (); + + return 0; +} diff --git a/gcc/tree.h b/gcc/tree.h index 3ebad4451877..b3cb02dae62d 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -3499,14 +3499,20 @@ extern tree fold_abs_const (tree, tree); extern tree force_fit_type (tree, int, bool, bool); -extern int add_double (unsigned HOST_WIDE_INT, HOST_WIDE_INT, - unsigned HOST_WIDE_INT, HOST_WIDE_INT, - unsigned HOST_WIDE_INT *, HOST_WIDE_INT *); +extern int add_double_with_sign (unsigned HOST_WIDE_INT, HOST_WIDE_INT, + unsigned HOST_WIDE_INT, HOST_WIDE_INT, + unsigned HOST_WIDE_INT *, HOST_WIDE_INT *, + bool); +#define add_double(l1,h1,l2,h2,lv,hv) \ + add_double_with_sign (l1, h1, l2, h2, lv, hv, false) extern int neg_double (unsigned HOST_WIDE_INT, HOST_WIDE_INT, unsigned HOST_WIDE_INT *, HOST_WIDE_INT *); -extern int mul_double (unsigned HOST_WIDE_INT, HOST_WIDE_INT, - unsigned HOST_WIDE_INT, HOST_WIDE_INT, - unsigned HOST_WIDE_INT *, HOST_WIDE_INT *); +extern int mul_double_with_sign (unsigned HOST_WIDE_INT, HOST_WIDE_INT, + unsigned HOST_WIDE_INT, HOST_WIDE_INT, + unsigned HOST_WIDE_INT *, HOST_WIDE_INT *, + bool); +#define mul_double(l1,h1,l2,h2,lv,hv) \ + mul_double_with_sign (l1, h1, l2, h2, lv, hv, false) extern void lshift_double (unsigned HOST_WIDE_INT, HOST_WIDE_INT, HOST_WIDE_INT, unsigned int, unsigned HOST_WIDE_INT *, HOST_WIDE_INT *, int);