https://gcc.gnu.org/g:e88f8d7bfc811f6d152c42ba009255506f5beba1
commit r17-442-ge88f8d7bfc811f6d152c42ba009255506f5beba1 Author: Richard Biener <[email protected]> Date: Mon May 11 10:25:57 2026 +0200 tree-optimization/125250 - LIM speculating not noop load/store 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). 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. Diff: --- gcc/testsuite/gcc.dg/torture/pr125250.c | 32 ++++++++++++++++++++++++++++++++ gcc/tree-ssa-loop-im.cc | 9 ++++++++- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/gcc/testsuite/gcc.dg/torture/pr125250.c b/gcc/testsuite/gcc.dg/torture/pr125250.c new file mode 100644 index 000000000000..25d69c0e3050 --- /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 72e199816984..4f7401e2d5d3 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)
