public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc/devel/loop-unswitch-support-switches] This fixes the execute FAIL of gfortran.fortran-torture/execute/forall_7.f90
@ 2022-05-18 12:23 Richard Biener
  0 siblings, 0 replies; only message in thread
From: Richard Biener @ 2022-05-18 12:23 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:74ccb99070906ed9bbed2079e6ffba732ef1678d

commit 74ccb99070906ed9bbed2079e6ffba732ef1678d
Author: Richard Biener <rguenther@suse.de>
Date:   Wed May 18 10:59:23 2022 +0200

    This fixes the execute FAIL of gfortran.fortran-torture/execute/forall_7.f90
    
    Using global ranges and inverting them is not correct - in the
    particular case we ended up with a global range from a if (a_1 = b_2)
    predicate and used the inversion on the false edge.  The change
    refactors the predicate CTORs again, using range-ops to create a bare
    range from the comparison in the GIMPLE_COND only and for switches
    resorts to computing the ranges manually by unioning the case ranges.
    
    The ranger query in the simplification code should probably change
    as well to use a path_range_query where we should seed the path
    range oracle with the predicate stack of the loop version we want
    to simplify.

Diff:
---
 gcc/tree-ssa-loop-unswitch.cc | 106 ++++++++++++++++++++++++------------------
 1 file changed, 62 insertions(+), 44 deletions(-)

diff --git a/gcc/tree-ssa-loop-unswitch.cc b/gcc/tree-ssa-loop-unswitch.cc
index 0e8baded8b9..c5d3762e867 100644
--- a/gcc/tree-ssa-loop-unswitch.cc
+++ b/gcc/tree-ssa-loop-unswitch.cc
@@ -101,52 +101,63 @@ along with GCC; see the file COPYING3.  If not see
    7) The process is repeated until we reach a growth threshold or all
       unswitching opportunities are taken.  */
 
