aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2023-03-30 11:32:19 +0200
committerRichard Biener <rguenther@suse.de>2023-03-30 13:02:19 +0200
commit1d0ba4467dd9cad11eb9ff547442e3ce6292b892 (patch)
treedaf4e2e864fd771d9e662346334bdf1e4b1d370c /gcc
parentee6ae8cb4793041590b479346433ed786a86985d (diff)
downloadgcc-1d0ba4467dd9cad11eb9ff547442e3ce6292b892.zip
gcc-1d0ba4467dd9cad11eb9ff547442e3ce6292b892.tar.gz
gcc-1d0ba4467dd9cad11eb9ff547442e3ce6292b892.tar.bz2
tree-optimization/109342 - wrong code with edge equivalences in VN
The following testcase shows a problem in how we query valitity for equivalences on edges when the edge is a backedge and thus refering to a block thats later in the iteration order we use for VN. That causes the dominated_by_p_w_unex helper to look at edge executable state that's not yet computed and thus still at optimistic not executable state. The following makes sure to use a plain dominance check in these cases. PR tree-optimization/109342 * tree-ssa-sccvn.cc (vn_nary_op_get_predicated_value): New overload for edge. When that edge is a backedge use dominated_by_p directly. * g++.dg/torture/pr109342.C: New testcase.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/testsuite/g++.dg/torture/pr109342.C33
-rw-r--r--gcc/tree-ssa-sccvn.cc37
2 files changed, 60 insertions, 10 deletions
diff --git a/gcc/testsuite/g++.dg/torture/pr109342.C b/gcc/testsuite/g++.dg/torture/pr109342.C
new file mode 100644
index 0000000..2cdfa76
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr109342.C
@@ -0,0 +1,33 @@
+// { dg-do run }
+
+unsigned long int var_4 = 42;
+unsigned long int var_14 = 10;
+unsigned char var_16 = 1;
+unsigned short var_18 = 0;
+short var_75;
+
+inline const int &foo(const int &b, const int &c)
+{
+ return b < c ? c : b;
+}
+inline unsigned long &bar(unsigned long &b, unsigned long &c)
+{
+ return !c ? c : b;
+}
+
+void __attribute__((noipa))
+test(unsigned long var_4, unsigned long var_14,
+ unsigned char var_16, unsigned short var_18)
+{
+ for (bool h = 0; h < (bool)foo(var_16 ? -7 : 4, var_4 ? var_4 : var_18);
+ h = 2)
+ var_75 = bar(var_4, var_14);
+}
+
+int main()
+{
+ test(var_4, var_14, var_16, var_18);
+ if (var_75 != 42)
+ __builtin_abort();
+ return 0;
+}
diff --git a/gcc/tree-ssa-sccvn.cc b/gcc/tree-ssa-sccvn.cc
index 6b8d38b..9960953 100644
--- a/gcc/tree-ssa-sccvn.cc
+++ b/gcc/tree-ssa-sccvn.cc
@@ -4583,22 +4583,39 @@ static bool
dominated_by_p_w_unex (basic_block bb1, basic_block bb2, bool);
static tree
-vn_nary_op_get_predicated_value (vn_nary_op_t vno, basic_block bb)
+vn_nary_op_get_predicated_value (vn_nary_op_t vno, basic_block bb,
+ edge e = NULL)
{
if (! vno->predicated_values)
return vno->u.result;
for (vn_pval *val = vno->u.values; val; val = val->next)
for (unsigned i = 0; i < val->n; ++i)
- /* Do not handle backedge executability optimistically since
- when figuring out whether to iterate we do not consider
- changed predication. */
- if (dominated_by_p_w_unex
- (bb, BASIC_BLOCK_FOR_FN (cfun, val->valid_dominated_by_p[i]),
- false))
- return val->result;
+ {
+ basic_block cand
+ = BASIC_BLOCK_FOR_FN (cfun, val->valid_dominated_by_p[i]);
+ /* Do not handle backedge executability optimistically since
+ when figuring out whether to iterate we do not consider
+ changed predication.
+ When asking for predicated values on an edge avoid looking
+ at edge executability for edges forward in our iteration
+ as well. */
+ if (e && (e->flags & EDGE_DFS_BACK))
+ {
+ if (dominated_by_p (CDI_DOMINATORS, bb, cand))
+ return val->result;
+ }
+ else if (dominated_by_p_w_unex (bb, cand, false))
+ return val->result;
+ }
return NULL_TREE;
}
+static tree
+vn_nary_op_get_predicated_value (vn_nary_op_t vno, edge e)
+{
+ return vn_nary_op_get_predicated_value (vno, e->src, e);
+}
+
/* Insert the rhs of STMT into the current hash table with a value number of
RESULT. */
@@ -5928,7 +5945,7 @@ visit_phi (gimple *phi, bool *inserted, bool backedges_varying_p)
ops, &vnresult);
if (! val && vnresult && vnresult->predicated_values)
{
- val = vn_nary_op_get_predicated_value (vnresult, e->src);
+ val = vn_nary_op_get_predicated_value (vnresult, e);
if (val && integer_truep (val)
&& !(sameval_e && (sameval_e->flags & EDGE_DFS_BACK)))
{
@@ -5947,7 +5964,7 @@ visit_phi (gimple *phi, bool *inserted, bool backedges_varying_p)
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))
+ (vnresult, EDGE_PRED (bb, 0)))
&& integer_truep (val)
&& !(e->flags & EDGE_DFS_BACK))
{