[PATCH] PHIOPT: Fix diamond case of match_simplify_replacement

Richard Biener richard.guenther@gmail.com
Fri May 5 06:14:18 GMT 2023


On Thu, May 4, 2023 at 11:57 PM Andrew Pinski via Gcc-patches
<gcc-patches@gcc.gnu.org> wrote:
>
> So it turns out I messed checking which edge was true/false for the diamond
> form. The edges, e0 and e1 here are edges from the merge block but the
> true/false edges are from the conditional block and with diamond/threeway,
> there is a bb inbetween on both edges.
> Most of the time, the check that was in match_simplify_replacement would
> happen to be correct for diamond form as most of the time the first edge in
> the conditional is the edge for the true side of the conditional.
> This is why I didn't see the issue during bootstrap/testing.
>
> I added a fragile gimple testcase which exposed the issue. Since there is
> no way to specify the order of the edges in the gimple fe, we have to
> have forwprop to swap the false/true edges (not order of them, just swapping
> true/false flags) and hope not to do cleanupcfg inbetween forwprop and the
> first phiopt pass. This is the fragile part really, it is not that we will
> produce wrong code, just we won't hit what was the failing case.
>
> OK? Bootstrapped and tested on x86_64-linux-gnu.

OK.

Thanks,
Richard.

>         PR tree-optimization/109732
>
> gcc/ChangeLog:
>
>         * tree-ssa-phiopt.cc (match_simplify_replacement): Fix the selection
>         of the argtrue/argfalse.
>
> gcc/testsuite/ChangeLog:
>
>         * gcc.dg/pr109732.c: New test.
> ---
>  gcc/testsuite/gcc.dg/pr109732.c | 40 +++++++++++++++++++++++++++++++++
>  gcc/tree-ssa-phiopt.cc          | 29 +++++++++++++++++++++---
>  2 files changed, 66 insertions(+), 3 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.dg/pr109732.c
>
> diff --git a/gcc/testsuite/gcc.dg/pr109732.c b/gcc/testsuite/gcc.dg/pr109732.c
> new file mode 100644
> index 00000000000..d8374705cd8
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/pr109732.c
> @@ -0,0 +1,40 @@
> +/* { dg-do run } */
> +/* We need to disable passes which might cause cfg cleanup */
> +/* { dg-options "-O1 -fgimple -fdisable-tree-ethread -fdisable-tree-fre1" } */
> +
> +/* This code is done this way to have the false edge as 1st
> +   successor edge of BB2. Normally the true edge would be
> +   the first and you would not hit the bug.  */
> +[[gnu::noipa]]
> +_Bool __GIMPLE (ssa, startwith("forwprop1"))
> +f3 (_Bool a)
> +{
> +  _Bool i;
> +  _Bool tt;
> +
> +  __BB(2):
> +  tt_4 = a_1(D) == _Literal (_Bool)0;
> +  if (tt_4 != _Literal (_Bool)0)
> +    goto __BB3;
> +  else
> +    goto __BB4;
> +
> +  __BB(3):
> +    goto __BB5;
> +
> +  __BB(4):
> +    goto __BB5;
> +
> +  __BB(5):
> +  i_2 = __PHI (__BB4: a_1(D), __BB3: _Literal (_Bool)0);
> +
> +  return i_2;
> +}
> +
> +int main()
> +{
> +  if (f3(0))
> +    __builtin_abort();
> +  if (!f3(1))
> +    __builtin_abort();
> +}
> diff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc
> index 14aeaadd6f6..2fb28b4e60e 100644
> --- a/gcc/tree-ssa-phiopt.cc
> +++ b/gcc/tree-ssa-phiopt.cc
> @@ -726,6 +726,7 @@ match_simplify_replacement (basic_block cond_bb, basic_block middle_bb,
>    gimple *stmt_to_move = NULL;
>    gimple *stmt_to_move_alt = NULL;
>    auto_bitmap inserted_exprs;
> +  tree arg_true, arg_false;
>
>    /* Special case A ? B : B as this will always simplify to B. */
>    if (operand_equal_for_phi_arg_p (arg0, arg1))
> @@ -756,12 +757,34 @@ match_simplify_replacement (basic_block cond_bb, basic_block middle_bb,
>    /* 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);
> -  if (e1 == true_edge || e0 == false_edge)
> -    std::swap (arg0, arg1);
> +
> +  /* 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);
> +
> +  /* When THREEWAY_P then e1 will point to the edge of the final transition
> +     from middle-bb to end.  */
> +  if (true_edge == e0)
> +    {
> +      if (!threeway_p)
> +       gcc_assert (false_edge == e1);
> +      arg_true = arg0;
> +      arg_false = arg1;
> +    }
> +  else
> +    {
> +      gcc_assert (false_edge == e0);
> +      if (!threeway_p)
> +       gcc_assert (true_edge == e1);
> +      arg_true = arg1;
> +      arg_false = arg0;
> +    }
>
>    tree type = TREE_TYPE (gimple_phi_result (phi));
>    result = gimple_simplify_phiopt (early_p, type, stmt,
> -                                  arg0, arg1,
> +                                  arg_true, arg_false,
>                                    &seq);
>    if (!result)
>      return false;
> --
> 2.39.1
>


More information about the Gcc-patches mailing list