diff mbox series

Replace PRE "DCE"

Message ID alpine.LSU.2.20.1709061504190.14191@zhemvz.fhfr.qr
State New
Headers show
Series Replace PRE "DCE" | expand

Commit Message

Richard Biener Sept. 6, 2017, 1:06 p.m. UTC
The following replaces the weird PRE "DCE" algorithm by a simple
work-list based one seeded by inserted_exprs.  This makes it possible
to get rid of the error-prone marking of stmts necessary and allows
re-ordering of elimination dead stmt removal and DCE again (I'm
in the process of developing a RPO based VN and want to keep
elimination common but move it out of PRE).

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk.

Richard.

2017-09-06  Richard Biener  <rguenther@suse.de>

	* tree-ssa-pre.c (NECESSARY): Remove.
	(create_expression_by_pieces): Do not touch pass-local flags.
	(insert_into_preds_of_block): Likewise.
	(do_pre_regular_insertion): Likewise.
	(eliminate_insert): Likewise.
	(eliminate_dom_walker::before_dom_children): Likewise.
	(fini_eliminate): Do not look at inserted_exprs.
	(mark_operand_necessary): Remove.
	(remove_dead_inserted_code): Replace with simple work-list
	algorithm based on inserted_exprs and SSA uses.
	(pass_pre::execute): Re-order fini_eliminate and
	remove_dead_inserted_code.
diff mbox series

Patch

Index: gcc/tree-ssa-pre.c
===================================================================
--- gcc/tree-ssa-pre.c	(revision 251790)
+++ gcc/tree-ssa-pre.c	(working copy)
@@ -2753,8 +2753,6 @@  find_or_generate_expression (basic_block
   return NULL_TREE;
 }
 
-#define NECESSARY GF_PLF_1
-
 /* Create an expression in pieces, so that we can handle very complex
    expressions that may be ANTIC, but not necessary GIMPLE.
    BLOCK is the basic block the expression will be inserted into,
@@ -2972,7 +2970,6 @@  create_expression_by_pieces (basic_block
 	    }
 
 	  bitmap_set_bit (inserted_exprs, SSA_NAME_VERSION (forcedname));
-	  gimple_set_plf (stmt, NECESSARY, false);
 	}
       gimple_seq_add_seq (stmts, forced_stmts);
     }
@@ -3095,7 +3092,6 @@  insert_into_preds_of_block (basic_block
   temp = make_temp_ssa_name (type, NULL, "prephitmp");
   phi = create_phi_node (temp, block);
 
-  gimple_set_plf (phi, NECESSARY, false);
   VN_INFO_GET (temp)->value_id = val;
   VN_INFO (temp)->valnum = sccvn_valnum_from_value_id (val);
   if (VN_INFO (temp)->valnum == NULL_TREE)
@@ -3342,7 +3338,6 @@  do_pre_regular_insertion (basic_block bl
 	      gimple_stmt_iterator gsi = gsi_after_labels (block);
 	      gsi_insert_before (&gsi, assign, GSI_NEW_STMT);
 
-	      gimple_set_plf (assign, NECESSARY, false);
 	      VN_INFO_GET (temp)->value_id = val;
 	      VN_INFO (temp)->valnum = sccvn_valnum_from_value_id (val);
 	      if (VN_INFO (temp)->valnum == NULL_TREE)
@@ -4204,9 +4199,6 @@  eliminate_insert (gimple_stmt_iterator *
     {
       gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
       VN_INFO_GET (res)->valnum = val;
-
-      if (TREE_CODE (leader) == SSA_NAME)
-	gimple_set_plf (SSA_NAME_DEF_STMT (leader), NECESSARY, true);
     }
 
   pre_stats.insertions++;
@@ -4291,17 +4283,9 @@  eliminate_dom_walker::before_dom_childre
 
 	  remove_phi_node (&gsi, false);
 
-	  if (inserted_exprs
-	      && !bitmap_bit_p (inserted_exprs, SSA_NAME_VERSION (res))
-	      && TREE_CODE (sprime) == SSA_NAME)
-	    gimple_set_plf (SSA_NAME_DEF_STMT (sprime), NECESSARY, true);
-
 	  if (!useless_type_conversion_p (TREE_TYPE (res), TREE_TYPE (sprime)))
 	    sprime = fold_convert (TREE_TYPE (res), sprime);
 	  gimple *stmt = gimple_build_assign (res, sprime);
-	  /* ???  It cannot yet be necessary (DOM walk).  */
-	  gimple_set_plf (stmt, NECESSARY, gimple_plf (phi, NECESSARY));
-
 	  gimple_stmt_iterator gsi2 = gsi_after_labels (b);
 	  gsi_insert_before (&gsi2, stmt, GSI_NEW_STMT);
 	  continue;
