tree-ssa-forwprop.c (simplify_builtin_call): Do not remove stmt at gsi_p, instead...
authorRichard Biener <rguenther@suse.de>
Fri, 16 Aug 2019 09:27:34 +0000 (09:27 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Fri, 16 Aug 2019 09:27:34 +0000 (09:27 +0000)
2019-08-16  Richard Biener  <rguenther@suse.de>

* tree-ssa-forwprop.c (simplify_builtin_call): Do not remove
stmt at gsi_p, instead replace it with a NOP removed later.
(pass_forwprop::execute): Fully propagate lattice, DCE stmts
that became dead because of that.

fortran/
* trans-intrinsic.c (gfc_conv_intrinsic_findloc): Initialize
forward_branch to avoid bogus uninitialized warning.

* gcc.dg/tree-ssa/forwprop-31.c: Adjust.

From-SVN: r274563

gcc/ChangeLog
gcc/fortran/ChangeLog
gcc/fortran/trans-intrinsic.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/forwprop-31.c
gcc/tree-ssa-forwprop.c

index f25c00b57031561e0334c2926a97a7f4c2873603..e447aabb367205d8aba97577b84945345cfd1b2b 100644 (file)
@@ -1,3 +1,10 @@
+2019-08-16  Richard Biener  <rguenther@suse.de>
+
+       * tree-ssa-forwprop.c (simplify_builtin_call): Do not remove
+       stmt at gsi_p, instead replace it with a NOP removed later.
+       (pass_forwprop::execute): Fully propagate lattice, DCE stmts
+       that became dead because of that.
+
 2019-08-16  Aldy Hernandez  <aldyh@redhat.com>
 
        * gimple-ssa-evrp-analyze.c (record_ranges_from_phis): Skip PHIs
index 3ddb00728a53de8fee068fce03315036ddd1ee5b..e745f48bddda82402297cd47b5a3e08142a63574 100644 (file)
@@ -1,3 +1,8 @@
+2019-08-16  Richard Biener  <rguenther@suse.de>
+
+       * trans-intrinsic.c (gfc_conv_intrinsic_findloc): Initialize
+       forward_branch to avoid bogus uninitialized warning.
+
 2019-08-15  Thomas Koenig  <tkoenig@gcc.gnu.org>
 
        PR fortran/91443
index 8f64c387258784f806fe3ce462772c98d6255f36..26ea624101d08931b272b4ac40395fd47e3ab9d3 100644 (file)
@@ -5428,7 +5428,7 @@ gfc_conv_intrinsic_findloc (gfc_se *se, gfc_expr *expr)
   tree type;
   tree tmp;
   tree found;
-  tree forward_branch;
+  tree forward_branch = NULL_TREE;
   tree back_branch;
   gfc_loopinfo loop;
   gfc_ss *arrayss;
index a5870f6022cdb7ffbc5b305337f6c18c79f409ac..cbe637eaca1d06f964654359dc21bfb0d536c057 100644 (file)
@@ -1,3 +1,7 @@
+2019-08-16  Richard Biener  <rguenther@suse.de>
+
+       * gcc.dg/tree-ssa/forwprop-31.c: Adjust.
+
 2019-08-16  Martin Liska  <mliska@suse.cz>
 
        PR ipa/91447
index e146ade61afb4cc69df20c16f35ebbeaa11396d6..edf8026488406718222298216c5cf460bd36fe72 100644 (file)
@@ -9,7 +9,6 @@ int foo (int x)
   return w - z; /* becomes 0 */
 }
 
-/* The original y = 0 stmt is also retained.  */
-/* { dg-final { scan-tree-dump-times "= 0;" 2 "forwprop1" } } */
-/* { dg-final { scan-tree-dump-times "-" 0 "forwprop1" } } */
-/* { dg-final { scan-tree-dump-times "\\+" 1 "forwprop1" } } */
+/* Only z = x + 1 is retained.  */
+/* { dg-final { scan-tree-dump-times " = " 1 "forwprop1" } } */
+/* { dg-final { scan-tree-dump "return 0;" "forwprop1" } } */
index 2828c6be351199f368304abf036eb600c84c5b03..c464c8995861022d6c553249751f678ebdf521df 100644 (file)
@@ -1403,7 +1403,7 @@ simplify_builtin_call (gimple_stmt_iterator *gsi_p, tree callee2)
                                   build_int_cst (TREE_TYPE (len1), src_len));
              update_stmt (stmt1);
              unlink_stmt_vdef (stmt2);
-             gsi_remove (gsi_p, true);
+             gsi_replace (gsi_p, gimple_build_nop (), false);
              fwprop_invalidate_lattice (gimple_get_lhs (stmt2));
              release_defs (stmt2);
              if (lhs1 && DECL_FUNCTION_CODE (callee1) == BUILT_IN_MEMPCPY)
