On Mon, May 11, 2026 at 2:45 AM Richard Biener <[email protected]> wrote:
>
> 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;

I was looking into doing this exact change, well only for boolean
types. So thanks for doing this and expanding it to the other problem
cases.

Thanks,
Andrea

>
>    if (multi_threaded_model_p && !use_other_flag_var)
> --
> 2.51.0

Reply via email to