]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/tree-ssa-loop-ch.c
2015-06-17 Andrew MacLeod <amacleod@redhat.com>
[thirdparty/gcc.git] / gcc / tree-ssa-loop-ch.c
CommitLineData
f3d9a16c 1/* Loop header copying on trees.
d353bf18 2 Copyright (C) 2004-2015 Free Software Foundation, Inc.
48e1416a 3
f3d9a16c 4This file is part of GCC.
48e1416a 5
f3d9a16c 6GCC is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by the
8c4c00c1 8Free Software Foundation; either version 3, or (at your option) any
f3d9a16c 9later version.
48e1416a 10
f3d9a16c 11GCC is distributed in the hope that it will be useful, but WITHOUT
12ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14for more details.
48e1416a 15
f3d9a16c 16You should have received a copy of the GNU General Public License
8c4c00c1 17along with GCC; see the file COPYING3. If not see
18<http://www.gnu.org/licenses/>. */
f3d9a16c 19
20#include "config.h"
21#include "system.h"
22#include "coretypes.h"
23#include "tm.h"
b20a8bb4 24#include "alias.h"
25#include "symtab.h"
f3d9a16c 26#include "tree.h"
b20a8bb4 27#include "fold-const.h"
f3d9a16c 28#include "tm_p.h"
94ea8568 29#include "predict.h"
94ea8568 30#include "hard-reg-set.h"
94ea8568 31#include "function.h"
32#include "dominance.h"
33#include "cfg.h"
f3d9a16c 34#include "basic-block.h"
bc61cadb 35#include "tree-ssa-alias.h"
36#include "internal-fn.h"
37#include "gimple-expr.h"
073c1fd5 38#include "gimple.h"
dcf1a1ec 39#include "gimple-iterator.h"
073c1fd5 40#include "gimple-ssa.h"
41#include "tree-cfg.h"
42#include "tree-into-ssa.h"
f3d9a16c 43#include "tree-pass.h"
f3d9a16c 44#include "cfgloop.h"
45#include "tree-inline.h"
46#include "flags.h"
545372c5 47#include "tree-ssa-scopedtables.h"
424a4a92 48#include "tree-ssa-threadedge.h"
f3d9a16c 49
50/* Duplicates headers of loops if they are small enough, so that the statements
51 in the loop body are always executed when the loop is entered. This
c26a6416 52 increases effectiveness of code motion optimizations, and reduces the need
f3d9a16c 53 for loop preconditioning. */
54
55/* Check whether we should duplicate HEADER of LOOP. At most *LIMIT
56 instructions should be duplicated, limit is decreased by the actual
57 amount. */
58
59static bool
60should_duplicate_loop_header_p (basic_block header, struct loop *loop,
61 int *limit)
62{
75a70cf9 63 gimple_stmt_iterator bsi;
64 gimple last;
f3d9a16c 65
66 /* Do not copy one block more than once (we do not really want to do
67 loop peeling here). */
68 if (header->aux)
69 return false;
70
94ba1cf1 71 /* Loop header copying usually increases size of the code. This used not to
72 be true, since quite often it is possible to verify that the condition is
73 satisfied in the first iteration and therefore to eliminate it. Jump
74 threading handles these cases now. */
75 if (optimize_loop_for_size_p (loop))
76 return false;
77
cd665a06 78 gcc_assert (EDGE_COUNT (header->succs) > 0);
ea091dfd 79 if (single_succ_p (header))
f3d9a16c 80 return false;
cd665a06 81 if (flow_bb_inside_loop_p (loop, EDGE_SUCC (header, 0)->dest)
82 && flow_bb_inside_loop_p (loop, EDGE_SUCC (header, 1)->dest))
f3d9a16c 83 return false;
84
85 /* If this is not the original loop header, we want it to have just
86 one predecessor in order to match the && pattern. */
ea091dfd 87 if (header != loop->header && !single_pred_p (header))
f3d9a16c 88 return false;
89
90 last = last_stmt (header);
75a70cf9 91 if (gimple_code (last) != GIMPLE_COND)
f3d9a16c 92 return false;
93
94 /* Approximately copy the conditions that used to be used in jump.c --
95 at most 20 insns and no calls. */
75a70cf9 96 for (bsi = gsi_start_bb (header); !gsi_end_p (bsi); gsi_next (&bsi))
f3d9a16c 97 {
75a70cf9 98 last = gsi_stmt (bsi);
f3d9a16c 99
75a70cf9 100 if (gimple_code (last) == GIMPLE_LABEL)
f3d9a16c 101 continue;
102
9845d120 103 if (is_gimple_debug (last))
104 continue;
105
75a70cf9 106 if (is_gimple_call (last))
f3d9a16c 107 return false;
108
bc8bb825 109 *limit -= estimate_num_insns (last, &eni_size_weights);
f3d9a16c 110 if (*limit < 0)
111 return false;
112 }
113
114 return true;
115}
116
f3d9a16c 117/* Checks whether LOOP is a do-while style loop. */
118
f86b328b 119static bool
f3d9a16c 120do_while_loop_p (struct loop *loop)
121{
75a70cf9 122 gimple stmt = last_stmt (loop->latch);
f3d9a16c 123
124 /* If the latch of the loop is not empty, it is not a do-while loop. */
125 if (stmt
75a70cf9 126 && gimple_code (stmt) != GIMPLE_LABEL)
f3d9a16c 127 return false;
128
129 /* If the header contains just a condition, it is not a do-while loop. */
130 stmt = last_and_only_stmt (loop->header);
131 if (stmt
75a70cf9 132 && gimple_code (stmt) == GIMPLE_COND)
f3d9a16c 133 return false;
134
135 return true;
136}
137
138/* For all loops, copy the condition at the end of the loop body in front
139 of the loop. This is beneficial since it increases efficiency of
140 code motion optimizations. It also saves one jump on entry to the loop. */
141
65b0537f 142namespace {
143
144const pass_data pass_data_ch =
145{
146 GIMPLE_PASS, /* type */
147 "ch", /* name */
148 OPTGROUP_LOOP, /* optinfo_flags */
65b0537f 149 TV_TREE_CH, /* tv_id */
150 ( PROP_cfg | PROP_ssa ), /* properties_required */
151 0, /* properties_provided */
152 0, /* properties_destroyed */
153 0, /* todo_flags_start */
051d7389 154 0, /* todo_flags_finish */
65b0537f 155};
156
157class pass_ch : public gimple_opt_pass
158{
159public:
160 pass_ch (gcc::context *ctxt)
161 : gimple_opt_pass (pass_data_ch, ctxt)
162 {}
163
164 /* opt_pass methods: */
165 virtual bool gate (function *) { return flag_tree_ch != 0; }
166 virtual unsigned int execute (function *);
167
168}; // class pass_ch
169
170unsigned int
171pass_ch::execute (function *fun)
f3d9a16c 172{
f3d9a16c 173 struct loop *loop;
174 basic_block header;
4d6b11ab 175 edge exit, entry;
176 basic_block *bbs, *copied_bbs;
d8b5b4fe 177 unsigned n_bbs;
4d6b11ab 178 unsigned bbs_size;
051d7389 179 bool changed = false;
f3d9a16c 180
88e6f696 181 loop_optimizer_init (LOOPS_HAVE_PREHEADERS
182 | LOOPS_HAVE_SIMPLE_LATCHES);
65b0537f 183 if (number_of_loops (fun) <= 1)
7a3bf727 184 {
185 loop_optimizer_finalize ();
186 return 0;
187 }
f3d9a16c 188
65b0537f 189 bbs = XNEWVEC (basic_block, n_basic_blocks_for_fn (fun));
190 copied_bbs = XNEWVEC (basic_block, n_basic_blocks_for_fn (fun));
191 bbs_size = n_basic_blocks_for_fn (fun);
d8b5b4fe 192
f21d4d00 193 FOR_EACH_LOOP (loop, 0)
f3d9a16c 194 {
195 /* Copy at most 20 insns. */
196 int limit = 20;
197
d8b5b4fe 198 header = loop->header;
f3d9a16c 199
200 /* If the loop is already a do-while style one (either because it was
201 written as such, or because jump threading transformed it into one),
202 we might be in fact peeling the first iteration of the loop. This
203 in general is not a good idea. */
204 if (do_while_loop_p (loop))
205 continue;
206
207 /* Iterate the header copying up to limit; this takes care of the cases
208 like while (a && b) {...}, where we want to have both of the conditions
209 copied. TODO -- handle while (a || b) - like cases, by not requiring
210 the header to have just a single successor and copying up to
d8b5b4fe 211 postdominator. */
212
213 exit = NULL;
214 n_bbs = 0;
f3d9a16c 215 while (should_duplicate_loop_header_p (header, loop, &limit))
216 {
f3d9a16c 217 /* Find a successor of header that is inside a loop; i.e. the new
218 header after the condition is copied. */
cd665a06 219 if (flow_bb_inside_loop_p (loop, EDGE_SUCC (header, 0)->dest))
220 exit = EDGE_SUCC (header, 0);
f3d9a16c 221 else
cd665a06 222 exit = EDGE_SUCC (header, 1);
d8b5b4fe 223 bbs[n_bbs++] = header;
4d6b11ab 224 gcc_assert (bbs_size > n_bbs);
d8b5b4fe 225 header = exit->dest;
f3d9a16c 226 }
f3d9a16c 227
d8b5b4fe 228 if (!exit)
229 continue;
f3d9a16c 230
d8b5b4fe 231 if (dump_file && (dump_flags & TDF_DETAILS))
232 fprintf (dump_file,
233 "Duplicating header of the loop %d up to edge %d->%d.\n",
234 loop->num, exit->src->index, exit->dest->index);
235
236 /* Ensure that the header will have just the latch as a predecessor
237 inside the loop. */
ea091dfd 238 if (!single_pred_p (exit->dest))
88e6f696 239 exit = single_pred_edge (split_edge (exit));
d8b5b4fe 240
4d6b11ab 241 entry = loop_preheader_edge (loop);
4d6b11ab 242
80ed2d81 243 propagate_threaded_block_debug_into (exit->dest, entry->dest);
d99f53b2 244 if (!gimple_duplicate_sese_region (entry, exit, bbs, n_bbs, copied_bbs,
245 true))
d8b5b4fe 246 {
247 fprintf (dump_file, "Duplication failed.\n");
248 continue;
249 }
250
c7addd8c 251 /* If the loop has the form "for (i = j; i < j + 10; i++)" then
252 this copying can introduce a case where we rely on undefined
253 signed overflow to eliminate the preheader condition, because
254 we assume that "j < j + 10" is true. We don't want to warn
255 about that case for -Wstrict-overflow, because in general we
256 don't warn about overflow involving loops. Prevent the
75a70cf9 257 warning by setting the no_warning flag in the condition. */
c7addd8c 258 if (warn_strict_overflow > 0)
259 {
260 unsigned int i;
261
262 for (i = 0; i < n_bbs; ++i)
263 {
75a70cf9 264 gimple_stmt_iterator bsi;
72c59a18 265
75a70cf9 266 for (bsi = gsi_start_bb (copied_bbs[i]);
267 !gsi_end_p (bsi);
268 gsi_next (&bsi))
72c59a18 269 {
75a70cf9 270 gimple stmt = gsi_stmt (bsi);
271 if (gimple_code (stmt) == GIMPLE_COND)
272 gimple_set_no_warning (stmt, true);
273 else if (is_gimple_assign (stmt))
72c59a18 274 {
75a70cf9 275 enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
276 if (TREE_CODE_CLASS (rhs_code) == tcc_comparison)
277 gimple_set_no_warning (stmt, true);
72c59a18 278 }
279 }
c7addd8c 280 }
281 }
282
d8b5b4fe 283 /* Ensure that the latch and the preheader is simple (we know that they
284 are not now, since there was the loop exit condition. */
88e6f696 285 split_edge (loop_preheader_edge (loop));
286 split_edge (loop_latch_edge (loop));
051d7389 287
288 changed = true;
f3d9a16c 289 }
290
8cb0acff 291 update_ssa (TODO_update_ssa);
d8b5b4fe 292 free (bbs);
4d6b11ab 293 free (copied_bbs);
d8b5b4fe 294
88e6f696 295 loop_optimizer_finalize ();
051d7389 296 return changed ? TODO_cleanup_cfg : 0;
f3d9a16c 297}
298
cbe8bda8 299} // anon namespace
300
301gimple_opt_pass *
302make_pass_ch (gcc::context *ctxt)
303{
304 return new pass_ch (ctxt);
305}