OSDN Git Service

2009-07-13 Kai Tietz <kai.tietz@onevision.com>
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-loop.c
index 816be15..0aab6d3 100644 (file)
@@ -1,11 +1,11 @@
 /* Loop optimizations over tree-ssa.
 /* Loop optimizations over tree-ssa.
-   Copyright (C) 2003 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
    
 This file is part of GCC.
    
 GCC is free software; you can redistribute it and/or modify it
 under the terms of the GNU General Public License as published by the
    
 This file is part of GCC.
    
 GCC is free software; you can redistribute it and/or modify it
 under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2, or (at your option) any
+Free Software Foundation; either version 3, or (at your option) any
 later version.
    
 GCC is distributed in the hope that it will be useful, but WITHOUT
 later version.
    
 GCC is distributed in the hope that it will be useful, but WITHOUT
@@ -14,9 +14,8 @@ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 for more details.
    
 You should have received a copy of the GNU General Public License
 for more details.
    
 You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 #include "config.h"
 #include "system.h"
 
 #include "config.h"
 #include "system.h"
@@ -29,7 +28,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "basic-block.h"
 #include "output.h"
 #include "diagnostic.h"
 #include "basic-block.h"
 #include "output.h"
 #include "diagnostic.h"
-#include "basic-block.h"
 #include "tree-flow.h"
 #include "tree-dump.h"
 #include "tree-pass.h"
 #include "tree-flow.h"
 #include "tree-dump.h"
 #include "tree-pass.h"
@@ -37,44 +35,23 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "cfgloop.h"
 #include "flags.h"
 #include "tree-inline.h"
 #include "cfgloop.h"
 #include "flags.h"
 #include "tree-inline.h"
-
-/* The loop tree currently optimized.  */
-
-struct loops *current_loops;
-
-/* Initializes the loop structures.  DUMP is the file to that the details
-   about the analysis should be dumped.  */
-
-static struct loops *
-tree_loop_optimizer_init (FILE *dump)
-{
-  struct loops *loops = loop_optimizer_init (dump);
-
-  if (!loops)
-    return NULL;
-
-  /* Creation of preheaders may create redundant phi nodes if the loop is
-     entered by more than one edge, but the initial value of the induction
-     variable is the same on all of them.  */
-  kill_redundant_phi_nodes ();
-  rewrite_into_ssa (false);
-  bitmap_clear (vars_to_rename);
-
-  return loops;
-}
+#include "tree-scalar-evolution.h"
+#include "tree-vectorizer.h"
 
 /* The loop superpass.  */
 
 static bool
 
 /* The loop superpass.  */
 
 static bool
-gate_loop (void)
+gate_tree_loop (void)
 {
   return flag_tree_loop_optimize != 0;
 }
 
 {
   return flag_tree_loop_optimize != 0;
 }
 
-struct tree_opt_pass pass_loop = 
+struct gimple_opt_pass pass_tree_loop = 
 {
 {
+ {
+  GIMPLE_PASS,
   "loop",                              /* name */
   "loop",                              /* name */
-  gate_loop,                           /* gate */
+  gate_tree_loop,                      /* gate */
   NULL,                                        /* execute */
   NULL,                                        /* sub */
   NULL,                                        /* next */
   NULL,                                        /* execute */
   NULL,                                        /* sub */
   NULL,                                        /* next */
@@ -85,51 +62,66 @@ struct tree_opt_pass pass_loop =
   0,                                   /* properties_destroyed */
   TODO_ggc_collect,                    /* todo_flags_start */
   TODO_dump_func | TODO_verify_ssa | TODO_ggc_collect  /* todo_flags_finish */
   0,                                   /* properties_destroyed */
   TODO_ggc_collect,                    /* todo_flags_start */
   TODO_dump_func | TODO_verify_ssa | TODO_ggc_collect  /* todo_flags_finish */
+ }
 };
 
 /* Loop optimizer initialization.  */
 
 };
 
 /* Loop optimizer initialization.  */
 
