xref: /dflybsd-src/contrib/gcc-4.7/gcc/tree-ssa-loop-ivcanon.c (revision 04febcfb30580676d3e95f58a16c5137ee478b32)
1*e4b17023SJohn Marino /* Induction variable canonicalization.
2*e4b17023SJohn Marino    Copyright (C) 2004, 2005, 2007, 2008, 2010
3*e4b17023SJohn Marino    Free Software Foundation, Inc.
4*e4b17023SJohn Marino 
5*e4b17023SJohn Marino This file is part of GCC.
6*e4b17023SJohn Marino 
7*e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it
8*e4b17023SJohn Marino under the terms of the GNU General Public License as published by the
9*e4b17023SJohn Marino Free Software Foundation; either version 3, or (at your option) any
10*e4b17023SJohn Marino later version.
11*e4b17023SJohn Marino 
12*e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT
13*e4b17023SJohn Marino ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14*e4b17023SJohn Marino FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15*e4b17023SJohn Marino for more details.
16*e4b17023SJohn Marino 
17*e4b17023SJohn Marino You should have received a copy of the GNU General Public License
18*e4b17023SJohn Marino along with GCC; see the file COPYING3.  If not see
19*e4b17023SJohn Marino <http://www.gnu.org/licenses/>.  */
20*e4b17023SJohn Marino 
21*e4b17023SJohn Marino /* This pass detects the loops that iterate a constant number of times,
22*e4b17023SJohn Marino    adds a canonical induction variable (step -1, tested against 0)
23*e4b17023SJohn Marino    and replaces the exit test.  This enables the less powerful rtl
24*e4b17023SJohn Marino    level analysis to use this information.
25*e4b17023SJohn Marino 
26*e4b17023SJohn Marino    This might spoil the code in some cases (by increasing register pressure).
27*e4b17023SJohn Marino    Note that in the case the new variable is not needed, ivopts will get rid
28*e4b17023SJohn Marino    of it, so it might only be a problem when there are no other linear induction
29*e4b17023SJohn Marino    variables.  In that case the created optimization possibilities are likely
30*e4b17023SJohn Marino    to pay up.
31*e4b17023SJohn Marino 
32*e4b17023SJohn Marino    Additionally in case we detect that it is beneficial to unroll the
33*e4b17023SJohn Marino    loop completely, we do it right here to expose the optimization
34*e4b17023SJohn Marino    possibilities to the following passes.  */
35*e4b17023SJohn Marino 
36*e4b17023SJohn Marino #include "config.h"
37*e4b17023SJohn Marino #include "system.h"
38*e4b17023SJohn Marino #include "coretypes.h"
39*e4b17023SJohn Marino #include "tm.h"
40*e4b17023SJohn Marino #include "tree.h"
41*e4b17023SJohn Marino #include "tm_p.h"
42*e4b17023SJohn Marino #include "basic-block.h"
43*e4b17023SJohn Marino #include "tree-pretty-print.h"
44*e4b17023SJohn Marino #include "gimple-pretty-print.h"
45*e4b17023SJohn Marino #include "tree-flow.h"
46*e4b17023SJohn Marino #include "tree-dump.h"
47*e4b17023SJohn Marino #include "cfgloop.h"
48*e4b17023SJohn Marino #include "tree-pass.h"
49*e4b17023SJohn Marino #include "tree-chrec.h"
50*e4b17023SJohn Marino #include "tree-scalar-evolution.h"
51*e4b17023SJohn Marino #include "params.h"
52*e4b17023SJohn Marino #include "flags.h"
53*e4b17023SJohn Marino #include "tree-inline.h"
54*e4b17023SJohn Marino #include "target.h"
55*e4b17023SJohn Marino 
56*e4b17023SJohn Marino /* Specifies types of loops that may be unrolled.  */
57*e4b17023SJohn Marino 
58*e4b17023SJohn Marino enum unroll_level
59*e4b17023SJohn Marino {
60*e4b17023SJohn Marino   UL_SINGLE_ITER,	/* Only loops that exit immediately in the first
61*e4b17023SJohn Marino 			   iteration.  */
62*e4b17023SJohn Marino   UL_NO_GROWTH,		/* Only loops whose unrolling will not cause increase
63*e4b17023SJohn Marino 			   of code size.  */
64*e4b17023SJohn Marino   UL_ALL		/* All suitable loops.  */
65*e4b17023SJohn Marino };
66*e4b17023SJohn Marino 
67*e4b17023SJohn Marino /* Adds a canonical induction variable to LOOP iterating NITER times.  EXIT
68*e4b17023SJohn Marino    is the exit edge whose condition is replaced.  */
69*e4b17023SJohn Marino 
70*e4b17023SJohn Marino static void
create_canonical_iv(struct loop * loop,edge exit,tree niter)71*e4b17023SJohn Marino create_canonical_iv (struct loop *loop, edge exit, tree niter)
72*e4b17023SJohn Marino {
73*e4b17023SJohn Marino   edge in;
74*e4b17023SJohn Marino   tree type, var;
75*e4b17023SJohn Marino   gimple cond;
76*e4b17023SJohn Marino   gimple_stmt_iterator incr_at;
77*e4b17023SJohn Marino   enum tree_code cmp;
78*e4b17023SJohn Marino 
79*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
80*e4b17023SJohn Marino     {
81*e4b17023SJohn Marino       fprintf (dump_file, "Added canonical iv to loop %d, ", loop->num);
82*e4b17023SJohn Marino       print_generic_expr (dump_file, niter, TDF_SLIM);
83*e4b17023SJohn Marino       fprintf (dump_file, " iterations.\n");
84*e4b17023SJohn Marino     }
85*e4b17023SJohn Marino 
86*e4b17023SJohn Marino   cond = last_stmt (exit->src);
87*e4b17023SJohn Marino   in = EDGE_SUCC (exit->src, 0);
88*e4b17023SJohn Marino   if (in == exit)
89*e4b17023SJohn Marino     in = EDGE_SUCC (exit->src, 1);
90*e4b17023SJohn Marino 
91*e4b17023SJohn Marino   /* Note that we do not need to worry about overflows, since
92*e4b17023SJohn Marino      type of niter is always unsigned and all comparisons are
93*e4b17023SJohn Marino      just for equality/nonequality -- i.e. everything works
94*e4b17023SJohn Marino      with a modulo arithmetics.  */
95*e4b17023SJohn Marino 
96*e4b17023SJohn Marino   type = TREE_TYPE (niter);
97*e4b17023SJohn Marino   niter = fold_build2 (PLUS_EXPR, type,
98*e4b17023SJohn Marino 		       niter,
99*e4b17023SJohn Marino 		       build_int_cst (type, 1));
100*e4b17023SJohn Marino   incr_at = gsi_last_bb (in->src);
101*e4b17023SJohn Marino   create_iv (niter,
102*e4b17023SJohn Marino 	     build_int_cst (type, -1),
103*e4b17023SJohn Marino 	     NULL_TREE, loop,
104*e4b17023SJohn Marino 	     &incr_at, false, NULL, &var);
105*e4b17023SJohn Marino 
106*e4b17023SJohn Marino   cmp = (exit->flags & EDGE_TRUE_VALUE) ? EQ_EXPR : NE_EXPR;
107*e4b17023SJohn Marino   gimple_cond_set_code (cond, cmp);
108*e4b17023SJohn Marino   gimple_cond_set_lhs (cond, var);
109*e4b17023SJohn Marino   gimple_cond_set_rhs (cond, build_int_cst (type, 0));
110*e4b17023SJohn Marino   update_stmt (cond);
111*e4b17023SJohn Marino }
112*e4b17023SJohn Marino 
113*e4b17023SJohn Marino /* Computes an estimated number of insns in LOOP, weighted by WEIGHTS.  */
114*e4b17023SJohn Marino 
115*e4b17023SJohn Marino unsigned
tree_num_loop_insns(struct loop * loop,eni_weights * weights)116*e4b17023SJohn Marino tree_num_loop_insns (struct loop *loop, eni_weights *weights)
117*e4b17023SJohn Marino {
118*e4b17023SJohn Marino   basic_block *body = get_loop_body (loop);
119*e4b17023SJohn Marino   gimple_stmt_iterator gsi;
120*e4b17023SJohn Marino   unsigned size = 0, i;
121*e4b17023SJohn Marino 
122*e4b17023SJohn Marino   for (i = 0; i < loop->num_nodes; i++)
123*e4b17023SJohn Marino     for (gsi = gsi_start_bb (body[i]); !gsi_end_p (gsi); gsi_next (&gsi))
124*e4b17023SJohn Marino       size += estimate_num_insns (gsi_stmt (gsi), weights);
125*e4b17023SJohn Marino   free (body);
126*e4b17023SJohn Marino 
127*e4b17023SJohn Marino   return size;
128*e4b17023SJohn Marino }
129*e4b17023SJohn Marino 
130*e4b17023SJohn Marino /* Describe size of loop as detected by tree_estimate_loop_size.  */
131*e4b17023SJohn Marino struct loop_size
132*e4b17023SJohn Marino {
133*e4b17023SJohn Marino   /* Number of instructions in the loop.  */
134*e4b17023SJohn Marino   int overall;
135*e4b17023SJohn Marino 
136*e4b17023SJohn Marino   /* Number of instructions that will be likely optimized out in
137*e4b17023SJohn Marino      peeled iterations of loop  (i.e. computation based on induction
138*e4b17023SJohn Marino      variable where induction variable starts at known constant.)  */
139*e4b17023SJohn Marino   int eliminated_by_peeling;
140*e4b17023SJohn Marino 
141*e4b17023SJohn Marino   /* Same statistics for last iteration of loop: it is smaller because
142*e4b17023SJohn Marino      instructions after exit are not executed.  */
143*e4b17023SJohn Marino   int last_iteration;
144*e4b17023SJohn Marino   int last_iteration_eliminated_by_peeling;
145*e4b17023SJohn Marino };
146*e4b17023SJohn Marino 
147*e4b17023SJohn Marino /* Return true if OP in STMT will be constant after peeling LOOP.  */
148*e4b17023SJohn Marino 
149*e4b17023SJohn Marino static bool
constant_after_peeling(tree op,gimple stmt,struct loop * loop)150*e4b17023SJohn Marino constant_after_peeling (tree op, gimple stmt, struct loop *loop)
151*e4b17023SJohn Marino {
152*e4b17023SJohn Marino   affine_iv iv;
153*e4b17023SJohn Marino 
154*e4b17023SJohn Marino   if (is_gimple_min_invariant (op))
155*e4b17023SJohn Marino     return true;
156*e4b17023SJohn Marino 
157*e4b17023SJohn Marino   /* We can still fold accesses to constant arrays when index is known.  */
158*e4b17023SJohn Marino   if (TREE_CODE (op) != SSA_NAME)
159*e4b17023SJohn Marino     {
160*e4b17023SJohn Marino       tree base = op;
161*e4b17023SJohn Marino 
162*e4b17023SJohn Marino       /* First make fast look if we see constant array inside.  */
163*e4b17023SJohn Marino       while (handled_component_p (base))
164*e4b17023SJohn Marino 	base = TREE_OPERAND (base, 0);
165*e4b17023SJohn Marino       if ((DECL_P (base) == VAR_DECL
166*e4b17023SJohn Marino 	   && const_value_known_p (base))
167*e4b17023SJohn Marino 	  || CONSTANT_CLASS_P (base))
168*e4b17023SJohn Marino 	{
169*e4b17023SJohn Marino 	  /* If so, see if we understand all the indices.  */
170*e4b17023SJohn Marino 	  base = op;
171*e4b17023SJohn Marino 	  while (handled_component_p (base))
172*e4b17023SJohn Marino 	    {
173*e4b17023SJohn Marino 	      if (TREE_CODE (base) == ARRAY_REF
174*e4b17023SJohn Marino 		  && !constant_after_peeling (TREE_OPERAND (base, 1), stmt, loop))
175*e4b17023SJohn Marino 		return false;
176*e4b17023SJohn Marino 	      base = TREE_OPERAND (base, 0);
177*e4b17023SJohn Marino 	    }
178*e4b17023SJohn Marino 	  return true;
179*e4b17023SJohn Marino 	}
180*e4b17023SJohn Marino       return false;
181*e4b17023SJohn Marino     }
182*e4b17023SJohn Marino 
183*e4b17023SJohn Marino   /* Induction variables are constants.  */
184*e4b17023SJohn Marino   if (!simple_iv (loop, loop_containing_stmt (stmt), op, &iv, false))
185*e4b17023SJohn Marino     return false;
186*e4b17023SJohn Marino   if (!is_gimple_min_invariant (iv.base))
187*e4b17023SJohn Marino     return false;
188*e4b17023SJohn Marino   if (!is_gimple_min_invariant (iv.step))
189*e4b17023SJohn Marino     return false;
190*e4b17023SJohn Marino   return true;
191*e4b17023SJohn Marino }
192*e4b17023SJohn Marino 
193*e4b17023SJohn Marino /* Computes an estimated number of insns in LOOP, weighted by WEIGHTS.
194*e4b17023SJohn Marino    Return results in SIZE, estimate benefits for complete unrolling exiting by EXIT.  */
195*e4b17023SJohn Marino 
196*e4b17023SJohn Marino static void
tree_estimate_loop_size(struct loop * loop,edge exit,struct loop_size * size)197*e4b17023SJohn Marino tree_estimate_loop_size (struct loop *loop, edge exit, struct loop_size *size)
198*e4b17023SJohn Marino {
199*e4b17023SJohn Marino   basic_block *body = get_loop_body (loop);
200*e4b17023SJohn Marino   gimple_stmt_iterator gsi;
201*e4b17023SJohn Marino   unsigned int i;
202*e4b17023SJohn Marino   bool after_exit;
203*e4b17023SJohn Marino 
204*e4b17023SJohn Marino   size->overall = 0;
205*e4b17023SJohn Marino   size->eliminated_by_peeling = 0;
206*e4b17023SJohn Marino   size->last_iteration = 0;
207*e4b17023SJohn Marino   size->last_iteration_eliminated_by_peeling = 0;
208*e4b17023SJohn Marino 
209*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
210*e4b17023SJohn Marino     fprintf (dump_file, "Estimating sizes for loop %i\n", loop->num);
211*e4b17023SJohn Marino   for (i = 0; i < loop->num_nodes; i++)
212*e4b17023SJohn Marino     {
213*e4b17023SJohn Marino       if (exit && body[i] != exit->src
214*e4b17023SJohn Marino 	  && dominated_by_p (CDI_DOMINATORS, body[i], exit->src))
215*e4b17023SJohn Marino 	after_exit = true;
216*e4b17023SJohn Marino       else
217*e4b17023SJohn Marino 	after_exit = false;
218*e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
219*e4b17023SJohn Marino 	fprintf (dump_file, " BB: %i, after_exit: %i\n", body[i]->index, after_exit);
220*e4b17023SJohn Marino 
221*e4b17023SJohn Marino       for (gsi = gsi_start_bb (body[i]); !gsi_end_p (gsi); gsi_next (&gsi))
222*e4b17023SJohn Marino 	{
223*e4b17023SJohn Marino 	  gimple stmt = gsi_stmt (gsi);
224*e4b17023SJohn Marino 	  int num = estimate_num_insns (stmt, &eni_size_weights);
225*e4b17023SJohn Marino 	  bool likely_eliminated = false;
226*e4b17023SJohn Marino 
227*e4b17023SJohn Marino 	  if (dump_file && (dump_flags & TDF_DETAILS))
228*e4b17023SJohn Marino 	    {
229*e4b17023SJohn Marino 	      fprintf (dump_file, "  size: %3i ", num);
230*e4b17023SJohn Marino 	      print_gimple_stmt (dump_file, gsi_stmt (gsi), 0, 0);
231*e4b17023SJohn Marino 	    }
232*e4b17023SJohn Marino 
233*e4b17023SJohn Marino 	  /* Look for reasons why we might optimize this stmt away. */
234*e4b17023SJohn Marino 
235*e4b17023SJohn Marino 	  /* Exit conditional.  */
236*e4b17023SJohn Marino 	  if (body[i] == exit->src && stmt == last_stmt (exit->src))
237*e4b17023SJohn Marino 	    {
238*e4b17023SJohn Marino 	      if (dump_file && (dump_flags & TDF_DETAILS))
239*e4b17023SJohn Marino 	        fprintf (dump_file, "   Exit condition will be eliminated.\n");
240*e4b17023SJohn Marino 	      likely_eliminated = true;
241*e4b17023SJohn Marino 	    }
242*e4b17023SJohn Marino 	  /* Sets of IV variables  */
243*e4b17023SJohn Marino 	  else if (gimple_code (stmt) == GIMPLE_ASSIGN
244*e4b17023SJohn Marino 	      && constant_after_peeling (gimple_assign_lhs (stmt), stmt, loop))
245*e4b17023SJohn Marino 	    {
246*e4b17023SJohn Marino 	      if (dump_file && (dump_flags & TDF_DETAILS))
247*e4b17023SJohn Marino 	        fprintf (dump_file, "   Induction variable computation will"
248*e4b17023SJohn Marino 			 " be folded away.\n");
249*e4b17023SJohn Marino 	      likely_eliminated = true;
250*e4b17023SJohn Marino 	    }
251*e4b17023SJohn Marino 	  /* Assignments of IV variables.  */
252*e4b17023SJohn Marino 	  else if (gimple_code (stmt) == GIMPLE_ASSIGN
253*e4b17023SJohn Marino 		   && TREE_CODE (gimple_assign_lhs (stmt)) == SSA_NAME
254*e4b17023SJohn Marino 		   && constant_after_peeling (gimple_assign_rhs1 (stmt), stmt,loop)
255*e4b17023SJohn Marino 		   && (gimple_assign_rhs_class (stmt) != GIMPLE_BINARY_RHS
256*e4b17023SJohn Marino 		       || constant_after_peeling (gimple_assign_rhs2 (stmt),
257*e4b17023SJohn Marino 		       				  stmt, loop)))
258*e4b17023SJohn Marino 	    {
259*e4b17023SJohn Marino 	      if (dump_file && (dump_flags & TDF_DETAILS))
260*e4b17023SJohn Marino 	        fprintf (dump_file, "   Constant expression will be folded away.\n");
261*e4b17023SJohn Marino 	      likely_eliminated = true;
262*e4b17023SJohn Marino 	    }
263*e4b17023SJohn Marino 	  /* Conditionals.  */
264*e4b17023SJohn Marino 	  else if (gimple_code (stmt) == GIMPLE_COND
265*e4b17023SJohn Marino 		   && constant_after_peeling (gimple_cond_lhs (stmt), stmt, loop)
266*e4b17023SJohn Marino 		   && constant_after_peeling (gimple_cond_rhs (stmt), stmt, loop))
267*e4b17023SJohn Marino 	    {
268*e4b17023SJohn Marino 	      if (dump_file && (dump_flags & TDF_DETAILS))
269*e4b17023SJohn Marino 	        fprintf (dump_file, "   Constant conditional.\n");
270*e4b17023SJohn Marino 	      likely_eliminated = true;
271*e4b17023SJohn Marino 	    }
272*e4b17023SJohn Marino 
273*e4b17023SJohn Marino 	  size->overall += num;
274*e4b17023SJohn Marino 	  if (likely_eliminated)
275*e4b17023SJohn Marino 	    size->eliminated_by_peeling += num;
276*e4b17023SJohn Marino 	  if (!after_exit)
277*e4b17023SJohn Marino 	    {
278*e4b17023SJohn Marino 	      size->last_iteration += num;
279*e4b17023SJohn Marino 	      if (likely_eliminated)
280*e4b17023SJohn Marino 		size->last_iteration_eliminated_by_peeling += num;
281*e4b17023SJohn Marino 	    }
282*e4b17023SJohn Marino 	}
283*e4b17023SJohn Marino     }
284*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
285*e4b17023SJohn Marino     fprintf (dump_file, "size: %i-%i, last_iteration: %i-%i\n", size->overall,
286*e4b17023SJohn Marino     	     size->eliminated_by_peeling, size->last_iteration,
287*e4b17023SJohn Marino 	     size->last_iteration_eliminated_by_peeling);
288*e4b17023SJohn Marino 
289*e4b17023SJohn Marino   free (body);
290*e4b17023SJohn Marino }
291*e4b17023SJohn Marino 
292*e4b17023SJohn Marino /* Estimate number of insns of completely unrolled loop.
293*e4b17023SJohn Marino    It is (NUNROLL + 1) * size of loop body with taking into account
294*e4b17023SJohn Marino    the fact that in last copy everything after exit conditional
295*e4b17023SJohn Marino    is dead and that some instructions will be eliminated after
296*e4b17023SJohn Marino    peeling.
297*e4b17023SJohn Marino 
298*e4b17023SJohn Marino    Loop body is likely going to simplify futher, this is difficult
299*e4b17023SJohn Marino    to guess, we just decrease the result by 1/3.  */
300*e4b17023SJohn Marino 
301*e4b17023SJohn Marino static unsigned HOST_WIDE_INT
estimated_unrolled_size(struct loop_size * size,unsigned HOST_WIDE_INT nunroll)302*e4b17023SJohn Marino estimated_unrolled_size (struct loop_size *size,
303*e4b17023SJohn Marino 			 unsigned HOST_WIDE_INT nunroll)
304*e4b17023SJohn Marino {
305*e4b17023SJohn Marino   HOST_WIDE_INT unr_insns = ((nunroll)
306*e4b17023SJohn Marino   			     * (HOST_WIDE_INT) (size->overall
307*e4b17023SJohn Marino 			     			- size->eliminated_by_peeling));
308*e4b17023SJohn Marino   if (!nunroll)
309*e4b17023SJohn Marino     unr_insns = 0;
310*e4b17023SJohn Marino   unr_insns += size->last_iteration - size->last_iteration_eliminated_by_peeling;
311*e4b17023SJohn Marino 
312*e4b17023SJohn Marino   unr_insns = unr_insns * 2 / 3;
313*e4b17023SJohn Marino   if (unr_insns <= 0)
314*e4b17023SJohn Marino     unr_insns = 1;
315*e4b17023SJohn Marino 
316*e4b17023SJohn Marino   return unr_insns;
317*e4b17023SJohn Marino }
318*e4b17023SJohn Marino 
319*e4b17023SJohn Marino /* Tries to unroll LOOP completely, i.e. NITER times.
320*e4b17023SJohn Marino    UL determines which loops we are allowed to unroll.
321*e4b17023SJohn Marino    EXIT is the exit of the loop that should be eliminated.  */
322*e4b17023SJohn Marino 
323*e4b17023SJohn Marino static bool
try_unroll_loop_completely(struct loop * loop,edge exit,tree niter,enum unroll_level ul)324*e4b17023SJohn Marino try_unroll_loop_completely (struct loop *loop,
325*e4b17023SJohn Marino 			    edge exit, tree niter,
326*e4b17023SJohn Marino 			    enum unroll_level ul)
327*e4b17023SJohn Marino {
328*e4b17023SJohn Marino   unsigned HOST_WIDE_INT n_unroll, ninsns, max_unroll, unr_insns;
329*e4b17023SJohn Marino   gimple cond;
330*e4b17023SJohn Marino   struct loop_size size;
331*e4b17023SJohn Marino 
332*e4b17023SJohn Marino   if (loop->inner)
333*e4b17023SJohn Marino     return false;
334*e4b17023SJohn Marino 
335*e4b17023SJohn Marino   if (!host_integerp (niter, 1))
336*e4b17023SJohn Marino     return false;
337*e4b17023SJohn Marino   n_unroll = tree_low_cst (niter, 1);
338*e4b17023SJohn Marino 
339*e4b17023SJohn Marino   max_unroll = PARAM_VALUE (PARAM_MAX_COMPLETELY_PEEL_TIMES);
340*e4b17023SJohn Marino   if (n_unroll > max_unroll)
341*e4b17023SJohn Marino     return false;
342*e4b17023SJohn Marino 
343*e4b17023SJohn Marino   if (n_unroll)
344*e4b17023SJohn Marino     {
345*e4b17023SJohn Marino       if (ul == UL_SINGLE_ITER)
346*e4b17023SJohn Marino 	return false;
347*e4b17023SJohn Marino 
348*e4b17023SJohn Marino       tree_estimate_loop_size (loop, exit, &size);
349*e4b17023SJohn Marino       ninsns = size.overall;
350*e4b17023SJohn Marino 
351*e4b17023SJohn Marino       unr_insns = estimated_unrolled_size (&size, n_unroll);
352*e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
353*e4b17023SJohn Marino 	{
354*e4b17023SJohn Marino 	  fprintf (dump_file, "  Loop size: %d\n", (int) ninsns);
355*e4b17023SJohn Marino 	  fprintf (dump_file, "  Estimated size after unrolling: %d\n",
356*e4b17023SJohn Marino 		   (int) unr_insns);
357*e4b17023SJohn Marino 	}
358*e4b17023SJohn Marino 
359*e4b17023SJohn Marino       if (unr_insns > ninsns
360*e4b17023SJohn Marino 	  && (unr_insns
361*e4b17023SJohn Marino 	      > (unsigned) PARAM_VALUE (PARAM_MAX_COMPLETELY_PEELED_INSNS)))
362*e4b17023SJohn Marino 	{
363*e4b17023SJohn Marino 	  if (dump_file && (dump_flags & TDF_DETAILS))
364*e4b17023SJohn Marino 	    fprintf (dump_file, "Not unrolling loop %d "
365*e4b17023SJohn Marino 		     "(--param max-completely-peeled-insns limit reached).\n",
366*e4b17023SJohn Marino 		     loop->num);
367*e4b17023SJohn Marino 	  return false;
368*e4b17023SJohn Marino 	}
369*e4b17023SJohn Marino 
370*e4b17023SJohn Marino       if (ul == UL_NO_GROWTH
371*e4b17023SJohn Marino 	  && unr_insns > ninsns)
372*e4b17023SJohn Marino 	{
373*e4b17023SJohn Marino 	  if (dump_file && (dump_flags & TDF_DETAILS))
374*e4b17023SJohn Marino 	    fprintf (dump_file, "Not unrolling loop %d.\n", loop->num);
375*e4b17023SJohn Marino 	  return false;
376*e4b17023SJohn Marino 	}
377*e4b17023SJohn Marino     }
378*e4b17023SJohn Marino 
379*e4b17023SJohn Marino   if (n_unroll)
380*e4b17023SJohn Marino     {
381*e4b17023SJohn Marino       sbitmap wont_exit;
382*e4b17023SJohn Marino       edge e;
383*e4b17023SJohn Marino       unsigned i;
384*e4b17023SJohn Marino       VEC (edge, heap) *to_remove = NULL;
385*e4b17023SJohn Marino 
386*e4b17023SJohn Marino       initialize_original_copy_tables ();
387*e4b17023SJohn Marino       wont_exit = sbitmap_alloc (n_unroll + 1);
388*e4b17023SJohn Marino       sbitmap_ones (wont_exit);
389*e4b17023SJohn Marino       RESET_BIT (wont_exit, 0);
390*e4b17023SJohn Marino 
391*e4b17023SJohn Marino       if (!gimple_duplicate_loop_to_header_edge (loop, loop_preheader_edge (loop),
392*e4b17023SJohn Marino 						 n_unroll, wont_exit,
393*e4b17023SJohn Marino 						 exit, &to_remove,
394*e4b17023SJohn Marino 						 DLTHE_FLAG_UPDATE_FREQ
395*e4b17023SJohn Marino 						 | DLTHE_FLAG_COMPLETTE_PEEL))
396*e4b17023SJohn Marino 	{
397*e4b17023SJohn Marino           free_original_copy_tables ();
398*e4b17023SJohn Marino 	  free (wont_exit);
399*e4b17023SJohn Marino 	  return false;
400*e4b17023SJohn Marino 	}
401*e4b17023SJohn Marino 
402*e4b17023SJohn Marino       FOR_EACH_VEC_ELT (edge, to_remove, i, e)
403*e4b17023SJohn Marino 	{
404*e4b17023SJohn Marino 	  bool ok = remove_path (e);
405*e4b17023SJohn Marino 	  gcc_assert (ok);
406*e4b17023SJohn Marino 	}
407*e4b17023SJohn Marino 
408*e4b17023SJohn Marino       VEC_free (edge, heap, to_remove);
409*e4b17023SJohn Marino       free (wont_exit);
410*e4b17023SJohn Marino       free_original_copy_tables ();
411*e4b17023SJohn Marino     }
412*e4b17023SJohn Marino 
413*e4b17023SJohn Marino   cond = last_stmt (exit->src);
414*e4b17023SJohn Marino   if (exit->flags & EDGE_TRUE_VALUE)
415*e4b17023SJohn Marino     gimple_cond_make_true (cond);
416*e4b17023SJohn Marino   else
417*e4b17023SJohn Marino     gimple_cond_make_false (cond);
418*e4b17023SJohn Marino   update_stmt (cond);
419*e4b17023SJohn Marino   update_ssa (TODO_update_ssa);
420*e4b17023SJohn Marino 
421*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
422*e4b17023SJohn Marino     fprintf (dump_file, "Unrolled loop %d completely.\n", loop->num);
423*e4b17023SJohn Marino 
424*e4b17023SJohn Marino   return true;
425*e4b17023SJohn Marino }
426*e4b17023SJohn Marino 
427*e4b17023SJohn Marino /* Adds a canonical induction variable to LOOP if suitable.
428*e4b17023SJohn Marino    CREATE_IV is true if we may create a new iv.  UL determines
429*e4b17023SJohn Marino    which loops we are allowed to completely unroll.  If TRY_EVAL is true, we try
430*e4b17023SJohn Marino    to determine the number of iterations of a loop by direct evaluation.
431*e4b17023SJohn Marino    Returns true if cfg is changed.  */
432*e4b17023SJohn Marino 
433*e4b17023SJohn Marino static bool
canonicalize_loop_induction_variables(struct loop * loop,bool create_iv,enum unroll_level ul,bool try_eval)434*e4b17023SJohn Marino canonicalize_loop_induction_variables (struct loop *loop,
435*e4b17023SJohn Marino 				       bool create_iv, enum unroll_level ul,
436*e4b17023SJohn Marino 				       bool try_eval)
437*e4b17023SJohn Marino {
438*e4b17023SJohn Marino   edge exit = NULL;
439*e4b17023SJohn Marino   tree niter;
440*e4b17023SJohn Marino 
441*e4b17023SJohn Marino   niter = number_of_latch_executions (loop);
442*e4b17023SJohn Marino   if (TREE_CODE (niter) == INTEGER_CST)
443*e4b17023SJohn Marino     {
444*e4b17023SJohn Marino       exit = single_exit (loop);
445*e4b17023SJohn Marino       if (!just_once_each_iteration_p (loop, exit->src))
446*e4b17023SJohn Marino 	return false;
447*e4b17023SJohn Marino     }
448*e4b17023SJohn Marino   else
449*e4b17023SJohn Marino     {
450*e4b17023SJohn Marino       /* If the loop has more than one exit, try checking all of them
451*e4b17023SJohn Marino 	 for # of iterations determinable through scev.  */
452*e4b17023SJohn Marino       if (!single_exit (loop))
453*e4b17023SJohn Marino 	niter = find_loop_niter (loop, &exit);
454*e4b17023SJohn Marino 
455*e4b17023SJohn Marino       /* Finally if everything else fails, try brute force evaluation.  */
456*e4b17023SJohn Marino       if (try_eval
457*e4b17023SJohn Marino 	  && (chrec_contains_undetermined (niter)
458*e4b17023SJohn Marino 	      || TREE_CODE (niter) != INTEGER_CST))
459*e4b17023SJohn Marino 	niter = find_loop_niter_by_eval (loop, &exit);
460*e4b17023SJohn Marino 
461*e4b17023SJohn Marino       if (chrec_contains_undetermined (niter)
462*e4b17023SJohn Marino 	  || TREE_CODE (niter) != INTEGER_CST)
463*e4b17023SJohn Marino 	return false;
464*e4b17023SJohn Marino     }
465*e4b17023SJohn Marino 
466*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
467*e4b17023SJohn Marino     {
468*e4b17023SJohn Marino       fprintf (dump_file, "Loop %d iterates ", loop->num);
469*e4b17023SJohn Marino       print_generic_expr (dump_file, niter, TDF_SLIM);
470*e4b17023SJohn Marino       fprintf (dump_file, " times.\n");
471*e4b17023SJohn Marino     }
472*e4b17023SJohn Marino 
473*e4b17023SJohn Marino   if (try_unroll_loop_completely (loop, exit, niter, ul))
474*e4b17023SJohn Marino     return true;
475*e4b17023SJohn Marino 
476*e4b17023SJohn Marino   if (create_iv)
477*e4b17023SJohn Marino     create_canonical_iv (loop, exit, niter);
478*e4b17023SJohn Marino 
479*e4b17023SJohn Marino   return false;
480*e4b17023SJohn Marino }
481*e4b17023SJohn Marino 
482*e4b17023SJohn Marino /* The main entry point of the pass.  Adds canonical induction variables
483*e4b17023SJohn Marino    to the suitable loops.  */
484*e4b17023SJohn Marino 
485*e4b17023SJohn Marino unsigned int
canonicalize_induction_variables(void)486*e4b17023SJohn Marino canonicalize_induction_variables (void)
487*e4b17023SJohn Marino {
488*e4b17023SJohn Marino   loop_iterator li;
489*e4b17023SJohn Marino   struct loop *loop;
490*e4b17023SJohn Marino   bool changed = false;
491*e4b17023SJohn Marino 
492*e4b17023SJohn Marino   FOR_EACH_LOOP (li, loop, 0)
493*e4b17023SJohn Marino     {
494*e4b17023SJohn Marino       changed |= canonicalize_loop_induction_variables (loop,
495*e4b17023SJohn Marino 							true, UL_SINGLE_ITER,
496*e4b17023SJohn Marino 							true);
497*e4b17023SJohn Marino     }
498*e4b17023SJohn Marino 
499*e4b17023SJohn Marino   /* Clean up the information about numbers of iterations, since brute force
500*e4b17023SJohn Marino      evaluation could reveal new information.  */
501*e4b17023SJohn Marino   scev_reset ();
502*e4b17023SJohn Marino 
503*e4b17023SJohn Marino   if (changed)
504*e4b17023SJohn Marino     return TODO_cleanup_cfg;
505*e4b17023SJohn Marino   return 0;
506*e4b17023SJohn Marino }
507*e4b17023SJohn Marino 
508*e4b17023SJohn Marino /* Unroll LOOPS completely if they iterate just few times.  Unless
509*e4b17023SJohn Marino    MAY_INCREASE_SIZE is true, perform the unrolling only if the
510*e4b17023SJohn Marino    size of the code does not increase.  */
511*e4b17023SJohn Marino 
512*e4b17023SJohn Marino unsigned int
tree_unroll_loops_completely(bool may_increase_size,bool unroll_outer)513*e4b17023SJohn Marino tree_unroll_loops_completely (bool may_increase_size, bool unroll_outer)
514*e4b17023SJohn Marino {
515*e4b17023SJohn Marino   loop_iterator li;
516*e4b17023SJohn Marino   struct loop *loop;
517*e4b17023SJohn Marino   bool changed;
518*e4b17023SJohn Marino   enum unroll_level ul;
519*e4b17023SJohn Marino   int iteration = 0;
520*e4b17023SJohn Marino 
521*e4b17023SJohn Marino   do
522*e4b17023SJohn Marino     {
523*e4b17023SJohn Marino       changed = false;
524*e4b17023SJohn Marino 
525*e4b17023SJohn Marino       FOR_EACH_LOOP (li, loop, LI_ONLY_INNERMOST)
526*e4b17023SJohn Marino 	{
527*e4b17023SJohn Marino 	  if (may_increase_size && optimize_loop_for_speed_p (loop)
528*e4b17023SJohn Marino 	      /* Unroll outermost loops only if asked to do so or they do
529*e4b17023SJohn Marino 		 not cause code growth.  */
530*e4b17023SJohn Marino 	      && (unroll_outer
531*e4b17023SJohn Marino 		  || loop_outer (loop_outer (loop))))
532*e4b17023SJohn Marino 	    ul = UL_ALL;
533*e4b17023SJohn Marino 	  else
534*e4b17023SJohn Marino 	    ul = UL_NO_GROWTH;
535*e4b17023SJohn Marino 	  changed |= canonicalize_loop_induction_variables
536*e4b17023SJohn Marino 		       (loop, false, ul, !flag_tree_loop_ivcanon);
537*e4b17023SJohn Marino 	}
538*e4b17023SJohn Marino 
539*e4b17023SJohn Marino       if (changed)
540*e4b17023SJohn Marino 	{
541*e4b17023SJohn Marino 	  /* This will take care of removing completely unrolled loops
542*e4b17023SJohn Marino 	     from the loop structures so we can continue unrolling now
543*e4b17023SJohn Marino 	     innermost loops.  */
544*e4b17023SJohn Marino 	  if (cleanup_tree_cfg ())
545*e4b17023SJohn Marino 	    update_ssa (TODO_update_ssa_only_virtuals);
546*e4b17023SJohn Marino 
547*e4b17023SJohn Marino 	  /* Clean up the information about numbers of iterations, since
548*e4b17023SJohn Marino 	     complete unrolling might have invalidated it.  */
549*e4b17023SJohn Marino 	  scev_reset ();
550*e4b17023SJohn Marino 	}
551*e4b17023SJohn Marino     }
552*e4b17023SJohn Marino   while (changed
553*e4b17023SJohn Marino 	 && ++iteration <= PARAM_VALUE (PARAM_MAX_UNROLL_ITERATIONS));
554*e4b17023SJohn Marino 
555*e4b17023SJohn Marino   return 0;
556*e4b17023SJohn Marino }
557