re PR target/65697 (__atomic memory barriers not strong enough for __sync builtins)
[gcc.git] / gcc / tree-ssa-dce.c
index 6543dc7d26add40a10e3ab31a73f6d88a0d06e3a..181626cf979d18eba9464ee881b139924e2b1c60 100644 (file)
@@ -1,5 +1,5 @@
 /* Dead code elimination pass for the GNU compiler.
-   Copyright (C) 2002-2014 Free Software Foundation, Inc.
+   Copyright (C) 2002-2015 Free Software Foundation, Inc.
    Contributed by Ben Elliston <bje@redhat.com>
    and Andrew MacLeod <amacleod@redhat.com>
    Adapted to use control dependence by Steven Bosscher, SUSE Labs.
@@ -46,17 +46,14 @@ along with GCC; see the file COPYING3.  If not see
 #include "system.h"
 #include "coretypes.h"
 #include "tm.h"
-
+#include "alias.h"
+#include "symtab.h"
 #include "tree.h"
+#include "fold-const.h"
 #include "calls.h"
 #include "gimple-pretty-print.h"
 #include "predict.h"
-#include "vec.h"
-#include "hashtab.h"
-#include "hash-set.h"
-#include "machmode.h"
 #include "hard-reg-set.h"
-#include "input.h"
 #include "function.h"
 #include "dominance.h"
 #include "cfg.h"
@@ -66,7 +63,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "internal-fn.h"
 #include "tree-eh.h"
 #include "gimple-expr.h"
-#include "is-a.h"
 #include "gimple.h"
 #include "gimplify.h"
 #include "gimple-iterator.h"
@@ -78,10 +74,18 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-ssanames.h"
 #include "tree-ssa-loop-niter.h"
 #include "tree-into-ssa.h"
+#include "rtl.h"
+#include "flags.h"
+#include "insn-config.h"
+#include "expmed.h"
+#include "dojump.h"
+#include "explow.h"
+#include "emit-rtl.h"
+#include "varasm.h"
+#include "stmt.h"
 #include "expr.h"
 #include "tree-dfa.h"
 #include "tree-pass.h"
-#include "flags.h"
 #include "cfgloop.h"
 #include "tree-scalar-evolution.h"
 #include "tree-chkp.h"
@@ -292,8 +296,7 @@ mark_stmt_if_obviously_necessary (gimple stmt, bool aggressive)
       break;
 
     case GIMPLE_ASSIGN:
-      if (TREE_CODE (gimple_assign_lhs (stmt)) == SSA_NAME
-         && TREE_CLOBBER_P (gimple_assign_rhs1 (stmt)))
+      if (gimple_clobber_p (stmt))
        return;
       break;
 
@@ -673,6 +676,7 @@ propagate_necessity (bool aggressive)
             we also consider the control dependent edges leading to the
             predecessor block associated with each PHI alternative as
             necessary.  */
+         gphi *phi = as_a <gphi *> (stmt);
          size_t k;
 
          for (k = 0; k < gimple_phi_num_args (stmt); k++)
@@ -755,7 +759,7 @@ propagate_necessity (bool aggressive)
            {
              for (k = 0; k < gimple_phi_num_args (stmt); k++)
                {
-                 basic_block arg_bb = gimple_phi_arg_edge (stmt, k)->src;
+                 basic_block arg_bb = gimple_phi_arg_edge (phi, k)->src;
 
                  if (gimple_bb (stmt)
                      != get_immediate_dominator (CDI_POST_DOMINATORS, arg_bb))
@@ -895,9 +899,9 @@ propagate_necessity (bool aggressive)
                    mark_all_reaching_defs_necessary (stmt);
                }
            }
-         else if (gimple_code (stmt) == GIMPLE_RETURN)
+         else if (greturn *return_stmt = dyn_cast <greturn *> (stmt))
            {
-             tree rhs = gimple_return_retval (stmt);
+             tree rhs = gimple_return_retval (return_stmt);
              /* A return statement may perform a load.  */
              if (rhs
                  && TREE_CODE (rhs) != SSA_NAME
@@ -910,14 +914,14 @@ propagate_necessity (bool aggressive)
                    mark_all_reaching_defs_necessary (stmt);
                }
            }
