diff mbox

[RFA,PR,tree-optimization/68619] Avoid direct cfg cleanups in tree-ssa-dom.c [2/3] v2

Message ID 5668B83D.7090106@redhat.com
State New
Headers show

Commit Message

Jeff Law Dec. 9, 2015, 11:24 p.m. UTC
Changes for DOM to use the new capability in the dom walker.

Jeff
commit 88806f8996419d50d00f33f5d9924a1638316e3b
Author: Jeff Law <law@redhat.com>
Date:   Mon Dec 7 22:43:06 2015 -0700

    	PR tree-optimization/68619
    	* tree-ssa-dom.c (dom_opt_dom_walker::before_dom_children): Propgate
    	return value from optimize_stmt.
    	(dom_opt_dom_walker): Add new argument to dom_walker constructor.
    	(pass_dominator:execute): If a block has an unreachable edge,
    	remove all jump threads through any successor of the affected block.
    	(record_equivalences_from_phis): Ignore alternative if the edge
    	does not have EDGE_EXECUTABLE set.
    	(single_incoming_edge_ignoring_loop_edges): Similarly.
    	(optimize_stmt): If a gimple_code has a compile-time constant
    	condition, return the edge taken for that constant value.  Also
    	change the condition to true/false as necessary.
diff mbox

Patch

diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c
index aeb726c..88fc517 100644
--- a/gcc/tree-ssa-dom.c
+++ b/gcc/tree-ssa-dom.c
@@ -99,7 +99,7 @@  struct opt_stats_d
 static struct opt_stats_d opt_stats;
 
 /* Local functions.  */
-static void optimize_stmt (basic_block, gimple_stmt_iterator,
+static edge optimize_stmt (basic_block, gimple_stmt_iterator,
 			   class const_and_copies *,
 			   class avail_exprs_stack *);
 static tree lookup_avail_expr (gimple *, bool, class avail_exprs_stack *);
@@ -493,12 +493,12 @@  public:
   dom_opt_dom_walker (cdi_direction direction,
 		      class const_and_copies *const_and_copies,
 		      class avail_exprs_stack *avail_exprs_stack)
-    : dom_walker (direction),
+    : dom_walker (direction, true),
       m_const_and_copies (const_and_copies),
       m_avail_exprs_stack (avail_exprs_stack),
       m_dummy_cond (NULL) {}
 
-  virtual void before_dom_children (basic_block);
+  virtual edge before_dom_children (basic_block);
   virtual void after_dom_children (basic_block);
 
 private:
@@ -611,6 +611,36 @@  pass_dominator::execute (function *fun)
 			     avail_exprs_stack);
   walker.walk (fun->cfg->x_entry_block_ptr);
 
+  /* Look for blocks where we cleared EDGE_EXECUTABLE on an outgoing
+     edge.  When found, remove jump threads which contain any outgoing
+     edge from the affected block.  */
+  if (cfg_altered)
+    {
+      FOR_EACH_BB_FN (bb, fun)
+	{
+	  edge_iterator ei;
+	  edge e;
+
+	  /* First see if there are any edges without EDGE_EXECUTABLE
+	     set.  */
+	  bool found = false;
+	  FOR_EACH_EDGE (e, ei, bb->succs)
+	    {
+	      if ((e->flags & EDGE_EXECUTABLE) == 0)
+		{
+		  found = true;
+		  break;
+		}
+	    }
+
+	  /* If there were any such edges found, then remove jump threads
+	     containing any edge leaving BB.  */
+	  if (found)
+	    FOR_EACH_EDGE (e, ei, bb->succs)
+	      remove_jump_threads_including (e);
+	}
+    }
+
   {
     gimple_stmt_iterator gsi;
     basic_block bb;
@@ -951,6 +981,11 @@  record_equivalences_from_phis (basic_block bb)
 	  if (lhs == t)
 	    continue;
 
+	  /* If the associated edge is not marked as executable, then it
+	     can be ignored.  */
+	  if ((gimple_phi_arg_edge (phi, i)->flags & EDGE_EXECUTABLE) == 0)
+	    continue;
+
 	  t = dom_valueize (t);
 
 	  /* If we have not processed an alternative yet, then set
@@ -997,6 +1032,10 @@  single_incoming_edge_ignoring_loop_edges (basic_block bb)
       if (dominated_by_p (CDI_DOMINATORS, e->src, e->dest))
 	continue;
 
+      /* We can safely ignore edges that are not executable.  */
+      if ((e->flags & EDGE_EXECUTABLE) == 0)
+	continue;
+
       /* If we have already seen a non-loop edge, then we must have
 	 multiple incoming non-loop edges and thus we return NULL.  */
       if (retval)
@@ -1294,7 +1333,7 @@  cprop_into_successor_phis (basic_block bb,
     }
 }
 