-static void
+static unsigned int
 tree_ssa_loop_init (void)
 {
 tree_ssa_loop_init (void)
 {
-  current_loops = tree_loop_optimizer_init (dump_file);
+  loop_optimizer_init (LOOPS_NORMAL
+                      | LOOPS_HAVE_RECORDED_EXITS);
+  rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa);
+
+  if (number_of_loops () <= 1)
+    return 0;
+
+  scev_initialize ();
+  return 0;
 }
   
 }
   
-struct tree_opt_pass pass_loop_init = 
+struct gimple_opt_pass pass_tree_loop_init = 
 {
 {
+ {
+  GIMPLE_PASS,
   "loopinit",                          /* name */
   NULL,                                        /* gate */
   tree_ssa_loop_init,                  /* execute */
   NULL,                                        /* sub */
   NULL,                                        /* next */
   0,                                   /* static_pass_number */
   "loopinit",                          /* name */
   NULL,                                        /* gate */
   tree_ssa_loop_init,                  /* execute */
   NULL,                                        /* sub */
   NULL,                                        /* next */
   0,                                   /* static_pass_number */
-  0,                                   /* tv_id */
+  TV_TREE_LOOP_INIT,                   /* tv_id */
   PROP_cfg,                            /* properties_required */
   0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
   PROP_cfg,                            /* properties_required */
   0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
-  0                                    /* todo_flags_finish */
+  TODO_dump_func | TODO_verify_loops   /* todo_flags_finish */
+ }
 };
 
 /* Loop invariant motion pass.  */
 
 };
 
 /* Loop invariant motion pass.  */
 
-static void
+static unsigned int
 tree_ssa_loop_im (void)
 {
 tree_ssa_loop_im (void)
 {
-  if (!current_loops)
-    return;
+  if (number_of_loops () <= 1)
+    return 0;
 
 
-  tree_ssa_lim (current_loops);
+  tree_ssa_lim ();
+  return 0;
 }
 
 static bool
 gate_tree_ssa_loop_im (void)
 {
 }
 
 static bool
 gate_tree_ssa_loop_im (void)
 {
-  return flag_tree_lim != 0;
+  return flag_tree_loop_im != 0;
 }
 
 }
 
