Like the previous patch this up slsr in the other locations for the
added overflow issues that were being introduced. This was slightly
harder than insert_initializers as we need to allow for type
mismatches in more cases.
But with this all fixed, the testcases in PR 120258 (and its duplicates)
are all working correctly.

Bootstrapped and tested on x86-linux-gnu.

        PR tree-optimization/120258
        PR tree-optimization/106883

gcc/ChangeLog:

        * gimple-ssa-strength-reduction.cc (replace_mult_candidate): Allow for
        basis_name and bump_tree not to be the same type as the lhs.
        Rewrite added multiply for undefined overflow.
        (create_add_on_incoming_edge): Allow for init
        to be a different type from the wanted type.
        Rewrite added add for undefined overflow.
        (replace_rhs_if_not_dup): Rewrite replaced stmts
        for undefined overflow.
        (replace_one_candidate): Allow for basis_name and
        rhs2 to be a different type from lhs.

gcc/testsuite/ChangeLog:

        * gcc.dg/tree-ssa/slsr-8.c: Update the number of `*`.
        * gcc.dg/torture/pr120258-1.c: New test.

Signed-off-by: Andrew Pinski <[email protected]>
---
 gcc/gimple-ssa-strength-reduction.cc      | 40 +++++++++++++++++++++--
 gcc/testsuite/gcc.dg/torture/pr120258-1.c | 12 +++++++
 gcc/testsuite/gcc.dg/tree-ssa/slsr-8.c    |  6 ++--
 3 files changed, 53 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr120258-1.c

