diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index e8a26efe66d64786a4581b612175af1930600436..93a10d71d78c4f4a5c922422121e20a3f45725f4 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,24 @@
+2006-02-04  Zdenek Dvorak <dvorakz@suse.cz>
+
+	* tree-vrp.c (cfg_loops): Removed.
+	(adjust_range_with_scev, vrp_visit_assignment, execute_vrp):
+	Use current_loops instead of cfg_loops.  Pass flags to
+	loop_optimizer_init.
+	* cfgloopmanip.c (fix_loop_structure): Update only available
+	information.
+	* tree-ssa-loop-ch.c (copy_loop_headers): Pass flags to
+	loop_optimizer_init.
+	* modulo-sched.c (build_loops_structure): Removed.
+	(sms_schedule): Use loop_optimizer_init.
+	* loop-init.c (loop_optimizer_init): Use flags to determine
+	which properties of loops to prepare.
+	(rtl_loop_init): Pass flags to loop_optimizer_init.
+	* tree-ssa-sink.c (execute_sink_code): Ditto.
+	* tree-ssa-loop.c (tree_loop_optimizer_init): Ditto.
+	* tree-ssa-pre.c (init_pre): Ditto.
+	* cfgloop.h (LOOPS_NORMAL): New.
+	(loop_optimizer_init): Declaration changed.
+
 2006-02-05  John David Anglin  <dave.anglin@nrc-cnrc.gc.ca>
 
 	* pa/x-ada-hpux10, pa/t-pa-hpux10, pa/t-pa-hpux11: New files.
diff --git a/gcc/cfgloop.h b/gcc/cfgloop.h
index 5bbde8b576d5b853cee7459aa198effaed1b9cc2..9e573849195ef0fc7f6e14b4cea3188ab58ebd03 100644
--- a/gcc/cfgloop.h
+++ b/gcc/cfgloop.h
@@ -185,6 +185,9 @@ enum
   LOOPS_HAVE_MARKED_SINGLE_EXITS = 8
 };
 
+#define LOOPS_NORMAL (LOOPS_HAVE_PREHEADERS | LOOPS_HAVE_SIMPLE_LATCHES \
+		      | LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS)
+
 /* Structure to hold CFG information about natural loops within a function.  */
 struct loops
 {
@@ -434,7 +437,7 @@ extern unsigned global_cost_for_size (unsigned, unsigned, unsigned);
 extern void init_set_costs (void);
 
 /* Loop optimizer initialization.  */
-extern struct loops *loop_optimizer_init (FILE *);
+extern struct loops *loop_optimizer_init (FILE *, unsigned);
 extern void loop_optimizer_finalize (struct loops *, FILE *);
 
 /* Optimization passes.  */
diff --git a/gcc/cfgloopmanip.c b/gcc/cfgloopmanip.c
index ac2a75b0b29c46c5d0e42ac13f01995a12bcb8a7..bb7aca0faebdd060ddf63705b987bd6b4ab1c123 100644
--- a/gcc/cfgloopmanip.c
+++ b/gcc/cfgloopmanip.c
@@ -1617,6 +1617,8 @@ fix_loop_structure (struct loops *loops, bitmap changed_bbs)
       bb->aux = NULL;
     }
 
-  mark_single_exit_loops (loops);
-  mark_irreducible_loops (loops);
+  if (loops->state & LOOPS_HAVE_MARKED_SINGLE_EXITS)
+    mark_single_exit_loops (loops);
+  if (loops->state & LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS)
+    mark_irreducible_loops (loops);
 }
diff --git a/gcc/loop-init.c b/gcc/loop-init.c
index d44575b983dd38d50931a6b9c86d8646a2b44113..d6c370314cccb0ede847c7c5ebb0000c16b436d8 100644
--- a/gcc/loop-init.c
+++ b/gcc/loop-init.c
@@ -34,10 +34,11 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 
 
 /* Initialize loop optimizer.  This is used by the tree and RTL loop
-   optimizers.  */
+   optimizers.  FLAGS specify what properties to compute and/or ensure for
+   loops.  */
 
 struct loops *
