annotate gcc/ssa-iterators.h @ 145:1830386684a0

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