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 * 43 * The purpose of the second one is so that we have places to insert code during 44 * GCM, as well as eliminating the possibility of critical edges. 45 */ 46/*@{*/ 47 48static inline void 49block_add_pred(nir_block *block, nir_block *pred) 50{ 51 _mesa_set_add(block->predecessors, pred); 52} 53 54static inline void 55block_remove_pred(nir_block *block, nir_block *pred) 56{ 57 struct set_entry *entry = _mesa_set_search(block->predecessors, pred); 58 59 assert(entry); 60 61 _mesa_set_remove(block->predecessors, entry); 62} 63 64static void 65link_blocks(nir_block *pred, nir_block *succ1, nir_block *succ2) 66{ 67 pred->successors[0] = succ1; 68 if (succ1 != NULL) 69 block_add_pred(succ1, pred); 70 71 pred->successors[1] = succ2; 72 if (succ2 != NULL) 73 block_add_pred(succ2, pred); 74} 75 76static void 77unlink_blocks(nir_block *pred, nir_block *succ) 78{ 79 if (pred->successors[0] == succ) { 80 pred->successors[0] = pred->successors[1]; 81 pred->successors[1] = NULL; 82 } else { 83 assert(pred->successors[1] == succ); 84 pred->successors[1] = NULL; 85 } 86 87 block_remove_pred(succ, pred); 88} 89 90static void 91unlink_block_successors(nir_block *block) 92{ 93 if (block->successors[1] != NULL) 94 unlink_blocks(block, block->successors[1]); 95 if (block->successors[0] != NULL) 96 unlink_blocks(block, block->successors[0]); 97} 98 99static void 100link_non_block_to_block(nir_cf_node *node, nir_block *block) 101{ 102 if (node->type == nir_cf_node_if) { 103 /* 104 * We're trying to link an if to a block after it; this just means linking 105 * the last block of the then and else branches. 106 */ 107 108 nir_if *if_stmt = nir_cf_node_as_if(node); 109 110 nir_block *last_then_block = nir_if_last_then_block(if_stmt); 111 nir_block *last_else_block = nir_if_last_else_block(if_stmt); 112 113 if (!nir_block_ends_in_jump(last_then_block)) { 114 unlink_block_successors(last_then_block); 115 link_blocks(last_then_block, block, NULL); 116 } 117 118 if (!nir_block_ends_in_jump(last_else_block)) { 119 unlink_block_successors(last_else_block); 120 link_blocks(last_else_block, block, NULL); 121 } 122 } else { 123 assert(node->type == nir_cf_node_loop); 124 } 125} 126 127static void 128link_block_to_non_block(nir_block *block, nir_cf_node *node) 129{ 130 if (node->type == nir_cf_node_if) { 131 /* 132 * We're trying to link a block to an if after it; this just means linking 133 * the block to the first block of the then and else branches. 134 */ 135 136 nir_if *if_stmt = nir_cf_node_as_if(node); 137 138 nir_block *first_then_block = nir_if_first_then_block(if_stmt); 139 nir_block *first_else_block = nir_if_first_else_block(if_stmt); 140 141 unlink_block_successors(block); 142 link_blocks(block, first_then_block, first_else_block); 143 } else if (node->type == nir_cf_node_loop) { 144 /* 145 * For similar reasons as the corresponding case in 146 * link_non_block_to_block(), don't worry about if the loop header has 147 * any predecessors that need to be unlinked. 148 */ 149 150 nir_loop *loop = nir_cf_node_as_loop(node); 151 152 nir_block *loop_header_block = nir_loop_first_block(loop); 153 154 unlink_block_successors(block); 155 link_blocks(block, loop_header_block, NULL); 156 } 157 158} 159 160/** 161 * Replace a block's successor with a different one. 162 */ 163static void 164replace_successor(nir_block *block, nir_block *old_succ, nir_block *new_succ) 165{ 166 if (block->successors[0] == old_succ) { 167 block->successors[0] = new_succ; 168 } else { 169 assert(block->successors[1] == old_succ); 170 block->successors[1] = new_succ; 171 } 172 173 block_remove_pred(old_succ, block); 174 block_add_pred(new_succ, block); 175} 176 177/** 178 * Takes a basic block and inserts a new empty basic block before it, making its 179 * predecessors point to the new block. This essentially splits the block into 180 * an empty header and a body so that another non-block CF node can be inserted 181 * between the two. Note that this does *not* link the two basic blocks, so 182 * some kind of cleanup *must* be performed after this call. 183 */ 184 185static nir_block * 186split_block_beginning(nir_block *block) 187{ 188 nir_block *new_block = nir_block_create(ralloc_parent(block)); 189 new_block->cf_node.parent = block->cf_node.parent; 190 exec_node_insert_node_before(&block->cf_node.node, &new_block->cf_node.node); 191 192 set_foreach(block->predecessors, entry) { 193 nir_block *pred = (nir_block *) entry->key; 194 replace_successor(pred, block, new_block); 195 } 196 197 /* Any phi nodes must stay part of the new block, or else their 198 * sources will be messed up. 199 */ 200 nir_foreach_instr_safe(instr, block) { 201 if (instr->type != nir_instr_type_phi) 202 break; 203 204 exec_node_remove(&instr->node); 205 instr->block = new_block; 206 exec_list_push_tail(&new_block->instr_list, &instr->node); 207 } 208 209 return new_block; 210} 211 212static void 213rewrite_phi_preds(nir_block *block, nir_block *old_pred, nir_block *new_pred) 214{ 215 nir_foreach_instr_safe(instr, block) { 216 if (instr->type != nir_instr_type_phi) 217 break; 218 219 nir_phi_instr *phi = nir_instr_as_phi(instr); 220 nir_foreach_phi_src(src, phi) { 221 if (src->pred == old_pred) { 222 src->pred = new_pred; 223 break; 224 } 225 } 226 } 227} 228 229void 230nir_insert_phi_undef(nir_block *block, nir_block *pred) 231{ 232 nir_function_impl *impl = nir_cf_node_get_function(&block->cf_node); 233 nir_foreach_instr(instr, block) { 234 if (instr->type != nir_instr_type_phi) 235 break; 236 237 nir_phi_instr *phi = nir_instr_as_phi(instr); 238 nir_ssa_undef_instr *undef = 239 nir_ssa_undef_instr_create(impl->function->shader, 240 phi->dest.ssa.num_components, 241 phi->dest.ssa.bit_size); 242 nir_instr_insert_before_cf_list(&impl->body, &undef->instr); 243 nir_phi_src *src = nir_phi_instr_add_src(phi, pred, nir_src_for_ssa(&undef->def)); 244 list_addtail(&src->src.use_link, &undef->def.uses); 245 } 246} 247 248/** 249 * Moves the successors of source to the successors of dest, leaving both 250 * successors of source NULL. 251 */ 252 253static void 254move_successors(nir_block *source, nir_block *dest) 255{ 256 nir_block *succ1 = source->successors[0]; 257 nir_block *succ2 = source->successors[1]; 258 259 if (succ1) { 260 unlink_blocks(source, succ1); 261 rewrite_phi_preds(succ1, source, dest); 262 } 263 264 if (succ2) { 265 unlink_blocks(source, succ2); 266 rewrite_phi_preds(succ2, source, dest); 267 } 268 269 unlink_block_successors(dest); 270 link_blocks(dest, succ1, succ2); 271} 272 273/* Given a basic block with no successors that has been inserted into the 274 * control flow tree, gives it the successors it would normally have assuming 275 * it doesn't end in a jump instruction. Also inserts phi sources with undefs 276 * if necessary. 277 */ 278static void 279block_add_normal_succs(nir_block *block) 280{ 281 if (exec_node_is_tail_sentinel(block->cf_node.node.next)) { 282 nir_cf_node *parent = block->cf_node.parent; 283 if (parent->type == nir_cf_node_if) { 284 nir_cf_node *next = nir_cf_node_next(parent); 285 nir_block *next_block = nir_cf_node_as_block(next); 286 287 link_blocks(block, next_block, NULL); 288 } else if (parent->type == nir_cf_node_loop) { 289 nir_loop *loop = nir_cf_node_as_loop(parent); 290 291 nir_block *head_block = nir_loop_first_block(loop); 292 293 link_blocks(block, head_block, NULL); 294 nir_insert_phi_undef(head_block, block); 295 } else { 296 nir_function_impl *impl = nir_cf_node_as_function(parent); 297 link_blocks(block, impl->end_block, NULL); 298 } 299 } else { 300 nir_cf_node *next = nir_cf_node_next(&block->cf_node); 301 if (next->type == nir_cf_node_if) { 302 nir_if *next_if = nir_cf_node_as_if(next); 303 304 nir_block *first_then_block = nir_if_first_then_block(next_if); 305 nir_block *first_else_block = nir_if_first_else_block(next_if); 306 307 link_blocks(block, first_then_block, first_else_block); 308 } else if (next->type == nir_cf_node_loop) { 309 nir_loop *next_loop = nir_cf_node_as_loop(next); 310 311 nir_block *first_block = nir_loop_first_block(next_loop); 312 313 link_blocks(block, first_block, NULL); 314 nir_insert_phi_undef(first_block, block); 315 } 316 } 317} 318 319static nir_block * 320split_block_end(nir_block *block) 321{ 322 nir_block *new_block = nir_block_create(ralloc_parent(block)); 323 new_block->cf_node.parent = block->cf_node.parent; 324 exec_node_insert_after(&block->cf_node.node, &new_block->cf_node.node); 325 326 if (nir_block_ends_in_jump(block)) { 327 /* Figure out what successor block would've had if it didn't have a jump 328 * instruction, and make new_block have that successor. 329 */ 330 block_add_normal_succs(new_block); 331 } else { 332 move_successors(block, new_block); 333 } 334 335 return new_block; 336} 337 338static nir_block * 339split_block_before_instr(nir_instr *instr) 340{ 341 assert(instr->type != nir_instr_type_phi); 342 nir_block *new_block = split_block_beginning(instr->block); 343 344 nir_foreach_instr_safe(cur_instr, instr->block) { 345 if (cur_instr == instr) 346 break; 347 348 exec_node_remove(&cur_instr->node); 349 cur_instr->block = new_block; 350 exec_list_push_tail(&new_block->instr_list, &cur_instr->node); 351 } 352 353 return new_block; 354} 355 356/* Splits a basic block at the point specified by the cursor. The "before" and 357 * "after" arguments are filled out with the blocks resulting from the split 358 * if non-NULL. Note that the "beginning" of the block is actually interpreted 359 * as before the first non-phi instruction, and it's illegal to split a block 360 * before a phi instruction. 361 */ 362 363static void 364split_block_cursor(nir_cursor cursor, 365 nir_block **_before, nir_block **_after) 366{ 367 nir_block *before, *after; 368 switch (cursor.option) { 369 case nir_cursor_before_block: 370 after = cursor.block; 371 before = split_block_beginning(cursor.block); 372 break; 373 374 case nir_cursor_after_block: 375 before = cursor.block; 376 after = split_block_end(cursor.block); 377 break; 378 379 case nir_cursor_before_instr: 380 after = cursor.instr->block; 381 before = split_block_before_instr(cursor.instr); 382 break; 383 384 case nir_cursor_after_instr: 385 /* We lower this to split_block_before_instr() so that we can keep the 386 * after-a-jump-instr case contained to split_block_end(). 387 */ 388 if (nir_instr_is_last(cursor.instr)) { 389 before = cursor.instr->block; 390 after = split_block_end(cursor.instr->block); 391 } else { 392 after = cursor.instr->block; 393 before = split_block_before_instr(nir_instr_next(cursor.instr)); 394 } 395 break; 396 397 default: 398 unreachable("not reached"); 399 } 400 401 if (_before) 402 *_before = before; 403 if (_after) 404 *_after = after; 405} 406 407/** 408 * Inserts a non-basic block between two basic blocks and links them together. 409 */ 410 411static void 412insert_non_block(nir_block *before, nir_cf_node *node, nir_block *after) 413{ 414 node->parent = before->cf_node.parent; 415 exec_node_insert_after(&before->cf_node.node, &node->node); 416 if (!nir_block_ends_in_jump(before)) 417 link_block_to_non_block(before, node); 418 link_non_block_to_block(node, after); 419} 420 421/* walk up the control flow tree to find the innermost enclosed loop */ 422static nir_loop * 423nearest_loop(nir_cf_node *node) 424{ 425 while (node->type != nir_cf_node_loop) { 426 node = node->parent; 427 } 428 429 return nir_cf_node_as_loop(node); 430} 431 432static void 433remove_phi_src(nir_block *block, nir_block *pred) 434{ 435 nir_foreach_instr(instr, block) { 436 if (instr->type != nir_instr_type_phi) 437 break; 438 439 nir_phi_instr *phi = nir_instr_as_phi(instr); 440 nir_foreach_phi_src_safe(src, phi) { 441 if (src->pred == pred) { 442 list_del(&src->src.use_link); 443 exec_node_remove(&src->node); 444 free(src); 445 } 446 } 447 } 448} 449 450/* 451 * update the CFG after a jump instruction has been added to the end of a block 452 */ 453 454void 455nir_handle_add_jump(nir_block *block) 456{ 457 nir_instr *instr = nir_block_last_instr(block); 458 nir_jump_instr *jump_instr = nir_instr_as_jump(instr); 459 460 if (block->successors[0]) 461 remove_phi_src(block->successors[0], block); 462 if (block->successors[1]) 463 remove_phi_src(block->successors[1], block); 464 unlink_block_successors(block); 465 466 nir_function_impl *impl = nir_cf_node_get_function(&block->cf_node); 467 nir_metadata_preserve(impl, nir_metadata_none); 468 469 switch (jump_instr->type) { 470 case nir_jump_return: 471 case nir_jump_halt: 472 link_blocks(block, impl->end_block, NULL); 473 break; 474 475 case nir_jump_break: { 476 nir_loop *loop = nearest_loop(&block->cf_node); 477 nir_cf_node *after = nir_cf_node_next(&loop->cf_node); 478 nir_block *after_block = nir_cf_node_as_block(after); 479 link_blocks(block, after_block, NULL); 480 break; 481 } 482 483 case nir_jump_continue: { 484 nir_loop *loop = nearest_loop(&block->cf_node); 485 nir_block *first_block = nir_loop_first_block(loop); 486 link_blocks(block, first_block, NULL); 487 break; 488 } 489 490 case nir_jump_goto: 491 link_blocks(block, jump_instr->target, NULL); 492 break; 493 494 case nir_jump_goto_if: 495 link_blocks(block, jump_instr->else_target, jump_instr->target); 496 break; 497 498 default: 499 unreachable("Invalid jump type"); 500 } 501} 502 503/* Removes the successor of a block with a jump. Note that the jump to be 504 * eliminated may be free-floating. 505 */ 506 507static void 508unlink_jump(nir_block *block, nir_jump_type type, bool add_normal_successors) 509{ 510 if (block->successors[0]) 511 remove_phi_src(block->successors[0], block); 512 if (block->successors[1]) 513 remove_phi_src(block->successors[1], block); 514 515 unlink_block_successors(block); 516 if (add_normal_successors) 517 block_add_normal_succs(block); 518} 519 520void 521nir_handle_remove_jump(nir_block *block, nir_jump_type type) 522{ 523 unlink_jump(block, type, true); 524 525 nir_function_impl *impl = nir_cf_node_get_function(&block->cf_node); 526 nir_metadata_preserve(impl, nir_metadata_none); 527} 528 529static void 530update_if_uses(nir_cf_node *node) 531{ 532 if (node->type != nir_cf_node_if) 533 return; 534 535 nir_if *if_stmt = nir_cf_node_as_if(node); 536 537 if_stmt->condition.parent_if = if_stmt; 538 if (if_stmt->condition.is_ssa) { 539 list_addtail(&if_stmt->condition.use_link, 540 &if_stmt->condition.ssa->if_uses); 541 } else { 542 list_addtail(&if_stmt->condition.use_link, 543 &if_stmt->condition.reg.reg->if_uses); 544 } 545} 546 547/** 548 * Stitch two basic blocks together into one. The aggregate must have the same 549 * predecessors as the first and the same successors as the second. 550 * 551 * Returns a cursor pointing at the end of the before block (i.e.m between the 552 * two blocks) once stiched together. 553 */ 554 555static nir_cursor 556stitch_blocks(nir_block *before, nir_block *after) 557{ 558 /* 559 * We move after into before, so we have to deal with up to 2 successors vs. 560 * possibly a large number of predecessors. 561 * 562 * TODO: special case when before is empty and after isn't? 563 */ 564 565 if (nir_block_ends_in_jump(before)) { 566 assert(exec_list_is_empty(&after->instr_list)); 567 if (after->successors[0]) 568 remove_phi_src(after->successors[0], after); 569 if (after->successors[1]) 570 remove_phi_src(after->successors[1], after); 571 unlink_block_successors(after); 572 exec_node_remove(&after->cf_node.node); 573 574 return nir_after_block(before); 575 } else { 576 nir_instr *last_before_instr = nir_block_last_instr(before); 577 578 move_successors(after, before); 579 580 foreach_list_typed(nir_instr, instr, node, &after->instr_list) { 581 instr->block = before; 582 } 583 584 exec_list_append(&before->instr_list, &after->instr_list); 585 exec_node_remove(&after->cf_node.node); 586 587 return last_before_instr ? nir_after_instr(last_before_instr) : 588 nir_before_block(before); 589 } 590} 591 592void 593nir_cf_node_insert(nir_cursor cursor, nir_cf_node *node) 594{ 595 nir_block *before, *after; 596 597 split_block_cursor(cursor, &before, &after); 598 599 if (node->type == nir_cf_node_block) { 600 nir_block *block = nir_cf_node_as_block(node); 601 exec_node_insert_after(&before->cf_node.node, &block->cf_node.node); 602 block->cf_node.parent = before->cf_node.parent; 603 /* stitch_blocks() assumes that any block that ends with a jump has 604 * already been setup with the correct successors, so we need to set 605 * up jumps here as the block is being inserted. 606 */ 607 if (nir_block_ends_in_jump(block)) 608 nir_handle_add_jump(block); 609 610 stitch_blocks(block, after); 611 stitch_blocks(before, block); 612 } else { 613 update_if_uses(node); 614 insert_non_block(before, node, after); 615 } 616} 617 618static bool 619replace_ssa_def_uses(nir_ssa_def *def, void *void_impl) 620{ 621 nir_function_impl *impl = void_impl; 622 623 nir_ssa_undef_instr *undef = 624 nir_ssa_undef_instr_create(impl->function->shader, 625 def->num_components, 626 def->bit_size); 627 nir_instr_insert_before_cf_list(&impl->body, &undef->instr); 628 nir_ssa_def_rewrite_uses(def, &undef->def); 629 return true; 630} 631 632static void 633cleanup_cf_node(nir_cf_node *node, nir_function_impl *impl) 634{ 635 switch (node->type) { 636 case nir_cf_node_block: { 637 nir_block *block = nir_cf_node_as_block(node); 638 /* We need to walk the instructions and clean up defs/uses */ 639 nir_foreach_instr_safe(instr, block) { 640 if (instr->type == nir_instr_type_jump) { 641 nir_jump_instr *jump = nir_instr_as_jump(instr); 642 unlink_jump(block, jump->type, false); 643 if (jump->type == nir_jump_goto_if) 644 nir_instr_rewrite_src(instr, &jump->condition, NIR_SRC_INIT); 645 } else { 646 nir_foreach_ssa_def(instr, replace_ssa_def_uses, impl); 647 nir_instr_remove(instr); 648 } 649 } 650 break; 651 } 652 653 case nir_cf_node_if: { 654 nir_if *if_stmt = nir_cf_node_as_if(node); 655 foreach_list_typed(nir_cf_node, child, node, &if_stmt->then_list) 656 cleanup_cf_node(child, impl); 657 foreach_list_typed(nir_cf_node, child, node, &if_stmt->else_list) 658 cleanup_cf_node(child, impl); 659 660 list_del(&if_stmt->condition.use_link); 661 break; 662 } 663 664 case nir_cf_node_loop: { 665 nir_loop *loop = nir_cf_node_as_loop(node); 666 foreach_list_typed(nir_cf_node, child, node, &loop->body) 667 cleanup_cf_node(child, impl); 668 break; 669 } 670 case nir_cf_node_function: { 671 nir_function_impl *impl = nir_cf_node_as_function(node); 672 foreach_list_typed(nir_cf_node, child, node, &impl->body) 673 cleanup_cf_node(child, impl); 674 break; 675 } 676 default: 677 unreachable("Invalid CF node type"); 678 } 679} 680 681/** 682 * Extracts everything between two cursors. Returns the cursor which is 683 * equivalent to the old begin/end curosors. 684 */ 685nir_cursor 686nir_cf_extract(nir_cf_list *extracted, nir_cursor begin, nir_cursor end) 687{ 688 nir_block *block_begin, *block_end, *block_before, *block_after; 689 690 if (nir_cursors_equal(begin, end)) { 691 exec_list_make_empty(&extracted->list); 692 extracted->impl = NULL; /* we shouldn't need this */ 693 return begin; 694 } 695 696 split_block_cursor(begin, &block_before, &block_begin); 697 698 /* Splitting a block twice with two cursors created before either split is 699 * tricky and there are a couple of places it can go wrong if both cursors 700 * point to the same block. One is if the second cursor is an block-based 701 * cursor and, thanks to the split above, it ends up pointing to the wrong 702 * block. If it's a before_block cursor and it's in the same block as 703 * begin, then begin must also be a before_block cursor and it should be 704 * caught by the nir_cursors_equal check above and we won't get here. If 705 * it's an after_block cursor, we need to re-adjust to ensure that it 706 * points to the second one of the split blocks, regardless of which it is. 707 */ 708 if (end.option == nir_cursor_after_block && end.block == block_before) 709 end.block = block_begin; 710 711 split_block_cursor(end, &block_end, &block_after); 712 713 /* The second place this can all go wrong is that it could be that the 714 * second split places the original block after the new block in which case 715 * the block_begin pointer that we saved off above is pointing to the block 716 * at the end rather than the block in the middle like it's supposed to be. 717 * In this case, we have to re-adjust begin_block to point to the middle 718 * one. 719 */ 720 if (block_begin == block_after) 721 block_begin = block_end; 722 723 extracted->impl = nir_cf_node_get_function(&block_begin->cf_node); 724 exec_list_make_empty(&extracted->list); 725 726 /* Dominance and other block-related information is toast. */ 727 nir_metadata_preserve(extracted->impl, nir_metadata_none); 728 729 nir_cf_node *cf_node = &block_begin->cf_node; 730 nir_cf_node *cf_node_end = &block_end->cf_node; 731 while (true) { 732 nir_cf_node *next = nir_cf_node_next(cf_node); 733 734 exec_node_remove(&cf_node->node); 735 cf_node->parent = NULL; 736 exec_list_push_tail(&extracted->list, &cf_node->node); 737 738 if (cf_node == cf_node_end) 739 break; 740 741 cf_node = next; 742 } 743 744 return stitch_blocks(block_before, block_after); 745} 746 747static void 748relink_jump_halt_cf_node(nir_cf_node *node, nir_block *end_block) 749{ 750 switch (node->type) { 751 case nir_cf_node_block: { 752 nir_block *block = nir_cf_node_as_block(node); 753 nir_instr *last_instr = nir_block_last_instr(block); 754 if (last_instr == NULL || last_instr->type != nir_instr_type_jump) 755 break; 756 757 nir_jump_instr *jump = nir_instr_as_jump(last_instr); 758 /* We can't move a CF list from one function to another while we still 759 * have returns. 760 */ 761 assert(jump->type != nir_jump_return); 762 763 if (jump->type == nir_jump_halt) { 764 unlink_block_successors(block); 765 link_blocks(block, end_block, NULL); 766 } 767 break; 768 } 769 770 case nir_cf_node_if: { 771 nir_if *if_stmt = nir_cf_node_as_if(node); 772 foreach_list_typed(nir_cf_node, child, node, &if_stmt->then_list) 773 relink_jump_halt_cf_node(child, end_block); 774 foreach_list_typed(nir_cf_node, child, node, &if_stmt->else_list) 775 relink_jump_halt_cf_node(child, end_block); 776 break; 777 } 778 779 case nir_cf_node_loop: { 780 nir_loop *loop = nir_cf_node_as_loop(node); 781 foreach_list_typed(nir_cf_node, child, node, &loop->body) 782 relink_jump_halt_cf_node(child, end_block); 783 break; 784 } 785 786 case nir_cf_node_function: 787 unreachable("Cannot insert a function in a function"); 788 789 default: 790 unreachable("Invalid CF node type"); 791 } 792} 793 794/** 795 * Inserts a list at a given cursor. Returns the cursor at the end of the 796 * insertion (i.e., at the end of the instructions contained in cf_list). 797 */ 798nir_cursor 799nir_cf_reinsert(nir_cf_list *cf_list, nir_cursor cursor) 800{ 801 nir_block *before, *after; 802 803 if (exec_list_is_empty(&cf_list->list)) 804 return cursor; 805 806 nir_function_impl *cursor_impl = 807 nir_cf_node_get_function(&nir_cursor_current_block(cursor)->cf_node); 808 if (cf_list->impl != cursor_impl) { 809 foreach_list_typed(nir_cf_node, node, node, &cf_list->list) 810 relink_jump_halt_cf_node(node, cursor_impl->end_block); 811 } 812 813 split_block_cursor(cursor, &before, &after); 814 815 foreach_list_typed_safe(nir_cf_node, node, node, &cf_list->list) { 816 exec_node_remove(&node->node); 817 node->parent = before->cf_node.parent; 818 exec_node_insert_node_before(&after->cf_node.node, &node->node); 819 } 820 821 stitch_blocks(before, 822 nir_cf_node_as_block(nir_cf_node_next(&before->cf_node))); 823 return stitch_blocks(nir_cf_node_as_block(nir_cf_node_prev(&after->cf_node)), 824 after); 825} 826 827void 828nir_cf_delete(nir_cf_list *cf_list) 829{ 830 foreach_list_typed(nir_cf_node, node, node, &cf_list->list) { 831 cleanup_cf_node(node, cf_list->impl); 832 } 833} 834