Lines Matching +full:structured +full:- +full:clone
9 // http://www.apache.org/licenses/LICENSE-2.0
29 // Indices of operands in SPIR-V instructions
37 uint32_t resultId = context()->TakeNextId(); in AddPointerToType()
47 context()->AddType(std::move(type_inst)); in AddPointerToType()
51 context()->get_type_mgr()->GetTypeAndPointerType( in AddPointerToType()
53 context()->get_type_mgr()->RegisterType(resultId, *pointerTy); in AddPointerToType()
62 (*block_ptr)->AddInstruction(std::move(newBranch)); in AddBranch()
73 (*block_ptr)->AddInstruction(std::move(newBranch)); in AddBranchCond()
83 (*block_ptr)->AddInstruction(std::move(newLoopMerge)); in AddLoopMerge()
95 newStore->AddDebugLine(line_inst); in AddStore()
97 newStore->SetDebugScope(dbg_scope); in AddStore()
98 (*block_ptr)->AddInstruction(std::move(newStore)); in AddStore()
109 newLoad->AddDebugLine(line_inst); in AddLoad()
111 newLoad->SetDebugScope(dbg_scope); in AddLoad()
112 (*block_ptr)->AddInstruction(std::move(newLoad)); in AddLoad()
123 false_id_ = get_module()->GetGlobalValue(spv::Op::OpConstantFalse); in GetFalseId()
125 uint32_t boolId = get_module()->GetGlobalValue(spv::Op::OpTypeBool); in GetFalseId()
127 boolId = context()->TakeNextId(); in GetFalseId()
131 get_module()->AddGlobalValue(spv::Op::OpTypeBool, boolId, 0); in GetFalseId()
133 false_id_ = context()->TakeNextId(); in GetFalseId()
137 get_module()->AddGlobalValue(spv::Op::OpConstantFalse, false_id_, boolId); in GetFalseId()
145 calleeFn->ForEachParam( in MapParams()
147 const uint32_t pid = cpi->result_id(); in MapParams()
148 (*callee2caller)[pid] = call_inst_itr->GetSingleWordOperand( in MapParams()
158 auto callee_block_itr = calleeFn->begin(); in CloneAndMapLocals()
159 auto callee_var_itr = callee_block_itr->begin(); in CloneAndMapLocals()
160 while (callee_var_itr->opcode() == spv::Op::OpVariable || in CloneAndMapLocals()
161 callee_var_itr->GetCommonDebugOpcode() == in CloneAndMapLocals()
163 if (callee_var_itr->opcode() != spv::Op::OpVariable) { in CloneAndMapLocals()
168 std::unique_ptr<Instruction> var_inst(callee_var_itr->Clone(context())); in CloneAndMapLocals()
169 uint32_t newId = context()->TakeNextId(); in CloneAndMapLocals()
173 get_decoration_mgr()->CloneDecorations(callee_var_itr->result_id(), newId); in CloneAndMapLocals()
174 var_inst->SetResultId(newId); in CloneAndMapLocals()
175 var_inst->UpdateDebugInlinedAt( in CloneAndMapLocals()
176 context()->get_debug_info_mgr()->BuildDebugInlinedAtChain( in CloneAndMapLocals()
177 callee_var_itr->GetDebugInlinedAt(), inlined_at_ctx)); in CloneAndMapLocals()
178 (*callee2caller)[callee_var_itr->result_id()] = newId; in CloneAndMapLocals()
179 new_vars->push_back(std::move(var_inst)); in CloneAndMapLocals()
188 const uint32_t calleeTypeId = calleeFn->type_id(); in CreateReturnVar()
189 analysis::TypeManager* type_mgr = context()->get_type_mgr(); in CreateReturnVar()
190 assert(type_mgr->GetType(calleeTypeId)->AsVoid() == nullptr && in CreateReturnVar()
194 type_mgr->FindPointerToType(calleeTypeId, spv::StorageClass::Function); in CreateReturnVar()
205 returnVarId = context()->TakeNextId(); in CreateReturnVar()
214 new_vars->push_back(std::move(var_inst)); in CreateReturnVar()
215 get_decoration_mgr()->CloneDecorations(calleeFn->result_id(), returnVarId); in CreateReturnVar()
220 return inst->opcode() == spv::Op::OpSampledImage || in IsSameBlockOp()
221 inst->opcode() == spv::Op::OpImage; in IsSameBlockOp()
229 return (*inst)->WhileEachInId([&postCallSB, &preCallSB, &block_ptr, in CloneSameBlockOps()
235 // Clone pre-call same-block ops, map result id. in CloneSameBlockOps()
236 const Instruction* inInst = mapItr2->second; in CloneSameBlockOps()
237 std::unique_ptr<Instruction> sb_inst(inInst->Clone(context())); in CloneSameBlockOps()
242 const uint32_t rid = sb_inst->result_id(); in CloneSameBlockOps()
243 const uint32_t nid = context()->TakeNextId(); in CloneSameBlockOps()
247 get_decoration_mgr()->CloneDecorations(rid, nid); in CloneSameBlockOps()
248 sb_inst->SetResultId(nid); in CloneSameBlockOps()
251 (*block_ptr)->AddInstruction(std::move(sb_inst)); in CloneSameBlockOps()
254 // Reset same-block op operand. in CloneSameBlockOps()
255 *iid = mapItr->second; in CloneSameBlockOps()
265 for (auto cii = call_block_itr->begin(); cii != call_inst_itr; in MoveInstsBeforeEntryBlock()
266 cii = call_block_itr->begin()) { in MoveInstsBeforeEntryBlock()
268 inst->RemoveFromList(); in MoveInstsBeforeEntryBlock()
270 // Remember same-block ops for possible regeneration. in MoveInstsBeforeEntryBlock()
273 (*preCallSB)[cp_inst->result_id()] = sb_inst_ptr; in MoveInstsBeforeEntryBlock()
275 new_blk_ptr->AddInstruction(std::move(cp_inst)); in MoveInstsBeforeEntryBlock()
283 const auto guard_block_id = context()->TakeNextId(); in AddGuardBlock()
288 new_blocks->push_back(std::move(new_blk_ptr)); in AddGuardBlock()
303 auto callee_itr = callee_first_block_itr->begin(); in AddStoresForVariableInitializers()
304 while (callee_itr->opcode() == spv::Op::OpVariable || in AddStoresForVariableInitializers()
305 callee_itr->GetCommonDebugOpcode() == CommonDebugInfoDebugDeclare) { in AddStoresForVariableInitializers()
306 if (callee_itr->opcode() == spv::Op::OpVariable && in AddStoresForVariableInitializers()
307 callee_itr->NumInOperands() == 2) { in AddStoresForVariableInitializers()
308 assert(callee2caller.count(callee_itr->result_id()) && in AddStoresForVariableInitializers()
310 uint32_t new_var_id = callee2caller.at(callee_itr->result_id()); in AddStoresForVariableInitializers()
314 uint32_t val_id = callee_itr->GetSingleWordInOperand(1); in AddStoresForVariableInitializers()
315 AddStore(new_var_id, val_id, new_blk_ptr, callee_itr->dbg_line_inst(), in AddStoresForVariableInitializers()
316 context()->get_debug_info_mgr()->BuildDebugScope( in AddStoresForVariableInitializers()
317 callee_itr->GetDebugScope(), inlined_at_ctx)); in AddStoresForVariableInitializers()
319 if (callee_itr->GetCommonDebugOpcode() == CommonDebugInfoDebugDeclare) { in AddStoresForVariableInitializers()
321 callee2caller, new_blk_ptr->get(), &*callee_itr, in AddStoresForVariableInitializers()
322 context()->get_debug_info_mgr()->BuildDebugInlinedAtChain( in AddStoresForVariableInitializers()
323 callee_itr->GetDebugScope().GetInlinedAt(), inlined_at_ctx)); in AddStoresForVariableInitializers()
335 if (inst->opcode() == spv::Op::OpReturnValue || in InlineSingleInstruction()
336 inst->opcode() == spv::Op::OpReturn) in InlineSingleInstruction()
340 std::unique_ptr<Instruction> cp_inst(inst->Clone(context())); in InlineSingleInstruction()
341 cp_inst->ForEachInId([&callee2caller](uint32_t* iid) { in InlineSingleInstruction()
344 *iid = mapItr->second; in InlineSingleInstruction()
348 // If result id is non-zero, remap it. in InlineSingleInstruction()
349 const uint32_t rid = cp_inst->result_id(); in InlineSingleInstruction()
355 uint32_t nid = mapItr->second; in InlineSingleInstruction()
356 cp_inst->SetResultId(nid); in InlineSingleInstruction()
357 get_decoration_mgr()->CloneDecorations(rid, nid); in InlineSingleInstruction()
360 cp_inst->UpdateDebugInlinedAt(dbg_inlined_at); in InlineSingleInstruction()
361 new_blk_ptr->AddInstruction(std::move(cp_inst)); in InlineSingleInstruction()
372 if (inst->opcode() == spv::Op::OpReturnValue) { in InlineReturn()
374 uint32_t valId = inst->GetInOperand(kSpvReturnValueId).words[0]; in InlineReturn()
377 valId = mapItr->second; in InlineReturn()
379 AddStore(returnVarId, valId, &new_blk_ptr, inst->dbg_line_inst(), in InlineReturn()
380 context()->get_debug_info_mgr()->BuildDebugScope( in InlineReturn()
381 inst->GetDebugScope(), inlined_at_ctx)); in InlineReturn()
385 for (auto callee_block_itr = calleeFn->begin(); in InlineReturn()
386 callee_block_itr != calleeFn->end(); ++callee_block_itr) { in InlineReturn()
387 if (spvOpcodeIsAbort(callee_block_itr->tail()->opcode())) { in InlineReturn()
388 returnLabelId = context()->TakeNextId(); in InlineReturn()
394 if (inst->opcode() == spv::Op::OpReturn || in InlineReturn()
395 inst->opcode() == spv::Op::OpReturnValue) in InlineReturn()
397 new_blocks->push_back(std::move(new_blk_ptr)); in InlineReturn()
409 while (callee_inst_itr != callee_first_block->end()) { in InlineEntryBlock()
412 if (callee_inst_itr->GetShader100DebugOpcode() == in InlineEntryBlock()
419 callee2caller, new_blk_ptr->get(), &*callee_inst_itr, in InlineEntryBlock()
420 context()->get_debug_info_mgr()->BuildDebugInlinedAtChain( in InlineEntryBlock()
421 callee_inst_itr->GetDebugScope().GetInlinedAt(), in InlineEntryBlock()
435 auto callee_block_itr = calleeFn->begin(); in InlineBasicBlocks()
438 while (callee_block_itr != calleeFn->end()) { in InlineBasicBlocks()
439 new_blocks->push_back(std::move(new_blk_ptr)); in InlineBasicBlocks()
441 callee2caller.find(callee_block_itr->GetLabelInst()->result_id()); in InlineBasicBlocks()
443 new_blk_ptr = MakeUnique<BasicBlock>(NewLabel(mapItr->second)); in InlineBasicBlocks()
445 auto tail_inst_itr = callee_block_itr->end(); in InlineBasicBlocks()
446 for (auto inst_itr = callee_block_itr->begin(); inst_itr != tail_inst_itr; in InlineBasicBlocks()
450 if (inst_itr->GetShader100DebugOpcode() == in InlineBasicBlocks()
455 context()->get_debug_info_mgr()->BuildDebugInlinedAtChain( in InlineBasicBlocks()
456 inst_itr->GetDebugScope().GetInlinedAt(), inlined_at_ctx))) { in InlineBasicBlocks()
472 for (Instruction* inst = call_inst_itr->NextNode(); inst; in MoveCallerInstsAfterFunctionCall()
473 inst = call_inst_itr->NextNode()) { in MoveCallerInstsAfterFunctionCall()
474 inst->RemoveFromList(); in MoveCallerInstsAfterFunctionCall()
476 // If multiple blocks generated, regenerate any same-block in MoveCallerInstsAfterFunctionCall()
483 // Remember same-block ops in this block. in MoveCallerInstsAfterFunctionCall()
485 const uint32_t rid = cp_inst->result_id(); in MoveCallerInstsAfterFunctionCall()
489 new_blk_ptr->get()->AddInstruction(std::move(cp_inst)); in MoveCallerInstsAfterFunctionCall()
499 auto& first = new_blocks->front(); in MoveLoopMergeInstToFirstBlock()
500 auto& last = new_blocks->back(); in MoveLoopMergeInstToFirstBlock()
504 auto loop_merge_itr = last->tail(); in MoveLoopMergeInstToFirstBlock()
505 --loop_merge_itr; in MoveLoopMergeInstToFirstBlock()
506 assert(loop_merge_itr->opcode() == spv::Op::OpLoopMerge); in MoveLoopMergeInstToFirstBlock()
507 std::unique_ptr<Instruction> cp_inst(loop_merge_itr->Clone(context())); in MoveLoopMergeInstToFirstBlock()
508 first->tail().InsertBefore(std::move(cp_inst)); in MoveLoopMergeInstToFirstBlock()
511 loop_merge_itr->RemoveFromList(); in MoveLoopMergeInstToFirstBlock()
517 auto& header = new_blocks->front(); in UpdateSingleBlockLoopContinueTarget()
518 auto* merge_inst = header->GetLoopMergeInst(); in UpdateSingleBlockLoopContinueTarget()
520 // The back-edge block is split at the branch to create a new back-edge in UpdateSingleBlockLoopContinueTarget()
531 auto& old_backedge = new_blocks->back(); in UpdateSingleBlockLoopContinueTarget()
532 auto old_branch = old_backedge->tail(); in UpdateSingleBlockLoopContinueTarget()
536 new_block->AddInstruction(std::move(br)); in UpdateSingleBlockLoopContinueTarget()
538 // Add a branch to the new block from the old back-edge block. in UpdateSingleBlockLoopContinueTarget()
540 new_blocks->push_back(std::move(new_block)); in UpdateSingleBlockLoopContinueTarget()
543 merge_inst->SetInOperand(1u, {new_id}); in UpdateSingleBlockLoopContinueTarget()
554 // Pre-call same-block insts in GenInlineCode()
556 // Post-call same-block op ids in GenInlineCode()
561 // Invalidate the def-use chains. They are not kept up to date while in GenInlineCode()
562 // inlining. However, certain calls try to keep them up-to-date if they are in GenInlineCode()
564 context()->InvalidateAnalyses(IRContext::kAnalysisDefUse); in GenInlineCode()
571 bool caller_is_loop_header = call_block_itr->GetLoopMergeInst() != nullptr; in GenInlineCode()
573 // Single-trip loop continue block in GenInlineCode()
576 Function* calleeFn = id2function_[call_inst_itr->GetSingleWordOperand( in GenInlineCode()
590 uint32_t entry_blk_label_id = calleeFn->begin()->GetLabelInst()->result_id(); in GenInlineCode()
591 callee2caller[entry_blk_label_id] = call_block_itr->id(); in GenInlineCode()
593 MakeUnique<BasicBlock>(NewLabel(call_block_itr->id())); in GenInlineCode()
600 (*(calleeFn->begin())).GetMergeInst() != nullptr) { in GenInlineCode()
614 const uint32_t calleeTypeId = calleeFn->type_id(); in GenInlineCode()
616 analysis::Type* calleeType = context()->get_type_mgr()->GetType(calleeTypeId); in GenInlineCode()
617 if (calleeType->AsVoid() == nullptr) { in GenInlineCode()
624 calleeFn->WhileEachInst([&callee2caller, this](const Instruction* cpi) { in GenInlineCode()
626 const uint32_t rid = cpi->result_id(); in GenInlineCode()
628 const uint32_t nid = context()->TakeNextId(); in GenInlineCode()
636 calleeFn->ForEachDebugInstructionsInHeader( in GenInlineCode()
640 context()->get_debug_info_mgr()->BuildDebugInlinedAtChain( in GenInlineCode()
641 inst->GetDebugScope().GetInlinedAt(), &inlined_at_ctx)); in GenInlineCode()
645 if (!InlineEntryBlock(callee2caller, &new_blk_ptr, calleeFn->begin(), in GenInlineCode()
658 &*(calleeFn->tail()->tail()), returnVarId); in GenInlineCode()
662 const uint32_t resId = call_inst_itr->result_id(); in GenInlineCode()
665 call_inst_itr->dbg_line_inst(), call_inst_itr->GetDebugScope()); in GenInlineCode()
671 calleeFn->begin() != calleeFn->end())) in GenInlineCode()
675 new_blocks->push_back(std::move(new_blk_ptr)); in GenInlineCode()
677 if (caller_is_loop_header && (new_blocks->size() > 1)) { in GenInlineCode()
681 auto& header = new_blocks->front(); in GenInlineCode()
682 auto* merge_inst = header->GetLoopMergeInst(); in GenInlineCode()
683 if (merge_inst->GetSingleWordInOperand(1u) == header->id()) { in GenInlineCode()
684 auto new_id = context()->TakeNextId(); in GenInlineCode()
692 id2block_[blk->id()] = &*blk; in GenInlineCode()
697 context()->KillNamesAndDecorates(&*call_inst_itr); in GenInlineCode()
703 if (inst->opcode() != spv::Op::OpFunctionCall) return false; in IsInlinableFunctionCall()
705 inst->GetSingleWordOperand(kSpvFunctionCallFunctionId); in IsInlinableFunctionCall()
710 // We rely on the merge-return pass to handle the early return case in IsInlinableFunctionCall()
713 "The function '" + id2function_[calleeFnId]->DefInst().PrettyPrint() + in IsInlinableFunctionCall()
716 "running merge-return before inlining."; in IsInlinableFunctionCall()
727 const auto lastBlk = new_blocks.end() - 1; in UpdateSucceedingPhis()
728 const uint32_t firstId = (*firstBlk)->id(); in UpdateSucceedingPhis()
729 const uint32_t lastId = (*lastBlk)->id(); in UpdateSucceedingPhis()
730 const BasicBlock& const_last_block = *lastBlk->get(); in UpdateSucceedingPhis()
733 BasicBlock* sbp = this->id2block_[succ]; in UpdateSucceedingPhis()
734 sbp->ForEachPhiInst([&firstId, &lastId](Instruction* phi) { in UpdateSucceedingPhis()
735 phi->ForEachInId([&firstId, &lastId](uint32_t* id) { in UpdateSucceedingPhis()
743 // If control not structured, do not do loop/return analysis in HasNoReturnInLoop()
744 // TODO: Analyze returns in non-structured control flow in HasNoReturnInLoop()
745 if (!context()->get_feature_mgr()->HasCapability(spv::Capability::Shader)) in HasNoReturnInLoop()
747 const auto structured_analysis = context()->GetStructuredCFGAnalysis(); in HasNoReturnInLoop()
748 // Search for returns in structured construct. in HasNoReturnInLoop()
752 --terminal_ii; in HasNoReturnInLoop()
753 if (spvOpcodeIsReturn(terminal_ii->opcode()) && in HasNoReturnInLoop()
754 structured_analysis->ContainingLoop(blk.id()) != 0) { in HasNoReturnInLoop()
765 no_return_in_loop_.insert(func->result_id()); in AnalyzeReturns()
770 --terminal_ii; in AnalyzeReturns()
771 if (spvOpcodeIsReturn(terminal_ii->opcode()) && &blk != func->tail()) { in AnalyzeReturns()
772 early_return_funcs_.insert(func->result_id()); in AnalyzeReturns()
780 if (func->cbegin() == func->cend()) return false; in IsInlinableFunction()
783 if (func->control_mask() & uint32_t(spv::FunctionControlMask::DontInline)) { in IsInlinableFunction()
793 if (no_return_in_loop_.find(func->result_id()) == no_return_in_loop_.cend()) { in IsInlinableFunction()
797 if (func->IsRecursive()) { in IsInlinableFunction()
803 // will no longer post-dominate the continue target, which is invalid. An in IsInlinableFunction()
804 // `OpUnreachable` is acceptable because it will not change post-dominance if in IsInlinableFunction()
807 funcs_called_from_continue_.count(func->result_id()) != 0; in IsInlinableFunction()
817 return !func->WhileEachInst([](Instruction* inst) { in ContainsAbortOtherThanUnreachable()
818 return inst->opcode() == spv::Op::OpUnreachable || in ContainsAbortOtherThanUnreachable()
819 !spvOpcodeIsAbort(inst->opcode()); in ContainsAbortOtherThanUnreachable()
833 context()->GetStructuredCFGAnalysis()->FindFuncsCalledFromContinue(); in InitializeInline()