> Am 18.01.2026 um 05:39 schrieb Andrew Pinski <[email protected]>:
>
> The canonicalization of args code was originally thinking edges e1/e2
> were edges out going from the cond block but they were the edges
> coming into the join block. This rewrites the canonicalization of arg0/1
> args to correct that mistake. And it fixes the wrong code that would
> happen in this case.
Ok
Thanks,
Richard
> PR tree-optimization/123645
>
> gcc/ChangeLog:
>
> * tree-ssa-phiopt.cc (cond_removal_in_builtin_zero_pattern): Rewrite
> the canonicalization of the args code based on e1/e2 being edges into
> the join block.
>
> gcc/testsuite/ChangeLog:
>
> * gcc.dg/torture/pr123645-1.c: New test.
> * gcc.dg/torture/pr123645-2.c: New test.
>
> Signed-off-by: Andrew Pinski <[email protected]>
> ---
> gcc/testsuite/gcc.dg/torture/pr123645-1.c | 24 +++++++++++++++++
> gcc/testsuite/gcc.dg/torture/pr123645-2.c | 24 +++++++++++++++++
> gcc/tree-ssa-phiopt.cc | 32 ++++++++++++++++++-----
> 3 files changed, 74 insertions(+), 6 deletions(-)
> create mode 100644 gcc/testsuite/gcc.dg/torture/pr123645-1.c
> create mode 100644 gcc/testsuite/gcc.dg/torture/pr123645-2.c
>
> diff --git a/gcc/testsuite/gcc.dg/torture/pr123645-1.c
> b/gcc/testsuite/gcc.dg/torture/pr123645-1.c
> new file mode 100644
> index 00000000000..c183cd31d41
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/torture/pr123645-1.c
> @@ -0,0 +1,24 @@
> +/* { dg-do run } */
> +
> +/* PR tree-optimization/123645 */
> +/* Phi-opt was transforming f into __builtin_popcount which was incorrect. */
> +
> +__attribute__((noinline))
> +int f(unsigned a)
> +{
> + return a < 1 ? __builtin_popcount(a) : 0;
> +}
> +
> +int main()
> +{
> + if (f(1) != 0)
> + __builtin_abort();
> + if (f(0) != 0)
> + __builtin_abort();
> + if (f(2) != 0)
> + __builtin_abort();
> + if (f(3) != 0)
> + __builtin_abort();
> + if (f(-1) != 0)
> + __builtin_abort();
> +}
> diff --git a/gcc/testsuite/gcc.dg/torture/pr123645-2.c
> b/gcc/testsuite/gcc.dg/torture/pr123645-2.c
> new file mode 100644
> index 00000000000..8c488acfbec
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/torture/pr123645-2.c
> @@ -0,0 +1,24 @@
> +/* { dg-do run } */
> +
> +/* PR tree-optimization/123645 */
> +/* Phi-opt was transforming f into __builtin_bswap which was incorrect. */
> +
> +__attribute__((noinline))
> +int f(unsigned a)
> +{
> + return a < 1 ? __builtin_bswap32(a) : 0;
> +}
> +
> +int main()
> +{
> + if (f(1) != 0)
> + __builtin_abort();
> + if (f(0) != 0)
> + __builtin_abort();
> + if (f(2) != 0)
> + __builtin_abort();
> + if (f(3) != 0)
> + __builtin_abort();
> + if (f(-1) != 0)
> + __builtin_abort();
> +}
> diff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc
> index 9ce24067377..167b86b3acc 100644
> --- a/gcc/tree-ssa-phiopt.cc
> +++ b/gcc/tree-ssa-phiopt.cc
> @@ -2627,16 +2627,36 @@ cond_removal_in_builtin_zero_pattern (basic_block
> cond_bb,
> || arg != gimple_cond_lhs (cond))
> return false;
>
> - /* Canonicalize. */
> - if ((e2->flags & EDGE_TRUE_VALUE
> - && gimple_cond_code (cond) == NE_EXPR)
> - || (e1->flags & EDGE_TRUE_VALUE
> - && gimple_cond_code (cond) == EQ_EXPR))
> + edge true_edge, false_edge;
> + /* We need to know which is the true edge and which is the false
> + edge so that we know when to invert the condition below. */
> + extract_true_false_edges_from_block (cond_bb, &true_edge, &false_edge);
> +
> + /* Forward the edges over the middle basic block. */
> + if (true_edge->dest == middle_bb)
> + true_edge = EDGE_SUCC (true_edge->dest, 0);
> + if (false_edge->dest == middle_bb)
> + false_edge = EDGE_SUCC (false_edge->dest, 0);
> +
> + /* Canonicalize the args with respect to the edges,
> + arg0 is from the true edge and arg1 is from the
> + false edge.
> + That is `cond ? arg0 : arg1`.*/
> + if (true_edge == e1)
> + gcc_assert (false_edge == e2);
> + else
> {
> + gcc_assert (false_edge == e1);
> + gcc_assert (true_edge == e2);
> std::swap (arg0, arg1);
> - std::swap (e1, e2);
> }
>
> + /* Canonicalize the args such that we get:
> + `arg != 0 ? arg0 : arg1`. So swap arg0/arg1
> + around if cond was an equals. */
> + if (gimple_cond_code (cond) == EQ_EXPR)
> + std::swap (arg0, arg1);
> +
> /* Check PHI arguments. */
> if (lhs != arg0
> || TREE_CODE (arg1) != INTEGER_CST)
> --
> 2.43.0
>