diff mbox series

tree-optimization/109342 - wrong code with edge equivalences in VN

Message ID 20230330110206.11FDD1348E@imap2.suse-dmz.suse.de
State New
Headers show
Series tree-optimization/109342 - wrong code with edge equivalences in VN | expand

Commit Message

Richard Biener March 30, 2023, 11:02 a.m. UTC
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.

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

	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.
---
 gcc/testsuite/g++.dg/torture/pr109342.C | 33 ++++++++++++++++++++++
 gcc/tree-ssa-sccvn.cc                   | 37 ++++++++++++++++++-------
 2 files changed, 60 insertions(+), 10 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/torture/pr109342.C
diff mbox series

Patch

diff --git a/gcc/testsuite/g++.dg/torture/pr109342.C b/gcc/testsuite/g++.dg/torture/pr109342.C
new file mode 100644
index 00000000000..2cdfa764faf
--- /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 6b8d38b270c..99609538f54 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))
 		      {