xref: /dflybsd-src/contrib/gcc-4.7/gcc/tree-ssa-loop-im.c (revision 04febcfb30580676d3e95f58a16c5137ee478b32)
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