1*e4b17023SJohn Marino /* Loop invariant motion.
2*e4b17023SJohn Marino Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2010
3*e4b17023SJohn Marino Free Software Foundation, Inc.
4*e4b17023SJohn Marino
5*e4b17023SJohn Marino This file is part of GCC.
6*e4b17023SJohn Marino
7*e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it
8*e4b17023SJohn Marino under the terms of the GNU General Public License as published by the
9*e4b17023SJohn Marino Free Software Foundation; either version 3, or (at your option) any
10*e4b17023SJohn Marino later version.
11*e4b17023SJohn Marino
12*e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT
13*e4b17023SJohn Marino ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14*e4b17023SJohn Marino FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15*e4b17023SJohn Marino for more details.
16*e4b17023SJohn Marino
17*e4b17023SJohn Marino You should have received a copy of the GNU General Public License
18*e4b17023SJohn Marino along with GCC; see the file COPYING3. If not see
19*e4b17023SJohn Marino <http://www.gnu.org/licenses/>. */
20*e4b17023SJohn Marino
21*e4b17023SJohn Marino #include "config.h"
22*e4b17023SJohn Marino #include "system.h"
23*e4b17023SJohn Marino #include "coretypes.h"
24*e4b17023SJohn Marino #include "tm.h"
25*e4b17023SJohn Marino #include "tree.h"
26*e4b17023SJohn Marino #include "tm_p.h"
27*e4b17023SJohn Marino #include "basic-block.h"
28*e4b17023SJohn Marino #include "output.h"
29*e4b17023SJohn Marino #include "tree-pretty-print.h"
30*e4b17023SJohn Marino #include "gimple-pretty-print.h"
31*e4b17023SJohn Marino #include "tree-flow.h"
32*e4b17023SJohn Marino #include "tree-dump.h"
33*e4b17023SJohn Marino #include "timevar.h"
34*e4b17023SJohn Marino #include "cfgloop.h"
35*e4b17023SJohn Marino #include "domwalk.h"
36*e4b17023SJohn Marino #include "params.h"
37*e4b17023SJohn Marino #include "tree-pass.h"
38*e4b17023SJohn Marino #include "flags.h"
39*e4b17023SJohn Marino #include "hashtab.h"
40*e4b17023SJohn Marino #include "tree-affine.h"
41*e4b17023SJohn Marino #include "pointer-set.h"
42*e4b17023SJohn Marino #include "tree-ssa-propagate.h"
43*e4b17023SJohn Marino
44*e4b17023SJohn Marino /* TODO: Support for predicated code motion. I.e.
45*e4b17023SJohn Marino
46*e4b17023SJohn Marino while (1)
47*e4b17023SJohn Marino {
48*e4b17023SJohn Marino if (cond)
49*e4b17023SJohn Marino {
50*e4b17023SJohn Marino a = inv;
51*e4b17023SJohn Marino something;
52*e4b17023SJohn Marino }
53*e4b17023SJohn Marino }
54*e4b17023SJohn Marino
55*e4b17023SJohn Marino Where COND and INV are invariants, but evaluating INV may trap or be
56*e4b17023SJohn Marino invalid from some other reason if !COND. This may be transformed to
57*e4b17023SJohn Marino
58*e4b17023SJohn Marino if (cond)
59*e4b17023SJohn Marino a = inv;
60*e4b17023SJohn Marino while (1)
61*e4b17023SJohn Marino {
62*e4b17023SJohn Marino if (cond)
63*e4b17023SJohn Marino something;
64*e4b17023SJohn Marino } */
65*e4b17023SJohn Marino
66*e4b17023SJohn Marino /* A type for the list of statements that have to be moved in order to be able
67*e4b17023SJohn Marino to hoist an invariant computation. */
68*e4b17023SJohn Marino
69*e4b17023SJohn Marino struct depend
70*e4b17023SJohn Marino {
71*e4b17023SJohn Marino gimple stmt;
72*e4b17023SJohn Marino struct depend *next;
73*e4b17023SJohn Marino };
74*e4b17023SJohn Marino
75*e4b17023SJohn Marino /* The auxiliary data kept for each statement. */
76*e4b17023SJohn Marino
77*e4b17023SJohn Marino struct lim_aux_data
78*e4b17023SJohn Marino {
79*e4b17023SJohn Marino struct loop *max_loop; /* The outermost loop in that the statement
80*e4b17023SJohn Marino is invariant. */
81*e4b17023SJohn Marino
82*e4b17023SJohn Marino struct loop *tgt_loop; /* The loop out of that we want to move the
83*e4b17023SJohn Marino invariant. */
84*e4b17023SJohn Marino
85*e4b17023SJohn Marino struct loop *always_executed_in;
86*e4b17023SJohn Marino /* The outermost loop for that we are sure
87*e4b17023SJohn Marino the statement is executed if the loop
88*e4b17023SJohn Marino is entered. */
89*e4b17023SJohn Marino
90*e4b17023SJohn Marino unsigned cost; /* Cost of the computation performed by the
91*e4b17023SJohn Marino statement. */
92*e4b17023SJohn Marino
93*e4b17023SJohn Marino struct depend *depends; /* List of statements that must be also hoisted
94*e4b17023SJohn Marino out of the loop when this statement is
95*e4b17023SJohn Marino hoisted; i.e. those that define the operands
96*e4b17023SJohn Marino of the statement and are inside of the
97*e4b17023SJohn Marino MAX_LOOP loop. */
98*e4b17023SJohn Marino };
99*e4b17023SJohn Marino
100*e4b17023SJohn Marino /* Maps statements to their lim_aux_data. */
101*e4b17023SJohn Marino
102*e4b17023SJohn Marino static struct pointer_map_t *lim_aux_data_map;
103*e4b17023SJohn Marino
104*e4b17023SJohn Marino /* Description of a memory reference location. */
105*e4b17023SJohn Marino
106*e4b17023SJohn Marino typedef struct mem_ref_loc
107*e4b17023SJohn Marino {
108*e4b17023SJohn Marino tree *ref; /* The reference itself. */
109*e4b17023SJohn Marino gimple stmt; /* The statement in that it occurs. */
110*e4b17023SJohn Marino } *mem_ref_loc_p;
111*e4b17023SJohn Marino
112*e4b17023SJohn Marino DEF_VEC_P(mem_ref_loc_p);
113*e4b17023SJohn Marino DEF_VEC_ALLOC_P(mem_ref_loc_p, heap);
114*e4b17023SJohn Marino
115*e4b17023SJohn Marino /* The list of memory reference locations in a loop. */
116*e4b17023SJohn Marino
117*e4b17023SJohn Marino typedef struct mem_ref_locs
118*e4b17023SJohn Marino {
119*e4b17023SJohn Marino VEC (mem_ref_loc_p, heap) *locs;
120*e4b17023SJohn Marino } *mem_ref_locs_p;
121*e4b17023SJohn Marino
122*e4b17023SJohn Marino DEF_VEC_P(mem_ref_locs_p);
123*e4b17023SJohn Marino DEF_VEC_ALLOC_P(mem_ref_locs_p, heap);
124*e4b17023SJohn Marino
125*e4b17023SJohn Marino /* Description of a memory reference. */
126*e4b17023SJohn Marino
127*e4b17023SJohn Marino typedef struct mem_ref
128*e4b17023SJohn Marino {
129*e4b17023SJohn Marino tree mem; /* The memory itself. */
130*e4b17023SJohn Marino unsigned id; /* ID assigned to the memory reference
131*e4b17023SJohn Marino (its index in memory_accesses.refs_list) */
132*e4b17023SJohn Marino hashval_t hash; /* Its hash value. */
133*e4b17023SJohn Marino bitmap stored; /* The set of loops in that this memory location
134*e4b17023SJohn Marino is stored to. */
135*e4b17023SJohn Marino VEC (mem_ref_locs_p, heap) *accesses_in_loop;
136*e4b17023SJohn Marino /* The locations of the accesses. Vector
137*e4b17023SJohn Marino indexed by the loop number. */
138*e4b17023SJohn Marino
139*e4b17023SJohn Marino /* The following sets are computed on demand. We keep both set and
140*e4b17023SJohn Marino its complement, so that we know whether the information was
141*e4b17023SJohn Marino already computed or not. */
142*e4b17023SJohn Marino bitmap indep_loop; /* The set of loops in that the memory
143*e4b17023SJohn Marino reference is independent, meaning:
144*e4b17023SJohn Marino If it is stored in the loop, this store
145*e4b17023SJohn Marino is independent on all other loads and
146*e4b17023SJohn Marino stores.
147*e4b17023SJohn Marino If it is only loaded, then it is independent
148*e4b17023SJohn Marino on all stores in the loop. */
149*e4b17023SJohn Marino bitmap dep_loop; /* The complement of INDEP_LOOP. */
150*e4b17023SJohn Marino
151*e4b17023SJohn Marino bitmap indep_ref; /* The set of memory references on that
152*e4b17023SJohn Marino this reference is independent. */
153*e4b17023SJohn Marino bitmap dep_ref; /* The complement of INDEP_REF. */
154*e4b17023SJohn Marino } *mem_ref_p;
155*e4b17023SJohn Marino
156*e4b17023SJohn Marino DEF_VEC_P(mem_ref_p);
157*e4b17023SJohn Marino DEF_VEC_ALLOC_P(mem_ref_p, heap);
158*e4b17023SJohn Marino
159*e4b17023SJohn Marino DEF_VEC_P(bitmap);
160*e4b17023SJohn Marino DEF_VEC_ALLOC_P(bitmap, heap);
161*e4b17023SJohn Marino
162*e4b17023SJohn Marino DEF_VEC_P(htab_t);
163*e4b17023SJohn Marino DEF_VEC_ALLOC_P(htab_t, heap);
164*e4b17023SJohn Marino
165*e4b17023SJohn Marino /* Description of memory accesses in loops. */
166*e4b17023SJohn Marino
167*e4b17023SJohn Marino static struct
168*e4b17023SJohn Marino {
169*e4b17023SJohn Marino /* The hash table of memory references accessed in loops. */
170*e4b17023SJohn Marino htab_t refs;
171*e4b17023SJohn Marino
172*e4b17023SJohn Marino /* The list of memory references. */
173*e4b17023SJohn Marino VEC (mem_ref_p, heap) *refs_list;
174*e4b17023SJohn Marino
175*e4b17023SJohn Marino /* The set of memory references accessed in each loop. */
176*e4b17023SJohn Marino VEC (bitmap, heap) *refs_in_loop;
177*e4b17023SJohn Marino
178*e4b17023SJohn Marino /* The set of memory references accessed in each loop, including
179*e4b17023SJohn Marino subloops. */
180*e4b17023SJohn Marino VEC (bitmap, heap) *all_refs_in_loop;
181*e4b17023SJohn Marino
182*e4b17023SJohn Marino /* The set of memory references stored in each loop, including
183*e4b17023SJohn Marino subloops. */
184*e4b17023SJohn Marino VEC (bitmap, heap) *all_refs_stored_in_loop;
185*e4b17023SJohn Marino
186*e4b17023SJohn Marino /* Cache for expanding memory addresses. */
187*e4b17023SJohn Marino struct pointer_map_t *ttae_cache;
188*e4b17023SJohn Marino } memory_accesses;
189*e4b17023SJohn Marino
190*e4b17023SJohn Marino static bool ref_indep_loop_p (struct loop *, mem_ref_p);
191*e4b17023SJohn Marino
192*e4b17023SJohn Marino /* Minimum cost of an expensive expression. */
193*e4b17023SJohn Marino #define LIM_EXPENSIVE ((unsigned) PARAM_VALUE (PARAM_LIM_EXPENSIVE))
194*e4b17023SJohn Marino
195*e4b17023SJohn Marino /* The outermost loop for which execution of the header guarantees that the
196*e4b17023SJohn Marino block will be executed. */
197*e4b17023SJohn Marino #define ALWAYS_EXECUTED_IN(BB) ((struct loop *) (BB)->aux)
198*e4b17023SJohn Marino #define SET_ALWAYS_EXECUTED_IN(BB, VAL) ((BB)->aux = (void *) (VAL))
199*e4b17023SJohn Marino
200*e4b17023SJohn Marino /* Whether the reference was analyzable. */
201*e4b17023SJohn Marino #define MEM_ANALYZABLE(REF) ((REF)->mem != error_mark_node)
202*e4b17023SJohn Marino
203*e4b17023SJohn Marino static struct lim_aux_data *
init_lim_data(gimple stmt)204*e4b17023SJohn Marino init_lim_data (gimple stmt)
205*e4b17023SJohn Marino {
206*e4b17023SJohn Marino void **p = pointer_map_insert (lim_aux_data_map, stmt);
207*e4b17023SJohn Marino
208*e4b17023SJohn Marino *p = XCNEW (struct lim_aux_data);
209*e4b17023SJohn Marino return (struct lim_aux_data *) *p;
210*e4b17023SJohn Marino }
211*e4b17023SJohn Marino
212*e4b17023SJohn Marino static struct lim_aux_data *
get_lim_data(gimple stmt)213*e4b17023SJohn Marino get_lim_data (gimple stmt)
214*e4b17023SJohn Marino {
215*e4b17023SJohn Marino void **p = pointer_map_contains (lim_aux_data_map, stmt);
216*e4b17023SJohn Marino if (!p)
217*e4b17023SJohn Marino return NULL;
218*e4b17023SJohn Marino
219*e4b17023SJohn Marino return (struct lim_aux_data *) *p;
220*e4b17023SJohn Marino }
221*e4b17023SJohn Marino
222*e4b17023SJohn Marino /* Releases the memory occupied by DATA. */
223*e4b17023SJohn Marino
224*e4b17023SJohn Marino static void
free_lim_aux_data(struct lim_aux_data * data)225*e4b17023SJohn Marino free_lim_aux_data (struct lim_aux_data *data)
226*e4b17023SJohn Marino {
227*e4b17023SJohn Marino struct depend *dep, *next;
228*e4b17023SJohn Marino
229*e4b17023SJohn Marino for (dep = data->depends; dep; dep = next)
230*e4b17023SJohn Marino {
231*e4b17023SJohn Marino next = dep->next;
232*e4b17023SJohn Marino free (dep);
233*e4b17023SJohn Marino }
234*e4b17023SJohn Marino free (data);
235*e4b17023SJohn Marino }
236*e4b17023SJohn Marino
237*e4b17023SJohn Marino static void
clear_lim_data(gimple stmt)238*e4b17023SJohn Marino clear_lim_data (gimple stmt)
239*e4b17023SJohn Marino {
240*e4b17023SJohn Marino void **p = pointer_map_contains (lim_aux_data_map, stmt);
241*e4b17023SJohn Marino if (!p)
242*e4b17023SJohn Marino return;
243*e4b17023SJohn Marino
244*e4b17023SJohn Marino free_lim_aux_data ((struct lim_aux_data *) *p);
245*e4b17023SJohn Marino *p = NULL;
246*e4b17023SJohn Marino }
247*e4b17023SJohn Marino
248*e4b17023SJohn Marino /* Calls CBCK for each index in memory reference ADDR_P. There are two
249*e4b17023SJohn Marino kinds situations handled; in each of these cases, the memory reference
250*e4b17023SJohn Marino and DATA are passed to the callback:
251*e4b17023SJohn Marino
252*e4b17023SJohn Marino Access to an array: ARRAY_{RANGE_}REF (base, index). In this case we also
253*e4b17023SJohn Marino pass the pointer to the index to the callback.
254*e4b17023SJohn Marino
255*e4b17023SJohn Marino Pointer dereference: INDIRECT_REF (addr). In this case we also pass the
256*e4b17023SJohn Marino pointer to addr to the callback.
257*e4b17023SJohn Marino
258*e4b17023SJohn Marino If the callback returns false, the whole search stops and false is returned.
259*e4b17023SJohn Marino Otherwise the function returns true after traversing through the whole
260*e4b17023SJohn Marino reference *ADDR_P. */
261*e4b17023SJohn Marino
262*e4b17023SJohn Marino bool
for_each_index(tree * addr_p,bool (* cbck)(tree,tree *,void *),void * data)263*e4b17023SJohn Marino for_each_index (tree *addr_p, bool (*cbck) (tree, tree *, void *), void *data)
264*e4b17023SJohn Marino {
265*e4b17023SJohn Marino tree *nxt, *idx;
266*e4b17023SJohn Marino
267*e4b17023SJohn Marino for (; ; addr_p = nxt)
268*e4b17023SJohn Marino {
269*e4b17023SJohn Marino switch (TREE_CODE (*addr_p))
270*e4b17023SJohn Marino {
271*e4b17023SJohn Marino case SSA_NAME:
272*e4b17023SJohn Marino return cbck (*addr_p, addr_p, data);
273*e4b17023SJohn Marino
274*e4b17023SJohn Marino case MEM_REF:
275*e4b17023SJohn Marino nxt = &TREE_OPERAND (*addr_p, 0);
276*e4b17023SJohn Marino return cbck (*addr_p, nxt, data);
277*e4b17023SJohn Marino
278*e4b17023SJohn Marino case BIT_FIELD_REF:
279*e4b17023SJohn Marino case VIEW_CONVERT_EXPR:
280*e4b17023SJohn Marino case REALPART_EXPR:
281*e4b17023SJohn Marino case IMAGPART_EXPR:
282*e4b17023SJohn Marino nxt = &TREE_OPERAND (*addr_p, 0);
283*e4b17023SJohn Marino break;
284*e4b17023SJohn Marino
285*e4b17023SJohn Marino case COMPONENT_REF:
286*e4b17023SJohn Marino /* If the component has varying offset, it behaves like index
287*e4b17023SJohn Marino as well. */
288*e4b17023SJohn Marino idx = &TREE_OPERAND (*addr_p, 2);
289*e4b17023SJohn Marino if (*idx
290*e4b17023SJohn Marino && !cbck (*addr_p, idx, data))
291*e4b17023SJohn Marino return false;
292*e4b17023SJohn Marino
293*e4b17023SJohn Marino nxt = &TREE_OPERAND (*addr_p, 0);
294*e4b17023SJohn Marino break;
295*e4b17023SJohn Marino
296*e4b17023SJohn Marino case ARRAY_REF:
297*e4b17023SJohn Marino case ARRAY_RANGE_REF:
298*e4b17023SJohn Marino nxt = &TREE_OPERAND (*addr_p, 0);
299*e4b17023SJohn Marino if (!cbck (*addr_p, &TREE_OPERAND (*addr_p, 1), data))
300*e4b17023SJohn Marino return false;
301*e4b17023SJohn Marino break;
302*e4b17023SJohn Marino
303*e4b17023SJohn Marino case VAR_DECL:
304*e4b17023SJohn Marino case PARM_DECL:
305*e4b17023SJohn Marino case STRING_CST:
306*e4b17023SJohn Marino case RESULT_DECL:
307*e4b17023SJohn Marino case VECTOR_CST:
308*e4b17023SJohn Marino case COMPLEX_CST:
309*e4b17023SJohn Marino case INTEGER_CST:
310*e4b17023SJohn Marino case REAL_CST:
311*e4b17023SJohn Marino case FIXED_CST:
312*e4b17023SJohn Marino case CONSTRUCTOR:
313*e4b17023SJohn Marino return true;
314*e4b17023SJohn Marino
315*e4b17023SJohn Marino case ADDR_EXPR:
316*e4b17023SJohn Marino gcc_assert (is_gimple_min_invariant (*addr_p));
317*e4b17023SJohn Marino return true;
318*e4b17023SJohn Marino
319*e4b17023SJohn Marino case TARGET_MEM_REF:
320*e4b17023SJohn Marino idx = &TMR_BASE (*addr_p);
321*e4b17023SJohn Marino if (*idx
322*e4b17023SJohn Marino && !cbck (*addr_p, idx, data))
323*e4b17023SJohn Marino return false;
324*e4b17023SJohn Marino idx = &TMR_INDEX (*addr_p);
325*e4b17023SJohn Marino if (*idx
326*e4b17023SJohn Marino && !cbck (*addr_p, idx, data))
327*e4b17023SJohn Marino return false;
328*e4b17023SJohn Marino idx = &TMR_INDEX2 (*addr_p);
329*e4b17023SJohn Marino if (*idx
330*e4b17023SJohn Marino && !cbck (*addr_p, idx, data))
331*e4b17023SJohn Marino return false;
332*e4b17023SJohn Marino return true;
333*e4b17023SJohn Marino
334*e4b17023SJohn Marino default:
335*e4b17023SJohn Marino gcc_unreachable ();
336*e4b17023SJohn Marino }
337*e4b17023SJohn Marino }
338*e4b17023SJohn Marino }
339*e4b17023SJohn Marino
340*e4b17023SJohn Marino /* If it is possible to hoist the statement STMT unconditionally,
341*e4b17023SJohn Marino returns MOVE_POSSIBLE.
342*e4b17023SJohn Marino If it is possible to hoist the statement STMT, but we must avoid making
343*e4b17023SJohn Marino it executed if it would not be executed in the original program (e.g.
344*e4b17023SJohn Marino because it may trap), return MOVE_PRESERVE_EXECUTION.
345*e4b17023SJohn Marino Otherwise return MOVE_IMPOSSIBLE. */
346*e4b17023SJohn Marino
347*e4b17023SJohn Marino enum move_pos
movement_possibility(gimple stmt)348*e4b17023SJohn Marino movement_possibility (gimple stmt)
349*e4b17023SJohn Marino {
350*e4b17023SJohn Marino tree lhs;
351*e4b17023SJohn Marino enum move_pos ret = MOVE_POSSIBLE;
352*e4b17023SJohn Marino
353*e4b17023SJohn Marino if (flag_unswitch_loops
354*e4b17023SJohn Marino && gimple_code (stmt) == GIMPLE_COND)
355*e4b17023SJohn Marino {
356*e4b17023SJohn Marino /* If we perform unswitching, force the operands of the invariant
357*e4b17023SJohn Marino condition to be moved out of the loop. */
358*e4b17023SJohn Marino return MOVE_POSSIBLE;
359*e4b17023SJohn Marino }
360*e4b17023SJohn Marino
361*e4b17023SJohn Marino if (gimple_code (stmt) == GIMPLE_PHI
362*e4b17023SJohn Marino && gimple_phi_num_args (stmt) <= 2
363*e4b17023SJohn Marino && is_gimple_reg (gimple_phi_result (stmt))
364*e4b17023SJohn Marino && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (gimple_phi_result (stmt)))
365*e4b17023SJohn Marino return MOVE_POSSIBLE;
366*e4b17023SJohn Marino
367*e4b17023SJohn Marino if (gimple_get_lhs (stmt) == NULL_TREE)
368*e4b17023SJohn Marino return MOVE_IMPOSSIBLE;
369*e4b17023SJohn Marino
370*e4b17023SJohn Marino if (gimple_vdef (stmt))
371*e4b17023SJohn Marino return MOVE_IMPOSSIBLE;
372*e4b17023SJohn Marino
373*e4b17023SJohn Marino if (stmt_ends_bb_p (stmt)
374*e4b17023SJohn Marino || gimple_has_volatile_ops (stmt)
375*e4b17023SJohn Marino || gimple_has_side_effects (stmt)
376*e4b17023SJohn Marino || stmt_could_throw_p (stmt))
377*e4b17023SJohn Marino return MOVE_IMPOSSIBLE;
378*e4b17023SJohn Marino
379*e4b17023SJohn Marino if (is_gimple_call (stmt))
380*e4b17023SJohn Marino {
381*e4b17023SJohn Marino /* While pure or const call is guaranteed to have no side effects, we
382*e4b17023SJohn Marino cannot move it arbitrarily. Consider code like
383*e4b17023SJohn Marino
384*e4b17023SJohn Marino char *s = something ();
385*e4b17023SJohn Marino
386*e4b17023SJohn Marino while (1)
387*e4b17023SJohn Marino {
388*e4b17023SJohn Marino if (s)
389*e4b17023SJohn Marino t = strlen (s);
390*e4b17023SJohn Marino else
391*e4b17023SJohn Marino t = 0;
392*e4b17023SJohn Marino }
393*e4b17023SJohn Marino
394*e4b17023SJohn Marino Here the strlen call cannot be moved out of the loop, even though
395*e4b17023SJohn Marino s is invariant. In addition to possibly creating a call with
396*e4b17023SJohn Marino invalid arguments, moving out a function call that is not executed
397*e4b17023SJohn Marino may cause performance regressions in case the call is costly and
398*e4b17023SJohn Marino not executed at all. */
399*e4b17023SJohn Marino ret = MOVE_PRESERVE_EXECUTION;
400*e4b17023SJohn Marino lhs = gimple_call_lhs (stmt);
401*e4b17023SJohn Marino }
402*e4b17023SJohn Marino else if (is_gimple_assign (stmt))
403*e4b17023SJohn Marino lhs = gimple_assign_lhs (stmt);
404*e4b17023SJohn Marino else
405*e4b17023SJohn Marino return MOVE_IMPOSSIBLE;
406*e4b17023SJohn Marino
407*e4b17023SJohn Marino if (TREE_CODE (lhs) == SSA_NAME
408*e4b17023SJohn Marino && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
409*e4b17023SJohn Marino return MOVE_IMPOSSIBLE;
410*e4b17023SJohn Marino
411*e4b17023SJohn Marino if (TREE_CODE (lhs) != SSA_NAME
412*e4b17023SJohn Marino || gimple_could_trap_p (stmt))
413*e4b17023SJohn Marino return MOVE_PRESERVE_EXECUTION;
414*e4b17023SJohn Marino
415*e4b17023SJohn Marino /* Non local loads in a transaction cannot be hoisted out. Well,
416*e4b17023SJohn Marino unless the load happens on every path out of the loop, but we
417*e4b17023SJohn Marino don't take this into account yet. */
418*e4b17023SJohn Marino if (flag_tm
419*e4b17023SJohn Marino && gimple_in_transaction (stmt)
420*e4b17023SJohn Marino && gimple_assign_single_p (stmt))
421*e4b17023SJohn Marino {
422*e4b17023SJohn Marino tree rhs = gimple_assign_rhs1 (stmt);
423*e4b17023SJohn Marino if (DECL_P (rhs) && is_global_var (rhs))
424*e4b17023SJohn Marino {
425*e4b17023SJohn Marino if (dump_file)
426*e4b17023SJohn Marino {
427*e4b17023SJohn Marino fprintf (dump_file, "Cannot hoist conditional load of ");
428*e4b17023SJohn Marino print_generic_expr (dump_file, rhs, TDF_SLIM);
429*e4b17023SJohn Marino fprintf (dump_file, " because it is in a transaction.\n");
430*e4b17023SJohn Marino }
431*e4b17023SJohn Marino return MOVE_IMPOSSIBLE;
432*e4b17023SJohn Marino }
433*e4b17023SJohn Marino }
434*e4b17023SJohn Marino
435*e4b17023SJohn Marino return ret;
436*e4b17023SJohn Marino }
437*e4b17023SJohn Marino
438*e4b17023SJohn Marino /* Suppose that operand DEF is used inside the LOOP. Returns the outermost
439*e4b17023SJohn Marino loop to that we could move the expression using DEF if it did not have
440*e4b17023SJohn Marino other operands, i.e. the outermost loop enclosing LOOP in that the value
441*e4b17023SJohn Marino of DEF is invariant. */
442*e4b17023SJohn Marino
443*e4b17023SJohn Marino static struct loop *
outermost_invariant_loop(tree def,struct loop * loop)444*e4b17023SJohn Marino outermost_invariant_loop (tree def, struct loop *loop)
445*e4b17023SJohn Marino {
446*e4b17023SJohn Marino gimple def_stmt;
447*e4b17023SJohn Marino basic_block def_bb;
448*e4b17023SJohn Marino struct loop *max_loop;
449*e4b17023SJohn Marino struct lim_aux_data *lim_data;
450*e4b17023SJohn Marino
451*e4b17023SJohn Marino if (!def)
452*e4b17023SJohn Marino return superloop_at_depth (loop, 1);
453*e4b17023SJohn Marino
454*e4b17023SJohn Marino if (TREE_CODE (def) != SSA_NAME)
455*e4b17023SJohn Marino {
456*e4b17023SJohn Marino gcc_assert (is_gimple_min_invariant (def));
457*e4b17023SJohn Marino return superloop_at_depth (loop, 1);
458*e4b17023SJohn Marino }
459*e4b17023SJohn Marino
460*e4b17023SJohn Marino def_stmt = SSA_NAME_DEF_STMT (def);
461*e4b17023SJohn Marino def_bb = gimple_bb (def_stmt);
462*e4b17023SJohn Marino if (!def_bb)
463*e4b17023SJohn Marino return superloop_at_depth (loop, 1);
464*e4b17023SJohn Marino
465*e4b17023SJohn Marino max_loop = find_common_loop (loop, def_bb->loop_father);
466*e4b17023SJohn Marino
467*e4b17023SJohn Marino lim_data = get_lim_data (def_stmt);
468*e4b17023SJohn Marino if (lim_data != NULL && lim_data->max_loop != NULL)
469*e4b17023SJohn Marino max_loop = find_common_loop (max_loop,
470*e4b17023SJohn Marino loop_outer (lim_data->max_loop));
471*e4b17023SJohn Marino if (max_loop == loop)
472*e4b17023SJohn Marino return NULL;
473*e4b17023SJohn Marino max_loop = superloop_at_depth (loop, loop_depth (max_loop) + 1);
474*e4b17023SJohn Marino
475*e4b17023SJohn Marino return max_loop;
476*e4b17023SJohn Marino }
477*e4b17023SJohn Marino
478*e4b17023SJohn Marino /* DATA is a structure containing information associated with a statement
479*e4b17023SJohn Marino inside LOOP. DEF is one of the operands of this statement.
480*e4b17023SJohn Marino
481*e4b17023SJohn Marino Find the outermost loop enclosing LOOP in that value of DEF is invariant
482*e4b17023SJohn Marino and record this in DATA->max_loop field. If DEF itself is defined inside
483*e4b17023SJohn Marino this loop as well (i.e. we need to hoist it out of the loop if we want
484*e4b17023SJohn Marino to hoist the statement represented by DATA), record the statement in that
485*e4b17023SJohn Marino DEF is defined to the DATA->depends list. Additionally if ADD_COST is true,
486*e4b17023SJohn Marino add the cost of the computation of DEF to the DATA->cost.
487*e4b17023SJohn Marino
488*e4b17023SJohn Marino If DEF is not invariant in LOOP, return false. Otherwise return TRUE. */
489*e4b17023SJohn Marino
490*e4b17023SJohn Marino static bool
add_dependency(tree def,struct lim_aux_data * data,struct loop * loop,bool add_cost)491*e4b17023SJohn Marino add_dependency (tree def, struct lim_aux_data *data, struct loop *loop,
492*e4b17023SJohn Marino bool add_cost)
493*e4b17023SJohn Marino {
494*e4b17023SJohn Marino gimple def_stmt = SSA_NAME_DEF_STMT (def);
495*e4b17023SJohn Marino basic_block def_bb = gimple_bb (def_stmt);
496*e4b17023SJohn Marino struct loop *max_loop;
497*e4b17023SJohn Marino struct depend *dep;
498*e4b17023SJohn Marino struct lim_aux_data *def_data;
499*e4b17023SJohn Marino
500*e4b17023SJohn Marino if (!def_bb)
501*e4b17023SJohn Marino return true;
502*e4b17023SJohn Marino
503*e4b17023SJohn Marino max_loop = outermost_invariant_loop (def, loop);
504*e4b17023SJohn Marino if (!max_loop)
505*e4b17023SJohn Marino return false;
506*e4b17023SJohn Marino
507*e4b17023SJohn Marino if (flow_loop_nested_p (data->max_loop, max_loop))
508*e4b17023SJohn Marino data->max_loop = max_loop;
509*e4b17023SJohn Marino
510*e4b17023SJohn Marino def_data = get_lim_data (def_stmt);
511*e4b17023SJohn Marino if (!def_data)
512*e4b17023SJohn Marino return true;
513*e4b17023SJohn Marino
514*e4b17023SJohn Marino if (add_cost
515*e4b17023SJohn Marino /* Only add the cost if the statement defining DEF is inside LOOP,
516*e4b17023SJohn Marino i.e. if it is likely that by moving the invariants dependent
517*e4b17023SJohn Marino on it, we will be able to avoid creating a new register for
518*e4b17023SJohn Marino it (since it will be only used in these dependent invariants). */
519*e4b17023SJohn Marino && def_bb->loop_father == loop)
520*e4b17023SJohn Marino data->cost += def_data->cost;
521*e4b17023SJohn Marino
522*e4b17023SJohn Marino dep = XNEW (struct depend);
523*e4b17023SJohn Marino dep->stmt = def_stmt;
524*e4b17023SJohn Marino dep->next = data->depends;
525*e4b17023SJohn Marino data->depends = dep;
526*e4b17023SJohn Marino
527*e4b17023SJohn Marino return true;
528*e4b17023SJohn Marino }
529*e4b17023SJohn Marino
530*e4b17023SJohn Marino /* Returns an estimate for a cost of statement STMT. The values here
531*e4b17023SJohn Marino are just ad-hoc constants, similar to costs for inlining. */
532*e4b17023SJohn Marino
533*e4b17023SJohn Marino static unsigned
stmt_cost(gimple stmt)534*e4b17023SJohn Marino stmt_cost (gimple stmt)
535*e4b17023SJohn Marino {
536*e4b17023SJohn Marino /* Always try to create possibilities for unswitching. */
537*e4b17023SJohn Marino if (gimple_code (stmt) == GIMPLE_COND
538*e4b17023SJohn Marino || gimple_code (stmt) == GIMPLE_PHI)
539*e4b17023SJohn Marino return LIM_EXPENSIVE;
540*e4b17023SJohn Marino
541*e4b17023SJohn Marino /* We should be hoisting calls if possible. */
542*e4b17023SJohn Marino if (is_gimple_call (stmt))
543*e4b17023SJohn Marino {
544*e4b17023SJohn Marino tree fndecl;
545*e4b17023SJohn Marino
546*e4b17023SJohn Marino /* Unless the call is a builtin_constant_p; this always folds to a
547*e4b17023SJohn Marino constant, so moving it is useless. */
548*e4b17023SJohn Marino fndecl = gimple_call_fndecl (stmt);
549*e4b17023SJohn Marino if (fndecl
550*e4b17023SJohn Marino && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
551*e4b17023SJohn Marino && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CONSTANT_P)
552*e4b17023SJohn Marino return 0;
553*e4b17023SJohn Marino
554*e4b17023SJohn Marino return LIM_EXPENSIVE;
555*e4b17023SJohn Marino }
556*e4b17023SJohn Marino
557*e4b17023SJohn Marino /* Hoisting memory references out should almost surely be a win. */
558*e4b17023SJohn Marino if (gimple_references_memory_p (stmt))
559*e4b17023SJohn Marino return LIM_EXPENSIVE;
560*e4b17023SJohn Marino
561*e4b17023SJohn Marino if (gimple_code (stmt) != GIMPLE_ASSIGN)
562*e4b17023SJohn Marino return 1;
563*e4b17023SJohn Marino
564*e4b17023SJohn Marino switch (gimple_assign_rhs_code (stmt))
565*e4b17023SJohn Marino {
566*e4b17023SJohn Marino case MULT_EXPR:
567*e4b17023SJohn Marino case WIDEN_MULT_EXPR:
568*e4b17023SJohn Marino case WIDEN_MULT_PLUS_EXPR:
569*e4b17023SJohn Marino case WIDEN_MULT_MINUS_EXPR:
570*e4b17023SJohn Marino case DOT_PROD_EXPR:
571*e4b17023SJohn Marino case FMA_EXPR:
572*e4b17023SJohn Marino case TRUNC_DIV_EXPR:
573*e4b17023SJohn Marino case CEIL_DIV_EXPR:
574*e4b17023SJohn Marino case FLOOR_DIV_EXPR:
575*e4b17023SJohn Marino case ROUND_DIV_EXPR:
576*e4b17023SJohn Marino case EXACT_DIV_EXPR:
577*e4b17023SJohn Marino case CEIL_MOD_EXPR:
578*e4b17023SJohn Marino case FLOOR_MOD_EXPR:
579*e4b17023SJohn Marino case ROUND_MOD_EXPR:
580*e4b17023SJohn Marino case TRUNC_MOD_EXPR:
581*e4b17023SJohn Marino case RDIV_EXPR:
582*e4b17023SJohn Marino /* Division and multiplication are usually expensive. */
583*e4b17023SJohn Marino return LIM_EXPENSIVE;
584*e4b17023SJohn Marino
585*e4b17023SJohn Marino case LSHIFT_EXPR:
586*e4b17023SJohn Marino case RSHIFT_EXPR:
587*e4b17023SJohn Marino case WIDEN_LSHIFT_EXPR:
588*e4b17023SJohn Marino case LROTATE_EXPR:
589*e4b17023SJohn Marino case RROTATE_EXPR:
590*e4b17023SJohn Marino /* Shifts and rotates are usually expensive. */
591*e4b17023SJohn Marino return LIM_EXPENSIVE;
592*e4b17023SJohn Marino
593*e4b17023SJohn Marino case CONSTRUCTOR:
594*e4b17023SJohn Marino /* Make vector construction cost proportional to the number
595*e4b17023SJohn Marino of elements. */
596*e4b17023SJohn Marino return CONSTRUCTOR_NELTS (gimple_assign_rhs1 (stmt));
597*e4b17023SJohn Marino
598*e4b17023SJohn Marino case SSA_NAME:
599*e4b17023SJohn Marino case PAREN_EXPR:
600*e4b17023SJohn Marino /* Whether or not something is wrapped inside a PAREN_EXPR
601*e4b17023SJohn Marino should not change move cost. Nor should an intermediate
602*e4b17023SJohn Marino unpropagated SSA name copy. */
603*e4b17023SJohn Marino return 0;
604*e4b17023SJohn Marino
605*e4b17023SJohn Marino default:
606*e4b17023SJohn Marino return 1;
607*e4b17023SJohn Marino }
608*e4b17023SJohn Marino }
609*e4b17023SJohn Marino
610*e4b17023SJohn Marino /* Finds the outermost loop between OUTER and LOOP in that the memory reference
611*e4b17023SJohn Marino REF is independent. If REF is not independent in LOOP, NULL is returned
612*e4b17023SJohn Marino instead. */
613*e4b17023SJohn Marino
614*e4b17023SJohn Marino static struct loop *
outermost_indep_loop(struct loop * outer,struct loop * loop,mem_ref_p ref)615*e4b17023SJohn Marino outermost_indep_loop (struct loop *outer, struct loop *loop, mem_ref_p ref)
616*e4b17023SJohn Marino {
617*e4b17023SJohn Marino struct loop *aloop;
618*e4b17023SJohn Marino
619*e4b17023SJohn Marino if (bitmap_bit_p (ref->stored, loop->num))
620*e4b17023SJohn Marino return NULL;
621*e4b17023SJohn Marino
622*e4b17023SJohn Marino for (aloop = outer;
623*e4b17023SJohn Marino aloop != loop;
624*e4b17023SJohn Marino aloop = superloop_at_depth (loop, loop_depth (aloop) + 1))
625*e4b17023SJohn Marino if (!bitmap_bit_p (ref->stored, aloop->num)
626*e4b17023SJohn Marino && ref_indep_loop_p (aloop, ref))
627*e4b17023SJohn Marino return aloop;
628*e4b17023SJohn Marino
629*e4b17023SJohn Marino if (ref_indep_loop_p (loop, ref))
630*e4b17023SJohn Marino return loop;
631*e4b17023SJohn Marino else
632*e4b17023SJohn Marino return NULL;
633*e4b17023SJohn Marino }
634*e4b17023SJohn Marino
635*e4b17023SJohn Marino /* If there is a simple load or store to a memory reference in STMT, returns
636*e4b17023SJohn Marino the location of the memory reference, and sets IS_STORE according to whether
637*e4b17023SJohn Marino it is a store or load. Otherwise, returns NULL. */
638*e4b17023SJohn Marino
639*e4b17023SJohn Marino static tree *
simple_mem_ref_in_stmt(gimple stmt,bool * is_store)640*e4b17023SJohn Marino simple_mem_ref_in_stmt (gimple stmt, bool *is_store)
641*e4b17023SJohn Marino {
642*e4b17023SJohn Marino tree *lhs;
643*e4b17023SJohn Marino enum tree_code code;
644*e4b17023SJohn Marino
645*e4b17023SJohn Marino /* Recognize MEM = (SSA_NAME | invariant) and SSA_NAME = MEM patterns. */
646*e4b17023SJohn Marino if (gimple_code (stmt) != GIMPLE_ASSIGN)
647*e4b17023SJohn Marino return NULL;
648*e4b17023SJohn Marino
649*e4b17023SJohn Marino code = gimple_assign_rhs_code (stmt);
650*e4b17023SJohn Marino
651*e4b17023SJohn Marino lhs = gimple_assign_lhs_ptr (stmt);
652*e4b17023SJohn Marino
653*e4b17023SJohn Marino if (TREE_CODE (*lhs) == SSA_NAME)
654*e4b17023SJohn Marino {
655*e4b17023SJohn Marino if (get_gimple_rhs_class (code) != GIMPLE_SINGLE_RHS
656*e4b17023SJohn Marino || !is_gimple_addressable (gimple_assign_rhs1 (stmt)))
657*e4b17023SJohn Marino return NULL;
658*e4b17023SJohn Marino
659*e4b17023SJohn Marino *is_store = false;
660*e4b17023SJohn Marino return gimple_assign_rhs1_ptr (stmt);
661*e4b17023SJohn Marino }
662*e4b17023SJohn Marino else if (code == SSA_NAME
663*e4b17023SJohn Marino || (get_gimple_rhs_class (code) == GIMPLE_SINGLE_RHS
664*e4b17023SJohn Marino && is_gimple_min_invariant (gimple_assign_rhs1 (stmt))))
665*e4b17023SJohn Marino {
666*e4b17023SJohn Marino *is_store = true;
667*e4b17023SJohn Marino return lhs;
668*e4b17023SJohn Marino }
669*e4b17023SJohn Marino else
670*e4b17023SJohn Marino return NULL;
671*e4b17023SJohn Marino }
672*e4b17023SJohn Marino
673*e4b17023SJohn Marino /* Returns the memory reference contained in STMT. */
674*e4b17023SJohn Marino
675*e4b17023SJohn Marino static mem_ref_p
mem_ref_in_stmt(gimple stmt)676*e4b17023SJohn Marino mem_ref_in_stmt (gimple stmt)
677*e4b17023SJohn Marino {
678*e4b17023SJohn Marino bool store;
679*e4b17023SJohn Marino tree *mem = simple_mem_ref_in_stmt (stmt, &store);
680*e4b17023SJohn Marino hashval_t hash;
681*e4b17023SJohn Marino mem_ref_p ref;
682*e4b17023SJohn Marino
683*e4b17023SJohn Marino if (!mem)
684*e4b17023SJohn Marino return NULL;
685*e4b17023SJohn Marino gcc_assert (!store);
686*e4b17023SJohn Marino
687*e4b17023SJohn Marino hash = iterative_hash_expr (*mem, 0);
688*e4b17023SJohn Marino ref = (mem_ref_p) htab_find_with_hash (memory_accesses.refs, *mem, hash);
689*e4b17023SJohn Marino
690*e4b17023SJohn Marino gcc_assert (ref != NULL);
691*e4b17023SJohn Marino return ref;
692*e4b17023SJohn Marino }
693*e4b17023SJohn Marino
694*e4b17023SJohn Marino /* From a controlling predicate in DOM determine the arguments from
695*e4b17023SJohn Marino the PHI node PHI that are chosen if the predicate evaluates to
696*e4b17023SJohn Marino true and false and store them to *TRUE_ARG_P and *FALSE_ARG_P if
697*e4b17023SJohn Marino they are non-NULL. Returns true if the arguments can be determined,
698*e4b17023SJohn Marino else return false. */
699*e4b17023SJohn Marino
700*e4b17023SJohn Marino static bool
extract_true_false_args_from_phi(basic_block dom,gimple phi,tree * true_arg_p,tree * false_arg_p)701*e4b17023SJohn Marino extract_true_false_args_from_phi (basic_block dom, gimple phi,
702*e4b17023SJohn Marino tree *true_arg_p, tree *false_arg_p)
703*e4b17023SJohn Marino {
704*e4b17023SJohn Marino basic_block bb = gimple_bb (phi);
705*e4b17023SJohn Marino edge true_edge, false_edge, tem;
706*e4b17023SJohn Marino tree arg0 = NULL_TREE, arg1 = NULL_TREE;
707*e4b17023SJohn Marino
708*e4b17023SJohn Marino /* We have to verify that one edge into the PHI node is dominated
709*e4b17023SJohn Marino by the true edge of the predicate block and the other edge
710*e4b17023SJohn Marino dominated by the false edge. This ensures that the PHI argument
711*e4b17023SJohn Marino we are going to take is completely determined by the path we
712*e4b17023SJohn Marino take from the predicate block.
713*e4b17023SJohn Marino We can only use BB dominance checks below if the destination of
714*e4b17023SJohn Marino the true/false edges are dominated by their edge, thus only
715*e4b17023SJohn Marino have a single predecessor. */
716*e4b17023SJohn Marino extract_true_false_edges_from_block (dom, &true_edge, &false_edge);
717*e4b17023SJohn Marino tem = EDGE_PRED (bb, 0);
718*e4b17023SJohn Marino if (tem == true_edge
719*e4b17023SJohn Marino || (single_pred_p (true_edge->dest)
720*e4b17023SJohn Marino && (tem->src == true_edge->dest
721*e4b17023SJohn Marino || dominated_by_p (CDI_DOMINATORS,
722*e4b17023SJohn Marino tem->src, true_edge->dest))))
723*e4b17023SJohn Marino arg0 = PHI_ARG_DEF (phi, tem->dest_idx);
724*e4b17023SJohn Marino else if (tem == false_edge
725*e4b17023SJohn Marino || (single_pred_p (false_edge->dest)
726*e4b17023SJohn Marino && (tem->src == false_edge->dest
727*e4b17023SJohn Marino || dominated_by_p (CDI_DOMINATORS,
728*e4b17023SJohn Marino tem->src, false_edge->dest))))
729*e4b17023SJohn Marino arg1 = PHI_ARG_DEF (phi, tem->dest_idx);
730*e4b17023SJohn Marino else
731*e4b17023SJohn Marino return false;
732*e4b17023SJohn Marino tem = EDGE_PRED (bb, 1);
733*e4b17023SJohn Marino if (tem == true_edge
734*e4b17023SJohn Marino || (single_pred_p (true_edge->dest)
735*e4b17023SJohn Marino && (tem->src == true_edge->dest
736*e4b17023SJohn Marino || dominated_by_p (CDI_DOMINATORS,
737*e4b17023SJohn Marino tem->src, true_edge->dest))))
738*e4b17023SJohn Marino arg0 = PHI_ARG_DEF (phi, tem->dest_idx);
739*e4b17023SJohn Marino else if (tem == false_edge
740*e4b17023SJohn Marino || (single_pred_p (false_edge->dest)
741*e4b17023SJohn Marino && (tem->src == false_edge->dest
742*e4b17023SJohn Marino || dominated_by_p (CDI_DOMINATORS,
743*e4b17023SJohn Marino tem->src, false_edge->dest))))
744*e4b17023SJohn Marino arg1 = PHI_ARG_DEF (phi, tem->dest_idx);
745*e4b17023SJohn Marino else
746*e4b17023SJohn Marino return false;
747*e4b17023SJohn Marino if (!arg0 || !arg1)
748*e4b17023SJohn Marino return false;
749*e4b17023SJohn Marino
750*e4b17023SJohn Marino if (true_arg_p)
751*e4b17023SJohn Marino *true_arg_p = arg0;
752*e4b17023SJohn Marino if (false_arg_p)
753*e4b17023SJohn Marino *false_arg_p = arg1;
754*e4b17023SJohn Marino
755*e4b17023SJohn Marino return true;
756*e4b17023SJohn Marino }
757*e4b17023SJohn Marino
758*e4b17023SJohn Marino /* Determine the outermost loop to that it is possible to hoist a statement
759*e4b17023SJohn Marino STMT and store it to LIM_DATA (STMT)->max_loop. To do this we determine
760*e4b17023SJohn Marino the outermost loop in that the value computed by STMT is invariant.
761*e4b17023SJohn Marino If MUST_PRESERVE_EXEC is true, additionally choose such a loop that
762*e4b17023SJohn Marino we preserve the fact whether STMT is executed. It also fills other related
763*e4b17023SJohn Marino information to LIM_DATA (STMT).
764*e4b17023SJohn Marino
765*e4b17023SJohn Marino The function returns false if STMT cannot be hoisted outside of the loop it
766*e4b17023SJohn Marino is defined in, and true otherwise. */
767*e4b17023SJohn Marino
768*e4b17023SJohn Marino static bool
determine_max_movement(gimple stmt,bool must_preserve_exec)769*e4b17023SJohn Marino determine_max_movement (gimple stmt, bool must_preserve_exec)
770*e4b17023SJohn Marino {
771*e4b17023SJohn Marino basic_block bb = gimple_bb (stmt);
772*e4b17023SJohn Marino struct loop *loop = bb->loop_father;
773*e4b17023SJohn Marino struct loop *level;
774*e4b17023SJohn Marino struct lim_aux_data *lim_data = get_lim_data (stmt);
775*e4b17023SJohn Marino tree val;
776*e4b17023SJohn Marino ssa_op_iter iter;
777*e4b17023SJohn Marino
778*e4b17023SJohn Marino if (must_preserve_exec)
779*e4b17023SJohn Marino level = ALWAYS_EXECUTED_IN (bb);
780*e4b17023SJohn Marino else
781*e4b17023SJohn Marino level = superloop_at_depth (loop, 1);
782*e4b17023SJohn Marino lim_data->max_loop = level;
783*e4b17023SJohn Marino
784*e4b17023SJohn Marino if (gimple_code (stmt) == GIMPLE_PHI)
785*e4b17023SJohn Marino {
786*e4b17023SJohn Marino use_operand_p use_p;
787*e4b17023SJohn Marino unsigned min_cost = UINT_MAX;
788*e4b17023SJohn Marino unsigned total_cost = 0;
789*e4b17023SJohn Marino struct lim_aux_data *def_data;
790*e4b17023SJohn Marino
791*e4b17023SJohn Marino /* We will end up promoting dependencies to be unconditionally
792*e4b17023SJohn Marino evaluated. For this reason the PHI cost (and thus the
793*e4b17023SJohn Marino cost we remove from the loop by doing the invariant motion)
794*e4b17023SJohn Marino is that of the cheapest PHI argument dependency chain. */
795*e4b17023SJohn Marino FOR_EACH_PHI_ARG (use_p, stmt, iter, SSA_OP_USE)
796*e4b17023SJohn Marino {
797*e4b17023SJohn Marino val = USE_FROM_PTR (use_p);
798*e4b17023SJohn Marino if (TREE_CODE (val) != SSA_NAME)
799*e4b17023SJohn Marino continue;
800*e4b17023SJohn Marino if (!add_dependency (val, lim_data, loop, false))
801*e4b17023SJohn Marino return false;
802*e4b17023SJohn Marino def_data = get_lim_data (SSA_NAME_DEF_STMT (val));
803*e4b17023SJohn Marino if (def_data)
804*e4b17023SJohn Marino {
805*e4b17023SJohn Marino min_cost = MIN (min_cost, def_data->cost);
806*e4b17023SJohn Marino total_cost += def_data->cost;
807*e4b17023SJohn Marino }
808*e4b17023SJohn Marino }
809*e4b17023SJohn Marino
810*e4b17023SJohn Marino lim_data->cost += min_cost;
811*e4b17023SJohn Marino
812*e4b17023SJohn Marino if (gimple_phi_num_args (stmt) > 1)
813*e4b17023SJohn Marino {
814*e4b17023SJohn Marino basic_block dom = get_immediate_dominator (CDI_DOMINATORS, bb);
815*e4b17023SJohn Marino gimple cond;
816*e4b17023SJohn Marino if (gsi_end_p (gsi_last_bb (dom)))
817*e4b17023SJohn Marino return false;
818*e4b17023SJohn Marino cond = gsi_stmt (gsi_last_bb (dom));
819*e4b17023SJohn Marino if (gimple_code (cond) != GIMPLE_COND)
820*e4b17023SJohn Marino return false;
821*e4b17023SJohn Marino /* Verify that this is an extended form of a diamond and
822*e4b17023SJohn Marino the PHI arguments are completely controlled by the
823*e4b17023SJohn Marino predicate in DOM. */
824*e4b17023SJohn Marino if (!extract_true_false_args_from_phi (dom, stmt, NULL, NULL))
825*e4b17023SJohn Marino return false;
826*e4b17023SJohn Marino
827*e4b17023SJohn Marino /* Fold in dependencies and cost of the condition. */
828*e4b17023SJohn Marino FOR_EACH_SSA_TREE_OPERAND (val, cond, iter, SSA_OP_USE)
829*e4b17023SJohn Marino {
830*e4b17023SJohn Marino if (!add_dependency (val, lim_data, loop, false))
831*e4b17023SJohn Marino return false;
832*e4b17023SJohn Marino def_data = get_lim_data (SSA_NAME_DEF_STMT (val));
833*e4b17023SJohn Marino if (def_data)
834*e4b17023SJohn Marino total_cost += def_data->cost;
835*e4b17023SJohn Marino }
836*e4b17023SJohn Marino
837*e4b17023SJohn Marino /* We want to avoid unconditionally executing very expensive
838*e4b17023SJohn Marino operations. As costs for our dependencies cannot be
839*e4b17023SJohn Marino negative just claim we are not invariand for this case.
840*e4b17023SJohn Marino We also are not sure whether the control-flow inside the
841*e4b17023SJohn Marino loop will vanish. */
842*e4b17023SJohn Marino if (total_cost - min_cost >= 2 * LIM_EXPENSIVE
843*e4b17023SJohn Marino && !(min_cost != 0
844*e4b17023SJohn Marino && total_cost / min_cost <= 2))
845*e4b17023SJohn Marino return false;
846*e4b17023SJohn Marino
847*e4b17023SJohn Marino /* Assume that the control-flow in the loop will vanish.
848*e4b17023SJohn Marino ??? We should verify this and not artificially increase
849*e4b17023SJohn Marino the cost if that is not the case. */
850*e4b17023SJohn Marino lim_data->cost += stmt_cost (stmt);
851*e4b17023SJohn Marino }
852*e4b17023SJohn Marino
853*e4b17023SJohn Marino return true;
854*e4b17023SJohn Marino }
855*e4b17023SJohn Marino else
856*e4b17023SJohn Marino FOR_EACH_SSA_TREE_OPERAND (val, stmt, iter, SSA_OP_USE)
857*e4b17023SJohn Marino if (!add_dependency (val, lim_data, loop, true))
858*e4b17023SJohn Marino return false;
859*e4b17023SJohn Marino
860*e4b17023SJohn Marino if (gimple_vuse (stmt))
861*e4b17023SJohn Marino {
862*e4b17023SJohn Marino mem_ref_p ref = mem_ref_in_stmt (stmt);
863*e4b17023SJohn Marino
864*e4b17023SJohn Marino if (ref)
865*e4b17023SJohn Marino {
866*e4b17023SJohn Marino lim_data->max_loop
867*e4b17023SJohn Marino = outermost_indep_loop (lim_data->max_loop, loop, ref);
868*e4b17023SJohn Marino if (!lim_data->max_loop)
869*e4b17023SJohn Marino return false;
870*e4b17023SJohn Marino }
871*e4b17023SJohn Marino else
872*e4b17023SJohn Marino {
873*e4b17023SJohn Marino if ((val = gimple_vuse (stmt)) != NULL_TREE)
874*e4b17023SJohn Marino {
875*e4b17023SJohn Marino if (!add_dependency (val, lim_data, loop, false))
876*e4b17023SJohn Marino return false;
877*e4b17023SJohn Marino }
878*e4b17023SJohn Marino }
879*e4b17023SJohn Marino }
880*e4b17023SJohn Marino
881*e4b17023SJohn Marino lim_data->cost += stmt_cost (stmt);
882*e4b17023SJohn Marino
883*e4b17023SJohn Marino return true;
884*e4b17023SJohn Marino }
885*e4b17023SJohn Marino
886*e4b17023SJohn Marino /* Suppose that some statement in ORIG_LOOP is hoisted to the loop LEVEL,
887*e4b17023SJohn Marino and that one of the operands of this statement is computed by STMT.
888*e4b17023SJohn Marino Ensure that STMT (together with all the statements that define its
889*e4b17023SJohn Marino operands) is hoisted at least out of the loop LEVEL. */
890*e4b17023SJohn Marino
891*e4b17023SJohn Marino static void
set_level(gimple stmt,struct loop * orig_loop,struct loop * level)892*e4b17023SJohn Marino set_level (gimple stmt, struct loop *orig_loop, struct loop *level)
893*e4b17023SJohn Marino {
894*e4b17023SJohn Marino struct loop *stmt_loop = gimple_bb (stmt)->loop_father;
895*e4b17023SJohn Marino struct depend *dep;
896*e4b17023SJohn Marino struct lim_aux_data *lim_data;
897*e4b17023SJohn Marino
898*e4b17023SJohn Marino stmt_loop = find_common_loop (orig_loop, stmt_loop);
899*e4b17023SJohn Marino lim_data = get_lim_data (stmt);
900*e4b17023SJohn Marino if (lim_data != NULL && lim_data->tgt_loop != NULL)
901*e4b17023SJohn Marino stmt_loop = find_common_loop (stmt_loop,
902*e4b17023SJohn Marino loop_outer (lim_data->tgt_loop));
903*e4b17023SJohn Marino if (flow_loop_nested_p (stmt_loop, level))
904*e4b17023SJohn Marino return;
905*e4b17023SJohn Marino
906*e4b17023SJohn Marino gcc_assert (level == lim_data->max_loop
907*e4b17023SJohn Marino || flow_loop_nested_p (lim_data->max_loop, level));
908*e4b17023SJohn Marino
909*e4b17023SJohn Marino lim_data->tgt_loop = level;
910*e4b17023SJohn Marino for (dep = lim_data->depends; dep; dep = dep->next)
911*e4b17023SJohn Marino set_level (dep->stmt, orig_loop, level);
912*e4b17023SJohn Marino }
913*e4b17023SJohn Marino
914*e4b17023SJohn Marino /* Determines an outermost loop from that we want to hoist the statement STMT.
915*e4b17023SJohn Marino For now we chose the outermost possible loop. TODO -- use profiling
916*e4b17023SJohn Marino information to set it more sanely. */
917*e4b17023SJohn Marino
918*e4b17023SJohn Marino static void
set_profitable_level(gimple stmt)919*e4b17023SJohn Marino set_profitable_level (gimple stmt)
920*e4b17023SJohn Marino {
921*e4b17023SJohn Marino set_level (stmt, gimple_bb (stmt)->loop_father, get_lim_data (stmt)->max_loop);
922*e4b17023SJohn Marino }
923*e4b17023SJohn Marino
924*e4b17023SJohn Marino /* Returns true if STMT is a call that has side effects. */
925*e4b17023SJohn Marino
926*e4b17023SJohn Marino static bool
nonpure_call_p(gimple stmt)927*e4b17023SJohn Marino nonpure_call_p (gimple stmt)
928*e4b17023SJohn Marino {
929*e4b17023SJohn Marino if (gimple_code (stmt) != GIMPLE_CALL)
930*e4b17023SJohn Marino return false;
931*e4b17023SJohn Marino
932*e4b17023SJohn Marino return gimple_has_side_effects (stmt);
933*e4b17023SJohn Marino }
934*e4b17023SJohn Marino
935*e4b17023SJohn Marino /* Rewrite a/b to a*(1/b). Return the invariant stmt to process. */
936*e4b17023SJohn Marino
937*e4b17023SJohn Marino static gimple
rewrite_reciprocal(gimple_stmt_iterator * bsi)938*e4b17023SJohn Marino rewrite_reciprocal (gimple_stmt_iterator *bsi)
939*e4b17023SJohn Marino {
940*e4b17023SJohn Marino gimple stmt, stmt1, stmt2;
941*e4b17023SJohn Marino tree var, name, lhs, type;
942*e4b17023SJohn Marino tree real_one;
943*e4b17023SJohn Marino gimple_stmt_iterator gsi;
944*e4b17023SJohn Marino
945*e4b17023SJohn Marino stmt = gsi_stmt (*bsi);
946*e4b17023SJohn Marino lhs = gimple_assign_lhs (stmt);
947*e4b17023SJohn Marino type = TREE_TYPE (lhs);
948*e4b17023SJohn Marino
949*e4b17023SJohn Marino var = create_tmp_var (type, "reciptmp");
950*e4b17023SJohn Marino add_referenced_var (var);
951*e4b17023SJohn Marino DECL_GIMPLE_REG_P (var) = 1;
952*e4b17023SJohn Marino
953*e4b17023SJohn Marino real_one = build_one_cst (type);
954*e4b17023SJohn Marino
955*e4b17023SJohn Marino stmt1 = gimple_build_assign_with_ops (RDIV_EXPR,
956*e4b17023SJohn Marino var, real_one, gimple_assign_rhs2 (stmt));
957*e4b17023SJohn Marino name = make_ssa_name (var, stmt1);
958*e4b17023SJohn Marino gimple_assign_set_lhs (stmt1, name);
959*e4b17023SJohn Marino
960*e4b17023SJohn Marino stmt2 = gimple_build_assign_with_ops (MULT_EXPR, lhs, name,
961*e4b17023SJohn Marino gimple_assign_rhs1 (stmt));
962*e4b17023SJohn Marino
963*e4b17023SJohn Marino /* Replace division stmt with reciprocal and multiply stmts.
964*e4b17023SJohn Marino The multiply stmt is not invariant, so update iterator
965*e4b17023SJohn Marino and avoid rescanning. */
966*e4b17023SJohn Marino gsi = *bsi;
967*e4b17023SJohn Marino gsi_insert_before (bsi, stmt1, GSI_NEW_STMT);
968*e4b17023SJohn Marino gsi_replace (&gsi, stmt2, true);
969*e4b17023SJohn Marino
970*e4b17023SJohn Marino /* Continue processing with invariant reciprocal statement. */
971*e4b17023SJohn Marino return stmt1;
972*e4b17023SJohn Marino }
973*e4b17023SJohn Marino
974*e4b17023SJohn Marino /* Check if the pattern at *BSI is a bittest of the form
975*e4b17023SJohn Marino (A >> B) & 1 != 0 and in this case rewrite it to A & (1 << B) != 0. */
976*e4b17023SJohn Marino
977*e4b17023SJohn Marino static gimple
rewrite_bittest(gimple_stmt_iterator * bsi)978*e4b17023SJohn Marino rewrite_bittest (gimple_stmt_iterator *bsi)
979*e4b17023SJohn Marino {
980*e4b17023SJohn Marino gimple stmt, use_stmt, stmt1, stmt2;
981*e4b17023SJohn Marino tree lhs, var, name, t, a, b;
982*e4b17023SJohn Marino use_operand_p use;
983*e4b17023SJohn Marino
984*e4b17023SJohn Marino stmt = gsi_stmt (*bsi);
985*e4b17023SJohn Marino lhs = gimple_assign_lhs (stmt);
986*e4b17023SJohn Marino
987*e4b17023SJohn Marino /* Verify that the single use of lhs is a comparison against zero. */
988*e4b17023SJohn Marino if (TREE_CODE (lhs) != SSA_NAME
989*e4b17023SJohn Marino || !single_imm_use (lhs, &use, &use_stmt)
990*e4b17023SJohn Marino || gimple_code (use_stmt) != GIMPLE_COND)
991*e4b17023SJohn Marino return stmt;
992*e4b17023SJohn Marino if (gimple_cond_lhs (use_stmt) != lhs
993*e4b17023SJohn Marino || (gimple_cond_code (use_stmt) != NE_EXPR
994*e4b17023SJohn Marino && gimple_cond_code (use_stmt) != EQ_EXPR)
995*e4b17023SJohn Marino || !integer_zerop (gimple_cond_rhs (use_stmt)))
996*e4b17023SJohn Marino return stmt;
997*e4b17023SJohn Marino
998*e4b17023SJohn Marino /* Get at the operands of the shift. The rhs is TMP1 & 1. */
999*e4b17023SJohn Marino stmt1 = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt));
1000*e4b17023SJohn Marino if (gimple_code (stmt1) != GIMPLE_ASSIGN)
1001*e4b17023SJohn Marino return stmt;
1002*e4b17023SJohn Marino
1003*e4b17023SJohn Marino /* There is a conversion in between possibly inserted by fold. */
1004*e4b17023SJohn Marino if (CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (stmt1)))
1005*e4b17023SJohn Marino {
1006*e4b17023SJohn Marino t = gimple_assign_rhs1 (stmt1);
1007*e4b17023SJohn Marino if (TREE_CODE (t) != SSA_NAME
1008*e4b17023SJohn Marino || !has_single_use (t))
1009*e4b17023SJohn Marino return stmt;
1010*e4b17023SJohn Marino stmt1 = SSA_NAME_DEF_STMT (t);
1011*e4b17023SJohn Marino if (gimple_code (stmt1) != GIMPLE_ASSIGN)
1012*e4b17023SJohn Marino return stmt;
1013*e4b17023SJohn Marino }
1014*e4b17023SJohn Marino
1015*e4b17023SJohn Marino /* Verify that B is loop invariant but A is not. Verify that with
1016*e4b17023SJohn Marino all the stmt walking we are still in the same loop. */
1017*e4b17023SJohn Marino if (gimple_assign_rhs_code (stmt1) != RSHIFT_EXPR
1018*e4b17023SJohn Marino || loop_containing_stmt (stmt1) != loop_containing_stmt (stmt))
1019*e4b17023SJohn Marino return stmt;
1020*e4b17023SJohn Marino
1021*e4b17023SJohn Marino a = gimple_assign_rhs1 (stmt1);
1022*e4b17023SJohn Marino b = gimple_assign_rhs2 (stmt1);
1023*e4b17023SJohn Marino
1024*e4b17023SJohn Marino if (outermost_invariant_loop (b, loop_containing_stmt (stmt1)) != NULL
1025*e4b17023SJohn Marino && outermost_invariant_loop (a, loop_containing_stmt (stmt1)) == NULL)
1026*e4b17023SJohn Marino {
1027*e4b17023SJohn Marino gimple_stmt_iterator rsi;
1028*e4b17023SJohn Marino
1029*e4b17023SJohn Marino /* 1 << B */
1030*e4b17023SJohn Marino var = create_tmp_var (TREE_TYPE (a), "shifttmp");
1031*e4b17023SJohn Marino add_referenced_var (var);
1032*e4b17023SJohn Marino t = fold_build2 (LSHIFT_EXPR, TREE_TYPE (a),
1033*e4b17023SJohn Marino build_int_cst (TREE_TYPE (a), 1), b);
1034*e4b17023SJohn Marino stmt1 = gimple_build_assign (var, t);
1035*e4b17023SJohn Marino name = make_ssa_name (var, stmt1);
1036*e4b17023SJohn Marino gimple_assign_set_lhs (stmt1, name);
1037*e4b17023SJohn Marino
1038*e4b17023SJohn Marino /* A & (1 << B) */
1039*e4b17023SJohn Marino t = fold_build2 (BIT_AND_EXPR, TREE_TYPE (a), a, name);
1040*e4b17023SJohn Marino stmt2 = gimple_build_assign (var, t);
1041*e4b17023SJohn Marino name = make_ssa_name (var, stmt2);
1042*e4b17023SJohn Marino gimple_assign_set_lhs (stmt2, name);
1043*e4b17023SJohn Marino
1044*e4b17023SJohn Marino /* Replace the SSA_NAME we compare against zero. Adjust
1045*e4b17023SJohn Marino the type of zero accordingly. */
1046*e4b17023SJohn Marino SET_USE (use, name);
1047*e4b17023SJohn Marino gimple_cond_set_rhs (use_stmt, build_int_cst_type (TREE_TYPE (name), 0));
1048*e4b17023SJohn Marino
1049*e4b17023SJohn Marino /* Don't use gsi_replace here, none of the new assignments sets
1050*e4b17023SJohn Marino the variable originally set in stmt. Move bsi to stmt1, and
1051*e4b17023SJohn Marino then remove the original stmt, so that we get a chance to
1052*e4b17023SJohn Marino retain debug info for it. */
1053*e4b17023SJohn Marino rsi = *bsi;
1054*e4b17023SJohn Marino gsi_insert_before (bsi, stmt1, GSI_NEW_STMT);
1055*e4b17023SJohn Marino gsi_insert_before (&rsi, stmt2, GSI_SAME_STMT);
1056*e4b17023SJohn Marino gsi_remove (&rsi, true);
1057*e4b17023SJohn Marino
1058*e4b17023SJohn Marino return stmt1;
1059*e4b17023SJohn Marino }
1060*e4b17023SJohn Marino
1061*e4b17023SJohn Marino return stmt;
1062*e4b17023SJohn Marino }
1063*e4b17023SJohn Marino
1064*e4b17023SJohn Marino
1065*e4b17023SJohn Marino /* Determine the outermost loops in that statements in basic block BB are
1066*e4b17023SJohn Marino invariant, and record them to the LIM_DATA associated with the statements.
1067*e4b17023SJohn Marino Callback for walk_dominator_tree. */
1068*e4b17023SJohn Marino
1069*e4b17023SJohn Marino static void
determine_invariantness_stmt(struct dom_walk_data * dw_data ATTRIBUTE_UNUSED,basic_block bb)1070*e4b17023SJohn Marino determine_invariantness_stmt (struct dom_walk_data *dw_data ATTRIBUTE_UNUSED,
1071*e4b17023SJohn Marino basic_block bb)
1072*e4b17023SJohn Marino {
1073*e4b17023SJohn Marino enum move_pos pos;
1074*e4b17023SJohn Marino gimple_stmt_iterator bsi;
1075*e4b17023SJohn Marino gimple stmt;
1076*e4b17023SJohn Marino bool maybe_never = ALWAYS_EXECUTED_IN (bb) == NULL;
1077*e4b17023SJohn Marino struct loop *outermost = ALWAYS_EXECUTED_IN (bb);
1078*e4b17023SJohn Marino struct lim_aux_data *lim_data;
1079*e4b17023SJohn Marino
1080*e4b17023SJohn Marino if (!loop_outer (bb->loop_father))
1081*e4b17023SJohn Marino return;
1082*e4b17023SJohn Marino
1083*e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS))
1084*e4b17023SJohn Marino fprintf (dump_file, "Basic block %d (loop %d -- depth %d):\n\n",
1085*e4b17023SJohn Marino bb->index, bb->loop_father->num, loop_depth (bb->loop_father));
1086*e4b17023SJohn Marino
1087*e4b17023SJohn Marino /* Look at PHI nodes, but only if there is at most two.
1088*e4b17023SJohn Marino ??? We could relax this further by post-processing the inserted
1089*e4b17023SJohn Marino code and transforming adjacent cond-exprs with the same predicate
1090*e4b17023SJohn Marino to control flow again. */
1091*e4b17023SJohn Marino bsi = gsi_start_phis (bb);
1092*e4b17023SJohn Marino if (!gsi_end_p (bsi)
1093*e4b17023SJohn Marino && ((gsi_next (&bsi), gsi_end_p (bsi))
1094*e4b17023SJohn Marino || (gsi_next (&bsi), gsi_end_p (bsi))))
1095*e4b17023SJohn Marino for (bsi = gsi_start_phis (bb); !gsi_end_p (bsi); gsi_next (&bsi))
1096*e4b17023SJohn Marino {
1097*e4b17023SJohn Marino stmt = gsi_stmt (bsi);
1098*e4b17023SJohn Marino
1099*e4b17023SJohn Marino pos = movement_possibility (stmt);
1100*e4b17023SJohn Marino if (pos == MOVE_IMPOSSIBLE)
1101*e4b17023SJohn Marino continue;
1102*e4b17023SJohn Marino
1103*e4b17023SJohn Marino lim_data = init_lim_data (stmt);
1104*e4b17023SJohn Marino lim_data->always_executed_in = outermost;
1105*e4b17023SJohn Marino
1106*e4b17023SJohn Marino if (!determine_max_movement (stmt, false))
1107*e4b17023SJohn Marino {
1108*e4b17023SJohn Marino lim_data->max_loop = NULL;
1109*e4b17023SJohn Marino continue;
1110*e4b17023SJohn Marino }
1111*e4b17023SJohn Marino
1112*e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS))
1113*e4b17023SJohn Marino {
1114*e4b17023SJohn Marino print_gimple_stmt (dump_file, stmt, 2, 0);
1115*e4b17023SJohn Marino fprintf (dump_file, " invariant up to level %d, cost %d.\n\n",
1116*e4b17023SJohn Marino loop_depth (lim_data->max_loop),
1117*e4b17023SJohn Marino lim_data->cost);
1118*e4b17023SJohn Marino }
1119*e4b17023SJohn Marino
1120*e4b17023SJohn Marino if (lim_data->cost >= LIM_EXPENSIVE)
1121*e4b17023SJohn Marino set_profitable_level (stmt);
1122*e4b17023SJohn Marino }
1123*e4b17023SJohn Marino
1124*e4b17023SJohn Marino for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi))
1125*e4b17023SJohn Marino {
1126*e4b17023SJohn Marino stmt = gsi_stmt (bsi);
1127*e4b17023SJohn Marino
1128*e4b17023SJohn Marino pos = movement_possibility (stmt);
1129*e4b17023SJohn Marino if (pos == MOVE_IMPOSSIBLE)
1130*e4b17023SJohn Marino {
1131*e4b17023SJohn Marino if (nonpure_call_p (stmt))
1132*e4b17023SJohn Marino {
1133*e4b17023SJohn Marino maybe_never = true;
1134*e4b17023SJohn Marino outermost = NULL;
1135*e4b17023SJohn Marino }
1136*e4b17023SJohn Marino /* Make sure to note always_executed_in for stores to make
1137*e4b17023SJohn Marino store-motion work. */
1138*e4b17023SJohn Marino else if (stmt_makes_single_store (stmt))
1139*e4b17023SJohn Marino {
1140*e4b17023SJohn Marino struct lim_aux_data *lim_data = init_lim_data (stmt);
1141*e4b17023SJohn Marino lim_data->always_executed_in = outermost;
1142*e4b17023SJohn Marino }
1143*e4b17023SJohn Marino continue;
1144*e4b17023SJohn Marino }
1145*e4b17023SJohn Marino
1146*e4b17023SJohn Marino if (is_gimple_assign (stmt)
1147*e4b17023SJohn Marino && (get_gimple_rhs_class (gimple_assign_rhs_code (stmt))
1148*e4b17023SJohn Marino == GIMPLE_BINARY_RHS))
1149*e4b17023SJohn Marino {
1150*e4b17023SJohn Marino tree op0 = gimple_assign_rhs1 (stmt);
1151*e4b17023SJohn Marino tree op1 = gimple_assign_rhs2 (stmt);
1152*e4b17023SJohn Marino struct loop *ol1 = outermost_invariant_loop (op1,
1153*e4b17023SJohn Marino loop_containing_stmt (stmt));
1154*e4b17023SJohn Marino
1155*e4b17023SJohn Marino /* If divisor is invariant, convert a/b to a*(1/b), allowing reciprocal
1156*e4b17023SJohn Marino to be hoisted out of loop, saving expensive divide. */
1157*e4b17023SJohn Marino if (pos == MOVE_POSSIBLE
1158*e4b17023SJohn Marino && gimple_assign_rhs_code (stmt) == RDIV_EXPR
1159*e4b17023SJohn Marino && flag_unsafe_math_optimizations
1160*e4b17023SJohn Marino && !flag_trapping_math
1161*e4b17023SJohn Marino && ol1 != NULL
1162*e4b17023SJohn Marino && outermost_invariant_loop (op0, ol1) == NULL)
1163*e4b17023SJohn Marino stmt = rewrite_reciprocal (&bsi);
1164*e4b17023SJohn Marino
1165*e4b17023SJohn Marino /* If the shift count is invariant, convert (A >> B) & 1 to
1166*e4b17023SJohn Marino A & (1 << B) allowing the bit mask to be hoisted out of the loop
1167*e4b17023SJohn Marino saving an expensive shift. */
1168*e4b17023SJohn Marino if (pos == MOVE_POSSIBLE
1169*e4b17023SJohn Marino && gimple_assign_rhs_code (stmt) == BIT_AND_EXPR
1170*e4b17023SJohn Marino && integer_onep (op1)
1171*e4b17023SJohn Marino && TREE_CODE (op0) == SSA_NAME
1172*e4b17023SJohn Marino && has_single_use (op0))
1173*e4b17023SJohn Marino stmt = rewrite_bittest (&bsi);
1174*e4b17023SJohn Marino }
1175*e4b17023SJohn Marino
1176*e4b17023SJohn Marino lim_data = init_lim_data (stmt);
1177*e4b17023SJohn Marino lim_data->always_executed_in = outermost;
1178*e4b17023SJohn Marino
1179*e4b17023SJohn Marino if (maybe_never && pos == MOVE_PRESERVE_EXECUTION)
1180*e4b17023SJohn Marino continue;
1181*e4b17023SJohn Marino
1182*e4b17023SJohn Marino if (!determine_max_movement (stmt, pos == MOVE_PRESERVE_EXECUTION))
1183*e4b17023SJohn Marino {
1184*e4b17023SJohn Marino lim_data->max_loop = NULL;
1185*e4b17023SJohn Marino continue;
1186*e4b17023SJohn Marino }
1187*e4b17023SJohn Marino
1188*e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS))
1189*e4b17023SJohn Marino {
1190*e4b17023SJohn Marino print_gimple_stmt (dump_file, stmt, 2, 0);
1191*e4b17023SJohn Marino fprintf (dump_file, " invariant up to level %d, cost %d.\n\n",
1192*e4b17023SJohn Marino loop_depth (lim_data->max_loop),
1193*e4b17023SJohn Marino lim_data->cost);
1194*e4b17023SJohn Marino }
1195*e4b17023SJohn Marino
1196*e4b17023SJohn Marino if (lim_data->cost >= LIM_EXPENSIVE)
1197*e4b17023SJohn Marino set_profitable_level (stmt);
1198*e4b17023SJohn Marino }
1199*e4b17023SJohn Marino }
1200*e4b17023SJohn Marino
1201*e4b17023SJohn Marino /* For each statement determines the outermost loop in that it is invariant,
1202*e4b17023SJohn Marino statements on whose motion it depends and the cost of the computation.
1203*e4b17023SJohn Marino This information is stored to the LIM_DATA structure associated with
1204*e4b17023SJohn Marino each statement. */
1205*e4b17023SJohn Marino
1206*e4b17023SJohn Marino static void
determine_invariantness(void)1207*e4b17023SJohn Marino determine_invariantness (void)
1208*e4b17023SJohn Marino {
1209*e4b17023SJohn Marino struct dom_walk_data walk_data;
1210*e4b17023SJohn Marino
1211*e4b17023SJohn Marino memset (&walk_data, 0, sizeof (struct dom_walk_data));
1212*e4b17023SJohn Marino walk_data.dom_direction = CDI_DOMINATORS;
1213*e4b17023SJohn Marino walk_data.before_dom_children = determine_invariantness_stmt;
1214*e4b17023SJohn Marino
1215*e4b17023SJohn Marino init_walk_dominator_tree (&walk_data);
1216*e4b17023SJohn Marino walk_dominator_tree (&walk_data, ENTRY_BLOCK_PTR);
1217*e4b17023SJohn Marino fini_walk_dominator_tree (&walk_data);
1218*e4b17023SJohn Marino }
1219*e4b17023SJohn Marino
1220*e4b17023SJohn Marino /* Hoist the statements in basic block BB out of the loops prescribed by
1221*e4b17023SJohn Marino data stored in LIM_DATA structures associated with each statement. Callback
1222*e4b17023SJohn Marino for walk_dominator_tree. */
1223*e4b17023SJohn Marino
1224*e4b17023SJohn Marino static void
move_computations_stmt(struct dom_walk_data * dw_data,basic_block bb)1225*e4b17023SJohn Marino move_computations_stmt (struct dom_walk_data *dw_data,
1226*e4b17023SJohn Marino basic_block bb)
1227*e4b17023SJohn Marino {
1228*e4b17023SJohn Marino struct loop *level;
1229*e4b17023SJohn Marino gimple_stmt_iterator bsi;
1230*e4b17023SJohn Marino gimple stmt;
1231*e4b17023SJohn Marino unsigned cost = 0;
1232*e4b17023SJohn Marino struct lim_aux_data *lim_data;
1233*e4b17023SJohn Marino
1234*e4b17023SJohn Marino if (!loop_outer (bb->loop_father))
1235*e4b17023SJohn Marino return;
1236*e4b17023SJohn Marino
1237*e4b17023SJohn Marino for (bsi = gsi_start_phis (bb); !gsi_end_p (bsi); )
1238*e4b17023SJohn Marino {
1239*e4b17023SJohn Marino gimple new_stmt;
1240*e4b17023SJohn Marino stmt = gsi_stmt (bsi);
1241*e4b17023SJohn Marino
1242*e4b17023SJohn Marino lim_data = get_lim_data (stmt);
1243*e4b17023SJohn Marino if (lim_data == NULL)
1244*e4b17023SJohn Marino {
1245*e4b17023SJohn Marino gsi_next (&bsi);
1246*e4b17023SJohn Marino continue;
1247*e4b17023SJohn Marino }
1248*e4b17023SJohn Marino
1249*e4b17023SJohn Marino cost = lim_data->cost;
1250*e4b17023SJohn Marino level = lim_data->tgt_loop;
1251*e4b17023SJohn Marino clear_lim_data (stmt);
1252*e4b17023SJohn Marino
1253*e4b17023SJohn Marino if (!level)
1254*e4b17023SJohn Marino {
1255*e4b17023SJohn Marino gsi_next (&bsi);
1256*e4b17023SJohn Marino continue;
1257*e4b17023SJohn Marino }
1258*e4b17023SJohn Marino
1259*e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS))
1260*e4b17023SJohn Marino {
1261*e4b17023SJohn Marino fprintf (dump_file, "Moving PHI node\n");
1262*e4b17023SJohn Marino print_gimple_stmt (dump_file, stmt, 0, 0);
1263*e4b17023SJohn Marino fprintf (dump_file, "(cost %u) out of loop %d.\n\n",
1264*e4b17023SJohn Marino cost, level->num);
1265*e4b17023SJohn Marino }
1266*e4b17023SJohn Marino
1267*e4b17023SJohn Marino if (gimple_phi_num_args (stmt) == 1)
1268*e4b17023SJohn Marino {
1269*e4b17023SJohn Marino tree arg = PHI_ARG_DEF (stmt, 0);
1270*e4b17023SJohn Marino new_stmt = gimple_build_assign_with_ops (TREE_CODE (arg),
1271*e4b17023SJohn Marino gimple_phi_result (stmt),
1272*e4b17023SJohn Marino arg, NULL_TREE);
1273*e4b17023SJohn Marino SSA_NAME_DEF_STMT (gimple_phi_result (stmt)) = new_stmt;
1274*e4b17023SJohn Marino }
1275*e4b17023SJohn Marino else
1276*e4b17023SJohn Marino {
1277*e4b17023SJohn Marino basic_block dom = get_immediate_dominator (CDI_DOMINATORS, bb);
1278*e4b17023SJohn Marino gimple cond = gsi_stmt (gsi_last_bb (dom));
1279*e4b17023SJohn Marino tree arg0 = NULL_TREE, arg1 = NULL_TREE, t;
1280*e4b17023SJohn Marino /* Get the PHI arguments corresponding to the true and false
1281*e4b17023SJohn Marino edges of COND. */
1282*e4b17023SJohn Marino extract_true_false_args_from_phi (dom, stmt, &arg0, &arg1);
1283*e4b17023SJohn Marino gcc_assert (arg0 && arg1);
1284*e4b17023SJohn Marino t = build2 (gimple_cond_code (cond), boolean_type_node,
1285*e4b17023SJohn Marino gimple_cond_lhs (cond), gimple_cond_rhs (cond));
1286*e4b17023SJohn Marino new_stmt = gimple_build_assign_with_ops3 (COND_EXPR,
1287*e4b17023SJohn Marino gimple_phi_result (stmt),
1288*e4b17023SJohn Marino t, arg0, arg1);
1289*e4b17023SJohn Marino SSA_NAME_DEF_STMT (gimple_phi_result (stmt)) = new_stmt;
1290*e4b17023SJohn Marino *((unsigned int *)(dw_data->global_data)) |= TODO_cleanup_cfg;
1291*e4b17023SJohn Marino }
1292*e4b17023SJohn Marino gsi_insert_on_edge (loop_preheader_edge (level), new_stmt);
1293*e4b17023SJohn Marino remove_phi_node (&bsi, false);
1294*e4b17023SJohn Marino }
1295*e4b17023SJohn Marino
1296*e4b17023SJohn Marino for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); )
1297*e4b17023SJohn Marino {
1298*e4b17023SJohn Marino stmt = gsi_stmt (bsi);
1299*e4b17023SJohn Marino
1300*e4b17023SJohn Marino lim_data = get_lim_data (stmt);
1301*e4b17023SJohn Marino if (lim_data == NULL)
1302*e4b17023SJohn Marino {
1303*e4b17023SJohn Marino gsi_next (&bsi);
1304*e4b17023SJohn Marino continue;
1305*e4b17023SJohn Marino }
1306*e4b17023SJohn Marino
1307*e4b17023SJohn Marino cost = lim_data->cost;
1308*e4b17023SJohn Marino level = lim_data->tgt_loop;
1309*e4b17023SJohn Marino clear_lim_data (stmt);
1310*e4b17023SJohn Marino
1311*e4b17023SJohn Marino if (!level)
1312*e4b17023SJohn Marino {
1313*e4b17023SJohn Marino gsi_next (&bsi);
1314*e4b17023SJohn Marino continue;
1315*e4b17023SJohn Marino }
1316*e4b17023SJohn Marino
1317*e4b17023SJohn Marino /* We do not really want to move conditionals out of the loop; we just
1318*e4b17023SJohn Marino placed it here to force its operands to be moved if necessary. */
1319*e4b17023SJohn Marino if (gimple_code (stmt) == GIMPLE_COND)
1320*e4b17023SJohn Marino continue;
1321*e4b17023SJohn Marino
1322*e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS))
1323*e4b17023SJohn Marino {
1324*e4b17023SJohn Marino fprintf (dump_file, "Moving statement\n");
1325*e4b17023SJohn Marino print_gimple_stmt (dump_file, stmt, 0, 0);
1326*e4b17023SJohn Marino fprintf (dump_file, "(cost %u) out of loop %d.\n\n",
1327*e4b17023SJohn Marino cost, level->num);
1328*e4b17023SJohn Marino }
1329*e4b17023SJohn Marino
1330*e4b17023SJohn Marino mark_virtual_ops_for_renaming (stmt);
1331*e4b17023SJohn Marino gsi_insert_on_edge (loop_preheader_edge (level), stmt);
1332*e4b17023SJohn Marino gsi_remove (&bsi, false);
1333*e4b17023SJohn Marino }
1334*e4b17023SJohn Marino }
1335*e4b17023SJohn Marino
1336*e4b17023SJohn Marino /* Hoist the statements out of the loops prescribed by data stored in
1337*e4b17023SJohn Marino LIM_DATA structures associated with each statement.*/
1338*e4b17023SJohn Marino
1339*e4b17023SJohn Marino static unsigned int
move_computations(void)1340*e4b17023SJohn Marino move_computations (void)
1341*e4b17023SJohn Marino {
1342*e4b17023SJohn Marino struct dom_walk_data walk_data;
1343*e4b17023SJohn Marino unsigned int todo = 0;
1344*e4b17023SJohn Marino
1345*e4b17023SJohn Marino memset (&walk_data, 0, sizeof (struct dom_walk_data));
1346*e4b17023SJohn Marino walk_data.global_data = &todo;
1347*e4b17023SJohn Marino walk_data.dom_direction = CDI_DOMINATORS;
1348*e4b17023SJohn Marino walk_data.before_dom_children = move_computations_stmt;
1349*e4b17023SJohn Marino
1350*e4b17023SJohn Marino init_walk_dominator_tree (&walk_data);
1351*e4b17023SJohn Marino walk_dominator_tree (&walk_data, ENTRY_BLOCK_PTR);
1352*e4b17023SJohn Marino fini_walk_dominator_tree (&walk_data);
1353*e4b17023SJohn Marino
1354*e4b17023SJohn Marino gsi_commit_edge_inserts ();
1355*e4b17023SJohn Marino if (need_ssa_update_p (cfun))
1356*e4b17023SJohn Marino rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa);
1357*e4b17023SJohn Marino
1358*e4b17023SJohn Marino return todo;
1359*e4b17023SJohn Marino }
1360*e4b17023SJohn Marino
1361*e4b17023SJohn Marino /* Checks whether the statement defining variable *INDEX can be hoisted
1362*e4b17023SJohn Marino out of the loop passed in DATA. Callback for for_each_index. */
1363*e4b17023SJohn Marino
1364*e4b17023SJohn Marino static bool
may_move_till(tree ref,tree * index,void * data)1365*e4b17023SJohn Marino may_move_till (tree ref, tree *index, void *data)
1366*e4b17023SJohn Marino {
1367*e4b17023SJohn Marino struct loop *loop = (struct loop *) data, *max_loop;
1368*e4b17023SJohn Marino
1369*e4b17023SJohn Marino /* If REF is an array reference, check also that the step and the lower
1370*e4b17023SJohn Marino bound is invariant in LOOP. */
1371*e4b17023SJohn Marino if (TREE_CODE (ref) == ARRAY_REF)
1372*e4b17023SJohn Marino {
1373*e4b17023SJohn Marino tree step = TREE_OPERAND (ref, 3);
1374*e4b17023SJohn Marino tree lbound = TREE_OPERAND (ref, 2);
1375*e4b17023SJohn Marino
1376*e4b17023SJohn Marino max_loop = outermost_invariant_loop (step, loop);
1377*e4b17023SJohn Marino if (!max_loop)
1378*e4b17023SJohn Marino return false;
1379*e4b17023SJohn Marino
1380*e4b17023SJohn Marino max_loop = outermost_invariant_loop (lbound, loop);
1381*e4b17023SJohn Marino if (!max_loop)
1382*e4b17023SJohn Marino return false;
1383*e4b17023SJohn Marino }
1384*e4b17023SJohn Marino
1385*e4b17023SJohn Marino max_loop = outermost_invariant_loop (*index, loop);
1386*e4b17023SJohn Marino if (!max_loop)
1387*e4b17023SJohn Marino return false;
1388*e4b17023SJohn Marino
1389*e4b17023SJohn Marino return true;
1390*e4b17023SJohn Marino }
1391*e4b17023SJohn Marino
1392*e4b17023SJohn Marino /* If OP is SSA NAME, force the statement that defines it to be
1393*e4b17023SJohn Marino moved out of the LOOP. ORIG_LOOP is the loop in that EXPR is used. */
1394*e4b17023SJohn Marino
1395*e4b17023SJohn Marino static void
force_move_till_op(tree op,struct loop * orig_loop,struct loop * loop)1396*e4b17023SJohn Marino force_move_till_op (tree op, struct loop *orig_loop, struct loop *loop)
1397*e4b17023SJohn Marino {
1398*e4b17023SJohn Marino gimple stmt;
1399*e4b17023SJohn Marino
1400*e4b17023SJohn Marino if (!op
1401*e4b17023SJohn Marino || is_gimple_min_invariant (op))
1402*e4b17023SJohn Marino return;
1403*e4b17023SJohn Marino
1404*e4b17023SJohn Marino gcc_assert (TREE_CODE (op) == SSA_NAME);
1405*e4b17023SJohn Marino
1406*e4b17023SJohn Marino stmt = SSA_NAME_DEF_STMT (op);
1407*e4b17023SJohn Marino if (gimple_nop_p (stmt))
1408*e4b17023SJohn Marino return;
1409*e4b17023SJohn Marino
1410*e4b17023SJohn Marino set_level (stmt, orig_loop, loop);
1411*e4b17023SJohn Marino }
1412*e4b17023SJohn Marino
1413*e4b17023SJohn Marino /* Forces statement defining invariants in REF (and *INDEX) to be moved out of
1414*e4b17023SJohn Marino the LOOP. The reference REF is used in the loop ORIG_LOOP. Callback for
1415*e4b17023SJohn Marino for_each_index. */
1416*e4b17023SJohn Marino
1417*e4b17023SJohn Marino struct fmt_data
1418*e4b17023SJohn Marino {
1419*e4b17023SJohn Marino struct loop *loop;
1420*e4b17023SJohn Marino struct loop *orig_loop;
1421*e4b17023SJohn Marino };
1422*e4b17023SJohn Marino
1423*e4b17023SJohn Marino static bool
force_move_till(tree ref,tree * index,void * data)1424*e4b17023SJohn Marino force_move_till (tree ref, tree *index, void *data)
1425*e4b17023SJohn Marino {
1426*e4b17023SJohn Marino struct fmt_data *fmt_data = (struct fmt_data *) data;
1427*e4b17023SJohn Marino
1428*e4b17023SJohn Marino if (TREE_CODE (ref) == ARRAY_REF)
1429*e4b17023SJohn Marino {
1430*e4b17023SJohn Marino tree step = TREE_OPERAND (ref, 3);
1431*e4b17023SJohn Marino tree lbound = TREE_OPERAND (ref, 2);
1432*e4b17023SJohn Marino
1433*e4b17023SJohn Marino force_move_till_op (step, fmt_data->orig_loop, fmt_data->loop);
1434*e4b17023SJohn Marino force_move_till_op (lbound, fmt_data->orig_loop, fmt_data->loop);
1435*e4b17023SJohn Marino }
1436*e4b17023SJohn Marino
1437*e4b17023SJohn Marino force_move_till_op (*index, fmt_data->orig_loop, fmt_data->loop);
1438*e4b17023SJohn Marino
1439*e4b17023SJohn Marino return true;
1440*e4b17023SJohn Marino }
1441*e4b17023SJohn Marino
1442*e4b17023SJohn Marino /* A hash function for struct mem_ref object OBJ. */
1443*e4b17023SJohn Marino
1444*e4b17023SJohn Marino static hashval_t
memref_hash(const void * obj)1445*e4b17023SJohn Marino memref_hash (const void *obj)
1446*e4b17023SJohn Marino {
1447*e4b17023SJohn Marino const struct mem_ref *const mem = (const struct mem_ref *) obj;
1448*e4b17023SJohn Marino
1449*e4b17023SJohn Marino return mem->hash;
1450*e4b17023SJohn Marino }
1451*e4b17023SJohn Marino
1452*e4b17023SJohn Marino /* An equality function for struct mem_ref object OBJ1 with
1453*e4b17023SJohn Marino memory reference OBJ2. */
1454*e4b17023SJohn Marino
1455*e4b17023SJohn Marino static int
memref_eq(const void * obj1,const void * obj2)1456*e4b17023SJohn Marino memref_eq (const void *obj1, const void *obj2)
1457*e4b17023SJohn Marino {
1458*e4b17023SJohn Marino const struct mem_ref *const mem1 = (const struct mem_ref *) obj1;
1459*e4b17023SJohn Marino
1460*e4b17023SJohn Marino return operand_equal_p (mem1->mem, (const_tree) obj2, 0);
1461*e4b17023SJohn Marino }
1462*e4b17023SJohn Marino
1463*e4b17023SJohn Marino /* Releases list of memory reference locations ACCS. */
1464*e4b17023SJohn Marino
1465*e4b17023SJohn Marino static void
free_mem_ref_locs(mem_ref_locs_p accs)1466*e4b17023SJohn Marino free_mem_ref_locs (mem_ref_locs_p accs)
1467*e4b17023SJohn Marino {
1468*e4b17023SJohn Marino unsigned i;
1469*e4b17023SJohn Marino mem_ref_loc_p loc;
1470*e4b17023SJohn Marino
1471*e4b17023SJohn Marino if (!accs)
1472*e4b17023SJohn Marino return;
1473*e4b17023SJohn Marino
1474*e4b17023SJohn Marino FOR_EACH_VEC_ELT (mem_ref_loc_p, accs->locs, i, loc)
1475*e4b17023SJohn Marino free (loc);
1476*e4b17023SJohn Marino VEC_free (mem_ref_loc_p, heap, accs->locs);
1477*e4b17023SJohn Marino free (accs);
1478*e4b17023SJohn Marino }
1479*e4b17023SJohn Marino
1480*e4b17023SJohn Marino /* A function to free the mem_ref object OBJ. */
1481*e4b17023SJohn Marino
1482*e4b17023SJohn Marino static void
memref_free(struct mem_ref * mem)1483*e4b17023SJohn Marino memref_free (struct mem_ref *mem)
1484*e4b17023SJohn Marino {
1485*e4b17023SJohn Marino unsigned i;
1486*e4b17023SJohn Marino mem_ref_locs_p accs;
1487*e4b17023SJohn Marino
1488*e4b17023SJohn Marino BITMAP_FREE (mem->stored);
1489*e4b17023SJohn Marino BITMAP_FREE (mem->indep_loop);
1490*e4b17023SJohn Marino BITMAP_FREE (mem->dep_loop);
1491*e4b17023SJohn Marino BITMAP_FREE (mem->indep_ref);
1492*e4b17023SJohn Marino BITMAP_FREE (mem->dep_ref);
1493*e4b17023SJohn Marino
1494*e4b17023SJohn Marino FOR_EACH_VEC_ELT (mem_ref_locs_p, mem->accesses_in_loop, i, accs)
1495*e4b17023SJohn Marino free_mem_ref_locs (accs);
1496*e4b17023SJohn Marino VEC_free (mem_ref_locs_p, heap, mem->accesses_in_loop);
1497*e4b17023SJohn Marino
1498*e4b17023SJohn Marino free (mem);
1499*e4b17023SJohn Marino }
1500*e4b17023SJohn Marino
1501*e4b17023SJohn Marino /* Allocates and returns a memory reference description for MEM whose hash
1502*e4b17023SJohn Marino value is HASH and id is ID. */
1503*e4b17023SJohn Marino
1504*e4b17023SJohn Marino static mem_ref_p
mem_ref_alloc(tree mem,unsigned hash,unsigned id)1505*e4b17023SJohn Marino mem_ref_alloc (tree mem, unsigned hash, unsigned id)
1506*e4b17023SJohn Marino {
1507*e4b17023SJohn Marino mem_ref_p ref = XNEW (struct mem_ref);
1508*e4b17023SJohn Marino ref->mem = mem;
1509*e4b17023SJohn Marino ref->id = id;
1510*e4b17023SJohn Marino ref->hash = hash;
1511*e4b17023SJohn Marino ref->stored = BITMAP_ALLOC (NULL);
1512*e4b17023SJohn Marino ref->indep_loop = BITMAP_ALLOC (NULL);
1513*e4b17023SJohn Marino ref->dep_loop = BITMAP_ALLOC (NULL);
1514*e4b17023SJohn Marino ref->indep_ref = BITMAP_ALLOC (NULL);
1515*e4b17023SJohn Marino ref->dep_ref = BITMAP_ALLOC (NULL);
1516*e4b17023SJohn Marino ref->accesses_in_loop = NULL;
1517*e4b17023SJohn Marino
1518*e4b17023SJohn Marino return ref;
1519*e4b17023SJohn Marino }
1520*e4b17023SJohn Marino
1521*e4b17023SJohn Marino /* Allocates and returns the new list of locations. */
1522*e4b17023SJohn Marino
1523*e4b17023SJohn Marino static mem_ref_locs_p
mem_ref_locs_alloc(void)1524*e4b17023SJohn Marino mem_ref_locs_alloc (void)
1525*e4b17023SJohn Marino {
1526*e4b17023SJohn Marino mem_ref_locs_p accs = XNEW (struct mem_ref_locs);
1527*e4b17023SJohn Marino accs->locs = NULL;
1528*e4b17023SJohn Marino return accs;
1529*e4b17023SJohn Marino }
1530*e4b17023SJohn Marino
1531*e4b17023SJohn Marino /* Records memory reference location *LOC in LOOP to the memory reference
1532*e4b17023SJohn Marino description REF. The reference occurs in statement STMT. */
1533*e4b17023SJohn Marino
1534*e4b17023SJohn Marino static void
record_mem_ref_loc(mem_ref_p ref,struct loop * loop,gimple stmt,tree * loc)1535*e4b17023SJohn Marino record_mem_ref_loc (mem_ref_p ref, struct loop *loop, gimple stmt, tree *loc)
1536*e4b17023SJohn Marino {
1537*e4b17023SJohn Marino mem_ref_loc_p aref = XNEW (struct mem_ref_loc);
1538*e4b17023SJohn Marino mem_ref_locs_p accs;
1539*e4b17023SJohn Marino bitmap ril = VEC_index (bitmap, memory_accesses.refs_in_loop, loop->num);
1540*e4b17023SJohn Marino
1541*e4b17023SJohn Marino if (VEC_length (mem_ref_locs_p, ref->accesses_in_loop)
1542*e4b17023SJohn Marino <= (unsigned) loop->num)
1543*e4b17023SJohn Marino VEC_safe_grow_cleared (mem_ref_locs_p, heap, ref->accesses_in_loop,
1544*e4b17023SJohn Marino loop->num + 1);
1545*e4b17023SJohn Marino accs = VEC_index (mem_ref_locs_p, ref->accesses_in_loop, loop->num);
1546*e4b17023SJohn Marino if (!accs)
1547*e4b17023SJohn Marino {
1548*e4b17023SJohn Marino accs = mem_ref_locs_alloc ();
1549*e4b17023SJohn Marino VEC_replace (mem_ref_locs_p, ref->accesses_in_loop, loop->num, accs);
1550*e4b17023SJohn Marino }
1551*e4b17023SJohn Marino
1552*e4b17023SJohn Marino aref->stmt = stmt;
1553*e4b17023SJohn Marino aref->ref = loc;
1554*e4b17023SJohn Marino
1555*e4b17023SJohn Marino VEC_safe_push (mem_ref_loc_p, heap, accs->locs, aref);
1556*e4b17023SJohn Marino bitmap_set_bit (ril, ref->id);
1557*e4b17023SJohn Marino }
1558*e4b17023SJohn Marino
1559*e4b17023SJohn Marino /* Marks reference REF as stored in LOOP. */
1560*e4b17023SJohn Marino
1561*e4b17023SJohn Marino static void
mark_ref_stored(mem_ref_p ref,struct loop * loop)1562*e4b17023SJohn Marino mark_ref_stored (mem_ref_p ref, struct loop *loop)
1563*e4b17023SJohn Marino {
1564*e4b17023SJohn Marino for (;
1565*e4b17023SJohn Marino loop != current_loops->tree_root
1566*e4b17023SJohn Marino && !bitmap_bit_p (ref->stored, loop->num);
1567*e4b17023SJohn Marino loop = loop_outer (loop))
1568*e4b17023SJohn Marino bitmap_set_bit (ref->stored, loop->num);
1569*e4b17023SJohn Marino }
1570*e4b17023SJohn Marino
1571*e4b17023SJohn Marino /* Gathers memory references in statement STMT in LOOP, storing the
1572*e4b17023SJohn Marino information about them in the memory_accesses structure. Marks
1573*e4b17023SJohn Marino the vops accessed through unrecognized statements there as
1574*e4b17023SJohn Marino well. */
1575*e4b17023SJohn Marino
1576*e4b17023SJohn Marino static void
gather_mem_refs_stmt(struct loop * loop,gimple stmt)1577*e4b17023SJohn Marino gather_mem_refs_stmt (struct loop *loop, gimple stmt)
1578*e4b17023SJohn Marino {
1579*e4b17023SJohn Marino tree *mem = NULL;
1580*e4b17023SJohn Marino hashval_t hash;
1581*e4b17023SJohn Marino PTR *slot;
1582*e4b17023SJohn Marino mem_ref_p ref;
1583*e4b17023SJohn Marino bool is_stored;
1584*e4b17023SJohn Marino unsigned id;
1585*e4b17023SJohn Marino
1586*e4b17023SJohn Marino if (!gimple_vuse (stmt))
1587*e4b17023SJohn Marino return;
1588*e4b17023SJohn Marino
1589*e4b17023SJohn Marino mem = simple_mem_ref_in_stmt (stmt, &is_stored);
1590*e4b17023SJohn Marino if (!mem)
1591*e4b17023SJohn Marino {
1592*e4b17023SJohn Marino id = VEC_length (mem_ref_p, memory_accesses.refs_list);
1593*e4b17023SJohn Marino ref = mem_ref_alloc (error_mark_node, 0, id);
1594*e4b17023SJohn Marino VEC_safe_push (mem_ref_p, heap, memory_accesses.refs_list, ref);
1595*e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS))
1596*e4b17023SJohn Marino {
1597*e4b17023SJohn Marino fprintf (dump_file, "Unanalyzed memory reference %u: ", id);
1598*e4b17023SJohn Marino print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1599*e4b17023SJohn Marino }
1600*e4b17023SJohn Marino if (gimple_vdef (stmt))
1601*e4b17023SJohn Marino mark_ref_stored (ref, loop);
1602*e4b17023SJohn Marino record_mem_ref_loc (ref, loop, stmt, mem);
1603*e4b17023SJohn Marino return;
1604*e4b17023SJohn Marino }
1605*e4b17023SJohn Marino
1606*e4b17023SJohn Marino hash = iterative_hash_expr (*mem, 0);
1607*e4b17023SJohn Marino slot = htab_find_slot_with_hash (memory_accesses.refs, *mem, hash, INSERT);
1608*e4b17023SJohn Marino
1609*e4b17023SJohn Marino if (*slot)
1610*e4b17023SJohn Marino {
1611*e4b17023SJohn Marino ref = (mem_ref_p) *slot;
1612*e4b17023SJohn Marino id = ref->id;
1613*e4b17023SJohn Marino }
1614*e4b17023SJohn Marino else
1615*e4b17023SJohn Marino {
1616*e4b17023SJohn Marino id = VEC_length (mem_ref_p, memory_accesses.refs_list);
1617*e4b17023SJohn Marino ref = mem_ref_alloc (*mem, hash, id);
1618*e4b17023SJohn Marino VEC_safe_push (mem_ref_p, heap, memory_accesses.refs_list, ref);
1619*e4b17023SJohn Marino *slot = ref;
1620*e4b17023SJohn Marino
1621*e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS))
1622*e4b17023SJohn Marino {
1623*e4b17023SJohn Marino fprintf (dump_file, "Memory reference %u: ", id);
1624*e4b17023SJohn Marino print_generic_expr (dump_file, ref->mem, TDF_SLIM);
1625*e4b17023SJohn Marino fprintf (dump_file, "\n");
1626*e4b17023SJohn Marino }
1627*e4b17023SJohn Marino }
1628*e4b17023SJohn Marino
1629*e4b17023SJohn Marino if (is_stored)
1630*e4b17023SJohn Marino mark_ref_stored (ref, loop);
1631*e4b17023SJohn Marino
1632*e4b17023SJohn Marino record_mem_ref_loc (ref, loop, stmt, mem);
1633*e4b17023SJohn Marino return;
1634*e4b17023SJohn Marino }
1635*e4b17023SJohn Marino
1636*e4b17023SJohn Marino /* Gathers memory references in loops. */
1637*e4b17023SJohn Marino
1638*e4b17023SJohn Marino static void
gather_mem_refs_in_loops(void)1639*e4b17023SJohn Marino gather_mem_refs_in_loops (void)
1640*e4b17023SJohn Marino {
1641*e4b17023SJohn Marino gimple_stmt_iterator bsi;
1642*e4b17023SJohn Marino basic_block bb;
1643*e4b17023SJohn Marino struct loop *loop;
1644*e4b17023SJohn Marino loop_iterator li;
1645*e4b17023SJohn Marino bitmap lrefs, alrefs, alrefso;
1646*e4b17023SJohn Marino
1647*e4b17023SJohn Marino FOR_EACH_BB (bb)
1648*e4b17023SJohn Marino {
1649*e4b17023SJohn Marino loop = bb->loop_father;
1650*e4b17023SJohn Marino if (loop == current_loops->tree_root)
1651*e4b17023SJohn Marino continue;
1652*e4b17023SJohn Marino
1653*e4b17023SJohn Marino for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi))
1654*e4b17023SJohn Marino gather_mem_refs_stmt (loop, gsi_stmt (bsi));
1655*e4b17023SJohn Marino }
1656*e4b17023SJohn Marino
1657*e4b17023SJohn Marino /* Propagate the information about accessed memory references up
1658*e4b17023SJohn Marino the loop hierarchy. */
1659*e4b17023SJohn Marino FOR_EACH_LOOP (li, loop, LI_FROM_INNERMOST)
1660*e4b17023SJohn Marino {
1661*e4b17023SJohn Marino lrefs = VEC_index (bitmap, memory_accesses.refs_in_loop, loop->num);
1662*e4b17023SJohn Marino alrefs = VEC_index (bitmap, memory_accesses.all_refs_in_loop, loop->num);
1663*e4b17023SJohn Marino bitmap_ior_into (alrefs, lrefs);
1664*e4b17023SJohn Marino
1665*e4b17023SJohn Marino if (loop_outer (loop) == current_loops->tree_root)
1666*e4b17023SJohn Marino continue;
1667*e4b17023SJohn Marino
1668*e4b17023SJohn Marino alrefso = VEC_index (bitmap, memory_accesses.all_refs_in_loop,
1669*e4b17023SJohn Marino loop_outer (loop)->num);
1670*e4b17023SJohn Marino bitmap_ior_into (alrefso, alrefs);
1671*e4b17023SJohn Marino }
1672*e4b17023SJohn Marino }
1673*e4b17023SJohn Marino
1674*e4b17023SJohn Marino /* Create a mapping from virtual operands to references that touch them
1675*e4b17023SJohn Marino in LOOP. */
1676*e4b17023SJohn Marino
1677*e4b17023SJohn Marino static void
create_vop_ref_mapping_loop(struct loop * loop)1678*e4b17023SJohn Marino create_vop_ref_mapping_loop (struct loop *loop)
1679*e4b17023SJohn Marino {
1680*e4b17023SJohn Marino bitmap refs = VEC_index (bitmap, memory_accesses.refs_in_loop, loop->num);
1681*e4b17023SJohn Marino struct loop *sloop;
1682*e4b17023SJohn Marino bitmap_iterator bi;
1683*e4b17023SJohn Marino unsigned i;
1684*e4b17023SJohn Marino mem_ref_p ref;
1685*e4b17023SJohn Marino
1686*e4b17023SJohn Marino EXECUTE_IF_SET_IN_BITMAP (refs, 0, i, bi)
1687*e4b17023SJohn Marino {
1688*e4b17023SJohn Marino ref = VEC_index (mem_ref_p, memory_accesses.refs_list, i);
1689*e4b17023SJohn Marino for (sloop = loop; sloop != current_loops->tree_root;
1690*e4b17023SJohn Marino sloop = loop_outer (sloop))
1691*e4b17023SJohn Marino if (bitmap_bit_p (ref->stored, loop->num))
1692*e4b17023SJohn Marino {
1693*e4b17023SJohn Marino bitmap refs_stored
1694*e4b17023SJohn Marino = VEC_index (bitmap, memory_accesses.all_refs_stored_in_loop,
1695*e4b17023SJohn Marino sloop->num);
1696*e4b17023SJohn Marino bitmap_set_bit (refs_stored, ref->id);
1697*e4b17023SJohn Marino }
1698*e4b17023SJohn Marino }
1699*e4b17023SJohn Marino }
1700*e4b17023SJohn Marino
1701*e4b17023SJohn Marino /* For each non-clobbered virtual operand and each loop, record the memory
1702*e4b17023SJohn Marino references in this loop that touch the operand. */
1703*e4b17023SJohn Marino
1704*e4b17023SJohn Marino static void
create_vop_ref_mapping(void)1705*e4b17023SJohn Marino create_vop_ref_mapping (void)
1706*e4b17023SJohn Marino {
1707*e4b17023SJohn Marino loop_iterator li;
1708*e4b17023SJohn Marino struct loop *loop;
1709*e4b17023SJohn Marino
1710*e4b17023SJohn Marino FOR_EACH_LOOP (li, loop, 0)
1711*e4b17023SJohn Marino {
1712*e4b17023SJohn Marino create_vop_ref_mapping_loop (loop);
1713*e4b17023SJohn Marino }
1714*e4b17023SJohn Marino }
1715*e4b17023SJohn Marino
1716*e4b17023SJohn Marino /* Gathers information about memory accesses in the loops. */
1717*e4b17023SJohn Marino
1718*e4b17023SJohn Marino static void
analyze_memory_references(void)1719*e4b17023SJohn Marino analyze_memory_references (void)
1720*e4b17023SJohn Marino {
1721*e4b17023SJohn Marino unsigned i;
1722*e4b17023SJohn Marino bitmap empty;
1723*e4b17023SJohn Marino
1724*e4b17023SJohn Marino memory_accesses.refs = htab_create (100, memref_hash, memref_eq, NULL);
1725*e4b17023SJohn Marino memory_accesses.refs_list = NULL;
1726*e4b17023SJohn Marino memory_accesses.refs_in_loop = VEC_alloc (bitmap, heap,
1727*e4b17023SJohn Marino number_of_loops ());
1728*e4b17023SJohn Marino memory_accesses.all_refs_in_loop = VEC_alloc (bitmap, heap,
1729*e4b17023SJohn Marino number_of_loops ());
1730*e4b17023SJohn Marino memory_accesses.all_refs_stored_in_loop = VEC_alloc (bitmap, heap,
1731*e4b17023SJohn Marino number_of_loops ());
1732*e4b17023SJohn Marino
1733*e4b17023SJohn Marino for (i = 0; i < number_of_loops (); i++)
1734*e4b17023SJohn Marino {
1735*e4b17023SJohn Marino empty = BITMAP_ALLOC (NULL);
1736*e4b17023SJohn Marino VEC_quick_push (bitmap, memory_accesses.refs_in_loop, empty);
1737*e4b17023SJohn Marino empty = BITMAP_ALLOC (NULL);
1738*e4b17023SJohn Marino VEC_quick_push (bitmap, memory_accesses.all_refs_in_loop, empty);
1739*e4b17023SJohn Marino empty = BITMAP_ALLOC (NULL);
1740*e4b17023SJohn Marino VEC_quick_push (bitmap, memory_accesses.all_refs_stored_in_loop, empty);
1741*e4b17023SJohn Marino }
1742*e4b17023SJohn Marino
1743*e4b17023SJohn Marino memory_accesses.ttae_cache = NULL;
1744*e4b17023SJohn Marino
1745*e4b17023SJohn Marino gather_mem_refs_in_loops ();
1746*e4b17023SJohn Marino create_vop_ref_mapping ();
1747*e4b17023SJohn Marino }
1748*e4b17023SJohn Marino
1749*e4b17023SJohn Marino /* Returns true if MEM1 and MEM2 may alias. TTAE_CACHE is used as a cache in
1750*e4b17023SJohn Marino tree_to_aff_combination_expand. */
1751*e4b17023SJohn Marino
1752*e4b17023SJohn Marino static bool
mem_refs_may_alias_p(tree mem1,tree mem2,struct pointer_map_t ** ttae_cache)1753*e4b17023SJohn Marino mem_refs_may_alias_p (tree mem1, tree mem2, struct pointer_map_t **ttae_cache)
1754*e4b17023SJohn Marino {
1755*e4b17023SJohn Marino /* Perform BASE + OFFSET analysis -- if MEM1 and MEM2 are based on the same
1756*e4b17023SJohn Marino object and their offset differ in such a way that the locations cannot
1757*e4b17023SJohn Marino overlap, then they cannot alias. */
1758*e4b17023SJohn Marino double_int size1, size2;
1759*e4b17023SJohn Marino aff_tree off1, off2;
1760*e4b17023SJohn Marino
1761*e4b17023SJohn Marino /* Perform basic offset and type-based disambiguation. */
1762*e4b17023SJohn Marino if (!refs_may_alias_p (mem1, mem2))
1763*e4b17023SJohn Marino return false;
1764*e4b17023SJohn Marino
1765*e4b17023SJohn Marino /* The expansion of addresses may be a bit expensive, thus we only do
1766*e4b17023SJohn Marino the check at -O2 and higher optimization levels. */
1767*e4b17023SJohn Marino if (optimize < 2)
1768*e4b17023SJohn Marino return true;
1769*e4b17023SJohn Marino
1770*e4b17023SJohn Marino get_inner_reference_aff (mem1, &off1, &size1);
1771*e4b17023SJohn Marino get_inner_reference_aff (mem2, &off2, &size2);
1772*e4b17023SJohn Marino aff_combination_expand (&off1, ttae_cache);
1773*e4b17023SJohn Marino aff_combination_expand (&off2, ttae_cache);
1774*e4b17023SJohn Marino aff_combination_scale (&off1, double_int_minus_one);
1775*e4b17023SJohn Marino aff_combination_add (&off2, &off1);
1776*e4b17023SJohn Marino
1777*e4b17023SJohn Marino if (aff_comb_cannot_overlap_p (&off2, size1, size2))
1778*e4b17023SJohn Marino return false;
1779*e4b17023SJohn Marino
1780*e4b17023SJohn Marino return true;
1781*e4b17023SJohn Marino }
1782*e4b17023SJohn Marino
1783*e4b17023SJohn Marino /* Rewrites location LOC by TMP_VAR. */
1784*e4b17023SJohn Marino
1785*e4b17023SJohn Marino static void
rewrite_mem_ref_loc(mem_ref_loc_p loc,tree tmp_var)1786*e4b17023SJohn Marino rewrite_mem_ref_loc (mem_ref_loc_p loc, tree tmp_var)
1787*e4b17023SJohn Marino {
1788*e4b17023SJohn Marino mark_virtual_ops_for_renaming (loc->stmt);
1789*e4b17023SJohn Marino *loc->ref = tmp_var;
1790*e4b17023SJohn Marino update_stmt (loc->stmt);
1791*e4b17023SJohn Marino }
1792*e4b17023SJohn Marino
1793*e4b17023SJohn Marino /* Adds all locations of REF in LOOP and its subloops to LOCS. */
1794*e4b17023SJohn Marino
1795*e4b17023SJohn Marino static void
get_all_locs_in_loop(struct loop * loop,mem_ref_p ref,VEC (mem_ref_loc_p,heap)** locs)1796*e4b17023SJohn Marino get_all_locs_in_loop (struct loop *loop, mem_ref_p ref,
1797*e4b17023SJohn Marino VEC (mem_ref_loc_p, heap) **locs)
1798*e4b17023SJohn Marino {
1799*e4b17023SJohn Marino mem_ref_locs_p accs;
1800*e4b17023SJohn Marino unsigned i;
1801*e4b17023SJohn Marino mem_ref_loc_p loc;
1802*e4b17023SJohn Marino bitmap refs = VEC_index (bitmap, memory_accesses.all_refs_in_loop,
1803*e4b17023SJohn Marino loop->num);
1804*e4b17023SJohn Marino struct loop *subloop;
1805*e4b17023SJohn Marino
1806*e4b17023SJohn Marino if (!bitmap_bit_p (refs, ref->id))
1807*e4b17023SJohn Marino return;
1808*e4b17023SJohn Marino
1809*e4b17023SJohn Marino if (VEC_length (mem_ref_locs_p, ref->accesses_in_loop)
1810*e4b17023SJohn Marino > (unsigned) loop->num)
1811*e4b17023SJohn Marino {
1812*e4b17023SJohn Marino accs = VEC_index (mem_ref_locs_p, ref->accesses_in_loop, loop->num);
1813*e4b17023SJohn Marino if (accs)
1814*e4b17023SJohn Marino {
1815*e4b17023SJohn Marino FOR_EACH_VEC_ELT (mem_ref_loc_p, accs->locs, i, loc)
1816*e4b17023SJohn Marino VEC_safe_push (mem_ref_loc_p, heap, *locs, loc);
1817*e4b17023SJohn Marino }
1818*e4b17023SJohn Marino }
1819*e4b17023SJohn Marino
1820*e4b17023SJohn Marino for (subloop = loop->inner; subloop != NULL; subloop = subloop->next)
1821*e4b17023SJohn Marino get_all_locs_in_loop (subloop, ref, locs);
1822*e4b17023SJohn Marino }
1823*e4b17023SJohn Marino
1824*e4b17023SJohn Marino /* Rewrites all references to REF in LOOP by variable TMP_VAR. */
1825*e4b17023SJohn Marino
1826*e4b17023SJohn Marino static void
rewrite_mem_refs(struct loop * loop,mem_ref_p ref,tree tmp_var)1827*e4b17023SJohn Marino rewrite_mem_refs (struct loop *loop, mem_ref_p ref, tree tmp_var)
1828*e4b17023SJohn Marino {
1829*e4b17023SJohn Marino unsigned i;
1830*e4b17023SJohn Marino mem_ref_loc_p loc;
1831*e4b17023SJohn Marino VEC (mem_ref_loc_p, heap) *locs = NULL;
1832*e4b17023SJohn Marino
1833*e4b17023SJohn Marino get_all_locs_in_loop (loop, ref, &locs);
1834*e4b17023SJohn Marino FOR_EACH_VEC_ELT (mem_ref_loc_p, locs, i, loc)
1835*e4b17023SJohn Marino rewrite_mem_ref_loc (loc, tmp_var);
1836*e4b17023SJohn Marino VEC_free (mem_ref_loc_p, heap, locs);
1837*e4b17023SJohn Marino }
1838*e4b17023SJohn Marino
1839*e4b17023SJohn Marino /* The name and the length of the currently generated variable
1840*e4b17023SJohn Marino for lsm. */
1841*e4b17023SJohn Marino #define MAX_LSM_NAME_LENGTH 40
1842*e4b17023SJohn Marino static char lsm_tmp_name[MAX_LSM_NAME_LENGTH + 1];
1843*e4b17023SJohn Marino static int lsm_tmp_name_length;
1844*e4b17023SJohn Marino
1845*e4b17023SJohn Marino /* Adds S to lsm_tmp_name. */
1846*e4b17023SJohn Marino
1847*e4b17023SJohn Marino static void
lsm_tmp_name_add(const char * s)1848*e4b17023SJohn Marino lsm_tmp_name_add (const char *s)
1849*e4b17023SJohn Marino {
1850*e4b17023SJohn Marino int l = strlen (s) + lsm_tmp_name_length;
1851*e4b17023SJohn Marino if (l > MAX_LSM_NAME_LENGTH)
1852*e4b17023SJohn Marino return;
1853*e4b17023SJohn Marino
1854*e4b17023SJohn Marino strcpy (lsm_tmp_name + lsm_tmp_name_length, s);
1855*e4b17023SJohn Marino lsm_tmp_name_length = l;
1856*e4b17023SJohn Marino }
1857*e4b17023SJohn Marino
1858*e4b17023SJohn Marino /* Stores the name for temporary variable that replaces REF to
1859*e4b17023SJohn Marino lsm_tmp_name. */
1860*e4b17023SJohn Marino
1861*e4b17023SJohn Marino static void
gen_lsm_tmp_name(tree ref)1862*e4b17023SJohn Marino gen_lsm_tmp_name (tree ref)
1863*e4b17023SJohn Marino {
1864*e4b17023SJohn Marino const char *name;
1865*e4b17023SJohn Marino
1866*e4b17023SJohn Marino switch (TREE_CODE (ref))
1867*e4b17023SJohn Marino {
1868*e4b17023SJohn Marino case MEM_REF:
1869*e4b17023SJohn Marino case TARGET_MEM_REF:
1870*e4b17023SJohn Marino gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
1871*e4b17023SJohn Marino lsm_tmp_name_add ("_");
1872*e4b17023SJohn Marino break;
1873*e4b17023SJohn Marino
1874*e4b17023SJohn Marino case ADDR_EXPR:
1875*e4b17023SJohn Marino gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
1876*e4b17023SJohn Marino break;
1877*e4b17023SJohn Marino
1878*e4b17023SJohn Marino case BIT_FIELD_REF:
1879*e4b17023SJohn Marino case VIEW_CONVERT_EXPR:
1880*e4b17023SJohn Marino case ARRAY_RANGE_REF:
1881*e4b17023SJohn Marino gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
1882*e4b17023SJohn Marino break;
1883*e4b17023SJohn Marino
1884*e4b17023SJohn Marino case REALPART_EXPR:
1885*e4b17023SJohn Marino gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
1886*e4b17023SJohn Marino lsm_tmp_name_add ("_RE");
1887*e4b17023SJohn Marino break;
1888*e4b17023SJohn Marino
1889*e4b17023SJohn Marino case IMAGPART_EXPR:
1890*e4b17023SJohn Marino gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
1891*e4b17023SJohn Marino lsm_tmp_name_add ("_IM");
1892*e4b17023SJohn Marino break;
1893*e4b17023SJohn Marino
1894*e4b17023SJohn Marino case COMPONENT_REF:
1895*e4b17023SJohn Marino gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
1896*e4b17023SJohn Marino lsm_tmp_name_add ("_");
1897*e4b17023SJohn Marino name = get_name (TREE_OPERAND (ref, 1));
1898*e4b17023SJohn Marino if (!name)
1899*e4b17023SJohn Marino name = "F";
1900*e4b17023SJohn Marino lsm_tmp_name_add (name);
1901*e4b17023SJohn Marino break;
1902*e4b17023SJohn Marino
1903*e4b17023SJohn Marino case ARRAY_REF:
1904*e4b17023SJohn Marino gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
1905*e4b17023SJohn Marino lsm_tmp_name_add ("_I");
1906*e4b17023SJohn Marino break;
1907*e4b17023SJohn Marino
1908*e4b17023SJohn Marino case SSA_NAME:
1909*e4b17023SJohn Marino ref = SSA_NAME_VAR (ref);
1910*e4b17023SJohn Marino /* Fallthru. */
1911*e4b17023SJohn Marino
1912*e4b17023SJohn Marino case VAR_DECL:
1913*e4b17023SJohn Marino case PARM_DECL:
1914*e4b17023SJohn Marino name = get_name (ref);
1915*e4b17023SJohn Marino if (!name)
1916*e4b17023SJohn Marino name = "D";
1917*e4b17023SJohn Marino lsm_tmp_name_add (name);
1918*e4b17023SJohn Marino break;
1919*e4b17023SJohn Marino
1920*e4b17023SJohn Marino case STRING_CST:
1921*e4b17023SJohn Marino lsm_tmp_name_add ("S");
1922*e4b17023SJohn Marino break;
1923*e4b17023SJohn Marino
1924*e4b17023SJohn Marino case RESULT_DECL:
1925*e4b17023SJohn Marino lsm_tmp_name_add ("R");
1926*e4b17023SJohn Marino break;
1927*e4b17023SJohn Marino
1928*e4b17023SJohn Marino case INTEGER_CST:
1929*e4b17023SJohn Marino /* Nothing. */
1930*e4b17023SJohn Marino break;
1931*e4b17023SJohn Marino
1932*e4b17023SJohn Marino default:
1933*e4b17023SJohn Marino gcc_unreachable ();
1934*e4b17023SJohn Marino }
1935*e4b17023SJohn Marino }
1936*e4b17023SJohn Marino
1937*e4b17023SJohn Marino /* Determines name for temporary variable that replaces REF.
1938*e4b17023SJohn Marino The name is accumulated into the lsm_tmp_name variable.
1939*e4b17023SJohn Marino N is added to the name of the temporary. */
1940*e4b17023SJohn Marino
1941*e4b17023SJohn Marino char *
get_lsm_tmp_name(tree ref,unsigned n)1942*e4b17023SJohn Marino get_lsm_tmp_name (tree ref, unsigned n)
1943*e4b17023SJohn Marino {
1944*e4b17023SJohn Marino char ns[2];
1945*e4b17023SJohn Marino
1946*e4b17023SJohn Marino lsm_tmp_name_length = 0;
1947*e4b17023SJohn Marino gen_lsm_tmp_name (ref);
1948*e4b17023SJohn Marino lsm_tmp_name_add ("_lsm");
1949*e4b17023SJohn Marino if (n < 10)
1950*e4b17023SJohn Marino {
1951*e4b17023SJohn Marino ns[0] = '0' + n;
1952*e4b17023SJohn Marino ns[1] = 0;
1953*e4b17023SJohn Marino lsm_tmp_name_add (ns);
1954*e4b17023SJohn Marino }
1955*e4b17023SJohn Marino return lsm_tmp_name;
1956*e4b17023SJohn Marino }
1957*e4b17023SJohn Marino
1958*e4b17023SJohn Marino struct prev_flag_edges {
1959*e4b17023SJohn Marino /* Edge to insert new flag comparison code. */
1960*e4b17023SJohn Marino edge append_cond_position;
1961*e4b17023SJohn Marino
1962*e4b17023SJohn Marino /* Edge for fall through from previous flag comparison. */
1963*e4b17023SJohn Marino edge last_cond_fallthru;
1964*e4b17023SJohn Marino };
1965*e4b17023SJohn Marino
1966*e4b17023SJohn Marino /* Helper function for execute_sm. Emit code to store TMP_VAR into
1967*e4b17023SJohn Marino MEM along edge EX.
1968*e4b17023SJohn Marino
1969*e4b17023SJohn Marino The store is only done if MEM has changed. We do this so no
1970*e4b17023SJohn Marino changes to MEM occur on code paths that did not originally store
1971*e4b17023SJohn Marino into it.
1972*e4b17023SJohn Marino
1973*e4b17023SJohn Marino The common case for execute_sm will transform:
1974*e4b17023SJohn Marino
1975*e4b17023SJohn Marino for (...) {
1976*e4b17023SJohn Marino if (foo)
1977*e4b17023SJohn Marino stuff;
1978*e4b17023SJohn Marino else
1979*e4b17023SJohn Marino MEM = TMP_VAR;
1980*e4b17023SJohn Marino }
1981*e4b17023SJohn Marino
1982*e4b17023SJohn Marino into:
1983*e4b17023SJohn Marino
1984*e4b17023SJohn Marino lsm = MEM;
1985*e4b17023SJohn Marino for (...) {
1986*e4b17023SJohn Marino if (foo)
1987*e4b17023SJohn Marino stuff;
1988*e4b17023SJohn Marino else
1989*e4b17023SJohn Marino lsm = TMP_VAR;
1990*e4b17023SJohn Marino }
1991*e4b17023SJohn Marino MEM = lsm;
1992*e4b17023SJohn Marino
1993*e4b17023SJohn Marino This function will generate:
1994*e4b17023SJohn Marino
1995*e4b17023SJohn Marino lsm = MEM;
1996*e4b17023SJohn Marino
1997*e4b17023SJohn Marino lsm_flag = false;
1998*e4b17023SJohn Marino ...
1999*e4b17023SJohn Marino for (...) {
2000*e4b17023SJohn Marino if (foo)
2001*e4b17023SJohn Marino stuff;
2002*e4b17023SJohn Marino else {
2003*e4b17023SJohn Marino lsm = TMP_VAR;
2004*e4b17023SJohn Marino lsm_flag = true;
2005*e4b17023SJohn Marino }
2006*e4b17023SJohn Marino }
2007*e4b17023SJohn Marino if (lsm_flag) <--
2008*e4b17023SJohn Marino MEM = lsm; <--
2009*e4b17023SJohn Marino */
2010*e4b17023SJohn Marino
2011*e4b17023SJohn Marino static void
execute_sm_if_changed(edge ex,tree mem,tree tmp_var,tree flag)2012*e4b17023SJohn Marino execute_sm_if_changed (edge ex, tree mem, tree tmp_var, tree flag)
2013*e4b17023SJohn Marino {
2014*e4b17023SJohn Marino basic_block new_bb, then_bb, old_dest;
2015*e4b17023SJohn Marino bool loop_has_only_one_exit;
2016*e4b17023SJohn Marino edge then_old_edge, orig_ex = ex;
2017*e4b17023SJohn Marino gimple_stmt_iterator gsi;
2018*e4b17023SJohn Marino gimple stmt;
2019*e4b17023SJohn Marino struct prev_flag_edges *prev_edges = (struct prev_flag_edges *) ex->aux;
2020*e4b17023SJohn Marino
2021*e4b17023SJohn Marino /* ?? Insert store after previous store if applicable. See note
2022*e4b17023SJohn Marino below. */
2023*e4b17023SJohn Marino if (prev_edges)
2024*e4b17023SJohn Marino ex = prev_edges->append_cond_position;
2025*e4b17023SJohn Marino
2026*e4b17023SJohn Marino loop_has_only_one_exit = single_pred_p (ex->dest);
2027*e4b17023SJohn Marino
2028*e4b17023SJohn Marino if (loop_has_only_one_exit)
2029*e4b17023SJohn Marino ex = split_block_after_labels (ex->dest);
2030*e4b17023SJohn Marino
2031*e4b17023SJohn Marino old_dest = ex->dest;
2032*e4b17023SJohn Marino new_bb = split_edge (ex);
2033*e4b17023SJohn Marino then_bb = create_empty_bb (new_bb);
2034*e4b17023SJohn Marino if (current_loops && new_bb->loop_father)
2035*e4b17023SJohn Marino add_bb_to_loop (then_bb, new_bb->loop_father);
2036*e4b17023SJohn Marino
2037*e4b17023SJohn Marino gsi = gsi_start_bb (new_bb);
2038*e4b17023SJohn Marino stmt = gimple_build_cond (NE_EXPR, flag, boolean_false_node,
2039*e4b17023SJohn Marino NULL_TREE, NULL_TREE);
2040*e4b17023SJohn Marino gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
2041*e4b17023SJohn Marino
2042*e4b17023SJohn Marino gsi = gsi_start_bb (then_bb);
2043*e4b17023SJohn Marino /* Insert actual store. */
2044*e4b17023SJohn Marino stmt = gimple_build_assign (unshare_expr (mem), tmp_var);
2045*e4b17023SJohn Marino gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
2046*e4b17023SJohn Marino
2047*e4b17023SJohn Marino make_edge (new_bb, then_bb, EDGE_TRUE_VALUE);
2048*e4b17023SJohn Marino make_edge (new_bb, old_dest, EDGE_FALSE_VALUE);
2049*e4b17023SJohn Marino then_old_edge = make_edge (then_bb, old_dest, EDGE_FALLTHRU);
2050*e4b17023SJohn Marino
2051*e4b17023SJohn Marino set_immediate_dominator (CDI_DOMINATORS, then_bb, new_bb);
2052*e4b17023SJohn Marino
2053*e4b17023SJohn Marino if (prev_edges)
2054*e4b17023SJohn Marino {
2055*e4b17023SJohn Marino basic_block prevbb = prev_edges->last_cond_fallthru->src;
2056*e4b17023SJohn Marino redirect_edge_succ (prev_edges->last_cond_fallthru, new_bb);
2057*e4b17023SJohn Marino set_immediate_dominator (CDI_DOMINATORS, new_bb, prevbb);
2058*e4b17023SJohn Marino set_immediate_dominator (CDI_DOMINATORS, old_dest,
2059*e4b17023SJohn Marino recompute_dominator (CDI_DOMINATORS, old_dest));
2060*e4b17023SJohn Marino }
2061*e4b17023SJohn Marino
2062*e4b17023SJohn Marino /* ?? Because stores may alias, they must happen in the exact
2063*e4b17023SJohn Marino sequence they originally happened. Save the position right after
2064*e4b17023SJohn Marino the (_lsm) store we just created so we can continue appending after
2065*e4b17023SJohn Marino it and maintain the original order. */
2066*e4b17023SJohn Marino {
2067*e4b17023SJohn Marino struct prev_flag_edges *p;
2068*e4b17023SJohn Marino
2069*e4b17023SJohn Marino if (orig_ex->aux)
2070*e4b17023SJohn Marino orig_ex->aux = NULL;
2071*e4b17023SJohn Marino alloc_aux_for_edge (orig_ex, sizeof (struct prev_flag_edges));
2072*e4b17023SJohn Marino p = (struct prev_flag_edges *) orig_ex->aux;
2073*e4b17023SJohn Marino p->append_cond_position = then_old_edge;
2074*e4b17023SJohn Marino p->last_cond_fallthru = find_edge (new_bb, old_dest);
2075*e4b17023SJohn Marino orig_ex->aux = (void *) p;
2076*e4b17023SJohn Marino }
2077*e4b17023SJohn Marino
2078*e4b17023SJohn Marino if (!loop_has_only_one_exit)
2079*e4b17023SJohn Marino for (gsi = gsi_start_phis (old_dest); !gsi_end_p (gsi); gsi_next (&gsi))
2080*e4b17023SJohn Marino {
2081*e4b17023SJohn Marino gimple phi = gsi_stmt (gsi);
2082*e4b17023SJohn Marino unsigned i;
2083*e4b17023SJohn Marino
2084*e4b17023SJohn Marino for (i = 0; i < gimple_phi_num_args (phi); i++)
2085*e4b17023SJohn Marino if (gimple_phi_arg_edge (phi, i)->src == new_bb)
2086*e4b17023SJohn Marino {
2087*e4b17023SJohn Marino tree arg = gimple_phi_arg_def (phi, i);
2088*e4b17023SJohn Marino add_phi_arg (phi, arg, then_old_edge, UNKNOWN_LOCATION);
2089*e4b17023SJohn Marino update_stmt (phi);
2090*e4b17023SJohn Marino }
2091*e4b17023SJohn Marino }
2092*e4b17023SJohn Marino /* Remove the original fall through edge. This was the
2093*e4b17023SJohn Marino single_succ_edge (new_bb). */
2094*e4b17023SJohn Marino EDGE_SUCC (new_bb, 0)->flags &= ~EDGE_FALLTHRU;
2095*e4b17023SJohn Marino }
2096*e4b17023SJohn Marino
2097*e4b17023SJohn Marino /* Helper function for execute_sm. On every location where REF is
2098*e4b17023SJohn Marino set, set an appropriate flag indicating the store. */
2099*e4b17023SJohn Marino
2100*e4b17023SJohn Marino static tree
execute_sm_if_changed_flag_set(struct loop * loop,mem_ref_p ref)2101*e4b17023SJohn Marino execute_sm_if_changed_flag_set (struct loop *loop, mem_ref_p ref)
2102*e4b17023SJohn Marino {
2103*e4b17023SJohn Marino unsigned i;
2104*e4b17023SJohn Marino mem_ref_loc_p loc;
2105*e4b17023SJohn Marino tree flag;
2106*e4b17023SJohn Marino VEC (mem_ref_loc_p, heap) *locs = NULL;
2107*e4b17023SJohn Marino char *str = get_lsm_tmp_name (ref->mem, ~0);
2108*e4b17023SJohn Marino
2109*e4b17023SJohn Marino lsm_tmp_name_add ("_flag");
2110*e4b17023SJohn Marino flag = make_rename_temp (boolean_type_node, str);
2111*e4b17023SJohn Marino get_all_locs_in_loop (loop, ref, &locs);
2112*e4b17023SJohn Marino FOR_EACH_VEC_ELT (mem_ref_loc_p, locs, i, loc)
2113*e4b17023SJohn Marino {
2114*e4b17023SJohn Marino gimple_stmt_iterator gsi;
2115*e4b17023SJohn Marino gimple stmt;
2116*e4b17023SJohn Marino
2117*e4b17023SJohn Marino gsi = gsi_for_stmt (loc->stmt);
2118*e4b17023SJohn Marino stmt = gimple_build_assign (flag, boolean_true_node);
2119*e4b17023SJohn Marino gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
2120*e4b17023SJohn Marino }
2121*e4b17023SJohn Marino VEC_free (mem_ref_loc_p, heap, locs);
2122*e4b17023SJohn Marino return flag;
2123*e4b17023SJohn Marino }
2124*e4b17023SJohn Marino
2125*e4b17023SJohn Marino /* Executes store motion of memory reference REF from LOOP.
2126*e4b17023SJohn Marino Exits from the LOOP are stored in EXITS. The initialization of the
2127*e4b17023SJohn Marino temporary variable is put to the preheader of the loop, and assignments
2128*e4b17023SJohn Marino to the reference from the temporary variable are emitted to exits. */
2129*e4b17023SJohn Marino
2130*e4b17023SJohn Marino static void
execute_sm(struct loop * loop,VEC (edge,heap)* exits,mem_ref_p ref)2131*e4b17023SJohn Marino execute_sm (struct loop *loop, VEC (edge, heap) *exits, mem_ref_p ref)
2132*e4b17023SJohn Marino {
2133*e4b17023SJohn Marino tree tmp_var, store_flag;
2134*e4b17023SJohn Marino unsigned i;
2135*e4b17023SJohn Marino gimple load;
2136*e4b17023SJohn Marino struct fmt_data fmt_data;
2137*e4b17023SJohn Marino edge ex, latch_edge;
2138*e4b17023SJohn Marino struct lim_aux_data *lim_data;
2139*e4b17023SJohn Marino bool multi_threaded_model_p = false;
2140*e4b17023SJohn Marino
2141*e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS))
2142*e4b17023SJohn Marino {
2143*e4b17023SJohn Marino fprintf (dump_file, "Executing store motion of ");
2144*e4b17023SJohn Marino print_generic_expr (dump_file, ref->mem, 0);
2145*e4b17023SJohn Marino fprintf (dump_file, " from loop %d\n", loop->num);
2146*e4b17023SJohn Marino }
2147*e4b17023SJohn Marino
2148*e4b17023SJohn Marino tmp_var = make_rename_temp (TREE_TYPE (ref->mem),
2149*e4b17023SJohn Marino get_lsm_tmp_name (ref->mem, ~0));
2150*e4b17023SJohn Marino
2151*e4b17023SJohn Marino fmt_data.loop = loop;
2152*e4b17023SJohn Marino fmt_data.orig_loop = loop;
2153*e4b17023SJohn Marino for_each_index (&ref->mem, force_move_till, &fmt_data);
2154*e4b17023SJohn Marino
2155*e4b17023SJohn Marino if (block_in_transaction (loop_preheader_edge (loop)->src)
2156*e4b17023SJohn Marino || !PARAM_VALUE (PARAM_ALLOW_STORE_DATA_RACES))
2157*e4b17023SJohn Marino multi_threaded_model_p = true;
2158*e4b17023SJohn Marino
2159*e4b17023SJohn Marino if (multi_threaded_model_p)
2160*e4b17023SJohn Marino store_flag = execute_sm_if_changed_flag_set (loop, ref);
2161*e4b17023SJohn Marino
2162*e4b17023SJohn Marino rewrite_mem_refs (loop, ref, tmp_var);
2163*e4b17023SJohn Marino
2164*e4b17023SJohn Marino /* Emit the load code into the latch, so that we are sure it will
2165*e4b17023SJohn Marino be processed after all dependencies. */
2166*e4b17023SJohn Marino latch_edge = loop_latch_edge (loop);
2167*e4b17023SJohn Marino
2168*e4b17023SJohn Marino /* FIXME/TODO: For the multi-threaded variant, we could avoid this
2169*e4b17023SJohn Marino load altogether, since the store is predicated by a flag. We
2170*e4b17023SJohn Marino could, do the load only if it was originally in the loop. */
2171*e4b17023SJohn Marino load = gimple_build_assign (tmp_var, unshare_expr (ref->mem));
2172*e4b17023SJohn Marino lim_data = init_lim_data (load);
2173*e4b17023SJohn Marino lim_data->max_loop = loop;
2174*e4b17023SJohn Marino lim_data->tgt_loop = loop;
2175*e4b17023SJohn Marino gsi_insert_on_edge (latch_edge, load);
2176*e4b17023SJohn Marino
2177*e4b17023SJohn Marino if (multi_threaded_model_p)
2178*e4b17023SJohn Marino {
2179*e4b17023SJohn Marino load = gimple_build_assign (store_flag, boolean_false_node);
2180*e4b17023SJohn Marino lim_data = init_lim_data (load);
2181*e4b17023SJohn Marino lim_data->max_loop = loop;
2182*e4b17023SJohn Marino lim_data->tgt_loop = loop;
2183*e4b17023SJohn Marino gsi_insert_on_edge (latch_edge, load);
2184*e4b17023SJohn Marino }
2185*e4b17023SJohn Marino
2186*e4b17023SJohn Marino /* Sink the store to every exit from the loop. */
2187*e4b17023SJohn Marino FOR_EACH_VEC_ELT (edge, exits, i, ex)
2188*e4b17023SJohn Marino if (!multi_threaded_model_p)
2189*e4b17023SJohn Marino {
2190*e4b17023SJohn Marino gimple store;
2191*e4b17023SJohn Marino store = gimple_build_assign (unshare_expr (ref->mem), tmp_var);
2192*e4b17023SJohn Marino gsi_insert_on_edge (ex, store);
2193*e4b17023SJohn Marino }
2194*e4b17023SJohn Marino else
2195*e4b17023SJohn Marino execute_sm_if_changed (ex, ref->mem, tmp_var, store_flag);
2196*e4b17023SJohn Marino }
2197*e4b17023SJohn Marino
2198*e4b17023SJohn Marino /* Hoists memory references MEM_REFS out of LOOP. EXITS is the list of exit
2199*e4b17023SJohn Marino edges of the LOOP. */
2200*e4b17023SJohn Marino
2201*e4b17023SJohn Marino static void
hoist_memory_references(struct loop * loop,bitmap mem_refs,VEC (edge,heap)* exits)2202*e4b17023SJohn Marino hoist_memory_references (struct loop *loop, bitmap mem_refs,
2203*e4b17023SJohn Marino VEC (edge, heap) *exits)
2204*e4b17023SJohn Marino {
2205*e4b17023SJohn Marino mem_ref_p ref;
2206*e4b17023SJohn Marino unsigned i;
2207*e4b17023SJohn Marino bitmap_iterator bi;
2208*e4b17023SJohn Marino
2209*e4b17023SJohn Marino EXECUTE_IF_SET_IN_BITMAP (mem_refs, 0, i, bi)
2210*e4b17023SJohn Marino {
2211*e4b17023SJohn Marino ref = VEC_index (mem_ref_p, memory_accesses.refs_list, i);
2212*e4b17023SJohn Marino execute_sm (loop, exits, ref);
2213*e4b17023SJohn Marino }
2214*e4b17023SJohn Marino }
2215*e4b17023SJohn Marino
2216*e4b17023SJohn Marino /* Returns true if REF is always accessed in LOOP. If STORED_P is true
2217*e4b17023SJohn Marino make sure REF is always stored to in LOOP. */
2218*e4b17023SJohn Marino
2219*e4b17023SJohn Marino static bool
ref_always_accessed_p(struct loop * loop,mem_ref_p ref,bool stored_p)2220*e4b17023SJohn Marino ref_always_accessed_p (struct loop *loop, mem_ref_p ref, bool stored_p)
2221*e4b17023SJohn Marino {
2222*e4b17023SJohn Marino VEC (mem_ref_loc_p, heap) *locs = NULL;
2223*e4b17023SJohn Marino unsigned i;
2224*e4b17023SJohn Marino mem_ref_loc_p loc;
2225*e4b17023SJohn Marino bool ret = false;
2226*e4b17023SJohn Marino struct loop *must_exec;
2227*e4b17023SJohn Marino tree base;
2228*e4b17023SJohn Marino
2229*e4b17023SJohn Marino base = get_base_address (ref->mem);
2230*e4b17023SJohn Marino if (INDIRECT_REF_P (base)
2231*e4b17023SJohn Marino || TREE_CODE (base) == MEM_REF)
2232*e4b17023SJohn Marino base = TREE_OPERAND (base, 0);
2233*e4b17023SJohn Marino
2234*e4b17023SJohn Marino get_all_locs_in_loop (loop, ref, &locs);
2235*e4b17023SJohn Marino FOR_EACH_VEC_ELT (mem_ref_loc_p, locs, i, loc)
2236*e4b17023SJohn Marino {
2237*e4b17023SJohn Marino if (!get_lim_data (loc->stmt))
2238*e4b17023SJohn Marino continue;
2239*e4b17023SJohn Marino
2240*e4b17023SJohn Marino /* If we require an always executed store make sure the statement
2241*e4b17023SJohn Marino stores to the reference. */
2242*e4b17023SJohn Marino if (stored_p)
2243*e4b17023SJohn Marino {
2244*e4b17023SJohn Marino tree lhs;
2245*e4b17023SJohn Marino if (!gimple_get_lhs (loc->stmt))
2246*e4b17023SJohn Marino continue;
2247*e4b17023SJohn Marino lhs = get_base_address (gimple_get_lhs (loc->stmt));
2248*e4b17023SJohn Marino if (!lhs)
2249*e4b17023SJohn Marino continue;
2250*e4b17023SJohn Marino if (INDIRECT_REF_P (lhs)
2251*e4b17023SJohn Marino || TREE_CODE (lhs) == MEM_REF)
2252*e4b17023SJohn Marino lhs = TREE_OPERAND (lhs, 0);
2253*e4b17023SJohn Marino if (lhs != base)
2254*e4b17023SJohn Marino continue;
2255*e4b17023SJohn Marino }
2256*e4b17023SJohn Marino
2257*e4b17023SJohn Marino must_exec = get_lim_data (loc->stmt)->always_executed_in;
2258*e4b17023SJohn Marino if (!must_exec)
2259*e4b17023SJohn Marino continue;
2260*e4b17023SJohn Marino
2261*e4b17023SJohn Marino if (must_exec == loop
2262*e4b17023SJohn Marino || flow_loop_nested_p (must_exec, loop))
2263*e4b17023SJohn Marino {
2264*e4b17023SJohn Marino ret = true;
2265*e4b17023SJohn Marino break;
2266*e4b17023SJohn Marino }
2267*e4b17023SJohn Marino }
2268*e4b17023SJohn Marino VEC_free (mem_ref_loc_p, heap, locs);
2269*e4b17023SJohn Marino
2270*e4b17023SJohn Marino return ret;
2271*e4b17023SJohn Marino }
2272*e4b17023SJohn Marino
2273*e4b17023SJohn Marino /* Returns true if REF1 and REF2 are independent. */
2274*e4b17023SJohn Marino
2275*e4b17023SJohn Marino static bool
refs_independent_p(mem_ref_p ref1,mem_ref_p ref2)2276*e4b17023SJohn Marino refs_independent_p (mem_ref_p ref1, mem_ref_p ref2)
2277*e4b17023SJohn Marino {
2278*e4b17023SJohn Marino if (ref1 == ref2
2279*e4b17023SJohn Marino || bitmap_bit_p (ref1->indep_ref, ref2->id))
2280*e4b17023SJohn Marino return true;
2281*e4b17023SJohn Marino if (bitmap_bit_p (ref1->dep_ref, ref2->id))
2282*e4b17023SJohn Marino return false;
2283*e4b17023SJohn Marino if (!MEM_ANALYZABLE (ref1)
2284*e4b17023SJohn Marino || !MEM_ANALYZABLE (ref2))
2285*e4b17023SJohn Marino return false;
2286*e4b17023SJohn Marino
2287*e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS))
2288*e4b17023SJohn Marino fprintf (dump_file, "Querying dependency of refs %u and %u: ",
2289*e4b17023SJohn Marino ref1->id, ref2->id);
2290*e4b17023SJohn Marino
2291*e4b17023SJohn Marino if (mem_refs_may_alias_p (ref1->mem, ref2->mem,
2292*e4b17023SJohn Marino &memory_accesses.ttae_cache))
2293*e4b17023SJohn Marino {
2294*e4b17023SJohn Marino bitmap_set_bit (ref1->dep_ref, ref2->id);
2295*e4b17023SJohn Marino bitmap_set_bit (ref2->dep_ref, ref1->id);
2296*e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS))
2297*e4b17023SJohn Marino fprintf (dump_file, "dependent.\n");
2298*e4b17023SJohn Marino return false;
2299*e4b17023SJohn Marino }
2300*e4b17023SJohn Marino else
2301*e4b17023SJohn Marino {
2302*e4b17023SJohn Marino bitmap_set_bit (ref1->indep_ref, ref2->id);
2303*e4b17023SJohn Marino bitmap_set_bit (ref2->indep_ref, ref1->id);
2304*e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS))
2305*e4b17023SJohn Marino fprintf (dump_file, "independent.\n");
2306*e4b17023SJohn Marino return true;
2307*e4b17023SJohn Marino }
2308*e4b17023SJohn Marino }
2309*e4b17023SJohn Marino
2310*e4b17023SJohn Marino /* Records the information whether REF is independent in LOOP (according
2311*e4b17023SJohn Marino to INDEP). */
2312*e4b17023SJohn Marino
2313*e4b17023SJohn Marino static void
record_indep_loop(struct loop * loop,mem_ref_p ref,bool indep)2314*e4b17023SJohn Marino record_indep_loop (struct loop *loop, mem_ref_p ref, bool indep)
2315*e4b17023SJohn Marino {
2316*e4b17023SJohn Marino if (indep)
2317*e4b17023SJohn Marino bitmap_set_bit (ref->indep_loop, loop->num);
2318*e4b17023SJohn Marino else
2319*e4b17023SJohn Marino bitmap_set_bit (ref->dep_loop, loop->num);
2320*e4b17023SJohn Marino }
2321*e4b17023SJohn Marino
2322*e4b17023SJohn Marino /* Returns true if REF is independent on all other memory references in
2323*e4b17023SJohn Marino LOOP. */
2324*e4b17023SJohn Marino
2325*e4b17023SJohn Marino static bool
ref_indep_loop_p_1(struct loop * loop,mem_ref_p ref)2326*e4b17023SJohn Marino ref_indep_loop_p_1 (struct loop *loop, mem_ref_p ref)
2327*e4b17023SJohn Marino {
2328*e4b17023SJohn Marino bitmap refs_to_check;
2329*e4b17023SJohn Marino unsigned i;
2330*e4b17023SJohn Marino bitmap_iterator bi;
2331*e4b17023SJohn Marino bool ret = true, stored = bitmap_bit_p (ref->stored, loop->num);
2332*e4b17023SJohn Marino mem_ref_p aref;
2333*e4b17023SJohn Marino
2334*e4b17023SJohn Marino if (stored)
2335*e4b17023SJohn Marino refs_to_check = VEC_index (bitmap,
2336*e4b17023SJohn Marino memory_accesses.all_refs_in_loop, loop->num);
2337*e4b17023SJohn Marino else
2338*e4b17023SJohn Marino refs_to_check = VEC_index (bitmap,
2339*e4b17023SJohn Marino memory_accesses.all_refs_stored_in_loop,
2340*e4b17023SJohn Marino loop->num);
2341*e4b17023SJohn Marino
2342*e4b17023SJohn Marino EXECUTE_IF_SET_IN_BITMAP (refs_to_check, 0, i, bi)
2343*e4b17023SJohn Marino {
2344*e4b17023SJohn Marino aref = VEC_index (mem_ref_p, memory_accesses.refs_list, i);
2345*e4b17023SJohn Marino if (!MEM_ANALYZABLE (aref)
2346*e4b17023SJohn Marino || !refs_independent_p (ref, aref))
2347*e4b17023SJohn Marino {
2348*e4b17023SJohn Marino ret = false;
2349*e4b17023SJohn Marino record_indep_loop (loop, aref, false);
2350*e4b17023SJohn Marino break;
2351*e4b17023SJohn Marino }
2352*e4b17023SJohn Marino }
2353*e4b17023SJohn Marino
2354*e4b17023SJohn Marino return ret;
2355*e4b17023SJohn Marino }
2356*e4b17023SJohn Marino
2357*e4b17023SJohn Marino /* Returns true if REF is independent on all other memory references in
2358*e4b17023SJohn Marino LOOP. Wrapper over ref_indep_loop_p_1, caching its results. */
2359*e4b17023SJohn Marino
2360*e4b17023SJohn Marino static bool
ref_indep_loop_p(struct loop * loop,mem_ref_p ref)2361*e4b17023SJohn Marino ref_indep_loop_p (struct loop *loop, mem_ref_p ref)
2362*e4b17023SJohn Marino {
2363*e4b17023SJohn Marino bool ret;
2364*e4b17023SJohn Marino
2365*e4b17023SJohn Marino if (bitmap_bit_p (ref->indep_loop, loop->num))
2366*e4b17023SJohn Marino return true;
2367*e4b17023SJohn Marino if (bitmap_bit_p (ref->dep_loop, loop->num))
2368*e4b17023SJohn Marino return false;
2369*e4b17023SJohn Marino
2370*e4b17023SJohn Marino ret = ref_indep_loop_p_1 (loop, ref);
2371*e4b17023SJohn Marino
2372*e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS))
2373*e4b17023SJohn Marino fprintf (dump_file, "Querying dependencies of ref %u in loop %d: %s\n",
2374*e4b17023SJohn Marino ref->id, loop->num, ret ? "independent" : "dependent");
2375*e4b17023SJohn Marino
2376*e4b17023SJohn Marino record_indep_loop (loop, ref, ret);
2377*e4b17023SJohn Marino
2378*e4b17023SJohn Marino return ret;
2379*e4b17023SJohn Marino }
2380*e4b17023SJohn Marino
2381*e4b17023SJohn Marino /* Returns true if we can perform store motion of REF from LOOP. */
2382*e4b17023SJohn Marino
2383*e4b17023SJohn Marino static bool
can_sm_ref_p(struct loop * loop,mem_ref_p ref)2384*e4b17023SJohn Marino can_sm_ref_p (struct loop *loop, mem_ref_p ref)
2385*e4b17023SJohn Marino {
2386*e4b17023SJohn Marino tree base;
2387*e4b17023SJohn Marino
2388*e4b17023SJohn Marino /* Can't hoist unanalyzable refs. */
2389*e4b17023SJohn Marino if (!MEM_ANALYZABLE (ref))
2390*e4b17023SJohn Marino return false;
2391*e4b17023SJohn Marino
2392*e4b17023SJohn Marino /* Unless the reference is stored in the loop, there is nothing to do. */
2393*e4b17023SJohn Marino if (!bitmap_bit_p (ref->stored, loop->num))
2394*e4b17023SJohn Marino return false;
2395*e4b17023SJohn Marino
2396*e4b17023SJohn Marino /* It should be movable. */
2397*e4b17023SJohn Marino if (!is_gimple_reg_type (TREE_TYPE (ref->mem))
2398*e4b17023SJohn Marino || TREE_THIS_VOLATILE (ref->mem)
2399*e4b17023SJohn Marino || !for_each_index (&ref->mem, may_move_till, loop))
2400*e4b17023SJohn Marino return false;
2401*e4b17023SJohn Marino
2402*e4b17023SJohn Marino /* If it can throw fail, we do not properly update EH info. */
2403*e4b17023SJohn Marino if (tree_could_throw_p (ref->mem))
2404*e4b17023SJohn Marino return false;
2405*e4b17023SJohn Marino
2406*e4b17023SJohn Marino /* If it can trap, it must be always executed in LOOP.
2407*e4b17023SJohn Marino Readonly memory locations may trap when storing to them, but
2408*e4b17023SJohn Marino tree_could_trap_p is a predicate for rvalues, so check that
2409*e4b17023SJohn Marino explicitly. */
2410*e4b17023SJohn Marino base = get_base_address (ref->mem);
2411*e4b17023SJohn Marino if ((tree_could_trap_p (ref->mem)
2412*e4b17023SJohn Marino || (DECL_P (base) && TREE_READONLY (base)))
2413*e4b17023SJohn Marino && !ref_always_accessed_p (loop, ref, true))
2414*e4b17023SJohn Marino return false;
2415*e4b17023SJohn Marino
2416*e4b17023SJohn Marino /* And it must be independent on all other memory references
2417*e4b17023SJohn Marino in LOOP. */
2418*e4b17023SJohn Marino if (!ref_indep_loop_p (loop, ref))
2419*e4b17023SJohn Marino return false;
2420*e4b17023SJohn Marino
2421*e4b17023SJohn Marino return true;
2422*e4b17023SJohn Marino }
2423*e4b17023SJohn Marino
2424*e4b17023SJohn Marino /* Marks the references in LOOP for that store motion should be performed
2425*e4b17023SJohn Marino in REFS_TO_SM. SM_EXECUTED is the set of references for that store
2426*e4b17023SJohn Marino motion was performed in one of the outer loops. */
2427*e4b17023SJohn Marino
2428*e4b17023SJohn Marino static void
find_refs_for_sm(struct loop * loop,bitmap sm_executed,bitmap refs_to_sm)2429*e4b17023SJohn Marino find_refs_for_sm (struct loop *loop, bitmap sm_executed, bitmap refs_to_sm)
2430*e4b17023SJohn Marino {
2431*e4b17023SJohn Marino bitmap refs = VEC_index (bitmap, memory_accesses.all_refs_in_loop,
2432*e4b17023SJohn Marino loop->num);
2433*e4b17023SJohn Marino unsigned i;
2434*e4b17023SJohn Marino bitmap_iterator bi;
2435*e4b17023SJohn Marino mem_ref_p ref;
2436*e4b17023SJohn Marino
2437*e4b17023SJohn Marino EXECUTE_IF_AND_COMPL_IN_BITMAP (refs, sm_executed, 0, i, bi)
2438*e4b17023SJohn Marino {
2439*e4b17023SJohn Marino ref = VEC_index (mem_ref_p, memory_accesses.refs_list, i);
2440*e4b17023SJohn Marino if (can_sm_ref_p (loop, ref))
2441*e4b17023SJohn Marino bitmap_set_bit (refs_to_sm, i);
2442*e4b17023SJohn Marino }
2443*e4b17023SJohn Marino }
2444*e4b17023SJohn Marino
2445*e4b17023SJohn Marino /* Checks whether LOOP (with exits stored in EXITS array) is suitable
2446*e4b17023SJohn Marino for a store motion optimization (i.e. whether we can insert statement
2447*e4b17023SJohn Marino on its exits). */
2448*e4b17023SJohn Marino
2449*e4b17023SJohn Marino static bool
loop_suitable_for_sm(struct loop * loop ATTRIBUTE_UNUSED,VEC (edge,heap)* exits)2450*e4b17023SJohn Marino loop_suitable_for_sm (struct loop *loop ATTRIBUTE_UNUSED,
2451*e4b17023SJohn Marino VEC (edge, heap) *exits)
2452*e4b17023SJohn Marino {
2453*e4b17023SJohn Marino unsigned i;
2454*e4b17023SJohn Marino edge ex;
2455*e4b17023SJohn Marino
2456*e4b17023SJohn Marino FOR_EACH_VEC_ELT (edge, exits, i, ex)
2457*e4b17023SJohn Marino if (ex->flags & (EDGE_ABNORMAL | EDGE_EH))
2458*e4b17023SJohn Marino return false;
2459*e4b17023SJohn Marino
2460*e4b17023SJohn Marino return true;
2461*e4b17023SJohn Marino }
2462*e4b17023SJohn Marino
2463*e4b17023SJohn Marino /* Try to perform store motion for all memory references modified inside
2464*e4b17023SJohn Marino LOOP. SM_EXECUTED is the bitmap of the memory references for that
2465*e4b17023SJohn Marino store motion was executed in one of the outer loops. */
2466*e4b17023SJohn Marino
2467*e4b17023SJohn Marino static void
store_motion_loop(struct loop * loop,bitmap sm_executed)2468*e4b17023SJohn Marino store_motion_loop (struct loop *loop, bitmap sm_executed)
2469*e4b17023SJohn Marino {
2470*e4b17023SJohn Marino VEC (edge, heap) *exits = get_loop_exit_edges (loop);
2471*e4b17023SJohn Marino struct loop *subloop;
2472*e4b17023SJohn Marino bitmap sm_in_loop = BITMAP_ALLOC (NULL);
2473*e4b17023SJohn Marino
2474*e4b17023SJohn Marino if (loop_suitable_for_sm (loop, exits))
2475*e4b17023SJohn Marino {
2476*e4b17023SJohn Marino find_refs_for_sm (loop, sm_executed, sm_in_loop);
2477*e4b17023SJohn Marino hoist_memory_references (loop, sm_in_loop, exits);
2478*e4b17023SJohn Marino }
2479*e4b17023SJohn Marino VEC_free (edge, heap, exits);
2480*e4b17023SJohn Marino
2481*e4b17023SJohn Marino bitmap_ior_into (sm_executed, sm_in_loop);
2482*e4b17023SJohn Marino for (subloop = loop->inner; subloop != NULL; subloop = subloop->next)
2483*e4b17023SJohn Marino store_motion_loop (subloop, sm_executed);
2484*e4b17023SJohn Marino bitmap_and_compl_into (sm_executed, sm_in_loop);
2485*e4b17023SJohn Marino BITMAP_FREE (sm_in_loop);
2486*e4b17023SJohn Marino }
2487*e4b17023SJohn Marino
2488*e4b17023SJohn Marino /* Try to perform store motion for all memory references modified inside
2489*e4b17023SJohn Marino loops. */
2490*e4b17023SJohn Marino
2491*e4b17023SJohn Marino static void
store_motion(void)2492*e4b17023SJohn Marino store_motion (void)
2493*e4b17023SJohn Marino {
2494*e4b17023SJohn Marino struct loop *loop;
2495*e4b17023SJohn Marino bitmap sm_executed = BITMAP_ALLOC (NULL);
2496*e4b17023SJohn Marino
2497*e4b17023SJohn Marino for (loop = current_loops->tree_root->inner; loop != NULL; loop = loop->next)
2498*e4b17023SJohn Marino store_motion_loop (loop, sm_executed);
2499*e4b17023SJohn Marino
2500*e4b17023SJohn Marino BITMAP_FREE (sm_executed);
2501*e4b17023SJohn Marino gsi_commit_edge_inserts ();
2502*e4b17023SJohn Marino }
2503*e4b17023SJohn Marino
2504*e4b17023SJohn Marino /* Fills ALWAYS_EXECUTED_IN information for basic blocks of LOOP, i.e.
2505*e4b17023SJohn Marino for each such basic block bb records the outermost loop for that execution
2506*e4b17023SJohn Marino of its header implies execution of bb. CONTAINS_CALL is the bitmap of
2507*e4b17023SJohn Marino blocks that contain a nonpure call. */
2508*e4b17023SJohn Marino
2509*e4b17023SJohn Marino static void
fill_always_executed_in(struct loop * loop,sbitmap contains_call)2510*e4b17023SJohn Marino fill_always_executed_in (struct loop *loop, sbitmap contains_call)
2511*e4b17023SJohn Marino {
2512*e4b17023SJohn Marino basic_block bb = NULL, *bbs, last = NULL;
2513*e4b17023SJohn Marino unsigned i;
2514*e4b17023SJohn Marino edge e;
2515*e4b17023SJohn Marino struct loop *inn_loop = loop;
2516*e4b17023SJohn Marino
2517*e4b17023SJohn Marino if (ALWAYS_EXECUTED_IN (loop->header) == NULL)
2518*e4b17023SJohn Marino {
2519*e4b17023SJohn Marino bbs = get_loop_body_in_dom_order (loop);
2520*e4b17023SJohn Marino
2521*e4b17023SJohn Marino for (i = 0; i < loop->num_nodes; i++)
2522*e4b17023SJohn Marino {
2523*e4b17023SJohn Marino edge_iterator ei;
2524*e4b17023SJohn Marino bb = bbs[i];
2525*e4b17023SJohn Marino
2526*e4b17023SJohn Marino if (dominated_by_p (CDI_DOMINATORS, loop->latch, bb))
2527*e4b17023SJohn Marino last = bb;
2528*e4b17023SJohn Marino
2529*e4b17023SJohn Marino if (TEST_BIT (contains_call, bb->index))
2530*e4b17023SJohn Marino break;
2531*e4b17023SJohn Marino
2532*e4b17023SJohn Marino FOR_EACH_EDGE (e, ei, bb->succs)
2533*e4b17023SJohn Marino if (!flow_bb_inside_loop_p (loop, e->dest))
2534*e4b17023SJohn Marino break;
2535*e4b17023SJohn Marino if (e)
2536*e4b17023SJohn Marino break;
2537*e4b17023SJohn Marino
2538*e4b17023SJohn Marino /* A loop might be infinite (TODO use simple loop analysis
2539*e4b17023SJohn Marino to disprove this if possible). */
2540*e4b17023SJohn Marino if (bb->flags & BB_IRREDUCIBLE_LOOP)
2541*e4b17023SJohn Marino break;
2542*e4b17023SJohn Marino
2543*e4b17023SJohn Marino if (!flow_bb_inside_loop_p (inn_loop, bb))
2544*e4b17023SJohn Marino break;
2545*e4b17023SJohn Marino
2546*e4b17023SJohn Marino if (bb->loop_father->header == bb)
2547*e4b17023SJohn Marino {
2548*e4b17023SJohn Marino if (!dominated_by_p (CDI_DOMINATORS, loop->latch, bb))
2549*e4b17023SJohn Marino break;
2550*e4b17023SJohn Marino
2551*e4b17023SJohn Marino /* In a loop that is always entered we may proceed anyway.
2552*e4b17023SJohn Marino But record that we entered it and stop once we leave it. */
2553*e4b17023SJohn Marino inn_loop = bb->loop_father;
2554*e4b17023SJohn Marino }
2555*e4b17023SJohn Marino }
2556*e4b17023SJohn Marino
2557*e4b17023SJohn Marino while (1)
2558*e4b17023SJohn Marino {
2559*e4b17023SJohn Marino SET_ALWAYS_EXECUTED_IN (last, loop);
2560*e4b17023SJohn Marino if (last == loop->header)
2561*e4b17023SJohn Marino break;
2562*e4b17023SJohn Marino last = get_immediate_dominator (CDI_DOMINATORS, last);
2563*e4b17023SJohn Marino }
2564*e4b17023SJohn Marino
2565*e4b17023SJohn Marino free (bbs);
2566*e4b17023SJohn Marino }
2567*e4b17023SJohn Marino
2568*e4b17023SJohn Marino for (loop = loop->inner; loop; loop = loop->next)
2569*e4b17023SJohn Marino fill_always_executed_in (loop, contains_call);
2570*e4b17023SJohn Marino }
2571*e4b17023SJohn Marino
2572*e4b17023SJohn Marino /* Compute the global information needed by the loop invariant motion pass. */
2573*e4b17023SJohn Marino
2574*e4b17023SJohn Marino static void
tree_ssa_lim_initialize(void)2575*e4b17023SJohn Marino tree_ssa_lim_initialize (void)
2576*e4b17023SJohn Marino {
2577*e4b17023SJohn Marino sbitmap contains_call = sbitmap_alloc (last_basic_block);
2578*e4b17023SJohn Marino gimple_stmt_iterator bsi;
2579*e4b17023SJohn Marino struct loop *loop;
2580*e4b17023SJohn Marino basic_block bb;
2581*e4b17023SJohn Marino
2582*e4b17023SJohn Marino sbitmap_zero (contains_call);
2583*e4b17023SJohn Marino FOR_EACH_BB (bb)
2584*e4b17023SJohn Marino {
2585*e4b17023SJohn Marino for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi))
2586*e4b17023SJohn Marino {
2587*e4b17023SJohn Marino if (nonpure_call_p (gsi_stmt (bsi)))
2588*e4b17023SJohn Marino break;
2589*e4b17023SJohn Marino }
2590*e4b17023SJohn Marino
2591*e4b17023SJohn Marino if (!gsi_end_p (bsi))
2592*e4b17023SJohn Marino SET_BIT (contains_call, bb->index);
2593*e4b17023SJohn Marino }
2594*e4b17023SJohn Marino
2595*e4b17023SJohn Marino for (loop = current_loops->tree_root->inner; loop; loop = loop->next)
2596*e4b17023SJohn Marino fill_always_executed_in (loop, contains_call);
2597*e4b17023SJohn Marino
2598*e4b17023SJohn Marino sbitmap_free (contains_call);
2599*e4b17023SJohn Marino
2600*e4b17023SJohn Marino lim_aux_data_map = pointer_map_create ();
2601*e4b17023SJohn Marino
2602*e4b17023SJohn Marino if (flag_tm)
2603*e4b17023SJohn Marino compute_transaction_bits ();
2604*e4b17023SJohn Marino
2605*e4b17023SJohn Marino alloc_aux_for_edges (0);
2606*e4b17023SJohn Marino }
2607*e4b17023SJohn Marino
2608*e4b17023SJohn Marino /* Cleans up after the invariant motion pass. */
2609*e4b17023SJohn Marino
2610*e4b17023SJohn Marino static void
tree_ssa_lim_finalize(void)2611*e4b17023SJohn Marino tree_ssa_lim_finalize (void)
2612*e4b17023SJohn Marino {
2613*e4b17023SJohn Marino basic_block bb;
2614*e4b17023SJohn Marino unsigned i;
2615*e4b17023SJohn Marino bitmap b;
2616*e4b17023SJohn Marino mem_ref_p ref;
2617*e4b17023SJohn Marino
2618*e4b17023SJohn Marino free_aux_for_edges ();
2619*e4b17023SJohn Marino
2620*e4b17023SJohn Marino FOR_EACH_BB (bb)
2621*e4b17023SJohn Marino SET_ALWAYS_EXECUTED_IN (bb, NULL);
2622*e4b17023SJohn Marino
2623*e4b17023SJohn Marino pointer_map_destroy (lim_aux_data_map);
2624*e4b17023SJohn Marino
2625*e4b17023SJohn Marino htab_delete (memory_accesses.refs);
2626*e4b17023SJohn Marino
2627*e4b17023SJohn Marino FOR_EACH_VEC_ELT (mem_ref_p, memory_accesses.refs_list, i, ref)
2628*e4b17023SJohn Marino memref_free (ref);
2629*e4b17023SJohn Marino VEC_free (mem_ref_p, heap, memory_accesses.refs_list);
2630*e4b17023SJohn Marino
2631*e4b17023SJohn Marino FOR_EACH_VEC_ELT (bitmap, memory_accesses.refs_in_loop, i, b)
2632*e4b17023SJohn Marino BITMAP_FREE (b);
2633*e4b17023SJohn Marino VEC_free (bitmap, heap, memory_accesses.refs_in_loop);
2634*e4b17023SJohn Marino
2635*e4b17023SJohn Marino FOR_EACH_VEC_ELT (bitmap, memory_accesses.all_refs_in_loop, i, b)
2636*e4b17023SJohn Marino BITMAP_FREE (b);
2637*e4b17023SJohn Marino VEC_free (bitmap, heap, memory_accesses.all_refs_in_loop);
2638*e4b17023SJohn Marino
2639*e4b17023SJohn Marino FOR_EACH_VEC_ELT (bitmap, memory_accesses.all_refs_stored_in_loop, i, b)
2640*e4b17023SJohn Marino BITMAP_FREE (b);
2641*e4b17023SJohn Marino VEC_free (bitmap, heap, memory_accesses.all_refs_stored_in_loop);
2642*e4b17023SJohn Marino
2643*e4b17023SJohn Marino if (memory_accesses.ttae_cache)
2644*e4b17023SJohn Marino free_affine_expand_cache (&memory_accesses.ttae_cache);
2645*e4b17023SJohn Marino }
2646*e4b17023SJohn Marino
2647*e4b17023SJohn Marino /* Moves invariants from loops. Only "expensive" invariants are moved out --
2648*e4b17023SJohn Marino i.e. those that are likely to be win regardless of the register pressure. */
2649*e4b17023SJohn Marino
2650*e4b17023SJohn Marino unsigned int
tree_ssa_lim(void)2651*e4b17023SJohn Marino tree_ssa_lim (void)
2652*e4b17023SJohn Marino {
2653*e4b17023SJohn Marino unsigned int todo;
2654*e4b17023SJohn Marino
2655*e4b17023SJohn Marino tree_ssa_lim_initialize ();
2656*e4b17023SJohn Marino
2657*e4b17023SJohn Marino /* Gathers information about memory accesses in the loops. */
2658*e4b17023SJohn Marino analyze_memory_references ();
2659*e4b17023SJohn Marino
2660*e4b17023SJohn Marino /* For each statement determine the outermost loop in that it is
2661*e4b17023SJohn Marino invariant and cost for computing the invariant. */
2662*e4b17023SJohn Marino determine_invariantness ();
2663*e4b17023SJohn Marino
2664*e4b17023SJohn Marino /* Execute store motion. Force the necessary invariants to be moved
2665*e4b17023SJohn Marino out of the loops as well. */
2666*e4b17023SJohn Marino store_motion ();
2667*e4b17023SJohn Marino
2668*e4b17023SJohn Marino /* Move the expressions that are expensive enough. */
2669*e4b17023SJohn Marino todo = move_computations ();
2670*e4b17023SJohn Marino
2671*e4b17023SJohn Marino tree_ssa_lim_finalize ();
2672*e4b17023SJohn Marino
2673*e4b17023SJohn Marino return todo;
2674*e4b17023SJohn Marino }
2675