diff gcc/tree-ssa-threadedge.c @ 131:84e7813d76e9

gcc-8.2
author mir3636
date Thu, 25 Oct 2018 07:37:49 +0900
parents 04ced10e8804
children 1830386684a0
line wrap: on
line diff
--- a/gcc/tree-ssa-threadedge.c	Fri Oct 27 22:46:09 2017 +0900
+++ b/gcc/tree-ssa-threadedge.c	Thu Oct 25 07:37:49 2018 +0900
@@ -1,5 +1,5 @@
 /* SSA Jump Threading
-   Copyright (C) 2005-2017 Free Software Foundation, Inc.
+   Copyright (C) 2005-2018 Free Software Foundation, Inc.
    Contributed by Jeff Law  <law@redhat.com>
 
 This file is part of GCC.
@@ -37,6 +37,9 @@
 #include "tree-ssa-dom.h"
 #include "gimple-fold.h"
 #include "cfganal.h"
+#include "alloc-pool.h"
+#include "vr-values.h"
+#include "gimple-ssa-evrp-analyze.h"
 
 /* To avoid code explosion due to jump threading, we limit the
    number of statements we are going to copy.  This variable
@@ -114,17 +117,16 @@
 }
 
 /* Record temporary equivalences created by PHIs at the target of the
-   edge E.  Record unwind information for the equivalences onto STACK.
+   edge E.  Record unwind information for the equivalences into
+   CONST_AND_COPIES and EVRP_RANGE_DATA.
 
    If a PHI which prevents threading is encountered, then return FALSE
-   indicating we should not thread this edge, else return TRUE.
-
-   If SRC_MAP/DST_MAP exist, then mark the source and destination SSA_NAMEs
-   of any equivalences recorded.  We use this to make invalidation after
-   traversing back edges less painful.  */
+   indicating we should not thread this edge, else return TRUE.  */
 
 static bool
-record_temporary_equivalences_from_phis (edge e, const_and_copies *const_and_copies)
+record_temporary_equivalences_from_phis (edge e,
+    const_and_copies *const_and_copies,
+    evrp_range_analyzer *evrp_range_analyzer)
 {
   gphi_iterator gsi;
 
@@ -152,6 +154,40 @@
 	stmt_count++;
 
       const_and_copies->record_const_or_copy (dst, src);
+
+      /* Also update the value range associated with DST, using
+	 the range from SRC.
+
+	 Note that even if SRC is a constant we need to set a suitable
+	 output range so that VR_UNDEFINED ranges do not leak through.  */
+      if (evrp_range_analyzer)
+	{
+	  /* Get an empty new VR we can pass to update_value_range and save
+	     away in the VR stack.  */
+	  vr_values *vr_values = evrp_range_analyzer->get_vr_values ();
+	  value_range *new_vr = vr_values->allocate_value_range ();
+	  *new_vr = value_range ();
+
+	  /* There are three cases to consider:
+
+	       First if SRC is an SSA_NAME, then we can copy the value
+	       range from SRC into NEW_VR.
+
+	       Second if SRC is an INTEGER_CST, then we can just wet
+	       NEW_VR to a singleton range.
+
+	       Otherwise set NEW_VR to varying.  This may be overly
+	       conservative.  */
+	  if (TREE_CODE (src) == SSA_NAME)
+	    new_vr->deep_copy (vr_values->get_value_range (src));
+	  else if (TREE_CODE (src) == INTEGER_CST)
+	    set_value_range_to_value (new_vr, src,  NULL);
+	  else
+	    set_value_range_to_varying (new_vr);
+
+	  /* This is a temporary range for DST, so push it.  */
+	  evrp_range_analyzer->push_value_range (dst, new_vr);
+	}
     }
   return true;
 }
