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]

[committed] [PR middle-end/87813] EVRP vs global range data for warning passes


So as discussed in BZ87813, the evrp range analyzer currently reflects
any globally valid ranges it finds into the global range information we
attach to SSA_NAMEs.

That is usually a good thing, except when the analyzer is called from a
warning pass.  Enabling/disabling of warnings should not affect code
generation.

This patch allows clients to indicate if they want the range analyzer to
reflect globally discovered ranges into the SSA_NAME.  The optimization
passes obviously want that behavior.  The sprintf warning pass does not.
 As expected, it was just a matter of adding a flag to the class and
testing it in a few places.

There was a solitary test, identified in the BZ, that turned out to be
problematical.

builtins/strnlen.c at -Og was relying on the range analyzer instance in
the sprintf warning pass to set a global range.  That in turn allowed
the call to strnlen to be eliminated.  With this patch that no longer
occurs and we call strnlen.  strnlen in this test is actually wrapped so
that it aborts if OPTIMIZE is defined.

I didn't see any reasonable way to preserve the optimization at -Og
given we don't run VRP, DOM, EVRP, etc.  So I've just added a strnlen.x
file to filter out the -Og run of the strnlen test.

Bootstrapped and regression tested on x86_64-linux-gnu.  Installing on
the trunk momentarily.

jeff
	* gimple-ssa-evrp-analyze.h (class evrp_range_analyzer): Add
	m_update_global_ranges member.  Add corresponding argument to ctor.
	* gimple-ssa-evrp-analyze.c
	(evrp_range_analyzer::evrp_range_analyzer): Add new argument and
	initialize m_update_global_ranges.
	(evrp_range_analyzer::set_ssa_range_info): Assert that we are
	updating global ranges.
	(evrp_range_analyzer::record_ranges_from_incoming_edge): Only
	update global ranges if explicitly requested.
	(evrp_range_analyzer::record_ranges_from_phis): Similarly.
	(evrp_range_analyzer::record_ranges_from_stmt): Similarly.
	* gimple-ssa-evrp.c (evrp_dom_walker): Pass new argument to
	evrp_range_analyzer ctor.
	* gimple-ssa-sprintf.c (sprintf_dom_walker): Similarly.
	* tree-ssa-dom.c (dom_opt_dom_walker): Similarly.

	* gcc.c-torture/builtins/strnlen.x: New file to filter -Og from
	options to test.

diff --git a/gcc/gimple-ssa-evrp-analyze.c b/gcc/gimple-ssa-evrp-analyze.c
index 220dde093b5..3efaca1a994 100644
--- a/gcc/gimple-ssa-evrp-analyze.c
+++ b/gcc/gimple-ssa-evrp-analyze.c
@@ -42,7 +42,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "vr-values.h"
 #include "gimple-ssa-evrp-analyze.h"
 
