The following patch makes EVRP remove stmts that will become dead
after propagation.  For this to work we have to propagate into PHIs
(sth we missed as well).

Bootstrap and regtest running on x86_64-unknown-linux-gnu.

Richard.

2016-10-18  Richard Biener  <rguent...@suse.de>

        * tree-vrp.c (evrp_dom_walker::evrp_dom_walker): Initialize
        stmts_to_remove.
        (evrp_dom_walker::~evrp_dom_walker): Free it.
        (evrp_dom_walker::stmts_to_remove): Add.
        (evrp_dom_walker::before_dom_children): Mark PHIs and stmts
        whose output we fully propagate for removal.  Propagate
        into BB destination PHI arguments.
        (execute_early_vrp): Remove queued stmts.  Dump value ranges
        before stmt removal.

Index: gcc/tree-vrp.c
===================================================================
--- gcc/tree-vrp.c      (revision 241302)
+++ gcc/tree-vrp.c      (working copy)
@@ -10643,11 +10643,13 @@ public:
     : dom_walker (CDI_DOMINATORS), stack (10)
     {
       stmts_to_fixup.create (0);
+      stmts_to_remove.create (0);
       need_eh_cleanup = BITMAP_ALLOC (NULL);
     }
   ~evrp_dom_walker ()
     {
       stmts_to_fixup.release ();
+      stmts_to_remove.release ();
       BITMAP_FREE (need_eh_cleanup);
     }
   virtual edge before_dom_children (basic_block);
@@ -10660,6 +10662,7 @@ public:
   auto_vec<std::pair <const_tree, value_range*> > stack;
   bitmap need_eh_cleanup;
   vec<gimple *> stmts_to_fixup;
+  vec<gimple *> stmts_to_remove;
 };
 
 
@@ -10769,6 +10772,15 @@ evrp_dom_walker::before_dom_children (ba
       else
        set_value_range_to_varying (&vr_result);
       update_value_range (lhs, &vr_result);
+
+      /* Mark PHIs whose lhs we fully propagate for removal.  */
+      tree val;
+      if ((val = op_with_constant_singleton_value_range (lhs))
+         && may_propagate_copy (lhs, val))
+       {
+         stmts_to_remove.safe_push (phi);
+         continue;
+       }
     }
 
   edge taken_edge = NULL;
@@ -10806,7 +10818,6 @@ evrp_dom_walker::before_dom_children (ba
              update_value_range (output, &vr);
              vr = *get_value_range (output);
 
-
              /* Set the SSA with the value range.  */
              if (INTEGRAL_TYPE_P (TREE_TYPE (output)))
                {
@@ -10824,6 +10835,17 @@ evrp_dom_walker::before_dom_children (ba
                               && range_includes_zero_p (vr.min,
                                                         vr.max) == 1)))
                set_ptr_nonnull (output);
+
+             /* Mark stmts whose output we fully propagate for removal.  */
+             tree val;
+             if ((val = op_with_constant_singleton_value_range (output))
+                 && may_propagate_copy (output, val)
+                 && !stmt_could_throw_p (stmt)
+                 && !gimple_has_side_effects (stmt))
+               {
+                 stmts_to_remove.safe_push (stmt);
+                 continue;
+               }
            }
          else
            set_defs_to_varying (stmt);
@@ -10860,6 +10882,24 @@ evrp_dom_walker::before_dom_children (ba
            }
        }
     }
+
+  /* Visit BB successor PHI nodes and replace PHI args.  */
+  FOR_EACH_EDGE (e, ei, bb->succs)
+    {
+      for (gphi_iterator gpi = gsi_start_phis (e->dest);
+          !gsi_end_p (gpi); gsi_next (&gpi))
+       {
+         gphi *phi = gpi.phi ();
+         use_operand_p use_p = PHI_ARG_DEF_PTR_FROM_EDGE (phi, e);
+         tree arg = USE_FROM_PTR (use_p);
+         if (TREE_CODE (arg) != SSA_NAME
+             || virtual_operand_p (arg))
+           continue;
+         if (tree val = op_with_constant_singleton_value_range (arg))
+           propagate_value (use_p, val);
+       }
+    }
+ 
   bb->flags |= BB_VISITED;
 
   return taken_edge;
@@ -10941,6 +10981,34 @@ execute_early_vrp ()
   evrp_dom_walker walker;
   walker.walk (ENTRY_BLOCK_PTR_FOR_FN (cfun));
 
+  if (dump_file)
+    {
+      fprintf (dump_file, "\nValue ranges after Early VRP:\n\n");
+      dump_all_value_ranges (dump_file);
+      fprintf (dump_file, "\n");
+    }
+
+  /* Remove stmts in reverse order to make debug stmt creation possible.  */
+  while (! walker.stmts_to_remove.is_empty ())
+    {
+      gimple *stmt = walker.stmts_to_remove.pop ();
+      if (dump_file && dump_flags & TDF_DETAILS)
+       {
+         fprintf (dump_file, "Removing dead stmt ");
+         print_gimple_stmt (dump_file, stmt, 0, 0);
+         fprintf (dump_file, "\n");
+       }
+      gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
+      if (gimple_code (stmt) == GIMPLE_PHI)
+       remove_phi_node (&gsi, true);
+      else
+       {
+         unlink_stmt_vdef (stmt);
+         gsi_remove (&gsi, true);
+         release_defs (stmt);
+       }
+    }
+
   if (!bitmap_empty_p (walker.need_eh_cleanup))
     gimple_purge_all_dead_eh_edges (walker.need_eh_cleanup);
 
@@ -10954,12 +11022,6 @@ execute_early_vrp ()
       fixup_noreturn_call (stmt);
     }
 
-  if (dump_file)
-    {
-      fprintf (dump_file, "\nValue ranges after Early VRP:\n\n");
-      dump_all_value_ranges (dump_file);
-      fprintf (dump_file, "\n");
-    }
   vrp_free_lattice ();
   scev_finalize ();
   loop_optimizer_finalize ();

Reply via email to