> 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
> 

Reply via email to