The following deals with the situation where we have

<bb 2> [local count: 1073741824]:
_5 = bytes.D.25336._M_impl.D.24643._M_start;
_6 = bytes.D.25336._M_impl.D.24643._M_finish;
pretmp_66 = bytes.D.25336._M_impl.D.24643._M_end_of_storage;
if (_5 != _6)
  goto <bb 3>; [70.00%]
else
  goto <bb 4>; [30.00%]

...

<bb 6> [local count: 329045359]:
_89 = operator new (4);
_43 = bytes.D.25336._M_impl.D.24643._M_start;
_Num_44 = _137 - _43;
if (_Num_44 != 0)

but fail to see that _137 is equal to _5 and thus eventually _Num_44
is zero if not operator new would possibly clobber the global
bytes variable.

The following resolves this in value-numbering by using the
predicated values for _5 == _6 recorded for the dominating
condition.

Bootstrapped and tested on x86_64-unknown-linux-gnu, pushed.

        PR tree-optimization/107852
        * tree-ssa-sccvn.cc (visit_phi): Use equivalences recorded
        as predicated values to elide more redundant PHIs.

        * gcc.dg/tree-ssa/ssa-fre-101.c: New testcase.
---
 gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-101.c | 47 +++++++++++++++++++
 gcc/tree-ssa-sccvn.cc                       | 51 ++++++++++++++++++++-
 2 files changed, 97 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-101.c

diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-101.c 
b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-101.c
new file mode 100644
index 00000000000..c67f211dcf6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-101.c
@@ -0,0 +1,47 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-fre1-details" } */
+
+int test1 (int i, int j)
+{
+  int k;
+  if (i != j)
+    k = i;
+  else
+    k = j;
+  return k;
+}
+
+int test2 (int i, int j)
+{
+  int k;
+  if (i != j)
+    k = j;
+  else
+    k = i;
+  return k;
+}
+
+int test3 (int i, int j)
+{
+  int k;
+  if (i == j)
+    k = j;
+  else
+    k = i;
+  return k;
+}
+
+int test4 (int i, int j)
+{
+  int k;
+  if (i == j)
+    k = i;
+  else
+    k = j;
+  return k;
+}
+
+/* We'd expect 4 hits but since we only keep one forwarder the
+   VN predication machinery cannot record something for the entry
+   block since it doesn't work on edges but on their source.  */
+/* { dg-final { scan-tree-dump-times "equal on edge" 2 "fre1" } } */
diff --git a/gcc/tree-ssa-sccvn.cc b/gcc/tree-ssa-sccvn.cc
index 1f9c6c53b52..6895ae84d13 100644
--- a/gcc/tree-ssa-sccvn.cc
+++ b/gcc/tree-ssa-sccvn.cc
@@ -5814,7 +5814,8 @@ visit_phi (gimple *phi, bool *inserted, bool 
backedges_varying_p)
 
   /* See if all non-TOP arguments have the same value.  TOP is
      equivalent to everything, so we can ignore it.  */
-  FOR_EACH_EDGE (e, ei, gimple_bb (phi)->preds)
+  basic_block bb = gimple_bb (phi);
+  FOR_EACH_EDGE (e, ei, bb->preds)
     if (e->flags & EDGE_EXECUTABLE)
       {
        tree def = PHI_ARG_DEF_FROM_EDGE (phi, e);
@@ -5859,6 +5860,54 @@ visit_phi (gimple *phi, bool *inserted, bool 
backedges_varying_p)
                         && known_eq (soff, doff))
                  continue;
              }
+           /* There's also the possibility to use equivalences.  */
+           if (!FLOAT_TYPE_P (TREE_TYPE (def)))
+             {
+               vn_nary_op_t vnresult;
+               tree ops[2];
+               ops[0] = def;
+               ops[1] = sameval;
+               tree val = vn_nary_op_lookup_pieces (2, EQ_EXPR,
+                                                    boolean_type_node,
+                                                    ops, &vnresult);
+               if (! val && vnresult && vnresult->predicated_values)
+                 {
+                   val = vn_nary_op_get_predicated_value (vnresult, e->src);
+                   if (val && integer_truep (val))
+                     {
+                       if (dump_file && (dump_flags & TDF_DETAILS))
+                         {
+                           fprintf (dump_file, "Predication says ");
+                           print_generic_expr (dump_file, def, TDF_NONE);
+                           fprintf (dump_file, " and ");
+                           print_generic_expr (dump_file, sameval, TDF_NONE);
+                           fprintf (dump_file, " are equal on edge %d -> %d\n",
+                                    e->src->index, e->dest->index);
+                         }
+                       continue;
+                     }
+                   /* If on all previous edges the value was equal to def
+                      we can change sameval to def.  */
+                   if (EDGE_COUNT (bb->preds) == 2
+                       && (val = vn_nary_op_get_predicated_value
+                                   (vnresult, EDGE_PRED (bb, 0)->src))
+                       && integer_truep (val))
+                     {
+                       if (dump_file && (dump_flags & TDF_DETAILS))
+                         {
+                           fprintf (dump_file, "Predication says ");
+                           print_generic_expr (dump_file, def, TDF_NONE);
+                           fprintf (dump_file, " and ");
+                           print_generic_expr (dump_file, sameval, TDF_NONE);
+                           fprintf (dump_file, " are equal on edge %d -> %d\n",
+                                    EDGE_PRED (bb, 0)->src->index,
+                                    EDGE_PRED (bb, 0)->dest->index);
+                         }
+                       sameval = def;
+                       continue;
+                     }
+                 }
+             }
            sameval = NULL_TREE;
            break;
          }
-- 
2.35.3

Reply via email to