]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
tree-optimization/121382 - avoid UB in IVOPTs inserted step computation
authorRichard Biener <rguenther@suse.de>
Tue, 5 Aug 2025 08:38:03 +0000 (10:38 +0200)
committerRichard Biener <rguenth@gcc.gnu.org>
Tue, 5 Aug 2025 11:03:50 +0000 (13:03 +0200)
IVOPTs, when replacing an IV, inserts the computation of the new IVs
step in the loop preheader without considering the case of the loop
not iterating.  This means we have to ensure the step computation
does not invoke UB.  There is also SCEV which does not care about
signed arithmetic UB when re-associating expressions to form CHRECs,
so even when we know the loop iterates this is required.

PR tree-optimization/121382
* tree-ssa-loop-ivopts.cc (create_new_iv): Rewrite the IV
step to defined form.

* gcc.dg/torture/pr121382.c: New testcase.

gcc/testsuite/gcc.dg/torture/pr121382.c [new file with mode: 0644]
gcc/tree-ssa-loop-ivopts.cc

diff --git a/gcc/testsuite/gcc.dg/torture/pr121382.c b/gcc/testsuite/gcc.dg/torture/pr121382.c
new file mode 100644 (file)
index 0000000..20b49b1
--- /dev/null
@@ -0,0 +1,23 @@
+/* { dg-do run } */
+/* { dg-require-effective-target int32plus } */
+
+int a, b, c;
+__attribute__((noipa))
+static void d(int e, int f)
+{
+  if (e != 5 && e != 2147483647)
+    __builtin_abort();
+  f = 2147483647;
+  do {
+    f = f - e;
+    if (c - 9 * f) {
+      __builtin_abort();
+    }
+  } while (c);
+}
+__attribute__((noipa))
+int main(void)
+{
+  d(2147483647, 2147483647);
+  return 0;
+}
index 879668c518ae04830f4d4893680ce4f355ea1eea..2fe2655220b7de0cd76b6c6b85c503ce002be098 100644 (file)
@@ -132,6 +132,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-vectorizer.h"
 #include "dbgcnt.h"
 #include "cfganal.h"
+#include "gimple-fold.h"
 
 /* For lang_hooks.types.type_for_mode.  */
 #include "langhooks.h"
@@ -7252,7 +7253,24 @@ create_new_iv (struct ivopts_data *data, struct iv_cand *cand)
 
   base = unshare_expr (cand->iv->base);
 
-  create_iv (base, PLUS_EXPR, unshare_expr (cand->iv->step),
+  /* The step computation could invoke UB when the loop does not iterate.
+     Avoid inserting it on the preheader in its native form but rewrite
+     it to a well-defined form.  This also helps masking SCEV issues
+     which freely re-associates the IV computations when building up
+     CHRECs without much regard for signed overflow invoking UB.  */
+  gimple_seq stmts = NULL;
+  tree step = force_gimple_operand (unshare_expr (cand->iv->step), &stmts,
+                                   true, NULL_TREE);
+  if (stmts)
+    {
+      for (auto gsi = gsi_start (stmts); !gsi_end_p (gsi); gsi_next (&gsi))
+       if (gimple_needing_rewrite_undefined (gsi_stmt (gsi)))
+         rewrite_to_defined_unconditional (&gsi);
+      gsi_insert_seq_on_edge_immediate
+       (loop_preheader_edge (data->current_loop), stmts);
+    }
+
+  create_iv (base, PLUS_EXPR, step,
             cand->var_before, data->current_loop,
             &incr_pos, after, &cand->var_before, &cand->var_after);
 }