-loop_optimizer_init (FILE *dumpfile)
+loop_optimizer_init (FILE *dumpfile, unsigned flags)
 {
   struct loops *loops = XCNEW (struct loops);
   edge e;
@@ -77,13 +78,19 @@ loop_optimizer_init (FILE *dumpfile)
   loops->cfg.dfs_order = NULL;
 
   /* Create pre-headers.  */
-  create_preheaders (loops, CP_SIMPLE_PREHEADERS);
+  if (flags & LOOPS_HAVE_PREHEADERS)
+    create_preheaders (loops, CP_SIMPLE_PREHEADERS);
 
   /* Force all latches to have only single successor.  */
-  force_single_succ_latches (loops);
+  if (flags & LOOPS_HAVE_SIMPLE_LATCHES)
+    force_single_succ_latches (loops);
 
   /* Mark irreducible loops.  */
-  mark_irreducible_loops (loops);
+  if (flags & LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS)
+    mark_irreducible_loops (loops);
+
+  if (flags & LOOPS_HAVE_MARKED_SINGLE_EXITS)
+    mark_single_exit_loops (loops);
 
   /* Dump loops.  */
   flow_loops_dump (loops, dumpfile, NULL, 1);
@@ -166,7 +173,7 @@ rtl_loop_init (void)
   /* Initialize structures for layout changes.  */
   cfg_layout_initialize (0);
 
-  current_loops = loop_optimizer_init (dump_file);
+  current_loops = loop_optimizer_init (dump_file, LOOPS_NORMAL);
 }
 
 struct tree_opt_pass pass_rtl_loop_init =
diff --git a/gcc/modulo-sched.c b/gcc/modulo-sched.c
index f76bcfdab441329571af5da21933519bc728a826..52190e0e777bf09b5aec701a68a58656b8b51b91 100644
--- a/gcc/modulo-sched.c
+++ b/gcc/modulo-sched.c
@@ -894,44 +894,6 @@ canon_loop (struct loop *loop)
     }
 }
 
-/* Build the loop information without loop
-   canonization, the loop canonization will
-   be performed if the loop is SMSable.  */
-static struct loops *
-build_loops_structure (FILE *dumpfile)
-{
-  struct loops *loops = XCNEW (struct loops);
-
-  /* Find the loops.  */
-
-  if (flow_loops_find (loops) <= 1)
-    {
-      /* No loops.  */
-      flow_loops_free (loops);
-      free (loops);
-
-      return NULL;
-    }
-
-  /* Not going to update these.  */
-  free (loops->cfg.rc_order);
-  loops->cfg.rc_order = NULL;
-  free (loops->cfg.dfs_order);
-  loops->cfg.dfs_order = NULL;
-
-  create_preheaders (loops, CP_SIMPLE_PREHEADERS);
-  mark_single_exit_loops (loops);
-  /* Dump loops.  */
-  flow_loops_dump (loops, dumpfile, NULL, 1);
-
-#ifdef ENABLE_CHECKING
-  verify_dominators (CDI_DOMINATORS);
-  verify_loop_structure (loops);
-#endif
-
-  return loops;
-}
-
 /* Main entry point, perform SMS scheduling on the loops of the function
    that consist of single basic blocks.  */
 static void
@@ -953,10 +915,11 @@ sms_schedule (FILE *dump_file)
   edge latch_edge;
   gcov_type trip_count = 0;
 
-  if (! (loops = build_loops_structure (dump_file)))
+  loops = loop_optimizer_init (dump_file, (LOOPS_HAVE_PREHEADERS
+					   | LOOPS_HAVE_MARKED_SINGLE_EXITS));
+  if (!loops)
     return;  /* There is no loops to schedule.  */
 
-
   stats_file = dump_file;
 
   /* Initialize issue_rate.  */
diff --git a/gcc/tree-ssa-loop-ch.c b/gcc/tree-ssa-loop-ch.c
index 7d8870cfed4094512e76ef4afe4839ffb4dce3a9..b9d1ce95058262ad5fc23e38141cb531fb1555b3 100644
--- a/gcc/tree-ssa-loop-ch.c
+++ b/gcc/tree-ssa-loop-ch.c
@@ -132,13 +132,10 @@ copy_loop_headers (void)
   unsigned n_bbs;
   unsigned bbs_size;
 
-  loops = loop_optimizer_init (dump_file);
+  loops = loop_optimizer_init (dump_file, (LOOPS_HAVE_PREHEADERS
+					   | LOOPS_HAVE_SIMPLE_LATCHES));
   if (!loops)
     return;
-  
-  /* We do not try to keep the information about irreducible regions
-     up-to-date.  */
-  loops->state &= ~LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS;
 
 #ifdef ENABLE_CHECKING
   verify_loop_structure (loops);
