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

Method PerformUnswitch

source/opt/loop_unswitch_pass.cpp:142–446  ·  view source on GitHub ↗

Unswitches |loop_|.

Source from the content-addressed store, hash-verified

140
141 // Unswitches |loop_|.
142 bool PerformUnswitch() {
143 assert(CanUnswitchLoop() &&
144 "Cannot unswitch if there is not constant condition");
145 assert(loop_->GetPreHeaderBlock() && "This loop has no pre-header block");
146 assert(loop_->IsLCSSA() && "This loop is not in LCSSA form");
147
148 CFG& cfg = *context_->cfg();
149 DominatorTree* dom_tree =
150 &context_->GetDominatorAnalysis(function_)->GetDomTree();
151 analysis::DefUseManager* def_use_mgr = context_->get_def_use_mgr();
152 LoopUtils loop_utils(context_, loop_);
153
154 //////////////////////////////////////////////////////////////////////////////
155 // Step 1: Create the if merge block for structured modules.
156 // To do so, the |loop_| merge block will become the if's one and we
157 // create a merge for the loop. This will limit the amount of duplicated
158 // code the structured control flow imposes.
159 // For non structured program, the new loop will be connected to
160 // the old loop's exit blocks.
161 //////////////////////////////////////////////////////////////////////////////
162
163 // Get the merge block if it exists.
164 BasicBlock* if_merge_block = loop_->GetMergeBlock();
165 // The merge block is only created if the loop has a unique exit block. We
166 // have this guarantee for structured loops, for compute loop it will
167 // trivially help maintain both a structured-like form and LCSAA.
168 BasicBlock* loop_merge_block =
169 if_merge_block
170 ? CreateBasicBlock(FindBasicBlockPosition(if_merge_block))
171 : nullptr;
172 if (if_merge_block && !loop_merge_block) {
173 return false;
174 }
175 if (loop_merge_block) {
176 // Add the instruction and update managers.
177 InstructionBuilder builder(
178 context_, loop_merge_block,
179 IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping);
180 builder.AddBranch(if_merge_block->id());
181 builder.SetInsertPoint(&*loop_merge_block->begin());
182 cfg.RegisterBlock(loop_merge_block);
183 def_use_mgr->AnalyzeInstDef(loop_merge_block->GetLabelInst());
184 bool ok = true;
185 if_merge_block->ForEachPhiInst(
186 [loop_merge_block, &ok, &builder, this](Instruction* phi) -> bool {
187 Instruction* cloned = phi->Clone(context_);
188 uint32_t new_id = TakeNextId();
189 if (new_id == 0) {
190 ok = false;
191 return false;
192 }
193 cloned->SetResultId(new_id);
194 builder.AddInstruction(std::unique_ptr<Instruction>(cloned));
195 phi->SetInOperand(0, {cloned->result_id()});
196 phi->SetInOperand(1, {loop_merge_block->id()});
197 for (uint32_t j = phi->NumInOperands() - 1; j > 1; j--)
198 phi->RemoveInOperand(j);
199 return true;

Callers 1

ProcessFunctionMethod · 0.80

Calls 15

findFunction · 0.85
InstructionBuilderClass · 0.85
GetPreHeaderBlockMethod · 0.80
IsLCSSAMethod · 0.80
GetDominatorAnalysisMethod · 0.80
GetMergeBlockMethod · 0.80
SetInsertPointMethod · 0.80
AnalyzeInstDefMethod · 0.80
GetLabelInstMethod · 0.80
ForEachPhiInstMethod · 0.80
SetInOperandMethod · 0.80
NumInOperandsMethod · 0.80

Tested by

no test coverage detected