-         else if (gimple_code (stmt) == GIMPLE_ASM)
+         else if (gasm *asm_stmt = dyn_cast <gasm *> (stmt))
            {
              unsigned i;
              mark_all_reaching_defs_necessary (stmt);
              /* Inputs may perform loads.  */
-             for (i = 0; i < gimple_asm_ninputs (stmt); ++i)
+             for (i = 0; i < gimple_asm_ninputs (asm_stmt); ++i)
                {
-                 tree op = TREE_VALUE (gimple_asm_input_op (stmt, i));
+                 tree op = TREE_VALUE (gimple_asm_input_op (asm_stmt, i));
                  if (TREE_CODE (op) != SSA_NAME
                      && !is_gimple_min_invariant (op)
                      && TREE_CODE (op) != CONSTRUCTOR
@@ -961,13 +965,13 @@ static bool
 remove_dead_phis (basic_block bb)
 {
   bool something_changed = false;
-  gimple phi;
-  gimple_stmt_iterator gsi;
+  gphi *phi;
+  gphi_iterator gsi;
 
   for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi);)
     {
       stats.total_phis++;
-      phi = gsi_stmt (gsi);
+      phi = gsi.phi ();
 
       /* We do not track necessity of virtual PHI nodes.  Instead do
          very simple dead PHI removal here.  */
@@ -1019,7 +1023,7 @@ remove_dead_phis (basic_block bb)
 static edge
 forward_edge_to_pdom (edge e, basic_block post_dom_bb)
 {
-  gimple_stmt_iterator gsi;
+  gphi_iterator gsi;
   edge e2 = NULL;
   edge_iterator ei;
 
@@ -1043,7 +1047,7 @@ forward_edge_to_pdom (edge e, basic_block post_dom_bb)
          break;
       for (gsi = gsi_start_phis (post_dom_bb); !gsi_end_p (gsi);)
        {
-         gimple phi = gsi_stmt (gsi);
+         gphi *phi = gsi.phi ();
          tree op;
          source_location locus;
 
@@ -1133,7 +1137,12 @@ remove_dead_stmt (gimple_stmt_iterator *i, basic_block bb)
        if (e != e2)
          {
            cfg_altered = true;
-            remove_edge (e2);
+           /* If we made a BB unconditionally exit a loop then this
+              transform alters the set of BBs in the loop.  Schedule
+              a fixup.  */
+           if (loop_exit_edge_p (bb->loop_father, e))
+             loops_state_set (LOOPS_NEED_FIXUP);
+           remove_edge (e2);
          }
        else
          ei_next (&ei);
@@ -1153,7 +1162,7 @@ remove_dead_stmt (gimple_stmt_iterator *i, basic_block bb)
          && !DECL_HAS_VALUE_EXPR_P (lhs))
        {
          tree rhs = gimple_assign_rhs1 (stmt);
-         gimple note
+         gdebug *note
            = gimple_build_debug_bind (lhs, unshare_expr (rhs), stmt);
          gsi_insert_after (i, note, GSI_SAME_STMT);
        }
@@ -1361,6 +1370,25 @@ eliminate_unnecessary_stmts (void)
          /* If GSI is not necessary then remove it.  */
          if (!gimple_plf (stmt, STMT_NECESSARY))
            {
+             /* Keep clobbers that we can keep live live.  */
+             if (gimple_clobber_p (stmt))
+               {
+                 ssa_op_iter iter;
+                 use_operand_p use_p;
+                 bool dead = false;
+                 FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE)
+                   {
+                     tree name = USE_FROM_PTR (use_p);
+                     if (!SSA_NAME_IS_DEFAULT_DEF (name)
+                         && !bitmap_bit_p (processed, SSA_NAME_VERSION (name)))
+                       {
+                         dead = true;
+                         break;
+                       }
+                   }
+                 if (!dead)
+                   continue;
+               }
              if (!is_gimple_debug (stmt))
                something_changed = true;
              remove_dead_stmt (&gsi, bb);
@@ -1369,7 +1397,7 @@ eliminate_unnecessary_stmts (void)
            {
              tree name = gimple_call_lhs (stmt);
 
-             notice_special_calls (stmt);
+             notice_special_calls (as_a <gcall *> (stmt));
 
              /* When LHS of var = call (); is dead, simplify it into
                 call (); saving one operand.  */
@@ -1402,6 +1430,11 @@ eliminate_unnecessary_stmts (void)
                  maybe_clean_or_replace_eh_stmt (stmt, stmt);
                  update_stmt (stmt);
                  release_ssa_name (name);
+
+                 /* GOMP_SIMD_LANE without lhs is not needed.  */
+                 if (gimple_call_internal_p (stmt)
+                     && gimple_call_internal_fn (stmt) == IFN_GOMP_SIMD_LANE)
+                   remove_dead_stmt (&gsi, bb);
                }
              else if (gimple_call_internal_p (stmt))
                switch (gimple_call_internal_fn (stmt))
@@ -1442,13 +1475,15 @@ eliminate_unnecessary_stmts (void)
          if (!bitmap_bit_p (bb_contains_live_stmts, bb->index)
              || !(bb->flags & BB_REACHABLE))
            {
-             for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
-               if (virtual_operand_p (gimple_phi_result (gsi_stmt (gsi))))
+             for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
+                  gsi_next (&gsi))
+               if (virtual_operand_p (gimple_phi_result (gsi.phi ())))
                  {
                    bool found = false;
                    imm_use_iterator iter;
 
-                   FOR_EACH_IMM_USE_STMT (stmt, iter, gimple_phi_result (gsi_stmt (gsi)))
+                   FOR_EACH_IMM_USE_STMT (stmt, iter,
+                                          gimple_phi_result (gsi.phi ()))
                      {
                        if (!(gimple_bb (stmt)->flags & BB_REACHABLE))
                          continue;
@@ -1460,7 +1495,7 @@ eliminate_unnecessary_stmts (void)
                          }
                      }
                    if (found)
-                     mark_virtual_phi_result_for_renaming (gsi_stmt (gsi));
+                     mark_virtual_phi_result_for_renaming (gsi.phi ());
                  }
 
              if (!(bb->flags & BB_REACHABLE))