diff --git a/gcc/tree-ssa-loop.c b/gcc/tree-ssa-loop.c
index 8565f255223addb667aca9f135394952e54f4144..b776d0fb3a65ebadfb7f5ab97d0baa8c37d1ca05 100644
--- a/gcc/tree-ssa-loop.c
+++ b/gcc/tree-ssa-loop.c
@@ -48,7 +48,10 @@ struct loops *current_loops = NULL;
 static struct loops *
 tree_loop_optimizer_init (FILE *dump)
 {
-  struct loops *loops = loop_optimizer_init (dump);
+  struct loops *loops;
+ 
+  loops = loop_optimizer_init (dump, (LOOPS_NORMAL
+				      | LOOPS_HAVE_MARKED_SINGLE_EXITS));
 
   if (!loops)
     return NULL;
@@ -92,9 +95,6 @@ tree_ssa_loop_init (void)
   if (!current_loops)
     return;
 
-  /* Find the loops that are exited just through a single edge.  */
-  mark_single_exit_loops (current_loops);
-
   scev_initialize (current_loops);
 }
   
diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c
index 6593deb49bf72cc3bf75c1ca992b5935a16c9cd4..4c4cec50da336eb6a9526d5e4b8d1304a69f5b4f 100644
--- a/gcc/tree-ssa-pre.c
+++ b/gcc/tree-ssa-pre.c
@@ -3441,7 +3441,7 @@ init_pre (bool do_fre)
 
   vn_init ();
   if (!do_fre)
-    current_loops = loop_optimizer_init (dump_file);
+    current_loops = loop_optimizer_init (dump_file, LOOPS_NORMAL);
 
   connect_infinite_loops_to_exit ();
   memset (&pre_stats, 0, sizeof (pre_stats));
diff --git a/gcc/tree-ssa-sink.c b/gcc/tree-ssa-sink.c
index c6cdc6f1e3514c8284fc987637854cce69f052e6..ed6baf2cd893b8d7860d6d2c15fa7a29a14a19d0 100644
--- a/gcc/tree-ssa-sink.c
+++ b/gcc/tree-ssa-sink.c
@@ -522,7 +522,7 @@ sink_code_in_bb (basic_block bb)
 static void
 execute_sink_code (void)
 {
-  struct loops *loops = loop_optimizer_init (dump_file);
+  struct loops *loops = loop_optimizer_init (dump_file, LOOPS_NORMAL);
   connect_infinite_loops_to_exit ();
   memset (&sink_stats, 0, sizeof (sink_stats));
   calculate_dominance_info (CDI_DOMINATORS | CDI_POST_DOMINATORS);
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index e80f385206f7bfd27bc2d0f751448ca8af2f9d9c..0938d6ce28b6f5223c93e49190772958c9a42ba0 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -41,10 +41,6 @@ Boston, MA 02110-1301, USA.  */
    sub-graph in find_assert_locations.  */
 static sbitmap found_in_subgraph;
 
-/* Loop structure of the program.  Used to analyze scalar evolutions
-   inside adjust_range_with_scev.  */
-static struct loops *cfg_loops;
-
 /* Local functions.  */
 static int compare_values (tree val1, tree val2);
 
@@ -1909,7 +1905,7 @@ adjust_range_with_scev (value_range_t *vr, struct loop *loop, tree stmt,
 
   /* Do not adjust ranges when chrec may wrap.  */
   if (scev_probably_wraps_p (chrec_type (chrec), init, step, stmt,
-			     cfg_loops->parray[CHREC_VARIABLE (chrec)],
+			     current_loops->parray[CHREC_VARIABLE (chrec)],
 			     &init_is_max, &unknown_max)
       || unknown_max)
     return;
@@ -3278,7 +3274,7 @@ vrp_visit_assignment (tree stmt, tree *output_p)
       /* If STMT is inside a loop, we may be able to know something
 	 else about the range of LHS by examining scalar evolution
 	 information.  */
-      if (cfg_loops && (l = loop_containing_stmt (stmt)))
+      if (current_loops && (l = loop_containing_stmt (stmt)))
 	adjust_range_with_scev (&new_vr, l, stmt, lhs);
 
       if (update_value_range (lhs, &new_vr))
@@ -4312,18 +4308,18 @@ execute_vrp (void)
 {
   insert_range_assertions ();
 
-  cfg_loops = loop_optimizer_init (NULL);
-  if (cfg_loops)
-    scev_initialize (cfg_loops);
+  current_loops = loop_optimizer_init (NULL, LOOPS_NORMAL);
+  if (current_loops)
+    scev_initialize (current_loops);
 
   vrp_initialize ();
   ssa_propagate (vrp_visit_stmt, vrp_visit_phi_node);
   vrp_finalize ();
 
-  if (cfg_loops)
+  if (current_loops)
     {
       scev_finalize ();
-      loop_optimizer_finalize (cfg_loops, NULL);
+      loop_optimizer_finalize (current_loops, NULL);
       current_loops = NULL;
     }