summaryrefslogtreecommitdiff
path: root/source/opt/inline_pass.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/opt/inline_pass.cpp')
-rw-r--r--source/opt/inline_pass.cpp167
1 files changed, 81 insertions, 86 deletions
diff --git a/source/opt/inline_pass.cpp b/source/opt/inline_pass.cpp
index a044fd37..665f3a7b 100644
--- a/source/opt/inline_pass.cpp
+++ b/source/opt/inline_pass.cpp
@@ -32,11 +32,11 @@ namespace opt {
uint32_t InlinePass::AddPointerToType(uint32_t type_id,
SpvStorageClass storage_class) {
uint32_t resultId = TakeNextId();
- std::unique_ptr<opt::Instruction> type_inst(new opt::Instruction(
- context(), SpvOpTypePointer, 0, resultId,
- {{spv_operand_type_t::SPV_OPERAND_TYPE_STORAGE_CLASS,
- {uint32_t(storage_class)}},
- {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {type_id}}}));
+ std::unique_ptr<Instruction> type_inst(
+ new Instruction(context(), SpvOpTypePointer, 0, resultId,
+ {{spv_operand_type_t::SPV_OPERAND_TYPE_STORAGE_CLASS,
+ {uint32_t(storage_class)}},
+ {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {type_id}}}));
context()->AddType(std::move(type_inst));
analysis::Type* pointeeTy;
std::unique_ptr<analysis::Pointer> pointerTy;
@@ -48,27 +48,27 @@ uint32_t InlinePass::AddPointerToType(uint32_t type_id,
}
void InlinePass::AddBranch(uint32_t label_id,
- std::unique_ptr<opt::BasicBlock>* block_ptr) {
- std::unique_ptr<opt::Instruction> newBranch(new opt::Instruction(
- context(), SpvOpBranch, 0, 0,
- {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {label_id}}}));
+ std::unique_ptr<BasicBlock>* block_ptr) {
+ std::unique_ptr<Instruction> newBranch(
+ new Instruction(context(), SpvOpBranch, 0, 0,
+ {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {label_id}}}));
(*block_ptr)->AddInstruction(std::move(newBranch));
}
void InlinePass::AddBranchCond(uint32_t cond_id, uint32_t true_id,
uint32_t false_id,
- std::unique_ptr<opt::BasicBlock>* block_ptr) {
- std::unique_ptr<opt::Instruction> newBranch(new opt::Instruction(
- context(), SpvOpBranchConditional, 0, 0,
- {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {cond_id}},
- {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {true_id}},
- {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {false_id}}}));
+ std::unique_ptr<BasicBlock>* block_ptr) {
+ std::unique_ptr<Instruction> newBranch(
+ new Instruction(context(), SpvOpBranchConditional, 0, 0,
+ {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {cond_id}},
+ {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {true_id}},
+ {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {false_id}}}));
(*block_ptr)->AddInstruction(std::move(newBranch));
}
void InlinePass::AddLoopMerge(uint32_t merge_id, uint32_t continue_id,
- std::unique_ptr<opt::BasicBlock>* block_ptr) {
- std::unique_ptr<opt::Instruction> newLoopMerge(new opt::Instruction(
+ std::unique_ptr<BasicBlock>* block_ptr) {
+ std::unique_ptr<Instruction> newLoopMerge(new Instruction(
context(), SpvOpLoopMerge, 0, 0,
{{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {merge_id}},
{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {continue_id}},
@@ -77,25 +77,25 @@ void InlinePass::AddLoopMerge(uint32_t merge_id, uint32_t continue_id,
}
void InlinePass::AddStore(uint32_t ptr_id, uint32_t val_id,
- std::unique_ptr<opt::BasicBlock>* block_ptr) {
- std::unique_ptr<opt::Instruction> newStore(new opt::Instruction(
- context(), SpvOpStore, 0, 0,
- {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {ptr_id}},
- {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {val_id}}}));
+ std::unique_ptr<BasicBlock>* block_ptr) {
+ std::unique_ptr<Instruction> newStore(
+ new Instruction(context(), SpvOpStore, 0, 0,
+ {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {ptr_id}},
+ {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {val_id}}}));
(*block_ptr)->AddInstruction(std::move(newStore));
}
void InlinePass::AddLoad(uint32_t type_id, uint32_t resultId, uint32_t ptr_id,
- std::unique_ptr<opt::BasicBlock>* block_ptr) {
- std::unique_ptr<opt::Instruction> newLoad(new opt::Instruction(
- context(), SpvOpLoad, type_id, resultId,
- {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {ptr_id}}}));
+ std::unique_ptr<BasicBlock>* block_ptr) {
+ std::unique_ptr<Instruction> newLoad(
+ new Instruction(context(), SpvOpLoad, type_id, resultId,
+ {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {ptr_id}}}));
(*block_ptr)->AddInstruction(std::move(newLoad));
}
-std::unique_ptr<opt::Instruction> InlinePass::NewLabel(uint32_t label_id) {
- std::unique_ptr<opt::Instruction> newLabel(
- new opt::Instruction(context(), SpvOpLabel, 0, label_id, {}));
+std::unique_ptr<Instruction> InlinePass::NewLabel(uint32_t label_id) {
+ std::unique_ptr<Instruction> newLabel(
+ new Instruction(context(), SpvOpLabel, 0, label_id, {}));
return newLabel;
}
@@ -114,11 +114,11 @@ uint32_t InlinePass::GetFalseId() {
}
void InlinePass::MapParams(
- opt::Function* calleeFn, opt::BasicBlock::iterator call_inst_itr,
+ Function* calleeFn, BasicBlock::iterator call_inst_itr,
std::unordered_map<uint32_t, uint32_t>* callee2caller) {
int param_idx = 0;
calleeFn->ForEachParam([&call_inst_itr, &param_idx,
- &callee2caller](const opt::Instruction* cpi) {
+ &callee2caller](const Instruction* cpi) {
const uint32_t pid = cpi->result_id();
(*callee2caller)[pid] = call_inst_itr->GetSingleWordOperand(
kSpvFunctionCallArgumentId + param_idx);
@@ -127,14 +127,12 @@ void InlinePass::MapParams(
}
void InlinePass::CloneAndMapLocals(
- opt::Function* calleeFn,
- std::vector<std::unique_ptr<opt::Instruction>>* new_vars,
+ Function* calleeFn, std::vector<std::unique_ptr<Instruction>>* new_vars,
std::unordered_map<uint32_t, uint32_t>* callee2caller) {
auto callee_block_itr = calleeFn->begin();
auto callee_var_itr = callee_block_itr->begin();
while (callee_var_itr->opcode() == SpvOp::SpvOpVariable) {
- std::unique_ptr<opt::Instruction> var_inst(
- callee_var_itr->Clone(context()));
+ std::unique_ptr<Instruction> var_inst(callee_var_itr->Clone(context()));
uint32_t newId = TakeNextId();
get_decoration_mgr()->CloneDecorations(callee_var_itr->result_id(), newId);
var_inst->SetResultId(newId);
@@ -145,8 +143,7 @@ void InlinePass::CloneAndMapLocals(
}
uint32_t InlinePass::CreateReturnVar(
- opt::Function* calleeFn,
- std::vector<std::unique_ptr<opt::Instruction>>* new_vars) {
+ Function* calleeFn, std::vector<std::unique_ptr<Instruction>>* new_vars) {
uint32_t returnVarId = 0;
const uint32_t calleeTypeId = calleeFn->type_id();
analysis::Type* calleeType = context()->get_type_mgr()->GetType(calleeTypeId);
@@ -158,25 +155,25 @@ uint32_t InlinePass::CreateReturnVar(
returnVarTypeId = AddPointerToType(calleeTypeId, SpvStorageClassFunction);
// Add return var to new function scope variables.
returnVarId = TakeNextId();
- std::unique_ptr<opt::Instruction> var_inst(new opt::Instruction(
- context(), SpvOpVariable, returnVarTypeId, returnVarId,
- {{spv_operand_type_t::SPV_OPERAND_TYPE_STORAGE_CLASS,
- {SpvStorageClassFunction}}}));
+ std::unique_ptr<Instruction> var_inst(
+ new Instruction(context(), SpvOpVariable, returnVarTypeId, returnVarId,
+ {{spv_operand_type_t::SPV_OPERAND_TYPE_STORAGE_CLASS,
+ {SpvStorageClassFunction}}}));
new_vars->push_back(std::move(var_inst));
}
get_decoration_mgr()->CloneDecorations(calleeFn->result_id(), returnVarId);
return returnVarId;
}
-bool InlinePass::IsSameBlockOp(const opt::Instruction* inst) const {
+bool InlinePass::IsSameBlockOp(const Instruction* inst) const {
return inst->opcode() == SpvOpSampledImage || inst->opcode() == SpvOpImage;
}
void InlinePass::CloneSameBlockOps(
- std::unique_ptr<opt::Instruction>* inst,
+ std::unique_ptr<Instruction>* inst,
std::unordered_map<uint32_t, uint32_t>* postCallSB,
- std::unordered_map<uint32_t, opt::Instruction*>* preCallSB,
- std::unique_ptr<opt::BasicBlock>* block_ptr) {
+ std::unordered_map<uint32_t, Instruction*>* preCallSB,
+ std::unique_ptr<BasicBlock>* block_ptr) {
(*inst)->ForEachInId(
[&postCallSB, &preCallSB, &block_ptr, this](uint32_t* iid) {
const auto mapItr = (*postCallSB).find(*iid);
@@ -184,8 +181,8 @@ void InlinePass::CloneSameBlockOps(
const auto mapItr2 = (*preCallSB).find(*iid);
if (mapItr2 != (*preCallSB).end()) {
// Clone pre-call same-block ops, map result id.
- const opt::Instruction* inInst = mapItr2->second;
- std::unique_ptr<opt::Instruction> sb_inst(inInst->Clone(context()));
+ const Instruction* inInst = mapItr2->second;
+ std::unique_ptr<Instruction> sb_inst(inInst->Clone(context()));
CloneSameBlockOps(&sb_inst, postCallSB, preCallSB, block_ptr);
const uint32_t rid = sb_inst->result_id();
const uint32_t nid = this->TakeNextId();
@@ -203,24 +200,24 @@ void InlinePass::CloneSameBlockOps(
}
void InlinePass::GenInlineCode(
- std::vector<std::unique_ptr<opt::BasicBlock>>* new_blocks,
- std::vector<std::unique_ptr<opt::Instruction>>* new_vars,
- opt::BasicBlock::iterator call_inst_itr,
- opt::UptrVectorIterator<opt::BasicBlock> call_block_itr) {
+ std::vector<std::unique_ptr<BasicBlock>>* new_blocks,
+ std::vector<std::unique_ptr<Instruction>>* new_vars,
+ BasicBlock::iterator call_inst_itr,
+ UptrVectorIterator<BasicBlock> call_block_itr) {
// Map from all ids in the callee to their equivalent id in the caller
// as callee instructions are copied into caller.
std::unordered_map<uint32_t, uint32_t> callee2caller;
// Pre-call same-block insts
- std::unordered_map<uint32_t, opt::Instruction*> preCallSB;
+ std::unordered_map<uint32_t, Instruction*> preCallSB;
// Post-call same-block op ids
std::unordered_map<uint32_t, uint32_t> postCallSB;
// Invalidate the def-use chains. They are not kept up to date while
// inlining. However, certain calls try to keep them up-to-date if they are
// valid. These operations can fail.
- context()->InvalidateAnalyses(opt::IRContext::kAnalysisDefUse);
+ context()->InvalidateAnalyses(IRContext::kAnalysisDefUse);
- opt::Function* calleeFn = id2function_[call_inst_itr->GetSingleWordOperand(
+ Function* calleeFn = id2function_[call_inst_itr->GetSingleWordOperand(
kSpvFunctionCallFunctionId)];
// Check for multiple returns in the callee.
@@ -239,7 +236,7 @@ void InlinePass::GenInlineCode(
// Create set of callee result ids. Used to detect forward references
std::unordered_set<uint32_t> callee_result_ids;
- calleeFn->ForEachInst([&callee_result_ids](const opt::Instruction* cpi) {
+ calleeFn->ForEachInst([&callee_result_ids](const Instruction* cpi) {
const uint32_t rid = cpi->result_id();
if (rid != 0) callee_result_ids.insert(rid);
});
@@ -274,15 +271,14 @@ void InlinePass::GenInlineCode(
// written to it. It is created when we encounter the OpLabel
// of the first callee block. It is appended to new_blocks only when
// it is complete.
- std::unique_ptr<opt::BasicBlock> new_blk_ptr;
+ std::unique_ptr<BasicBlock> new_blk_ptr;
calleeFn->ForEachInst([&new_blocks, &callee2caller, &call_block_itr,
&call_inst_itr, &new_blk_ptr, &prevInstWasReturn,
&returnLabelId, &returnVarId, caller_is_loop_header,
callee_begins_with_structured_header, &calleeTypeId,
&multiBlocks, &postCallSB, &preCallSB, multiReturn,
&singleTripLoopHeaderId, &singleTripLoopContinueId,
- &callee_result_ids,
- this](const opt::Instruction* cpi) {
+ &callee_result_ids, this](const Instruction* cpi) {
switch (cpi->opcode()) {
case SpvOpFunction:
case SpvOpFunctionParameter:
@@ -305,8 +301,8 @@ void InlinePass::GenInlineCode(
// Generate a return label so that we split the block with the function
// call. Copy the terminator into the new block.
if (returnLabelId == 0) returnLabelId = this->TakeNextId();
- std::unique_ptr<opt::Instruction> terminator(
- new opt::Instruction(context(), cpi->opcode(), 0, 0, {}));
+ std::unique_ptr<Instruction> terminator(
+ new Instruction(context(), cpi->opcode(), 0, 0, {}));
new_blk_ptr->AddInstruction(std::move(terminator));
break;
}
@@ -337,14 +333,14 @@ void InlinePass::GenInlineCode(
firstBlock = true;
}
// Create first/next block.
- new_blk_ptr.reset(new opt::BasicBlock(NewLabel(labelId)));
+ new_blk_ptr.reset(new BasicBlock(NewLabel(labelId)));
if (firstBlock) {
// Copy contents of original caller block up to call instruction.
for (auto cii = call_block_itr->begin(); cii != call_inst_itr;
cii = call_block_itr->begin()) {
- opt::Instruction* inst = &*cii;
+ Instruction* inst = &*cii;
inst->RemoveFromList();
- std::unique_ptr<opt::Instruction> cp_inst(inst);
+ std::unique_ptr<Instruction> cp_inst(inst);
// Remember same-block ops for possible regeneration.
if (IsSameBlockOp(&*cp_inst)) {
auto* sb_inst_ptr = cp_inst.get();
@@ -363,7 +359,7 @@ void InlinePass::GenInlineCode(
AddBranch(guard_block_id, &new_blk_ptr);
new_blocks->push_back(std::move(new_blk_ptr));
// Start the next block.
- new_blk_ptr.reset(new opt::BasicBlock(NewLabel(guard_block_id)));
+ new_blk_ptr.reset(new BasicBlock(NewLabel(guard_block_id)));
// Reset the mapping of the callee's entry block to point to
// the guard block. Do this so we can fix up phis later on to
// satisfy dominance.
@@ -384,15 +380,14 @@ void InlinePass::GenInlineCode(
singleTripLoopHeaderId = this->TakeNextId();
AddBranch(singleTripLoopHeaderId, &new_blk_ptr);
new_blocks->push_back(std::move(new_blk_ptr));
- new_blk_ptr.reset(
- new opt::BasicBlock(NewLabel(singleTripLoopHeaderId)));
+ new_blk_ptr.reset(new BasicBlock(NewLabel(singleTripLoopHeaderId)));
returnLabelId = this->TakeNextId();
singleTripLoopContinueId = this->TakeNextId();
AddLoopMerge(returnLabelId, singleTripLoopContinueId, &new_blk_ptr);
uint32_t postHeaderId = this->TakeNextId();
AddBranch(postHeaderId, &new_blk_ptr);
new_blocks->push_back(std::move(new_blk_ptr));
- new_blk_ptr.reset(new opt::BasicBlock(NewLabel(postHeaderId)));
+ new_blk_ptr.reset(new BasicBlock(NewLabel(postHeaderId)));
multiBlocks = true;
// Reset the mapping of the callee's entry block to point to
// the post-header block. Do this so we can fix up phis later
@@ -435,13 +430,13 @@ void InlinePass::GenInlineCode(
// target block now, with a false branch back to the loop header.
new_blocks->push_back(std::move(new_blk_ptr));
new_blk_ptr.reset(
- new opt::BasicBlock(NewLabel(singleTripLoopContinueId)));
+ new BasicBlock(NewLabel(singleTripLoopContinueId)));
AddBranchCond(GetFalseId(), singleTripLoopHeaderId, returnLabelId,
&new_blk_ptr);
}
// Generate the return block.
new_blocks->push_back(std::move(new_blk_ptr));
- new_blk_ptr.reset(new opt::BasicBlock(NewLabel(returnLabelId)));
+ new_blk_ptr.reset(new BasicBlock(NewLabel(returnLabelId)));
multiBlocks = true;
}
// Load return value into result id of call, if it exists.
@@ -451,10 +446,10 @@ void InlinePass::GenInlineCode(
AddLoad(calleeTypeId, resId, returnVarId, &new_blk_ptr);
}
// Copy remaining instructions from caller block.
- for (opt::Instruction* inst = call_inst_itr->NextNode(); inst;
+ for (Instruction* inst = call_inst_itr->NextNode(); inst;
inst = call_inst_itr->NextNode()) {
inst->RemoveFromList();
- std::unique_ptr<opt::Instruction> cp_inst(inst);
+ std::unique_ptr<Instruction> cp_inst(inst);
// If multiple blocks generated, regenerate any same-block
// instruction that has not been seen in this last block.
if (multiBlocks) {
@@ -472,7 +467,7 @@ void InlinePass::GenInlineCode(
} break;
default: {
// Copy callee instruction and remap all input Ids.
- std::unique_ptr<opt::Instruction> cp_inst(cpi->Clone(context()));
+ std::unique_ptr<Instruction> cp_inst(cpi->Clone(context()));
cp_inst->ForEachInId([&callee2caller, &callee_result_ids,
this](uint32_t* iid) {
const auto mapItr = callee2caller.find(*iid);
@@ -517,7 +512,7 @@ void InlinePass::GenInlineCode(
auto loop_merge_itr = last->tail();
--loop_merge_itr;
assert(loop_merge_itr->opcode() == SpvOpLoopMerge);
- std::unique_ptr<opt::Instruction> cp_inst(loop_merge_itr->Clone(context()));
+ std::unique_ptr<Instruction> cp_inst(loop_merge_itr->Clone(context()));
if (caller_is_single_block_loop) {
// Also, update its continue target to point to the last block.
cp_inst->SetInOperand(kSpvLoopMergeContinueTargetIdInIdx, {last->id()});
@@ -535,7 +530,7 @@ void InlinePass::GenInlineCode(
}
}
-bool InlinePass::IsInlinableFunctionCall(const opt::Instruction* inst) {
+bool InlinePass::IsInlinableFunctionCall(const Instruction* inst) {
if (inst->opcode() != SpvOp::SpvOpFunctionCall) return false;
const uint32_t calleeFnId =
inst->GetSingleWordOperand(kSpvFunctionCallFunctionId);
@@ -544,16 +539,16 @@ bool InlinePass::IsInlinableFunctionCall(const opt::Instruction* inst) {
}
void InlinePass::UpdateSucceedingPhis(
- std::vector<std::unique_ptr<opt::BasicBlock>>& new_blocks) {
+ std::vector<std::unique_ptr<BasicBlock>>& new_blocks) {
const auto firstBlk = new_blocks.begin();
const auto lastBlk = new_blocks.end() - 1;
const uint32_t firstId = (*firstBlk)->id();
const uint32_t lastId = (*lastBlk)->id();
- const opt::BasicBlock& const_last_block = *lastBlk->get();
+ const BasicBlock& const_last_block = *lastBlk->get();
const_last_block.ForEachSuccessorLabel(
[&firstId, &lastId, this](const uint32_t succ) {
- opt::BasicBlock* sbp = this->id2block_[succ];
- sbp->ForEachPhiInst([&firstId, &lastId](opt::Instruction* phi) {
+ BasicBlock* sbp = this->id2block_[succ];
+ sbp->ForEachPhiInst([&firstId, &lastId](Instruction* phi) {
phi->ForEachInId([&firstId, &lastId](uint32_t* id) {
if (*id == firstId) *id = lastId;
});
@@ -561,7 +556,7 @@ void InlinePass::UpdateSucceedingPhis(
});
}
-bool InlinePass::HasMultipleReturns(opt::Function* func) {
+bool InlinePass::HasMultipleReturns(Function* func) {
bool seenReturn = false;
bool multipleReturns = false;
for (auto& blk : *func) {
@@ -579,7 +574,7 @@ bool InlinePass::HasMultipleReturns(opt::Function* func) {
return multipleReturns;
}
-void InlinePass::ComputeStructuredSuccessors(opt::Function* func) {
+void InlinePass::ComputeStructuredSuccessors(Function* func) {
// If header, make merge block first successor.
for (auto& blk : *func) {
uint32_t mbid = blk.MergeBlockIdIfAny();
@@ -596,12 +591,12 @@ void InlinePass::ComputeStructuredSuccessors(opt::Function* func) {
}
InlinePass::GetBlocksFunction InlinePass::StructuredSuccessorsFunction() {
- return [this](const opt::BasicBlock* block) {
+ return [this](const BasicBlock* block) {
return &(block2structured_succs_[block]);
};
}
-bool InlinePass::HasNoReturnInLoop(opt::Function* func) {
+bool InlinePass::HasNoReturnInLoop(Function* func) {
// If control not structured, do not do loop/return analysis
// TODO: Analyze returns in non-structured control flow
if (!context()->get_feature_mgr()->HasCapability(SpvCapabilityShader))
@@ -612,8 +607,8 @@ bool InlinePass::HasNoReturnInLoop(opt::Function* func) {
ComputeStructuredSuccessors(func);
auto ignore_block = [](cbb_ptr) {};
auto ignore_edge = [](cbb_ptr, cbb_ptr) {};
- std::list<const opt::BasicBlock*> structuredOrder;
- CFA<opt::BasicBlock>::DepthFirstTraversal(
+ std::list<const BasicBlock*> structuredOrder;
+ CFA<BasicBlock>::DepthFirstTraversal(
&*func->begin(), StructuredSuccessorsFunction(), ignore_block,
[&](cbb_ptr b) { structuredOrder.push_front(b); }, ignore_edge);
// Search for returns in loops. Only need to track outermost loop
@@ -643,7 +638,7 @@ bool InlinePass::HasNoReturnInLoop(opt::Function* func) {
return !return_in_loop;
}
-void InlinePass::AnalyzeReturns(opt::Function* func) {
+void InlinePass::AnalyzeReturns(Function* func) {
// Look for multiple returns
if (!HasMultipleReturns(func)) {
no_return_in_loop_.insert(func->result_id());
@@ -654,7 +649,7 @@ void InlinePass::AnalyzeReturns(opt::Function* func) {
if (HasNoReturnInLoop(func)) no_return_in_loop_.insert(func->result_id());
}
-bool InlinePass::IsInlinableFunction(opt::Function* func) {
+bool InlinePass::IsInlinableFunction(Function* func) {
// We can only inline a function if it has blocks.
if (func->cbegin() == func->cend()) return false;
// Do not inline functions with returns in loops. Currently early return