Hi,

PR60930 exposes an SLSR problem with a fold.  When multiplying two
constants to create a new stride, the result must fit in the stride type
for the computation or the fold is invalid.

Bootstrapped and tested on powerpc64le-unknown-linux-gnu with no
regressions.  The same patch applies equally to 4.8, 4.9, and trunk.  Is
this ok for trunk (and for 4.8/4.9 after a suitable burn-in period)?

Thanks,
Bill


[gcc]

2014-04-24  Bill Schmidt  <wschm...@linux.vnet.ibm.com>

        PR tree-optimization/60930
        * gimple-ssa-strength-reduction.c (create_mul_imm_cand):  Reject
        creating a multiply candidate by folding two constant
        multiplicands when the result overflows.

[gcc/testsuite]

2014-04-24  Bill Schmidt  <wschm...@linux.vnet.ibm.com>

        PR tree-optimization/60930
        * gcc.dg/torture/pr60930.c:  New test.


Index: gcc/gimple-ssa-strength-reduction.c
===================================================================
--- gcc/gimple-ssa-strength-reduction.c (revision 209714)
+++ gcc/gimple-ssa-strength-reduction.c (working copy)
@@ -1114,15 +1114,18 @@ create_mul_imm_cand (gimple gs, tree base_in, tree
             X = Y * c
             ============================
             X = (B + i') * (S * c)  */
-         base = base_cand->base_expr;
-         index = base_cand->index;
          temp = tree_to_double_int (base_cand->stride)
                 * tree_to_double_int (stride_in);
-         stride = double_int_to_tree (TREE_TYPE (stride_in), temp);
-         ctype = base_cand->cand_type;
-         if (has_single_use (base_in))
-           savings = (base_cand->dead_savings 
-                      + stmt_cost (base_cand->cand_stmt, speed));
+         if (double_int_fits_to_tree_p (TREE_TYPE (stride_in), temp))
+           {
+             base = base_cand->base_expr;
+             index = base_cand->index;
+             stride = double_int_to_tree (TREE_TYPE (stride_in), temp);
+             ctype = base_cand->cand_type;
+             if (has_single_use (base_in))
+               savings = (base_cand->dead_savings 
+                          + stmt_cost (base_cand->cand_stmt, speed));
+           }
        }
       else if (base_cand->kind == CAND_ADD && integer_onep (base_cand->stride))
        {
Index: gcc/testsuite/gcc.dg/torture/pr60930.c
===================================================================
--- gcc/testsuite/gcc.dg/torture/pr60930.c      (revision 0)
+++ gcc/testsuite/gcc.dg/torture/pr60930.c      (working copy)
@@ -0,0 +1,20 @@
+/* { dg-do run } */
+
+int x = 1;
+
+__attribute__((noinline, noclone)) void
+foo (unsigned long long t)
+{
+  asm volatile ("" : : "r" (&t));
+  if (t == 1)
+    __builtin_abort ();
+}
+
+int
+main ()
+{
+  unsigned long long t = 0xffffffffffffffffULL * (0xffffffffUL * x);
+  if (t != 0xffffffff00000001ULL)
+    foo (t);;
+  return 0;
+}


Reply via email to