-void
+edge
 dom_opt_dom_walker::before_dom_children (basic_block bb)
 {
   gimple_stmt_iterator gsi;
@@ -1322,12 +1361,15 @@  dom_opt_dom_walker::before_dom_children (basic_block bb)
 				      m_avail_exprs_stack);
   m_avail_exprs_stack->pop_to_marker ();
 
+  edge taken_edge = NULL;
   for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
-    optimize_stmt (bb, gsi, m_const_and_copies, m_avail_exprs_stack);
+    taken_edge
+      = optimize_stmt (bb, gsi, m_const_and_copies, m_avail_exprs_stack);
 
   /* Now prepare to process dominated blocks.  */
   record_edge_info (bb);
   cprop_into_successor_phis (bb, m_const_and_copies);
+  return taken_edge;
 }
 
 /* We have finished processing the dominator children of BB, perform
@@ -1694,7 +1736,7 @@  cprop_into_stmt (gimple *stmt)
       assignment is found, we map the value on the RHS of the assignment to
       the variable in the LHS in the CONST_AND_COPIES table.  */
 
-static void
+static edge
 optimize_stmt (basic_block bb, gimple_stmt_iterator si,
 	       class const_and_copies *const_and_copies,
 	       class avail_exprs_stack *avail_exprs_stack)
@@ -1703,6 +1745,7 @@  optimize_stmt (basic_block bb, gimple_stmt_iterator si,
   bool may_optimize_p;
   bool modified_p = false;
   bool was_noreturn;
+  edge retval = NULL;
 
   old_stmt = stmt = gsi_stmt (si);
   was_noreturn = is_gimple_call (stmt) && gimple_call_noreturn_p (stmt);
@@ -1823,7 +1866,7 @@  optimize_stmt (basic_block bb, gimple_stmt_iterator si,
 		    fprintf (dump_file, "  Flagged to clear EH edges.\n");
 		}
 	      release_defs (stmt);
-	      return;
+	      return retval;
 	    }
 	}
     }
@@ -1849,25 +1892,19 @@  optimize_stmt (basic_block bb, gimple_stmt_iterator si,
 
       if (val && TREE_CODE (val) == INTEGER_CST)
 	{
-	  edge taken_edge = find_taken_edge (bb, val);
-	  if (taken_edge)
+	  retval = find_taken_edge (bb, val);
+	  if (retval)
 	    {
-
-	      /* We need to remove any queued jump threads that
-		 reference outgoing edges from this block.  */
-	      edge_iterator ei;
-	      edge e;
-	      FOR_EACH_EDGE (e, ei, bb->succs)
-		remove_jump_threads_including (e);
-
-	      /* Now clean up the control statement at the end of
-		 BB and remove unexecutable edges.  */
-	      remove_ctrl_stmt_and_useless_edges (bb, taken_edge->dest);
-
-	      /* Fixup the flags on the single remaining edge.  */
-	      taken_edge->flags
-		&= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE | EDGE_ABNORMAL);
-	      taken_edge->flags |= EDGE_FALLTHRU;
+	      /* Fix the condition to be either true or false.  */
+	      if (gimple_code (stmt) == GIMPLE_COND)
+		{
+		  if (integer_zerop (val))
+		    gimple_cond_make_false (as_a <gcond *> (stmt));
+		  else if (integer_onep (val))
+		    gimple_cond_make_true (as_a <gcond *> (stmt));
+		  else
+		    gcc_unreachable ();
+		}
 
 	      /* Further simplifications may be possible.  */
 	      cfg_altered = true;
@@ -1887,6 +1924,7 @@  optimize_stmt (basic_block bb, gimple_stmt_iterator si,
 	  && is_gimple_call (stmt) && gimple_call_noreturn_p (stmt))
 	need_noreturn_fixup.safe_push (stmt);
     }
+  return retval;
 }
 
 /* Helper for walk_non_aliased_vuses.  Determine if we arrived at