@@ -191,6 +227,7 @@
 record_temporary_equivalences_from_stmts_at_dest (edge e,
     const_and_copies *const_and_copies,
     avail_exprs_stack *avail_exprs_stack,
+    evrp_range_analyzer *evrp_range_analyzer,
     pfn_simplify simplify)
 {
   gimple *stmt = NULL;
@@ -233,7 +270,27 @@
 	 expansion, then do not thread through this block.  */
       stmt_count++;
       if (stmt_count > max_stmt_count)
-	return NULL;
+	{
+	  /* If any of the stmts in the PATH's dests are going to be
+	     killed due to threading, grow the max count
+	     accordingly.  */
+	  if (max_stmt_count
+	      == PARAM_VALUE (PARAM_MAX_JUMP_THREAD_DUPLICATION_STMTS))
+	    {
+	      max_stmt_count += estimate_threading_killed_stmts (e->dest);
+	      if (dump_file)
+		fprintf (dump_file, "threading bb %i up to %i stmts\n",
+			 e->dest->index, max_stmt_count);
+	    }
+	  /* If we're still past the limit, we're done.  */
+	  if (stmt_count > max_stmt_count)
+	    return NULL;
+	}
+
+      /* These are temporary ranges, do nto reflect them back into
+	 the global range data.  */
+      if (evrp_range_analyzer)
+	evrp_range_analyzer->record_ranges_from_stmt (stmt, true);
 
       /* If this is not a statement that sets an SSA_NAME to a new
 	 value, then do not try to simplify this statement as it will
@@ -692,7 +749,7 @@
 void
 propagate_threaded_block_debug_into (basic_block dest, basic_block src)
 {
-  if (!MAY_HAVE_DEBUG_STMTS)
+  if (!MAY_HAVE_DEBUG_BIND_STMTS)
     return;
 
   if (!single_pred_p (dest))
@@ -712,6 +769,8 @@
       gimple *stmt = gsi_stmt (si);
       if (!is_gimple_debug (stmt))
 	break;
+      if (gimple_debug_nonbind_marker_p (stmt))
+	continue;
       i++;
     }
 
@@ -739,6 +798,8 @@
 	var = gimple_debug_bind_get_var (stmt);
       else if (gimple_debug_source_bind_p (stmt))
 	var = gimple_debug_source_bind_get_var (stmt);
+      else if (gimple_debug_nonbind_marker_p (stmt))
+	continue;
       else
 	gcc_unreachable ();
 
@@ -766,17 +827,23 @@
 	    var = gimple_debug_bind_get_var (stmt);
 	  else if (gimple_debug_source_bind_p (stmt))
 	    var = gimple_debug_source_bind_get_var (stmt);
+	  else if (gimple_debug_nonbind_marker_p (stmt))
+	    continue;
 	  else
 	    gcc_unreachable ();
 
-	  /* Discard debug bind overlaps.  ??? Unlike stmts from src,
+	  /* Discard debug bind overlaps.  Unlike stmts from src,
 	     copied into a new block that will precede BB, debug bind
 	     stmts in bypassed BBs may actually be discarded if
-	     they're overwritten by subsequent debug bind stmts, which
-	     might be a problem once we introduce stmt frontier notes
-	     or somesuch.  Adding `&& bb == src' to the condition
-	     below will preserve all potentially relevant debug
-	     notes.  */
+	     they're overwritten by subsequent debug bind stmts.  We
+	     want to copy binds for all modified variables, so that we
+	     retain a bind to the shared def if there is one, or to a
+	     newly introduced PHI node if there is one.  Our bind will
+	     end up reset if the value is dead, but that implies the
+	     variable couldn't have survived, so it's fine.  We are
+	     not actually running the code that performed the binds at
+	     this point, we're just adding binds so that they survive
+	     the new confluence, so markers should not be copied.  */
 	  if (vars && vars->add (var))
 	    continue;
 	  else if (!vars)
@@ -787,8 +854,7 @@
 		  break;
 	      if (i >= 0)
 		continue;
-
-	      if (fewvars.length () < (unsigned) alloc_count)
+	      else if (fewvars.length () < (unsigned) alloc_count)
 		fewvars.quick_push (var);
 	      else
 		{
@@ -911,11 +977,12 @@
 	  || TREE_CODE (cond) == CASE_LABEL_EXPR))
     {
       if (TREE_CODE (cond) == CASE_LABEL_EXPR)
-	taken_edge = find_edge (bb, label_to_block (CASE_LABEL (cond)));
+	taken_edge = find_edge (bb, label_to_block (cfun, CASE_LABEL (cond)));
       else
 	taken_edge = find_taken_edge (bb, cond);
 
-      if ((taken_edge->flags & EDGE_DFS_BACK) != 0)
+      if (!taken_edge
+	  || (taken_edge->flags & EDGE_DFS_BACK) != 0)
 	return false;
 
       if (bitmap_bit_p (visited, taken_edge->dest->index))
@@ -972,6 +1039,7 @@
 			     gcond *dummy_cond,
 			     const_and_copies *const_and_copies,
 			     avail_exprs_stack *avail_exprs_stack,
+			     evrp_range_analyzer *evrp_range_analyzer,
 			     pfn_simplify simplify,
 			     vec<jump_thread_edge *> *path,
 			     bitmap visited)
@@ -983,7 +1051,8 @@
      Note that if we found a PHI that made the block non-threadable, then
      we need to bubble that up to our caller in the same manner we do
      when we prematurely stop processing statements below.  */
