This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] EVRP edge info refactoring and simple improvement


The following refactors range extraction from edges and makes EVRP
able to merge such edge based ranges for the case of multiple 
predecessors.  This allows it to catch anti-ranges from
if (a < 4 || a > 8) if that is not re-written to a single test like
when using gotos.

I don't expect this to catch very much in practice but the refactoring
means we can incorporate the tricks from register_edge_assert_for
more easily (we "simply" have to use extract_ranges_from_edge as the
one-and-true kind-of interface).

Motivated by Martin Sebors work on b_o_s and the appearant inability
of EVRP to do anything useful for him.

Bootstrap & regtest running on x86_64-unknown-linux-gnu.

Richard.

2016-12-02  Richard Biener  <rguenther@suse.de>

	* tree-vrp.c (evrp_dom_walker::extract_ranges_from_edge): New method
	split out from evrp_dom_walker::before_dom_children.
	(evrp_dom_walker::before_dom_children): Use it and implement merging
	of edge range info from multiple predecessors.

	* gcc.dg/tree-ssa/evrp7.c: New testcase.

diff --git a/gcc/testsuite/gcc.dg/tree-ssa/evrp7.c b/gcc/testsuite/gcc.dg/tree-ssa/evrp7.c
new file mode 100644
index 0000000..c28347d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/evrp7.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fgimple -fdump-tree-evrp" } */
+
+void __GIMPLE (startwith("evrp"))
+f (unsigned int a)
+{
+  if (a < 4U)
+    goto x;
+  else
+    goto bb_3;
+
+bb_3:
+  if (a > 8U)
+    goto x;
+  else
+    goto bb_4;
+
+x:
+  if (a == 5U)
+    goto bb_5;
+  else
+    goto bb_4;
+
+bb_5:
+  __builtin_abort ();
+
+bb_4:
+  return;
+}
+
+/* { dg-final { scan-tree-dump-times "evrp" 0 "if" } } */
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 600634d..592d3b0 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -10700,6 +10700,7 @@ public:
   void push_value_range (tree var, value_range *vr);
   value_range *pop_value_range (tree var);
   value_range *try_find_new_range (tree op, tree_code code, tree limit);
+  void extract_ranges_from_edge (edge, vec<std::pair <tree, value_range*> > &);
 
   /* Cond_stack holds the old VR.  */
   auto_vec<std::pair <tree, value_range*> > stack;
@@ -10736,13 +10737,69 @@ evrp_dom_walker::try_find_new_range (tree op, tree_code code, tree limit)
   return NULL;
 }
 
+/* Extract ranges on E and store them into V.  */
+
+void
+evrp_dom_walker::extract_ranges_from_edge (edge e,
+					   vec<std::pair
+						<tree, value_range*> > & v)
+{
+  gimple *stmt = last_stmt (e->src);
+  tree op0;
+  if (stmt
+      && gimple_code (stmt) == GIMPLE_COND
+      && (op0 = gimple_cond_lhs (stmt))
+      && TREE_CODE (op0) == SSA_NAME
+      && (INTEGRAL_TYPE_P (TREE_TYPE (gimple_cond_lhs (stmt)))
+	  || POINTER_TYPE_P (TREE_TYPE (gimple_cond_lhs (stmt)))))
+    {
+      if (dump_file && (dump_flags & TDF_DETAILS))
+	{
+	  fprintf (dump_file, "Visiting controlling predicate ");
+	  print_gimple_stmt (dump_file, stmt, 0, 0);
+	}
+      /* Entering a new scope.  Try to see if we can find a VR
+	 here.  */
+      tree op1 = gimple_cond_rhs (stmt);
+      tree_code code = gimple_cond_code (stmt);
+
+      if (TREE_OVERFLOW_P (op1))
+	op1 = drop_tree_overflow (op1);
+
+      /* If condition is false, invert the cond.  */
+      if (e->flags & EDGE_FALSE_VALUE)
+	code = invert_tree_comparison (gimple_cond_code (stmt),
+				       HONOR_NANS (op0));
+      /* Add VR when (OP0 CODE OP1) condition is true.  */
+      value_range *op0_range = try_find_new_range (op0, code, op1);
+
+      /* Register ranges for y in x < y where
+	 y might have ranges that are useful.  */
+      tree limit;
+      tree_code new_code;
+      if (TREE_CODE (op1) == SSA_NAME
+	  && extract_code_and_val_from_cond_with_ops (op1, code,
+						      op0, op1,
+						      false,
+						      &new_code, &limit))
+	{
+	  /* Add VR when (OP1 NEW_CODE LIMIT) condition is true.  */
+	  value_range *op1_range = try_find_new_range (op1, new_code, limit);
+	  if (op1_range)
+	    v.safe_push (std::make_pair (op1, op1_range));
+	}
+
+      if (op0_range)
+	v.safe_push (std::make_pair (op0, op0_range));
+    }
+}
+
 /* See if there is any new scope is entered with new VR and set that VR to
    ssa_name before visiting the statements in the scope.  */
 
 edge
 evrp_dom_walker::before_dom_children (basic_block bb)
 {
-  tree op0 = NULL_TREE;
   edge_iterator ei;
   edge e;
 
@@ -10768,53 +10825,10 @@ evrp_dom_walker::before_dom_children (basic_block bb)
     }
   if (pred_e)
     {
-      gimple *stmt = last_stmt (pred_e->src);
-      if (stmt
-	  && gimple_code (stmt) == GIMPLE_COND
-	  && (op0 = gimple_cond_lhs (stmt))
-	  && TREE_CODE (op0) == SSA_NAME
-	  && (INTEGRAL_TYPE_P (TREE_TYPE (gimple_cond_lhs (stmt)))
-	      || POINTER_TYPE_P (TREE_TYPE (gimple_cond_lhs (stmt)))))
-	{
-	  if (dump_file && (dump_flags & TDF_DETAILS))
-	    {
-	      fprintf (dump_file, "Visiting controlling predicate ");
-	      print_gimple_stmt (dump_file, stmt, 0, 0);
-	    }
-	  /* Entering a new scope.  Try to see if we can find a VR
-	     here.  */
-	  tree op1 = gimple_cond_rhs (stmt);
-	  tree_code code = gimple_cond_code (stmt);
-
-	  if (TREE_OVERFLOW_P (op1))
-	    op1 = drop_tree_overflow (op1);
-
-	  /* If condition is false, invert the cond.  */
-	  if (pred_e->flags & EDGE_FALSE_VALUE)
-	    code = invert_tree_comparison (gimple_cond_code (stmt),
-					   HONOR_NANS (op0));
-	  /* Add VR when (OP0 CODE OP1) condition is true.  */
-	  value_range *op0_range = try_find_new_range (op0, code, op1);
-
-	  /* Register ranges for y in x < y where
-	     y might have ranges that are useful.  */
-	  tree limit;
-	  tree_code new_code;
-	  if (TREE_CODE (op1) == SSA_NAME
-	      && extract_code_and_val_from_cond_with_ops (op1, code,
-							  op0, op1,
-							  false,
-							  &new_code, &limit))
-	    {
-	      /* Add VR when (OP1 NEW_CODE LIMIT) condition is true.  */
-	      value_range *op1_range = try_find_new_range (op1, new_code, limit);
-	      if (op1_range)
-		push_value_range (op1, op1_range);
-	    }
-
-	  if (op0_range)
-	    push_value_range (op0, op0_range);
-	}
+      auto_vec<std::pair<tree, value_range *>, 2> ranges;
+      extract_ranges_from_edge (pred_e, ranges);
+      for (unsigned i = 0; i < ranges.length (); ++i)
+	push_value_range (ranges[i].first, ranges[i].second);
     }
 
   /* Visit PHI stmts and discover any new VRs possible.  */
