]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
slsr: Fix replace_rhs_if_not_dup and others for overflow [PR106883]
authorAndrew Pinski <andrew.pinski@oss.qualcomm.com>
Sat, 17 Jan 2026 04:50:53 +0000 (20:50 -0800)
committerAndrew Pinski <andrew.pinski@oss.qualcomm.com>
Fri, 23 Jan 2026 16:03:24 +0000 (08:03 -0800)
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 <andrew.pinski@oss.qualcomm.com>
gcc/gimple-ssa-strength-reduction.cc
gcc/testsuite/gcc.dg/torture/pr120258-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/slsr-8.c

index 990943c767cd54c97d2e0d62be2ebb06f6144fca..d493dc87d3a5ea8eb9c859fc3dcd8d7e784edb76 100644 (file)
@@ -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 (file)
index 0000000..4198deb
--- /dev/null
@@ -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();
+}
index 479f40f93de7112b963a7d9eda89658dfbe4434a..b6d76b39646e1d53be8e956faf3d1efcd1a5e8bd 100644 (file)
@@ -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" } } */