OSDN Git Service

2005-07-05 Paolo Bonzini <bonzini@gnu.org>
[pf3gnuchains/gcc-fork.git] / gcc / loop-init.c
1 /* Loop optimizer initialization routines.
2    Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
3
4 This file is part of GCC.
5
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 2, or (at your option) any later
9 version.
10
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING.  If not, write to the Free
18 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301, USA.  */
20
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tm.h"
25 #include "rtl.h"
26 #include "hard-reg-set.h"
27 #include "obstack.h"
28 #include "basic-block.h"
29 #include "cfgloop.h"
30 #include "cfglayout.h"
31 #include "tree-pass.h"
32 #include "timevar.h"
33 #include "flags.h"
34
35 /* Initialize loop optimizer.  */
36
37 struct loops *
38 loop_optimizer_init (FILE *dumpfile)
39 {
40   struct loops *loops = xcalloc (1, sizeof (struct loops));
41   edge e;
42   edge_iterator ei;
43   static bool first_time = true;
44
45   if (first_time)
46     {
47       first_time = false;
48       init_set_costs ();
49     }
50
51   /* Avoid annoying special cases of edges going to exit
52      block.  */
53
54   for (ei = ei_start (EXIT_BLOCK_PTR->preds); (e = ei_safe_edge (ei)); )
55     if ((e->flags & EDGE_FALLTHRU) && !single_succ_p (e->src))
56       split_edge (e);
57     else
58       ei_next (&ei);
59
60   /* Find the loops.  */
61
62   if (flow_loops_find (loops) <= 1)
63     {
64       /* No loops.  */
65       flow_loops_free (loops);
66       free (loops);
67
68       return NULL;
69     }
70
71   /* Not going to update these.  */
72   free (loops->cfg.rc_order);
73   loops->cfg.rc_order = NULL;
74   free (loops->cfg.dfs_order);
75   loops->cfg.dfs_order = NULL;
76
77   /* Create pre-headers.  */
78   create_preheaders (loops, CP_SIMPLE_PREHEADERS);
79
80   /* Force all latches to have only single successor.  */
81   force_single_succ_latches (loops);
82
83   /* Mark irreducible loops.  */
84   mark_irreducible_loops (loops);
85
86   /* Dump loops.  */
87   flow_loops_dump (loops, dumpfile, NULL, 1);
88
89 #ifdef ENABLE_CHECKING
90   verify_dominators (CDI_DOMINATORS);
91   verify_loop_structure (loops);
92 #endif
93
94   return loops;
95 }
96
97 /* Finalize loop optimizer.  */
98 void
99 loop_optimizer_finalize (struct loops *loops, FILE *dumpfile)
100 {
101   unsigned i;
102
103   if (!loops)
104     return;
105
106   for (i = 1; i < loops->num; i++)
107     if (loops->parray[i])
108       free_simple_loop_desc (loops->parray[i]);
109
110   /* Another dump.  */
111   flow_loops_dump (loops, dumpfile, NULL, 1);
112
113   /* Clean up.  */
114   flow_loops_free (loops);
115   free (loops);
116
117   /* Checking.  */
118 #ifdef ENABLE_CHECKING
119   verify_flow_info ();
120 #endif
121 }
122 \f
123 static bool
124 gate_handle_loop2 (void)
125 {
126   return (optimize > 0 && flag_loop_optimize2
127           && (flag_move_loop_invariants
128               || flag_unswitch_loops
129               || flag_peel_loops
130               || flag_unroll_loops
131               || flag_branch_on_count_reg));
132 }
133
134 /* Perform loop optimizations.  It might be better to do them a bit
135    sooner, but we want the profile feedback to work more
136    efficiently.  */
137 static void
138 rest_of_handle_loop2 (void)
139 {
140   struct loops *loops;
141   basic_block bb;
142
143   if (dump_file)
144     dump_flow_info (dump_file);
145
146   /* Initialize structures for layout changes.  */
147   cfg_layout_initialize (0);
148
149   loops = loop_optimizer_init (dump_file);
150
151   if (loops)
152     {
153       /* The optimizations:  */
154       if (flag_move_loop_invariants)
155         move_loop_invariants (loops);
156
157       if (flag_unswitch_loops)
158         unswitch_loops (loops);
159
160       if (flag_peel_loops || flag_unroll_loops)
161         unroll_and_peel_loops (loops,
162                                (flag_peel_loops ? UAP_PEEL : 0) |
163                                (flag_unroll_loops ? UAP_UNROLL : 0) |
164                                (flag_unroll_all_loops ? UAP_UNROLL_ALL : 0));
165
166 #ifdef HAVE_doloop_end
167       if (flag_branch_on_count_reg && HAVE_doloop_end)
168         doloop_optimize_loops (loops);
169 #endif /* HAVE_doloop_end */
170
171       loop_optimizer_finalize (loops, dump_file);
172     }
173
174   free_dominance_info (CDI_DOMINATORS);
175
176   /* Finalize layout changes.  */
177   FOR_EACH_BB (bb)
178     if (bb->next_bb != EXIT_BLOCK_PTR)
179       bb->aux = bb->next_bb;
180   cfg_layout_finalize ();
181
182   cleanup_cfg (CLEANUP_EXPENSIVE);
183   delete_trivially_dead_insns (get_insns (), max_reg_num ());
184   reg_scan (get_insns (), max_reg_num ());
185   if (dump_file)
186     dump_flow_info (dump_file);
187 }
188
189 struct tree_opt_pass pass_loop2 =
190 {
191   "loop2",                              /* name */
192   gate_handle_loop2,                    /* gate */
193   rest_of_handle_loop2,                 /* execute */
194   NULL,                                 /* sub */
195   NULL,                                 /* next */
196   0,                                    /* static_pass_number */
197   TV_LOOP,                              /* tv_id */
198   0,                                    /* properties_required */
199   0,                                    /* properties_provided */
200   0,                                    /* properties_destroyed */
201   0,                                    /* todo_flags_start */
202   TODO_dump_func |
203   TODO_ggc_collect,                     /* todo_flags_finish */
204   'L'                                   /* letter */
205 };
206