[PR tree-optimization/71550 ] Drop cached loop iteration information as needed due to threading

Jeff Law law@redhat.com
Mon Oct 3 19:29:00 GMT 2016


As noted in BZs 71550 and 71403 (and possibly others, I'm going to have 
to do some searching).  Jump threading can sometimes fuse two loops, in 
the process creating an irreducible loop and invalidating the cached 
iteration information.

The no longer valid cached iteration information can result in unrolling 
doing some unpleasant transformations and generating incorrect code.

I believe it was Jan that pointed me at vect_free_loop_info_assumption. 
It's somewhat poorly named, but does exactly what we need.

I look at renaming it and putting it elsewhere, but it seems to straddle 
scev, vectorization, the generic loop infrastructure, etc.  So I just 
left it as-is.

Bootstrapped and regression tested on x86_64-linux-gnu.  Also tested by 
reverting the changes on the trunk which make 71550 latent, adding this 
patch and verifying 71550 works correctly.

Installed on the trunk.

Jeff
-------------- next part --------------
commit 88cd085912752f971aa2e6aee2ed2d05dd2c5ca7
Author: law <law@138bc75d-0d04-0410-961f-82ee72b054a4>
Date:   Mon Oct 3 19:28:24 2016 +0000

    	PR tree-optimization/71550
    	PR tree-optimization/71403
    	* tree-ssa-threadbackward.c: Include tree-vectorizer.h
    	(profitable_jump_thread_path): Also return boolean indicating if
    	the realized path will create an irreducible loop.
    	Remove loop depth tests from 71403.
    	(fsm_find_control_statement_thread_paths): Remove loop depth tests
    	from 71403.  If threading will create an irreducible loop, then
    	throw away loop iteration and related information.
    
    	PR tree-optimization/71550
    	PR tree-optimization/71403
    	* gcc.c-torture/execute/pr71550.c: New test.
    
    git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@240727 138bc75d-0d04-0410-961f-82ee72b054a4

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 7f4e311..ba56e63 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,15 @@
+2016-10-03  Jeff Law  <law@redhat.com>
+
+	PR tree-optimization/71550
+	PR tree-optimization/71403
+	* tree-ssa-threadbackward.c: Include tree-vectorizer.h
+	(profitable_jump_thread_path): Also return boolean indicating if
+	the realized path will create an irreducible loop.
+	Remove loop depth tests from 71403.
+	(fsm_find_control_statement_thread_paths): Remove loop depth tests
+	from 71403.  If threading will create an irreducible loop, then
+	throw away loop iteration and related information.
+
 2016-10-03  Uros Bizjak  <ubizjak@gmail.com>
 
 	* configure.ac (strict_warn): Merge -Wmissing-format-attribute and
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index d0ed6a6..9e62464 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2016-09-26  Jeff Law  <law@redhat.com>
+
+	PR tree-optimization/71550
+	PR tree-optimization/71403
+	* gcc.c-torture/execute/pr71550.c: New test.
+
 2016-10-03  Senthil Kumar Selvaraj  <senthil_kumar.selvaraj@atmel.com>
 
 	* gcc.target/avr/torture/builtins-error.c: Add -ffat-lto-objects
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr71550.c b/gcc/testsuite/gcc.c-torture/execute/pr71550.c
new file mode 100644
index 0000000..8d1ecda
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr71550.c
@@ -0,0 +1,26 @@
+
+extern void exit (int);
+
+int a = 3, b, c, f, g, h;
+unsigned d;
+char *e;
+
+int
+main ()
+{
+  for (; a; a--)
+    {
+      int i;
+      if (h && i)
+	__builtin_printf ("%d%d", c, f);
+      i = 0;
+      for (; i < 2; i++)
+	if (g)
+	  for (; d < 10; d++)
+	    b = *e;
+      i = 0;
+      for (; i < 1; i++)
+	;
+    }
+  exit (0);
+}
diff --git a/gcc/tree-ssa-threadbackward.c b/gcc/tree-ssa-threadbackward.c
index 6b522ad..fd7d855 100644
--- a/gcc/tree-ssa-threadbackward.c
+++ b/gcc/tree-ssa-threadbackward.c
@@ -36,6 +36,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimple-ssa.h"
 #include "tree-phinodes.h"
 #include "tree-inline.h"
+#include "tree-vectorizer.h"
 
 static int max_threaded_paths;
 
