On Fri, Jan 30, 2026 at 7:18 AM Richard Biener <[email protected]> wrote:
>
> The following properly checks expr_no_side_effects_p on two patterns
> that turns a conditionally evaluated operand into unconditonal.
>
> Bootstrapped on x86_64-unknown-linux-gnu, testing in progress.
>
> PR middle-end/123887
> * match.pd ((zero_one ==/!= 0) ? .. z <op> y .. -> zero_one * z ..):
> Check evaluating z unconditionally has no side-effects, like
> trapping.
Looks like I had missed adding expr_no_side_effects_p to those
patterns when I did r15-3870-g6c5543d3d9c4bb.
The other patterns which have the same issue which is missed:
```
/* (a ? x : y) != (b ? x : y) --> (a^b & (x != y)) ? TRUE : FALSE */
/* (a ? x : y) == (b ? x : y) --> (a^b & (x != y)) ? FALSE : TRUE */
/* (a ? x : y) != (b ? y : x) --> (a^b | (x == y)) ? FALSE : TRUE */
/* (a ? x : y) == (b ? y : x) --> (a^b | (x == y)) ? TRUE : FALSE */
/* These are only valid if x and y don't have NaNs. */
```
With this testcase:
```
[[gnu::noipa]]
int f(int a, int b, int *x)
{
return (a ? *x : 0) != (b ? *x : 0);
}
int main()
{
f(0, 0, 0);
return 0;
}
```
I audited the other patterns (that you did not change) and only could
find the above one.
Thanks,
Andrew
>
> * gcc.dg/torture/pr123887.c: New testcase.
> ---
> gcc/match.pd | 6 ++++--
> gcc/testsuite/gcc.dg/torture/pr123887.c | 14 ++++++++++++++
> 2 files changed, 18 insertions(+), 2 deletions(-)
> create mode 100644 gcc/testsuite/gcc.dg/torture/pr123887.c
>
> diff --git a/gcc/match.pd b/gcc/match.pd
> index 05e8ea7a229..9b2da2be4c5 100644
> --- a/gcc/match.pd
> +++ b/gcc/match.pd
> @@ -5178,7 +5178,8 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
> (op:c @2 @1))
> (if (INTEGRAL_TYPE_P (type)
> && TYPE_PRECISION (type) > 1
> - && (INTEGRAL_TYPE_P (TREE_TYPE (@0))))
> + && INTEGRAL_TYPE_P (TREE_TYPE (@0))
> + && expr_no_side_effects_p (@2))
> (op (mult (convert:type @0) @2) @1))))
>
> /* (zero_one != 0) ? z <op> y : y -> ((typeof(y))zero_one * z) <op> y */
> @@ -5190,7 +5191,8 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
> @1)
> (if (INTEGRAL_TYPE_P (type)
> && TYPE_PRECISION (type) > 1
> - && (INTEGRAL_TYPE_P (TREE_TYPE (@0))))
> + && INTEGRAL_TYPE_P (TREE_TYPE (@0))
> + && expr_no_side_effects_p (@2))
> (op (mult (convert:type @0) @2) @1))))
>
> /* ?: Value replacement. */
> diff --git a/gcc/testsuite/gcc.dg/torture/pr123887.c
> b/gcc/testsuite/gcc.dg/torture/pr123887.c
> new file mode 100644
> index 00000000000..c2a9659c5b5
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/torture/pr123887.c
> @@ -0,0 +1,14 @@
> +/* { dg-do run } */
> +
> +typedef struct {
> + unsigned s;
> +} struct_t;
> +
> +struct_t *p;
> +bool cond;
> +int v = 1;
> +int main()
> +{
> + int u = 1 + (cond ? p->s : 0);
> + return u - v;
> +}
> --
> 2.51.0