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, ®no, 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