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

Method CreateLoopDedicatedExits

source/opt/loop_utils.cpp:332–457  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

330} // namespace
331
332bool LoopUtils::CreateLoopDedicatedExits() {
333 Function* function = loop_->GetHeaderBlock()->GetParent();
334 LoopDescriptor& loop_desc = *context_->GetLoopDescriptor(function);
335 CFG& cfg = *context_->cfg();
336 analysis::DefUseManager* def_use_mgr = context_->get_def_use_mgr();
337
338 const IRContext::Analysis PreservedAnalyses =
339 IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping;
340
341 // Gathers the set of basic block that are not in this loop and have at least
342 // one predecessor in the loop and one not in the loop.
343 std::unordered_set<uint32_t> exit_bb_set;
344 loop_->GetExitBlocks(&exit_bb_set);
345
346 std::unordered_set<BasicBlock*> new_loop_exits;
347 bool made_change = false;
348 // For each block, we create a new one that gathers all branches from
349 // the loop and fall into the block.
350 for (uint32_t non_dedicate_id : exit_bb_set) {
351 BasicBlock* non_dedicate = cfg.block(non_dedicate_id);
352 const std::vector<uint32_t>& bb_pred = cfg.preds(non_dedicate_id);
353 // Ignore the block if all the predecessors are in the loop.
354 if (std::all_of(bb_pred.begin(), bb_pred.end(),
355 [this](uint32_t id) { return loop_->IsInsideLoop(id); })) {
356 new_loop_exits.insert(non_dedicate);
357 continue;
358 }
359
360 made_change = true;
361 Function::iterator insert_pt = function->begin();
362 for (; insert_pt != function->end() && &*insert_pt != non_dedicate;
363 ++insert_pt) {
364 }
365 assert(insert_pt != function->end() && "Basic Block not found");
366
367 // Create the dedicate exit basic block.
368 uint32_t exit_id = context_->TakeNextId();
369 if (exit_id == 0) {
370 return false;
371 }
372 BasicBlock& exit = *insert_pt.InsertBefore(
373 std::unique_ptr<BasicBlock>(new BasicBlock(std::unique_ptr<Instruction>(
374 new Instruction(context_, spv::Op::OpLabel, 0, exit_id, {})))));
375 exit.SetParent(function);
376
377 // Redirect in loop predecessors to |exit| block.
378 for (uint32_t exit_pred_id : bb_pred) {
379 if (loop_->IsInsideLoop(exit_pred_id)) {
380 BasicBlock* pred_block = cfg.block(exit_pred_id);
381 pred_block->ForEachSuccessorLabel([non_dedicate, &exit](uint32_t* id) {
382 if (*id == non_dedicate->id()) *id = exit.id();
383 });
384 // Update the CFG.
385 // |non_dedicate|'s predecessor list will be updated at the end of the
386 // loop.
387 cfg.RegisterBlock(pred_block);
388 }
389 }

Callers

nothing calls this directly

Calls 15

GetExitBlocksMethod · 0.80
ForEachSuccessorLabelMethod · 0.80
AnalyzeInstDefUseMethod · 0.80
GetLabelInstMethod · 0.80
set_instr_blockMethod · 0.80
SetInsertPointMethod · 0.80
WhileEachPhiInstMethod · 0.80
NumInOperandsMethod · 0.80
AddPhiMethod · 0.80
SetInOperandMethod · 0.80
RemoveInOperandMethod · 0.80

Tested by

no test coverage detected