From: Andrew Pinski Date: Fri, 23 Jan 2026 07:12:42 +0000 (-0800) Subject: match: Fix some `(op (cnd @0 @1 @2) @3)` patterns [PR123778] X-Git-Tag: basepoints/gcc-17~1800 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=0cdcc61fb9976b9f6ba2fbf5e9211c3e23a9799c;p=thirdparty%2Fgcc.git 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 --- 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 %"); eat_token (CPP_XOR); + token = peek (); e->match_phi = true; } diff --git a/gcc/match.pd b/gcc/match.pd index b66fd9022eb..e94e474bdc5 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 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 ((void *)_Literal (t)&d + _Literal (void *) 2) + : _Literal (t)&__MEM ((void *)_Literal (t)&d + _Literal (void *) 3); + _14 = _36 - _Literal (char*)&d; + return _14; +}