The following avoids speculating a load/store pair for modes
that cannot transfer bits or, as for the testcase, bitfield
loads that are either value changing or invoke UB when out-of-bound
(and that we'd rewrite to be defined with explicit truncation).

Bootstrapped and tested on x86_64-unknown-linux-gnu, will push later
today.

Richard.

        PR tree-optimization/125250
        * tree-ssa-loop-im.cc (execute_sm): For modes that cannot
        transfer bits, _Bool and bitfield accesses force the
        multi-threaded model.

        * gcc.dg/torture/pr125250.c: New testcase.
---
 gcc/testsuite/gcc.dg/torture/pr125250.c | 32 +++++++++++++++++++++++++
 gcc/tree-ssa-loop-im.cc                 |  9 ++++++-
 2 files changed, 40 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr125250.c

diff --git a/gcc/testsuite/gcc.dg/torture/pr125250.c 
b/gcc/testsuite/gcc.dg/torture/pr125250.c
new file mode 100644
index 00000000000..25d69c0e305
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr125250.c
@@ -0,0 +1,32 @@
+/* { dg-do run } */
+
+short g0, __chk, g9, g6;
+_Bool g1;
+void *g4;
+
+void __attribute__((noipa)) f5(_Bool a2, int a5)
+{
+  void *a1 = &a2;
+lbl_br11:
+  *(_Bool *)a1 = 0;
+  a1 = &a5;
+  if (!a2)
+    {
+      g1 = *(_Bool *)g4;
+      if (g1)
+        {
+          g9 = -g9;
+          goto lbl_br11;
+        }
+    }
+  g6 = a5;
+}
+
+int main()
+{
+  g4 = &g0;
+  f5(0, 8);
+  __chk = g6;
+  if (__chk != 8)
+    __builtin_abort ();
+}
diff --git a/gcc/tree-ssa-loop-im.cc b/gcc/tree-ssa-loop-im.cc
index 72e19981698..4f7401e2d5d 100644
--- a/gcc/tree-ssa-loop-im.cc
+++ b/gcc/tree-ssa-loop-im.cc
@@ -2323,7 +2323,14 @@ execute_sm (class loop *loop, im_mem_ref *ref,
   bool always_stored = ref_always_accessed_p (loop, ref, true);
   if (maybe_mt
       && (bb_in_transaction (loop_preheader_edge (loop)->src)
-         || (ref_can_have_store_data_races (ref->mem.ref) && ! always_stored)))
+         || (ref_can_have_store_data_races (ref->mem.ref) && ! always_stored)
+         /* Do not speculate a load/store when that's not a noop, either
+            because the mode cannot be transferred or because there's
+            UB involved for out-of-bound values.  */
+         || !mode_can_transfer_bits (TYPE_MODE (TREE_TYPE (ref->mem.ref)))
+         || TREE_CODE (TREE_TYPE (ref->mem.ref)) == BOOLEAN_TYPE
+         || (TREE_CODE (ref->mem.ref) == COMPONENT_REF
+             && DECL_BIT_FIELD (TREE_OPERAND (ref->mem.ref, 1)))))
     multi_threaded_model_p = true;
 
   if (multi_threaded_model_p && !use_other_flag_var)
-- 
2.51.0

Reply via email to