verify SCEV cache for stale entries

Message ID nycvar.YFH.7.76.2007291239030.9963@zhemvz.fhfr.qr
State New
Headers show
Series
  • verify SCEV cache for stale entries
Related show

Commit Message

Richard Biener July 29, 2020, 10:39 a.m.
This adds verification for the SCEV cache to avoid stale entries
that when picked up will lead to ICEs or other surprises.

Bootstrapped / tested on x86_64-unknown-linux-gnu with the two
previous fixes.

Posted for reference and archival purposes, I'm not going to push
this at this point.

2020-07-29  Richard Biener  <rguenther@suse.de>

	* passes.c (execute_function_todo): Call verify_scev_cache
	if it is initialized.
	* tree-scalar-evolution.h (verify_scev_cache): Declare.
	* tree-scalar-evolution.c (verify_scev_cache_r): New.
	(verify_scev_cache): Likewise.
---
 gcc/passes.c                | 11 ++++++++---
 gcc/tree-scalar-evolution.c | 29 +++++++++++++++++++++++++++++
 gcc/tree-scalar-evolution.h |  1 +
 3 files changed, 38 insertions(+), 3 deletions(-)

-- 
2.26.2

Patch

diff --git a/gcc/passes.c b/gcc/passes.c
index a5da9a46f4e..c3c3a086236 100644
--- a/gcc/passes.c
+++ b/gcc/passes.c
@@ -63,6 +63,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "diagnostic-core.h" /* for fnotice */
 #include "stringpool.h"
 #include "attribs.h"
+#include "tree-scalar-evolution.h" /* for verify_scev_cache.  */
 
 using namespace gcc;
 
@@ -1994,9 +1995,13 @@  execute_function_todo (function *fn, void *data)
 		verify_gimple_in_seq (gimple_body (cfun->decl));
 	    }
 	  if (cfun->curr_properties & PROP_ssa)
-	    /* IPA passes leave stmts to be fixed up, so make sure to
-	       not verify SSA operands whose verifier will choke on that.  */
-	    verify_ssa (true, !from_ipa_pass);
+	    {
+	      /* IPA passes leave stmts to be fixed up, so make sure to
+		 not verify SSA operands whose verifier will choke on that.  */
+	      verify_ssa (true, !from_ipa_pass);
+	      if (scev_initialized_p ())
+		verify_scev_cache ();
+	    }
 	  /* IPA passes leave basic-blocks unsplit, so make sure to
 	     not trip on that.  */
 	  if ((cfun->curr_properties & PROP_cfg)
diff --git a/gcc/tree-scalar-evolution.c b/gcc/tree-scalar-evolution.c
index edab778277b..9645fed980c 100644
--- a/gcc/tree-scalar-evolution.c
+++ b/gcc/tree-scalar-evolution.c
@@ -284,6 +284,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "tree-into-ssa.h"
 #include "builtins.h"
 #include "case-cfn-macros.h"
+#include "diagnostic.h"
 
 static tree analyze_scalar_evolution_1 (class loop *, tree);
 static tree analyze_scalar_evolution_for_address_of (class loop *loop,
@@ -3025,6 +3026,34 @@  scev_reset (void)
     }
 }
 
+/* CHREC walker for verify_scev_cache.  */
+
+static tree
+verify_scev_cache_r (tree *tp, int *walk_subtrees, void *)
+{
+  if (TREE_CODE (*tp) == SSA_NAME
+      && SSA_NAME_IN_FREE_LIST (*tp))
+    internal_error ("stale SCEV hash table entries");
+  if (!EXPR_P (*tp))
+    *walk_subtrees = 0;
+  return NULL_TREE;
+}
+
+/* Verify the SCEV cache has no stale entries.  */
+
+void
+verify_scev_cache ()
+{
+  for (auto i = scalar_evolution_info->begin ();
+       i != scalar_evolution_info->end (); ++i)
+    {
+      if ((*i)->name_version >= num_ssa_names
+	  || ! ssa_name ((*i)->name_version))
+	internal_error ("stale SCEV hash table entries");
+      walk_tree (&(*i)->chrec, verify_scev_cache_r, NULL, NULL);
+    }
+}
+
 /* Return true if the IV calculation in TYPE can overflow based on the knowledge
    of the upper bound on the number of iterations of LOOP, the BASE and STEP
    of IV.
diff --git a/gcc/tree-scalar-evolution.h b/gcc/tree-scalar-evolution.h
index e2fbfb55bd0..d0c578708ac 100644
--- a/gcc/tree-scalar-evolution.h
+++ b/gcc/tree-scalar-evolution.h
@@ -42,6 +42,7 @@  extern bool simple_iv (class loop *, class loop *, tree, struct affine_iv *,
 		       bool);
 extern bool iv_can_overflow_p (class loop *, tree, tree, tree);
 extern tree compute_overall_effect_of_inner_loop (class loop *, tree);
+extern void verify_scev_cache ();
 
 /* Returns the basic block preceding LOOP, or the CFG entry block when
    the loop is function's body.  */