]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/tree-call-cdce.c
Merge from trunk.
[thirdparty/gcc.git] / gcc / tree-call-cdce.c
index 273aed20a93e2d1a6f12f907909e8fd5f58a67b4..4c6aae7c484b0aaf09e4199fecede9e44c54e573 100644 (file)
@@ -1,6 +1,5 @@
 /* Conditional Dead Call Elimination pass for the GNU compiler.
-   Copyright (C) 2008, 2009, 2010
-   Free Software Foundation, Inc.
+   Copyright (C) 2008-2013 Free Software Foundation, Inc.
    Contributed by Xinliang David Li <davidxl@google.com>
 
 This file is part of GCC.
@@ -25,9 +24,15 @@ along with GCC; see the file COPYING3.  If not see
 #include "tm.h"
 #include "basic-block.h"
 #include "tree.h"
+#include "stor-layout.h"
 #include "gimple-pretty-print.h"
-#include "tree-flow.h"
 #include "gimple.h"
+#include "gimple-iterator.h"
+#include "gimple-ssa.h"
+#include "tree-cfg.h"
+#include "stringpool.h"
+#include "tree-ssanames.h"
+#include "tree-into-ssa.h"
 #include "tree-pass.h"
 #include "flags.h"
 \f
@@ -196,7 +201,7 @@ check_pow (gimple pow_call)
         return false;
       if (REAL_VALUES_LESS (bcv, dconst1))
         return false;
-      real_from_integer (&mv, TYPE_MODE (TREE_TYPE (base)), 256, 0, 1);
+      real_from_integer (&mv, TYPE_MODE (TREE_TYPE (base)), 256, UNSIGNED);
       if (REAL_VALUES_LESS (mv, bcv))
         return false;
       return true;
@@ -413,7 +418,7 @@ gen_conditions_for_pow_cst_base (tree base, tree expn,
   REAL_VALUE_TYPE bcv = TREE_REAL_CST (base);
   gcc_assert (!REAL_VALUES_EQUAL (bcv, dconst1)
               && !REAL_VALUES_LESS (bcv, dconst1));
-  real_from_integer (&mv, TYPE_MODE (TREE_TYPE (base)), 256, 0, 1);
+  real_from_integer (&mv, TYPE_MODE (TREE_TYPE (base)), 256, UNSIGNED);
   gcc_assert (!REAL_VALUES_LESS (mv, bcv));
 
   exp_domain = get_domain (0, false, false,
@@ -711,7 +716,6 @@ shrink_wrap_one_built_in_call (gimple bi_call)
   basic_block bi_call_bb, join_tgt_bb, guard_bb, guard_bb0;
   edge join_tgt_in_edge_from_call, join_tgt_in_edge_fall_thru;
   edge bi_call_in_edge0, guard_bb_in_edge;
-  vec<gimple> conds;
   unsigned tn_cond_stmts, nconds;
   unsigned ci;
   gimple cond_expr = NULL;
@@ -719,7 +723,7 @@ shrink_wrap_one_built_in_call (gimple bi_call)
   tree bi_call_label_decl;
   gimple bi_call_label;
 
-  conds.create (12);
+  stack_vec<gimple, 12> conds;
   gen_shrink_wrap_conditions (bi_call, conds, &nconds);
 
   /* This can happen if the condition generator decides
@@ -731,11 +735,18 @@ shrink_wrap_one_built_in_call (gimple bi_call)
 
   bi_call_bb = gimple_bb (bi_call);
 
-  /* Now find the join target bb -- split
-     bi_call_bb if needed.  */
-  bi_call_bsi = gsi_for_stmt (bi_call);
+  /* Now find the join target bb -- split bi_call_bb if needed.  */
+  if (stmt_ends_bb_p (bi_call))
+    {
+      /* If the call must be the last in the bb, don't split the block,
+        it could e.g. have EH edges.  */
+      join_tgt_in_edge_from_call = find_fallthru_edge (bi_call_bb->succs);
+      if (join_tgt_in_edge_from_call == NULL)
+        return false;
+    }
+  else
+    join_tgt_in_edge_from_call = split_block (bi_call_bb, bi_call);
 
-  join_tgt_in_edge_from_call = split_block (bi_call_bb, bi_call);
   bi_call_bsi = gsi_for_stmt (bi_call);
 
   join_tgt_bb = join_tgt_in_edge_from_call->dest;
@@ -817,7 +828,6 @@ shrink_wrap_one_built_in_call (gimple bi_call)
       guard_bb_in_edge->count = guard_bb->count - bi_call_in_edge->count;
     }
 
-  conds.release ();
   if (dump_file && (dump_flags & TDF_DETAILS))
     {
       location_t loc;
@@ -899,11 +909,10 @@ tree_call_cdce (void)
       /* As we introduced new control-flow we need to insert PHI-nodes
          for the call-clobbers of the remaining call.  */
       mark_virtual_operands_for_renaming (cfun);
-      return (TODO_update_ssa | TODO_cleanup_cfg | TODO_ggc_collect
-              | TODO_remove_unused_locals);
+      return TODO_update_ssa;
     }
-  else
-    return 0;
+
+  return 0;
 }
 
 static bool
@@ -915,22 +924,40 @@ gate_call_cdce (void)
   return flag_tree_builtin_call_dce != 0 && optimize_function_for_speed_p (cfun);
 }
 
-struct gimple_opt_pass pass_call_cdce =
+namespace {
+
+const pass_data pass_data_call_cdce =
 {
- {
-  GIMPLE_PASS,
-  "cdce",                               /* name */
-  OPTGROUP_NONE,                        /* optinfo_flags */
-  gate_call_cdce,                       /* gate */
-  tree_call_cdce,                       /* execute */
-  NULL,                                 /* sub */
-  NULL,                                 /* next */
-  0,                                    /* static_pass_number */
-  TV_TREE_CALL_CDCE,                    /* tv_id */
-  PROP_cfg | PROP_ssa,                  /* properties_required */
-  0,                                    /* properties_provided */
-  0,                                    /* properties_destroyed */
-  0,                                    /* todo_flags_start */
-  TODO_verify_ssa                       /* todo_flags_finish */
- }
+  GIMPLE_PASS, /* type */
+  "cdce", /* name */
+  OPTGROUP_NONE, /* optinfo_flags */
+  true, /* has_gate */
+  true, /* has_execute */
+  TV_TREE_CALL_CDCE, /* tv_id */
+  ( PROP_cfg | PROP_ssa ), /* properties_required */
+  0, /* properties_provided */
+  0, /* properties_destroyed */
+  0, /* todo_flags_start */
+  TODO_verify_ssa, /* todo_flags_finish */
 };
+
+class pass_call_cdce : public gimple_opt_pass
+{
+public:
+  pass_call_cdce (gcc::context *ctxt)
+    : gimple_opt_pass (pass_data_call_cdce, ctxt)
+  {}
+
+  /* opt_pass methods: */
+  bool gate () { return gate_call_cdce (); }
+  unsigned int execute () { return tree_call_cdce (); }
+
+}; // class pass_call_cdce
+
+} // anon namespace
+
+gimple_opt_pass *
+make_pass_call_cdce (gcc::context *ctxt)
+{
+  return new pass_call_cdce (ctxt);
+}