1e4b17023SJohn Marino /* Induction variable optimizations.
2e4b17023SJohn Marino    Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
3e4b17023SJohn Marino    Free Software Foundation, Inc.
4e4b17023SJohn Marino 
5e4b17023SJohn Marino This file is part of GCC.
6e4b17023SJohn Marino 
7e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it
8e4b17023SJohn Marino under the terms of the GNU General Public License as published by the
9e4b17023SJohn Marino Free Software Foundation; either version 3, or (at your option) any
10e4b17023SJohn Marino later version.
11e4b17023SJohn Marino 
12e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT
13e4b17023SJohn Marino ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14e4b17023SJohn Marino FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15e4b17023SJohn Marino for more details.
16e4b17023SJohn Marino 
17e4b17023SJohn Marino You should have received a copy of the GNU General Public License
18e4b17023SJohn Marino along with GCC; see the file COPYING3.  If not see
19e4b17023SJohn Marino <http://www.gnu.org/licenses/>.  */
20e4b17023SJohn Marino 
21e4b17023SJohn Marino /* This pass tries to find the optimal set of induction variables for the loop.
22e4b17023SJohn Marino    It optimizes just the basic linear induction variables (although adding
23e4b17023SJohn Marino    support for other types should not be too hard).  It includes the
24e4b17023SJohn Marino    optimizations commonly known as strength reduction, induction variable
25e4b17023SJohn Marino    coalescing and induction variable elimination.  It does it in the
26e4b17023SJohn Marino    following steps:
27e4b17023SJohn Marino 
28e4b17023SJohn Marino    1) The interesting uses of induction variables are found.  This includes
29e4b17023SJohn Marino 
30e4b17023SJohn Marino       -- uses of induction variables in non-linear expressions
31e4b17023SJohn Marino       -- addresses of arrays
32e4b17023SJohn Marino       -- comparisons of induction variables
33e4b17023SJohn Marino 
34e4b17023SJohn Marino    2) Candidates for the induction variables are found.  This includes
35e4b17023SJohn Marino 
36e4b17023SJohn Marino       -- old induction variables
37e4b17023SJohn Marino       -- the variables defined by expressions derived from the "interesting
38e4b17023SJohn Marino 	 uses" above
39e4b17023SJohn Marino 
40e4b17023SJohn Marino    3) The optimal (w.r. to a cost function) set of variables is chosen.  The
41e4b17023SJohn Marino       cost function assigns a cost to sets of induction variables and consists
42e4b17023SJohn Marino       of three parts:
43e4b17023SJohn Marino 
44e4b17023SJohn Marino       -- The use costs.  Each of the interesting uses chooses the best induction
45e4b17023SJohn Marino 	 variable in the set and adds its cost to the sum.  The cost reflects
46e4b17023SJohn Marino 	 the time spent on modifying the induction variables value to be usable
47e4b17023SJohn Marino 	 for the given purpose (adding base and offset for arrays, etc.).
48e4b17023SJohn Marino       -- The variable costs.  Each of the variables has a cost assigned that
49e4b17023SJohn Marino 	 reflects the costs associated with incrementing the value of the
50e4b17023SJohn Marino 	 variable.  The original variables are somewhat preferred.
51e4b17023SJohn Marino       -- The set cost.  Depending on the size of the set, extra cost may be
52e4b17023SJohn Marino 	 added to reflect register pressure.
53e4b17023SJohn Marino 
54e4b17023SJohn Marino       All the costs are defined in a machine-specific way, using the target
55e4b17023SJohn Marino       hooks and machine descriptions to determine them.
56e4b17023SJohn Marino 
57e4b17023SJohn Marino    4) The trees are transformed to use the new variables, the dead code is
58e4b17023SJohn Marino       removed.
59e4b17023SJohn Marino 
60e4b17023SJohn Marino    All of this is done loop by loop.  Doing it globally is theoretically
61e4b17023SJohn Marino    possible, it might give a better performance and it might enable us
62e4b17023SJohn Marino    to decide costs more precisely, but getting all the interactions right
63e4b17023SJohn Marino    would be complicated.  */
64e4b17023SJohn Marino 
65e4b17023SJohn Marino #include "config.h"
66e4b17023SJohn Marino #include "system.h"
67e4b17023SJohn Marino #include "coretypes.h"
68e4b17023SJohn Marino #include "tm.h"
69e4b17023SJohn Marino #include "tree.h"
70e4b17023SJohn Marino #include "tm_p.h"
71e4b17023SJohn Marino #include "basic-block.h"
72e4b17023SJohn Marino #include "output.h"
73e4b17023SJohn Marino #include "tree-pretty-print.h"
74e4b17023SJohn Marino #include "gimple-pretty-print.h"
75e4b17023SJohn Marino #include "tree-flow.h"
76e4b17023SJohn Marino #include "tree-dump.h"
77e4b17023SJohn Marino #include "timevar.h"
78e4b17023SJohn Marino #include "cfgloop.h"
79e4b17023SJohn Marino #include "tree-pass.h"
80e4b17023SJohn Marino #include "ggc.h"
81e4b17023SJohn Marino #include "insn-config.h"
82e4b17023SJohn Marino #include "recog.h"
83e4b17023SJohn Marino #include "pointer-set.h"
84e4b17023SJohn Marino #include "hashtab.h"
85e4b17023SJohn Marino #include "tree-chrec.h"
86e4b17023SJohn Marino #include "tree-scalar-evolution.h"
87e4b17023SJohn Marino #include "cfgloop.h"
88e4b17023SJohn Marino #include "params.h"
89e4b17023SJohn Marino #include "langhooks.h"
90e4b17023SJohn Marino #include "tree-affine.h"
91e4b17023SJohn Marino #include "target.h"
92e4b17023SJohn Marino #include "tree-inline.h"
93e4b17023SJohn Marino #include "tree-ssa-propagate.h"
94e4b17023SJohn Marino 
95e4b17023SJohn Marino /* FIXME: add_cost and zero_cost defined in exprmed.h conflict with local uses.
96e4b17023SJohn Marino  */
97e4b17023SJohn Marino #include "expmed.h"
98e4b17023SJohn Marino #undef add_cost
99e4b17023SJohn Marino #undef zero_cost
100e4b17023SJohn Marino 
101e4b17023SJohn Marino /* FIXME: Expressions are expanded to RTL in this pass to determine the
102e4b17023SJohn Marino    cost of different addressing modes.  This should be moved to a TBD
103e4b17023SJohn Marino    interface between the GIMPLE and RTL worlds.  */
104e4b17023SJohn Marino #include "expr.h"
105e4b17023SJohn Marino 
106e4b17023SJohn Marino /* The infinite cost.  */
107e4b17023SJohn Marino #define INFTY 10000000
108e4b17023SJohn Marino 
109e4b17023SJohn Marino #define AVG_LOOP_NITER(LOOP) 5
110e4b17023SJohn Marino 
111e4b17023SJohn Marino /* Returns the expected number of loop iterations for LOOP.
112e4b17023SJohn Marino    The average trip count is computed from profile data if it
113e4b17023SJohn Marino    exists. */
114e4b17023SJohn Marino 
115e4b17023SJohn Marino static inline HOST_WIDE_INT
avg_loop_niter(struct loop * loop)116e4b17023SJohn Marino avg_loop_niter (struct loop *loop)
117e4b17023SJohn Marino {
118e4b17023SJohn Marino   HOST_WIDE_INT niter = max_stmt_executions_int (loop, false);
119e4b17023SJohn Marino   if (niter == -1)
120e4b17023SJohn Marino     return AVG_LOOP_NITER (loop);
121e4b17023SJohn Marino 
122e4b17023SJohn Marino   return niter;
123e4b17023SJohn Marino }
124e4b17023SJohn Marino 
125e4b17023SJohn Marino /* Representation of the induction variable.  */
126e4b17023SJohn Marino struct iv
127e4b17023SJohn Marino {
128e4b17023SJohn Marino   tree base;		/* Initial value of the iv.  */
129e4b17023SJohn Marino   tree base_object;	/* A memory object to that the induction variable points.  */
130e4b17023SJohn Marino   tree step;		/* Step of the iv (constant only).  */
131e4b17023SJohn Marino   tree ssa_name;	/* The ssa name with the value.  */
132e4b17023SJohn Marino   bool biv_p;		/* Is it a biv?  */
133e4b17023SJohn Marino   bool have_use_for;	/* Do we already have a use for it?  */
134e4b17023SJohn Marino   unsigned use_id;	/* The identifier in the use if it is the case.  */
135e4b17023SJohn Marino };
136e4b17023SJohn Marino 
137e4b17023SJohn Marino /* Per-ssa version information (induction variable descriptions, etc.).  */
138e4b17023SJohn Marino struct version_info
139e4b17023SJohn Marino {
140e4b17023SJohn Marino   tree name;		/* The ssa name.  */
141e4b17023SJohn Marino   struct iv *iv;	/* Induction variable description.  */
142e4b17023SJohn Marino   bool has_nonlin_use;	/* For a loop-level invariant, whether it is used in
143e4b17023SJohn Marino 			   an expression that is not an induction variable.  */
144e4b17023SJohn Marino   bool preserve_biv;	/* For the original biv, whether to preserve it.  */
145e4b17023SJohn Marino   unsigned inv_id;	/* Id of an invariant.  */
146e4b17023SJohn Marino };
147e4b17023SJohn Marino 
148e4b17023SJohn Marino /* Types of uses.  */
149e4b17023SJohn Marino enum use_type
150e4b17023SJohn Marino {
151e4b17023SJohn Marino   USE_NONLINEAR_EXPR,	/* Use in a nonlinear expression.  */
152e4b17023SJohn Marino   USE_ADDRESS,		/* Use in an address.  */
153e4b17023SJohn Marino   USE_COMPARE		/* Use is a compare.  */
154e4b17023SJohn Marino };
155e4b17023SJohn Marino 
156e4b17023SJohn Marino /* Cost of a computation.  */
157e4b17023SJohn Marino typedef struct
158e4b17023SJohn Marino {
159e4b17023SJohn Marino   int cost;		/* The runtime cost.  */
160e4b17023SJohn Marino   unsigned complexity;	/* The estimate of the complexity of the code for
161e4b17023SJohn Marino 			   the computation (in no concrete units --
162e4b17023SJohn Marino 			   complexity field should be larger for more
163e4b17023SJohn Marino 			   complex expressions and addressing modes).  */
164e4b17023SJohn Marino } comp_cost;
165e4b17023SJohn Marino 
166e4b17023SJohn Marino static const comp_cost zero_cost = {0, 0};
167e4b17023SJohn Marino static const comp_cost infinite_cost = {INFTY, INFTY};
168e4b17023SJohn Marino 
169e4b17023SJohn Marino /* The candidate - cost pair.  */
170e4b17023SJohn Marino struct cost_pair
171e4b17023SJohn Marino {
172e4b17023SJohn Marino   struct iv_cand *cand;	/* The candidate.  */
173e4b17023SJohn Marino   comp_cost cost;	/* The cost.  */
174e4b17023SJohn Marino   bitmap depends_on;	/* The list of invariants that have to be
175e4b17023SJohn Marino 			   preserved.  */
176e4b17023SJohn Marino   tree value;		/* For final value elimination, the expression for
177e4b17023SJohn Marino 			   the final value of the iv.  For iv elimination,
178e4b17023SJohn Marino 			   the new bound to compare with.  */
179e4b17023SJohn Marino   enum tree_code comp;	/* For iv elimination, the comparison.  */
180e4b17023SJohn Marino   int inv_expr_id;      /* Loop invariant expression id.  */
181e4b17023SJohn Marino };
182e4b17023SJohn Marino 
183e4b17023SJohn Marino /* Use.  */
184e4b17023SJohn Marino struct iv_use
185e4b17023SJohn Marino {
186e4b17023SJohn Marino   unsigned id;		/* The id of the use.  */
187e4b17023SJohn Marino   enum use_type type;	/* Type of the use.  */
188e4b17023SJohn Marino   struct iv *iv;	/* The induction variable it is based on.  */
189e4b17023SJohn Marino   gimple stmt;		/* Statement in that it occurs.  */
190e4b17023SJohn Marino   tree *op_p;		/* The place where it occurs.  */
191e4b17023SJohn Marino   bitmap related_cands;	/* The set of "related" iv candidates, plus the common
192e4b17023SJohn Marino 			   important ones.  */
193e4b17023SJohn Marino 
194e4b17023SJohn Marino   unsigned n_map_members; /* Number of candidates in the cost_map list.  */
195e4b17023SJohn Marino   struct cost_pair *cost_map;
196e4b17023SJohn Marino 			/* The costs wrto the iv candidates.  */
197e4b17023SJohn Marino 
198e4b17023SJohn Marino   struct iv_cand *selected;
199e4b17023SJohn Marino 			/* The selected candidate.  */
200e4b17023SJohn Marino };
201e4b17023SJohn Marino 
202e4b17023SJohn Marino /* The position where the iv is computed.  */
203e4b17023SJohn Marino enum iv_position
204e4b17023SJohn Marino {
205e4b17023SJohn Marino   IP_NORMAL,		/* At the end, just before the exit condition.  */
206e4b17023SJohn Marino   IP_END,		/* At the end of the latch block.  */
207e4b17023SJohn Marino   IP_BEFORE_USE,	/* Immediately before a specific use.  */
208e4b17023SJohn Marino   IP_AFTER_USE,		/* Immediately after a specific use.  */
209e4b17023SJohn Marino   IP_ORIGINAL		/* The original biv.  */
210e4b17023SJohn Marino };
211e4b17023SJohn Marino 
212e4b17023SJohn Marino /* The induction variable candidate.  */
213e4b17023SJohn Marino struct iv_cand
214e4b17023SJohn Marino {
215e4b17023SJohn Marino   unsigned id;		/* The number of the candidate.  */
216e4b17023SJohn Marino   bool important;	/* Whether this is an "important" candidate, i.e. such
217e4b17023SJohn Marino 			   that it should be considered by all uses.  */
218e4b17023SJohn Marino   ENUM_BITFIELD(iv_position) pos : 8;	/* Where it is computed.  */
219e4b17023SJohn Marino   gimple incremented_at;/* For original biv, the statement where it is
220e4b17023SJohn Marino 			   incremented.  */
221e4b17023SJohn Marino   tree var_before;	/* The variable used for it before increment.  */
222e4b17023SJohn Marino   tree var_after;	/* The variable used for it after increment.  */
223e4b17023SJohn Marino   struct iv *iv;	/* The value of the candidate.  NULL for
224e4b17023SJohn Marino 			   "pseudocandidate" used to indicate the possibility
225e4b17023SJohn Marino 			   to replace the final value of an iv by direct
226e4b17023SJohn Marino 			   computation of the value.  */
227e4b17023SJohn Marino   unsigned cost;	/* Cost of the candidate.  */
228e4b17023SJohn Marino   unsigned cost_step;	/* Cost of the candidate's increment operation.  */
229e4b17023SJohn Marino   struct iv_use *ainc_use; /* For IP_{BEFORE,AFTER}_USE candidates, the place
230e4b17023SJohn Marino 			      where it is incremented.  */
231e4b17023SJohn Marino   bitmap depends_on;	/* The list of invariants that are used in step of the
232e4b17023SJohn Marino 			   biv.  */
233e4b17023SJohn Marino };
234e4b17023SJohn Marino 
235e4b17023SJohn Marino /* Loop invariant expression hashtable entry.  */
236e4b17023SJohn Marino struct iv_inv_expr_ent
237e4b17023SJohn Marino {
238e4b17023SJohn Marino   tree expr;
239e4b17023SJohn Marino   int id;
240e4b17023SJohn Marino   hashval_t hash;
241e4b17023SJohn Marino };
242e4b17023SJohn Marino 
243e4b17023SJohn Marino /* The data used by the induction variable optimizations.  */
244e4b17023SJohn Marino 
245e4b17023SJohn Marino typedef struct iv_use *iv_use_p;
246e4b17023SJohn Marino DEF_VEC_P(iv_use_p);
247e4b17023SJohn Marino DEF_VEC_ALLOC_P(iv_use_p,heap);
248e4b17023SJohn Marino 
249e4b17023SJohn Marino typedef struct iv_cand *iv_cand_p;
250e4b17023SJohn Marino DEF_VEC_P(iv_cand_p);
251e4b17023SJohn Marino DEF_VEC_ALLOC_P(iv_cand_p,heap);
252e4b17023SJohn Marino 
253e4b17023SJohn Marino struct ivopts_data
254e4b17023SJohn Marino {
255e4b17023SJohn Marino   /* The currently optimized loop.  */
256e4b17023SJohn Marino   struct loop *current_loop;
257e4b17023SJohn Marino 
258e4b17023SJohn Marino   /* Numbers of iterations for all exits of the current loop.  */
259e4b17023SJohn Marino   struct pointer_map_t *niters;
260e4b17023SJohn Marino 
261e4b17023SJohn Marino   /* Number of registers used in it.  */
262e4b17023SJohn Marino   unsigned regs_used;
263e4b17023SJohn Marino 
264e4b17023SJohn Marino   /* The size of version_info array allocated.  */
265e4b17023SJohn Marino   unsigned version_info_size;
266e4b17023SJohn Marino 
267e4b17023SJohn Marino   /* The array of information for the ssa names.  */
268e4b17023SJohn Marino   struct version_info *version_info;
269e4b17023SJohn Marino 
270e4b17023SJohn Marino   /* The hashtable of loop invariant expressions created
271e4b17023SJohn Marino      by ivopt.  */
272e4b17023SJohn Marino   htab_t inv_expr_tab;
273e4b17023SJohn Marino 
274e4b17023SJohn Marino   /* Loop invariant expression id.  */
275e4b17023SJohn Marino   int inv_expr_id;
276e4b17023SJohn Marino 
277e4b17023SJohn Marino   /* The bitmap of indices in version_info whose value was changed.  */
278e4b17023SJohn Marino   bitmap relevant;
279e4b17023SJohn Marino 
280e4b17023SJohn Marino   /* The uses of induction variables.  */
281e4b17023SJohn Marino   VEC(iv_use_p,heap) *iv_uses;
282e4b17023SJohn Marino 
283e4b17023SJohn Marino   /* The candidates.  */
284e4b17023SJohn Marino   VEC(iv_cand_p,heap) *iv_candidates;
285e4b17023SJohn Marino 
286e4b17023SJohn Marino   /* A bitmap of important candidates.  */
287e4b17023SJohn Marino   bitmap important_candidates;
288e4b17023SJohn Marino 
289e4b17023SJohn Marino   /* The maximum invariant id.  */
290e4b17023SJohn Marino   unsigned max_inv_id;
291e4b17023SJohn Marino 
292e4b17023SJohn Marino   /* Whether to consider just related and important candidates when replacing a
293e4b17023SJohn Marino      use.  */
294e4b17023SJohn Marino   bool consider_all_candidates;
295e4b17023SJohn Marino 
296e4b17023SJohn Marino   /* Are we optimizing for speed?  */
297e4b17023SJohn Marino   bool speed;
298e4b17023SJohn Marino 
299e4b17023SJohn Marino   /* Whether the loop body includes any function calls.  */
300e4b17023SJohn Marino   bool body_includes_call;
301e4b17023SJohn Marino 
302e4b17023SJohn Marino   /* Whether the loop body can only be exited via single exit.  */
303e4b17023SJohn Marino   bool loop_single_exit_p;
304e4b17023SJohn Marino };
305e4b17023SJohn Marino 
306e4b17023SJohn Marino /* An assignment of iv candidates to uses.  */
307e4b17023SJohn Marino 
308e4b17023SJohn Marino struct iv_ca
309e4b17023SJohn Marino {
310e4b17023SJohn Marino   /* The number of uses covered by the assignment.  */
311e4b17023SJohn Marino   unsigned upto;
312e4b17023SJohn Marino 
313e4b17023SJohn Marino   /* Number of uses that cannot be expressed by the candidates in the set.  */
314e4b17023SJohn Marino   unsigned bad_uses;
315e4b17023SJohn Marino 
316e4b17023SJohn Marino   /* Candidate assigned to a use, together with the related costs.  */
317e4b17023SJohn Marino   struct cost_pair **cand_for_use;
318e4b17023SJohn Marino 
319e4b17023SJohn Marino   /* Number of times each candidate is used.  */
320e4b17023SJohn Marino   unsigned *n_cand_uses;
321e4b17023SJohn Marino 
322e4b17023SJohn Marino   /* The candidates used.  */
323e4b17023SJohn Marino   bitmap cands;
324e4b17023SJohn Marino 
325e4b17023SJohn Marino   /* The number of candidates in the set.  */
326e4b17023SJohn Marino   unsigned n_cands;
327e4b17023SJohn Marino 
328e4b17023SJohn Marino   /* Total number of registers needed.  */
329e4b17023SJohn Marino   unsigned n_regs;
330e4b17023SJohn Marino 
331e4b17023SJohn Marino   /* Total cost of expressing uses.  */
332e4b17023SJohn Marino   comp_cost cand_use_cost;
333e4b17023SJohn Marino 
334e4b17023SJohn Marino   /* Total cost of candidates.  */
335e4b17023SJohn Marino   unsigned cand_cost;
336e4b17023SJohn Marino 
337e4b17023SJohn Marino   /* Number of times each invariant is used.  */
338e4b17023SJohn Marino   unsigned *n_invariant_uses;
339e4b17023SJohn Marino 
340e4b17023SJohn Marino   /* The array holding the number of uses of each loop
341e4b17023SJohn Marino      invariant expressions created by ivopt.  */
342e4b17023SJohn Marino   unsigned *used_inv_expr;
343e4b17023SJohn Marino 
344e4b17023SJohn Marino   /* The number of created loop invariants.  */
345e4b17023SJohn Marino   unsigned num_used_inv_expr;
346e4b17023SJohn Marino 
347e4b17023SJohn Marino   /* Total cost of the assignment.  */
348e4b17023SJohn Marino   comp_cost cost;
349e4b17023SJohn Marino };
350e4b17023SJohn Marino 
351e4b17023SJohn Marino /* Difference of two iv candidate assignments.  */
352e4b17023SJohn Marino 
353e4b17023SJohn Marino struct iv_ca_delta
354e4b17023SJohn Marino {
355e4b17023SJohn Marino   /* Changed use.  */
356e4b17023SJohn Marino   struct iv_use *use;
357e4b17023SJohn Marino 
358e4b17023SJohn Marino   /* An old assignment (for rollback purposes).  */
359e4b17023SJohn Marino   struct cost_pair *old_cp;
360e4b17023SJohn Marino 
361e4b17023SJohn Marino   /* A new assignment.  */
362e4b17023SJohn Marino   struct cost_pair *new_cp;
363e4b17023SJohn Marino 
364e4b17023SJohn Marino   /* Next change in the list.  */
365e4b17023SJohn Marino   struct iv_ca_delta *next_change;
366e4b17023SJohn Marino };
367e4b17023SJohn Marino 
368e4b17023SJohn Marino /* Bound on number of candidates below that all candidates are considered.  */
369e4b17023SJohn Marino 
370e4b17023SJohn Marino #define CONSIDER_ALL_CANDIDATES_BOUND \
371e4b17023SJohn Marino   ((unsigned) PARAM_VALUE (PARAM_IV_CONSIDER_ALL_CANDIDATES_BOUND))
372e4b17023SJohn Marino 
373e4b17023SJohn Marino /* If there are more iv occurrences, we just give up (it is quite unlikely that
374e4b17023SJohn Marino    optimizing such a loop would help, and it would take ages).  */
375e4b17023SJohn Marino 
376e4b17023SJohn Marino #define MAX_CONSIDERED_USES \
377e4b17023SJohn Marino   ((unsigned) PARAM_VALUE (PARAM_IV_MAX_CONSIDERED_USES))
378e4b17023SJohn Marino 
379e4b17023SJohn Marino /* If there are at most this number of ivs in the set, try removing unnecessary
380e4b17023SJohn Marino    ivs from the set always.  */
381e4b17023SJohn Marino 
382e4b17023SJohn Marino #define ALWAYS_PRUNE_CAND_SET_BOUND \
383e4b17023SJohn Marino   ((unsigned) PARAM_VALUE (PARAM_IV_ALWAYS_PRUNE_CAND_SET_BOUND))
384e4b17023SJohn Marino 
385e4b17023SJohn Marino /* The list of trees for that the decl_rtl field must be reset is stored
386e4b17023SJohn Marino    here.  */
387e4b17023SJohn Marino 
VEC(tree,heap)388e4b17023SJohn Marino static VEC(tree,heap) *decl_rtl_to_reset;
389e4b17023SJohn Marino 
390e4b17023SJohn Marino static comp_cost force_expr_to_var_cost (tree, bool);
391e4b17023SJohn Marino 
392e4b17023SJohn Marino /* Number of uses recorded in DATA.  */
393e4b17023SJohn Marino 
394e4b17023SJohn Marino static inline unsigned
395e4b17023SJohn Marino n_iv_uses (struct ivopts_data *data)
396e4b17023SJohn Marino {
397e4b17023SJohn Marino   return VEC_length (iv_use_p, data->iv_uses);
398e4b17023SJohn Marino }
399e4b17023SJohn Marino 
400e4b17023SJohn Marino /* Ith use recorded in DATA.  */
401e4b17023SJohn Marino 
402e4b17023SJohn Marino static inline struct iv_use *
iv_use(struct ivopts_data * data,unsigned i)403e4b17023SJohn Marino iv_use (struct ivopts_data *data, unsigned i)
404e4b17023SJohn Marino {
405e4b17023SJohn Marino   return VEC_index (iv_use_p, data->iv_uses, i);
406e4b17023SJohn Marino }
407e4b17023SJohn Marino 
408e4b17023SJohn Marino /* Number of candidates recorded in DATA.  */
409e4b17023SJohn Marino 
410e4b17023SJohn Marino static inline unsigned
n_iv_cands(struct ivopts_data * data)411e4b17023SJohn Marino n_iv_cands (struct ivopts_data *data)
412e4b17023SJohn Marino {
413e4b17023SJohn Marino   return VEC_length (iv_cand_p, data->iv_candidates);
414e4b17023SJohn Marino }
415e4b17023SJohn Marino 
416e4b17023SJohn Marino /* Ith candidate recorded in DATA.  */
417e4b17023SJohn Marino 
418e4b17023SJohn Marino static inline struct iv_cand *
iv_cand(struct ivopts_data * data,unsigned i)419e4b17023SJohn Marino iv_cand (struct ivopts_data *data, unsigned i)
420e4b17023SJohn Marino {
421e4b17023SJohn Marino   return VEC_index (iv_cand_p, data->iv_candidates, i);
422e4b17023SJohn Marino }
423e4b17023SJohn Marino 
424e4b17023SJohn Marino /* The single loop exit if it dominates the latch, NULL otherwise.  */
425e4b17023SJohn Marino 
426e4b17023SJohn Marino edge
single_dom_exit(struct loop * loop)427e4b17023SJohn Marino single_dom_exit (struct loop *loop)
428e4b17023SJohn Marino {
429e4b17023SJohn Marino   edge exit = single_exit (loop);
430e4b17023SJohn Marino 
431e4b17023SJohn Marino   if (!exit)
432e4b17023SJohn Marino     return NULL;
433e4b17023SJohn Marino 
434e4b17023SJohn Marino   if (!just_once_each_iteration_p (loop, exit->src))
435e4b17023SJohn Marino     return NULL;
436e4b17023SJohn Marino 
437e4b17023SJohn Marino   return exit;
438e4b17023SJohn Marino }
439e4b17023SJohn Marino 
440e4b17023SJohn Marino /* Dumps information about the induction variable IV to FILE.  */
441e4b17023SJohn Marino 
442e4b17023SJohn Marino extern void dump_iv (FILE *, struct iv *);
443e4b17023SJohn Marino void
dump_iv(FILE * file,struct iv * iv)444e4b17023SJohn Marino dump_iv (FILE *file, struct iv *iv)
445e4b17023SJohn Marino {
446e4b17023SJohn Marino   if (iv->ssa_name)
447e4b17023SJohn Marino     {
448e4b17023SJohn Marino       fprintf (file, "ssa name ");
449e4b17023SJohn Marino       print_generic_expr (file, iv->ssa_name, TDF_SLIM);
450e4b17023SJohn Marino       fprintf (file, "\n");
451e4b17023SJohn Marino     }
452e4b17023SJohn Marino 
453e4b17023SJohn Marino   fprintf (file, "  type ");
454e4b17023SJohn Marino   print_generic_expr (file, TREE_TYPE (iv->base), TDF_SLIM);
455e4b17023SJohn Marino   fprintf (file, "\n");
456e4b17023SJohn Marino 
457e4b17023SJohn Marino   if (iv->step)
458e4b17023SJohn Marino     {
459e4b17023SJohn Marino       fprintf (file, "  base ");
460e4b17023SJohn Marino       print_generic_expr (file, iv->base, TDF_SLIM);
461e4b17023SJohn Marino       fprintf (file, "\n");
462e4b17023SJohn Marino 
463e4b17023SJohn Marino       fprintf (file, "  step ");
464e4b17023SJohn Marino       print_generic_expr (file, iv->step, TDF_SLIM);
465e4b17023SJohn Marino       fprintf (file, "\n");
466e4b17023SJohn Marino     }
467e4b17023SJohn Marino   else
468e4b17023SJohn Marino     {
469e4b17023SJohn Marino       fprintf (file, "  invariant ");
470e4b17023SJohn Marino       print_generic_expr (file, iv->base, TDF_SLIM);
471e4b17023SJohn Marino       fprintf (file, "\n");
472e4b17023SJohn Marino     }
473e4b17023SJohn Marino 
474e4b17023SJohn Marino   if (iv->base_object)
475e4b17023SJohn Marino     {
476e4b17023SJohn Marino       fprintf (file, "  base object ");
477e4b17023SJohn Marino       print_generic_expr (file, iv->base_object, TDF_SLIM);
478e4b17023SJohn Marino       fprintf (file, "\n");
479e4b17023SJohn Marino     }
480e4b17023SJohn Marino 
481e4b17023SJohn Marino   if (iv->biv_p)
482e4b17023SJohn Marino     fprintf (file, "  is a biv\n");
483e4b17023SJohn Marino }
484e4b17023SJohn Marino 
485e4b17023SJohn Marino /* Dumps information about the USE to FILE.  */
486e4b17023SJohn Marino 
487e4b17023SJohn Marino extern void dump_use (FILE *, struct iv_use *);
488e4b17023SJohn Marino void
dump_use(FILE * file,struct iv_use * use)489e4b17023SJohn Marino dump_use (FILE *file, struct iv_use *use)
490e4b17023SJohn Marino {
491e4b17023SJohn Marino   fprintf (file, "use %d\n", use->id);
492e4b17023SJohn Marino 
493e4b17023SJohn Marino   switch (use->type)
494e4b17023SJohn Marino     {
495e4b17023SJohn Marino     case USE_NONLINEAR_EXPR:
496e4b17023SJohn Marino       fprintf (file, "  generic\n");
497e4b17023SJohn Marino       break;
498e4b17023SJohn Marino 
499e4b17023SJohn Marino     case USE_ADDRESS:
500e4b17023SJohn Marino       fprintf (file, "  address\n");
501e4b17023SJohn Marino       break;
502e4b17023SJohn Marino 
503e4b17023SJohn Marino     case USE_COMPARE:
504e4b17023SJohn Marino       fprintf (file, "  compare\n");
505e4b17023SJohn Marino       break;
506e4b17023SJohn Marino 
507e4b17023SJohn Marino     default:
508e4b17023SJohn Marino       gcc_unreachable ();
509e4b17023SJohn Marino     }
510e4b17023SJohn Marino 
511e4b17023SJohn Marino   fprintf (file, "  in statement ");
512e4b17023SJohn Marino   print_gimple_stmt (file, use->stmt, 0, 0);
513e4b17023SJohn Marino   fprintf (file, "\n");
514e4b17023SJohn Marino 
515e4b17023SJohn Marino   fprintf (file, "  at position ");
516e4b17023SJohn Marino   if (use->op_p)
517e4b17023SJohn Marino     print_generic_expr (file, *use->op_p, TDF_SLIM);
518e4b17023SJohn Marino   fprintf (file, "\n");
519e4b17023SJohn Marino 
520e4b17023SJohn Marino   dump_iv (file, use->iv);
521e4b17023SJohn Marino 
522e4b17023SJohn Marino   if (use->related_cands)
523e4b17023SJohn Marino     {
524e4b17023SJohn Marino       fprintf (file, "  related candidates ");
525e4b17023SJohn Marino       dump_bitmap (file, use->related_cands);
526e4b17023SJohn Marino     }
527e4b17023SJohn Marino }
528e4b17023SJohn Marino 
529e4b17023SJohn Marino /* Dumps information about the uses to FILE.  */
530e4b17023SJohn Marino 
531e4b17023SJohn Marino extern void dump_uses (FILE *, struct ivopts_data *);
532e4b17023SJohn Marino void
dump_uses(FILE * file,struct ivopts_data * data)533e4b17023SJohn Marino dump_uses (FILE *file, struct ivopts_data *data)
534e4b17023SJohn Marino {
535e4b17023SJohn Marino   unsigned i;
536e4b17023SJohn Marino   struct iv_use *use;
537e4b17023SJohn Marino 
538e4b17023SJohn Marino   for (i = 0; i < n_iv_uses (data); i++)
539e4b17023SJohn Marino     {
540e4b17023SJohn Marino       use = iv_use (data, i);
541e4b17023SJohn Marino 
542e4b17023SJohn Marino       dump_use (file, use);
543e4b17023SJohn Marino       fprintf (file, "\n");
544e4b17023SJohn Marino     }
545e4b17023SJohn Marino }
546e4b17023SJohn Marino 
547e4b17023SJohn Marino /* Dumps information about induction variable candidate CAND to FILE.  */
548e4b17023SJohn Marino 
549e4b17023SJohn Marino extern void dump_cand (FILE *, struct iv_cand *);
550e4b17023SJohn Marino void
dump_cand(FILE * file,struct iv_cand * cand)551e4b17023SJohn Marino dump_cand (FILE *file, struct iv_cand *cand)
552e4b17023SJohn Marino {
553e4b17023SJohn Marino   struct iv *iv = cand->iv;
554e4b17023SJohn Marino 
555e4b17023SJohn Marino   fprintf (file, "candidate %d%s\n",
556e4b17023SJohn Marino 	   cand->id, cand->important ? " (important)" : "");
557e4b17023SJohn Marino 
558e4b17023SJohn Marino   if (cand->depends_on)
559e4b17023SJohn Marino     {
560e4b17023SJohn Marino       fprintf (file, "  depends on ");
561e4b17023SJohn Marino       dump_bitmap (file, cand->depends_on);
562e4b17023SJohn Marino     }
563e4b17023SJohn Marino 
564e4b17023SJohn Marino   if (!iv)
565e4b17023SJohn Marino     {
566e4b17023SJohn Marino       fprintf (file, "  final value replacement\n");
567e4b17023SJohn Marino       return;
568e4b17023SJohn Marino     }
569e4b17023SJohn Marino 
570e4b17023SJohn Marino   if (cand->var_before)
571e4b17023SJohn Marino     {
572e4b17023SJohn Marino       fprintf (file, "  var_before ");
573e4b17023SJohn Marino       print_generic_expr (file, cand->var_before, TDF_SLIM);
574e4b17023SJohn Marino       fprintf (file, "\n");
575e4b17023SJohn Marino     }
576e4b17023SJohn Marino   if (cand->var_after)
577e4b17023SJohn Marino     {
578e4b17023SJohn Marino       fprintf (file, "  var_after ");
579e4b17023SJohn Marino       print_generic_expr (file, cand->var_after, TDF_SLIM);
580e4b17023SJohn Marino       fprintf (file, "\n");
581e4b17023SJohn Marino     }
582e4b17023SJohn Marino 
583e4b17023SJohn Marino   switch (cand->pos)
584e4b17023SJohn Marino     {
585e4b17023SJohn Marino     case IP_NORMAL:
586e4b17023SJohn Marino       fprintf (file, "  incremented before exit test\n");
587e4b17023SJohn Marino       break;
588e4b17023SJohn Marino 
589e4b17023SJohn Marino     case IP_BEFORE_USE:
590e4b17023SJohn Marino       fprintf (file, "  incremented before use %d\n", cand->ainc_use->id);
591e4b17023SJohn Marino       break;
592e4b17023SJohn Marino 
593e4b17023SJohn Marino     case IP_AFTER_USE:
594e4b17023SJohn Marino       fprintf (file, "  incremented after use %d\n", cand->ainc_use->id);
595e4b17023SJohn Marino       break;
596e4b17023SJohn Marino 
597e4b17023SJohn Marino     case IP_END:
598e4b17023SJohn Marino       fprintf (file, "  incremented at end\n");
599e4b17023SJohn Marino       break;
600e4b17023SJohn Marino 
601e4b17023SJohn Marino     case IP_ORIGINAL:
602e4b17023SJohn Marino       fprintf (file, "  original biv\n");
603e4b17023SJohn Marino       break;
604e4b17023SJohn Marino     }
605e4b17023SJohn Marino 
606e4b17023SJohn Marino   dump_iv (file, iv);
607e4b17023SJohn Marino }
608e4b17023SJohn Marino 
609e4b17023SJohn Marino /* Returns the info for ssa version VER.  */
610e4b17023SJohn Marino 
611e4b17023SJohn Marino static inline struct version_info *
ver_info(struct ivopts_data * data,unsigned ver)612e4b17023SJohn Marino ver_info (struct ivopts_data *data, unsigned ver)
613e4b17023SJohn Marino {
614e4b17023SJohn Marino   return data->version_info + ver;
615e4b17023SJohn Marino }
616e4b17023SJohn Marino 
617e4b17023SJohn Marino /* Returns the info for ssa name NAME.  */
618e4b17023SJohn Marino 
619e4b17023SJohn Marino static inline struct version_info *
name_info(struct ivopts_data * data,tree name)620e4b17023SJohn Marino name_info (struct ivopts_data *data, tree name)
621e4b17023SJohn Marino {
622e4b17023SJohn Marino   return ver_info (data, SSA_NAME_VERSION (name));
623e4b17023SJohn Marino }
624e4b17023SJohn Marino 
625e4b17023SJohn Marino /* Returns true if STMT is after the place where the IP_NORMAL ivs will be
626e4b17023SJohn Marino    emitted in LOOP.  */
627e4b17023SJohn Marino 
628e4b17023SJohn Marino static bool
stmt_after_ip_normal_pos(struct loop * loop,gimple stmt)629e4b17023SJohn Marino stmt_after_ip_normal_pos (struct loop *loop, gimple stmt)
630e4b17023SJohn Marino {
631e4b17023SJohn Marino   basic_block bb = ip_normal_pos (loop), sbb = gimple_bb (stmt);
632e4b17023SJohn Marino 
633e4b17023SJohn Marino   gcc_assert (bb);
634e4b17023SJohn Marino 
635e4b17023SJohn Marino   if (sbb == loop->latch)
636e4b17023SJohn Marino     return true;
637e4b17023SJohn Marino 
638e4b17023SJohn Marino   if (sbb != bb)
639e4b17023SJohn Marino     return false;
640e4b17023SJohn Marino 
641e4b17023SJohn Marino   return stmt == last_stmt (bb);
642e4b17023SJohn Marino }
643e4b17023SJohn Marino 
644e4b17023SJohn Marino /* Returns true if STMT if after the place where the original induction
645e4b17023SJohn Marino    variable CAND is incremented.  If TRUE_IF_EQUAL is set, we return true
646e4b17023SJohn Marino    if the positions are identical.  */
647e4b17023SJohn Marino 
648e4b17023SJohn Marino static bool
stmt_after_inc_pos(struct iv_cand * cand,gimple stmt,bool true_if_equal)649e4b17023SJohn Marino stmt_after_inc_pos (struct iv_cand *cand, gimple stmt, bool true_if_equal)
650e4b17023SJohn Marino {
651e4b17023SJohn Marino   basic_block cand_bb = gimple_bb (cand->incremented_at);
652e4b17023SJohn Marino   basic_block stmt_bb = gimple_bb (stmt);
653e4b17023SJohn Marino 
654e4b17023SJohn Marino   if (!dominated_by_p (CDI_DOMINATORS, stmt_bb, cand_bb))
655e4b17023SJohn Marino     return false;
656e4b17023SJohn Marino 
657e4b17023SJohn Marino   if (stmt_bb != cand_bb)
658e4b17023SJohn Marino     return true;
659e4b17023SJohn Marino 
660e4b17023SJohn Marino   if (true_if_equal
661e4b17023SJohn Marino       && gimple_uid (stmt) == gimple_uid (cand->incremented_at))
662e4b17023SJohn Marino     return true;
663e4b17023SJohn Marino   return gimple_uid (stmt) > gimple_uid (cand->incremented_at);
664e4b17023SJohn Marino }
665e4b17023SJohn Marino 
666e4b17023SJohn Marino /* Returns true if STMT if after the place where the induction variable
667e4b17023SJohn Marino    CAND is incremented in LOOP.  */
668e4b17023SJohn Marino 
669e4b17023SJohn Marino static bool
stmt_after_increment(struct loop * loop,struct iv_cand * cand,gimple stmt)670e4b17023SJohn Marino stmt_after_increment (struct loop *loop, struct iv_cand *cand, gimple stmt)
671e4b17023SJohn Marino {
672e4b17023SJohn Marino   switch (cand->pos)
673e4b17023SJohn Marino     {
674e4b17023SJohn Marino     case IP_END:
675e4b17023SJohn Marino       return false;
676e4b17023SJohn Marino 
677e4b17023SJohn Marino     case IP_NORMAL:
678e4b17023SJohn Marino       return stmt_after_ip_normal_pos (loop, stmt);
679e4b17023SJohn Marino 
680e4b17023SJohn Marino     case IP_ORIGINAL:
681e4b17023SJohn Marino     case IP_AFTER_USE:
682e4b17023SJohn Marino       return stmt_after_inc_pos (cand, stmt, false);
683e4b17023SJohn Marino 
684e4b17023SJohn Marino     case IP_BEFORE_USE:
685e4b17023SJohn Marino       return stmt_after_inc_pos (cand, stmt, true);
686e4b17023SJohn Marino 
687e4b17023SJohn Marino     default:
688e4b17023SJohn Marino       gcc_unreachable ();
689e4b17023SJohn Marino     }
690e4b17023SJohn Marino }
691e4b17023SJohn Marino 
692e4b17023SJohn Marino /* Returns true if EXP is a ssa name that occurs in an abnormal phi node.  */
693e4b17023SJohn Marino 
694e4b17023SJohn Marino static bool
abnormal_ssa_name_p(tree exp)695e4b17023SJohn Marino abnormal_ssa_name_p (tree exp)
696e4b17023SJohn Marino {
697e4b17023SJohn Marino   if (!exp)
698e4b17023SJohn Marino     return false;
699e4b17023SJohn Marino 
700e4b17023SJohn Marino   if (TREE_CODE (exp) != SSA_NAME)
701e4b17023SJohn Marino     return false;
702e4b17023SJohn Marino 
703e4b17023SJohn Marino   return SSA_NAME_OCCURS_IN_ABNORMAL_PHI (exp) != 0;
704e4b17023SJohn Marino }
705e4b17023SJohn Marino 
706e4b17023SJohn Marino /* Returns false if BASE or INDEX contains a ssa name that occurs in an
707e4b17023SJohn Marino    abnormal phi node.  Callback for for_each_index.  */
708e4b17023SJohn Marino 
709e4b17023SJohn Marino static bool
idx_contains_abnormal_ssa_name_p(tree base,tree * index,void * data ATTRIBUTE_UNUSED)710e4b17023SJohn Marino idx_contains_abnormal_ssa_name_p (tree base, tree *index,
711e4b17023SJohn Marino 				  void *data ATTRIBUTE_UNUSED)
712e4b17023SJohn Marino {
713e4b17023SJohn Marino   if (TREE_CODE (base) == ARRAY_REF || TREE_CODE (base) == ARRAY_RANGE_REF)
714e4b17023SJohn Marino     {
715e4b17023SJohn Marino       if (abnormal_ssa_name_p (TREE_OPERAND (base, 2)))
716e4b17023SJohn Marino 	return false;
717e4b17023SJohn Marino       if (abnormal_ssa_name_p (TREE_OPERAND (base, 3)))
718e4b17023SJohn Marino 	return false;
719e4b17023SJohn Marino     }
720e4b17023SJohn Marino 
721e4b17023SJohn Marino   return !abnormal_ssa_name_p (*index);
722e4b17023SJohn Marino }
723e4b17023SJohn Marino 
724e4b17023SJohn Marino /* Returns true if EXPR contains a ssa name that occurs in an
725e4b17023SJohn Marino    abnormal phi node.  */
726e4b17023SJohn Marino 
727e4b17023SJohn Marino bool
contains_abnormal_ssa_name_p(tree expr)728e4b17023SJohn Marino contains_abnormal_ssa_name_p (tree expr)
729e4b17023SJohn Marino {
730e4b17023SJohn Marino   enum tree_code code;
731e4b17023SJohn Marino   enum tree_code_class codeclass;
732e4b17023SJohn Marino 
733e4b17023SJohn Marino   if (!expr)
734e4b17023SJohn Marino     return false;
735e4b17023SJohn Marino 
736e4b17023SJohn Marino   code = TREE_CODE (expr);
737e4b17023SJohn Marino   codeclass = TREE_CODE_CLASS (code);
738e4b17023SJohn Marino 
739e4b17023SJohn Marino   if (code == SSA_NAME)
740e4b17023SJohn Marino     return SSA_NAME_OCCURS_IN_ABNORMAL_PHI (expr) != 0;
741e4b17023SJohn Marino 
742e4b17023SJohn Marino   if (code == INTEGER_CST
743e4b17023SJohn Marino       || is_gimple_min_invariant (expr))
744e4b17023SJohn Marino     return false;
745e4b17023SJohn Marino 
746e4b17023SJohn Marino   if (code == ADDR_EXPR)
747e4b17023SJohn Marino     return !for_each_index (&TREE_OPERAND (expr, 0),
748e4b17023SJohn Marino 			    idx_contains_abnormal_ssa_name_p,
749e4b17023SJohn Marino 			    NULL);
750e4b17023SJohn Marino 
751e4b17023SJohn Marino   if (code == COND_EXPR)
752e4b17023SJohn Marino     return contains_abnormal_ssa_name_p (TREE_OPERAND (expr, 0))
753e4b17023SJohn Marino       || contains_abnormal_ssa_name_p (TREE_OPERAND (expr, 1))
754e4b17023SJohn Marino       || contains_abnormal_ssa_name_p (TREE_OPERAND (expr, 2));
755e4b17023SJohn Marino 
756e4b17023SJohn Marino   switch (codeclass)
757e4b17023SJohn Marino     {
758e4b17023SJohn Marino     case tcc_binary:
759e4b17023SJohn Marino     case tcc_comparison:
760e4b17023SJohn Marino       if (contains_abnormal_ssa_name_p (TREE_OPERAND (expr, 1)))
761e4b17023SJohn Marino 	return true;
762e4b17023SJohn Marino 
763e4b17023SJohn Marino       /* Fallthru.  */
764e4b17023SJohn Marino     case tcc_unary:
765e4b17023SJohn Marino       if (contains_abnormal_ssa_name_p (TREE_OPERAND (expr, 0)))
766e4b17023SJohn Marino 	return true;
767e4b17023SJohn Marino 
768e4b17023SJohn Marino       break;
769e4b17023SJohn Marino 
770e4b17023SJohn Marino     default:
771e4b17023SJohn Marino       gcc_unreachable ();
772e4b17023SJohn Marino     }
773e4b17023SJohn Marino 
774e4b17023SJohn Marino   return false;
775e4b17023SJohn Marino }
776e4b17023SJohn Marino 
777e4b17023SJohn Marino /*  Returns the structure describing number of iterations determined from
778e4b17023SJohn Marino     EXIT of DATA->current_loop, or NULL if something goes wrong.  */
779e4b17023SJohn Marino 
780e4b17023SJohn Marino static struct tree_niter_desc *
niter_for_exit(struct ivopts_data * data,edge exit)781e4b17023SJohn Marino niter_for_exit (struct ivopts_data *data, edge exit)
782e4b17023SJohn Marino {
783e4b17023SJohn Marino   struct tree_niter_desc *desc;
784e4b17023SJohn Marino   void **slot;
785e4b17023SJohn Marino 
786e4b17023SJohn Marino   if (!data->niters)
787e4b17023SJohn Marino     {
788e4b17023SJohn Marino       data->niters = pointer_map_create ();
789e4b17023SJohn Marino       slot = NULL;
790e4b17023SJohn Marino     }
791e4b17023SJohn Marino   else
792e4b17023SJohn Marino     slot = pointer_map_contains (data->niters, exit);
793e4b17023SJohn Marino 
794e4b17023SJohn Marino   if (!slot)
795e4b17023SJohn Marino     {
796e4b17023SJohn Marino       /* Try to determine number of iterations.  We cannot safely work with ssa
797e4b17023SJohn Marino          names that appear in phi nodes on abnormal edges, so that we do not
798e4b17023SJohn Marino          create overlapping life ranges for them (PR 27283).  */
799e4b17023SJohn Marino       desc = XNEW (struct tree_niter_desc);
800e4b17023SJohn Marino       if (!number_of_iterations_exit (data->current_loop,
801e4b17023SJohn Marino 				      exit, desc, true)
802e4b17023SJohn Marino      	  || contains_abnormal_ssa_name_p (desc->niter))
803e4b17023SJohn Marino 	{
804e4b17023SJohn Marino 	  XDELETE (desc);
805e4b17023SJohn Marino 	  desc = NULL;
806e4b17023SJohn Marino 	}
807e4b17023SJohn Marino       slot = pointer_map_insert (data->niters, exit);
808e4b17023SJohn Marino       *slot = desc;
809e4b17023SJohn Marino     }
810e4b17023SJohn Marino   else
811e4b17023SJohn Marino     desc = (struct tree_niter_desc *) *slot;
812e4b17023SJohn Marino 
813e4b17023SJohn Marino   return desc;
814e4b17023SJohn Marino }
815e4b17023SJohn Marino 
816e4b17023SJohn Marino /* Returns the structure describing number of iterations determined from
817e4b17023SJohn Marino    single dominating exit of DATA->current_loop, or NULL if something
818e4b17023SJohn Marino    goes wrong.  */
819e4b17023SJohn Marino 
820e4b17023SJohn Marino static struct tree_niter_desc *
niter_for_single_dom_exit(struct ivopts_data * data)821e4b17023SJohn Marino niter_for_single_dom_exit (struct ivopts_data *data)
822e4b17023SJohn Marino {
823e4b17023SJohn Marino   edge exit = single_dom_exit (data->current_loop);
824e4b17023SJohn Marino 
825e4b17023SJohn Marino   if (!exit)
826e4b17023SJohn Marino     return NULL;
827e4b17023SJohn Marino 
828e4b17023SJohn Marino   return niter_for_exit (data, exit);
829e4b17023SJohn Marino }
830e4b17023SJohn Marino 
831e4b17023SJohn Marino /* Hash table equality function for expressions.  */
832e4b17023SJohn Marino 
833e4b17023SJohn Marino static int
htab_inv_expr_eq(const void * ent1,const void * ent2)834e4b17023SJohn Marino htab_inv_expr_eq (const void *ent1, const void *ent2)
835e4b17023SJohn Marino {
836e4b17023SJohn Marino   const struct iv_inv_expr_ent *expr1 =
837e4b17023SJohn Marino       (const struct iv_inv_expr_ent *)ent1;
838e4b17023SJohn Marino   const struct iv_inv_expr_ent *expr2 =
839e4b17023SJohn Marino       (const struct iv_inv_expr_ent *)ent2;
840e4b17023SJohn Marino 
841e4b17023SJohn Marino   return expr1->hash == expr2->hash
842e4b17023SJohn Marino 	 && operand_equal_p (expr1->expr, expr2->expr, 0);
843e4b17023SJohn Marino }
844e4b17023SJohn Marino 
845e4b17023SJohn Marino /* Hash function for loop invariant expressions.  */
846e4b17023SJohn Marino 
847e4b17023SJohn Marino static hashval_t
htab_inv_expr_hash(const void * ent)848e4b17023SJohn Marino htab_inv_expr_hash (const void *ent)
849e4b17023SJohn Marino {
850e4b17023SJohn Marino   const struct iv_inv_expr_ent *expr =
851e4b17023SJohn Marino       (const struct iv_inv_expr_ent *)ent;
852e4b17023SJohn Marino   return expr->hash;
853e4b17023SJohn Marino }
854e4b17023SJohn Marino 
855e4b17023SJohn Marino /* Initializes data structures used by the iv optimization pass, stored
856e4b17023SJohn Marino    in DATA.  */
857e4b17023SJohn Marino 
858e4b17023SJohn Marino static void
tree_ssa_iv_optimize_init(struct ivopts_data * data)859e4b17023SJohn Marino tree_ssa_iv_optimize_init (struct ivopts_data *data)
860e4b17023SJohn Marino {
861e4b17023SJohn Marino   data->version_info_size = 2 * num_ssa_names;
862e4b17023SJohn Marino   data->version_info = XCNEWVEC (struct version_info, data->version_info_size);
863e4b17023SJohn Marino   data->relevant = BITMAP_ALLOC (NULL);
864e4b17023SJohn Marino   data->important_candidates = BITMAP_ALLOC (NULL);
865e4b17023SJohn Marino   data->max_inv_id = 0;
866e4b17023SJohn Marino   data->niters = NULL;
867e4b17023SJohn Marino   data->iv_uses = VEC_alloc (iv_use_p, heap, 20);
868e4b17023SJohn Marino   data->iv_candidates = VEC_alloc (iv_cand_p, heap, 20);
869e4b17023SJohn Marino   data->inv_expr_tab = htab_create (10, htab_inv_expr_hash,
870e4b17023SJohn Marino                                     htab_inv_expr_eq, free);
871e4b17023SJohn Marino   data->inv_expr_id = 0;
872e4b17023SJohn Marino   decl_rtl_to_reset = VEC_alloc (tree, heap, 20);
873e4b17023SJohn Marino }
874e4b17023SJohn Marino 
875e4b17023SJohn Marino /* Returns a memory object to that EXPR points.  In case we are able to
876e4b17023SJohn Marino    determine that it does not point to any such object, NULL is returned.  */
877e4b17023SJohn Marino 
878e4b17023SJohn Marino static tree
determine_base_object(tree expr)879e4b17023SJohn Marino determine_base_object (tree expr)
880e4b17023SJohn Marino {
881e4b17023SJohn Marino   enum tree_code code = TREE_CODE (expr);
882e4b17023SJohn Marino   tree base, obj;
883e4b17023SJohn Marino 
884e4b17023SJohn Marino   /* If this is a pointer casted to any type, we need to determine
885e4b17023SJohn Marino      the base object for the pointer; so handle conversions before
886e4b17023SJohn Marino      throwing away non-pointer expressions.  */
887e4b17023SJohn Marino   if (CONVERT_EXPR_P (expr))
888e4b17023SJohn Marino     return determine_base_object (TREE_OPERAND (expr, 0));
889e4b17023SJohn Marino 
890e4b17023SJohn Marino   if (!POINTER_TYPE_P (TREE_TYPE (expr)))
891e4b17023SJohn Marino     return NULL_TREE;
892e4b17023SJohn Marino 
893e4b17023SJohn Marino   switch (code)
894e4b17023SJohn Marino     {
895e4b17023SJohn Marino     case INTEGER_CST:
896e4b17023SJohn Marino       return NULL_TREE;
897e4b17023SJohn Marino 
898e4b17023SJohn Marino     case ADDR_EXPR:
899e4b17023SJohn Marino       obj = TREE_OPERAND (expr, 0);
900e4b17023SJohn Marino       base = get_base_address (obj);
901e4b17023SJohn Marino 
902e4b17023SJohn Marino       if (!base)
903e4b17023SJohn Marino 	return expr;
904e4b17023SJohn Marino 
905e4b17023SJohn Marino       if (TREE_CODE (base) == MEM_REF)
906e4b17023SJohn Marino 	return determine_base_object (TREE_OPERAND (base, 0));
907e4b17023SJohn Marino 
908e4b17023SJohn Marino       return fold_convert (ptr_type_node,
909e4b17023SJohn Marino 		           build_fold_addr_expr (base));
910e4b17023SJohn Marino 
911e4b17023SJohn Marino     case POINTER_PLUS_EXPR:
912e4b17023SJohn Marino       return determine_base_object (TREE_OPERAND (expr, 0));
913e4b17023SJohn Marino 
914e4b17023SJohn Marino     case PLUS_EXPR:
915e4b17023SJohn Marino     case MINUS_EXPR:
916e4b17023SJohn Marino       /* Pointer addition is done solely using POINTER_PLUS_EXPR.  */
917e4b17023SJohn Marino       gcc_unreachable ();
918e4b17023SJohn Marino 
919e4b17023SJohn Marino     default:
920e4b17023SJohn Marino       return fold_convert (ptr_type_node, expr);
921e4b17023SJohn Marino     }
922e4b17023SJohn Marino }
923e4b17023SJohn Marino 
924e4b17023SJohn Marino /* Allocates an induction variable with given initial value BASE and step STEP
925e4b17023SJohn Marino    for loop LOOP.  */
926e4b17023SJohn Marino 
927e4b17023SJohn Marino static struct iv *
alloc_iv(tree base,tree step)928e4b17023SJohn Marino alloc_iv (tree base, tree step)
929e4b17023SJohn Marino {
930e4b17023SJohn Marino   struct iv *iv = XCNEW (struct iv);
931e4b17023SJohn Marino   gcc_assert (step != NULL_TREE);
932e4b17023SJohn Marino 
933e4b17023SJohn Marino   iv->base = base;
934e4b17023SJohn Marino   iv->base_object = determine_base_object (base);
935e4b17023SJohn Marino   iv->step = step;
936e4b17023SJohn Marino   iv->biv_p = false;
937e4b17023SJohn Marino   iv->have_use_for = false;
938e4b17023SJohn Marino   iv->use_id = 0;
939e4b17023SJohn Marino   iv->ssa_name = NULL_TREE;
940e4b17023SJohn Marino 
941e4b17023SJohn Marino   return iv;
942e4b17023SJohn Marino }
943e4b17023SJohn Marino 
944e4b17023SJohn Marino /* Sets STEP and BASE for induction variable IV.  */
945e4b17023SJohn Marino 
946e4b17023SJohn Marino static void
set_iv(struct ivopts_data * data,tree iv,tree base,tree step)947e4b17023SJohn Marino set_iv (struct ivopts_data *data, tree iv, tree base, tree step)
948e4b17023SJohn Marino {
949e4b17023SJohn Marino   struct version_info *info = name_info (data, iv);
950e4b17023SJohn Marino 
951e4b17023SJohn Marino   gcc_assert (!info->iv);
952e4b17023SJohn Marino 
953e4b17023SJohn Marino   bitmap_set_bit (data->relevant, SSA_NAME_VERSION (iv));
954e4b17023SJohn Marino   info->iv = alloc_iv (base, step);
955e4b17023SJohn Marino   info->iv->ssa_name = iv;
956e4b17023SJohn Marino }
957e4b17023SJohn Marino 
958e4b17023SJohn Marino /* Finds induction variable declaration for VAR.  */
959e4b17023SJohn Marino 
960e4b17023SJohn Marino static struct iv *
get_iv(struct ivopts_data * data,tree var)961e4b17023SJohn Marino get_iv (struct ivopts_data *data, tree var)
962e4b17023SJohn Marino {
963e4b17023SJohn Marino   basic_block bb;
964e4b17023SJohn Marino   tree type = TREE_TYPE (var);
965e4b17023SJohn Marino 
966e4b17023SJohn Marino   if (!POINTER_TYPE_P (type)
967e4b17023SJohn Marino       && !INTEGRAL_TYPE_P (type))
968e4b17023SJohn Marino     return NULL;
969e4b17023SJohn Marino 
970e4b17023SJohn Marino   if (!name_info (data, var)->iv)
971e4b17023SJohn Marino     {
972e4b17023SJohn Marino       bb = gimple_bb (SSA_NAME_DEF_STMT (var));
973e4b17023SJohn Marino 
974e4b17023SJohn Marino       if (!bb
975e4b17023SJohn Marino 	  || !flow_bb_inside_loop_p (data->current_loop, bb))
976e4b17023SJohn Marino 	set_iv (data, var, var, build_int_cst (type, 0));
977e4b17023SJohn Marino     }
978e4b17023SJohn Marino 
979e4b17023SJohn Marino   return name_info (data, var)->iv;
980e4b17023SJohn Marino }
981e4b17023SJohn Marino 
982e4b17023SJohn Marino /* Determines the step of a biv defined in PHI.  Returns NULL if PHI does
983e4b17023SJohn Marino    not define a simple affine biv with nonzero step.  */
984e4b17023SJohn Marino 
985e4b17023SJohn Marino static tree
determine_biv_step(gimple phi)986e4b17023SJohn Marino determine_biv_step (gimple phi)
987e4b17023SJohn Marino {
988e4b17023SJohn Marino   struct loop *loop = gimple_bb (phi)->loop_father;
989e4b17023SJohn Marino   tree name = PHI_RESULT (phi);
990e4b17023SJohn Marino   affine_iv iv;
991e4b17023SJohn Marino 
992e4b17023SJohn Marino   if (!is_gimple_reg (name))
993e4b17023SJohn Marino     return NULL_TREE;
994e4b17023SJohn Marino 
995e4b17023SJohn Marino   if (!simple_iv (loop, loop, name, &iv, true))
996e4b17023SJohn Marino     return NULL_TREE;
997e4b17023SJohn Marino 
998e4b17023SJohn Marino   return integer_zerop (iv.step) ? NULL_TREE : iv.step;
999e4b17023SJohn Marino }
1000e4b17023SJohn Marino 
1001e4b17023SJohn Marino /* Finds basic ivs.  */
1002e4b17023SJohn Marino 
1003e4b17023SJohn Marino static bool
find_bivs(struct ivopts_data * data)1004e4b17023SJohn Marino find_bivs (struct ivopts_data *data)
1005e4b17023SJohn Marino {
1006e4b17023SJohn Marino   gimple phi;
1007e4b17023SJohn Marino   tree step, type, base;
1008e4b17023SJohn Marino   bool found = false;
1009e4b17023SJohn Marino   struct loop *loop = data->current_loop;
1010e4b17023SJohn Marino   gimple_stmt_iterator psi;
1011e4b17023SJohn Marino 
1012e4b17023SJohn Marino   for (psi = gsi_start_phis (loop->header); !gsi_end_p (psi); gsi_next (&psi))
1013e4b17023SJohn Marino     {
1014e4b17023SJohn Marino       phi = gsi_stmt (psi);
1015e4b17023SJohn Marino 
1016e4b17023SJohn Marino       if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (PHI_RESULT (phi)))
1017e4b17023SJohn Marino 	continue;
1018e4b17023SJohn Marino 
1019e4b17023SJohn Marino       step = determine_biv_step (phi);
1020e4b17023SJohn Marino       if (!step)
1021e4b17023SJohn Marino 	continue;
1022e4b17023SJohn Marino 
1023e4b17023SJohn Marino       base = PHI_ARG_DEF_FROM_EDGE (phi, loop_preheader_edge (loop));
1024e4b17023SJohn Marino       base = expand_simple_operations (base);
1025e4b17023SJohn Marino       if (contains_abnormal_ssa_name_p (base)
1026e4b17023SJohn Marino 	  || contains_abnormal_ssa_name_p (step))
1027e4b17023SJohn Marino 	continue;
1028e4b17023SJohn Marino 
1029e4b17023SJohn Marino       type = TREE_TYPE (PHI_RESULT (phi));
1030e4b17023SJohn Marino       base = fold_convert (type, base);
1031e4b17023SJohn Marino       if (step)
1032e4b17023SJohn Marino 	{
1033e4b17023SJohn Marino 	  if (POINTER_TYPE_P (type))
1034e4b17023SJohn Marino 	    step = convert_to_ptrofftype (step);
1035e4b17023SJohn Marino 	  else
1036e4b17023SJohn Marino 	    step = fold_convert (type, step);
1037e4b17023SJohn Marino 	}
1038e4b17023SJohn Marino 
1039e4b17023SJohn Marino       set_iv (data, PHI_RESULT (phi), base, step);
1040e4b17023SJohn Marino       found = true;
1041e4b17023SJohn Marino     }
1042e4b17023SJohn Marino 
1043e4b17023SJohn Marino   return found;
1044e4b17023SJohn Marino }
1045e4b17023SJohn Marino 
1046e4b17023SJohn Marino /* Marks basic ivs.  */
1047e4b17023SJohn Marino 
1048e4b17023SJohn Marino static void
mark_bivs(struct ivopts_data * data)1049e4b17023SJohn Marino mark_bivs (struct ivopts_data *data)
1050e4b17023SJohn Marino {
1051e4b17023SJohn Marino   gimple phi;
1052e4b17023SJohn Marino   tree var;
1053e4b17023SJohn Marino   struct iv *iv, *incr_iv;
1054e4b17023SJohn Marino   struct loop *loop = data->current_loop;
1055e4b17023SJohn Marino   basic_block incr_bb;
1056e4b17023SJohn Marino   gimple_stmt_iterator psi;
1057e4b17023SJohn Marino 
1058e4b17023SJohn Marino   for (psi = gsi_start_phis (loop->header); !gsi_end_p (psi); gsi_next (&psi))
1059e4b17023SJohn Marino     {
1060e4b17023SJohn Marino       phi = gsi_stmt (psi);
1061e4b17023SJohn Marino 
1062e4b17023SJohn Marino       iv = get_iv (data, PHI_RESULT (phi));
1063e4b17023SJohn Marino       if (!iv)
1064e4b17023SJohn Marino 	continue;
1065e4b17023SJohn Marino 
1066e4b17023SJohn Marino       var = PHI_ARG_DEF_FROM_EDGE (phi, loop_latch_edge (loop));
1067e4b17023SJohn Marino       incr_iv = get_iv (data, var);
1068e4b17023SJohn Marino       if (!incr_iv)
1069e4b17023SJohn Marino 	continue;
1070e4b17023SJohn Marino 
1071e4b17023SJohn Marino       /* If the increment is in the subloop, ignore it.  */
1072e4b17023SJohn Marino       incr_bb = gimple_bb (SSA_NAME_DEF_STMT (var));
1073e4b17023SJohn Marino       if (incr_bb->loop_father != data->current_loop
1074e4b17023SJohn Marino 	  || (incr_bb->flags & BB_IRREDUCIBLE_LOOP))
1075e4b17023SJohn Marino 	continue;
1076e4b17023SJohn Marino 
1077e4b17023SJohn Marino       iv->biv_p = true;
1078e4b17023SJohn Marino       incr_iv->biv_p = true;
1079e4b17023SJohn Marino     }
1080e4b17023SJohn Marino }
1081e4b17023SJohn Marino 
1082e4b17023SJohn Marino /* Checks whether STMT defines a linear induction variable and stores its
1083e4b17023SJohn Marino    parameters to IV.  */
1084e4b17023SJohn Marino 
1085e4b17023SJohn Marino static bool
find_givs_in_stmt_scev(struct ivopts_data * data,gimple stmt,affine_iv * iv)1086e4b17023SJohn Marino find_givs_in_stmt_scev (struct ivopts_data *data, gimple stmt, affine_iv *iv)
1087e4b17023SJohn Marino {
1088e4b17023SJohn Marino   tree lhs;
1089e4b17023SJohn Marino   struct loop *loop = data->current_loop;
1090e4b17023SJohn Marino 
1091e4b17023SJohn Marino   iv->base = NULL_TREE;
1092e4b17023SJohn Marino   iv->step = NULL_TREE;
1093e4b17023SJohn Marino 
1094e4b17023SJohn Marino   if (gimple_code (stmt) != GIMPLE_ASSIGN)
1095e4b17023SJohn Marino     return false;
1096e4b17023SJohn Marino 
1097e4b17023SJohn Marino   lhs = gimple_assign_lhs (stmt);
1098e4b17023SJohn Marino   if (TREE_CODE (lhs) != SSA_NAME)
1099e4b17023SJohn Marino     return false;
1100e4b17023SJohn Marino 
1101e4b17023SJohn Marino   if (!simple_iv (loop, loop_containing_stmt (stmt), lhs, iv, true))
1102e4b17023SJohn Marino     return false;
1103e4b17023SJohn Marino   iv->base = expand_simple_operations (iv->base);
1104e4b17023SJohn Marino 
1105e4b17023SJohn Marino   if (contains_abnormal_ssa_name_p (iv->base)
1106e4b17023SJohn Marino       || contains_abnormal_ssa_name_p (iv->step))
1107e4b17023SJohn Marino     return false;
1108e4b17023SJohn Marino 
1109e4b17023SJohn Marino   /* If STMT could throw, then do not consider STMT as defining a GIV.
1110e4b17023SJohn Marino      While this will suppress optimizations, we can not safely delete this
1111e4b17023SJohn Marino      GIV and associated statements, even if it appears it is not used.  */
1112e4b17023SJohn Marino   if (stmt_could_throw_p (stmt))
1113e4b17023SJohn Marino     return false;
1114e4b17023SJohn Marino 
1115e4b17023SJohn Marino   return true;
1116e4b17023SJohn Marino }
1117e4b17023SJohn Marino 
1118e4b17023SJohn Marino /* Finds general ivs in statement STMT.  */
1119e4b17023SJohn Marino 
1120e4b17023SJohn Marino static void
find_givs_in_stmt(struct ivopts_data * data,gimple stmt)1121e4b17023SJohn Marino find_givs_in_stmt (struct ivopts_data *data, gimple stmt)
1122e4b17023SJohn Marino {
1123e4b17023SJohn Marino   affine_iv iv;
1124e4b17023SJohn Marino 
1125e4b17023SJohn Marino   if (!find_givs_in_stmt_scev (data, stmt, &iv))
1126e4b17023SJohn Marino     return;
1127e4b17023SJohn Marino 
1128e4b17023SJohn Marino   set_iv (data, gimple_assign_lhs (stmt), iv.base, iv.step);
1129e4b17023SJohn Marino }
1130e4b17023SJohn Marino 
1131e4b17023SJohn Marino /* Finds general ivs in basic block BB.  */
1132e4b17023SJohn Marino 
1133e4b17023SJohn Marino static void
find_givs_in_bb(struct ivopts_data * data,basic_block bb)1134e4b17023SJohn Marino find_givs_in_bb (struct ivopts_data *data, basic_block bb)
1135e4b17023SJohn Marino {
1136e4b17023SJohn Marino   gimple_stmt_iterator bsi;
1137e4b17023SJohn Marino 
1138e4b17023SJohn Marino   for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi))
1139e4b17023SJohn Marino     find_givs_in_stmt (data, gsi_stmt (bsi));
1140e4b17023SJohn Marino }
1141e4b17023SJohn Marino 
1142e4b17023SJohn Marino /* Finds general ivs.  */
1143e4b17023SJohn Marino 
1144e4b17023SJohn Marino static void
find_givs(struct ivopts_data * data)1145e4b17023SJohn Marino find_givs (struct ivopts_data *data)
1146e4b17023SJohn Marino {
1147e4b17023SJohn Marino   struct loop *loop = data->current_loop;
1148e4b17023SJohn Marino   basic_block *body = get_loop_body_in_dom_order (loop);
1149e4b17023SJohn Marino   unsigned i;
1150e4b17023SJohn Marino 
1151e4b17023SJohn Marino   for (i = 0; i < loop->num_nodes; i++)
1152e4b17023SJohn Marino     find_givs_in_bb (data, body[i]);
1153e4b17023SJohn Marino   free (body);
1154e4b17023SJohn Marino }
1155e4b17023SJohn Marino 
1156e4b17023SJohn Marino /* For each ssa name defined in LOOP determines whether it is an induction
1157e4b17023SJohn Marino    variable and if so, its initial value and step.  */
1158e4b17023SJohn Marino 
1159e4b17023SJohn Marino static bool
find_induction_variables(struct ivopts_data * data)1160e4b17023SJohn Marino find_induction_variables (struct ivopts_data *data)
1161e4b17023SJohn Marino {
1162e4b17023SJohn Marino   unsigned i;
1163e4b17023SJohn Marino   bitmap_iterator bi;
1164e4b17023SJohn Marino 
1165e4b17023SJohn Marino   if (!find_bivs (data))
1166e4b17023SJohn Marino     return false;
1167e4b17023SJohn Marino 
1168e4b17023SJohn Marino   find_givs (data);
1169e4b17023SJohn Marino   mark_bivs (data);
1170e4b17023SJohn Marino 
1171e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
1172e4b17023SJohn Marino     {
1173e4b17023SJohn Marino       struct tree_niter_desc *niter = niter_for_single_dom_exit (data);
1174e4b17023SJohn Marino 
1175e4b17023SJohn Marino       if (niter)
1176e4b17023SJohn Marino 	{
1177e4b17023SJohn Marino 	  fprintf (dump_file, "  number of iterations ");
1178e4b17023SJohn Marino 	  print_generic_expr (dump_file, niter->niter, TDF_SLIM);
1179e4b17023SJohn Marino 	  if (!integer_zerop (niter->may_be_zero))
1180e4b17023SJohn Marino 	    {
1181e4b17023SJohn Marino 	      fprintf (dump_file, "; zero if ");
1182e4b17023SJohn Marino 	      print_generic_expr (dump_file, niter->may_be_zero, TDF_SLIM);
1183e4b17023SJohn Marino 	    }
1184e4b17023SJohn Marino 	  fprintf (dump_file, "\n\n");
1185e4b17023SJohn Marino     	};
1186e4b17023SJohn Marino 
1187e4b17023SJohn Marino       fprintf (dump_file, "Induction variables:\n\n");
1188e4b17023SJohn Marino 
1189e4b17023SJohn Marino       EXECUTE_IF_SET_IN_BITMAP (data->relevant, 0, i, bi)
1190e4b17023SJohn Marino 	{
1191e4b17023SJohn Marino 	  if (ver_info (data, i)->iv)
1192e4b17023SJohn Marino 	    dump_iv (dump_file, ver_info (data, i)->iv);
1193e4b17023SJohn Marino 	}
1194e4b17023SJohn Marino     }
1195e4b17023SJohn Marino 
1196e4b17023SJohn Marino   return true;
1197e4b17023SJohn Marino }
1198e4b17023SJohn Marino 
1199e4b17023SJohn Marino /* Records a use of type USE_TYPE at *USE_P in STMT whose value is IV.  */
1200e4b17023SJohn Marino 
1201e4b17023SJohn Marino static struct iv_use *
record_use(struct ivopts_data * data,tree * use_p,struct iv * iv,gimple stmt,enum use_type use_type)1202e4b17023SJohn Marino record_use (struct ivopts_data *data, tree *use_p, struct iv *iv,
1203e4b17023SJohn Marino 	    gimple stmt, enum use_type use_type)
1204e4b17023SJohn Marino {
1205e4b17023SJohn Marino   struct iv_use *use = XCNEW (struct iv_use);
1206e4b17023SJohn Marino 
1207e4b17023SJohn Marino   use->id = n_iv_uses (data);
1208e4b17023SJohn Marino   use->type = use_type;
1209e4b17023SJohn Marino   use->iv = iv;
1210e4b17023SJohn Marino   use->stmt = stmt;
1211e4b17023SJohn Marino   use->op_p = use_p;
1212e4b17023SJohn Marino   use->related_cands = BITMAP_ALLOC (NULL);
1213e4b17023SJohn Marino 
1214e4b17023SJohn Marino   /* To avoid showing ssa name in the dumps, if it was not reset by the
1215e4b17023SJohn Marino      caller.  */
1216e4b17023SJohn Marino   iv->ssa_name = NULL_TREE;
1217e4b17023SJohn Marino 
1218e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
1219e4b17023SJohn Marino     dump_use (dump_file, use);
1220e4b17023SJohn Marino 
1221e4b17023SJohn Marino   VEC_safe_push (iv_use_p, heap, data->iv_uses, use);
1222e4b17023SJohn Marino 
1223e4b17023SJohn Marino   return use;
1224e4b17023SJohn Marino }
1225e4b17023SJohn Marino 
1226e4b17023SJohn Marino /* Checks whether OP is a loop-level invariant and if so, records it.
1227e4b17023SJohn Marino    NONLINEAR_USE is true if the invariant is used in a way we do not
1228e4b17023SJohn Marino    handle specially.  */
1229e4b17023SJohn Marino 
1230e4b17023SJohn Marino static void
record_invariant(struct ivopts_data * data,tree op,bool nonlinear_use)1231e4b17023SJohn Marino record_invariant (struct ivopts_data *data, tree op, bool nonlinear_use)
1232e4b17023SJohn Marino {
1233e4b17023SJohn Marino   basic_block bb;
1234e4b17023SJohn Marino   struct version_info *info;
1235e4b17023SJohn Marino 
1236e4b17023SJohn Marino   if (TREE_CODE (op) != SSA_NAME
1237e4b17023SJohn Marino       || !is_gimple_reg (op))
1238e4b17023SJohn Marino     return;
1239e4b17023SJohn Marino 
1240e4b17023SJohn Marino   bb = gimple_bb (SSA_NAME_DEF_STMT (op));
1241e4b17023SJohn Marino   if (bb
1242e4b17023SJohn Marino       && flow_bb_inside_loop_p (data->current_loop, bb))
1243e4b17023SJohn Marino     return;
1244e4b17023SJohn Marino 
1245e4b17023SJohn Marino   info = name_info (data, op);
1246e4b17023SJohn Marino   info->name = op;
1247e4b17023SJohn Marino   info->has_nonlin_use |= nonlinear_use;
1248e4b17023SJohn Marino   if (!info->inv_id)
1249e4b17023SJohn Marino     info->inv_id = ++data->max_inv_id;
1250e4b17023SJohn Marino   bitmap_set_bit (data->relevant, SSA_NAME_VERSION (op));
1251e4b17023SJohn Marino }
1252e4b17023SJohn Marino 
1253e4b17023SJohn Marino /* Checks whether the use OP is interesting and if so, records it.  */
1254e4b17023SJohn Marino 
1255e4b17023SJohn Marino static struct iv_use *
find_interesting_uses_op(struct ivopts_data * data,tree op)1256e4b17023SJohn Marino find_interesting_uses_op (struct ivopts_data *data, tree op)
1257e4b17023SJohn Marino {
1258e4b17023SJohn Marino   struct iv *iv;
1259e4b17023SJohn Marino   struct iv *civ;
1260e4b17023SJohn Marino   gimple stmt;
1261e4b17023SJohn Marino   struct iv_use *use;
1262e4b17023SJohn Marino 
1263e4b17023SJohn Marino   if (TREE_CODE (op) != SSA_NAME)
1264e4b17023SJohn Marino     return NULL;
1265e4b17023SJohn Marino 
1266e4b17023SJohn Marino   iv = get_iv (data, op);
1267e4b17023SJohn Marino   if (!iv)
1268e4b17023SJohn Marino     return NULL;
1269e4b17023SJohn Marino 
1270e4b17023SJohn Marino   if (iv->have_use_for)
1271e4b17023SJohn Marino     {
1272e4b17023SJohn Marino       use = iv_use (data, iv->use_id);
1273e4b17023SJohn Marino 
1274e4b17023SJohn Marino       gcc_assert (use->type == USE_NONLINEAR_EXPR);
1275e4b17023SJohn Marino       return use;
1276e4b17023SJohn Marino     }
1277e4b17023SJohn Marino 
1278e4b17023SJohn Marino   if (integer_zerop (iv->step))
1279e4b17023SJohn Marino     {
1280e4b17023SJohn Marino       record_invariant (data, op, true);
1281e4b17023SJohn Marino       return NULL;
1282e4b17023SJohn Marino     }
1283e4b17023SJohn Marino   iv->have_use_for = true;
1284e4b17023SJohn Marino 
1285e4b17023SJohn Marino   civ = XNEW (struct iv);
1286e4b17023SJohn Marino   *civ = *iv;
1287e4b17023SJohn Marino 
1288e4b17023SJohn Marino   stmt = SSA_NAME_DEF_STMT (op);
1289e4b17023SJohn Marino   gcc_assert (gimple_code (stmt) == GIMPLE_PHI
1290e4b17023SJohn Marino 	      || is_gimple_assign (stmt));
1291e4b17023SJohn Marino 
1292e4b17023SJohn Marino   use = record_use (data, NULL, civ, stmt, USE_NONLINEAR_EXPR);
1293e4b17023SJohn Marino   iv->use_id = use->id;
1294e4b17023SJohn Marino 
1295e4b17023SJohn Marino   return use;
1296e4b17023SJohn Marino }
1297e4b17023SJohn Marino 
1298e4b17023SJohn Marino /* Given a condition in statement STMT, checks whether it is a compare
1299e4b17023SJohn Marino    of an induction variable and an invariant.  If this is the case,
1300e4b17023SJohn Marino    CONTROL_VAR is set to location of the iv, BOUND to the location of
1301e4b17023SJohn Marino    the invariant, IV_VAR and IV_BOUND are set to the corresponding
1302e4b17023SJohn Marino    induction variable descriptions, and true is returned.  If this is not
1303e4b17023SJohn Marino    the case, CONTROL_VAR and BOUND are set to the arguments of the
1304e4b17023SJohn Marino    condition and false is returned.  */
1305e4b17023SJohn Marino 
1306e4b17023SJohn Marino static bool
extract_cond_operands(struct ivopts_data * data,gimple stmt,tree ** control_var,tree ** bound,struct iv ** iv_var,struct iv ** iv_bound)1307e4b17023SJohn Marino extract_cond_operands (struct ivopts_data *data, gimple stmt,
1308e4b17023SJohn Marino 		       tree **control_var, tree **bound,
1309e4b17023SJohn Marino 		       struct iv **iv_var, struct iv **iv_bound)
1310e4b17023SJohn Marino {
1311e4b17023SJohn Marino   /* The objects returned when COND has constant operands.  */
1312e4b17023SJohn Marino   static struct iv const_iv;
1313e4b17023SJohn Marino   static tree zero;
1314e4b17023SJohn Marino   tree *op0 = &zero, *op1 = &zero, *tmp_op;
1315e4b17023SJohn Marino   struct iv *iv0 = &const_iv, *iv1 = &const_iv, *tmp_iv;
1316e4b17023SJohn Marino   bool ret = false;
1317e4b17023SJohn Marino 
1318e4b17023SJohn Marino   if (gimple_code (stmt) == GIMPLE_COND)
1319e4b17023SJohn Marino     {
1320e4b17023SJohn Marino       op0 = gimple_cond_lhs_ptr (stmt);
1321e4b17023SJohn Marino       op1 = gimple_cond_rhs_ptr (stmt);
1322e4b17023SJohn Marino     }
1323e4b17023SJohn Marino   else
1324e4b17023SJohn Marino     {
1325e4b17023SJohn Marino       op0 = gimple_assign_rhs1_ptr (stmt);
1326e4b17023SJohn Marino       op1 = gimple_assign_rhs2_ptr (stmt);
1327e4b17023SJohn Marino     }
1328e4b17023SJohn Marino 
1329e4b17023SJohn Marino   zero = integer_zero_node;
1330e4b17023SJohn Marino   const_iv.step = integer_zero_node;
1331e4b17023SJohn Marino 
1332e4b17023SJohn Marino   if (TREE_CODE (*op0) == SSA_NAME)
1333e4b17023SJohn Marino     iv0 = get_iv (data, *op0);
1334e4b17023SJohn Marino   if (TREE_CODE (*op1) == SSA_NAME)
1335e4b17023SJohn Marino     iv1 = get_iv (data, *op1);
1336e4b17023SJohn Marino 
1337e4b17023SJohn Marino   /* Exactly one of the compared values must be an iv, and the other one must
1338e4b17023SJohn Marino      be an invariant.  */
1339e4b17023SJohn Marino   if (!iv0 || !iv1)
1340e4b17023SJohn Marino     goto end;
1341e4b17023SJohn Marino 
1342e4b17023SJohn Marino   if (integer_zerop (iv0->step))
1343e4b17023SJohn Marino     {
1344e4b17023SJohn Marino       /* Control variable may be on the other side.  */
1345e4b17023SJohn Marino       tmp_op = op0; op0 = op1; op1 = tmp_op;
1346e4b17023SJohn Marino       tmp_iv = iv0; iv0 = iv1; iv1 = tmp_iv;
1347e4b17023SJohn Marino     }
1348e4b17023SJohn Marino   ret = !integer_zerop (iv0->step) && integer_zerop (iv1->step);
1349e4b17023SJohn Marino 
1350e4b17023SJohn Marino end:
1351e4b17023SJohn Marino   if (control_var)
1352e4b17023SJohn Marino     *control_var = op0;;
1353e4b17023SJohn Marino   if (iv_var)
1354e4b17023SJohn Marino     *iv_var = iv0;;
1355e4b17023SJohn Marino   if (bound)
1356e4b17023SJohn Marino     *bound = op1;
1357e4b17023SJohn Marino   if (iv_bound)
1358e4b17023SJohn Marino     *iv_bound = iv1;
1359e4b17023SJohn Marino 
1360e4b17023SJohn Marino   return ret;
1361e4b17023SJohn Marino }
1362e4b17023SJohn Marino 
1363e4b17023SJohn Marino /* Checks whether the condition in STMT is interesting and if so,
1364e4b17023SJohn Marino    records it.  */
1365e4b17023SJohn Marino 
1366e4b17023SJohn Marino static void
find_interesting_uses_cond(struct ivopts_data * data,gimple stmt)1367e4b17023SJohn Marino find_interesting_uses_cond (struct ivopts_data *data, gimple stmt)
1368e4b17023SJohn Marino {
1369e4b17023SJohn Marino   tree *var_p, *bound_p;
1370e4b17023SJohn Marino   struct iv *var_iv, *civ;
1371e4b17023SJohn Marino 
1372e4b17023SJohn Marino   if (!extract_cond_operands (data, stmt, &var_p, &bound_p, &var_iv, NULL))
1373e4b17023SJohn Marino     {
1374e4b17023SJohn Marino       find_interesting_uses_op (data, *var_p);
1375e4b17023SJohn Marino       find_interesting_uses_op (data, *bound_p);
1376e4b17023SJohn Marino       return;
1377e4b17023SJohn Marino     }
1378e4b17023SJohn Marino 
1379e4b17023SJohn Marino   civ = XNEW (struct iv);
1380e4b17023SJohn Marino   *civ = *var_iv;
1381e4b17023SJohn Marino   record_use (data, NULL, civ, stmt, USE_COMPARE);
1382e4b17023SJohn Marino }
1383e4b17023SJohn Marino 
1384e4b17023SJohn Marino /* Returns true if expression EXPR is obviously invariant in LOOP,
1385e4b17023SJohn Marino    i.e. if all its operands are defined outside of the LOOP.  LOOP
1386e4b17023SJohn Marino    should not be the function body.  */
1387e4b17023SJohn Marino 
1388e4b17023SJohn Marino bool
expr_invariant_in_loop_p(struct loop * loop,tree expr)1389e4b17023SJohn Marino expr_invariant_in_loop_p (struct loop *loop, tree expr)
1390e4b17023SJohn Marino {
1391e4b17023SJohn Marino   basic_block def_bb;
1392e4b17023SJohn Marino   unsigned i, len;
1393e4b17023SJohn Marino 
1394e4b17023SJohn Marino   gcc_assert (loop_depth (loop) > 0);
1395e4b17023SJohn Marino 
1396e4b17023SJohn Marino   if (is_gimple_min_invariant (expr))
1397e4b17023SJohn Marino     return true;
1398e4b17023SJohn Marino 
1399e4b17023SJohn Marino   if (TREE_CODE (expr) == SSA_NAME)
1400e4b17023SJohn Marino     {
1401e4b17023SJohn Marino       def_bb = gimple_bb (SSA_NAME_DEF_STMT (expr));
1402e4b17023SJohn Marino       if (def_bb
1403e4b17023SJohn Marino 	  && flow_bb_inside_loop_p (loop, def_bb))
1404e4b17023SJohn Marino 	return false;
1405e4b17023SJohn Marino 
1406e4b17023SJohn Marino       return true;
1407e4b17023SJohn Marino     }
1408e4b17023SJohn Marino 
1409e4b17023SJohn Marino   if (!EXPR_P (expr))
1410e4b17023SJohn Marino     return false;
1411e4b17023SJohn Marino 
1412e4b17023SJohn Marino   len = TREE_OPERAND_LENGTH (expr);
1413e4b17023SJohn Marino   for (i = 0; i < len; i++)
1414e4b17023SJohn Marino     if (!expr_invariant_in_loop_p (loop, TREE_OPERAND (expr, i)))
1415e4b17023SJohn Marino       return false;
1416e4b17023SJohn Marino 
1417e4b17023SJohn Marino   return true;
1418e4b17023SJohn Marino }
1419e4b17023SJohn Marino 
1420e4b17023SJohn Marino /* Returns true if statement STMT is obviously invariant in LOOP,
1421e4b17023SJohn Marino    i.e. if all its operands on the RHS are defined outside of the LOOP.
1422e4b17023SJohn Marino    LOOP should not be the function body.  */
1423e4b17023SJohn Marino 
1424e4b17023SJohn Marino bool
stmt_invariant_in_loop_p(struct loop * loop,gimple stmt)1425e4b17023SJohn Marino stmt_invariant_in_loop_p (struct loop *loop, gimple stmt)
1426e4b17023SJohn Marino {
1427e4b17023SJohn Marino   unsigned i;
1428e4b17023SJohn Marino   tree lhs;
1429e4b17023SJohn Marino 
1430e4b17023SJohn Marino   gcc_assert (loop_depth (loop) > 0);
1431e4b17023SJohn Marino 
1432e4b17023SJohn Marino   lhs = gimple_get_lhs (stmt);
1433e4b17023SJohn Marino   for (i = 0; i < gimple_num_ops (stmt); i++)
1434e4b17023SJohn Marino     {
1435e4b17023SJohn Marino       tree op = gimple_op (stmt, i);
1436e4b17023SJohn Marino       if (op != lhs && !expr_invariant_in_loop_p (loop, op))
1437e4b17023SJohn Marino 	return false;
1438e4b17023SJohn Marino     }
1439e4b17023SJohn Marino 
1440e4b17023SJohn Marino   return true;
1441e4b17023SJohn Marino }
1442e4b17023SJohn Marino 
1443e4b17023SJohn Marino /* Cumulates the steps of indices into DATA and replaces their values with the
1444e4b17023SJohn Marino    initial ones.  Returns false when the value of the index cannot be determined.
1445e4b17023SJohn Marino    Callback for for_each_index.  */
1446e4b17023SJohn Marino 
1447e4b17023SJohn Marino struct ifs_ivopts_data
1448e4b17023SJohn Marino {
1449e4b17023SJohn Marino   struct ivopts_data *ivopts_data;
1450e4b17023SJohn Marino   gimple stmt;
1451e4b17023SJohn Marino   tree step;
1452e4b17023SJohn Marino };
1453e4b17023SJohn Marino 
1454e4b17023SJohn Marino static bool
idx_find_step(tree base,tree * idx,void * data)1455e4b17023SJohn Marino idx_find_step (tree base, tree *idx, void *data)
1456e4b17023SJohn Marino {
1457e4b17023SJohn Marino   struct ifs_ivopts_data *dta = (struct ifs_ivopts_data *) data;
1458e4b17023SJohn Marino   struct iv *iv;
1459e4b17023SJohn Marino   tree step, iv_base, iv_step, lbound, off;
1460e4b17023SJohn Marino   struct loop *loop = dta->ivopts_data->current_loop;
1461e4b17023SJohn Marino 
1462e4b17023SJohn Marino   /* If base is a component ref, require that the offset of the reference
1463e4b17023SJohn Marino      be invariant.  */
1464e4b17023SJohn Marino   if (TREE_CODE (base) == COMPONENT_REF)
1465e4b17023SJohn Marino     {
1466e4b17023SJohn Marino       off = component_ref_field_offset (base);
1467e4b17023SJohn Marino       return expr_invariant_in_loop_p (loop, off);
1468e4b17023SJohn Marino     }
1469e4b17023SJohn Marino 
1470e4b17023SJohn Marino   /* If base is array, first check whether we will be able to move the
1471e4b17023SJohn Marino      reference out of the loop (in order to take its address in strength
1472e4b17023SJohn Marino      reduction).  In order for this to work we need both lower bound
1473e4b17023SJohn Marino      and step to be loop invariants.  */
1474e4b17023SJohn Marino   if (TREE_CODE (base) == ARRAY_REF || TREE_CODE (base) == ARRAY_RANGE_REF)
1475e4b17023SJohn Marino     {
1476e4b17023SJohn Marino       /* Moreover, for a range, the size needs to be invariant as well.  */
1477e4b17023SJohn Marino       if (TREE_CODE (base) == ARRAY_RANGE_REF
1478e4b17023SJohn Marino 	  && !expr_invariant_in_loop_p (loop, TYPE_SIZE (TREE_TYPE (base))))
1479e4b17023SJohn Marino 	return false;
1480e4b17023SJohn Marino 
1481e4b17023SJohn Marino       step = array_ref_element_size (base);
1482e4b17023SJohn Marino       lbound = array_ref_low_bound (base);
1483e4b17023SJohn Marino 
1484e4b17023SJohn Marino       if (!expr_invariant_in_loop_p (loop, step)
1485e4b17023SJohn Marino 	  || !expr_invariant_in_loop_p (loop, lbound))
1486e4b17023SJohn Marino 	return false;
1487e4b17023SJohn Marino     }
1488e4b17023SJohn Marino 
1489e4b17023SJohn Marino   if (TREE_CODE (*idx) != SSA_NAME)
1490e4b17023SJohn Marino     return true;
1491e4b17023SJohn Marino 
1492e4b17023SJohn Marino   iv = get_iv (dta->ivopts_data, *idx);
1493e4b17023SJohn Marino   if (!iv)
1494e4b17023SJohn Marino     return false;
1495e4b17023SJohn Marino 
1496e4b17023SJohn Marino   /* XXX  We produce for a base of *D42 with iv->base being &x[0]
1497e4b17023SJohn Marino 	  *&x[0], which is not folded and does not trigger the
1498e4b17023SJohn Marino 	  ARRAY_REF path below.  */
1499e4b17023SJohn Marino   *idx = iv->base;
1500e4b17023SJohn Marino 
1501e4b17023SJohn Marino   if (integer_zerop (iv->step))
1502e4b17023SJohn Marino     return true;
1503e4b17023SJohn Marino 
1504e4b17023SJohn Marino   if (TREE_CODE (base) == ARRAY_REF || TREE_CODE (base) == ARRAY_RANGE_REF)
1505e4b17023SJohn Marino     {
1506e4b17023SJohn Marino       step = array_ref_element_size (base);
1507e4b17023SJohn Marino 
1508e4b17023SJohn Marino       /* We only handle addresses whose step is an integer constant.  */
1509e4b17023SJohn Marino       if (TREE_CODE (step) != INTEGER_CST)
1510e4b17023SJohn Marino 	return false;
1511e4b17023SJohn Marino     }
1512e4b17023SJohn Marino   else
1513e4b17023SJohn Marino     /* The step for pointer arithmetics already is 1 byte.  */
1514e4b17023SJohn Marino     step = size_one_node;
1515e4b17023SJohn Marino 
1516e4b17023SJohn Marino   iv_base = iv->base;
1517e4b17023SJohn Marino   iv_step = iv->step;
1518e4b17023SJohn Marino   if (!convert_affine_scev (dta->ivopts_data->current_loop,
1519e4b17023SJohn Marino 			    sizetype, &iv_base, &iv_step, dta->stmt,
1520e4b17023SJohn Marino 			    false))
1521e4b17023SJohn Marino     {
1522e4b17023SJohn Marino       /* The index might wrap.  */
1523e4b17023SJohn Marino       return false;
1524e4b17023SJohn Marino     }
1525e4b17023SJohn Marino 
1526e4b17023SJohn Marino   step = fold_build2 (MULT_EXPR, sizetype, step, iv_step);
1527e4b17023SJohn Marino   dta->step = fold_build2 (PLUS_EXPR, sizetype, dta->step, step);
1528e4b17023SJohn Marino 
1529e4b17023SJohn Marino   return true;
1530e4b17023SJohn Marino }
1531e4b17023SJohn Marino 
1532e4b17023SJohn Marino /* Records use in index IDX.  Callback for for_each_index.  Ivopts data
1533e4b17023SJohn Marino    object is passed to it in DATA.  */
1534e4b17023SJohn Marino 
1535e4b17023SJohn Marino static bool
idx_record_use(tree base,tree * idx,void * vdata)1536e4b17023SJohn Marino idx_record_use (tree base, tree *idx,
1537e4b17023SJohn Marino 		void *vdata)
1538e4b17023SJohn Marino {
1539e4b17023SJohn Marino   struct ivopts_data *data = (struct ivopts_data *) vdata;
1540e4b17023SJohn Marino   find_interesting_uses_op (data, *idx);
1541e4b17023SJohn Marino   if (TREE_CODE (base) == ARRAY_REF || TREE_CODE (base) == ARRAY_RANGE_REF)
1542e4b17023SJohn Marino     {
1543e4b17023SJohn Marino       find_interesting_uses_op (data, array_ref_element_size (base));
1544e4b17023SJohn Marino       find_interesting_uses_op (data, array_ref_low_bound (base));
1545e4b17023SJohn Marino     }
1546e4b17023SJohn Marino   return true;
1547e4b17023SJohn Marino }
1548e4b17023SJohn Marino 
1549e4b17023SJohn Marino /* If we can prove that TOP = cst * BOT for some constant cst,
1550e4b17023SJohn Marino    store cst to MUL and return true.  Otherwise return false.
1551e4b17023SJohn Marino    The returned value is always sign-extended, regardless of the
1552e4b17023SJohn Marino    signedness of TOP and BOT.  */
1553e4b17023SJohn Marino 
1554e4b17023SJohn Marino static bool
constant_multiple_of(tree top,tree bot,double_int * mul)1555e4b17023SJohn Marino constant_multiple_of (tree top, tree bot, double_int *mul)
1556e4b17023SJohn Marino {
1557e4b17023SJohn Marino   tree mby;
1558e4b17023SJohn Marino   enum tree_code code;
1559e4b17023SJohn Marino   double_int res, p0, p1;
1560e4b17023SJohn Marino   unsigned precision = TYPE_PRECISION (TREE_TYPE (top));
1561e4b17023SJohn Marino 
1562e4b17023SJohn Marino   STRIP_NOPS (top);
1563e4b17023SJohn Marino   STRIP_NOPS (bot);
1564e4b17023SJohn Marino 
1565e4b17023SJohn Marino   if (operand_equal_p (top, bot, 0))
1566e4b17023SJohn Marino     {
1567e4b17023SJohn Marino       *mul = double_int_one;
1568e4b17023SJohn Marino       return true;
1569e4b17023SJohn Marino     }
1570e4b17023SJohn Marino 
1571e4b17023SJohn Marino   code = TREE_CODE (top);
1572e4b17023SJohn Marino   switch (code)
1573e4b17023SJohn Marino     {
1574e4b17023SJohn Marino     case MULT_EXPR:
1575e4b17023SJohn Marino       mby = TREE_OPERAND (top, 1);
1576e4b17023SJohn Marino       if (TREE_CODE (mby) != INTEGER_CST)
1577e4b17023SJohn Marino 	return false;
1578e4b17023SJohn Marino 
1579e4b17023SJohn Marino       if (!constant_multiple_of (TREE_OPERAND (top, 0), bot, &res))
1580e4b17023SJohn Marino 	return false;
1581e4b17023SJohn Marino 
1582e4b17023SJohn Marino       *mul = double_int_sext (double_int_mul (res, tree_to_double_int (mby)),
1583e4b17023SJohn Marino 			      precision);
1584e4b17023SJohn Marino       return true;
1585e4b17023SJohn Marino 
1586e4b17023SJohn Marino     case PLUS_EXPR:
1587e4b17023SJohn Marino     case MINUS_EXPR:
1588e4b17023SJohn Marino       if (!constant_multiple_of (TREE_OPERAND (top, 0), bot, &p0)
1589e4b17023SJohn Marino 	  || !constant_multiple_of (TREE_OPERAND (top, 1), bot, &p1))
1590e4b17023SJohn Marino 	return false;
1591e4b17023SJohn Marino 
1592e4b17023SJohn Marino       if (code == MINUS_EXPR)
1593e4b17023SJohn Marino 	p1 = double_int_neg (p1);
1594e4b17023SJohn Marino       *mul = double_int_sext (double_int_add (p0, p1), precision);
1595e4b17023SJohn Marino       return true;
1596e4b17023SJohn Marino 
1597e4b17023SJohn Marino     case INTEGER_CST:
1598e4b17023SJohn Marino       if (TREE_CODE (bot) != INTEGER_CST)
1599e4b17023SJohn Marino 	return false;
1600e4b17023SJohn Marino 
1601e4b17023SJohn Marino       p0 = double_int_sext (tree_to_double_int (top), precision);
1602e4b17023SJohn Marino       p1 = double_int_sext (tree_to_double_int (bot), precision);
1603e4b17023SJohn Marino       if (double_int_zero_p (p1))
1604e4b17023SJohn Marino 	return false;
1605e4b17023SJohn Marino       *mul = double_int_sext (double_int_sdivmod (p0, p1, FLOOR_DIV_EXPR, &res),
1606e4b17023SJohn Marino 			      precision);
1607e4b17023SJohn Marino       return double_int_zero_p (res);
1608e4b17023SJohn Marino 
1609e4b17023SJohn Marino     default:
1610e4b17023SJohn Marino       return false;
1611e4b17023SJohn Marino     }
1612e4b17023SJohn Marino }
1613e4b17023SJohn Marino 
1614e4b17023SJohn Marino /* Returns true if memory reference REF with step STEP may be unaligned.  */
1615e4b17023SJohn Marino 
1616e4b17023SJohn Marino static bool
may_be_unaligned_p(tree ref,tree step)1617e4b17023SJohn Marino may_be_unaligned_p (tree ref, tree step)
1618e4b17023SJohn Marino {
1619e4b17023SJohn Marino   tree base;
1620e4b17023SJohn Marino   tree base_type;
1621e4b17023SJohn Marino   HOST_WIDE_INT bitsize;
1622e4b17023SJohn Marino   HOST_WIDE_INT bitpos;
1623e4b17023SJohn Marino   tree toffset;
1624e4b17023SJohn Marino   enum machine_mode mode;
1625e4b17023SJohn Marino   int unsignedp, volatilep;
1626e4b17023SJohn Marino   unsigned base_align;
1627e4b17023SJohn Marino 
1628e4b17023SJohn Marino   /* TARGET_MEM_REFs are translated directly to valid MEMs on the target,
1629e4b17023SJohn Marino      thus they are not misaligned.  */
1630e4b17023SJohn Marino   if (TREE_CODE (ref) == TARGET_MEM_REF)
1631e4b17023SJohn Marino     return false;
1632e4b17023SJohn Marino 
1633e4b17023SJohn Marino   /* The test below is basically copy of what expr.c:normal_inner_ref
1634e4b17023SJohn Marino      does to check whether the object must be loaded by parts when
1635e4b17023SJohn Marino      STRICT_ALIGNMENT is true.  */
1636e4b17023SJohn Marino   base = get_inner_reference (ref, &bitsize, &bitpos, &toffset, &mode,
1637e4b17023SJohn Marino 			      &unsignedp, &volatilep, true);
1638e4b17023SJohn Marino   base_type = TREE_TYPE (base);
1639e4b17023SJohn Marino   base_align = get_object_alignment (base);
1640e4b17023SJohn Marino   base_align = MAX (base_align, TYPE_ALIGN (base_type));
1641e4b17023SJohn Marino 
1642e4b17023SJohn Marino   if (mode != BLKmode)
1643e4b17023SJohn Marino     {
1644e4b17023SJohn Marino       unsigned mode_align = GET_MODE_ALIGNMENT (mode);
1645e4b17023SJohn Marino 
1646e4b17023SJohn Marino       if (base_align < mode_align
1647e4b17023SJohn Marino 	  || (bitpos % mode_align) != 0
1648e4b17023SJohn Marino 	  || (bitpos % BITS_PER_UNIT) != 0)
1649e4b17023SJohn Marino 	return true;
1650e4b17023SJohn Marino 
1651e4b17023SJohn Marino       if (toffset
1652e4b17023SJohn Marino 	  && (highest_pow2_factor (toffset) * BITS_PER_UNIT) < mode_align)
1653e4b17023SJohn Marino 	return true;
1654e4b17023SJohn Marino 
1655e4b17023SJohn Marino       if ((highest_pow2_factor (step) * BITS_PER_UNIT) < mode_align)
1656e4b17023SJohn Marino 	return true;
1657e4b17023SJohn Marino     }
1658e4b17023SJohn Marino 
1659e4b17023SJohn Marino   return false;
1660e4b17023SJohn Marino }
1661e4b17023SJohn Marino 
1662e4b17023SJohn Marino /* Return true if EXPR may be non-addressable.   */
1663e4b17023SJohn Marino 
1664e4b17023SJohn Marino bool
may_be_nonaddressable_p(tree expr)1665e4b17023SJohn Marino may_be_nonaddressable_p (tree expr)
1666e4b17023SJohn Marino {
1667e4b17023SJohn Marino   switch (TREE_CODE (expr))
1668e4b17023SJohn Marino     {
1669e4b17023SJohn Marino     case TARGET_MEM_REF:
1670e4b17023SJohn Marino       /* TARGET_MEM_REFs are translated directly to valid MEMs on the
1671e4b17023SJohn Marino 	 target, thus they are always addressable.  */
1672e4b17023SJohn Marino       return false;
1673e4b17023SJohn Marino 
1674e4b17023SJohn Marino     case COMPONENT_REF:
1675e4b17023SJohn Marino       return DECL_NONADDRESSABLE_P (TREE_OPERAND (expr, 1))
1676e4b17023SJohn Marino 	     || may_be_nonaddressable_p (TREE_OPERAND (expr, 0));
1677e4b17023SJohn Marino 
1678e4b17023SJohn Marino     case VIEW_CONVERT_EXPR:
1679e4b17023SJohn Marino       /* This kind of view-conversions may wrap non-addressable objects
1680e4b17023SJohn Marino 	 and make them look addressable.  After some processing the
1681e4b17023SJohn Marino 	 non-addressability may be uncovered again, causing ADDR_EXPRs
1682e4b17023SJohn Marino 	 of inappropriate objects to be built.  */
1683e4b17023SJohn Marino       if (is_gimple_reg (TREE_OPERAND (expr, 0))
1684e4b17023SJohn Marino 	  || !is_gimple_addressable (TREE_OPERAND (expr, 0)))
1685e4b17023SJohn Marino 	return true;
1686e4b17023SJohn Marino 
1687e4b17023SJohn Marino       /* ... fall through ... */
1688e4b17023SJohn Marino 
1689e4b17023SJohn Marino     case ARRAY_REF:
1690e4b17023SJohn Marino     case ARRAY_RANGE_REF:
1691e4b17023SJohn Marino       return may_be_nonaddressable_p (TREE_OPERAND (expr, 0));
1692e4b17023SJohn Marino 
1693e4b17023SJohn Marino     CASE_CONVERT:
1694e4b17023SJohn Marino       return true;
1695e4b17023SJohn Marino 
1696e4b17023SJohn Marino     default:
1697e4b17023SJohn Marino       break;
1698e4b17023SJohn Marino     }
1699e4b17023SJohn Marino 
1700e4b17023SJohn Marino   return false;
1701e4b17023SJohn Marino }
1702e4b17023SJohn Marino 
1703e4b17023SJohn Marino /* Finds addresses in *OP_P inside STMT.  */
1704e4b17023SJohn Marino 
1705e4b17023SJohn Marino static void
find_interesting_uses_address(struct ivopts_data * data,gimple stmt,tree * op_p)1706e4b17023SJohn Marino find_interesting_uses_address (struct ivopts_data *data, gimple stmt, tree *op_p)
1707e4b17023SJohn Marino {
1708e4b17023SJohn Marino   tree base = *op_p, step = size_zero_node;
1709e4b17023SJohn Marino   struct iv *civ;
1710e4b17023SJohn Marino   struct ifs_ivopts_data ifs_ivopts_data;
1711e4b17023SJohn Marino 
1712e4b17023SJohn Marino   /* Do not play with volatile memory references.  A bit too conservative,
1713e4b17023SJohn Marino      perhaps, but safe.  */
1714e4b17023SJohn Marino   if (gimple_has_volatile_ops (stmt))
1715e4b17023SJohn Marino     goto fail;
1716e4b17023SJohn Marino 
1717e4b17023SJohn Marino   /* Ignore bitfields for now.  Not really something terribly complicated
1718e4b17023SJohn Marino      to handle.  TODO.  */
1719e4b17023SJohn Marino   if (TREE_CODE (base) == BIT_FIELD_REF)
1720e4b17023SJohn Marino     goto fail;
1721e4b17023SJohn Marino 
1722e4b17023SJohn Marino   base = unshare_expr (base);
1723e4b17023SJohn Marino 
1724e4b17023SJohn Marino   if (TREE_CODE (base) == TARGET_MEM_REF)
1725e4b17023SJohn Marino     {
1726e4b17023SJohn Marino       tree type = build_pointer_type (TREE_TYPE (base));
1727e4b17023SJohn Marino       tree astep;
1728e4b17023SJohn Marino 
1729e4b17023SJohn Marino       if (TMR_BASE (base)
1730e4b17023SJohn Marino 	  && TREE_CODE (TMR_BASE (base)) == SSA_NAME)
1731e4b17023SJohn Marino 	{
1732e4b17023SJohn Marino 	  civ = get_iv (data, TMR_BASE (base));
1733e4b17023SJohn Marino 	  if (!civ)
1734e4b17023SJohn Marino 	    goto fail;
1735e4b17023SJohn Marino 
1736e4b17023SJohn Marino 	  TMR_BASE (base) = civ->base;
1737e4b17023SJohn Marino 	  step = civ->step;
1738e4b17023SJohn Marino 	}
1739e4b17023SJohn Marino       if (TMR_INDEX2 (base)
1740e4b17023SJohn Marino 	  && TREE_CODE (TMR_INDEX2 (base)) == SSA_NAME)
1741e4b17023SJohn Marino 	{
1742e4b17023SJohn Marino 	  civ = get_iv (data, TMR_INDEX2 (base));
1743e4b17023SJohn Marino 	  if (!civ)
1744e4b17023SJohn Marino 	    goto fail;
1745e4b17023SJohn Marino 
1746e4b17023SJohn Marino 	  TMR_INDEX2 (base) = civ->base;
1747e4b17023SJohn Marino 	  step = civ->step;
1748e4b17023SJohn Marino 	}
1749e4b17023SJohn Marino       if (TMR_INDEX (base)
1750e4b17023SJohn Marino 	  && TREE_CODE (TMR_INDEX (base)) == SSA_NAME)
1751e4b17023SJohn Marino 	{
1752e4b17023SJohn Marino 	  civ = get_iv (data, TMR_INDEX (base));
1753e4b17023SJohn Marino 	  if (!civ)
1754e4b17023SJohn Marino 	    goto fail;
1755e4b17023SJohn Marino 
1756e4b17023SJohn Marino 	  TMR_INDEX (base) = civ->base;
1757e4b17023SJohn Marino 	  astep = civ->step;
1758e4b17023SJohn Marino 
1759e4b17023SJohn Marino 	  if (astep)
1760e4b17023SJohn Marino 	    {
1761e4b17023SJohn Marino 	      if (TMR_STEP (base))
1762e4b17023SJohn Marino 		astep = fold_build2 (MULT_EXPR, type, TMR_STEP (base), astep);
1763e4b17023SJohn Marino 
1764e4b17023SJohn Marino 	      step = fold_build2 (PLUS_EXPR, type, step, astep);
1765e4b17023SJohn Marino 	    }
1766e4b17023SJohn Marino 	}
1767e4b17023SJohn Marino 
1768e4b17023SJohn Marino       if (integer_zerop (step))
1769e4b17023SJohn Marino 	goto fail;
1770e4b17023SJohn Marino       base = tree_mem_ref_addr (type, base);
1771e4b17023SJohn Marino     }
1772e4b17023SJohn Marino   else
1773e4b17023SJohn Marino     {
1774e4b17023SJohn Marino       ifs_ivopts_data.ivopts_data = data;
1775e4b17023SJohn Marino       ifs_ivopts_data.stmt = stmt;
1776e4b17023SJohn Marino       ifs_ivopts_data.step = size_zero_node;
1777e4b17023SJohn Marino       if (!for_each_index (&base, idx_find_step, &ifs_ivopts_data)
1778e4b17023SJohn Marino 	  || integer_zerop (ifs_ivopts_data.step))
1779e4b17023SJohn Marino 	goto fail;
1780e4b17023SJohn Marino       step = ifs_ivopts_data.step;
1781e4b17023SJohn Marino 
1782e4b17023SJohn Marino       /* Check that the base expression is addressable.  This needs
1783e4b17023SJohn Marino 	 to be done after substituting bases of IVs into it.  */
1784e4b17023SJohn Marino       if (may_be_nonaddressable_p (base))
1785e4b17023SJohn Marino 	goto fail;
1786e4b17023SJohn Marino 
1787e4b17023SJohn Marino       /* Moreover, on strict alignment platforms, check that it is
1788e4b17023SJohn Marino 	 sufficiently aligned.  */
1789e4b17023SJohn Marino       if (STRICT_ALIGNMENT && may_be_unaligned_p (base, step))
1790e4b17023SJohn Marino 	goto fail;
1791e4b17023SJohn Marino 
1792e4b17023SJohn Marino       base = build_fold_addr_expr (base);
1793e4b17023SJohn Marino 
1794e4b17023SJohn Marino       /* Substituting bases of IVs into the base expression might
1795e4b17023SJohn Marino 	 have caused folding opportunities.  */
1796e4b17023SJohn Marino       if (TREE_CODE (base) == ADDR_EXPR)
1797e4b17023SJohn Marino 	{
1798e4b17023SJohn Marino 	  tree *ref = &TREE_OPERAND (base, 0);
1799e4b17023SJohn Marino 	  while (handled_component_p (*ref))
1800e4b17023SJohn Marino 	    ref = &TREE_OPERAND (*ref, 0);
1801e4b17023SJohn Marino 	  if (TREE_CODE (*ref) == MEM_REF)
1802e4b17023SJohn Marino 	    {
1803e4b17023SJohn Marino 	      tree tem = fold_binary (MEM_REF, TREE_TYPE (*ref),
1804e4b17023SJohn Marino 				      TREE_OPERAND (*ref, 0),
1805e4b17023SJohn Marino 				      TREE_OPERAND (*ref, 1));
1806e4b17023SJohn Marino 	      if (tem)
1807e4b17023SJohn Marino 		*ref = tem;
1808e4b17023SJohn Marino 	    }
1809e4b17023SJohn Marino 	}
1810e4b17023SJohn Marino     }
1811e4b17023SJohn Marino 
1812e4b17023SJohn Marino   civ = alloc_iv (base, step);
1813e4b17023SJohn Marino   record_use (data, op_p, civ, stmt, USE_ADDRESS);
1814e4b17023SJohn Marino   return;
1815e4b17023SJohn Marino 
1816e4b17023SJohn Marino fail:
1817e4b17023SJohn Marino   for_each_index (op_p, idx_record_use, data);
1818e4b17023SJohn Marino }
1819e4b17023SJohn Marino 
1820e4b17023SJohn Marino /* Finds and records invariants used in STMT.  */
1821e4b17023SJohn Marino 
1822e4b17023SJohn Marino static void
find_invariants_stmt(struct ivopts_data * data,gimple stmt)1823e4b17023SJohn Marino find_invariants_stmt (struct ivopts_data *data, gimple stmt)
1824e4b17023SJohn Marino {
1825e4b17023SJohn Marino   ssa_op_iter iter;
1826e4b17023SJohn Marino   use_operand_p use_p;
1827e4b17023SJohn Marino   tree op;
1828e4b17023SJohn Marino 
1829e4b17023SJohn Marino   FOR_EACH_PHI_OR_STMT_USE (use_p, stmt, iter, SSA_OP_USE)
1830e4b17023SJohn Marino     {
1831e4b17023SJohn Marino       op = USE_FROM_PTR (use_p);
1832e4b17023SJohn Marino       record_invariant (data, op, false);
1833e4b17023SJohn Marino     }
1834e4b17023SJohn Marino }
1835e4b17023SJohn Marino 
1836e4b17023SJohn Marino /* Finds interesting uses of induction variables in the statement STMT.  */
1837e4b17023SJohn Marino 
1838e4b17023SJohn Marino static void
find_interesting_uses_stmt(struct ivopts_data * data,gimple stmt)1839e4b17023SJohn Marino find_interesting_uses_stmt (struct ivopts_data *data, gimple stmt)
1840e4b17023SJohn Marino {
1841e4b17023SJohn Marino   struct iv *iv;
1842e4b17023SJohn Marino   tree op, *lhs, *rhs;
1843e4b17023SJohn Marino   ssa_op_iter iter;
1844e4b17023SJohn Marino   use_operand_p use_p;
1845e4b17023SJohn Marino   enum tree_code code;
1846e4b17023SJohn Marino 
1847e4b17023SJohn Marino   find_invariants_stmt (data, stmt);
1848e4b17023SJohn Marino 
1849e4b17023SJohn Marino   if (gimple_code (stmt) == GIMPLE_COND)
1850e4b17023SJohn Marino     {
1851e4b17023SJohn Marino       find_interesting_uses_cond (data, stmt);
1852e4b17023SJohn Marino       return;
1853e4b17023SJohn Marino     }
1854e4b17023SJohn Marino 
1855e4b17023SJohn Marino   if (is_gimple_assign (stmt))
1856e4b17023SJohn Marino     {
1857e4b17023SJohn Marino       lhs = gimple_assign_lhs_ptr (stmt);
1858e4b17023SJohn Marino       rhs = gimple_assign_rhs1_ptr (stmt);
1859e4b17023SJohn Marino 
1860e4b17023SJohn Marino       if (TREE_CODE (*lhs) == SSA_NAME)
1861e4b17023SJohn Marino 	{
1862e4b17023SJohn Marino 	  /* If the statement defines an induction variable, the uses are not
1863e4b17023SJohn Marino 	     interesting by themselves.  */
1864e4b17023SJohn Marino 
1865e4b17023SJohn Marino 	  iv = get_iv (data, *lhs);
1866e4b17023SJohn Marino 
1867e4b17023SJohn Marino 	  if (iv && !integer_zerop (iv->step))
1868e4b17023SJohn Marino 	    return;
1869e4b17023SJohn Marino 	}
1870e4b17023SJohn Marino 
1871e4b17023SJohn Marino       code = gimple_assign_rhs_code (stmt);
1872e4b17023SJohn Marino       if (get_gimple_rhs_class (code) == GIMPLE_SINGLE_RHS
1873e4b17023SJohn Marino 	  && (REFERENCE_CLASS_P (*rhs)
1874e4b17023SJohn Marino 	      || is_gimple_val (*rhs)))
1875e4b17023SJohn Marino 	{
1876e4b17023SJohn Marino 	  if (REFERENCE_CLASS_P (*rhs))
1877e4b17023SJohn Marino 	    find_interesting_uses_address (data, stmt, rhs);
1878e4b17023SJohn Marino 	  else
1879e4b17023SJohn Marino 	    find_interesting_uses_op (data, *rhs);
1880e4b17023SJohn Marino 
1881e4b17023SJohn Marino 	  if (REFERENCE_CLASS_P (*lhs))
1882e4b17023SJohn Marino 	    find_interesting_uses_address (data, stmt, lhs);
1883e4b17023SJohn Marino 	  return;
1884e4b17023SJohn Marino 	}
1885e4b17023SJohn Marino       else if (TREE_CODE_CLASS (code) == tcc_comparison)
1886e4b17023SJohn Marino 	{
1887e4b17023SJohn Marino 	  find_interesting_uses_cond (data, stmt);
1888e4b17023SJohn Marino 	  return;
1889e4b17023SJohn Marino 	}
1890e4b17023SJohn Marino 
1891e4b17023SJohn Marino       /* TODO -- we should also handle address uses of type
1892e4b17023SJohn Marino 
1893e4b17023SJohn Marino 	 memory = call (whatever);
1894e4b17023SJohn Marino 
1895e4b17023SJohn Marino 	 and
1896e4b17023SJohn Marino 
1897e4b17023SJohn Marino 	 call (memory).  */
1898e4b17023SJohn Marino     }
1899e4b17023SJohn Marino 
1900e4b17023SJohn Marino   if (gimple_code (stmt) == GIMPLE_PHI
1901e4b17023SJohn Marino       && gimple_bb (stmt) == data->current_loop->header)
1902e4b17023SJohn Marino     {
1903e4b17023SJohn Marino       iv = get_iv (data, PHI_RESULT (stmt));
1904e4b17023SJohn Marino 
1905e4b17023SJohn Marino       if (iv && !integer_zerop (iv->step))
1906e4b17023SJohn Marino 	return;
1907e4b17023SJohn Marino     }
1908e4b17023SJohn Marino 
1909e4b17023SJohn Marino   FOR_EACH_PHI_OR_STMT_USE (use_p, stmt, iter, SSA_OP_USE)
1910e4b17023SJohn Marino     {
1911e4b17023SJohn Marino       op = USE_FROM_PTR (use_p);
1912e4b17023SJohn Marino 
1913e4b17023SJohn Marino       if (TREE_CODE (op) != SSA_NAME)
1914e4b17023SJohn Marino 	continue;
1915e4b17023SJohn Marino 
1916e4b17023SJohn Marino       iv = get_iv (data, op);
1917e4b17023SJohn Marino       if (!iv)
1918e4b17023SJohn Marino 	continue;
1919e4b17023SJohn Marino 
1920e4b17023SJohn Marino       find_interesting_uses_op (data, op);
1921e4b17023SJohn Marino     }
1922e4b17023SJohn Marino }
1923e4b17023SJohn Marino 
1924e4b17023SJohn Marino /* Finds interesting uses of induction variables outside of loops
1925e4b17023SJohn Marino    on loop exit edge EXIT.  */
1926e4b17023SJohn Marino 
1927e4b17023SJohn Marino static void
find_interesting_uses_outside(struct ivopts_data * data,edge exit)1928e4b17023SJohn Marino find_interesting_uses_outside (struct ivopts_data *data, edge exit)
1929e4b17023SJohn Marino {
1930e4b17023SJohn Marino   gimple phi;
1931e4b17023SJohn Marino   gimple_stmt_iterator psi;
1932e4b17023SJohn Marino   tree def;
1933e4b17023SJohn Marino 
1934e4b17023SJohn Marino   for (psi = gsi_start_phis (exit->dest); !gsi_end_p (psi); gsi_next (&psi))
1935e4b17023SJohn Marino     {
1936e4b17023SJohn Marino       phi = gsi_stmt (psi);
1937e4b17023SJohn Marino       def = PHI_ARG_DEF_FROM_EDGE (phi, exit);
1938e4b17023SJohn Marino       if (is_gimple_reg (def))
1939e4b17023SJohn Marino         find_interesting_uses_op (data, def);
1940e4b17023SJohn Marino     }
1941e4b17023SJohn Marino }
1942e4b17023SJohn Marino 
1943e4b17023SJohn Marino /* Finds uses of the induction variables that are interesting.  */
1944e4b17023SJohn Marino 
1945e4b17023SJohn Marino static void
find_interesting_uses(struct ivopts_data * data)1946e4b17023SJohn Marino find_interesting_uses (struct ivopts_data *data)
1947e4b17023SJohn Marino {
1948e4b17023SJohn Marino   basic_block bb;
1949e4b17023SJohn Marino   gimple_stmt_iterator bsi;
1950e4b17023SJohn Marino   basic_block *body = get_loop_body (data->current_loop);
1951e4b17023SJohn Marino   unsigned i;
1952e4b17023SJohn Marino   struct version_info *info;
1953e4b17023SJohn Marino   edge e;
1954e4b17023SJohn Marino 
1955e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
1956e4b17023SJohn Marino     fprintf (dump_file, "Uses:\n\n");
1957e4b17023SJohn Marino 
1958e4b17023SJohn Marino   for (i = 0; i < data->current_loop->num_nodes; i++)
1959e4b17023SJohn Marino     {
1960e4b17023SJohn Marino       edge_iterator ei;
1961e4b17023SJohn Marino       bb = body[i];
1962e4b17023SJohn Marino 
1963e4b17023SJohn Marino       FOR_EACH_EDGE (e, ei, bb->succs)
1964e4b17023SJohn Marino 	if (e->dest != EXIT_BLOCK_PTR
1965e4b17023SJohn Marino 	    && !flow_bb_inside_loop_p (data->current_loop, e->dest))
1966e4b17023SJohn Marino 	  find_interesting_uses_outside (data, e);
1967e4b17023SJohn Marino 
1968e4b17023SJohn Marino       for (bsi = gsi_start_phis (bb); !gsi_end_p (bsi); gsi_next (&bsi))
1969e4b17023SJohn Marino 	find_interesting_uses_stmt (data, gsi_stmt (bsi));
1970e4b17023SJohn Marino       for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi))
1971e4b17023SJohn Marino 	if (!is_gimple_debug (gsi_stmt (bsi)))
1972e4b17023SJohn Marino 	  find_interesting_uses_stmt (data, gsi_stmt (bsi));
1973e4b17023SJohn Marino     }
1974e4b17023SJohn Marino 
1975e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
1976e4b17023SJohn Marino     {
1977e4b17023SJohn Marino       bitmap_iterator bi;
1978e4b17023SJohn Marino 
1979e4b17023SJohn Marino       fprintf (dump_file, "\n");
1980e4b17023SJohn Marino 
1981e4b17023SJohn Marino       EXECUTE_IF_SET_IN_BITMAP (data->relevant, 0, i, bi)
1982e4b17023SJohn Marino 	{
1983e4b17023SJohn Marino 	  info = ver_info (data, i);
1984e4b17023SJohn Marino 	  if (info->inv_id)
1985e4b17023SJohn Marino 	    {
1986e4b17023SJohn Marino 	      fprintf (dump_file, "  ");
1987e4b17023SJohn Marino 	      print_generic_expr (dump_file, info->name, TDF_SLIM);
1988e4b17023SJohn Marino 	      fprintf (dump_file, " is invariant (%d)%s\n",
1989e4b17023SJohn Marino 		       info->inv_id, info->has_nonlin_use ? "" : ", eliminable");
1990e4b17023SJohn Marino 	    }
1991e4b17023SJohn Marino 	}
1992e4b17023SJohn Marino 
1993e4b17023SJohn Marino       fprintf (dump_file, "\n");
1994e4b17023SJohn Marino     }
1995e4b17023SJohn Marino 
1996e4b17023SJohn Marino   free (body);
1997e4b17023SJohn Marino }
1998e4b17023SJohn Marino 
1999e4b17023SJohn Marino /* Strips constant offsets from EXPR and stores them to OFFSET.  If INSIDE_ADDR
2000e4b17023SJohn Marino    is true, assume we are inside an address.  If TOP_COMPREF is true, assume
2001e4b17023SJohn Marino    we are at the top-level of the processed address.  */
2002e4b17023SJohn Marino 
2003e4b17023SJohn Marino static tree
strip_offset_1(tree expr,bool inside_addr,bool top_compref,unsigned HOST_WIDE_INT * offset)2004e4b17023SJohn Marino strip_offset_1 (tree expr, bool inside_addr, bool top_compref,
2005e4b17023SJohn Marino 		unsigned HOST_WIDE_INT *offset)
2006e4b17023SJohn Marino {
2007e4b17023SJohn Marino   tree op0 = NULL_TREE, op1 = NULL_TREE, tmp, step;
2008e4b17023SJohn Marino   enum tree_code code;
2009e4b17023SJohn Marino   tree type, orig_type = TREE_TYPE (expr);
2010e4b17023SJohn Marino   unsigned HOST_WIDE_INT off0, off1, st;
2011e4b17023SJohn Marino   tree orig_expr = expr;
2012e4b17023SJohn Marino 
2013e4b17023SJohn Marino   STRIP_NOPS (expr);
2014e4b17023SJohn Marino 
2015e4b17023SJohn Marino   type = TREE_TYPE (expr);
2016e4b17023SJohn Marino   code = TREE_CODE (expr);
2017e4b17023SJohn Marino   *offset = 0;
2018e4b17023SJohn Marino 
2019e4b17023SJohn Marino   switch (code)
2020e4b17023SJohn Marino     {
2021e4b17023SJohn Marino     case INTEGER_CST:
2022e4b17023SJohn Marino       if (!cst_and_fits_in_hwi (expr)
2023e4b17023SJohn Marino 	  || integer_zerop (expr))
2024e4b17023SJohn Marino 	return orig_expr;
2025e4b17023SJohn Marino 
2026e4b17023SJohn Marino       *offset = int_cst_value (expr);
2027e4b17023SJohn Marino       return build_int_cst (orig_type, 0);
2028e4b17023SJohn Marino 
2029e4b17023SJohn Marino     case POINTER_PLUS_EXPR:
2030e4b17023SJohn Marino     case PLUS_EXPR:
2031e4b17023SJohn Marino     case MINUS_EXPR:
2032e4b17023SJohn Marino       op0 = TREE_OPERAND (expr, 0);
2033e4b17023SJohn Marino       op1 = TREE_OPERAND (expr, 1);
2034e4b17023SJohn Marino 
2035e4b17023SJohn Marino       op0 = strip_offset_1 (op0, false, false, &off0);
2036e4b17023SJohn Marino       op1 = strip_offset_1 (op1, false, false, &off1);
2037e4b17023SJohn Marino 
2038e4b17023SJohn Marino       *offset = (code == MINUS_EXPR ? off0 - off1 : off0 + off1);
2039e4b17023SJohn Marino       if (op0 == TREE_OPERAND (expr, 0)
2040e4b17023SJohn Marino 	  && op1 == TREE_OPERAND (expr, 1))
2041e4b17023SJohn Marino 	return orig_expr;
2042e4b17023SJohn Marino 
2043e4b17023SJohn Marino       if (integer_zerop (op1))
2044e4b17023SJohn Marino 	expr = op0;
2045e4b17023SJohn Marino       else if (integer_zerop (op0))
2046e4b17023SJohn Marino 	{
2047e4b17023SJohn Marino 	  if (code == MINUS_EXPR)
2048e4b17023SJohn Marino 	    expr = fold_build1 (NEGATE_EXPR, type, op1);
2049e4b17023SJohn Marino 	  else
2050e4b17023SJohn Marino 	    expr = op1;
2051e4b17023SJohn Marino 	}
2052e4b17023SJohn Marino       else
2053e4b17023SJohn Marino 	expr = fold_build2 (code, type, op0, op1);
2054e4b17023SJohn Marino 
2055e4b17023SJohn Marino       return fold_convert (orig_type, expr);
2056e4b17023SJohn Marino 
2057e4b17023SJohn Marino     case MULT_EXPR:
2058e4b17023SJohn Marino       op1 = TREE_OPERAND (expr, 1);
2059e4b17023SJohn Marino       if (!cst_and_fits_in_hwi (op1))
2060e4b17023SJohn Marino 	return orig_expr;
2061e4b17023SJohn Marino 
2062e4b17023SJohn Marino       op0 = TREE_OPERAND (expr, 0);
2063e4b17023SJohn Marino       op0 = strip_offset_1 (op0, false, false, &off0);
2064e4b17023SJohn Marino       if (op0 == TREE_OPERAND (expr, 0))
2065e4b17023SJohn Marino 	return orig_expr;
2066e4b17023SJohn Marino 
2067e4b17023SJohn Marino       *offset = off0 * int_cst_value (op1);
2068e4b17023SJohn Marino       if (integer_zerop (op0))
2069e4b17023SJohn Marino 	expr = op0;
2070e4b17023SJohn Marino       else
2071e4b17023SJohn Marino 	expr = fold_build2 (MULT_EXPR, type, op0, op1);
2072e4b17023SJohn Marino 
2073e4b17023SJohn Marino       return fold_convert (orig_type, expr);
2074e4b17023SJohn Marino 
2075e4b17023SJohn Marino     case ARRAY_REF:
2076e4b17023SJohn Marino     case ARRAY_RANGE_REF:
2077e4b17023SJohn Marino       if (!inside_addr)
2078e4b17023SJohn Marino 	return orig_expr;
2079e4b17023SJohn Marino 
2080e4b17023SJohn Marino       step = array_ref_element_size (expr);
2081e4b17023SJohn Marino       if (!cst_and_fits_in_hwi (step))
2082e4b17023SJohn Marino 	break;
2083e4b17023SJohn Marino 
2084e4b17023SJohn Marino       st = int_cst_value (step);
2085e4b17023SJohn Marino       op1 = TREE_OPERAND (expr, 1);
2086e4b17023SJohn Marino       op1 = strip_offset_1 (op1, false, false, &off1);
2087e4b17023SJohn Marino       *offset = off1 * st;
2088e4b17023SJohn Marino 
2089e4b17023SJohn Marino       if (top_compref
2090e4b17023SJohn Marino 	  && integer_zerop (op1))
2091e4b17023SJohn Marino 	{
2092e4b17023SJohn Marino 	  /* Strip the component reference completely.  */
2093e4b17023SJohn Marino 	  op0 = TREE_OPERAND (expr, 0);
2094e4b17023SJohn Marino 	  op0 = strip_offset_1 (op0, inside_addr, top_compref, &off0);
2095e4b17023SJohn Marino 	  *offset += off0;
2096e4b17023SJohn Marino 	  return op0;
2097e4b17023SJohn Marino 	}
2098e4b17023SJohn Marino       break;
2099e4b17023SJohn Marino 
2100e4b17023SJohn Marino     case COMPONENT_REF:
2101e4b17023SJohn Marino       if (!inside_addr)
2102e4b17023SJohn Marino 	return orig_expr;
2103e4b17023SJohn Marino 
2104e4b17023SJohn Marino       tmp = component_ref_field_offset (expr);
2105e4b17023SJohn Marino       if (top_compref
2106e4b17023SJohn Marino 	  && cst_and_fits_in_hwi (tmp))
2107e4b17023SJohn Marino 	{
2108e4b17023SJohn Marino 	  /* Strip the component reference completely.  */
2109e4b17023SJohn Marino 	  op0 = TREE_OPERAND (expr, 0);
2110e4b17023SJohn Marino 	  op0 = strip_offset_1 (op0, inside_addr, top_compref, &off0);
2111e4b17023SJohn Marino 	  *offset = off0 + int_cst_value (tmp);
2112e4b17023SJohn Marino 	  return op0;
2113e4b17023SJohn Marino 	}
2114e4b17023SJohn Marino       break;
2115e4b17023SJohn Marino 
2116e4b17023SJohn Marino     case ADDR_EXPR:
2117e4b17023SJohn Marino       op0 = TREE_OPERAND (expr, 0);
2118e4b17023SJohn Marino       op0 = strip_offset_1 (op0, true, true, &off0);
2119e4b17023SJohn Marino       *offset += off0;
2120e4b17023SJohn Marino 
2121e4b17023SJohn Marino       if (op0 == TREE_OPERAND (expr, 0))
2122e4b17023SJohn Marino 	return orig_expr;
2123e4b17023SJohn Marino 
2124e4b17023SJohn Marino       expr = build_fold_addr_expr (op0);
2125e4b17023SJohn Marino       return fold_convert (orig_type, expr);
2126e4b17023SJohn Marino 
2127e4b17023SJohn Marino     case MEM_REF:
2128e4b17023SJohn Marino       /* ???  Offset operand?  */
2129e4b17023SJohn Marino       inside_addr = false;
2130e4b17023SJohn Marino       break;
2131e4b17023SJohn Marino 
2132e4b17023SJohn Marino     default:
2133e4b17023SJohn Marino       return orig_expr;
2134e4b17023SJohn Marino     }
2135e4b17023SJohn Marino 
2136e4b17023SJohn Marino   /* Default handling of expressions for that we want to recurse into
2137e4b17023SJohn Marino      the first operand.  */
2138e4b17023SJohn Marino   op0 = TREE_OPERAND (expr, 0);
2139e4b17023SJohn Marino   op0 = strip_offset_1 (op0, inside_addr, false, &off0);
2140e4b17023SJohn Marino   *offset += off0;
2141e4b17023SJohn Marino 
2142e4b17023SJohn Marino   if (op0 == TREE_OPERAND (expr, 0)
2143e4b17023SJohn Marino       && (!op1 || op1 == TREE_OPERAND (expr, 1)))
2144e4b17023SJohn Marino     return orig_expr;
2145e4b17023SJohn Marino 
2146e4b17023SJohn Marino   expr = copy_node (expr);
2147e4b17023SJohn Marino   TREE_OPERAND (expr, 0) = op0;
2148e4b17023SJohn Marino   if (op1)
2149e4b17023SJohn Marino     TREE_OPERAND (expr, 1) = op1;
2150e4b17023SJohn Marino 
2151e4b17023SJohn Marino   /* Inside address, we might strip the top level component references,
2152e4b17023SJohn Marino      thus changing type of the expression.  Handling of ADDR_EXPR
2153e4b17023SJohn Marino      will fix that.  */
2154e4b17023SJohn Marino   expr = fold_convert (orig_type, expr);
2155e4b17023SJohn Marino 
2156e4b17023SJohn Marino   return expr;
2157e4b17023SJohn Marino }
2158e4b17023SJohn Marino 
2159e4b17023SJohn Marino /* Strips constant offsets from EXPR and stores them to OFFSET.  */
2160e4b17023SJohn Marino 
2161e4b17023SJohn Marino static tree
strip_offset(tree expr,unsigned HOST_WIDE_INT * offset)2162e4b17023SJohn Marino strip_offset (tree expr, unsigned HOST_WIDE_INT *offset)
2163e4b17023SJohn Marino {
2164e4b17023SJohn Marino   return strip_offset_1 (expr, false, false, offset);
2165e4b17023SJohn Marino }
2166e4b17023SJohn Marino 
2167e4b17023SJohn Marino /* Returns variant of TYPE that can be used as base for different uses.
2168e4b17023SJohn Marino    We return unsigned type with the same precision, which avoids problems
2169e4b17023SJohn Marino    with overflows.  */
2170e4b17023SJohn Marino 
2171e4b17023SJohn Marino static tree
generic_type_for(tree type)2172e4b17023SJohn Marino generic_type_for (tree type)
2173e4b17023SJohn Marino {
2174e4b17023SJohn Marino   if (POINTER_TYPE_P (type))
2175e4b17023SJohn Marino     return unsigned_type_for (type);
2176e4b17023SJohn Marino 
2177e4b17023SJohn Marino   if (TYPE_UNSIGNED (type))
2178e4b17023SJohn Marino     return type;
2179e4b17023SJohn Marino 
2180e4b17023SJohn Marino   return unsigned_type_for (type);
2181e4b17023SJohn Marino }
2182e4b17023SJohn Marino 
2183e4b17023SJohn Marino /* Records invariants in *EXPR_P.  Callback for walk_tree.  DATA contains
2184e4b17023SJohn Marino    the bitmap to that we should store it.  */
2185e4b17023SJohn Marino 
2186e4b17023SJohn Marino static struct ivopts_data *fd_ivopts_data;
2187e4b17023SJohn Marino static tree
find_depends(tree * expr_p,int * ws ATTRIBUTE_UNUSED,void * data)2188e4b17023SJohn Marino find_depends (tree *expr_p, int *ws ATTRIBUTE_UNUSED, void *data)
2189e4b17023SJohn Marino {
2190e4b17023SJohn Marino   bitmap *depends_on = (bitmap *) data;
2191e4b17023SJohn Marino   struct version_info *info;
2192e4b17023SJohn Marino 
2193e4b17023SJohn Marino   if (TREE_CODE (*expr_p) != SSA_NAME)
2194e4b17023SJohn Marino     return NULL_TREE;
2195e4b17023SJohn Marino   info = name_info (fd_ivopts_data, *expr_p);
2196e4b17023SJohn Marino 
2197e4b17023SJohn Marino   if (!info->inv_id || info->has_nonlin_use)
2198e4b17023SJohn Marino     return NULL_TREE;
2199e4b17023SJohn Marino 
2200e4b17023SJohn Marino   if (!*depends_on)
2201e4b17023SJohn Marino     *depends_on = BITMAP_ALLOC (NULL);
2202e4b17023SJohn Marino   bitmap_set_bit (*depends_on, info->inv_id);
2203e4b17023SJohn Marino 
2204e4b17023SJohn Marino   return NULL_TREE;
2205e4b17023SJohn Marino }
2206e4b17023SJohn Marino 
2207e4b17023SJohn Marino /* Adds a candidate BASE + STEP * i.  Important field is set to IMPORTANT and
2208e4b17023SJohn Marino    position to POS.  If USE is not NULL, the candidate is set as related to
2209e4b17023SJohn Marino    it.  If both BASE and STEP are NULL, we add a pseudocandidate for the
2210e4b17023SJohn Marino    replacement of the final value of the iv by a direct computation.  */
2211e4b17023SJohn Marino 
2212e4b17023SJohn Marino static struct iv_cand *
add_candidate_1(struct ivopts_data * data,tree base,tree step,bool important,enum iv_position pos,struct iv_use * use,gimple incremented_at)2213e4b17023SJohn Marino add_candidate_1 (struct ivopts_data *data,
2214e4b17023SJohn Marino 		 tree base, tree step, bool important, enum iv_position pos,
2215e4b17023SJohn Marino 		 struct iv_use *use, gimple incremented_at)
2216e4b17023SJohn Marino {
2217e4b17023SJohn Marino   unsigned i;
2218e4b17023SJohn Marino   struct iv_cand *cand = NULL;
2219e4b17023SJohn Marino   tree type, orig_type;
2220e4b17023SJohn Marino 
2221e4b17023SJohn Marino   /* For non-original variables, make sure their values are computed in a type
2222e4b17023SJohn Marino      that does not invoke undefined behavior on overflows (since in general,
2223e4b17023SJohn Marino      we cannot prove that these induction variables are non-wrapping).  */
2224e4b17023SJohn Marino   if (pos != IP_ORIGINAL)
2225e4b17023SJohn Marino     {
2226e4b17023SJohn Marino       orig_type = TREE_TYPE (base);
2227e4b17023SJohn Marino       type = generic_type_for (orig_type);
2228e4b17023SJohn Marino       if (type != orig_type)
2229e4b17023SJohn Marino 	{
2230e4b17023SJohn Marino 	  base = fold_convert (type, base);
2231e4b17023SJohn Marino 	  step = fold_convert (type, step);
2232e4b17023SJohn Marino 	}
2233e4b17023SJohn Marino     }
2234e4b17023SJohn Marino 
2235e4b17023SJohn Marino   for (i = 0; i < n_iv_cands (data); i++)
2236e4b17023SJohn Marino     {
2237e4b17023SJohn Marino       cand = iv_cand (data, i);
2238e4b17023SJohn Marino 
2239e4b17023SJohn Marino       if (cand->pos != pos)
2240e4b17023SJohn Marino 	continue;
2241e4b17023SJohn Marino 
2242e4b17023SJohn Marino       if (cand->incremented_at != incremented_at
2243e4b17023SJohn Marino 	  || ((pos == IP_AFTER_USE || pos == IP_BEFORE_USE)
2244e4b17023SJohn Marino 	      && cand->ainc_use != use))
2245e4b17023SJohn Marino 	continue;
2246e4b17023SJohn Marino 
2247e4b17023SJohn Marino       if (!cand->iv)
2248e4b17023SJohn Marino 	{
2249e4b17023SJohn Marino 	  if (!base && !step)
2250e4b17023SJohn Marino 	    break;
2251e4b17023SJohn Marino 
2252e4b17023SJohn Marino 	  continue;
2253e4b17023SJohn Marino 	}
2254e4b17023SJohn Marino 
2255e4b17023SJohn Marino       if (!base && !step)
2256e4b17023SJohn Marino 	continue;
2257e4b17023SJohn Marino 
2258e4b17023SJohn Marino       if (operand_equal_p (base, cand->iv->base, 0)
2259e4b17023SJohn Marino 	  && operand_equal_p (step, cand->iv->step, 0)
2260e4b17023SJohn Marino           && (TYPE_PRECISION (TREE_TYPE (base))
2261e4b17023SJohn Marino               == TYPE_PRECISION (TREE_TYPE (cand->iv->base))))
2262e4b17023SJohn Marino 	break;
2263e4b17023SJohn Marino     }
2264e4b17023SJohn Marino 
2265e4b17023SJohn Marino   if (i == n_iv_cands (data))
2266e4b17023SJohn Marino     {
2267e4b17023SJohn Marino       cand = XCNEW (struct iv_cand);
2268e4b17023SJohn Marino       cand->id = i;
2269e4b17023SJohn Marino 
2270e4b17023SJohn Marino       if (!base && !step)
2271e4b17023SJohn Marino 	cand->iv = NULL;
2272e4b17023SJohn Marino       else
2273e4b17023SJohn Marino 	cand->iv = alloc_iv (base, step);
2274e4b17023SJohn Marino 
2275e4b17023SJohn Marino       cand->pos = pos;
2276e4b17023SJohn Marino       if (pos != IP_ORIGINAL && cand->iv)
2277e4b17023SJohn Marino 	{
2278e4b17023SJohn Marino 	  cand->var_before = create_tmp_var_raw (TREE_TYPE (base), "ivtmp");
2279e4b17023SJohn Marino 	  cand->var_after = cand->var_before;
2280e4b17023SJohn Marino 	}
2281e4b17023SJohn Marino       cand->important = important;
2282e4b17023SJohn Marino       cand->incremented_at = incremented_at;
2283e4b17023SJohn Marino       VEC_safe_push (iv_cand_p, heap, data->iv_candidates, cand);
2284e4b17023SJohn Marino 
2285e4b17023SJohn Marino       if (step
2286e4b17023SJohn Marino 	  && TREE_CODE (step) != INTEGER_CST)
2287e4b17023SJohn Marino 	{
2288e4b17023SJohn Marino 	  fd_ivopts_data = data;
2289e4b17023SJohn Marino 	  walk_tree (&step, find_depends, &cand->depends_on, NULL);
2290e4b17023SJohn Marino 	}
2291e4b17023SJohn Marino 
2292e4b17023SJohn Marino       if (pos == IP_AFTER_USE || pos == IP_BEFORE_USE)
2293e4b17023SJohn Marino 	cand->ainc_use = use;
2294e4b17023SJohn Marino       else
2295e4b17023SJohn Marino 	cand->ainc_use = NULL;
2296e4b17023SJohn Marino 
2297e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
2298e4b17023SJohn Marino 	dump_cand (dump_file, cand);
2299e4b17023SJohn Marino     }
2300e4b17023SJohn Marino 
2301e4b17023SJohn Marino   if (important && !cand->important)
2302e4b17023SJohn Marino     {
2303e4b17023SJohn Marino       cand->important = true;
2304e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
2305e4b17023SJohn Marino 	fprintf (dump_file, "Candidate %d is important\n", cand->id);
2306e4b17023SJohn Marino     }
2307e4b17023SJohn Marino 
2308e4b17023SJohn Marino   if (use)
2309e4b17023SJohn Marino     {
2310e4b17023SJohn Marino       bitmap_set_bit (use->related_cands, i);
2311e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
2312e4b17023SJohn Marino 	fprintf (dump_file, "Candidate %d is related to use %d\n",
2313e4b17023SJohn Marino 		 cand->id, use->id);
2314e4b17023SJohn Marino     }
2315e4b17023SJohn Marino 
2316e4b17023SJohn Marino   return cand;
2317e4b17023SJohn Marino }
2318e4b17023SJohn Marino 
2319e4b17023SJohn Marino /* Returns true if incrementing the induction variable at the end of the LOOP
2320e4b17023SJohn Marino    is allowed.
2321e4b17023SJohn Marino 
2322e4b17023SJohn Marino    The purpose is to avoid splitting latch edge with a biv increment, thus
2323e4b17023SJohn Marino    creating a jump, possibly confusing other optimization passes and leaving
2324e4b17023SJohn Marino    less freedom to scheduler.  So we allow IP_END_POS only if IP_NORMAL_POS
2325e4b17023SJohn Marino    is not available (so we do not have a better alternative), or if the latch
2326e4b17023SJohn Marino    edge is already nonempty.  */
2327e4b17023SJohn Marino 
2328e4b17023SJohn Marino static bool
allow_ip_end_pos_p(struct loop * loop)2329e4b17023SJohn Marino allow_ip_end_pos_p (struct loop *loop)
2330e4b17023SJohn Marino {
2331e4b17023SJohn Marino   if (!ip_normal_pos (loop))
2332e4b17023SJohn Marino     return true;
2333e4b17023SJohn Marino 
2334e4b17023SJohn Marino   if (!empty_block_p (ip_end_pos (loop)))
2335e4b17023SJohn Marino     return true;
2336e4b17023SJohn Marino 
2337e4b17023SJohn Marino   return false;
2338e4b17023SJohn Marino }
2339e4b17023SJohn Marino 
2340e4b17023SJohn Marino /* If possible, adds autoincrement candidates BASE + STEP * i based on use USE.
2341e4b17023SJohn Marino    Important field is set to IMPORTANT.  */
2342e4b17023SJohn Marino 
2343e4b17023SJohn Marino static void
add_autoinc_candidates(struct ivopts_data * data,tree base,tree step,bool important,struct iv_use * use)2344e4b17023SJohn Marino add_autoinc_candidates (struct ivopts_data *data, tree base, tree step,
2345e4b17023SJohn Marino 			bool important, struct iv_use *use)
2346e4b17023SJohn Marino {
2347e4b17023SJohn Marino   basic_block use_bb = gimple_bb (use->stmt);
2348e4b17023SJohn Marino   enum machine_mode mem_mode;
2349e4b17023SJohn Marino   unsigned HOST_WIDE_INT cstepi;
2350e4b17023SJohn Marino 
2351e4b17023SJohn Marino   /* If we insert the increment in any position other than the standard
2352e4b17023SJohn Marino      ones, we must ensure that it is incremented once per iteration.
2353e4b17023SJohn Marino      It must not be in an inner nested loop, or one side of an if
2354e4b17023SJohn Marino      statement.  */
2355e4b17023SJohn Marino   if (use_bb->loop_father != data->current_loop
2356e4b17023SJohn Marino       || !dominated_by_p (CDI_DOMINATORS, data->current_loop->latch, use_bb)
2357e4b17023SJohn Marino       || stmt_could_throw_p (use->stmt)
2358e4b17023SJohn Marino       || !cst_and_fits_in_hwi (step))
2359e4b17023SJohn Marino     return;
2360e4b17023SJohn Marino 
2361e4b17023SJohn Marino   cstepi = int_cst_value (step);
2362e4b17023SJohn Marino 
2363e4b17023SJohn Marino   mem_mode = TYPE_MODE (TREE_TYPE (*use->op_p));
2364e4b17023SJohn Marino   if ((HAVE_PRE_INCREMENT && GET_MODE_SIZE (mem_mode) == cstepi)
2365e4b17023SJohn Marino       || (HAVE_PRE_DECREMENT && GET_MODE_SIZE (mem_mode) == -cstepi))
2366e4b17023SJohn Marino     {
2367e4b17023SJohn Marino       enum tree_code code = MINUS_EXPR;
2368e4b17023SJohn Marino       tree new_base;
2369e4b17023SJohn Marino       tree new_step = step;
2370e4b17023SJohn Marino 
2371e4b17023SJohn Marino       if (POINTER_TYPE_P (TREE_TYPE (base)))
2372e4b17023SJohn Marino 	{
2373e4b17023SJohn Marino 	  new_step = fold_build1 (NEGATE_EXPR, TREE_TYPE (step), step);
2374e4b17023SJohn Marino 	  code = POINTER_PLUS_EXPR;
2375e4b17023SJohn Marino 	}
2376e4b17023SJohn Marino       else
2377e4b17023SJohn Marino 	new_step = fold_convert (TREE_TYPE (base), new_step);
2378e4b17023SJohn Marino       new_base = fold_build2 (code, TREE_TYPE (base), base, new_step);
2379e4b17023SJohn Marino       add_candidate_1 (data, new_base, step, important, IP_BEFORE_USE, use,
2380e4b17023SJohn Marino 		       use->stmt);
2381e4b17023SJohn Marino     }
2382e4b17023SJohn Marino   if ((HAVE_POST_INCREMENT && GET_MODE_SIZE (mem_mode) == cstepi)
2383e4b17023SJohn Marino       || (HAVE_POST_DECREMENT && GET_MODE_SIZE (mem_mode) == -cstepi))
2384e4b17023SJohn Marino     {
2385e4b17023SJohn Marino       add_candidate_1 (data, base, step, important, IP_AFTER_USE, use,
2386e4b17023SJohn Marino 		       use->stmt);
2387e4b17023SJohn Marino     }
2388e4b17023SJohn Marino }
2389e4b17023SJohn Marino 
2390e4b17023SJohn Marino /* Adds a candidate BASE + STEP * i.  Important field is set to IMPORTANT and
2391e4b17023SJohn Marino    position to POS.  If USE is not NULL, the candidate is set as related to
2392e4b17023SJohn Marino    it.  The candidate computation is scheduled on all available positions.  */
2393e4b17023SJohn Marino 
2394e4b17023SJohn Marino static void
add_candidate(struct ivopts_data * data,tree base,tree step,bool important,struct iv_use * use)2395e4b17023SJohn Marino add_candidate (struct ivopts_data *data,
2396e4b17023SJohn Marino 	       tree base, tree step, bool important, struct iv_use *use)
2397e4b17023SJohn Marino {
2398e4b17023SJohn Marino   if (ip_normal_pos (data->current_loop))
2399e4b17023SJohn Marino     add_candidate_1 (data, base, step, important, IP_NORMAL, use, NULL);
2400e4b17023SJohn Marino   if (ip_end_pos (data->current_loop)
2401e4b17023SJohn Marino       && allow_ip_end_pos_p (data->current_loop))
2402e4b17023SJohn Marino     add_candidate_1 (data, base, step, important, IP_END, use, NULL);
2403e4b17023SJohn Marino 
2404e4b17023SJohn Marino   if (use != NULL && use->type == USE_ADDRESS)
2405e4b17023SJohn Marino     add_autoinc_candidates (data, base, step, important, use);
2406e4b17023SJohn Marino }
2407e4b17023SJohn Marino 
2408e4b17023SJohn Marino /* Add a standard "0 + 1 * iteration" iv candidate for a
2409e4b17023SJohn Marino    type with SIZE bits.  */
2410e4b17023SJohn Marino 
2411e4b17023SJohn Marino static void
add_standard_iv_candidates_for_size(struct ivopts_data * data,unsigned int size)2412e4b17023SJohn Marino add_standard_iv_candidates_for_size (struct ivopts_data *data,
2413e4b17023SJohn Marino 				     unsigned int size)
2414e4b17023SJohn Marino {
2415e4b17023SJohn Marino   tree type = lang_hooks.types.type_for_size (size, true);
2416e4b17023SJohn Marino   add_candidate (data, build_int_cst (type, 0), build_int_cst (type, 1),
2417e4b17023SJohn Marino 		 true, NULL);
2418e4b17023SJohn Marino }
2419e4b17023SJohn Marino 
2420e4b17023SJohn Marino /* Adds standard iv candidates.  */
2421e4b17023SJohn Marino 
2422e4b17023SJohn Marino static void
add_standard_iv_candidates(struct ivopts_data * data)2423e4b17023SJohn Marino add_standard_iv_candidates (struct ivopts_data *data)
2424e4b17023SJohn Marino {
2425e4b17023SJohn Marino   add_standard_iv_candidates_for_size (data, INT_TYPE_SIZE);
2426e4b17023SJohn Marino 
2427e4b17023SJohn Marino   /* The same for a double-integer type if it is still fast enough.  */
2428e4b17023SJohn Marino   if (BITS_PER_WORD >= INT_TYPE_SIZE * 2)
2429e4b17023SJohn Marino     add_standard_iv_candidates_for_size (data, INT_TYPE_SIZE * 2);
2430e4b17023SJohn Marino }
2431e4b17023SJohn Marino 
2432e4b17023SJohn Marino 
2433e4b17023SJohn Marino /* Adds candidates bases on the old induction variable IV.  */
2434e4b17023SJohn Marino 
2435e4b17023SJohn Marino static void
add_old_iv_candidates(struct ivopts_data * data,struct iv * iv)2436e4b17023SJohn Marino add_old_iv_candidates (struct ivopts_data *data, struct iv *iv)
2437e4b17023SJohn Marino {
2438e4b17023SJohn Marino   gimple phi;
2439e4b17023SJohn Marino   tree def;
2440e4b17023SJohn Marino   struct iv_cand *cand;
2441e4b17023SJohn Marino 
2442e4b17023SJohn Marino   add_candidate (data, iv->base, iv->step, true, NULL);
2443e4b17023SJohn Marino 
2444e4b17023SJohn Marino   /* The same, but with initial value zero.  */
2445e4b17023SJohn Marino   if (POINTER_TYPE_P (TREE_TYPE (iv->base)))
2446e4b17023SJohn Marino     add_candidate (data, size_int (0), iv->step, true, NULL);
2447e4b17023SJohn Marino   else
2448e4b17023SJohn Marino     add_candidate (data, build_int_cst (TREE_TYPE (iv->base), 0),
2449e4b17023SJohn Marino 		   iv->step, true, NULL);
2450e4b17023SJohn Marino 
2451e4b17023SJohn Marino   phi = SSA_NAME_DEF_STMT (iv->ssa_name);
2452e4b17023SJohn Marino   if (gimple_code (phi) == GIMPLE_PHI)
2453e4b17023SJohn Marino     {
2454e4b17023SJohn Marino       /* Additionally record the possibility of leaving the original iv
2455e4b17023SJohn Marino 	 untouched.  */
2456e4b17023SJohn Marino       def = PHI_ARG_DEF_FROM_EDGE (phi, loop_latch_edge (data->current_loop));
2457e4b17023SJohn Marino       cand = add_candidate_1 (data,
2458e4b17023SJohn Marino 			      iv->base, iv->step, true, IP_ORIGINAL, NULL,
2459e4b17023SJohn Marino 			      SSA_NAME_DEF_STMT (def));
2460e4b17023SJohn Marino       cand->var_before = iv->ssa_name;
2461e4b17023SJohn Marino       cand->var_after = def;
2462e4b17023SJohn Marino     }
2463e4b17023SJohn Marino }
2464e4b17023SJohn Marino 
2465e4b17023SJohn Marino /* Adds candidates based on the old induction variables.  */
2466e4b17023SJohn Marino 
2467e4b17023SJohn Marino static void
add_old_ivs_candidates(struct ivopts_data * data)2468e4b17023SJohn Marino add_old_ivs_candidates (struct ivopts_data *data)
2469e4b17023SJohn Marino {
2470e4b17023SJohn Marino   unsigned i;
2471e4b17023SJohn Marino   struct iv *iv;
2472e4b17023SJohn Marino   bitmap_iterator bi;
2473e4b17023SJohn Marino 
2474e4b17023SJohn Marino   EXECUTE_IF_SET_IN_BITMAP (data->relevant, 0, i, bi)
2475e4b17023SJohn Marino     {
2476e4b17023SJohn Marino       iv = ver_info (data, i)->iv;
2477e4b17023SJohn Marino       if (iv && iv->biv_p && !integer_zerop (iv->step))
2478e4b17023SJohn Marino 	add_old_iv_candidates (data, iv);
2479e4b17023SJohn Marino     }
2480e4b17023SJohn Marino }
2481e4b17023SJohn Marino 
2482e4b17023SJohn Marino /* Adds candidates based on the value of the induction variable IV and USE.  */
2483e4b17023SJohn Marino 
2484e4b17023SJohn Marino static void
add_iv_value_candidates(struct ivopts_data * data,struct iv * iv,struct iv_use * use)2485e4b17023SJohn Marino add_iv_value_candidates (struct ivopts_data *data,
2486e4b17023SJohn Marino 			 struct iv *iv, struct iv_use *use)
2487e4b17023SJohn Marino {
2488e4b17023SJohn Marino   unsigned HOST_WIDE_INT offset;
2489e4b17023SJohn Marino   tree base;
2490e4b17023SJohn Marino   tree basetype;
2491e4b17023SJohn Marino 
2492e4b17023SJohn Marino   add_candidate (data, iv->base, iv->step, false, use);
2493e4b17023SJohn Marino 
2494e4b17023SJohn Marino   /* The same, but with initial value zero.  Make such variable important,
2495e4b17023SJohn Marino      since it is generic enough so that possibly many uses may be based
2496e4b17023SJohn Marino      on it.  */
2497e4b17023SJohn Marino   basetype = TREE_TYPE (iv->base);
2498e4b17023SJohn Marino   if (POINTER_TYPE_P (basetype))
2499e4b17023SJohn Marino     basetype = sizetype;
2500e4b17023SJohn Marino   add_candidate (data, build_int_cst (basetype, 0),
2501e4b17023SJohn Marino 		 iv->step, true, use);
2502e4b17023SJohn Marino 
2503e4b17023SJohn Marino   /* Third, try removing the constant offset.  Make sure to even
2504e4b17023SJohn Marino      add a candidate for &a[0] vs. (T *)&a.  */
2505e4b17023SJohn Marino   base = strip_offset (iv->base, &offset);
2506e4b17023SJohn Marino   if (offset
2507e4b17023SJohn Marino       || base != iv->base)
2508e4b17023SJohn Marino     add_candidate (data, base, iv->step, false, use);
2509e4b17023SJohn Marino }
2510e4b17023SJohn Marino 
2511e4b17023SJohn Marino /* Adds candidates based on the uses.  */
2512e4b17023SJohn Marino 
2513e4b17023SJohn Marino static void
add_derived_ivs_candidates(struct ivopts_data * data)2514e4b17023SJohn Marino add_derived_ivs_candidates (struct ivopts_data *data)
2515e4b17023SJohn Marino {
2516e4b17023SJohn Marino   unsigned i;
2517e4b17023SJohn Marino 
2518e4b17023SJohn Marino   for (i = 0; i < n_iv_uses (data); i++)
2519e4b17023SJohn Marino     {
2520e4b17023SJohn Marino       struct iv_use *use = iv_use (data, i);
2521e4b17023SJohn Marino 
2522e4b17023SJohn Marino       if (!use)
2523e4b17023SJohn Marino 	continue;
2524e4b17023SJohn Marino 
2525e4b17023SJohn Marino       switch (use->type)
2526e4b17023SJohn Marino 	{
2527e4b17023SJohn Marino 	case USE_NONLINEAR_EXPR:
2528e4b17023SJohn Marino 	case USE_COMPARE:
2529e4b17023SJohn Marino 	case USE_ADDRESS:
2530e4b17023SJohn Marino 	  /* Just add the ivs based on the value of the iv used here.  */
2531e4b17023SJohn Marino 	  add_iv_value_candidates (data, use->iv, use);
2532e4b17023SJohn Marino 	  break;
2533e4b17023SJohn Marino 
2534e4b17023SJohn Marino 	default:
2535e4b17023SJohn Marino 	  gcc_unreachable ();
2536e4b17023SJohn Marino 	}
2537e4b17023SJohn Marino     }
2538e4b17023SJohn Marino }
2539e4b17023SJohn Marino 
2540e4b17023SJohn Marino /* Record important candidates and add them to related_cands bitmaps
2541e4b17023SJohn Marino    if needed.  */
2542e4b17023SJohn Marino 
2543e4b17023SJohn Marino static void
record_important_candidates(struct ivopts_data * data)2544e4b17023SJohn Marino record_important_candidates (struct ivopts_data *data)
2545e4b17023SJohn Marino {
2546e4b17023SJohn Marino   unsigned i;
2547e4b17023SJohn Marino   struct iv_use *use;
2548e4b17023SJohn Marino 
2549e4b17023SJohn Marino   for (i = 0; i < n_iv_cands (data); i++)
2550e4b17023SJohn Marino     {
2551e4b17023SJohn Marino       struct iv_cand *cand = iv_cand (data, i);
2552e4b17023SJohn Marino 
2553e4b17023SJohn Marino       if (cand->important)
2554e4b17023SJohn Marino 	bitmap_set_bit (data->important_candidates, i);
2555e4b17023SJohn Marino     }
2556e4b17023SJohn Marino 
2557e4b17023SJohn Marino   data->consider_all_candidates = (n_iv_cands (data)
2558e4b17023SJohn Marino 				   <= CONSIDER_ALL_CANDIDATES_BOUND);
2559e4b17023SJohn Marino 
2560e4b17023SJohn Marino   if (data->consider_all_candidates)
2561e4b17023SJohn Marino     {
2562e4b17023SJohn Marino       /* We will not need "related_cands" bitmaps in this case,
2563e4b17023SJohn Marino 	 so release them to decrease peak memory consumption.  */
2564e4b17023SJohn Marino       for (i = 0; i < n_iv_uses (data); i++)
2565e4b17023SJohn Marino 	{
2566e4b17023SJohn Marino 	  use = iv_use (data, i);
2567e4b17023SJohn Marino 	  BITMAP_FREE (use->related_cands);
2568e4b17023SJohn Marino 	}
2569e4b17023SJohn Marino     }
2570e4b17023SJohn Marino   else
2571e4b17023SJohn Marino     {
2572e4b17023SJohn Marino       /* Add important candidates to the related_cands bitmaps.  */
2573e4b17023SJohn Marino       for (i = 0; i < n_iv_uses (data); i++)
2574e4b17023SJohn Marino 	bitmap_ior_into (iv_use (data, i)->related_cands,
2575e4b17023SJohn Marino 			 data->important_candidates);
2576e4b17023SJohn Marino     }
2577e4b17023SJohn Marino }
2578e4b17023SJohn Marino 
2579e4b17023SJohn Marino /* Allocates the data structure mapping the (use, candidate) pairs to costs.
2580e4b17023SJohn Marino    If consider_all_candidates is true, we use a two-dimensional array, otherwise
2581e4b17023SJohn Marino    we allocate a simple list to every use.  */
2582e4b17023SJohn Marino 
2583e4b17023SJohn Marino static void
alloc_use_cost_map(struct ivopts_data * data)2584e4b17023SJohn Marino alloc_use_cost_map (struct ivopts_data *data)
2585e4b17023SJohn Marino {
2586e4b17023SJohn Marino   unsigned i, size, s, j;
2587e4b17023SJohn Marino 
2588e4b17023SJohn Marino   for (i = 0; i < n_iv_uses (data); i++)
2589e4b17023SJohn Marino     {
2590e4b17023SJohn Marino       struct iv_use *use = iv_use (data, i);
2591e4b17023SJohn Marino       bitmap_iterator bi;
2592e4b17023SJohn Marino 
2593e4b17023SJohn Marino       if (data->consider_all_candidates)
2594e4b17023SJohn Marino 	size = n_iv_cands (data);
2595e4b17023SJohn Marino       else
2596e4b17023SJohn Marino 	{
2597e4b17023SJohn Marino 	  s = 0;
2598e4b17023SJohn Marino 	  EXECUTE_IF_SET_IN_BITMAP (use->related_cands, 0, j, bi)
2599e4b17023SJohn Marino 	    {
2600e4b17023SJohn Marino 	      s++;
2601e4b17023SJohn Marino 	    }
2602e4b17023SJohn Marino 
2603e4b17023SJohn Marino 	  /* Round up to the power of two, so that moduling by it is fast.  */
2604e4b17023SJohn Marino 	  for (size = 1; size < s; size <<= 1)
2605e4b17023SJohn Marino 	    continue;
2606e4b17023SJohn Marino 	}
2607e4b17023SJohn Marino 
2608e4b17023SJohn Marino       use->n_map_members = size;
2609e4b17023SJohn Marino       use->cost_map = XCNEWVEC (struct cost_pair, size);
2610e4b17023SJohn Marino     }
2611e4b17023SJohn Marino }
2612e4b17023SJohn Marino 
2613e4b17023SJohn Marino /* Returns description of computation cost of expression whose runtime
2614e4b17023SJohn Marino    cost is RUNTIME and complexity corresponds to COMPLEXITY.  */
2615e4b17023SJohn Marino 
2616e4b17023SJohn Marino static comp_cost
new_cost(unsigned runtime,unsigned complexity)2617e4b17023SJohn Marino new_cost (unsigned runtime, unsigned complexity)
2618e4b17023SJohn Marino {
2619e4b17023SJohn Marino   comp_cost cost;
2620e4b17023SJohn Marino 
2621e4b17023SJohn Marino   cost.cost = runtime;
2622e4b17023SJohn Marino   cost.complexity = complexity;
2623e4b17023SJohn Marino 
2624e4b17023SJohn Marino   return cost;
2625e4b17023SJohn Marino }
2626e4b17023SJohn Marino 
2627e4b17023SJohn Marino /* Adds costs COST1 and COST2.  */
2628e4b17023SJohn Marino 
2629e4b17023SJohn Marino static comp_cost
add_costs(comp_cost cost1,comp_cost cost2)2630e4b17023SJohn Marino add_costs (comp_cost cost1, comp_cost cost2)
2631e4b17023SJohn Marino {
2632e4b17023SJohn Marino   cost1.cost += cost2.cost;
2633e4b17023SJohn Marino   cost1.complexity += cost2.complexity;
2634e4b17023SJohn Marino 
2635e4b17023SJohn Marino   return cost1;
2636e4b17023SJohn Marino }
2637e4b17023SJohn Marino /* Subtracts costs COST1 and COST2.  */
2638e4b17023SJohn Marino 
2639e4b17023SJohn Marino static comp_cost
sub_costs(comp_cost cost1,comp_cost cost2)2640e4b17023SJohn Marino sub_costs (comp_cost cost1, comp_cost cost2)
2641e4b17023SJohn Marino {
2642e4b17023SJohn Marino   cost1.cost -= cost2.cost;
2643e4b17023SJohn Marino   cost1.complexity -= cost2.complexity;
2644e4b17023SJohn Marino 
2645e4b17023SJohn Marino   return cost1;
2646e4b17023SJohn Marino }
2647e4b17023SJohn Marino 
2648e4b17023SJohn Marino /* Returns a negative number if COST1 < COST2, a positive number if
2649e4b17023SJohn Marino    COST1 > COST2, and 0 if COST1 = COST2.  */
2650e4b17023SJohn Marino 
2651e4b17023SJohn Marino static int
compare_costs(comp_cost cost1,comp_cost cost2)2652e4b17023SJohn Marino compare_costs (comp_cost cost1, comp_cost cost2)
2653e4b17023SJohn Marino {
2654e4b17023SJohn Marino   if (cost1.cost == cost2.cost)
2655e4b17023SJohn Marino     return cost1.complexity - cost2.complexity;
2656e4b17023SJohn Marino 
2657e4b17023SJohn Marino   return cost1.cost - cost2.cost;
2658e4b17023SJohn Marino }
2659e4b17023SJohn Marino 
2660e4b17023SJohn Marino /* Returns true if COST is infinite.  */
2661e4b17023SJohn Marino 
2662e4b17023SJohn Marino static bool
infinite_cost_p(comp_cost cost)2663e4b17023SJohn Marino infinite_cost_p (comp_cost cost)
2664e4b17023SJohn Marino {
2665e4b17023SJohn Marino   return cost.cost == INFTY;
2666e4b17023SJohn Marino }
2667e4b17023SJohn Marino 
2668e4b17023SJohn Marino /* Sets cost of (USE, CANDIDATE) pair to COST and record that it depends
2669e4b17023SJohn Marino    on invariants DEPENDS_ON and that the value used in expressing it
2670e4b17023SJohn Marino    is VALUE, and in case of iv elimination the comparison operator is COMP.  */
2671e4b17023SJohn Marino 
2672e4b17023SJohn Marino static void
set_use_iv_cost(struct ivopts_data * data,struct iv_use * use,struct iv_cand * cand,comp_cost cost,bitmap depends_on,tree value,enum tree_code comp,int inv_expr_id)2673e4b17023SJohn Marino set_use_iv_cost (struct ivopts_data *data,
2674e4b17023SJohn Marino 		 struct iv_use *use, struct iv_cand *cand,
2675e4b17023SJohn Marino 		 comp_cost cost, bitmap depends_on, tree value,
2676e4b17023SJohn Marino 		 enum tree_code comp, int inv_expr_id)
2677e4b17023SJohn Marino {
2678e4b17023SJohn Marino   unsigned i, s;
2679e4b17023SJohn Marino 
2680e4b17023SJohn Marino   if (infinite_cost_p (cost))
2681e4b17023SJohn Marino     {
2682e4b17023SJohn Marino       BITMAP_FREE (depends_on);
2683e4b17023SJohn Marino       return;
2684e4b17023SJohn Marino     }
2685e4b17023SJohn Marino 
2686e4b17023SJohn Marino   if (data->consider_all_candidates)
2687e4b17023SJohn Marino     {
2688e4b17023SJohn Marino       use->cost_map[cand->id].cand = cand;
2689e4b17023SJohn Marino       use->cost_map[cand->id].cost = cost;
2690e4b17023SJohn Marino       use->cost_map[cand->id].depends_on = depends_on;
2691e4b17023SJohn Marino       use->cost_map[cand->id].value = value;
2692e4b17023SJohn Marino       use->cost_map[cand->id].comp = comp;
2693e4b17023SJohn Marino       use->cost_map[cand->id].inv_expr_id = inv_expr_id;
2694e4b17023SJohn Marino       return;
2695e4b17023SJohn Marino     }
2696e4b17023SJohn Marino 
2697e4b17023SJohn Marino   /* n_map_members is a power of two, so this computes modulo.  */
2698e4b17023SJohn Marino   s = cand->id & (use->n_map_members - 1);
2699e4b17023SJohn Marino   for (i = s; i < use->n_map_members; i++)
2700e4b17023SJohn Marino     if (!use->cost_map[i].cand)
2701e4b17023SJohn Marino       goto found;
2702e4b17023SJohn Marino   for (i = 0; i < s; i++)
2703e4b17023SJohn Marino     if (!use->cost_map[i].cand)
2704e4b17023SJohn Marino       goto found;
2705e4b17023SJohn Marino 
2706e4b17023SJohn Marino   gcc_unreachable ();
2707e4b17023SJohn Marino 
2708e4b17023SJohn Marino found:
2709e4b17023SJohn Marino   use->cost_map[i].cand = cand;
2710e4b17023SJohn Marino   use->cost_map[i].cost = cost;
2711e4b17023SJohn Marino   use->cost_map[i].depends_on = depends_on;
2712e4b17023SJohn Marino   use->cost_map[i].value = value;
2713e4b17023SJohn Marino   use->cost_map[i].comp = comp;
2714e4b17023SJohn Marino   use->cost_map[i].inv_expr_id = inv_expr_id;
2715e4b17023SJohn Marino }
2716e4b17023SJohn Marino 
2717e4b17023SJohn Marino /* Gets cost of (USE, CANDIDATE) pair.  */
2718e4b17023SJohn Marino 
2719e4b17023SJohn Marino static struct cost_pair *
get_use_iv_cost(struct ivopts_data * data,struct iv_use * use,struct iv_cand * cand)2720e4b17023SJohn Marino get_use_iv_cost (struct ivopts_data *data, struct iv_use *use,
2721e4b17023SJohn Marino 		 struct iv_cand *cand)
2722e4b17023SJohn Marino {
2723e4b17023SJohn Marino   unsigned i, s;
2724e4b17023SJohn Marino   struct cost_pair *ret;
2725e4b17023SJohn Marino 
2726e4b17023SJohn Marino   if (!cand)
2727e4b17023SJohn Marino     return NULL;
2728e4b17023SJohn Marino 
2729e4b17023SJohn Marino   if (data->consider_all_candidates)
2730e4b17023SJohn Marino     {
2731e4b17023SJohn Marino       ret = use->cost_map + cand->id;
2732e4b17023SJohn Marino       if (!ret->cand)
2733e4b17023SJohn Marino 	return NULL;
2734e4b17023SJohn Marino 
2735e4b17023SJohn Marino       return ret;
2736e4b17023SJohn Marino     }
2737e4b17023SJohn Marino 
2738e4b17023SJohn Marino   /* n_map_members is a power of two, so this computes modulo.  */
2739e4b17023SJohn Marino   s = cand->id & (use->n_map_members - 1);
2740e4b17023SJohn Marino   for (i = s; i < use->n_map_members; i++)
2741e4b17023SJohn Marino     if (use->cost_map[i].cand == cand)
2742e4b17023SJohn Marino       return use->cost_map + i;
2743e4b17023SJohn Marino 
2744e4b17023SJohn Marino   for (i = 0; i < s; i++)
2745e4b17023SJohn Marino     if (use->cost_map[i].cand == cand)
2746e4b17023SJohn Marino       return use->cost_map + i;
2747e4b17023SJohn Marino 
2748e4b17023SJohn Marino   return NULL;
2749e4b17023SJohn Marino }
2750e4b17023SJohn Marino 
2751e4b17023SJohn Marino /* Returns estimate on cost of computing SEQ.  */
2752e4b17023SJohn Marino 
2753e4b17023SJohn Marino static unsigned
seq_cost(rtx seq,bool speed)2754e4b17023SJohn Marino seq_cost (rtx seq, bool speed)
2755e4b17023SJohn Marino {
2756e4b17023SJohn Marino   unsigned cost = 0;
2757e4b17023SJohn Marino   rtx set;
2758e4b17023SJohn Marino 
2759e4b17023SJohn Marino   for (; seq; seq = NEXT_INSN (seq))
2760e4b17023SJohn Marino     {
2761e4b17023SJohn Marino       set = single_set (seq);
2762e4b17023SJohn Marino       if (set)
2763e4b17023SJohn Marino 	cost += set_src_cost (SET_SRC (set), speed);
2764e4b17023SJohn Marino       else
2765e4b17023SJohn Marino 	cost++;
2766e4b17023SJohn Marino     }
2767e4b17023SJohn Marino 
2768e4b17023SJohn Marino   return cost;
2769e4b17023SJohn Marino }
2770e4b17023SJohn Marino 
2771e4b17023SJohn Marino /* Produce DECL_RTL for object obj so it looks like it is stored in memory.  */
2772e4b17023SJohn Marino static rtx
produce_memory_decl_rtl(tree obj,int * regno)2773e4b17023SJohn Marino produce_memory_decl_rtl (tree obj, int *regno)
2774e4b17023SJohn Marino {
2775e4b17023SJohn Marino   addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (obj));
2776e4b17023SJohn Marino   enum machine_mode address_mode = targetm.addr_space.address_mode (as);
2777e4b17023SJohn Marino   rtx x;
2778e4b17023SJohn Marino 
2779e4b17023SJohn Marino   gcc_assert (obj);
2780e4b17023SJohn Marino   if (TREE_STATIC (obj) || DECL_EXTERNAL (obj))
2781e4b17023SJohn Marino     {
2782e4b17023SJohn Marino       const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (obj));
2783e4b17023SJohn Marino       x = gen_rtx_SYMBOL_REF (address_mode, name);
2784e4b17023SJohn Marino       SET_SYMBOL_REF_DECL (x, obj);
2785e4b17023SJohn Marino       x = gen_rtx_MEM (DECL_MODE (obj), x);
2786e4b17023SJohn Marino       set_mem_addr_space (x, as);
2787e4b17023SJohn Marino       targetm.encode_section_info (obj, x, true);
2788e4b17023SJohn Marino     }
2789e4b17023SJohn Marino   else
2790e4b17023SJohn Marino     {
2791e4b17023SJohn Marino       x = gen_raw_REG (address_mode, (*regno)++);
2792e4b17023SJohn Marino       x = gen_rtx_MEM (DECL_MODE (obj), x);
2793e4b17023SJohn Marino       set_mem_addr_space (x, as);
2794e4b17023SJohn Marino     }
2795e4b17023SJohn Marino 
2796e4b17023SJohn Marino   return x;
2797e4b17023SJohn Marino }
2798e4b17023SJohn Marino 
2799e4b17023SJohn Marino /* Prepares decl_rtl for variables referred in *EXPR_P.  Callback for
2800e4b17023SJohn Marino    walk_tree.  DATA contains the actual fake register number.  */
2801e4b17023SJohn Marino 
2802e4b17023SJohn Marino static tree
prepare_decl_rtl(tree * expr_p,int * ws,void * data)2803e4b17023SJohn Marino prepare_decl_rtl (tree *expr_p, int *ws, void *data)
2804e4b17023SJohn Marino {
2805e4b17023SJohn Marino   tree obj = NULL_TREE;
2806e4b17023SJohn Marino   rtx x = NULL_RTX;
2807e4b17023SJohn Marino   int *regno = (int *) data;
2808e4b17023SJohn Marino 
2809e4b17023SJohn Marino   switch (TREE_CODE (*expr_p))
2810e4b17023SJohn Marino     {
2811e4b17023SJohn Marino     case ADDR_EXPR:
2812e4b17023SJohn Marino       for (expr_p = &TREE_OPERAND (*expr_p, 0);
2813e4b17023SJohn Marino 	   handled_component_p (*expr_p);
2814e4b17023SJohn Marino 	   expr_p = &TREE_OPERAND (*expr_p, 0))
2815e4b17023SJohn Marino 	continue;
2816e4b17023SJohn Marino       obj = *expr_p;
2817e4b17023SJohn Marino       if (DECL_P (obj) && !DECL_RTL_SET_P (obj))
2818e4b17023SJohn Marino         x = produce_memory_decl_rtl (obj, regno);
2819e4b17023SJohn Marino       break;
2820e4b17023SJohn Marino 
2821e4b17023SJohn Marino     case SSA_NAME:
2822e4b17023SJohn Marino       *ws = 0;
2823e4b17023SJohn Marino       obj = SSA_NAME_VAR (*expr_p);
2824e4b17023SJohn Marino       if (!DECL_RTL_SET_P (obj))
2825e4b17023SJohn Marino 	x = gen_raw_REG (DECL_MODE (obj), (*regno)++);
2826e4b17023SJohn Marino       break;
2827e4b17023SJohn Marino 
2828e4b17023SJohn Marino     case VAR_DECL:
2829e4b17023SJohn Marino     case PARM_DECL:
2830e4b17023SJohn Marino     case RESULT_DECL:
2831e4b17023SJohn Marino       *ws = 0;
2832e4b17023SJohn Marino       obj = *expr_p;
2833e4b17023SJohn Marino 
2834e4b17023SJohn Marino       if (DECL_RTL_SET_P (obj))
2835e4b17023SJohn Marino 	break;
2836e4b17023SJohn Marino 
2837e4b17023SJohn Marino       if (DECL_MODE (obj) == BLKmode)
2838e4b17023SJohn Marino 	x = produce_memory_decl_rtl (obj, regno);
2839e4b17023SJohn Marino       else
2840e4b17023SJohn Marino 	x = gen_raw_REG (DECL_MODE (obj), (*regno)++);
2841e4b17023SJohn Marino 
2842e4b17023SJohn Marino       break;
2843e4b17023SJohn Marino 
2844e4b17023SJohn Marino     default:
2845e4b17023SJohn Marino       break;
2846e4b17023SJohn Marino     }
2847e4b17023SJohn Marino 
2848e4b17023SJohn Marino   if (x)
2849e4b17023SJohn Marino     {
2850e4b17023SJohn Marino       VEC_safe_push (tree, heap, decl_rtl_to_reset, obj);
2851e4b17023SJohn Marino       SET_DECL_RTL (obj, x);
2852e4b17023SJohn Marino     }
2853e4b17023SJohn Marino 
2854e4b17023SJohn Marino   return NULL_TREE;
2855e4b17023SJohn Marino }
2856e4b17023SJohn Marino 
2857e4b17023SJohn Marino /* Determines cost of the computation of EXPR.  */
2858e4b17023SJohn Marino 
2859e4b17023SJohn Marino static unsigned
computation_cost(tree expr,bool speed)2860e4b17023SJohn Marino computation_cost (tree expr, bool speed)
2861e4b17023SJohn Marino {
2862e4b17023SJohn Marino   rtx seq, rslt;
2863e4b17023SJohn Marino   tree type = TREE_TYPE (expr);
2864e4b17023SJohn Marino   unsigned cost;
2865e4b17023SJohn Marino   /* Avoid using hard regs in ways which may be unsupported.  */
2866e4b17023SJohn Marino   int regno = LAST_VIRTUAL_REGISTER + 1;
2867e4b17023SJohn Marino   struct cgraph_node *node = cgraph_get_node (current_function_decl);
2868e4b17023SJohn Marino   enum node_frequency real_frequency = node->frequency;
2869e4b17023SJohn Marino 
2870e4b17023SJohn Marino   node->frequency = NODE_FREQUENCY_NORMAL;
2871e4b17023SJohn Marino   crtl->maybe_hot_insn_p = speed;
2872e4b17023SJohn Marino   walk_tree (&expr, prepare_decl_rtl, &regno, NULL);
2873e4b17023SJohn Marino   start_sequence ();
2874e4b17023SJohn Marino   rslt = expand_expr (expr, NULL_RTX, TYPE_MODE (type), EXPAND_NORMAL);
2875e4b17023SJohn Marino   seq = get_insns ();
2876e4b17023SJohn Marino   end_sequence ();
2877e4b17023SJohn Marino   default_rtl_profile ();
2878e4b17023SJohn Marino   node->frequency = real_frequency;
2879e4b17023SJohn Marino 
2880e4b17023SJohn Marino   cost = seq_cost (seq, speed);
2881e4b17023SJohn Marino   if (MEM_P (rslt))
2882e4b17023SJohn Marino     cost += address_cost (XEXP (rslt, 0), TYPE_MODE (type),
2883e4b17023SJohn Marino 			  TYPE_ADDR_SPACE (type), speed);
2884e4b17023SJohn Marino   else if (!REG_P (rslt))
2885e4b17023SJohn Marino     cost += set_src_cost (rslt, speed);
2886e4b17023SJohn Marino 
2887e4b17023SJohn Marino   return cost;
2888e4b17023SJohn Marino }
2889e4b17023SJohn Marino 
2890e4b17023SJohn Marino /* Returns variable containing the value of candidate CAND at statement AT.  */
2891e4b17023SJohn Marino 
2892e4b17023SJohn Marino static tree
var_at_stmt(struct loop * loop,struct iv_cand * cand,gimple stmt)2893e4b17023SJohn Marino var_at_stmt (struct loop *loop, struct iv_cand *cand, gimple stmt)
2894e4b17023SJohn Marino {
2895e4b17023SJohn Marino   if (stmt_after_increment (loop, cand, stmt))
2896e4b17023SJohn Marino     return cand->var_after;
2897e4b17023SJohn Marino   else
2898e4b17023SJohn Marino     return cand->var_before;
2899e4b17023SJohn Marino }
2900e4b17023SJohn Marino 
2901e4b17023SJohn Marino /* If A is (TYPE) BA and B is (TYPE) BB, and the types of BA and BB have the
2902e4b17023SJohn Marino    same precision that is at least as wide as the precision of TYPE, stores
2903e4b17023SJohn Marino    BA to A and BB to B, and returns the type of BA.  Otherwise, returns the
2904e4b17023SJohn Marino    type of A and B.  */
2905e4b17023SJohn Marino 
2906e4b17023SJohn Marino static tree
determine_common_wider_type(tree * a,tree * b)2907e4b17023SJohn Marino determine_common_wider_type (tree *a, tree *b)
2908e4b17023SJohn Marino {
2909e4b17023SJohn Marino   tree wider_type = NULL;
2910e4b17023SJohn Marino   tree suba, subb;
2911e4b17023SJohn Marino   tree atype = TREE_TYPE (*a);
2912e4b17023SJohn Marino 
2913e4b17023SJohn Marino   if (CONVERT_EXPR_P (*a))
2914e4b17023SJohn Marino     {
2915e4b17023SJohn Marino       suba = TREE_OPERAND (*a, 0);
2916e4b17023SJohn Marino       wider_type = TREE_TYPE (suba);
2917e4b17023SJohn Marino       if (TYPE_PRECISION (wider_type) < TYPE_PRECISION (atype))
2918e4b17023SJohn Marino 	return atype;
2919e4b17023SJohn Marino     }
2920e4b17023SJohn Marino   else
2921e4b17023SJohn Marino     return atype;
2922e4b17023SJohn Marino 
2923e4b17023SJohn Marino   if (CONVERT_EXPR_P (*b))
2924e4b17023SJohn Marino     {
2925e4b17023SJohn Marino       subb = TREE_OPERAND (*b, 0);
2926e4b17023SJohn Marino       if (TYPE_PRECISION (wider_type) != TYPE_PRECISION (TREE_TYPE (subb)))
2927e4b17023SJohn Marino 	return atype;
2928e4b17023SJohn Marino     }
2929e4b17023SJohn Marino   else
2930e4b17023SJohn Marino     return atype;
2931e4b17023SJohn Marino 
2932e4b17023SJohn Marino   *a = suba;
2933e4b17023SJohn Marino   *b = subb;
2934e4b17023SJohn Marino   return wider_type;
2935e4b17023SJohn Marino }
2936e4b17023SJohn Marino 
2937e4b17023SJohn Marino /* Determines the expression by that USE is expressed from induction variable
2938e4b17023SJohn Marino    CAND at statement AT in LOOP.  The expression is stored in a decomposed
2939e4b17023SJohn Marino    form into AFF.  Returns false if USE cannot be expressed using CAND.  */
2940e4b17023SJohn Marino 
2941e4b17023SJohn Marino static bool
get_computation_aff(struct loop * loop,struct iv_use * use,struct iv_cand * cand,gimple at,struct affine_tree_combination * aff)2942e4b17023SJohn Marino get_computation_aff (struct loop *loop,
2943e4b17023SJohn Marino 		     struct iv_use *use, struct iv_cand *cand, gimple at,
2944e4b17023SJohn Marino 		     struct affine_tree_combination *aff)
2945e4b17023SJohn Marino {
2946e4b17023SJohn Marino   tree ubase = use->iv->base;
2947e4b17023SJohn Marino   tree ustep = use->iv->step;
2948e4b17023SJohn Marino   tree cbase = cand->iv->base;
2949e4b17023SJohn Marino   tree cstep = cand->iv->step, cstep_common;
2950e4b17023SJohn Marino   tree utype = TREE_TYPE (ubase), ctype = TREE_TYPE (cbase);
2951e4b17023SJohn Marino   tree common_type, var;
2952e4b17023SJohn Marino   tree uutype;
2953e4b17023SJohn Marino   aff_tree cbase_aff, var_aff;
2954e4b17023SJohn Marino   double_int rat;
2955e4b17023SJohn Marino 
2956e4b17023SJohn Marino   if (TYPE_PRECISION (utype) > TYPE_PRECISION (ctype))
2957e4b17023SJohn Marino     {
2958e4b17023SJohn Marino       /* We do not have a precision to express the values of use.  */
2959e4b17023SJohn Marino       return false;
2960e4b17023SJohn Marino     }
2961e4b17023SJohn Marino 
2962e4b17023SJohn Marino   var = var_at_stmt (loop, cand, at);
2963e4b17023SJohn Marino   uutype = unsigned_type_for (utype);
2964e4b17023SJohn Marino 
2965e4b17023SJohn Marino   /* If the conversion is not noop, perform it.  */
2966e4b17023SJohn Marino   if (TYPE_PRECISION (utype) < TYPE_PRECISION (ctype))
2967e4b17023SJohn Marino     {
2968e4b17023SJohn Marino       cstep = fold_convert (uutype, cstep);
2969e4b17023SJohn Marino       cbase = fold_convert (uutype, cbase);
2970e4b17023SJohn Marino       var = fold_convert (uutype, var);
2971e4b17023SJohn Marino     }
2972e4b17023SJohn Marino 
2973e4b17023SJohn Marino   if (!constant_multiple_of (ustep, cstep, &rat))
2974e4b17023SJohn Marino     return false;
2975e4b17023SJohn Marino 
2976e4b17023SJohn Marino   /* In case both UBASE and CBASE are shortened to UUTYPE from some common
2977e4b17023SJohn Marino      type, we achieve better folding by computing their difference in this
2978e4b17023SJohn Marino      wider type, and cast the result to UUTYPE.  We do not need to worry about
2979e4b17023SJohn Marino      overflows, as all the arithmetics will in the end be performed in UUTYPE
2980e4b17023SJohn Marino      anyway.  */
2981e4b17023SJohn Marino   common_type = determine_common_wider_type (&ubase, &cbase);
2982e4b17023SJohn Marino 
2983e4b17023SJohn Marino   /* use = ubase - ratio * cbase + ratio * var.  */
2984e4b17023SJohn Marino   tree_to_aff_combination (ubase, common_type, aff);
2985e4b17023SJohn Marino   tree_to_aff_combination (cbase, common_type, &cbase_aff);
2986e4b17023SJohn Marino   tree_to_aff_combination (var, uutype, &var_aff);
2987e4b17023SJohn Marino 
2988e4b17023SJohn Marino   /* We need to shift the value if we are after the increment.  */
2989e4b17023SJohn Marino   if (stmt_after_increment (loop, cand, at))
2990e4b17023SJohn Marino     {
2991e4b17023SJohn Marino       aff_tree cstep_aff;
2992e4b17023SJohn Marino 
2993e4b17023SJohn Marino       if (common_type != uutype)
2994e4b17023SJohn Marino 	cstep_common = fold_convert (common_type, cstep);
2995e4b17023SJohn Marino       else
2996e4b17023SJohn Marino 	cstep_common = cstep;
2997e4b17023SJohn Marino 
2998e4b17023SJohn Marino       tree_to_aff_combination (cstep_common, common_type, &cstep_aff);
2999e4b17023SJohn Marino       aff_combination_add (&cbase_aff, &cstep_aff);
3000e4b17023SJohn Marino     }
3001e4b17023SJohn Marino 
3002e4b17023SJohn Marino   aff_combination_scale (&cbase_aff, double_int_neg (rat));
3003e4b17023SJohn Marino   aff_combination_add (aff, &cbase_aff);
3004e4b17023SJohn Marino   if (common_type != uutype)
3005e4b17023SJohn Marino     aff_combination_convert (aff, uutype);
3006e4b17023SJohn Marino 
3007e4b17023SJohn Marino   aff_combination_scale (&var_aff, rat);
3008e4b17023SJohn Marino   aff_combination_add (aff, &var_aff);
3009e4b17023SJohn Marino 
3010e4b17023SJohn Marino   return true;
3011e4b17023SJohn Marino }
3012e4b17023SJohn Marino 
3013e4b17023SJohn Marino /* Determines the expression by that USE is expressed from induction variable
3014e4b17023SJohn Marino    CAND at statement AT in LOOP.  The computation is unshared.  */
3015e4b17023SJohn Marino 
3016e4b17023SJohn Marino static tree
get_computation_at(struct loop * loop,struct iv_use * use,struct iv_cand * cand,gimple at)3017e4b17023SJohn Marino get_computation_at (struct loop *loop,
3018e4b17023SJohn Marino 		    struct iv_use *use, struct iv_cand *cand, gimple at)
3019e4b17023SJohn Marino {
3020e4b17023SJohn Marino   aff_tree aff;
3021e4b17023SJohn Marino   tree type = TREE_TYPE (use->iv->base);
3022e4b17023SJohn Marino 
3023e4b17023SJohn Marino   if (!get_computation_aff (loop, use, cand, at, &aff))
3024e4b17023SJohn Marino     return NULL_TREE;
3025e4b17023SJohn Marino   unshare_aff_combination (&aff);
3026e4b17023SJohn Marino   return fold_convert (type, aff_combination_to_tree (&aff));
3027e4b17023SJohn Marino }
3028e4b17023SJohn Marino 
3029e4b17023SJohn Marino /* Determines the expression by that USE is expressed from induction variable
3030e4b17023SJohn Marino    CAND in LOOP.  The computation is unshared.  */
3031e4b17023SJohn Marino 
3032e4b17023SJohn Marino static tree
get_computation(struct loop * loop,struct iv_use * use,struct iv_cand * cand)3033e4b17023SJohn Marino get_computation (struct loop *loop, struct iv_use *use, struct iv_cand *cand)
3034e4b17023SJohn Marino {
3035e4b17023SJohn Marino   return get_computation_at (loop, use, cand, use->stmt);
3036e4b17023SJohn Marino }
3037e4b17023SJohn Marino 
3038e4b17023SJohn Marino /* Adjust the cost COST for being in loop setup rather than loop body.
3039e4b17023SJohn Marino    If we're optimizing for space, the loop setup overhead is constant;
3040e4b17023SJohn Marino    if we're optimizing for speed, amortize it over the per-iteration cost.  */
3041e4b17023SJohn Marino static unsigned
adjust_setup_cost(struct ivopts_data * data,unsigned cost)3042e4b17023SJohn Marino adjust_setup_cost (struct ivopts_data *data, unsigned cost)
3043e4b17023SJohn Marino {
3044e4b17023SJohn Marino   if (cost == INFTY)
3045e4b17023SJohn Marino     return cost;
3046e4b17023SJohn Marino   else if (optimize_loop_for_speed_p (data->current_loop))
3047e4b17023SJohn Marino     return cost / avg_loop_niter (data->current_loop);
3048e4b17023SJohn Marino   else
3049e4b17023SJohn Marino     return cost;
3050e4b17023SJohn Marino }
3051e4b17023SJohn Marino 
3052e4b17023SJohn Marino /* Returns cost of addition in MODE.  */
3053e4b17023SJohn Marino 
3054e4b17023SJohn Marino static unsigned
add_cost(enum machine_mode mode,bool speed)3055e4b17023SJohn Marino add_cost (enum machine_mode mode, bool speed)
3056e4b17023SJohn Marino {
3057e4b17023SJohn Marino   static unsigned costs[NUM_MACHINE_MODES];
3058e4b17023SJohn Marino   rtx seq;
3059e4b17023SJohn Marino   unsigned cost;
3060e4b17023SJohn Marino 
3061e4b17023SJohn Marino   if (costs[mode])
3062e4b17023SJohn Marino     return costs[mode];
3063e4b17023SJohn Marino 
3064e4b17023SJohn Marino   start_sequence ();
3065e4b17023SJohn Marino   force_operand (gen_rtx_fmt_ee (PLUS, mode,
3066e4b17023SJohn Marino 				 gen_raw_REG (mode, LAST_VIRTUAL_REGISTER + 1),
3067e4b17023SJohn Marino 				 gen_raw_REG (mode, LAST_VIRTUAL_REGISTER + 2)),
3068e4b17023SJohn Marino 		 NULL_RTX);
3069e4b17023SJohn Marino   seq = get_insns ();
3070e4b17023SJohn Marino   end_sequence ();
3071e4b17023SJohn Marino 
3072e4b17023SJohn Marino   cost = seq_cost (seq, speed);
3073e4b17023SJohn Marino   if (!cost)
3074e4b17023SJohn Marino     cost = 1;
3075e4b17023SJohn Marino 
3076e4b17023SJohn Marino   costs[mode] = cost;
3077e4b17023SJohn Marino 
3078e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
3079e4b17023SJohn Marino     fprintf (dump_file, "Addition in %s costs %d\n",
3080e4b17023SJohn Marino 	     GET_MODE_NAME (mode), cost);
3081e4b17023SJohn Marino   return cost;
3082e4b17023SJohn Marino }
3083e4b17023SJohn Marino 
3084e4b17023SJohn Marino /* Entry in a hashtable of already known costs for multiplication.  */
3085e4b17023SJohn Marino struct mbc_entry
3086e4b17023SJohn Marino {
3087e4b17023SJohn Marino   HOST_WIDE_INT cst;		/* The constant to multiply by.  */
3088e4b17023SJohn Marino   enum machine_mode mode;	/* In mode.  */
3089e4b17023SJohn Marino   unsigned cost;		/* The cost.  */
3090e4b17023SJohn Marino };
3091e4b17023SJohn Marino 
3092e4b17023SJohn Marino /* Counts hash value for the ENTRY.  */
3093e4b17023SJohn Marino 
3094e4b17023SJohn Marino static hashval_t
mbc_entry_hash(const void * entry)3095e4b17023SJohn Marino mbc_entry_hash (const void *entry)
3096e4b17023SJohn Marino {
3097e4b17023SJohn Marino   const struct mbc_entry *e = (const struct mbc_entry *) entry;
3098e4b17023SJohn Marino 
3099e4b17023SJohn Marino   return 57 * (hashval_t) e->mode + (hashval_t) (e->cst % 877);
3100e4b17023SJohn Marino }
3101e4b17023SJohn Marino 
3102e4b17023SJohn Marino /* Compares the hash table entries ENTRY1 and ENTRY2.  */
3103e4b17023SJohn Marino 
3104e4b17023SJohn Marino static int
mbc_entry_eq(const void * entry1,const void * entry2)3105e4b17023SJohn Marino mbc_entry_eq (const void *entry1, const void *entry2)
3106e4b17023SJohn Marino {
3107e4b17023SJohn Marino   const struct mbc_entry *e1 = (const struct mbc_entry *) entry1;
3108e4b17023SJohn Marino   const struct mbc_entry *e2 = (const struct mbc_entry *) entry2;
3109e4b17023SJohn Marino 
3110e4b17023SJohn Marino   return (e1->mode == e2->mode
3111e4b17023SJohn Marino 	  && e1->cst == e2->cst);
3112e4b17023SJohn Marino }
3113e4b17023SJohn Marino 
3114e4b17023SJohn Marino /* Returns cost of multiplication by constant CST in MODE.  */
3115e4b17023SJohn Marino 
3116e4b17023SJohn Marino unsigned
multiply_by_cost(HOST_WIDE_INT cst,enum machine_mode mode,bool speed)3117e4b17023SJohn Marino multiply_by_cost (HOST_WIDE_INT cst, enum machine_mode mode, bool speed)
3118e4b17023SJohn Marino {
3119e4b17023SJohn Marino   static htab_t costs;
3120e4b17023SJohn Marino   struct mbc_entry **cached, act;
3121e4b17023SJohn Marino   rtx seq;
3122e4b17023SJohn Marino   unsigned cost;
3123e4b17023SJohn Marino 
3124e4b17023SJohn Marino   if (!costs)
3125e4b17023SJohn Marino     costs = htab_create (100, mbc_entry_hash, mbc_entry_eq, free);
3126e4b17023SJohn Marino 
3127e4b17023SJohn Marino   act.mode = mode;
3128e4b17023SJohn Marino   act.cst = cst;
3129e4b17023SJohn Marino   cached = (struct mbc_entry **) htab_find_slot (costs, &act, INSERT);
3130e4b17023SJohn Marino   if (*cached)
3131e4b17023SJohn Marino     return (*cached)->cost;
3132e4b17023SJohn Marino 
3133e4b17023SJohn Marino   *cached = XNEW (struct mbc_entry);
3134e4b17023SJohn Marino   (*cached)->mode = mode;
3135e4b17023SJohn Marino   (*cached)->cst = cst;
3136e4b17023SJohn Marino 
3137e4b17023SJohn Marino   start_sequence ();
3138e4b17023SJohn Marino   expand_mult (mode, gen_raw_REG (mode, LAST_VIRTUAL_REGISTER + 1),
3139e4b17023SJohn Marino 	       gen_int_mode (cst, mode), NULL_RTX, 0);
3140e4b17023SJohn Marino   seq = get_insns ();
3141e4b17023SJohn Marino   end_sequence ();
3142e4b17023SJohn Marino 
3143e4b17023SJohn Marino   cost = seq_cost (seq, speed);
3144e4b17023SJohn Marino 
3145e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
3146e4b17023SJohn Marino     fprintf (dump_file, "Multiplication by %d in %s costs %d\n",
3147e4b17023SJohn Marino 	     (int) cst, GET_MODE_NAME (mode), cost);
3148e4b17023SJohn Marino 
3149e4b17023SJohn Marino   (*cached)->cost = cost;
3150e4b17023SJohn Marino 
3151e4b17023SJohn Marino   return cost;
3152e4b17023SJohn Marino }
3153e4b17023SJohn Marino 
3154e4b17023SJohn Marino /* Returns true if multiplying by RATIO is allowed in an address.  Test the
3155e4b17023SJohn Marino    validity for a memory reference accessing memory of mode MODE in
3156e4b17023SJohn Marino    address space AS.  */
3157e4b17023SJohn Marino 
3158e4b17023SJohn Marino DEF_VEC_P (sbitmap);
3159e4b17023SJohn Marino DEF_VEC_ALLOC_P (sbitmap, heap);
3160e4b17023SJohn Marino 
3161e4b17023SJohn Marino bool
multiplier_allowed_in_address_p(HOST_WIDE_INT ratio,enum machine_mode mode,addr_space_t as)3162e4b17023SJohn Marino multiplier_allowed_in_address_p (HOST_WIDE_INT ratio, enum machine_mode mode,
3163e4b17023SJohn Marino 				 addr_space_t as)
3164e4b17023SJohn Marino {
3165e4b17023SJohn Marino #define MAX_RATIO 128
3166e4b17023SJohn Marino   unsigned int data_index = (int) as * MAX_MACHINE_MODE + (int) mode;
3167e4b17023SJohn Marino   static VEC (sbitmap, heap) *valid_mult_list;
3168e4b17023SJohn Marino   sbitmap valid_mult;
3169e4b17023SJohn Marino 
3170e4b17023SJohn Marino   if (data_index >= VEC_length (sbitmap, valid_mult_list))
3171e4b17023SJohn Marino     VEC_safe_grow_cleared (sbitmap, heap, valid_mult_list, data_index + 1);
3172e4b17023SJohn Marino 
3173e4b17023SJohn Marino   valid_mult = VEC_index (sbitmap, valid_mult_list, data_index);
3174e4b17023SJohn Marino   if (!valid_mult)
3175e4b17023SJohn Marino     {
3176e4b17023SJohn Marino       enum machine_mode address_mode = targetm.addr_space.address_mode (as);
3177e4b17023SJohn Marino       rtx reg1 = gen_raw_REG (address_mode, LAST_VIRTUAL_REGISTER + 1);
3178e4b17023SJohn Marino       rtx addr;
3179e4b17023SJohn Marino       HOST_WIDE_INT i;
3180e4b17023SJohn Marino 
3181e4b17023SJohn Marino       valid_mult = sbitmap_alloc (2 * MAX_RATIO + 1);
3182e4b17023SJohn Marino       sbitmap_zero (valid_mult);
3183e4b17023SJohn Marino       addr = gen_rtx_fmt_ee (MULT, address_mode, reg1, NULL_RTX);
3184e4b17023SJohn Marino       for (i = -MAX_RATIO; i <= MAX_RATIO; i++)
3185e4b17023SJohn Marino 	{
3186e4b17023SJohn Marino 	  XEXP (addr, 1) = gen_int_mode (i, address_mode);
3187e4b17023SJohn Marino 	  if (memory_address_addr_space_p (mode, addr, as))
3188e4b17023SJohn Marino 	    SET_BIT (valid_mult, i + MAX_RATIO);
3189e4b17023SJohn Marino 	}
3190e4b17023SJohn Marino 
3191e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
3192e4b17023SJohn Marino 	{
3193e4b17023SJohn Marino 	  fprintf (dump_file, "  allowed multipliers:");
3194e4b17023SJohn Marino 	  for (i = -MAX_RATIO; i <= MAX_RATIO; i++)
3195e4b17023SJohn Marino 	    if (TEST_BIT (valid_mult, i + MAX_RATIO))
3196e4b17023SJohn Marino 	      fprintf (dump_file, " %d", (int) i);
3197e4b17023SJohn Marino 	  fprintf (dump_file, "\n");
3198e4b17023SJohn Marino 	  fprintf (dump_file, "\n");
3199e4b17023SJohn Marino 	}
3200e4b17023SJohn Marino 
3201e4b17023SJohn Marino       VEC_replace (sbitmap, valid_mult_list, data_index, valid_mult);
3202e4b17023SJohn Marino     }
3203e4b17023SJohn Marino 
3204e4b17023SJohn Marino   if (ratio > MAX_RATIO || ratio < -MAX_RATIO)
3205e4b17023SJohn Marino     return false;
3206e4b17023SJohn Marino 
3207e4b17023SJohn Marino   return TEST_BIT (valid_mult, ratio + MAX_RATIO);
3208e4b17023SJohn Marino }
3209e4b17023SJohn Marino 
3210e4b17023SJohn Marino /* Returns cost of address in shape symbol + var + OFFSET + RATIO * index.
3211e4b17023SJohn Marino    If SYMBOL_PRESENT is false, symbol is omitted.  If VAR_PRESENT is false,
3212e4b17023SJohn Marino    variable is omitted.  Compute the cost for a memory reference that accesses
3213e4b17023SJohn Marino    a memory location of mode MEM_MODE in address space AS.
3214e4b17023SJohn Marino 
3215e4b17023SJohn Marino    MAY_AUTOINC is set to true if the autoincrement (increasing index by
3216e4b17023SJohn Marino    size of MEM_MODE / RATIO) is available.  To make this determination, we
3217e4b17023SJohn Marino    look at the size of the increment to be made, which is given in CSTEP.
3218e4b17023SJohn Marino    CSTEP may be zero if the step is unknown.
3219e4b17023SJohn Marino    STMT_AFTER_INC is true iff the statement we're looking at is after the
3220e4b17023SJohn Marino    increment of the original biv.
3221e4b17023SJohn Marino 
3222e4b17023SJohn Marino    TODO -- there must be some better way.  This all is quite crude.  */
3223e4b17023SJohn Marino 
3224e4b17023SJohn Marino typedef struct
3225e4b17023SJohn Marino {
3226e4b17023SJohn Marino   HOST_WIDE_INT min_offset, max_offset;
3227e4b17023SJohn Marino   unsigned costs[2][2][2][2];
3228e4b17023SJohn Marino } *address_cost_data;
3229e4b17023SJohn Marino 
3230e4b17023SJohn Marino DEF_VEC_P (address_cost_data);
3231e4b17023SJohn Marino DEF_VEC_ALLOC_P (address_cost_data, heap);
3232e4b17023SJohn Marino 
3233e4b17023SJohn Marino static comp_cost
get_address_cost(bool symbol_present,bool var_present,unsigned HOST_WIDE_INT offset,HOST_WIDE_INT ratio,HOST_WIDE_INT cstep,enum machine_mode mem_mode,addr_space_t as,bool speed,bool stmt_after_inc,bool * may_autoinc)3234e4b17023SJohn Marino get_address_cost (bool symbol_present, bool var_present,
3235e4b17023SJohn Marino 		  unsigned HOST_WIDE_INT offset, HOST_WIDE_INT ratio,
3236e4b17023SJohn Marino 		  HOST_WIDE_INT cstep, enum machine_mode mem_mode,
3237e4b17023SJohn Marino 		  addr_space_t as, bool speed,
3238e4b17023SJohn Marino 		  bool stmt_after_inc, bool *may_autoinc)
3239e4b17023SJohn Marino {
3240e4b17023SJohn Marino   enum machine_mode address_mode = targetm.addr_space.address_mode (as);
3241e4b17023SJohn Marino   static VEC(address_cost_data, heap) *address_cost_data_list;
3242e4b17023SJohn Marino   unsigned int data_index = (int) as * MAX_MACHINE_MODE + (int) mem_mode;
3243e4b17023SJohn Marino   address_cost_data data;
3244e4b17023SJohn Marino   static bool has_preinc[MAX_MACHINE_MODE], has_postinc[MAX_MACHINE_MODE];
3245e4b17023SJohn Marino   static bool has_predec[MAX_MACHINE_MODE], has_postdec[MAX_MACHINE_MODE];
3246e4b17023SJohn Marino   unsigned cost, acost, complexity;
3247e4b17023SJohn Marino   bool offset_p, ratio_p, autoinc;
3248e4b17023SJohn Marino   HOST_WIDE_INT s_offset, autoinc_offset, msize;
3249e4b17023SJohn Marino   unsigned HOST_WIDE_INT mask;
3250e4b17023SJohn Marino   unsigned bits;
3251e4b17023SJohn Marino 
3252e4b17023SJohn Marino   if (data_index >= VEC_length (address_cost_data, address_cost_data_list))
3253e4b17023SJohn Marino     VEC_safe_grow_cleared (address_cost_data, heap, address_cost_data_list,
3254e4b17023SJohn Marino 			   data_index + 1);
3255e4b17023SJohn Marino 
3256e4b17023SJohn Marino   data = VEC_index (address_cost_data, address_cost_data_list, data_index);
3257e4b17023SJohn Marino   if (!data)
3258e4b17023SJohn Marino     {
3259e4b17023SJohn Marino       HOST_WIDE_INT i;
3260e4b17023SJohn Marino       HOST_WIDE_INT rat, off = 0;
3261e4b17023SJohn Marino       int old_cse_not_expected, width;
3262e4b17023SJohn Marino       unsigned sym_p, var_p, off_p, rat_p, add_c;
3263e4b17023SJohn Marino       rtx seq, addr, base;
3264e4b17023SJohn Marino       rtx reg0, reg1;
3265e4b17023SJohn Marino 
3266e4b17023SJohn Marino       data = (address_cost_data) xcalloc (1, sizeof (*data));
3267e4b17023SJohn Marino 
3268e4b17023SJohn Marino       reg1 = gen_raw_REG (address_mode, LAST_VIRTUAL_REGISTER + 1);
3269e4b17023SJohn Marino 
3270e4b17023SJohn Marino       width = GET_MODE_BITSIZE (address_mode) - 1;
3271e4b17023SJohn Marino       if (width > (HOST_BITS_PER_WIDE_INT - 1))
3272e4b17023SJohn Marino 	width = HOST_BITS_PER_WIDE_INT - 1;
3273e4b17023SJohn Marino       addr = gen_rtx_fmt_ee (PLUS, address_mode, reg1, NULL_RTX);
3274e4b17023SJohn Marino 
3275e4b17023SJohn Marino       for (i = width; i >= 0; i--)
3276e4b17023SJohn Marino 	{
3277e4b17023SJohn Marino 	  off = -((HOST_WIDE_INT) 1 << i);
3278e4b17023SJohn Marino 	  XEXP (addr, 1) = gen_int_mode (off, address_mode);
3279e4b17023SJohn Marino 	  if (memory_address_addr_space_p (mem_mode, addr, as))
3280e4b17023SJohn Marino 	    break;
3281e4b17023SJohn Marino 	}
3282e4b17023SJohn Marino       data->min_offset = (i == -1? 0 : off);
3283e4b17023SJohn Marino 
3284e4b17023SJohn Marino       for (i = width; i >= 0; i--)
3285e4b17023SJohn Marino 	{
3286e4b17023SJohn Marino 	  off = ((HOST_WIDE_INT) 1 << i) - 1;
3287e4b17023SJohn Marino 	  XEXP (addr, 1) = gen_int_mode (off, address_mode);
3288e4b17023SJohn Marino 	  if (memory_address_addr_space_p (mem_mode, addr, as))
3289e4b17023SJohn Marino 	    break;
3290e4b17023SJohn Marino 	}
3291e4b17023SJohn Marino       if (i == -1)
3292e4b17023SJohn Marino         off = 0;
3293e4b17023SJohn Marino       data->max_offset = off;
3294e4b17023SJohn Marino 
3295e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
3296e4b17023SJohn Marino 	{
3297e4b17023SJohn Marino 	  fprintf (dump_file, "get_address_cost:\n");
3298e4b17023SJohn Marino 	  fprintf (dump_file, "  min offset %s " HOST_WIDE_INT_PRINT_DEC "\n",
3299e4b17023SJohn Marino 		   GET_MODE_NAME (mem_mode),
3300e4b17023SJohn Marino 		   data->min_offset);
3301e4b17023SJohn Marino 	  fprintf (dump_file, "  max offset %s " HOST_WIDE_INT_PRINT_DEC "\n",
3302e4b17023SJohn Marino 		   GET_MODE_NAME (mem_mode),
3303e4b17023SJohn Marino 		   data->max_offset);
3304e4b17023SJohn Marino 	}
3305e4b17023SJohn Marino 
3306e4b17023SJohn Marino       rat = 1;
3307e4b17023SJohn Marino       for (i = 2; i <= MAX_RATIO; i++)
3308e4b17023SJohn Marino 	if (multiplier_allowed_in_address_p (i, mem_mode, as))
3309e4b17023SJohn Marino 	  {
3310e4b17023SJohn Marino 	    rat = i;
3311e4b17023SJohn Marino 	    break;
3312e4b17023SJohn Marino 	  }
3313e4b17023SJohn Marino 
3314e4b17023SJohn Marino       /* Compute the cost of various addressing modes.  */
3315e4b17023SJohn Marino       acost = 0;
3316e4b17023SJohn Marino       reg0 = gen_raw_REG (address_mode, LAST_VIRTUAL_REGISTER + 1);
3317e4b17023SJohn Marino       reg1 = gen_raw_REG (address_mode, LAST_VIRTUAL_REGISTER + 2);
3318e4b17023SJohn Marino 
3319e4b17023SJohn Marino       if (HAVE_PRE_DECREMENT)
3320e4b17023SJohn Marino 	{
3321e4b17023SJohn Marino 	  addr = gen_rtx_PRE_DEC (address_mode, reg0);
3322e4b17023SJohn Marino 	  has_predec[mem_mode]
3323e4b17023SJohn Marino 	    = memory_address_addr_space_p (mem_mode, addr, as);
3324e4b17023SJohn Marino 	}
3325e4b17023SJohn Marino       if (HAVE_POST_DECREMENT)
3326e4b17023SJohn Marino 	{
3327e4b17023SJohn Marino 	  addr = gen_rtx_POST_DEC (address_mode, reg0);
3328e4b17023SJohn Marino 	  has_postdec[mem_mode]
3329e4b17023SJohn Marino 	    = memory_address_addr_space_p (mem_mode, addr, as);
3330e4b17023SJohn Marino 	}
3331e4b17023SJohn Marino       if (HAVE_PRE_INCREMENT)
3332e4b17023SJohn Marino 	{
3333e4b17023SJohn Marino 	  addr = gen_rtx_PRE_INC (address_mode, reg0);
3334e4b17023SJohn Marino 	  has_preinc[mem_mode]
3335e4b17023SJohn Marino 	    = memory_address_addr_space_p (mem_mode, addr, as);
3336e4b17023SJohn Marino 	}
3337e4b17023SJohn Marino       if (HAVE_POST_INCREMENT)
3338e4b17023SJohn Marino 	{
3339e4b17023SJohn Marino 	  addr = gen_rtx_POST_INC (address_mode, reg0);
3340e4b17023SJohn Marino 	  has_postinc[mem_mode]
3341e4b17023SJohn Marino 	    = memory_address_addr_space_p (mem_mode, addr, as);
3342e4b17023SJohn Marino 	}
3343e4b17023SJohn Marino       for (i = 0; i < 16; i++)
3344e4b17023SJohn Marino 	{
3345e4b17023SJohn Marino 	  sym_p = i & 1;
3346e4b17023SJohn Marino 	  var_p = (i >> 1) & 1;
3347e4b17023SJohn Marino 	  off_p = (i >> 2) & 1;
3348e4b17023SJohn Marino 	  rat_p = (i >> 3) & 1;
3349e4b17023SJohn Marino 
3350e4b17023SJohn Marino 	  addr = reg0;
3351e4b17023SJohn Marino 	  if (rat_p)
3352e4b17023SJohn Marino 	    addr = gen_rtx_fmt_ee (MULT, address_mode, addr,
3353e4b17023SJohn Marino 				   gen_int_mode (rat, address_mode));
3354e4b17023SJohn Marino 
3355e4b17023SJohn Marino 	  if (var_p)
3356e4b17023SJohn Marino 	    addr = gen_rtx_fmt_ee (PLUS, address_mode, addr, reg1);
3357e4b17023SJohn Marino 
3358e4b17023SJohn Marino 	  if (sym_p)
3359e4b17023SJohn Marino 	    {
3360e4b17023SJohn Marino 	      base = gen_rtx_SYMBOL_REF (address_mode, ggc_strdup (""));
3361e4b17023SJohn Marino 	      /* ??? We can run into trouble with some backends by presenting
3362e4b17023SJohn Marino 		 it with symbols which haven't been properly passed through
3363e4b17023SJohn Marino 		 targetm.encode_section_info.  By setting the local bit, we
3364e4b17023SJohn Marino 		 enhance the probability of things working.  */
3365e4b17023SJohn Marino 	      SYMBOL_REF_FLAGS (base) = SYMBOL_FLAG_LOCAL;
3366e4b17023SJohn Marino 
3367e4b17023SJohn Marino 	      if (off_p)
3368e4b17023SJohn Marino 		base = gen_rtx_fmt_e (CONST, address_mode,
3369e4b17023SJohn Marino 				      gen_rtx_fmt_ee
3370e4b17023SJohn Marino 					(PLUS, address_mode, base,
3371e4b17023SJohn Marino 					 gen_int_mode (off, address_mode)));
3372e4b17023SJohn Marino 	    }
3373e4b17023SJohn Marino 	  else if (off_p)
3374e4b17023SJohn Marino 	    base = gen_int_mode (off, address_mode);
3375e4b17023SJohn Marino 	  else
3376e4b17023SJohn Marino 	    base = NULL_RTX;
3377e4b17023SJohn Marino 
3378e4b17023SJohn Marino 	  if (base)
3379e4b17023SJohn Marino 	    addr = gen_rtx_fmt_ee (PLUS, address_mode, addr, base);
3380e4b17023SJohn Marino 
3381e4b17023SJohn Marino 	  start_sequence ();
3382e4b17023SJohn Marino 	  /* To avoid splitting addressing modes, pretend that no cse will
3383e4b17023SJohn Marino 	     follow.  */
3384e4b17023SJohn Marino 	  old_cse_not_expected = cse_not_expected;
3385e4b17023SJohn Marino 	  cse_not_expected = true;
3386e4b17023SJohn Marino 	  addr = memory_address_addr_space (mem_mode, addr, as);
3387e4b17023SJohn Marino 	  cse_not_expected = old_cse_not_expected;
3388e4b17023SJohn Marino 	  seq = get_insns ();
3389e4b17023SJohn Marino 	  end_sequence ();
3390e4b17023SJohn Marino 
3391e4b17023SJohn Marino 	  acost = seq_cost (seq, speed);
3392e4b17023SJohn Marino 	  acost += address_cost (addr, mem_mode, as, speed);
3393e4b17023SJohn Marino 
3394e4b17023SJohn Marino 	  if (!acost)
3395e4b17023SJohn Marino 	    acost = 1;
3396e4b17023SJohn Marino 	  data->costs[sym_p][var_p][off_p][rat_p] = acost;
3397e4b17023SJohn Marino 	}
3398e4b17023SJohn Marino 
3399e4b17023SJohn Marino       /* On some targets, it is quite expensive to load symbol to a register,
3400e4b17023SJohn Marino 	 which makes addresses that contain symbols look much more expensive.
3401e4b17023SJohn Marino 	 However, the symbol will have to be loaded in any case before the
3402e4b17023SJohn Marino 	 loop (and quite likely we have it in register already), so it does not
3403e4b17023SJohn Marino 	 make much sense to penalize them too heavily.  So make some final
3404e4b17023SJohn Marino          tweaks for the SYMBOL_PRESENT modes:
3405e4b17023SJohn Marino 
3406e4b17023SJohn Marino          If VAR_PRESENT is false, and the mode obtained by changing symbol to
3407e4b17023SJohn Marino 	 var is cheaper, use this mode with small penalty.
3408e4b17023SJohn Marino 	 If VAR_PRESENT is true, try whether the mode with
3409e4b17023SJohn Marino 	 SYMBOL_PRESENT = false is cheaper even with cost of addition, and
3410e4b17023SJohn Marino 	 if this is the case, use it.  */
3411e4b17023SJohn Marino       add_c = add_cost (address_mode, speed);
3412e4b17023SJohn Marino       for (i = 0; i < 8; i++)
3413e4b17023SJohn Marino 	{
3414e4b17023SJohn Marino 	  var_p = i & 1;
3415e4b17023SJohn Marino 	  off_p = (i >> 1) & 1;
3416e4b17023SJohn Marino 	  rat_p = (i >> 2) & 1;
3417e4b17023SJohn Marino 
3418e4b17023SJohn Marino 	  acost = data->costs[0][1][off_p][rat_p] + 1;
3419e4b17023SJohn Marino 	  if (var_p)
3420e4b17023SJohn Marino 	    acost += add_c;
3421e4b17023SJohn Marino 
3422e4b17023SJohn Marino 	  if (acost < data->costs[1][var_p][off_p][rat_p])
3423e4b17023SJohn Marino 	    data->costs[1][var_p][off_p][rat_p] = acost;
3424e4b17023SJohn Marino 	}
3425e4b17023SJohn Marino 
3426e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
3427e4b17023SJohn Marino 	{
3428e4b17023SJohn Marino 	  fprintf (dump_file, "Address costs:\n");
3429e4b17023SJohn Marino 
3430e4b17023SJohn Marino 	  for (i = 0; i < 16; i++)
3431e4b17023SJohn Marino 	    {
3432e4b17023SJohn Marino 	      sym_p = i & 1;
3433e4b17023SJohn Marino 	      var_p = (i >> 1) & 1;
3434e4b17023SJohn Marino 	      off_p = (i >> 2) & 1;
3435e4b17023SJohn Marino 	      rat_p = (i >> 3) & 1;
3436e4b17023SJohn Marino 
3437e4b17023SJohn Marino 	      fprintf (dump_file, "  ");
3438e4b17023SJohn Marino 	      if (sym_p)
3439e4b17023SJohn Marino 		fprintf (dump_file, "sym + ");
3440e4b17023SJohn Marino 	      if (var_p)
3441e4b17023SJohn Marino 		fprintf (dump_file, "var + ");
3442e4b17023SJohn Marino 	      if (off_p)
3443e4b17023SJohn Marino 		fprintf (dump_file, "cst + ");
3444e4b17023SJohn Marino 	      if (rat_p)
3445e4b17023SJohn Marino 		fprintf (dump_file, "rat * ");
3446e4b17023SJohn Marino 
3447e4b17023SJohn Marino 	      acost = data->costs[sym_p][var_p][off_p][rat_p];
3448e4b17023SJohn Marino 	      fprintf (dump_file, "index costs %d\n", acost);
3449e4b17023SJohn Marino 	    }
3450e4b17023SJohn Marino 	  if (has_predec[mem_mode] || has_postdec[mem_mode]
3451e4b17023SJohn Marino 	      || has_preinc[mem_mode] || has_postinc[mem_mode])
3452e4b17023SJohn Marino 	    fprintf (dump_file, "  May include autoinc/dec\n");
3453e4b17023SJohn Marino 	  fprintf (dump_file, "\n");
3454e4b17023SJohn Marino 	}
3455e4b17023SJohn Marino 
3456e4b17023SJohn Marino       VEC_replace (address_cost_data, address_cost_data_list,
3457e4b17023SJohn Marino 		   data_index, data);
3458e4b17023SJohn Marino     }
3459e4b17023SJohn Marino 
3460e4b17023SJohn Marino   bits = GET_MODE_BITSIZE (address_mode);
3461e4b17023SJohn Marino   mask = ~(~(unsigned HOST_WIDE_INT) 0 << (bits - 1) << 1);
3462e4b17023SJohn Marino   offset &= mask;
3463e4b17023SJohn Marino   if ((offset >> (bits - 1) & 1))
3464e4b17023SJohn Marino     offset |= ~mask;
3465e4b17023SJohn Marino   s_offset = offset;
3466e4b17023SJohn Marino 
3467e4b17023SJohn Marino   autoinc = false;
3468e4b17023SJohn Marino   msize = GET_MODE_SIZE (mem_mode);
3469e4b17023SJohn Marino   autoinc_offset = offset;
3470e4b17023SJohn Marino   if (stmt_after_inc)
3471e4b17023SJohn Marino     autoinc_offset += ratio * cstep;
3472e4b17023SJohn Marino   if (symbol_present || var_present || ratio != 1)
3473e4b17023SJohn Marino     autoinc = false;
3474e4b17023SJohn Marino   else if ((has_postinc[mem_mode] && autoinc_offset == 0
3475e4b17023SJohn Marino 	       && msize == cstep)
3476e4b17023SJohn Marino 	   || (has_postdec[mem_mode] && autoinc_offset == 0
3477e4b17023SJohn Marino 	       && msize == -cstep)
3478e4b17023SJohn Marino 	   || (has_preinc[mem_mode] && autoinc_offset == msize
3479e4b17023SJohn Marino 	       && msize == cstep)
3480e4b17023SJohn Marino 	   || (has_predec[mem_mode] && autoinc_offset == -msize
3481e4b17023SJohn Marino 	       && msize == -cstep))
3482e4b17023SJohn Marino     autoinc = true;
3483e4b17023SJohn Marino 
3484e4b17023SJohn Marino   cost = 0;
3485e4b17023SJohn Marino   offset_p = (s_offset != 0
3486e4b17023SJohn Marino 	      && data->min_offset <= s_offset
3487e4b17023SJohn Marino 	      && s_offset <= data->max_offset);
3488e4b17023SJohn Marino   ratio_p = (ratio != 1
3489e4b17023SJohn Marino 	     && multiplier_allowed_in_address_p (ratio, mem_mode, as));
3490e4b17023SJohn Marino 
3491e4b17023SJohn Marino   if (ratio != 1 && !ratio_p)
3492e4b17023SJohn Marino     cost += multiply_by_cost (ratio, address_mode, speed);
3493e4b17023SJohn Marino 
3494e4b17023SJohn Marino   if (s_offset && !offset_p && !symbol_present)
3495e4b17023SJohn Marino     cost += add_cost (address_mode, speed);
3496e4b17023SJohn Marino 
3497e4b17023SJohn Marino   if (may_autoinc)
3498e4b17023SJohn Marino     *may_autoinc = autoinc;
3499e4b17023SJohn Marino   acost = data->costs[symbol_present][var_present][offset_p][ratio_p];
3500e4b17023SJohn Marino   complexity = (symbol_present != 0) + (var_present != 0) + offset_p + ratio_p;
3501e4b17023SJohn Marino   return new_cost (cost + acost, complexity);
3502e4b17023SJohn Marino }
3503e4b17023SJohn Marino 
3504e4b17023SJohn Marino  /* Calculate the SPEED or size cost of shiftadd EXPR in MODE.  MULT is the
3505e4b17023SJohn Marino     the EXPR operand holding the shift.  COST0 and COST1 are the costs for
3506e4b17023SJohn Marino     calculating the operands of EXPR.  Returns true if successful, and returns
3507e4b17023SJohn Marino     the cost in COST.  */
3508e4b17023SJohn Marino 
3509e4b17023SJohn Marino static bool
get_shiftadd_cost(tree expr,enum machine_mode mode,comp_cost cost0,comp_cost cost1,tree mult,bool speed,comp_cost * cost)3510e4b17023SJohn Marino get_shiftadd_cost (tree expr, enum machine_mode mode, comp_cost cost0,
3511e4b17023SJohn Marino                    comp_cost cost1, tree mult, bool speed, comp_cost *cost)
3512e4b17023SJohn Marino {
3513e4b17023SJohn Marino   comp_cost res;
3514e4b17023SJohn Marino   tree op1 = TREE_OPERAND (expr, 1);
3515e4b17023SJohn Marino   tree cst = TREE_OPERAND (mult, 1);
3516e4b17023SJohn Marino   tree multop = TREE_OPERAND (mult, 0);
3517e4b17023SJohn Marino   int m = exact_log2 (int_cst_value (cst));
3518e4b17023SJohn Marino   int maxm = MIN (BITS_PER_WORD, GET_MODE_BITSIZE (mode));
3519e4b17023SJohn Marino   int sa_cost;
3520e4b17023SJohn Marino 
3521e4b17023SJohn Marino   if (!(m >= 0 && m < maxm))
3522e4b17023SJohn Marino     return false;
3523e4b17023SJohn Marino 
3524e4b17023SJohn Marino   sa_cost = (TREE_CODE (expr) != MINUS_EXPR
3525e4b17023SJohn Marino              ? shiftadd_cost[speed][mode][m]
3526e4b17023SJohn Marino              : (mult == op1
3527e4b17023SJohn Marino                 ? shiftsub1_cost[speed][mode][m]
3528e4b17023SJohn Marino                 : shiftsub0_cost[speed][mode][m]));
3529e4b17023SJohn Marino   res = new_cost (sa_cost, 0);
3530e4b17023SJohn Marino   res = add_costs (res, mult == op1 ? cost0 : cost1);
3531e4b17023SJohn Marino 
3532e4b17023SJohn Marino   STRIP_NOPS (multop);
3533e4b17023SJohn Marino   if (!is_gimple_val (multop))
3534e4b17023SJohn Marino     res = add_costs (res, force_expr_to_var_cost (multop, speed));
3535e4b17023SJohn Marino 
3536e4b17023SJohn Marino   *cost = res;
3537e4b17023SJohn Marino   return true;
3538e4b17023SJohn Marino }
3539e4b17023SJohn Marino 
3540e4b17023SJohn Marino /* Estimates cost of forcing expression EXPR into a variable.  */
3541e4b17023SJohn Marino 
3542e4b17023SJohn Marino static comp_cost
force_expr_to_var_cost(tree expr,bool speed)3543e4b17023SJohn Marino force_expr_to_var_cost (tree expr, bool speed)
3544e4b17023SJohn Marino {
3545e4b17023SJohn Marino   static bool costs_initialized = false;
3546e4b17023SJohn Marino   static unsigned integer_cost [2];
3547e4b17023SJohn Marino   static unsigned symbol_cost [2];
3548e4b17023SJohn Marino   static unsigned address_cost [2];
3549e4b17023SJohn Marino   tree op0, op1;
3550e4b17023SJohn Marino   comp_cost cost0, cost1, cost;
3551e4b17023SJohn Marino   enum machine_mode mode;
3552e4b17023SJohn Marino 
3553e4b17023SJohn Marino   if (!costs_initialized)
3554e4b17023SJohn Marino     {
3555e4b17023SJohn Marino       tree type = build_pointer_type (integer_type_node);
3556e4b17023SJohn Marino       tree var, addr;
3557e4b17023SJohn Marino       rtx x;
3558e4b17023SJohn Marino       int i;
3559e4b17023SJohn Marino 
3560e4b17023SJohn Marino       var = create_tmp_var_raw (integer_type_node, "test_var");
3561e4b17023SJohn Marino       TREE_STATIC (var) = 1;
3562e4b17023SJohn Marino       x = produce_memory_decl_rtl (var, NULL);
3563e4b17023SJohn Marino       SET_DECL_RTL (var, x);
3564e4b17023SJohn Marino 
3565e4b17023SJohn Marino       addr = build1 (ADDR_EXPR, type, var);
3566e4b17023SJohn Marino 
3567e4b17023SJohn Marino 
3568e4b17023SJohn Marino       for (i = 0; i < 2; i++)
3569e4b17023SJohn Marino 	{
3570e4b17023SJohn Marino 	  integer_cost[i] = computation_cost (build_int_cst (integer_type_node,
3571e4b17023SJohn Marino 							     2000), i);
3572e4b17023SJohn Marino 
3573e4b17023SJohn Marino 	  symbol_cost[i] = computation_cost (addr, i) + 1;
3574e4b17023SJohn Marino 
3575e4b17023SJohn Marino 	  address_cost[i]
3576e4b17023SJohn Marino 	    = computation_cost (fold_build_pointer_plus_hwi (addr, 2000), i) + 1;
3577e4b17023SJohn Marino 	  if (dump_file && (dump_flags & TDF_DETAILS))
3578e4b17023SJohn Marino 	    {
3579e4b17023SJohn Marino 	      fprintf (dump_file, "force_expr_to_var_cost %s costs:\n", i ? "speed" : "size");
3580e4b17023SJohn Marino 	      fprintf (dump_file, "  integer %d\n", (int) integer_cost[i]);
3581e4b17023SJohn Marino 	      fprintf (dump_file, "  symbol %d\n", (int) symbol_cost[i]);
3582e4b17023SJohn Marino 	      fprintf (dump_file, "  address %d\n", (int) address_cost[i]);
3583e4b17023SJohn Marino 	      fprintf (dump_file, "  other %d\n", (int) target_spill_cost[i]);
3584e4b17023SJohn Marino 	      fprintf (dump_file, "\n");
3585e4b17023SJohn Marino 	    }
3586e4b17023SJohn Marino 	}
3587e4b17023SJohn Marino 
3588e4b17023SJohn Marino       costs_initialized = true;
3589e4b17023SJohn Marino     }
3590e4b17023SJohn Marino 
3591e4b17023SJohn Marino   STRIP_NOPS (expr);
3592e4b17023SJohn Marino 
3593e4b17023SJohn Marino   if (SSA_VAR_P (expr))
3594e4b17023SJohn Marino     return zero_cost;
3595e4b17023SJohn Marino 
3596e4b17023SJohn Marino   if (is_gimple_min_invariant (expr))
3597e4b17023SJohn Marino     {
3598e4b17023SJohn Marino       if (TREE_CODE (expr) == INTEGER_CST)
3599e4b17023SJohn Marino 	return new_cost (integer_cost [speed], 0);
3600e4b17023SJohn Marino 
3601e4b17023SJohn Marino       if (TREE_CODE (expr) == ADDR_EXPR)
3602e4b17023SJohn Marino 	{
3603e4b17023SJohn Marino 	  tree obj = TREE_OPERAND (expr, 0);
3604e4b17023SJohn Marino 
3605e4b17023SJohn Marino 	  if (TREE_CODE (obj) == VAR_DECL
3606e4b17023SJohn Marino 	      || TREE_CODE (obj) == PARM_DECL
3607e4b17023SJohn Marino 	      || TREE_CODE (obj) == RESULT_DECL)
3608e4b17023SJohn Marino 	    return new_cost (symbol_cost [speed], 0);
3609e4b17023SJohn Marino 	}
3610e4b17023SJohn Marino 
3611e4b17023SJohn Marino       return new_cost (address_cost [speed], 0);
3612e4b17023SJohn Marino     }
3613e4b17023SJohn Marino 
3614e4b17023SJohn Marino   switch (TREE_CODE (expr))
3615e4b17023SJohn Marino     {
3616e4b17023SJohn Marino     case POINTER_PLUS_EXPR:
3617e4b17023SJohn Marino     case PLUS_EXPR:
3618e4b17023SJohn Marino     case MINUS_EXPR:
3619e4b17023SJohn Marino     case MULT_EXPR:
3620e4b17023SJohn Marino       op0 = TREE_OPERAND (expr, 0);
3621e4b17023SJohn Marino       op1 = TREE_OPERAND (expr, 1);
3622e4b17023SJohn Marino       STRIP_NOPS (op0);
3623e4b17023SJohn Marino       STRIP_NOPS (op1);
3624e4b17023SJohn Marino 
3625e4b17023SJohn Marino       if (is_gimple_val (op0))
3626e4b17023SJohn Marino 	cost0 = zero_cost;
3627e4b17023SJohn Marino       else
3628e4b17023SJohn Marino 	cost0 = force_expr_to_var_cost (op0, speed);
3629e4b17023SJohn Marino 
3630e4b17023SJohn Marino       if (is_gimple_val (op1))
3631e4b17023SJohn Marino 	cost1 = zero_cost;
3632e4b17023SJohn Marino       else
3633e4b17023SJohn Marino 	cost1 = force_expr_to_var_cost (op1, speed);
3634e4b17023SJohn Marino 
3635e4b17023SJohn Marino       break;
3636e4b17023SJohn Marino 
3637e4b17023SJohn Marino     case NEGATE_EXPR:
3638e4b17023SJohn Marino       op0 = TREE_OPERAND (expr, 0);
3639e4b17023SJohn Marino       STRIP_NOPS (op0);
3640e4b17023SJohn Marino       op1 = NULL_TREE;
3641e4b17023SJohn Marino 
3642e4b17023SJohn Marino       if (is_gimple_val (op0))
3643e4b17023SJohn Marino 	cost0 = zero_cost;
3644e4b17023SJohn Marino       else
3645e4b17023SJohn Marino 	cost0 = force_expr_to_var_cost (op0, speed);
3646e4b17023SJohn Marino 
3647e4b17023SJohn Marino       cost1 = zero_cost;
3648e4b17023SJohn Marino       break;
3649e4b17023SJohn Marino 
3650e4b17023SJohn Marino     default:
3651e4b17023SJohn Marino       /* Just an arbitrary value, FIXME.  */
3652e4b17023SJohn Marino       return new_cost (target_spill_cost[speed], 0);
3653e4b17023SJohn Marino     }
3654e4b17023SJohn Marino 
3655e4b17023SJohn Marino   mode = TYPE_MODE (TREE_TYPE (expr));
3656e4b17023SJohn Marino   switch (TREE_CODE (expr))
3657e4b17023SJohn Marino     {
3658e4b17023SJohn Marino     case POINTER_PLUS_EXPR:
3659e4b17023SJohn Marino     case PLUS_EXPR:
3660e4b17023SJohn Marino     case MINUS_EXPR:
3661e4b17023SJohn Marino     case NEGATE_EXPR:
3662e4b17023SJohn Marino       cost = new_cost (add_cost (mode, speed), 0);
3663e4b17023SJohn Marino       if (TREE_CODE (expr) != NEGATE_EXPR)
3664e4b17023SJohn Marino         {
3665e4b17023SJohn Marino           tree mult = NULL_TREE;
3666e4b17023SJohn Marino           comp_cost sa_cost;
3667e4b17023SJohn Marino           if (TREE_CODE (op1) == MULT_EXPR)
3668e4b17023SJohn Marino             mult = op1;
3669e4b17023SJohn Marino           else if (TREE_CODE (op0) == MULT_EXPR)
3670e4b17023SJohn Marino             mult = op0;
3671e4b17023SJohn Marino 
3672e4b17023SJohn Marino           if (mult != NULL_TREE
3673e4b17023SJohn Marino               && cst_and_fits_in_hwi (TREE_OPERAND (mult, 1))
3674e4b17023SJohn Marino               && get_shiftadd_cost (expr, mode, cost0, cost1, mult, speed,
3675e4b17023SJohn Marino                                     &sa_cost))
3676e4b17023SJohn Marino             return sa_cost;
3677e4b17023SJohn Marino         }
3678e4b17023SJohn Marino       break;
3679e4b17023SJohn Marino 
3680e4b17023SJohn Marino     case MULT_EXPR:
3681e4b17023SJohn Marino       if (cst_and_fits_in_hwi (op0))
3682e4b17023SJohn Marino 	cost = new_cost (multiply_by_cost (int_cst_value (op0), mode, speed), 0);
3683e4b17023SJohn Marino       else if (cst_and_fits_in_hwi (op1))
3684e4b17023SJohn Marino 	cost = new_cost (multiply_by_cost (int_cst_value (op1), mode, speed), 0);
3685e4b17023SJohn Marino       else
3686e4b17023SJohn Marino 	return new_cost (target_spill_cost [speed], 0);
3687e4b17023SJohn Marino       break;
3688e4b17023SJohn Marino 
3689e4b17023SJohn Marino     default:
3690e4b17023SJohn Marino       gcc_unreachable ();
3691e4b17023SJohn Marino     }
3692e4b17023SJohn Marino 
3693e4b17023SJohn Marino   cost = add_costs (cost, cost0);
3694e4b17023SJohn Marino   cost = add_costs (cost, cost1);
3695e4b17023SJohn Marino 
3696e4b17023SJohn Marino   /* Bound the cost by target_spill_cost.  The parts of complicated
3697e4b17023SJohn Marino      computations often are either loop invariant or at least can
3698e4b17023SJohn Marino      be shared between several iv uses, so letting this grow without
3699e4b17023SJohn Marino      limits would not give reasonable results.  */
3700e4b17023SJohn Marino   if (cost.cost > (int) target_spill_cost [speed])
3701e4b17023SJohn Marino     cost.cost = target_spill_cost [speed];
3702e4b17023SJohn Marino 
3703e4b17023SJohn Marino   return cost;
3704e4b17023SJohn Marino }
3705e4b17023SJohn Marino 
3706e4b17023SJohn Marino /* Estimates cost of forcing EXPR into a variable.  DEPENDS_ON is a set of the
3707e4b17023SJohn Marino    invariants the computation depends on.  */
3708e4b17023SJohn Marino 
3709e4b17023SJohn Marino static comp_cost
force_var_cost(struct ivopts_data * data,tree expr,bitmap * depends_on)3710e4b17023SJohn Marino force_var_cost (struct ivopts_data *data,
3711e4b17023SJohn Marino 		tree expr, bitmap *depends_on)
3712e4b17023SJohn Marino {
3713e4b17023SJohn Marino   if (depends_on)
3714e4b17023SJohn Marino     {
3715e4b17023SJohn Marino       fd_ivopts_data = data;
3716e4b17023SJohn Marino       walk_tree (&expr, find_depends, depends_on, NULL);
3717e4b17023SJohn Marino     }
3718e4b17023SJohn Marino 
3719e4b17023SJohn Marino   return force_expr_to_var_cost (expr, data->speed);
3720e4b17023SJohn Marino }
3721e4b17023SJohn Marino 
3722e4b17023SJohn Marino /* Estimates cost of expressing address ADDR  as var + symbol + offset.  The
3723e4b17023SJohn Marino    value of offset is added to OFFSET, SYMBOL_PRESENT and VAR_PRESENT are set
3724e4b17023SJohn Marino    to false if the corresponding part is missing.  DEPENDS_ON is a set of the
3725e4b17023SJohn Marino    invariants the computation depends on.  */
3726e4b17023SJohn Marino 
3727e4b17023SJohn Marino static comp_cost
split_address_cost(struct ivopts_data * data,tree addr,bool * symbol_present,bool * var_present,unsigned HOST_WIDE_INT * offset,bitmap * depends_on)3728e4b17023SJohn Marino split_address_cost (struct ivopts_data *data,
3729e4b17023SJohn Marino 		    tree addr, bool *symbol_present, bool *var_present,
3730e4b17023SJohn Marino 		    unsigned HOST_WIDE_INT *offset, bitmap *depends_on)
3731e4b17023SJohn Marino {
3732e4b17023SJohn Marino   tree core;
3733e4b17023SJohn Marino   HOST_WIDE_INT bitsize;
3734e4b17023SJohn Marino   HOST_WIDE_INT bitpos;
3735e4b17023SJohn Marino   tree toffset;
3736e4b17023SJohn Marino   enum machine_mode mode;
3737e4b17023SJohn Marino   int unsignedp, volatilep;
3738e4b17023SJohn Marino 
3739e4b17023SJohn Marino   core = get_inner_reference (addr, &bitsize, &bitpos, &toffset, &mode,
3740e4b17023SJohn Marino 			      &unsignedp, &volatilep, false);
3741e4b17023SJohn Marino 
3742e4b17023SJohn Marino   if (toffset != 0
3743e4b17023SJohn Marino       || bitpos % BITS_PER_UNIT != 0
3744e4b17023SJohn Marino       || TREE_CODE (core) != VAR_DECL)
3745e4b17023SJohn Marino     {
3746e4b17023SJohn Marino       *symbol_present = false;
3747e4b17023SJohn Marino       *var_present = true;
3748e4b17023SJohn Marino       fd_ivopts_data = data;
3749e4b17023SJohn Marino       walk_tree (&addr, find_depends, depends_on, NULL);
3750e4b17023SJohn Marino       return new_cost (target_spill_cost[data->speed], 0);
3751e4b17023SJohn Marino     }
3752e4b17023SJohn Marino 
3753e4b17023SJohn Marino   *offset += bitpos / BITS_PER_UNIT;
3754e4b17023SJohn Marino   if (TREE_STATIC (core)
3755e4b17023SJohn Marino       || DECL_EXTERNAL (core))
3756e4b17023SJohn Marino     {
3757e4b17023SJohn Marino       *symbol_present = true;
3758e4b17023SJohn Marino       *var_present = false;
3759e4b17023SJohn Marino       return zero_cost;
3760e4b17023SJohn Marino     }
3761e4b17023SJohn Marino 
3762e4b17023SJohn Marino   *symbol_present = false;
3763e4b17023SJohn Marino   *var_present = true;
3764e4b17023SJohn Marino   return zero_cost;
3765e4b17023SJohn Marino }
3766e4b17023SJohn Marino 
3767e4b17023SJohn Marino /* Estimates cost of expressing difference of addresses E1 - E2 as
3768e4b17023SJohn Marino    var + symbol + offset.  The value of offset is added to OFFSET,
3769e4b17023SJohn Marino    SYMBOL_PRESENT and VAR_PRESENT are set to false if the corresponding
3770e4b17023SJohn Marino    part is missing.  DEPENDS_ON is a set of the invariants the computation
3771e4b17023SJohn Marino    depends on.  */
3772e4b17023SJohn Marino 
3773e4b17023SJohn Marino static comp_cost
ptr_difference_cost(struct ivopts_data * data,tree e1,tree e2,bool * symbol_present,bool * var_present,unsigned HOST_WIDE_INT * offset,bitmap * depends_on)3774e4b17023SJohn Marino ptr_difference_cost (struct ivopts_data *data,
3775e4b17023SJohn Marino 		     tree e1, tree e2, bool *symbol_present, bool *var_present,
3776e4b17023SJohn Marino 		     unsigned HOST_WIDE_INT *offset, bitmap *depends_on)
3777e4b17023SJohn Marino {
3778e4b17023SJohn Marino   HOST_WIDE_INT diff = 0;
3779e4b17023SJohn Marino   aff_tree aff_e1, aff_e2;
3780e4b17023SJohn Marino   tree type;
3781e4b17023SJohn Marino 
3782e4b17023SJohn Marino   gcc_assert (TREE_CODE (e1) == ADDR_EXPR);
3783e4b17023SJohn Marino 
3784e4b17023SJohn Marino   if (ptr_difference_const (e1, e2, &diff))
3785e4b17023SJohn Marino     {
3786e4b17023SJohn Marino       *offset += diff;
3787e4b17023SJohn Marino       *symbol_present = false;
3788e4b17023SJohn Marino       *var_present = false;
3789e4b17023SJohn Marino       return zero_cost;
3790e4b17023SJohn Marino     }
3791e4b17023SJohn Marino 
3792e4b17023SJohn Marino   if (integer_zerop (e2))
3793e4b17023SJohn Marino     return split_address_cost (data, TREE_OPERAND (e1, 0),
3794e4b17023SJohn Marino 			       symbol_present, var_present, offset, depends_on);
3795e4b17023SJohn Marino 
3796e4b17023SJohn Marino   *symbol_present = false;
3797e4b17023SJohn Marino   *var_present = true;
3798e4b17023SJohn Marino 
3799e4b17023SJohn Marino   type = signed_type_for (TREE_TYPE (e1));
3800e4b17023SJohn Marino   tree_to_aff_combination (e1, type, &aff_e1);
3801e4b17023SJohn Marino   tree_to_aff_combination (e2, type, &aff_e2);
3802e4b17023SJohn Marino   aff_combination_scale (&aff_e2, double_int_minus_one);
3803e4b17023SJohn Marino   aff_combination_add (&aff_e1, &aff_e2);
3804e4b17023SJohn Marino 
3805e4b17023SJohn Marino   return force_var_cost (data, aff_combination_to_tree (&aff_e1), depends_on);
3806e4b17023SJohn Marino }
3807e4b17023SJohn Marino 
3808e4b17023SJohn Marino /* Estimates cost of expressing difference E1 - E2 as
3809e4b17023SJohn Marino    var + symbol + offset.  The value of offset is added to OFFSET,
3810e4b17023SJohn Marino    SYMBOL_PRESENT and VAR_PRESENT are set to false if the corresponding
3811e4b17023SJohn Marino    part is missing.  DEPENDS_ON is a set of the invariants the computation
3812e4b17023SJohn Marino    depends on.  */
3813e4b17023SJohn Marino 
3814e4b17023SJohn Marino static comp_cost
difference_cost(struct ivopts_data * data,tree e1,tree e2,bool * symbol_present,bool * var_present,unsigned HOST_WIDE_INT * offset,bitmap * depends_on)3815e4b17023SJohn Marino difference_cost (struct ivopts_data *data,
3816e4b17023SJohn Marino 		 tree e1, tree e2, bool *symbol_present, bool *var_present,
3817e4b17023SJohn Marino 		 unsigned HOST_WIDE_INT *offset, bitmap *depends_on)
3818e4b17023SJohn Marino {
3819e4b17023SJohn Marino   enum machine_mode mode = TYPE_MODE (TREE_TYPE (e1));
3820e4b17023SJohn Marino   unsigned HOST_WIDE_INT off1, off2;
3821e4b17023SJohn Marino   aff_tree aff_e1, aff_e2;
3822e4b17023SJohn Marino   tree type;
3823e4b17023SJohn Marino 
3824e4b17023SJohn Marino   e1 = strip_offset (e1, &off1);
3825e4b17023SJohn Marino   e2 = strip_offset (e2, &off2);
3826e4b17023SJohn Marino   *offset += off1 - off2;
3827e4b17023SJohn Marino 
3828e4b17023SJohn Marino   STRIP_NOPS (e1);
3829e4b17023SJohn Marino   STRIP_NOPS (e2);
3830e4b17023SJohn Marino 
3831e4b17023SJohn Marino   if (TREE_CODE (e1) == ADDR_EXPR)
3832e4b17023SJohn Marino     return ptr_difference_cost (data, e1, e2, symbol_present, var_present,
3833e4b17023SJohn Marino 				offset, depends_on);
3834e4b17023SJohn Marino   *symbol_present = false;
3835e4b17023SJohn Marino 
3836e4b17023SJohn Marino   if (operand_equal_p (e1, e2, 0))
3837e4b17023SJohn Marino     {
3838e4b17023SJohn Marino       *var_present = false;
3839e4b17023SJohn Marino       return zero_cost;
3840e4b17023SJohn Marino     }
3841e4b17023SJohn Marino 
3842e4b17023SJohn Marino   *var_present = true;
3843e4b17023SJohn Marino 
3844e4b17023SJohn Marino   if (integer_zerop (e2))
3845e4b17023SJohn Marino     return force_var_cost (data, e1, depends_on);
3846e4b17023SJohn Marino 
3847e4b17023SJohn Marino   if (integer_zerop (e1))
3848e4b17023SJohn Marino     {
3849e4b17023SJohn Marino       comp_cost cost = force_var_cost (data, e2, depends_on);
3850e4b17023SJohn Marino       cost.cost += multiply_by_cost (-1, mode, data->speed);
3851e4b17023SJohn Marino       return cost;
3852e4b17023SJohn Marino     }
3853e4b17023SJohn Marino 
3854e4b17023SJohn Marino   type = signed_type_for (TREE_TYPE (e1));
3855e4b17023SJohn Marino   tree_to_aff_combination (e1, type, &aff_e1);
3856e4b17023SJohn Marino   tree_to_aff_combination (e2, type, &aff_e2);
3857e4b17023SJohn Marino   aff_combination_scale (&aff_e2, double_int_minus_one);
3858e4b17023SJohn Marino   aff_combination_add (&aff_e1, &aff_e2);
3859e4b17023SJohn Marino 
3860e4b17023SJohn Marino   return force_var_cost (data, aff_combination_to_tree (&aff_e1), depends_on);
3861e4b17023SJohn Marino }
3862e4b17023SJohn Marino 
3863e4b17023SJohn Marino /* Returns true if AFF1 and AFF2 are identical.  */
3864e4b17023SJohn Marino 
3865e4b17023SJohn Marino static bool
compare_aff_trees(aff_tree * aff1,aff_tree * aff2)3866e4b17023SJohn Marino compare_aff_trees (aff_tree *aff1, aff_tree *aff2)
3867e4b17023SJohn Marino {
3868e4b17023SJohn Marino   unsigned i;
3869e4b17023SJohn Marino 
3870e4b17023SJohn Marino   if (aff1->n != aff2->n)
3871e4b17023SJohn Marino     return false;
3872e4b17023SJohn Marino 
3873e4b17023SJohn Marino   for (i = 0; i < aff1->n; i++)
3874e4b17023SJohn Marino     {
3875e4b17023SJohn Marino       if (double_int_cmp (aff1->elts[i].coef, aff2->elts[i].coef, 0) != 0)
3876e4b17023SJohn Marino         return false;
3877e4b17023SJohn Marino 
3878e4b17023SJohn Marino       if (!operand_equal_p (aff1->elts[i].val, aff2->elts[i].val, 0))
3879e4b17023SJohn Marino         return false;
3880e4b17023SJohn Marino     }
3881e4b17023SJohn Marino   return true;
3882e4b17023SJohn Marino }
3883e4b17023SJohn Marino 
3884e4b17023SJohn Marino /* Stores EXPR in DATA->inv_expr_tab, and assigns it an inv_expr_id.  */
3885e4b17023SJohn Marino 
3886e4b17023SJohn Marino static int
get_expr_id(struct ivopts_data * data,tree expr)3887e4b17023SJohn Marino get_expr_id (struct ivopts_data *data, tree expr)
3888e4b17023SJohn Marino {
3889e4b17023SJohn Marino   struct iv_inv_expr_ent ent;
3890e4b17023SJohn Marino   struct iv_inv_expr_ent **slot;
3891e4b17023SJohn Marino 
3892e4b17023SJohn Marino   ent.expr = expr;
3893e4b17023SJohn Marino   ent.hash = iterative_hash_expr (expr, 0);
3894e4b17023SJohn Marino   slot = (struct iv_inv_expr_ent **) htab_find_slot (data->inv_expr_tab,
3895e4b17023SJohn Marino                                                      &ent, INSERT);
3896e4b17023SJohn Marino   if (*slot)
3897e4b17023SJohn Marino     return (*slot)->id;
3898e4b17023SJohn Marino 
3899e4b17023SJohn Marino   *slot = XNEW (struct iv_inv_expr_ent);
3900e4b17023SJohn Marino   (*slot)->expr = expr;
3901e4b17023SJohn Marino   (*slot)->hash = ent.hash;
3902e4b17023SJohn Marino   (*slot)->id = data->inv_expr_id++;
3903e4b17023SJohn Marino   return (*slot)->id;
3904e4b17023SJohn Marino }
3905e4b17023SJohn Marino 
3906e4b17023SJohn Marino /* Returns the pseudo expr id if expression UBASE - RATIO * CBASE
3907e4b17023SJohn Marino    requires a new compiler generated temporary.  Returns -1 otherwise.
3908e4b17023SJohn Marino    ADDRESS_P is a flag indicating if the expression is for address
3909e4b17023SJohn Marino    computation.  */
3910e4b17023SJohn Marino 
3911e4b17023SJohn Marino static int
get_loop_invariant_expr_id(struct ivopts_data * data,tree ubase,tree cbase,HOST_WIDE_INT ratio,bool address_p)3912e4b17023SJohn Marino get_loop_invariant_expr_id (struct ivopts_data *data, tree ubase,
3913e4b17023SJohn Marino                             tree cbase, HOST_WIDE_INT ratio,
3914e4b17023SJohn Marino                             bool address_p)
3915e4b17023SJohn Marino {
3916e4b17023SJohn Marino   aff_tree ubase_aff, cbase_aff;
3917e4b17023SJohn Marino   tree expr, ub, cb;
3918e4b17023SJohn Marino 
3919e4b17023SJohn Marino   STRIP_NOPS (ubase);
3920e4b17023SJohn Marino   STRIP_NOPS (cbase);
3921e4b17023SJohn Marino   ub = ubase;
3922e4b17023SJohn Marino   cb = cbase;
3923e4b17023SJohn Marino 
3924e4b17023SJohn Marino   if ((TREE_CODE (ubase) == INTEGER_CST)
3925e4b17023SJohn Marino       && (TREE_CODE (cbase) == INTEGER_CST))
3926e4b17023SJohn Marino     return -1;
3927e4b17023SJohn Marino 
3928e4b17023SJohn Marino   /* Strips the constant part. */
3929e4b17023SJohn Marino   if (TREE_CODE (ubase) == PLUS_EXPR
3930e4b17023SJohn Marino       || TREE_CODE (ubase) == MINUS_EXPR
3931e4b17023SJohn Marino       || TREE_CODE (ubase) == POINTER_PLUS_EXPR)
3932e4b17023SJohn Marino     {
3933e4b17023SJohn Marino       if (TREE_CODE (TREE_OPERAND (ubase, 1)) == INTEGER_CST)
3934e4b17023SJohn Marino         ubase = TREE_OPERAND (ubase, 0);
3935e4b17023SJohn Marino     }
3936e4b17023SJohn Marino 
3937e4b17023SJohn Marino   /* Strips the constant part. */
3938e4b17023SJohn Marino   if (TREE_CODE (cbase) == PLUS_EXPR
3939e4b17023SJohn Marino       || TREE_CODE (cbase) == MINUS_EXPR
3940e4b17023SJohn Marino       || TREE_CODE (cbase) == POINTER_PLUS_EXPR)
3941e4b17023SJohn Marino     {
3942e4b17023SJohn Marino       if (TREE_CODE (TREE_OPERAND (cbase, 1)) == INTEGER_CST)
3943e4b17023SJohn Marino         cbase = TREE_OPERAND (cbase, 0);
3944e4b17023SJohn Marino     }
3945e4b17023SJohn Marino 
3946e4b17023SJohn Marino   if (address_p)
3947e4b17023SJohn Marino     {
3948e4b17023SJohn Marino       if (((TREE_CODE (ubase) == SSA_NAME)
3949e4b17023SJohn Marino            || (TREE_CODE (ubase) == ADDR_EXPR
3950e4b17023SJohn Marino                && is_gimple_min_invariant (ubase)))
3951e4b17023SJohn Marino           && (TREE_CODE (cbase) == INTEGER_CST))
3952e4b17023SJohn Marino         return -1;
3953e4b17023SJohn Marino 
3954e4b17023SJohn Marino       if (((TREE_CODE (cbase) == SSA_NAME)
3955e4b17023SJohn Marino            || (TREE_CODE (cbase) == ADDR_EXPR
3956e4b17023SJohn Marino                && is_gimple_min_invariant (cbase)))
3957e4b17023SJohn Marino           && (TREE_CODE (ubase) == INTEGER_CST))
3958e4b17023SJohn Marino         return -1;
3959e4b17023SJohn Marino     }
3960e4b17023SJohn Marino 
3961e4b17023SJohn Marino   if (ratio == 1)
3962e4b17023SJohn Marino     {
3963e4b17023SJohn Marino       if(operand_equal_p (ubase, cbase, 0))
3964e4b17023SJohn Marino         return -1;
3965e4b17023SJohn Marino 
3966e4b17023SJohn Marino       if (TREE_CODE (ubase) == ADDR_EXPR
3967e4b17023SJohn Marino           && TREE_CODE (cbase) == ADDR_EXPR)
3968e4b17023SJohn Marino         {
3969e4b17023SJohn Marino           tree usym, csym;
3970e4b17023SJohn Marino 
3971e4b17023SJohn Marino           usym = TREE_OPERAND (ubase, 0);
3972e4b17023SJohn Marino           csym = TREE_OPERAND (cbase, 0);
3973e4b17023SJohn Marino           if (TREE_CODE (usym) == ARRAY_REF)
3974e4b17023SJohn Marino             {
3975e4b17023SJohn Marino               tree ind = TREE_OPERAND (usym, 1);
3976e4b17023SJohn Marino               if (TREE_CODE (ind) == INTEGER_CST
3977e4b17023SJohn Marino                   && host_integerp (ind, 0)
3978e4b17023SJohn Marino                   && TREE_INT_CST_LOW (ind) == 0)
3979e4b17023SJohn Marino                 usym = TREE_OPERAND (usym, 0);
3980e4b17023SJohn Marino             }
3981e4b17023SJohn Marino           if (TREE_CODE (csym) == ARRAY_REF)
3982e4b17023SJohn Marino             {
3983e4b17023SJohn Marino               tree ind = TREE_OPERAND (csym, 1);
3984e4b17023SJohn Marino               if (TREE_CODE (ind) == INTEGER_CST
3985e4b17023SJohn Marino                   && host_integerp (ind, 0)
3986e4b17023SJohn Marino                   && TREE_INT_CST_LOW (ind) == 0)
3987e4b17023SJohn Marino                 csym = TREE_OPERAND (csym, 0);
3988e4b17023SJohn Marino             }
3989e4b17023SJohn Marino           if (operand_equal_p (usym, csym, 0))
3990e4b17023SJohn Marino             return -1;
3991e4b17023SJohn Marino         }
3992e4b17023SJohn Marino       /* Now do more complex comparison  */
3993e4b17023SJohn Marino       tree_to_aff_combination (ubase, TREE_TYPE (ubase), &ubase_aff);
3994e4b17023SJohn Marino       tree_to_aff_combination (cbase, TREE_TYPE (cbase), &cbase_aff);
3995e4b17023SJohn Marino       if (compare_aff_trees (&ubase_aff, &cbase_aff))
3996e4b17023SJohn Marino         return -1;
3997e4b17023SJohn Marino     }
3998e4b17023SJohn Marino 
3999e4b17023SJohn Marino   tree_to_aff_combination (ub, TREE_TYPE (ub), &ubase_aff);
4000e4b17023SJohn Marino   tree_to_aff_combination (cb, TREE_TYPE (cb), &cbase_aff);
4001e4b17023SJohn Marino 
4002e4b17023SJohn Marino   aff_combination_scale (&cbase_aff, shwi_to_double_int (-1 * ratio));
4003e4b17023SJohn Marino   aff_combination_add (&ubase_aff, &cbase_aff);
4004e4b17023SJohn Marino   expr = aff_combination_to_tree (&ubase_aff);
4005e4b17023SJohn Marino   return get_expr_id (data, expr);
4006e4b17023SJohn Marino }
4007e4b17023SJohn Marino 
4008e4b17023SJohn Marino 
4009e4b17023SJohn Marino 
4010e4b17023SJohn Marino /* Determines the cost of the computation by that USE is expressed
4011e4b17023SJohn Marino    from induction variable CAND.  If ADDRESS_P is true, we just need
4012e4b17023SJohn Marino    to create an address from it, otherwise we want to get it into
4013e4b17023SJohn Marino    register.  A set of invariants we depend on is stored in
4014e4b17023SJohn Marino    DEPENDS_ON.  AT is the statement at that the value is computed.
4015e4b17023SJohn Marino    If CAN_AUTOINC is nonnull, use it to record whether autoinc
4016e4b17023SJohn Marino    addressing is likely.  */
4017e4b17023SJohn Marino 
4018e4b17023SJohn Marino static comp_cost
get_computation_cost_at(struct ivopts_data * data,struct iv_use * use,struct iv_cand * cand,bool address_p,bitmap * depends_on,gimple at,bool * can_autoinc,int * inv_expr_id)4019e4b17023SJohn Marino get_computation_cost_at (struct ivopts_data *data,
4020e4b17023SJohn Marino 			 struct iv_use *use, struct iv_cand *cand,
4021e4b17023SJohn Marino 			 bool address_p, bitmap *depends_on, gimple at,
4022e4b17023SJohn Marino 			 bool *can_autoinc,
4023e4b17023SJohn Marino                          int *inv_expr_id)
4024e4b17023SJohn Marino {
4025e4b17023SJohn Marino   tree ubase = use->iv->base, ustep = use->iv->step;
4026e4b17023SJohn Marino   tree cbase, cstep;
4027e4b17023SJohn Marino   tree utype = TREE_TYPE (ubase), ctype;
4028e4b17023SJohn Marino   unsigned HOST_WIDE_INT cstepi, offset = 0;
4029e4b17023SJohn Marino   HOST_WIDE_INT ratio, aratio;
4030e4b17023SJohn Marino   bool var_present, symbol_present, stmt_is_after_inc;
4031e4b17023SJohn Marino   comp_cost cost;
4032e4b17023SJohn Marino   double_int rat;
4033e4b17023SJohn Marino   bool speed = optimize_bb_for_speed_p (gimple_bb (at));
4034e4b17023SJohn Marino 
4035e4b17023SJohn Marino   *depends_on = NULL;
4036e4b17023SJohn Marino 
4037e4b17023SJohn Marino   /* Only consider real candidates.  */
4038e4b17023SJohn Marino   if (!cand->iv)
4039e4b17023SJohn Marino     return infinite_cost;
4040e4b17023SJohn Marino 
4041e4b17023SJohn Marino   cbase = cand->iv->base;
4042e4b17023SJohn Marino   cstep = cand->iv->step;
4043e4b17023SJohn Marino   ctype = TREE_TYPE (cbase);
4044e4b17023SJohn Marino 
4045e4b17023SJohn Marino   if (TYPE_PRECISION (utype) > TYPE_PRECISION (ctype))
4046e4b17023SJohn Marino     {
4047e4b17023SJohn Marino       /* We do not have a precision to express the values of use.  */
4048e4b17023SJohn Marino       return infinite_cost;
4049e4b17023SJohn Marino     }
4050e4b17023SJohn Marino 
4051e4b17023SJohn Marino   if (address_p
4052e4b17023SJohn Marino       || (use->iv->base_object
4053e4b17023SJohn Marino 	  && cand->iv->base_object
4054e4b17023SJohn Marino 	  && POINTER_TYPE_P (TREE_TYPE (use->iv->base_object))
4055e4b17023SJohn Marino 	  && POINTER_TYPE_P (TREE_TYPE (cand->iv->base_object))))
4056e4b17023SJohn Marino     {
4057e4b17023SJohn Marino       /* Do not try to express address of an object with computation based
4058e4b17023SJohn Marino 	 on address of a different object.  This may cause problems in rtl
4059e4b17023SJohn Marino 	 level alias analysis (that does not expect this to be happening,
4060e4b17023SJohn Marino 	 as this is illegal in C), and would be unlikely to be useful
4061e4b17023SJohn Marino 	 anyway.  */
4062e4b17023SJohn Marino       if (use->iv->base_object
4063e4b17023SJohn Marino 	  && cand->iv->base_object
4064e4b17023SJohn Marino 	  && !operand_equal_p (use->iv->base_object, cand->iv->base_object, 0))
4065e4b17023SJohn Marino 	return infinite_cost;
4066e4b17023SJohn Marino     }
4067e4b17023SJohn Marino 
4068e4b17023SJohn Marino   if (TYPE_PRECISION (utype) < TYPE_PRECISION (ctype))
4069e4b17023SJohn Marino     {
4070e4b17023SJohn Marino       /* TODO -- add direct handling of this case.  */
4071e4b17023SJohn Marino       goto fallback;
4072e4b17023SJohn Marino     }
4073e4b17023SJohn Marino 
4074e4b17023SJohn Marino   /* CSTEPI is removed from the offset in case statement is after the
4075e4b17023SJohn Marino      increment.  If the step is not constant, we use zero instead.
4076e4b17023SJohn Marino      This is a bit imprecise (there is the extra addition), but
4077e4b17023SJohn Marino      redundancy elimination is likely to transform the code so that
4078e4b17023SJohn Marino      it uses value of the variable before increment anyway,
4079e4b17023SJohn Marino      so it is not that much unrealistic.  */
4080e4b17023SJohn Marino   if (cst_and_fits_in_hwi (cstep))
4081e4b17023SJohn Marino     cstepi = int_cst_value (cstep);
4082e4b17023SJohn Marino   else
4083e4b17023SJohn Marino     cstepi = 0;
4084e4b17023SJohn Marino 
4085e4b17023SJohn Marino   if (!constant_multiple_of (ustep, cstep, &rat))
4086e4b17023SJohn Marino     return infinite_cost;
4087e4b17023SJohn Marino 
4088e4b17023SJohn Marino   if (double_int_fits_in_shwi_p (rat))
4089e4b17023SJohn Marino     ratio = double_int_to_shwi (rat);
4090e4b17023SJohn Marino   else
4091e4b17023SJohn Marino     return infinite_cost;
4092e4b17023SJohn Marino 
4093e4b17023SJohn Marino   STRIP_NOPS (cbase);
4094e4b17023SJohn Marino   ctype = TREE_TYPE (cbase);
4095e4b17023SJohn Marino 
4096e4b17023SJohn Marino   stmt_is_after_inc = stmt_after_increment (data->current_loop, cand, at);
4097e4b17023SJohn Marino 
4098e4b17023SJohn Marino   /* use = ubase + ratio * (var - cbase).  If either cbase is a constant
4099e4b17023SJohn Marino      or ratio == 1, it is better to handle this like
4100e4b17023SJohn Marino 
4101e4b17023SJohn Marino      ubase - ratio * cbase + ratio * var
4102e4b17023SJohn Marino 
4103e4b17023SJohn Marino      (also holds in the case ratio == -1, TODO.  */
4104e4b17023SJohn Marino 
4105e4b17023SJohn Marino   if (cst_and_fits_in_hwi (cbase))
4106e4b17023SJohn Marino     {
4107e4b17023SJohn Marino       offset = - ratio * int_cst_value (cbase);
4108e4b17023SJohn Marino       cost = difference_cost (data,
4109e4b17023SJohn Marino 			      ubase, build_int_cst (utype, 0),
4110e4b17023SJohn Marino 			      &symbol_present, &var_present, &offset,
4111e4b17023SJohn Marino 			      depends_on);
4112e4b17023SJohn Marino       cost.cost /= avg_loop_niter (data->current_loop);
4113e4b17023SJohn Marino     }
4114e4b17023SJohn Marino   else if (ratio == 1)
4115e4b17023SJohn Marino     {
4116e4b17023SJohn Marino       tree real_cbase = cbase;
4117e4b17023SJohn Marino 
4118e4b17023SJohn Marino       /* Check to see if any adjustment is needed.  */
4119e4b17023SJohn Marino       if (cstepi == 0 && stmt_is_after_inc)
4120e4b17023SJohn Marino         {
4121e4b17023SJohn Marino           aff_tree real_cbase_aff;
4122e4b17023SJohn Marino           aff_tree cstep_aff;
4123e4b17023SJohn Marino 
4124e4b17023SJohn Marino           tree_to_aff_combination (cbase, TREE_TYPE (real_cbase),
4125e4b17023SJohn Marino                                    &real_cbase_aff);
4126e4b17023SJohn Marino           tree_to_aff_combination (cstep, TREE_TYPE (cstep), &cstep_aff);
4127e4b17023SJohn Marino 
4128e4b17023SJohn Marino           aff_combination_add (&real_cbase_aff, &cstep_aff);
4129e4b17023SJohn Marino           real_cbase = aff_combination_to_tree (&real_cbase_aff);
4130e4b17023SJohn Marino         }
4131e4b17023SJohn Marino 
4132e4b17023SJohn Marino       cost = difference_cost (data,
4133e4b17023SJohn Marino 			      ubase, real_cbase,
4134e4b17023SJohn Marino 			      &symbol_present, &var_present, &offset,
4135e4b17023SJohn Marino 			      depends_on);
4136e4b17023SJohn Marino       cost.cost /= avg_loop_niter (data->current_loop);
4137e4b17023SJohn Marino     }
4138e4b17023SJohn Marino   else if (address_p
4139e4b17023SJohn Marino 	   && !POINTER_TYPE_P (ctype)
4140e4b17023SJohn Marino 	   && multiplier_allowed_in_address_p
4141e4b17023SJohn Marino 		(ratio, TYPE_MODE (TREE_TYPE (utype)),
4142e4b17023SJohn Marino 			TYPE_ADDR_SPACE (TREE_TYPE (utype))))
4143e4b17023SJohn Marino     {
4144e4b17023SJohn Marino       cbase
4145e4b17023SJohn Marino 	= fold_build2 (MULT_EXPR, ctype, cbase, build_int_cst (ctype, ratio));
4146e4b17023SJohn Marino       cost = difference_cost (data,
4147e4b17023SJohn Marino 			      ubase, cbase,
4148e4b17023SJohn Marino 			      &symbol_present, &var_present, &offset,
4149e4b17023SJohn Marino 			      depends_on);
4150e4b17023SJohn Marino       cost.cost /= avg_loop_niter (data->current_loop);
4151e4b17023SJohn Marino     }
4152e4b17023SJohn Marino   else
4153e4b17023SJohn Marino     {
4154e4b17023SJohn Marino       cost = force_var_cost (data, cbase, depends_on);
4155e4b17023SJohn Marino       cost = add_costs (cost,
4156e4b17023SJohn Marino 			difference_cost (data,
4157e4b17023SJohn Marino 					 ubase, build_int_cst (utype, 0),
4158e4b17023SJohn Marino 					 &symbol_present, &var_present,
4159e4b17023SJohn Marino 					 &offset, depends_on));
4160e4b17023SJohn Marino       cost.cost /= avg_loop_niter (data->current_loop);
4161e4b17023SJohn Marino       cost.cost += add_cost (TYPE_MODE (ctype), data->speed);
4162e4b17023SJohn Marino     }
4163e4b17023SJohn Marino 
4164e4b17023SJohn Marino   if (inv_expr_id)
4165e4b17023SJohn Marino     {
4166e4b17023SJohn Marino       *inv_expr_id =
4167e4b17023SJohn Marino           get_loop_invariant_expr_id (data, ubase, cbase, ratio, address_p);
4168e4b17023SJohn Marino       /* Clear depends on.  */
4169e4b17023SJohn Marino       if (*inv_expr_id != -1 && depends_on && *depends_on)
4170e4b17023SJohn Marino         bitmap_clear (*depends_on);
4171e4b17023SJohn Marino     }
4172e4b17023SJohn Marino 
4173e4b17023SJohn Marino   /* If we are after the increment, the value of the candidate is higher by
4174e4b17023SJohn Marino      one iteration.  */
4175e4b17023SJohn Marino   if (stmt_is_after_inc)
4176e4b17023SJohn Marino     offset -= ratio * cstepi;
4177e4b17023SJohn Marino 
4178e4b17023SJohn Marino   /* Now the computation is in shape symbol + var1 + const + ratio * var2.
4179e4b17023SJohn Marino      (symbol/var1/const parts may be omitted).  If we are looking for an
4180e4b17023SJohn Marino      address, find the cost of addressing this.  */
4181e4b17023SJohn Marino   if (address_p)
4182e4b17023SJohn Marino     return add_costs (cost,
4183e4b17023SJohn Marino 		      get_address_cost (symbol_present, var_present,
4184e4b17023SJohn Marino 					offset, ratio, cstepi,
4185e4b17023SJohn Marino 					TYPE_MODE (TREE_TYPE (utype)),
4186e4b17023SJohn Marino 					TYPE_ADDR_SPACE (TREE_TYPE (utype)),
4187e4b17023SJohn Marino 					speed, stmt_is_after_inc,
4188e4b17023SJohn Marino 					can_autoinc));
4189e4b17023SJohn Marino 
4190e4b17023SJohn Marino   /* Otherwise estimate the costs for computing the expression.  */
4191e4b17023SJohn Marino   if (!symbol_present && !var_present && !offset)
4192e4b17023SJohn Marino     {
4193e4b17023SJohn Marino       if (ratio != 1)
4194e4b17023SJohn Marino 	cost.cost += multiply_by_cost (ratio, TYPE_MODE (ctype), speed);
4195e4b17023SJohn Marino       return cost;
4196e4b17023SJohn Marino     }
4197e4b17023SJohn Marino 
4198e4b17023SJohn Marino   /* Symbol + offset should be compile-time computable so consider that they
4199e4b17023SJohn Marino       are added once to the variable, if present.  */
4200e4b17023SJohn Marino   if (var_present && (symbol_present || offset))
4201e4b17023SJohn Marino     cost.cost += adjust_setup_cost (data,
4202e4b17023SJohn Marino 				    add_cost (TYPE_MODE (ctype), speed));
4203e4b17023SJohn Marino 
4204e4b17023SJohn Marino   /* Having offset does not affect runtime cost in case it is added to
4205e4b17023SJohn Marino      symbol, but it increases complexity.  */
4206e4b17023SJohn Marino   if (offset)
4207e4b17023SJohn Marino     cost.complexity++;
4208e4b17023SJohn Marino 
4209e4b17023SJohn Marino   cost.cost += add_cost (TYPE_MODE (ctype), speed);
4210e4b17023SJohn Marino 
4211e4b17023SJohn Marino   aratio = ratio > 0 ? ratio : -ratio;
4212e4b17023SJohn Marino   if (aratio != 1)
4213e4b17023SJohn Marino     cost.cost += multiply_by_cost (aratio, TYPE_MODE (ctype), speed);
4214e4b17023SJohn Marino   return cost;
4215e4b17023SJohn Marino 
4216e4b17023SJohn Marino fallback:
4217e4b17023SJohn Marino   if (can_autoinc)
4218e4b17023SJohn Marino     *can_autoinc = false;
4219e4b17023SJohn Marino 
4220e4b17023SJohn Marino   {
4221e4b17023SJohn Marino     /* Just get the expression, expand it and measure the cost.  */
4222e4b17023SJohn Marino     tree comp = get_computation_at (data->current_loop, use, cand, at);
4223e4b17023SJohn Marino 
4224e4b17023SJohn Marino     if (!comp)
4225e4b17023SJohn Marino       return infinite_cost;
4226e4b17023SJohn Marino 
4227e4b17023SJohn Marino     if (address_p)
4228e4b17023SJohn Marino       comp = build_simple_mem_ref (comp);
4229e4b17023SJohn Marino 
4230e4b17023SJohn Marino     return new_cost (computation_cost (comp, speed), 0);
4231e4b17023SJohn Marino   }
4232e4b17023SJohn Marino }
4233e4b17023SJohn Marino 
4234e4b17023SJohn Marino /* Determines the cost of the computation by that USE is expressed
4235e4b17023SJohn Marino    from induction variable CAND.  If ADDRESS_P is true, we just need
4236e4b17023SJohn Marino    to create an address from it, otherwise we want to get it into
4237e4b17023SJohn Marino    register.  A set of invariants we depend on is stored in
4238e4b17023SJohn Marino    DEPENDS_ON.  If CAN_AUTOINC is nonnull, use it to record whether
4239e4b17023SJohn Marino    autoinc addressing is likely.  */
4240e4b17023SJohn Marino 
4241e4b17023SJohn Marino static comp_cost
get_computation_cost(struct ivopts_data * data,struct iv_use * use,struct iv_cand * cand,bool address_p,bitmap * depends_on,bool * can_autoinc,int * inv_expr_id)4242e4b17023SJohn Marino get_computation_cost (struct ivopts_data *data,
4243e4b17023SJohn Marino 		      struct iv_use *use, struct iv_cand *cand,
4244e4b17023SJohn Marino 		      bool address_p, bitmap *depends_on,
4245e4b17023SJohn Marino                       bool *can_autoinc, int *inv_expr_id)
4246e4b17023SJohn Marino {
4247e4b17023SJohn Marino   return get_computation_cost_at (data,
4248e4b17023SJohn Marino 				  use, cand, address_p, depends_on, use->stmt,
4249e4b17023SJohn Marino 				  can_autoinc, inv_expr_id);
4250e4b17023SJohn Marino }
4251e4b17023SJohn Marino 
4252e4b17023SJohn Marino /* Determines cost of basing replacement of USE on CAND in a generic
4253e4b17023SJohn Marino    expression.  */
4254e4b17023SJohn Marino 
4255e4b17023SJohn Marino static bool
determine_use_iv_cost_generic(struct ivopts_data * data,struct iv_use * use,struct iv_cand * cand)4256e4b17023SJohn Marino determine_use_iv_cost_generic (struct ivopts_data *data,
4257e4b17023SJohn Marino 			       struct iv_use *use, struct iv_cand *cand)
4258e4b17023SJohn Marino {
4259e4b17023SJohn Marino   bitmap depends_on;
4260e4b17023SJohn Marino   comp_cost cost;
4261e4b17023SJohn Marino   int inv_expr_id = -1;
4262e4b17023SJohn Marino 
4263e4b17023SJohn Marino   /* The simple case first -- if we need to express value of the preserved
4264e4b17023SJohn Marino      original biv, the cost is 0.  This also prevents us from counting the
4265e4b17023SJohn Marino      cost of increment twice -- once at this use and once in the cost of
4266e4b17023SJohn Marino      the candidate.  */
4267e4b17023SJohn Marino   if (cand->pos == IP_ORIGINAL
4268e4b17023SJohn Marino       && cand->incremented_at == use->stmt)
4269e4b17023SJohn Marino     {
4270e4b17023SJohn Marino       set_use_iv_cost (data, use, cand, zero_cost, NULL, NULL_TREE,
4271e4b17023SJohn Marino                        ERROR_MARK, -1);
4272e4b17023SJohn Marino       return true;
4273e4b17023SJohn Marino     }
4274e4b17023SJohn Marino 
4275e4b17023SJohn Marino   cost = get_computation_cost (data, use, cand, false, &depends_on,
4276e4b17023SJohn Marino                                NULL, &inv_expr_id);
4277e4b17023SJohn Marino 
4278e4b17023SJohn Marino   set_use_iv_cost (data, use, cand, cost, depends_on, NULL_TREE, ERROR_MARK,
4279e4b17023SJohn Marino                    inv_expr_id);
4280e4b17023SJohn Marino 
4281e4b17023SJohn Marino   return !infinite_cost_p (cost);
4282e4b17023SJohn Marino }
4283e4b17023SJohn Marino 
4284e4b17023SJohn Marino /* Determines cost of basing replacement of USE on CAND in an address.  */
4285e4b17023SJohn Marino 
4286e4b17023SJohn Marino static bool
determine_use_iv_cost_address(struct ivopts_data * data,struct iv_use * use,struct iv_cand * cand)4287e4b17023SJohn Marino determine_use_iv_cost_address (struct ivopts_data *data,
4288e4b17023SJohn Marino 			       struct iv_use *use, struct iv_cand *cand)
4289e4b17023SJohn Marino {
4290e4b17023SJohn Marino   bitmap depends_on;
4291e4b17023SJohn Marino   bool can_autoinc;
4292e4b17023SJohn Marino   int inv_expr_id = -1;
4293e4b17023SJohn Marino   comp_cost cost = get_computation_cost (data, use, cand, true, &depends_on,
4294e4b17023SJohn Marino 					 &can_autoinc, &inv_expr_id);
4295e4b17023SJohn Marino 
4296e4b17023SJohn Marino   if (cand->ainc_use == use)
4297e4b17023SJohn Marino     {
4298e4b17023SJohn Marino       if (can_autoinc)
4299e4b17023SJohn Marino 	cost.cost -= cand->cost_step;
4300e4b17023SJohn Marino       /* If we generated the candidate solely for exploiting autoincrement
4301e4b17023SJohn Marino 	 opportunities, and it turns out it can't be used, set the cost to
4302e4b17023SJohn Marino 	 infinity to make sure we ignore it.  */
4303e4b17023SJohn Marino       else if (cand->pos == IP_AFTER_USE || cand->pos == IP_BEFORE_USE)
4304e4b17023SJohn Marino 	cost = infinite_cost;
4305e4b17023SJohn Marino     }
4306e4b17023SJohn Marino   set_use_iv_cost (data, use, cand, cost, depends_on, NULL_TREE, ERROR_MARK,
4307e4b17023SJohn Marino                    inv_expr_id);
4308e4b17023SJohn Marino 
4309e4b17023SJohn Marino   return !infinite_cost_p (cost);
4310e4b17023SJohn Marino }
4311e4b17023SJohn Marino 
4312e4b17023SJohn Marino /* Computes value of candidate CAND at position AT in iteration NITER, and
4313e4b17023SJohn Marino    stores it to VAL.  */
4314e4b17023SJohn Marino 
4315e4b17023SJohn Marino static void
cand_value_at(struct loop * loop,struct iv_cand * cand,gimple at,tree niter,aff_tree * val)4316e4b17023SJohn Marino cand_value_at (struct loop *loop, struct iv_cand *cand, gimple at, tree niter,
4317e4b17023SJohn Marino 	       aff_tree *val)
4318e4b17023SJohn Marino {
4319e4b17023SJohn Marino   aff_tree step, delta, nit;
4320e4b17023SJohn Marino   struct iv *iv = cand->iv;
4321e4b17023SJohn Marino   tree type = TREE_TYPE (iv->base);
4322e4b17023SJohn Marino   tree steptype = type;
4323e4b17023SJohn Marino   if (POINTER_TYPE_P (type))
4324e4b17023SJohn Marino     steptype = sizetype;
4325e4b17023SJohn Marino 
4326e4b17023SJohn Marino   tree_to_aff_combination (iv->step, steptype, &step);
4327e4b17023SJohn Marino   tree_to_aff_combination (niter, TREE_TYPE (niter), &nit);
4328e4b17023SJohn Marino   aff_combination_convert (&nit, steptype);
4329e4b17023SJohn Marino   aff_combination_mult (&nit, &step, &delta);
4330e4b17023SJohn Marino   if (stmt_after_increment (loop, cand, at))
4331e4b17023SJohn Marino     aff_combination_add (&delta, &step);
4332e4b17023SJohn Marino 
4333e4b17023SJohn Marino   tree_to_aff_combination (iv->base, type, val);
4334e4b17023SJohn Marino   aff_combination_add (val, &delta);
4335e4b17023SJohn Marino }
4336e4b17023SJohn Marino 
4337e4b17023SJohn Marino /* Returns period of induction variable iv.  */
4338e4b17023SJohn Marino 
4339e4b17023SJohn Marino static tree
iv_period(struct iv * iv)4340e4b17023SJohn Marino iv_period (struct iv *iv)
4341e4b17023SJohn Marino {
4342e4b17023SJohn Marino   tree step = iv->step, period, type;
4343e4b17023SJohn Marino   tree pow2div;
4344e4b17023SJohn Marino 
4345e4b17023SJohn Marino   gcc_assert (step && TREE_CODE (step) == INTEGER_CST);
4346e4b17023SJohn Marino 
4347e4b17023SJohn Marino   type = unsigned_type_for (TREE_TYPE (step));
4348e4b17023SJohn Marino   /* Period of the iv is lcm (step, type_range)/step -1,
4349e4b17023SJohn Marino      i.e., N*type_range/step - 1. Since type range is power
4350e4b17023SJohn Marino      of two, N == (step >> num_of_ending_zeros_binary (step),
4351e4b17023SJohn Marino      so the final result is
4352e4b17023SJohn Marino 
4353e4b17023SJohn Marino        (type_range >> num_of_ending_zeros_binary (step)) - 1
4354e4b17023SJohn Marino 
4355e4b17023SJohn Marino   */
4356e4b17023SJohn Marino   pow2div = num_ending_zeros (step);
4357e4b17023SJohn Marino 
4358e4b17023SJohn Marino   period = build_low_bits_mask (type,
4359e4b17023SJohn Marino                                 (TYPE_PRECISION (type)
4360e4b17023SJohn Marino                                  - tree_low_cst (pow2div, 1)));
4361e4b17023SJohn Marino 
4362e4b17023SJohn Marino   return period;
4363e4b17023SJohn Marino }
4364e4b17023SJohn Marino 
4365e4b17023SJohn Marino /* Returns the comparison operator used when eliminating the iv USE.  */
4366e4b17023SJohn Marino 
4367e4b17023SJohn Marino static enum tree_code
iv_elimination_compare(struct ivopts_data * data,struct iv_use * use)4368e4b17023SJohn Marino iv_elimination_compare (struct ivopts_data *data, struct iv_use *use)
4369e4b17023SJohn Marino {
4370e4b17023SJohn Marino   struct loop *loop = data->current_loop;
4371e4b17023SJohn Marino   basic_block ex_bb;
4372e4b17023SJohn Marino   edge exit;
4373e4b17023SJohn Marino 
4374e4b17023SJohn Marino   ex_bb = gimple_bb (use->stmt);
4375e4b17023SJohn Marino   exit = EDGE_SUCC (ex_bb, 0);
4376e4b17023SJohn Marino   if (flow_bb_inside_loop_p (loop, exit->dest))
4377e4b17023SJohn Marino     exit = EDGE_SUCC (ex_bb, 1);
4378e4b17023SJohn Marino 
4379e4b17023SJohn Marino   return (exit->flags & EDGE_TRUE_VALUE ? EQ_EXPR : NE_EXPR);
4380e4b17023SJohn Marino }
4381e4b17023SJohn Marino 
4382e4b17023SJohn Marino static tree
strip_wrap_conserving_type_conversions(tree exp)4383e4b17023SJohn Marino strip_wrap_conserving_type_conversions (tree exp)
4384e4b17023SJohn Marino {
4385e4b17023SJohn Marino   while (tree_ssa_useless_type_conversion (exp)
4386e4b17023SJohn Marino 	 && (nowrap_type_p (TREE_TYPE (exp))
4387e4b17023SJohn Marino 	     == nowrap_type_p (TREE_TYPE (TREE_OPERAND (exp, 0)))))
4388e4b17023SJohn Marino     exp = TREE_OPERAND (exp, 0);
4389e4b17023SJohn Marino   return exp;
4390e4b17023SJohn Marino }
4391e4b17023SJohn Marino 
4392e4b17023SJohn Marino /* Walk the SSA form and check whether E == WHAT.  Fairly simplistic, we
4393e4b17023SJohn Marino    check for an exact match.  */
4394e4b17023SJohn Marino 
4395e4b17023SJohn Marino static bool
expr_equal_p(tree e,tree what)4396e4b17023SJohn Marino expr_equal_p (tree e, tree what)
4397e4b17023SJohn Marino {
4398e4b17023SJohn Marino   gimple stmt;
4399e4b17023SJohn Marino   enum tree_code code;
4400e4b17023SJohn Marino 
4401e4b17023SJohn Marino   e = strip_wrap_conserving_type_conversions (e);
4402e4b17023SJohn Marino   what = strip_wrap_conserving_type_conversions (what);
4403e4b17023SJohn Marino 
4404e4b17023SJohn Marino   code = TREE_CODE (what);
4405e4b17023SJohn Marino   if (TREE_TYPE (e) != TREE_TYPE (what))
4406e4b17023SJohn Marino     return false;
4407e4b17023SJohn Marino 
4408e4b17023SJohn Marino   if (operand_equal_p (e, what, 0))
4409e4b17023SJohn Marino     return true;
4410e4b17023SJohn Marino 
4411e4b17023SJohn Marino   if (TREE_CODE (e) != SSA_NAME)
4412e4b17023SJohn Marino     return false;
4413e4b17023SJohn Marino 
4414e4b17023SJohn Marino   stmt = SSA_NAME_DEF_STMT (e);
4415e4b17023SJohn Marino   if (gimple_code (stmt) != GIMPLE_ASSIGN
4416e4b17023SJohn Marino       || gimple_assign_rhs_code (stmt) != code)
4417e4b17023SJohn Marino     return false;
4418e4b17023SJohn Marino 
4419e4b17023SJohn Marino   switch (get_gimple_rhs_class (code))
4420e4b17023SJohn Marino     {
4421e4b17023SJohn Marino     case GIMPLE_BINARY_RHS:
4422e4b17023SJohn Marino       if (!expr_equal_p (gimple_assign_rhs2 (stmt), TREE_OPERAND (what, 1)))
4423e4b17023SJohn Marino 	return false;
4424e4b17023SJohn Marino       /* Fallthru.  */
4425e4b17023SJohn Marino 
4426e4b17023SJohn Marino     case GIMPLE_UNARY_RHS:
4427e4b17023SJohn Marino     case GIMPLE_SINGLE_RHS:
4428e4b17023SJohn Marino       return expr_equal_p (gimple_assign_rhs1 (stmt), TREE_OPERAND (what, 0));
4429e4b17023SJohn Marino     default:
4430e4b17023SJohn Marino       return false;
4431e4b17023SJohn Marino     }
4432e4b17023SJohn Marino }
4433e4b17023SJohn Marino 
4434e4b17023SJohn Marino /* Returns true if we can prove that BASE - OFFSET does not overflow.  For now,
4435e4b17023SJohn Marino    we only detect the situation that BASE = SOMETHING + OFFSET, where the
4436e4b17023SJohn Marino    calculation is performed in non-wrapping type.
4437e4b17023SJohn Marino 
4438e4b17023SJohn Marino    TODO: More generally, we could test for the situation that
4439e4b17023SJohn Marino 	 BASE = SOMETHING + OFFSET' and OFFSET is between OFFSET' and zero.
4440e4b17023SJohn Marino 	 This would require knowing the sign of OFFSET.
4441e4b17023SJohn Marino 
4442e4b17023SJohn Marino 	 Also, we only look for the first addition in the computation of BASE.
4443e4b17023SJohn Marino 	 More complex analysis would be better, but introducing it just for
4444e4b17023SJohn Marino 	 this optimization seems like an overkill.  */
4445e4b17023SJohn Marino 
4446e4b17023SJohn Marino static bool
difference_cannot_overflow_p(tree base,tree offset)4447e4b17023SJohn Marino difference_cannot_overflow_p (tree base, tree offset)
4448e4b17023SJohn Marino {
4449e4b17023SJohn Marino   enum tree_code code;
4450e4b17023SJohn Marino   tree e1, e2;
4451e4b17023SJohn Marino 
4452e4b17023SJohn Marino   if (!nowrap_type_p (TREE_TYPE (base)))
4453e4b17023SJohn Marino     return false;
4454e4b17023SJohn Marino 
4455e4b17023SJohn Marino   base = expand_simple_operations (base);
4456e4b17023SJohn Marino 
4457e4b17023SJohn Marino   if (TREE_CODE (base) == SSA_NAME)
4458e4b17023SJohn Marino     {
4459e4b17023SJohn Marino       gimple stmt = SSA_NAME_DEF_STMT (base);
4460e4b17023SJohn Marino 
4461e4b17023SJohn Marino       if (gimple_code (stmt) != GIMPLE_ASSIGN)
4462e4b17023SJohn Marino 	return false;
4463e4b17023SJohn Marino 
4464e4b17023SJohn Marino       code = gimple_assign_rhs_code (stmt);
4465e4b17023SJohn Marino       if (get_gimple_rhs_class (code) != GIMPLE_BINARY_RHS)
4466e4b17023SJohn Marino 	return false;
4467e4b17023SJohn Marino 
4468e4b17023SJohn Marino       e1 = gimple_assign_rhs1 (stmt);
4469e4b17023SJohn Marino       e2 = gimple_assign_rhs2 (stmt);
4470e4b17023SJohn Marino     }
4471e4b17023SJohn Marino   else
4472e4b17023SJohn Marino     {
4473e4b17023SJohn Marino       code = TREE_CODE (base);
4474e4b17023SJohn Marino       if (get_gimple_rhs_class (code) != GIMPLE_BINARY_RHS)
4475e4b17023SJohn Marino 	return false;
4476e4b17023SJohn Marino       e1 = TREE_OPERAND (base, 0);
4477e4b17023SJohn Marino       e2 = TREE_OPERAND (base, 1);
4478e4b17023SJohn Marino     }
4479e4b17023SJohn Marino 
4480e4b17023SJohn Marino   /* TODO: deeper inspection may be necessary to prove the equality.  */
4481e4b17023SJohn Marino   switch (code)
4482e4b17023SJohn Marino     {
4483e4b17023SJohn Marino     case PLUS_EXPR:
4484e4b17023SJohn Marino       return expr_equal_p (e1, offset) || expr_equal_p (e2, offset);
4485e4b17023SJohn Marino     case POINTER_PLUS_EXPR:
4486e4b17023SJohn Marino       return expr_equal_p (e2, offset);
4487e4b17023SJohn Marino 
4488e4b17023SJohn Marino     default:
4489e4b17023SJohn Marino       return false;
4490e4b17023SJohn Marino     }
4491e4b17023SJohn Marino }
4492e4b17023SJohn Marino 
4493e4b17023SJohn Marino /* Tries to replace loop exit by one formulated in terms of a LT_EXPR
4494e4b17023SJohn Marino    comparison with CAND.  NITER describes the number of iterations of
4495e4b17023SJohn Marino    the loops.  If successful, the comparison in COMP_P is altered accordingly.
4496e4b17023SJohn Marino 
4497e4b17023SJohn Marino    We aim to handle the following situation:
4498e4b17023SJohn Marino 
4499e4b17023SJohn Marino    sometype *base, *p;
4500e4b17023SJohn Marino    int a, b, i;
4501e4b17023SJohn Marino 
4502e4b17023SJohn Marino    i = a;
4503e4b17023SJohn Marino    p = p_0 = base + a;
4504e4b17023SJohn Marino 
4505e4b17023SJohn Marino    do
4506e4b17023SJohn Marino      {
4507e4b17023SJohn Marino        bla (*p);
4508e4b17023SJohn Marino        p++;
4509e4b17023SJohn Marino        i++;
4510e4b17023SJohn Marino      }
4511e4b17023SJohn Marino    while (i < b);
4512e4b17023SJohn Marino 
4513e4b17023SJohn Marino    Here, the number of iterations of the loop is (a + 1 > b) ? 0 : b - a - 1.
4514e4b17023SJohn Marino    We aim to optimize this to
4515e4b17023SJohn Marino 
4516e4b17023SJohn Marino    p = p_0 = base + a;
4517e4b17023SJohn Marino    do
4518e4b17023SJohn Marino      {
4519e4b17023SJohn Marino        bla (*p);
4520e4b17023SJohn Marino        p++;
4521e4b17023SJohn Marino      }
4522e4b17023SJohn Marino    while (p < p_0 - a + b);
4523e4b17023SJohn Marino 
4524e4b17023SJohn Marino    This preserves the correctness, since the pointer arithmetics does not
4525e4b17023SJohn Marino    overflow.  More precisely:
4526e4b17023SJohn Marino 
4527e4b17023SJohn Marino    1) if a + 1 <= b, then p_0 - a + b is the final value of p, hence there is no
4528e4b17023SJohn Marino       overflow in computing it or the values of p.
4529e4b17023SJohn Marino    2) if a + 1 > b, then we need to verify that the expression p_0 - a does not
4530e4b17023SJohn Marino       overflow.  To prove this, we use the fact that p_0 = base + a.  */
4531e4b17023SJohn Marino 
4532e4b17023SJohn Marino static bool
iv_elimination_compare_lt(struct ivopts_data * data,struct iv_cand * cand,enum tree_code * comp_p,struct tree_niter_desc * niter)4533e4b17023SJohn Marino iv_elimination_compare_lt (struct ivopts_data *data,
4534e4b17023SJohn Marino                            struct iv_cand *cand, enum tree_code *comp_p,
4535e4b17023SJohn Marino 			   struct tree_niter_desc *niter)
4536e4b17023SJohn Marino {
4537e4b17023SJohn Marino   tree cand_type, a, b, mbz, nit_type = TREE_TYPE (niter->niter), offset;
4538e4b17023SJohn Marino   struct affine_tree_combination nit, tmpa, tmpb;
4539e4b17023SJohn Marino   enum tree_code comp;
4540e4b17023SJohn Marino   HOST_WIDE_INT step;
4541e4b17023SJohn Marino 
4542e4b17023SJohn Marino   /* We need to know that the candidate induction variable does not overflow.
4543e4b17023SJohn Marino      While more complex analysis may be used to prove this, for now just
4544e4b17023SJohn Marino      check that the variable appears in the original program and that it
4545e4b17023SJohn Marino      is computed in a type that guarantees no overflows.  */
4546e4b17023SJohn Marino   cand_type = TREE_TYPE (cand->iv->base);
4547e4b17023SJohn Marino   if (cand->pos != IP_ORIGINAL || !nowrap_type_p (cand_type))
4548e4b17023SJohn Marino     return false;
4549e4b17023SJohn Marino 
4550e4b17023SJohn Marino   /* Make sure that the loop iterates till the loop bound is hit, as otherwise
4551e4b17023SJohn Marino      the calculation of the BOUND could overflow, making the comparison
4552e4b17023SJohn Marino      invalid.  */
4553e4b17023SJohn Marino   if (!data->loop_single_exit_p)
4554e4b17023SJohn Marino     return false;
4555e4b17023SJohn Marino 
4556e4b17023SJohn Marino   /* We need to be able to decide whether candidate is increasing or decreasing
4557e4b17023SJohn Marino      in order to choose the right comparison operator.  */
4558e4b17023SJohn Marino   if (!cst_and_fits_in_hwi (cand->iv->step))
4559e4b17023SJohn Marino     return false;
4560e4b17023SJohn Marino   step = int_cst_value (cand->iv->step);
4561e4b17023SJohn Marino 
4562e4b17023SJohn Marino   /* Check that the number of iterations matches the expected pattern:
4563e4b17023SJohn Marino      a + 1 > b ? 0 : b - a - 1.  */
4564e4b17023SJohn Marino   mbz = niter->may_be_zero;
4565e4b17023SJohn Marino   if (TREE_CODE (mbz) == GT_EXPR)
4566e4b17023SJohn Marino     {
4567e4b17023SJohn Marino       /* Handle a + 1 > b.  */
4568e4b17023SJohn Marino       tree op0 = TREE_OPERAND (mbz, 0);
4569e4b17023SJohn Marino       if (TREE_CODE (op0) == PLUS_EXPR && integer_onep (TREE_OPERAND (op0, 1)))
4570e4b17023SJohn Marino 	{
4571e4b17023SJohn Marino 	  a = TREE_OPERAND (op0, 0);
4572e4b17023SJohn Marino 	  b = TREE_OPERAND (mbz, 1);
4573e4b17023SJohn Marino 	}
4574e4b17023SJohn Marino       else
4575e4b17023SJohn Marino 	return false;
4576e4b17023SJohn Marino     }
4577e4b17023SJohn Marino   else if (TREE_CODE (mbz) == LT_EXPR)
4578e4b17023SJohn Marino     {
4579e4b17023SJohn Marino       tree op1 = TREE_OPERAND (mbz, 1);
4580e4b17023SJohn Marino 
4581e4b17023SJohn Marino       /* Handle b < a + 1.  */
4582e4b17023SJohn Marino       if (TREE_CODE (op1) == PLUS_EXPR && integer_onep (TREE_OPERAND (op1, 1)))
4583e4b17023SJohn Marino         {
4584e4b17023SJohn Marino           a = TREE_OPERAND (op1, 0);
4585e4b17023SJohn Marino           b = TREE_OPERAND (mbz, 0);
4586e4b17023SJohn Marino         }
4587e4b17023SJohn Marino       else
4588e4b17023SJohn Marino 	return false;
4589e4b17023SJohn Marino     }
4590e4b17023SJohn Marino   else
4591e4b17023SJohn Marino     return false;
4592e4b17023SJohn Marino 
4593e4b17023SJohn Marino   /* Expected number of iterations is B - A - 1.  Check that it matches
4594e4b17023SJohn Marino      the actual number, i.e., that B - A - NITER = 1.  */
4595e4b17023SJohn Marino   tree_to_aff_combination (niter->niter, nit_type, &nit);
4596e4b17023SJohn Marino   tree_to_aff_combination (fold_convert (nit_type, a), nit_type, &tmpa);
4597e4b17023SJohn Marino   tree_to_aff_combination (fold_convert (nit_type, b), nit_type, &tmpb);
4598e4b17023SJohn Marino   aff_combination_scale (&nit, double_int_minus_one);
4599e4b17023SJohn Marino   aff_combination_scale (&tmpa, double_int_minus_one);
4600e4b17023SJohn Marino   aff_combination_add (&tmpb, &tmpa);
4601e4b17023SJohn Marino   aff_combination_add (&tmpb, &nit);
4602e4b17023SJohn Marino   if (tmpb.n != 0 || !double_int_equal_p (tmpb.offset, double_int_one))
4603e4b17023SJohn Marino     return false;
4604e4b17023SJohn Marino 
4605e4b17023SJohn Marino   /* Finally, check that CAND->IV->BASE - CAND->IV->STEP * A does not
4606e4b17023SJohn Marino      overflow.  */
4607e4b17023SJohn Marino   offset = fold_build2 (MULT_EXPR, TREE_TYPE (cand->iv->step),
4608e4b17023SJohn Marino 			cand->iv->step,
4609e4b17023SJohn Marino 			fold_convert (TREE_TYPE (cand->iv->step), a));
4610e4b17023SJohn Marino   if (!difference_cannot_overflow_p (cand->iv->base, offset))
4611e4b17023SJohn Marino     return false;
4612e4b17023SJohn Marino 
4613e4b17023SJohn Marino   /* Determine the new comparison operator.  */
4614e4b17023SJohn Marino   comp = step < 0 ? GT_EXPR : LT_EXPR;
4615e4b17023SJohn Marino   if (*comp_p == NE_EXPR)
4616e4b17023SJohn Marino     *comp_p = comp;
4617e4b17023SJohn Marino   else if (*comp_p == EQ_EXPR)
4618e4b17023SJohn Marino     *comp_p = invert_tree_comparison (comp, false);
4619e4b17023SJohn Marino   else
4620e4b17023SJohn Marino     gcc_unreachable ();
4621e4b17023SJohn Marino 
4622e4b17023SJohn Marino   return true;
4623e4b17023SJohn Marino }
4624e4b17023SJohn Marino 
4625e4b17023SJohn Marino /* Check whether it is possible to express the condition in USE by comparison
4626e4b17023SJohn Marino    of candidate CAND.  If so, store the value compared with to BOUND, and the
4627e4b17023SJohn Marino    comparison operator to COMP.  */
4628e4b17023SJohn Marino 
4629e4b17023SJohn Marino static bool
may_eliminate_iv(struct ivopts_data * data,struct iv_use * use,struct iv_cand * cand,tree * bound,enum tree_code * comp)4630e4b17023SJohn Marino may_eliminate_iv (struct ivopts_data *data,
4631e4b17023SJohn Marino 		  struct iv_use *use, struct iv_cand *cand, tree *bound,
4632e4b17023SJohn Marino 		  enum tree_code *comp)
4633e4b17023SJohn Marino {
4634e4b17023SJohn Marino   basic_block ex_bb;
4635e4b17023SJohn Marino   edge exit;
4636e4b17023SJohn Marino   tree period;
4637e4b17023SJohn Marino   struct loop *loop = data->current_loop;
4638e4b17023SJohn Marino   aff_tree bnd;
4639e4b17023SJohn Marino   struct tree_niter_desc *desc = NULL;
4640e4b17023SJohn Marino 
4641e4b17023SJohn Marino   if (TREE_CODE (cand->iv->step) != INTEGER_CST)
4642e4b17023SJohn Marino     return false;
4643e4b17023SJohn Marino 
4644e4b17023SJohn Marino   /* For now works only for exits that dominate the loop latch.
4645e4b17023SJohn Marino      TODO: extend to other conditions inside loop body.  */
4646e4b17023SJohn Marino   ex_bb = gimple_bb (use->stmt);
4647e4b17023SJohn Marino   if (use->stmt != last_stmt (ex_bb)
4648e4b17023SJohn Marino       || gimple_code (use->stmt) != GIMPLE_COND
4649e4b17023SJohn Marino       || !dominated_by_p (CDI_DOMINATORS, loop->latch, ex_bb))
4650e4b17023SJohn Marino     return false;
4651e4b17023SJohn Marino 
4652e4b17023SJohn Marino   exit = EDGE_SUCC (ex_bb, 0);
4653e4b17023SJohn Marino   if (flow_bb_inside_loop_p (loop, exit->dest))
4654e4b17023SJohn Marino     exit = EDGE_SUCC (ex_bb, 1);
4655e4b17023SJohn Marino   if (flow_bb_inside_loop_p (loop, exit->dest))
4656e4b17023SJohn Marino     return false;
4657e4b17023SJohn Marino 
4658e4b17023SJohn Marino   desc = niter_for_exit (data, exit);
4659e4b17023SJohn Marino   if (!desc)
4660e4b17023SJohn Marino     return false;
4661e4b17023SJohn Marino 
4662e4b17023SJohn Marino   /* Determine whether we can use the variable to test the exit condition.
4663e4b17023SJohn Marino      This is the case iff the period of the induction variable is greater
4664e4b17023SJohn Marino      than the number of iterations for which the exit condition is true.  */
4665e4b17023SJohn Marino   period = iv_period (cand->iv);
4666e4b17023SJohn Marino 
4667e4b17023SJohn Marino   /* If the number of iterations is constant, compare against it directly.  */
4668e4b17023SJohn Marino   if (TREE_CODE (desc->niter) == INTEGER_CST)
4669e4b17023SJohn Marino     {
4670e4b17023SJohn Marino       /* See cand_value_at.  */
4671e4b17023SJohn Marino       if (stmt_after_increment (loop, cand, use->stmt))
4672e4b17023SJohn Marino         {
4673e4b17023SJohn Marino           if (!tree_int_cst_lt (desc->niter, period))
4674e4b17023SJohn Marino             return false;
4675e4b17023SJohn Marino         }
4676e4b17023SJohn Marino       else
4677e4b17023SJohn Marino         {
4678e4b17023SJohn Marino           if (tree_int_cst_lt (period, desc->niter))
4679e4b17023SJohn Marino             return false;
4680e4b17023SJohn Marino         }
4681e4b17023SJohn Marino     }
4682e4b17023SJohn Marino 
4683e4b17023SJohn Marino   /* If not, and if this is the only possible exit of the loop, see whether
4684e4b17023SJohn Marino      we can get a conservative estimate on the number of iterations of the
4685e4b17023SJohn Marino      entire loop and compare against that instead.  */
4686e4b17023SJohn Marino   else
4687e4b17023SJohn Marino     {
4688e4b17023SJohn Marino       double_int period_value, max_niter;
4689e4b17023SJohn Marino 
4690e4b17023SJohn Marino       max_niter = desc->max;
4691e4b17023SJohn Marino       if (stmt_after_increment (loop, cand, use->stmt))
4692e4b17023SJohn Marino         max_niter = double_int_add (max_niter, double_int_one);
4693e4b17023SJohn Marino       period_value = tree_to_double_int (period);
4694e4b17023SJohn Marino       if (double_int_ucmp (max_niter, period_value) > 0)
4695e4b17023SJohn Marino         {
4696e4b17023SJohn Marino           /* See if we can take advantage of infered loop bound information.  */
4697e4b17023SJohn Marino           if (data->loop_single_exit_p)
4698e4b17023SJohn Marino             {
4699e4b17023SJohn Marino               if (!estimated_loop_iterations (loop, true, &max_niter))
4700e4b17023SJohn Marino                 return false;
4701e4b17023SJohn Marino               /* The loop bound is already adjusted by adding 1.  */
4702e4b17023SJohn Marino               if (double_int_ucmp (max_niter, period_value) > 0)
4703e4b17023SJohn Marino                 return false;
4704e4b17023SJohn Marino             }
4705e4b17023SJohn Marino           else
4706e4b17023SJohn Marino             return false;
4707e4b17023SJohn Marino         }
4708e4b17023SJohn Marino     }
4709e4b17023SJohn Marino 
4710e4b17023SJohn Marino   cand_value_at (loop, cand, use->stmt, desc->niter, &bnd);
4711e4b17023SJohn Marino 
4712e4b17023SJohn Marino   *bound = aff_combination_to_tree (&bnd);
4713e4b17023SJohn Marino   *comp = iv_elimination_compare (data, use);
4714e4b17023SJohn Marino 
4715e4b17023SJohn Marino   /* It is unlikely that computing the number of iterations using division
4716e4b17023SJohn Marino      would be more profitable than keeping the original induction variable.  */
4717e4b17023SJohn Marino   if (expression_expensive_p (*bound))
4718e4b17023SJohn Marino     return false;
4719e4b17023SJohn Marino 
4720e4b17023SJohn Marino   /* Sometimes, it is possible to handle the situation that the number of
4721e4b17023SJohn Marino      iterations may be zero unless additional assumtions by using <
4722e4b17023SJohn Marino      instead of != in the exit condition.
4723e4b17023SJohn Marino 
4724e4b17023SJohn Marino      TODO: we could also calculate the value MAY_BE_ZERO ? 0 : NITER and
4725e4b17023SJohn Marino 	   base the exit condition on it.  However, that is often too
4726e4b17023SJohn Marino 	   expensive.  */
4727e4b17023SJohn Marino   if (!integer_zerop (desc->may_be_zero))
4728e4b17023SJohn Marino     return iv_elimination_compare_lt (data, cand, comp, desc);
4729e4b17023SJohn Marino 
4730e4b17023SJohn Marino   return true;
4731e4b17023SJohn Marino }
4732e4b17023SJohn Marino 
4733e4b17023SJohn Marino  /* Calculates the cost of BOUND, if it is a PARM_DECL.  A PARM_DECL must
4734e4b17023SJohn Marino     be copied, if is is used in the loop body and DATA->body_includes_call.  */
4735e4b17023SJohn Marino 
4736e4b17023SJohn Marino static int
parm_decl_cost(struct ivopts_data * data,tree bound)4737e4b17023SJohn Marino parm_decl_cost (struct ivopts_data *data, tree bound)
4738e4b17023SJohn Marino {
4739e4b17023SJohn Marino   tree sbound = bound;
4740e4b17023SJohn Marino   STRIP_NOPS (sbound);
4741e4b17023SJohn Marino 
4742e4b17023SJohn Marino   if (TREE_CODE (sbound) == SSA_NAME
4743e4b17023SJohn Marino       && TREE_CODE (SSA_NAME_VAR (sbound)) == PARM_DECL
4744e4b17023SJohn Marino       && gimple_nop_p (SSA_NAME_DEF_STMT (sbound))
4745e4b17023SJohn Marino       && data->body_includes_call)
4746e4b17023SJohn Marino     return COSTS_N_INSNS (1);
4747e4b17023SJohn Marino 
4748e4b17023SJohn Marino   return 0;
4749e4b17023SJohn Marino }
4750e4b17023SJohn Marino 
4751e4b17023SJohn Marino /* Determines cost of basing replacement of USE on CAND in a condition.  */
4752e4b17023SJohn Marino 
4753e4b17023SJohn Marino static bool
determine_use_iv_cost_condition(struct ivopts_data * data,struct iv_use * use,struct iv_cand * cand)4754e4b17023SJohn Marino determine_use_iv_cost_condition (struct ivopts_data *data,
4755e4b17023SJohn Marino 				 struct iv_use *use, struct iv_cand *cand)
4756e4b17023SJohn Marino {
4757e4b17023SJohn Marino   tree bound = NULL_TREE;
4758e4b17023SJohn Marino   struct iv *cmp_iv;
4759e4b17023SJohn Marino   bitmap depends_on_elim = NULL, depends_on_express = NULL, depends_on;
4760e4b17023SJohn Marino   comp_cost elim_cost, express_cost, cost, bound_cost;
4761e4b17023SJohn Marino   bool ok;
4762e4b17023SJohn Marino   int elim_inv_expr_id = -1, express_inv_expr_id = -1, inv_expr_id;
4763e4b17023SJohn Marino   tree *control_var, *bound_cst;
4764e4b17023SJohn Marino   enum tree_code comp = ERROR_MARK;
4765e4b17023SJohn Marino 
4766e4b17023SJohn Marino   /* Only consider real candidates.  */
4767e4b17023SJohn Marino   if (!cand->iv)
4768e4b17023SJohn Marino     {
4769e4b17023SJohn Marino       set_use_iv_cost (data, use, cand, infinite_cost, NULL, NULL_TREE,
4770e4b17023SJohn Marino 		       ERROR_MARK, -1);
4771e4b17023SJohn Marino       return false;
4772e4b17023SJohn Marino     }
4773e4b17023SJohn Marino 
4774e4b17023SJohn Marino   /* Try iv elimination.  */
4775e4b17023SJohn Marino   if (may_eliminate_iv (data, use, cand, &bound, &comp))
4776e4b17023SJohn Marino     {
4777e4b17023SJohn Marino       elim_cost = force_var_cost (data, bound, &depends_on_elim);
4778e4b17023SJohn Marino       if (elim_cost.cost == 0)
4779e4b17023SJohn Marino         elim_cost.cost = parm_decl_cost (data, bound);
4780e4b17023SJohn Marino       else if (TREE_CODE (bound) == INTEGER_CST)
4781e4b17023SJohn Marino         elim_cost.cost = 0;
4782e4b17023SJohn Marino       /* If we replace a loop condition 'i < n' with 'p < base + n',
4783e4b17023SJohn Marino 	 depends_on_elim will have 'base' and 'n' set, which implies
4784e4b17023SJohn Marino 	 that both 'base' and 'n' will be live during the loop.	 More likely,
4785e4b17023SJohn Marino 	 'base + n' will be loop invariant, resulting in only one live value
4786e4b17023SJohn Marino 	 during the loop.  So in that case we clear depends_on_elim and set
4787e4b17023SJohn Marino         elim_inv_expr_id instead.  */
4788e4b17023SJohn Marino       if (depends_on_elim && bitmap_count_bits (depends_on_elim) > 1)
4789e4b17023SJohn Marino 	{
4790e4b17023SJohn Marino 	  elim_inv_expr_id = get_expr_id (data, bound);
4791e4b17023SJohn Marino 	  bitmap_clear (depends_on_elim);
4792e4b17023SJohn Marino 	}
4793e4b17023SJohn Marino       /* The bound is a loop invariant, so it will be only computed
4794e4b17023SJohn Marino 	 once.  */
4795e4b17023SJohn Marino       elim_cost.cost = adjust_setup_cost (data, elim_cost.cost);
4796e4b17023SJohn Marino     }
4797e4b17023SJohn Marino   else
4798e4b17023SJohn Marino     elim_cost = infinite_cost;
4799e4b17023SJohn Marino 
4800e4b17023SJohn Marino   /* Try expressing the original giv.  If it is compared with an invariant,
4801e4b17023SJohn Marino      note that we cannot get rid of it.  */
4802e4b17023SJohn Marino   ok = extract_cond_operands (data, use->stmt, &control_var, &bound_cst,
4803e4b17023SJohn Marino 			      NULL, &cmp_iv);
4804e4b17023SJohn Marino   gcc_assert (ok);
4805e4b17023SJohn Marino 
4806e4b17023SJohn Marino   /* When the condition is a comparison of the candidate IV against
4807e4b17023SJohn Marino      zero, prefer this IV.
4808e4b17023SJohn Marino 
4809e4b17023SJohn Marino      TODO: The constant that we're substracting from the cost should
4810e4b17023SJohn Marino      be target-dependent.  This information should be added to the
4811e4b17023SJohn Marino      target costs for each backend.  */
4812e4b17023SJohn Marino   if (!infinite_cost_p (elim_cost) /* Do not try to decrease infinite! */
4813e4b17023SJohn Marino       && integer_zerop (*bound_cst)
4814e4b17023SJohn Marino       && (operand_equal_p (*control_var, cand->var_after, 0)
4815e4b17023SJohn Marino 	  || operand_equal_p (*control_var, cand->var_before, 0)))
4816e4b17023SJohn Marino     elim_cost.cost -= 1;
4817e4b17023SJohn Marino 
4818e4b17023SJohn Marino   express_cost = get_computation_cost (data, use, cand, false,
4819e4b17023SJohn Marino 				       &depends_on_express, NULL,
4820e4b17023SJohn Marino                                        &express_inv_expr_id);
4821e4b17023SJohn Marino   fd_ivopts_data = data;
4822e4b17023SJohn Marino   walk_tree (&cmp_iv->base, find_depends, &depends_on_express, NULL);
4823e4b17023SJohn Marino 
4824e4b17023SJohn Marino   /* Count the cost of the original bound as well.  */
4825e4b17023SJohn Marino   bound_cost = force_var_cost (data, *bound_cst, NULL);
4826e4b17023SJohn Marino   if (bound_cost.cost == 0)
4827e4b17023SJohn Marino     bound_cost.cost = parm_decl_cost (data, *bound_cst);
4828e4b17023SJohn Marino   else if (TREE_CODE (*bound_cst) == INTEGER_CST)
4829e4b17023SJohn Marino     bound_cost.cost = 0;
4830e4b17023SJohn Marino   express_cost.cost += bound_cost.cost;
4831e4b17023SJohn Marino 
4832e4b17023SJohn Marino   /* Choose the better approach, preferring the eliminated IV. */
4833e4b17023SJohn Marino   if (compare_costs (elim_cost, express_cost) <= 0)
4834e4b17023SJohn Marino     {
4835e4b17023SJohn Marino       cost = elim_cost;
4836e4b17023SJohn Marino       depends_on = depends_on_elim;
4837e4b17023SJohn Marino       depends_on_elim = NULL;
4838e4b17023SJohn Marino       inv_expr_id = elim_inv_expr_id;
4839e4b17023SJohn Marino     }
4840e4b17023SJohn Marino   else
4841e4b17023SJohn Marino     {
4842e4b17023SJohn Marino       cost = express_cost;
4843e4b17023SJohn Marino       depends_on = depends_on_express;
4844e4b17023SJohn Marino       depends_on_express = NULL;
4845e4b17023SJohn Marino       bound = NULL_TREE;
4846e4b17023SJohn Marino       comp = ERROR_MARK;
4847e4b17023SJohn Marino       inv_expr_id = express_inv_expr_id;
4848e4b17023SJohn Marino     }
4849e4b17023SJohn Marino 
4850e4b17023SJohn Marino   set_use_iv_cost (data, use, cand, cost, depends_on, bound, comp, inv_expr_id);
4851e4b17023SJohn Marino 
4852e4b17023SJohn Marino   if (depends_on_elim)
4853e4b17023SJohn Marino     BITMAP_FREE (depends_on_elim);
4854e4b17023SJohn Marino   if (depends_on_express)
4855e4b17023SJohn Marino     BITMAP_FREE (depends_on_express);
4856e4b17023SJohn Marino 
4857e4b17023SJohn Marino   return !infinite_cost_p (cost);
4858e4b17023SJohn Marino }
4859e4b17023SJohn Marino 
4860e4b17023SJohn Marino /* Determines cost of basing replacement of USE on CAND.  Returns false
4861e4b17023SJohn Marino    if USE cannot be based on CAND.  */
4862e4b17023SJohn Marino 
4863e4b17023SJohn Marino static bool
determine_use_iv_cost(struct ivopts_data * data,struct iv_use * use,struct iv_cand * cand)4864e4b17023SJohn Marino determine_use_iv_cost (struct ivopts_data *data,
4865e4b17023SJohn Marino 		       struct iv_use *use, struct iv_cand *cand)
4866e4b17023SJohn Marino {
4867e4b17023SJohn Marino   switch (use->type)
4868e4b17023SJohn Marino     {
4869e4b17023SJohn Marino     case USE_NONLINEAR_EXPR:
4870e4b17023SJohn Marino       return determine_use_iv_cost_generic (data, use, cand);
4871e4b17023SJohn Marino 
4872e4b17023SJohn Marino     case USE_ADDRESS:
4873e4b17023SJohn Marino       return determine_use_iv_cost_address (data, use, cand);
4874e4b17023SJohn Marino 
4875e4b17023SJohn Marino     case USE_COMPARE:
4876e4b17023SJohn Marino       return determine_use_iv_cost_condition (data, use, cand);
4877e4b17023SJohn Marino 
4878e4b17023SJohn Marino     default:
4879e4b17023SJohn Marino       gcc_unreachable ();
4880e4b17023SJohn Marino     }
4881e4b17023SJohn Marino }
4882e4b17023SJohn Marino 
4883e4b17023SJohn Marino /* Return true if get_computation_cost indicates that autoincrement is
4884e4b17023SJohn Marino    a possibility for the pair of USE and CAND, false otherwise.  */
4885e4b17023SJohn Marino 
4886e4b17023SJohn Marino static bool
autoinc_possible_for_pair(struct ivopts_data * data,struct iv_use * use,struct iv_cand * cand)4887e4b17023SJohn Marino autoinc_possible_for_pair (struct ivopts_data *data, struct iv_use *use,
4888e4b17023SJohn Marino 			   struct iv_cand *cand)
4889e4b17023SJohn Marino {
4890e4b17023SJohn Marino   bitmap depends_on;
4891e4b17023SJohn Marino   bool can_autoinc;
4892e4b17023SJohn Marino   comp_cost cost;
4893e4b17023SJohn Marino 
4894e4b17023SJohn Marino   if (use->type != USE_ADDRESS)
4895e4b17023SJohn Marino     return false;
4896e4b17023SJohn Marino 
4897e4b17023SJohn Marino   cost = get_computation_cost (data, use, cand, true, &depends_on,
4898e4b17023SJohn Marino 			       &can_autoinc, NULL);
4899e4b17023SJohn Marino 
4900e4b17023SJohn Marino   BITMAP_FREE (depends_on);
4901e4b17023SJohn Marino 
4902e4b17023SJohn Marino   return !infinite_cost_p (cost) && can_autoinc;
4903e4b17023SJohn Marino }
4904e4b17023SJohn Marino 
4905e4b17023SJohn Marino /* Examine IP_ORIGINAL candidates to see if they are incremented next to a
4906e4b17023SJohn Marino    use that allows autoincrement, and set their AINC_USE if possible.  */
4907e4b17023SJohn Marino 
4908e4b17023SJohn Marino static void
set_autoinc_for_original_candidates(struct ivopts_data * data)4909e4b17023SJohn Marino set_autoinc_for_original_candidates (struct ivopts_data *data)
4910e4b17023SJohn Marino {
4911e4b17023SJohn Marino   unsigned i, j;
4912e4b17023SJohn Marino 
4913e4b17023SJohn Marino   for (i = 0; i < n_iv_cands (data); i++)
4914e4b17023SJohn Marino     {
4915e4b17023SJohn Marino       struct iv_cand *cand = iv_cand (data, i);
4916e4b17023SJohn Marino       struct iv_use *closest = NULL;
4917e4b17023SJohn Marino       if (cand->pos != IP_ORIGINAL)
4918e4b17023SJohn Marino 	continue;
4919e4b17023SJohn Marino       for (j = 0; j < n_iv_uses (data); j++)
4920e4b17023SJohn Marino 	{
4921e4b17023SJohn Marino 	  struct iv_use *use = iv_use (data, j);
4922e4b17023SJohn Marino 	  unsigned uid = gimple_uid (use->stmt);
4923e4b17023SJohn Marino 	  if (gimple_bb (use->stmt) != gimple_bb (cand->incremented_at)
4924e4b17023SJohn Marino 	      || uid > gimple_uid (cand->incremented_at))
4925e4b17023SJohn Marino 	    continue;
4926e4b17023SJohn Marino 	  if (closest == NULL || uid > gimple_uid (closest->stmt))
4927e4b17023SJohn Marino 	    closest = use;
4928e4b17023SJohn Marino 	}
4929e4b17023SJohn Marino       if (closest == NULL || !autoinc_possible_for_pair (data, closest, cand))
4930e4b17023SJohn Marino 	continue;
4931e4b17023SJohn Marino       cand->ainc_use = closest;
4932e4b17023SJohn Marino     }
4933e4b17023SJohn Marino }
4934e4b17023SJohn Marino 
4935e4b17023SJohn Marino /* Finds the candidates for the induction variables.  */
4936e4b17023SJohn Marino 
4937e4b17023SJohn Marino static void
find_iv_candidates(struct ivopts_data * data)4938e4b17023SJohn Marino find_iv_candidates (struct ivopts_data *data)
4939e4b17023SJohn Marino {
4940e4b17023SJohn Marino   /* Add commonly used ivs.  */
4941e4b17023SJohn Marino   add_standard_iv_candidates (data);
4942e4b17023SJohn Marino 
4943e4b17023SJohn Marino   /* Add old induction variables.  */
4944e4b17023SJohn Marino   add_old_ivs_candidates (data);
4945e4b17023SJohn Marino 
4946e4b17023SJohn Marino   /* Add induction variables derived from uses.  */
4947e4b17023SJohn Marino   add_derived_ivs_candidates (data);
4948e4b17023SJohn Marino 
4949e4b17023SJohn Marino   set_autoinc_for_original_candidates (data);
4950e4b17023SJohn Marino 
4951e4b17023SJohn Marino   /* Record the important candidates.  */
4952e4b17023SJohn Marino   record_important_candidates (data);
4953e4b17023SJohn Marino }
4954e4b17023SJohn Marino 
4955e4b17023SJohn Marino /* Determines costs of basing the use of the iv on an iv candidate.  */
4956e4b17023SJohn Marino 
4957e4b17023SJohn Marino static void
determine_use_iv_costs(struct ivopts_data * data)4958e4b17023SJohn Marino determine_use_iv_costs (struct ivopts_data *data)
4959e4b17023SJohn Marino {
4960e4b17023SJohn Marino   unsigned i, j;
4961e4b17023SJohn Marino   struct iv_use *use;
4962e4b17023SJohn Marino   struct iv_cand *cand;
4963e4b17023SJohn Marino   bitmap to_clear = BITMAP_ALLOC (NULL);
4964e4b17023SJohn Marino 
4965e4b17023SJohn Marino   alloc_use_cost_map (data);
4966e4b17023SJohn Marino 
4967e4b17023SJohn Marino   for (i = 0; i < n_iv_uses (data); i++)
4968e4b17023SJohn Marino     {
4969e4b17023SJohn Marino       use = iv_use (data, i);
4970e4b17023SJohn Marino 
4971e4b17023SJohn Marino       if (data->consider_all_candidates)
4972e4b17023SJohn Marino 	{
4973e4b17023SJohn Marino 	  for (j = 0; j < n_iv_cands (data); j++)
4974e4b17023SJohn Marino 	    {
4975e4b17023SJohn Marino 	      cand = iv_cand (data, j);
4976e4b17023SJohn Marino 	      determine_use_iv_cost (data, use, cand);
4977e4b17023SJohn Marino 	    }
4978e4b17023SJohn Marino 	}
4979e4b17023SJohn Marino       else
4980e4b17023SJohn Marino 	{
4981e4b17023SJohn Marino 	  bitmap_iterator bi;
4982e4b17023SJohn Marino 
4983e4b17023SJohn Marino 	  EXECUTE_IF_SET_IN_BITMAP (use->related_cands, 0, j, bi)
4984e4b17023SJohn Marino 	    {
4985e4b17023SJohn Marino 	      cand = iv_cand (data, j);
4986e4b17023SJohn Marino 	      if (!determine_use_iv_cost (data, use, cand))
4987e4b17023SJohn Marino 		bitmap_set_bit (to_clear, j);
4988e4b17023SJohn Marino 	    }
4989e4b17023SJohn Marino 
4990e4b17023SJohn Marino 	  /* Remove the candidates for that the cost is infinite from
4991e4b17023SJohn Marino 	     the list of related candidates.  */
4992e4b17023SJohn Marino 	  bitmap_and_compl_into (use->related_cands, to_clear);
4993e4b17023SJohn Marino 	  bitmap_clear (to_clear);
4994e4b17023SJohn Marino 	}
4995e4b17023SJohn Marino     }
4996e4b17023SJohn Marino 
4997e4b17023SJohn Marino   BITMAP_FREE (to_clear);
4998e4b17023SJohn Marino 
4999e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
5000e4b17023SJohn Marino     {
5001e4b17023SJohn Marino       fprintf (dump_file, "Use-candidate costs:\n");
5002e4b17023SJohn Marino 
5003e4b17023SJohn Marino       for (i = 0; i < n_iv_uses (data); i++)
5004e4b17023SJohn Marino 	{
5005e4b17023SJohn Marino 	  use = iv_use (data, i);
5006e4b17023SJohn Marino 
5007e4b17023SJohn Marino 	  fprintf (dump_file, "Use %d:\n", i);
5008e4b17023SJohn Marino 	  fprintf (dump_file, "  cand\tcost\tcompl.\tdepends on\n");
5009e4b17023SJohn Marino 	  for (j = 0; j < use->n_map_members; j++)
5010e4b17023SJohn Marino 	    {
5011e4b17023SJohn Marino 	      if (!use->cost_map[j].cand
5012e4b17023SJohn Marino 		  || infinite_cost_p (use->cost_map[j].cost))
5013e4b17023SJohn Marino 		continue;
5014e4b17023SJohn Marino 
5015e4b17023SJohn Marino 	      fprintf (dump_file, "  %d\t%d\t%d\t",
5016e4b17023SJohn Marino 		       use->cost_map[j].cand->id,
5017e4b17023SJohn Marino 		       use->cost_map[j].cost.cost,
5018e4b17023SJohn Marino 		       use->cost_map[j].cost.complexity);
5019e4b17023SJohn Marino 	      if (use->cost_map[j].depends_on)
5020e4b17023SJohn Marino 		bitmap_print (dump_file,
5021e4b17023SJohn Marino 			      use->cost_map[j].depends_on, "","");
5022e4b17023SJohn Marino               if (use->cost_map[j].inv_expr_id != -1)
5023e4b17023SJohn Marino                 fprintf (dump_file, " inv_expr:%d", use->cost_map[j].inv_expr_id);
5024e4b17023SJohn Marino 	      fprintf (dump_file, "\n");
5025e4b17023SJohn Marino 	    }
5026e4b17023SJohn Marino 
5027e4b17023SJohn Marino 	  fprintf (dump_file, "\n");
5028e4b17023SJohn Marino 	}
5029e4b17023SJohn Marino       fprintf (dump_file, "\n");
5030e4b17023SJohn Marino     }
5031e4b17023SJohn Marino }
5032e4b17023SJohn Marino 
5033e4b17023SJohn Marino /* Determines cost of the candidate CAND.  */
5034e4b17023SJohn Marino 
5035e4b17023SJohn Marino static void
determine_iv_cost(struct ivopts_data * data,struct iv_cand * cand)5036e4b17023SJohn Marino determine_iv_cost (struct ivopts_data *data, struct iv_cand *cand)
5037e4b17023SJohn Marino {
5038e4b17023SJohn Marino   comp_cost cost_base;
5039e4b17023SJohn Marino   unsigned cost, cost_step;
5040e4b17023SJohn Marino   tree base;
5041e4b17023SJohn Marino 
5042e4b17023SJohn Marino   if (!cand->iv)
5043e4b17023SJohn Marino     {
5044e4b17023SJohn Marino       cand->cost = 0;
5045e4b17023SJohn Marino       return;
5046e4b17023SJohn Marino     }
5047e4b17023SJohn Marino 
5048e4b17023SJohn Marino   /* There are two costs associated with the candidate -- its increment
5049e4b17023SJohn Marino      and its initialization.  The second is almost negligible for any loop
5050e4b17023SJohn Marino      that rolls enough, so we take it just very little into account.  */
5051e4b17023SJohn Marino 
5052e4b17023SJohn Marino   base = cand->iv->base;
5053e4b17023SJohn Marino   cost_base = force_var_cost (data, base, NULL);
5054e4b17023SJohn Marino   /* It will be exceptional that the iv register happens to be initialized with
5055e4b17023SJohn Marino      the proper value at no cost.  In general, there will at least be a regcopy
5056e4b17023SJohn Marino      or a const set.  */
5057e4b17023SJohn Marino   if (cost_base.cost == 0)
5058e4b17023SJohn Marino     cost_base.cost = COSTS_N_INSNS (1);
5059e4b17023SJohn Marino   cost_step = add_cost (TYPE_MODE (TREE_TYPE (base)), data->speed);
5060e4b17023SJohn Marino 
5061e4b17023SJohn Marino   cost = cost_step + adjust_setup_cost (data, cost_base.cost);
5062e4b17023SJohn Marino 
5063e4b17023SJohn Marino   /* Prefer the original ivs unless we may gain something by replacing it.
5064e4b17023SJohn Marino      The reason is to make debugging simpler; so this is not relevant for
5065e4b17023SJohn Marino      artificial ivs created by other optimization passes.  */
5066e4b17023SJohn Marino   if (cand->pos != IP_ORIGINAL
5067e4b17023SJohn Marino       || DECL_ARTIFICIAL (SSA_NAME_VAR (cand->var_before)))
5068e4b17023SJohn Marino     cost++;
5069e4b17023SJohn Marino 
5070e4b17023SJohn Marino   /* Prefer not to insert statements into latch unless there are some
5071e4b17023SJohn Marino      already (so that we do not create unnecessary jumps).  */
5072e4b17023SJohn Marino   if (cand->pos == IP_END
5073e4b17023SJohn Marino       && empty_block_p (ip_end_pos (data->current_loop)))
5074e4b17023SJohn Marino     cost++;
5075e4b17023SJohn Marino 
5076e4b17023SJohn Marino   cand->cost = cost;
5077e4b17023SJohn Marino   cand->cost_step = cost_step;
5078e4b17023SJohn Marino }
5079e4b17023SJohn Marino 
5080e4b17023SJohn Marino /* Determines costs of computation of the candidates.  */
5081e4b17023SJohn Marino 
5082e4b17023SJohn Marino static void
determine_iv_costs(struct ivopts_data * data)5083e4b17023SJohn Marino determine_iv_costs (struct ivopts_data *data)
5084e4b17023SJohn Marino {
5085e4b17023SJohn Marino   unsigned i;
5086e4b17023SJohn Marino 
5087e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
5088e4b17023SJohn Marino     {
5089e4b17023SJohn Marino       fprintf (dump_file, "Candidate costs:\n");
5090e4b17023SJohn Marino       fprintf (dump_file, "  cand\tcost\n");
5091e4b17023SJohn Marino     }
5092e4b17023SJohn Marino 
5093e4b17023SJohn Marino   for (i = 0; i < n_iv_cands (data); i++)
5094e4b17023SJohn Marino     {
5095e4b17023SJohn Marino       struct iv_cand *cand = iv_cand (data, i);
5096e4b17023SJohn Marino 
5097e4b17023SJohn Marino       determine_iv_cost (data, cand);
5098e4b17023SJohn Marino 
5099e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
5100e4b17023SJohn Marino 	fprintf (dump_file, "  %d\t%d\n", i, cand->cost);
5101e4b17023SJohn Marino     }
5102e4b17023SJohn Marino 
5103e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
5104e4b17023SJohn Marino     fprintf (dump_file, "\n");
5105e4b17023SJohn Marino }
5106e4b17023SJohn Marino 
5107e4b17023SJohn Marino /* Calculates cost for having SIZE induction variables.  */
5108e4b17023SJohn Marino 
5109e4b17023SJohn Marino static unsigned
ivopts_global_cost_for_size(struct ivopts_data * data,unsigned size)5110e4b17023SJohn Marino ivopts_global_cost_for_size (struct ivopts_data *data, unsigned size)
5111e4b17023SJohn Marino {
5112e4b17023SJohn Marino   /* We add size to the cost, so that we prefer eliminating ivs
5113e4b17023SJohn Marino      if possible.  */
5114e4b17023SJohn Marino   return size + estimate_reg_pressure_cost (size, data->regs_used, data->speed,
5115e4b17023SJohn Marino 					    data->body_includes_call);
5116e4b17023SJohn Marino }
5117e4b17023SJohn Marino 
5118e4b17023SJohn Marino /* For each size of the induction variable set determine the penalty.  */
5119e4b17023SJohn Marino 
5120e4b17023SJohn Marino static void
determine_set_costs(struct ivopts_data * data)5121e4b17023SJohn Marino determine_set_costs (struct ivopts_data *data)
5122e4b17023SJohn Marino {
5123e4b17023SJohn Marino   unsigned j, n;
5124e4b17023SJohn Marino   gimple phi;
5125e4b17023SJohn Marino   gimple_stmt_iterator psi;
5126e4b17023SJohn Marino   tree op;
5127e4b17023SJohn Marino   struct loop *loop = data->current_loop;
5128e4b17023SJohn Marino   bitmap_iterator bi;
5129e4b17023SJohn Marino 
5130e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
5131e4b17023SJohn Marino     {
5132e4b17023SJohn Marino       fprintf (dump_file, "Global costs:\n");
5133e4b17023SJohn Marino       fprintf (dump_file, "  target_avail_regs %d\n", target_avail_regs);
5134e4b17023SJohn Marino       fprintf (dump_file, "  target_clobbered_regs %d\n", target_clobbered_regs);
5135e4b17023SJohn Marino       fprintf (dump_file, "  target_reg_cost %d\n", target_reg_cost[data->speed]);
5136e4b17023SJohn Marino       fprintf (dump_file, "  target_spill_cost %d\n", target_spill_cost[data->speed]);
5137e4b17023SJohn Marino     }
5138e4b17023SJohn Marino 
5139e4b17023SJohn Marino   n = 0;
5140e4b17023SJohn Marino   for (psi = gsi_start_phis (loop->header); !gsi_end_p (psi); gsi_next (&psi))
5141e4b17023SJohn Marino     {
5142e4b17023SJohn Marino       phi = gsi_stmt (psi);
5143e4b17023SJohn Marino       op = PHI_RESULT (phi);
5144e4b17023SJohn Marino 
5145e4b17023SJohn Marino       if (!is_gimple_reg (op))
5146e4b17023SJohn Marino 	continue;
5147e4b17023SJohn Marino 
5148e4b17023SJohn Marino       if (get_iv (data, op))
5149e4b17023SJohn Marino 	continue;
5150e4b17023SJohn Marino 
5151e4b17023SJohn Marino       n++;
5152e4b17023SJohn Marino     }
5153e4b17023SJohn Marino 
5154e4b17023SJohn Marino   EXECUTE_IF_SET_IN_BITMAP (data->relevant, 0, j, bi)
5155e4b17023SJohn Marino     {
5156e4b17023SJohn Marino       struct version_info *info = ver_info (data, j);
5157e4b17023SJohn Marino 
5158e4b17023SJohn Marino       if (info->inv_id && info->has_nonlin_use)
5159e4b17023SJohn Marino 	n++;
5160e4b17023SJohn Marino     }
5161e4b17023SJohn Marino 
5162e4b17023SJohn Marino   data->regs_used = n;
5163e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
5164e4b17023SJohn Marino     fprintf (dump_file, "  regs_used %d\n", n);
5165e4b17023SJohn Marino 
5166e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
5167e4b17023SJohn Marino     {
5168e4b17023SJohn Marino       fprintf (dump_file, "  cost for size:\n");
5169e4b17023SJohn Marino       fprintf (dump_file, "  ivs\tcost\n");
5170e4b17023SJohn Marino       for (j = 0; j <= 2 * target_avail_regs; j++)
5171e4b17023SJohn Marino 	fprintf (dump_file, "  %d\t%d\n", j,
5172e4b17023SJohn Marino 		 ivopts_global_cost_for_size (data, j));
5173e4b17023SJohn Marino       fprintf (dump_file, "\n");
5174e4b17023SJohn Marino     }
5175e4b17023SJohn Marino }
5176e4b17023SJohn Marino 
5177e4b17023SJohn Marino /* Returns true if A is a cheaper cost pair than B.  */
5178e4b17023SJohn Marino 
5179e4b17023SJohn Marino static bool
cheaper_cost_pair(struct cost_pair * a,struct cost_pair * b)5180e4b17023SJohn Marino cheaper_cost_pair (struct cost_pair *a, struct cost_pair *b)
5181e4b17023SJohn Marino {
5182e4b17023SJohn Marino   int cmp;
5183e4b17023SJohn Marino 
5184e4b17023SJohn Marino   if (!a)
5185e4b17023SJohn Marino     return false;
5186e4b17023SJohn Marino 
5187e4b17023SJohn Marino   if (!b)
5188e4b17023SJohn Marino     return true;
5189e4b17023SJohn Marino 
5190e4b17023SJohn Marino   cmp = compare_costs (a->cost, b->cost);
5191e4b17023SJohn Marino   if (cmp < 0)
5192e4b17023SJohn Marino     return true;
5193e4b17023SJohn Marino 
5194e4b17023SJohn Marino   if (cmp > 0)
5195e4b17023SJohn Marino     return false;
5196e4b17023SJohn Marino 
5197e4b17023SJohn Marino   /* In case the costs are the same, prefer the cheaper candidate.  */
5198e4b17023SJohn Marino   if (a->cand->cost < b->cand->cost)
5199e4b17023SJohn Marino     return true;
5200e4b17023SJohn Marino 
5201e4b17023SJohn Marino   return false;
5202e4b17023SJohn Marino }
5203e4b17023SJohn Marino 
5204e4b17023SJohn Marino 
5205e4b17023SJohn Marino /* Returns candidate by that USE is expressed in IVS.  */
5206e4b17023SJohn Marino 
5207e4b17023SJohn Marino static struct cost_pair *
iv_ca_cand_for_use(struct iv_ca * ivs,struct iv_use * use)5208e4b17023SJohn Marino iv_ca_cand_for_use (struct iv_ca *ivs, struct iv_use *use)
5209e4b17023SJohn Marino {
5210e4b17023SJohn Marino   return ivs->cand_for_use[use->id];
5211e4b17023SJohn Marino }
5212e4b17023SJohn Marino 
5213e4b17023SJohn Marino /* Computes the cost field of IVS structure.  */
5214e4b17023SJohn Marino 
5215e4b17023SJohn Marino static void
iv_ca_recount_cost(struct ivopts_data * data,struct iv_ca * ivs)5216e4b17023SJohn Marino iv_ca_recount_cost (struct ivopts_data *data, struct iv_ca *ivs)
5217e4b17023SJohn Marino {
5218e4b17023SJohn Marino   comp_cost cost = ivs->cand_use_cost;
5219e4b17023SJohn Marino 
5220e4b17023SJohn Marino   cost.cost += ivs->cand_cost;
5221e4b17023SJohn Marino 
5222e4b17023SJohn Marino   cost.cost += ivopts_global_cost_for_size (data,
5223e4b17023SJohn Marino                                             ivs->n_regs + ivs->num_used_inv_expr);
5224e4b17023SJohn Marino 
5225e4b17023SJohn Marino   ivs->cost = cost;
5226e4b17023SJohn Marino }
5227e4b17023SJohn Marino 
5228e4b17023SJohn Marino /* Remove invariants in set INVS to set IVS.  */
5229e4b17023SJohn Marino 
5230e4b17023SJohn Marino static void
iv_ca_set_remove_invariants(struct iv_ca * ivs,bitmap invs)5231e4b17023SJohn Marino iv_ca_set_remove_invariants (struct iv_ca *ivs, bitmap invs)
5232e4b17023SJohn Marino {
5233e4b17023SJohn Marino   bitmap_iterator bi;
5234e4b17023SJohn Marino   unsigned iid;
5235e4b17023SJohn Marino 
5236e4b17023SJohn Marino   if (!invs)
5237e4b17023SJohn Marino     return;
5238e4b17023SJohn Marino 
5239e4b17023SJohn Marino   EXECUTE_IF_SET_IN_BITMAP (invs, 0, iid, bi)
5240e4b17023SJohn Marino     {
5241e4b17023SJohn Marino       ivs->n_invariant_uses[iid]--;
5242e4b17023SJohn Marino       if (ivs->n_invariant_uses[iid] == 0)
5243e4b17023SJohn Marino         ivs->n_regs--;
5244e4b17023SJohn Marino     }
5245e4b17023SJohn Marino }
5246e4b17023SJohn Marino 
5247e4b17023SJohn Marino /* Set USE not to be expressed by any candidate in IVS.  */
5248e4b17023SJohn Marino 
5249e4b17023SJohn Marino static void
iv_ca_set_no_cp(struct ivopts_data * data,struct iv_ca * ivs,struct iv_use * use)5250e4b17023SJohn Marino iv_ca_set_no_cp (struct ivopts_data *data, struct iv_ca *ivs,
5251e4b17023SJohn Marino 		 struct iv_use *use)
5252e4b17023SJohn Marino {
5253e4b17023SJohn Marino   unsigned uid = use->id, cid;
5254e4b17023SJohn Marino   struct cost_pair *cp;
5255e4b17023SJohn Marino 
5256e4b17023SJohn Marino   cp = ivs->cand_for_use[uid];
5257e4b17023SJohn Marino   if (!cp)
5258e4b17023SJohn Marino     return;
5259e4b17023SJohn Marino   cid = cp->cand->id;
5260e4b17023SJohn Marino 
5261e4b17023SJohn Marino   ivs->bad_uses++;
5262e4b17023SJohn Marino   ivs->cand_for_use[uid] = NULL;
5263e4b17023SJohn Marino   ivs->n_cand_uses[cid]--;
5264e4b17023SJohn Marino 
5265e4b17023SJohn Marino   if (ivs->n_cand_uses[cid] == 0)
5266e4b17023SJohn Marino     {
5267e4b17023SJohn Marino       bitmap_clear_bit (ivs->cands, cid);
5268e4b17023SJohn Marino       /* Do not count the pseudocandidates.  */
5269e4b17023SJohn Marino       if (cp->cand->iv)
5270e4b17023SJohn Marino 	ivs->n_regs--;
5271e4b17023SJohn Marino       ivs->n_cands--;
5272e4b17023SJohn Marino       ivs->cand_cost -= cp->cand->cost;
5273e4b17023SJohn Marino 
5274e4b17023SJohn Marino       iv_ca_set_remove_invariants (ivs, cp->cand->depends_on);
5275e4b17023SJohn Marino     }
5276e4b17023SJohn Marino 
5277e4b17023SJohn Marino   ivs->cand_use_cost = sub_costs (ivs->cand_use_cost, cp->cost);
5278e4b17023SJohn Marino 
5279e4b17023SJohn Marino   iv_ca_set_remove_invariants (ivs, cp->depends_on);
5280e4b17023SJohn Marino 
5281e4b17023SJohn Marino   if (cp->inv_expr_id != -1)
5282e4b17023SJohn Marino     {
5283e4b17023SJohn Marino       ivs->used_inv_expr[cp->inv_expr_id]--;
5284e4b17023SJohn Marino       if (ivs->used_inv_expr[cp->inv_expr_id] == 0)
5285e4b17023SJohn Marino         ivs->num_used_inv_expr--;
5286e4b17023SJohn Marino     }
5287e4b17023SJohn Marino   iv_ca_recount_cost (data, ivs);
5288e4b17023SJohn Marino }
5289e4b17023SJohn Marino 
5290e4b17023SJohn Marino /* Add invariants in set INVS to set IVS.  */
5291e4b17023SJohn Marino 
5292e4b17023SJohn Marino static void
iv_ca_set_add_invariants(struct iv_ca * ivs,bitmap invs)5293e4b17023SJohn Marino iv_ca_set_add_invariants (struct iv_ca *ivs, bitmap invs)
5294e4b17023SJohn Marino {
5295e4b17023SJohn Marino   bitmap_iterator bi;
5296e4b17023SJohn Marino   unsigned iid;
5297e4b17023SJohn Marino 
5298e4b17023SJohn Marino   if (!invs)
5299e4b17023SJohn Marino     return;
5300e4b17023SJohn Marino 
5301e4b17023SJohn Marino   EXECUTE_IF_SET_IN_BITMAP (invs, 0, iid, bi)
5302e4b17023SJohn Marino     {
5303e4b17023SJohn Marino       ivs->n_invariant_uses[iid]++;
5304e4b17023SJohn Marino       if (ivs->n_invariant_uses[iid] == 1)
5305e4b17023SJohn Marino         ivs->n_regs++;
5306e4b17023SJohn Marino     }
5307e4b17023SJohn Marino }
5308e4b17023SJohn Marino 
5309e4b17023SJohn Marino /* Set cost pair for USE in set IVS to CP.  */
5310e4b17023SJohn Marino 
5311e4b17023SJohn Marino static void
iv_ca_set_cp(struct ivopts_data * data,struct iv_ca * ivs,struct iv_use * use,struct cost_pair * cp)5312e4b17023SJohn Marino iv_ca_set_cp (struct ivopts_data *data, struct iv_ca *ivs,
5313e4b17023SJohn Marino 	      struct iv_use *use, struct cost_pair *cp)
5314e4b17023SJohn Marino {
5315e4b17023SJohn Marino   unsigned uid = use->id, cid;
5316e4b17023SJohn Marino 
5317e4b17023SJohn Marino   if (ivs->cand_for_use[uid] == cp)
5318e4b17023SJohn Marino     return;
5319e4b17023SJohn Marino 
5320e4b17023SJohn Marino   if (ivs->cand_for_use[uid])
5321e4b17023SJohn Marino     iv_ca_set_no_cp (data, ivs, use);
5322e4b17023SJohn Marino 
5323e4b17023SJohn Marino   if (cp)
5324e4b17023SJohn Marino     {
5325e4b17023SJohn Marino       cid = cp->cand->id;
5326e4b17023SJohn Marino 
5327e4b17023SJohn Marino       ivs->bad_uses--;
5328e4b17023SJohn Marino       ivs->cand_for_use[uid] = cp;
5329e4b17023SJohn Marino       ivs->n_cand_uses[cid]++;
5330e4b17023SJohn Marino       if (ivs->n_cand_uses[cid] == 1)
5331e4b17023SJohn Marino 	{
5332e4b17023SJohn Marino 	  bitmap_set_bit (ivs->cands, cid);
5333e4b17023SJohn Marino 	  /* Do not count the pseudocandidates.  */
5334e4b17023SJohn Marino 	  if (cp->cand->iv)
5335e4b17023SJohn Marino 	    ivs->n_regs++;
5336e4b17023SJohn Marino 	  ivs->n_cands++;
5337e4b17023SJohn Marino 	  ivs->cand_cost += cp->cand->cost;
5338e4b17023SJohn Marino 
5339e4b17023SJohn Marino 	  iv_ca_set_add_invariants (ivs, cp->cand->depends_on);
5340e4b17023SJohn Marino 	}
5341e4b17023SJohn Marino 
5342e4b17023SJohn Marino       ivs->cand_use_cost = add_costs (ivs->cand_use_cost, cp->cost);
5343e4b17023SJohn Marino       iv_ca_set_add_invariants (ivs, cp->depends_on);
5344e4b17023SJohn Marino 
5345e4b17023SJohn Marino       if (cp->inv_expr_id != -1)
5346e4b17023SJohn Marino         {
5347e4b17023SJohn Marino           ivs->used_inv_expr[cp->inv_expr_id]++;
5348e4b17023SJohn Marino           if (ivs->used_inv_expr[cp->inv_expr_id] == 1)
5349e4b17023SJohn Marino             ivs->num_used_inv_expr++;
5350e4b17023SJohn Marino         }
5351e4b17023SJohn Marino       iv_ca_recount_cost (data, ivs);
5352e4b17023SJohn Marino     }
5353e4b17023SJohn Marino }
5354e4b17023SJohn Marino 
5355e4b17023SJohn Marino /* Extend set IVS by expressing USE by some of the candidates in it
5356e4b17023SJohn Marino    if possible. All important candidates will be considered
5357e4b17023SJohn Marino    if IMPORTANT_CANDIDATES is true.  */
5358e4b17023SJohn Marino 
5359e4b17023SJohn Marino static void
iv_ca_add_use(struct ivopts_data * data,struct iv_ca * ivs,struct iv_use * use,bool important_candidates)5360e4b17023SJohn Marino iv_ca_add_use (struct ivopts_data *data, struct iv_ca *ivs,
5361e4b17023SJohn Marino 	       struct iv_use *use, bool important_candidates)
5362e4b17023SJohn Marino {
5363e4b17023SJohn Marino   struct cost_pair *best_cp = NULL, *cp;
5364e4b17023SJohn Marino   bitmap_iterator bi;
5365e4b17023SJohn Marino   bitmap cands;
5366e4b17023SJohn Marino   unsigned i;
5367e4b17023SJohn Marino 
5368e4b17023SJohn Marino   gcc_assert (ivs->upto >= use->id);
5369e4b17023SJohn Marino 
5370e4b17023SJohn Marino   if (ivs->upto == use->id)
5371e4b17023SJohn Marino     {
5372e4b17023SJohn Marino       ivs->upto++;
5373e4b17023SJohn Marino       ivs->bad_uses++;
5374e4b17023SJohn Marino     }
5375e4b17023SJohn Marino 
5376e4b17023SJohn Marino   cands = (important_candidates ? data->important_candidates : ivs->cands);
5377e4b17023SJohn Marino   EXECUTE_IF_SET_IN_BITMAP (cands, 0, i, bi)
5378e4b17023SJohn Marino     {
5379e4b17023SJohn Marino       struct iv_cand *cand = iv_cand (data, i);
5380e4b17023SJohn Marino 
5381e4b17023SJohn Marino       cp = get_use_iv_cost (data, use, cand);
5382e4b17023SJohn Marino 
5383e4b17023SJohn Marino       if (cheaper_cost_pair (cp, best_cp))
5384e4b17023SJohn Marino 	best_cp = cp;
5385e4b17023SJohn Marino     }
5386e4b17023SJohn Marino 
5387e4b17023SJohn Marino   iv_ca_set_cp (data, ivs, use, best_cp);
5388e4b17023SJohn Marino }
5389e4b17023SJohn Marino 
5390e4b17023SJohn Marino /* Get cost for assignment IVS.  */
5391e4b17023SJohn Marino 
5392e4b17023SJohn Marino static comp_cost
iv_ca_cost(struct iv_ca * ivs)5393e4b17023SJohn Marino iv_ca_cost (struct iv_ca *ivs)
5394e4b17023SJohn Marino {
5395e4b17023SJohn Marino   /* This was a conditional expression but it triggered a bug in
5396e4b17023SJohn Marino      Sun C 5.5.  */
5397e4b17023SJohn Marino   if (ivs->bad_uses)
5398e4b17023SJohn Marino     return infinite_cost;
5399e4b17023SJohn Marino   else
5400e4b17023SJohn Marino     return ivs->cost;
5401e4b17023SJohn Marino }
5402e4b17023SJohn Marino 
5403e4b17023SJohn Marino /* Returns true if all dependences of CP are among invariants in IVS.  */
5404e4b17023SJohn Marino 
5405e4b17023SJohn Marino static bool
iv_ca_has_deps(struct iv_ca * ivs,struct cost_pair * cp)5406e4b17023SJohn Marino iv_ca_has_deps (struct iv_ca *ivs, struct cost_pair *cp)
5407e4b17023SJohn Marino {
5408e4b17023SJohn Marino   unsigned i;
5409e4b17023SJohn Marino   bitmap_iterator bi;
5410e4b17023SJohn Marino 
5411e4b17023SJohn Marino   if (!cp->depends_on)
5412e4b17023SJohn Marino     return true;
5413e4b17023SJohn Marino 
5414e4b17023SJohn Marino   EXECUTE_IF_SET_IN_BITMAP (cp->depends_on, 0, i, bi)
5415e4b17023SJohn Marino     {
5416e4b17023SJohn Marino       if (ivs->n_invariant_uses[i] == 0)
5417e4b17023SJohn Marino 	return false;
5418e4b17023SJohn Marino     }
5419e4b17023SJohn Marino 
5420e4b17023SJohn Marino   return true;
5421e4b17023SJohn Marino }
5422e4b17023SJohn Marino 
5423e4b17023SJohn Marino /* Creates change of expressing USE by NEW_CP instead of OLD_CP and chains
5424e4b17023SJohn Marino    it before NEXT_CHANGE.  */
5425e4b17023SJohn Marino 
5426e4b17023SJohn Marino static struct iv_ca_delta *
iv_ca_delta_add(struct iv_use * use,struct cost_pair * old_cp,struct cost_pair * new_cp,struct iv_ca_delta * next_change)5427e4b17023SJohn Marino iv_ca_delta_add (struct iv_use *use, struct cost_pair *old_cp,
5428e4b17023SJohn Marino 		 struct cost_pair *new_cp, struct iv_ca_delta *next_change)
5429e4b17023SJohn Marino {
5430e4b17023SJohn Marino   struct iv_ca_delta *change = XNEW (struct iv_ca_delta);
5431e4b17023SJohn Marino 
5432e4b17023SJohn Marino   change->use = use;
5433e4b17023SJohn Marino   change->old_cp = old_cp;
5434e4b17023SJohn Marino   change->new_cp = new_cp;
5435e4b17023SJohn Marino   change->next_change = next_change;
5436e4b17023SJohn Marino 
5437e4b17023SJohn Marino   return change;
5438e4b17023SJohn Marino }
5439e4b17023SJohn Marino 
5440e4b17023SJohn Marino /* Joins two lists of changes L1 and L2.  Destructive -- old lists
5441e4b17023SJohn Marino    are rewritten.  */
5442e4b17023SJohn Marino 
5443e4b17023SJohn Marino static struct iv_ca_delta *
iv_ca_delta_join(struct iv_ca_delta * l1,struct iv_ca_delta * l2)5444e4b17023SJohn Marino iv_ca_delta_join (struct iv_ca_delta *l1, struct iv_ca_delta *l2)
5445e4b17023SJohn Marino {
5446e4b17023SJohn Marino   struct iv_ca_delta *last;
5447e4b17023SJohn Marino 
5448e4b17023SJohn Marino   if (!l2)
5449e4b17023SJohn Marino     return l1;
5450e4b17023SJohn Marino 
5451e4b17023SJohn Marino   if (!l1)
5452e4b17023SJohn Marino     return l2;
5453e4b17023SJohn Marino 
5454e4b17023SJohn Marino   for (last = l1; last->next_change; last = last->next_change)
5455e4b17023SJohn Marino     continue;
5456e4b17023SJohn Marino   last->next_change = l2;
5457e4b17023SJohn Marino 
5458e4b17023SJohn Marino   return l1;
5459e4b17023SJohn Marino }
5460e4b17023SJohn Marino 
5461e4b17023SJohn Marino /* Reverse the list of changes DELTA, forming the inverse to it.  */
5462e4b17023SJohn Marino 
5463e4b17023SJohn Marino static struct iv_ca_delta *
iv_ca_delta_reverse(struct iv_ca_delta * delta)5464e4b17023SJohn Marino iv_ca_delta_reverse (struct iv_ca_delta *delta)
5465e4b17023SJohn Marino {
5466e4b17023SJohn Marino   struct iv_ca_delta *act, *next, *prev = NULL;
5467e4b17023SJohn Marino   struct cost_pair *tmp;
5468e4b17023SJohn Marino 
5469e4b17023SJohn Marino   for (act = delta; act; act = next)
5470e4b17023SJohn Marino     {
5471e4b17023SJohn Marino       next = act->next_change;
5472e4b17023SJohn Marino       act->next_change = prev;
5473e4b17023SJohn Marino       prev = act;
5474e4b17023SJohn Marino 
5475e4b17023SJohn Marino       tmp = act->old_cp;
5476e4b17023SJohn Marino       act->old_cp = act->new_cp;
5477e4b17023SJohn Marino       act->new_cp = tmp;
5478e4b17023SJohn Marino     }
5479e4b17023SJohn Marino 
5480e4b17023SJohn Marino   return prev;
5481e4b17023SJohn Marino }
5482e4b17023SJohn Marino 
5483e4b17023SJohn Marino /* Commit changes in DELTA to IVS.  If FORWARD is false, the changes are
5484e4b17023SJohn Marino    reverted instead.  */
5485e4b17023SJohn Marino 
5486e4b17023SJohn Marino static void
iv_ca_delta_commit(struct ivopts_data * data,struct iv_ca * ivs,struct iv_ca_delta * delta,bool forward)5487e4b17023SJohn Marino iv_ca_delta_commit (struct ivopts_data *data, struct iv_ca *ivs,
5488e4b17023SJohn Marino 		    struct iv_ca_delta *delta, bool forward)
5489e4b17023SJohn Marino {
5490e4b17023SJohn Marino   struct cost_pair *from, *to;
5491e4b17023SJohn Marino   struct iv_ca_delta *act;
5492e4b17023SJohn Marino 
5493e4b17023SJohn Marino   if (!forward)
5494e4b17023SJohn Marino     delta = iv_ca_delta_reverse (delta);
5495e4b17023SJohn Marino 
5496e4b17023SJohn Marino   for (act = delta; act; act = act->next_change)
5497e4b17023SJohn Marino     {
5498e4b17023SJohn Marino       from = act->old_cp;
5499e4b17023SJohn Marino       to = act->new_cp;
5500e4b17023SJohn Marino       gcc_assert (iv_ca_cand_for_use (ivs, act->use) == from);
5501e4b17023SJohn Marino       iv_ca_set_cp (data, ivs, act->use, to);
5502e4b17023SJohn Marino     }
5503e4b17023SJohn Marino 
5504e4b17023SJohn Marino   if (!forward)
5505e4b17023SJohn Marino     iv_ca_delta_reverse (delta);
5506e4b17023SJohn Marino }
5507e4b17023SJohn Marino 
5508e4b17023SJohn Marino /* Returns true if CAND is used in IVS.  */
5509e4b17023SJohn Marino 
5510e4b17023SJohn Marino static bool
iv_ca_cand_used_p(struct iv_ca * ivs,struct iv_cand * cand)5511e4b17023SJohn Marino iv_ca_cand_used_p (struct iv_ca *ivs, struct iv_cand *cand)
5512e4b17023SJohn Marino {
5513e4b17023SJohn Marino   return ivs->n_cand_uses[cand->id] > 0;
5514e4b17023SJohn Marino }
5515e4b17023SJohn Marino 
5516e4b17023SJohn Marino /* Returns number of induction variable candidates in the set IVS.  */
5517e4b17023SJohn Marino 
5518e4b17023SJohn Marino static unsigned
iv_ca_n_cands(struct iv_ca * ivs)5519e4b17023SJohn Marino iv_ca_n_cands (struct iv_ca *ivs)
5520e4b17023SJohn Marino {
5521e4b17023SJohn Marino   return ivs->n_cands;
5522e4b17023SJohn Marino }
5523e4b17023SJohn Marino 
5524e4b17023SJohn Marino /* Free the list of changes DELTA.  */
5525e4b17023SJohn Marino 
5526e4b17023SJohn Marino static void
iv_ca_delta_free(struct iv_ca_delta ** delta)5527e4b17023SJohn Marino iv_ca_delta_free (struct iv_ca_delta **delta)
5528e4b17023SJohn Marino {
5529e4b17023SJohn Marino   struct iv_ca_delta *act, *next;
5530e4b17023SJohn Marino 
5531e4b17023SJohn Marino   for (act = *delta; act; act = next)
5532e4b17023SJohn Marino     {
5533e4b17023SJohn Marino       next = act->next_change;
5534e4b17023SJohn Marino       free (act);
5535e4b17023SJohn Marino     }
5536e4b17023SJohn Marino 
5537e4b17023SJohn Marino   *delta = NULL;
5538e4b17023SJohn Marino }
5539e4b17023SJohn Marino 
5540e4b17023SJohn Marino /* Allocates new iv candidates assignment.  */
5541e4b17023SJohn Marino 
5542e4b17023SJohn Marino static struct iv_ca *
iv_ca_new(struct ivopts_data * data)5543e4b17023SJohn Marino iv_ca_new (struct ivopts_data *data)
5544e4b17023SJohn Marino {
5545e4b17023SJohn Marino   struct iv_ca *nw = XNEW (struct iv_ca);
5546e4b17023SJohn Marino 
5547e4b17023SJohn Marino   nw->upto = 0;
5548e4b17023SJohn Marino   nw->bad_uses = 0;
5549e4b17023SJohn Marino   nw->cand_for_use = XCNEWVEC (struct cost_pair *, n_iv_uses (data));
5550e4b17023SJohn Marino   nw->n_cand_uses = XCNEWVEC (unsigned, n_iv_cands (data));
5551e4b17023SJohn Marino   nw->cands = BITMAP_ALLOC (NULL);
5552e4b17023SJohn Marino   nw->n_cands = 0;
5553e4b17023SJohn Marino   nw->n_regs = 0;
5554e4b17023SJohn Marino   nw->cand_use_cost = zero_cost;
5555e4b17023SJohn Marino   nw->cand_cost = 0;
5556e4b17023SJohn Marino   nw->n_invariant_uses = XCNEWVEC (unsigned, data->max_inv_id + 1);
5557e4b17023SJohn Marino   nw->cost = zero_cost;
5558e4b17023SJohn Marino   nw->used_inv_expr = XCNEWVEC (unsigned, data->inv_expr_id + 1);
5559e4b17023SJohn Marino   nw->num_used_inv_expr = 0;
5560e4b17023SJohn Marino 
5561e4b17023SJohn Marino   return nw;
5562e4b17023SJohn Marino }
5563e4b17023SJohn Marino 
5564e4b17023SJohn Marino /* Free memory occupied by the set IVS.  */
5565e4b17023SJohn Marino 
5566e4b17023SJohn Marino static void
iv_ca_free(struct iv_ca ** ivs)5567e4b17023SJohn Marino iv_ca_free (struct iv_ca **ivs)
5568e4b17023SJohn Marino {
5569e4b17023SJohn Marino   free ((*ivs)->cand_for_use);
5570e4b17023SJohn Marino   free ((*ivs)->n_cand_uses);
5571e4b17023SJohn Marino   BITMAP_FREE ((*ivs)->cands);
5572e4b17023SJohn Marino   free ((*ivs)->n_invariant_uses);
5573e4b17023SJohn Marino   free ((*ivs)->used_inv_expr);
5574e4b17023SJohn Marino   free (*ivs);
5575e4b17023SJohn Marino   *ivs = NULL;
5576e4b17023SJohn Marino }
5577e4b17023SJohn Marino 
5578e4b17023SJohn Marino /* Dumps IVS to FILE.  */
5579e4b17023SJohn Marino 
5580e4b17023SJohn Marino static void
iv_ca_dump(struct ivopts_data * data,FILE * file,struct iv_ca * ivs)5581e4b17023SJohn Marino iv_ca_dump (struct ivopts_data *data, FILE *file, struct iv_ca *ivs)
5582e4b17023SJohn Marino {
5583e4b17023SJohn Marino   const char *pref = "  invariants ";
5584e4b17023SJohn Marino   unsigned i;
5585e4b17023SJohn Marino   comp_cost cost = iv_ca_cost (ivs);
5586e4b17023SJohn Marino 
5587e4b17023SJohn Marino   fprintf (file, "  cost: %d (complexity %d)\n", cost.cost, cost.complexity);
5588e4b17023SJohn Marino   fprintf (file, "  cand_cost: %d\n  cand_use_cost: %d (complexity %d)\n",
5589e4b17023SJohn Marino            ivs->cand_cost, ivs->cand_use_cost.cost, ivs->cand_use_cost.complexity);
5590e4b17023SJohn Marino   bitmap_print (file, ivs->cands, "  candidates: ","\n");
5591e4b17023SJohn Marino 
5592e4b17023SJohn Marino    for (i = 0; i < ivs->upto; i++)
5593e4b17023SJohn Marino     {
5594e4b17023SJohn Marino       struct iv_use *use = iv_use (data, i);
5595e4b17023SJohn Marino       struct cost_pair *cp = iv_ca_cand_for_use (ivs, use);
5596e4b17023SJohn Marino       if (cp)
5597e4b17023SJohn Marino         fprintf (file, "   use:%d --> iv_cand:%d, cost=(%d,%d)\n",
5598e4b17023SJohn Marino                  use->id, cp->cand->id, cp->cost.cost, cp->cost.complexity);
5599e4b17023SJohn Marino       else
5600e4b17023SJohn Marino         fprintf (file, "   use:%d --> ??\n", use->id);
5601e4b17023SJohn Marino     }
5602e4b17023SJohn Marino 
5603e4b17023SJohn Marino   for (i = 1; i <= data->max_inv_id; i++)
5604e4b17023SJohn Marino     if (ivs->n_invariant_uses[i])
5605e4b17023SJohn Marino       {
5606e4b17023SJohn Marino 	fprintf (file, "%s%d", pref, i);
5607e4b17023SJohn Marino 	pref = ", ";
5608e4b17023SJohn Marino       }
5609e4b17023SJohn Marino   fprintf (file, "\n\n");
5610e4b17023SJohn Marino }
5611e4b17023SJohn Marino 
5612e4b17023SJohn Marino /* Try changing candidate in IVS to CAND for each use.  Return cost of the
5613e4b17023SJohn Marino    new set, and store differences in DELTA.  Number of induction variables
5614e4b17023SJohn Marino    in the new set is stored to N_IVS. MIN_NCAND is a flag. When it is true
5615e4b17023SJohn Marino    the function will try to find a solution with mimimal iv candidates.  */
5616e4b17023SJohn Marino 
5617e4b17023SJohn Marino static comp_cost
iv_ca_extend(struct ivopts_data * data,struct iv_ca * ivs,struct iv_cand * cand,struct iv_ca_delta ** delta,unsigned * n_ivs,bool min_ncand)5618e4b17023SJohn Marino iv_ca_extend (struct ivopts_data *data, struct iv_ca *ivs,
5619e4b17023SJohn Marino 	      struct iv_cand *cand, struct iv_ca_delta **delta,
5620e4b17023SJohn Marino 	      unsigned *n_ivs, bool min_ncand)
5621e4b17023SJohn Marino {
5622e4b17023SJohn Marino   unsigned i;
5623e4b17023SJohn Marino   comp_cost cost;
5624e4b17023SJohn Marino   struct iv_use *use;
5625e4b17023SJohn Marino   struct cost_pair *old_cp, *new_cp;
5626e4b17023SJohn Marino 
5627e4b17023SJohn Marino   *delta = NULL;
5628e4b17023SJohn Marino   for (i = 0; i < ivs->upto; i++)
5629e4b17023SJohn Marino     {
5630e4b17023SJohn Marino       use = iv_use (data, i);
5631e4b17023SJohn Marino       old_cp = iv_ca_cand_for_use (ivs, use);
5632e4b17023SJohn Marino 
5633e4b17023SJohn Marino       if (old_cp
5634e4b17023SJohn Marino 	  && old_cp->cand == cand)
5635e4b17023SJohn Marino 	continue;
5636e4b17023SJohn Marino 
5637e4b17023SJohn Marino       new_cp = get_use_iv_cost (data, use, cand);
5638e4b17023SJohn Marino       if (!new_cp)
5639e4b17023SJohn Marino 	continue;
5640e4b17023SJohn Marino 
5641e4b17023SJohn Marino       if (!min_ncand && !iv_ca_has_deps (ivs, new_cp))
5642e4b17023SJohn Marino 	continue;
5643e4b17023SJohn Marino 
5644e4b17023SJohn Marino       if (!min_ncand && !cheaper_cost_pair (new_cp, old_cp))
5645e4b17023SJohn Marino         continue;
5646e4b17023SJohn Marino 
5647e4b17023SJohn Marino       *delta = iv_ca_delta_add (use, old_cp, new_cp, *delta);
5648e4b17023SJohn Marino     }
5649e4b17023SJohn Marino 
5650e4b17023SJohn Marino   iv_ca_delta_commit (data, ivs, *delta, true);
5651e4b17023SJohn Marino   cost = iv_ca_cost (ivs);
5652e4b17023SJohn Marino   if (n_ivs)
5653e4b17023SJohn Marino     *n_ivs = iv_ca_n_cands (ivs);
5654e4b17023SJohn Marino   iv_ca_delta_commit (data, ivs, *delta, false);
5655e4b17023SJohn Marino 
5656e4b17023SJohn Marino   return cost;
5657e4b17023SJohn Marino }
5658e4b17023SJohn Marino 
5659e4b17023SJohn Marino /* Try narrowing set IVS by removing CAND.  Return the cost of
5660e4b17023SJohn Marino    the new set and store the differences in DELTA.  */
5661e4b17023SJohn Marino 
5662e4b17023SJohn Marino static comp_cost
iv_ca_narrow(struct ivopts_data * data,struct iv_ca * ivs,struct iv_cand * cand,struct iv_ca_delta ** delta)5663e4b17023SJohn Marino iv_ca_narrow (struct ivopts_data *data, struct iv_ca *ivs,
5664e4b17023SJohn Marino 	      struct iv_cand *cand, struct iv_ca_delta **delta)
5665e4b17023SJohn Marino {
5666e4b17023SJohn Marino   unsigned i, ci;
5667e4b17023SJohn Marino   struct iv_use *use;
5668e4b17023SJohn Marino   struct cost_pair *old_cp, *new_cp, *cp;
5669e4b17023SJohn Marino   bitmap_iterator bi;
5670e4b17023SJohn Marino   struct iv_cand *cnd;
5671e4b17023SJohn Marino   comp_cost cost;
5672e4b17023SJohn Marino 
5673e4b17023SJohn Marino   *delta = NULL;
5674e4b17023SJohn Marino   for (i = 0; i < n_iv_uses (data); i++)
5675e4b17023SJohn Marino     {
5676e4b17023SJohn Marino       use = iv_use (data, i);
5677e4b17023SJohn Marino 
5678e4b17023SJohn Marino       old_cp = iv_ca_cand_for_use (ivs, use);
5679e4b17023SJohn Marino       if (old_cp->cand != cand)
5680e4b17023SJohn Marino 	continue;
5681e4b17023SJohn Marino 
5682e4b17023SJohn Marino       new_cp = NULL;
5683e4b17023SJohn Marino 
5684e4b17023SJohn Marino       if (data->consider_all_candidates)
5685e4b17023SJohn Marino 	{
5686e4b17023SJohn Marino 	  EXECUTE_IF_SET_IN_BITMAP (ivs->cands, 0, ci, bi)
5687e4b17023SJohn Marino 	    {
5688e4b17023SJohn Marino 	      if (ci == cand->id)
5689e4b17023SJohn Marino 		continue;
5690e4b17023SJohn Marino 
5691e4b17023SJohn Marino 	      cnd = iv_cand (data, ci);
5692e4b17023SJohn Marino 
5693e4b17023SJohn Marino 	      cp = get_use_iv_cost (data, use, cnd);
5694e4b17023SJohn Marino 	      if (!cp)
5695e4b17023SJohn Marino 		continue;
5696e4b17023SJohn Marino 
5697e4b17023SJohn Marino 	      if (!iv_ca_has_deps (ivs, cp))
5698e4b17023SJohn Marino                 continue;
5699e4b17023SJohn Marino 
5700e4b17023SJohn Marino 	      if (!cheaper_cost_pair (cp, new_cp))
5701e4b17023SJohn Marino 		continue;
5702e4b17023SJohn Marino 
5703e4b17023SJohn Marino 	      new_cp = cp;
5704e4b17023SJohn Marino 	    }
5705e4b17023SJohn Marino 	}
5706e4b17023SJohn Marino       else
5707e4b17023SJohn Marino 	{
5708e4b17023SJohn Marino 	  EXECUTE_IF_AND_IN_BITMAP (use->related_cands, ivs->cands, 0, ci, bi)
5709e4b17023SJohn Marino 	    {
5710e4b17023SJohn Marino 	      if (ci == cand->id)
5711e4b17023SJohn Marino 		continue;
5712e4b17023SJohn Marino 
5713e4b17023SJohn Marino 	      cnd = iv_cand (data, ci);
5714e4b17023SJohn Marino 
5715e4b17023SJohn Marino 	      cp = get_use_iv_cost (data, use, cnd);
5716e4b17023SJohn Marino 	      if (!cp)
5717e4b17023SJohn Marino 		continue;
5718e4b17023SJohn Marino 	      if (!iv_ca_has_deps (ivs, cp))
5719e4b17023SJohn Marino 		continue;
5720e4b17023SJohn Marino 
5721e4b17023SJohn Marino 	      if (!cheaper_cost_pair (cp, new_cp))
5722e4b17023SJohn Marino 		continue;
5723e4b17023SJohn Marino 
5724e4b17023SJohn Marino 	      new_cp = cp;
5725e4b17023SJohn Marino 	    }
5726e4b17023SJohn Marino 	}
5727e4b17023SJohn Marino 
5728e4b17023SJohn Marino       if (!new_cp)
5729e4b17023SJohn Marino 	{
5730e4b17023SJohn Marino 	  iv_ca_delta_free (delta);
5731e4b17023SJohn Marino 	  return infinite_cost;
5732e4b17023SJohn Marino 	}
5733e4b17023SJohn Marino 
5734e4b17023SJohn Marino       *delta = iv_ca_delta_add (use, old_cp, new_cp, *delta);
5735e4b17023SJohn Marino     }
5736e4b17023SJohn Marino 
5737e4b17023SJohn Marino   iv_ca_delta_commit (data, ivs, *delta, true);
5738e4b17023SJohn Marino   cost = iv_ca_cost (ivs);
5739e4b17023SJohn Marino   iv_ca_delta_commit (data, ivs, *delta, false);
5740e4b17023SJohn Marino 
5741e4b17023SJohn Marino   return cost;
5742e4b17023SJohn Marino }
5743e4b17023SJohn Marino 
5744e4b17023SJohn Marino /* Try optimizing the set of candidates IVS by removing candidates different
5745e4b17023SJohn Marino    from to EXCEPT_CAND from it.  Return cost of the new set, and store
5746e4b17023SJohn Marino    differences in DELTA.  */
5747e4b17023SJohn Marino 
5748e4b17023SJohn Marino static comp_cost
iv_ca_prune(struct ivopts_data * data,struct iv_ca * ivs,struct iv_cand * except_cand,struct iv_ca_delta ** delta)5749e4b17023SJohn Marino iv_ca_prune (struct ivopts_data *data, struct iv_ca *ivs,
5750e4b17023SJohn Marino 	     struct iv_cand *except_cand, struct iv_ca_delta **delta)
5751e4b17023SJohn Marino {
5752e4b17023SJohn Marino   bitmap_iterator bi;
5753e4b17023SJohn Marino   struct iv_ca_delta *act_delta, *best_delta;
5754e4b17023SJohn Marino   unsigned i;
5755e4b17023SJohn Marino   comp_cost best_cost, acost;
5756e4b17023SJohn Marino   struct iv_cand *cand;
5757e4b17023SJohn Marino 
5758e4b17023SJohn Marino   best_delta = NULL;
5759e4b17023SJohn Marino   best_cost = iv_ca_cost (ivs);
5760e4b17023SJohn Marino 
5761e4b17023SJohn Marino   EXECUTE_IF_SET_IN_BITMAP (ivs->cands, 0, i, bi)
5762e4b17023SJohn Marino     {
5763e4b17023SJohn Marino       cand = iv_cand (data, i);
5764e4b17023SJohn Marino 
5765e4b17023SJohn Marino       if (cand == except_cand)
5766e4b17023SJohn Marino 	continue;
5767e4b17023SJohn Marino 
5768e4b17023SJohn Marino       acost = iv_ca_narrow (data, ivs, cand, &act_delta);
5769e4b17023SJohn Marino 
5770e4b17023SJohn Marino       if (compare_costs (acost, best_cost) < 0)
5771e4b17023SJohn Marino 	{
5772e4b17023SJohn Marino 	  best_cost = acost;
5773e4b17023SJohn Marino 	  iv_ca_delta_free (&best_delta);
5774e4b17023SJohn Marino 	  best_delta = act_delta;
5775e4b17023SJohn Marino 	}
5776e4b17023SJohn Marino       else
5777e4b17023SJohn Marino 	iv_ca_delta_free (&act_delta);
5778e4b17023SJohn Marino     }
5779e4b17023SJohn Marino 
5780e4b17023SJohn Marino   if (!best_delta)
5781e4b17023SJohn Marino     {
5782e4b17023SJohn Marino       *delta = NULL;
5783e4b17023SJohn Marino       return best_cost;
5784e4b17023SJohn Marino     }
5785e4b17023SJohn Marino 
5786e4b17023SJohn Marino   /* Recurse to possibly remove other unnecessary ivs.  */
5787e4b17023SJohn Marino   iv_ca_delta_commit (data, ivs, best_delta, true);
5788e4b17023SJohn Marino   best_cost = iv_ca_prune (data, ivs, except_cand, delta);
5789e4b17023SJohn Marino   iv_ca_delta_commit (data, ivs, best_delta, false);
5790e4b17023SJohn Marino   *delta = iv_ca_delta_join (best_delta, *delta);
5791e4b17023SJohn Marino   return best_cost;
5792e4b17023SJohn Marino }
5793e4b17023SJohn Marino 
5794e4b17023SJohn Marino /* Tries to extend the sets IVS in the best possible way in order
5795e4b17023SJohn Marino    to express the USE.  If ORIGINALP is true, prefer candidates from
5796e4b17023SJohn Marino    the original set of IVs, otherwise favor important candidates not
5797e4b17023SJohn Marino    based on any memory object.  */
5798e4b17023SJohn Marino 
5799e4b17023SJohn Marino static bool
try_add_cand_for(struct ivopts_data * data,struct iv_ca * ivs,struct iv_use * use,bool originalp)5800e4b17023SJohn Marino try_add_cand_for (struct ivopts_data *data, struct iv_ca *ivs,
5801e4b17023SJohn Marino 		  struct iv_use *use, bool originalp)
5802e4b17023SJohn Marino {
5803e4b17023SJohn Marino   comp_cost best_cost, act_cost;
5804e4b17023SJohn Marino   unsigned i;
5805e4b17023SJohn Marino   bitmap_iterator bi;
5806e4b17023SJohn Marino   struct iv_cand *cand;
5807e4b17023SJohn Marino   struct iv_ca_delta *best_delta = NULL, *act_delta;
5808e4b17023SJohn Marino   struct cost_pair *cp;
5809e4b17023SJohn Marino 
5810e4b17023SJohn Marino   iv_ca_add_use (data, ivs, use, false);
5811e4b17023SJohn Marino   best_cost = iv_ca_cost (ivs);
5812e4b17023SJohn Marino 
5813e4b17023SJohn Marino   cp = iv_ca_cand_for_use (ivs, use);
5814e4b17023SJohn Marino   if (!cp)
5815e4b17023SJohn Marino     {
5816e4b17023SJohn Marino       ivs->upto--;
5817e4b17023SJohn Marino       ivs->bad_uses--;
5818e4b17023SJohn Marino       iv_ca_add_use (data, ivs, use, true);
5819e4b17023SJohn Marino       best_cost = iv_ca_cost (ivs);
5820e4b17023SJohn Marino       cp = iv_ca_cand_for_use (ivs, use);
5821e4b17023SJohn Marino     }
5822e4b17023SJohn Marino   if (cp)
5823e4b17023SJohn Marino     {
5824e4b17023SJohn Marino       best_delta = iv_ca_delta_add (use, NULL, cp, NULL);
5825e4b17023SJohn Marino       iv_ca_set_no_cp (data, ivs, use);
5826e4b17023SJohn Marino     }
5827e4b17023SJohn Marino 
5828e4b17023SJohn Marino   /* If ORIGINALP is true, try to find the original IV for the use.  Otherwise
5829e4b17023SJohn Marino      first try important candidates not based on any memory object.  Only if
5830e4b17023SJohn Marino      this fails, try the specific ones.  Rationale -- in loops with many
5831e4b17023SJohn Marino      variables the best choice often is to use just one generic biv.  If we
5832e4b17023SJohn Marino      added here many ivs specific to the uses, the optimization algorithm later
5833e4b17023SJohn Marino      would be likely to get stuck in a local minimum, thus causing us to create
5834e4b17023SJohn Marino      too many ivs.  The approach from few ivs to more seems more likely to be
5835e4b17023SJohn Marino      successful -- starting from few ivs, replacing an expensive use by a
5836e4b17023SJohn Marino      specific iv should always be a win.  */
5837e4b17023SJohn Marino   EXECUTE_IF_SET_IN_BITMAP (data->important_candidates, 0, i, bi)
5838e4b17023SJohn Marino     {
5839e4b17023SJohn Marino       cand = iv_cand (data, i);
5840e4b17023SJohn Marino 
5841e4b17023SJohn Marino       if (originalp && cand->pos !=IP_ORIGINAL)
5842e4b17023SJohn Marino 	continue;
5843e4b17023SJohn Marino 
5844e4b17023SJohn Marino       if (!originalp && cand->iv->base_object != NULL_TREE)
5845e4b17023SJohn Marino 	continue;
5846e4b17023SJohn Marino 
5847e4b17023SJohn Marino       if (iv_ca_cand_used_p (ivs, cand))
5848e4b17023SJohn Marino         continue;
5849e4b17023SJohn Marino 
5850e4b17023SJohn Marino       cp = get_use_iv_cost (data, use, cand);
5851e4b17023SJohn Marino       if (!cp)
5852e4b17023SJohn Marino 	continue;
5853e4b17023SJohn Marino 
5854e4b17023SJohn Marino       iv_ca_set_cp (data, ivs, use, cp);
5855e4b17023SJohn Marino       act_cost = iv_ca_extend (data, ivs, cand, &act_delta, NULL,
5856e4b17023SJohn Marino                                true);
5857e4b17023SJohn Marino       iv_ca_set_no_cp (data, ivs, use);
5858e4b17023SJohn Marino       act_delta = iv_ca_delta_add (use, NULL, cp, act_delta);
5859e4b17023SJohn Marino 
5860e4b17023SJohn Marino       if (compare_costs (act_cost, best_cost) < 0)
5861e4b17023SJohn Marino 	{
5862e4b17023SJohn Marino 	  best_cost = act_cost;
5863e4b17023SJohn Marino 
5864e4b17023SJohn Marino 	  iv_ca_delta_free (&best_delta);
5865e4b17023SJohn Marino 	  best_delta = act_delta;
5866e4b17023SJohn Marino 	}
5867e4b17023SJohn Marino       else
5868e4b17023SJohn Marino 	iv_ca_delta_free (&act_delta);
5869e4b17023SJohn Marino     }
5870e4b17023SJohn Marino 
5871e4b17023SJohn Marino   if (infinite_cost_p (best_cost))
5872e4b17023SJohn Marino     {
5873e4b17023SJohn Marino       for (i = 0; i < use->n_map_members; i++)
5874e4b17023SJohn Marino 	{
5875e4b17023SJohn Marino 	  cp = use->cost_map + i;
5876e4b17023SJohn Marino 	  cand = cp->cand;
5877e4b17023SJohn Marino 	  if (!cand)
5878e4b17023SJohn Marino 	    continue;
5879e4b17023SJohn Marino 
5880e4b17023SJohn Marino 	  /* Already tried this.  */
5881e4b17023SJohn Marino 	  if (cand->important)
5882e4b17023SJohn Marino 	    {
5883e4b17023SJohn Marino 	      if (originalp && cand->pos == IP_ORIGINAL)
5884e4b17023SJohn Marino 		continue;
5885e4b17023SJohn Marino 	      if (!originalp && cand->iv->base_object == NULL_TREE)
5886e4b17023SJohn Marino 		continue;
5887e4b17023SJohn Marino 	    }
5888e4b17023SJohn Marino 
5889e4b17023SJohn Marino 	  if (iv_ca_cand_used_p (ivs, cand))
5890e4b17023SJohn Marino 	    continue;
5891e4b17023SJohn Marino 
5892e4b17023SJohn Marino 	  act_delta = NULL;
5893e4b17023SJohn Marino 	  iv_ca_set_cp (data, ivs, use, cp);
5894e4b17023SJohn Marino 	  act_cost = iv_ca_extend (data, ivs, cand, &act_delta, NULL, true);
5895e4b17023SJohn Marino 	  iv_ca_set_no_cp (data, ivs, use);
5896e4b17023SJohn Marino 	  act_delta = iv_ca_delta_add (use, iv_ca_cand_for_use (ivs, use),
5897e4b17023SJohn Marino 				       cp, act_delta);
5898e4b17023SJohn Marino 
5899e4b17023SJohn Marino 	  if (compare_costs (act_cost, best_cost) < 0)
5900e4b17023SJohn Marino 	    {
5901e4b17023SJohn Marino 	      best_cost = act_cost;
5902e4b17023SJohn Marino 
5903e4b17023SJohn Marino 	      if (best_delta)
5904e4b17023SJohn Marino 		iv_ca_delta_free (&best_delta);
5905e4b17023SJohn Marino 	      best_delta = act_delta;
5906e4b17023SJohn Marino 	    }
5907e4b17023SJohn Marino 	  else
5908e4b17023SJohn Marino 	    iv_ca_delta_free (&act_delta);
5909e4b17023SJohn Marino 	}
5910e4b17023SJohn Marino     }
5911e4b17023SJohn Marino 
5912e4b17023SJohn Marino   iv_ca_delta_commit (data, ivs, best_delta, true);
5913e4b17023SJohn Marino   iv_ca_delta_free (&best_delta);
5914e4b17023SJohn Marino 
5915e4b17023SJohn Marino   return !infinite_cost_p (best_cost);
5916e4b17023SJohn Marino }
5917e4b17023SJohn Marino 
5918e4b17023SJohn Marino /* Finds an initial assignment of candidates to uses.  */
5919e4b17023SJohn Marino 
5920e4b17023SJohn Marino static struct iv_ca *
get_initial_solution(struct ivopts_data * data,bool originalp)5921e4b17023SJohn Marino get_initial_solution (struct ivopts_data *data, bool originalp)
5922e4b17023SJohn Marino {
5923e4b17023SJohn Marino   struct iv_ca *ivs = iv_ca_new (data);
5924e4b17023SJohn Marino   unsigned i;
5925e4b17023SJohn Marino 
5926e4b17023SJohn Marino   for (i = 0; i < n_iv_uses (data); i++)
5927e4b17023SJohn Marino     if (!try_add_cand_for (data, ivs, iv_use (data, i), originalp))
5928e4b17023SJohn Marino       {
5929e4b17023SJohn Marino 	iv_ca_free (&ivs);
5930e4b17023SJohn Marino 	return NULL;
5931e4b17023SJohn Marino       }
5932e4b17023SJohn Marino 
5933e4b17023SJohn Marino   return ivs;
5934e4b17023SJohn Marino }
5935e4b17023SJohn Marino 
5936e4b17023SJohn Marino /* Tries to improve set of induction variables IVS.  */
5937e4b17023SJohn Marino 
5938e4b17023SJohn Marino static bool
try_improve_iv_set(struct ivopts_data * data,struct iv_ca * ivs)5939e4b17023SJohn Marino try_improve_iv_set (struct ivopts_data *data, struct iv_ca *ivs)
5940e4b17023SJohn Marino {
5941e4b17023SJohn Marino   unsigned i, n_ivs;
5942e4b17023SJohn Marino   comp_cost acost, best_cost = iv_ca_cost (ivs);
5943e4b17023SJohn Marino   struct iv_ca_delta *best_delta = NULL, *act_delta, *tmp_delta;
5944e4b17023SJohn Marino   struct iv_cand *cand;
5945e4b17023SJohn Marino 
5946e4b17023SJohn Marino   /* Try extending the set of induction variables by one.  */
5947e4b17023SJohn Marino   for (i = 0; i < n_iv_cands (data); i++)
5948e4b17023SJohn Marino     {
5949e4b17023SJohn Marino       cand = iv_cand (data, i);
5950e4b17023SJohn Marino 
5951e4b17023SJohn Marino       if (iv_ca_cand_used_p (ivs, cand))
5952e4b17023SJohn Marino 	continue;
5953e4b17023SJohn Marino 
5954e4b17023SJohn Marino       acost = iv_ca_extend (data, ivs, cand, &act_delta, &n_ivs, false);
5955e4b17023SJohn Marino       if (!act_delta)
5956e4b17023SJohn Marino 	continue;
5957e4b17023SJohn Marino 
5958e4b17023SJohn Marino       /* If we successfully added the candidate and the set is small enough,
5959e4b17023SJohn Marino 	 try optimizing it by removing other candidates.  */
5960e4b17023SJohn Marino       if (n_ivs <= ALWAYS_PRUNE_CAND_SET_BOUND)
5961e4b17023SJohn Marino       	{
5962e4b17023SJohn Marino 	  iv_ca_delta_commit (data, ivs, act_delta, true);
5963e4b17023SJohn Marino 	  acost = iv_ca_prune (data, ivs, cand, &tmp_delta);
5964e4b17023SJohn Marino 	  iv_ca_delta_commit (data, ivs, act_delta, false);
5965e4b17023SJohn Marino 	  act_delta = iv_ca_delta_join (act_delta, tmp_delta);
5966e4b17023SJohn Marino 	}
5967e4b17023SJohn Marino 
5968e4b17023SJohn Marino       if (compare_costs (acost, best_cost) < 0)
5969e4b17023SJohn Marino 	{
5970e4b17023SJohn Marino 	  best_cost = acost;
5971e4b17023SJohn Marino 	  iv_ca_delta_free (&best_delta);
5972e4b17023SJohn Marino 	  best_delta = act_delta;
5973e4b17023SJohn Marino 	}
5974e4b17023SJohn Marino       else
5975e4b17023SJohn Marino 	iv_ca_delta_free (&act_delta);
5976e4b17023SJohn Marino     }
5977e4b17023SJohn Marino 
5978e4b17023SJohn Marino   if (!best_delta)
5979e4b17023SJohn Marino     {
5980e4b17023SJohn Marino       /* Try removing the candidates from the set instead.  */
5981e4b17023SJohn Marino       best_cost = iv_ca_prune (data, ivs, NULL, &best_delta);
5982e4b17023SJohn Marino 
5983e4b17023SJohn Marino       /* Nothing more we can do.  */
5984e4b17023SJohn Marino       if (!best_delta)
5985e4b17023SJohn Marino 	return false;
5986e4b17023SJohn Marino     }
5987e4b17023SJohn Marino 
5988e4b17023SJohn Marino   iv_ca_delta_commit (data, ivs, best_delta, true);
5989e4b17023SJohn Marino   gcc_assert (compare_costs (best_cost, iv_ca_cost (ivs)) == 0);
5990e4b17023SJohn Marino   iv_ca_delta_free (&best_delta);
5991e4b17023SJohn Marino   return true;
5992e4b17023SJohn Marino }
5993e4b17023SJohn Marino 
5994e4b17023SJohn Marino /* Attempts to find the optimal set of induction variables.  We do simple
5995e4b17023SJohn Marino    greedy heuristic -- we try to replace at most one candidate in the selected
5996e4b17023SJohn Marino    solution and remove the unused ivs while this improves the cost.  */
5997e4b17023SJohn Marino 
5998e4b17023SJohn Marino static struct iv_ca *
find_optimal_iv_set_1(struct ivopts_data * data,bool originalp)5999e4b17023SJohn Marino find_optimal_iv_set_1 (struct ivopts_data *data, bool originalp)
6000e4b17023SJohn Marino {
6001e4b17023SJohn Marino   struct iv_ca *set;
6002e4b17023SJohn Marino 
6003e4b17023SJohn Marino   /* Get the initial solution.  */
6004e4b17023SJohn Marino   set = get_initial_solution (data, originalp);
6005e4b17023SJohn Marino   if (!set)
6006e4b17023SJohn Marino     {
6007e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
6008e4b17023SJohn Marino 	fprintf (dump_file, "Unable to substitute for ivs, failed.\n");
6009e4b17023SJohn Marino       return NULL;
6010e4b17023SJohn Marino     }
6011e4b17023SJohn Marino 
6012e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
6013e4b17023SJohn Marino     {
6014e4b17023SJohn Marino       fprintf (dump_file, "Initial set of candidates:\n");
6015e4b17023SJohn Marino       iv_ca_dump (data, dump_file, set);
6016e4b17023SJohn Marino     }
6017e4b17023SJohn Marino 
6018e4b17023SJohn Marino   while (try_improve_iv_set (data, set))
6019e4b17023SJohn Marino     {
6020e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
6021e4b17023SJohn Marino 	{
6022e4b17023SJohn Marino 	  fprintf (dump_file, "Improved to:\n");
6023e4b17023SJohn Marino 	  iv_ca_dump (data, dump_file, set);
6024e4b17023SJohn Marino 	}
6025e4b17023SJohn Marino     }
6026e4b17023SJohn Marino 
6027e4b17023SJohn Marino   return set;
6028e4b17023SJohn Marino }
6029e4b17023SJohn Marino 
6030e4b17023SJohn Marino static struct iv_ca *
find_optimal_iv_set(struct ivopts_data * data)6031e4b17023SJohn Marino find_optimal_iv_set (struct ivopts_data *data)
6032e4b17023SJohn Marino {
6033e4b17023SJohn Marino   unsigned i;
6034e4b17023SJohn Marino   struct iv_ca *set, *origset;
6035e4b17023SJohn Marino   struct iv_use *use;
6036e4b17023SJohn Marino   comp_cost cost, origcost;
6037e4b17023SJohn Marino 
6038e4b17023SJohn Marino   /* Determine the cost based on a strategy that starts with original IVs,
6039e4b17023SJohn Marino      and try again using a strategy that prefers candidates not based
6040e4b17023SJohn Marino      on any IVs.  */
6041e4b17023SJohn Marino   origset = find_optimal_iv_set_1 (data, true);
6042e4b17023SJohn Marino   set = find_optimal_iv_set_1 (data, false);
6043e4b17023SJohn Marino 
6044e4b17023SJohn Marino   if (!origset && !set)
6045e4b17023SJohn Marino     return NULL;
6046e4b17023SJohn Marino 
6047e4b17023SJohn Marino   origcost = origset ? iv_ca_cost (origset) : infinite_cost;
6048e4b17023SJohn Marino   cost = set ? iv_ca_cost (set) : infinite_cost;
6049e4b17023SJohn Marino 
6050e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
6051e4b17023SJohn Marino     {
6052e4b17023SJohn Marino       fprintf (dump_file, "Original cost %d (complexity %d)\n\n",
6053e4b17023SJohn Marino 	       origcost.cost, origcost.complexity);
6054e4b17023SJohn Marino       fprintf (dump_file, "Final cost %d (complexity %d)\n\n",
6055e4b17023SJohn Marino 	       cost.cost, cost.complexity);
6056e4b17023SJohn Marino     }
6057e4b17023SJohn Marino 
6058e4b17023SJohn Marino   /* Choose the one with the best cost.  */
6059e4b17023SJohn Marino   if (compare_costs (origcost, cost) <= 0)
6060e4b17023SJohn Marino     {
6061e4b17023SJohn Marino       if (set)
6062e4b17023SJohn Marino 	iv_ca_free (&set);
6063e4b17023SJohn Marino       set = origset;
6064e4b17023SJohn Marino     }
6065e4b17023SJohn Marino   else if (origset)
6066e4b17023SJohn Marino     iv_ca_free (&origset);
6067e4b17023SJohn Marino 
6068e4b17023SJohn Marino   for (i = 0; i < n_iv_uses (data); i++)
6069e4b17023SJohn Marino     {
6070e4b17023SJohn Marino       use = iv_use (data, i);
6071e4b17023SJohn Marino       use->selected = iv_ca_cand_for_use (set, use)->cand;
6072e4b17023SJohn Marino     }
6073e4b17023SJohn Marino 
6074e4b17023SJohn Marino   return set;
6075e4b17023SJohn Marino }
6076e4b17023SJohn Marino 
6077e4b17023SJohn Marino /* Creates a new induction variable corresponding to CAND.  */
6078e4b17023SJohn Marino 
6079e4b17023SJohn Marino static void
create_new_iv(struct ivopts_data * data,struct iv_cand * cand)6080e4b17023SJohn Marino create_new_iv (struct ivopts_data *data, struct iv_cand *cand)
6081e4b17023SJohn Marino {
6082e4b17023SJohn Marino   gimple_stmt_iterator incr_pos;
6083e4b17023SJohn Marino   tree base;
6084e4b17023SJohn Marino   bool after = false;
6085e4b17023SJohn Marino 
6086e4b17023SJohn Marino   if (!cand->iv)
6087e4b17023SJohn Marino     return;
6088e4b17023SJohn Marino 
6089e4b17023SJohn Marino   switch (cand->pos)
6090e4b17023SJohn Marino     {
6091e4b17023SJohn Marino     case IP_NORMAL:
6092e4b17023SJohn Marino       incr_pos = gsi_last_bb (ip_normal_pos (data->current_loop));
6093e4b17023SJohn Marino       break;
6094e4b17023SJohn Marino 
6095e4b17023SJohn Marino     case IP_END:
6096e4b17023SJohn Marino       incr_pos = gsi_last_bb (ip_end_pos (data->current_loop));
6097e4b17023SJohn Marino       after = true;
6098e4b17023SJohn Marino       break;
6099e4b17023SJohn Marino 
6100e4b17023SJohn Marino     case IP_AFTER_USE:
6101e4b17023SJohn Marino       after = true;
6102e4b17023SJohn Marino       /* fall through */
6103e4b17023SJohn Marino     case IP_BEFORE_USE:
6104e4b17023SJohn Marino       incr_pos = gsi_for_stmt (cand->incremented_at);
6105e4b17023SJohn Marino       break;
6106e4b17023SJohn Marino 
6107e4b17023SJohn Marino     case IP_ORIGINAL:
6108e4b17023SJohn Marino       /* Mark that the iv is preserved.  */
6109e4b17023SJohn Marino       name_info (data, cand->var_before)->preserve_biv = true;
6110e4b17023SJohn Marino       name_info (data, cand->var_after)->preserve_biv = true;
6111e4b17023SJohn Marino 
6112e4b17023SJohn Marino       /* Rewrite the increment so that it uses var_before directly.  */
6113e4b17023SJohn Marino       find_interesting_uses_op (data, cand->var_after)->selected = cand;
6114e4b17023SJohn Marino       return;
6115e4b17023SJohn Marino     }
6116e4b17023SJohn Marino 
6117e4b17023SJohn Marino   gimple_add_tmp_var (cand->var_before);
6118e4b17023SJohn Marino   add_referenced_var (cand->var_before);
6119e4b17023SJohn Marino 
6120e4b17023SJohn Marino   base = unshare_expr (cand->iv->base);
6121e4b17023SJohn Marino 
6122e4b17023SJohn Marino   create_iv (base, unshare_expr (cand->iv->step),
6123e4b17023SJohn Marino 	     cand->var_before, data->current_loop,
6124e4b17023SJohn Marino 	     &incr_pos, after, &cand->var_before, &cand->var_after);
6125e4b17023SJohn Marino }
6126e4b17023SJohn Marino 
6127e4b17023SJohn Marino /* Creates new induction variables described in SET.  */
6128e4b17023SJohn Marino 
6129e4b17023SJohn Marino static void
create_new_ivs(struct ivopts_data * data,struct iv_ca * set)6130e4b17023SJohn Marino create_new_ivs (struct ivopts_data *data, struct iv_ca *set)
6131e4b17023SJohn Marino {
6132e4b17023SJohn Marino   unsigned i;
6133e4b17023SJohn Marino   struct iv_cand *cand;
6134e4b17023SJohn Marino   bitmap_iterator bi;
6135e4b17023SJohn Marino 
6136e4b17023SJohn Marino   EXECUTE_IF_SET_IN_BITMAP (set->cands, 0, i, bi)
6137e4b17023SJohn Marino     {
6138e4b17023SJohn Marino       cand = iv_cand (data, i);
6139e4b17023SJohn Marino       create_new_iv (data, cand);
6140e4b17023SJohn Marino     }
6141e4b17023SJohn Marino 
6142e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
6143e4b17023SJohn Marino     {
6144e4b17023SJohn Marino       fprintf (dump_file, "\nSelected IV set: \n");
6145e4b17023SJohn Marino       EXECUTE_IF_SET_IN_BITMAP (set->cands, 0, i, bi)
6146e4b17023SJohn Marino         {
6147e4b17023SJohn Marino           cand = iv_cand (data, i);
6148e4b17023SJohn Marino           dump_cand (dump_file, cand);
6149e4b17023SJohn Marino         }
6150e4b17023SJohn Marino       fprintf (dump_file, "\n");
6151e4b17023SJohn Marino     }
6152e4b17023SJohn Marino }
6153e4b17023SJohn Marino 
6154e4b17023SJohn Marino /* Rewrites USE (definition of iv used in a nonlinear expression)
6155e4b17023SJohn Marino    using candidate CAND.  */
6156e4b17023SJohn Marino 
6157e4b17023SJohn Marino static void
rewrite_use_nonlinear_expr(struct ivopts_data * data,struct iv_use * use,struct iv_cand * cand)6158e4b17023SJohn Marino rewrite_use_nonlinear_expr (struct ivopts_data *data,
6159e4b17023SJohn Marino 			    struct iv_use *use, struct iv_cand *cand)
6160e4b17023SJohn Marino {
6161e4b17023SJohn Marino   tree comp;
6162e4b17023SJohn Marino   tree op, tgt;
6163e4b17023SJohn Marino   gimple ass;
6164e4b17023SJohn Marino   gimple_stmt_iterator bsi;
6165e4b17023SJohn Marino 
6166e4b17023SJohn Marino   /* An important special case -- if we are asked to express value of
6167e4b17023SJohn Marino      the original iv by itself, just exit; there is no need to
6168e4b17023SJohn Marino      introduce a new computation (that might also need casting the
6169e4b17023SJohn Marino      variable to unsigned and back).  */
6170e4b17023SJohn Marino   if (cand->pos == IP_ORIGINAL
6171e4b17023SJohn Marino       && cand->incremented_at == use->stmt)
6172e4b17023SJohn Marino     {
6173*5ce9237cSJohn Marino       enum tree_code stmt_code;
6174e4b17023SJohn Marino 
6175e4b17023SJohn Marino       gcc_assert (is_gimple_assign (use->stmt));
6176e4b17023SJohn Marino       gcc_assert (gimple_assign_lhs (use->stmt) == cand->var_after);
6177e4b17023SJohn Marino 
6178e4b17023SJohn Marino       /* Check whether we may leave the computation unchanged.
6179e4b17023SJohn Marino 	 This is the case only if it does not rely on other
6180e4b17023SJohn Marino 	 computations in the loop -- otherwise, the computation
6181e4b17023SJohn Marino 	 we rely upon may be removed in remove_unused_ivs,
6182e4b17023SJohn Marino 	 thus leading to ICE.  */
6183*5ce9237cSJohn Marino       stmt_code = gimple_assign_rhs_code (use->stmt);
6184*5ce9237cSJohn Marino       if (stmt_code == PLUS_EXPR
6185*5ce9237cSJohn Marino 	  || stmt_code == MINUS_EXPR
6186*5ce9237cSJohn Marino 	  || stmt_code == POINTER_PLUS_EXPR)
6187e4b17023SJohn Marino 	{
6188e4b17023SJohn Marino 	  if (gimple_assign_rhs1 (use->stmt) == cand->var_before)
6189e4b17023SJohn Marino 	    op = gimple_assign_rhs2 (use->stmt);
6190*5ce9237cSJohn Marino 	  else if (gimple_assign_rhs2 (use->stmt) == cand->var_before)
6191e4b17023SJohn Marino 	    op = gimple_assign_rhs1 (use->stmt);
6192e4b17023SJohn Marino 	  else
6193e4b17023SJohn Marino 	    op = NULL_TREE;
6194e4b17023SJohn Marino 	}
6195e4b17023SJohn Marino       else
6196e4b17023SJohn Marino 	op = NULL_TREE;
6197e4b17023SJohn Marino 
6198*5ce9237cSJohn Marino       if (op && expr_invariant_in_loop_p (data->current_loop, op))
6199e4b17023SJohn Marino 	return;
6200e4b17023SJohn Marino     }
6201*5ce9237cSJohn Marino 
6202e4b17023SJohn Marino   comp = get_computation (data->current_loop, use, cand);
6203e4b17023SJohn Marino   gcc_assert (comp != NULL_TREE);
6204e4b17023SJohn Marino 
6205e4b17023SJohn Marino   switch (gimple_code (use->stmt))
6206e4b17023SJohn Marino     {
6207e4b17023SJohn Marino     case GIMPLE_PHI:
6208e4b17023SJohn Marino       tgt = PHI_RESULT (use->stmt);
6209e4b17023SJohn Marino 
6210e4b17023SJohn Marino       /* If we should keep the biv, do not replace it.  */
6211e4b17023SJohn Marino       if (name_info (data, tgt)->preserve_biv)
6212e4b17023SJohn Marino 	return;
6213e4b17023SJohn Marino 
6214e4b17023SJohn Marino       bsi = gsi_after_labels (gimple_bb (use->stmt));
6215e4b17023SJohn Marino       break;
6216e4b17023SJohn Marino 
6217e4b17023SJohn Marino     case GIMPLE_ASSIGN:
6218e4b17023SJohn Marino       tgt = gimple_assign_lhs (use->stmt);
6219e4b17023SJohn Marino       bsi = gsi_for_stmt (use->stmt);
6220e4b17023SJohn Marino       break;
6221e4b17023SJohn Marino 
6222e4b17023SJohn Marino     default:
6223e4b17023SJohn Marino       gcc_unreachable ();
6224e4b17023SJohn Marino     }
6225e4b17023SJohn Marino 
6226e4b17023SJohn Marino   if (!valid_gimple_rhs_p (comp)
6227e4b17023SJohn Marino       || (gimple_code (use->stmt) != GIMPLE_PHI
6228e4b17023SJohn Marino 	  /* We can't allow re-allocating the stmt as it might be pointed
6229e4b17023SJohn Marino 	     to still.  */
6230e4b17023SJohn Marino 	  && (get_gimple_rhs_num_ops (TREE_CODE (comp))
6231e4b17023SJohn Marino 	      >= gimple_num_ops (gsi_stmt (bsi)))))
6232e4b17023SJohn Marino     {
6233e4b17023SJohn Marino       comp = force_gimple_operand_gsi (&bsi, comp, true, NULL_TREE,
6234e4b17023SJohn Marino 				       true, GSI_SAME_STMT);
6235e4b17023SJohn Marino       if (POINTER_TYPE_P (TREE_TYPE (tgt)))
6236e4b17023SJohn Marino 	{
6237e4b17023SJohn Marino 	  duplicate_ssa_name_ptr_info (comp, SSA_NAME_PTR_INFO (tgt));
6238e4b17023SJohn Marino 	  /* As this isn't a plain copy we have to reset alignment
6239e4b17023SJohn Marino 	     information.  */
6240e4b17023SJohn Marino 	  if (SSA_NAME_PTR_INFO (comp))
6241e4b17023SJohn Marino 	    {
6242e4b17023SJohn Marino 	      SSA_NAME_PTR_INFO (comp)->align = 1;
6243e4b17023SJohn Marino 	      SSA_NAME_PTR_INFO (comp)->misalign = 0;
6244e4b17023SJohn Marino 	    }
6245e4b17023SJohn Marino 	}
6246e4b17023SJohn Marino     }
6247e4b17023SJohn Marino 
6248e4b17023SJohn Marino   if (gimple_code (use->stmt) == GIMPLE_PHI)
6249e4b17023SJohn Marino     {
6250e4b17023SJohn Marino       ass = gimple_build_assign (tgt, comp);
6251e4b17023SJohn Marino       gsi_insert_before (&bsi, ass, GSI_SAME_STMT);
6252e4b17023SJohn Marino 
6253e4b17023SJohn Marino       bsi = gsi_for_stmt (use->stmt);
6254e4b17023SJohn Marino       remove_phi_node (&bsi, false);
6255e4b17023SJohn Marino     }
6256e4b17023SJohn Marino   else
6257e4b17023SJohn Marino     {
6258e4b17023SJohn Marino       gimple_assign_set_rhs_from_tree (&bsi, comp);
6259e4b17023SJohn Marino       use->stmt = gsi_stmt (bsi);
6260e4b17023SJohn Marino     }
6261e4b17023SJohn Marino }
6262e4b17023SJohn Marino 
6263e4b17023SJohn Marino /* Performs a peephole optimization to reorder the iv update statement with
6264e4b17023SJohn Marino    a mem ref to enable instruction combining in later phases. The mem ref uses
6265e4b17023SJohn Marino    the iv value before the update, so the reordering transformation requires
6266e4b17023SJohn Marino    adjustment of the offset. CAND is the selected IV_CAND.
6267e4b17023SJohn Marino 
6268e4b17023SJohn Marino    Example:
6269e4b17023SJohn Marino 
6270e4b17023SJohn Marino    t = MEM_REF (base, iv1, 8, 16);  // base, index, stride, offset
6271e4b17023SJohn Marino    iv2 = iv1 + 1;
6272e4b17023SJohn Marino 
6273e4b17023SJohn Marino    if (t < val)      (1)
6274e4b17023SJohn Marino      goto L;
6275e4b17023SJohn Marino    goto Head;
6276e4b17023SJohn Marino 
6277e4b17023SJohn Marino 
6278e4b17023SJohn Marino    directly propagating t over to (1) will introduce overlapping live range
6279e4b17023SJohn Marino    thus increase register pressure. This peephole transform it into:
6280e4b17023SJohn Marino 
6281e4b17023SJohn Marino 
6282e4b17023SJohn Marino    iv2 = iv1 + 1;
6283e4b17023SJohn Marino    t = MEM_REF (base, iv2, 8, 8);
6284e4b17023SJohn Marino    if (t < val)
6285e4b17023SJohn Marino      goto L;
6286e4b17023SJohn Marino    goto Head;
6287e4b17023SJohn Marino */
6288e4b17023SJohn Marino 
6289e4b17023SJohn Marino static void
adjust_iv_update_pos(struct iv_cand * cand,struct iv_use * use)6290e4b17023SJohn Marino adjust_iv_update_pos (struct iv_cand *cand, struct iv_use *use)
6291e4b17023SJohn Marino {
6292e4b17023SJohn Marino   tree var_after;
6293e4b17023SJohn Marino   gimple iv_update, stmt;
6294e4b17023SJohn Marino   basic_block bb;
6295e4b17023SJohn Marino   gimple_stmt_iterator gsi, gsi_iv;
6296e4b17023SJohn Marino 
6297e4b17023SJohn Marino   if (cand->pos != IP_NORMAL)
6298e4b17023SJohn Marino     return;
6299e4b17023SJohn Marino 
6300e4b17023SJohn Marino   var_after = cand->var_after;
6301e4b17023SJohn Marino   iv_update = SSA_NAME_DEF_STMT (var_after);
6302e4b17023SJohn Marino 
6303e4b17023SJohn Marino   bb = gimple_bb (iv_update);
6304e4b17023SJohn Marino   gsi = gsi_last_nondebug_bb (bb);
6305e4b17023SJohn Marino   stmt = gsi_stmt (gsi);
6306e4b17023SJohn Marino 
6307e4b17023SJohn Marino   /* Only handle conditional statement for now.  */
6308e4b17023SJohn Marino   if (gimple_code (stmt) != GIMPLE_COND)
6309e4b17023SJohn Marino     return;
6310e4b17023SJohn Marino 
6311e4b17023SJohn Marino   gsi_prev_nondebug (&gsi);
6312e4b17023SJohn Marino   stmt = gsi_stmt (gsi);
6313e4b17023SJohn Marino   if (stmt != iv_update)
6314e4b17023SJohn Marino     return;
6315e4b17023SJohn Marino 
6316e4b17023SJohn Marino   gsi_prev_nondebug (&gsi);
6317e4b17023SJohn Marino   if (gsi_end_p (gsi))
6318e4b17023SJohn Marino     return;
6319e4b17023SJohn Marino 
6320e4b17023SJohn Marino   stmt = gsi_stmt (gsi);
6321e4b17023SJohn Marino   if (gimple_code (stmt) != GIMPLE_ASSIGN)
6322e4b17023SJohn Marino     return;
6323e4b17023SJohn Marino 
6324e4b17023SJohn Marino   if (stmt != use->stmt)
6325e4b17023SJohn Marino     return;
6326e4b17023SJohn Marino 
6327e4b17023SJohn Marino   if (TREE_CODE (gimple_assign_lhs (stmt)) != SSA_NAME)
6328e4b17023SJohn Marino     return;
6329e4b17023SJohn Marino 
6330e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
6331e4b17023SJohn Marino     {
6332e4b17023SJohn Marino       fprintf (dump_file, "Reordering \n");
6333e4b17023SJohn Marino       print_gimple_stmt (dump_file, iv_update, 0, 0);
6334e4b17023SJohn Marino       print_gimple_stmt (dump_file, use->stmt, 0, 0);
6335e4b17023SJohn Marino       fprintf (dump_file, "\n");
6336e4b17023SJohn Marino     }
6337e4b17023SJohn Marino 
6338e4b17023SJohn Marino   gsi = gsi_for_stmt (use->stmt);
6339e4b17023SJohn Marino   gsi_iv = gsi_for_stmt (iv_update);
6340e4b17023SJohn Marino   gsi_move_before (&gsi_iv, &gsi);
6341e4b17023SJohn Marino 
6342e4b17023SJohn Marino   cand->pos = IP_BEFORE_USE;
6343e4b17023SJohn Marino   cand->incremented_at = use->stmt;
6344e4b17023SJohn Marino }
6345e4b17023SJohn Marino 
6346e4b17023SJohn Marino /* Rewrites USE (address that is an iv) using candidate CAND.  */
6347e4b17023SJohn Marino 
6348e4b17023SJohn Marino static void
rewrite_use_address(struct ivopts_data * data,struct iv_use * use,struct iv_cand * cand)6349e4b17023SJohn Marino rewrite_use_address (struct ivopts_data *data,
6350e4b17023SJohn Marino 		     struct iv_use *use, struct iv_cand *cand)
6351e4b17023SJohn Marino {
6352e4b17023SJohn Marino   aff_tree aff;
6353e4b17023SJohn Marino   gimple_stmt_iterator bsi = gsi_for_stmt (use->stmt);
6354e4b17023SJohn Marino   tree base_hint = NULL_TREE;
6355e4b17023SJohn Marino   tree ref, iv;
6356e4b17023SJohn Marino   bool ok;
6357e4b17023SJohn Marino 
6358e4b17023SJohn Marino   adjust_iv_update_pos (cand, use);
6359e4b17023SJohn Marino   ok = get_computation_aff (data->current_loop, use, cand, use->stmt, &aff);
6360e4b17023SJohn Marino   gcc_assert (ok);
6361e4b17023SJohn Marino   unshare_aff_combination (&aff);
6362e4b17023SJohn Marino 
6363e4b17023SJohn Marino   /* To avoid undefined overflow problems, all IV candidates use unsigned
6364e4b17023SJohn Marino      integer types.  The drawback is that this makes it impossible for
6365e4b17023SJohn Marino      create_mem_ref to distinguish an IV that is based on a memory object
6366e4b17023SJohn Marino      from one that represents simply an offset.
6367e4b17023SJohn Marino 
6368e4b17023SJohn Marino      To work around this problem, we pass a hint to create_mem_ref that
6369e4b17023SJohn Marino      indicates which variable (if any) in aff is an IV based on a memory
6370e4b17023SJohn Marino      object.  Note that we only consider the candidate.  If this is not
6371e4b17023SJohn Marino      based on an object, the base of the reference is in some subexpression
6372e4b17023SJohn Marino      of the use -- but these will use pointer types, so they are recognized
6373e4b17023SJohn Marino      by the create_mem_ref heuristics anyway.  */
6374e4b17023SJohn Marino   if (cand->iv->base_object)
6375e4b17023SJohn Marino     base_hint = var_at_stmt (data->current_loop, cand, use->stmt);
6376e4b17023SJohn Marino 
6377e4b17023SJohn Marino   iv = var_at_stmt (data->current_loop, cand, use->stmt);
6378e4b17023SJohn Marino   ref = create_mem_ref (&bsi, TREE_TYPE (*use->op_p), &aff,
6379e4b17023SJohn Marino 			reference_alias_ptr_type (*use->op_p),
6380e4b17023SJohn Marino 			iv, base_hint, data->speed);
6381e4b17023SJohn Marino   copy_ref_info (ref, *use->op_p);
6382e4b17023SJohn Marino   *use->op_p = ref;
6383e4b17023SJohn Marino }
6384e4b17023SJohn Marino 
6385e4b17023SJohn Marino /* Rewrites USE (the condition such that one of the arguments is an iv) using
6386e4b17023SJohn Marino    candidate CAND.  */
6387e4b17023SJohn Marino 
6388e4b17023SJohn Marino static void
rewrite_use_compare(struct ivopts_data * data,struct iv_use * use,struct iv_cand * cand)6389e4b17023SJohn Marino rewrite_use_compare (struct ivopts_data *data,
6390e4b17023SJohn Marino 		     struct iv_use *use, struct iv_cand *cand)
6391e4b17023SJohn Marino {
6392e4b17023SJohn Marino   tree comp, *var_p, op, bound;
6393e4b17023SJohn Marino   gimple_stmt_iterator bsi = gsi_for_stmt (use->stmt);
6394e4b17023SJohn Marino   enum tree_code compare;
6395e4b17023SJohn Marino   struct cost_pair *cp = get_use_iv_cost (data, use, cand);
6396e4b17023SJohn Marino   bool ok;
6397e4b17023SJohn Marino 
6398e4b17023SJohn Marino   bound = cp->value;
6399e4b17023SJohn Marino   if (bound)
6400e4b17023SJohn Marino     {
6401e4b17023SJohn Marino       tree var = var_at_stmt (data->current_loop, cand, use->stmt);
6402e4b17023SJohn Marino       tree var_type = TREE_TYPE (var);
6403e4b17023SJohn Marino       gimple_seq stmts;
6404e4b17023SJohn Marino 
6405e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
6406e4b17023SJohn Marino         {
6407e4b17023SJohn Marino           fprintf (dump_file, "Replacing exit test: ");
6408e4b17023SJohn Marino           print_gimple_stmt (dump_file, use->stmt, 0, TDF_SLIM);
6409e4b17023SJohn Marino         }
6410e4b17023SJohn Marino       compare = cp->comp;
6411e4b17023SJohn Marino       bound = unshare_expr (fold_convert (var_type, bound));
6412e4b17023SJohn Marino       op = force_gimple_operand (bound, &stmts, true, NULL_TREE);
6413e4b17023SJohn Marino       if (stmts)
6414e4b17023SJohn Marino 	gsi_insert_seq_on_edge_immediate (
6415e4b17023SJohn Marino 		loop_preheader_edge (data->current_loop),
6416e4b17023SJohn Marino 		stmts);
6417e4b17023SJohn Marino 
6418e4b17023SJohn Marino       gimple_cond_set_lhs (use->stmt, var);
6419e4b17023SJohn Marino       gimple_cond_set_code (use->stmt, compare);
6420e4b17023SJohn Marino       gimple_cond_set_rhs (use->stmt, op);
6421e4b17023SJohn Marino       return;
6422e4b17023SJohn Marino     }
6423e4b17023SJohn Marino 
6424e4b17023SJohn Marino   /* The induction variable elimination failed; just express the original
6425e4b17023SJohn Marino      giv.  */
6426e4b17023SJohn Marino   comp = get_computation (data->current_loop, use, cand);
6427e4b17023SJohn Marino   gcc_assert (comp != NULL_TREE);
6428e4b17023SJohn Marino 
6429e4b17023SJohn Marino   ok = extract_cond_operands (data, use->stmt, &var_p, NULL, NULL, NULL);
6430e4b17023SJohn Marino   gcc_assert (ok);
6431e4b17023SJohn Marino 
6432e4b17023SJohn Marino   *var_p = force_gimple_operand_gsi (&bsi, comp, true, SSA_NAME_VAR (*var_p),
6433e4b17023SJohn Marino 				     true, GSI_SAME_STMT);
6434e4b17023SJohn Marino }
6435e4b17023SJohn Marino 
6436e4b17023SJohn Marino /* Rewrites USE using candidate CAND.  */
6437e4b17023SJohn Marino 
6438e4b17023SJohn Marino static void
rewrite_use(struct ivopts_data * data,struct iv_use * use,struct iv_cand * cand)6439e4b17023SJohn Marino rewrite_use (struct ivopts_data *data, struct iv_use *use, struct iv_cand *cand)
6440e4b17023SJohn Marino {
6441e4b17023SJohn Marino   switch (use->type)
6442e4b17023SJohn Marino     {
6443e4b17023SJohn Marino       case USE_NONLINEAR_EXPR:
6444e4b17023SJohn Marino 	rewrite_use_nonlinear_expr (data, use, cand);
6445e4b17023SJohn Marino 	break;
6446e4b17023SJohn Marino 
6447e4b17023SJohn Marino       case USE_ADDRESS:
6448e4b17023SJohn Marino 	rewrite_use_address (data, use, cand);
6449e4b17023SJohn Marino 	break;
6450e4b17023SJohn Marino 
6451e4b17023SJohn Marino       case USE_COMPARE:
6452e4b17023SJohn Marino 	rewrite_use_compare (data, use, cand);
6453e4b17023SJohn Marino 	break;
6454e4b17023SJohn Marino 
6455e4b17023SJohn Marino       default:
6456e4b17023SJohn Marino 	gcc_unreachable ();
6457e4b17023SJohn Marino     }
6458e4b17023SJohn Marino 
6459e4b17023SJohn Marino   update_stmt (use->stmt);
6460e4b17023SJohn Marino }
6461e4b17023SJohn Marino 
6462e4b17023SJohn Marino /* Rewrite the uses using the selected induction variables.  */
6463e4b17023SJohn Marino 
6464e4b17023SJohn Marino static void
rewrite_uses(struct ivopts_data * data)6465e4b17023SJohn Marino rewrite_uses (struct ivopts_data *data)
6466e4b17023SJohn Marino {
6467e4b17023SJohn Marino   unsigned i;
6468e4b17023SJohn Marino   struct iv_cand *cand;
6469e4b17023SJohn Marino   struct iv_use *use;
6470e4b17023SJohn Marino 
6471e4b17023SJohn Marino   for (i = 0; i < n_iv_uses (data); i++)
6472e4b17023SJohn Marino     {
6473e4b17023SJohn Marino       use = iv_use (data, i);
6474e4b17023SJohn Marino       cand = use->selected;
6475e4b17023SJohn Marino       gcc_assert (cand);
6476e4b17023SJohn Marino 
6477e4b17023SJohn Marino       rewrite_use (data, use, cand);
6478e4b17023SJohn Marino     }
6479e4b17023SJohn Marino }
6480e4b17023SJohn Marino 
6481e4b17023SJohn Marino /* Removes the ivs that are not used after rewriting.  */
6482e4b17023SJohn Marino 
6483e4b17023SJohn Marino static void
remove_unused_ivs(struct ivopts_data * data)6484e4b17023SJohn Marino remove_unused_ivs (struct ivopts_data *data)
6485e4b17023SJohn Marino {
6486e4b17023SJohn Marino   unsigned j;
6487e4b17023SJohn Marino   bitmap_iterator bi;
6488e4b17023SJohn Marino   bitmap toremove = BITMAP_ALLOC (NULL);
6489e4b17023SJohn Marino 
6490e4b17023SJohn Marino   /* Figure out an order in which to release SSA DEFs so that we don't
6491e4b17023SJohn Marino      release something that we'd have to propagate into a debug stmt
6492e4b17023SJohn Marino      afterwards.  */
6493e4b17023SJohn Marino   EXECUTE_IF_SET_IN_BITMAP (data->relevant, 0, j, bi)
6494e4b17023SJohn Marino     {
6495e4b17023SJohn Marino       struct version_info *info;
6496e4b17023SJohn Marino 
6497e4b17023SJohn Marino       info = ver_info (data, j);
6498e4b17023SJohn Marino       if (info->iv
6499e4b17023SJohn Marino 	  && !integer_zerop (info->iv->step)
6500e4b17023SJohn Marino 	  && !info->inv_id
6501e4b17023SJohn Marino 	  && !info->iv->have_use_for
6502e4b17023SJohn Marino 	  && !info->preserve_biv)
6503e4b17023SJohn Marino 	bitmap_set_bit (toremove, SSA_NAME_VERSION (info->iv->ssa_name));
6504e4b17023SJohn Marino     }
6505e4b17023SJohn Marino 
6506e4b17023SJohn Marino   release_defs_bitset (toremove);
6507e4b17023SJohn Marino 
6508e4b17023SJohn Marino   BITMAP_FREE (toremove);
6509e4b17023SJohn Marino }
6510e4b17023SJohn Marino 
6511e4b17023SJohn Marino /* Frees memory occupied by struct tree_niter_desc in *VALUE. Callback
6512e4b17023SJohn Marino    for pointer_map_traverse.  */
6513e4b17023SJohn Marino 
6514e4b17023SJohn Marino static bool
free_tree_niter_desc(const void * key ATTRIBUTE_UNUSED,void ** value,void * data ATTRIBUTE_UNUSED)6515e4b17023SJohn Marino free_tree_niter_desc (const void *key ATTRIBUTE_UNUSED, void **value,
6516e4b17023SJohn Marino                       void *data ATTRIBUTE_UNUSED)
6517e4b17023SJohn Marino {
6518e4b17023SJohn Marino   struct tree_niter_desc *const niter = (struct tree_niter_desc *) *value;
6519e4b17023SJohn Marino 
6520e4b17023SJohn Marino   free (niter);
6521e4b17023SJohn Marino   return true;
6522e4b17023SJohn Marino }
6523e4b17023SJohn Marino 
6524e4b17023SJohn Marino /* Frees data allocated by the optimization of a single loop.  */
6525e4b17023SJohn Marino 
6526e4b17023SJohn Marino static void
free_loop_data(struct ivopts_data * data)6527e4b17023SJohn Marino free_loop_data (struct ivopts_data *data)
6528e4b17023SJohn Marino {
6529e4b17023SJohn Marino   unsigned i, j;
6530e4b17023SJohn Marino   bitmap_iterator bi;
6531e4b17023SJohn Marino   tree obj;
6532e4b17023SJohn Marino 
6533e4b17023SJohn Marino   if (data->niters)
6534e4b17023SJohn Marino     {
6535e4b17023SJohn Marino       pointer_map_traverse (data->niters, free_tree_niter_desc, NULL);
6536e4b17023SJohn Marino       pointer_map_destroy (data->niters);
6537e4b17023SJohn Marino       data->niters = NULL;
6538e4b17023SJohn Marino     }
6539e4b17023SJohn Marino 
6540e4b17023SJohn Marino   EXECUTE_IF_SET_IN_BITMAP (data->relevant, 0, i, bi)
6541e4b17023SJohn Marino     {
6542e4b17023SJohn Marino       struct version_info *info;
6543e4b17023SJohn Marino 
6544e4b17023SJohn Marino       info = ver_info (data, i);
6545e4b17023SJohn Marino       free (info->iv);
6546e4b17023SJohn Marino       info->iv = NULL;
6547e4b17023SJohn Marino       info->has_nonlin_use = false;
6548e4b17023SJohn Marino       info->preserve_biv = false;
6549e4b17023SJohn Marino       info->inv_id = 0;
6550e4b17023SJohn Marino     }
6551e4b17023SJohn Marino   bitmap_clear (data->relevant);
6552e4b17023SJohn Marino   bitmap_clear (data->important_candidates);
6553e4b17023SJohn Marino 
6554e4b17023SJohn Marino   for (i = 0; i < n_iv_uses (data); i++)
6555e4b17023SJohn Marino     {
6556e4b17023SJohn Marino       struct iv_use *use = iv_use (data, i);
6557e4b17023SJohn Marino 
6558e4b17023SJohn Marino       free (use->iv);
6559e4b17023SJohn Marino       BITMAP_FREE (use->related_cands);
6560e4b17023SJohn Marino       for (j = 0; j < use->n_map_members; j++)
6561e4b17023SJohn Marino 	if (use->cost_map[j].depends_on)
6562e4b17023SJohn Marino 	  BITMAP_FREE (use->cost_map[j].depends_on);
6563e4b17023SJohn Marino       free (use->cost_map);
6564e4b17023SJohn Marino       free (use);
6565e4b17023SJohn Marino     }
6566e4b17023SJohn Marino   VEC_truncate (iv_use_p, data->iv_uses, 0);
6567e4b17023SJohn Marino 
6568e4b17023SJohn Marino   for (i = 0; i < n_iv_cands (data); i++)
6569e4b17023SJohn Marino     {
6570e4b17023SJohn Marino       struct iv_cand *cand = iv_cand (data, i);
6571e4b17023SJohn Marino 
6572e4b17023SJohn Marino       free (cand->iv);
6573e4b17023SJohn Marino       if (cand->depends_on)
6574e4b17023SJohn Marino 	BITMAP_FREE (cand->depends_on);
6575e4b17023SJohn Marino       free (cand);
6576e4b17023SJohn Marino     }
6577e4b17023SJohn Marino   VEC_truncate (iv_cand_p, data->iv_candidates, 0);
6578e4b17023SJohn Marino 
6579e4b17023SJohn Marino   if (data->version_info_size < num_ssa_names)
6580e4b17023SJohn Marino     {
6581e4b17023SJohn Marino       data->version_info_size = 2 * num_ssa_names;
6582e4b17023SJohn Marino       free (data->version_info);
6583e4b17023SJohn Marino       data->version_info = XCNEWVEC (struct version_info, data->version_info_size);
6584e4b17023SJohn Marino     }
6585e4b17023SJohn Marino 
6586e4b17023SJohn Marino   data->max_inv_id = 0;
6587e4b17023SJohn Marino 
6588e4b17023SJohn Marino   FOR_EACH_VEC_ELT (tree, decl_rtl_to_reset, i, obj)
6589e4b17023SJohn Marino     SET_DECL_RTL (obj, NULL_RTX);
6590e4b17023SJohn Marino 
6591e4b17023SJohn Marino   VEC_truncate (tree, decl_rtl_to_reset, 0);
6592e4b17023SJohn Marino 
6593e4b17023SJohn Marino   htab_empty (data->inv_expr_tab);
6594e4b17023SJohn Marino   data->inv_expr_id = 0;
6595e4b17023SJohn Marino }
6596e4b17023SJohn Marino 
6597e4b17023SJohn Marino /* Finalizes data structures used by the iv optimization pass.  LOOPS is the
6598e4b17023SJohn Marino    loop tree.  */
6599e4b17023SJohn Marino 
6600e4b17023SJohn Marino static void
tree_ssa_iv_optimize_finalize(struct ivopts_data * data)6601e4b17023SJohn Marino tree_ssa_iv_optimize_finalize (struct ivopts_data *data)
6602e4b17023SJohn Marino {
6603e4b17023SJohn Marino   free_loop_data (data);
6604e4b17023SJohn Marino   free (data->version_info);
6605e4b17023SJohn Marino   BITMAP_FREE (data->relevant);
6606e4b17023SJohn Marino   BITMAP_FREE (data->important_candidates);
6607e4b17023SJohn Marino 
6608e4b17023SJohn Marino   VEC_free (tree, heap, decl_rtl_to_reset);
6609e4b17023SJohn Marino   VEC_free (iv_use_p, heap, data->iv_uses);
6610e4b17023SJohn Marino   VEC_free (iv_cand_p, heap, data->iv_candidates);
6611e4b17023SJohn Marino   htab_delete (data->inv_expr_tab);
6612e4b17023SJohn Marino }
6613e4b17023SJohn Marino 
6614e4b17023SJohn Marino /* Returns true if the loop body BODY includes any function calls.  */
6615e4b17023SJohn Marino 
6616e4b17023SJohn Marino static bool
loop_body_includes_call(basic_block * body,unsigned num_nodes)6617e4b17023SJohn Marino loop_body_includes_call (basic_block *body, unsigned num_nodes)
6618e4b17023SJohn Marino {
6619e4b17023SJohn Marino   gimple_stmt_iterator gsi;
6620e4b17023SJohn Marino   unsigned i;
6621e4b17023SJohn Marino 
6622e4b17023SJohn Marino   for (i = 0; i < num_nodes; i++)
6623e4b17023SJohn Marino     for (gsi = gsi_start_bb (body[i]); !gsi_end_p (gsi); gsi_next (&gsi))
6624e4b17023SJohn Marino       {
6625e4b17023SJohn Marino 	gimple stmt = gsi_stmt (gsi);
6626e4b17023SJohn Marino 	if (is_gimple_call (stmt)
6627e4b17023SJohn Marino 	    && !is_inexpensive_builtin (gimple_call_fndecl (stmt)))
6628e4b17023SJohn Marino 	  return true;
6629e4b17023SJohn Marino       }
6630e4b17023SJohn Marino   return false;
6631e4b17023SJohn Marino }
6632e4b17023SJohn Marino 
6633e4b17023SJohn Marino /* Optimizes the LOOP.  Returns true if anything changed.  */
6634e4b17023SJohn Marino 
6635e4b17023SJohn Marino static bool
tree_ssa_iv_optimize_loop(struct ivopts_data * data,struct loop * loop)6636e4b17023SJohn Marino tree_ssa_iv_optimize_loop (struct ivopts_data *data, struct loop *loop)
6637e4b17023SJohn Marino {
6638e4b17023SJohn Marino   bool changed = false;
6639e4b17023SJohn Marino   struct iv_ca *iv_ca;
6640e4b17023SJohn Marino   edge exit = single_dom_exit (loop);
6641e4b17023SJohn Marino   basic_block *body;
6642e4b17023SJohn Marino 
6643e4b17023SJohn Marino   gcc_assert (!data->niters);
6644e4b17023SJohn Marino   data->current_loop = loop;
6645e4b17023SJohn Marino   data->speed = optimize_loop_for_speed_p (loop);
6646e4b17023SJohn Marino 
6647e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
6648e4b17023SJohn Marino     {
6649e4b17023SJohn Marino       fprintf (dump_file, "Processing loop %d\n", loop->num);
6650e4b17023SJohn Marino 
6651e4b17023SJohn Marino       if (exit)
6652e4b17023SJohn Marino 	{
6653e4b17023SJohn Marino 	  fprintf (dump_file, "  single exit %d -> %d, exit condition ",
6654e4b17023SJohn Marino 		   exit->src->index, exit->dest->index);
6655e4b17023SJohn Marino 	  print_gimple_stmt (dump_file, last_stmt (exit->src), 0, TDF_SLIM);
6656e4b17023SJohn Marino 	  fprintf (dump_file, "\n");
6657e4b17023SJohn Marino 	}
6658e4b17023SJohn Marino 
6659e4b17023SJohn Marino       fprintf (dump_file, "\n");
6660e4b17023SJohn Marino     }
6661e4b17023SJohn Marino 
6662e4b17023SJohn Marino   body = get_loop_body (loop);
6663e4b17023SJohn Marino   data->body_includes_call = loop_body_includes_call (body, loop->num_nodes);
6664e4b17023SJohn Marino   renumber_gimple_stmt_uids_in_blocks (body, loop->num_nodes);
6665e4b17023SJohn Marino   free (body);
6666e4b17023SJohn Marino 
6667e4b17023SJohn Marino   data->loop_single_exit_p = exit != NULL && loop_only_exit_p (loop, exit);
6668e4b17023SJohn Marino 
6669e4b17023SJohn Marino   /* For each ssa name determines whether it behaves as an induction variable
6670e4b17023SJohn Marino      in some loop.  */
6671e4b17023SJohn Marino   if (!find_induction_variables (data))
6672e4b17023SJohn Marino     goto finish;
6673e4b17023SJohn Marino 
6674e4b17023SJohn Marino   /* Finds interesting uses (item 1).  */
6675e4b17023SJohn Marino   find_interesting_uses (data);
6676e4b17023SJohn Marino   if (n_iv_uses (data) > MAX_CONSIDERED_USES)
6677e4b17023SJohn Marino     goto finish;
6678e4b17023SJohn Marino 
6679e4b17023SJohn Marino   /* Finds candidates for the induction variables (item 2).  */
6680e4b17023SJohn Marino   find_iv_candidates (data);
6681e4b17023SJohn Marino 
6682e4b17023SJohn Marino   /* Calculates the costs (item 3, part 1).  */
6683e4b17023SJohn Marino   determine_iv_costs (data);
6684e4b17023SJohn Marino   determine_use_iv_costs (data);
6685e4b17023SJohn Marino   determine_set_costs (data);
6686e4b17023SJohn Marino 
6687e4b17023SJohn Marino   /* Find the optimal set of induction variables (item 3, part 2).  */
6688e4b17023SJohn Marino   iv_ca = find_optimal_iv_set (data);
6689e4b17023SJohn Marino   if (!iv_ca)
6690e4b17023SJohn Marino     goto finish;
6691e4b17023SJohn Marino   changed = true;
6692e4b17023SJohn Marino 
6693e4b17023SJohn Marino   /* Create the new induction variables (item 4, part 1).  */
6694e4b17023SJohn Marino   create_new_ivs (data, iv_ca);
6695e4b17023SJohn Marino   iv_ca_free (&iv_ca);
6696e4b17023SJohn Marino 
6697e4b17023SJohn Marino   /* Rewrite the uses (item 4, part 2).  */
6698e4b17023SJohn Marino   rewrite_uses (data);
6699e4b17023SJohn Marino 
6700e4b17023SJohn Marino   /* Remove the ivs that are unused after rewriting.  */
6701e4b17023SJohn Marino   remove_unused_ivs (data);
6702e4b17023SJohn Marino 
6703e4b17023SJohn Marino   /* We have changed the structure of induction variables; it might happen
6704e4b17023SJohn Marino      that definitions in the scev database refer to some of them that were
6705e4b17023SJohn Marino      eliminated.  */
6706e4b17023SJohn Marino   scev_reset ();
6707e4b17023SJohn Marino 
6708e4b17023SJohn Marino finish:
6709e4b17023SJohn Marino   free_loop_data (data);
6710e4b17023SJohn Marino 
6711e4b17023SJohn Marino   return changed;
6712e4b17023SJohn Marino }
6713e4b17023SJohn Marino 
6714e4b17023SJohn Marino /* Main entry point.  Optimizes induction variables in loops.  */
6715e4b17023SJohn Marino 
6716e4b17023SJohn Marino void
tree_ssa_iv_optimize(void)6717e4b17023SJohn Marino tree_ssa_iv_optimize (void)
6718e4b17023SJohn Marino {
6719e4b17023SJohn Marino   struct loop *loop;
6720e4b17023SJohn Marino   struct ivopts_data data;
6721e4b17023SJohn Marino   loop_iterator li;
6722e4b17023SJohn Marino 
6723e4b17023SJohn Marino   tree_ssa_iv_optimize_init (&data);
6724e4b17023SJohn Marino 
6725e4b17023SJohn Marino   /* Optimize the loops starting with the innermost ones.  */
6726e4b17023SJohn Marino   FOR_EACH_LOOP (li, loop, LI_FROM_INNERMOST)
6727e4b17023SJohn Marino     {
6728e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
6729e4b17023SJohn Marino 	flow_loop_dump (loop, dump_file, NULL, 1);
6730e4b17023SJohn Marino 
6731e4b17023SJohn Marino       tree_ssa_iv_optimize_loop (&data, loop);
6732e4b17023SJohn Marino     }
6733e4b17023SJohn Marino 
6734e4b17023SJohn Marino   tree_ssa_iv_optimize_finalize (&data);
6735e4b17023SJohn Marino }
6736