-struct tree_opt_pass pass_lim = 
+struct gimple_opt_pass pass_lim = 
 {
 {
+ {
+  GIMPLE_PASS,
   "lim",                               /* name */
   gate_tree_ssa_loop_im,               /* gate */
   tree_ssa_loop_im,                    /* execute */
   "lim",                               /* name */
   gate_tree_ssa_loop_im,               /* gate */
   tree_ssa_loop_im,                    /* execute */
@@ -141,36 +133,563 @@ struct tree_opt_pass pass_lim =
   0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
   0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
+  TODO_dump_func | TODO_verify_loops   /* todo_flags_finish */
+ }
+};
+
+/* Loop unswitching pass.  */
+
+static unsigned int
+tree_ssa_loop_unswitch (void)
+{
+  if (number_of_loops () <= 1)
+    return 0;
+
+  return tree_ssa_unswitch_loops ();
+}
+
+static bool
+gate_tree_ssa_loop_unswitch (void)
+{
+  return flag_unswitch_loops != 0;
+}
+
+struct gimple_opt_pass pass_tree_unswitch = 
+{
+ {
+  GIMPLE_PASS,
+  "unswitch",                          /* name */
+  gate_tree_ssa_loop_unswitch,         /* gate */
+  tree_ssa_loop_unswitch,              /* execute */
+  NULL,                                        /* sub */
+  NULL,                                        /* next */
+  0,                                   /* static_pass_number */
+  TV_TREE_LOOP_UNSWITCH,               /* tv_id */
+  PROP_cfg,                            /* properties_required */
+  0,                                   /* properties_provided */
+  0,                                   /* properties_destroyed */
+  0,                                   /* todo_flags_start */
+  TODO_ggc_collect | TODO_dump_func
+    | TODO_verify_loops                        /* todo_flags_finish */
+ }
+};
+
+/* Predictive commoning.  */
+
+static unsigned
+run_tree_predictive_commoning (void)
+{
+  if (!current_loops)
+    return 0;
+
+  tree_predictive_commoning ();
+  return 0;
+}
+
+static bool
+gate_tree_predictive_commoning (void)
+{
+  return flag_predictive_commoning != 0;
+}
+
+struct gimple_opt_pass pass_predcom = 
+{
+ {
+  GIMPLE_PASS,
+  "pcom",                              /* name */
+  gate_tree_predictive_commoning,      /* gate */
+  run_tree_predictive_commoning,       /* execute */
+  NULL,                                        /* sub */
+  NULL,                                        /* next */
+  0,                                   /* static_pass_number */
+  TV_PREDCOM,                          /* tv_id */
+  PROP_cfg,                            /* properties_required */
+  0,                                   /* properties_provided */
+  0,                                   /* properties_destroyed */
+  0,                                   /* todo_flags_start */
+  TODO_dump_func | TODO_verify_loops
+    | TODO_update_ssa_only_virtuals    /* todo_flags_finish */
+ }
+};
+
+/* Loop autovectorization.  */
+
+static unsigned int
+tree_vectorize (void)
+{
+  if (number_of_loops () <= 1)
+    return 0;
+
+  return vectorize_loops ();
+}
+
+static bool
+gate_tree_vectorize (void)
+{
+  return flag_tree_vectorize;
+}
+
+struct gimple_opt_pass pass_vectorize =
+{
+ {
+  GIMPLE_PASS,
+  "vect",                               /* name */
+  gate_tree_vectorize,                  /* gate */
+  tree_vectorize,                       /* execute */
+  NULL,                                 /* sub */
+  NULL,                                 /* next */
+  0,                                    /* static_pass_number */
+  TV_TREE_VECTORIZATION,                /* tv_id */
+  PROP_cfg | PROP_ssa,                  /* properties_required */
+  0,                                    /* properties_provided */
+  0,                                    /* properties_destroyed */
+  TODO_verify_loops,                   /* todo_flags_start */
+  TODO_dump_func | TODO_update_ssa
+    | TODO_ggc_collect                 /* todo_flags_finish */
+ }
+};
+
+/* Loop nest optimizations.  */
+
+static unsigned int
+tree_linear_transform (void)
+{
+  if (number_of_loops () <= 1)
+    return 0;
+
+  linear_transform_loops ();
+  return 0;
+}
+
+static bool
+gate_tree_linear_transform (void)
+{
+  return flag_tree_loop_linear != 0;
+}
+
+struct gimple_opt_pass pass_linear_transform =
+{
+ {
+  GIMPLE_PASS,
+  "ltrans",                            /* name */
+  gate_tree_linear_transform,          /* gate */
+  tree_linear_transform,                       /* execute */
+  NULL,                                        /* sub */
+  NULL,                                        /* next */
+  0,                                   /* static_pass_number */
+  TV_TREE_LINEAR_TRANSFORM,            /* tv_id */
+  PROP_cfg | PROP_ssa,                 /* properties_required */
+  0,                                   /* properties_provided */
+  0,                                   /* properties_destroyed */
+  0,                                   /* todo_flags_start */
+  TODO_dump_func | TODO_verify_loops
+    | TODO_update_ssa_only_virtuals
+    | TODO_ggc_collect                 /* todo_flags_finish */
+ }
+};
+
+/* GRAPHITE optimizations.  */
+
+static unsigned int
+graphite_transforms (void)
+{
+  if (!current_loops)
+    return 0;
+
+  graphite_transform_loops ();
+
+  return 0;
+}
+
+static bool
+gate_graphite_transforms (void)
+{
+  /* Enable -fgraphite pass if any one of the graphite optimization flags 
+     is turned on.  */
+  if (flag_loop_block || flag_loop_interchange || flag_loop_strip_mine
+      || flag_graphite_identity)
+    flag_graphite = 1;
+
+  return flag_graphite != 0;
+}
+
+struct gimple_opt_pass pass_graphite_transforms =
+{
+ {
+  GIMPLE_PASS,
+  "graphite",                          /* name */
+  gate_graphite_transforms,            /* gate */
+  graphite_transforms,                 /* execute */
+  NULL,                                        /* sub */
+  NULL,                                        /* next */
+  0,                                   /* static_pass_number */
+  TV_GRAPHITE_TRANSFORMS,              /* tv_id */
+  PROP_cfg | PROP_ssa,                 /* properties_required */
+  0,                                   /* properties_provided */
+  0,                                   /* properties_destroyed */
+  0,                                   /* todo_flags_start */
+  TODO_verify_loops                    /* todo_flags_finish */
+ }
+};
+
+/* Check the correctness of the data dependence analyzers.  */
+
+static unsigned int
+check_data_deps (void)
+{
+  if (number_of_loops () <= 1)
+    return 0;
+
+  tree_check_data_deps ();
+  return 0;
+}
+
+static bool
+gate_check_data_deps (void)
+{
+  return flag_check_data_deps != 0;
+}
+
+struct gimple_opt_pass pass_check_data_deps =
+{
+ {
+  GIMPLE_PASS,
+  "ckdd",                              /* name */
+  gate_check_data_deps,                        /* gate */
+  check_data_deps,                     /* execute */
+  NULL,                                        /* sub */
+  NULL,                                        /* next */
+  0,                                   /* static_pass_number */
+  TV_CHECK_DATA_DEPS,                          /* tv_id */
+  PROP_cfg | PROP_ssa,                 /* properties_required */
+  0,                                   /* properties_provided */
+  0,                                   /* properties_destroyed */
+  0,                                   /* todo_flags_start */
   TODO_dump_func                       /* todo_flags_finish */
   TODO_dump_func                       /* todo_flags_finish */
+ }
+};
+
+/* Canonical induction variable creation pass.  */
+
+static unsigned int
+tree_ssa_loop_ivcanon (void)
+{
+  if (number_of_loops () <= 1)
+    return 0;
+
+  return canonicalize_induction_variables ();
+}
+
+static bool
+gate_tree_ssa_loop_ivcanon (void)
+{
+  return flag_tree_loop_ivcanon != 0;
+}
+
+struct gimple_opt_pass pass_iv_canon =
+{
+ {
+  GIMPLE_PASS,
+  "ivcanon",                           /* name */
+  gate_tree_ssa_loop_ivcanon,          /* gate */
+  tree_ssa_loop_ivcanon,               /* execute */
+  NULL,                                        /* sub */
+  NULL,                                        /* next */
+  0,                                   /* static_pass_number */
+  TV_TREE_LOOP_IVCANON,                        /* tv_id */
+  PROP_cfg | PROP_ssa,                 /* properties_required */
+  0,                                   /* properties_provided */
+  0,                                   /* properties_destroyed */
+  0,                                   /* todo_flags_start */
+  TODO_dump_func | TODO_verify_loops   /* todo_flags_finish */
+ }
+};
+
+/* Propagation of constants using scev.  */
+
+static bool
+gate_scev_const_prop (void)
+{
+  return flag_tree_scev_cprop;
+}
+
+struct gimple_opt_pass pass_scev_cprop =
+{
+ {
+  GIMPLE_PASS,
+  "sccp",                              /* name */
+  gate_scev_const_prop,                        /* gate */
+  scev_const_prop,                     /* execute */
+  NULL,                                        /* sub */
+  NULL,                                        /* next */
+  0,                                   /* static_pass_number */
+  TV_SCEV_CONST,                       /* tv_id */
+  PROP_cfg | PROP_ssa,                 /* properties_required */
+  0,                                   /* properties_provided */
+  0,                                   /* properties_destroyed */
+  0,                                   /* todo_flags_start */
+  TODO_dump_func | TODO_cleanup_cfg
+    | TODO_update_ssa_only_virtuals
+                                       /* todo_flags_finish */
+ }
+};
+
+/* Record bounds on numbers of iterations of loops.  */
+
+static unsigned int
+tree_ssa_loop_bounds (void)
+{
+  if (number_of_loops () <= 1)
+    return 0;
+
+  estimate_numbers_of_iterations ();
+  scev_reset ();
+  return 0;
+}
+
+struct gimple_opt_pass pass_record_bounds =
+{
+ {
+  GIMPLE_PASS,
+  NULL,                                        /* name */
+  NULL,                                        /* gate */
+  tree_ssa_loop_bounds,                        /* execute */
+  NULL,                                        /* sub */
+  NULL,                                        /* next */
+  0,                                   /* static_pass_number */
+  TV_TREE_LOOP_BOUNDS,                 /* tv_id */
+  PROP_cfg | PROP_ssa,                 /* properties_required */
+  0,                                   /* properties_provided */
+  0,                                   /* properties_destroyed */
+  0,                                   /* todo_flags_start */
+  0                                    /* todo_flags_finish */
+ }
+};
+
+/* Complete unrolling of loops.  */
+
+static unsigned int
+tree_complete_unroll (void)
+{
+  if (number_of_loops () <= 1)
+    return 0;
+
+  return tree_unroll_loops_completely (flag_unroll_loops
+                                      || flag_peel_loops
+                                      || optimize >= 3, true);
+}
+
+static bool
+gate_tree_complete_unroll (void)
+{
+  return true;
+}
+
+struct gimple_opt_pass pass_complete_unroll =
+{
+ {
+  GIMPLE_PASS,
+  "cunroll",                           /* name */
+  gate_tree_complete_unroll,           /* gate */
+  tree_complete_unroll,                        /* execute */
+  NULL,                                        /* sub */
+  NULL,                                        /* next */
+  0,                                   /* static_pass_number */
+  TV_COMPLETE_UNROLL,                  /* tv_id */
+  PROP_cfg | PROP_ssa,                 /* properties_required */
+  0,                                   /* properties_provided */
+  0,                                   /* properties_destroyed */
+  0,                                   /* todo_flags_start */
+  TODO_dump_func | TODO_verify_loops
+    | TODO_ggc_collect                 /* todo_flags_finish */
+ }
+};
+
+/* Complete unrolling of inner loops.  */
+
+static unsigned int
+tree_complete_unroll_inner (void)
+{
+  unsigned ret = 0;
+
+  loop_optimizer_init (LOOPS_NORMAL
+                      | LOOPS_HAVE_RECORDED_EXITS);
+  if (number_of_loops () > 1)
+    {
+      scev_initialize ();
+      ret = tree_unroll_loops_completely (optimize >= 3, false);
+      free_numbers_of_iterations_estimates ();
+      scev_finalize ();
+    }
+  loop_optimizer_finalize ();
+
+  return ret;
+}
+
+static bool
+gate_tree_complete_unroll_inner (void)
+{
+  return optimize >= 2;
+}
+
+struct gimple_opt_pass pass_complete_unrolli =
+{
+ {
+  GIMPLE_PASS,
+  "cunrolli",                          /* name */
+  gate_tree_complete_unroll_inner,     /* gate */
+  tree_complete_unroll_inner,          /* execute */
+  NULL,                                        /* sub */
+  NULL,                                        /* next */
+  0,                                   /* static_pass_number */
+  TV_COMPLETE_UNROLL,                  /* tv_id */
+  PROP_cfg | PROP_ssa,                 /* properties_required */
+  0,                                   /* properties_provided */
+  0,                                   /* properties_destroyed */
+  0,                                   /* todo_flags_start */
+  TODO_dump_func | TODO_verify_loops
+    | TODO_ggc_collect                         /* todo_flags_finish */
+ }
+};
+
+/* Parallelization.  */
+
+static bool
+gate_tree_parallelize_loops (void)
+{
+  return flag_tree_parallelize_loops > 1;
+}
+
+static unsigned
+tree_parallelize_loops (void)
+{
+  if (number_of_loops () <= 1)
+    return 0;
+
+  if (parallelize_loops ())
+    return TODO_cleanup_cfg | TODO_rebuild_alias;
+  return 0;
+}
+
+struct gimple_opt_pass pass_parallelize_loops =
+{
+ {
+  GIMPLE_PASS,
+  "parloops",                          /* name */
+  gate_tree_parallelize_loops,         /* gate */
+  tree_parallelize_loops,                      /* execute */
+  NULL,                                        /* sub */
+  NULL,                                        /* next */
+  0,                                   /* static_pass_number */
+  TV_TREE_PARALLELIZE_LOOPS,           /* tv_id */
+  PROP_cfg | PROP_ssa,                 /* properties_required */
+  0,                                   /* properties_provided */
+  0,                                   /* properties_destroyed */
+  0,                                   /* todo_flags_start */
+  TODO_dump_func | TODO_verify_loops   /* todo_flags_finish */
+ }
+};
+
+/* Prefetching.  */
+
+static unsigned int
+tree_ssa_loop_prefetch (void)
+{
+  if (number_of_loops () <= 1)
+    return 0;
+
+  return tree_ssa_prefetch_arrays ();
+}
+
+static bool
+gate_tree_ssa_loop_prefetch (void)
+{
+  return flag_prefetch_loop_arrays != 0;
+}
+
+struct gimple_opt_pass pass_loop_prefetch =
+{
+ {
+  GIMPLE_PASS,
+  "aprefetch",                         /* name */
+  gate_tree_ssa_loop_prefetch,         /* gate */
+  tree_ssa_loop_prefetch,              /* execute */
+  NULL,                                        /* sub */
+  NULL,                                        /* next */
+  0,                                   /* static_pass_number */
+  TV_TREE_PREFETCH,                    /* tv_id */
+  PROP_cfg | PROP_ssa,                 /* properties_required */
+  0,                                   /* properties_provided */
+  0,                                   /* properties_destroyed */
+  0,                                   /* todo_flags_start */
+  TODO_dump_func | TODO_verify_loops   /* todo_flags_finish */
+ }
+};
+
+/* Induction variable optimizations.  */
+
+static unsigned int
+tree_ssa_loop_ivopts (void)
+{
+  if (number_of_loops () <= 1)
+    return 0;
+
+  tree_ssa_iv_optimize ();
+  return 0;
+}
+
+static bool
+gate_tree_ssa_loop_ivopts (void)
+{
+  return flag_ivopts != 0;
+}
+
+struct gimple_opt_pass pass_iv_optimize =
+{
+ {
+  GIMPLE_PASS,
+  "ivopts",                            /* name */
+  gate_tree_ssa_loop_ivopts,           /* gate */
+  tree_ssa_loop_ivopts,                        /* execute */
+  NULL,                                        /* sub */
+  NULL,                                        /* next */
+  0,                                   /* static_pass_number */
+  TV_TREE_LOOP_IVOPTS,                 /* tv_id */
+  PROP_cfg | PROP_ssa,                 /* properties_required */
+  0,                                   /* properties_provided */
+  0,                                   /* properties_destroyed */
+  0,                                   /* todo_flags_start */
+  TODO_dump_func | TODO_verify_loops
+  | TODO_update_ssa | TODO_ggc_collect /* todo_flags_finish */
+ }
 };
 
 /* Loop optimizer finalization.  */
 
 };
 
 /* Loop optimizer finalization.  */
 