diff --git a/gcc/gimple-ssa-strength-reduction.cc 
b/gcc/gimple-ssa-strength-reduction.cc
index 990943c767c..d493dc87d3a 100644
--- a/gcc/gimple-ssa-strength-reduction.cc
+++ b/gcc/gimple-ssa-strength-reduction.cc
@@ -2220,6 +2220,13 @@ replace_mult_candidate (slsr_cand_t c, tree basis_name, 
offset_int bump,
        {
          gimple_stmt_iterator gsi = gsi_for_stmt (c->cand_stmt);
          slsr_cand_t cc = lookup_cand (c->first_interp);
+         tree lhs = gimple_assign_lhs (c->cand_stmt);
+         basis_name = gimple_convert (&gsi, true, GSI_SAME_STMT,
+                                      UNKNOWN_LOCATION,
+                                      TREE_TYPE (lhs), basis_name);
+         bump_tree = gimple_convert (&gsi, true, GSI_SAME_STMT,
+                                     UNKNOWN_LOCATION,
+                                     TREE_TYPE (lhs), bump_tree);
          gimple_assign_set_rhs_with_ops (&gsi, code, basis_name, bump_tree);
          update_stmt (gsi_stmt (gsi));
          while (cc)
@@ -2227,6 +2234,9 @@ replace_mult_candidate (slsr_cand_t c, tree basis_name, 
offset_int bump,
              cc->cand_stmt = gsi_stmt (gsi);
              cc = lookup_cand (cc->next_interp);
            }
+         if (gimple_needing_rewrite_undefined (gsi_stmt (gsi)))
+           rewrite_to_defined_unconditional (&gsi);
+
          if (dump_file && (dump_flags & TDF_DETAILS))
            stmt_to_print = gsi_stmt (gsi);
        }
@@ -2330,9 +2340,19 @@ create_add_on_incoming_edge (slsr_cand_t c, tree 
basis_name,
 
       if (incr_vec[i].initializer)
        {
+         tree init = incr_vec[i].initializer;
+         tree wanted_type = POINTER_TYPE_P (basis_type) ? c->stride_type : 
basis_type;
+
+         if (!types_compatible_p (TREE_TYPE (c->stride), wanted_type))
+           {
+             tree cast_stride = make_temp_ssa_name (wanted_type, NULL,
+                                                    "slsr");
+             cast_stmt = gimple_build_assign (cast_stride, NOP_EXPR,
+                                              init);
+             init = cast_stride;
+           }
          enum tree_code code = negate_incr ? MINUS_EXPR : plus_code;
-         new_stmt = gimple_build_assign (lhs, code, basis_name,
-                                         incr_vec[i].initializer);
+         new_stmt = gimple_build_assign (lhs, code, basis_name, init);
        }
       else {
        tree stride;
@@ -3689,7 +3709,14 @@ replace_rhs_if_not_dup (enum tree_code new_code, tree 
new_rhs1, tree new_rhs2,
          && (!operand_equal_p (new_rhs1, old_rhs2, 0)
              || !operand_equal_p (new_rhs2, old_rhs1, 0))))
     {
+      tree lhs = gimple_assign_lhs (c->cand_stmt);
       gimple_stmt_iterator gsi = gsi_for_stmt (c->cand_stmt);
+      new_rhs1 = gimple_convert (&gsi, true, GSI_SAME_STMT,
+                                UNKNOWN_LOCATION,
+                                TREE_TYPE (lhs), new_rhs1);
+      new_rhs2 = gimple_convert (&gsi, true, GSI_SAME_STMT,
+                                UNKNOWN_LOCATION,
+                                TREE_TYPE (lhs), new_rhs2);
       slsr_cand_t cc = lookup_cand (c->first_interp);
       gimple_assign_set_rhs_with_ops (&gsi, new_code, new_rhs1, new_rhs2);
       update_stmt (gsi_stmt (gsi));
@@ -3699,6 +3726,8 @@ replace_rhs_if_not_dup (enum tree_code new_code, tree 
new_rhs1, tree new_rhs2,
          cc = lookup_cand (cc->next_interp);
        }
 
+      if (gimple_needing_rewrite_undefined (gsi_stmt (gsi)))
+       rewrite_to_defined_unconditional (&gsi);
       if (dump_file && (dump_flags & TDF_DETAILS))
        return gsi_stmt (gsi);
     }
@@ -3813,7 +3842,14 @@ replace_one_candidate (slsr_cand_t c, unsigned i, tree 
basis_name,
          || !operand_equal_p (rhs2, orig_rhs2, 0))
        {
          gimple_stmt_iterator gsi = gsi_for_stmt (c->cand_stmt);
+         tree lhs = gimple_assign_lhs (c->cand_stmt);
          slsr_cand_t cc = lookup_cand (c->first_interp);
+         basis_name = gimple_convert (&gsi, true, GSI_SAME_STMT,
+                                      UNKNOWN_LOCATION,
+                                      TREE_TYPE (lhs), basis_name);
+         rhs2 = gimple_convert (&gsi, true, GSI_SAME_STMT,
+                                UNKNOWN_LOCATION,
+                                TREE_TYPE (lhs), rhs2);
          gimple_assign_set_rhs_with_ops (&gsi, MINUS_EXPR, basis_name, rhs2);
          update_stmt (gsi_stmt (gsi));
          while (cc)
diff --git a/gcc/testsuite/gcc.dg/torture/pr120258-1.c 
b/gcc/testsuite/gcc.dg/torture/pr120258-1.c
new file mode 100644
index 00000000000..4198deb955d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr120258-1.c
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+/* PR tree-optimization/120258 */
+/* SLSR would introduce an addition and multiplication
+   that would have undefined behavior with respect to overflow
+   and that would cause the following to be incorrect. */
+
+int a = 1, b, c;
+int main() {
+  c = -__INT_MAX__* b - __INT_MAX__* a;
+  if (b - __INT_MAX__ * a >= 0)
+    __builtin_abort();
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/slsr-8.c 
b/gcc/testsuite/gcc.dg/tree-ssa/slsr-8.c
index 479f40f93de..b6d76b39646 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/slsr-8.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/slsr-8.c
@@ -23,7 +23,7 @@ f (int s, int *c, int *d)
    However, this proves to be a useful test for introducing an
    initializer with a cast, so we'll keep it as is.  */
 
-/* There are 5 ' * ' instances in the decls (since "int * iftmp.0;" is
-   added), 2 parms, 3 in the code, and the return value.  The second one
+/* There are 2 ' * ' instances in the decls (holding x1 and a temp),
+   2 parms, 3 in the code, and the return type.  The second one
    in the code may be a widening multiply (for example, on AArch64).  */
-/* { dg-final { scan-tree-dump-times " w?\\* " 10 "optimized" } } */
+/* { dg-final { scan-tree-dump-times " w?\\* " 8 "optimized" } } */
-- 
2.43.0

Reply via email to