-  if (!record_temporary_equivalences_from_phis (e, const_and_copies))
+  if (!record_temporary_equivalences_from_phis (e, const_and_copies,
+					        evrp_range_analyzer))
     return -1;
 
   /* Now walk each statement recording any context sensitive
@@ -991,6 +1060,7 @@
   gimple *stmt
     = record_temporary_equivalences_from_stmts_at_dest (e, const_and_copies,
 							avail_exprs_stack,
+							evrp_range_analyzer,
 							simplify);
 
   /* There's two reasons STMT might be null, and distinguishing
@@ -1040,7 +1110,7 @@
 	  edge taken_edge;
 	  if (TREE_CODE (cond) == CASE_LABEL_EXPR)
 	    taken_edge = find_edge (e->dest,
-				    label_to_block (CASE_LABEL (cond)));
+				    label_to_block (cfun, CASE_LABEL (cond)));
 	  else
 	    taken_edge = find_taken_edge (e->dest, cond);
 
@@ -1105,12 +1175,15 @@
 		    edge e,
 		    class const_and_copies *const_and_copies,
 		    class avail_exprs_stack *avail_exprs_stack,
+		    class evrp_range_analyzer *evrp_range_analyzer,
 		    pfn_simplify simplify)
 {
   bitmap visited = BITMAP_ALLOC (NULL);
 
   const_and_copies->push_marker ();
   avail_exprs_stack->push_marker ();
+  if (evrp_range_analyzer)
+    evrp_range_analyzer->push_marker ();
 
   stmt_count = 0;
 
@@ -1124,6 +1197,7 @@
     threaded = thread_through_normal_block (e, dummy_cond,
 					    const_and_copies,
 					    avail_exprs_stack,
+					    evrp_range_analyzer,
 					    simplify, path,
 					    visited);
   else
@@ -1135,6 +1209,8 @@
 					   e->dest);
       const_and_copies->pop_to_marker ();
       avail_exprs_stack->pop_to_marker ();
+      if (evrp_range_analyzer)
+	evrp_range_analyzer->pop_to_marker ();
       BITMAP_FREE (visited);
       register_jump_thread (path);
       return;
@@ -1160,6 +1236,8 @@
 	  BITMAP_FREE (visited);
 	  const_and_copies->pop_to_marker ();
           avail_exprs_stack->pop_to_marker ();
+	  if (evrp_range_analyzer)
+	    evrp_range_analyzer->pop_to_marker ();
 	  return;
 	}
     }
@@ -1187,6 +1265,8 @@
 	{
 	  const_and_copies->pop_to_marker ();
           avail_exprs_stack->pop_to_marker ();
+	  if (evrp_range_analyzer)
+	    evrp_range_analyzer->pop_to_marker ();
 	  BITMAP_FREE (visited);
 	  return;
 	}
@@ -1202,6 +1282,8 @@
 	   for each of E->dest's successors.  */
 	const_and_copies->push_marker ();
 	avail_exprs_stack->push_marker ();
+	if (evrp_range_analyzer)
+	  evrp_range_analyzer->push_marker ();
 
 	/* Avoid threading to any block we have already visited.  */
 	bitmap_clear (visited);
@@ -1229,6 +1311,7 @@
 	  found = thread_through_normal_block (path->last ()->e, dummy_cond,
 					       const_and_copies,
 					       avail_exprs_stack,
+					       evrp_range_analyzer,
 					       simplify, path,
 					       visited) > 0;
 
@@ -1244,12 +1327,16 @@
 	  delete_jump_thread_path (path);
 
 	/* And unwind the equivalence table.  */
+	if (evrp_range_analyzer)
+	  evrp_range_analyzer->pop_to_marker ();
 	avail_exprs_stack->pop_to_marker ();
 	const_and_copies->pop_to_marker ();
       }
     BITMAP_FREE (visited);
   }
 
+  if (evrp_range_analyzer)
+    evrp_range_analyzer->pop_to_marker ();
   const_and_copies->pop_to_marker ();
   avail_exprs_stack->pop_to_marker ();
 }
@@ -1271,6 +1358,7 @@
 thread_outgoing_edges (basic_block bb, gcond *dummy_cond,
 		       class const_and_copies *const_and_copies,
 		       class avail_exprs_stack *avail_exprs_stack,
+		       class evrp_range_analyzer *evrp_range_analyzer,
 		       tree (*simplify) (gimple *, gimple *,
 					 class avail_exprs_stack *,
 					 basic_block))
@@ -1288,7 +1376,7 @@
     {
       thread_across_edge (dummy_cond, single_succ_edge (bb),
 			  const_and_copies, avail_exprs_stack,
-			  simplify);
+			  evrp_range_analyzer, simplify);
     }
   else if ((last = last_stmt (bb))
 	   && gimple_code (last) == GIMPLE_COND
@@ -1304,11 +1392,13 @@
 	 more than one predecessor and more than one successor.  */
       if (potentially_threadable_block (true_edge->dest))
 	thread_across_edge (dummy_cond, true_edge,
-			    const_and_copies, avail_exprs_stack, simplify);
+			    const_and_copies, avail_exprs_stack,
+			    evrp_range_analyzer, simplify);
 
       /* Similarly for the ELSE arm.  */
       if (potentially_threadable_block (false_edge->dest))
 	thread_across_edge (dummy_cond, false_edge,
-			    const_and_copies, avail_exprs_stack, simplify);
+			    const_and_copies, avail_exprs_stack,
+			    evrp_range_analyzer, simplify);
     }
 }