@@ -110,7 +111,8 @@ fsm_find_thread_path (basic_block start_bb, basic_block end_bb,
 
 static edge
 profitable_jump_thread_path (vec<basic_block, va_gc> *&path,
-			     basic_block bbi, tree name, tree arg, bool speed_p)
+			     basic_block bbi, tree name, tree arg, bool speed_p,
+			     bool *creates_irreducible_loop)
 {
   /* Note BBI is not in the path yet, hence the +1 in the test below
      to make sure BBI is accounted for in the path length test.  */
@@ -296,12 +298,12 @@ profitable_jump_thread_path (vec<basic_block, va_gc> *&path,
       return NULL;
     }
 
-  bool creates_irreducible_loop = false;
+  *creates_irreducible_loop = false;
   if (threaded_through_latch
       && loop == taken_edge->dest->loop_father
       && (determine_bb_domination_status (loop, taken_edge->dest)
 	  == DOMST_NONDOMINATING))
-    creates_irreducible_loop = true;
+    *creates_irreducible_loop = true;
 
   if (path_crosses_loops)
     {
@@ -343,7 +345,7 @@ profitable_jump_thread_path (vec<basic_block, va_gc> *&path,
      the path -- in that case there's little the traditional loop
      optimizer would have done anyway, so an irreducible loop is not
      so bad.  */
-  if (!threaded_multiway_branch && creates_irreducible_loop
+  if (!threaded_multiway_branch && *creates_irreducible_loop
       && (n_insns * PARAM_VALUE (PARAM_FSM_SCALE_PATH_STMTS)
 	  > path_length * PARAM_VALUE (PARAM_FSM_SCALE_PATH_BLOCKS)))
 
@@ -479,9 +481,6 @@ fsm_find_control_statement_thread_paths (tree name,
       seen_loop_phi = true;
     }
 
-  if (bb_loop_depth (last_bb_in_path) > bb_loop_depth (var_bb))
-    return;
-
   /* Following the chain of SSA_NAME definitions, we jumped from a definition in
      LAST_BB_IN_PATH to a definition in VAR_BB.  When these basic blocks are
      different, append to PATH the blocks from LAST_BB_IN_PATH to VAR_BB.  */
@@ -528,9 +527,7 @@ fsm_find_control_statement_thread_paths (tree name,
 	 NEXT_PATH.  Don't add them here to avoid pollution.  */
       for (unsigned int i = 0; i < next_path->length () - 1; i++)
 	{
-	  if (visited_bbs->contains ((*next_path)[i])
-	      || (bb_loop_depth (last_bb_in_path)
-		  > bb_loop_depth ((*next_path)[i])))
+	  if (visited_bbs->contains ((*next_path)[i]))
 	    {
 	      vec_free (next_path);
 	      return;
@@ -580,14 +577,16 @@ fsm_find_control_statement_thread_paths (tree name,
 
 	  /* If this is a profitable jump thread path, then convert it
 	     into the canonical form and register it.  */
+	  bool irreducible = false;
 	  edge taken_edge = profitable_jump_thread_path (path, bbi, name, arg,
-							 speed_p);
+							 speed_p, &irreducible);
 	  if (taken_edge)
 	    {
-	      if (bb_loop_depth (taken_edge->src)
-		  >= bb_loop_depth (taken_edge->dest))
-		convert_and_register_jump_thread_path (path, taken_edge);
+	      convert_and_register_jump_thread_path (path, taken_edge);
 	      path->pop ();
+
+	      if (irreducible)
+		vect_free_loop_info_assumptions ((*path)[0]->loop_father);
 	    }
 	}
     }
@@ -606,14 +605,17 @@ fsm_find_control_statement_thread_paths (tree name,
 	     block at this point.  So we can just pop it.  */
 	  path->pop ();
 
+	  bool irreducible = false;
 	  edge taken_edge = profitable_jump_thread_path (path, var_bb,
-						         name, arg, speed_p);
+						         name, arg, speed_p,
+							 &irreducible);
 	  if (taken_edge)
 	    {
-	      if (bb_loop_depth (taken_edge->src)
-		  >= bb_loop_depth (taken_edge->dest))
-		convert_and_register_jump_thread_path (path, taken_edge);
+	      convert_and_register_jump_thread_path (path, taken_edge);
 	      path->pop ();
+
+	      if (irreducible)
+		vect_free_loop_info_assumptions ((*path)[0]->loop_father);
 	    }
 
 	  /* And put the current block back onto the path so that the


More information about the Gcc-patches mailing list