1*e4b17023SJohn Marino /* Loop unswitching.
2*e4b17023SJohn Marino Copyright (C) 2004, 2005, 2007, 2008, 2010 Free Software Foundation, Inc.
3*e4b17023SJohn Marino
4*e4b17023SJohn Marino This file is part of GCC.
5*e4b17023SJohn Marino
6*e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it
7*e4b17023SJohn Marino under the terms of the GNU General Public License as published by the
8*e4b17023SJohn Marino Free Software Foundation; either version 3, or (at your option) any
9*e4b17023SJohn Marino later version.
10*e4b17023SJohn Marino
11*e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT
12*e4b17023SJohn Marino ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13*e4b17023SJohn Marino FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14*e4b17023SJohn Marino for more details.
15*e4b17023SJohn Marino
16*e4b17023SJohn Marino You should have received a copy of the GNU General Public License
17*e4b17023SJohn Marino along with GCC; see the file COPYING3. If not see
18*e4b17023SJohn Marino <http://www.gnu.org/licenses/>. */
19*e4b17023SJohn Marino
20*e4b17023SJohn Marino #include "config.h"
21*e4b17023SJohn Marino #include "system.h"
22*e4b17023SJohn Marino #include "coretypes.h"
23*e4b17023SJohn Marino #include "tm.h"
24*e4b17023SJohn Marino #include "tree.h"
25*e4b17023SJohn Marino #include "tm_p.h"
26*e4b17023SJohn Marino #include "basic-block.h"
27*e4b17023SJohn Marino #include "output.h"
28*e4b17023SJohn Marino #include "tree-flow.h"
29*e4b17023SJohn Marino #include "tree-dump.h"
30*e4b17023SJohn Marino #include "timevar.h"
31*e4b17023SJohn Marino #include "cfgloop.h"
32*e4b17023SJohn Marino #include "params.h"
33*e4b17023SJohn Marino #include "tree-pass.h"
34*e4b17023SJohn Marino #include "tree-inline.h"
35*e4b17023SJohn Marino
36*e4b17023SJohn Marino /* This file implements the loop unswitching, i.e. transformation of loops like
37*e4b17023SJohn Marino
38*e4b17023SJohn Marino while (A)
39*e4b17023SJohn Marino {
40*e4b17023SJohn Marino if (inv)
41*e4b17023SJohn Marino B;
42*e4b17023SJohn Marino
43*e4b17023SJohn Marino X;
44*e4b17023SJohn Marino
45*e4b17023SJohn Marino if (!inv)
46*e4b17023SJohn Marino C;
47*e4b17023SJohn Marino }
48*e4b17023SJohn Marino
49*e4b17023SJohn Marino where inv is the loop invariant, into
50*e4b17023SJohn Marino
51*e4b17023SJohn Marino if (inv)
52*e4b17023SJohn Marino {
53*e4b17023SJohn Marino while (A)
54*e4b17023SJohn Marino {
55*e4b17023SJohn Marino B;
56*e4b17023SJohn Marino X;
57*e4b17023SJohn Marino }
58*e4b17023SJohn Marino }
59*e4b17023SJohn Marino else
60*e4b17023SJohn Marino {
61*e4b17023SJohn Marino while (A)
62*e4b17023SJohn Marino {
63*e4b17023SJohn Marino X;
64*e4b17023SJohn Marino C;
65*e4b17023SJohn Marino }
66*e4b17023SJohn Marino }
67*e4b17023SJohn Marino
68*e4b17023SJohn Marino Inv is considered invariant iff the values it compares are both invariant;
69*e4b17023SJohn Marino tree-ssa-loop-im.c ensures that all the suitable conditions are in this
70*e4b17023SJohn Marino shape. */
71*e4b17023SJohn Marino
72*e4b17023SJohn Marino static struct loop *tree_unswitch_loop (struct loop *, basic_block, tree);
73*e4b17023SJohn Marino static bool tree_unswitch_single_loop (struct loop *, int);
74*e4b17023SJohn Marino static tree tree_may_unswitch_on (basic_block, struct loop *);
75*e4b17023SJohn Marino
76*e4b17023SJohn Marino /* Main entry point. Perform loop unswitching on all suitable loops. */
77*e4b17023SJohn Marino
78*e4b17023SJohn Marino unsigned int
tree_ssa_unswitch_loops(void)79*e4b17023SJohn Marino tree_ssa_unswitch_loops (void)
80*e4b17023SJohn Marino {
81*e4b17023SJohn Marino loop_iterator li;
82*e4b17023SJohn Marino struct loop *loop;
83*e4b17023SJohn Marino bool changed = false;
84*e4b17023SJohn Marino
85*e4b17023SJohn Marino /* Go through inner loops (only original ones). */
86*e4b17023SJohn Marino FOR_EACH_LOOP (li, loop, LI_ONLY_INNERMOST)
87*e4b17023SJohn Marino {
88*e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS))
89*e4b17023SJohn Marino fprintf (dump_file, ";; Considering loop %d\n", loop->num);
90*e4b17023SJohn Marino
91*e4b17023SJohn Marino /* Do not unswitch in cold regions. */
92*e4b17023SJohn Marino if (optimize_loop_for_size_p (loop))
93*e4b17023SJohn Marino {
94*e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS))
95*e4b17023SJohn Marino fprintf (dump_file, ";; Not unswitching cold loops\n");
96*e4b17023SJohn Marino continue;
97*e4b17023SJohn Marino }
98*e4b17023SJohn Marino
99*e4b17023SJohn Marino /* The loop should not be too large, to limit code growth. */
100*e4b17023SJohn Marino if (tree_num_loop_insns (loop, &eni_size_weights)
101*e4b17023SJohn Marino > (unsigned) PARAM_VALUE (PARAM_MAX_UNSWITCH_INSNS))
102*e4b17023SJohn Marino {
103*e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS))
104*e4b17023SJohn Marino fprintf (dump_file, ";; Not unswitching, loop too big\n");
105*e4b17023SJohn Marino continue;
106*e4b17023SJohn Marino }
107*e4b17023SJohn Marino
108*e4b17023SJohn Marino changed |= tree_unswitch_single_loop (loop, 0);
109*e4b17023SJohn Marino }
110*e4b17023SJohn Marino
111*e4b17023SJohn Marino if (changed)
112*e4b17023SJohn Marino return TODO_cleanup_cfg;
113*e4b17023SJohn Marino return 0;
114*e4b17023SJohn Marino }
115*e4b17023SJohn Marino
116*e4b17023SJohn Marino /* Checks whether we can unswitch LOOP on condition at end of BB -- one of its
117*e4b17023SJohn Marino basic blocks (for what it means see comments below). */
118*e4b17023SJohn Marino
119*e4b17023SJohn Marino static tree
tree_may_unswitch_on(basic_block bb,struct loop * loop)120*e4b17023SJohn Marino tree_may_unswitch_on (basic_block bb, struct loop *loop)
121*e4b17023SJohn Marino {
122*e4b17023SJohn Marino gimple stmt, def;
123*e4b17023SJohn Marino tree cond, use;
124*e4b17023SJohn Marino basic_block def_bb;
125*e4b17023SJohn Marino ssa_op_iter iter;
126*e4b17023SJohn Marino
127*e4b17023SJohn Marino /* BB must end in a simple conditional jump. */
128*e4b17023SJohn Marino stmt = last_stmt (bb);
129*e4b17023SJohn Marino if (!stmt || gimple_code (stmt) != GIMPLE_COND)
130*e4b17023SJohn Marino return NULL_TREE;
131*e4b17023SJohn Marino
132*e4b17023SJohn Marino /* To keep the things simple, we do not directly remove the conditions,
133*e4b17023SJohn Marino but just replace tests with 0 != 0 resp. 1 != 0. Prevent the infinite
134*e4b17023SJohn Marino loop where we would unswitch again on such a condition. */
135*e4b17023SJohn Marino if (gimple_cond_true_p (stmt) || gimple_cond_false_p (stmt))
136*e4b17023SJohn Marino return NULL_TREE;
137*e4b17023SJohn Marino
138*e4b17023SJohn Marino /* Condition must be invariant. */
139*e4b17023SJohn Marino FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE)
140*e4b17023SJohn Marino {
141*e4b17023SJohn Marino def = SSA_NAME_DEF_STMT (use);
142*e4b17023SJohn Marino def_bb = gimple_bb (def);
143*e4b17023SJohn Marino if (def_bb
144*e4b17023SJohn Marino && flow_bb_inside_loop_p (loop, def_bb))
145*e4b17023SJohn Marino return NULL_TREE;
146*e4b17023SJohn Marino }
147*e4b17023SJohn Marino
148*e4b17023SJohn Marino cond = build2 (gimple_cond_code (stmt), boolean_type_node,
149*e4b17023SJohn Marino gimple_cond_lhs (stmt), gimple_cond_rhs (stmt));
150*e4b17023SJohn Marino
151*e4b17023SJohn Marino return cond;
152*e4b17023SJohn Marino }
153*e4b17023SJohn Marino
154*e4b17023SJohn Marino /* Simplifies COND using checks in front of the entry of the LOOP. Just very
155*e4b17023SJohn Marino simplish (sufficient to prevent us from duplicating loop in unswitching
156*e4b17023SJohn Marino unnecessarily). */
157*e4b17023SJohn Marino
158*e4b17023SJohn Marino static tree
simplify_using_entry_checks(struct loop * loop,tree cond)159*e4b17023SJohn Marino simplify_using_entry_checks (struct loop *loop, tree cond)
160*e4b17023SJohn Marino {
161*e4b17023SJohn Marino edge e = loop_preheader_edge (loop);
162*e4b17023SJohn Marino gimple stmt;
163*e4b17023SJohn Marino
164*e4b17023SJohn Marino while (1)
165*e4b17023SJohn Marino {
166*e4b17023SJohn Marino stmt = last_stmt (e->src);
167*e4b17023SJohn Marino if (stmt
168*e4b17023SJohn Marino && gimple_code (stmt) == GIMPLE_COND
169*e4b17023SJohn Marino && gimple_cond_code (stmt) == TREE_CODE (cond)
170*e4b17023SJohn Marino && operand_equal_p (gimple_cond_lhs (stmt),
171*e4b17023SJohn Marino TREE_OPERAND (cond, 0), 0)
172*e4b17023SJohn Marino && operand_equal_p (gimple_cond_rhs (stmt),
173*e4b17023SJohn Marino TREE_OPERAND (cond, 1), 0))
174*e4b17023SJohn Marino return (e->flags & EDGE_TRUE_VALUE
175*e4b17023SJohn Marino ? boolean_true_node
176*e4b17023SJohn Marino : boolean_false_node);
177*e4b17023SJohn Marino
178*e4b17023SJohn Marino if (!single_pred_p (e->src))
179*e4b17023SJohn Marino return cond;
180*e4b17023SJohn Marino
181*e4b17023SJohn Marino e = single_pred_edge (e->src);
182*e4b17023SJohn Marino if (e->src == ENTRY_BLOCK_PTR)
183*e4b17023SJohn Marino return cond;
184*e4b17023SJohn Marino }
185*e4b17023SJohn Marino }
186*e4b17023SJohn Marino
187*e4b17023SJohn Marino /* Unswitch single LOOP. NUM is number of unswitchings done; we do not allow
188*e4b17023SJohn Marino it to grow too much, it is too easy to create example on that the code would
189*e4b17023SJohn Marino grow exponentially. */
190*e4b17023SJohn Marino
191*e4b17023SJohn Marino static bool
tree_unswitch_single_loop(struct loop * loop,int num)192*e4b17023SJohn Marino tree_unswitch_single_loop (struct loop *loop, int num)
193*e4b17023SJohn Marino {
194*e4b17023SJohn Marino basic_block *bbs;
195*e4b17023SJohn Marino struct loop *nloop;
196*e4b17023SJohn Marino unsigned i, found;
197*e4b17023SJohn Marino tree cond = NULL_TREE;
198*e4b17023SJohn Marino gimple stmt;
199*e4b17023SJohn Marino bool changed = false;
200*e4b17023SJohn Marino
201*e4b17023SJohn Marino i = 0;
202*e4b17023SJohn Marino bbs = get_loop_body (loop);
203*e4b17023SJohn Marino found = loop->num_nodes;
204*e4b17023SJohn Marino
205*e4b17023SJohn Marino while (1)
206*e4b17023SJohn Marino {
207*e4b17023SJohn Marino /* Find a bb to unswitch on. */
208*e4b17023SJohn Marino for (; i < loop->num_nodes; i++)
209*e4b17023SJohn Marino if ((cond = tree_may_unswitch_on (bbs[i], loop)))
210*e4b17023SJohn Marino break;
211*e4b17023SJohn Marino
212*e4b17023SJohn Marino if (i == loop->num_nodes)
213*e4b17023SJohn Marino {
214*e4b17023SJohn Marino if (dump_file
215*e4b17023SJohn Marino && num > PARAM_VALUE (PARAM_MAX_UNSWITCH_LEVEL)
216*e4b17023SJohn Marino && (dump_flags & TDF_DETAILS))
217*e4b17023SJohn Marino fprintf (dump_file, ";; Not unswitching anymore, hit max level\n");
218*e4b17023SJohn Marino
219*e4b17023SJohn Marino if (found == loop->num_nodes)
220*e4b17023SJohn Marino {
221*e4b17023SJohn Marino free (bbs);
222*e4b17023SJohn Marino return changed;
223*e4b17023SJohn Marino }
224*e4b17023SJohn Marino break;
225*e4b17023SJohn Marino }
226*e4b17023SJohn Marino
227*e4b17023SJohn Marino cond = simplify_using_entry_checks (loop, cond);
228*e4b17023SJohn Marino stmt = last_stmt (bbs[i]);
229*e4b17023SJohn Marino if (integer_nonzerop (cond))
230*e4b17023SJohn Marino {
231*e4b17023SJohn Marino /* Remove false path. */
232*e4b17023SJohn Marino gimple_cond_set_condition_from_tree (stmt, boolean_true_node);
233*e4b17023SJohn Marino changed = true;
234*e4b17023SJohn Marino }
235*e4b17023SJohn Marino else if (integer_zerop (cond))
236*e4b17023SJohn Marino {
237*e4b17023SJohn Marino /* Remove true path. */
238*e4b17023SJohn Marino gimple_cond_set_condition_from_tree (stmt, boolean_false_node);
239*e4b17023SJohn Marino changed = true;
240*e4b17023SJohn Marino }
241*e4b17023SJohn Marino /* Do not unswitch too much. */
242*e4b17023SJohn Marino else if (num > PARAM_VALUE (PARAM_MAX_UNSWITCH_LEVEL))
243*e4b17023SJohn Marino {
244*e4b17023SJohn Marino i++;
245*e4b17023SJohn Marino continue;
246*e4b17023SJohn Marino }
247*e4b17023SJohn Marino /* In nested tree_unswitch_single_loop first optimize all conditions
248*e4b17023SJohn Marino using entry checks, then discover still reachable blocks in the
249*e4b17023SJohn Marino loop and find the condition only among those still reachable bbs. */
250*e4b17023SJohn Marino else if (num != 0)
251*e4b17023SJohn Marino {
252*e4b17023SJohn Marino if (found == loop->num_nodes)
253*e4b17023SJohn Marino found = i;
254*e4b17023SJohn Marino i++;
255*e4b17023SJohn Marino continue;
256*e4b17023SJohn Marino }
257*e4b17023SJohn Marino else
258*e4b17023SJohn Marino {
259*e4b17023SJohn Marino found = i;
260*e4b17023SJohn Marino break;
261*e4b17023SJohn Marino }
262*e4b17023SJohn Marino
263*e4b17023SJohn Marino update_stmt (stmt);
264*e4b17023SJohn Marino i++;
265*e4b17023SJohn Marino }
266*e4b17023SJohn Marino
267*e4b17023SJohn Marino if (num != 0)
268*e4b17023SJohn Marino {
269*e4b17023SJohn Marino basic_block *tos, *worklist;
270*e4b17023SJohn Marino
271*e4b17023SJohn Marino /* When called recursively, first do a quick discovery
272*e4b17023SJohn Marino of reachable bbs after the above changes and only
273*e4b17023SJohn Marino consider conditions in still reachable bbs. */
274*e4b17023SJohn Marino tos = worklist = XNEWVEC (basic_block, loop->num_nodes);
275*e4b17023SJohn Marino
276*e4b17023SJohn Marino for (i = 0; i < loop->num_nodes; i++)
277*e4b17023SJohn Marino bbs[i]->flags &= ~BB_REACHABLE;
278*e4b17023SJohn Marino
279*e4b17023SJohn Marino /* Start with marking header. */
280*e4b17023SJohn Marino *tos++ = bbs[0];
281*e4b17023SJohn Marino bbs[0]->flags |= BB_REACHABLE;
282*e4b17023SJohn Marino
283*e4b17023SJohn Marino /* Iterate: find everything reachable from what we've already seen
284*e4b17023SJohn Marino within the same innermost loop. Don't look through false edges
285*e4b17023SJohn Marino if condition is always true or true edges if condition is
286*e4b17023SJohn Marino always false. */
287*e4b17023SJohn Marino while (tos != worklist)
288*e4b17023SJohn Marino {
289*e4b17023SJohn Marino basic_block b = *--tos;
290*e4b17023SJohn Marino edge e;
291*e4b17023SJohn Marino edge_iterator ei;
292*e4b17023SJohn Marino int flags = 0;
293*e4b17023SJohn Marino
294*e4b17023SJohn Marino if (EDGE_COUNT (b->succs) == 2)
295*e4b17023SJohn Marino {
296*e4b17023SJohn Marino gimple stmt = last_stmt (b);
297*e4b17023SJohn Marino if (stmt
298*e4b17023SJohn Marino && gimple_code (stmt) == GIMPLE_COND)
299*e4b17023SJohn Marino {
300*e4b17023SJohn Marino if (gimple_cond_true_p (stmt))
301*e4b17023SJohn Marino flags = EDGE_FALSE_VALUE;
302*e4b17023SJohn Marino else if (gimple_cond_false_p (stmt))
303*e4b17023SJohn Marino flags = EDGE_TRUE_VALUE;
304*e4b17023SJohn Marino }
305*e4b17023SJohn Marino }
306*e4b17023SJohn Marino
307*e4b17023SJohn Marino FOR_EACH_EDGE (e, ei, b->succs)
308*e4b17023SJohn Marino {
309*e4b17023SJohn Marino basic_block dest = e->dest;
310*e4b17023SJohn Marino
311*e4b17023SJohn Marino if (dest->loop_father == loop
312*e4b17023SJohn Marino && !(dest->flags & BB_REACHABLE)
313*e4b17023SJohn Marino && !(e->flags & flags))
314*e4b17023SJohn Marino {
315*e4b17023SJohn Marino *tos++ = dest;
316*e4b17023SJohn Marino dest->flags |= BB_REACHABLE;
317*e4b17023SJohn Marino }
318*e4b17023SJohn Marino }
319*e4b17023SJohn Marino }
320*e4b17023SJohn Marino
321*e4b17023SJohn Marino free (worklist);
322*e4b17023SJohn Marino
323*e4b17023SJohn Marino /* Find a bb to unswitch on. */
324*e4b17023SJohn Marino for (; found < loop->num_nodes; found++)
325*e4b17023SJohn Marino if ((bbs[found]->flags & BB_REACHABLE)
326*e4b17023SJohn Marino && (cond = tree_may_unswitch_on (bbs[found], loop)))
327*e4b17023SJohn Marino break;
328*e4b17023SJohn Marino
329*e4b17023SJohn Marino if (found == loop->num_nodes)
330*e4b17023SJohn Marino {
331*e4b17023SJohn Marino free (bbs);
332*e4b17023SJohn Marino return changed;
333*e4b17023SJohn Marino }
334*e4b17023SJohn Marino }
335*e4b17023SJohn Marino
336*e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS))
337*e4b17023SJohn Marino fprintf (dump_file, ";; Unswitching loop\n");
338*e4b17023SJohn Marino
339*e4b17023SJohn Marino initialize_original_copy_tables ();
340*e4b17023SJohn Marino /* Unswitch the loop on this condition. */
341*e4b17023SJohn Marino nloop = tree_unswitch_loop (loop, bbs[found], cond);
342*e4b17023SJohn Marino if (!nloop)
343*e4b17023SJohn Marino {
344*e4b17023SJohn Marino free_original_copy_tables ();
345*e4b17023SJohn Marino free (bbs);
346*e4b17023SJohn Marino return changed;
347*e4b17023SJohn Marino }
348*e4b17023SJohn Marino
349*e4b17023SJohn Marino /* Update the SSA form after unswitching. */
350*e4b17023SJohn Marino update_ssa (TODO_update_ssa);
351*e4b17023SJohn Marino free_original_copy_tables ();
352*e4b17023SJohn Marino
353*e4b17023SJohn Marino /* Invoke itself on modified loops. */
354*e4b17023SJohn Marino tree_unswitch_single_loop (nloop, num + 1);
355*e4b17023SJohn Marino tree_unswitch_single_loop (loop, num + 1);
356*e4b17023SJohn Marino free (bbs);
357*e4b17023SJohn Marino return true;
358*e4b17023SJohn Marino }
359*e4b17023SJohn Marino
360*e4b17023SJohn Marino /* Unswitch a LOOP w.r. to given basic block UNSWITCH_ON. We only support
361*e4b17023SJohn Marino unswitching of innermost loops. COND is the condition determining which
362*e4b17023SJohn Marino loop is entered -- the new loop is entered if COND is true. Returns NULL
363*e4b17023SJohn Marino if impossible, new loop otherwise. */
364*e4b17023SJohn Marino
365*e4b17023SJohn Marino static struct loop *
tree_unswitch_loop(struct loop * loop,basic_block unswitch_on,tree cond)366*e4b17023SJohn Marino tree_unswitch_loop (struct loop *loop,
367*e4b17023SJohn Marino basic_block unswitch_on, tree cond)
368*e4b17023SJohn Marino {
369*e4b17023SJohn Marino unsigned prob_true;
370*e4b17023SJohn Marino edge edge_true, edge_false;
371*e4b17023SJohn Marino
372*e4b17023SJohn Marino /* Some sanity checking. */
373*e4b17023SJohn Marino gcc_assert (flow_bb_inside_loop_p (loop, unswitch_on));
374*e4b17023SJohn Marino gcc_assert (EDGE_COUNT (unswitch_on->succs) == 2);
375*e4b17023SJohn Marino gcc_assert (loop->inner == NULL);
376*e4b17023SJohn Marino
377*e4b17023SJohn Marino extract_true_false_edges_from_block (unswitch_on, &edge_true, &edge_false);
378*e4b17023SJohn Marino prob_true = edge_true->probability;
379*e4b17023SJohn Marino return loop_version (loop, unshare_expr (cond),
380*e4b17023SJohn Marino NULL, prob_true, prob_true,
381*e4b17023SJohn Marino REG_BR_PROB_BASE - prob_true, false);
382*e4b17023SJohn Marino }
383