public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r13-2314] Avoid fatal fails in predicate::init_from_control_deps
@ 2022-08-31 14:26 Richard Biener
  0 siblings, 0 replies; only message in thread
From: Richard Biener @ 2022-08-31 14:26 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:a8ebd27d0ab69b08fd6e335bbb48a73a50202586

commit r13-2314-ga8ebd27d0ab69b08fd6e335bbb48a73a50202586
Author: Richard Biener <rguenther@suse.de>
Date:   Wed Aug 31 15:25:32 2022 +0200

    Avoid fatal fails in predicate::init_from_control_deps
    
    When processing USE predicates we can drop from the AND chain,
    when procsssing DEF predicates we can drop from the OR chain.  Do
    that instead of giving up completely.  This also removes cases
    that should never trigger.
    
            * gimple-predicate-analysis.cc (predicate::init_from_control_deps):
            Assert the guard_bb isn't empty and has more than one successor.
            Drop appropriate parts of the predicate when an edge fails to
            register a predicate.
            (predicate::dump): Dump empty predicate as TRUE.

Diff:
---
 gcc/gimple-predicate-analysis.cc | 119 ++++++++++++++++++---------------------
 1 file changed, 55 insertions(+), 64 deletions(-)

diff --git a/gcc/gimple-predicate-analysis.cc b/gcc/gimple-predicate-analysis.cc
index 58eade433dc..eb1e11cead8 100644
--- a/gcc/gimple-predicate-analysis.cc
+++ b/gcc/gimple-predicate-analysis.cc
@@ -1671,7 +1671,6 @@ predicate::init_from_control_deps (const vec<edge> *dep_chains,
 {
   gcc_assert (is_empty ());
 
-  bool has_valid_pred = false;
   if (num_chains == 0)
     return;
 
@@ -1689,27 +1688,16 @@ predicate::init_from_control_deps (const vec<edge> *dep_chains,
 	 of the predicates.  */
       const vec<edge> &path = dep_chains[i];
 
-      has_valid_pred = false;
+      bool has_valid_pred = false;
       /* The chain of predicates guarding the definition along this path.  */
       pred_chain t_chain{ };
       for (unsigned j = 0; j < path.length (); j++)
 	{
 	  edge e = path[j];
 	  basic_block guard_bb = e->src;
-	  /* Ignore empty forwarder blocks.  */
-	  if (empty_block_p (guard_bb) && single_succ_p (guard_bb))
-	    continue;
 
-	  /* An empty basic block here is likely a PHI, and is not one
-	     of the cases we handle below.  */
-	  gimple_stmt_iterator gsi = gsi_last_bb (guard_bb);
-	  if (gsi_end_p (gsi))
-	    {
-	      has_valid_pred = false;
-	      break;
-	    }
-	  /* Get the conditional controlling the bb exit edge.  */
-	  gimple *cond_stmt = gsi_stmt (gsi);
+	  gcc_assert (!empty_block_p (guard_bb) && !single_succ_p (guard_bb));
+
 	  /* Skip this edge if it is bypassing an abort - when the
 	     condition is not satisfied we are neither reaching the
 	     definition nor the use so it isn't meaningful.  Note if
@@ -1730,8 +1718,13 @@ predicate::init_from_control_deps (const vec<edge> *dep_chains,
 		    }
 		}
 	      if (skip)
-		continue;
+		{
+		  has_valid_pred = true;
+		  continue;
+		}
 	    }
+	  /* Get the conditional controlling the bb exit edge.  */
+	  gimple *cond_stmt = last_stmt (guard_bb);
 	  if (gimple_code (cond_stmt) == GIMPLE_COND)
 	    {
 	      /* The true edge corresponds to the uninteresting condition.
@@ -1757,37 +1750,29 @@ predicate::init_from_control_deps (const vec<edge> *dep_chains,
 	    }
 	  else if (gswitch *gs = dyn_cast<gswitch *> (cond_stmt))
 	    {
-	      /* Avoid quadratic behavior.  */
-	      if (gimple_switch_num_labels (gs) > MAX_SWITCH_CASES)
-		{
-		  has_valid_pred = false;
-		  break;
-		}
-	      /* Find the case label.  */
 	      tree l = NULL_TREE;
-	      unsigned idx;
-	      for (idx = 0; idx < gimple_switch_num_labels (gs); ++idx)
-		{
-		  tree tl = gimple_switch_label (gs, idx);
-		  if (e->dest == label_to_block (cfun, CASE_LABEL (tl)))
-		    {
-		      if (!l)
-			l = tl;
-		      else
-			{
-			  l = NULL_TREE;
-			  break;
-			}
-		    }
-		}
+	      /* Find the case label, but avoid quadratic behavior.  */
+	      if (gimple_switch_num_labels (gs) <= MAX_SWITCH_CASES)
+		for (unsigned idx = 0;
+		     idx < gimple_switch_num_labels (gs); ++idx)
+		  {
+		    tree tl = gimple_switch_label (gs, idx);
+		    if (e->dest == label_to_block (cfun, CASE_LABEL (tl)))
+		      {
+			if (!l)
+			  l = tl;
+			else
+			  {
+			    l = NULL_TREE;
+			    break;
+			  }
+		      }
+		  }
 	      /* If more than one label reaches this block or the case
 		 label doesn't have a contiguous range of values (like the
 		 default one) fail.  */
 	      if (!l || !CASE_LOW (l))
-		{
-		  has_valid_pred = false;
-		  break;
-		}
+		has_valid_pred = false;
 	      else if (!CASE_HIGH (l)
 		      || operand_equal_p (CASE_LOW (l), CASE_HIGH (l)))
 		{
@@ -1824,31 +1809,37 @@ predicate::init_from_control_deps (const vec<edge> *dep_chains,
 	       both the USE (valid) and DEF (questionable) case.  */
 	    has_valid_pred = true;
 	  else
-	    {
-	      has_valid_pred = false;
-	      break;
-	    }
+	    has_valid_pred = false;
+
+	  /* For USE predicates we can drop components of the
+	     AND chain.  */
+	  if (!has_valid_pred && !is_use)
+	    break;
 	}
 
-      if (!has_valid_pred)
-	break;
-      else
-	m_preds.quick_push (t_chain);
-    }
+      /* For DEF predicates we have to drop components of the OR chain
+	 on failure.  */
+      if (!has_valid_pred && !is_use)
+	{
+	  t_chain.release ();
+	  continue;
+	}
 
-  if (has_valid_pred)
-    {
-      gcc_assert (m_preds.length () != 0);
-      if (DEBUG_PREDICATE_ANALYZER && dump_file)
-	dump (NULL, "");
-    }
-  else
-    {
-      if (DEBUG_PREDICATE_ANALYZER && dump_file)
-	fprintf (dump_file, "\tFAILED\n");
-      /* Clear M_PREDS to indicate failure.  */
-      m_preds.release ();
+      /* When we add || 1 simply prune the chain and return.  */
+      if (t_chain.is_empty ())
+	{
+	  t_chain.release ();
+	  for (auto chain : m_preds)
+	    chain.release ();
+	  m_preds.truncate (0);
+	  break;
+	}
+
+      m_preds.quick_push (t_chain);
     }
+
+  if (DEBUG_PREDICATE_ANALYZER && dump_file)
+    dump (NULL, "");
 }
 
 /* Store a PRED in *THIS.  */
@@ -1877,7 +1868,7 @@ predicate::dump (gimple *stmt, const char *msg) const
   unsigned np = m_preds.length ();
   if (np == 0)
     {
-      fprintf (dump_file, "\t(empty)\n");
+      fprintf (dump_file, "\tTRUE (empty)\n");
       return;
     }

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

only message in thread, other threads:[~2022-08-31 14:26 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-08-31 14:26 [gcc r13-2314] Avoid fatal fails in predicate::init_from_control_deps 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).