nir/cf: handle jumps in split_block_end()
[mesa.git] / src / glsl / nir / nir_control_flow.c
1 /*
2 * Copyright © 2014 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 *
23 * Authors:
24 * Connor Abbott (cwabbott0@gmail.com)
25 *
26 */
27
28 #include "nir_control_flow_private.h"
29
30 /**
31 * \name Control flow modification
32 *
33 * These functions modify the control flow tree while keeping the control flow
34 * graph up-to-date. The invariants respected are:
35 * 1. Each then statement, else statement, or loop body must have at least one
36 * control flow node.
37 * 2. Each if-statement and loop must have one basic block before it and one
38 * after.
39 * 3. Two basic blocks cannot be directly next to each other.
40 * 4. If a basic block has a jump instruction, there must be only one and it
41 * must be at the end of the block.
42 * 5. The CFG must always be connected - this means that we must insert a fake
43 * CFG edge for loops with no break statement.
44 *
45 * The purpose of the second one is so that we have places to insert code during
46 * GCM, as well as eliminating the possibility of critical edges.
47 */
48 /*@{*/
49
50 static inline void
51 block_add_pred(nir_block *block, nir_block *pred)
52 {
53 _mesa_set_add(block->predecessors, pred);
54 }
55
56 static void
57 link_blocks(nir_block *pred, nir_block *succ1, nir_block *succ2)
58 {
59 pred->successors[0] = succ1;
60 block_add_pred(succ1, pred);
61
62 pred->successors[1] = succ2;
63 if (succ2 != NULL)
64 block_add_pred(succ2, pred);
65 }
66
67 static void
68 unlink_blocks(nir_block *pred, nir_block *succ)
69 {
70 if (pred->successors[0] == succ) {
71 pred->successors[0] = pred->successors[1];
72 pred->successors[1] = NULL;
73 } else {
74 assert(pred->successors[1] == succ);
75 pred->successors[1] = NULL;
76 }
77
78 struct set_entry *entry = _mesa_set_search(succ->predecessors, pred);
79
80 assert(entry);
81
82 _mesa_set_remove(succ->predecessors, entry);
83 }
84
85 static void
86 unlink_block_successors(nir_block *block)
87 {
88 if (block->successors[0] != NULL)
89 unlink_blocks(block, block->successors[0]);
90 if (block->successors[1] != NULL)
91 unlink_blocks(block, block->successors[1]);
92 }
93
94 static void
95 link_non_block_to_block(nir_cf_node *node, nir_block *block)
96 {
97 if (node->type == nir_cf_node_if) {
98 /*
99 * We're trying to link an if to a block after it; this just means linking
100 * the last block of the then and else branches.
101 */
102
103 nir_if *if_stmt = nir_cf_node_as_if(node);
104
105 nir_cf_node *last_then = nir_if_last_then_node(if_stmt);
106 assert(last_then->type == nir_cf_node_block);
107 nir_block *last_then_block = nir_cf_node_as_block(last_then);
108
109 nir_cf_node *last_else = nir_if_last_else_node(if_stmt);
110 assert(last_else->type == nir_cf_node_block);
111 nir_block *last_else_block = nir_cf_node_as_block(last_else);
112
113 if (exec_list_is_empty(&last_then_block->instr_list) ||
114 nir_block_last_instr(last_then_block)->type != nir_instr_type_jump) {
115 unlink_block_successors(last_then_block);
116 link_blocks(last_then_block, block, NULL);
117 }
118
119 if (exec_list_is_empty(&last_else_block->instr_list) ||
120 nir_block_last_instr(last_else_block)->type != nir_instr_type_jump) {
121 unlink_block_successors(last_else_block);
122 link_blocks(last_else_block, block, NULL);
123 }
124 } else {
125 assert(node->type == nir_cf_node_loop);
126
127 /*
128 * We can only get to this codepath if we're inserting a new loop, or
129 * at least a loop with no break statements; we can't insert break
130 * statements into a loop when we haven't inserted it into the CFG
131 * because we wouldn't know which block comes after the loop
132 * and therefore, which block should be the successor of the block with
133 * the break). Therefore, we need to insert a fake edge (see invariant
134 * #5).
135 */
136
137 nir_loop *loop = nir_cf_node_as_loop(node);
138
139 nir_cf_node *last = nir_loop_last_cf_node(loop);
140 assert(last->type == nir_cf_node_block);
141 nir_block *last_block = nir_cf_node_as_block(last);
142
143 last_block->successors[1] = block;
144 block_add_pred(block, last_block);
145 }
146 }
147
148 static void
149 link_block_to_non_block(nir_block *block, nir_cf_node *node)
150 {
151 if (node->type == nir_cf_node_if) {
152 /*
153 * We're trying to link a block to an if after it; this just means linking
154 * the block to the first block of the then and else branches.
155 */
156
157 nir_if *if_stmt = nir_cf_node_as_if(node);
158
159 nir_cf_node *first_then = nir_if_first_then_node(if_stmt);
160 assert(first_then->type == nir_cf_node_block);
161 nir_block *first_then_block = nir_cf_node_as_block(first_then);
162
163 nir_cf_node *first_else = nir_if_first_else_node(if_stmt);
164 assert(first_else->type == nir_cf_node_block);
165 nir_block *first_else_block = nir_cf_node_as_block(first_else);
166
167 unlink_block_successors(block);
168 link_blocks(block, first_then_block, first_else_block);
169 } else {
170 /*
171 * For similar reasons as the corresponding case in
172 * link_non_block_to_block(), don't worry about if the loop header has
173 * any predecessors that need to be unlinked.
174 */
175
176 assert(node->type == nir_cf_node_loop);
177
178 nir_loop *loop = nir_cf_node_as_loop(node);
179
180 nir_cf_node *loop_header = nir_loop_first_cf_node(loop);
181 assert(loop_header->type == nir_cf_node_block);
182 nir_block *loop_header_block = nir_cf_node_as_block(loop_header);
183
184 unlink_block_successors(block);
185 link_blocks(block, loop_header_block, NULL);
186 }
187
188 }
189
190 /**
191 * Takes a basic block and inserts a new empty basic block before it, making its
192 * predecessors point to the new block. This essentially splits the block into
193 * an empty header and a body so that another non-block CF node can be inserted
194 * between the two. Note that this does *not* link the two basic blocks, so
195 * some kind of cleanup *must* be performed after this call.
196 */
197
198 static nir_block *
199 split_block_beginning(nir_block *block)
200 {
201 nir_block *new_block = nir_block_create(ralloc_parent(block));
202 new_block->cf_node.parent = block->cf_node.parent;
203 exec_node_insert_node_before(&block->cf_node.node, &new_block->cf_node.node);
204
205 struct set_entry *entry;
206 set_foreach(block->predecessors, entry) {
207 nir_block *pred = (nir_block *) entry->key;
208
209 unlink_blocks(pred, block);
210 link_blocks(pred, new_block, NULL);
211 }
212
213 /* Any phi nodes must stay part of the new block, or else their
214 * sourcse will be messed up. This will reverse the order of the phi's, but
215 * order shouldn't matter.
216 */
217 nir_foreach_instr_safe(block, instr) {
218 if (instr->type != nir_instr_type_phi)
219 break;
220
221 exec_node_remove(&instr->node);
222 instr->block = new_block;
223 exec_list_push_head(&new_block->instr_list, &instr->node);
224 }
225
226 return new_block;
227 }
228
229 static void
230 rewrite_phi_preds(nir_block *block, nir_block *old_pred, nir_block *new_pred)
231 {
232 nir_foreach_instr_safe(block, instr) {
233 if (instr->type != nir_instr_type_phi)
234 break;
235
236 nir_phi_instr *phi = nir_instr_as_phi(instr);
237 nir_foreach_phi_src(phi, src) {
238 if (src->pred == old_pred) {
239 src->pred = new_pred;
240 break;
241 }
242 }
243 }
244 }
245
246 static void
247 insert_phi_undef(nir_block *block, nir_block *pred)
248 {
249 nir_function_impl *impl = nir_cf_node_get_function(&block->cf_node);
250 nir_foreach_instr(block, instr) {
251 if (instr->type != nir_instr_type_phi)
252 break;
253
254 nir_phi_instr *phi = nir_instr_as_phi(instr);
255 nir_ssa_undef_instr *undef =
256 nir_ssa_undef_instr_create(ralloc_parent(phi),
257 phi->dest.ssa.num_components);
258 nir_instr_insert_before_cf_list(&impl->body, &undef->instr);
259 nir_phi_src *src = ralloc(phi, nir_phi_src);
260 src->pred = pred;
261 src->src.parent_instr = &phi->instr;
262 src->src.is_ssa = true;
263 src->src.ssa = &undef->def;
264
265 list_addtail(&src->src.use_link, &undef->def.uses);
266
267 exec_list_push_tail(&phi->srcs, &src->node);
268 }
269 }
270
271 /**
272 * Moves the successors of source to the successors of dest, leaving both
273 * successors of source NULL.
274 */
275
276 static void
277 move_successors(nir_block *source, nir_block *dest)
278 {
279 nir_block *succ1 = source->successors[0];
280 nir_block *succ2 = source->successors[1];
281
282 if (succ1) {
283 unlink_blocks(source, succ1);
284 rewrite_phi_preds(succ1, source, dest);
285 }
286
287 if (succ2) {
288 unlink_blocks(source, succ2);
289 rewrite_phi_preds(succ2, source, dest);
290 }
291
292 unlink_block_successors(dest);
293 link_blocks(dest, succ1, succ2);
294 }
295
296 static bool
297 block_ends_in_jump(nir_block *block)
298 {
299 return !exec_list_is_empty(&block->instr_list) &&
300 nir_block_last_instr(block)->type == nir_instr_type_jump;
301 }
302
303
304 /* Given a basic block with no successors that has been inserted into the
305 * control flow tree, gives it the successors it would normally have assuming
306 * it doesn't end in a jump instruction. Also inserts phi sources with undefs
307 * if necessary.
308 */
309 static void
310 block_add_normal_succs(nir_block *block)
311 {
312 if (exec_node_is_tail_sentinel(block->cf_node.node.next)) {
313 nir_cf_node *parent = block->cf_node.parent;
314 if (parent->type == nir_cf_node_if) {
315 nir_cf_node *next = nir_cf_node_next(parent);
316 assert(next->type == nir_cf_node_block);
317 nir_block *next_block = nir_cf_node_as_block(next);
318
319 link_blocks(block, next_block, NULL);
320 } else {
321 assert(parent->type == nir_cf_node_loop);
322 nir_loop *loop = nir_cf_node_as_loop(parent);
323
324 nir_cf_node *head = nir_loop_first_cf_node(loop);
325 assert(head->type == nir_cf_node_block);
326 nir_block *head_block = nir_cf_node_as_block(head);
327
328 link_blocks(block, head_block, NULL);
329 insert_phi_undef(head_block, block);
330 }
331 } else {
332 nir_cf_node *next = nir_cf_node_next(&block->cf_node);
333 if (next->type == nir_cf_node_if) {
334 nir_if *next_if = nir_cf_node_as_if(next);
335
336 nir_cf_node *first_then = nir_if_first_then_node(next_if);
337 assert(first_then->type == nir_cf_node_block);
338 nir_block *first_then_block = nir_cf_node_as_block(first_then);
339
340 nir_cf_node *first_else = nir_if_first_else_node(next_if);
341 assert(first_else->type == nir_cf_node_block);
342 nir_block *first_else_block = nir_cf_node_as_block(first_else);
343
344 link_blocks(block, first_then_block, first_else_block);
345 } else {
346 assert(next->type == nir_cf_node_loop);
347 nir_loop *next_loop = nir_cf_node_as_loop(next);
348
349 nir_cf_node *first = nir_loop_first_cf_node(next_loop);
350 assert(first->type == nir_cf_node_block);
351 nir_block *first_block = nir_cf_node_as_block(first);
352
353 link_blocks(block, first_block, NULL);
354 insert_phi_undef(first_block, block);
355 }
356 }
357 }
358
359 static nir_block *
360 split_block_end(nir_block *block)
361 {
362 nir_block *new_block = nir_block_create(ralloc_parent(block));
363 new_block->cf_node.parent = block->cf_node.parent;
364 exec_node_insert_after(&block->cf_node.node, &new_block->cf_node.node);
365
366 if (block_ends_in_jump(block)) {
367 /* Figure out what successor block would've had if it didn't have a jump
368 * instruction, and make new_block have that successor.
369 */
370 block_add_normal_succs(new_block);
371 } else {
372 move_successors(block, new_block);
373 }
374
375 return new_block;
376 }
377
378 /**
379 * Inserts a non-basic block between two basic blocks and links them together.
380 */
381
382 static void
383 insert_non_block(nir_block *before, nir_cf_node *node, nir_block *after)
384 {
385 node->parent = before->cf_node.parent;
386 exec_node_insert_after(&before->cf_node.node, &node->node);
387 link_block_to_non_block(before, node);
388 link_non_block_to_block(node, after);
389 }
390
391 /**
392 * Inserts a non-basic block before a basic block.
393 */
394
395 static void
396 insert_non_block_before_block(nir_cf_node *node, nir_block *block)
397 {
398 /* split off the beginning of block into new_block */
399 nir_block *new_block = split_block_beginning(block);
400
401 /* insert our node in between new_block and block */
402 insert_non_block(new_block, node, block);
403 }
404
405 /* walk up the control flow tree to find the innermost enclosed loop */
406 static nir_loop *
407 nearest_loop(nir_cf_node *node)
408 {
409 while (node->type != nir_cf_node_loop) {
410 node = node->parent;
411 }
412
413 return nir_cf_node_as_loop(node);
414 }
415
416 /*
417 * update the CFG after a jump instruction has been added to the end of a block
418 */
419
420 void
421 nir_handle_add_jump(nir_block *block)
422 {
423 nir_instr *instr = nir_block_last_instr(block);
424 nir_jump_instr *jump_instr = nir_instr_as_jump(instr);
425
426 unlink_block_successors(block);
427
428 nir_function_impl *impl = nir_cf_node_get_function(&block->cf_node);
429 nir_metadata_preserve(impl, nir_metadata_none);
430
431 if (jump_instr->type == nir_jump_break ||
432 jump_instr->type == nir_jump_continue) {
433 nir_loop *loop = nearest_loop(&block->cf_node);
434
435 if (jump_instr->type == nir_jump_continue) {
436 nir_cf_node *first_node = nir_loop_first_cf_node(loop);
437 assert(first_node->type == nir_cf_node_block);
438 nir_block *first_block = nir_cf_node_as_block(first_node);
439 link_blocks(block, first_block, NULL);
440 } else {
441 nir_cf_node *after = nir_cf_node_next(&loop->cf_node);
442 assert(after->type == nir_cf_node_block);
443 nir_block *after_block = nir_cf_node_as_block(after);
444 link_blocks(block, after_block, NULL);
445
446 /* If we inserted a fake link, remove it */
447 nir_cf_node *last = nir_loop_last_cf_node(loop);
448 assert(last->type == nir_cf_node_block);
449 nir_block *last_block = nir_cf_node_as_block(last);
450 if (last_block->successors[1] != NULL)
451 unlink_blocks(last_block, after_block);
452 }
453 } else {
454 assert(jump_instr->type == nir_jump_return);
455 link_blocks(block, impl->end_block, NULL);
456 }
457 }
458
459 static void
460 remove_phi_src(nir_block *block, nir_block *pred)
461 {
462 nir_foreach_instr(block, instr) {
463 if (instr->type != nir_instr_type_phi)
464 break;
465
466 nir_phi_instr *phi = nir_instr_as_phi(instr);
467 nir_foreach_phi_src_safe(phi, src) {
468 if (src->pred == pred) {
469 list_del(&src->src.use_link);
470 exec_node_remove(&src->node);
471 }
472 }
473 }
474 }
475
476 /* Removes the successor of a block with a jump, and inserts a fake edge for
477 * infinite loops. Note that the jump to be eliminated may be free-floating.
478 */
479
480 static
481 void unlink_jump(nir_block *block, nir_jump_type type)
482 {
483 if (block->successors[0])
484 remove_phi_src(block->successors[0], block);
485 if (block->successors[1])
486 remove_phi_src(block->successors[1], block);
487
488 if (type == nir_jump_break) {
489 nir_block *next = block->successors[0];
490
491 if (next->predecessors->entries == 1) {
492 nir_loop *loop =
493 nir_cf_node_as_loop(nir_cf_node_prev(&next->cf_node));
494
495 /* insert fake link */
496 nir_cf_node *last = nir_loop_last_cf_node(loop);
497 assert(last->type == nir_cf_node_block);
498 nir_block *last_block = nir_cf_node_as_block(last);
499
500 last_block->successors[1] = next;
501 block_add_pred(next, last_block);
502 }
503 }
504
505 unlink_block_successors(block);
506 }
507
508 void
509 nir_handle_remove_jump(nir_block *block, nir_jump_type type)
510 {
511 unlink_jump(block, type);
512
513 block_add_normal_succs(block);
514
515 nir_function_impl *impl = nir_cf_node_get_function(&block->cf_node);
516 nir_metadata_preserve(impl, nir_metadata_none);
517 }
518
519 static void
520 insert_non_block_after_block(nir_block *block, nir_cf_node *node)
521 {
522 /* split off the end of block into new_block */
523 nir_block *new_block = split_block_end(block);
524
525 /* insert our node in between block and new_block */
526 insert_non_block(block, node, new_block);
527 }
528
529 /**
530 * Inserts a basic block before another by merging the instructions.
531 *
532 * @param block the target of the insertion
533 * @param before the block to be inserted - must not have been inserted before
534 * @param has_jump whether \before has a jump instruction at the end
535 */
536
537 static void
538 insert_block_before_block(nir_block *block, nir_block *before, bool has_jump)
539 {
540 assert(!has_jump || exec_list_is_empty(&block->instr_list));
541
542 foreach_list_typed(nir_instr, instr, node, &before->instr_list) {
543 instr->block = block;
544 }
545
546 exec_list_prepend(&block->instr_list, &before->instr_list);
547
548 if (has_jump)
549 nir_handle_add_jump(block);
550 }
551
552 /**
553 * Inserts a basic block after another by merging the instructions.
554 *
555 * @param block the target of the insertion
556 * @param after the block to be inserted - must not have been inserted before
557 * @param has_jump whether \after has a jump instruction at the end
558 */
559
560 static void
561 insert_block_after_block(nir_block *block, nir_block *after, bool has_jump)
562 {
563 foreach_list_typed(nir_instr, instr, node, &after->instr_list) {
564 instr->block = block;
565 }
566
567 exec_list_append(&block->instr_list, &after->instr_list);
568
569 if (has_jump)
570 nir_handle_add_jump(block);
571 }
572
573 static void
574 update_if_uses(nir_cf_node *node)
575 {
576 if (node->type != nir_cf_node_if)
577 return;
578
579 nir_if *if_stmt = nir_cf_node_as_if(node);
580
581 if_stmt->condition.parent_if = if_stmt;
582 if (if_stmt->condition.is_ssa) {
583 list_addtail(&if_stmt->condition.use_link,
584 &if_stmt->condition.ssa->if_uses);
585 } else {
586 list_addtail(&if_stmt->condition.use_link,
587 &if_stmt->condition.reg.reg->if_uses);
588 }
589 }
590
591 void
592 nir_cf_node_insert_after(nir_cf_node *node, nir_cf_node *after)
593 {
594 update_if_uses(after);
595
596 if (after->type == nir_cf_node_block) {
597 /*
598 * either node or the one after it must be a basic block, by invariant #2;
599 * in either case, just merge the blocks together.
600 */
601 nir_block *after_block = nir_cf_node_as_block(after);
602
603 bool has_jump = !exec_list_is_empty(&after_block->instr_list) &&
604 nir_block_last_instr(after_block)->type == nir_instr_type_jump;
605
606 if (node->type == nir_cf_node_block) {
607 insert_block_after_block(nir_cf_node_as_block(node), after_block,
608 has_jump);
609 } else {
610 nir_cf_node *next = nir_cf_node_next(node);
611 assert(next->type == nir_cf_node_block);
612 nir_block *next_block = nir_cf_node_as_block(next);
613
614 insert_block_before_block(next_block, after_block, has_jump);
615 }
616 } else {
617 if (node->type == nir_cf_node_block) {
618 insert_non_block_after_block(nir_cf_node_as_block(node), after);
619 } else {
620 /*
621 * We have to insert a non-basic block after a non-basic block. Since
622 * every non-basic block has a basic block after it, this is equivalent
623 * to inserting a non-basic block before a basic block.
624 */
625
626 nir_cf_node *next = nir_cf_node_next(node);
627 assert(next->type == nir_cf_node_block);
628 nir_block *next_block = nir_cf_node_as_block(next);
629
630 insert_non_block_before_block(after, next_block);
631 }
632 }
633
634 nir_function_impl *impl = nir_cf_node_get_function(node);
635 nir_metadata_preserve(impl, nir_metadata_none);
636 }
637
638 void
639 nir_cf_node_insert_before(nir_cf_node *node, nir_cf_node *before)
640 {
641 update_if_uses(before);
642
643 if (before->type == nir_cf_node_block) {
644 nir_block *before_block = nir_cf_node_as_block(before);
645
646 bool has_jump = !exec_list_is_empty(&before_block->instr_list) &&
647 nir_block_last_instr(before_block)->type == nir_instr_type_jump;
648
649 if (node->type == nir_cf_node_block) {
650 insert_block_before_block(nir_cf_node_as_block(node), before_block,
651 has_jump);
652 } else {
653 nir_cf_node *prev = nir_cf_node_prev(node);
654 assert(prev->type == nir_cf_node_block);
655 nir_block *prev_block = nir_cf_node_as_block(prev);
656
657 insert_block_after_block(prev_block, before_block, has_jump);
658 }
659 } else {
660 if (node->type == nir_cf_node_block) {
661 insert_non_block_before_block(before, nir_cf_node_as_block(node));
662 } else {
663 /*
664 * We have to insert a non-basic block before a non-basic block. This
665 * is equivalent to inserting a non-basic block after a basic block.
666 */
667
668 nir_cf_node *prev_node = nir_cf_node_prev(node);
669 assert(prev_node->type == nir_cf_node_block);
670 nir_block *prev_block = nir_cf_node_as_block(prev_node);
671
672 insert_non_block_after_block(prev_block, before);
673 }
674 }
675
676 nir_function_impl *impl = nir_cf_node_get_function(node);
677 nir_metadata_preserve(impl, nir_metadata_none);
678 }
679
680 void
681 nir_cf_node_insert_begin(struct exec_list *list, nir_cf_node *node)
682 {
683 nir_cf_node *begin = exec_node_data(nir_cf_node, list->head, node);
684 nir_cf_node_insert_before(begin, node);
685 }
686
687 void
688 nir_cf_node_insert_end(struct exec_list *list, nir_cf_node *node)
689 {
690 nir_cf_node *end = exec_node_data(nir_cf_node, list->tail_pred, node);
691 nir_cf_node_insert_after(end, node);
692 }
693
694 /**
695 * Stitch two basic blocks together into one. The aggregate must have the same
696 * predecessors as the first and the same successors as the second.
697 */
698
699 static void
700 stitch_blocks(nir_block *before, nir_block *after)
701 {
702 /*
703 * We move after into before, so we have to deal with up to 2 successors vs.
704 * possibly a large number of predecessors.
705 *
706 * TODO: special case when before is empty and after isn't?
707 */
708
709 move_successors(after, before);
710
711 foreach_list_typed(nir_instr, instr, node, &after->instr_list) {
712 instr->block = before;
713 }
714
715 exec_list_append(&before->instr_list, &after->instr_list);
716 exec_node_remove(&after->cf_node.node);
717 }
718
719
720 static void
721 cleanup_cf_node(nir_cf_node *node)
722 {
723 switch (node->type) {
724 case nir_cf_node_block: {
725 nir_block *block = nir_cf_node_as_block(node);
726 /* We need to walk the instructions and clean up defs/uses */
727 nir_foreach_instr_safe(block, instr)
728 if (instr->type != nir_instr_type_jump)
729 nir_instr_remove(instr);
730 break;
731 }
732
733 case nir_cf_node_if: {
734 nir_if *if_stmt = nir_cf_node_as_if(node);
735 foreach_list_typed(nir_cf_node, child, node, &if_stmt->then_list)
736 cleanup_cf_node(child);
737 foreach_list_typed(nir_cf_node, child, node, &if_stmt->else_list)
738 cleanup_cf_node(child);
739
740 list_del(&if_stmt->condition.use_link);
741 break;
742 }
743
744 case nir_cf_node_loop: {
745 nir_loop *loop = nir_cf_node_as_loop(node);
746 foreach_list_typed(nir_cf_node, child, node, &loop->body)
747 cleanup_cf_node(child);
748 break;
749 }
750 case nir_cf_node_function: {
751 nir_function_impl *impl = nir_cf_node_as_function(node);
752 foreach_list_typed(nir_cf_node, child, node, &impl->body)
753 cleanup_cf_node(child);
754 break;
755 }
756 default:
757 unreachable("Invalid CF node type");
758 }
759 }
760
761 void
762 nir_cf_node_remove(nir_cf_node *node)
763 {
764 nir_function_impl *impl = nir_cf_node_get_function(node);
765 nir_metadata_preserve(impl, nir_metadata_none);
766
767 if (node->type == nir_cf_node_block) {
768 /*
769 * Basic blocks can't really be removed by themselves, since they act as
770 * padding between the non-basic blocks. So all we do here is empty the
771 * block of instructions.
772 *
773 * TODO: could we assert here?
774 */
775 exec_list_make_empty(&nir_cf_node_as_block(node)->instr_list);
776 } else {
777 nir_cf_node *before = nir_cf_node_prev(node);
778 assert(before->type == nir_cf_node_block);
779 nir_block *before_block = nir_cf_node_as_block(before);
780
781 nir_cf_node *after = nir_cf_node_next(node);
782 assert(after->type == nir_cf_node_block);
783 nir_block *after_block = nir_cf_node_as_block(after);
784
785 exec_node_remove(&node->node);
786 stitch_blocks(before_block, after_block);
787 }
788
789 cleanup_cf_node(node);
790 }