Create startup files from the GCC sources and drop our versions.
[dragonfly.git] / contrib / gcc-4.0 / gcc / tree-ssa-loop-ch.c
1 /* Loop header copying on trees.
2    Copyright (C) 2004 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
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
9 later version.
10    
11 GCC is distributed in the hope that it will be useful, but WITHOUT
12 ANY 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, 59 Temple Place - Suite 330, Boston, MA
19 02111-1307, USA.  */
20
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tm.h"
25 #include "tree.h"
26 #include "rtl.h"
27 #include "tm_p.h"
28 #include "hard-reg-set.h"
29 #include "basic-block.h"
30 #include "output.h"
31 #include "diagnostic.h"
32 #include "tree-flow.h"
33 #include "tree-dump.h"
34 #include "tree-pass.h"
35 #include "timevar.h"
36 #include "cfgloop.h"
37 #include "tree-inline.h"
38 #include "flags.h"
39 #include "tree-inline.h"
40
41 /* Duplicates headers of loops if they are small enough, so that the statements
42    in the loop body are always executed when the loop is entered.  This
43    increases effectiveness of code motion optimizations, and reduces the need
44    for loop preconditioning.  */
45
46 /* Check whether we should duplicate HEADER of LOOP.  At most *LIMIT
47    instructions should be duplicated, limit is decreased by the actual
48    amount.  */
49
50 static bool
51 should_duplicate_loop_header_p (basic_block header, struct loop *loop,
52                                 int *limit)
53 {
54   block_stmt_iterator bsi;
55   tree last;
56
57   /* Do not copy one block more than once (we do not really want to do
58      loop peeling here).  */
59   if (header->aux)
60     return false;
61
62   gcc_assert (EDGE_COUNT (header->succs) > 0);
63   if (EDGE_COUNT (header->succs) == 1)
64     return false;
65   if (flow_bb_inside_loop_p (loop, EDGE_SUCC (header, 0)->dest)
66       && flow_bb_inside_loop_p (loop, EDGE_SUCC (header, 1)->dest))
67     return false;
68
69   /* If this is not the original loop header, we want it to have just
70      one predecessor in order to match the && pattern.  */
71   if (header != loop->header && EDGE_COUNT (header->preds) >= 2)
72     return false;
73
74   last = last_stmt (header);
75   if (TREE_CODE (last) != COND_EXPR)
76     return false;
77
78   /* Approximately copy the conditions that used to be used in jump.c --
79      at most 20 insns and no calls.  */
80   for (bsi = bsi_start (header); !bsi_end_p (bsi); bsi_next (&bsi))
81     {
82       last = bsi_stmt (bsi);
83
84       if (TREE_CODE (last) == LABEL_EXPR)
85         continue;
86
87       if (get_call_expr_in (last))
88         return false;
89
90       *limit -= estimate_num_insns (last);
91       if (*limit < 0)
92         return false;
93     }
94
95   return true;
96 }
97
98 /* Checks whether LOOP is a do-while style loop.  */
99
100 static bool
101 do_while_loop_p (struct loop *loop)
102 {
103   tree stmt = last_stmt (loop->latch);
104
105   /* If the latch of the loop is not empty, it is not a do-while loop.  */
106   if (stmt
107       && TREE_CODE (stmt) != LABEL_EXPR)
108     return false;
109
110   /* If the header contains just a condition, it is not a do-while loop.  */
111   stmt = last_and_only_stmt (loop->header);
112   if (stmt
113       && TREE_CODE (stmt) == COND_EXPR)
114     return false;
115
116   return true;
117 }
118
119 /* For all loops, copy the condition at the end of the loop body in front
120    of the loop.  This is beneficial since it increases efficiency of
121    code motion optimizations.  It also saves one jump on entry to the loop.  */
122
123 static void
124 copy_loop_headers (void)
125 {
126   struct loops *loops;
127   unsigned i;
128   struct loop *loop;
129   basic_block header;
130   edge exit;
131   basic_block *bbs;
132   unsigned n_bbs;
133
134   loops = loop_optimizer_init (dump_file);
135   if (!loops)
136     return;
137   rewrite_into_loop_closed_ssa ();
138   
139   /* We do not try to keep the information about irreducible regions
140      up-to-date.  */
141   loops->state &= ~LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS;
142
143 #ifdef ENABLE_CHECKING
144   verify_loop_structure (loops);
145 #endif
146
147   bbs = xmalloc (sizeof (basic_block) * n_basic_blocks);
148
149   for (i = 1; i < loops->num; i++)
150     {
151       /* Copy at most 20 insns.  */
152       int limit = 20;
153
154       loop = loops->parray[i];
155       if (!loop)
156         continue;
157       header = loop->header;
158
159       /* If the loop is already a do-while style one (either because it was
160          written as such, or because jump threading transformed it into one),
161          we might be in fact peeling the first iteration of the loop.  This
162          in general is not a good idea.  */
163       if (do_while_loop_p (loop))
164         continue;
165
166       /* Iterate the header copying up to limit; this takes care of the cases
167          like while (a && b) {...}, where we want to have both of the conditions
168          copied.  TODO -- handle while (a || b) - like cases, by not requiring
169          the header to have just a single successor and copying up to
170          postdominator.  */
171
172       exit = NULL;
173       n_bbs = 0;
174       while (should_duplicate_loop_header_p (header, loop, &limit))
175         {
176           /* Find a successor of header that is inside a loop; i.e. the new
177              header after the condition is copied.  */
178           if (flow_bb_inside_loop_p (loop, EDGE_SUCC (header, 0)->dest))
179             exit = EDGE_SUCC (header, 0);
180           else
181             exit = EDGE_SUCC (header, 1);
182           bbs[n_bbs++] = header;
183           header = exit->dest;
184         }
185
186       if (!exit)
187         continue;
188
189       if (dump_file && (dump_flags & TDF_DETAILS))
190         fprintf (dump_file,
191                  "Duplicating header of the loop %d up to edge %d->%d.\n",
192                  loop->num, exit->src->index, exit->dest->index);
193
194       /* Ensure that the header will have just the latch as a predecessor
195          inside the loop.  */
196       if (EDGE_COUNT (exit->dest->preds) > 1)
197         exit = EDGE_SUCC (loop_split_edge_with (exit, NULL), 0);
198
199       if (!tree_duplicate_sese_region (loop_preheader_edge (loop), exit,
200                                        bbs, n_bbs, NULL))
201         {
202           fprintf (dump_file, "Duplication failed.\n");
203           continue;
204         }
205
206       /* Ensure that the latch and the preheader is simple (we know that they
207          are not now, since there was the loop exit condition.  */
208       loop_split_edge_with (loop_preheader_edge (loop), NULL);
209       loop_split_edge_with (loop_latch_edge (loop), NULL);
210     }
211
212   free (bbs);
213
214 #ifdef ENABLE_CHECKING
215   verify_loop_closed_ssa ();
216 #endif
217
218   loop_optimizer_finalize (loops, NULL);
219 }
220
221 static bool
222 gate_ch (void)
223 {
224   return flag_tree_ch != 0;
225 }
226
227 struct tree_opt_pass pass_ch = 
228 {
229   "ch",                                 /* name */
230   gate_ch,                              /* gate */
231   copy_loop_headers,                    /* execute */
232   NULL,                                 /* sub */
233   NULL,                                 /* next */
234   0,                                    /* static_pass_number */
235   TV_TREE_CH,                           /* tv_id */
236   PROP_cfg | PROP_ssa,                  /* properties_required */
237   0,                                    /* properties_provided */
238   0,                                    /* properties_destroyed */
239   0,                                    /* todo_flags_start */
240   TODO_cleanup_cfg | TODO_dump_func 
241   | TODO_verify_ssa,                    /* todo_flags_finish */
242   0                                     /* letter */
243 };