MCPcopy Create free account
hub / github.com/InoriRus/Kyty / CloneAndAttachLoopToHeader

Method CloneAndAttachLoopToHeader

source/3rdparty/vulkan/source/opt/loop_utils.cpp:490–549  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

488}
489
490Loop* LoopUtils::CloneAndAttachLoopToHeader(LoopCloningResult* cloning_result) {
491 // Clone the loop.
492 Loop* new_loop = CloneLoop(cloning_result);
493
494 // Create a new exit block/label for the new loop.
495 // TODO(1841): Handle id overflow.
496 std::unique_ptr<Instruction> new_label{new Instruction(
497 context_, SpvOp::SpvOpLabel, 0, context_->TakeNextId(), {})};
498 std::unique_ptr<BasicBlock> new_exit_bb{new BasicBlock(std::move(new_label))};
499 new_exit_bb->SetParent(loop_->GetMergeBlock()->GetParent());
500
501 // Create an unconditional branch to the header block.
502 InstructionBuilder builder{context_, new_exit_bb.get()};
503 builder.AddBranch(loop_->GetHeaderBlock()->id());
504
505 // Save the ids of the new and old merge block.
506 const uint32_t old_merge_block = loop_->GetMergeBlock()->id();
507 const uint32_t new_merge_block = new_exit_bb->id();
508
509 // Replace the uses of the old merge block in the new loop with the new merge
510 // block.
511 for (std::unique_ptr<BasicBlock>& basic_block : cloning_result->cloned_bb_) {
512 for (Instruction& inst : *basic_block) {
513 // For each operand in each instruction check if it is using the old merge
514 // block and change it to be the new merge block.
515 auto replace_merge_use = [old_merge_block,
516 new_merge_block](uint32_t* id) {
517 if (*id == old_merge_block) *id = new_merge_block;
518 };
519 inst.ForEachInOperand(replace_merge_use);
520 }
521 }
522
523 const uint32_t old_header = loop_->GetHeaderBlock()->id();
524 const uint32_t new_header = new_loop->GetHeaderBlock()->id();
525 analysis::DefUseManager* def_use = context_->get_def_use_mgr();
526
527 def_use->ForEachUse(old_header,
528 [new_header, this](Instruction* inst, uint32_t operand) {
529 if (!this->loop_->IsInsideLoop(inst))
530 inst->SetOperand(operand, {new_header});
531 });
532
533 // TODO(1841): Handle failure to create pre-header.
534 def_use->ForEachUse(
535 loop_->GetOrCreatePreHeaderBlock()->id(),
536 [new_merge_block, this](Instruction* inst, uint32_t operand) {
537 if (this->loop_->IsInsideLoop(inst))
538 inst->SetOperand(operand, {new_merge_block});
539
540 });
541 new_loop->SetMergeBlock(new_exit_bb.get());
542
543 new_loop->SetPreHeaderBlock(loop_->GetPreHeaderBlock());
544
545 // Add the new block into the cloned instructions.
546 cloning_result->cloned_bb_.push_back(std::move(new_exit_bb));
547

Callers 1

SplitLoopMethod · 0.80

Calls 15

GetMergeBlockMethod · 0.80
GetHeaderBlockMethod · 0.80
ForEachInOperandMethod · 0.80
ForEachUseMethod · 0.80
SetOperandMethod · 0.80
SetMergeBlockMethod · 0.80
SetPreHeaderBlockMethod · 0.80
GetPreHeaderBlockMethod · 0.80
TakeNextIdMethod · 0.45
SetParentMethod · 0.45
GetParentMethod · 0.45

Tested by

no test coverage detected