MCPcopy Create free account
hub / github.com/KhronosGroup/SPIRV-Tools / Fuse

Method Fuse

source/opt/loop_fusion.cpp:533–730  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

531}
532
533void LoopFusion::Fuse() {
534 assert(AreCompatible() && "Can't fuse, loops aren't compatible");
535 assert(IsLegal() && "Can't fuse, illegal");
536
537 // Save the pointers/ids, won't be found in the middle of doing modifications.
538 auto header_1 = loop_1_->GetHeaderBlock()->id();
539 auto condition_1 = loop_1_->FindConditionBlock()->id();
540 auto continue_1 = loop_1_->GetContinueBlock()->id();
541 auto continue_0 = loop_0_->GetContinueBlock()->id();
542 auto condition_block_of_0 = loop_0_->FindConditionBlock();
543
544 // Find the blocks whose branches need updating.
545 auto first_block_of_1 = &*(++containing_function_->FindBlock(condition_1));
546 auto last_block_of_1 = &*(--containing_function_->FindBlock(continue_1));
547 auto last_block_of_0 = &*(--containing_function_->FindBlock(continue_0));
548
549 // Update the branch for |last_block_of_loop_0| to go to |first_block_of_1|.
550 last_block_of_0->ForEachSuccessorLabel(
551 [first_block_of_1](uint32_t* succ) { *succ = first_block_of_1->id(); });
552
553 // Update the branch for the |last_block_of_loop_1| to go to the continue
554 // block of |loop_0_|.
555 last_block_of_1->ForEachSuccessorLabel(
556 [this](uint32_t* succ) { *succ = loop_0_->GetContinueBlock()->id(); });
557
558 // Update merge block id in the header of |loop_0_| to the merge block of
559 // |loop_1_|.
560 loop_0_->GetHeaderBlock()->ForEachInst([this](Instruction* inst) {
561 if (inst->opcode() == spv::Op::OpLoopMerge) {
562 inst->SetInOperand(0, {loop_1_->GetMergeBlock()->id()});
563 }
564 });
565
566 // Update condition branch target in |loop_0_| to the merge block of
567 // |loop_1_|.
568 condition_block_of_0->ForEachInst([this](Instruction* inst) {
569 if (inst->opcode() == spv::Op::OpBranchConditional) {
570 auto loop_0_merge_block_id = loop_0_->GetMergeBlock()->id();
571
572 if (inst->GetSingleWordInOperand(1) == loop_0_merge_block_id) {
573 inst->SetInOperand(1, {loop_1_->GetMergeBlock()->id()});
574 } else {
575 inst->SetInOperand(2, {loop_1_->GetMergeBlock()->id()});
576 }
577 }
578 });
579
580 // Move OpPhi instructions not corresponding to the induction variable from
581 // the header of |loop_1_| to the header of |loop_0_|.
582 std::vector<Instruction*> instructions_to_move{};
583 for (auto& instruction : *loop_1_->GetHeaderBlock()) {
584 if (instruction.opcode() == spv::Op::OpPhi &&
585 &instruction != induction_1_) {
586 instructions_to_move.push_back(&instruction);
587 }
588 }
589
590 for (auto& it : instructions_to_move) {

Callers 2

ProcessFunctionMethod · 0.80
TEST_FFunction · 0.80

Calls 15

ReplacePhiParentWithFunction · 0.85
AddInstructionsInBlockFunction · 0.85
FindConditionBlockMethod · 0.80
GetContinueBlockMethod · 0.80
FindBlockMethod · 0.80
ForEachSuccessorLabelMethod · 0.80
SetInOperandMethod · 0.80
GetMergeBlockMethod · 0.80
RemoveFromListMethod · 0.80
ForEachPhiInstMethod · 0.80
GetPreHeaderBlockMethod · 0.80

Tested by

no test coverage detected