https://gcc.gnu.org/g:0cdcc61fb9976b9f6ba2fbf5e9211c3e23a9799c
commit r16-7004-g0cdcc61fb9976b9f6ba2fbf5e9211c3e23a9799c Author: Andrew Pinski <[email protected]> Date: Thu Jan 22 23:12:42 2026 -0800 match: Fix some `(op (cnd @0 @1 @2) @3)` patterns [PR123778] 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. 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)`, `(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]> Diff: --- gcc/genmatch.cc | 2 ++ gcc/match.pd | 14 +++++++------- gcc/testsuite/gcc.dg/torture/pr123778-1.c | 20 ++++++++++++++++++++ 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/gcc/genmatch.cc b/gcc/genmatch.cc index 1cb252229769..633ff9e1db21 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 b66fd9022eb3..e94e474bdc57 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. */ @@ -6281,7 +6281,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) @@ -6301,7 +6301,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) @@ -6310,7 +6310,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) @@ -8638,7 +8638,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) @@ -8649,13 +8649,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 000000000000..ebaa92b76b3c --- /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; +}
