re PR c/61136 (ice in tree_nop_conversion)
authorRichard Sandiford <rdsandiford@googlemail.com>
Sun, 11 May 2014 20:21:55 +0000 (20:21 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Sun, 11 May 2014 20:21:55 +0000 (20:21 +0000)
gcc/
PR tree-optimization/61136
* wide-int.h (multiple_of_p): Define a version that doesn't return
the quotient.
* fold-const.c (extract_muldiv_1): Use wi::multiple_of_p instead of an
integer_zerop/const_binop pair.
(multiple_of_p): Likewise, converting both operands to widest_int
precision.

gcc/testsuite/
* gcc.dg/torture/pr61136.c: New test.

From-SVN: r210312

gcc/ChangeLog
gcc/fold-const.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/torture/pr61136.c [new file with mode: 0644]
gcc/wide-int.h

index 67bfdbf..083aca3 100644 (file)
@@ -1,3 +1,13 @@
+2014-05-11  Richard Sandiford  <rdsandiford@googlemail.com>
+
+       PR tree-optimization/61136
+       * wide-int.h (multiple_of_p): Define a version that doesn't return
+       the quotient.
+       * fold-const.c (extract_muldiv_1): Use wi::multiple_of_p instead of an
+       integer_zerop/const_binop pair.
+       (multiple_of_p): Likewise, converting both operands to widest_int
+       precision.
+
 2014-05-09  Teresa Johnson  <tejohnson@google.com>
 
        * cgraphunit.c (analyze_functions): Use correct dump file.
index c5bf811..0fcb87f 100644 (file)
@@ -5708,7 +5708,7 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type,
       /* For a constant, we can always simplify if we are a multiply
         or (for divide and modulus) if it is a multiple of our constant.  */
       if (code == MULT_EXPR
-         || integer_zerop (const_binop (TRUNC_MOD_EXPR, t, c)))
+         || wi::multiple_of_p (t, c, TYPE_SIGN (type)))
        return const_binop (code, fold_convert (ctype, t),
                            fold_convert (ctype, c));
       break;
@@ -5888,7 +5888,7 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type,
       /* If it's a multiply or a division/modulus operation of a multiple
          of our constant, do the operation and verify it doesn't overflow.  */
       if (code == MULT_EXPR
-         || integer_zerop (const_binop (TRUNC_MOD_EXPR, op1, c)))
+         || wi::multiple_of_p (op1, c, TYPE_SIGN (type)))
        {
          op1 = const_binop (code, fold_convert (ctype, op1),
                             fold_convert (ctype, c));
@@ -5932,7 +5932,7 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type,
          /* If the multiplication can overflow we cannot optimize this.  */
          && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (t))
          && TREE_CODE (TREE_OPERAND (t, 1)) == INTEGER_CST
-         && integer_zerop (const_binop (TRUNC_MOD_EXPR, op1, c)))
+         && wi::multiple_of_p (op1, c, TYPE_SIGN (type)))
        {
          *strict_overflow_p = true;
          return omit_one_operand (type, integer_zero_node, op0);
@@ -5989,7 +5989,7 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type,
                  && code != FLOOR_MOD_EXPR && code != ROUND_MOD_EXPR
                  && code != MULT_EXPR)))
        {
-         if (integer_zerop (const_binop (TRUNC_MOD_EXPR, op1, c)))
+         if (wi::multiple_of_p (op1, c, TYPE_SIGN (type)))
            {
              if (TYPE_OVERFLOW_UNDEFINED (ctype))
                *strict_overflow_p = true;
@@ -5998,7 +5998,7 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type,
                                                const_binop (TRUNC_DIV_EXPR,
                                                             op1, c)));
            }
-         else if (integer_zerop (const_binop (TRUNC_MOD_EXPR, c, op1)))
+         else if (wi::multiple_of_p (c, op1, TYPE_SIGN (type)))
            {
              if (TYPE_OVERFLOW_UNDEFINED (ctype))
                *strict_overflow_p = true;
@@ -15314,8 +15314,8 @@ multiple_of_p (tree type, const_tree top, const_tree bottom)
              && (tree_int_cst_sgn (top) < 0
                  || tree_int_cst_sgn (bottom) < 0)))
        return 0;
-      return integer_zerop (int_const_binop (TRUNC_MOD_EXPR,
-                                            top, bottom));
+      return wi::multiple_of_p (wi::to_widest (top), wi::to_widest (bottom),
+                               SIGNED);
 
     default:
       return 0;
index bcf4038..7459796 100644 (file)
@@ -1,3 +1,7 @@
+2014-05-11  Richard Sandiford  <rdsandiford@googlemail.com>
+
+       * gcc.dg/torture/pr61136.c: New test.
+
 2014-05-11  Paolo Carlini  <paolo.carlini@oracle.com>
 
        PR c++/59705
diff --git a/gcc/testsuite/gcc.dg/torture/pr61136.c b/gcc/testsuite/gcc.dg/torture/pr61136.c
new file mode 100644 (file)
index 0000000..4fc908a
--- /dev/null
@@ -0,0 +1,5 @@
+unsigned long long
+foo (int a)
+{
+  return a * 7 & 1ULL << 63;
+}
index 46a1c22..d5ab428 100644 (file)
@@ -530,6 +530,9 @@ namespace wi
   BINARY_FUNCTION mod_round (const T1 &, const T2 &, signop, bool * = 0);
 
   template <typename T1, typename T2>
+  bool multiple_of_p (const T1 &, const T2 &, signop);
+
+  template <typename T1, typename T2>
   bool multiple_of_p (const T1 &, const T2 &, signop,
                      WI_BINARY_RESULT (T1, T2) *);
 
@@ -2791,6 +2794,15 @@ wi::mod_round (const T1 &x, const T2 &y, signop sgn, bool *overflow)
   return remainder;
 }
 
+/* Return true if X is a multiple of Y.  Treat X and Y as having the
+   signedness given by SGN.  */
+template <typename T1, typename T2>
+inline bool
+wi::multiple_of_p (const T1 &x, const T2 &y, signop sgn)
+{
+  return wi::mod_trunc (x, y, sgn) == 0;
+}
+
 /* Return true if X is a multiple of Y, storing X / Y in *RES if so.
    Treat X and Y as having the signedness given by SGN.  */
 template <typename T1, typename T2>