@@ -2299,13 +2299,14 @@ pass_forwprop::execute (function *fun)
   int postorder_num = pre_and_rev_post_order_compute_fn (cfun, NULL,
                                                         postorder, false);
   auto_vec<gimple *, 4> to_fixup;
+  auto_vec<gimple *, 32> to_remove;
   to_purge = BITMAP_ALLOC (NULL);
   for (int i = 0; i < postorder_num; ++i)
     {
       gimple_stmt_iterator gsi;
       basic_block bb = BASIC_BLOCK_FOR_FN (fun, postorder[i]);
 
-      /* Propagate into PHIs and record degenerate ones in the lattice.  */
+      /* Record degenerate PHIs in the lattice.  */
       for (gphi_iterator si = gsi_start_phis (bb); !gsi_end_p (si);
           gsi_next (&si))
        {
@@ -2321,17 +2322,20 @@ pass_forwprop::execute (function *fun)
          FOR_EACH_PHI_ARG (use_p, phi, it, SSA_OP_USE)
            {
              tree use = USE_FROM_PTR (use_p);
-             tree tem = fwprop_ssa_val (use);
              if (! first)
-               first = tem;
-             else if (! operand_equal_p (first, tem, 0))
-               all_same = false;
-             if (tem != use
-                 && may_propagate_copy (use, tem))
-               propagate_value (use_p, tem);
+               first = use;
+             else if (! operand_equal_p (first, use, 0))
+               {
+                 all_same = false;
+                 break;
+               }
            }
          if (all_same)
-           fwprop_set_lattice_val (res, first);
+           {
+             if (may_propagate_copy (res, first))
+               to_remove.safe_push (phi);
+             fwprop_set_lattice_val (res, first);
+           }
        }
 
       /* Apply forward propagation to all stmts in the basic-block.
@@ -2648,148 +2652,223 @@ pass_forwprop::execute (function *fun)
 
       /* Combine stmts with the stmts defining their operands.
         Note we update GSI within the loop as necessary.  */
-      for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
+      for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
        {
          gimple *stmt = gsi_stmt (gsi);
-         gimple *orig_stmt = stmt;
-         bool changed = false;
-         bool was_noreturn = (is_gimple_call (stmt)
-                              && gimple_call_noreturn_p (stmt));
 
          /* Mark stmt as potentially needing revisiting.  */
          gimple_set_plf (stmt, GF_PLF_1, false);
 
-         if (fold_stmt (&gsi, fwprop_ssa_val))
+         /* Substitute from our lattice.  We need to do so only once.  */
+         bool substituted_p = false;
+         use_operand_p usep;
+         ssa_op_iter iter;
+         FOR_EACH_SSA_USE_OPERAND (usep, stmt, iter, SSA_OP_USE)
            {
-             changed = true;
-             stmt = gsi_stmt (gsi);
-             if (maybe_clean_or_replace_eh_stmt (orig_stmt, stmt))
-               bitmap_set_bit (to_purge, bb->index);
-             if (!was_noreturn
-                 && is_gimple_call (stmt) && gimple_call_noreturn_p (stmt))
-               to_fixup.safe_push (stmt);
-             /* Cleanup the CFG if we simplified a condition to
-                true or false.  */
-             if (gcond *cond = dyn_cast <gcond *> (stmt))
-               if (gimple_cond_true_p (cond)
-                   || gimple_cond_false_p (cond))
-                 cfg_changed = true;
-             update_stmt (stmt);
+             tree use = USE_FROM_PTR (usep);
+             tree val = fwprop_ssa_val (use);
+             if (val && val != use && may_propagate_copy (use, val))
+               {
+                 propagate_value (usep, val);
+                 substituted_p = true;
+               }
            }
+         if (substituted_p
+             && is_gimple_assign (stmt)
+             && gimple_assign_rhs_code (stmt) == ADDR_EXPR)
+           recompute_tree_invariant_for_addr_expr (gimple_assign_rhs1 (stmt));
 
-         switch (gimple_code (stmt))
+         bool changed;
+         do
            {
-           case GIMPLE_ASSIGN:
-             {
-               tree rhs1 = gimple_assign_rhs1 (stmt);
-               enum tree_code code = gimple_assign_rhs_code (stmt);
+             gimple *orig_stmt = stmt = gsi_stmt (gsi);
+             bool was_noreturn = (is_gimple_call (stmt)
+                                  && gimple_call_noreturn_p (stmt));
+             changed = false;
 
-               if (code == COND_EXPR
-                   || code == VEC_COND_EXPR)
+             if (fold_stmt (&gsi, fwprop_ssa_val))
+               {
+                 changed = true;
+                 stmt = gsi_stmt (gsi);
+                 /* Cleanup the CFG if we simplified a condition to
+                    true or false.  */
+                 if (gcond *cond = dyn_cast <gcond *> (stmt))
+                   if (gimple_cond_true_p (cond)
+                       || gimple_cond_false_p (cond))
+                     cfg_changed = true;
+               }
+
+             if (changed || substituted_p)
+               {
+                 if (maybe_clean_or_replace_eh_stmt (orig_stmt, stmt))
+                   bitmap_set_bit (to_purge, bb->index);
+                 if (!was_noreturn
+                     && is_gimple_call (stmt) && gimple_call_noreturn_p (stmt))
+                   to_fixup.safe_push (stmt);
+                 update_stmt (stmt);
+                 substituted_p = false;
+               }
+
+             switch (gimple_code (stmt))
+               {
+               case GIMPLE_ASSIGN:
                  {
-                   /* In this case the entire COND_EXPR is in rhs1. */
-                   if (forward_propagate_into_cond (&gsi))
+                   tree rhs1 = gimple_assign_rhs1 (stmt);
+                   enum tree_code code = gimple_assign_rhs_code (stmt);
+
+                   if (code == COND_EXPR
+                       || code == VEC_COND_EXPR)
                      {
-                       changed = true;
-                       stmt = gsi_stmt (gsi);
+                       /* In this case the entire COND_EXPR is in rhs1. */
+                       if (forward_propagate_into_cond (&gsi))
+                         {
+                           changed = true;
+                           stmt = gsi_stmt (gsi);
+                         }
                      }
+                   else if (TREE_CODE_CLASS (code) == tcc_comparison)
+                     {
+                       int did_something;
+                       did_something = forward_propagate_into_comparison (&gsi);
+                       if (maybe_clean_or_replace_eh_stmt (stmt, gsi_stmt (gsi)))
+                         bitmap_set_bit (to_purge, bb->index);
+                       if (did_something == 2)
+                         cfg_changed = true;
+                       changed = did_something != 0;
+                     }
+                   else if ((code == PLUS_EXPR
+                             || code == BIT_IOR_EXPR
+                             || code == BIT_XOR_EXPR)
+                            && simplify_rotate (&gsi))
+                     changed = true;
+                   else if (code == VEC_PERM_EXPR)
+                     {
+                       int did_something = simplify_permutation (&gsi);
+                       if (did_something == 2)
+                         cfg_changed = true;
+                       changed = did_something != 0;
+                     }
+                   else if (code == BIT_FIELD_REF)
+                     changed = simplify_bitfield_ref (&gsi);
+                   else if (code == CONSTRUCTOR
+                            && TREE_CODE (TREE_TYPE (rhs1)) == VECTOR_TYPE)
+                     changed = simplify_vector_constructor (&gsi);
+                   break;
                  }
-               else if (TREE_CODE_CLASS (code) == tcc_comparison)
+
+               case GIMPLE_SWITCH:
+                 changed = simplify_gimple_switch (as_a <gswitch *> (stmt));
+                 break;
+
+               case GIMPLE_COND:
                  {
-                   int did_something;
-                   did_something = forward_propagate_into_comparison (&gsi);
-                   if (maybe_clean_or_replace_eh_stmt (stmt, gsi_stmt (gsi)))
-                     bitmap_set_bit (to_purge, bb->index);
+                   int did_something = forward_propagate_into_gimple_cond
+                                                       (as_a <gcond *> (stmt));
                    if (did_something == 2)
                      cfg_changed = true;
                    changed = did_something != 0;
+                   break;
                  }
-               else if ((code == PLUS_EXPR
-                         || code == BIT_IOR_EXPR
-                         || code == BIT_XOR_EXPR)
-                        && simplify_rotate (&gsi))
-                 changed = true;
-               else if (code == VEC_PERM_EXPR)
+
+               case GIMPLE_CALL:
                  {
-                   int did_something = simplify_permutation (&gsi);
-                   if (did_something == 2)
-                     cfg_changed = true;
-                   changed = did_something != 0;
+                   tree callee = gimple_call_fndecl (stmt);
+                   if (callee != NULL_TREE
+                       && fndecl_built_in_p (callee, BUILT_IN_NORMAL))
+                     changed = simplify_builtin_call (&gsi, callee);
+                   break;
                  }
-               else if (code == BIT_FIELD_REF)
-                 changed = simplify_bitfield_ref (&gsi);
-                else if (code == CONSTRUCTOR
-                         && TREE_CODE (TREE_TYPE (rhs1)) == VECTOR_TYPE)
-                  changed = simplify_vector_constructor (&gsi);
-               break;
-             }
-
-           case GIMPLE_SWITCH:
-             changed = simplify_gimple_switch (as_a <gswitch *> (stmt));
-             break;
 
-           case GIMPLE_COND:
-             {
-               int did_something
-                 = forward_propagate_into_gimple_cond (as_a <gcond *> (stmt));
-               if (did_something == 2)
-                 cfg_changed = true;
-               changed = did_something != 0;
-               break;
-             }
-
-           case GIMPLE_CALL:
-             {
-               tree callee = gimple_call_fndecl (stmt);
-               if (callee != NULL_TREE
-                   && fndecl_built_in_p (callee, BUILT_IN_NORMAL))
-                 changed = simplify_builtin_call (&gsi, callee);
-               break;
-             }
+               default:;
+               }
 
-           default:;
+             if (changed)
+               {
+                 /* If the stmt changed then re-visit it and the statements
+                    inserted before it.  */
+                 for (; !gsi_end_p (gsi); gsi_prev (&gsi))
+                   if (gimple_plf (gsi_stmt (gsi), GF_PLF_1))
+                     break;
+                 if (gsi_end_p (gsi))
+                   gsi = gsi_start_bb (bb);
+                 else
+                   gsi_next (&gsi);
+               }
            }
+         while (changed);
 
-         if (changed)
-           {
-             /* If the stmt changed then re-visit it and the statements
-                inserted before it.  */
-             for (; !gsi_end_p (gsi); gsi_prev (&gsi))
-               if (gimple_plf (gsi_stmt (gsi), GF_PLF_1))
-                 break;
-             if (gsi_end_p (gsi))
-               gsi = gsi_start_bb (bb);
-             else
-               gsi_next (&gsi);
-           }
-         else
-           {
-             /* Stmt no longer needs to be revisited.  */
-             gimple_set_plf (stmt, GF_PLF_1, true);
+         /* Stmt no longer needs to be revisited.  */
+         stmt = gsi_stmt (gsi);
+         gcc_checking_assert (!gimple_plf (stmt, GF_PLF_1));
+         gimple_set_plf (stmt, GF_PLF_1, true);
 
-             /* Fill up the lattice.  */
-             if (gimple_assign_single_p (stmt))
+         /* Fill up the lattice.  */
+         if (gimple_assign_single_p (stmt))
+           {
+             tree lhs = gimple_assign_lhs (stmt);
+             tree rhs = gimple_assign_rhs1 (stmt);
+             if (TREE_CODE (lhs) == SSA_NAME)
                {
-                 tree lhs = gimple_assign_lhs (stmt);
-                 tree rhs = gimple_assign_rhs1 (stmt);
-                 if (TREE_CODE (lhs) == SSA_NAME)
-                   {
-                     tree val = lhs;
-                     if (TREE_CODE (rhs) == SSA_NAME)
-                       val = fwprop_ssa_val (rhs);
-                     else if (is_gimple_min_invariant (rhs))
-                       val = rhs;
-                     fwprop_set_lattice_val (lhs, val);
-                   }
+                 tree val = lhs;
+                 if (TREE_CODE (rhs) == SSA_NAME)
+                   val = fwprop_ssa_val (rhs);
+                 else if (is_gimple_min_invariant (rhs))
+                   val = rhs;
+                 /* If we can propagate the lattice-value mark the
+                    stmt for removal.  */
+                 if (val != lhs
+                     && may_propagate_copy (lhs, val))
+                   to_remove.safe_push (stmt);
+                 fwprop_set_lattice_val (lhs, val);
                }
-
-             gsi_next (&gsi);
            }
+         else if (gimple_nop_p (stmt))
+           to_remove.safe_push (stmt);
        }
+
+      /* Substitute in destination PHI arguments.  */
+      edge_iterator ei;
+      edge e;
+      FOR_EACH_EDGE (e, ei, bb->succs)
+       for (gphi_iterator gsi = gsi_start_phis (e->dest);
+            !gsi_end_p (gsi); gsi_next (&gsi))
+         {
+           gphi *phi = gsi.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;
+           tree val = fwprop_ssa_val (arg);
+           if (val != arg
+               && may_propagate_copy (arg, val))
+             propagate_value (use_p, val);
+         }
     }
   free (postorder);
   lattice.release ();
 
+  /* Remove stmts in reverse order to make debug stmt creation possible.  */
+  while (!to_remove.is_empty())
+    {
+      gimple *stmt = to_remove.pop ();
+      if (dump_file && (dump_flags & TDF_DETAILS))
+       {
+         fprintf (dump_file, "Removing dead stmt ");
+         print_gimple_stmt (dump_file, stmt, 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);
+       }
+    }
+
   /* Fixup stmts that became noreturn calls.  This may require splitting
      blocks and thus isn't possible during the walk.  Do this
      in reverse order so we don't inadvertedly remove a stmt we want to