@@ -4478,10 +4462,6 @@  eliminate_dom_walker::before_dom_childre
 		  print_gimple_stmt (dump_file, stmt, 0);
 		}
 
-	      if (TREE_CODE (sprime) == SSA_NAME)
-		gimple_set_plf (SSA_NAME_DEF_STMT (sprime),
-				NECESSARY, true);
-
 	      pre_stats.eliminations++;
 	      gimple *orig_stmt = stmt;
 	      if (!useless_type_conversion_p (TREE_TYPE (lhs),
@@ -4615,10 +4595,6 @@  eliminate_dom_walker::before_dom_childre
 	    {
 	      propagate_value (use_p, sprime);
 	      modified = true;
-	      if (TREE_CODE (sprime) == SSA_NAME
-		  && !is_gimple_debug (stmt))
-		gimple_set_plf (SSA_NAME_DEF_STMT (sprime),
-				NECESSARY, true);
 	    }
 	}
 
@@ -4787,11 +4763,7 @@  eliminate_dom_walker::before_dom_childre
 	    continue;
 	  tree sprime = eliminate_avail (arg);
 	  if (sprime && may_propagate_copy (arg, sprime))
-	    {
-	      propagate_value (use_p, sprime);
-	      if (TREE_CODE (sprime) == SSA_NAME)
-		gimple_set_plf (SSA_NAME_DEF_STMT (sprime), NECESSARY, true);
-	    }
+	    propagate_value (use_p, sprime);
 	}
   return NULL;
 }
