aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-phiopt.cc
diff options
context:
space:
mode:
authorAndrew Pinski <apinski@marvell.com>2023-05-04 10:07:50 -0700
committerAndrew Pinski <apinski@marvell.com>2023-05-04 23:04:34 -0700
commit2e4e899641c0c558eabf0128ee72cb8d3999c990 (patch)
treeaec860664e13af6e99d4f04d0d5f2bc6438d9a41 /gcc/tree-ssa-phiopt.cc
parent6fe385eac6ff8ecddb6cbdff2c706b27b5137006 (diff)
downloadgcc-2e4e899641c0c558eabf0128ee72cb8d3999c990.zip
gcc-2e4e899641c0c558eabf0128ee72cb8d3999c990.tar.gz
gcc-2e4e899641c0c558eabf0128ee72cb8d3999c990.tar.bz2
PHIOPT: Fix diamond case of match_simplify_replacement
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. 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.dg/pr109732-1.c: New test.
Diffstat (limited to 'gcc/tree-ssa-phiopt.cc')
-rw-r--r--gcc/tree-ssa-phiopt.cc29
1 files changed, 26 insertions, 3 deletions
diff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc
index 2f70463..f14b7e8 100644
--- a/gcc/tree-ssa-phiopt.cc
+++ b/gcc/tree-ssa-phiopt.cc
@@ -720,6 +720,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))
@@ -750,12 +751,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;