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.

        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