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

Method DuplicateAndConnectLoop

source/opt/loop_peeling.cpp:48–160  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

46size_t LoopPeelingPass::code_grow_threshold_ = 1000;
47
48bool LoopPeeling::DuplicateAndConnectLoop(
49 LoopUtils::LoopCloningResult* clone_results) {
50 CFG& cfg = *context_->cfg();
51 analysis::DefUseManager* def_use_mgr = context_->get_def_use_mgr();
52
53 assert(CanPeelLoop() && "Cannot peel loop!");
54
55 std::vector<BasicBlock*> ordered_loop_blocks;
56 BasicBlock* pre_header = loop_->GetOrCreatePreHeaderBlock();
57 if (!pre_header) {
58 return false;
59 }
60
61 loop_->ComputeLoopStructuredOrder(&ordered_loop_blocks);
62
63 cloned_loop_ = loop_utils_.CloneLoop(clone_results, ordered_loop_blocks);
64 if (!cloned_loop_) {
65 return false;
66 }
67
68 // Add the basic block to the function.
69 Function::iterator it =
70 loop_utils_.GetFunction()->FindBlock(pre_header->id());
71 assert(it != loop_utils_.GetFunction()->end() &&
72 "Pre-header not found in the function.");
73 loop_utils_.GetFunction()->AddBasicBlocks(
74 clone_results->cloned_bb_.begin(), clone_results->cloned_bb_.end(), ++it);
75
76 // Make the |loop_|'s preheader the |cloned_loop_| one.
77 BasicBlock* cloned_header = cloned_loop_->GetHeaderBlock();
78 pre_header->ForEachSuccessorLabel(
79 [cloned_header](uint32_t* succ) { *succ = cloned_header->id(); });
80
81 // Update cfg.
82 cfg.RemoveEdge(pre_header->id(), loop_->GetHeaderBlock()->id());
83 cloned_loop_->SetPreHeaderBlock(pre_header);
84 loop_->SetPreHeaderBlock(nullptr);
85
86 // When cloning the loop, we didn't cloned the merge block, so currently
87 // |cloned_loop_| shares the same block as |loop_|.
88 // We mutate all branches from |cloned_loop_| block to |loop_|'s merge into a
89 // branch to |loop_|'s header (so header will also be the merge of
90 // |cloned_loop_|).
91 uint32_t cloned_loop_exit = 0;
92 for (uint32_t pred_id : cfg.preds(loop_->GetMergeBlock()->id())) {
93 if (loop_->IsInsideLoop(pred_id)) continue;
94 BasicBlock* bb = cfg.block(pred_id);
95 assert(cloned_loop_exit == 0 && "The loop has multiple exits.");
96 cloned_loop_exit = bb->id();
97 bb->ForEachSuccessorLabel([this](uint32_t* succ) {
98 if (*succ == loop_->GetMergeBlock()->id())
99 *succ = loop_->GetHeaderBlock()->id();
100 });
101 }
102
103 // Update cfg.
104 cfg.RemoveNonExistingEdges(loop_->GetMergeBlock()->id());
105 cfg.AddEdge(cloned_loop_exit, loop_->GetHeaderBlock()->id());

Callers

nothing calls this directly

Calls 15

CloneLoopMethod · 0.80
FindBlockMethod · 0.80
AddBasicBlocksMethod · 0.80
ForEachSuccessorLabelMethod · 0.80
RemoveEdgeMethod · 0.80
SetPreHeaderBlockMethod · 0.80
GetMergeBlockMethod · 0.80
AddEdgeMethod · 0.80
ForEachPhiInstMethod · 0.80

Tested by

no test coverage detected