1 /* Header file for gimple iterators.
2    Copyright (C) 2013-2021 Free Software Foundation, Inc.
3 
4 This file is part of GCC.
5 
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
9 version.
10 
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3.  If not see
18 <http://www.gnu.org/licenses/>.  */
19 
20 #ifndef GCC_GIMPLE_ITERATOR_H
21 #define GCC_GIMPLE_ITERATOR_H
22 
23 /* Iterator object for GIMPLE statement sequences.  */
24 
25 struct gimple_stmt_iterator
26 {
27   /* Sequence node holding the current statement.  */
28   gimple_seq_node ptr;
29 
30   /* Sequence and basic block holding the statement.  These fields
31      are necessary to handle edge cases such as when statement is
32      added to an empty basic block or when the last statement of a
33      block/sequence is removed.  */
34   gimple_seq *seq;
35   basic_block bb;
36 };
37 
38 /* Iterator over GIMPLE_PHI statements.  */
39 struct gphi_iterator : public gimple_stmt_iterator
40 {
phigphi_iterator41   gphi *phi () const
42   {
43     return as_a <gphi *> (ptr);
44   }
45 };
46 
47 enum gsi_iterator_update
48 {
49   GSI_NEW_STMT = 2,	/* Move the iterator to the first statement added.  */
50   GSI_LAST_NEW_STMT,	/* Move the iterator to the last statement added.  */
51   GSI_SAME_STMT,	/* Leave the iterator at the same statement.  */
52   GSI_CONTINUE_LINKING	/* Move iterator to whatever position is suitable
53 			   for linking other statements in the same
54 			   direction.  */
55 };
56 
57 extern void gsi_insert_seq_before_without_update (gimple_stmt_iterator *,
58 						  gimple_seq,
59 						  enum gsi_iterator_update);
60 extern void gsi_insert_seq_before (gimple_stmt_iterator *, gimple_seq,
61 				   enum gsi_iterator_update);
62 extern void gsi_insert_seq_after_without_update (gimple_stmt_iterator *,
63 						 gimple_seq,
64 						 enum gsi_iterator_update);
65 extern void gsi_insert_seq_after (gimple_stmt_iterator *, gimple_seq,
66 				  enum gsi_iterator_update);
67 extern gimple_seq gsi_split_seq_after (gimple_stmt_iterator);
68 extern void gsi_set_stmt (gimple_stmt_iterator *, gimple *);
69 extern void gsi_split_seq_before (gimple_stmt_iterator *, gimple_seq *);
70 extern bool gsi_replace (gimple_stmt_iterator *, gimple *, bool);
71 extern void gsi_replace_with_seq (gimple_stmt_iterator *, gimple_seq, bool);
72 extern void gsi_insert_before_without_update (gimple_stmt_iterator *, gimple *,
73 					      enum gsi_iterator_update);
74 extern void gsi_insert_before (gimple_stmt_iterator *, gimple *,
75 			       enum gsi_iterator_update);
76 extern void gsi_insert_after_without_update (gimple_stmt_iterator *, gimple *,
77 					     enum gsi_iterator_update);
78 extern void gsi_insert_after (gimple_stmt_iterator *, gimple *,
79 			      enum gsi_iterator_update);
80 extern bool gsi_remove (gimple_stmt_iterator *, bool);
81 extern gimple_stmt_iterator gsi_for_stmt (gimple *);
82 extern gimple_stmt_iterator gsi_for_stmt (gimple *, gimple_seq *);
83 extern gphi_iterator gsi_for_phi (gphi *);
84 extern void gsi_move_after (gimple_stmt_iterator *, gimple_stmt_iterator *);
85 extern void gsi_move_before (gimple_stmt_iterator *, gimple_stmt_iterator *);
86 extern void gsi_move_to_bb_end (gimple_stmt_iterator *, basic_block);
87 extern void gsi_insert_on_edge (edge, gimple *);
88 extern void gsi_insert_seq_on_edge (edge, gimple_seq);
89 extern basic_block gsi_insert_on_edge_immediate (edge, gimple *);
90 extern basic_block gsi_insert_seq_on_edge_immediate (edge, gimple_seq);
91 extern void gsi_commit_edge_inserts (void);
92 extern void gsi_commit_one_edge_insert (edge, basic_block *);
93 extern gphi_iterator gsi_start_phis (basic_block);
94 extern void update_modified_stmts (gimple_seq);
95 
96 /* Return a new iterator pointing to GIMPLE_SEQ's first statement.  */
97 
98 static inline gimple_stmt_iterator
gsi_start_1(gimple_seq * seq)99 gsi_start_1 (gimple_seq *seq)
100 {
101   gimple_stmt_iterator i;
102 
103   i.ptr = gimple_seq_first (*seq);
104   i.seq = seq;
105   i.bb = i.ptr ? gimple_bb (i.ptr) : NULL;
106 
107   return i;
108 }
109 
110 #define gsi_start(x) gsi_start_1 (&(x))
111 
112 static inline gimple_stmt_iterator
gsi_none(void)113 gsi_none (void)
114 {
115   gimple_stmt_iterator i;
116   i.ptr = NULL;
117   i.seq = NULL;
118   i.bb = NULL;
119   return i;
120 }
121 
122 /* Return a new iterator pointing to the first statement in basic block BB.  */
123 
124 static inline gimple_stmt_iterator
gsi_start_bb(basic_block bb)125 gsi_start_bb (basic_block bb)
126 {
127   gimple_stmt_iterator i;
128   gimple_seq *seq;
129 
130   seq = bb_seq_addr (bb);
131   i.ptr = gimple_seq_first (*seq);
132   i.seq = seq;
133   i.bb = bb;
134 
135   return i;
136 }
137 
138 gimple_stmt_iterator gsi_start_edge (edge e);
139 
140 /* Return a new iterator initially pointing to GIMPLE_SEQ's last statement.  */
141 
142 static inline gimple_stmt_iterator
gsi_last_1(gimple_seq * seq)143 gsi_last_1 (gimple_seq *seq)
144 {
145   gimple_stmt_iterator i;
146 
147   i.ptr = gimple_seq_last (*seq);
148   i.seq = seq;
149   i.bb = i.ptr ? gimple_bb (i.ptr) : NULL;
150 
151   return i;
152 }
153 
154 #define gsi_last(x) gsi_last_1 (&(x))
155 
156 /* Return a new iterator pointing to the last statement in basic block BB.  */
157 
158 static inline gimple_stmt_iterator
gsi_last_bb(basic_block bb)159 gsi_last_bb (basic_block bb)
160 {
161   gimple_stmt_iterator i;
162   gimple_seq *seq;
163 
164   seq = bb_seq_addr (bb);
165   i.ptr = gimple_seq_last (*seq);
166   i.seq = seq;
167   i.bb = bb;
168 
169   return i;
170 }
171 
172 /* Return true if I is at the end of its sequence.  */
173 
174 static inline bool
gsi_end_p(gimple_stmt_iterator i)175 gsi_end_p (gimple_stmt_iterator i)
176 {
177   return i.ptr == NULL;
178 }
179 
180 /* Return true if I is one statement before the end of its sequence.  */
181 
182 static inline bool
gsi_one_before_end_p(gimple_stmt_iterator i)183 gsi_one_before_end_p (gimple_stmt_iterator i)
184 {
185   return i.ptr != NULL && i.ptr->next == NULL;
186 }
187 
188 /* Advance the iterator to the next gimple statement.  */
189 
190 static inline void
gsi_next(gimple_stmt_iterator * i)191 gsi_next (gimple_stmt_iterator *i)
192 {
193   i->ptr = i->ptr->next;
194 }
195 
196 /* Advance the iterator to the previous gimple statement.  */
197 
198 static inline void
gsi_prev(gimple_stmt_iterator * i)199 gsi_prev (gimple_stmt_iterator *i)
200 {
201   gimple *prev = i->ptr->prev;
202   if (prev->next)
203     i->ptr = prev;
204   else
205     i->ptr = NULL;
206 }
207 
208 /* Return the current stmt.  */
209 
210 static inline gimple *
gsi_stmt(gimple_stmt_iterator i)211 gsi_stmt (gimple_stmt_iterator i)
212 {
213   return i.ptr;
214 }
215 
216 /* Return a block statement iterator that points to the first
217    non-label statement in block BB.  */
218 
219 static inline gimple_stmt_iterator
gsi_after_labels(basic_block bb)220 gsi_after_labels (basic_block bb)
221 {
222   gimple_stmt_iterator gsi = gsi_start_bb (bb);
223 
224   for (; !gsi_end_p (gsi); )
225     {
226       if (gimple_code (gsi_stmt (gsi)) == GIMPLE_LABEL)
227 	gsi_next (&gsi);
228       else
229 	break;
230     }
231 
232   return gsi;
233 }
234 
235 /* Advance the iterator to the next non-debug gimple statement.  */
236 
237 static inline void
gsi_next_nondebug(gimple_stmt_iterator * i)238 gsi_next_nondebug (gimple_stmt_iterator *i)
239 {
240   do
241     {
242       gsi_next (i);
243     }
244   while (!gsi_end_p (*i) && is_gimple_debug (gsi_stmt (*i)));
245 }
246 
247 /* Advance the iterator to the previous non-debug gimple statement.  */
248 
249 static inline void
gsi_prev_nondebug(gimple_stmt_iterator * i)250 gsi_prev_nondebug (gimple_stmt_iterator *i)
251 {
252   do
253     {
254       gsi_prev (i);
255     }
256   while (!gsi_end_p (*i) && is_gimple_debug (gsi_stmt (*i)));
257 }
258 
259 /* Return a new iterator pointing to the first non-debug statement in
260    SEQ.  */
261 
262 static inline gimple_stmt_iterator
gsi_start_nondebug(gimple_seq seq)263 gsi_start_nondebug (gimple_seq seq)
264 {
265   gimple_stmt_iterator gsi = gsi_start (seq);
266   if (!gsi_end_p (gsi) && is_gimple_debug (gsi_stmt (gsi)))
267     gsi_next_nondebug (&gsi);
268 
269   return gsi;
270 }
271 
272 /* Return a new iterator pointing to the first non-debug statement in
273    basic block BB.  */
274 
275 static inline gimple_stmt_iterator
gsi_start_nondebug_bb(basic_block bb)276 gsi_start_nondebug_bb (basic_block bb)
277 {
278   gimple_stmt_iterator i = gsi_start_bb (bb);
279 
280   if (!gsi_end_p (i) && is_gimple_debug (gsi_stmt (i)))
281     gsi_next_nondebug (&i);
282 
283   return i;
284 }
285 
286 /* Return a new iterator pointing to the first non-debug non-label statement in
287    basic block BB.  */
288 
289 static inline gimple_stmt_iterator
gsi_start_nondebug_after_labels_bb(basic_block bb)290 gsi_start_nondebug_after_labels_bb (basic_block bb)
291 {
292   gimple_stmt_iterator i = gsi_after_labels (bb);
293 
294   if (!gsi_end_p (i) && is_gimple_debug (gsi_stmt (i)))
295     gsi_next_nondebug (&i);
296 
297   return i;
298 }
299 
300 /* Return a new iterator pointing to the last non-debug statement in
301    basic block BB.  */
302 
303 static inline gimple_stmt_iterator
gsi_last_nondebug_bb(basic_block bb)304 gsi_last_nondebug_bb (basic_block bb)
305 {
306   gimple_stmt_iterator i = gsi_last_bb (bb);
307 
308   if (!gsi_end_p (i) && is_gimple_debug (gsi_stmt (i)))
309     gsi_prev_nondebug (&i);
310 
311   return i;
312 }
313 
314 /* Return true if I is followed only by debug statements in its
315    sequence.  */
316 
317 static inline bool
gsi_one_nondebug_before_end_p(gimple_stmt_iterator i)318 gsi_one_nondebug_before_end_p (gimple_stmt_iterator i)
319 {
320   if (gsi_one_before_end_p (i))
321     return true;
322   if (gsi_end_p (i))
323     return false;
324   gsi_next_nondebug (&i);
325   return gsi_end_p (i);
326 }
327 
328 /* Advance I statement iterator to the next non-virtual GIMPLE_PHI
329    statement.  */
330 
331 static inline void
gsi_next_nonvirtual_phi(gphi_iterator * i)332 gsi_next_nonvirtual_phi (gphi_iterator *i)
333 {
334   do
335     {
336       gsi_next (i);
337     }
338   while (!gsi_end_p (*i) && virtual_operand_p (gimple_phi_result (i->phi ())));
339 }
340 
341 /* Return a new iterator pointing to the first non-virtual phi statement in
342    basic block BB.  */
343 
344 static inline gphi_iterator
gsi_start_nonvirtual_phis(basic_block bb)345 gsi_start_nonvirtual_phis (basic_block bb)
346 {
347   gphi_iterator i = gsi_start_phis (bb);
348 
349   if (!gsi_end_p (i) && virtual_operand_p (gimple_phi_result (i.phi ())))
350     gsi_next_nonvirtual_phi (&i);
351 
352   return i;
353 }
354 
355 /* Return the basic block associated with this iterator.  */
356 
357 static inline basic_block
gsi_bb(gimple_stmt_iterator i)358 gsi_bb (gimple_stmt_iterator i)
359 {
360   return i.bb;
361 }
362 
363 /* Return the sequence associated with this iterator.  */
364 
365 static inline gimple_seq
gsi_seq(gimple_stmt_iterator i)366 gsi_seq (gimple_stmt_iterator i)
367 {
368   return *i.seq;
369 }
370 
371 /* Determine whether SEQ is a nondebug singleton.  */
372 
373 static inline bool
gimple_seq_nondebug_singleton_p(gimple_seq seq)374 gimple_seq_nondebug_singleton_p (gimple_seq seq)
375 {
376   gimple_stmt_iterator gsi;
377 
378   /* Find a nondebug gimple.  */
379   gsi.ptr = gimple_seq_first (seq);
380   gsi.seq = &seq;
381   gsi.bb = NULL;
382   while (!gsi_end_p (gsi)
383 	 && is_gimple_debug (gsi_stmt (gsi)))
384     gsi_next (&gsi);
385 
386   /* No nondebug gimple found, not a singleton.  */
387   if (gsi_end_p (gsi))
388     return false;
389 
390   /* Find a next nondebug gimple.  */
391   gsi_next (&gsi);
392   while (!gsi_end_p (gsi)
393 	 && is_gimple_debug (gsi_stmt (gsi)))
394     gsi_next (&gsi);
395 
396   /* Only a singleton if there's no next nondebug gimple.  */
397   return gsi_end_p (gsi);
398 }
399 
400 #endif /* GCC_GIMPLE_ITERATOR_H */
401