> Am 23.01.2026 um 16:53 schrieb Andrew Pinski <[email protected]>:
>
> All of these patterns have in common is they try to move
> the op inside the cnd if it simplifies. The problem is the
> type of the op does not need to be the type of first operand
> and instead is the type of the type variable. The fix is to
> supply the type to the op like in `(op:type @1 @3)`.
> But since they were originally in the `(op! @1 @3)`, it should be:
> `(op!:type @1 @3)`. Though this would be rejected as we don't pick
> up the next token after parsing the `!` (note `^` has the same issue
> which is also fixed here too).
>
> Bootstrapped and tested on x86_64-linux-gnu.
Ok
Richard
> PR tree-optimization/123778
>
> gcc/ChangeLog:
>
> * genmatch.cc (parser::parse_expr): Peek on the next
> token after eating the `!` or `^`.
> * match.pd (`(op (cnd @0 @1 @2) @3)` and `(op @3 (cnd @0 @1 @2))`:
> Add the type to resulting op.
>
> gcc/testsuite/ChangeLog:
>
> * gcc.dg/torture/pr123778-1.c: New test.
>
> Signed-off-by: Andrew Pinski <[email protected]>
> ---
> gcc/genmatch.cc | 2 ++
> gcc/match.pd | 14 +++++++-------
> gcc/testsuite/gcc.dg/torture/pr123778-1.c | 20 ++++++++++++++++++++
> 3 files changed, 29 insertions(+), 7 deletions(-)
> create mode 100644 gcc/testsuite/gcc.dg/torture/pr123778-1.c
>
> diff --git a/gcc/genmatch.cc b/gcc/genmatch.cc
> index 1cb25222976..633ff9e1db2 100644
> --- a/gcc/genmatch.cc
> +++ b/gcc/genmatch.cc
> @@ -5435,6 +5435,7 @@ parser::parse_expr ()
> && !(token->flags & PREV_WHITE))
> {
> eat_token (CPP_NOT);
> + token = peek ();
> e->force_leaf = true;
> }
>
> @@ -5447,6 +5448,7 @@ parser::parse_expr ()
> fatal_at (token, "modifier %<^%> can only act on operation %<COND_EXPR%>");
>
> eat_token (CPP_XOR);
> + token = peek ();
> e->match_phi = true;
> }
>
> diff --git a/gcc/match.pd b/gcc/match.pd
> index e0a2399ca65..d1a7956e531 100644
> --- a/gcc/match.pd
> +++ b/gcc/match.pd
> @@ -6242,7 +6242,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
> (for op (negate bit_not abs absu)
> (simplify
> (op (vec_cond:s @0 @1 @2))
> - (vec_cond @0 (op! @1) (op! @2))))
> + (vec_cond @0 (op!:type @1) (op!:type @2))))
>
> /* Sink unary conversions to branches, but only if we do fold both
> and the target's truth type is the same as we already have. */
> @@ -6277,7 +6277,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
> missing the legacy vcond{,u,eq} cases. Do this only when
> lowering will be able to fixup.. */
> && !expand_vec_cond_expr_p (TREE_TYPE (@1), TREE_TYPE (@0)))))
> - (vec_cond @0 (op! @1 @3) (op! @2 @4))))
> + (vec_cond @0 (op!:type @1 @3) (op!:type @2 @4))))
>
> /* (@0 ? @2 : @3) lop (@1 ? @2 : @3) --> (@0 lop @1) ? @2 : @3. */
> (for lop (bit_and bit_ior bit_xor)
> @@ -6297,7 +6297,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
> || expand_vec_cond_expr_p (type, TREE_TYPE (@0))
> || (optimize_vectors_before_lowering_p ()
> && !expand_vec_cond_expr_p (TREE_TYPE (@1), TREE_TYPE (@0)))))
> - (vec_cond @0 (op! @1 @3) (op! @2 @3))))
> + (vec_cond @0 (op!:type @1 @3) (op!:type @2 @3))))
> (simplify
> (op @3 (vec_cond:s @0 @1 @2))
> (if (VECTOR_TYPE_P (type)
> @@ -6306,7 +6306,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
> || expand_vec_cond_expr_p (type, TREE_TYPE (@0))
> || (optimize_vectors_before_lowering_p ()
> && !expand_vec_cond_expr_p (TREE_TYPE (@1), TREE_TYPE (@0)))))
> - (vec_cond @0 (op! @3 @1) (op! @3 @2)))))
> + (vec_cond @0 (op!:type @3 @1) (op!:type @3 @2)))))
>
> #if GIMPLE
> (match (nop_atomic_bit_test_and_p @0 @1 @4)
> @@ -8634,7 +8634,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
> pessimizes code and causes gimplification issues when applied late. */
> (if (!FLOAT_TYPE_P (TREE_TYPE (@3))
> || !operation_could_trap_p (cmp, true, false, @3))
> - (cond @0 (cmp! @1 @3) (cmp! @2 @3)))))
> + (cond @0 (cmp!:type @1 @3) (cmp!:type @2 @3)))))
>
> /* Similar to above:
> (c ? a : b) op d -> c ? (a op d) : (b op d)
> @@ -8645,13 +8645,13 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
> lrotate rrotate mult_highpart)
> (simplify
> (op (cond @0 @1 @2) @3)
> - (cond @0 (op! @1 @3) (op! @2 @3)))
> + (cond @0 (op!:type @1 @3) (op!:type @2 @3)))
>
> /* Support the variant
> d op (c ? a : b) -> c ? (d op a) : (d op b) */
> (simplify
> (op @3 (cond @0 @1 @2))
> - (cond @0 (op! @3 @1) (op! @3 @2))))
> + (cond @0 (op!:type @3 @1) (op!:type @3 @2))))
> #endif
>
> /* Transform comparisons of the form (X & Y) CMP 0 to X CMP2 Z
> diff --git a/gcc/testsuite/gcc.dg/torture/pr123778-1.c
> b/gcc/testsuite/gcc.dg/torture/pr123778-1.c
> new file mode 100644
> index 00000000000..ebaa92b76b3
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/torture/pr123778-1.c
> @@ -0,0 +1,20 @@
> +/* { dg-do compile } */
> +/* { dg-options "-fgimple" } */
> +
> +/* PR tree-optimization/123778 */
> +
> +typedef char (*t)[3];
> +long __GIMPLE(ssa) f(char a, int d)
> +{
> + _Bool _107;
> + __PTRDIFF_TYPE__ _14;
> + char *_36;
> +
> +__BB(2):
> + _107 = a_2(D) != _Literal (char) 0;
> + _36 = _107
> + ? _Literal (t)&__MEM <char[3]> ((void *)_Literal (t)&d + _Literal
> (void *) 2)
> + : _Literal (t)&__MEM <char[3]> ((void *)_Literal (t)&d + _Literal
> (void *) 3);
> + _14 = _36 - _Literal (char*)&d;
> + return _14;
> +}
> --
> 2.43.0
>