@@ -4853,18 +4825,6 @@  fini_eliminate (void)
     {
       stmt = el_to_remove.pop ();
 
-      tree lhs;
-      if (gimple_code (stmt) == GIMPLE_PHI)
-	lhs = gimple_phi_result (stmt);
-      else
-	lhs = gimple_get_lhs (stmt);
-
-      if (inserted_exprs
-	  && lhs
-	  && TREE_CODE (lhs) == SSA_NAME
-	  && bitmap_bit_p (inserted_exprs, SSA_NAME_VERSION (lhs)))
-	continue;
-
       if (dump_file && (dump_flags & TDF_DETAILS))
 	{
 	  fprintf (dump_file, "Removing dead stmt ");
@@ -4926,36 +4886,9 @@  fini_eliminate (void)
   return todo;
 }
 
-/* Borrow a bit of tree-ssa-dce.c for the moment.
-   XXX: In 4.1, we should be able to just run a DCE pass after PRE, though
-   this may be a bit faster, and we may want critical edges kept split.  */
-
-/* If OP's defining statement has not already been determined to be necessary,
-   mark that statement necessary. Return the stmt, if it is newly
-   necessary.  */
+/* Cheap DCE of a known set of possibly dead stmts.
 
-static inline gimple *
-mark_operand_necessary (tree op)
-{
-  gimple *stmt;
-
-  gcc_assert (op);
-
-  if (TREE_CODE (op) != SSA_NAME)
-    return NULL;
-
-  stmt = SSA_NAME_DEF_STMT (op);
-  gcc_assert (stmt);
-
-  if (gimple_plf (stmt, NECESSARY)
-      || gimple_nop_p (stmt))
-    return NULL;
-
-  gimple_set_plf (stmt, NECESSARY, true);
-  return stmt;
-}
-
-/* Because we don't follow exactly the standard PRE algorithm, and decide not
+   Because we don't follow exactly the standard PRE algorithm, and decide not
    to insert PHI nodes sometimes, and because value numbering of casts isn't
    perfect, we sometimes end up inserting dead code.   This simple DCE-like
    pass removes any insertions we made that weren't actually used.  */
@@ -4963,99 +4896,50 @@  mark_operand_necessary (tree op)
 static void
 remove_dead_inserted_code (void)
 {
-  unsigned i;
-  bitmap_iterator bi;
-  gimple *t;
-
-  auto_bitmap worklist;
-  EXECUTE_IF_SET_IN_BITMAP (inserted_exprs, 0, i, bi)
-    {
-      t = SSA_NAME_DEF_STMT (ssa_name (i));
-      if (gimple_plf (t, NECESSARY))
-	bitmap_set_bit (worklist, i);
-    }
-  while (!bitmap_empty_p (worklist))
+  /* ???  Re-use inserted_exprs as worklist not only as initial set.
+     This may end up removing non-inserted code as well.  If we
+     keep inserted_exprs unchanged we could restrict new worklist
+     elements to members of inserted_exprs.  */
+  bitmap worklist = inserted_exprs;
+  while (! bitmap_empty_p (worklist))
     {
-      i = bitmap_first_set_bit (worklist);
+      /* Pop item.  */
+      unsigned i = bitmap_first_set_bit (worklist);
       bitmap_clear_bit (worklist, i);
-      t = SSA_NAME_DEF_STMT (ssa_name (i));
-
-      /* PHI nodes are somewhat special in that each PHI alternative has
-	 data and control dependencies.  All the statements feeding the
-	 PHI node's arguments are always necessary. */
-      if (gimple_code (t) == GIMPLE_PHI)
-	{
-	  unsigned k;
 
-	  for (k = 0; k < gimple_phi_num_args (t); k++)
-	    {
-	      tree arg = PHI_ARG_DEF (t, k);
-	      if (TREE_CODE (arg) == SSA_NAME)
-		{
-		  gimple *n = mark_operand_necessary (arg);
-		  if (n)
-		    bitmap_set_bit (worklist, SSA_NAME_VERSION (arg));
-		}
-	    }
-	}
-      else
-	{
-	  /* Propagate through the operands.  Examine all the USE, VUSE and
-	     VDEF operands in this statement.  Mark all the statements
-	     which feed this statement's uses as necessary.  */
-	  ssa_op_iter iter;
-	  tree use;
+      tree def = ssa_name (i);
+      /* Removed by somebody else or still in use.  */
+      if (! def || ! has_zero_uses (def))
+	continue;
 
-	  /* The operands of VDEF expressions are also needed as they
-	     represent potential definitions that may reach this
-	     statement (VDEF operands allow us to follow def-def
-	     links).  */
+      gimple *t = SSA_NAME_DEF_STMT (def);
 
-	  FOR_EACH_SSA_TREE_OPERAND (use, t, iter, SSA_OP_ALL_USES)
-	    {
-	      gimple *n = mark_operand_necessary (use);
-	      if (n)
-		bitmap_set_bit (worklist, SSA_NAME_VERSION (use));
-	    }
+      /* Add uses to the worklist.  */
+      ssa_op_iter iter;
+      use_operand_p use_p;
+      FOR_EACH_PHI_OR_STMT_USE (use_p, t, iter, SSA_OP_USE)
+	{
+	  tree use = USE_FROM_PTR (use_p);
+	  if (TREE_CODE (use) == SSA_NAME
+	      && ! SSA_NAME_IS_DEFAULT_DEF (use))
+	    bitmap_set_bit (worklist, SSA_NAME_VERSION (use));
 	}
-    }
 
-  unsigned int to_clear = -1U;
-  EXECUTE_IF_SET_IN_BITMAP (inserted_exprs, 0, i, bi)
-    {
-      if (to_clear != -1U)
+      /* Remove stmt.  */
+      if (dump_file && (dump_flags & TDF_DETAILS))
 	{
-	  bitmap_clear_bit (inserted_exprs, to_clear);
-	  to_clear = -1U;
+	  fprintf (dump_file, "Removing unnecessary insertion:");
+	  print_gimple_stmt (dump_file, t, 0);
 	}
-      t = SSA_NAME_DEF_STMT (ssa_name (i));
-      if (!gimple_plf (t, NECESSARY))
+      gimple_stmt_iterator gsi = gsi_for_stmt (t);
+      if (gimple_code (t) == GIMPLE_PHI)
+	remove_phi_node (&gsi, true);
+      else
 	{
-	  gimple_stmt_iterator gsi;
-
-	  if (dump_file && (dump_flags & TDF_DETAILS))
-	    {
-	      fprintf (dump_file, "Removing unnecessary insertion:");
-	      print_gimple_stmt (dump_file, t, 0);
-	    }
-
-	  gsi = gsi_for_stmt (t);
-	  if (gimple_code (t) == GIMPLE_PHI)
-	    remove_phi_node (&gsi, true);
-	  else
-	    {
-	      gsi_remove (&gsi, true);
-	      release_defs (t);
-	    }
+	  gsi_remove (&gsi, true);
+	  release_defs (t);
 	}
-      else
-	/* eliminate_fini will skip stmts marked for removal if we
-	   already removed it and uses inserted_exprs for this, so
-	   clear those we didn't end up removing.  */
-	to_clear = i;
     }
-  if (to_clear != -1U)
-    bitmap_clear_bit (inserted_exprs, to_clear);
 }
 
 
@@ -5196,10 +5080,10 @@  pass_pre::execute (function *fun)
   statistics_counter_event (fun, "Eliminated", pre_stats.eliminations);
 
   clear_expression_ids ();
-  remove_dead_inserted_code ();
 
   scev_finalize ();
   todo |= fini_eliminate ();
+  remove_dead_inserted_code ();
   fini_pre ();
   loop_optimizer_finalize ();