-static void
+static unsigned int
 tree_ssa_loop_done (void)
 {
 tree_ssa_loop_done (void)
 {
-  if (!current_loops)
-    return;
-
-  loop_optimizer_finalize (current_loops,
-                          (dump_flags & TDF_DETAILS ? dump_file : NULL));
-  current_loops = NULL;
-  cleanup_tree_cfg ();
+  free_numbers_of_iterations_estimates ();
+  scev_finalize ();
+  loop_optimizer_finalize ();
+  return 0;
 }
   
 }
   
-struct tree_opt_pass pass_loop_done = 
+struct gimple_opt_pass pass_tree_loop_done = 
 {
 {
+ {
+  GIMPLE_PASS,
   "loopdone",                          /* name */
   NULL,                                        /* gate */
   tree_ssa_loop_done,                  /* execute */
   NULL,                                        /* sub */
   NULL,                                        /* next */
   0,                                   /* static_pass_number */
   "loopdone",                          /* name */
   NULL,                                        /* gate */
   tree_ssa_loop_done,                  /* execute */
   NULL,                                        /* sub */
   NULL,                                        /* next */
   0,                                   /* static_pass_number */
-  0,                                   /* tv_id */
+  TV_TREE_LOOP_FINI,                   /* tv_id */
   PROP_cfg,                            /* properties_required */
   0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
   PROP_cfg,                            /* properties_required */
   0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
-  0                                    /* todo_flags_finish */
+  TODO_cleanup_cfg | TODO_dump_func    /* todo_flags_finish */
+ }
 };
 };
-