aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2022-11-29 12:56:22 +0100
committerRichard Biener <rguenther@suse.de>2022-11-29 14:30:35 +0100
commitfd8dd6c0384969170e594be34da278a072d5eb76 (patch)
tree9afc4155efc589af6eb7990d7e8793cfbf503a9a
parent063ba138eaa15ceecf23a24906e0e19be98d509d (diff)
downloadgcc-fd8dd6c0384969170e594be34da278a072d5eb76.zip
gcc-fd8dd6c0384969170e594be34da278a072d5eb76.tar.gz
gcc-fd8dd6c0384969170e594be34da278a072d5eb76.tar.bz2
tree-optimization/107852 - missed optimization with PHIs
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. 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.
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-101.c47
-rw-r--r--gcc/tree-ssa-sccvn.cc51
2 files changed, 97 insertions, 1 deletions
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 0000000..c67f211
--- /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 3748440..1e7763b 100644
--- a/gcc/tree-ssa-sccvn.cc
+++ b/gcc/tree-ssa-sccvn.cc
@@ -5793,7 +5793,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);
@@ -5838,6 +5839,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;
}