@@ -10827,6 +10841,71 @@ evrp_dom_walker::before_dom_children (basic_block bb)
 	break;
       }
 
+  /* If we have multiple predecessors try merging range info from them.  */
+  edge first = NULL;
+  if (! pred_e
+      && ! has_unvisited_preds)
+    FOR_EACH_EDGE (e, ei, bb->preds)
+      if ((e->flags & EDGE_EXECUTABLE)
+	  && ! dominated_by_p (CDI_DOMINATORS, e->dest, e->src))
+	{
+	  first = e;
+	  break;
+	}
+  if (first)
+    {
+      auto_vec<std::pair<tree, value_range *>, 2> ranges;
+      extract_ranges_from_edge (first, ranges);
+      if (! ranges.is_empty ())
+	{
+	  FOR_EACH_EDGE (e, ei, bb->preds)
+	    {
+	      if (! (e->flags & EDGE_EXECUTABLE)
+		  || e == first)
+		continue;
+	      bool can_use_lattice_for_edge
+		= dominated_by_p (CDI_DOMINATORS, e->dest, e->src);
+	      auto_vec<std::pair<tree, value_range *>, 2> e_ranges;
+	      extract_ranges_from_edge (e, e_ranges);
+	      /* ??? Sort the range vectors once we may get more than two
+		 ranges and remove the quadratic seach below.  */
+	      for (unsigned i = 0; i < ranges.length ();)
+		{
+		  tree name = ranges[i].first;
+		  bool found = false;
+		  for (unsigned j = 0; j < e_ranges.length (); ++j)
+		    {
+		      if (e_ranges[j].first == name)
+			{
+			  found = true;
+			  vrp_meet (ranges[i].second, e_ranges[j].second);
+			}
+		    }
+		  if (! found
+		      && can_use_lattice_for_edge)
+		    {
+		      found = true;
+		      vrp_meet (ranges[i].second, get_value_range (name));
+		    }
+		  if (! found
+		      || ranges[i].second->type == VR_VARYING)
+		    {
+		      vrp_value_range_pool.remove (ranges[i].second);
+		      ranges.unordered_remove (i);
+		      continue;
+		    }
+		  ++i;
+		}
+	      for (unsigned i = 0; i < e_ranges.length (); ++i)
+		vrp_value_range_pool.remove (e_ranges[i].second);
+	      if (ranges.is_empty ())
+		break;
+	    }
+	  for (unsigned i = 0; i < ranges.length (); ++i)
+	    push_value_range (ranges[i].first, ranges[i].second);
+	}
+    }
+
   for (gphi_iterator gpi = gsi_start_phis (bb);
        !gsi_end_p (gpi); gsi_next (&gpi))
     {


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]