coretypes.h: Include input.h and as-a.h.
[platform/upstream/gcc.git] / gcc / tree-ssa-loop-ch.c
index 3845004..98534ba 100644 (file)
@@ -1,6 +1,5 @@
 /* Loop header copying on trees.
-   Copyright (C) 2004, 2005, 2006, 2007, 2008, 2010
-   Free Software Foundation, Inc.
+   Copyright (C) 2004-2015 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -22,17 +21,31 @@ 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 "tm_p.h"
+#include "predict.h"
+#include "hard-reg-set.h"
+#include "function.h"
+#include "dominance.h"
+#include "cfg.h"
 #include "basic-block.h"
-#include "tree-flow.h"
-#include "tree-dump.h"
+#include "tree-ssa-alias.h"
+#include "internal-fn.h"
+#include "gimple-expr.h"
+#include "gimple.h"
+#include "gimple-iterator.h"
+#include "gimple-ssa.h"
+#include "tree-cfg.h"
+#include "tree-into-ssa.h"
 #include "tree-pass.h"
-#include "timevar.h"
 #include "cfgloop.h"
 #include "tree-inline.h"
 #include "flags.h"
-#include "tree-inline.h"
+#include "tree-ssa-scopedtables.h"
+#include "tree-ssa-threadedge.h"
 
 /* Duplicates headers of loops if they are small enough, so that the statements
    in the loop body are always executed when the loop is entered.  This
@@ -103,7 +116,7 @@ should_duplicate_loop_header_p (basic_block header, struct loop *loop,
 
 /* Checks whether LOOP is a do-while style loop.  */
 
-bool
+static bool
 do_while_loop_p (struct loop *loop)
 {
   gimple stmt = last_stmt (loop->latch);
@@ -126,34 +139,58 @@ do_while_loop_p (struct loop *loop)
    of the loop.  This is beneficial since it increases efficiency of
    code motion optimizations.  It also saves one jump on entry to the loop.  */
 
-static unsigned int
-copy_loop_headers (void)
+namespace {
+
+const pass_data pass_data_ch =
+{
+  GIMPLE_PASS, /* type */
+  "ch", /* name */
+  OPTGROUP_LOOP, /* optinfo_flags */
+  TV_TREE_CH, /* tv_id */
+  ( PROP_cfg | PROP_ssa ), /* properties_required */
+  0, /* properties_provided */
+  0, /* properties_destroyed */
+  0, /* todo_flags_start */
+  0, /* todo_flags_finish */
+};
+
+class pass_ch : public gimple_opt_pass
+{
+public:
+  pass_ch (gcc::context *ctxt)
+    : gimple_opt_pass (pass_data_ch, ctxt)
+  {}
+
+  /* opt_pass methods: */
+  virtual bool gate (function *) { return flag_tree_ch != 0; }
+  virtual unsigned int execute (function *);
+
+}; // class pass_ch
+
+unsigned int
+pass_ch::execute (function *fun)
 {
-  loop_iterator li;
   struct loop *loop;
   basic_block header;
   edge exit, entry;
   basic_block *bbs, *copied_bbs;
   unsigned n_bbs;
   unsigned bbs_size;
+  bool changed = false;
 
   loop_optimizer_init (LOOPS_HAVE_PREHEADERS
                       | LOOPS_HAVE_SIMPLE_LATCHES);
-  if (number_of_loops () <= 1)
+  if (number_of_loops (fun) <= 1)
     {
       loop_optimizer_finalize ();
       return 0;
     }
 
-#ifdef ENABLE_CHECKING
-  verify_loop_structure ();
-#endif
-
-  bbs = XNEWVEC (basic_block, n_basic_blocks);
-  copied_bbs = XNEWVEC (basic_block, n_basic_blocks);
-  bbs_size = n_basic_blocks;
+  bbs = XNEWVEC (basic_block, n_basic_blocks_for_fn (fun));
+  copied_bbs = XNEWVEC (basic_block, n_basic_blocks_for_fn (fun));
+  bbs_size = n_basic_blocks_for_fn (fun);
 
-  FOR_EACH_LOOP (li, loop, 0)
+  FOR_EACH_LOOP (loop, 0)
     {
       /* Copy at most 20 insns.  */
       int limit = 20;
@@ -203,7 +240,9 @@ copy_loop_headers (void)
 
       entry = loop_preheader_edge (loop);
 
-      if (!gimple_duplicate_sese_region (entry, exit, bbs, n_bbs, copied_bbs))
+      propagate_threaded_block_debug_into (exit->dest, entry->dest);
+      if (!gimple_duplicate_sese_region (entry, exit, bbs, n_bbs, copied_bbs,
+                                        true))
        {
          fprintf (dump_file, "Duplication failed.\n");
          continue;
@@ -245,38 +284,22 @@ copy_loop_headers (void)
         are not now, since there was the loop exit condition.  */
       split_edge (loop_preheader_edge (loop));
       split_edge (loop_latch_edge (loop));
+
+      changed = true;
     }
 
+  update_ssa (TODO_update_ssa);
   free (bbs);
   free (copied_bbs);
 
   loop_optimizer_finalize ();
-  return 0;
+  return changed ? TODO_cleanup_cfg : 0;
 }
 
-static bool
-gate_ch (void)
-{
-  return flag_tree_ch != 0;
-}
+} // anon namespace
 
-struct gimple_opt_pass pass_ch =
+gimple_opt_pass *
+make_pass_ch (gcc::context *ctxt)
 {
- {
-  GIMPLE_PASS,
-  "ch",                                        /* name */
-  gate_ch,                             /* gate */
-  copy_loop_headers,                   /* execute */
-  NULL,                                        /* sub */
-  NULL,                                        /* next */
-  0,                                   /* static_pass_number */
-  TV_TREE_CH,                          /* tv_id */
-  PROP_cfg | PROP_ssa,                 /* properties_required */
-  0,                                   /* properties_provided */
-  0,                                   /* properties_destroyed */
-  0,                                   /* todo_flags_start */
-  TODO_cleanup_cfg
-    | TODO_verify_ssa
-    | TODO_verify_flow                 /* todo_flags_finish */
- }
-};
+  return new pass_ch (ctxt);
+}