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