-/* Ranger instance used in the pass.  */
-static gimple_ranger *ranger = NULL;
-
 /* A tuple that holds a GENERIC condition and value range for an unswitching
    predicate.  */
 
 struct unswitch_predicate
 {
   /* CTOR for a switch edge predicate.  */
-  unswitch_predicate (tree cond, tree lhs_, int edge_index_, edge e)
-  : condition (cond), lhs (lhs_), true_range (), false_range (),
+  unswitch_predicate (tree cond, tree lhs_, int edge_index_, edge e,
+		      const int_range_max& edge_range)
+  : condition (cond), lhs (lhs_), true_range (edge_range), false_range (),
     merged_true_range (), merged_false_range (),
     edge_index (edge_index_)
   {
-    gcc_assert (!(e->flags & (EDGE_TRUE_VALUE|EDGE_FALSE_VALUE)));
-    if (irange::supports_type_p (TREE_TYPE (lhs)))
-      {
-	if (ranger->gori ().outgoing_edge_range_p (true_range, e, lhs,
-						   *get_global_range_query ()))
-	  {
-	    false_range = true_range;
-	    if (!false_range.varying_p ()
-		&& !false_range.undefined_p ())
-	      false_range.invert ();
-	  }
-      }
+    gcc_assert (!(e->flags & (EDGE_TRUE_VALUE|EDGE_FALSE_VALUE))
+		&& irange::supports_type_p (TREE_TYPE (lhs)));
+    false_range = true_range;
+    if (!false_range.varying_p ()
+	&& !false_range.undefined_p ())
+      false_range.invert ();
     num = predicates->length ();
     predicates->safe_push (this);
   }
 
-  /* CTOR for an if true edge predicate.  */
-  unswitch_predicate (tree cond, tree lhs_, edge e)
-  : condition (cond), lhs (lhs_), true_range (), false_range (),
-    merged_true_range (), merged_false_range ()
+  /* CTOR for a GIMPLE condition statement.  */
+  unswitch_predicate (gcond *stmt)
+    : true_range (), false_range (), merged_true_range (), merged_false_range ()
   {
-    gcc_assert (e->flags & EDGE_TRUE_VALUE);
-    edge_index = (EDGE_SUCC (e->src, 0) == e) ? 0 : 1;
+    if (EDGE_SUCC (gimple_bb (stmt), 0)->flags & EDGE_TRUE_VALUE)
+      edge_index = 0;
+    else
+      edge_index = 1;
+    lhs = gimple_cond_lhs (stmt);
+    tree rhs = gimple_cond_rhs (stmt);
+    enum tree_code code = gimple_cond_code (stmt);
+    condition = build2 (code, boolean_type_node, lhs, rhs);
     if (irange::supports_type_p (TREE_TYPE (lhs)))
       {
-	if (ranger->gori ().outgoing_edge_range_p (true_range, e, lhs,
-						   *get_global_range_query ()))
+	auto range_op = range_op_handler (code, TREE_TYPE (lhs));
+	int_range<2> rhs_range (TREE_TYPE (rhs));
+	if (CONSTANT_CLASS_P (rhs))
+	  rhs_range.set (rhs);
+	if (!range_op->op1_range (true_range, TREE_TYPE (lhs),
+				  int_range<2> (boolean_true_node,
+						boolean_true_node), rhs_range))
+	  {
+	    true_range.set_varying (TREE_TYPE (lhs));
+	    false_range.set_varying (TREE_TYPE (lhs));
+	  }
+	else
 	  {
 	    false_range = true_range;
 	    if (!false_range.varying_p ()
 		&& !false_range.undefined_p ())
 	      false_range.invert ();
+	    else
+	      /* ???  Inversion of undefined is varying, of varying
+		 is undefined but ranger asserts.  */
+	      false_range.set_varying (TREE_TYPE (lhs));
 	  }
       }
     num = predicates->length ();
@@ -188,6 +199,9 @@ struct unswitch_predicate
 
 vec<unswitch_predicate *> *unswitch_predicate::predicates;
 
+/* Ranger instance used in the pass.  */
+static gimple_ranger *ranger = NULL;
+
 /* Cache storage for unswitch_predicate belonging to a basic block.  */
 static vec<vec<unswitch_predicate *>> *bb_predicates;
 
@@ -444,7 +458,7 @@ find_unswitching_predicates_for_bb (basic_block bb, class loop *loop,
 				    vec<unswitch_predicate *> &candidates)
 {
   gimple *last, *def;
-  tree cond, use;
+  tree use;
   basic_block def_bb;
   ssa_op_iter iter;
 
@@ -461,6 +475,10 @@ find_unswitching_predicates_for_bb (basic_block bb, class loop *loop,
       if (gimple_cond_true_p (stmt) || gimple_cond_false_p (stmt))
 	return;
 
+      /* At least the LHS needs to be symbolic.  */
+      if (TREE_CODE (gimple_cond_lhs (stmt)) != SSA_NAME)
+	return;
+
       /* Condition must be invariant.  */
       FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE)
 	{
@@ -475,17 +493,7 @@ find_unswitching_predicates_for_bb (basic_block bb, class loop *loop,
 	    return;
 	}
 
-      tree lhs = gimple_cond_lhs (stmt);
-      tree rhs = gimple_cond_rhs (stmt);
-      if (TREE_CODE (lhs) != SSA_NAME)
-	return;
-
-      cond = build2 (gimple_cond_code (stmt), boolean_type_node, lhs, rhs);
-      edge edge_true, edge_false;
-      extract_true_false_edges_from_block (bb, &edge_true, &edge_false);
-
-      unswitch_predicate *predicate = new unswitch_predicate (cond, lhs,
-							      edge_true);
+      unswitch_predicate *predicate = new unswitch_predicate (stmt);
       candidates.safe_push (predicate);
     }
   else if (gswitch *stmt = safe_dyn_cast <gswitch *> (last))
@@ -508,7 +516,9 @@ find_unswitching_predicates_for_bb (basic_block bb, class loop *loop,
 
       /* Build compound expression for all outgoing edges of the switch.  */
       auto_vec<tree, 16> preds;
-      preds.safe_grow_cleared (EDGE_COUNT (gimple_bb (stmt)->succs));
+      auto_vec<int_range_max> edge_range;
+      preds.safe_grow_cleared (EDGE_COUNT (gimple_bb (stmt)->succs), true);
+      edge_range.safe_grow_cleared (EDGE_COUNT (gimple_bb (stmt)->succs), true);
       edge e;
       edge_iterator ei;
       unsigned edge_index = 0;
@@ -518,6 +528,7 @@ find_unswitching_predicates_for_bb (basic_block bb, class loop *loop,
 	{
 	  tree lab = gimple_switch_label (stmt, i);
 	  tree cmp;
+	  int_range<2> lab_range;
 	  if (CASE_HIGH (lab) != NULL_TREE)
 	    {
 	      tree cmp1 = fold_build2 (GE_EXPR, boolean_type_node, idx,
@@ -525,9 +536,14 @@ find_unswitching_predicates_for_bb (basic_block bb, class loop *loop,
 	      tree cmp2 = fold_build2 (LE_EXPR, boolean_type_node, idx,
 				       CASE_HIGH (lab));
 	      cmp = fold_build2 (BIT_AND_EXPR, boolean_type_node, cmp1, cmp2);
+	      lab_range.set (CASE_LOW (lab), CASE_HIGH (lab));
 	    }
 	  else
-	    cmp = fold_build2 (EQ_EXPR, boolean_type_node, idx, CASE_LOW (lab));
+	    {
+	      cmp = fold_build2 (EQ_EXPR, boolean_type_node, idx,
+				 CASE_LOW (lab));
+	      lab_range.set (CASE_LOW (lab));
+	    }
 
 	  /* Combine the expression with the existing one.  */
 	  basic_block dest = label_to_block (cfun, CASE_LABEL (lab));
@@ -537,6 +553,7 @@ find_unswitching_predicates_for_bb (basic_block bb, class loop *loop,
 	    expr = cmp;
 	  else
 	    expr = fold_build2 (BIT_IOR_EXPR, boolean_type_node, expr, cmp);
+	  edge_range[(uintptr_t)e->aux].union_ (lab_range);
 	}
 
       /* Now register the predicates.  */
@@ -548,7 +565,8 @@ find_unswitching_predicates_for_bb (basic_block bb, class loop *loop,
 	    {
 	      unswitch_predicate *predicate
 		= new unswitch_predicate (preds[edge_index], idx,
-					  edge_index, e);
+					  edge_index, e,
+					  edge_range[edge_index]);
 	      candidates.safe_push (predicate);
 	    }
 	}
@@ -637,7 +655,7 @@ evaluate_control_stmt_using_entry_checks (gimple *stmt,
       /* Else try ranger if it supports LHS.  */
       else if (irange::supports_type_p (TREE_TYPE (lhs)))
 	{
-	  int_range_max r;
+	  int_range<2> r;
 	  int_range_max path_range;
 
 	  if (find_range_for_lhs (predicate_path, lhs, path_range)
@@ -671,9 +689,9 @@ evaluate_control_stmt_using_entry_checks (gimple *stmt,
 	    continue;
 
 	  int_range_max r;
-
-	  ranger->gori ().outgoing_edge_range_p (r, e, idx,
-						 *get_global_range_query ());
+	  if (!ranger->gori ().outgoing_edge_range_p (r, e, idx,
+						      *get_global_range_query ()))
+	    continue;
 	  r.intersect (path_range);
 	  if (r.undefined_p ())
 	    ignored_edges->add (e);


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-05-18 12:23 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-05-18 12:23 [gcc/devel/loop-unswitch-support-switches] This fixes the execute FAIL of gfortran.fortran-torture/execute/forall_7.f90 Richard Biener

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).