annotate gcc/ssa-iterators.h @ 111:04ced10e8804

gcc 7
author kono
date Fri, 27 Oct 2017 22:46:09 +0900
parents
children 84e7813d76e9
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 /* Header file for SSA iterators.
kono
parents:
diff changeset
2 Copyright (C) 2013-2017 Free Software Foundation, Inc.
kono
parents:
diff changeset
3
kono
parents:
diff changeset
4 This file is part of GCC.
kono
parents:
diff changeset
5
kono
parents:
diff changeset
6 GCC is free software; you can redistribute it and/or modify it under
kono
parents:
diff changeset
7 the terms of the GNU General Public License as published by the Free
kono
parents:
diff changeset
8 Software Foundation; either version 3, or (at your option) any later
kono
parents:
diff changeset
9 version.
kono
parents:
diff changeset
10
kono
parents:
diff changeset
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
kono
parents:
diff changeset
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
kono
parents:
diff changeset
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
kono
parents:
diff changeset
14 for more details.
kono
parents:
diff changeset
15
kono
parents:
diff changeset
16 You should have received a copy of the GNU General Public License
kono
parents:
diff changeset
17 along with GCC; see the file COPYING3. If not see
kono
parents:
diff changeset
18 <http://www.gnu.org/licenses/>. */
kono
parents:
diff changeset
19
kono
parents:
diff changeset
20 #ifndef GCC_SSA_ITERATORS_H
kono
parents:
diff changeset
21 #define GCC_SSA_ITERATORS_H
kono
parents:
diff changeset
22
kono
parents:
diff changeset
23 /* Immediate use lists are used to directly access all uses for an SSA
kono
parents:
diff changeset
24 name and get pointers to the statement for each use.
kono
parents:
diff changeset
25
kono
parents:
diff changeset
26 The structure ssa_use_operand_t consists of PREV and NEXT pointers
kono
parents:
diff changeset
27 to maintain the list. A USE pointer, which points to address where
kono
parents:
diff changeset
28 the use is located and a LOC pointer which can point to the
kono
parents:
diff changeset
29 statement where the use is located, or, in the case of the root
kono
parents:
diff changeset
30 node, it points to the SSA name itself.
kono
parents:
diff changeset
31
kono
parents:
diff changeset
32 The list is anchored by an occurrence of ssa_operand_d *in* the
kono
parents:
diff changeset
33 ssa_name node itself (named 'imm_uses'). This node is uniquely
kono
parents:
diff changeset
34 identified by having a NULL USE pointer. and the LOC pointer
kono
parents:
diff changeset
35 pointing back to the ssa_name node itself. This node forms the
kono
parents:
diff changeset
36 base for a circular list, and initially this is the only node in
kono
parents:
diff changeset
37 the list.
kono
parents:
diff changeset
38
kono
parents:
diff changeset
39 Fast iteration allows each use to be examined, but does not allow
kono
parents:
diff changeset
40 any modifications to the uses or stmts.
kono
parents:
diff changeset
41
kono
parents:
diff changeset
42 Normal iteration allows insertion, deletion, and modification. the
kono
parents:
diff changeset
43 iterator manages this by inserting a marker node into the list
kono
parents:
diff changeset
44 immediately before the node currently being examined in the list.
kono
parents:
diff changeset
45 this marker node is uniquely identified by having null stmt *and* a
kono
parents:
diff changeset
46 null use pointer.
kono
parents:
diff changeset
47
kono
parents:
diff changeset
48 When iterating to the next use, the iteration routines check to see
kono
parents:
diff changeset
49 if the node after the marker has changed. if it has, then the node
kono
parents:
diff changeset
50 following the marker is now the next one to be visited. if not, the
kono
parents:
diff changeset
51 marker node is moved past that node in the list (visualize it as
kono
parents:
diff changeset
52 bumping the marker node through the list). this continues until
kono
parents:
diff changeset
53 the marker node is moved to the original anchor position. the
kono
parents:
diff changeset
54 marker node is then removed from the list.
kono
parents:
diff changeset
55
kono
parents:
diff changeset
56 If iteration is halted early, the marker node must be removed from
kono
parents:
diff changeset
57 the list before continuing. */
kono
parents:
diff changeset
58 struct imm_use_iterator
kono
parents:
diff changeset
59 {
kono
parents:
diff changeset
60 /* This is the current use the iterator is processing. */
kono
parents:
diff changeset
61 ssa_use_operand_t *imm_use;
kono
parents:
diff changeset
62 /* This marks the last use in the list (use node from SSA_NAME) */
kono
parents:
diff changeset
63 ssa_use_operand_t *end_p;
kono
parents:
diff changeset
64 /* This node is inserted and used to mark the end of the uses for a stmt. */
kono
parents:
diff changeset
65 ssa_use_operand_t iter_node;
kono
parents:
diff changeset
66 /* This is the next ssa_name to visit. IMM_USE may get removed before
kono
parents:
diff changeset
67 the next one is traversed to, so it must be cached early. */
kono
parents:
diff changeset
68 ssa_use_operand_t *next_imm_name;
kono
parents:
diff changeset
69 };
kono
parents:
diff changeset
70
kono
parents:
diff changeset
71
kono
parents:
diff changeset
72 /* Use this iterator when simply looking at stmts. Adding, deleting or
kono
parents:
diff changeset
73 modifying stmts will cause this iterator to malfunction. */
kono
parents:
diff changeset
74
kono
parents:
diff changeset
75 #define FOR_EACH_IMM_USE_FAST(DEST, ITER, SSAVAR) \
kono
parents:
diff changeset
76 for ((DEST) = first_readonly_imm_use (&(ITER), (SSAVAR)); \
kono
parents:
diff changeset
77 !end_readonly_imm_use_p (&(ITER)); \
kono
parents:
diff changeset
78 (void) ((DEST) = next_readonly_imm_use (&(ITER))))
kono
parents:
diff changeset
79
kono
parents:
diff changeset
80 /* Use this iterator to visit each stmt which has a use of SSAVAR. */
kono
parents:
diff changeset
81
kono
parents:
diff changeset
82 #define FOR_EACH_IMM_USE_STMT(STMT, ITER, SSAVAR) \
kono
parents:
diff changeset
83 for ((STMT) = first_imm_use_stmt (&(ITER), (SSAVAR)); \
kono
parents:
diff changeset
84 !end_imm_use_stmt_p (&(ITER)); \
kono
parents:
diff changeset
85 (void) ((STMT) = next_imm_use_stmt (&(ITER))))
kono
parents:
diff changeset
86
kono
parents:
diff changeset
87 /* Use this to terminate the FOR_EACH_IMM_USE_STMT loop early. Failure to
kono
parents:
diff changeset
88 do so will result in leaving a iterator marker node in the immediate
kono
parents:
diff changeset
89 use list, and nothing good will come from that. */
kono
parents:
diff changeset
90 #define BREAK_FROM_IMM_USE_STMT(ITER) \
kono
parents:
diff changeset
91 { \
kono
parents:
diff changeset
92 end_imm_use_stmt_traverse (&(ITER)); \
kono
parents:
diff changeset
93 break; \
kono
parents:
diff changeset
94 }
kono
parents:
diff changeset
95
kono
parents:
diff changeset
96
kono
parents:
diff changeset
97 /* Use this iterator in combination with FOR_EACH_IMM_USE_STMT to
kono
parents:
diff changeset
98 get access to each occurrence of ssavar on the stmt returned by
kono
parents:
diff changeset
99 that iterator.. for instance:
kono
parents:
diff changeset
100
kono
parents:
diff changeset
101 FOR_EACH_IMM_USE_STMT (stmt, iter, ssavar)
kono
parents:
diff changeset
102 {
kono
parents:
diff changeset
103 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
kono
parents:
diff changeset
104 {
kono
parents:
diff changeset
105 SET_USE (use_p, blah);
kono
parents:
diff changeset
106 }
kono
parents:
diff changeset
107 update_stmt (stmt);
kono
parents:
diff changeset
108 } */
kono
parents:
diff changeset
109
kono
parents:
diff changeset
110 #define FOR_EACH_IMM_USE_ON_STMT(DEST, ITER) \
kono
parents:
diff changeset
111 for ((DEST) = first_imm_use_on_stmt (&(ITER)); \
kono
parents:
diff changeset
112 !end_imm_use_on_stmt_p (&(ITER)); \
kono
parents:
diff changeset
113 (void) ((DEST) = next_imm_use_on_stmt (&(ITER))))
kono
parents:
diff changeset
114
kono
parents:
diff changeset
115
kono
parents:
diff changeset
116
kono
parents:
diff changeset
117 extern bool single_imm_use_1 (const ssa_use_operand_t *head,
kono
parents:
diff changeset
118 use_operand_p *use_p, gimple **stmt);
kono
parents:
diff changeset
119
kono
parents:
diff changeset
120
kono
parents:
diff changeset
121 enum ssa_op_iter_type {
kono
parents:
diff changeset
122 ssa_op_iter_none = 0,
kono
parents:
diff changeset
123 ssa_op_iter_tree,
kono
parents:
diff changeset
124 ssa_op_iter_use,
kono
parents:
diff changeset
125 ssa_op_iter_def
kono
parents:
diff changeset
126 };
kono
parents:
diff changeset
127
kono
parents:
diff changeset
128 /* This structure is used in the operand iterator loops. It contains the
kono
parents:
diff changeset
129 items required to determine which operand is retrieved next. During
kono
parents:
diff changeset
130 optimization, this structure is scalarized, and any unused fields are
kono
parents:
diff changeset
131 optimized away, resulting in little overhead. */
kono
parents:
diff changeset
132
kono
parents:
diff changeset
133 struct ssa_op_iter
kono
parents:
diff changeset
134 {
kono
parents:
diff changeset
135 enum ssa_op_iter_type iter_type;
kono
parents:
diff changeset
136 bool done;
kono
parents:
diff changeset
137 int flags;
kono
parents:
diff changeset
138 unsigned i;
kono
parents:
diff changeset
139 unsigned numops;
kono
parents:
diff changeset
140 use_optype_p uses;
kono
parents:
diff changeset
141 gimple *stmt;
kono
parents:
diff changeset
142 };
kono
parents:
diff changeset
143
kono
parents:
diff changeset
144 /* NOTE: Keep these in sync with doc/tree-ssa.texi. */
kono
parents:
diff changeset
145 /* These flags are used to determine which operands are returned during
kono
parents:
diff changeset
146 execution of the loop. */
kono
parents:
diff changeset
147 #define SSA_OP_USE 0x01 /* Real USE operands. */
kono
parents:
diff changeset
148 #define SSA_OP_DEF 0x02 /* Real DEF operands. */
kono
parents:
diff changeset
149 #define SSA_OP_VUSE 0x04 /* VUSE operands. */
kono
parents:
diff changeset
150 #define SSA_OP_VDEF 0x08 /* VDEF operands. */
kono
parents:
diff changeset
151 /* These are commonly grouped operand flags. */
kono
parents:
diff changeset
152 #define SSA_OP_VIRTUAL_USES (SSA_OP_VUSE)
kono
parents:
diff changeset
153 #define SSA_OP_VIRTUAL_DEFS (SSA_OP_VDEF)
kono
parents:
diff changeset
154 #define SSA_OP_ALL_VIRTUALS (SSA_OP_VIRTUAL_USES | SSA_OP_VIRTUAL_DEFS)
kono
parents:
diff changeset
155 #define SSA_OP_ALL_USES (SSA_OP_VIRTUAL_USES | SSA_OP_USE)
kono
parents:
diff changeset
156 #define SSA_OP_ALL_DEFS (SSA_OP_VIRTUAL_DEFS | SSA_OP_DEF)
kono
parents:
diff changeset
157 #define SSA_OP_ALL_OPERANDS (SSA_OP_ALL_USES | SSA_OP_ALL_DEFS)
kono
parents:
diff changeset
158
kono
parents:
diff changeset
159 /* This macro executes a loop over the operands of STMT specified in FLAG,
kono
parents:
diff changeset
160 returning each operand as a 'tree' in the variable TREEVAR. ITER is an
kono
parents:
diff changeset
161 ssa_op_iter structure used to control the loop. */
kono
parents:
diff changeset
162 #define FOR_EACH_SSA_TREE_OPERAND(TREEVAR, STMT, ITER, FLAGS) \
kono
parents:
diff changeset
163 for (TREEVAR = op_iter_init_tree (&(ITER), STMT, FLAGS); \
kono
parents:
diff changeset
164 !op_iter_done (&(ITER)); \
kono
parents:
diff changeset
165 (void) (TREEVAR = op_iter_next_tree (&(ITER))))
kono
parents:
diff changeset
166
kono
parents:
diff changeset
167 /* This macro executes a loop over the operands of STMT specified in FLAG,
kono
parents:
diff changeset
168 returning each operand as a 'use_operand_p' in the variable USEVAR.
kono
parents:
diff changeset
169 ITER is an ssa_op_iter structure used to control the loop. */
kono
parents:
diff changeset
170 #define FOR_EACH_SSA_USE_OPERAND(USEVAR, STMT, ITER, FLAGS) \
kono
parents:
diff changeset
171 for (USEVAR = op_iter_init_use (&(ITER), STMT, FLAGS); \
kono
parents:
diff changeset
172 !op_iter_done (&(ITER)); \
kono
parents:
diff changeset
173 USEVAR = op_iter_next_use (&(ITER)))
kono
parents:
diff changeset
174
kono
parents:
diff changeset
175 /* This macro executes a loop over the operands of STMT specified in FLAG,
kono
parents:
diff changeset
176 returning each operand as a 'def_operand_p' in the variable DEFVAR.
kono
parents:
diff changeset
177 ITER is an ssa_op_iter structure used to control the loop. */
kono
parents:
diff changeset
178 #define FOR_EACH_SSA_DEF_OPERAND(DEFVAR, STMT, ITER, FLAGS) \
kono
parents:
diff changeset
179 for (DEFVAR = op_iter_init_def (&(ITER), STMT, FLAGS); \
kono
parents:
diff changeset
180 !op_iter_done (&(ITER)); \
kono
parents:
diff changeset
181 DEFVAR = op_iter_next_def (&(ITER)))
kono
parents:
diff changeset
182
kono
parents:
diff changeset
183 /* This macro will execute a loop over all the arguments of a PHI which
kono
parents:
diff changeset
184 match FLAGS. A use_operand_p is always returned via USEVAR. FLAGS
kono
parents:
diff changeset
185 can be either SSA_OP_USE or SSA_OP_VIRTUAL_USES or SSA_OP_ALL_USES. */
kono
parents:
diff changeset
186 #define FOR_EACH_PHI_ARG(USEVAR, STMT, ITER, FLAGS) \
kono
parents:
diff changeset
187 for ((USEVAR) = op_iter_init_phiuse (&(ITER), STMT, FLAGS); \
kono
parents:
diff changeset
188 !op_iter_done (&(ITER)); \
kono
parents:
diff changeset
189 (USEVAR) = op_iter_next_use (&(ITER)))
kono
parents:
diff changeset
190
kono
parents:
diff changeset
191
kono
parents:
diff changeset
192 /* This macro will execute a loop over a stmt, regardless of whether it is
kono
parents:
diff changeset
193 a real stmt or a PHI node, looking at the USE nodes matching FLAGS. */
kono
parents:
diff changeset
194 #define FOR_EACH_PHI_OR_STMT_USE(USEVAR, STMT, ITER, FLAGS) \
kono
parents:
diff changeset
195 for ((USEVAR) = (gimple_code (STMT) == GIMPLE_PHI \
kono
parents:
diff changeset
196 ? op_iter_init_phiuse (&(ITER), \
kono
parents:
diff changeset
197 as_a <gphi *> (STMT), \
kono
parents:
diff changeset
198 FLAGS) \
kono
parents:
diff changeset
199 : op_iter_init_use (&(ITER), STMT, FLAGS)); \
kono
parents:
diff changeset
200 !op_iter_done (&(ITER)); \
kono
parents:
diff changeset
201 (USEVAR) = op_iter_next_use (&(ITER)))
kono
parents:
diff changeset
202
kono
parents:
diff changeset
203 /* This macro will execute a loop over a stmt, regardless of whether it is
kono
parents:
diff changeset
204 a real stmt or a PHI node, looking at the DEF nodes matching FLAGS. */
kono
parents:
diff changeset
205 #define FOR_EACH_PHI_OR_STMT_DEF(DEFVAR, STMT, ITER, FLAGS) \
kono
parents:
diff changeset
206 for ((DEFVAR) = (gimple_code (STMT) == GIMPLE_PHI \
kono
parents:
diff changeset
207 ? op_iter_init_phidef (&(ITER), \
kono
parents:
diff changeset
208 as_a <gphi *> (STMT), \
kono
parents:
diff changeset
209 FLAGS) \
kono
parents:
diff changeset
210 : op_iter_init_def (&(ITER), STMT, FLAGS)); \
kono
parents:
diff changeset
211 !op_iter_done (&(ITER)); \
kono
parents:
diff changeset
212 (DEFVAR) = op_iter_next_def (&(ITER)))
kono
parents:
diff changeset
213
kono
parents:
diff changeset
214 /* This macro returns an operand in STMT as a tree if it is the ONLY
kono
parents:
diff changeset
215 operand matching FLAGS. If there are 0 or more than 1 operand matching
kono
parents:
diff changeset
216 FLAGS, then NULL_TREE is returned. */
kono
parents:
diff changeset
217 #define SINGLE_SSA_TREE_OPERAND(STMT, FLAGS) \
kono
parents:
diff changeset
218 single_ssa_tree_operand (STMT, FLAGS)
kono
parents:
diff changeset
219
kono
parents:
diff changeset
220 /* This macro returns an operand in STMT as a use_operand_p if it is the ONLY
kono
parents:
diff changeset
221 operand matching FLAGS. If there are 0 or more than 1 operand matching
kono
parents:
diff changeset
222 FLAGS, then NULL_USE_OPERAND_P is returned. */
kono
parents:
diff changeset
223 #define SINGLE_SSA_USE_OPERAND(STMT, FLAGS) \
kono
parents:
diff changeset
224 single_ssa_use_operand (STMT, FLAGS)
kono
parents:
diff changeset
225
kono
parents:
diff changeset
226 /* This macro returns an operand in STMT as a def_operand_p if it is the ONLY
kono
parents:
diff changeset
227 operand matching FLAGS. If there are 0 or more than 1 operand matching
kono
parents:
diff changeset
228 FLAGS, then NULL_DEF_OPERAND_P is returned. */
kono
parents:
diff changeset
229 #define SINGLE_SSA_DEF_OPERAND(STMT, FLAGS) \
kono
parents:
diff changeset
230 single_ssa_def_operand (STMT, FLAGS)
kono
parents:
diff changeset
231
kono
parents:
diff changeset
232 /* This macro returns TRUE if there are no operands matching FLAGS in STMT. */
kono
parents:
diff changeset
233 #define ZERO_SSA_OPERANDS(STMT, FLAGS) zero_ssa_operands (STMT, FLAGS)
kono
parents:
diff changeset
234
kono
parents:
diff changeset
235 /* This macro counts the number of operands in STMT matching FLAGS. */
kono
parents:
diff changeset
236 #define NUM_SSA_OPERANDS(STMT, FLAGS) num_ssa_operands (STMT, FLAGS)
kono
parents:
diff changeset
237
kono
parents:
diff changeset
238
kono
parents:
diff changeset
239 /* Delink an immediate_uses node from its chain. */
kono
parents:
diff changeset
240 static inline void
kono
parents:
diff changeset
241 delink_imm_use (ssa_use_operand_t *linknode)
kono
parents:
diff changeset
242 {
kono
parents:
diff changeset
243 /* Return if this node is not in a list. */
kono
parents:
diff changeset
244 if (linknode->prev == NULL)
kono
parents:
diff changeset
245 return;
kono
parents:
diff changeset
246
kono
parents:
diff changeset
247 linknode->prev->next = linknode->next;
kono
parents:
diff changeset
248 linknode->next->prev = linknode->prev;
kono
parents:
diff changeset
249 linknode->prev = NULL;
kono
parents:
diff changeset
250 linknode->next = NULL;
kono
parents:
diff changeset
251 }
kono
parents:
diff changeset
252
kono
parents:
diff changeset
253 /* Link ssa_imm_use node LINKNODE into the chain for LIST. */
kono
parents:
diff changeset
254 static inline void
kono
parents:
diff changeset
255 link_imm_use_to_list (ssa_use_operand_t *linknode, ssa_use_operand_t *list)
kono
parents:
diff changeset
256 {
kono
parents:
diff changeset
257 /* Link the new node at the head of the list. If we are in the process of
kono
parents:
diff changeset
258 traversing the list, we won't visit any new nodes added to it. */
kono
parents:
diff changeset
259 linknode->prev = list;
kono
parents:
diff changeset
260 linknode->next = list->next;
kono
parents:
diff changeset
261 list->next->prev = linknode;
kono
parents:
diff changeset
262 list->next = linknode;
kono
parents:
diff changeset
263 }
kono
parents:
diff changeset
264
kono
parents:
diff changeset
265 /* Link ssa_imm_use node LINKNODE into the chain for DEF. */
kono
parents:
diff changeset
266 static inline void
kono
parents:
diff changeset
267 link_imm_use (ssa_use_operand_t *linknode, tree def)
kono
parents:
diff changeset
268 {
kono
parents:
diff changeset
269 ssa_use_operand_t *root;
kono
parents:
diff changeset
270
kono
parents:
diff changeset
271 if (!def || TREE_CODE (def) != SSA_NAME)
kono
parents:
diff changeset
272 linknode->prev = NULL;
kono
parents:
diff changeset
273 else
kono
parents:
diff changeset
274 {
kono
parents:
diff changeset
275 root = &(SSA_NAME_IMM_USE_NODE (def));
kono
parents:
diff changeset
276 if (linknode->use)
kono
parents:
diff changeset
277 gcc_checking_assert (*(linknode->use) == def);
kono
parents:
diff changeset
278 link_imm_use_to_list (linknode, root);
kono
parents:
diff changeset
279 }
kono
parents:
diff changeset
280 }
kono
parents:
diff changeset
281
kono
parents:
diff changeset
282 /* Set the value of a use pointed to by USE to VAL. */
kono
parents:
diff changeset
283 static inline void
kono
parents:
diff changeset
284 set_ssa_use_from_ptr (use_operand_p use, tree val)
kono
parents:
diff changeset
285 {
kono
parents:
diff changeset
286 delink_imm_use (use);
kono
parents:
diff changeset
287 *(use->use) = val;
kono
parents:
diff changeset
288 link_imm_use (use, val);
kono
parents:
diff changeset
289 }
kono
parents:
diff changeset
290
kono
parents:
diff changeset
291 /* Link ssa_imm_use node LINKNODE into the chain for DEF, with use occurring
kono
parents:
diff changeset
292 in STMT. */
kono
parents:
diff changeset
293 static inline void
kono
parents:
diff changeset
294 link_imm_use_stmt (ssa_use_operand_t *linknode, tree def, gimple *stmt)
kono
parents:
diff changeset
295 {
kono
parents:
diff changeset
296 if (stmt)
kono
parents:
diff changeset
297 link_imm_use (linknode, def);
kono
parents:
diff changeset
298 else
kono
parents:
diff changeset
299 link_imm_use (linknode, NULL);
kono
parents:
diff changeset
300 linknode->loc.stmt = stmt;
kono
parents:
diff changeset
301 }
kono
parents:
diff changeset
302
kono
parents:
diff changeset
303 /* Relink a new node in place of an old node in the list. */
kono
parents:
diff changeset
304 static inline void
kono
parents:
diff changeset
305 relink_imm_use (ssa_use_operand_t *node, ssa_use_operand_t *old)
kono
parents:
diff changeset
306 {
kono
parents:
diff changeset
307 /* The node one had better be in the same list. */
kono
parents:
diff changeset
308 gcc_checking_assert (*(old->use) == *(node->use));
kono
parents:
diff changeset
309 node->prev = old->prev;
kono
parents:
diff changeset
310 node->next = old->next;
kono
parents:
diff changeset
311 if (old->prev)
kono
parents:
diff changeset
312 {
kono
parents:
diff changeset
313 old->prev->next = node;
kono
parents:
diff changeset
314 old->next->prev = node;
kono
parents:
diff changeset
315 /* Remove the old node from the list. */
kono
parents:
diff changeset
316 old->prev = NULL;
kono
parents:
diff changeset
317 }
kono
parents:
diff changeset
318 }
kono
parents:
diff changeset
319
kono
parents:
diff changeset
320 /* Relink ssa_imm_use node LINKNODE into the chain for OLD, with use occurring
kono
parents:
diff changeset
321 in STMT. */
kono
parents:
diff changeset
322 static inline void
kono
parents:
diff changeset
323 relink_imm_use_stmt (ssa_use_operand_t *linknode, ssa_use_operand_t *old,
kono
parents:
diff changeset
324 gimple *stmt)
kono
parents:
diff changeset
325 {
kono
parents:
diff changeset
326 if (stmt)
kono
parents:
diff changeset
327 relink_imm_use (linknode, old);
kono
parents:
diff changeset
328 else
kono
parents:
diff changeset
329 link_imm_use (linknode, NULL);
kono
parents:
diff changeset
330 linknode->loc.stmt = stmt;
kono
parents:
diff changeset
331 }
kono
parents:
diff changeset
332
kono
parents:
diff changeset
333
kono
parents:
diff changeset
334 /* Return true is IMM has reached the end of the immediate use list. */
kono
parents:
diff changeset
335 static inline bool
kono
parents:
diff changeset
336 end_readonly_imm_use_p (const imm_use_iterator *imm)
kono
parents:
diff changeset
337 {
kono
parents:
diff changeset
338 return (imm->imm_use == imm->end_p);
kono
parents:
diff changeset
339 }
kono
parents:
diff changeset
340
kono
parents:
diff changeset
341 /* Initialize iterator IMM to process the list for VAR. */
kono
parents:
diff changeset
342 static inline use_operand_p
kono
parents:
diff changeset
343 first_readonly_imm_use (imm_use_iterator *imm, tree var)
kono
parents:
diff changeset
344 {
kono
parents:
diff changeset
345 imm->end_p = &(SSA_NAME_IMM_USE_NODE (var));
kono
parents:
diff changeset
346 imm->imm_use = imm->end_p->next;
kono
parents:
diff changeset
347 imm->iter_node.next = imm->imm_use->next;
kono
parents:
diff changeset
348 if (end_readonly_imm_use_p (imm))
kono
parents:
diff changeset
349 return NULL_USE_OPERAND_P;
kono
parents:
diff changeset
350 return imm->imm_use;
kono
parents:
diff changeset
351 }
kono
parents:
diff changeset
352
kono
parents:
diff changeset
353 /* Bump IMM to the next use in the list. */
kono
parents:
diff changeset
354 static inline use_operand_p
kono
parents:
diff changeset
355 next_readonly_imm_use (imm_use_iterator *imm)
kono
parents:
diff changeset
356 {
kono
parents:
diff changeset
357 use_operand_p old = imm->imm_use;
kono
parents:
diff changeset
358
kono
parents:
diff changeset
359 /* If this assertion fails, it indicates the 'next' pointer has changed
kono
parents:
diff changeset
360 since the last bump. This indicates that the list is being modified
kono
parents:
diff changeset
361 via stmt changes, or SET_USE, or somesuch thing, and you need to be
kono
parents:
diff changeset
362 using the SAFE version of the iterator. */
kono
parents:
diff changeset
363 if (flag_checking)
kono
parents:
diff changeset
364 {
kono
parents:
diff changeset
365 gcc_assert (imm->iter_node.next == old->next);
kono
parents:
diff changeset
366 imm->iter_node.next = old->next->next;
kono
parents:
diff changeset
367 }
kono
parents:
diff changeset
368
kono
parents:
diff changeset
369 imm->imm_use = old->next;
kono
parents:
diff changeset
370 if (end_readonly_imm_use_p (imm))
kono
parents:
diff changeset
371 return NULL_USE_OPERAND_P;
kono
parents:
diff changeset
372 return imm->imm_use;
kono
parents:
diff changeset
373 }
kono
parents:
diff changeset
374
kono
parents:
diff changeset
375
kono
parents:
diff changeset
376 /* Return true if VAR has no nondebug uses. */
kono
parents:
diff changeset
377 static inline bool
kono
parents:
diff changeset
378 has_zero_uses (const_tree var)
kono
parents:
diff changeset
379 {
kono
parents:
diff changeset
380 const ssa_use_operand_t *const head = &(SSA_NAME_IMM_USE_NODE (var));
kono
parents:
diff changeset
381 const ssa_use_operand_t *ptr;
kono
parents:
diff changeset
382
kono
parents:
diff changeset
383 for (ptr = head->next; ptr != head; ptr = ptr->next)
kono
parents:
diff changeset
384 if (USE_STMT (ptr) && !is_gimple_debug (USE_STMT (ptr)))
kono
parents:
diff changeset
385 return false;
kono
parents:
diff changeset
386
kono
parents:
diff changeset
387 return true;
kono
parents:
diff changeset
388 }
kono
parents:
diff changeset
389
kono
parents:
diff changeset
390 /* Return true if VAR has a single nondebug use. */
kono
parents:
diff changeset
391 static inline bool
kono
parents:
diff changeset
392 has_single_use (const_tree var)
kono
parents:
diff changeset
393 {
kono
parents:
diff changeset
394 const ssa_use_operand_t *const head = &(SSA_NAME_IMM_USE_NODE (var));
kono
parents:
diff changeset
395 const ssa_use_operand_t *ptr;
kono
parents:
diff changeset
396 bool single = false;
kono
parents:
diff changeset
397
kono
parents:
diff changeset
398 for (ptr = head->next; ptr != head; ptr = ptr->next)
kono
parents:
diff changeset
399 if (USE_STMT(ptr) && !is_gimple_debug (USE_STMT (ptr)))
kono
parents:
diff changeset
400 {
kono
parents:
diff changeset
401 if (single)
kono
parents:
diff changeset
402 return false;
kono
parents:
diff changeset
403 else
kono
parents:
diff changeset
404 single = true;
kono
parents:
diff changeset
405 }
kono
parents:
diff changeset
406
kono
parents:
diff changeset
407 return single;
kono
parents:
diff changeset
408 }
kono
parents:
diff changeset
409
kono
parents:
diff changeset
410 /* If VAR has only a single immediate nondebug use, return true, and
kono
parents:
diff changeset
411 set USE_P and STMT to the use pointer and stmt of occurrence. */
kono
parents:
diff changeset
412 static inline bool
kono
parents:
diff changeset
413 single_imm_use (const_tree var, use_operand_p *use_p, gimple **stmt)
kono
parents:
diff changeset
414 {
kono
parents:
diff changeset
415 const ssa_use_operand_t *const ptr = &(SSA_NAME_IMM_USE_NODE (var));
kono
parents:
diff changeset
416
kono
parents:
diff changeset
417 /* If there aren't any uses whatsoever, we're done. */
kono
parents:
diff changeset
418 if (ptr == ptr->next)
kono
parents:
diff changeset
419 {
kono
parents:
diff changeset
420 return_false:
kono
parents:
diff changeset
421 *use_p = NULL_USE_OPERAND_P;
kono
parents:
diff changeset
422 *stmt = NULL;
kono
parents:
diff changeset
423 return false;
kono
parents:
diff changeset
424 }
kono
parents:
diff changeset
425
kono
parents:
diff changeset
426 /* If there's a single use, check that it's not a debug stmt. */
kono
parents:
diff changeset
427 if (ptr == ptr->next->next)
kono
parents:
diff changeset
428 {
kono
parents:
diff changeset
429 if (USE_STMT (ptr->next) && !is_gimple_debug (USE_STMT (ptr->next)))
kono
parents:
diff changeset
430 {
kono
parents:
diff changeset
431 *use_p = ptr->next;
kono
parents:
diff changeset
432 *stmt = ptr->next->loc.stmt;
kono
parents:
diff changeset
433 return true;
kono
parents:
diff changeset
434 }
kono
parents:
diff changeset
435 else
kono
parents:
diff changeset
436 goto return_false;
kono
parents:
diff changeset
437 }
kono
parents:
diff changeset
438
kono
parents:
diff changeset
439 return single_imm_use_1 (ptr, use_p, stmt);
kono
parents:
diff changeset
440 }
kono
parents:
diff changeset
441
kono
parents:
diff changeset
442 /* Return the number of nondebug immediate uses of VAR. */
kono
parents:
diff changeset
443 static inline unsigned int
kono
parents:
diff changeset
444 num_imm_uses (const_tree var)
kono
parents:
diff changeset
445 {
kono
parents:
diff changeset
446 const ssa_use_operand_t *const start = &(SSA_NAME_IMM_USE_NODE (var));
kono
parents:
diff changeset
447 const ssa_use_operand_t *ptr;
kono
parents:
diff changeset
448 unsigned int num = 0;
kono
parents:
diff changeset
449
kono
parents:
diff changeset
450 if (!MAY_HAVE_DEBUG_STMTS)
kono
parents:
diff changeset
451 {
kono
parents:
diff changeset
452 for (ptr = start->next; ptr != start; ptr = ptr->next)
kono
parents:
diff changeset
453 if (USE_STMT (ptr))
kono
parents:
diff changeset
454 num++;
kono
parents:
diff changeset
455 }
kono
parents:
diff changeset
456 else
kono
parents:
diff changeset
457 for (ptr = start->next; ptr != start; ptr = ptr->next)
kono
parents:
diff changeset
458 if (USE_STMT (ptr) && !is_gimple_debug (USE_STMT (ptr)))
kono
parents:
diff changeset
459 num++;
kono
parents:
diff changeset
460
kono
parents:
diff changeset
461 return num;
kono
parents:
diff changeset
462 }
kono
parents:
diff changeset
463
kono
parents:
diff changeset
464 /* ----------------------------------------------------------------------- */
kono
parents:
diff changeset
465
kono
parents:
diff changeset
466 /* The following set of routines are used to iterator over various type of
kono
parents:
diff changeset
467 SSA operands. */
kono
parents:
diff changeset
468
kono
parents:
diff changeset
469 /* Return true if PTR is finished iterating. */
kono
parents:
diff changeset
470 static inline bool
kono
parents:
diff changeset
471 op_iter_done (const ssa_op_iter *ptr)
kono
parents:
diff changeset
472 {
kono
parents:
diff changeset
473 return ptr->done;
kono
parents:
diff changeset
474 }
kono
parents:
diff changeset
475
kono
parents:
diff changeset
476 /* Get the next iterator use value for PTR. */
kono
parents:
diff changeset
477 static inline use_operand_p
kono
parents:
diff changeset
478 op_iter_next_use (ssa_op_iter *ptr)
kono
parents:
diff changeset
479 {
kono
parents:
diff changeset
480 use_operand_p use_p;
kono
parents:
diff changeset
481 gcc_checking_assert (ptr->iter_type == ssa_op_iter_use);
kono
parents:
diff changeset
482 if (ptr->uses)
kono
parents:
diff changeset
483 {
kono
parents:
diff changeset
484 use_p = USE_OP_PTR (ptr->uses);
kono
parents:
diff changeset
485 ptr->uses = ptr->uses->next;
kono
parents:
diff changeset
486 return use_p;
kono
parents:
diff changeset
487 }
kono
parents:
diff changeset
488 if (ptr->i < ptr->numops)
kono
parents:
diff changeset
489 {
kono
parents:
diff changeset
490 return PHI_ARG_DEF_PTR (ptr->stmt, (ptr->i)++);
kono
parents:
diff changeset
491 }
kono
parents:
diff changeset
492 ptr->done = true;
kono
parents:
diff changeset
493 return NULL_USE_OPERAND_P;
kono
parents:
diff changeset
494 }
kono
parents:
diff changeset
495
kono
parents:
diff changeset
496 /* Get the next iterator def value for PTR. */
kono
parents:
diff changeset
497 static inline def_operand_p
kono
parents:
diff changeset
498 op_iter_next_def (ssa_op_iter *ptr)
kono
parents:
diff changeset
499 {
kono
parents:
diff changeset
500 gcc_checking_assert (ptr->iter_type == ssa_op_iter_def);
kono
parents:
diff changeset
501 if (ptr->flags & SSA_OP_VDEF)
kono
parents:
diff changeset
502 {
kono
parents:
diff changeset
503 tree *p;
kono
parents:
diff changeset
504 ptr->flags &= ~SSA_OP_VDEF;
kono
parents:
diff changeset
505 p = gimple_vdef_ptr (ptr->stmt);
kono
parents:
diff changeset
506 if (p && *p)
kono
parents:
diff changeset
507 return p;
kono
parents:
diff changeset
508 }
kono
parents:
diff changeset
509 if (ptr->flags & SSA_OP_DEF)
kono
parents:
diff changeset
510 {
kono
parents:
diff changeset
511 while (ptr->i < ptr->numops)
kono
parents:
diff changeset
512 {
kono
parents:
diff changeset
513 tree *val = gimple_op_ptr (ptr->stmt, ptr->i);
kono
parents:
diff changeset
514 ptr->i++;
kono
parents:
diff changeset
515 if (*val)
kono
parents:
diff changeset
516 {
kono
parents:
diff changeset
517 if (TREE_CODE (*val) == TREE_LIST)
kono
parents:
diff changeset
518 val = &TREE_VALUE (*val);
kono
parents:
diff changeset
519 if (TREE_CODE (*val) == SSA_NAME
kono
parents:
diff changeset
520 || is_gimple_reg (*val))
kono
parents:
diff changeset
521 return val;
kono
parents:
diff changeset
522 }
kono
parents:
diff changeset
523 }
kono
parents:
diff changeset
524 ptr->flags &= ~SSA_OP_DEF;
kono
parents:
diff changeset
525 }
kono
parents:
diff changeset
526
kono
parents:
diff changeset
527 ptr->done = true;
kono
parents:
diff changeset
528 return NULL_DEF_OPERAND_P;
kono
parents:
diff changeset
529 }
kono
parents:
diff changeset
530
kono
parents:
diff changeset
531 /* Get the next iterator tree value for PTR. */
kono
parents:
diff changeset
532 static inline tree
kono
parents:
diff changeset
533 op_iter_next_tree (ssa_op_iter *ptr)
kono
parents:
diff changeset
534 {
kono
parents:
diff changeset
535 tree val;
kono
parents:
diff changeset
536 gcc_checking_assert (ptr->iter_type == ssa_op_iter_tree);
kono
parents:
diff changeset
537 if (ptr->uses)
kono
parents:
diff changeset
538 {
kono
parents:
diff changeset
539 val = USE_OP (ptr->uses);
kono
parents:
diff changeset
540 ptr->uses = ptr->uses->next;
kono
parents:
diff changeset
541 return val;
kono
parents:
diff changeset
542 }
kono
parents:
diff changeset
543 if (ptr->flags & SSA_OP_VDEF)
kono
parents:
diff changeset
544 {
kono
parents:
diff changeset
545 ptr->flags &= ~SSA_OP_VDEF;
kono
parents:
diff changeset
546 if ((val = gimple_vdef (ptr->stmt)))
kono
parents:
diff changeset
547 return val;
kono
parents:
diff changeset
548 }
kono
parents:
diff changeset
549 if (ptr->flags & SSA_OP_DEF)
kono
parents:
diff changeset
550 {
kono
parents:
diff changeset
551 while (ptr->i < ptr->numops)
kono
parents:
diff changeset
552 {
kono
parents:
diff changeset
553 val = gimple_op (ptr->stmt, ptr->i);
kono
parents:
diff changeset
554 ptr->i++;
kono
parents:
diff changeset
555 if (val)
kono
parents:
diff changeset
556 {
kono
parents:
diff changeset
557 if (TREE_CODE (val) == TREE_LIST)
kono
parents:
diff changeset
558 val = TREE_VALUE (val);
kono
parents:
diff changeset
559 if (TREE_CODE (val) == SSA_NAME
kono
parents:
diff changeset
560 || is_gimple_reg (val))
kono
parents:
diff changeset
561 return val;
kono
parents:
diff changeset
562 }
kono
parents:
diff changeset
563 }
kono
parents:
diff changeset
564 ptr->flags &= ~SSA_OP_DEF;
kono
parents:
diff changeset
565 }
kono
parents:
diff changeset
566
kono
parents:
diff changeset
567 ptr->done = true;
kono
parents:
diff changeset
568 return NULL_TREE;
kono
parents:
diff changeset
569 }
kono
parents:
diff changeset
570
kono
parents:
diff changeset
571
kono
parents:
diff changeset
572 /* This functions clears the iterator PTR, and marks it done. This is normally
kono
parents:
diff changeset
573 used to prevent warnings in the compile about might be uninitialized
kono
parents:
diff changeset
574 components. */
kono
parents:
diff changeset
575
kono
parents:
diff changeset
576 static inline void
kono
parents:
diff changeset
577 clear_and_done_ssa_iter (ssa_op_iter *ptr)
kono
parents:
diff changeset
578 {
kono
parents:
diff changeset
579 ptr->i = 0;
kono
parents:
diff changeset
580 ptr->numops = 0;
kono
parents:
diff changeset
581 ptr->uses = NULL;
kono
parents:
diff changeset
582 ptr->iter_type = ssa_op_iter_none;
kono
parents:
diff changeset
583 ptr->stmt = NULL;
kono
parents:
diff changeset
584 ptr->done = true;
kono
parents:
diff changeset
585 ptr->flags = 0;
kono
parents:
diff changeset
586 }
kono
parents:
diff changeset
587
kono
parents:
diff changeset
588 /* Initialize the iterator PTR to the virtual defs in STMT. */
kono
parents:
diff changeset
589 static inline void
kono
parents:
diff changeset
590 op_iter_init (ssa_op_iter *ptr, gimple *stmt, int flags)
kono
parents:
diff changeset
591 {
kono
parents:
diff changeset
592 /* PHI nodes require a different iterator initialization path. We
kono
parents:
diff changeset
593 do not support iterating over virtual defs or uses without
kono
parents:
diff changeset
594 iterating over defs or uses at the same time. */
kono
parents:
diff changeset
595 gcc_checking_assert (gimple_code (stmt) != GIMPLE_PHI
kono
parents:
diff changeset
596 && (!(flags & SSA_OP_VDEF) || (flags & SSA_OP_DEF))
kono
parents:
diff changeset
597 && (!(flags & SSA_OP_VUSE) || (flags & SSA_OP_USE)));
kono
parents:
diff changeset
598 ptr->numops = 0;
kono
parents:
diff changeset
599 if (flags & (SSA_OP_DEF | SSA_OP_VDEF))
kono
parents:
diff changeset
600 {
kono
parents:
diff changeset
601 switch (gimple_code (stmt))
kono
parents:
diff changeset
602 {
kono
parents:
diff changeset
603 case GIMPLE_ASSIGN:
kono
parents:
diff changeset
604 case GIMPLE_CALL:
kono
parents:
diff changeset
605 ptr->numops = 1;
kono
parents:
diff changeset
606 break;
kono
parents:
diff changeset
607 case GIMPLE_ASM:
kono
parents:
diff changeset
608 ptr->numops = gimple_asm_noutputs (as_a <gasm *> (stmt));
kono
parents:
diff changeset
609 break;
kono
parents:
diff changeset
610 case GIMPLE_TRANSACTION:
kono
parents:
diff changeset
611 ptr->numops = 0;
kono
parents:
diff changeset
612 flags &= ~SSA_OP_DEF;
kono
parents:
diff changeset
613 break;
kono
parents:
diff changeset
614 default:
kono
parents:
diff changeset
615 ptr->numops = 0;
kono
parents:
diff changeset
616 flags &= ~(SSA_OP_DEF | SSA_OP_VDEF);
kono
parents:
diff changeset
617 break;
kono
parents:
diff changeset
618 }
kono
parents:
diff changeset
619 }
kono
parents:
diff changeset
620 ptr->uses = (flags & (SSA_OP_USE|SSA_OP_VUSE)) ? gimple_use_ops (stmt) : NULL;
kono
parents:
diff changeset
621 if (!(flags & SSA_OP_VUSE)
kono
parents:
diff changeset
622 && ptr->uses
kono
parents:
diff changeset
623 && gimple_vuse (stmt) != NULL_TREE)
kono
parents:
diff changeset
624 ptr->uses = ptr->uses->next;
kono
parents:
diff changeset
625 ptr->done = false;
kono
parents:
diff changeset
626 ptr->i = 0;
kono
parents:
diff changeset
627
kono
parents:
diff changeset
628 ptr->stmt = stmt;
kono
parents:
diff changeset
629 ptr->flags = flags;
kono
parents:
diff changeset
630 }
kono
parents:
diff changeset
631
kono
parents:
diff changeset
632 /* Initialize iterator PTR to the use operands in STMT based on FLAGS. Return
kono
parents:
diff changeset
633 the first use. */
kono
parents:
diff changeset
634 static inline use_operand_p
kono
parents:
diff changeset
635 op_iter_init_use (ssa_op_iter *ptr, gimple *stmt, int flags)
kono
parents:
diff changeset
636 {
kono
parents:
diff changeset
637 gcc_checking_assert ((flags & SSA_OP_ALL_DEFS) == 0
kono
parents:
diff changeset
638 && (flags & SSA_OP_USE));
kono
parents:
diff changeset
639 op_iter_init (ptr, stmt, flags);
kono
parents:
diff changeset
640 ptr->iter_type = ssa_op_iter_use;
kono
parents:
diff changeset
641 return op_iter_next_use (ptr);
kono
parents:
diff changeset
642 }
kono
parents:
diff changeset
643
kono
parents:
diff changeset
644 /* Initialize iterator PTR to the def operands in STMT based on FLAGS. Return
kono
parents:
diff changeset
645 the first def. */
kono
parents:
diff changeset
646 static inline def_operand_p
kono
parents:
diff changeset
647 op_iter_init_def (ssa_op_iter *ptr, gimple *stmt, int flags)
kono
parents:
diff changeset
648 {
kono
parents:
diff changeset
649 gcc_checking_assert ((flags & SSA_OP_ALL_USES) == 0
kono
parents:
diff changeset
650 && (flags & SSA_OP_DEF));
kono
parents:
diff changeset
651 op_iter_init (ptr, stmt, flags);
kono
parents:
diff changeset
652 ptr->iter_type = ssa_op_iter_def;
kono
parents:
diff changeset
653 return op_iter_next_def (ptr);
kono
parents:
diff changeset
654 }
kono
parents:
diff changeset
655
kono
parents:
diff changeset
656 /* Initialize iterator PTR to the operands in STMT based on FLAGS. Return
kono
parents:
diff changeset
657 the first operand as a tree. */
kono
parents:
diff changeset
658 static inline tree
kono
parents:
diff changeset
659 op_iter_init_tree (ssa_op_iter *ptr, gimple *stmt, int flags)
kono
parents:
diff changeset
660 {
kono
parents:
diff changeset
661 op_iter_init (ptr, stmt, flags);
kono
parents:
diff changeset
662 ptr->iter_type = ssa_op_iter_tree;
kono
parents:
diff changeset
663 return op_iter_next_tree (ptr);
kono
parents:
diff changeset
664 }
kono
parents:
diff changeset
665
kono
parents:
diff changeset
666
kono
parents:
diff changeset
667 /* If there is a single operand in STMT matching FLAGS, return it. Otherwise
kono
parents:
diff changeset
668 return NULL. */
kono
parents:
diff changeset
669 static inline tree
kono
parents:
diff changeset
670 single_ssa_tree_operand (gimple *stmt, int flags)
kono
parents:
diff changeset
671 {
kono
parents:
diff changeset
672 tree var;
kono
parents:
diff changeset
673 ssa_op_iter iter;
kono
parents:
diff changeset
674
kono
parents:
diff changeset
675 var = op_iter_init_tree (&iter, stmt, flags);
kono
parents:
diff changeset
676 if (op_iter_done (&iter))
kono
parents:
diff changeset
677 return NULL_TREE;
kono
parents:
diff changeset
678 op_iter_next_tree (&iter);
kono
parents:
diff changeset
679 if (op_iter_done (&iter))
kono
parents:
diff changeset
680 return var;
kono
parents:
diff changeset
681 return NULL_TREE;
kono
parents:
diff changeset
682 }
kono
parents:
diff changeset
683
kono
parents:
diff changeset
684
kono
parents:
diff changeset
685 /* If there is a single operand in STMT matching FLAGS, return it. Otherwise
kono
parents:
diff changeset
686 return NULL. */
kono
parents:
diff changeset
687 static inline use_operand_p
kono
parents:
diff changeset
688 single_ssa_use_operand (gimple *stmt, int flags)
kono
parents:
diff changeset
689 {
kono
parents:
diff changeset
690 use_operand_p var;
kono
parents:
diff changeset
691 ssa_op_iter iter;
kono
parents:
diff changeset
692
kono
parents:
diff changeset
693 var = op_iter_init_use (&iter, stmt, flags);
kono
parents:
diff changeset
694 if (op_iter_done (&iter))
kono
parents:
diff changeset
695 return NULL_USE_OPERAND_P;
kono
parents:
diff changeset
696 op_iter_next_use (&iter);
kono
parents:
diff changeset
697 if (op_iter_done (&iter))
kono
parents:
diff changeset
698 return var;
kono
parents:
diff changeset
699 return NULL_USE_OPERAND_P;
kono
parents:
diff changeset
700 }
kono
parents:
diff changeset
701
kono
parents:
diff changeset
702 /* Return the single virtual use operand in STMT if present. Otherwise
kono
parents:
diff changeset
703 return NULL. */
kono
parents:
diff changeset
704 static inline use_operand_p
kono
parents:
diff changeset
705 ssa_vuse_operand (gimple *stmt)
kono
parents:
diff changeset
706 {
kono
parents:
diff changeset
707 if (! gimple_vuse (stmt))
kono
parents:
diff changeset
708 return NULL_USE_OPERAND_P;
kono
parents:
diff changeset
709 return USE_OP_PTR (gimple_use_ops (stmt));
kono
parents:
diff changeset
710 }
kono
parents:
diff changeset
711
kono
parents:
diff changeset
712
kono
parents:
diff changeset
713 /* If there is a single operand in STMT matching FLAGS, return it. Otherwise
kono
parents:
diff changeset
714 return NULL. */
kono
parents:
diff changeset
715 static inline def_operand_p
kono
parents:
diff changeset
716 single_ssa_def_operand (gimple *stmt, int flags)
kono
parents:
diff changeset
717 {
kono
parents:
diff changeset
718 def_operand_p var;
kono
parents:
diff changeset
719 ssa_op_iter iter;
kono
parents:
diff changeset
720
kono
parents:
diff changeset
721 var = op_iter_init_def (&iter, stmt, flags);
kono
parents:
diff changeset
722 if (op_iter_done (&iter))
kono
parents:
diff changeset
723 return NULL_DEF_OPERAND_P;
kono
parents:
diff changeset
724 op_iter_next_def (&iter);
kono
parents:
diff changeset
725 if (op_iter_done (&iter))
kono
parents:
diff changeset
726 return var;
kono
parents:
diff changeset
727 return NULL_DEF_OPERAND_P;
kono
parents:
diff changeset
728 }
kono
parents:
diff changeset
729
kono
parents:
diff changeset
730
kono
parents:
diff changeset
731 /* Return true if there are zero operands in STMT matching the type
kono
parents:
diff changeset
732 given in FLAGS. */
kono
parents:
diff changeset
733 static inline bool
kono
parents:
diff changeset
734 zero_ssa_operands (gimple *stmt, int flags)
kono
parents:
diff changeset
735 {
kono
parents:
diff changeset
736 ssa_op_iter iter;
kono
parents:
diff changeset
737
kono
parents:
diff changeset
738 op_iter_init_tree (&iter, stmt, flags);
kono
parents:
diff changeset
739 return op_iter_done (&iter);
kono
parents:
diff changeset
740 }
kono
parents:
diff changeset
741
kono
parents:
diff changeset
742
kono
parents:
diff changeset
743 /* Return the number of operands matching FLAGS in STMT. */
kono
parents:
diff changeset
744 static inline int
kono
parents:
diff changeset
745 num_ssa_operands (gimple *stmt, int flags)
kono
parents:
diff changeset
746 {
kono
parents:
diff changeset
747 ssa_op_iter iter;
kono
parents:
diff changeset
748 tree t;
kono
parents:
diff changeset
749 int num = 0;
kono
parents:
diff changeset
750
kono
parents:
diff changeset
751 gcc_checking_assert (gimple_code (stmt) != GIMPLE_PHI);
kono
parents:
diff changeset
752 FOR_EACH_SSA_TREE_OPERAND (t, stmt, iter, flags)
kono
parents:
diff changeset
753 num++;
kono
parents:
diff changeset
754 return num;
kono
parents:
diff changeset
755 }
kono
parents:
diff changeset
756
kono
parents:
diff changeset
757 /* If there is a single DEF in the PHI node which matches FLAG, return it.
kono
parents:
diff changeset
758 Otherwise return NULL_DEF_OPERAND_P. */
kono
parents:
diff changeset
759 static inline tree
kono
parents:
diff changeset
760 single_phi_def (gphi *stmt, int flags)
kono
parents:
diff changeset
761 {
kono
parents:
diff changeset
762 tree def = PHI_RESULT (stmt);
kono
parents:
diff changeset
763 if ((flags & SSA_OP_DEF) && is_gimple_reg (def))
kono
parents:
diff changeset
764 return def;
kono
parents:
diff changeset
765 if ((flags & SSA_OP_VIRTUAL_DEFS) && !is_gimple_reg (def))
kono
parents:
diff changeset
766 return def;
kono
parents:
diff changeset
767 return NULL_TREE;
kono
parents:
diff changeset
768 }
kono
parents:
diff changeset
769
kono
parents:
diff changeset
770 /* Initialize the iterator PTR for uses matching FLAGS in PHI. FLAGS should
kono
parents:
diff changeset
771 be either SSA_OP_USES or SSA_OP_VIRTUAL_USES. */
kono
parents:
diff changeset
772 static inline use_operand_p
kono
parents:
diff changeset
773 op_iter_init_phiuse (ssa_op_iter *ptr, gphi *phi, int flags)
kono
parents:
diff changeset
774 {
kono
parents:
diff changeset
775 tree phi_def = gimple_phi_result (phi);
kono
parents:
diff changeset
776 int comp;
kono
parents:
diff changeset
777
kono
parents:
diff changeset
778 clear_and_done_ssa_iter (ptr);
kono
parents:
diff changeset
779 ptr->done = false;
kono
parents:
diff changeset
780
kono
parents:
diff changeset
781 gcc_checking_assert ((flags & (SSA_OP_USE | SSA_OP_VIRTUAL_USES)) != 0);
kono
parents:
diff changeset
782
kono
parents:
diff changeset
783 comp = (is_gimple_reg (phi_def) ? SSA_OP_USE : SSA_OP_VIRTUAL_USES);
kono
parents:
diff changeset
784
kono
parents:
diff changeset
785 /* If the PHI node doesn't the operand type we care about, we're done. */
kono
parents:
diff changeset
786 if ((flags & comp) == 0)
kono
parents:
diff changeset
787 {
kono
parents:
diff changeset
788 ptr->done = true;
kono
parents:
diff changeset
789 return NULL_USE_OPERAND_P;
kono
parents:
diff changeset
790 }
kono
parents:
diff changeset
791
kono
parents:
diff changeset
792 ptr->stmt = phi;
kono
parents:
diff changeset
793 ptr->numops = gimple_phi_num_args (phi);
kono
parents:
diff changeset
794 ptr->iter_type = ssa_op_iter_use;
kono
parents:
diff changeset
795 ptr->flags = flags;
kono
parents:
diff changeset
796 return op_iter_next_use (ptr);
kono
parents:
diff changeset
797 }
kono
parents:
diff changeset
798
kono
parents:
diff changeset
799
kono
parents:
diff changeset
800 /* Start an iterator for a PHI definition. */
kono
parents:
diff changeset
801
kono
parents:
diff changeset
802 static inline def_operand_p
kono
parents:
diff changeset
803 op_iter_init_phidef (ssa_op_iter *ptr, gphi *phi, int flags)
kono
parents:
diff changeset
804 {
kono
parents:
diff changeset
805 tree phi_def = PHI_RESULT (phi);
kono
parents:
diff changeset
806 int comp;
kono
parents:
diff changeset
807
kono
parents:
diff changeset
808 clear_and_done_ssa_iter (ptr);
kono
parents:
diff changeset
809 ptr->done = false;
kono
parents:
diff changeset
810
kono
parents:
diff changeset
811 gcc_checking_assert ((flags & (SSA_OP_DEF | SSA_OP_VIRTUAL_DEFS)) != 0);
kono
parents:
diff changeset
812
kono
parents:
diff changeset
813 comp = (is_gimple_reg (phi_def) ? SSA_OP_DEF : SSA_OP_VIRTUAL_DEFS);
kono
parents:
diff changeset
814
kono
parents:
diff changeset
815 /* If the PHI node doesn't have the operand type we care about,
kono
parents:
diff changeset
816 we're done. */
kono
parents:
diff changeset
817 if ((flags & comp) == 0)
kono
parents:
diff changeset
818 {
kono
parents:
diff changeset
819 ptr->done = true;
kono
parents:
diff changeset
820 return NULL_DEF_OPERAND_P;
kono
parents:
diff changeset
821 }
kono
parents:
diff changeset
822
kono
parents:
diff changeset
823 ptr->iter_type = ssa_op_iter_def;
kono
parents:
diff changeset
824 /* The first call to op_iter_next_def will terminate the iterator since
kono
parents:
diff changeset
825 all the fields are NULL. Simply return the result here as the first and
kono
parents:
diff changeset
826 therefore only result. */
kono
parents:
diff changeset
827 return PHI_RESULT_PTR (phi);
kono
parents:
diff changeset
828 }
kono
parents:
diff changeset
829
kono
parents:
diff changeset
830 /* Return true is IMM has reached the end of the immediate use stmt list. */
kono
parents:
diff changeset
831
kono
parents:
diff changeset
832 static inline bool
kono
parents:
diff changeset
833 end_imm_use_stmt_p (const imm_use_iterator *imm)
kono
parents:
diff changeset
834 {
kono
parents:
diff changeset
835 return (imm->imm_use == imm->end_p);
kono
parents:
diff changeset
836 }
kono
parents:
diff changeset
837
kono
parents:
diff changeset
838 /* Finished the traverse of an immediate use stmt list IMM by removing the
kono
parents:
diff changeset
839 placeholder node from the list. */
kono
parents:
diff changeset
840
kono
parents:
diff changeset
841 static inline void
kono
parents:
diff changeset
842 end_imm_use_stmt_traverse (imm_use_iterator *imm)
kono
parents:
diff changeset
843 {
kono
parents:
diff changeset
844 delink_imm_use (&(imm->iter_node));
kono
parents:
diff changeset
845 }
kono
parents:
diff changeset
846
kono
parents:
diff changeset
847 /* Immediate use traversal of uses within a stmt require that all the
kono
parents:
diff changeset
848 uses on a stmt be sequentially listed. This routine is used to build up
kono
parents:
diff changeset
849 this sequential list by adding USE_P to the end of the current list
kono
parents:
diff changeset
850 currently delimited by HEAD and LAST_P. The new LAST_P value is
kono
parents:
diff changeset
851 returned. */
kono
parents:
diff changeset
852
kono
parents:
diff changeset
853 static inline use_operand_p
kono
parents:
diff changeset
854 move_use_after_head (use_operand_p use_p, use_operand_p head,
kono
parents:
diff changeset
855 use_operand_p last_p)
kono
parents:
diff changeset
856 {
kono
parents:
diff changeset
857 gcc_checking_assert (USE_FROM_PTR (use_p) == USE_FROM_PTR (head));
kono
parents:
diff changeset
858 /* Skip head when we find it. */
kono
parents:
diff changeset
859 if (use_p != head)
kono
parents:
diff changeset
860 {
kono
parents:
diff changeset
861 /* If use_p is already linked in after last_p, continue. */
kono
parents:
diff changeset
862 if (last_p->next == use_p)
kono
parents:
diff changeset
863 last_p = use_p;
kono
parents:
diff changeset
864 else
kono
parents:
diff changeset
865 {
kono
parents:
diff changeset
866 /* Delink from current location, and link in at last_p. */
kono
parents:
diff changeset
867 delink_imm_use (use_p);
kono
parents:
diff changeset
868 link_imm_use_to_list (use_p, last_p);
kono
parents:
diff changeset
869 last_p = use_p;
kono
parents:
diff changeset
870 }
kono
parents:
diff changeset
871 }
kono
parents:
diff changeset
872 return last_p;
kono
parents:
diff changeset
873 }
kono
parents:
diff changeset
874
kono
parents:
diff changeset
875
kono
parents:
diff changeset
876 /* This routine will relink all uses with the same stmt as HEAD into the list
kono
parents:
diff changeset
877 immediately following HEAD for iterator IMM. */
kono
parents:
diff changeset
878
kono
parents:
diff changeset
879 static inline void
kono
parents:
diff changeset
880 link_use_stmts_after (use_operand_p head, imm_use_iterator *imm)
kono
parents:
diff changeset
881 {
kono
parents:
diff changeset
882 use_operand_p use_p;
kono
parents:
diff changeset
883 use_operand_p last_p = head;
kono
parents:
diff changeset
884 gimple *head_stmt = USE_STMT (head);
kono
parents:
diff changeset
885 tree use = USE_FROM_PTR (head);
kono
parents:
diff changeset
886 ssa_op_iter op_iter;
kono
parents:
diff changeset
887 int flag;
kono
parents:
diff changeset
888
kono
parents:
diff changeset
889 /* Only look at virtual or real uses, depending on the type of HEAD. */
kono
parents:
diff changeset
890 flag = (is_gimple_reg (use) ? SSA_OP_USE : SSA_OP_VIRTUAL_USES);
kono
parents:
diff changeset
891
kono
parents:
diff changeset
892 if (gphi *phi = dyn_cast <gphi *> (head_stmt))
kono
parents:
diff changeset
893 {
kono
parents:
diff changeset
894 FOR_EACH_PHI_ARG (use_p, phi, op_iter, flag)
kono
parents:
diff changeset
895 if (USE_FROM_PTR (use_p) == use)
kono
parents:
diff changeset
896 last_p = move_use_after_head (use_p, head, last_p);
kono
parents:
diff changeset
897 }
kono
parents:
diff changeset
898 else
kono
parents:
diff changeset
899 {
kono
parents:
diff changeset
900 if (flag == SSA_OP_USE)
kono
parents:
diff changeset
901 {
kono
parents:
diff changeset
902 FOR_EACH_SSA_USE_OPERAND (use_p, head_stmt, op_iter, flag)
kono
parents:
diff changeset
903 if (USE_FROM_PTR (use_p) == use)
kono
parents:
diff changeset
904 last_p = move_use_after_head (use_p, head, last_p);
kono
parents:
diff changeset
905 }
kono
parents:
diff changeset
906 else if ((use_p = gimple_vuse_op (head_stmt)) != NULL_USE_OPERAND_P)
kono
parents:
diff changeset
907 {
kono
parents:
diff changeset
908 if (USE_FROM_PTR (use_p) == use)
kono
parents:
diff changeset
909 last_p = move_use_after_head (use_p, head, last_p);
kono
parents:
diff changeset
910 }
kono
parents:
diff changeset
911 }
kono
parents:
diff changeset
912 /* Link iter node in after last_p. */
kono
parents:
diff changeset
913 if (imm->iter_node.prev != NULL)
kono
parents:
diff changeset
914 delink_imm_use (&imm->iter_node);
kono
parents:
diff changeset
915 link_imm_use_to_list (&(imm->iter_node), last_p);
kono
parents:
diff changeset
916 }
kono
parents:
diff changeset
917
kono
parents:
diff changeset
918 /* Initialize IMM to traverse over uses of VAR. Return the first statement. */
kono
parents:
diff changeset
919 static inline gimple *
kono
parents:
diff changeset
920 first_imm_use_stmt (imm_use_iterator *imm, tree var)
kono
parents:
diff changeset
921 {
kono
parents:
diff changeset
922 imm->end_p = &(SSA_NAME_IMM_USE_NODE (var));
kono
parents:
diff changeset
923 imm->imm_use = imm->end_p->next;
kono
parents:
diff changeset
924 imm->next_imm_name = NULL_USE_OPERAND_P;
kono
parents:
diff changeset
925
kono
parents:
diff changeset
926 /* iter_node is used as a marker within the immediate use list to indicate
kono
parents:
diff changeset
927 where the end of the current stmt's uses are. Initialize it to NULL
kono
parents:
diff changeset
928 stmt and use, which indicates a marker node. */
kono
parents:
diff changeset
929 imm->iter_node.prev = NULL_USE_OPERAND_P;
kono
parents:
diff changeset
930 imm->iter_node.next = NULL_USE_OPERAND_P;
kono
parents:
diff changeset
931 imm->iter_node.loc.stmt = NULL;
kono
parents:
diff changeset
932 imm->iter_node.use = NULL;
kono
parents:
diff changeset
933
kono
parents:
diff changeset
934 if (end_imm_use_stmt_p (imm))
kono
parents:
diff changeset
935 return NULL;
kono
parents:
diff changeset
936
kono
parents:
diff changeset
937 link_use_stmts_after (imm->imm_use, imm);
kono
parents:
diff changeset
938
kono
parents:
diff changeset
939 return USE_STMT (imm->imm_use);
kono
parents:
diff changeset
940 }
kono
parents:
diff changeset
941
kono
parents:
diff changeset
942 /* Bump IMM to the next stmt which has a use of var. */
kono
parents:
diff changeset
943
kono
parents:
diff changeset
944 static inline gimple *
kono
parents:
diff changeset
945 next_imm_use_stmt (imm_use_iterator *imm)
kono
parents:
diff changeset
946 {
kono
parents:
diff changeset
947 imm->imm_use = imm->iter_node.next;
kono
parents:
diff changeset
948 if (end_imm_use_stmt_p (imm))
kono
parents:
diff changeset
949 {
kono
parents:
diff changeset
950 if (imm->iter_node.prev != NULL)
kono
parents:
diff changeset
951 delink_imm_use (&imm->iter_node);
kono
parents:
diff changeset
952 return NULL;
kono
parents:
diff changeset
953 }
kono
parents:
diff changeset
954
kono
parents:
diff changeset
955 link_use_stmts_after (imm->imm_use, imm);
kono
parents:
diff changeset
956 return USE_STMT (imm->imm_use);
kono
parents:
diff changeset
957 }
kono
parents:
diff changeset
958
kono
parents:
diff changeset
959 /* This routine will return the first use on the stmt IMM currently refers
kono
parents:
diff changeset
960 to. */
kono
parents:
diff changeset
961
kono
parents:
diff changeset
962 static inline use_operand_p
kono
parents:
diff changeset
963 first_imm_use_on_stmt (imm_use_iterator *imm)
kono
parents:
diff changeset
964 {
kono
parents:
diff changeset
965 imm->next_imm_name = imm->imm_use->next;
kono
parents:
diff changeset
966 return imm->imm_use;
kono
parents:
diff changeset
967 }
kono
parents:
diff changeset
968
kono
parents:
diff changeset
969 /* Return TRUE if the last use on the stmt IMM refers to has been visited. */
kono
parents:
diff changeset
970
kono
parents:
diff changeset
971 static inline bool
kono
parents:
diff changeset
972 end_imm_use_on_stmt_p (const imm_use_iterator *imm)
kono
parents:
diff changeset
973 {
kono
parents:
diff changeset
974 return (imm->imm_use == &(imm->iter_node));
kono
parents:
diff changeset
975 }
kono
parents:
diff changeset
976
kono
parents:
diff changeset
977 /* Bump to the next use on the stmt IMM refers to, return NULL if done. */
kono
parents:
diff changeset
978
kono
parents:
diff changeset
979 static inline use_operand_p
kono
parents:
diff changeset
980 next_imm_use_on_stmt (imm_use_iterator *imm)
kono
parents:
diff changeset
981 {
kono
parents:
diff changeset
982 imm->imm_use = imm->next_imm_name;
kono
parents:
diff changeset
983 if (end_imm_use_on_stmt_p (imm))
kono
parents:
diff changeset
984 return NULL_USE_OPERAND_P;
kono
parents:
diff changeset
985 else
kono
parents:
diff changeset
986 {
kono
parents:
diff changeset
987 imm->next_imm_name = imm->imm_use->next;
kono
parents:
diff changeset
988 return imm->imm_use;
kono
parents:
diff changeset
989 }
kono
parents:
diff changeset
990 }
kono
parents:
diff changeset
991
kono
parents:
diff changeset
992 /* Delink all immediate_use information for STMT. */
kono
parents:
diff changeset
993 static inline void
kono
parents:
diff changeset
994 delink_stmt_imm_use (gimple *stmt)
kono
parents:
diff changeset
995 {
kono
parents:
diff changeset
996 ssa_op_iter iter;
kono
parents:
diff changeset
997 use_operand_p use_p;
kono
parents:
diff changeset
998
kono
parents:
diff changeset
999 if (ssa_operands_active (cfun))
kono
parents:
diff changeset
1000 FOR_EACH_PHI_OR_STMT_USE (use_p, stmt, iter, SSA_OP_ALL_USES)
kono
parents:
diff changeset
1001 delink_imm_use (use_p);
kono
parents:
diff changeset
1002 }
kono
parents:
diff changeset
1003
kono
parents:
diff changeset
1004 #endif /* GCC_TREE_SSA_ITERATORS_H */