-evrp_range_analyzer::evrp_range_analyzer () : stack (10)
+evrp_range_analyzer::evrp_range_analyzer (bool update_global_ranges)
+  : stack (10), m_update_global_ranges (update_global_ranges)
 {
   edge e;
   edge_iterator ei;
@@ -107,6 +108,8 @@ evrp_range_analyzer::try_find_new_range (tree name,
 void
 evrp_range_analyzer::set_ssa_range_info (tree lhs, value_range *vr)
 {
+  gcc_assert (m_update_global_ranges);
+
   /* Set the SSA with the value range.  */
   if (INTEGRAL_TYPE_P (TREE_TYPE (lhs)))
     {
@@ -213,6 +216,7 @@ evrp_range_analyzer::record_ranges_from_incoming_edge (basic_block bb)
 		continue;
 	      push_value_range (vrs[i].first, vrs[i].second);
 	      if (is_fallthru
+		  && m_update_global_ranges
 		  && all_uses_feed_or_dominated_by_stmt (vrs[i].first, stmt))
 		{
 		  set_ssa_range_info (vrs[i].first, vrs[i].second);
@@ -267,7 +271,8 @@ evrp_range_analyzer::record_ranges_from_phis (basic_block bb)
       vr_values->update_value_range (lhs, &vr_result);
 
       /* Set the SSA with the value range.  */
-      set_ssa_range_info (lhs, &vr_result);
+      if (m_update_global_ranges)
+	set_ssa_range_info (lhs, &vr_result);
     }
 }
 
@@ -309,7 +314,8 @@ evrp_range_analyzer::record_ranges_from_stmt (gimple *stmt, bool temporary)
 	      /* Case one.  We can just update the underlying range
 		 information as well as the global information.  */
 	      vr_values->update_value_range (output, &vr);
-	      set_ssa_range_info (output, &vr);
+	      if (m_update_global_ranges)
+		set_ssa_range_info (output, &vr);
 	    }
 	  else
 	    {
diff --git a/gcc/gimple-ssa-evrp-analyze.h b/gcc/gimple-ssa-evrp-analyze.h
index 0d2b4188b8c..01942f06362 100644
--- a/gcc/gimple-ssa-evrp-analyze.h
+++ b/gcc/gimple-ssa-evrp-analyze.h
@@ -23,7 +23,7 @@ along with GCC; see the file COPYING3.  If not see
 class evrp_range_analyzer
 {
  public:
-  evrp_range_analyzer (void);
+  evrp_range_analyzer (bool update_global_ranges);
   ~evrp_range_analyzer (void)
   {
     delete vr_values;
@@ -70,6 +70,9 @@ class evrp_range_analyzer
 
   /* STACK holds the old VR.  */
   auto_vec<std::pair <tree, value_range*> > stack;
+
+  /* True if we are updating global ranges, false otherwise.  */
+  bool m_update_global_ranges;
 };
 
 #endif /* GCC_GIMPLE_SSA_EVRP_ANALYZE_H */
diff --git a/gcc/gimple-ssa-evrp.c b/gcc/gimple-ssa-evrp.c
index deb45cdb9f6..9900980aecf 100644
--- a/gcc/gimple-ssa-evrp.c
+++ b/gcc/gimple-ssa-evrp.c
@@ -70,6 +70,7 @@ class evrp_dom_walker : public dom_walker
 public:
   evrp_dom_walker ()
     : dom_walker (CDI_DOMINATORS),
+      evrp_range_analyzer (true),
       evrp_folder (evrp_range_analyzer.get_vr_values ())
     {
       need_eh_cleanup = BITMAP_ALLOC (NULL);
diff --git a/gcc/gimple-ssa-sprintf.c b/gcc/gimple-ssa-sprintf.c
index 456a7d40011..00485d9a073 100644
--- a/gcc/gimple-ssa-sprintf.c
+++ b/gcc/gimple-ssa-sprintf.c
@@ -121,7 +121,9 @@ struct format_result;
 class sprintf_dom_walker : public dom_walker
 {
  public:
-  sprintf_dom_walker () : dom_walker (CDI_DOMINATORS) {}
+  sprintf_dom_walker ()
+    : dom_walker (CDI_DOMINATORS),
+      evrp_range_analyzer (false) {}
   ~sprintf_dom_walker () {}
 
   edge before_dom_children (basic_block) FINAL OVERRIDE;
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/strnlen.x b/gcc/testsuite/gcc.c-torture/execute/builtins/strnlen.x
new file mode 100644
index 00000000000..9ee8a52baab
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/strnlen.x
@@ -0,0 +1,14 @@
+# At -Og no pass records the global range information
+# necessary to optimize the strnlen calls down to
+# a constant.  The framework assumes that the test
+# will never call strnlen when the optimizer is
+# enabled.  So we filter out the -Og run here.
+
+set torture_eval_before_compile {
+  if {[string match {*-Og*} "$option"]} {
+    continue
+  }
+}
+
+return 0
+
diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c
index ce840488403..e3e009a0e63 100644
--- a/gcc/tree-ssa-dom.c
+++ b/gcc/tree-ssa-dom.c
@@ -578,6 +578,7 @@ public:
     : dom_walker (direction, REACHABLE_BLOCKS),
       m_const_and_copies (const_and_copies),
       m_avail_exprs_stack (avail_exprs_stack),
+      evrp_range_analyzer (true),
       m_dummy_cond (dummy_cond) { }
 
   virtual edge before_dom_children (basic_block);

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