annotate gcc/tree-ssa-loop-im.c @ 111:04ced10e8804

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