diff options
author | dan sinclair <dj2@everburning.com> | 2018-07-12 15:14:43 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-07-12 15:14:43 -0400 |
commit | c7da51a0855d0d32627b0b38edacc3cb0d407c4f (patch) | |
tree | 4a0e158be2508aff0ce423f0de7911ad6def0370 /source | |
parent | e477e7573ed02f0db6e84438c916a1a2206a4255 (diff) |
Cleanup extraneous namespace qualifies in source/opt. (#1716)
This CL follows up on the opt namespacing CLs by removing the
unnecessary opt:: and opt::analysis:: namespace prefixes.
Diffstat (limited to 'source')
144 files changed, 3146 insertions, 3412 deletions
diff --git a/source/opt/aggressive_dead_code_elim_pass.cpp b/source/opt/aggressive_dead_code_elim_pass.cpp index d0bcbbdc..54fc8d71 100644 --- a/source/opt/aggressive_dead_code_elim_pass.cpp +++ b/source/opt/aggressive_dead_code_elim_pass.cpp @@ -50,8 +50,7 @@ const uint32_t kCopyMemorySourceAddrInIdx = 1; // SpvOpDecorateStringGOOGLE // SpvOpDecorationGroup struct DecorationLess { - bool operator()(const opt::Instruction* lhs, - const opt::Instruction* rhs) const { + bool operator()(const Instruction* lhs, const Instruction* rhs) const { assert(lhs && rhs); SpvOp lhsOp = lhs->opcode(); SpvOp rhsOp = rhs->opcode(); @@ -82,11 +81,11 @@ struct DecorationLess { bool AggressiveDCEPass::IsVarOfStorage(uint32_t varId, uint32_t storageClass) { if (varId == 0) return false; - const opt::Instruction* varInst = get_def_use_mgr()->GetDef(varId); + const Instruction* varInst = get_def_use_mgr()->GetDef(varId); const SpvOp op = varInst->opcode(); if (op != SpvOpVariable) return false; const uint32_t varTypeId = varInst->type_id(); - const opt::Instruction* varTypeInst = get_def_use_mgr()->GetDef(varTypeId); + const Instruction* varTypeInst = get_def_use_mgr()->GetDef(varTypeId); if (varTypeInst->opcode() != SpvOpTypePointer) return false; return varTypeInst->GetSingleWordInOperand(kTypePointerStorageClassInIdx) == storageClass; @@ -105,7 +104,7 @@ bool AggressiveDCEPass::IsLocalVar(uint32_t varId) { } void AggressiveDCEPass::AddStores(uint32_t ptrId) { - get_def_use_mgr()->ForEachUser(ptrId, [this, ptrId](opt::Instruction* user) { + get_def_use_mgr()->ForEachUser(ptrId, [this, ptrId](Instruction* user) { switch (user->opcode()) { case SpvOpAccessChain: case SpvOpInBoundsAccessChain: @@ -140,7 +139,7 @@ bool AggressiveDCEPass::AllExtensionsSupported() const { return true; } -bool AggressiveDCEPass::IsDead(opt::Instruction* inst) { +bool AggressiveDCEPass::IsDead(Instruction* inst) { if (IsLive(inst)) return false; if (inst->IsBranch() && !IsStructuredHeader(context()->get_instr_block(inst), nullptr, nullptr, nullptr)) @@ -148,16 +147,16 @@ bool AggressiveDCEPass::IsDead(opt::Instruction* inst) { return true; } -bool AggressiveDCEPass::IsTargetDead(opt::Instruction* inst) { +bool AggressiveDCEPass::IsTargetDead(Instruction* inst) { const uint32_t tId = inst->GetSingleWordInOperand(0); - opt::Instruction* tInst = get_def_use_mgr()->GetDef(tId); - if (opt::IsAnnotationInst(tInst->opcode())) { + Instruction* tInst = get_def_use_mgr()->GetDef(tId); + if (IsAnnotationInst(tInst->opcode())) { // This must be a decoration group. We go through annotations in a specific // order. So if this is not used by any group or group member decorates, it // is dead. assert(tInst->opcode() == SpvOpDecorationGroup); bool dead = true; - get_def_use_mgr()->ForEachUser(tInst, [&dead](opt::Instruction* user) { + get_def_use_mgr()->ForEachUser(tInst, [&dead](Instruction* user) { if (user->opcode() == SpvOpGroupDecorate || user->opcode() == SpvOpGroupMemberDecorate) dead = false; @@ -178,14 +177,14 @@ void AggressiveDCEPass::ProcessLoad(uint32_t varId) { live_local_vars_.insert(varId); } -bool AggressiveDCEPass::IsStructuredHeader(opt::BasicBlock* bp, - opt::Instruction** mergeInst, - opt::Instruction** branchInst, +bool AggressiveDCEPass::IsStructuredHeader(BasicBlock* bp, + Instruction** mergeInst, + Instruction** branchInst, uint32_t* mergeBlockId) { if (!bp) return false; - opt::Instruction* mi = bp->GetMergeInst(); + Instruction* mi = bp->GetMergeInst(); if (mi == nullptr) return false; - opt::Instruction* bri = &*bp->tail(); + Instruction* bri = &*bp->tail(); if (branchInst != nullptr) *branchInst = bri; if (mergeInst != nullptr) *mergeInst = mi; if (mergeBlockId != nullptr) *mergeBlockId = mi->GetSingleWordInOperand(0); @@ -193,11 +192,11 @@ bool AggressiveDCEPass::IsStructuredHeader(opt::BasicBlock* bp, } void AggressiveDCEPass::ComputeBlock2HeaderMaps( - std::list<opt::BasicBlock*>& structuredOrder) { + std::list<BasicBlock*>& structuredOrder) { block2headerBranch_.clear(); branch2merge_.clear(); structured_order_index_.clear(); - std::stack<opt::Instruction*> currentHeaderBranch; + std::stack<Instruction*> currentHeaderBranch; currentHeaderBranch.push(nullptr); uint32_t currentMergeBlockId = 0; uint32_t index = 0; @@ -208,12 +207,12 @@ void AggressiveDCEPass::ComputeBlock2HeaderMaps( // we are leaving the current construct so we must update state if ((*bi)->id() == currentMergeBlockId) { currentHeaderBranch.pop(); - opt::Instruction* chb = currentHeaderBranch.top(); + Instruction* chb = currentHeaderBranch.top(); if (chb != nullptr) currentMergeBlockId = branch2merge_[chb]->GetSingleWordInOperand(0); } - opt::Instruction* mergeInst; - opt::Instruction* branchInst; + Instruction* mergeInst; + Instruction* branchInst; uint32_t mergeBlockId; bool is_header = IsStructuredHeader(*bi, &mergeInst, &branchInst, &mergeBlockId); @@ -235,45 +234,44 @@ void AggressiveDCEPass::ComputeBlock2HeaderMaps( } } -void AggressiveDCEPass::AddBranch(uint32_t labelId, opt::BasicBlock* bp) { - std::unique_ptr<opt::Instruction> newBranch(new opt::Instruction( - context(), SpvOpBranch, 0, 0, - {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {labelId}}})); +void AggressiveDCEPass::AddBranch(uint32_t labelId, BasicBlock* bp) { + std::unique_ptr<Instruction> newBranch( + new Instruction(context(), SpvOpBranch, 0, 0, + {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {labelId}}})); context()->AnalyzeDefUse(&*newBranch); context()->set_instr_block(&*newBranch, bp); bp->AddInstruction(std::move(newBranch)); } void AggressiveDCEPass::AddBreaksAndContinuesToWorklist( - opt::Instruction* loopMerge) { - opt::BasicBlock* header = context()->get_instr_block(loopMerge); + Instruction* loopMerge) { + BasicBlock* header = context()->get_instr_block(loopMerge); uint32_t headerIndex = structured_order_index_[header]; const uint32_t mergeId = loopMerge->GetSingleWordInOperand(kLoopMergeMergeBlockIdInIdx); - opt::BasicBlock* merge = context()->get_instr_block(mergeId); + BasicBlock* merge = context()->get_instr_block(mergeId); uint32_t mergeIndex = structured_order_index_[merge]; get_def_use_mgr()->ForEachUser( - mergeId, [headerIndex, mergeIndex, this](opt::Instruction* user) { + mergeId, [headerIndex, mergeIndex, this](Instruction* user) { if (!user->IsBranch()) return; - opt::BasicBlock* block = context()->get_instr_block(user); + BasicBlock* block = context()->get_instr_block(user); uint32_t index = structured_order_index_[block]; if (headerIndex < index && index < mergeIndex) { // This is a break from the loop. AddToWorklist(user); // Add branch's merge if there is one. - opt::Instruction* userMerge = branch2merge_[user]; + Instruction* userMerge = branch2merge_[user]; if (userMerge != nullptr) AddToWorklist(userMerge); } }); const uint32_t contId = loopMerge->GetSingleWordInOperand(kLoopMergeContinueBlockIdInIdx); - get_def_use_mgr()->ForEachUser(contId, [&contId, - this](opt::Instruction* user) { + get_def_use_mgr()->ForEachUser(contId, [&contId, this](Instruction* user) { SpvOp op = user->opcode(); if (op == SpvOpBranchConditional || op == SpvOpSwitch) { // A conditional branch or switch can only be a continue if it does not // have a merge instruction or its merge block is not the continue block. - opt::Instruction* hdrMerge = branch2merge_[user]; + Instruction* hdrMerge = branch2merge_[user]; if (hdrMerge != nullptr && hdrMerge->opcode() == SpvOpSelectionMerge) { uint32_t hdrMergeId = hdrMerge->GetSingleWordInOperand(kSelectionMergeMergeBlockIdInIdx); @@ -284,10 +282,10 @@ void AggressiveDCEPass::AddBreaksAndContinuesToWorklist( } else if (op == SpvOpBranch) { // An unconditional branch can only be a continue if it is not // branching to its own merge block. - opt::BasicBlock* blk = context()->get_instr_block(user); - opt::Instruction* hdrBranch = block2headerBranch_[blk]; + BasicBlock* blk = context()->get_instr_block(user); + Instruction* hdrBranch = block2headerBranch_[blk]; if (hdrBranch == nullptr) return; - opt::Instruction* hdrMerge = branch2merge_[hdrBranch]; + Instruction* hdrMerge = branch2merge_[hdrBranch]; if (hdrMerge->opcode() == SpvOpLoopMerge) return; uint32_t hdrMergeId = hdrMerge->GetSingleWordInOperand(kSelectionMergeMergeBlockIdInIdx); @@ -299,17 +297,17 @@ void AggressiveDCEPass::AddBreaksAndContinuesToWorklist( }); } -bool AggressiveDCEPass::AggressiveDCE(opt::Function* func) { +bool AggressiveDCEPass::AggressiveDCE(Function* func) { // Mark function parameters as live. AddToWorklist(&func->DefInst()); func->ForEachParam( - [this](const opt::Instruction* param) { - AddToWorklist(const_cast<opt::Instruction*>(param)); + [this](const Instruction* param) { + AddToWorklist(const_cast<Instruction*>(param)); }, false); // Compute map from block to controlling conditional branch - std::list<opt::BasicBlock*> structuredOrder; + std::list<BasicBlock*> structuredOrder; cfg()->ComputeStructuredOrder(func, &*func->begin(), &structuredOrder); ComputeBlock2HeaderMaps(structuredOrder); bool modified = false; @@ -404,10 +402,10 @@ bool AggressiveDCEPass::AggressiveDCE(opt::Function* func) { for (auto& ps : private_stores_) AddToWorklist(ps); // Perform closure on live instruction set. while (!worklist_.empty()) { - opt::Instruction* liveInst = worklist_.front(); + Instruction* liveInst = worklist_.front(); // Add all operand instructions if not already live liveInst->ForEachInId([&liveInst, this](const uint32_t* iid) { - opt::Instruction* inInst = get_def_use_mgr()->GetDef(*iid); + Instruction* inInst = get_def_use_mgr()->GetDef(*iid); // Do not add label if an operand of a branch. This is not needed // as part of live code discovery and can create false live code, // for example, the branch to a header of a loop. @@ -421,11 +419,11 @@ bool AggressiveDCEPass::AggressiveDCE(opt::Function* func) { // conditional branch and its merge. Any containing control construct // is marked live when the merge and branch are processed out of the // worklist. - opt::BasicBlock* blk = context()->get_instr_block(liveInst); - opt::Instruction* branchInst = block2headerBranch_[blk]; + BasicBlock* blk = context()->get_instr_block(liveInst); + Instruction* branchInst = block2headerBranch_[blk]; if (branchInst != nullptr) { AddToWorklist(branchInst); - opt::Instruction* mergeInst = branch2merge_[branchInst]; + Instruction* mergeInst = branch2merge_[branchInst]; AddToWorklist(mergeInst); // If in a loop, mark all its break and continue instructions live if (mergeInst->opcode() == SpvOpLoopMerge) @@ -473,8 +471,7 @@ bool AggressiveDCEPass::AggressiveDCE(opt::Function* func) { // Kill dead instructions and remember dead blocks for (auto bi = structuredOrder.begin(); bi != structuredOrder.end();) { uint32_t mergeBlockId = 0; - (*bi)->ForEachInst([this, &modified, - &mergeBlockId](opt::Instruction* inst) { + (*bi)->ForEachInst([this, &modified, &mergeBlockId](Instruction* inst) { if (!IsDead(inst)) return; if (inst->opcode() == SpvOpLabel) return; // If dead instruction is selection merge, remember merge block @@ -540,7 +537,7 @@ Pass::Status AggressiveDCEPass::ProcessImpl() { InitializeModuleScopeLiveInstructions(); // Process all entry point functions. - ProcessFunction pfn = [this](opt::Function* fp) { return AggressiveDCE(fp); }; + ProcessFunction pfn = [this](Function* fp) { return AggressiveDCE(fp); }; modified |= ProcessEntryPointCallTree(pfn, get_module()); // Process module-level instructions. Now that all live instructions have @@ -553,7 +550,7 @@ Pass::Status AggressiveDCEPass::ProcessImpl() { } // Cleanup all CFG including all unreachable blocks. - ProcessFunction cleanup = [this](opt::Function* f) { return CFGCleanup(f); }; + ProcessFunction cleanup = [this](Function* f) { return CFGCleanup(f); }; modified |= ProcessEntryPointCallTree(cleanup, get_module()); return modified ? Status::SuccessWithChange : Status::SuccessWithoutChange; @@ -563,8 +560,8 @@ bool AggressiveDCEPass::EliminateDeadFunctions() { // Identify live functions first. Those that are not live // are dead. ADCE is disabled for non-shaders so we do not check for exported // functions here. - std::unordered_set<const opt::Function*> live_function_set; - ProcessFunction mark_live = [&live_function_set](opt::Function* fp) { + std::unordered_set<const Function*> live_function_set; + ProcessFunction mark_live = [&live_function_set](Function* fp) { live_function_set.insert(fp); return false; }; @@ -585,10 +582,10 @@ bool AggressiveDCEPass::EliminateDeadFunctions() { return modified; } -void AggressiveDCEPass::EliminateFunction(opt::Function* func) { +void AggressiveDCEPass::EliminateFunction(Function* func) { // Remove all of the instruction in the function body - func->ForEachInst( - [this](opt::Instruction* inst) { context()->KillInst(inst); }, true); + func->ForEachInst([this](Instruction* inst) { context()->KillInst(inst); }, + true); } bool AggressiveDCEPass::ProcessGlobalValues() { @@ -596,7 +593,7 @@ bool AggressiveDCEPass::ProcessGlobalValues() { // This must be done before killing the instructions, otherwise there are // dead objects in the def/use database. bool modified = false; - opt::Instruction* instruction = &*get_module()->debug2_begin(); + Instruction* instruction = &*get_module()->debug2_begin(); while (instruction) { if (instruction->opcode() != SpvOpName) { instruction = instruction->NextNode(); @@ -614,7 +611,7 @@ bool AggressiveDCEPass::ProcessGlobalValues() { // This code removes all unnecessary decorations safely (see #1174). It also // does so in a more efficient manner than deleting them only as the targets // are deleted. - std::vector<opt::Instruction*> annotations; + std::vector<Instruction*> annotations; for (auto& inst : get_module()->annotations()) annotations.push_back(&inst); std::sort(annotations.begin(), annotations.end(), DecorationLess()); for (auto annotation : annotations) { @@ -633,7 +630,7 @@ bool AggressiveDCEPass::ProcessGlobalValues() { // target. If all targets are dead, remove this decoration. bool dead = true; for (uint32_t i = 1; i < annotation->NumOperands();) { - opt::Instruction* opInst = + Instruction* opInst = get_def_use_mgr()->GetDef(annotation->GetSingleWordOperand(i)); if (IsDead(opInst)) { // Don't increment |i|. @@ -656,7 +653,7 @@ bool AggressiveDCEPass::ProcessGlobalValues() { // decoration. bool dead = true; for (uint32_t i = 1; i < annotation->NumOperands();) { - opt::Instruction* opInst = + Instruction* opInst = get_def_use_mgr()->GetDef(annotation->GetSingleWordOperand(i)); if (IsDead(opInst)) { // Don't increment |i|. diff --git a/source/opt/aggressive_dead_code_elim_pass.h b/source/opt/aggressive_dead_code_elim_pass.h index 88c74111..34481eb1 100644 --- a/source/opt/aggressive_dead_code_elim_pass.h +++ b/source/opt/aggressive_dead_code_elim_pass.h @@ -35,19 +35,18 @@ namespace opt { // See optimizer.hpp for documentation. class AggressiveDCEPass : public MemPass { - using cbb_ptr = const opt::BasicBlock*; + using cbb_ptr = const BasicBlock*; public: using GetBlocksFunction = - std::function<std::vector<opt::BasicBlock*>*(const opt::BasicBlock*)>; + std::function<std::vector<BasicBlock*>*(const BasicBlock*)>; AggressiveDCEPass(); const char* name() const override { return "eliminate-dead-code-aggressive"; } Status Process() override; - opt::IRContext::Analysis GetPreservedAnalyses() override { - return opt::IRContext::kAnalysisDefUse | - opt::IRContext::kAnalysisInstrToBlockMapping; + IRContext::Analysis GetPreservedAnalyses() override { + return IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping; } private: @@ -61,19 +60,19 @@ class AggressiveDCEPass : public MemPass { bool IsLocalVar(uint32_t varId); // Return true if |inst| is marked live. - bool IsLive(const opt::Instruction* inst) const { + bool IsLive(const Instruction* inst) const { return live_insts_.Get(inst->unique_id()); } // Returns true if |inst| is dead. - bool IsDead(opt::Instruction* inst); + bool IsDead(Instruction* inst); // Adds entry points, execution modes and workgroup size decorations to the // worklist for processing with the first function. void InitializeModuleScopeLiveInstructions(); // Add |inst| to worklist_ and live_insts_. - void AddToWorklist(opt::Instruction* inst) { + void AddToWorklist(Instruction* inst) { if (!live_insts_.Set(inst->unique_id())) { worklist_.push(inst); } @@ -92,7 +91,7 @@ class AggressiveDCEPass : public MemPass { // Returns true if the target of |inst| is dead. An instruction is dead if // its result id is used in decoration or debug instructions only. |inst| is // assumed to be OpName, OpMemberName or an annotation instruction. - bool IsTargetDead(opt::Instruction* inst); + bool IsTargetDead(Instruction* inst); // If |varId| is local, mark all stores of varId as live. void ProcessLoad(uint32_t varId); @@ -102,20 +101,19 @@ class AggressiveDCEPass : public MemPass { // merge block if they are not nullptr. Any of |mergeInst|, |branchInst| or // |mergeBlockId| may be a null pointer. Returns false if |bp| is a null // pointer. - bool IsStructuredHeader(opt::BasicBlock* bp, opt::Instruction** mergeInst, - opt::Instruction** branchInst, - uint32_t* mergeBlockId); + bool IsStructuredHeader(BasicBlock* bp, Instruction** mergeInst, + Instruction** branchInst, uint32_t* mergeBlockId); // Initialize block2headerBranch_ and branch2merge_ using |structuredOrder| // to order blocks. - void ComputeBlock2HeaderMaps(std::list<opt::BasicBlock*>& structuredOrder); + void ComputeBlock2HeaderMaps(std::list<BasicBlock*>& structuredOrder); // Add branch to |labelId| to end of block |bp|. - void AddBranch(uint32_t labelId, opt::BasicBlock* bp); + void AddBranch(uint32_t labelId, BasicBlock* bp); // Add all break and continue branches in the loop associated with // |mergeInst| to worklist if not already live - void AddBreaksAndContinuesToWorklist(opt::Instruction* mergeInst); + void AddBreaksAndContinuesToWorklist(Instruction* mergeInst); // Eliminates dead debug2 and annotation instructions. Marks dead globals for // removal (e.g. types, constants and variables). @@ -125,7 +123,7 @@ class AggressiveDCEPass : public MemPass { bool EliminateDeadFunctions(); // Removes |func| from the module and deletes all its instructions. - void EliminateFunction(opt::Function* func); + void EliminateFunction(Function* func); // For function |func|, mark all Stores to non-function-scope variables // and block terminating instructions as live. Recursively mark the values @@ -136,7 +134,7 @@ class AggressiveDCEPass : public MemPass { // existing control structures will remain. This can leave not-insignificant // sequences of ultimately useless code. // TODO(): Remove useless control constructs. - bool AggressiveDCE(opt::Function* func); + bool AggressiveDCE(Function* func); Pass::Status ProcessImpl(); @@ -154,22 +152,22 @@ class AggressiveDCEPass : public MemPass { // If we don't know, then add it to this list. Instructions are // removed from this list as the algorithm traces side effects, // building up the live instructions set |live_insts_|. - std::queue<opt::Instruction*> worklist_; + std::queue<Instruction*> worklist_; // Map from block to the branch instruction in the header of the most // immediate controlling structured if or loop. A loop header block points // to its own branch instruction. An if-selection block points to the branch // of an enclosing construct's header, if one exists. - std::unordered_map<opt::BasicBlock*, opt::Instruction*> block2headerBranch_; + std::unordered_map<BasicBlock*, Instruction*> block2headerBranch_; // Maps basic block to their index in the structured order traversal. - std::unordered_map<opt::BasicBlock*, uint32_t> structured_order_index_; + std::unordered_map<BasicBlock*, uint32_t> structured_order_index_; // Map from branch to its associated merge instruction, if any - std::unordered_map<opt::Instruction*, opt::Instruction*> branch2merge_; + std::unordered_map<Instruction*, Instruction*> branch2merge_; // Store instructions to variables of private storage - std::vector<opt::Instruction*> private_stores_; + std::vector<Instruction*> private_stores_; // Live Instructions utils::BitVector live_insts_; @@ -179,7 +177,7 @@ class AggressiveDCEPass : public MemPass { // List of instructions to delete. Deletion is delayed until debug and // annotation instructions are processed. - std::vector<opt::Instruction*> to_kill_; + std::vector<Instruction*> to_kill_; // Extensions supported by this pass. std::unordered_set<std::string> extensions_whitelist_; diff --git a/source/opt/basic_block.cpp b/source/opt/basic_block.cpp index 292341c8..5005061b 100644 --- a/source/opt/basic_block.cpp +++ b/source/opt/basic_block.cpp @@ -90,7 +90,7 @@ Instruction* BasicBlock::GetLoopMergeInst() { } void BasicBlock::KillAllInsts(bool killLabel) { - ForEachInst([killLabel](opt::Instruction* ip) { + ForEachInst([killLabel](Instruction* ip) { if (killLabel || ip->opcode() != SpvOpLabel) { ip->context()->KillInst(ip); } @@ -139,7 +139,7 @@ void BasicBlock::ForEachSuccessorLabel( } } -bool BasicBlock::IsSuccessor(const opt::BasicBlock* block) const { +bool BasicBlock::IsSuccessor(const BasicBlock* block) const { uint32_t succId = block->id(); bool isSuccessor = false; ForEachSuccessorLabel([&isSuccessor, succId](const uint32_t label) { @@ -195,7 +195,7 @@ std::ostream& operator<<(std::ostream& str, const BasicBlock& block) { std::string BasicBlock::PrettyPrint(uint32_t options) const { std::ostringstream str; - ForEachInst([&str, options](const opt::Instruction* inst) { + ForEachInst([&str, options](const Instruction* inst) { str << inst->PrettyPrint(options); if (!IsTerminatorInst(inst->opcode())) { str << std::endl; @@ -209,13 +209,13 @@ BasicBlock* BasicBlock::SplitBasicBlock(IRContext* context, uint32_t label_id, assert(!insts_.empty()); BasicBlock* new_block = new BasicBlock(MakeUnique<Instruction>( - context, SpvOpLabel, 0, label_id, std::initializer_list<opt::Operand>{})); + context, SpvOpLabel, 0, label_id, std::initializer_list<Operand>{})); new_block->insts_.Splice(new_block->end(), &insts_, iter, end()); new_block->SetParent(GetParent()); - if (context->AreAnalysesValid(opt::IRContext::kAnalysisInstrToBlockMapping)) { - new_block->ForEachInst([new_block, context](opt::Instruction* inst) { + if (context->AreAnalysesValid(IRContext::kAnalysisInstrToBlockMapping)) { + new_block->ForEachInst([new_block, context](Instruction* inst) { context->set_instr_block(inst, new_block); }); } diff --git a/source/opt/basic_block.h b/source/opt/basic_block.h index 12252500..1277c176 100644 --- a/source/opt/basic_block.h +++ b/source/opt/basic_block.h @@ -159,14 +159,14 @@ class BasicBlock { void ForEachSuccessorLabel(const std::function<void(uint32_t*)>& f); // Returns true if |block| is a direct successor of |this|. - bool IsSuccessor(const opt::BasicBlock* block) const; + bool IsSuccessor(const BasicBlock* block) const; // Runs the given function |f| on the merge and continue label, if any void ForMergeAndContinueLabel(const std::function<void(const uint32_t)>& f); // Returns true if this basic block has any Phi instructions. bool HasPhiInstructions() { - return !WhileEachPhiInst([](opt::Instruction*) { return false; }); + return !WhileEachPhiInst([](Instruction*) { return false; }); } // Return true if this block is a loop header block. diff --git a/source/opt/block_merge_pass.cpp b/source/opt/block_merge_pass.cpp index 19fbc44e..9d5bc5cd 100644 --- a/source/opt/block_merge_pass.cpp +++ b/source/opt/block_merge_pass.cpp @@ -22,9 +22,9 @@ namespace spvtools { namespace opt { -void BlockMergePass::KillInstAndName(opt::Instruction* inst) { - std::vector<opt::Instruction*> to_kill; - get_def_use_mgr()->ForEachUser(inst, [&to_kill](opt::Instruction* user) { +void BlockMergePass::KillInstAndName(Instruction* inst) { + std::vector<Instruction*> to_kill; + get_def_use_mgr()->ForEachUser(inst, [&to_kill](Instruction* user) { if (user->opcode() == SpvOpName) { to_kill.push_back(user); } @@ -35,13 +35,13 @@ void BlockMergePass::KillInstAndName(opt::Instruction* inst) { context()->KillInst(inst); } -bool BlockMergePass::MergeBlocks(opt::Function* func) { +bool BlockMergePass::MergeBlocks(Function* func) { bool modified = false; for (auto bi = func->begin(); bi != func->end();) { // Find block with single successor which has no other predecessors. auto ii = bi->end(); --ii; - opt::Instruction* br = &*ii; + Instruction* br = &*ii; if (br->opcode() != SpvOpBranch) { ++bi; continue; @@ -69,14 +69,14 @@ bool BlockMergePass::MergeBlocks(opt::Function* func) { continue; } - opt::Instruction* merge_inst = bi->GetMergeInst(); + Instruction* merge_inst = bi->GetMergeInst(); if (pred_is_header && lab_id != merge_inst->GetSingleWordInOperand(0u)) { // If this is a header block and the successor is not its merge, we must // be careful about which blocks we are willing to merge together. // OpLoopMerge must be followed by a conditional or unconditional branch. // The merge must be a loop merge because a selection merge cannot be // followed by an unconditional branch. - opt::BasicBlock* succ_block = context()->get_instr_block(lab_id); + BasicBlock* succ_block = context()->get_instr_block(lab_id); SpvOp succ_term_op = succ_block->terminator()->opcode(); assert(merge_inst->opcode() == SpvOpLoopMerge); if (succ_term_op != SpvOpBranch && @@ -122,7 +122,7 @@ bool BlockMergePass::MergeBlocks(opt::Function* func) { return modified; } -bool BlockMergePass::IsHeader(opt::BasicBlock* block) { +bool BlockMergePass::IsHeader(BasicBlock* block) { return block->GetMergeInst() != nullptr; } @@ -131,7 +131,7 @@ bool BlockMergePass::IsHeader(uint32_t id) { } bool BlockMergePass::IsMerge(uint32_t id) { - return !get_def_use_mgr()->WhileEachUse(id, [](opt::Instruction* user, + return !get_def_use_mgr()->WhileEachUse(id, [](Instruction* user, uint32_t index) { SpvOp op = user->opcode(); if ((op == SpvOpLoopMerge || op == SpvOpSelectionMerge) && index == 0u) { @@ -141,13 +141,11 @@ bool BlockMergePass::IsMerge(uint32_t id) { }); } -bool BlockMergePass::IsMerge(opt::BasicBlock* block) { - return IsMerge(block->id()); -} +bool BlockMergePass::IsMerge(BasicBlock* block) { return IsMerge(block->id()); } Pass::Status BlockMergePass::Process() { // Process all entry point functions. - ProcessFunction pfn = [this](opt::Function* fp) { return MergeBlocks(fp); }; + ProcessFunction pfn = [this](Function* fp) { return MergeBlocks(fp); }; bool modified = ProcessEntryPointCallTree(pfn, get_module()); return modified ? Status::SuccessWithChange : Status::SuccessWithoutChange; } diff --git a/source/opt/block_merge_pass.h b/source/opt/block_merge_pass.h index ed11443c..d11e44b8 100644 --- a/source/opt/block_merge_pass.h +++ b/source/opt/block_merge_pass.h @@ -40,29 +40,28 @@ class BlockMergePass : public Pass { const char* name() const override { return "merge-blocks"; } Status Process() override; - opt::IRContext::Analysis GetPreservedAnalyses() override { - return opt::IRContext::kAnalysisDefUse | - opt::IRContext::kAnalysisInstrToBlockMapping | - opt::IRContext::kAnalysisDecorations | - opt::IRContext::kAnalysisCombinators | - opt::IRContext::kAnalysisNameMap; + IRContext::Analysis GetPreservedAnalyses() override { + return IRContext::kAnalysisDefUse | + IRContext::kAnalysisInstrToBlockMapping | + IRContext::kAnalysisDecorations | IRContext::kAnalysisCombinators | + IRContext::kAnalysisNameMap; } private: // Kill any OpName instruction referencing |inst|, then kill |inst|. - void KillInstAndName(opt::Instruction* inst); + void KillInstAndName(Instruction* inst); // Search |func| for blocks which have a single Branch to a block // with no other predecessors. Merge these blocks into a single block. - bool MergeBlocks(opt::Function* func); + bool MergeBlocks(Function* func); // Returns true if |block| (or |id|) contains a merge instruction. - bool IsHeader(opt::BasicBlock* block); + bool IsHeader(BasicBlock* block); bool IsHeader(uint32_t id); // Returns true if |block| (or |id|) is the merge target of a merge // instruction. - bool IsMerge(opt::BasicBlock* block); + bool IsMerge(BasicBlock* block); bool IsMerge(uint32_t id); }; diff --git a/source/opt/build_module.h b/source/opt/build_module.h index 336b5690..aca7b242 100644 --- a/source/opt/build_module.h +++ b/source/opt/build_module.h @@ -24,7 +24,7 @@ namespace spvtools { -// Builds an opt::Module returns the owning opt::IRContext from the given SPIR-V +// Builds an Module returns the owning IRContext from the given SPIR-V // |binary|. |size| specifies number of words in |binary|. The |binary| will be // decoded according to the given target |env|. Returns nullptr if errors occur // and sends the errors to |consumer|. @@ -33,7 +33,7 @@ std::unique_ptr<opt::IRContext> BuildModule(spv_target_env env, const uint32_t* binary, size_t size); -// Builds an opt::Module and returns the owning opt::IRContext from the given +// Builds an Module and returns the owning IRContext from the given // SPIR-V assembly |text|. The |text| will be encoded according to the given // target |env|. Returns nullptr if errors occur and sends the errors to // |consumer|. diff --git a/source/opt/ccp_pass.cpp b/source/opt/ccp_pass.cpp index ac3e261d..570d2022 100644 --- a/source/opt/ccp_pass.cpp +++ b/source/opt/ccp_pass.cpp @@ -38,15 +38,14 @@ const uint32_t kVaryingSSAId = std::numeric_limits<uint32_t>::max(); bool CCPPass::IsVaryingValue(uint32_t id) const { return id == kVaryingSSAId; } -SSAPropagator::PropStatus CCPPass::MarkInstructionVarying( - opt::Instruction* instr) { +SSAPropagator::PropStatus CCPPass::MarkInstructionVarying(Instruction* instr) { assert(instr->result_id() != 0 && "Instructions with no result cannot be marked varying."); values_[instr->result_id()] = kVaryingSSAId; return SSAPropagator::kVarying; } -SSAPropagator::PropStatus CCPPass::VisitPhi(opt::Instruction* phi) { +SSAPropagator::PropStatus CCPPass::VisitPhi(Instruction* phi) { uint32_t meet_val_id = 0; // Implement the lattice meet operation. The result of this Phi instruction is @@ -100,7 +99,7 @@ SSAPropagator::PropStatus CCPPass::VisitPhi(opt::Instruction* phi) { return SSAPropagator::kInteresting; } -SSAPropagator::PropStatus CCPPass::VisitAssignment(opt::Instruction* instr) { +SSAPropagator::PropStatus CCPPass::VisitAssignment(Instruction* instr) { assert(instr->result_id() != 0 && "Expecting an instruction that produces a result"); @@ -133,7 +132,7 @@ SSAPropagator::PropStatus CCPPass::VisitAssignment(opt::Instruction* instr) { } return it->second; }; - opt::Instruction* folded_inst = + Instruction* folded_inst = context()->get_instruction_folder().FoldInstructionToConstant(instr, map_func); if (folded_inst != nullptr) { @@ -168,8 +167,8 @@ SSAPropagator::PropStatus CCPPass::VisitAssignment(opt::Instruction* instr) { return MarkInstructionVarying(instr); } -SSAPropagator::PropStatus CCPPass::VisitBranch( - opt::Instruction* instr, opt::BasicBlock** dest_bb) const { +SSAPropagator::PropStatus CCPPass::VisitBranch(Instruction* instr, + BasicBlock** dest_bb) const { assert(instr->IsBranch() && "Expected a branch instruction."); *dest_bb = nullptr; @@ -250,8 +249,8 @@ SSAPropagator::PropStatus CCPPass::VisitBranch( return SSAPropagator::kInteresting; } -SSAPropagator::PropStatus CCPPass::VisitInstruction(opt::Instruction* instr, - opt::BasicBlock** dest_bb) { +SSAPropagator::PropStatus CCPPass::VisitInstruction(Instruction* instr, + BasicBlock** dest_bb) { *dest_bb = nullptr; if (instr->opcode() == SpvOpPhi) { return VisitPhi(instr); @@ -275,14 +274,13 @@ bool CCPPass::ReplaceValues() { return retval; } -bool CCPPass::PropagateConstants(opt::Function* fp) { +bool CCPPass::PropagateConstants(Function* fp) { // Mark function parameters as varying. - fp->ForEachParam([this](const opt::Instruction* inst) { + fp->ForEachParam([this](const Instruction* inst) { values_[inst->result_id()] = kVaryingSSAId; }); - const auto visit_fn = [this](opt::Instruction* instr, - opt::BasicBlock** dest_bb) { + const auto visit_fn = [this](Instruction* instr, BasicBlock** dest_bb) { return VisitInstruction(instr, dest_bb); }; @@ -317,9 +315,7 @@ Pass::Status CCPPass::Process() { Initialize(); // Process all entry point functions. - ProcessFunction pfn = [this](opt::Function* fp) { - return PropagateConstants(fp); - }; + ProcessFunction pfn = [this](Function* fp) { return PropagateConstants(fp); }; bool modified = ProcessReachableCallTree(pfn, context()); return modified ? Pass::Status::SuccessWithChange : Pass::Status::SuccessWithoutChange; diff --git a/source/opt/ccp_pass.h b/source/opt/ccp_pass.h index 6bf14a0b..1f5d0468 100644 --- a/source/opt/ccp_pass.h +++ b/source/opt/ccp_pass.h @@ -32,13 +32,12 @@ class CCPPass : public MemPass { const char* name() const override { return "ccp"; } Status Process() override; - opt::IRContext::Analysis GetPreservedAnalyses() override { - return opt::IRContext::kAnalysisDefUse | - opt::IRContext::kAnalysisInstrToBlockMapping | - opt::IRContext::kAnalysisDecorations | - opt::IRContext::kAnalysisCombinators | opt::IRContext::kAnalysisCFG | - opt::IRContext::kAnalysisDominatorAnalysis | - opt::IRContext::kAnalysisNameMap; + IRContext::Analysis GetPreservedAnalyses() override { + return IRContext::kAnalysisDefUse | + IRContext::kAnalysisInstrToBlockMapping | + IRContext::kAnalysisDecorations | IRContext::kAnalysisCombinators | + IRContext::kAnalysisCFG | IRContext::kAnalysisDominatorAnalysis | + IRContext::kAnalysisNameMap; } private: @@ -47,30 +46,30 @@ class CCPPass : public MemPass { // Runs constant propagation on the given function |fp|. Returns true if any // constants were propagated and the IR modified. - bool PropagateConstants(opt::Function* fp); + bool PropagateConstants(Function* fp); // Visits a single instruction |instr|. If the instruction is a conditional // branch that always jumps to the same basic block, it sets the destination // block in |dest_bb|. - SSAPropagator::PropStatus VisitInstruction(opt::Instruction* instr, - opt::BasicBlock** dest_bb); + SSAPropagator::PropStatus VisitInstruction(Instruction* instr, + BasicBlock** dest_bb); // Visits an OpPhi instruction |phi|. This applies the meet operator for the // CCP lattice. Essentially, if all the operands in |phi| have the same // constant value C, the result for |phi| gets assigned the value C. - SSAPropagator::PropStatus VisitPhi(opt::Instruction* phi); + SSAPropagator::PropStatus VisitPhi(Instruction* phi); // Visits an SSA assignment instruction |instr|. If the RHS of |instr| folds // into a constant value C, then the LHS of |instr| is assigned the value C in // |values_|. - SSAPropagator::PropStatus VisitAssignment(opt::Instruction* instr); + SSAPropagator::PropStatus VisitAssignment(Instruction* instr); // Visits a branch instruction |instr|. If the branch is conditional // (OpBranchConditional or OpSwitch), and the value of its selector is known, // |dest_bb| will be set to the corresponding destination block. Unconditional // branches always set |dest_bb| to the single destination block. - SSAPropagator::PropStatus VisitBranch(opt::Instruction* instr, - opt::BasicBlock** dest_bb) const; + SSAPropagator::PropStatus VisitBranch(Instruction* instr, + BasicBlock** dest_bb) const; // Replaces all operands used in |fp| with the corresponding constant values // in |values_|. Returns true if any operands were replaced, and false @@ -79,7 +78,7 @@ class CCPPass : public MemPass { // Marks |instr| as varying by registering a varying value for its result // into the |values_| table. Returns SSAPropagator::kVarying. - SSAPropagator::PropStatus MarkInstructionVarying(opt::Instruction* instr); + SSAPropagator::PropStatus MarkInstructionVarying(Instruction* instr); // Returns true if |id| is the special SSA id that corresponds to a varying // value. diff --git a/source/opt/cfg.cpp b/source/opt/cfg.cpp index fcda6ae7..8625358c 100644 --- a/source/opt/cfg.cpp +++ b/source/opt/cfg.cpp @@ -29,11 +29,11 @@ const int kMaxResultId = 0x400000; } // namespace -CFG::CFG(opt::Module* module) +CFG::CFG(Module* module) : module_(module), - pseudo_entry_block_(std::unique_ptr<opt::Instruction>( - new opt::Instruction(module->context(), SpvOpLabel, 0, 0, {}))), - pseudo_exit_block_(std::unique_ptr<opt::Instruction>(new opt::Instruction( + pseudo_entry_block_(std::unique_ptr<Instruction>( + new Instruction(module->context(), SpvOpLabel, 0, 0, {}))), + pseudo_exit_block_(std::unique_ptr<Instruction>(new Instruction( module->context(), SpvOpLabel, 0, kMaxResultId, {}))) { for (auto& fn : *module) { for (auto& blk : fn) { @@ -42,7 +42,7 @@ CFG::CFG(opt::Module* module) } } -void CFG::AddEdges(opt::BasicBlock* blk) { +void CFG::AddEdges(BasicBlock* blk) { uint32_t blk_id = blk->id(); // Force the creation of an entry, not all basic block have predecessors // (such as the entry blocks and some unreachables). @@ -55,7 +55,7 @@ void CFG::AddEdges(opt::BasicBlock* blk) { void CFG::RemoveNonExistingEdges(uint32_t blk_id) { std::vector<uint32_t> updated_pred_list; for (uint32_t id : preds(blk_id)) { - const opt::BasicBlock* pred_blk = block(id); + const BasicBlock* pred_blk = block(id); bool has_branch = false; pred_blk->ForEachSuccessorLabel([&has_branch, blk_id](uint32_t succ) { if (succ == blk_id) { @@ -68,8 +68,8 @@ void CFG::RemoveNonExistingEdges(uint32_t blk_id) { label2preds_.at(blk_id) = std::move(updated_pred_list); } -void CFG::ComputeStructuredOrder(opt::Function* func, opt::BasicBlock* root, - std::list<opt::BasicBlock*>* order) { +void CFG::ComputeStructuredOrder(Function* func, BasicBlock* root, + std::list<BasicBlock*>* order) { assert(module_->context()->get_feature_mgr()->HasCapability( SpvCapabilityShader) && "This only works on structured control flow"); @@ -78,17 +78,17 @@ void CFG::ComputeStructuredOrder(opt::Function* func, opt::BasicBlock* root, ComputeStructuredSuccessors(func); auto ignore_block = [](cbb_ptr) {}; auto ignore_edge = [](cbb_ptr, cbb_ptr) {}; - auto get_structured_successors = [this](const opt::BasicBlock* b) { + auto get_structured_successors = [this](const BasicBlock* b) { return &(block2structured_succs_[b]); }; // TODO(greg-lunarg): Get rid of const_cast by making moving const // out of the cfa.h prototypes and into the invoking code. auto post_order = [&](cbb_ptr b) { - order->push_front(const_cast<opt::BasicBlock*>(b)); + order->push_front(const_cast<BasicBlock*>(b)); }; - CFA<opt::BasicBlock>::DepthFirstTraversal( - root, get_structured_successors, ignore_block, post_order, ignore_edge); + CFA<BasicBlock>::DepthFirstTraversal(root, get_structured_successors, + ignore_block, post_order, ignore_edge); } void CFG::ForEachBlockInPostOrder(BasicBlock* bb, @@ -117,7 +117,7 @@ void CFG::ForEachBlockInReversePostOrder( } } -void CFG::ComputeStructuredSuccessors(opt::Function* func) { +void CFG::ComputeStructuredSuccessors(Function* func) { block2structured_succs_.clear(); for (auto& blk : *func) { // If no predecessors in function, make successor to pseudo entry. @@ -156,7 +156,7 @@ void CFG::ComputePostOrderTraversal(BasicBlock* bb, vector<BasicBlock*>* order, order->push_back(bb); } -BasicBlock* CFG::SplitLoopHeader(opt::BasicBlock* bb) { +BasicBlock* CFG::SplitLoopHeader(BasicBlock* bb) { assert(bb->GetLoopMergeInst() && "Expecting bb to be the header of a loop."); Function* fn = bb->GetParent(); @@ -170,7 +170,7 @@ BasicBlock* CFG::SplitLoopHeader(opt::BasicBlock* bb) { const std::vector<uint32_t>& pred = preds(bb->id()); // Find the back edge - opt::BasicBlock* latch_block = nullptr; + BasicBlock* latch_block = nullptr; Function::iterator latch_block_iter = header_it; while (++latch_block_iter != fn->end()) { // If blocks are in the proper order, then the only branch that appears @@ -192,13 +192,13 @@ BasicBlock* CFG::SplitLoopHeader(opt::BasicBlock* bb) { ++iter; } - std::unique_ptr<opt::BasicBlock> newBlock( + std::unique_ptr<BasicBlock> newBlock( bb->SplitBasicBlock(context, context->TakeNextId(), iter)); // Insert the new bb in the correct position auto insert_pos = header_it; ++insert_pos; - opt::BasicBlock* new_header = &*insert_pos.InsertBefore(std::move(newBlock)); + BasicBlock* new_header = &*insert_pos.InsertBefore(std::move(newBlock)); new_header->SetParent(fn); uint32_t new_header_id = new_header->id(); context->AnalyzeDefUse(new_header->GetLabelInst()); @@ -208,7 +208,7 @@ BasicBlock* CFG::SplitLoopHeader(opt::BasicBlock* bb) { // Update bb mappings. context->set_instr_block(new_header->GetLabelInst(), new_header); - new_header->ForEachInst([new_header, context](opt::Instruction* inst) { + new_header->ForEachInst([new_header, context](Instruction* inst) { context->set_instr_block(inst, new_header); }); @@ -234,13 +234,11 @@ BasicBlock* CFG::SplitLoopHeader(opt::BasicBlock* bb) { // Create a phi instruction if and only if the preheader_phi_ops has more // than one pair. if (preheader_phi_ops.size() > 2) { - opt::InstructionBuilder builder( + InstructionBuilder builder( context, &*bb->begin(), - opt::IRContext::kAnalysisDefUse | - opt::IRContext::kAnalysisInstrToBlockMapping); + IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping); - opt::Instruction* new_phi = - builder.AddPhi(phi->type_id(), preheader_phi_ops); + Instruction* new_phi = builder.AddPhi(phi->type_id(), preheader_phi_ops); // Add the OpPhi to the header bb. header_phi_ops.push_back({SPV_OPERAND_TYPE_ID, {new_phi->result_id()}}); @@ -253,7 +251,7 @@ BasicBlock* CFG::SplitLoopHeader(opt::BasicBlock* bb) { } phi->RemoveFromList(); - std::unique_ptr<opt::Instruction> phi_owner(phi); + std::unique_ptr<Instruction> phi_owner(phi); phi->SetInOperands(std::move(header_phi_ops)); new_header->begin()->InsertBefore(std::move(phi_owner)); context->set_instr_block(phi, new_header); @@ -261,14 +259,13 @@ BasicBlock* CFG::SplitLoopHeader(opt::BasicBlock* bb) { }); // Add a branch to the new header. - opt::InstructionBuilder branch_builder( + InstructionBuilder branch_builder( context, bb, - opt::IRContext::kAnalysisDefUse | - opt::IRContext::kAnalysisInstrToBlockMapping); - bb->AddInstruction(MakeUnique<opt::Instruction>( - context, SpvOpBranch, 0, 0, - std::initializer_list<opt::Operand>{ - {SPV_OPERAND_TYPE_ID, {new_header->id()}}})); + IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping); + bb->AddInstruction( + MakeUnique<Instruction>(context, SpvOpBranch, 0, 0, + std::initializer_list<Operand>{ + {SPV_OPERAND_TYPE_ID, {new_header->id()}}})); context->AnalyzeUses(bb->terminator()); context->set_instr_block(bb->terminator(), bb); label2preds_[new_header->id()].push_back(bb->id()); @@ -279,7 +276,7 @@ BasicBlock* CFG::SplitLoopHeader(opt::BasicBlock* bb) { *id = new_header_id; } }); - opt::Instruction* latch_branch = latch_block->terminator(); + Instruction* latch_branch = latch_block->terminator(); context->AnalyzeUses(latch_branch); label2preds_[new_header->id()].push_back(latch_block->id()); @@ -290,7 +287,7 @@ BasicBlock* CFG::SplitLoopHeader(opt::BasicBlock* bb) { block_preds.erase(latch_pos); // Update the loop descriptors - if (context->AreAnalysesValid(opt::IRContext::kAnalysisLoopAnalysis)) { + if (context->AreAnalysesValid(IRContext::kAnalysisLoopAnalysis)) { LoopDescriptor* loop_desc = context->GetLoopDescriptor(bb->GetParent()); Loop* loop = (*loop_desc)[bb->id()]; diff --git a/source/opt/cfg.h b/source/opt/cfg.h index 759145f6..c472f2cd 100644 --- a/source/opt/cfg.h +++ b/source/opt/cfg.h @@ -27,10 +27,10 @@ namespace opt { class CFG { public: - explicit CFG(opt::Module* module); + explicit CFG(Module* module); // Return the list of predecesors for basic block with label |blkid|. - // TODO(dnovillo): Move this to opt::BasicBlock. + // TODO(dnovillo): Move this to BasicBlock. const std::vector<uint32_t>& preds(uint32_t blk_id) const { assert(label2preds_.count(blk_id)); return label2preds_.at(blk_id); @@ -38,26 +38,22 @@ class CFG { // Return a pointer to the basic block instance corresponding to the label // |blk_id|. - opt::BasicBlock* block(uint32_t blk_id) const { return id2block_.at(blk_id); } + BasicBlock* block(uint32_t blk_id) const { return id2block_.at(blk_id); } // Return the pseudo entry and exit blocks. - const opt::BasicBlock* pseudo_entry_block() const { - return &pseudo_entry_block_; - } - opt::BasicBlock* pseudo_entry_block() { return &pseudo_entry_block_; } + const BasicBlock* pseudo_entry_block() const { return &pseudo_entry_block_; } + BasicBlock* pseudo_entry_block() { return &pseudo_entry_block_; } - const opt::BasicBlock* pseudo_exit_block() const { - return &pseudo_exit_block_; - } - opt::BasicBlock* pseudo_exit_block() { return &pseudo_exit_block_; } + const BasicBlock* pseudo_exit_block() const { return &pseudo_exit_block_; } + BasicBlock* pseudo_exit_block() { return &pseudo_exit_block_; } // Return true if |block_ptr| is the pseudo-entry block. - bool IsPseudoEntryBlock(opt::BasicBlock* block_ptr) const { + bool IsPseudoEntryBlock(BasicBlock* block_ptr) const { return block_ptr == &pseudo_entry_block_; } // Return true if |block_ptr| is the pseudo-exit block. - bool IsPseudoExitBlock(opt::BasicBlock* block_ptr) const { + bool IsPseudoExitBlock(BasicBlock* block_ptr) const { return block_ptr == &pseudo_exit_block_; } @@ -65,8 +61,8 @@ class CFG { // This order has the property that dominators come before all blocks they // dominate and merge blocks come after all blocks that are in the control // constructs of their header. - void ComputeStructuredOrder(opt::Function* func, opt::BasicBlock* root, - std::list<opt::BasicBlock*>* order); + void ComputeStructuredOrder(Function* func, BasicBlock* root, + std::list<BasicBlock*>* order); // Applies |f| to the basic block in post order starting with |bb|. // Note that basic blocks that cannot be reached from |bb| node will not be @@ -82,14 +78,14 @@ class CFG { // Registers |blk| as a basic block in the cfg, this also updates the // predecessor lists of each successor of |blk|. - void RegisterBlock(opt::BasicBlock* blk) { + void RegisterBlock(BasicBlock* blk) { uint32_t blk_id = blk->id(); id2block_[blk_id] = blk; AddEdges(blk); } // Removes from the CFG any mapping for the basic block id |blk_id|. - void ForgetBlock(const opt::BasicBlock* blk) { + void ForgetBlock(const BasicBlock* blk) { id2block_.erase(blk->id()); label2preds_.erase(blk->id()); RemoveSuccessorEdges(blk); @@ -104,7 +100,7 @@ class CFG { } // Registers |blk| to all of its successors. - void AddEdges(opt::BasicBlock* blk); + void AddEdges(BasicBlock* blk); // Registers the basic block id |pred_blk_id| as being a predecessor of the // basic block id |succ_blk_id|. @@ -117,7 +113,7 @@ class CFG { void RemoveNonExistingEdges(uint32_t blk_id); // Remove all edges that leave |bb|. - void RemoveSuccessorEdges(const opt::BasicBlock* bb) { + void RemoveSuccessorEdges(const BasicBlock* bb) { bb->ForEachSuccessorLabel( [bb, this](uint32_t succ_id) { RemoveEdge(bb->id(), succ_id); }); } @@ -127,7 +123,7 @@ class CFG { // is a new block that will be the new loop header. // // Returns a pointer to the new loop header. - BasicBlock* SplitLoopHeader(opt::BasicBlock* bb); + BasicBlock* SplitLoopHeader(BasicBlock* bb); private: // Compute structured successors for function |func|. A block's structured @@ -137,7 +133,7 @@ class CFG { // first search in the presence of early returns and kills. If the successor // vector contain duplicates of the merge or continue blocks, they are safely // ignored by DFS. - void ComputeStructuredSuccessors(opt::Function* func); + void ComputeStructuredSuccessors(Function* func); // Computes the post-order traversal of the cfg starting at |bb| skipping // nodes in |seen|. The order of the traversal is appended to |order|, and @@ -147,25 +143,25 @@ class CFG { std::unordered_set<BasicBlock*>* seen); // Module for this CFG. - opt::Module* module_; + Module* module_; // Map from block to its structured successor blocks. See // ComputeStructuredSuccessors() for definition. - std::unordered_map<const opt::BasicBlock*, std::vector<opt::BasicBlock*>> + std::unordered_map<const BasicBlock*, std::vector<BasicBlock*>> block2structured_succs_; // Extra block whose successors are all blocks with no predecessors // in function. - opt::BasicBlock pseudo_entry_block_; + BasicBlock pseudo_entry_block_; // Augmented CFG Exit Block. - opt::BasicBlock pseudo_exit_block_; + BasicBlock pseudo_exit_block_; // Map from block's label id to its predecessor blocks ids std::unordered_map<uint32_t, std::vector<uint32_t>> label2preds_; // Map from block's label id to block. - std::unordered_map<uint32_t, opt::BasicBlock*> id2block_; + std::unordered_map<uint32_t, BasicBlock*> id2block_; }; } // namespace opt diff --git a/source/opt/cfg_cleanup_pass.cpp b/source/opt/cfg_cleanup_pass.cpp index 2910e3dc..ac99135e 100644 --- a/source/opt/cfg_cleanup_pass.cpp +++ b/source/opt/cfg_cleanup_pass.cpp @@ -29,7 +29,7 @@ namespace opt { Pass::Status CFGCleanupPass::Process() { // Process all entry point functions. - ProcessFunction pfn = [this](opt::Function* fp) { return CFGCleanup(fp); }; + ProcessFunction pfn = [this](Function* fp) { return CFGCleanup(fp); }; bool modified = ProcessReachableCallTree(pfn, context()); return modified ? Pass::Status::SuccessWithChange : Pass::Status::SuccessWithoutChange; diff --git a/source/opt/cfg_cleanup_pass.h b/source/opt/cfg_cleanup_pass.h index 23003407..27589bfa 100644 --- a/source/opt/cfg_cleanup_pass.h +++ b/source/opt/cfg_cleanup_pass.h @@ -29,8 +29,8 @@ class CFGCleanupPass : public MemPass { const char* name() const override { return "cfg-cleanup"; } Status Process() override; - opt::IRContext::Analysis GetPreservedAnalyses() override { - return opt::IRContext::kAnalysisDefUse; + IRContext::Analysis GetPreservedAnalyses() override { + return IRContext::kAnalysisDefUse; } }; diff --git a/source/opt/common_uniform_elim_pass.cpp b/source/opt/common_uniform_elim_pass.cpp index e5c1af73..e6a2b1c8 100644 --- a/source/opt/common_uniform_elim_pass.cpp +++ b/source/opt/common_uniform_elim_pass.cpp @@ -41,7 +41,7 @@ bool CommonUniformElimPass::IsNonPtrAccessChain(const SpvOp opcode) const { } bool CommonUniformElimPass::IsSamplerOrImageType( - const opt::Instruction* typeInst) const { + const Instruction* typeInst) const { switch (typeInst->opcode()) { case SpvOpTypeSampler: case SpvOpTypeImage: @@ -53,7 +53,7 @@ bool CommonUniformElimPass::IsSamplerOrImageType( if (typeInst->opcode() != SpvOpTypeStruct) return false; // Return true if any member is a sampler or image return !typeInst->WhileEachInId([this](const uint32_t* tid) { - const opt::Instruction* compTypeInst = get_def_use_mgr()->GetDef(*tid); + const Instruction* compTypeInst = get_def_use_mgr()->GetDef(*tid); if (IsSamplerOrImageType(compTypeInst)) { return false; } @@ -62,28 +62,27 @@ bool CommonUniformElimPass::IsSamplerOrImageType( } bool CommonUniformElimPass::IsSamplerOrImageVar(uint32_t varId) const { - const opt::Instruction* varInst = get_def_use_mgr()->GetDef(varId); + const Instruction* varInst = get_def_use_mgr()->GetDef(varId); assert(varInst->opcode() == SpvOpVariable); const uint32_t varTypeId = varInst->type_id(); - const opt::Instruction* varTypeInst = get_def_use_mgr()->GetDef(varTypeId); + const Instruction* varTypeInst = get_def_use_mgr()->GetDef(varTypeId); const uint32_t varPteTypeId = varTypeInst->GetSingleWordInOperand(kTypePointerTypeIdInIdx); - opt::Instruction* varPteTypeInst = get_def_use_mgr()->GetDef(varPteTypeId); + Instruction* varPteTypeInst = get_def_use_mgr()->GetDef(varPteTypeId); return IsSamplerOrImageType(varPteTypeInst); } -opt::Instruction* CommonUniformElimPass::GetPtr(opt::Instruction* ip, - uint32_t* objId) { +Instruction* CommonUniformElimPass::GetPtr(Instruction* ip, uint32_t* objId) { const SpvOp op = ip->opcode(); assert(op == SpvOpStore || op == SpvOpLoad); *objId = ip->GetSingleWordInOperand(op == SpvOpStore ? kStorePtrIdInIdx : kLoadPtrIdInIdx); - opt::Instruction* ptrInst = get_def_use_mgr()->GetDef(*objId); + Instruction* ptrInst = get_def_use_mgr()->GetDef(*objId); while (ptrInst->opcode() == SpvOpCopyObject) { *objId = ptrInst->GetSingleWordInOperand(kCopyObjectOperandInIdx); ptrInst = get_def_use_mgr()->GetDef(*objId); } - opt::Instruction* objInst = ptrInst; + Instruction* objInst = ptrInst; while (objInst->opcode() != SpvOpVariable && objInst->opcode() != SpvOpFunctionParameter) { if (IsNonPtrAccessChain(objInst->opcode())) { @@ -100,22 +99,21 @@ opt::Instruction* CommonUniformElimPass::GetPtr(opt::Instruction* ip, bool CommonUniformElimPass::IsVolatileStruct(uint32_t type_id) { assert(get_def_use_mgr()->GetDef(type_id)->opcode() == SpvOpTypeStruct); return !get_decoration_mgr()->WhileEachDecoration( - type_id, SpvDecorationVolatile, - [](const opt::Instruction&) { return false; }); + type_id, SpvDecorationVolatile, [](const Instruction&) { return false; }); } bool CommonUniformElimPass::IsAccessChainToVolatileStructType( - const opt::Instruction& AccessChainInst) { + const Instruction& AccessChainInst) { assert(AccessChainInst.opcode() == SpvOpAccessChain); uint32_t ptr_id = AccessChainInst.GetSingleWordInOperand(0); - const opt::Instruction* ptr_inst = get_def_use_mgr()->GetDef(ptr_id); + const Instruction* ptr_inst = get_def_use_mgr()->GetDef(ptr_id); uint32_t pointee_type_id = GetPointeeTypeId(ptr_inst); const uint32_t num_operands = AccessChainInst.NumOperands(); // walk the type tree: for (uint32_t idx = 3; idx < num_operands; ++idx) { - opt::Instruction* pointee_type = get_def_use_mgr()->GetDef(pointee_type_id); + Instruction* pointee_type = get_def_use_mgr()->GetDef(pointee_type_id); switch (pointee_type->opcode()) { case SpvOpTypeMatrix: @@ -130,8 +128,7 @@ bool CommonUniformElimPass::IsAccessChainToVolatileStructType( if (idx < num_operands - 1) { const uint32_t index_id = AccessChainInst.GetSingleWordOperand(idx); - const opt::Instruction* index_inst = - get_def_use_mgr()->GetDef(index_id); + const Instruction* index_inst = get_def_use_mgr()->GetDef(index_id); uint32_t index_value = index_inst->GetSingleWordOperand( 2); // TODO: replace with GetUintValueFromConstant() pointee_type_id = pointee_type->GetSingleWordInOperand(index_value); @@ -144,7 +141,7 @@ bool CommonUniformElimPass::IsAccessChainToVolatileStructType( return false; } -bool CommonUniformElimPass::IsVolatileLoad(const opt::Instruction& loadInst) { +bool CommonUniformElimPass::IsVolatileLoad(const Instruction& loadInst) { assert(loadInst.opcode() == SpvOpLoad); // Check if this Load instruction has Volatile Memory Access flag if (loadInst.NumOperands() == 4) { @@ -161,11 +158,11 @@ bool CommonUniformElimPass::IsVolatileLoad(const opt::Instruction& loadInst) { } bool CommonUniformElimPass::IsUniformVar(uint32_t varId) { - const opt::Instruction* varInst = + const Instruction* varInst = get_def_use_mgr()->id_to_defs().find(varId)->second; if (varInst->opcode() != SpvOpVariable) return false; const uint32_t varTypeId = varInst->type_id(); - const opt::Instruction* varTypeInst = + const Instruction* varTypeInst = get_def_use_mgr()->id_to_defs().find(varTypeId)->second; return varTypeInst->GetSingleWordInOperand(kTypePointerStorageClassInIdx) == SpvStorageClassUniform || @@ -174,21 +171,21 @@ bool CommonUniformElimPass::IsUniformVar(uint32_t varId) { } bool CommonUniformElimPass::HasUnsupportedDecorates(uint32_t id) const { - return !get_def_use_mgr()->WhileEachUser(id, [this](opt::Instruction* user) { + return !get_def_use_mgr()->WhileEachUser(id, [this](Instruction* user) { if (IsNonTypeDecorate(user->opcode())) return false; return true; }); } bool CommonUniformElimPass::HasOnlyNamesAndDecorates(uint32_t id) const { - return get_def_use_mgr()->WhileEachUser(id, [this](opt::Instruction* user) { + return get_def_use_mgr()->WhileEachUser(id, [this](Instruction* user) { SpvOp op = user->opcode(); if (op != SpvOpName && !IsNonTypeDecorate(op)) return false; return true; }); } -void CommonUniformElimPass::DeleteIfUseless(opt::Instruction* inst) { +void CommonUniformElimPass::DeleteIfUseless(Instruction* inst) { const uint32_t resId = inst->result_id(); assert(resId != 0); if (HasOnlyNamesAndDecorates(resId)) { @@ -196,34 +193,33 @@ void CommonUniformElimPass::DeleteIfUseless(opt::Instruction* inst) { } } -opt::Instruction* CommonUniformElimPass::ReplaceAndDeleteLoad( - opt::Instruction* loadInst, uint32_t replId, opt::Instruction* ptrInst) { +Instruction* CommonUniformElimPass::ReplaceAndDeleteLoad(Instruction* loadInst, + uint32_t replId, + Instruction* ptrInst) { const uint32_t loadId = loadInst->result_id(); context()->KillNamesAndDecorates(loadId); (void)context()->ReplaceAllUsesWith(loadId, replId); // remove load instruction - opt::Instruction* next_instruction = context()->KillInst(loadInst); + Instruction* next_instruction = context()->KillInst(loadInst); // if access chain, see if it can be removed as well if (IsNonPtrAccessChain(ptrInst->opcode())) DeleteIfUseless(ptrInst); return next_instruction; } void CommonUniformElimPass::GenACLoadRepl( - const opt::Instruction* ptrInst, - std::vector<std::unique_ptr<opt::Instruction>>* newInsts, - uint32_t* resultId) { + const Instruction* ptrInst, + std::vector<std::unique_ptr<Instruction>>* newInsts, uint32_t* resultId) { // Build and append Load const uint32_t ldResultId = TakeNextId(); const uint32_t varId = ptrInst->GetSingleWordInOperand(kAccessChainPtrIdInIdx); - const opt::Instruction* varInst = get_def_use_mgr()->GetDef(varId); + const Instruction* varInst = get_def_use_mgr()->GetDef(varId); assert(varInst->opcode() == SpvOpVariable); const uint32_t varPteTypeId = GetPointeeTypeId(varInst); - std::vector<opt::Operand> load_in_operands; - load_in_operands.push_back( - opt::Operand(spv_operand_type_t::SPV_OPERAND_TYPE_ID, - std::initializer_list<uint32_t>{varId})); - std::unique_ptr<opt::Instruction> newLoad(new opt::Instruction( + std::vector<Operand> load_in_operands; + load_in_operands.push_back(Operand(spv_operand_type_t::SPV_OPERAND_TYPE_ID, + std::initializer_list<uint32_t>{varId})); + std::unique_ptr<Instruction> newLoad(new Instruction( context(), SpvOpLoad, varPteTypeId, ldResultId, load_in_operands)); get_def_use_mgr()->AnalyzeInstDefUse(&*newLoad); newInsts->emplace_back(std::move(newLoad)); @@ -231,34 +227,33 @@ void CommonUniformElimPass::GenACLoadRepl( // Build and append Extract const uint32_t extResultId = TakeNextId(); const uint32_t ptrPteTypeId = GetPointeeTypeId(ptrInst); - std::vector<opt::Operand> ext_in_opnds; - ext_in_opnds.push_back( - opt::Operand(spv_operand_type_t::SPV_OPERAND_TYPE_ID, - std::initializer_list<uint32_t>{ldResultId})); + std::vector<Operand> ext_in_opnds; + ext_in_opnds.push_back(Operand(spv_operand_type_t::SPV_OPERAND_TYPE_ID, + std::initializer_list<uint32_t>{ldResultId})); uint32_t iidIdx = 0; ptrInst->ForEachInId([&iidIdx, &ext_in_opnds, this](const uint32_t* iid) { if (iidIdx > 0) { - const opt::Instruction* cInst = get_def_use_mgr()->GetDef(*iid); + const Instruction* cInst = get_def_use_mgr()->GetDef(*iid); uint32_t val = cInst->GetSingleWordInOperand(kConstantValueInIdx); ext_in_opnds.push_back( - opt::Operand(spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER, - std::initializer_list<uint32_t>{val})); + Operand(spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER, + std::initializer_list<uint32_t>{val})); } ++iidIdx; }); - std::unique_ptr<opt::Instruction> newExt( - new opt::Instruction(context(), SpvOpCompositeExtract, ptrPteTypeId, - extResultId, ext_in_opnds)); + std::unique_ptr<Instruction> newExt( + new Instruction(context(), SpvOpCompositeExtract, ptrPteTypeId, + extResultId, ext_in_opnds)); get_def_use_mgr()->AnalyzeInstDefUse(&*newExt); newInsts->emplace_back(std::move(newExt)); *resultId = extResultId; } -bool CommonUniformElimPass::IsConstantIndexAccessChain(opt::Instruction* acp) { +bool CommonUniformElimPass::IsConstantIndexAccessChain(Instruction* acp) { uint32_t inIdx = 0; return acp->WhileEachInId([&inIdx, this](uint32_t* tid) { if (inIdx > 0) { - opt::Instruction* opInst = get_def_use_mgr()->GetDef(*tid); + Instruction* opInst = get_def_use_mgr()->GetDef(*tid); if (opInst->opcode() != SpvOpConstant) return false; } ++inIdx; @@ -266,14 +261,13 @@ bool CommonUniformElimPass::IsConstantIndexAccessChain(opt::Instruction* acp) { }); } -bool CommonUniformElimPass::UniformAccessChainConvert(opt::Function* func) { +bool CommonUniformElimPass::UniformAccessChainConvert(Function* func) { bool modified = false; for (auto bi = func->begin(); bi != func->end(); ++bi) { - for (opt::Instruction* inst = &*bi->begin(); inst; - inst = inst->NextNode()) { + for (Instruction* inst = &*bi->begin(); inst; inst = inst->NextNode()) { if (inst->opcode() != SpvOpLoad) continue; uint32_t varId; - opt::Instruction* ptrInst = GetPtr(inst, &varId); + Instruction* ptrInst = GetPtr(inst, &varId); if (!IsNonPtrAccessChain(ptrInst->opcode())) continue; // Do not convert nested access chains if (ptrInst->GetSingleWordInOperand(kAccessChainPtrIdInIdx) != varId) @@ -284,7 +278,7 @@ bool CommonUniformElimPass::UniformAccessChainConvert(opt::Function* func) { if (HasUnsupportedDecorates(ptrInst->result_id())) continue; if (IsVolatileLoad(*inst)) continue; if (IsAccessChainToVolatileStructType(*ptrInst)) continue; - std::vector<std::unique_ptr<opt::Instruction>> newInsts; + std::vector<std::unique_ptr<Instruction>> newInsts; uint32_t replId; GenACLoadRepl(ptrInst, &newInsts, &replId); inst = ReplaceAndDeleteLoad(inst, replId, ptrInst); @@ -295,7 +289,7 @@ bool CommonUniformElimPass::UniformAccessChainConvert(opt::Function* func) { return modified; } -void CommonUniformElimPass::ComputeStructuredSuccessors(opt::Function* func) { +void CommonUniformElimPass::ComputeStructuredSuccessors(Function* func) { block2structured_succs_.clear(); for (auto& blk : *func) { // If header, make merge block first successor. @@ -316,32 +310,32 @@ void CommonUniformElimPass::ComputeStructuredSuccessors(opt::Function* func) { } void CommonUniformElimPass::ComputeStructuredOrder( - opt::Function* func, std::list<opt::BasicBlock*>* order) { + Function* func, std::list<BasicBlock*>* order) { // Compute structured successors and do DFS ComputeStructuredSuccessors(func); auto ignore_block = [](cbb_ptr) {}; auto ignore_edge = [](cbb_ptr, cbb_ptr) {}; - auto get_structured_successors = [this](const opt::BasicBlock* block) { + auto get_structured_successors = [this](const BasicBlock* block) { return &(block2structured_succs_[block]); }; // TODO(greg-lunarg): Get rid of const_cast by making moving const // out of the cfa.h prototypes and into the invoking code. auto post_order = [&](cbb_ptr b) { - order->push_front(const_cast<opt::BasicBlock*>(b)); + order->push_front(const_cast<BasicBlock*>(b)); }; order->clear(); - CFA<opt::BasicBlock>::DepthFirstTraversal( - &*func->begin(), get_structured_successors, ignore_block, post_order, - ignore_edge); + CFA<BasicBlock>::DepthFirstTraversal(&*func->begin(), + get_structured_successors, ignore_block, + post_order, ignore_edge); } -bool CommonUniformElimPass::CommonUniformLoadElimination(opt::Function* func) { +bool CommonUniformElimPass::CommonUniformLoadElimination(Function* func) { // Process all blocks in structured order. This is just one way (the // simplest?) to keep track of the most recent block outside of control // flow, used to copy common instructions, guaranteed to dominate all // following load sites. - std::list<opt::BasicBlock*> structuredOrder; + std::list<BasicBlock*> structuredOrder; ComputeStructuredOrder(func, &structuredOrder); uniform2load_id_.clear(); bool modified = false; @@ -355,7 +349,7 @@ bool CommonUniformElimPass::CommonUniformLoadElimination(opt::Function* func) { while (IsUniformLoadToBeRemoved(&*insertItr)) ++insertItr; uint32_t mergeBlockId = 0; for (auto bi = structuredOrder.begin(); bi != structuredOrder.end(); ++bi) { - opt::BasicBlock* bp = *bi; + BasicBlock* bp = *bi; // Check if we are exiting outermost control construct. If so, remember // new load insertion point. Trying to keep register pressure down. if (mergeBlockId == bp->id()) { @@ -365,11 +359,10 @@ bool CommonUniformElimPass::CommonUniformLoadElimination(opt::Function* func) { // ReplaceAndDeleteLoad() can set |insertItr| as a dangling pointer. while (IsUniformLoadToBeRemoved(&*insertItr)) ++insertItr; } - for (opt::Instruction* inst = &*bp->begin(); inst; - inst = inst->NextNode()) { + for (Instruction* inst = &*bp->begin(); inst; inst = inst->NextNode()) { if (inst->opcode() != SpvOpLoad) continue; uint32_t varId; - opt::Instruction* ptrInst = GetPtr(inst, &varId); + Instruction* ptrInst = GetPtr(inst, &varId); if (ptrInst->opcode() != SpvOpVariable) continue; if (!IsUniformVar(varId)) continue; if (IsSamplerOrImageVar(varId)) continue; @@ -387,7 +380,7 @@ bool CommonUniformElimPass::CommonUniformLoadElimination(opt::Function* func) { } else { // Copy load into most recent dominating block and remember it replId = TakeNextId(); - std::unique_ptr<opt::Instruction> newLoad(new opt::Instruction( + std::unique_ptr<Instruction> newLoad(new Instruction( context(), SpvOpLoad, inst->type_id(), replId, {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {varId}}})); get_def_use_mgr()->AnalyzeInstDefUse(&*newLoad); @@ -408,15 +401,14 @@ bool CommonUniformElimPass::CommonUniformLoadElimination(opt::Function* func) { return modified; } -bool CommonUniformElimPass::CommonUniformLoadElimBlock(opt::Function* func) { +bool CommonUniformElimPass::CommonUniformLoadElimBlock(Function* func) { bool modified = false; for (auto& blk : *func) { uniform2load_id_.clear(); - for (opt::Instruction* inst = &*blk.begin(); inst; - inst = inst->NextNode()) { + for (Instruction* inst = &*blk.begin(); inst; inst = inst->NextNode()) { if (inst->opcode() != SpvOpLoad) continue; uint32_t varId; - opt::Instruction* ptrInst = GetPtr(inst, &varId); + Instruction* ptrInst = GetPtr(inst, &varId); if (ptrInst->opcode() != SpvOpVariable) continue; if (!IsUniformVar(varId)) continue; if (!IsSamplerOrImageVar(varId)) continue; @@ -437,7 +429,7 @@ bool CommonUniformElimPass::CommonUniformLoadElimBlock(opt::Function* func) { return modified; } -bool CommonUniformElimPass::CommonExtractElimination(opt::Function* func) { +bool CommonUniformElimPass::CommonExtractElimination(Function* func) { // Find all composite ids with duplicate extracts. for (auto bi = func->begin(); bi != func->end(); ++bi) { for (auto ii = bi->begin(); ii != bi->end(); ++ii) { @@ -460,7 +452,7 @@ bool CommonUniformElimPass::CommonExtractElimination(opt::Function* func) { for (auto idxItr : cItr->second) { if (idxItr.second.size() < 2) continue; uint32_t replId = TakeNextId(); - std::unique_ptr<opt::Instruction> newExtract( + std::unique_ptr<Instruction> newExtract( idxItr.second.front()->Clone(context())); newExtract->SetResultId(replId); get_def_use_mgr()->AnalyzeInstDefUse(&*newExtract); @@ -479,7 +471,7 @@ bool CommonUniformElimPass::CommonExtractElimination(opt::Function* func) { return modified; } -bool CommonUniformElimPass::EliminateCommonUniform(opt::Function* func) { +bool CommonUniformElimPass::EliminateCommonUniform(Function* func) { bool modified = false; modified |= UniformAccessChainConvert(func); modified |= CommonUniformLoadElimination(func); @@ -526,12 +518,12 @@ Pass::Status CommonUniformElimPass::ProcessImpl() { if (ai.opcode() == SpvOpGroupDecorate) return Status::SuccessWithoutChange; // If non-32-bit integer type in module, terminate processing // TODO(): Handle non-32-bit integer constants in access chains - for (const opt::Instruction& inst : get_module()->types_values()) + for (const Instruction& inst : get_module()->types_values()) if (inst.opcode() == SpvOpTypeInt && inst.GetSingleWordInOperand(kTypeIntWidthInIdx) != 32) return Status::SuccessWithoutChange; // Process entry point functions - ProcessFunction pfn = [this](opt::Function* fp) { + ProcessFunction pfn = [this](Function* fp) { return EliminateCommonUniform(fp); }; bool modified = ProcessEntryPointCallTree(pfn, get_module()); diff --git a/source/opt/common_uniform_elim_pass.h b/source/opt/common_uniform_elim_pass.h index 3353d247..d234a9da 100644 --- a/source/opt/common_uniform_elim_pass.h +++ b/source/opt/common_uniform_elim_pass.h @@ -36,11 +36,11 @@ namespace opt { // See optimizer.hpp for documentation. class CommonUniformElimPass : public Pass { - using cbb_ptr = const opt::BasicBlock*; + using cbb_ptr = const BasicBlock*; public: using GetBlocksFunction = - std::function<std::vector<opt::BasicBlock*>*(const opt::BasicBlock*)>; + std::function<std::vector<BasicBlock*>*(const BasicBlock*)>; CommonUniformElimPass(); @@ -53,7 +53,7 @@ class CommonUniformElimPass : public Pass { // Returns true if |typeInst| is a sampler or image type or a struct // containing one, recursively. - bool IsSamplerOrImageType(const opt::Instruction* typeInst) const; + bool IsSamplerOrImageType(const Instruction* typeInst) const; // Returns true if |varId| is a variable containing a sampler or image. bool IsSamplerOrImageVar(uint32_t varId) const; @@ -61,7 +61,7 @@ class CommonUniformElimPass : public Pass { // Given a load or store pointed at by |ip|, return the top-most // non-CopyObj in its pointer operand. Also return the base pointer // in |objId|. - opt::Instruction* GetPtr(opt::Instruction* ip, uint32_t* objId); + Instruction* GetPtr(Instruction* ip, uint32_t* objId); // Return true if variable is uniform bool IsUniformVar(uint32_t varId); @@ -73,13 +73,12 @@ class CommonUniformElimPass : public Pass { // Given an OpAccessChain instruction, return true // if the accessed variable belongs to a volatile // decorated object or member of a struct type - bool IsAccessChainToVolatileStructType( - const opt::Instruction& AccessChainInst); + bool IsAccessChainToVolatileStructType(const Instruction& AccessChainInst); // Given an OpLoad instruction, return true if // OpLoad has a Volatile Memory Access flag or if // the resulting type is a volatile decorated struct - bool IsVolatileLoad(const opt::Instruction& loadInst); + bool IsVolatileLoad(const Instruction& loadInst); // Return true if any uses of |id| are decorate ops. bool HasUnsupportedDecorates(uint32_t id) const; @@ -88,25 +87,24 @@ class CommonUniformElimPass : public Pass { bool HasOnlyNamesAndDecorates(uint32_t id) const; // Delete inst if it has no uses. Assumes inst has a resultId. - void DeleteIfUseless(opt::Instruction* inst); + void DeleteIfUseless(Instruction* inst); // Replace all instances of load's id with replId and delete load // and its access chain, if any - opt::Instruction* ReplaceAndDeleteLoad(opt::Instruction* loadInst, - uint32_t replId, - opt::Instruction* ptrInst); + Instruction* ReplaceAndDeleteLoad(Instruction* loadInst, uint32_t replId, + Instruction* ptrInst); // For the (constant index) access chain ptrInst, create an // equivalent load and extract - void GenACLoadRepl(const opt::Instruction* ptrInst, - std::vector<std::unique_ptr<opt::Instruction>>* newInsts, + void GenACLoadRepl(const Instruction* ptrInst, + std::vector<std::unique_ptr<Instruction>>* newInsts, uint32_t* resultId); // Return true if all indices are constant - bool IsConstantIndexAccessChain(opt::Instruction* acp); + bool IsConstantIndexAccessChain(Instruction* acp); // Convert all uniform access chain loads into load/extract. - bool UniformAccessChainConvert(opt::Function* func); + bool UniformAccessChainConvert(Function* func); // Compute structured successors for function |func|. // A block's structured successors are the blocks it branches to @@ -118,7 +116,7 @@ class CommonUniformElimPass : public Pass { // // TODO(dnovillo): This pass computes structured successors slightly different // than the implementation in class Pass. Can this be re-factored? - void ComputeStructuredSuccessors(opt::Function* func); + void ComputeStructuredSuccessors(Function* func); // Compute structured block order for |func| into |structuredOrder|. This // order has the property that dominators come before all blocks they @@ -127,24 +125,23 @@ class CommonUniformElimPass : public Pass { // // TODO(dnovillo): This pass computes structured order slightly different // than the implementation in class Pass. Can this be re-factored? - void ComputeStructuredOrder(opt::Function* func, - std::list<opt::BasicBlock*>* order); + void ComputeStructuredOrder(Function* func, std::list<BasicBlock*>* order); // Eliminate loads of uniform variables which have previously been loaded. // If first load is in control flow, move it to first block of function. // Most effective if preceded by UniformAccessChainRemoval(). - bool CommonUniformLoadElimination(opt::Function* func); + bool CommonUniformLoadElimination(Function* func); // Eliminate loads of uniform sampler and image variables which have // previously // been loaded in the same block for types whose loads cannot cross blocks. - bool CommonUniformLoadElimBlock(opt::Function* func); + bool CommonUniformLoadElimBlock(Function* func); // Eliminate duplicated extracts of same id. Extract may be moved to same // block as the id definition. This is primarily intended for extracts // from uniform loads. Most effective if preceded by // CommonUniformLoadElimination(). - bool CommonExtractElimination(opt::Function* func); + bool CommonExtractElimination(Function* func); // For function |func|, first change all uniform constant index // access chain loads into equivalent composite extracts. Then consolidate @@ -158,7 +155,7 @@ class CommonUniformElimPass : public Pass { // is not enabled. It also currently does not support any extensions. // // This function currently only optimizes loads with a single index. - bool EliminateCommonUniform(opt::Function* func); + bool EliminateCommonUniform(Function* func); // Initialize extensions whitelist void InitExtensions(); @@ -173,10 +170,10 @@ class CommonUniformElimPass : public Pass { // Return true if |inst| is an instruction that loads uniform variable and // can be replaced with other uniform load instruction. - bool IsUniformLoadToBeRemoved(opt::Instruction* inst) { + bool IsUniformLoadToBeRemoved(Instruction* inst) { if (inst->opcode() == SpvOpLoad) { uint32_t varId; - opt::Instruction* ptrInst = GetPtr(inst, &varId); + Instruction* ptrInst = GetPtr(inst, &varId); if (ptrInst->opcode() == SpvOpVariable && IsUniformVar(varId) && !IsSamplerOrImageVar(varId) && !HasUnsupportedDecorates(inst->result_id()) && !IsVolatileLoad(*inst)) @@ -194,7 +191,7 @@ class CommonUniformElimPass : public Pass { // Map of extract composite ids to map of indices to insts // TODO(greg-lunarg): Consider std::vector. std::unordered_map<uint32_t, - std::unordered_map<uint32_t, std::list<opt::Instruction*>>> + std::unordered_map<uint32_t, std::list<Instruction*>>> comp2idx2inst_; // Extensions supported by this pass. @@ -202,7 +199,7 @@ class CommonUniformElimPass : public Pass { // Map from block to its structured successor blocks. See // ComputeStructuredSuccessors() for definition. - std::unordered_map<const opt::BasicBlock*, std::vector<opt::BasicBlock*>> + std::unordered_map<const BasicBlock*, std::vector<BasicBlock*>> block2structured_succs_; }; diff --git a/source/opt/compact_ids_pass.cpp b/source/opt/compact_ids_pass.cpp index 0fe8da40..7fe58228 100644 --- a/source/opt/compact_ids_pass.cpp +++ b/source/opt/compact_ids_pass.cpp @@ -21,9 +21,6 @@ namespace spvtools { namespace opt { -using opt::Instruction; -using opt::Operand; - Pass::Status CompactIdsPass::Process() { bool modified = false; std::unordered_map<uint32_t, uint32_t> result_id_mapping; diff --git a/source/opt/compact_ids_pass.h b/source/opt/compact_ids_pass.h index b7416261..987dc945 100644 --- a/source/opt/compact_ids_pass.h +++ b/source/opt/compact_ids_pass.h @@ -29,10 +29,10 @@ class CompactIdsPass : public Pass { Status Process() override; // Return the mask of preserved Analyses. - opt::IRContext::Analysis GetPreservedAnalyses() override { - return opt::IRContext::kAnalysisInstrToBlockMapping | - opt::IRContext::kAnalysisDominatorAnalysis | - opt::IRContext::kAnalysisLoopAnalysis; + IRContext::Analysis GetPreservedAnalyses() override { + return IRContext::kAnalysisInstrToBlockMapping | + IRContext::kAnalysisDominatorAnalysis | + IRContext::kAnalysisLoopAnalysis; } }; diff --git a/source/opt/composite.cpp b/source/opt/composite.cpp index 7338be92..8d35d05b 100644 --- a/source/opt/composite.cpp +++ b/source/opt/composite.cpp @@ -26,7 +26,7 @@ namespace spvtools { namespace opt { bool ExtInsMatch(const std::vector<uint32_t>& extIndices, - const opt::Instruction* insInst, const uint32_t extOffset) { + const Instruction* insInst, const uint32_t extOffset) { uint32_t numIndices = static_cast<uint32_t>(extIndices.size()) - extOffset; if (numIndices != insInst->NumInOperands() - 2) return false; for (uint32_t i = 0; i < numIndices; ++i) @@ -36,7 +36,7 @@ bool ExtInsMatch(const std::vector<uint32_t>& extIndices, } bool ExtInsConflict(const std::vector<uint32_t>& extIndices, - const opt::Instruction* insInst, const uint32_t extOffset) { + const Instruction* insInst, const uint32_t extOffset) { if (extIndices.size() - extOffset == insInst->NumInOperands() - 2) return false; uint32_t extNumIndices = static_cast<uint32_t>(extIndices.size()) - extOffset; diff --git a/source/opt/composite.h b/source/opt/composite.h index 276ff2c5..c64fdc59 100644 --- a/source/opt/composite.h +++ b/source/opt/composite.h @@ -34,7 +34,7 @@ namespace opt { // Return true if the extract indices in |extIndices| starting at |extOffset| // match indices of insert |insInst|. bool ExtInsMatch(const std::vector<uint32_t>& extIndices, - const opt::Instruction* insInst, const uint32_t extOffset); + const Instruction* insInst, const uint32_t extOffset); // Return true if indices in |extIndices| starting at |extOffset| and // indices of insert |insInst| conflict, specifically, if the insert @@ -42,7 +42,7 @@ bool ExtInsMatch(const std::vector<uint32_t>& extIndices, // or less bits than the extract specifies, meaning the exact value being // inserted cannot be used to replace the extract. bool ExtInsConflict(const std::vector<uint32_t>& extIndices, - const opt::Instruction* insInst, const uint32_t extOffset); + const Instruction* insInst, const uint32_t extOffset); } // namespace opt } // namespace spvtools diff --git a/source/opt/const_folding_rules.cpp b/source/opt/const_folding_rules.cpp index f0e413a1..5e8ca83b 100644 --- a/source/opt/const_folding_rules.cpp +++ b/source/opt/const_folding_rules.cpp @@ -18,8 +18,8 @@ namespace spvtools { namespace opt { - namespace { + const uint32_t kExtractCompositeIdInIdx = 0; // Returns true if |type| is Float or a vector of Float. @@ -35,7 +35,7 @@ bool HasFloatingPoint(const analysis::Type* type) { // Folds an OpcompositeExtract where input is a composite constant. ConstantFoldingRule FoldExtractWithConstants() { - return [](IRContext* context, opt::Instruction* inst, + return [](IRContext* context, Instruction* inst, const std::vector<const analysis::Constant*>& constants) -> const analysis::Constant* { const analysis::Constant* c = constants[kExtractCompositeIdInIdx]; @@ -62,7 +62,7 @@ ConstantFoldingRule FoldExtractWithConstants() { } ConstantFoldingRule FoldVectorShuffleWithConstants() { - return [](IRContext* context, opt::Instruction* inst, + return [](IRContext* context, Instruction* inst, const std::vector<const analysis::Constant*>& constants) -> const analysis::Constant* { assert(inst->opcode() == SpvOpVectorShuffle); @@ -98,11 +98,11 @@ ConstantFoldingRule FoldVectorShuffleWithConstants() { for (uint32_t i = 2; i < inst->NumInOperands(); ++i) { uint32_t index = inst->GetSingleWordInOperand(i); if (index < c1_components.size()) { - opt::Instruction* member_inst = + Instruction* member_inst = const_mgr->GetDefiningInstruction(c1_components[index]); ids.push_back(member_inst->result_id()); } else { - opt::Instruction* member_inst = const_mgr->GetDefiningInstruction( + Instruction* member_inst = const_mgr->GetDefiningInstruction( c2_components[index - c1_components.size()]); ids.push_back(member_inst->result_id()); } @@ -114,7 +114,7 @@ ConstantFoldingRule FoldVectorShuffleWithConstants() { } ConstantFoldingRule FoldVectorTimesScalar() { - return [](IRContext* context, opt::Instruction* inst, + return [](IRContext* context, Instruction* inst, const std::vector<const analysis::Constant*>& constants) -> const analysis::Constant* { assert(inst->opcode() == SpvOpVectorTimesScalar); @@ -191,7 +191,7 @@ ConstantFoldingRule FoldVectorTimesScalar() { ConstantFoldingRule FoldCompositeWithConstants() { // Folds an OpCompositeConstruct where all of the inputs are constants to a // constant. A new constant is created if necessary. - return [](IRContext* context, opt::Instruction* inst, + return [](IRContext* context, Instruction* inst, const std::vector<const analysis::Constant*>& constants) -> const analysis::Constant* { analysis::ConstantManager* const_mgr = context->get_constant_mgr(); @@ -234,7 +234,7 @@ using BinaryScalarFoldingRule = std::function<const analysis::Constant*( // not |nullptr|, then their type is either |Float| or |Integer| or a |Vector| // whose element type is |Float| or |Integer|. ConstantFoldingRule FoldFPUnaryOp(UnaryScalarFoldingRule scalar_rule) { - return [scalar_rule](IRContext* context, opt::Instruction* inst, + return [scalar_rule](IRContext* context, Instruction* inst, const std::vector<const analysis::Constant*>& constants) -> const analysis::Constant* { analysis::ConstantManager* const_mgr = context->get_constant_mgr(); @@ -283,7 +283,7 @@ ConstantFoldingRule FoldFPUnaryOp(UnaryScalarFoldingRule scalar_rule) { // that |constants| contains 2 entries. If they are not |nullptr|, then their // type is either |Float| or a |Vector| whose element type is |Float|. ConstantFoldingRule FoldFPBinaryOp(BinaryScalarFoldingRule scalar_rule) { - return [scalar_rule](IRContext* context, opt::Instruction* inst, + return [scalar_rule](IRContext* context, Instruction* inst, const std::vector<const analysis::Constant*>& constants) -> const analysis::Constant* { analysis::ConstantManager* const_mgr = context->get_constant_mgr(); @@ -512,7 +512,7 @@ ConstantFoldingRule FoldFUnordGreaterThanEqual() { // Folds an OpDot where all of the inputs are constants to a // constant. A new constant is created if necessary. ConstantFoldingRule FoldOpDotWithConstants() { - return [](IRContext* context, opt::Instruction* inst, + return [](IRContext* context, Instruction* inst, const std::vector<const analysis::Constant*>& constants) -> const analysis::Constant* { analysis::ConstantManager* const_mgr = context->get_constant_mgr(); @@ -607,7 +607,7 @@ UnaryScalarFoldingRule FoldFNegateOp() { ConstantFoldingRule FoldFNegate() { return FoldFPUnaryOp(FoldFNegateOp()); } ConstantFoldingRule FoldFClampFeedingCompare(uint32_t cmp_opcode) { - return [cmp_opcode](IRContext* context, opt::Instruction* inst, + return [cmp_opcode](IRContext* context, Instruction* inst, const std::vector<const analysis::Constant*>& constants) -> const analysis::Constant* { analysis::ConstantManager* const_mgr = context->get_constant_mgr(); @@ -619,7 +619,7 @@ ConstantFoldingRule FoldFClampFeedingCompare(uint32_t cmp_opcode) { uint32_t non_const_idx = (constants[0] ? 1 : 0); uint32_t operand_id = inst->GetSingleWordInOperand(non_const_idx); - opt::Instruction* operand_inst = def_use_mgr->GetDef(operand_id); + Instruction* operand_inst = def_use_mgr->GetDef(operand_id); analysis::TypeManager* type_mgr = context->get_type_mgr(); const analysis::Type* operand_type = diff --git a/source/opt/const_folding_rules.h b/source/opt/const_folding_rules.h index 543df1c6..11fb1e60 100644 --- a/source/opt/const_folding_rules.h +++ b/source/opt/const_folding_rules.h @@ -48,7 +48,7 @@ namespace opt { // fold an instruction, the later rules will not be attempted. using ConstantFoldingRule = std::function<const analysis::Constant*( - IRContext* ctx, opt::Instruction* inst, + IRContext* ctx, Instruction* inst, const std::vector<const analysis::Constant*>& constants)>; class ConstantFoldingRules { diff --git a/source/opt/constants.cpp b/source/opt/constants.cpp index 45b57e77..238dab38 100644 --- a/source/opt/constants.cpp +++ b/source/opt/constants.cpp @@ -102,7 +102,7 @@ int64_t Constant::GetS64() const { } } -ConstantManager::ConstantManager(opt::IRContext* ctx) : ctx_(ctx) { +ConstantManager::ConstantManager(IRContext* ctx) : ctx_(ctx) { // Populate the constant table with values from constant declarations in the // module. The values of each OpConstant declaration is the identity // assignment (i.e., each constant is its own value). @@ -111,15 +111,15 @@ ConstantManager::ConstantManager(opt::IRContext* ctx) : ctx_(ctx) { } } -Type* ConstantManager::GetType(const opt::Instruction* inst) const { +Type* ConstantManager::GetType(const Instruction* inst) const { return context()->get_type_mgr()->GetType(inst->type_id()); } std::vector<const Constant*> ConstantManager::GetOperandConstants( - opt::Instruction* inst) const { + Instruction* inst) const { std::vector<const Constant*> constants; for (uint32_t i = 0; i < inst->NumInOperands(); i++) { - const opt::Operand* operand = &inst->GetInOperand(i); + const Operand* operand = &inst->GetInOperand(i); if (operand->type != SPV_OPERAND_TYPE_ID) { constants.push_back(nullptr); } else { @@ -144,9 +144,8 @@ std::vector<const Constant*> ConstantManager::GetConstantsFromIds( return constants; } -opt::Instruction* ConstantManager::BuildInstructionAndAddToModule( - const Constant* new_const, opt::Module::inst_iterator* pos, - uint32_t type_id) { +Instruction* ConstantManager::BuildInstructionAndAddToModule( + const Constant* new_const, Module::inst_iterator* pos, uint32_t type_id) { uint32_t new_id = context()->TakeNextId(); auto new_inst = CreateInstruction(new_id, new_const, type_id); if (!new_inst) { @@ -160,8 +159,8 @@ opt::Instruction* ConstantManager::BuildInstructionAndAddToModule( return new_inst_ptr; } -opt::Instruction* ConstantManager::GetDefiningInstruction( - const Constant* c, uint32_t type_id, opt::Module::inst_iterator* pos) { +Instruction* ConstantManager::GetDefiningInstruction( + const Constant* c, uint32_t type_id, Module::inst_iterator* pos) { assert(type_id == 0 || context()->get_type_mgr()->GetType(type_id) == c->type()); uint32_t decl_id = FindDeclaredConstant(c); @@ -231,7 +230,7 @@ const Constant* ConstantManager::CreateConstant( } } -const Constant* ConstantManager::GetConstantFromInst(opt::Instruction* inst) { +const Constant* ConstantManager::GetConstantFromInst(Instruction* inst) { std::vector<uint32_t> literal_words_or_ids; // Collect the constant defining literals or component ids. @@ -262,31 +261,30 @@ const Constant* ConstantManager::GetConstantFromInst(opt::Instruction* inst) { return GetConstant(GetType(inst), literal_words_or_ids); } -std::unique_ptr<opt::Instruction> ConstantManager::CreateInstruction( +std::unique_ptr<Instruction> ConstantManager::CreateInstruction( uint32_t id, const Constant* c, uint32_t type_id) const { uint32_t type = (type_id == 0) ? context()->get_type_mgr()->GetId(c->type()) : type_id; if (c->AsNullConstant()) { - return MakeUnique<opt::Instruction>(context(), SpvOp::SpvOpConstantNull, - type, id, - std::initializer_list<opt::Operand>{}); + return MakeUnique<Instruction>(context(), SpvOp::SpvOpConstantNull, type, + id, std::initializer_list<Operand>{}); } else if (const BoolConstant* bc = c->AsBoolConstant()) { - return MakeUnique<opt::Instruction>( + return MakeUnique<Instruction>( context(), bc->value() ? SpvOp::SpvOpConstantTrue : SpvOp::SpvOpConstantFalse, - type, id, std::initializer_list<opt::Operand>{}); + type, id, std::initializer_list<Operand>{}); } else if (const IntConstant* ic = c->AsIntConstant()) { - return MakeUnique<opt::Instruction>( + return MakeUnique<Instruction>( context(), SpvOp::SpvOpConstant, type, id, - std::initializer_list<opt::Operand>{opt::Operand( - spv_operand_type_t::SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER, - ic->words())}); + std::initializer_list<Operand>{ + Operand(spv_operand_type_t::SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER, + ic->words())}); } else if (const FloatConstant* fc = c->AsFloatConstant()) { - return MakeUnique<opt::Instruction>( + return MakeUnique<Instruction>( context(), SpvOp::SpvOpConstant, type, id, - std::initializer_list<opt::Operand>{opt::Operand( - spv_operand_type_t::SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER, - fc->words())}); + std::initializer_list<Operand>{ + Operand(spv_operand_type_t::SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER, + fc->words())}); } else if (const CompositeConstant* cc = c->AsCompositeConstant()) { return CreateCompositeInstruction(id, cc, type_id); } else { @@ -294,9 +292,9 @@ std::unique_ptr<opt::Instruction> ConstantManager::CreateInstruction( } } -std::unique_ptr<opt::Instruction> ConstantManager::CreateCompositeInstruction( +std::unique_ptr<Instruction> ConstantManager::CreateCompositeInstruction( uint32_t result_id, const CompositeConstant* cc, uint32_t type_id) const { - std::vector<opt::Operand> operands; + std::vector<Operand> operands; for (const Constant* component_const : cc->GetComponents()) { uint32_t id = FindDeclaredConstant(component_const); if (id == 0) { @@ -310,8 +308,8 @@ std::unique_ptr<opt::Instruction> ConstantManager::CreateCompositeInstruction( } uint32_t type = (type_id == 0) ? context()->get_type_mgr()->GetId(cc->type()) : type_id; - return MakeUnique<opt::Instruction>(context(), SpvOp::SpvOpConstantComposite, - type, result_id, std::move(operands)); + return MakeUnique<Instruction>(context(), SpvOp::SpvOpConstantComposite, type, + result_id, std::move(operands)); } const Constant* ConstantManager::GetConstant( diff --git a/source/opt/constants.h b/source/opt/constants.h index 353022b5..8b9614df 100644 --- a/source/opt/constants.h +++ b/source/opt/constants.h @@ -491,9 +491,9 @@ struct ConstantEqual { // This class represents a pool of constants. class ConstantManager { public: - ConstantManager(opt::IRContext* ctx); + ConstantManager(IRContext* ctx); - opt::IRContext* context() const { return ctx_; } + IRContext* context() const { return ctx_; } // Gets or creates a unique Constant instance of type |type| and a vector of // constant defining words |words|. If a Constant instance existed already in @@ -512,7 +512,7 @@ class ConstantManager { // Gets or creates a Constant instance to hold the constant value of the given // instruction. It returns a pointer to a Constant instance or nullptr if it // could not create the constant. - const Constant* GetConstantFromInst(opt::Instruction* inst); + const Constant* GetConstantFromInst(Instruction* inst); // Gets or creates a constant defining instruction for the given Constant |c|. // If |c| had already been defined, it returns a pointer to the existing @@ -528,9 +528,8 @@ class ConstantManager { // // When |type_id| is not zero, the type of |c| must be the type returned by // type manager when given |type_id|. - opt::Instruction* GetDefiningInstruction( - const Constant* c, uint32_t type_id = 0, - opt::Module::inst_iterator* pos = nullptr); + Instruction* GetDefiningInstruction(const Constant* c, uint32_t type_id = 0, + Module::inst_iterator* pos = nullptr); // Creates a constant defining instruction for the given Constant instance // and inserts the instruction at the position specified by the given @@ -544,12 +543,13 @@ class ConstantManager { // |type_id| is specified, it is used as the type of the constant. Otherwise // the type of the constant is derived by getting an id from the type manager // for |c|. - opt::Instruction* BuildInstructionAndAddToModule( - const Constant* c, opt::Module::inst_iterator* pos, uint32_t type_id = 0); + Instruction* BuildInstructionAndAddToModule(const Constant* c, + Module::inst_iterator* pos, + uint32_t type_id = 0); // A helper function to get the result type of the given instruction. Returns // nullptr if the instruction does not have a type id (type id is 0). - Type* GetType(const opt::Instruction* inst) const; + Type* GetType(const Instruction* inst) const; // A helper function to get the collected normal constant with the given id. // Returns the pointer to the Constant instance in case it is found. @@ -592,13 +592,12 @@ class ConstantManager { // Returns a vector of constants representing each in operand. If an operand // is not constant its entry is nullptr. - std::vector<const Constant*> GetOperandConstants( - opt::Instruction* inst) const; + std::vector<const Constant*> GetOperandConstants(Instruction* inst) const; // Records a mapping between |inst| and the constant value generated by it. // It returns true if a new Constant was successfully mapped, false if |inst| // generates no constant values. - bool MapInst(opt::Instruction* inst) { + bool MapInst(Instruction* inst) { if (auto cst = GetConstantFromInst(inst)) { MapConstantToInst(cst, inst); return true; @@ -616,7 +615,7 @@ class ConstantManager { // Records a new mapping between |inst| and |const_value|. This updates the // two mappings |id_to_const_val_| and |const_val_to_id_|. - void MapConstantToInst(const Constant* const_value, opt::Instruction* inst) { + void MapConstantToInst(const Constant* const_value, Instruction* inst) { const_val_to_id_[const_value] = inst->result_id(); id_to_const_val_[inst->result_id()] = const_value; } @@ -647,8 +646,9 @@ class ConstantManager { // |type_id| is specified, it is used as the type of the constant. Otherwise // the type of the constant is derived by getting an id from the type manager // for |c|. - std::unique_ptr<opt::Instruction> CreateInstruction( - uint32_t result_id, const Constant* c, uint32_t type_id = 0) const; + std::unique_ptr<Instruction> CreateInstruction(uint32_t result_id, + const Constant* c, + uint32_t type_id = 0) const; // Creates an OpConstantComposite instruction with the given result id and // the CompositeConst instance which represents a composite constant. Returns @@ -659,12 +659,12 @@ class ConstantManager { // |type_id| is specified, it is used as the type of the constant. Otherwise // the type of the constant is derived by getting an id from the type manager // for |c|. - std::unique_ptr<opt::Instruction> CreateCompositeInstruction( + std::unique_ptr<Instruction> CreateCompositeInstruction( uint32_t result_id, const CompositeConstant* cc, uint32_t type_id = 0) const; // IR context that owns this constant manager. - opt::IRContext* ctx_; + IRContext* ctx_; // A mapping from the result ids of Normal Constants to their // Constant instances. All Normal Constants in the module, either diff --git a/source/opt/copy_prop_arrays.cpp b/source/opt/copy_prop_arrays.cpp index eba2bc1b..6fa232fe 100644 --- a/source/opt/copy_prop_arrays.cpp +++ b/source/opt/copy_prop_arrays.cpp @@ -15,20 +15,21 @@ #include "copy_prop_arrays.h" #include "ir_builder.h" +namespace spvtools { +namespace opt { namespace { + const uint32_t kLoadPointerInOperand = 0; const uint32_t kStorePointerInOperand = 0; const uint32_t kStoreObjectInOperand = 1; const uint32_t kCompositeExtractObjectInOperand = 0; -} // namespace -namespace spvtools { -namespace opt { +} // namespace Pass::Status CopyPropagateArrays::Process() { bool modified = false; - for (opt::Function& function : *get_module()) { - opt::BasicBlock* entry_bb = &*function.begin(); + for (Function& function : *get_module()) { + BasicBlock* entry_bb = &*function.begin(); for (auto var_inst = entry_bb->begin(); var_inst->opcode() == SpvOpVariable; ++var_inst) { @@ -37,7 +38,7 @@ Pass::Status CopyPropagateArrays::Process() { } // Find the only store to the entire memory location, if it exists. - opt::Instruction* store_inst = FindStoreInstruction(&*var_inst); + Instruction* store_inst = FindStoreInstruction(&*var_inst); if (!store_inst) { continue; @@ -58,8 +59,8 @@ Pass::Status CopyPropagateArrays::Process() { } std::unique_ptr<CopyPropagateArrays::MemoryObject> -CopyPropagateArrays::FindSourceObjectIfPossible(opt::Instruction* var_inst, - opt::Instruction* store_inst) { +CopyPropagateArrays::FindSourceObjectIfPossible(Instruction* var_inst, + Instruction* store_inst) { assert(var_inst->opcode() == SpvOpVariable && "Expecting a variable."); // Check that the variable is a composite object where |store_inst| @@ -93,11 +94,11 @@ CopyPropagateArrays::FindSourceObjectIfPossible(opt::Instruction* var_inst, return source; } -opt::Instruction* CopyPropagateArrays::FindStoreInstruction( - const opt::Instruction* var_inst) const { - opt::Instruction* store_inst = nullptr; +Instruction* CopyPropagateArrays::FindStoreInstruction( + const Instruction* var_inst) const { + Instruction* store_inst = nullptr; get_def_use_mgr()->WhileEachUser( - var_inst, [&store_inst, var_inst](opt::Instruction* use) { + var_inst, [&store_inst, var_inst](Instruction* use) { if (use->opcode() == SpvOpStore && use->GetSingleWordInOperand(kStorePointerInOperand) == var_inst->result_id()) { @@ -113,24 +114,23 @@ opt::Instruction* CopyPropagateArrays::FindStoreInstruction( return store_inst; } -void CopyPropagateArrays::PropagateObject(opt::Instruction* var_inst, +void CopyPropagateArrays::PropagateObject(Instruction* var_inst, MemoryObject* source, - opt::Instruction* insertion_point) { + Instruction* insertion_point) { assert(var_inst->opcode() == SpvOpVariable && "This function propagates variables."); - opt::Instruction* new_access_chain = - BuildNewAccessChain(insertion_point, source); + Instruction* new_access_chain = BuildNewAccessChain(insertion_point, source); context()->KillNamesAndDecorates(var_inst); UpdateUses(var_inst, new_access_chain); } -opt::Instruction* CopyPropagateArrays::BuildNewAccessChain( - opt::Instruction* insertion_point, +Instruction* CopyPropagateArrays::BuildNewAccessChain( + Instruction* insertion_point, CopyPropagateArrays::MemoryObject* source) const { - InstructionBuilder builder(context(), insertion_point, - opt::IRContext::kAnalysisDefUse | - opt::IRContext::kAnalysisInstrToBlockMapping); + InstructionBuilder builder( + context(), insertion_point, + IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping); if (source->AccessChain().size() == 0) { return source->GetVariable(); @@ -141,34 +141,33 @@ opt::Instruction* CopyPropagateArrays::BuildNewAccessChain( source->AccessChain()); } -bool CopyPropagateArrays::HasNoStores(opt::Instruction* ptr_inst) { - return get_def_use_mgr()->WhileEachUser( - ptr_inst, [this](opt::Instruction* use) { - if (use->opcode() == SpvOpLoad) { - return true; - } else if (use->opcode() == SpvOpAccessChain) { - return HasNoStores(use); - } else if (use->IsDecoration() || use->opcode() == SpvOpName) { - return true; - } else if (use->opcode() == SpvOpStore) { - return false; - } else if (use->opcode() == SpvOpImageTexelPointer) { - return true; - } - // Some other instruction. Be conservative. - return false; - }); +bool CopyPropagateArrays::HasNoStores(Instruction* ptr_inst) { + return get_def_use_mgr()->WhileEachUser(ptr_inst, [this](Instruction* use) { + if (use->opcode() == SpvOpLoad) { + return true; + } else if (use->opcode() == SpvOpAccessChain) { + return HasNoStores(use); + } else if (use->IsDecoration() || use->opcode() == SpvOpName) { + return true; + } else if (use->opcode() == SpvOpStore) { + return false; + } else if (use->opcode() == SpvOpImageTexelPointer) { + return true; + } + // Some other instruction. Be conservative. + return false; + }); } -bool CopyPropagateArrays::HasValidReferencesOnly(opt::Instruction* ptr_inst, - opt::Instruction* store_inst) { - opt::BasicBlock* store_block = context()->get_instr_block(store_inst); - opt::DominatorAnalysis* dominator_analysis = +bool CopyPropagateArrays::HasValidReferencesOnly(Instruction* ptr_inst, + Instruction* store_inst) { + BasicBlock* store_block = context()->get_instr_block(store_inst); + DominatorAnalysis* dominator_analysis = context()->GetDominatorAnalysis(store_block->GetParent()); return get_def_use_mgr()->WhileEachUser( ptr_inst, - [this, store_inst, dominator_analysis, ptr_inst](opt::Instruction* use) { + [this, store_inst, dominator_analysis, ptr_inst](Instruction* use) { if (use->opcode() == SpvOpLoad || use->opcode() == SpvOpImageTexelPointer) { // TODO: If there are many load in the same BB as |store_inst| the @@ -192,7 +191,7 @@ bool CopyPropagateArrays::HasValidReferencesOnly(opt::Instruction* ptr_inst, std::unique_ptr<CopyPropagateArrays::MemoryObject> CopyPropagateArrays::GetSourceObjectIfAny(uint32_t result) { - opt::Instruction* result_inst = context()->get_def_use_mgr()->GetDef(result); + Instruction* result_inst = context()->get_def_use_mgr()->GetDef(result); switch (result_inst->opcode()) { case SpvOpLoad: @@ -211,11 +210,11 @@ CopyPropagateArrays::GetSourceObjectIfAny(uint32_t result) { } std::unique_ptr<CopyPropagateArrays::MemoryObject> -CopyPropagateArrays::BuildMemoryObjectFromLoad(opt::Instruction* load_inst) { +CopyPropagateArrays::BuildMemoryObjectFromLoad(Instruction* load_inst) { std::vector<uint32_t> components_in_reverse; analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr(); - opt::Instruction* current_inst = def_use_mgr->GetDef( + Instruction* current_inst = def_use_mgr->GetDef( load_inst->GetSingleWordInOperand(kLoadPointerInOperand)); // Build the access chain for the memory object by collecting the indices used @@ -249,8 +248,7 @@ CopyPropagateArrays::BuildMemoryObjectFromLoad(opt::Instruction* load_inst) { } std::unique_ptr<CopyPropagateArrays::MemoryObject> -CopyPropagateArrays::BuildMemoryObjectFromExtract( - opt::Instruction* extract_inst) { +CopyPropagateArrays::BuildMemoryObjectFromExtract(Instruction* extract_inst) { assert(extract_inst->opcode() == SpvOpCompositeExtract && "Expecting an OpCompositeExtract instruction."); analysis::ConstantManager* const_mgr = context()->get_constant_mgr(); @@ -281,7 +279,7 @@ CopyPropagateArrays::BuildMemoryObjectFromExtract( std::unique_ptr<CopyPropagateArrays::MemoryObject> CopyPropagateArrays::BuildMemoryObjectFromCompositeConstruct( - opt::Instruction* conststruct_inst) { + Instruction* conststruct_inst) { assert(conststruct_inst->opcode() == SpvOpCompositeConstruct && "Expecting an OpCompositeConstruct instruction."); @@ -345,8 +343,7 @@ CopyPropagateArrays::BuildMemoryObjectFromCompositeConstruct( } std::unique_ptr<CopyPropagateArrays::MemoryObject> -CopyPropagateArrays::BuildMemoryObjectFromInsert( - opt::Instruction* insert_inst) { +CopyPropagateArrays::BuildMemoryObjectFromInsert(Instruction* insert_inst) { assert(insert_inst->opcode() == SpvOpCompositeInsert && "Expecting an OpCompositeInsert instruction."); @@ -405,7 +402,7 @@ CopyPropagateArrays::BuildMemoryObjectFromInsert( memory_object->GetParent(); - opt::Instruction* current_insert = + Instruction* current_insert = def_use_mgr->GetDef(insert_inst->GetSingleWordInOperand(1)); for (uint32_t i = number_of_elements - 1; i > 0; --i) { if (current_insert->opcode() != SpvOpCompositeInsert) { @@ -467,7 +464,7 @@ bool CopyPropagateArrays::IsPointerToArrayType(uint32_t type_id) { return false; } -bool CopyPropagateArrays::CanUpdateUses(opt::Instruction* original_ptr_inst, +bool CopyPropagateArrays::CanUpdateUses(Instruction* original_ptr_inst, uint32_t type_id) { analysis::TypeManager* type_mgr = context()->get_type_mgr(); analysis::ConstantManager* const_mgr = context()->get_constant_mgr(); @@ -486,7 +483,7 @@ bool CopyPropagateArrays::CanUpdateUses(opt::Instruction* original_ptr_inst, return def_use_mgr->WhileEachUse( original_ptr_inst, - [this, type_mgr, const_mgr, type](opt::Instruction* use, uint32_t) { + [this, type_mgr, const_mgr, type](Instruction* use, uint32_t) { switch (use->opcode()) { case SpvOpLoad: { analysis::Pointer* pointer_type = type->AsPointer(); @@ -518,8 +515,8 @@ bool CopyPropagateArrays::CanUpdateUses(opt::Instruction* original_ptr_inst, const analysis::Type* new_pointee_type = type_mgr->GetMemberType(pointee_type, access_chain); - opt::analysis::Pointer pointerTy(new_pointee_type, - pointer_type->storage_class()); + analysis::Pointer pointerTy(new_pointee_type, + pointer_type->storage_class()); uint32_t new_pointer_type_id = context()->get_type_mgr()->GetTypeInstruction(&pointerTy); @@ -559,8 +556,8 @@ bool CopyPropagateArrays::CanUpdateUses(opt::Instruction* original_ptr_inst, } }); } -void CopyPropagateArrays::UpdateUses(opt::Instruction* original_ptr_inst, - opt::Instruction* new_ptr_inst) { +void CopyPropagateArrays::UpdateUses(Instruction* original_ptr_inst, + Instruction* new_ptr_inst) { // TODO (s-perron): Keep the def-use manager up to date. Not done now because // it can cause problems for the |ForEachUse| traversals. Can be use by // keeping a list of instructions that need updating, and then updating them @@ -570,14 +567,14 @@ void CopyPropagateArrays::UpdateUses(opt::Instruction* original_ptr_inst, analysis::ConstantManager* const_mgr = context()->get_constant_mgr(); analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr(); - std::vector<std::pair<opt::Instruction*, uint32_t> > uses; + std::vector<std::pair<Instruction*, uint32_t> > uses; def_use_mgr->ForEachUse(original_ptr_inst, - [&uses](opt::Instruction* use, uint32_t index) { + [&uses](Instruction* use, uint32_t index) { uses.push_back({use, index}); }); for (auto pair : uses) { - opt::Instruction* use = pair.first; + Instruction* use = pair.first; uint32_t index = pair.second; analysis::Pointer* pointer_type = nullptr; switch (use->opcode()) { @@ -624,8 +621,8 @@ void CopyPropagateArrays::UpdateUses(opt::Instruction* original_ptr_inst, type_mgr->GetMemberType(pointee_type, access_chain); // Now build a pointer to the type of the member. - opt::analysis::Pointer new_pointer_type(new_pointee_type, - pointer_type->storage_class()); + analysis::Pointer new_pointer_type(new_pointee_type, + pointer_type->storage_class()); uint32_t new_pointer_type_id = context()->get_type_mgr()->GetTypeInstruction(&new_pointer_type); @@ -670,7 +667,7 @@ void CopyPropagateArrays::UpdateUses(opt::Instruction* original_ptr_inst, // decomposing the object into the base type, which must be the same, // and then rebuilding them. if (index == 1) { - opt::Instruction* target_pointer = def_use_mgr->GetDef( + Instruction* target_pointer = def_use_mgr->GetDef( use->GetSingleWordInOperand(kStorePointerInOperand)); pointer_type = type_mgr->GetType(target_pointer->type_id())->AsPointer(); @@ -700,9 +697,9 @@ void CopyPropagateArrays::UpdateUses(opt::Instruction* original_ptr_inst, } } -uint32_t CopyPropagateArrays::GenerateCopy( - opt::Instruction* object_inst, uint32_t new_type_id, - opt::Instruction* insertion_position) { +uint32_t CopyPropagateArrays::GenerateCopy(Instruction* object_inst, + uint32_t new_type_id, + Instruction* insertion_position) { analysis::TypeManager* type_mgr = context()->get_type_mgr(); analysis::ConstantManager* const_mgr = context()->get_constant_mgr(); @@ -711,10 +708,9 @@ uint32_t CopyPropagateArrays::GenerateCopy( return object_inst->result_id(); } - opt::InstructionBuilder ir_builder( + InstructionBuilder ir_builder( context(), insertion_position, - opt::IRContext::kAnalysisInstrToBlockMapping | - opt::IRContext::kAnalysisDefUse); + IRContext::kAnalysisInstrToBlockMapping | IRContext::kAnalysisDefUse); analysis::Type* original_type = type_mgr->GetType(original_type_id); analysis::Type* new_type = type_mgr->GetType(new_type_id); @@ -734,7 +730,7 @@ uint32_t CopyPropagateArrays::GenerateCopy( assert(length_const->AsIntConstant()); uint32_t array_length = length_const->AsIntConstant()->GetU32(); for (uint32_t i = 0; i < array_length; i++) { - opt::Instruction* extract = ir_builder.AddCompositeExtract( + Instruction* extract = ir_builder.AddCompositeExtract( original_element_type_id, object_inst->result_id(), {i}); element_ids.push_back( GenerateCopy(extract, new_element_type_id, insertion_position)); @@ -752,7 +748,7 @@ uint32_t CopyPropagateArrays::GenerateCopy( new_struct_type->element_types(); std::vector<uint32_t> element_ids; for (uint32_t i = 0; i < original_types.size(); i++) { - opt::Instruction* extract = ir_builder.AddCompositeExtract( + Instruction* extract = ir_builder.AddCompositeExtract( type_mgr->GetId(original_types[i]), object_inst->result_id(), {i}); element_ids.push_back(GenerateCopy(extract, type_mgr->GetId(new_types[i]), insertion_position)); @@ -776,7 +772,7 @@ void CopyPropagateArrays::MemoryObject::GetMember( } uint32_t CopyPropagateArrays::MemoryObject::GetNumberOfMembers() { - opt::IRContext* context = variable_inst_->context(); + IRContext* context = variable_inst_->context(); analysis::TypeManager* type_mgr = context->get_type_mgr(); const analysis::Type* type = type_mgr->GetType(variable_inst_->type_id()); @@ -803,7 +799,7 @@ uint32_t CopyPropagateArrays::MemoryObject::GetNumberOfMembers() { } template <class iterator> -CopyPropagateArrays::MemoryObject::MemoryObject(opt::Instruction* var_inst, +CopyPropagateArrays::MemoryObject::MemoryObject(Instruction* var_inst, iterator begin, iterator end) : variable_inst_(var_inst), access_chain_(begin, end) {} diff --git a/source/opt/copy_prop_arrays.h b/source/opt/copy_prop_arrays.h index ed05849c..82ae21e2 100644 --- a/source/opt/copy_prop_arrays.h +++ b/source/opt/copy_prop_arrays.h @@ -40,13 +40,11 @@ class CopyPropagateArrays : public MemPass { const char* name() const override { return "copy-propagate-arrays"; } Status Process() override; - opt::IRContext::Analysis GetPreservedAnalyses() override { - return opt::IRContext::kAnalysisDefUse | opt::IRContext::kAnalysisCFG | - opt::IRContext::kAnalysisInstrToBlockMapping | - opt::IRContext::kAnalysisLoopAnalysis | - opt::IRContext::kAnalysisDecorations | - opt::IRContext::kAnalysisDominatorAnalysis | - opt::IRContext::kAnalysisNameMap; + IRContext::Analysis GetPreservedAnalyses() override { + return IRContext::kAnalysisDefUse | IRContext::kAnalysisCFG | + IRContext::kAnalysisInstrToBlockMapping | + IRContext::kAnalysisLoopAnalysis | IRContext::kAnalysisDecorations | + IRContext::kAnalysisDominatorAnalysis | IRContext::kAnalysisNameMap; } private: @@ -62,7 +60,7 @@ class CopyPropagateArrays : public MemPass { // are interpreted the same way they would be in an |OpAccessChain| // instruction. template <class iterator> - MemoryObject(opt::Instruction* var_inst, iterator begin, iterator end); + MemoryObject(Instruction* var_inst, iterator begin, iterator end); // Change |this| to now point to the member identified by |access_chain| // (starting from the current member). The elements in |access_chain| are @@ -87,7 +85,7 @@ class CopyPropagateArrays : public MemPass { uint32_t GetNumberOfMembers(); // Returns the owning variable that the memory object is contained in. - opt::Instruction* GetVariable() const { return variable_inst_; } + Instruction* GetVariable() const { return variable_inst_; } // Returns a vector of integers that can be used to access the specific // member that |this| represents starting from the owning variable. These @@ -127,7 +125,7 @@ class CopyPropagateArrays : public MemPass { private: // The variable that owns this memory object. - opt::Instruction* variable_inst_; + Instruction* variable_inst_; // The access chain to reach the particular member the memory object // represents. It should be interpreted the same way the indices in an @@ -142,18 +140,17 @@ class CopyPropagateArrays : public MemPass { // and only identifies very simple cases. If no such memory object can be // found, the return value is |nullptr|. std::unique_ptr<CopyPropagateArrays::MemoryObject> FindSourceObjectIfPossible( - opt::Instruction* var_inst, opt::Instruction* store_inst); + Instruction* var_inst, Instruction* store_inst); // Replaces all loads of |var_inst| with a load from |source| instead. // |insertion_pos| is a position where it is possible to construct the // address of |source| and also dominates all of the loads of |var_inst|. - void PropagateObject(opt::Instruction* var_inst, MemoryObject* source, - opt::Instruction* insertion_pos); + void PropagateObject(Instruction* var_inst, MemoryObject* source, + Instruction* insertion_pos); // Returns true if all of the references to |ptr_inst| can be rewritten and // are dominated by |store_inst|. - bool HasValidReferencesOnly(opt::Instruction* ptr_inst, - opt::Instruction* store_inst); + bool HasValidReferencesOnly(Instruction* ptr_inst, Instruction* store_inst); // Returns a memory object that at one time was equivalent to the value in // |result|. If no such memory object exists, the return value is |nullptr|. @@ -163,21 +160,21 @@ class CopyPropagateArrays : public MemPass { // object cannot be identified, the return value is |nullptr|. The opcode of // |load_inst| must be |OpLoad|. std::unique_ptr<MemoryObject> BuildMemoryObjectFromLoad( - opt::Instruction* load_inst); + Instruction* load_inst); // Returns the memory object that at some point was equivalent to the result // of |extract_inst|. If a memory object cannot be identified, the return // value is |nullptr|. The opcode of |extract_inst| must be // |OpCompositeExtract|. std::unique_ptr<MemoryObject> BuildMemoryObjectFromExtract( - opt::Instruction* extract_inst); + Instruction* extract_inst); // Returns the memory object that at some point was equivalent to the result // of |construct_inst|. If a memory object cannot be identified, the return // value is |nullptr|. The opcode of |constuct_inst| must be // |OpCompositeConstruct|. std::unique_ptr<MemoryObject> BuildMemoryObjectFromCompositeConstruct( - opt::Instruction* conststruct_inst); + Instruction* conststruct_inst); // Returns the memory object that at some point was equivalent to the result // of |insert_inst|. If a memory object cannot be identified, the return @@ -186,44 +183,43 @@ class CopyPropagateArrays : public MemPass { // |OpCompositeInsert| instructions that insert the elements one at a time in // order from beginning to end. std::unique_ptr<MemoryObject> BuildMemoryObjectFromInsert( - opt::Instruction* insert_inst); + Instruction* insert_inst); // Return true if |type_id| is a pointer type whose pointee type is an array. bool IsPointerToArrayType(uint32_t type_id); // Returns true of there are not stores using |ptr_inst| or something derived // from it. - bool HasNoStores(opt::Instruction* ptr_inst); + bool HasNoStores(Instruction* ptr_inst); // Creates an |OpAccessChain| instruction whose result is a pointer the memory // represented by |source|. The new instruction will be placed before // |insertion_point|. |insertion_point| must be part of a function. Returns // the new instruction. - opt::Instruction* BuildNewAccessChain(opt::Instruction* insertion_point, - MemoryObject* source) const; + Instruction* BuildNewAccessChain(Instruction* insertion_point, + MemoryObject* source) const; // Rewrites all uses of |original_ptr| to use |new_pointer_inst| updating // types of other instructions as needed. This function should not be called // if |CanUpdateUses(original_ptr_inst, new_pointer_inst->type_id())| returns // false. - void UpdateUses(opt::Instruction* original_ptr_inst, - opt::Instruction* new_pointer_inst); + void UpdateUses(Instruction* original_ptr_inst, + Instruction* new_pointer_inst); // Return true if |UpdateUses| is able to change all of the uses of // |original_ptr_inst| to |type_id| and still have valid code. - bool CanUpdateUses(opt::Instruction* original_ptr_inst, uint32_t type_id); + bool CanUpdateUses(Instruction* original_ptr_inst, uint32_t type_id); // Returns the id whose value is the same as |object_to_copy| except its type // is |new_type_id|. Any instructions need to generate this value will be // inserted before |insertion_position|. - uint32_t GenerateCopy(opt::Instruction* object_to_copy, uint32_t new_type_id, - opt::Instruction* insertion_position); + uint32_t GenerateCopy(Instruction* object_to_copy, uint32_t new_type_id, + Instruction* insertion_position); // Returns a store to |var_inst| that writes to the entire variable, and is // the only store that does so. Note it does not look through OpAccessChain // instruction, so partial stores are not considered. - opt::Instruction* FindStoreInstruction( - const opt::Instruction* var_inst) const; + Instruction* FindStoreInstruction(const Instruction* var_inst) const; }; } // namespace opt diff --git a/source/opt/dead_branch_elim_pass.cpp b/source/opt/dead_branch_elim_pass.cpp index 73d2610c..694e7a43 100644 --- a/source/opt/dead_branch_elim_pass.cpp +++ b/source/opt/dead_branch_elim_pass.cpp @@ -34,7 +34,7 @@ const uint32_t kBranchCondFalseLabIdInIdx = 2; bool DeadBranchElimPass::GetConstCondition(uint32_t condId, bool* condVal) { bool condIsConst; - opt::Instruction* cInst = get_def_use_mgr()->GetDef(condId); + Instruction* cInst = get_def_use_mgr()->GetDef(condId); switch (cInst->opcode()) { case SpvOpConstantFalse: { *condVal = false; @@ -56,9 +56,9 @@ bool DeadBranchElimPass::GetConstCondition(uint32_t condId, bool* condVal) { } bool DeadBranchElimPass::GetConstInteger(uint32_t selId, uint32_t* selVal) { - opt::Instruction* sInst = get_def_use_mgr()->GetDef(selId); + Instruction* sInst = get_def_use_mgr()->GetDef(selId); uint32_t typeId = sInst->type_id(); - opt::Instruction* typeInst = get_def_use_mgr()->GetDef(typeId); + Instruction* typeInst = get_def_use_mgr()->GetDef(typeId); if (!typeInst || (typeInst->opcode() != SpvOpTypeInt)) return false; // TODO(greg-lunarg): Support non-32 bit ints if (typeInst->GetSingleWordInOperand(0) != 32) return false; @@ -72,28 +72,28 @@ bool DeadBranchElimPass::GetConstInteger(uint32_t selId, uint32_t* selVal) { return false; } -void DeadBranchElimPass::AddBranch(uint32_t labelId, opt::BasicBlock* bp) { +void DeadBranchElimPass::AddBranch(uint32_t labelId, BasicBlock* bp) { assert(get_def_use_mgr()->GetDef(labelId) != nullptr); - std::unique_ptr<opt::Instruction> newBranch(new opt::Instruction( - context(), SpvOpBranch, 0, 0, - {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {labelId}}})); + std::unique_ptr<Instruction> newBranch( + new Instruction(context(), SpvOpBranch, 0, 0, + {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {labelId}}})); context()->AnalyzeDefUse(&*newBranch); context()->set_instr_block(&*newBranch, bp); bp->AddInstruction(std::move(newBranch)); } -opt::BasicBlock* DeadBranchElimPass::GetParentBlock(uint32_t id) { +BasicBlock* DeadBranchElimPass::GetParentBlock(uint32_t id) { return context()->get_instr_block(get_def_use_mgr()->GetDef(id)); } bool DeadBranchElimPass::MarkLiveBlocks( - opt::Function* func, std::unordered_set<opt::BasicBlock*>* live_blocks) { - std::unordered_set<opt::BasicBlock*> continues; - std::vector<opt::BasicBlock*> stack; + Function* func, std::unordered_set<BasicBlock*>* live_blocks) { + std::unordered_set<BasicBlock*> continues; + std::vector<BasicBlock*> stack; stack.push_back(&*func->begin()); bool modified = false; while (!stack.empty()) { - opt::BasicBlock* block = stack.back(); + BasicBlock* block = stack.back(); stack.pop_back(); // Live blocks doubles as visited set. @@ -102,7 +102,7 @@ bool DeadBranchElimPass::MarkLiveBlocks( uint32_t cont_id = block->ContinueBlockIdIfAny(); if (cont_id != 0) continues.insert(GetParentBlock(cont_id)); - opt::Instruction* terminator = block->terminator(); + Instruction* terminator = block->terminator(); uint32_t live_lab_id = 0; // Check if the terminator has a single valid successor. if (terminator->opcode() == SpvOpBranchConditional) { @@ -153,7 +153,7 @@ bool DeadBranchElimPass::MarkLiveBlocks( // Remove the merge instruction if it is a selection merge. AddBranch(live_lab_id, block); context()->KillInst(terminator); - opt::Instruction* mergeInst = block->GetMergeInst(); + Instruction* mergeInst = block->GetMergeInst(); if (mergeInst && mergeInst->opcode() == SpvOpSelectionMerge) { context()->KillInst(mergeInst); } @@ -171,18 +171,17 @@ bool DeadBranchElimPass::MarkLiveBlocks( } void DeadBranchElimPass::MarkUnreachableStructuredTargets( - const std::unordered_set<opt::BasicBlock*>& live_blocks, - std::unordered_set<opt::BasicBlock*>* unreachable_merges, - std::unordered_map<opt::BasicBlock*, opt::BasicBlock*>* - unreachable_continues) { + const std::unordered_set<BasicBlock*>& live_blocks, + std::unordered_set<BasicBlock*>* unreachable_merges, + std::unordered_map<BasicBlock*, BasicBlock*>* unreachable_continues) { for (auto block : live_blocks) { if (auto merge_id = block->MergeBlockIdIfAny()) { - opt::BasicBlock* merge_block = GetParentBlock(merge_id); + BasicBlock* merge_block = GetParentBlock(merge_id); if (!live_blocks.count(merge_block)) { unreachable_merges->insert(merge_block); } if (auto cont_id = block->ContinueBlockIdIfAny()) { - opt::BasicBlock* cont_block = GetParentBlock(cont_id); + BasicBlock* cont_block = GetParentBlock(cont_id); if (!live_blocks.count(cont_block)) { (*unreachable_continues)[cont_block] = block; } @@ -192,10 +191,8 @@ void DeadBranchElimPass::MarkUnreachableStructuredTargets( } bool DeadBranchElimPass::FixPhiNodesInLiveBlocks( - opt::Function* func, - const std::unordered_set<opt::BasicBlock*>& live_blocks, - const std::unordered_map<opt::BasicBlock*, opt::BasicBlock*>& - unreachable_continues) { + Function* func, const std::unordered_set<BasicBlock*>& live_blocks, + const std::unordered_map<BasicBlock*, BasicBlock*>& unreachable_continues) { bool modified = false; for (auto& block : *func) { if (live_blocks.count(&block)) { @@ -206,8 +203,8 @@ bool DeadBranchElimPass::FixPhiNodesInLiveBlocks( bool changed = false; bool backedge_added = false; - opt::Instruction* inst = &*iter; - std::vector<opt::Operand> operands; + Instruction* inst = &*iter; + std::vector<Operand> operands; // Build a complete set of operands (not just input operands). Start // with type and result id operands. operands.push_back(inst->GetOperand(0u)); @@ -220,8 +217,7 @@ bool DeadBranchElimPass::FixPhiNodesInLiveBlocks( // However, if there is only one other incoming edge, the OpPhi can be // eliminated. for (uint32_t i = 1; i < inst->NumInOperands(); i += 2) { - opt::BasicBlock* inc = - GetParentBlock(inst->GetSingleWordInOperand(i)); + BasicBlock* inc = GetParentBlock(inst->GetSingleWordInOperand(i)); auto cont_iter = unreachable_continues.find(inc); if (cont_iter != unreachable_continues.end() && cont_iter->second == &block && inst->NumInOperands() > 4) { @@ -304,11 +300,9 @@ bool DeadBranchElimPass::FixPhiNodesInLiveBlocks( } bool DeadBranchElimPass::EraseDeadBlocks( - opt::Function* func, - const std::unordered_set<opt::BasicBlock*>& live_blocks, - const std::unordered_set<opt::BasicBlock*>& unreachable_merges, - const std::unordered_map<opt::BasicBlock*, opt::BasicBlock*>& - unreachable_continues) { + Function* func, const std::unordered_set<BasicBlock*>& live_blocks, + const std::unordered_set<BasicBlock*>& unreachable_merges, + const std::unordered_map<BasicBlock*, BasicBlock*>& unreachable_continues) { bool modified = false; for (auto ebi = func->begin(); ebi != func->end();) { if (unreachable_merges.count(&*ebi)) { @@ -317,9 +311,9 @@ bool DeadBranchElimPass::EraseDeadBlocks( // Make unreachable, but leave the label. KillAllInsts(&*ebi, false); // Add unreachable terminator. - ebi->AddInstruction(MakeUnique<opt::Instruction>( - context(), SpvOpUnreachable, 0, 0, - std::initializer_list<opt::Operand>{})); + ebi->AddInstruction( + MakeUnique<Instruction>(context(), SpvOpUnreachable, 0, 0, + std::initializer_list<Operand>{})); context()->set_instr_block(&*ebi->tail(), &*ebi); modified = true; } @@ -333,10 +327,9 @@ bool DeadBranchElimPass::EraseDeadBlocks( KillAllInsts(&*ebi, false); // Add unconditional branch to header. assert(unreachable_continues.count(&*ebi)); - ebi->AddInstruction(MakeUnique<opt::Instruction>( + ebi->AddInstruction(MakeUnique<Instruction>( context(), SpvOpBranch, 0, 0, - std::initializer_list<opt::Operand>{ - {SPV_OPERAND_TYPE_ID, {cont_id}}})); + std::initializer_list<Operand>{{SPV_OPERAND_TYPE_ID, {cont_id}}})); get_def_use_mgr()->AnalyzeInstUse(&*ebi->tail()); context()->set_instr_block(&*ebi->tail(), &*ebi); modified = true; @@ -355,13 +348,13 @@ bool DeadBranchElimPass::EraseDeadBlocks( return modified; } -bool DeadBranchElimPass::EliminateDeadBranches(opt::Function* func) { +bool DeadBranchElimPass::EliminateDeadBranches(Function* func) { bool modified = false; - std::unordered_set<opt::BasicBlock*> live_blocks; + std::unordered_set<BasicBlock*> live_blocks; modified |= MarkLiveBlocks(func, &live_blocks); - std::unordered_set<opt::BasicBlock*> unreachable_merges; - std::unordered_map<opt::BasicBlock*, opt::BasicBlock*> unreachable_continues; + std::unordered_set<BasicBlock*> unreachable_merges; + std::unordered_map<BasicBlock*, BasicBlock*> unreachable_continues; MarkUnreachableStructuredTargets(live_blocks, &unreachable_merges, &unreachable_continues); modified |= FixPhiNodesInLiveBlocks(func, live_blocks, unreachable_continues); @@ -378,7 +371,7 @@ Pass::Status DeadBranchElimPass::Process() { for (auto& ai : get_module()->annotations()) if (ai.opcode() == SpvOpGroupDecorate) return Status::SuccessWithoutChange; // Process all entry point functions - ProcessFunction pfn = [this](opt::Function* fp) { + ProcessFunction pfn = [this](Function* fp) { return EliminateDeadBranches(fp); }; bool modified = ProcessReachableCallTree(pfn, context()); diff --git a/source/opt/dead_branch_elim_pass.h b/source/opt/dead_branch_elim_pass.h index 91961a97..a54e8ae2 100644 --- a/source/opt/dead_branch_elim_pass.h +++ b/source/opt/dead_branch_elim_pass.h @@ -34,7 +34,7 @@ namespace opt { // See optimizer.hpp for documentation. class DeadBranchElimPass : public MemPass { - using cbb_ptr = const opt::BasicBlock*; + using cbb_ptr = const BasicBlock*; public: DeadBranchElimPass() = default; @@ -42,9 +42,8 @@ class DeadBranchElimPass : public MemPass { const char* name() const override { return "eliminate-dead-branches"; } Status Process() override; - opt::IRContext::Analysis GetPreservedAnalyses() override { - return opt::IRContext::kAnalysisDefUse | - opt::IRContext::kAnalysisInstrToBlockMapping; + IRContext::Analysis GetPreservedAnalyses() override { + return IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping; } private: @@ -57,7 +56,7 @@ class DeadBranchElimPass : public MemPass { bool GetConstInteger(uint32_t valId, uint32_t* value); // Add branch to |labelId| to end of block |bp|. - void AddBranch(uint32_t labelId, opt::BasicBlock* bp); + void AddBranch(uint32_t labelId, BasicBlock* bp); // For function |func|, look for BranchConditionals with constant condition // and convert to a Branch to the indicated label. Delete resulting dead @@ -65,21 +64,21 @@ class DeadBranchElimPass : public MemPass { // invalid control flow. // TODO(greg-lunarg): Remove remaining constant conditional branches and dead // blocks. - bool EliminateDeadBranches(opt::Function* func); + bool EliminateDeadBranches(Function* func); // Returns the basic block containing |id|. // Note: this pass only requires correct instruction block mappings for the // input. This pass does not preserve the block mapping, so it is not kept // up-to-date during processing. - opt::BasicBlock* GetParentBlock(uint32_t id); + BasicBlock* GetParentBlock(uint32_t id); // Marks live blocks reachable from the entry of |func|. Simplifies constant // branches and switches as it proceeds, to limit the number of live blocks. // It is careful not to eliminate backedges even if they are dead, but the // header is live. Likewise, unreachable merge blocks named in live merge // instruction must be retained (though they may be clobbered). - bool MarkLiveBlocks(opt::Function* func, - std::unordered_set<opt::BasicBlock*>* live_blocks); + bool MarkLiveBlocks(Function* func, + std::unordered_set<BasicBlock*>* live_blocks); // Checks for unreachable merge and continue blocks with live headers; those // blocks must be retained. Continues are tracked separately so that a live @@ -89,10 +88,9 @@ class DeadBranchElimPass : public MemPass { // |unreachable_continues| maps the id of an unreachable continue target to // the header block that declares it. void MarkUnreachableStructuredTargets( - const std::unordered_set<opt::BasicBlock*>& live_blocks, - std::unordered_set<opt::BasicBlock*>* unreachable_merges, - std::unordered_map<opt::BasicBlock*, opt::BasicBlock*>* - unreachable_continues); + const std::unordered_set<BasicBlock*>& live_blocks, + std::unordered_set<BasicBlock*>* unreachable_merges, + std::unordered_map<BasicBlock*, BasicBlock*>* unreachable_continues); // Fix phis in reachable blocks so that only live (or unremovable) incoming // edges are present. If the block now only has a single live incoming edge, @@ -107,9 +105,8 @@ class DeadBranchElimPass : public MemPass { // |unreachable_continues| maps continue targets that cannot be reached to // merge instruction that declares them. bool FixPhiNodesInLiveBlocks( - opt::Function* func, - const std::unordered_set<opt::BasicBlock*>& live_blocks, - const std::unordered_map<opt::BasicBlock*, opt::BasicBlock*>& + Function* func, const std::unordered_set<BasicBlock*>& live_blocks, + const std::unordered_map<BasicBlock*, BasicBlock*>& unreachable_continues); // Erases dead blocks. Any block captured in |unreachable_merges| or @@ -124,10 +121,9 @@ class DeadBranchElimPass : public MemPass { // |unreachable_continues| maps continue targets that cannot be reached to // corresponding header block that declares them. bool EraseDeadBlocks( - opt::Function* func, - const std::unordered_set<opt::BasicBlock*>& live_blocks, - const std::unordered_set<opt::BasicBlock*>& unreachable_merges, - const std::unordered_map<opt::BasicBlock*, opt::BasicBlock*>& + Function* func, const std::unordered_set<BasicBlock*>& live_blocks, + const std::unordered_set<BasicBlock*>& unreachable_merges, + const std::unordered_map<BasicBlock*, BasicBlock*>& unreachable_continues); }; diff --git a/source/opt/dead_insert_elim_pass.cpp b/source/opt/dead_insert_elim_pass.cpp index 80a7db3b..53bdad4e 100644 --- a/source/opt/dead_insert_elim_pass.cpp +++ b/source/opt/dead_insert_elim_pass.cpp @@ -38,7 +38,7 @@ const uint32_t kInsertCompositeIdInIdx = 1; } // anonymous namespace -uint32_t DeadInsertElimPass::NumComponents(opt::Instruction* typeInst) { +uint32_t DeadInsertElimPass::NumComponents(Instruction* typeInst) { switch (typeInst->opcode()) { case SpvOpTypeVector: { return typeInst->GetSingleWordInOperand(kTypeVectorCountInIdx); @@ -49,10 +49,10 @@ uint32_t DeadInsertElimPass::NumComponents(opt::Instruction* typeInst) { case SpvOpTypeArray: { uint32_t lenId = typeInst->GetSingleWordInOperand(kTypeArrayLengthIdInIdx); - opt::Instruction* lenInst = get_def_use_mgr()->GetDef(lenId); + Instruction* lenInst = get_def_use_mgr()->GetDef(lenId); if (lenInst->opcode() != SpvOpConstant) return 0; uint32_t lenTypeId = lenInst->type_id(); - opt::Instruction* lenTypeInst = get_def_use_mgr()->GetDef(lenTypeId); + Instruction* lenTypeInst = get_def_use_mgr()->GetDef(lenTypeId); // TODO(greg-lunarg): Support non-32-bit array length if (lenTypeInst->GetSingleWordInOperand(kTypeIntWidthInIdx) != 32) return 0; @@ -66,11 +66,10 @@ uint32_t DeadInsertElimPass::NumComponents(opt::Instruction* typeInst) { } void DeadInsertElimPass::MarkInsertChain( - opt::Instruction* insertChain, std::vector<uint32_t>* pExtIndices, + Instruction* insertChain, std::vector<uint32_t>* pExtIndices, uint32_t extOffset, std::unordered_set<uint32_t>* visited_phis) { // Not currently optimizing array inserts. - opt::Instruction* typeInst = - get_def_use_mgr()->GetDef(insertChain->type_id()); + Instruction* typeInst = get_def_use_mgr()->GetDef(insertChain->type_id()); if (typeInst->opcode() == SpvOpTypeArray) return; // Insert chains are only composed of inserts and phis if (insertChain->opcode() != SpvOpCompositeInsert && @@ -91,7 +90,7 @@ void DeadInsertElimPass::MarkInsertChain( return; } } - opt::Instruction* insInst = insertChain; + Instruction* insInst = insertChain; while (insInst->opcode() == SpvOpCompositeInsert) { // If no extract indices, mark insert and inserted object (which might // also be an insert chain) and continue up the chain though the input @@ -157,12 +156,12 @@ void DeadInsertElimPass::MarkInsertChain( std::sort(ids.begin(), ids.end()); auto new_end = std::unique(ids.begin(), ids.end()); for (auto id_iter = ids.begin(); id_iter != new_end; ++id_iter) { - opt::Instruction* pi = get_def_use_mgr()->GetDef(*id_iter); + Instruction* pi = get_def_use_mgr()->GetDef(*id_iter); MarkInsertChain(pi, pExtIndices, extOffset, visited_phis); } } -bool DeadInsertElimPass::EliminateDeadInserts(opt::Function* func) { +bool DeadInsertElimPass::EliminateDeadInserts(Function* func) { bool modified = false; bool lastmodified = true; // Each pass can delete dead instructions, thus potentially revealing @@ -174,7 +173,7 @@ bool DeadInsertElimPass::EliminateDeadInserts(opt::Function* func) { return modified; } -bool DeadInsertElimPass::EliminateDeadInsertsOnePass(opt::Function* func) { +bool DeadInsertElimPass::EliminateDeadInsertsOnePass(Function* func) { bool modified = false; liveInserts_.clear(); visitedPhis_.clear(); @@ -183,7 +182,7 @@ bool DeadInsertElimPass::EliminateDeadInsertsOnePass(opt::Function* func) { for (auto ii = bi->begin(); ii != bi->end(); ++ii) { // Only process Inserts and composite Phis SpvOp op = ii->opcode(); - opt::Instruction* typeInst = get_def_use_mgr()->GetDef(ii->type_id()); + Instruction* typeInst = get_def_use_mgr()->GetDef(ii->type_id()); if (op != SpvOpCompositeInsert && (op != SpvOpPhi || !spvOpcodeIsComposite(typeInst->opcode()))) continue; @@ -198,7 +197,7 @@ bool DeadInsertElimPass::EliminateDeadInsertsOnePass(opt::Function* func) { } } const uint32_t id = ii->result_id(); - get_def_use_mgr()->ForEachUser(id, [&ii, this](opt::Instruction* user) { + get_def_use_mgr()->ForEachUser(id, [&ii, this](Instruction* user) { switch (user->opcode()) { case SpvOpCompositeInsert: case SpvOpPhi: @@ -225,7 +224,7 @@ bool DeadInsertElimPass::EliminateDeadInsertsOnePass(opt::Function* func) { } } // Find and disconnect dead inserts - std::vector<opt::Instruction*> dead_instructions; + std::vector<Instruction*> dead_instructions; for (auto bi = func->begin(); bi != func->end(); ++bi) { for (auto ii = bi->begin(); ii != bi->end(); ++ii) { if (ii->opcode() != SpvOpCompositeInsert) continue; @@ -240,9 +239,9 @@ bool DeadInsertElimPass::EliminateDeadInsertsOnePass(opt::Function* func) { } // DCE dead inserts while (!dead_instructions.empty()) { - opt::Instruction* inst = dead_instructions.back(); + Instruction* inst = dead_instructions.back(); dead_instructions.pop_back(); - DCEInst(inst, [&dead_instructions](opt::Instruction* other_inst) { + DCEInst(inst, [&dead_instructions](Instruction* other_inst) { auto i = std::find(dead_instructions.begin(), dead_instructions.end(), other_inst); if (i != dead_instructions.end()) { @@ -255,7 +254,7 @@ bool DeadInsertElimPass::EliminateDeadInsertsOnePass(opt::Function* func) { Pass::Status DeadInsertElimPass::Process() { // Process all entry point functions. - ProcessFunction pfn = [this](opt::Function* fp) { + ProcessFunction pfn = [this](Function* fp) { return EliminateDeadInserts(fp); }; bool modified = ProcessEntryPointCallTree(pfn, get_module()); diff --git a/source/opt/dead_insert_elim_pass.h b/source/opt/dead_insert_elim_pass.h index 6f4204aa..aef44906 100644 --- a/source/opt/dead_insert_elim_pass.h +++ b/source/opt/dead_insert_elim_pass.h @@ -39,39 +39,38 @@ class DeadInsertElimPass : public MemPass { const char* name() const override { return "eliminate-dead-inserts"; } Status Process() override; - opt::IRContext::Analysis GetPreservedAnalyses() override { - return opt::IRContext::kAnalysisDefUse | - opt::IRContext::kAnalysisInstrToBlockMapping | - opt::IRContext::kAnalysisDecorations | - opt::IRContext::kAnalysisCombinators | opt::IRContext::kAnalysisCFG | - opt::IRContext::kAnalysisDominatorAnalysis | - opt::IRContext::kAnalysisNameMap; + IRContext::Analysis GetPreservedAnalyses() override { + return IRContext::kAnalysisDefUse | + IRContext::kAnalysisInstrToBlockMapping | + IRContext::kAnalysisDecorations | IRContext::kAnalysisCombinators | + IRContext::kAnalysisCFG | IRContext::kAnalysisDominatorAnalysis | + IRContext::kAnalysisNameMap; } private: // Return the number of subcomponents in the composite type |typeId|. // Return 0 if not a composite type or number of components is not a // 32-bit constant. - uint32_t NumComponents(opt::Instruction* typeInst); + uint32_t NumComponents(Instruction* typeInst); // Mark all inserts in instruction chain ending at |insertChain| with // indices that intersect with extract indices |extIndices| starting with // index at |extOffset|. Chains are composed solely of Inserts and Phis. // Mark all inserts in chain if |extIndices| is nullptr. - void MarkInsertChain(opt::Instruction* insertChain, + void MarkInsertChain(Instruction* insertChain, std::vector<uint32_t>* extIndices, uint32_t extOffset, std::unordered_set<uint32_t>* visited_phis); // Perform EliminateDeadInsertsOnePass(|func|) until no modification is // made. Return true if modified. - bool EliminateDeadInserts(opt::Function* func); + bool EliminateDeadInserts(Function* func); // DCE all dead struct, matrix and vector inserts in |func|. An insert is // dead if the value it inserts is never used. Replace any reference to the // insert with its original composite. Return true if modified. Dead inserts // in dependence cycles are not currently eliminated. Dead inserts into // arrays are not currently eliminated. - bool EliminateDeadInsertsOnePass(opt::Function* func); + bool EliminateDeadInsertsOnePass(Function* func); // Return true if all extensions in this module are allowed by this pass. bool AllExtensionsSupported() const; diff --git a/source/opt/dead_variable_elimination.cpp b/source/opt/dead_variable_elimination.cpp index b9ba966e..bdd97083 100644 --- a/source/opt/dead_variable_elimination.cpp +++ b/source/opt/dead_variable_elimination.cpp @@ -42,7 +42,7 @@ Pass::Status DeadVariableElimination::Process() { // else, so we must keep the variable around. get_decoration_mgr()->ForEachDecoration( result_id, SpvDecorationLinkageAttributes, - [&count](const opt::Instruction& linkage_instruction) { + [&count](const Instruction& linkage_instruction) { uint32_t last_operand = linkage_instruction.NumOperands() - 1; if (linkage_instruction.GetSingleWordOperand(last_operand) == SpvLinkageTypeExport) { @@ -54,13 +54,11 @@ Pass::Status DeadVariableElimination::Process() { // If we don't have to keep the instruction for other reasons, then look // at the uses and count the number of real references. count = 0; - get_def_use_mgr()->ForEachUser( - result_id, [&count](opt::Instruction* user) { - if (!opt::IsAnnotationInst(user->opcode()) && - user->opcode() != SpvOpName) { - ++count; - } - }); + get_def_use_mgr()->ForEachUser(result_id, [&count](Instruction* user) { + if (!IsAnnotationInst(user->opcode()) && user->opcode() != SpvOpName) { + ++count; + } + }); } reference_count_[result_id] = count; if (count == 0) { @@ -80,14 +78,14 @@ Pass::Status DeadVariableElimination::Process() { } void DeadVariableElimination::DeleteVariable(uint32_t result_id) { - opt::Instruction* inst = get_def_use_mgr()->GetDef(result_id); + Instruction* inst = get_def_use_mgr()->GetDef(result_id); assert(inst->opcode() == SpvOpVariable && "Should not be trying to delete anything other than an OpVariable."); // Look for an initializer that references another variable. We need to know // if that variable can be deleted after the reference is removed. if (inst->NumOperands() == 4) { - opt::Instruction* initializer = + Instruction* initializer = get_def_use_mgr()->GetDef(inst->GetSingleWordOperand(3)); // TODO: Handle OpSpecConstantOP which might be defined in terms of other diff --git a/source/opt/dead_variable_elimination.h b/source/opt/dead_variable_elimination.h index be8975bb..dc8d76ec 100644 --- a/source/opt/dead_variable_elimination.h +++ b/source/opt/dead_variable_elimination.h @@ -29,8 +29,8 @@ class DeadVariableElimination : public MemPass { const char* name() const override { return "dead-variable-elimination"; } Status Process() override; - opt::IRContext::Analysis GetPreservedAnalyses() override { - return opt::IRContext::kAnalysisDefUse; + IRContext::Analysis GetPreservedAnalyses() override { + return IRContext::kAnalysisDefUse; } private: diff --git a/source/opt/decoration_manager.cpp b/source/opt/decoration_manager.cpp index 9078c9f0..f218e149 100644 --- a/source/opt/decoration_manager.cpp +++ b/source/opt/decoration_manager.cpp @@ -25,35 +25,35 @@ namespace opt { namespace analysis { void DecorationManager::RemoveDecorationsFrom( - uint32_t id, std::function<bool(const opt::Instruction&)> pred) { + uint32_t id, std::function<bool(const Instruction&)> pred) { const auto ids_iter = id_to_decoration_insts_.find(id); if (ids_iter == id_to_decoration_insts_.end()) return; TargetData& decorations_info = ids_iter->second; auto context = module_->context(); - std::vector<opt::Instruction*> insts_to_kill; + std::vector<Instruction*> insts_to_kill; const bool is_group = !decorations_info.decorate_insts.empty(); // Schedule all direct decorations for removal if instructed as such by // |pred|. - for (opt::Instruction* inst : decorations_info.direct_decorations) + for (Instruction* inst : decorations_info.direct_decorations) if (pred(*inst)) insts_to_kill.push_back(inst); // For all groups being directly applied to |id|, remove |id| (and the // literal if |inst| is an OpGroupMemberDecorate) from the instruction // applying the group. - std::unordered_set<const opt::Instruction*> indirect_decorations_to_remove; - for (opt::Instruction* inst : decorations_info.indirect_decorations) { + std::unordered_set<const Instruction*> indirect_decorations_to_remove; + for (Instruction* inst : decorations_info.indirect_decorations) { assert(inst->opcode() == SpvOpGroupDecorate || inst->opcode() == SpvOpGroupMemberDecorate); - std::vector<opt::Instruction*> group_decorations_to_keep; + std::vector<Instruction*> group_decorations_to_keep; const uint32_t group_id = inst->GetSingleWordInOperand(0u); const auto group_iter = id_to_decoration_insts_.find(group_id); assert(group_iter != id_to_decoration_insts_.end() && "Unknown decoration group"); const auto& group_decorations = group_iter->second.direct_decorations; - for (opt::Instruction* decoration : group_decorations) { + for (Instruction* decoration : group_decorations) { if (!pred(*decoration)) group_decorations_to_keep.push_back(decoration); } @@ -97,9 +97,9 @@ void DecorationManager::RemoveDecorationsFrom( // If only some of the decorations should be kept, clone them and apply // them directly to |id|. if (!group_decorations_to_keep.empty()) { - for (opt::Instruction* decoration : group_decorations_to_keep) { + for (Instruction* decoration : group_decorations_to_keep) { // simply clone decoration and change |group_id| to |id| - std::unique_ptr<opt::Instruction> new_inst( + std::unique_ptr<Instruction> new_inst( decoration->Clone(module_->context())); new_inst->SetInOperand(0, {id}); module_->AddAnnotationInst(std::move(new_inst)); @@ -113,22 +113,22 @@ void DecorationManager::RemoveDecorationsFrom( indirect_decorations.erase( std::remove_if( indirect_decorations.begin(), indirect_decorations.end(), - [&indirect_decorations_to_remove](const opt::Instruction* inst) { + [&indirect_decorations_to_remove](const Instruction* inst) { return indirect_decorations_to_remove.count(inst); }), indirect_decorations.end()); - for (opt::Instruction* inst : insts_to_kill) context->KillInst(inst); + for (Instruction* inst : insts_to_kill) context->KillInst(inst); insts_to_kill.clear(); // Schedule all instructions applying the group for removal if this group no // longer applies decorations, either directly or indirectly. if (is_group && decorations_info.direct_decorations.empty() && decorations_info.indirect_decorations.empty()) { - for (opt::Instruction* inst : decorations_info.decorate_insts) + for (Instruction* inst : decorations_info.decorate_insts) insts_to_kill.push_back(inst); } - for (opt::Instruction* inst : insts_to_kill) context->KillInst(inst); + for (Instruction* inst : insts_to_kill) context->KillInst(inst); if (decorations_info.direct_decorations.empty() && decorations_info.indirect_decorations.empty() && @@ -140,20 +140,20 @@ void DecorationManager::RemoveDecorationsFrom( } } -std::vector<opt::Instruction*> DecorationManager::GetDecorationsFor( +std::vector<Instruction*> DecorationManager::GetDecorationsFor( uint32_t id, bool include_linkage) { - return InternalGetDecorationsFor<opt::Instruction*>(id, include_linkage); + return InternalGetDecorationsFor<Instruction*>(id, include_linkage); } -std::vector<const opt::Instruction*> DecorationManager::GetDecorationsFor( +std::vector<const Instruction*> DecorationManager::GetDecorationsFor( uint32_t id, bool include_linkage) const { return const_cast<DecorationManager*>(this) - ->InternalGetDecorationsFor<const opt::Instruction*>(id, include_linkage); + ->InternalGetDecorationsFor<const Instruction*>(id, include_linkage); } bool DecorationManager::HaveTheSameDecorations(uint32_t id1, uint32_t id2) const { - using InstructionList = std::vector<const opt::Instruction*>; + using InstructionList = std::vector<const Instruction*>; using DecorationSet = std::set<std::u32string>; const InstructionList decorations_for1 = GetDecorationsFor(id1, false); @@ -167,7 +167,7 @@ bool DecorationManager::HaveTheSameDecorations(uint32_t id1, [](const InstructionList& decoration_list, DecorationSet* decorate_set, DecorationSet* decorate_id_set, DecorationSet* decorate_string_set, DecorationSet* member_decorate_set) { - for (const opt::Instruction* inst : decoration_list) { + for (const Instruction* inst : decoration_list) { std::u32string decoration_payload; // Ignore the opcode and the target as we do not want them to be // compared. @@ -223,8 +223,8 @@ bool DecorationManager::HaveTheSameDecorations(uint32_t id1, // TODO(pierremoreau): If OpDecorateId is referencing an OpConstant, one could // check that the constants are the same rather than just // looking at the constant ID. -bool DecorationManager::AreDecorationsTheSame(const opt::Instruction* inst1, - const opt::Instruction* inst2, +bool DecorationManager::AreDecorationsTheSame(const Instruction* inst1, + const Instruction* inst2, bool ignore_target) const { switch (inst1->opcode()) { case SpvOpDecorate: @@ -250,11 +250,11 @@ void DecorationManager::AnalyzeDecorations() { if (!module_) return; // For each group and instruction, collect all their decoration instructions. - for (opt::Instruction& inst : module_->annotations()) { + for (Instruction& inst : module_->annotations()) { AddDecoration(&inst); } } -void DecorationManager::AddDecoration(opt::Instruction* inst) { +void DecorationManager::AddDecoration(Instruction* inst) { switch (inst->opcode()) { case SpvOpDecorate: case SpvOpDecorateId: @@ -295,8 +295,8 @@ std::vector<T> DecorationManager::InternalGetDecorationsFor( const auto process_direct_decorations = [include_linkage, - &decorations](const std::vector<opt::Instruction*>& direct_decorations) { - for (opt::Instruction* inst : direct_decorations) { + &decorations](const std::vector<Instruction*>& direct_decorations) { + for (Instruction* inst : direct_decorations) { const bool is_linkage = inst->opcode() == SpvOpDecorate && inst->GetSingleWordInOperand(1u) == SpvDecorationLinkageAttributes; @@ -308,7 +308,7 @@ std::vector<T> DecorationManager::InternalGetDecorationsFor( process_direct_decorations(ids_iter->second.direct_decorations); // Process the decorations of all groups applied to |id|. - for (const opt::Instruction* inst : target_data.indirect_decorations) { + for (const Instruction* inst : target_data.indirect_decorations) { const uint32_t group_id = inst->GetSingleWordInOperand(0u); const auto group_iter = id_to_decoration_insts_.find(group_id); assert(group_iter != id_to_decoration_insts_.end() && "Unknown group ID"); @@ -320,8 +320,8 @@ std::vector<T> DecorationManager::InternalGetDecorationsFor( bool DecorationManager::WhileEachDecoration( uint32_t id, uint32_t decoration, - std::function<bool(const opt::Instruction&)> f) { - for (const opt::Instruction* inst : GetDecorationsFor(id, true)) { + std::function<bool(const Instruction&)> f) { + for (const Instruction* inst : GetDecorationsFor(id, true)) { switch (inst->opcode()) { case SpvOpMemberDecorate: if (inst->GetSingleWordInOperand(2) == decoration) { @@ -344,8 +344,8 @@ bool DecorationManager::WhileEachDecoration( void DecorationManager::ForEachDecoration( uint32_t id, uint32_t decoration, - std::function<void(const opt::Instruction&)> f) { - WhileEachDecoration(id, decoration, [&f](const opt::Instruction& inst) { + std::function<void(const Instruction&)> f) { + WhileEachDecoration(id, decoration, [&f](const Instruction& inst) { f(inst); return true; }); @@ -355,9 +355,9 @@ void DecorationManager::CloneDecorations(uint32_t from, uint32_t to) { const auto decoration_list = id_to_decoration_insts_.find(from); if (decoration_list == id_to_decoration_insts_.end()) return; auto context = module_->context(); - for (opt::Instruction* inst : decoration_list->second.direct_decorations) { + for (Instruction* inst : decoration_list->second.direct_decorations) { // simply clone decoration and change |target-id| to |to| - std::unique_ptr<opt::Instruction> new_inst(inst->Clone(module_->context())); + std::unique_ptr<Instruction> new_inst(inst->Clone(module_->context())); new_inst->SetInOperand(0, {to}); module_->AddAnnotationInst(std::move(new_inst)); auto decoration_iter = --module_->annotation_end(); @@ -365,15 +365,15 @@ void DecorationManager::CloneDecorations(uint32_t from, uint32_t to) { } // We need to copy the list of instructions as ForgetUses and AnalyzeUses are // going to modify it. - std::vector<opt::Instruction*> indirect_decorations = + std::vector<Instruction*> indirect_decorations = decoration_list->second.indirect_decorations; - for (opt::Instruction* inst : indirect_decorations) { + for (Instruction* inst : indirect_decorations) { switch (inst->opcode()) { case SpvOpGroupDecorate: context->ForgetUses(inst); // add |to| to list of decorated id's inst->AddOperand( - opt::Operand(spv_operand_type_t::SPV_OPERAND_TYPE_ID, {to})); + Operand(spv_operand_type_t::SPV_OPERAND_TYPE_ID, {to})); context->AnalyzeUses(inst); break; case SpvOpGroupMemberDecorate: { @@ -381,10 +381,10 @@ void DecorationManager::CloneDecorations(uint32_t from, uint32_t to) { // for each (id == from), add (to, literal) as operands const uint32_t num_operands = inst->NumOperands(); for (uint32_t i = 1; i < num_operands; i += 2) { - opt::Operand op = inst->GetOperand(i); + Operand op = inst->GetOperand(i); if (op.words[0] == from) { // add new pair of operands: (to, literal) inst->AddOperand( - opt::Operand(spv_operand_type_t::SPV_OPERAND_TYPE_ID, {to})); + Operand(spv_operand_type_t::SPV_OPERAND_TYPE_ID, {to})); op = inst->GetOperand(i + 1); inst->AddOperand(std::move(op)); } @@ -398,8 +398,8 @@ void DecorationManager::CloneDecorations(uint32_t from, uint32_t to) { } } -void DecorationManager::RemoveDecoration(opt::Instruction* inst) { - const auto remove_from_container = [inst](std::vector<opt::Instruction*>& v) { +void DecorationManager::RemoveDecoration(Instruction* inst) { + const auto remove_from_container = [inst](std::vector<Instruction*>& v) { v.erase(std::remove(v.begin(), v.end(), inst), v.end()); }; diff --git a/source/opt/decoration_manager.h b/source/opt/decoration_manager.h index 3ecda8f7..11182001 100644 --- a/source/opt/decoration_manager.h +++ b/source/opt/decoration_manager.h @@ -27,11 +27,11 @@ namespace spvtools { namespace opt { namespace analysis { -// A class for analyzing and managing decorations in an opt::Module. +// A class for analyzing and managing decorations in an Module. class DecorationManager { public: // Constructs a decoration manager from the given |module| - explicit DecorationManager(opt::Module* module) : module_(module) { + explicit DecorationManager(Module* module) : module_(module) { AnalyzeDecorations(); } DecorationManager() = delete; @@ -42,23 +42,23 @@ class DecorationManager { // removed if they have no targets left, and OpDecorationGroup will be // removed if the group is not applied to anyone and contains no decorations. void RemoveDecorationsFrom(uint32_t id, - std::function<bool(const opt::Instruction&)> pred = - [](const opt::Instruction&) { return true; }); + std::function<bool(const Instruction&)> pred = + [](const Instruction&) { return true; }); // Removes all decorations from the result id of |inst|. // // NOTE: This is only meant to be called from ir_context, as only metadata // will be removed, and no actual instruction. - void RemoveDecoration(opt::Instruction* inst); + void RemoveDecoration(Instruction* inst); // Returns a vector of all decorations affecting |id|. If a group is applied // to |id|, the decorations of that group are returned rather than the group // decoration instruction. If |include_linkage| is not set, linkage // decorations won't be returned. - std::vector<opt::Instruction*> GetDecorationsFor(uint32_t id, - bool include_linkage); - std::vector<const opt::Instruction*> GetDecorationsFor( - uint32_t id, bool include_linkage) const; + std::vector<Instruction*> GetDecorationsFor(uint32_t id, + bool include_linkage); + std::vector<const Instruction*> GetDecorationsFor(uint32_t id, + bool include_linkage) const; // Returns whether two IDs have the same decorations. Two SpvOpGroupDecorate // instructions that apply the same decorations but to different IDs, still // count as being the same. @@ -69,22 +69,21 @@ class DecorationManager { // // This is only valid for OpDecorate, OpMemberDecorate and OpDecorateId; it // will return false for other opcodes. - bool AreDecorationsTheSame(const opt::Instruction* inst1, - const opt::Instruction* inst2, + bool AreDecorationsTheSame(const Instruction* inst1, const Instruction* inst2, bool ignore_target) const; // |f| is run on each decoration instruction for |id| with decoration // |decoration|. Processed are all decorations which target |id| either // directly or indirectly by Decoration Groups. void ForEachDecoration(uint32_t id, uint32_t decoration, - std::function<void(const opt::Instruction&)> f); + std::function<void(const Instruction&)> f); // |f| is run on each decoration instruction for |id| with decoration // |decoration|. Processes all decoration which target |id| either directly or // indirectly through decoration groups. If |f| returns false, iteration is // terminated and this function returns false. bool WhileEachDecoration(uint32_t id, uint32_t decoration, - std::function<bool(const opt::Instruction&)> f); + std::function<bool(const Instruction&)> f); // Clone all decorations from one id |from|. // The cloned decorations are assigned to the given id |to| and are @@ -93,7 +92,7 @@ class DecorationManager { void CloneDecorations(uint32_t from, uint32_t to); // Informs the decoration manager of a new decoration that it needs to track. - void AddDecoration(opt::Instruction* inst); + void AddDecoration(Instruction* inst); private: // Analyzes the defs and uses in the given |module| and populates data @@ -105,19 +104,19 @@ class DecorationManager { // Tracks decoration information of an ID. struct TargetData { - std::vector<opt::Instruction*> direct_decorations; // All decorate - // instructions applied - // to the tracked ID. - std::vector<opt::Instruction*> indirect_decorations; // All instructions - // applying a group to - // the tracked ID. - std::vector<opt::Instruction*> decorate_insts; // All decorate instructions - // applying the decorations - // of the tracked ID to - // targets. - // It is empty if the - // tracked ID is not a - // group. + std::vector<Instruction*> direct_decorations; // All decorate + // instructions applied + // to the tracked ID. + std::vector<Instruction*> indirect_decorations; // All instructions + // applying a group to + // the tracked ID. + std::vector<Instruction*> decorate_insts; // All decorate instructions + // applying the decorations + // of the tracked ID to + // targets. + // It is empty if the + // tracked ID is not a + // group. }; // Mapping from ids to the instructions applying a decoration to those ids. @@ -127,7 +126,7 @@ class DecorationManager { // SpvOpMemberGroupDecorate). std::unordered_map<uint32_t, TargetData> id_to_decoration_insts_; // The enclosing module. - opt::Module* module_; + Module* module_; }; } // namespace analysis diff --git a/source/opt/def_use_manager.cpp b/source/opt/def_use_manager.cpp index 140bfb70..c581e399 100644 --- a/source/opt/def_use_manager.cpp +++ b/source/opt/def_use_manager.cpp @@ -23,7 +23,7 @@ namespace spvtools { namespace opt { namespace analysis { -void DefUseManager::AnalyzeInstDef(opt::Instruction* inst) { +void DefUseManager::AnalyzeInstDef(Instruction* inst) { const uint32_t def_id = inst->result_id(); if (def_id != 0) { auto iter = id_to_def_.find(def_id); @@ -38,7 +38,7 @@ void DefUseManager::AnalyzeInstDef(opt::Instruction* inst) { } } -void DefUseManager::AnalyzeInstUse(opt::Instruction* inst) { +void DefUseManager::AnalyzeInstUse(Instruction* inst) { // Create entry for the given instruction. Note that the instruction may // not have any in-operands. In such cases, we still need a entry for those // instructions so this manager knows it has seen the instruction later. @@ -57,7 +57,7 @@ void DefUseManager::AnalyzeInstUse(opt::Instruction* inst) { case SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID: case SPV_OPERAND_TYPE_SCOPE_ID: { uint32_t use_id = inst->GetSingleWordOperand(i); - opt::Instruction* def = GetDef(use_id); + Instruction* def = GetDef(use_id); assert(def && "Definition is not registered."); id_to_users_.insert(UserEntry(def, inst)); used_ids->push_back(use_id); @@ -68,12 +68,12 @@ void DefUseManager::AnalyzeInstUse(opt::Instruction* inst) { } } -void DefUseManager::AnalyzeInstDefUse(opt::Instruction* inst) { +void DefUseManager::AnalyzeInstDefUse(Instruction* inst) { AnalyzeInstDef(inst); AnalyzeInstUse(inst); } -void DefUseManager::UpdateDefUse(opt::Instruction* inst) { +void DefUseManager::UpdateDefUse(Instruction* inst) { const uint32_t def_id = inst->result_id(); if (def_id != 0) { auto iter = id_to_def_.find(def_id); @@ -84,38 +84,37 @@ void DefUseManager::UpdateDefUse(opt::Instruction* inst) { AnalyzeInstUse(inst); } -opt::Instruction* DefUseManager::GetDef(uint32_t id) { +Instruction* DefUseManager::GetDef(uint32_t id) { auto iter = id_to_def_.find(id); if (iter == id_to_def_.end()) return nullptr; return iter->second; } -const opt::Instruction* DefUseManager::GetDef(uint32_t id) const { +const Instruction* DefUseManager::GetDef(uint32_t id) const { const auto iter = id_to_def_.find(id); if (iter == id_to_def_.end()) return nullptr; return iter->second; } DefUseManager::IdToUsersMap::const_iterator DefUseManager::UsersBegin( - const opt::Instruction* def) const { + const Instruction* def) const { return id_to_users_.lower_bound( - UserEntry(const_cast<opt::Instruction*>(def), nullptr)); + UserEntry(const_cast<Instruction*>(def), nullptr)); } bool DefUseManager::UsersNotEnd(const IdToUsersMap::const_iterator& iter, const IdToUsersMap::const_iterator& cached_end, - const opt::Instruction* inst) const { + const Instruction* inst) const { return (iter != cached_end && iter->first == inst); } bool DefUseManager::UsersNotEnd(const IdToUsersMap::const_iterator& iter, - const opt::Instruction* inst) const { + const Instruction* inst) const { return UsersNotEnd(iter, id_to_users_.end(), inst); } bool DefUseManager::WhileEachUser( - const opt::Instruction* def, - const std::function<bool(opt::Instruction*)>& f) const { + const Instruction* def, const std::function<bool(Instruction*)>& f) const { // Ensure that |def| has been registered. assert(def && (!def->HasResultId() || def == GetDef(def->result_id())) && "Definition is not registered."); @@ -129,27 +128,26 @@ bool DefUseManager::WhileEachUser( } bool DefUseManager::WhileEachUser( - uint32_t id, const std::function<bool(opt::Instruction*)>& f) const { + uint32_t id, const std::function<bool(Instruction*)>& f) const { return WhileEachUser(GetDef(id), f); } void DefUseManager::ForEachUser( - const opt::Instruction* def, - const std::function<void(opt::Instruction*)>& f) const { - WhileEachUser(def, [&f](opt::Instruction* user) { + const Instruction* def, const std::function<void(Instruction*)>& f) const { + WhileEachUser(def, [&f](Instruction* user) { f(user); return true; }); } void DefUseManager::ForEachUser( - uint32_t id, const std::function<void(opt::Instruction*)>& f) const { + uint32_t id, const std::function<void(Instruction*)>& f) const { ForEachUser(GetDef(id), f); } bool DefUseManager::WhileEachUse( - const opt::Instruction* def, - const std::function<bool(opt::Instruction*, uint32_t)>& f) const { + const Instruction* def, + const std::function<bool(Instruction*, uint32_t)>& f) const { // Ensure that |def| has been registered. assert(def && (!def->HasResultId() || def == GetDef(def->result_id())) && "Definition is not registered."); @@ -157,9 +155,9 @@ bool DefUseManager::WhileEachUse( auto end = id_to_users_.end(); for (auto iter = UsersBegin(def); UsersNotEnd(iter, end, def); ++iter) { - opt::Instruction* user = iter->second; + Instruction* user = iter->second; for (uint32_t idx = 0; idx != user->NumOperands(); ++idx) { - const opt::Operand& op = user->GetOperand(idx); + const Operand& op = user->GetOperand(idx); if (op.type != SPV_OPERAND_TYPE_RESULT_ID && spvIsIdType(op.type)) { if (def->result_id() == op.words[0]) { if (!f(user, idx)) return false; @@ -171,29 +169,27 @@ bool DefUseManager::WhileEachUse( } bool DefUseManager::WhileEachUse( - uint32_t id, - const std::function<bool(opt::Instruction*, uint32_t)>& f) const { + uint32_t id, const std::function<bool(Instruction*, uint32_t)>& f) const { return WhileEachUse(GetDef(id), f); } void DefUseManager::ForEachUse( - const opt::Instruction* def, - const std::function<void(opt::Instruction*, uint32_t)>& f) const { - WhileEachUse(def, [&f](opt::Instruction* user, uint32_t index) { + const Instruction* def, + const std::function<void(Instruction*, uint32_t)>& f) const { + WhileEachUse(def, [&f](Instruction* user, uint32_t index) { f(user, index); return true; }); } void DefUseManager::ForEachUse( - uint32_t id, - const std::function<void(opt::Instruction*, uint32_t)>& f) const { + uint32_t id, const std::function<void(Instruction*, uint32_t)>& f) const { ForEachUse(GetDef(id), f); } -uint32_t DefUseManager::NumUsers(const opt::Instruction* def) const { +uint32_t DefUseManager::NumUsers(const Instruction* def) const { uint32_t count = 0; - ForEachUser(def, [&count](opt::Instruction*) { ++count; }); + ForEachUser(def, [&count](Instruction*) { ++count; }); return count; } @@ -201,9 +197,9 @@ uint32_t DefUseManager::NumUsers(uint32_t id) const { return NumUsers(GetDef(id)); } -uint32_t DefUseManager::NumUses(const opt::Instruction* def) const { +uint32_t DefUseManager::NumUses(const Instruction* def) const { uint32_t count = 0; - ForEachUse(def, [&count](opt::Instruction*, uint32_t) { ++count; }); + ForEachUse(def, [&count](Instruction*, uint32_t) { ++count; }); return count; } @@ -211,21 +207,20 @@ uint32_t DefUseManager::NumUses(uint32_t id) const { return NumUses(GetDef(id)); } -std::vector<opt::Instruction*> DefUseManager::GetAnnotations( - uint32_t id) const { - std::vector<opt::Instruction*> annos; - const opt::Instruction* def = GetDef(id); +std::vector<Instruction*> DefUseManager::GetAnnotations(uint32_t id) const { + std::vector<Instruction*> annos; + const Instruction* def = GetDef(id); if (!def) return annos; - ForEachUser(def, [&annos](opt::Instruction* user) { - if (opt::IsAnnotationInst(user->opcode())) { + ForEachUser(def, [&annos](Instruction* user) { + if (IsAnnotationInst(user->opcode())) { annos.push_back(user); } }); return annos; } -void DefUseManager::AnalyzeDefUse(opt::Module* module) { +void DefUseManager::AnalyzeDefUse(Module* module) { if (!module) return; // Analyze all the defs before any uses to catch forward references. module->ForEachInst( @@ -234,7 +229,7 @@ void DefUseManager::AnalyzeDefUse(opt::Module* module) { std::bind(&DefUseManager::AnalyzeInstUse, this, std::placeholders::_1)); } -void DefUseManager::ClearInst(opt::Instruction* inst) { +void DefUseManager::ClearInst(Instruction* inst) { auto iter = inst_to_used_ids_.find(inst); if (iter != inst_to_used_ids_.end()) { EraseUseRecordsOfOperandIds(inst); @@ -251,14 +246,14 @@ void DefUseManager::ClearInst(opt::Instruction* inst) { } } -void DefUseManager::EraseUseRecordsOfOperandIds(const opt::Instruction* inst) { +void DefUseManager::EraseUseRecordsOfOperandIds(const Instruction* inst) { // Go through all ids used by this instruction, remove this instruction's // uses of them. auto iter = inst_to_used_ids_.find(inst); if (iter != inst_to_used_ids_.end()) { for (auto use_id : iter->second) { id_to_users_.erase( - UserEntry(GetDef(use_id), const_cast<opt::Instruction*>(inst))); + UserEntry(GetDef(use_id), const_cast<Instruction*>(inst))); } inst_to_used_ids_.erase(inst); } diff --git a/source/opt/def_use_manager.h b/source/opt/def_use_manager.h index 9fe286d7..cc09198a 100644 --- a/source/opt/def_use_manager.h +++ b/source/opt/def_use_manager.h @@ -33,7 +33,7 @@ namespace analysis { // * Ids referenced in OpSectionMerge & OpLoopMerge are considered as use. // * Ids referenced in OpPhi's in operands are considered as use. struct Use { - opt::Instruction* inst; // Instruction using the id. + Instruction* inst; // Instruction using the id. uint32_t operand_index; // logical operand index of the id use. This can be // the index of result type id. }; @@ -58,7 +58,7 @@ inline bool operator<(const Use& lhs, const Use& rhs) { // Definition should never be null. User can be null, however, such an entry // should be used only for searching (e.g. all users of a particular definition) // and never stored in a container. -using UserEntry = std::pair<opt::Instruction*, opt::Instruction*>; +using UserEntry = std::pair<Instruction*, Instruction*>; // Orders UserEntry for use in associative containers (i.e. less than ordering). // @@ -92,17 +92,17 @@ struct UserEntryLess { } }; -// A class for analyzing and managing defs and uses in an opt::Module. +// A class for analyzing and managing defs and uses in an Module. class DefUseManager { public: - using IdToDefMap = std::unordered_map<uint32_t, opt::Instruction*>; + using IdToDefMap = std::unordered_map<uint32_t, Instruction*>; using IdToUsersMap = std::set<UserEntry, UserEntryLess>; // Constructs a def-use manager from the given |module|. All internal messages // will be communicated to the outside via the given message |consumer|. This // instance only keeps a reference to the |consumer|, so the |consumer| should // outlive this instance. - DefUseManager(opt::Module* module) { AnalyzeDefUse(module); } + DefUseManager(Module* module) { AnalyzeDefUse(module); } DefUseManager(const DefUseManager&) = delete; DefUseManager(DefUseManager&&) = delete; @@ -110,20 +110,20 @@ class DefUseManager { DefUseManager& operator=(DefUseManager&&) = delete; // Analyzes the defs in the given |inst|. - void AnalyzeInstDef(opt::Instruction* inst); + void AnalyzeInstDef(Instruction* inst); // Analyzes the uses in the given |inst|. // // All operands of |inst| must be analyzed as defs. - void AnalyzeInstUse(opt::Instruction* inst); + void AnalyzeInstUse(Instruction* inst); // Analyzes the defs and uses in the given |inst|. - void AnalyzeInstDefUse(opt::Instruction* inst); + void AnalyzeInstDefUse(Instruction* inst); // Returns the def instruction for the given |id|. If there is no instruction // defining |id|, returns nullptr. - opt::Instruction* GetDef(uint32_t id); - const opt::Instruction* GetDef(uint32_t id) const; + Instruction* GetDef(uint32_t id); + const Instruction* GetDef(uint32_t id) const; // Runs the given function |f| on each unique user instruction of |def| (or // |id|). @@ -132,10 +132,10 @@ class DefUseManager { // only be visited once. // // |def| (or |id|) must be registered as a definition. - void ForEachUser(const opt::Instruction* def, - const std::function<void(opt::Instruction*)>& f) const; + void ForEachUser(const Instruction* def, + const std::function<void(Instruction*)>& f) const; void ForEachUser(uint32_t id, - const std::function<void(opt::Instruction*)>& f) const; + const std::function<void(Instruction*)>& f) const; // Runs the given function |f| on each unique user instruction of |def| (or // |id|). If |f| returns false, iteration is terminated and this function @@ -145,10 +145,10 @@ class DefUseManager { // be only be visited once. // // |def| (or |id|) must be registered as a definition. - bool WhileEachUser(const opt::Instruction* def, - const std::function<bool(opt::Instruction*)>& f) const; + bool WhileEachUser(const Instruction* def, + const std::function<bool(Instruction*)>& f) const; bool WhileEachUser(uint32_t id, - const std::function<bool(opt::Instruction*)>& f) const; + const std::function<bool(Instruction*)>& f) const; // Runs the given function |f| on each unique use of |def| (or // |id|). @@ -157,12 +157,12 @@ class DefUseManager { // visited separately. // // |def| (or |id|) must be registered as a definition. - void ForEachUse(const opt::Instruction* def, - const std::function<void(opt::Instruction*, - uint32_t operand_index)>& f) const; - void ForEachUse(uint32_t id, - const std::function<void(opt::Instruction*, - uint32_t operand_index)>& f) const; + void ForEachUse( + const Instruction* def, + const std::function<void(Instruction*, uint32_t operand_index)>& f) const; + void ForEachUse( + uint32_t id, + const std::function<void(Instruction*, uint32_t operand_index)>& f) const; // Runs the given function |f| on each unique use of |def| (or // |id|). If |f| returns false, iteration is terminated and this function @@ -172,19 +172,19 @@ class DefUseManager { // visited separately. // // |def| (or |id|) must be registered as a definition. - bool WhileEachUse(const opt::Instruction* def, - const std::function<bool(opt::Instruction*, - uint32_t operand_index)>& f) const; - bool WhileEachUse(uint32_t id, - const std::function<bool(opt::Instruction*, - uint32_t operand_index)>& f) const; + bool WhileEachUse( + const Instruction* def, + const std::function<bool(Instruction*, uint32_t operand_index)>& f) const; + bool WhileEachUse( + uint32_t id, + const std::function<bool(Instruction*, uint32_t operand_index)>& f) const; // Returns the number of users of |def| (or |id|). - uint32_t NumUsers(const opt::Instruction* def) const; + uint32_t NumUsers(const Instruction* def) const; uint32_t NumUsers(uint32_t id) const; // Returns the number of uses of |def| (or |id|). - uint32_t NumUses(const opt::Instruction* def) const; + uint32_t NumUses(const Instruction* def) const; uint32_t NumUses(uint32_t id) const; // Returns the annotation instrunctions which are a direct use of the given @@ -192,7 +192,7 @@ class DefUseManager { // group(s), this function will just return the OpGroupDecorate // instrcution(s) which refer to the given id as an operand. The OpDecorate // instructions which decorate the decoration group will not be returned. - std::vector<opt::Instruction*> GetAnnotations(uint32_t id) const; + std::vector<Instruction*> GetAnnotations(uint32_t id) const; // Returns the map from ids to their def instructions. const IdToDefMap& id_to_defs() const { return id_to_def_; } @@ -204,10 +204,10 @@ class DefUseManager { // record: |inst| uses an |id|, will be removed from the use records of |id|. // If |inst| defines an result id, the use record of this result id will also // be removed. Does nothing if |inst| was not analyzed before. - void ClearInst(opt::Instruction* inst); + void ClearInst(Instruction* inst); // Erases the records that a given instruction uses its operand ids. - void EraseUseRecordsOfOperandIds(const opt::Instruction* inst); + void EraseUseRecordsOfOperandIds(const Instruction* inst); friend bool operator==(const DefUseManager&, const DefUseManager&); friend bool operator!=(const DefUseManager& lhs, const DefUseManager& rhs) { @@ -216,15 +216,15 @@ class DefUseManager { // If |inst| has not already been analysed, then analyses its defintion and // uses. - void UpdateDefUse(opt::Instruction* inst); + void UpdateDefUse(Instruction* inst); private: using InstToUsedIdsMap = - std::unordered_map<const opt::Instruction*, std::vector<uint32_t>>; + std::unordered_map<const Instruction*, std::vector<uint32_t>>; // Returns the first location that {|def|, nullptr} could be inserted into the // users map without violating ordering. - IdToUsersMap::const_iterator UsersBegin(const opt::Instruction* def) const; + IdToUsersMap::const_iterator UsersBegin(const Instruction* def) const; // Returns true if |iter| has not reached the end of |def|'s users. // @@ -233,14 +233,14 @@ class DefUseManager { // against |cached_end| for validity before other checks. This allows caching // the map's end which is a performance improvement on some platforms. bool UsersNotEnd(const IdToUsersMap::const_iterator& iter, - const opt::Instruction* def) const; + const Instruction* def) const; bool UsersNotEnd(const IdToUsersMap::const_iterator& iter, const IdToUsersMap::const_iterator& cached_end, - const opt::Instruction* def) const; + const Instruction* def) const; // Analyzes the defs and uses in the given |module| and populates data // structures in this class. Does nothing if |module| is nullptr. - void AnalyzeDefUse(opt::Module* module); + void AnalyzeDefUse(Module* module); IdToDefMap id_to_def_; // Mapping from ids to their definitions IdToUsersMap id_to_users_; // Mapping from ids to their users diff --git a/source/opt/dominator_analysis.cpp b/source/opt/dominator_analysis.cpp index 709e4cbd..f045ee46 100644 --- a/source/opt/dominator_analysis.cpp +++ b/source/opt/dominator_analysis.cpp @@ -21,12 +21,12 @@ namespace spvtools { namespace opt { -opt::BasicBlock* DominatorAnalysisBase::CommonDominator( - opt::BasicBlock* b1, opt::BasicBlock* b2) const { +BasicBlock* DominatorAnalysisBase::CommonDominator(BasicBlock* b1, + BasicBlock* b2) const { if (!b1 || !b2) return nullptr; - std::unordered_set<opt::BasicBlock*> seen; - opt::BasicBlock* block = b1; + std::unordered_set<BasicBlock*> seen; + BasicBlock* block = b1; while (block && seen.insert(block).second) { block = ImmediateDominator(block); } @@ -39,8 +39,7 @@ opt::BasicBlock* DominatorAnalysisBase::CommonDominator( return block; } -bool DominatorAnalysisBase::Dominates(opt::Instruction* a, - opt::Instruction* b) const { +bool DominatorAnalysisBase::Dominates(Instruction* a, Instruction* b) const { if (!a || !b) { return false; } @@ -49,14 +48,14 @@ bool DominatorAnalysisBase::Dominates(opt::Instruction* a, return true; } - opt::BasicBlock* bb_a = a->context()->get_instr_block(a); - opt::BasicBlock* bb_b = b->context()->get_instr_block(b); + BasicBlock* bb_a = a->context()->get_instr_block(a); + BasicBlock* bb_b = b->context()->get_instr_block(b); if (bb_a != bb_b) { return tree_.Dominates(bb_a, bb_b); } - opt::Instruction* current_inst = a; + Instruction* current_inst = a; while ((current_inst = current_inst->NextNode())) { if (current_inst == b) { return true; diff --git a/source/opt/dominator_analysis.h b/source/opt/dominator_analysis.h index c4e53ca2..6b7a904f 100644 --- a/source/opt/dominator_analysis.h +++ b/source/opt/dominator_analysis.h @@ -29,13 +29,12 @@ class DominatorAnalysisBase { explicit DominatorAnalysisBase(bool is_post_dom) : tree_(is_post_dom) {} // Calculates the dominator (or postdominator) tree for given function |f|. - inline void InitializeTree(const CFG& cfg, const opt::Function* f) { + inline void InitializeTree(const CFG& cfg, const Function* f) { tree_.InitializeTree(cfg, f); } // Returns true if BasicBlock |a| dominates BasicBlock |b|. - inline bool Dominates(const opt::BasicBlock* a, - const opt::BasicBlock* b) const { + inline bool Dominates(const BasicBlock* a, const BasicBlock* b) const { if (!a || !b) return false; return Dominates(a->id(), b->id()); } @@ -47,11 +46,11 @@ class DominatorAnalysisBase { } // Returns true if instruction |a| dominates instruction |b|. - bool Dominates(opt::Instruction* a, opt::Instruction* b) const; + bool Dominates(Instruction* a, Instruction* b) const; // Returns true if BasicBlock |a| strictly dominates BasicBlock |b|. - inline bool StrictlyDominates(const opt::BasicBlock* a, - const opt::BasicBlock* b) const { + inline bool StrictlyDominates(const BasicBlock* a, + const BasicBlock* b) const { if (!a || !b) return false; return StrictlyDominates(a->id(), b->id()); } @@ -64,20 +63,19 @@ class DominatorAnalysisBase { // Returns the immediate dominator of |node| or returns nullptr if it is has // no dominator. - inline opt::BasicBlock* ImmediateDominator( - const opt::BasicBlock* node) const { + inline BasicBlock* ImmediateDominator(const BasicBlock* node) const { if (!node) return nullptr; return tree_.ImmediateDominator(node); } // Returns the immediate dominator of |node_id| or returns nullptr if it is // has no dominator. Same as above but operates on IDs. - inline opt::BasicBlock* ImmediateDominator(uint32_t node_id) const { + inline BasicBlock* ImmediateDominator(uint32_t node_id) const { return tree_.ImmediateDominator(node_id); } // Returns true if |node| is reachable from the entry. - inline bool IsReachable(const opt::BasicBlock* node) const { + inline bool IsReachable(const BasicBlock* node) const { if (!node) return false; return tree_.ReachableFromRoots(node->id()); } @@ -116,8 +114,7 @@ class DominatorAnalysisBase { // Returns the most immediate basic block that dominates both |b1| and |b2|. // If there is no such basic block, nullptr is returned. - opt::BasicBlock* CommonDominator(opt::BasicBlock* b1, - opt::BasicBlock* b2) const; + BasicBlock* CommonDominator(BasicBlock* b1, BasicBlock* b2) const; protected: DominatorTree tree_; diff --git a/source/opt/dominator_tree.cpp b/source/opt/dominator_tree.cpp index b08f11cc..df3aae6d 100644 --- a/source/opt/dominator_tree.cpp +++ b/source/opt/dominator_tree.cpp @@ -45,7 +45,7 @@ namespace { // depth first search on generic BasicBlock types. Will call post and pre order // user defined functions during traversal // -// BBType - BasicBlock type. Will either be opt::BasicBlock or DominatorTreeNode +// BBType - BasicBlock type. Will either be BasicBlock or DominatorTreeNode // SuccessorLambda - Lamdba matching the signature of 'const // std::vector<BBType>*(const BBType *A)'. Will return a vector of the nodes // succeding BasicBlock A. @@ -66,7 +66,7 @@ static void DepthFirstSearch(const BBType* bb, SuccessorLambda successors, // depth first search on generic BasicBlock types. This overload is for only // performing user defined post order. // -// BBType - BasicBlock type. Will either be opt::BasicBlock or DominatorTreeNode +// BBType - BasicBlock type. Will either be BasicBlock or DominatorTreeNode // SuccessorLambda - Lamdba matching the signature of 'const // std::vector<BBType>*(const BBType *A)'. Will return a vector of the nodes // succeding BasicBlock A. @@ -84,7 +84,7 @@ static void DepthFirstSearchPostOrder(const BBType* bb, // Small type trait to get the function class type. template <typename BBType> struct GetFunctionClass { - using FunctionType = opt::Function; + using FunctionType = Function; }; // Helper class to compute predecessors and successors for each Basic Block in a @@ -98,7 +98,7 @@ struct GetFunctionClass { // returned by this class will be predecessors in the original CFG. template <typename BBType> class BasicBlockSuccessorHelper { - // This should eventually become const opt::BasicBlock. + // This should eventually become const BasicBlock. using BasicBlock = BBType; using Function = typename GetFunctionClass<BBType>::FunctionType; @@ -219,8 +219,8 @@ bool DominatorTree::StrictlyDominates(uint32_t a, uint32_t b) const { return Dominates(a, b); } -bool DominatorTree::StrictlyDominates(const opt::BasicBlock* a, - const opt::BasicBlock* b) const { +bool DominatorTree::StrictlyDominates(const BasicBlock* a, + const BasicBlock* b) const { return DominatorTree::StrictlyDominates(a->id(), b->id()); } @@ -248,17 +248,15 @@ bool DominatorTree::Dominates(const DominatorTreeNode* a, a->dfs_num_post_ > b->dfs_num_post_; } -bool DominatorTree::Dominates(const opt::BasicBlock* A, - const opt::BasicBlock* B) const { +bool DominatorTree::Dominates(const BasicBlock* A, const BasicBlock* B) const { return Dominates(A->id(), B->id()); } -opt::BasicBlock* DominatorTree::ImmediateDominator( - const opt::BasicBlock* A) const { +BasicBlock* DominatorTree::ImmediateDominator(const BasicBlock* A) const { return ImmediateDominator(A->id()); } -opt::BasicBlock* DominatorTree::ImmediateDominator(uint32_t a) const { +BasicBlock* DominatorTree::ImmediateDominator(uint32_t a) const { // Check that A is a valid node in the tree. auto a_itr = nodes_.find(a); if (a_itr == nodes_.end()) return nullptr; @@ -272,7 +270,7 @@ opt::BasicBlock* DominatorTree::ImmediateDominator(uint32_t a) const { return node->parent_->bb_; } -DominatorTreeNode* DominatorTree::GetOrInsertNode(opt::BasicBlock* bb) { +DominatorTreeNode* DominatorTree::GetOrInsertNode(BasicBlock* bb) { DominatorTreeNode* dtn = nullptr; std::map<uint32_t, DominatorTreeNode>::iterator node_iter = @@ -287,21 +285,21 @@ DominatorTreeNode* DominatorTree::GetOrInsertNode(opt::BasicBlock* bb) { } void DominatorTree::GetDominatorEdges( - const opt::Function* f, const opt::BasicBlock* dummy_start_node, - std::vector<std::pair<opt::BasicBlock*, opt::BasicBlock*>>* edges) { + const Function* f, const BasicBlock* dummy_start_node, + std::vector<std::pair<BasicBlock*, BasicBlock*>>* edges) { // Each time the depth first traversal calls the postorder callback // std::function we push that node into the postorder vector to create our // postorder list. - std::vector<const opt::BasicBlock*> postorder; - auto postorder_function = [&](const opt::BasicBlock* b) { + std::vector<const BasicBlock*> postorder; + auto postorder_function = [&](const BasicBlock* b) { postorder.push_back(b); }; - // CFA::CalculateDominators requires std::vector<opt::BasicBlock*> + // CFA::CalculateDominators requires std::vector<BasicBlock*> // BB are derived from F, so we need to const cast it at some point // no modification is made on F. - BasicBlockSuccessorHelper<opt::BasicBlock> helper{ - *const_cast<opt::Function*>(f), dummy_start_node, postdominator_}; + BasicBlockSuccessorHelper<BasicBlock> helper{ + *const_cast<Function*>(f), dummy_start_node, postdominator_}; // The successor function tells DepthFirstTraversal how to move to successive // nodes by providing an interface to get a list of successor nodes from any @@ -317,11 +315,10 @@ void DominatorTree::GetDominatorEdges( // versa. DepthFirstSearchPostOrder(dummy_start_node, successor_functor, postorder_function); - *edges = - CFA<opt::BasicBlock>::CalculateDominators(postorder, predecessor_functor); + *edges = CFA<BasicBlock>::CalculateDominators(postorder, predecessor_functor); } -void DominatorTree::InitializeTree(const CFG& cfg, const opt::Function* f) { +void DominatorTree::InitializeTree(const CFG& cfg, const Function* f) { ClearTree(); // Skip over empty functions. @@ -329,11 +326,11 @@ void DominatorTree::InitializeTree(const CFG& cfg, const opt::Function* f) { return; } - const opt::BasicBlock* dummy_start_node = + const BasicBlock* dummy_start_node = postdominator_ ? cfg.pseudo_exit_block() : cfg.pseudo_entry_block(); // Get the immediate dominator for each node. - std::vector<std::pair<opt::BasicBlock*, opt::BasicBlock*>> edges; + std::vector<std::pair<BasicBlock*, BasicBlock*>> edges; GetDominatorEdges(f, dummy_start_node, &edges); // Transform the vector<pair> into the tree structure which we can use to diff --git a/source/opt/dominator_tree.h b/source/opt/dominator_tree.h index c25f0b77..2e2f6f58 100644 --- a/source/opt/dominator_tree.h +++ b/source/opt/dominator_tree.h @@ -30,7 +30,7 @@ namespace opt { // children. It also contains two values, for the pre and post indexes in the // tree which are used to compare two nodes. struct DominatorTreeNode { - explicit DominatorTreeNode(opt::BasicBlock* bb) + explicit DominatorTreeNode(BasicBlock* bb) : bb_(bb), parent_(nullptr), children_({}), @@ -76,7 +76,7 @@ struct DominatorTreeNode { inline uint32_t id() const { return bb_->id(); } - opt::BasicBlock* bb_; + BasicBlock* bb_; DominatorTreeNode* parent_; std::vector<DominatorTreeNode*> children_; @@ -158,10 +158,10 @@ class DominatorTree { // Build the (post-)dominator tree for the given control flow graph // |cfg| and the function |f|. |f| must exist in the |cfg|. Any // existing data in the dominator tree will be overwritten - void InitializeTree(const CFG& cfg, const opt::Function* f); + void InitializeTree(const CFG& cfg, const Function* f); // Check if the basic block |a| dominates the basic block |b|. - bool Dominates(const opt::BasicBlock* a, const opt::BasicBlock* b) const; + bool Dominates(const BasicBlock* a, const BasicBlock* b) const; // Check if the basic block id |a| dominates the basic block id |b|. bool Dominates(uint32_t a, uint32_t b) const; @@ -170,8 +170,7 @@ class DominatorTree { bool Dominates(const DominatorTreeNode* a, const DominatorTreeNode* b) const; // Check if the basic block |a| strictly dominates the basic block |b|. - bool StrictlyDominates(const opt::BasicBlock* a, - const opt::BasicBlock* b) const; + bool StrictlyDominates(const BasicBlock* a, const BasicBlock* b) const; // Check if the basic block id |a| strictly dominates the basic block id |b|. bool StrictlyDominates(uint32_t a, uint32_t b) const; @@ -182,15 +181,15 @@ class DominatorTree { const DominatorTreeNode* b) const; // Returns the immediate dominator of basic block |a|. - opt::BasicBlock* ImmediateDominator(const opt::BasicBlock* A) const; + BasicBlock* ImmediateDominator(const BasicBlock* A) const; // Returns the immediate dominator of basic block id |a|. - opt::BasicBlock* ImmediateDominator(uint32_t a) const; + BasicBlock* ImmediateDominator(uint32_t a) const; // Returns true if the basic block |a| is reachable by this tree. A node would // be unreachable if it cannot be reached by traversal from the start node or // for a postdominator tree, cannot be reached from the exit nodes. - inline bool ReachableFromRoots(const opt::BasicBlock* a) const { + inline bool ReachableFromRoots(const BasicBlock* a) const { if (!a) return false; return ReachableFromRoots(a->id()); } @@ -242,12 +241,12 @@ class DominatorTree { // Returns the DominatorTreeNode associated with the basic block |bb|. // If the |bb| is unknown to the dominator tree, it returns null. - inline DominatorTreeNode* GetTreeNode(opt::BasicBlock* bb) { + inline DominatorTreeNode* GetTreeNode(BasicBlock* bb) { return GetTreeNode(bb->id()); } // Returns the DominatorTreeNode associated with the basic block |bb|. // If the |bb| is unknown to the dominator tree, it returns null. - inline const DominatorTreeNode* GetTreeNode(opt::BasicBlock* bb) const { + inline const DominatorTreeNode* GetTreeNode(BasicBlock* bb) const { return GetTreeNode(bb->id()); } @@ -272,7 +271,7 @@ class DominatorTree { // Adds the basic block |bb| to the tree structure if it doesn't already // exist. - DominatorTreeNode* GetOrInsertNode(opt::BasicBlock* bb); + DominatorTreeNode* GetOrInsertNode(BasicBlock* bb); // Recomputes the DF numbering of the tree. void ResetDFNumbering(); @@ -287,8 +286,8 @@ class DominatorTree { // pair is its immediate dominator. // The root of the tree has themself as immediate dominator. void GetDominatorEdges( - const opt::Function* f, const opt::BasicBlock* dummy_start_node, - std::vector<std::pair<opt::BasicBlock*, opt::BasicBlock*>>* edges); + const Function* f, const BasicBlock* dummy_start_node, + std::vector<std::pair<BasicBlock*, BasicBlock*>>* edges); // The roots of the tree. std::vector<DominatorTreeNode*> roots_; diff --git a/source/opt/eliminate_dead_constant_pass.cpp b/source/opt/eliminate_dead_constant_pass.cpp index 35926f5d..28b84caf 100644 --- a/source/opt/eliminate_dead_constant_pass.cpp +++ b/source/opt/eliminate_dead_constant_pass.cpp @@ -27,21 +27,21 @@ namespace spvtools { namespace opt { Pass::Status EliminateDeadConstantPass::Process() { - std::unordered_set<opt::Instruction*> working_list; + std::unordered_set<Instruction*> working_list; // Traverse all the instructions to get the initial set of dead constants as // working list and count number of real uses for constants. Uses in // annotation instructions do not count. - std::unordered_map<opt::Instruction*, size_t> use_counts; - std::vector<opt::Instruction*> constants = context()->GetConstants(); + std::unordered_map<Instruction*, size_t> use_counts; + std::vector<Instruction*> constants = context()->GetConstants(); for (auto* c : constants) { uint32_t const_id = c->result_id(); size_t count = 0; context()->get_def_use_mgr()->ForEachUse( - const_id, [&count](opt::Instruction* user, uint32_t index) { + const_id, [&count](Instruction* user, uint32_t index) { (void)index; SpvOp op = user->opcode(); - if (!(opt::IsAnnotationInst(op) || opt::IsDebug1Inst(op) || - opt::IsDebug2Inst(op) || opt::IsDebug3Inst(op))) { + if (!(IsAnnotationInst(op) || IsDebug1Inst(op) || IsDebug2Inst(op) || + IsDebug3Inst(op))) { ++count; } }); @@ -53,9 +53,9 @@ Pass::Status EliminateDeadConstantPass::Process() { // Start from the constants with 0 uses, back trace through the def-use chain // to find all dead constants. - std::unordered_set<opt::Instruction*> dead_consts; + std::unordered_set<Instruction*> dead_consts; while (!working_list.empty()) { - opt::Instruction* inst = *working_list.begin(); + Instruction* inst = *working_list.begin(); // Back propagate if the instruction contains IDs in its operands. switch (inst->opcode()) { case SpvOp::SpvOpConstantComposite: @@ -68,7 +68,7 @@ Pass::Status EliminateDeadConstantPass::Process() { continue; } uint32_t operand_id = inst->GetSingleWordInOperand(i); - opt::Instruction* def_inst = + Instruction* def_inst = context()->get_def_use_mgr()->GetDef(operand_id); // If the use_count does not have any count for the def_inst, // def_inst must not be a constant, and should be ignored here. diff --git a/source/opt/eliminate_dead_functions_pass.cpp b/source/opt/eliminate_dead_functions_pass.cpp index d91778c7..383c267a 100644 --- a/source/opt/eliminate_dead_functions_pass.cpp +++ b/source/opt/eliminate_dead_functions_pass.cpp @@ -23,8 +23,8 @@ namespace opt { Pass::Status EliminateDeadFunctionsPass::Process() { // Identify live functions first. Those that are not live // are dead. - std::unordered_set<const opt::Function*> live_function_set; - ProcessFunction mark_live = [&live_function_set](opt::Function* fp) { + std::unordered_set<const Function*> live_function_set; + ProcessFunction mark_live = [&live_function_set](Function* fp) { live_function_set.insert(fp); return false; }; @@ -46,10 +46,10 @@ Pass::Status EliminateDeadFunctionsPass::Process() { : Pass::Status::SuccessWithoutChange; } -void EliminateDeadFunctionsPass::EliminateFunction(opt::Function* func) { +void EliminateDeadFunctionsPass::EliminateFunction(Function* func) { // Remove all of the instruction in the function body - func->ForEachInst( - [this](opt::Instruction* inst) { context()->KillInst(inst); }, true); + func->ForEachInst([this](Instruction* inst) { context()->KillInst(inst); }, + true); } } // namespace opt } // namespace spvtools diff --git a/source/opt/eliminate_dead_functions_pass.h b/source/opt/eliminate_dead_functions_pass.h index 94eafaf3..ad4b04cc 100644 --- a/source/opt/eliminate_dead_functions_pass.h +++ b/source/opt/eliminate_dead_functions_pass.h @@ -29,12 +29,12 @@ class EliminateDeadFunctionsPass : public MemPass { const char* name() const override { return "eliminate-dead-functions"; } Status Process() override; - opt::IRContext::Analysis GetPreservedAnalyses() override { - return opt::IRContext::kAnalysisDefUse; + IRContext::Analysis GetPreservedAnalyses() override { + return IRContext::kAnalysisDefUse; } private: - void EliminateFunction(opt::Function* func); + void EliminateFunction(Function* func); }; } // namespace opt diff --git a/source/opt/feature_manager.cpp b/source/opt/feature_manager.cpp index 580d96d4..15739f3a 100644 --- a/source/opt/feature_manager.cpp +++ b/source/opt/feature_manager.cpp @@ -21,13 +21,13 @@ namespace spvtools { namespace opt { -void FeatureManager::Analyze(opt::Module* module) { +void FeatureManager::Analyze(Module* module) { AddExtensions(module); AddCapabilities(module); AddExtInstImportIds(module); } -void FeatureManager::AddExtensions(opt::Module* module) { +void FeatureManager::AddExtensions(Module* module) { for (auto ext : module->extensions()) { const std::string name = reinterpret_cast<const char*>(ext.GetInOperand(0u).words.data()); @@ -51,13 +51,13 @@ void FeatureManager::AddCapability(SpvCapability cap) { } } -void FeatureManager::AddCapabilities(opt::Module* module) { - for (opt::Instruction& inst : module->capabilities()) { +void FeatureManager::AddCapabilities(Module* module) { + for (Instruction& inst : module->capabilities()) { AddCapability(static_cast<SpvCapability>(inst.GetSingleWordInOperand(0))); } } -void FeatureManager::AddExtInstImportIds(opt::Module* module) { +void FeatureManager::AddExtInstImportIds(Module* module) { extinst_importid_GLSLstd450_ = module->GetExtInstImportId("GLSL.std.450"); } diff --git a/source/opt/feature_manager.h b/source/opt/feature_manager.h index 9419ce9b..a907d76a 100644 --- a/source/opt/feature_manager.h +++ b/source/opt/feature_manager.h @@ -36,7 +36,7 @@ class FeatureManager { } // Analyzes |module| and records enabled extensions and capabilities. - void Analyze(opt::Module* module); + void Analyze(Module* module); CapabilitySet* GetCapabilities() { return &capabilities_; } const CapabilitySet* GetCapabilities() const { return &capabilities_; } @@ -47,17 +47,17 @@ class FeatureManager { private: // Analyzes |module| and records enabled extensions. - void AddExtensions(opt::Module* module); + void AddExtensions(Module* module); // Adds the given |capability| and all implied capabilities into the current // FeatureManager. void AddCapability(SpvCapability capability); // Analyzes |module| and records enabled capabilities. - void AddCapabilities(opt::Module* module); + void AddCapabilities(Module* module); // Analyzes |module| and records imported external instruction sets. - void AddExtInstImportIds(opt::Module* module); + void AddExtInstImportIds(Module* module); // Auxiliary object for querying SPIR-V grammar facts. const AssemblyGrammar& grammar_; diff --git a/source/opt/flatten_decoration_pass.cpp b/source/opt/flatten_decoration_pass.cpp index 1aaa8126..74c25fcb 100644 --- a/source/opt/flatten_decoration_pass.cpp +++ b/source/opt/flatten_decoration_pass.cpp @@ -23,9 +23,6 @@ namespace spvtools { namespace opt { -using opt::Instruction; -using opt::Operand; - using Words = std::vector<uint32_t>; using OrderedUsesMap = std::unordered_map<uint32_t, Words>; diff --git a/source/opt/fold.cpp b/source/opt/fold.cpp index fcef7509..20071383 100644 --- a/source/opt/fold.cpp +++ b/source/opt/fold.cpp @@ -26,7 +26,6 @@ namespace spvtools { namespace opt { - namespace { #ifndef INT32_MIN @@ -177,9 +176,9 @@ uint32_t InstructionFolder::OperateWords( } } -bool InstructionFolder::FoldInstructionInternal(opt::Instruction* inst) const { +bool InstructionFolder::FoldInstructionInternal(Instruction* inst) const { auto identity_map = [](uint32_t id) { return id; }; - opt::Instruction* folded_inst = FoldInstructionToConstant(inst, identity_map); + Instruction* folded_inst = FoldInstructionToConstant(inst, identity_map); if (folded_inst != nullptr) { inst->SetOpcode(SpvOpCopyObject); inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {folded_inst->result_id()}}}); @@ -229,7 +228,7 @@ uint32_t InstructionFolder::FoldScalars( } bool InstructionFolder::FoldBinaryIntegerOpToConstant( - opt::Instruction* inst, const std::function<uint32_t(uint32_t)>& id_map, + Instruction* inst, const std::function<uint32_t(uint32_t)>& id_map, uint32_t* result) const { SpvOp opcode = inst->opcode(); analysis::ConstantManager* const_manger = context_->get_constant_mgr(); @@ -237,7 +236,7 @@ bool InstructionFolder::FoldBinaryIntegerOpToConstant( uint32_t ids[2]; const analysis::IntConstant* constants[2]; for (uint32_t i = 0; i < 2; i++) { - const opt::Operand* operand = &inst->GetInOperand(i); + const Operand* operand = &inst->GetInOperand(i); if (operand->type != SPV_OPERAND_TYPE_ID) { return false; } @@ -412,7 +411,7 @@ bool InstructionFolder::FoldBinaryIntegerOpToConstant( } bool InstructionFolder::FoldBinaryBooleanOpToConstant( - opt::Instruction* inst, const std::function<uint32_t(uint32_t)>& id_map, + Instruction* inst, const std::function<uint32_t(uint32_t)>& id_map, uint32_t* result) const { SpvOp opcode = inst->opcode(); analysis::ConstantManager* const_manger = context_->get_constant_mgr(); @@ -420,7 +419,7 @@ bool InstructionFolder::FoldBinaryBooleanOpToConstant( uint32_t ids[2]; const analysis::BoolConstant* constants[2]; for (uint32_t i = 0; i < 2; i++) { - const opt::Operand* operand = &inst->GetInOperand(i); + const Operand* operand = &inst->GetInOperand(i); if (operand->type != SPV_OPERAND_TYPE_ID) { return false; } @@ -460,7 +459,7 @@ bool InstructionFolder::FoldBinaryBooleanOpToConstant( } bool InstructionFolder::FoldIntegerOpToConstant( - opt::Instruction* inst, const std::function<uint32_t(uint32_t)>& id_map, + Instruction* inst, const std::function<uint32_t(uint32_t)>& id_map, uint32_t* result) const { assert(IsFoldableOpcode(inst->opcode()) && "Unhandled instruction opcode in FoldScalars"); @@ -569,8 +568,8 @@ bool InstructionFolder::IsFoldableConstant( return cst->AsNullConstant() != nullptr; } -opt::Instruction* InstructionFolder::FoldInstructionToConstant( - opt::Instruction* inst, std::function<uint32_t(uint32_t)> id_map) const { +Instruction* InstructionFolder::FoldInstructionToConstant( + Instruction* inst, std::function<uint32_t(uint32_t)> id_map) const { analysis::ConstantManager* const_mgr = context_->get_constant_mgr(); if (!inst->IsFoldableByFoldScalar() && @@ -598,7 +597,7 @@ opt::Instruction* InstructionFolder::FoldInstructionToConstant( GetConstantFoldingRules().GetRulesForOpcode(inst->opcode())) { folded_const = rule(context_, inst, constants); if (folded_const != nullptr) { - opt::Instruction* const_inst = + Instruction* const_inst = const_mgr->GetDefiningInstruction(folded_const, inst->type_id()); assert(const_inst->type_id() == inst->type_id()); // May be a new instruction that needs to be analysed. @@ -623,14 +622,14 @@ opt::Instruction* InstructionFolder::FoldInstructionToConstant( if (successful) { const analysis::Constant* result_const = const_mgr->GetConstant(const_mgr->GetType(inst), {result_val}); - opt::Instruction* folded_inst = + Instruction* folded_inst = const_mgr->GetDefiningInstruction(result_const, inst->type_id()); return folded_inst; } return nullptr; } -bool InstructionFolder::IsFoldableType(opt::Instruction* type_inst) const { +bool InstructionFolder::IsFoldableType(Instruction* type_inst) const { // Support 32-bit integers. if (type_inst->opcode() == SpvOpTypeInt) { return type_inst->GetSingleWordInOperand(0) == 32; @@ -643,9 +642,9 @@ bool InstructionFolder::IsFoldableType(opt::Instruction* type_inst) const { return false; } -bool InstructionFolder::FoldInstruction(opt::Instruction* inst) const { +bool InstructionFolder::FoldInstruction(Instruction* inst) const { bool modified = false; - opt::Instruction* folded_inst(inst); + Instruction* folded_inst(inst); while (folded_inst->opcode() != SpvOpCopyObject && FoldInstructionInternal(&*folded_inst)) { modified = true; diff --git a/source/opt/fold.h b/source/opt/fold.h index 0e027b1d..143182f3 100644 --- a/source/opt/fold.h +++ b/source/opt/fold.h @@ -68,7 +68,7 @@ class InstructionFolder { // Returns true if |FoldInstructionToConstant| could fold an instruction whose // result type is |type_inst|. - bool IsFoldableType(opt::Instruction* type_inst) const; + bool IsFoldableType(Instruction* type_inst) const; // Tries to fold |inst| to a single constant, when the input ids to |inst| // have been substituted using |id_map|. Returns a pointer to the OpConstant* @@ -79,8 +79,8 @@ class InstructionFolder { // can be used for things like CCP where it is known that some ids contain a // constant, but the instruction itself has not been updated yet. This can // map those ids to the appropriate constants. - opt::Instruction* FoldInstructionToConstant( - opt::Instruction* inst, std::function<uint32_t(uint32_t)> id_map) const; + Instruction* FoldInstructionToConstant( + Instruction* inst, std::function<uint32_t(uint32_t)> id_map) const; // Returns true if |inst| can be folded into a simpler instruction. // If |inst| can be simplified, |inst| is overwritten with the simplified // instruction reusing the same result id. @@ -92,7 +92,7 @@ class InstructionFolder { // 1) An OpPhi becomes and OpCopyObject - If there are OpPhi instruction after // |inst| in a basic block then this is invalid. The caller must fix this // up. - bool FoldInstruction(opt::Instruction* inst) const; + bool FoldInstruction(Instruction* inst) const; // Return true if this opcode has a const folding rule associtated with it. bool HasConstFoldingRule(SpvOp opcode) const { @@ -128,7 +128,7 @@ class InstructionFolder { uint32_t OperateWords(SpvOp opcode, const std::vector<uint32_t>& operand_words) const; - bool FoldInstructionInternal(opt::Instruction* inst) const; + bool FoldInstructionInternal(Instruction* inst) const; // Returns true if |inst| is a binary operation that takes two integers as // parameters and folds to a constant that can be represented as an unsigned diff --git a/source/opt/fold_spec_constant_op_and_composite_pass.cpp b/source/opt/fold_spec_constant_op_and_composite_pass.cpp index 2574628f..3f394e74 100644 --- a/source/opt/fold_spec_constant_op_and_composite_pass.cpp +++ b/source/opt/fold_spec_constant_op_and_composite_pass.cpp @@ -48,13 +48,13 @@ Pass::Status FoldSpecConstantOpAndCompositePass::Process() { // the dependee Spec Constants, all its dependent constants must have been // processed and all its dependent Spec Constants should have been folded if // possible. - opt::Module::inst_iterator next_inst = context()->types_values_begin(); - for (opt::Module::inst_iterator inst_iter = next_inst; + Module::inst_iterator next_inst = context()->types_values_begin(); + for (Module::inst_iterator inst_iter = next_inst; // Need to re-evaluate the end iterator since we may modify the list of // instructions in this section of the module as the process goes. inst_iter != context()->types_values_end(); inst_iter = next_inst) { ++next_inst; - opt::Instruction* inst = &*inst_iter; + Instruction* inst = &*inst_iter; // Collect constant values of normal constants and process the // OpSpecConstantOp and OpSpecConstantComposite instructions if possible. // The constant values will be stored in analysis::Constant instances. @@ -110,9 +110,9 @@ Pass::Status FoldSpecConstantOpAndCompositePass::Process() { } bool FoldSpecConstantOpAndCompositePass::ProcessOpSpecConstantOp( - opt::Module::inst_iterator* pos) { - opt::Instruction* inst = &**pos; - opt::Instruction* folded_inst = nullptr; + Module::inst_iterator* pos) { + Instruction* inst = &**pos; + Instruction* folded_inst = nullptr; assert(inst->GetInOperand(0).type == SPV_OPERAND_TYPE_SPEC_CONSTANT_OP_NUMBER && "The first in-operand of OpSpecContantOp instruction must be of " @@ -150,16 +150,16 @@ bool FoldSpecConstantOpAndCompositePass::ProcessOpSpecConstantOp( uint32_t FoldSpecConstantOpAndCompositePass::GetTypeComponent( uint32_t typeId, uint32_t element) const { - opt::Instruction* type = context()->get_def_use_mgr()->GetDef(typeId); + Instruction* type = context()->get_def_use_mgr()->GetDef(typeId); uint32_t subtype = type->GetTypeComponent(element); assert(subtype != 0); return subtype; } -opt::Instruction* FoldSpecConstantOpAndCompositePass::DoCompositeExtract( - opt::Module::inst_iterator* pos) { - opt::Instruction* inst = &**pos; +Instruction* FoldSpecConstantOpAndCompositePass::DoCompositeExtract( + Module::inst_iterator* pos) { + Instruction* inst = &**pos; assert(inst->NumInOperands() - 1 >= 2 && "OpSpecConstantOp CompositeExtract requires at least two non-type " "non-opcode operands."); @@ -207,9 +207,9 @@ opt::Instruction* FoldSpecConstantOpAndCompositePass::DoCompositeExtract( current_const, pos); } -opt::Instruction* FoldSpecConstantOpAndCompositePass::DoVectorShuffle( - opt::Module::inst_iterator* pos) { - opt::Instruction* inst = &**pos; +Instruction* FoldSpecConstantOpAndCompositePass::DoVectorShuffle( + Module::inst_iterator* pos) { + Instruction* inst = &**pos; analysis::Vector* result_vec_type = context()->get_constant_mgr()->GetType(inst)->AsVector(); assert(inst->NumInOperands() - 1 > 2 && @@ -312,9 +312,9 @@ bool IsValidTypeForComponentWiseOperation(const analysis::Type* type) { } } // namespace -opt::Instruction* FoldSpecConstantOpAndCompositePass::DoComponentWiseOperation( - opt::Module::inst_iterator* pos) { - const opt::Instruction* inst = &**pos; +Instruction* FoldSpecConstantOpAndCompositePass::DoComponentWiseOperation( + Module::inst_iterator* pos) { + const Instruction* inst = &**pos; const analysis::Type* result_type = context()->get_constant_mgr()->GetType(inst); SpvOp spec_opcode = static_cast<SpvOp>(inst->GetSingleWordInOperand(0)); @@ -322,8 +322,7 @@ opt::Instruction* FoldSpecConstantOpAndCompositePass::DoComponentWiseOperation( std::vector<const analysis::Constant*> operands; if (!std::all_of( - inst->cbegin(), inst->cend(), - [&operands, this](const opt::Operand& o) { + inst->cbegin(), inst->cend(), [&operands, this](const Operand& o) { // skip the operands that is not an id. if (o.type != spv_operand_type_t::SPV_OPERAND_TYPE_ID) return true; uint32_t id = o.words.front(); diff --git a/source/opt/fold_spec_constant_op_and_composite_pass.h b/source/opt/fold_spec_constant_op_and_composite_pass.h index 738bf0c1..ab27a629 100644 --- a/source/opt/fold_spec_constant_op_and_composite_pass.h +++ b/source/opt/fold_spec_constant_op_and_composite_pass.h @@ -52,27 +52,25 @@ class FoldSpecConstantOpAndCompositePass : public Pass { // folding is done successfully, the original OpSpecConstantOp instruction // will be changed to Nop and new folded instruction will be inserted before // it. - bool ProcessOpSpecConstantOp(opt::Module::inst_iterator* pos); + bool ProcessOpSpecConstantOp(Module::inst_iterator* pos); // Try to fold the OpSpecConstantOp CompositeExtract instruction pointed by // the given instruction iterator to a normal constant defining instruction. // Returns the pointer to the new constant defining instruction if succeeded. // Otherwise returns nullptr. - opt::Instruction* DoCompositeExtract( - opt::Module::inst_iterator* inst_iter_ptr); + Instruction* DoCompositeExtract(Module::inst_iterator* inst_iter_ptr); // Try to fold the OpSpecConstantOp VectorShuffle instruction pointed by the // given instruction iterator to a normal constant defining instruction. // Returns the pointer to the new constant defining instruction if succeeded. // Otherwise return nullptr. - opt::Instruction* DoVectorShuffle(opt::Module::inst_iterator* inst_iter_ptr); + Instruction* DoVectorShuffle(Module::inst_iterator* inst_iter_ptr); // Try to fold the OpSpecConstantOp <component wise operations> instruction // pointed by the given instruction iterator to a normal constant defining // instruction. Returns the pointer to the new constant defining instruction // if succeeded, otherwise return nullptr. - opt::Instruction* DoComponentWiseOperation( - opt::Module::inst_iterator* inst_iter_ptr); + Instruction* DoComponentWiseOperation(Module::inst_iterator* inst_iter_ptr); // Returns the |element|'th subtype of |type|. // diff --git a/source/opt/folding_rules.cpp b/source/opt/folding_rules.cpp index edc73488..3d3cf31d 100644 --- a/source/opt/folding_rules.cpp +++ b/source/opt/folding_rules.cpp @@ -75,9 +75,8 @@ const analysis::Constant* ConstInput( return constants[0] ? constants[0] : constants[1]; } -opt::Instruction* NonConstInput(opt::IRContext* context, - const analysis::Constant* c, - opt::Instruction* inst) { +Instruction* NonConstInput(IRContext* context, const analysis::Constant* c, + Instruction* inst) { uint32_t in_op = c ? 1u : 0u; return context->get_def_use_mgr()->GetDef( inst->GetSingleWordInOperand(in_op)); @@ -199,7 +198,7 @@ uint32_t Reciprocal(analysis::ConstantManager* const_mgr, // Replaces fdiv where second operand is constant with fmul. FoldingRule ReciprocalFDiv() { - return [](IRContext* context, opt::Instruction* inst, + return [](IRContext* context, Instruction* inst, const std::vector<const analysis::Constant*>& constants) { assert(inst->opcode() == SpvOpFDiv); analysis::ConstantManager* const_mgr = context->get_constant_mgr(); @@ -243,7 +242,7 @@ FoldingRule ReciprocalFDiv() { // Elides consecutive negate instructions. FoldingRule MergeNegateArithmetic() { - return [](IRContext* context, opt::Instruction* inst, + return [](IRContext* context, Instruction* inst, const std::vector<const analysis::Constant*>& constants) { assert(inst->opcode() == SpvOpFNegate || inst->opcode() == SpvOpSNegate); (void)constants; @@ -252,7 +251,7 @@ FoldingRule MergeNegateArithmetic() { if (HasFloatingPoint(type) && !inst->IsFloatingPointFoldingAllowed()) return false; - opt::Instruction* op_inst = + Instruction* op_inst = context->get_def_use_mgr()->GetDef(inst->GetSingleWordInOperand(0u)); if (HasFloatingPoint(type) && !op_inst->IsFloatingPointFoldingAllowed()) return false; @@ -277,7 +276,7 @@ FoldingRule MergeNegateArithmetic() { // -(x / 2) = x / -2 // -(2 / x) = -2 / x FoldingRule MergeNegateMulDivArithmetic() { - return [](IRContext* context, opt::Instruction* inst, + return [](IRContext* context, Instruction* inst, const std::vector<const analysis::Constant*>& constants) { assert(inst->opcode() == SpvOpFNegate || inst->opcode() == SpvOpSNegate); (void)constants; @@ -287,7 +286,7 @@ FoldingRule MergeNegateMulDivArithmetic() { if (HasFloatingPoint(type) && !inst->IsFloatingPointFoldingAllowed()) return false; - opt::Instruction* op_inst = + Instruction* op_inst = context->get_def_use_mgr()->GetDef(inst->GetSingleWordInOperand(0u)); if (HasFloatingPoint(type) && !op_inst->IsFloatingPointFoldingAllowed()) return false; @@ -335,7 +334,7 @@ FoldingRule MergeNegateMulDivArithmetic() { // -(x - 2) = 2 - x // -(2 - x) = x - 2 FoldingRule MergeNegateAddSubArithmetic() { - return [](IRContext* context, opt::Instruction* inst, + return [](IRContext* context, Instruction* inst, const std::vector<const analysis::Constant*>& constants) { assert(inst->opcode() == SpvOpFNegate || inst->opcode() == SpvOpSNegate); (void)constants; @@ -345,7 +344,7 @@ FoldingRule MergeNegateAddSubArithmetic() { if (HasFloatingPoint(type) && !inst->IsFloatingPointFoldingAllowed()) return false; - opt::Instruction* op_inst = + Instruction* op_inst = context->get_def_use_mgr()->GetDef(inst->GetSingleWordInOperand(0u)); if (HasFloatingPoint(type) && !op_inst->IsFloatingPointFoldingAllowed()) return false; @@ -567,7 +566,7 @@ uint32_t PerformOperation(analysis::ConstantManager* const_mgr, SpvOp opcode, // (x * 2) * 2 = x * 4 // (2 * x) * 2 = x * 4 FoldingRule MergeMulMulArithmetic() { - return [](IRContext* context, opt::Instruction* inst, + return [](IRContext* context, Instruction* inst, const std::vector<const analysis::Constant*>& constants) { assert(inst->opcode() == SpvOpFMul || inst->opcode() == SpvOpIMul); analysis::ConstantManager* const_mgr = context->get_constant_mgr(); @@ -582,7 +581,7 @@ FoldingRule MergeMulMulArithmetic() { // Determine the constant input and the variable input in |inst|. const analysis::Constant* const_input1 = ConstInput(constants); if (!const_input1) return false; - opt::Instruction* other_inst = NonConstInput(context, constants[0], inst); + Instruction* other_inst = NonConstInput(context, constants[0], inst); if (HasFloatingPoint(type) && !other_inst->IsFloatingPointFoldingAllowed()) return false; @@ -619,7 +618,7 @@ FoldingRule MergeMulMulArithmetic() { // (y / x) * x = y // x * (y / x) = y FoldingRule MergeMulDivArithmetic() { - return [](IRContext* context, opt::Instruction* inst, + return [](IRContext* context, Instruction* inst, const std::vector<const analysis::Constant*>& constants) { assert(inst->opcode() == SpvOpFMul); analysis::ConstantManager* const_mgr = context->get_constant_mgr(); @@ -634,7 +633,7 @@ FoldingRule MergeMulDivArithmetic() { for (uint32_t i = 0; i < 2; i++) { uint32_t op_id = inst->GetSingleWordInOperand(i); - opt::Instruction* op_inst = def_use_mgr->GetDef(op_id); + Instruction* op_inst = def_use_mgr->GetDef(op_id); if (op_inst->opcode() == SpvOpFDiv) { if (op_inst->GetSingleWordInOperand(1) == inst->GetSingleWordInOperand(1 - i)) { @@ -648,7 +647,7 @@ FoldingRule MergeMulDivArithmetic() { const analysis::Constant* const_input1 = ConstInput(constants); if (!const_input1) return false; - opt::Instruction* other_inst = NonConstInput(context, constants[0], inst); + Instruction* other_inst = NonConstInput(context, constants[0], inst); if (!other_inst->IsFloatingPointFoldingAllowed()) return false; if (other_inst->opcode() == SpvOpFDiv) { @@ -693,7 +692,7 @@ FoldingRule MergeMulDivArithmetic() { // (-x) * 2 = x * -2 // 2 * (-x) = x * -2 FoldingRule MergeMulNegateArithmetic() { - return [](IRContext* context, opt::Instruction* inst, + return [](IRContext* context, Instruction* inst, const std::vector<const analysis::Constant*>& constants) { assert(inst->opcode() == SpvOpFMul || inst->opcode() == SpvOpIMul); analysis::ConstantManager* const_mgr = context->get_constant_mgr(); @@ -707,7 +706,7 @@ FoldingRule MergeMulNegateArithmetic() { const analysis::Constant* const_input1 = ConstInput(constants); if (!const_input1) return false; - opt::Instruction* other_inst = NonConstInput(context, constants[0], inst); + Instruction* other_inst = NonConstInput(context, constants[0], inst); if (uses_float && !other_inst->IsFloatingPointFoldingAllowed()) return false; @@ -733,7 +732,7 @@ FoldingRule MergeMulNegateArithmetic() { // (4 / x) / 2 = 2 / x // (x / 2) / 2 = x / 4 FoldingRule MergeDivDivArithmetic() { - return [](IRContext* context, opt::Instruction* inst, + return [](IRContext* context, Instruction* inst, const std::vector<const analysis::Constant*>& constants) { assert(inst->opcode() == SpvOpFDiv); analysis::ConstantManager* const_mgr = context->get_constant_mgr(); @@ -746,7 +745,7 @@ FoldingRule MergeDivDivArithmetic() { const analysis::Constant* const_input1 = ConstInput(constants); if (!const_input1 || HasZero(const_input1)) return false; - opt::Instruction* other_inst = NonConstInput(context, constants[0], inst); + Instruction* other_inst = NonConstInput(context, constants[0], inst); if (!other_inst->IsFloatingPointFoldingAllowed()) return false; bool first_is_variable = constants[0] == nullptr; @@ -804,7 +803,7 @@ FoldingRule MergeDivDivArithmetic() { // (x * y) / x = y // (y * x) / x = y FoldingRule MergeDivMulArithmetic() { - return [](IRContext* context, opt::Instruction* inst, + return [](IRContext* context, Instruction* inst, const std::vector<const analysis::Constant*>& constants) { assert(inst->opcode() == SpvOpFDiv); analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr(); @@ -818,7 +817,7 @@ FoldingRule MergeDivMulArithmetic() { if (width != 32 && width != 64) return false; uint32_t op_id = inst->GetSingleWordInOperand(0); - opt::Instruction* op_inst = def_use_mgr->GetDef(op_id); + Instruction* op_inst = def_use_mgr->GetDef(op_id); if (op_inst->opcode() == SpvOpFMul) { for (uint32_t i = 0; i < 2; i++) { @@ -834,7 +833,7 @@ FoldingRule MergeDivMulArithmetic() { const analysis::Constant* const_input1 = ConstInput(constants); if (!const_input1 || HasZero(const_input1)) return false; - opt::Instruction* other_inst = NonConstInput(context, constants[0], inst); + Instruction* other_inst = NonConstInput(context, constants[0], inst); if (!other_inst->IsFloatingPointFoldingAllowed()) return false; bool first_is_variable = constants[0] == nullptr; @@ -876,7 +875,7 @@ FoldingRule MergeDivMulArithmetic() { // (-x) / 2 = x / -2 // 2 / (-x) = 2 / -x FoldingRule MergeDivNegateArithmetic() { - return [](IRContext* context, opt::Instruction* inst, + return [](IRContext* context, Instruction* inst, const std::vector<const analysis::Constant*>& constants) { assert(inst->opcode() == SpvOpFDiv || inst->opcode() == SpvOpSDiv || inst->opcode() == SpvOpUDiv); @@ -891,7 +890,7 @@ FoldingRule MergeDivNegateArithmetic() { const analysis::Constant* const_input1 = ConstInput(constants); if (!const_input1) return false; - opt::Instruction* other_inst = NonConstInput(context, constants[0], inst); + Instruction* other_inst = NonConstInput(context, constants[0], inst); if (uses_float && !other_inst->IsFloatingPointFoldingAllowed()) return false; @@ -921,7 +920,7 @@ FoldingRule MergeDivNegateArithmetic() { // (-x) + 2 = 2 - x // 2 + (-x) = 2 - x FoldingRule MergeAddNegateArithmetic() { - return [](IRContext* context, opt::Instruction* inst, + return [](IRContext* context, Instruction* inst, const std::vector<const analysis::Constant*>& constants) { assert(inst->opcode() == SpvOpFAdd || inst->opcode() == SpvOpIAdd); const analysis::Type* type = @@ -931,7 +930,7 @@ FoldingRule MergeAddNegateArithmetic() { const analysis::Constant* const_input1 = ConstInput(constants); if (!const_input1) return false; - opt::Instruction* other_inst = NonConstInput(context, constants[0], inst); + Instruction* other_inst = NonConstInput(context, constants[0], inst); if (uses_float && !other_inst->IsFloatingPointFoldingAllowed()) return false; @@ -954,7 +953,7 @@ FoldingRule MergeAddNegateArithmetic() { // (-x) - 2 = -2 - x // 2 - (-x) = x + 2 FoldingRule MergeSubNegateArithmetic() { - return [](IRContext* context, opt::Instruction* inst, + return [](IRContext* context, Instruction* inst, const std::vector<const analysis::Constant*>& constants) { assert(inst->opcode() == SpvOpFSub || inst->opcode() == SpvOpISub); analysis::ConstantManager* const_mgr = context->get_constant_mgr(); @@ -968,7 +967,7 @@ FoldingRule MergeSubNegateArithmetic() { const analysis::Constant* const_input1 = ConstInput(constants); if (!const_input1) return false; - opt::Instruction* other_inst = NonConstInput(context, constants[0], inst); + Instruction* other_inst = NonConstInput(context, constants[0], inst); if (uses_float && !other_inst->IsFloatingPointFoldingAllowed()) return false; @@ -1002,7 +1001,7 @@ FoldingRule MergeSubNegateArithmetic() { // 2 + (x + 2) = x + 4 // 2 + (2 + x) = x + 4 FoldingRule MergeAddAddArithmetic() { - return [](IRContext* context, opt::Instruction* inst, + return [](IRContext* context, Instruction* inst, const std::vector<const analysis::Constant*>& constants) { assert(inst->opcode() == SpvOpFAdd || inst->opcode() == SpvOpIAdd); const analysis::Type* type = @@ -1016,7 +1015,7 @@ FoldingRule MergeAddAddArithmetic() { const analysis::Constant* const_input1 = ConstInput(constants); if (!const_input1) return false; - opt::Instruction* other_inst = NonConstInput(context, constants[0], inst); + Instruction* other_inst = NonConstInput(context, constants[0], inst); if (uses_float && !other_inst->IsFloatingPointFoldingAllowed()) return false; @@ -1027,7 +1026,7 @@ FoldingRule MergeAddAddArithmetic() { const analysis::Constant* const_input2 = ConstInput(other_constants); if (!const_input2) return false; - opt::Instruction* non_const_input = + Instruction* non_const_input = NonConstInput(context, other_constants[0], other_inst); uint32_t merged_id = PerformOperation(const_mgr, inst->opcode(), const_input1, const_input2); @@ -1049,7 +1048,7 @@ FoldingRule MergeAddAddArithmetic() { // 2 + (x - 2) = x + 0 // 2 + (2 - x) = 4 - x FoldingRule MergeAddSubArithmetic() { - return [](IRContext* context, opt::Instruction* inst, + return [](IRContext* context, Instruction* inst, const std::vector<const analysis::Constant*>& constants) { assert(inst->opcode() == SpvOpFAdd || inst->opcode() == SpvOpIAdd); const analysis::Type* type = @@ -1063,7 +1062,7 @@ FoldingRule MergeAddSubArithmetic() { const analysis::Constant* const_input1 = ConstInput(constants); if (!const_input1) return false; - opt::Instruction* other_inst = NonConstInput(context, constants[0], inst); + Instruction* other_inst = NonConstInput(context, constants[0], inst); if (uses_float && !other_inst->IsFloatingPointFoldingAllowed()) return false; @@ -1108,7 +1107,7 @@ FoldingRule MergeAddSubArithmetic() { // 2 - (x + 2) = 0 - x // 2 - (2 + x) = 0 - x FoldingRule MergeSubAddArithmetic() { - return [](IRContext* context, opt::Instruction* inst, + return [](IRContext* context, Instruction* inst, const std::vector<const analysis::Constant*>& constants) { assert(inst->opcode() == SpvOpFSub || inst->opcode() == SpvOpISub); const analysis::Type* type = @@ -1122,7 +1121,7 @@ FoldingRule MergeSubAddArithmetic() { const analysis::Constant* const_input1 = ConstInput(constants); if (!const_input1) return false; - opt::Instruction* other_inst = NonConstInput(context, constants[0], inst); + Instruction* other_inst = NonConstInput(context, constants[0], inst); if (uses_float && !other_inst->IsFloatingPointFoldingAllowed()) return false; @@ -1133,7 +1132,7 @@ FoldingRule MergeSubAddArithmetic() { const analysis::Constant* const_input2 = ConstInput(other_constants); if (!const_input2) return false; - opt::Instruction* non_const_input = + Instruction* non_const_input = NonConstInput(context, other_constants[0], other_inst); // If the first operand of the sub is not a constant, swap the constants @@ -1173,7 +1172,7 @@ FoldingRule MergeSubAddArithmetic() { // 2 - (x - 2) = 4 - x // 2 - (2 - x) = x + 0 FoldingRule MergeSubSubArithmetic() { - return [](IRContext* context, opt::Instruction* inst, + return [](IRContext* context, Instruction* inst, const std::vector<const analysis::Constant*>& constants) { assert(inst->opcode() == SpvOpFSub || inst->opcode() == SpvOpISub); const analysis::Type* type = @@ -1187,7 +1186,7 @@ FoldingRule MergeSubSubArithmetic() { const analysis::Constant* const_input1 = ConstInput(constants); if (!const_input1) return false; - opt::Instruction* other_inst = NonConstInput(context, constants[0], inst); + Instruction* other_inst = NonConstInput(context, constants[0], inst); if (uses_float && !other_inst->IsFloatingPointFoldingAllowed()) return false; @@ -1198,7 +1197,7 @@ FoldingRule MergeSubSubArithmetic() { const analysis::Constant* const_input2 = ConstInput(other_constants); if (!const_input2) return false; - opt::Instruction* non_const_input = + Instruction* non_const_input = NonConstInput(context, other_constants[0], other_inst); // Merge the constants. @@ -1239,7 +1238,7 @@ FoldingRule MergeSubSubArithmetic() { } FoldingRule IntMultipleBy1() { - return [](IRContext*, opt::Instruction* inst, + return [](IRContext*, Instruction* inst, const std::vector<const analysis::Constant*>& constants) { assert(inst->opcode() == SpvOpIMul && "Wrong opcode. Should be OpIMul."); for (uint32_t i = 0; i < 2; i++) { @@ -1265,7 +1264,7 @@ FoldingRule IntMultipleBy1() { } FoldingRule CompositeConstructFeedingExtract() { - return [](IRContext* context, opt::Instruction* inst, + return [](IRContext* context, Instruction* inst, const std::vector<const analysis::Constant*>&) { // If the input to an OpCompositeExtract is an OpCompositeConstruct, // then we can simply use the appropriate element in the construction. @@ -1274,13 +1273,13 @@ FoldingRule CompositeConstructFeedingExtract() { analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr(); analysis::TypeManager* type_mgr = context->get_type_mgr(); uint32_t cid = inst->GetSingleWordInOperand(kExtractCompositeIdInIdx); - opt::Instruction* cinst = def_use_mgr->GetDef(cid); + Instruction* cinst = def_use_mgr->GetDef(cid); if (cinst->opcode() != SpvOpCompositeConstruct) { return false; } - std::vector<opt::Operand> operands; + std::vector<Operand> operands; analysis::Type* composite_type = type_mgr->GetType(cinst->type_id()); if (composite_type->AsVector() == nullptr) { // Get the element being extracted from the OpCompositeConstruct @@ -1305,7 +1304,7 @@ FoldingRule CompositeConstructFeedingExtract() { for (uint32_t construct_index = 0; construct_index < cinst->NumInOperands(); ++construct_index) { uint32_t element_id = cinst->GetSingleWordInOperand(construct_index); - opt::Instruction* element_def = def_use_mgr->GetDef(element_id); + Instruction* element_def = def_use_mgr->GetDef(element_id); analysis::Vector* element_type = type_mgr->GetType(element_def->type_id())->AsVector(); if (element_type) { @@ -1350,7 +1349,7 @@ FoldingRule CompositeExtractFeedingConstruct() { // // This is a common code pattern because of the way that scalar replacement // works. - return [](IRContext* context, opt::Instruction* inst, + return [](IRContext* context, Instruction* inst, const std::vector<const analysis::Constant*>&) { assert(inst->opcode() == SpvOpCompositeConstruct && "Wrong opcode. Should be OpCompositeConstruct."); @@ -1363,7 +1362,7 @@ FoldingRule CompositeExtractFeedingConstruct() { // - all extract from the same id. for (uint32_t i = 0; i < inst->NumInOperands(); ++i) { uint32_t element_id = inst->GetSingleWordInOperand(i); - opt::Instruction* element_inst = def_use_mgr->GetDef(element_id); + Instruction* element_inst = def_use_mgr->GetDef(element_id); if (element_inst->opcode() != SpvOpCompositeExtract) { return false; @@ -1388,7 +1387,7 @@ FoldingRule CompositeExtractFeedingConstruct() { // The last check it to see that the object being extracted from is the // correct type. - opt::Instruction* original_inst = def_use_mgr->GetDef(original_id); + Instruction* original_inst = def_use_mgr->GetDef(original_id); if (original_inst->type_id() != inst->type_id()) { return false; } @@ -1401,13 +1400,13 @@ FoldingRule CompositeExtractFeedingConstruct() { } FoldingRule InsertFeedingExtract() { - return [](IRContext* context, opt::Instruction* inst, + return [](IRContext* context, Instruction* inst, const std::vector<const analysis::Constant*>&) { assert(inst->opcode() == SpvOpCompositeExtract && "Wrong opcode. Should be OpCompositeExtract."); analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr(); uint32_t cid = inst->GetSingleWordInOperand(kExtractCompositeIdInIdx); - opt::Instruction* cinst = def_use_mgr->GetDef(cid); + Instruction* cinst = def_use_mgr->GetDef(cid); if (cinst->opcode() != SpvOpCompositeInsert) { return false; @@ -1445,7 +1444,7 @@ FoldingRule InsertFeedingExtract() { // Extracting an element of the value that was inserted. Extract from // that value directly. if (i + 1 == cinst->NumInOperands()) { - std::vector<opt::Operand> operands; + std::vector<Operand> operands; operands.push_back( {SPV_OPERAND_TYPE_ID, {cinst->GetSingleWordInOperand(kInsertObjectIdInIdx)}}); @@ -1459,7 +1458,7 @@ FoldingRule InsertFeedingExtract() { // Extracting a value that is disjoint from the element being inserted. // Rewrite the extract to use the composite input to the insert. - std::vector<opt::Operand> operands; + std::vector<Operand> operands; operands.push_back( {SPV_OPERAND_TYPE_ID, {cinst->GetSingleWordInOperand(kInsertCompositeIdInIdx)}}); @@ -1476,21 +1475,21 @@ FoldingRule InsertFeedingExtract() { // operands of the VectorShuffle. We just need to adjust the index in the // extract instruction. FoldingRule VectorShuffleFeedingExtract() { - return [](IRContext* context, opt::Instruction* inst, + return [](IRContext* context, Instruction* inst, const std::vector<const analysis::Constant*>&) { assert(inst->opcode() == SpvOpCompositeExtract && "Wrong opcode. Should be OpCompositeExtract."); analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr(); analysis::TypeManager* type_mgr = context->get_type_mgr(); uint32_t cid = inst->GetSingleWordInOperand(kExtractCompositeIdInIdx); - opt::Instruction* cinst = def_use_mgr->GetDef(cid); + Instruction* cinst = def_use_mgr->GetDef(cid); if (cinst->opcode() != SpvOpVectorShuffle) { return false; } // Find the size of the first vector operand of the VectorShuffle - opt::Instruction* first_input = + Instruction* first_input = def_use_mgr->GetDef(cinst->GetSingleWordInOperand(0)); analysis::Type* first_input_type = type_mgr->GetType(first_input->type_id()); @@ -1524,7 +1523,7 @@ FoldingRule VectorShuffleFeedingExtract() { // corresponding |a| in the FMix is 0 or 1, we can extract from one of the // operands of the FMix. FoldingRule FMixFeedingExtract() { - return [](IRContext* context, opt::Instruction* inst, + return [](IRContext* context, Instruction* inst, const std::vector<const analysis::Constant*>&) { assert(inst->opcode() == SpvOpCompositeExtract && "Wrong opcode. Should be OpCompositeExtract."); @@ -1533,7 +1532,7 @@ FoldingRule FMixFeedingExtract() { uint32_t composite_id = inst->GetSingleWordInOperand(kExtractCompositeIdInIdx); - opt::Instruction* composite_inst = def_use_mgr->GetDef(composite_id); + Instruction* composite_inst = def_use_mgr->GetDef(composite_id); if (composite_inst->opcode() != SpvOpExtInst) { return false; @@ -1551,7 +1550,7 @@ FoldingRule FMixFeedingExtract() { // Get the |a| for the FMix instruction. uint32_t a_id = composite_inst->GetSingleWordInOperand(kFMixAIdInIdx); - std::unique_ptr<opt::Instruction> a(inst->Clone(context)); + std::unique_ptr<Instruction> a(inst->Clone(context)); a->SetInOperand(kExtractCompositeIdInIdx, {a_id}); context->get_instruction_folder().FoldInstruction(a.get()); @@ -1595,7 +1594,7 @@ FoldingRule FMixFeedingExtract() { FoldingRule RedundantPhi() { // An OpPhi instruction where all values are the same or the result of the phi // itself, can be replaced by the value itself. - return [](IRContext*, opt::Instruction* inst, + return [](IRContext*, Instruction* inst, const std::vector<const analysis::Constant*>&) { assert(inst->opcode() == SpvOpPhi && "Wrong opcode. Should be OpPhi."); @@ -1630,7 +1629,7 @@ FoldingRule RedundantPhi() { FoldingRule RedundantSelect() { // An OpSelect instruction where both values are the same or the condition is // constant can be replaced by one of the values - return [](IRContext*, opt::Instruction* inst, + return [](IRContext*, Instruction* inst, const std::vector<const analysis::Constant*>& constants) { assert(inst->opcode() == SpvOpSelect && "Wrong opcode. Should be OpSelect."); @@ -1666,7 +1665,7 @@ FoldingRule RedundantSelect() { return true; } else { // Convert to a vector shuffle. - std::vector<opt::Operand> ops; + std::vector<Operand> ops; ops.push_back({SPV_OPERAND_TYPE_ID, {true_id}}); ops.push_back({SPV_OPERAND_TYPE_ID, {false_id}}); const analysis::VectorConstant* vector_const = @@ -1746,7 +1745,7 @@ FloatConstantKind getFloatConstantKind(const analysis::Constant* constant) { } FoldingRule RedundantFAdd() { - return [](IRContext*, opt::Instruction* inst, + return [](IRContext*, Instruction* inst, const std::vector<const analysis::Constant*>& constants) { assert(inst->opcode() == SpvOpFAdd && "Wrong opcode. Should be OpFAdd."); assert(constants.size() == 2); @@ -1771,7 +1770,7 @@ FoldingRule RedundantFAdd() { } FoldingRule RedundantFSub() { - return [](IRContext*, opt::Instruction* inst, + return [](IRContext*, Instruction* inst, const std::vector<const analysis::Constant*>& constants) { assert(inst->opcode() == SpvOpFSub && "Wrong opcode. Should be OpFSub."); assert(constants.size() == 2); @@ -1802,7 +1801,7 @@ FoldingRule RedundantFSub() { } FoldingRule RedundantFMul() { - return [](IRContext*, opt::Instruction* inst, + return [](IRContext*, Instruction* inst, const std::vector<const analysis::Constant*>& constants) { assert(inst->opcode() == SpvOpFMul && "Wrong opcode. Should be OpFMul."); assert(constants.size() == 2); @@ -1835,7 +1834,7 @@ FoldingRule RedundantFMul() { } FoldingRule RedundantFDiv() { - return [](IRContext*, opt::Instruction* inst, + return [](IRContext*, Instruction* inst, const std::vector<const analysis::Constant*>& constants) { assert(inst->opcode() == SpvOpFDiv && "Wrong opcode. Should be OpFDiv."); assert(constants.size() == 2); @@ -1866,7 +1865,7 @@ FoldingRule RedundantFDiv() { } FoldingRule RedundantFMix() { - return [](IRContext* context, opt::Instruction* inst, + return [](IRContext* context, Instruction* inst, const std::vector<const analysis::Constant*>& constants) { assert(inst->opcode() == SpvOpExtInst && "Wrong opcode. Should be OpExtInst."); @@ -1903,7 +1902,7 @@ FoldingRule RedundantFMix() { // This rule look for a dot with a constant vector containing a single 1 and // the rest 0s. This is the same as doing an extract. FoldingRule DotProductDoingExtract() { - return [](IRContext* context, opt::Instruction* inst, + return [](IRContext* context, Instruction* inst, const std::vector<const analysis::Constant*>& constants) { assert(inst->opcode() == SpvOpDot && "Wrong opcode. Should be OpDot."); @@ -1958,7 +1957,7 @@ FoldingRule DotProductDoingExtract() { continue; } - std::vector<opt::Operand> operands; + std::vector<Operand> operands; operands.push_back( {SPV_OPERAND_TYPE_ID, {inst->GetSingleWordInOperand(1u - i)}}); operands.push_back( @@ -1977,7 +1976,7 @@ FoldingRule DotProductDoingExtract() { // TODO: We can do something similar for OpImageWrite, but checking for volatile // is complicated. Waiting to see if it is needed. FoldingRule StoringUndef() { - return [](IRContext* context, opt::Instruction* inst, + return [](IRContext* context, Instruction* inst, const std::vector<const analysis::Constant*>&) { assert(inst->opcode() == SpvOpStore && "Wrong opcode. Should be OpStore."); @@ -1991,7 +1990,7 @@ FoldingRule StoringUndef() { } uint32_t object_id = inst->GetSingleWordInOperand(kStoreObjectInIdx); - opt::Instruction* object_inst = def_use_mgr->GetDef(object_id); + Instruction* object_inst = def_use_mgr->GetDef(object_id); if (object_inst->opcode() == SpvOpUndef) { inst->ToNop(); return true; @@ -2001,7 +2000,7 @@ FoldingRule StoringUndef() { } FoldingRule VectorShuffleFeedingShuffle() { - return [](IRContext* context, opt::Instruction* inst, + return [](IRContext* context, Instruction* inst, const std::vector<const analysis::Constant*>&) { assert(inst->opcode() == SpvOpVectorShuffle && "Wrong opcode. Should be OpVectorShuffle."); diff --git a/source/opt/folding_rules.h b/source/opt/folding_rules.h index d807ec1e..efb58ec5 100644 --- a/source/opt/folding_rules.h +++ b/source/opt/folding_rules.h @@ -52,7 +52,7 @@ namespace opt { // the later rules will not be attempted. using FoldingRule = std::function<bool( - IRContext* context, opt::Instruction* inst, + IRContext* context, Instruction* inst, const std::vector<const analysis::Constant*>& constants)>; class FoldingRules { diff --git a/source/opt/freeze_spec_constant_value_pass.cpp b/source/opt/freeze_spec_constant_value_pass.cpp index 18a695fb..60de4b2b 100644 --- a/source/opt/freeze_spec_constant_value_pass.cpp +++ b/source/opt/freeze_spec_constant_value_pass.cpp @@ -21,7 +21,7 @@ namespace opt { Pass::Status FreezeSpecConstantValuePass::Process() { bool modified = false; auto ctx = context(); - ctx->module()->ForEachInst([&modified, ctx](opt::Instruction* inst) { + ctx->module()->ForEachInst([&modified, ctx](Instruction* inst) { switch (inst->opcode()) { case SpvOp::SpvOpSpecConstant: inst->SetOpcode(SpvOp::SpvOpConstant); diff --git a/source/opt/function.cpp b/source/opt/function.cpp index 943022e2..0fbf1e9f 100644 --- a/source/opt/function.cpp +++ b/source/opt/function.cpp @@ -96,7 +96,7 @@ std::ostream& operator<<(std::ostream& str, const Function& func) { std::string Function::PrettyPrint(uint32_t options) const { std::ostringstream str; - ForEachInst([&str, options](const opt::Instruction* inst) { + ForEachInst([&str, options](const Instruction* inst) { str << inst->PrettyPrint(options); if (inst->opcode() != SpvOpFunctionEnd) { str << std::endl; diff --git a/source/opt/function.h b/source/opt/function.h index ff43430c..3c5cc929 100644 --- a/source/opt/function.h +++ b/source/opt/function.h @@ -98,7 +98,7 @@ class Function { // Returns an iterator to the basic block |id|. iterator FindBlock(uint32_t bb_id) { - return std::find_if(begin(), end(), [bb_id](const opt::BasicBlock& it_bb) { + return std::find_if(begin(), end(), [bb_id](const BasicBlock& it_bb) { return bb_id == it_bb.id(); }); } @@ -115,8 +115,8 @@ class Function { void ForEachParam(const std::function<void(const Instruction*)>& f, bool run_on_debug_line_insts = false) const; - BasicBlock* InsertBasicBlockAfter( - std::unique_ptr<opt::BasicBlock>&& new_block, BasicBlock* position); + BasicBlock* InsertBasicBlockAfter(std::unique_ptr<BasicBlock>&& new_block, + BasicBlock* position); // Pretty-prints all the basic blocks in this function into a std::string. // diff --git a/source/opt/if_conversion.cpp b/source/opt/if_conversion.cpp index b4ec8ebf..2e599519 100644 --- a/source/opt/if_conversion.cpp +++ b/source/opt/if_conversion.cpp @@ -22,13 +22,13 @@ namespace opt { Pass::Status IfConversion::Process() { const ValueNumberTable& vn_table = *context()->GetValueNumberTable(); bool modified = false; - std::vector<opt::Instruction*> to_kill; + std::vector<Instruction*> to_kill; for (auto& func : *get_module()) { DominatorAnalysis* dominators = context()->GetDominatorAnalysis(&func); for (auto& block : func) { // Check if it is possible for |block| to have phis that can be // transformed. - opt::BasicBlock* common = nullptr; + BasicBlock* common = nullptr; if (!CheckBlock(&block, dominators, &common)) continue; // Get an insertion point. @@ -39,11 +39,9 @@ Pass::Status IfConversion::Process() { InstructionBuilder builder( context(), &*iter, - opt::IRContext::kAnalysisDefUse | - opt::IRContext::kAnalysisInstrToBlockMapping); + IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping); block.ForEachPhiInst([this, &builder, &modified, &common, &to_kill, - dominators, &block, - &vn_table](opt::Instruction* phi) { + dominators, &block, &vn_table](Instruction* phi) { // This phi is not compatible, but subsequent phis might be. if (!CheckType(phi->type_id())) return; @@ -57,13 +55,12 @@ Pass::Status IfConversion::Process() { // branches. If |then_block| dominates |inc0| or if the true edge // branches straight to this block and |common| is |inc0|, then |inc0| // is on the true branch. Otherwise the |inc1| is on the true branch. - opt::BasicBlock* inc0 = GetIncomingBlock(phi, 0u); - opt::Instruction* branch = common->terminator(); + BasicBlock* inc0 = GetIncomingBlock(phi, 0u); + Instruction* branch = common->terminator(); uint32_t condition = branch->GetSingleWordInOperand(0u); - opt::BasicBlock* then_block = - GetBlock(branch->GetSingleWordInOperand(1u)); - opt::Instruction* true_value = nullptr; - opt::Instruction* false_value = nullptr; + BasicBlock* then_block = GetBlock(branch->GetSingleWordInOperand(1u)); + Instruction* true_value = nullptr; + Instruction* false_value = nullptr; if ((then_block == &block && inc0 == common) || dominators->Dominates(then_block, inc0)) { true_value = GetIncomingValue(phi, 0u); @@ -73,15 +70,13 @@ Pass::Status IfConversion::Process() { false_value = GetIncomingValue(phi, 0u); } - opt::BasicBlock* true_def_block = - context()->get_instr_block(true_value); - opt::BasicBlock* false_def_block = - context()->get_instr_block(false_value); + BasicBlock* true_def_block = context()->get_instr_block(true_value); + BasicBlock* false_def_block = context()->get_instr_block(false_value); uint32_t true_vn = vn_table.GetValueNumber(true_value); uint32_t false_vn = vn_table.GetValueNumber(false_value); if (true_vn != 0 && true_vn == false_vn) { - opt::Instruction* inst_to_use = nullptr; + Instruction* inst_to_use = nullptr; // Try to pick an instruction that is not in a side node. If we can't // pick either the true for false branch as long as they can be @@ -124,9 +119,9 @@ Pass::Status IfConversion::Process() { condition = SplatCondition(vec_data_ty, condition, &builder); } - opt::Instruction* select = builder.AddSelect(phi->type_id(), condition, - true_value->result_id(), - false_value->result_id()); + Instruction* select = builder.AddSelect(phi->type_id(), condition, + true_value->result_id(), + false_value->result_id()); context()->ReplaceAllUsesWith(phi->result_id(), select->result_id()); to_kill.push_back(phi); modified = true; @@ -143,18 +138,17 @@ Pass::Status IfConversion::Process() { return modified ? Status::SuccessWithChange : Status::SuccessWithoutChange; } -bool IfConversion::CheckBlock(opt::BasicBlock* block, - DominatorAnalysis* dominators, - opt::BasicBlock** common) { +bool IfConversion::CheckBlock(BasicBlock* block, DominatorAnalysis* dominators, + BasicBlock** common) { const std::vector<uint32_t>& preds = cfg()->preds(block->id()); // TODO(alan-baker): Extend to more than two predecessors if (preds.size() != 2) return false; - opt::BasicBlock* inc0 = context()->get_instr_block(preds[0]); + BasicBlock* inc0 = context()->get_instr_block(preds[0]); if (dominators->Dominates(block, inc0)) return false; - opt::BasicBlock* inc1 = context()->get_instr_block(preds[1]); + BasicBlock* inc1 = context()->get_instr_block(preds[1]); if (dominators->Dominates(block, inc1)) return false; // All phis will have the same common dominator, so cache the result @@ -162,16 +156,15 @@ bool IfConversion::CheckBlock(opt::BasicBlock* block, // any phi in this basic block. *common = dominators->CommonDominator(inc0, inc1); if (!*common || cfg()->IsPseudoEntryBlock(*common)) return false; - opt::Instruction* branch = (*common)->terminator(); + Instruction* branch = (*common)->terminator(); if (branch->opcode() != SpvOpBranchConditional) return false; return true; } -bool IfConversion::CheckPhiUsers(opt::Instruction* phi, - opt::BasicBlock* block) { +bool IfConversion::CheckPhiUsers(Instruction* phi, BasicBlock* block) { return get_def_use_mgr()->WhileEachUser(phi, [block, - this](opt::Instruction* user) { + this](Instruction* user) { if (user->opcode() == SpvOpPhi && context()->get_instr_block(user) == block) return false; return true; @@ -194,7 +187,7 @@ uint32_t IfConversion::SplatCondition(analysis::Vector* vec_data_ty, } bool IfConversion::CheckType(uint32_t id) { - opt::Instruction* type = get_def_use_mgr()->GetDef(id); + Instruction* type = get_def_use_mgr()->GetDef(id); SpvOp op = type->opcode(); if (spvOpcodeIsScalarType(op) || op == SpvOpTypePointer || op == SpvOpTypeVector) @@ -202,26 +195,25 @@ bool IfConversion::CheckType(uint32_t id) { return false; } -opt::BasicBlock* IfConversion::GetBlock(uint32_t id) { +BasicBlock* IfConversion::GetBlock(uint32_t id) { return context()->get_instr_block(get_def_use_mgr()->GetDef(id)); } -opt::BasicBlock* IfConversion::GetIncomingBlock(opt::Instruction* phi, - uint32_t predecessor) { +BasicBlock* IfConversion::GetIncomingBlock(Instruction* phi, + uint32_t predecessor) { uint32_t in_index = 2 * predecessor + 1; return GetBlock(phi->GetSingleWordInOperand(in_index)); } -opt::Instruction* IfConversion::GetIncomingValue(opt::Instruction* phi, - uint32_t predecessor) { +Instruction* IfConversion::GetIncomingValue(Instruction* phi, + uint32_t predecessor) { uint32_t in_index = 2 * predecessor; return get_def_use_mgr()->GetDef(phi->GetSingleWordInOperand(in_index)); } -void IfConversion::HoistInstruction(opt::Instruction* inst, - opt::BasicBlock* target_block, +void IfConversion::HoistInstruction(Instruction* inst, BasicBlock* target_block, DominatorAnalysis* dominators) { - opt::BasicBlock* inst_block = context()->get_instr_block(inst); + BasicBlock* inst_block = context()->get_instr_block(inst); if (!inst_block) { // This is in the header, and dominates everything. return; @@ -239,23 +231,23 @@ void IfConversion::HoistInstruction(opt::Instruction* inst, analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr(); inst->ForEachInId( [this, target_block, def_use_mgr, dominators](uint32_t* id) { - opt::Instruction* operand_inst = def_use_mgr->GetDef(*id); + Instruction* operand_inst = def_use_mgr->GetDef(*id); HoistInstruction(operand_inst, target_block, dominators); }); - opt::Instruction* insertion_pos = target_block->terminator(); + Instruction* insertion_pos = target_block->terminator(); if ((insertion_pos)->PreviousNode()->opcode() == SpvOpSelectionMerge) { insertion_pos = insertion_pos->PreviousNode(); } inst->RemoveFromList(); - insertion_pos->InsertBefore(std::unique_ptr<opt::Instruction>(inst)); + insertion_pos->InsertBefore(std::unique_ptr<Instruction>(inst)); context()->set_instr_block(inst, target_block); } -bool IfConversion::CanHoistInstruction(opt::Instruction* inst, - opt::BasicBlock* target_block, +bool IfConversion::CanHoistInstruction(Instruction* inst, + BasicBlock* target_block, DominatorAnalysis* dominators) { - opt::BasicBlock* inst_block = context()->get_instr_block(inst); + BasicBlock* inst_block = context()->get_instr_block(inst); if (!inst_block) { // This is in the header, and dominates everything. return true; @@ -274,7 +266,7 @@ bool IfConversion::CanHoistInstruction(opt::Instruction* inst, analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr(); return inst->WhileEachInId( [this, target_block, def_use_mgr, dominators](uint32_t* id) { - opt::Instruction* operand_inst = def_use_mgr->GetDef(*id); + Instruction* operand_inst = def_use_mgr->GetDef(*id); return CanHoistInstruction(operand_inst, target_block, dominators); }); } diff --git a/source/opt/if_conversion.h b/source/opt/if_conversion.h index d37e1bd1..18b8bc5b 100644 --- a/source/opt/if_conversion.h +++ b/source/opt/if_conversion.h @@ -29,11 +29,10 @@ class IfConversion : public Pass { const char* name() const override { return "if-conversion"; } Status Process() override; - opt::IRContext::Analysis GetPreservedAnalyses() override { - return opt::IRContext::kAnalysisDefUse | - opt::IRContext::kAnalysisDominatorAnalysis | - opt::IRContext::kAnalysisInstrToBlockMapping | - opt::IRContext::kAnalysisCFG | opt::IRContext::kAnalysisNameMap; + IRContext::Analysis GetPreservedAnalyses() override { + return IRContext::kAnalysisDefUse | IRContext::kAnalysisDominatorAnalysis | + IRContext::kAnalysisInstrToBlockMapping | IRContext::kAnalysisCFG | + IRContext::kAnalysisNameMap; } private: @@ -42,16 +41,14 @@ class IfConversion : public Pass { bool CheckType(uint32_t id); // Returns the basic block containing |id|. - opt::BasicBlock* GetBlock(uint32_t id); + BasicBlock* GetBlock(uint32_t id); // Returns the basic block for the |predecessor|'th index predecessor of // |phi|. - opt::BasicBlock* GetIncomingBlock(opt::Instruction* phi, - uint32_t predecessor); + BasicBlock* GetIncomingBlock(Instruction* phi, uint32_t predecessor); // Returns the instruction defining the |predecessor|'th index of |phi|. - opt::Instruction* GetIncomingValue(opt::Instruction* phi, - uint32_t predecessor); + Instruction* GetIncomingValue(Instruction* phi, uint32_t predecessor); // Returns the id of a OpCompositeConstruct boolean vector. The composite has // the same number of elements as |vec_data_ty| and each member is |cond|. @@ -62,27 +59,26 @@ class IfConversion : public Pass { InstructionBuilder* builder); // Returns true if none of |phi|'s users are in |block|. - bool CheckPhiUsers(opt::Instruction* phi, opt::BasicBlock* block); + bool CheckPhiUsers(Instruction* phi, BasicBlock* block); // Returns |false| if |block| is not appropriate to transform. Only // transforms blocks with two predecessors. Neither incoming block can be // dominated by |block|. Both predecessors must share a common dominator that // is terminated by a conditional branch. - bool CheckBlock(opt::BasicBlock* block, DominatorAnalysis* dominators, - opt::BasicBlock** common); + bool CheckBlock(BasicBlock* block, DominatorAnalysis* dominators, + BasicBlock** common); // Moves |inst| to |target_block| if it does not already dominate the block. // Any instructions that |inst| depends on are move if necessary. It is // assumed that |inst| can be hoisted to |target_block| as defined by // |CanHoistInstruction|. |dominators| is the dominator analysis for the // function that contains |target_block|. - void HoistInstruction(opt::Instruction* inst, opt::BasicBlock* target_block, + void HoistInstruction(Instruction* inst, BasicBlock* target_block, DominatorAnalysis* dominators); // Returns true if it is legal to move |inst| and the instructions it depends // on to |target_block| if they do not already dominate |target_block|. - bool CanHoistInstruction(opt::Instruction* inst, - opt::BasicBlock* target_block, + bool CanHoistInstruction(Instruction* inst, BasicBlock* target_block, DominatorAnalysis* dominators); }; diff --git a/source/opt/inline_exhaustive_pass.cpp b/source/opt/inline_exhaustive_pass.cpp index beb29c4d..a5399f7e 100644 --- a/source/opt/inline_exhaustive_pass.cpp +++ b/source/opt/inline_exhaustive_pass.cpp @@ -19,15 +19,15 @@ namespace spvtools { namespace opt { -bool InlineExhaustivePass::InlineExhaustive(opt::Function* func) { +bool InlineExhaustivePass::InlineExhaustive(Function* func) { bool modified = false; // Using block iterators here because of block erasures and insertions. for (auto bi = func->begin(); bi != func->end(); ++bi) { for (auto ii = bi->begin(); ii != bi->end();) { if (IsInlinableFunctionCall(&*ii)) { // Inline call. - std::vector<std::unique_ptr<opt::BasicBlock>> newBlocks; - std::vector<std::unique_ptr<opt::Instruction>> newVars; + std::vector<std::unique_ptr<BasicBlock>> newBlocks; + std::vector<std::unique_ptr<Instruction>> newVars; GenInlineCode(&newBlocks, &newVars, ii, bi); // If call block is replaced with more than one block, point // succeeding phis at new last block. @@ -61,9 +61,7 @@ bool InlineExhaustivePass::InlineExhaustive(opt::Function* func) { Pass::Status InlineExhaustivePass::ProcessImpl() { // Attempt exhaustive inlining on each entry point function in module - ProcessFunction pfn = [this](opt::Function* fp) { - return InlineExhaustive(fp); - }; + ProcessFunction pfn = [this](Function* fp) { return InlineExhaustive(fp); }; bool modified = ProcessEntryPointCallTree(pfn, get_module()); return modified ? Status::SuccessWithChange : Status::SuccessWithoutChange; } diff --git a/source/opt/inline_exhaustive_pass.h b/source/opt/inline_exhaustive_pass.h index 58595956..532facb4 100644 --- a/source/opt/inline_exhaustive_pass.h +++ b/source/opt/inline_exhaustive_pass.h @@ -41,7 +41,7 @@ class InlineExhaustivePass : public InlinePass { private: // Exhaustively inline all function calls in func as well as in // all code that is inlined into func. Return true if func is modified. - bool InlineExhaustive(opt::Function* func); + bool InlineExhaustive(Function* func); void Initialize(); Pass::Status ProcessImpl(); diff --git a/source/opt/inline_opaque_pass.cpp b/source/opt/inline_opaque_pass.cpp index f4c0eca6..03d74a9f 100644 --- a/source/opt/inline_opaque_pass.cpp +++ b/source/opt/inline_opaque_pass.cpp @@ -26,7 +26,7 @@ const uint32_t kTypePointerTypeIdInIdx = 1; } // anonymous namespace bool InlineOpaquePass::IsOpaqueType(uint32_t typeId) { - const opt::Instruction* typeInst = get_def_use_mgr()->GetDef(typeId); + const Instruction* typeInst = get_def_use_mgr()->GetDef(typeId); switch (typeInst->opcode()) { case SpvOpTypeSampler: case SpvOpTypeImage: @@ -47,14 +47,14 @@ bool InlineOpaquePass::IsOpaqueType(uint32_t typeId) { }); } -bool InlineOpaquePass::HasOpaqueArgsOrReturn(const opt::Instruction* callInst) { +bool InlineOpaquePass::HasOpaqueArgsOrReturn(const Instruction* callInst) { // Check return type if (IsOpaqueType(callInst->type_id())) return true; // Check args int icnt = 0; return !callInst->WhileEachInId([&icnt, this](const uint32_t* iid) { if (icnt > 0) { - const opt::Instruction* argInst = get_def_use_mgr()->GetDef(*iid); + const Instruction* argInst = get_def_use_mgr()->GetDef(*iid); if (IsOpaqueType(argInst->type_id())) return false; } ++icnt; @@ -62,15 +62,15 @@ bool InlineOpaquePass::HasOpaqueArgsOrReturn(const opt::Instruction* callInst) { }); } -bool InlineOpaquePass::InlineOpaque(opt::Function* func) { +bool InlineOpaquePass::InlineOpaque(Function* func) { bool modified = false; // Using block iterators here because of block erasures and insertions. for (auto bi = func->begin(); bi != func->end(); ++bi) { for (auto ii = bi->begin(); ii != bi->end();) { if (IsInlinableFunctionCall(&*ii) && HasOpaqueArgsOrReturn(&*ii)) { // Inline call. - std::vector<std::unique_ptr<opt::BasicBlock>> newBlocks; - std::vector<std::unique_ptr<opt::Instruction>> newVars; + std::vector<std::unique_ptr<BasicBlock>> newBlocks; + std::vector<std::unique_ptr<Instruction>> newVars; GenInlineCode(&newBlocks, &newVars, ii, bi); // If call block is replaced with more than one block, point // succeeding phis at new last block. @@ -96,7 +96,7 @@ void InlineOpaquePass::Initialize() { InitializeInline(); } Pass::Status InlineOpaquePass::ProcessImpl() { // Do opaque inlining on each function in entry point call tree - ProcessFunction pfn = [this](opt::Function* fp) { return InlineOpaque(fp); }; + ProcessFunction pfn = [this](Function* fp) { return InlineOpaque(fp); }; bool modified = ProcessEntryPointCallTree(pfn, get_module()); return modified ? Status::SuccessWithChange : Status::SuccessWithoutChange; } diff --git a/source/opt/inline_opaque_pass.h b/source/opt/inline_opaque_pass.h index 40a46c87..493cd165 100644 --- a/source/opt/inline_opaque_pass.h +++ b/source/opt/inline_opaque_pass.h @@ -43,12 +43,12 @@ class InlineOpaquePass : public InlinePass { bool IsOpaqueType(uint32_t typeId); // Return true if function call |callInst| has opaque argument or return type - bool HasOpaqueArgsOrReturn(const opt::Instruction* callInst); + bool HasOpaqueArgsOrReturn(const Instruction* callInst); // Inline all function calls in |func| that have opaque params or return // type. Inline similarly all code that is inlined into func. Return true // if func is modified. - bool InlineOpaque(opt::Function* func); + bool InlineOpaque(Function* func); void Initialize(); Pass::Status ProcessImpl(); 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, ¶m_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 diff --git a/source/opt/inline_pass.h b/source/opt/inline_pass.h index 957945a0..dc60de5f 100644 --- a/source/opt/inline_pass.h +++ b/source/opt/inline_pass.h @@ -32,11 +32,11 @@ namespace opt { // See optimizer.hpp for documentation. class InlinePass : public Pass { - using cbb_ptr = const opt::BasicBlock*; + using cbb_ptr = const BasicBlock*; public: using GetBlocksFunction = - std::function<std::vector<opt::BasicBlock*>*(const opt::BasicBlock*)>; + std::function<std::vector<BasicBlock*>*(const BasicBlock*)>; virtual ~InlinePass() = default; @@ -47,61 +47,57 @@ class InlinePass : public Pass { uint32_t AddPointerToType(uint32_t type_id, SpvStorageClass storage_class); // Add unconditional branch to labelId to end of block block_ptr. - void AddBranch(uint32_t labelId, std::unique_ptr<opt::BasicBlock>* block_ptr); + void AddBranch(uint32_t labelId, std::unique_ptr<BasicBlock>* block_ptr); // Add conditional branch to end of block |block_ptr|. void AddBranchCond(uint32_t cond_id, uint32_t true_id, uint32_t false_id, - std::unique_ptr<opt::BasicBlock>* block_ptr); + std::unique_ptr<BasicBlock>* block_ptr); // Add unconditional branch to labelId to end of block block_ptr. void AddLoopMerge(uint32_t merge_id, uint32_t continue_id, - std::unique_ptr<opt::BasicBlock>* block_ptr); + std::unique_ptr<BasicBlock>* block_ptr); // Add store of valId to ptrId to end of block block_ptr. void AddStore(uint32_t ptrId, uint32_t valId, - std::unique_ptr<opt::BasicBlock>* block_ptr); + std::unique_ptr<BasicBlock>* block_ptr); // Add load of ptrId into resultId to end of block block_ptr. void AddLoad(uint32_t typeId, uint32_t resultId, uint32_t ptrId, - std::unique_ptr<opt::BasicBlock>* block_ptr); + std::unique_ptr<BasicBlock>* block_ptr); // Return new label. - std::unique_ptr<opt::Instruction> NewLabel(uint32_t label_id); + std::unique_ptr<Instruction> NewLabel(uint32_t label_id); // Returns the id for the boolean false value. Looks in the module first // and creates it if not found. Remembers it for future calls. uint32_t GetFalseId(); // Map callee params to caller args - void MapParams(opt::Function* calleeFn, - opt::BasicBlock::iterator call_inst_itr, + void MapParams(Function* calleeFn, BasicBlock::iterator call_inst_itr, std::unordered_map<uint32_t, uint32_t>* callee2caller); // Clone and map callee locals - void CloneAndMapLocals( - opt::Function* calleeFn, - std::vector<std::unique_ptr<opt::Instruction>>* new_vars, - std::unordered_map<uint32_t, uint32_t>* callee2caller); + void CloneAndMapLocals(Function* calleeFn, + std::vector<std::unique_ptr<Instruction>>* new_vars, + std::unordered_map<uint32_t, uint32_t>* callee2caller); // Create return variable for callee clone code if needed. Return id // if created, otherwise 0. - uint32_t CreateReturnVar( - opt::Function* calleeFn, - std::vector<std::unique_ptr<opt::Instruction>>* new_vars); + uint32_t CreateReturnVar(Function* calleeFn, + std::vector<std::unique_ptr<Instruction>>* new_vars); // Return true if instruction must be in the same block that its result // is used. - bool IsSameBlockOp(const opt::Instruction* inst) const; + bool IsSameBlockOp(const Instruction* inst) const; // Clone operands which must be in same block as consumer instructions. // Look in preCallSB for instructions that need cloning. Look in // postCallSB for instructions already cloned. Add cloned instruction // to postCallSB. - void CloneSameBlockOps( - std::unique_ptr<opt::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); + void CloneSameBlockOps(std::unique_ptr<Instruction>* inst, + std::unordered_map<uint32_t, uint32_t>* postCallSB, + std::unordered_map<uint32_t, Instruction*>* preCallSB, + std::unique_ptr<BasicBlock>* block_ptr); // Return in new_blocks the result of inlining the call at call_inst_itr // within its block at call_block_itr. The block at call_block_itr can @@ -117,13 +113,13 @@ class InlinePass : public Pass { // Also return in new_vars additional OpVariable instructions required by // and to be inserted into the caller function after the block at // call_block_itr is replaced with new_blocks. - void 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); + void GenInlineCode(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); // Return true if |inst| is a function call that can be inlined. - bool IsInlinableFunctionCall(const opt::Instruction* inst); + bool IsInlinableFunctionCall(const Instruction* inst); // Compute structured successors for function |func|. // A block's structured successors are the blocks it branches to @@ -132,39 +128,39 @@ class InlinePass : public Pass { // This assures correct depth first search in the presence of early // returns and kills. If the successor vector contain duplicates // if the merge block, they are safely ignored by DFS. - void ComputeStructuredSuccessors(opt::Function* func); + void ComputeStructuredSuccessors(Function* func); // Return function to return ordered structure successors for a given block // Assumes ComputeStructuredSuccessors() has been called. GetBlocksFunction StructuredSuccessorsFunction(); // Return true if |func| has multiple returns - bool HasMultipleReturns(opt::Function* func); + bool HasMultipleReturns(Function* func); // Return true if |func| has no return in a loop. The current analysis // requires structured control flow, so return false if control flow not // structured ie. module is not a shader. - bool HasNoReturnInLoop(opt::Function* func); + bool HasNoReturnInLoop(Function* func); // Find all functions with multiple returns and no returns in loops - void AnalyzeReturns(opt::Function* func); + void AnalyzeReturns(Function* func); // Return true if |func| is a function that can be inlined. - bool IsInlinableFunction(opt::Function* func); + bool IsInlinableFunction(Function* func); // Update phis in succeeding blocks to point to new last block void UpdateSucceedingPhis( - std::vector<std::unique_ptr<opt::BasicBlock>>& new_blocks); + std::vector<std::unique_ptr<BasicBlock>>& new_blocks); // Initialize state for optimization of |module| void InitializeInline(); // Map from function's result id to function. - std::unordered_map<uint32_t, opt::Function*> id2function_; + std::unordered_map<uint32_t, Function*> id2function_; // Map from block's label id to block. TODO(dnovillo): This is superfluous wrt - // opt::CFG. It has functionality not present in opt::CFG. Consolidate. - std::unordered_map<uint32_t, opt::BasicBlock*> id2block_; + // CFG. It has functionality not present in CFG. Consolidate. + std::unordered_map<uint32_t, BasicBlock*> id2block_; // Set of ids of functions with multiple returns. std::set<uint32_t> multi_return_funcs_; @@ -180,9 +176,9 @@ class InlinePass : public Pass { // Map from block to its structured successor blocks. See // ComputeStructuredSuccessors() for definition. TODO(dnovillo): This is - // superfluous wrt opt::CFG, but it seems to be computed in a slightly + // superfluous wrt CFG, but it seems to be computed in a slightly // different way in the inliner. Can these be consolidated? - std::unordered_map<const opt::BasicBlock*, std::vector<opt::BasicBlock*>> + std::unordered_map<const BasicBlock*, std::vector<BasicBlock*>> block2structured_succs_; }; diff --git a/source/opt/instruction.cpp b/source/opt/instruction.cpp index 37ff0358..af61bf19 100644 --- a/source/opt/instruction.cpp +++ b/source/opt/instruction.cpp @@ -145,7 +145,7 @@ void Instruction::ReplaceOperands(const OperandList& new_operands) { bool Instruction::IsReadOnlyLoad() const { if (IsLoad()) { - opt::Instruction* address_def = GetBaseAddress(); + Instruction* address_def = GetBaseAddress(); if (!address_def || address_def->opcode() != SpvOpVariable) { return false; } @@ -161,7 +161,7 @@ Instruction* Instruction::GetBaseAddress() const { "GetBaseAddress should only be called on instructions that take a " "pointer or image."); uint32_t base = GetSingleWordInOperand(kLoadBaseIndex); - opt::Instruction* base_inst = context()->get_def_use_mgr()->GetDef(base); + Instruction* base_inst = context()->get_def_use_mgr()->GetDef(base); bool done = false; while (!done) { switch (base_inst->opcode()) { @@ -217,7 +217,7 @@ bool Instruction::IsVulkanStorageImage() const { return false; } - opt::Instruction* base_type = + Instruction* base_type = context()->get_def_use_mgr()->GetDef(GetSingleWordInOperand(1)); if (base_type->opcode() != SpvOpTypeImage) { return false; @@ -243,7 +243,7 @@ bool Instruction::IsVulkanSampledImage() const { return false; } - opt::Instruction* base_type = + Instruction* base_type = context()->get_def_use_mgr()->GetDef(GetSingleWordInOperand(1)); if (base_type->opcode() != SpvOpTypeImage) { return false; @@ -269,7 +269,7 @@ bool Instruction::IsVulkanStorageTexelBuffer() const { return false; } - opt::Instruction* base_type = + Instruction* base_type = context()->get_def_use_mgr()->GetDef(GetSingleWordInOperand(1)); if (base_type->opcode() != SpvOpTypeImage) { return false; @@ -291,7 +291,7 @@ bool Instruction::IsVulkanStorageBuffer() const { return false; } - opt::Instruction* base_type = + Instruction* base_type = context()->get_def_use_mgr()->GetDef(GetSingleWordInOperand(1)); if (base_type->opcode() != SpvOpTypeStruct) { @@ -303,15 +303,13 @@ bool Instruction::IsVulkanStorageBuffer() const { bool is_buffer_block = false; context()->get_decoration_mgr()->ForEachDecoration( base_type->result_id(), SpvDecorationBufferBlock, - [&is_buffer_block](const opt::Instruction&) { - is_buffer_block = true; - }); + [&is_buffer_block](const Instruction&) { is_buffer_block = true; }); return is_buffer_block; } else if (storage_class == SpvStorageClassStorageBuffer) { bool is_block = false; context()->get_decoration_mgr()->ForEachDecoration( base_type->result_id(), SpvDecorationBlock, - [&is_block](const opt::Instruction&) { is_block = true; }); + [&is_block](const Instruction&) { is_block = true; }); return is_block; } return false; @@ -327,7 +325,7 @@ bool Instruction::IsVulkanUniformBuffer() const { return false; } - opt::Instruction* base_type = + Instruction* base_type = context()->get_def_use_mgr()->GetDef(GetSingleWordInOperand(1)); if (base_type->opcode() != SpvOpTypeStruct) { return false; @@ -336,7 +334,7 @@ bool Instruction::IsVulkanUniformBuffer() const { bool is_block = false; context()->get_decoration_mgr()->ForEachDecoration( base_type->result_id(), SpvDecorationBlock, - [&is_block](const opt::Instruction&) { is_block = true; }); + [&is_block](const Instruction&) { is_block = true; }); return is_block; } @@ -416,7 +414,7 @@ bool Instruction::IsValidBasePointer() const { return false; } - opt::Instruction* type = context()->get_def_use_mgr()->GetDef(tid); + Instruction* type = context()->get_def_use_mgr()->GetDef(tid); if (type->opcode() != SpvOpTypePointer) { return false; } @@ -431,7 +429,7 @@ bool Instruction::IsValidBasePointer() const { } uint32_t pointee_type_id = type->GetSingleWordInOperand(1); - opt::Instruction* pointee_type_inst = + Instruction* pointee_type_inst = context()->get_def_use_mgr()->GetDef(pointee_type_id); if (pointee_type_inst->IsOpaqueType()) { @@ -446,7 +444,7 @@ bool Instruction::IsValidBaseImage() const { return false; } - opt::Instruction* type = context()->get_def_use_mgr()->GetDef(tid); + Instruction* type = context()->get_def_use_mgr()->GetDef(tid); return (type->opcode() == SpvOpTypeImage || type->opcode() == SpvOpTypeSampledImage); } @@ -455,14 +453,13 @@ bool Instruction::IsOpaqueType() const { if (opcode() == SpvOpTypeStruct) { bool is_opaque = false; ForEachInOperand([&is_opaque, this](const uint32_t* op_id) { - opt::Instruction* type_inst = - context()->get_def_use_mgr()->GetDef(*op_id); + Instruction* type_inst = context()->get_def_use_mgr()->GetDef(*op_id); is_opaque |= type_inst->IsOpaqueType(); }); return is_opaque; } else if (opcode() == SpvOpTypeArray) { uint32_t sub_type_id = GetSingleWordInOperand(0); - opt::Instruction* sub_type_inst = + Instruction* sub_type_inst = context()->get_def_use_mgr()->GetDef(sub_type_id); return sub_type_inst->IsOpaqueType(); } else { @@ -477,7 +474,7 @@ bool Instruction::IsFoldable() const { } bool Instruction::IsFoldableByFoldScalar() const { - const opt::InstructionFolder& folder = context()->get_instruction_folder(); + const InstructionFolder& folder = context()->get_instruction_folder(); if (!folder.IsFoldableOpcode(opcode())) { return false; } @@ -494,7 +491,7 @@ bool Instruction::IsFloatingPointFoldingAllowed() const { bool is_nocontract = false; context_->get_decoration_mgr()->WhileEachDecoration( opcode_, SpvDecorationNoContraction, - [&is_nocontract](const opt::Instruction&) { + [&is_nocontract](const Instruction&) { is_nocontract = true; return false; }); @@ -518,7 +515,7 @@ std::string Instruction::PrettyPrint(uint32_t options) const { options | SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); } -std::ostream& operator<<(std::ostream& str, const opt::Instruction& inst) { +std::ostream& operator<<(std::ostream& str, const Instruction& inst) { str << inst.PrettyPrint(); return str; } diff --git a/source/opt/instruction.h b/source/opt/instruction.h index 807e7ae5..812c4831 100644 --- a/source/opt/instruction.h +++ b/source/opt/instruction.h @@ -458,7 +458,7 @@ class Instruction : public utils::IntrusiveNodeBase<Instruction> { // to provide the correct interpretation of types, constants, etc. // // Disassembly uses raw ids (not pretty printed names). -std::ostream& operator<<(std::ostream& str, const opt::Instruction& inst); +std::ostream& operator<<(std::ostream& str, const Instruction& inst); inline bool Instruction::operator==(const Instruction& other) const { return unique_id() == other.unique_id(); diff --git a/source/opt/ir_builder.h b/source/opt/ir_builder.h index b0e0d300..9a105408 100644 --- a/source/opt/ir_builder.h +++ b/source/opt/ir_builder.h @@ -34,31 +34,31 @@ const uint32_t kInvalidId = std::numeric_limits<uint32_t>::max(); // - Instruction to block analysis class InstructionBuilder { public: - using InsertionPointTy = opt::BasicBlock::iterator; + using InsertionPointTy = BasicBlock::iterator; // Creates an InstructionBuilder, all new instructions will be inserted before // the instruction |insert_before|. - InstructionBuilder(opt::IRContext* context, opt::Instruction* insert_before, - opt::IRContext::Analysis preserved_analyses = - opt::IRContext::kAnalysisNone) + InstructionBuilder( + IRContext* context, Instruction* insert_before, + IRContext::Analysis preserved_analyses = IRContext::kAnalysisNone) : InstructionBuilder(context, context->get_instr_block(insert_before), InsertionPointTy(insert_before), preserved_analyses) {} // Creates an InstructionBuilder, all new instructions will be inserted at the // end of the basic block |parent_block|. - InstructionBuilder(opt::IRContext* context, opt::BasicBlock* parent_block, - opt::IRContext::Analysis preserved_analyses = - opt::IRContext::kAnalysisNone) + InstructionBuilder( + IRContext* context, BasicBlock* parent_block, + IRContext::Analysis preserved_analyses = IRContext::kAnalysisNone) : InstructionBuilder(context, parent_block, parent_block->end(), preserved_analyses) {} // Creates a new selection merge instruction. // The id |merge_id| is the merge basic block id. - opt::Instruction* AddSelectionMerge( + Instruction* AddSelectionMerge( uint32_t merge_id, uint32_t selection_control = SpvSelectionControlMaskNone) { - std::unique_ptr<opt::Instruction> new_branch_merge(new opt::Instruction( + std::unique_ptr<Instruction> new_branch_merge(new Instruction( GetContext(), SpvOpSelectionMerge, 0, 0, {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {merge_id}}, {spv_operand_type_t::SPV_OPERAND_TYPE_SELECTION_CONTROL, @@ -69,8 +69,8 @@ class InstructionBuilder { // Creates a new branch instruction to |label_id|. // Note that the user must make sure the final basic block is // well formed. - opt::Instruction* AddBranch(uint32_t label_id) { - std::unique_ptr<opt::Instruction> new_branch(new opt::Instruction( + Instruction* AddBranch(uint32_t label_id) { + std::unique_ptr<Instruction> new_branch(new Instruction( GetContext(), SpvOpBranch, 0, 0, {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {label_id}}})); return AddInstruction(std::move(new_branch)); @@ -91,14 +91,14 @@ class InstructionBuilder { // selection merge instruction. // Note that the user must make sure the final basic block is // well formed. - opt::Instruction* AddConditionalBranch( + Instruction* AddConditionalBranch( uint32_t cond_id, uint32_t true_id, uint32_t false_id, uint32_t merge_id = kInvalidId, uint32_t selection_control = SpvSelectionControlMaskNone) { if (merge_id != kInvalidId) { AddSelectionMerge(merge_id, selection_control); } - std::unique_ptr<opt::Instruction> new_branch(new opt::Instruction( + std::unique_ptr<Instruction> new_branch(new Instruction( GetContext(), SpvOpBranchConditional, 0, 0, {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {cond_id}}, {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {true_id}}, @@ -119,29 +119,28 @@ class InstructionBuilder { // selection merge instruction. // Note that the user must make sure the final basic block is // well formed. - opt::Instruction* AddSwitch( + Instruction* AddSwitch( uint32_t selector_id, uint32_t default_id, - const std::vector<std::pair<opt::Operand::OperandData, uint32_t>>& - targets, + const std::vector<std::pair<Operand::OperandData, uint32_t>>& targets, uint32_t merge_id = kInvalidId, uint32_t selection_control = SpvSelectionControlMaskNone) { if (merge_id != kInvalidId) { AddSelectionMerge(merge_id, selection_control); } - std::vector<opt::Operand> operands; + std::vector<Operand> operands; operands.emplace_back( - opt::Operand{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {selector_id}}); + Operand{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {selector_id}}); operands.emplace_back( - opt::Operand{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {default_id}}); + Operand{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {default_id}}); for (auto& target : targets) { - operands.emplace_back(opt::Operand{ - spv_operand_type_t::SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER, - target.first}); - operands.emplace_back(opt::Operand{ - spv_operand_type_t::SPV_OPERAND_TYPE_ID, {target.second}}); + operands.emplace_back( + Operand{spv_operand_type_t::SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER, + target.first}); + operands.emplace_back( + Operand{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {target.second}}); } - std::unique_ptr<opt::Instruction> new_switch( - new opt::Instruction(GetContext(), SpvOpSwitch, 0, 0, operands)); + std::unique_ptr<Instruction> new_switch( + new Instruction(GetContext(), SpvOpSwitch, 0, 0, operands)); return AddInstruction(std::move(new_switch)); } @@ -149,14 +148,13 @@ class InstructionBuilder { // The id |type| must be the id of the phi instruction's type. // The vector |incomings| must be a sequence of pairs of <definition id, // parent id>. - opt::Instruction* AddPhi(uint32_t type, - const std::vector<uint32_t>& incomings) { + Instruction* AddPhi(uint32_t type, const std::vector<uint32_t>& incomings) { assert(incomings.size() % 2 == 0 && "A sequence of pairs is expected"); - std::vector<opt::Operand> phi_ops; + std::vector<Operand> phi_ops; for (size_t i = 0; i < incomings.size(); i++) { phi_ops.push_back({SPV_OPERAND_TYPE_ID, {incomings[i]}}); } - std::unique_ptr<opt::Instruction> phi_inst(new opt::Instruction( + std::unique_ptr<Instruction> phi_inst(new Instruction( GetContext(), SpvOpPhi, type, GetContext()->TakeNextId(), phi_ops)); return AddInstruction(std::move(phi_inst)); } @@ -166,8 +164,8 @@ class InstructionBuilder { // |op1| and |op2| types. // The id |op1| is the left hand side of the operation. // The id |op2| is the right hand side of the operation. - opt::Instruction* AddIAdd(uint32_t type, uint32_t op1, uint32_t op2) { - std::unique_ptr<opt::Instruction> inst(new opt::Instruction( + Instruction* AddIAdd(uint32_t type, uint32_t op1, uint32_t op2) { + std::unique_ptr<Instruction> inst(new Instruction( GetContext(), SpvOpIAdd, type, GetContext()->TakeNextId(), {{SPV_OPERAND_TYPE_ID, {op1}}, {SPV_OPERAND_TYPE_ID, {op2}}})); return AddInstruction(std::move(inst)); @@ -177,10 +175,10 @@ class InstructionBuilder { // The id |op1| is the left hand side of the operation. // The id |op2| is the right hand side of the operation. // It is assumed that |op1| and |op2| have the same underlying type. - opt::Instruction* AddULessThan(uint32_t op1, uint32_t op2) { + Instruction* AddULessThan(uint32_t op1, uint32_t op2) { analysis::Bool bool_type; uint32_t type = GetContext()->get_type_mgr()->GetId(&bool_type); - std::unique_ptr<opt::Instruction> inst(new opt::Instruction( + std::unique_ptr<Instruction> inst(new Instruction( GetContext(), SpvOpULessThan, type, GetContext()->TakeNextId(), {{SPV_OPERAND_TYPE_ID, {op1}}, {SPV_OPERAND_TYPE_ID, {op2}}})); return AddInstruction(std::move(inst)); @@ -190,10 +188,10 @@ class InstructionBuilder { // The id |op1| is the left hand side of the operation. // The id |op2| is the right hand side of the operation. // It is assumed that |op1| and |op2| have the same underlying type. - opt::Instruction* AddSLessThan(uint32_t op1, uint32_t op2) { + Instruction* AddSLessThan(uint32_t op1, uint32_t op2) { analysis::Bool bool_type; uint32_t type = GetContext()->get_type_mgr()->GetId(&bool_type); - std::unique_ptr<opt::Instruction> inst(new opt::Instruction( + std::unique_ptr<Instruction> inst(new Instruction( GetContext(), SpvOpSLessThan, type, GetContext()->TakeNextId(), {{SPV_OPERAND_TYPE_ID, {op1}}, {SPV_OPERAND_TYPE_ID, {op2}}})); return AddInstruction(std::move(inst)); @@ -203,8 +201,8 @@ class InstructionBuilder { // |op1|. The id |op1| is the left hand side of the operation. The id |op2| is // the right hand side of the operation. It is assumed that |op1| and |op2| // have the same underlying type. - opt::Instruction* AddLessThan(uint32_t op1, uint32_t op2) { - opt::Instruction* op1_insn = context_->get_def_use_mgr()->GetDef(op1); + Instruction* AddLessThan(uint32_t op1, uint32_t op2) { + Instruction* op1_insn = context_->get_def_use_mgr()->GetDef(op1); analysis::Type* type = GetContext()->get_type_mgr()->GetType(op1_insn->type_id()); analysis::Integer* int_type = type->AsInteger(); @@ -220,41 +218,40 @@ class InstructionBuilder { // |type| must match the types of |true_value| and |false_value|. It is up to // the caller to ensure that |cond| is a correct type (bool or vector of // bool) for |type|. - opt::Instruction* AddSelect(uint32_t type, uint32_t cond, uint32_t true_value, - uint32_t false_value) { - std::unique_ptr<opt::Instruction> select(new opt::Instruction( + Instruction* AddSelect(uint32_t type, uint32_t cond, uint32_t true_value, + uint32_t false_value) { + std::unique_ptr<Instruction> select(new Instruction( GetContext(), SpvOpSelect, type, GetContext()->TakeNextId(), - std::initializer_list<opt::Operand>{ - {SPV_OPERAND_TYPE_ID, {cond}}, - {SPV_OPERAND_TYPE_ID, {true_value}}, - {SPV_OPERAND_TYPE_ID, {false_value}}})); + std::initializer_list<Operand>{{SPV_OPERAND_TYPE_ID, {cond}}, + {SPV_OPERAND_TYPE_ID, {true_value}}, + {SPV_OPERAND_TYPE_ID, {false_value}}})); return AddInstruction(std::move(select)); } // Adds a signed int32 constant to the binary. // The |value| parameter is the constant value to be added. - opt::Instruction* Add32BitSignedIntegerConstant(int32_t value) { + Instruction* Add32BitSignedIntegerConstant(int32_t value) { return Add32BitConstantInteger<int32_t>(value, true); } // Create a composite construct. // |type| should be a composite type and the number of elements it has should // match the size od |ids|. - opt::Instruction* AddCompositeConstruct(uint32_t type, - const std::vector<uint32_t>& ids) { - std::vector<opt::Operand> ops; + Instruction* AddCompositeConstruct(uint32_t type, + const std::vector<uint32_t>& ids) { + std::vector<Operand> ops; for (auto id : ids) { ops.emplace_back(SPV_OPERAND_TYPE_ID, std::initializer_list<uint32_t>{id}); } - std::unique_ptr<opt::Instruction> construct( - new opt::Instruction(GetContext(), SpvOpCompositeConstruct, type, - GetContext()->TakeNextId(), ops)); + std::unique_ptr<Instruction> construct( + new Instruction(GetContext(), SpvOpCompositeConstruct, type, + GetContext()->TakeNextId(), ops)); return AddInstruction(std::move(construct)); } // Adds an unsigned int32 constant to the binary. // The |value| parameter is the constant value to be added. - opt::Instruction* Add32BitUnsignedIntegerConstant(uint32_t value) { + Instruction* Add32BitUnsignedIntegerConstant(uint32_t value) { return Add32BitConstantInteger<uint32_t>(value, false); } @@ -263,7 +260,7 @@ class InstructionBuilder { // signed constant otherwise as an unsigned constant. If |sign| is false the // value must not be a negative number. template <typename T> - opt::Instruction* Add32BitConstantInteger(T value, bool sign) { + Instruction* Add32BitConstantInteger(T value, bool sign) { // Assert that we are not trying to store a negative number in an unsigned // type. if (!sign) @@ -287,65 +284,64 @@ class InstructionBuilder { uint32_t word = value; // Create the constant value. - const opt::analysis::Constant* constant = + const analysis::Constant* constant = GetContext()->get_constant_mgr()->GetConstant(rebuilt_type, {word}); // Create the OpConstant instruction using the type and the value. return GetContext()->get_constant_mgr()->GetDefiningInstruction(constant); } - opt::Instruction* AddCompositeExtract( - uint32_t type, uint32_t id_of_composite, - const std::vector<uint32_t>& index_list) { - std::vector<opt::Operand> operands; + Instruction* AddCompositeExtract(uint32_t type, uint32_t id_of_composite, + const std::vector<uint32_t>& index_list) { + std::vector<Operand> operands; operands.push_back({SPV_OPERAND_TYPE_ID, {id_of_composite}}); for (uint32_t index : index_list) { operands.push_back({SPV_OPERAND_TYPE_LITERAL_INTEGER, {index}}); } - std::unique_ptr<opt::Instruction> new_inst( - new opt::Instruction(GetContext(), SpvOpCompositeExtract, type, - GetContext()->TakeNextId(), operands)); + std::unique_ptr<Instruction> new_inst( + new Instruction(GetContext(), SpvOpCompositeExtract, type, + GetContext()->TakeNextId(), operands)); return AddInstruction(std::move(new_inst)); } // Creates an unreachable instruction. - opt::Instruction* AddUnreachable() { - std::unique_ptr<opt::Instruction> select( - new opt::Instruction(GetContext(), SpvOpUnreachable, 0, 0, - std::initializer_list<opt::Operand>{})); + Instruction* AddUnreachable() { + std::unique_ptr<Instruction> select( + new Instruction(GetContext(), SpvOpUnreachable, 0, 0, + std::initializer_list<Operand>{})); return AddInstruction(std::move(select)); } - opt::Instruction* AddAccessChain(uint32_t type_id, uint32_t base_ptr_id, - std::vector<uint32_t> ids) { - std::vector<opt::Operand> operands; + Instruction* AddAccessChain(uint32_t type_id, uint32_t base_ptr_id, + std::vector<uint32_t> ids) { + std::vector<Operand> operands; operands.push_back({SPV_OPERAND_TYPE_ID, {base_ptr_id}}); for (uint32_t index_id : ids) { operands.push_back({SPV_OPERAND_TYPE_ID, {index_id}}); } - std::unique_ptr<opt::Instruction> new_inst( - new opt::Instruction(GetContext(), SpvOpAccessChain, type_id, - GetContext()->TakeNextId(), operands)); + std::unique_ptr<Instruction> new_inst( + new Instruction(GetContext(), SpvOpAccessChain, type_id, + GetContext()->TakeNextId(), operands)); return AddInstruction(std::move(new_inst)); } - opt::Instruction* AddLoad(uint32_t type_id, uint32_t base_ptr_id) { - std::vector<opt::Operand> operands; + Instruction* AddLoad(uint32_t type_id, uint32_t base_ptr_id) { + std::vector<Operand> operands; operands.push_back({SPV_OPERAND_TYPE_ID, {base_ptr_id}}); - std::unique_ptr<opt::Instruction> new_inst( - new opt::Instruction(GetContext(), SpvOpLoad, type_id, - GetContext()->TakeNextId(), operands)); + std::unique_ptr<Instruction> new_inst( + new Instruction(GetContext(), SpvOpLoad, type_id, + GetContext()->TakeNextId(), operands)); return AddInstruction(std::move(new_inst)); } // Inserts the new instruction before the insertion point. - opt::Instruction* AddInstruction(std::unique_ptr<opt::Instruction>&& insn) { - opt::Instruction* insn_ptr = &*insert_before_.InsertBefore(std::move(insn)); + Instruction* AddInstruction(std::unique_ptr<Instruction>&& insn) { + Instruction* insn_ptr = &*insert_before_.InsertBefore(std::move(insn)); UpdateInstrToBlockMapping(insn_ptr); UpdateDefUseMgr(insn_ptr); return insn_ptr; @@ -356,65 +352,62 @@ class InstructionBuilder { // Change the insertion point to insert before the instruction // |insert_before|. - void SetInsertPoint(opt::Instruction* insert_before) { + void SetInsertPoint(Instruction* insert_before) { parent_ = context_->get_instr_block(insert_before); insert_before_ = InsertionPointTy(insert_before); } // Change the insertion point to insert at the end of the basic block // |parent_block|. - void SetInsertPoint(opt::BasicBlock* parent_block) { + void SetInsertPoint(BasicBlock* parent_block) { parent_ = parent_block; insert_before_ = parent_block->end(); } // Returns the context which instructions are constructed for. - opt::IRContext* GetContext() const { return context_; } + IRContext* GetContext() const { return context_; } // Returns the set of preserved analyses. - inline opt::IRContext::Analysis GetPreservedAnalysis() const { + inline IRContext::Analysis GetPreservedAnalysis() const { return preserved_analyses_; } private: - InstructionBuilder(opt::IRContext* context, opt::BasicBlock* parent, + InstructionBuilder(IRContext* context, BasicBlock* parent, InsertionPointTy insert_before, - opt::IRContext::Analysis preserved_analyses) + IRContext::Analysis preserved_analyses) : context_(context), parent_(parent), insert_before_(insert_before), preserved_analyses_(preserved_analyses) { - assert(!(preserved_analyses_ & - ~(opt::IRContext::kAnalysisDefUse | - opt::IRContext::kAnalysisInstrToBlockMapping))); + assert(!(preserved_analyses_ & ~(IRContext::kAnalysisDefUse | + IRContext::kAnalysisInstrToBlockMapping))); } // Returns true if the users requested to update |analysis|. - inline bool IsAnalysisUpdateRequested( - opt::IRContext::Analysis analysis) const { + inline bool IsAnalysisUpdateRequested(IRContext::Analysis analysis) const { return preserved_analyses_ & analysis; } // Updates the def/use manager if the user requested it. If he did not request // an update, this function does nothing. - inline void UpdateDefUseMgr(opt::Instruction* insn) { - if (IsAnalysisUpdateRequested(opt::IRContext::kAnalysisDefUse)) + inline void UpdateDefUseMgr(Instruction* insn) { + if (IsAnalysisUpdateRequested(IRContext::kAnalysisDefUse)) GetContext()->get_def_use_mgr()->AnalyzeInstDefUse(insn); } // Updates the instruction to block analysis if the user requested it. If he // did not request an update, this function does nothing. - inline void UpdateInstrToBlockMapping(opt::Instruction* insn) { - if (IsAnalysisUpdateRequested( - opt::IRContext::kAnalysisInstrToBlockMapping) && + inline void UpdateInstrToBlockMapping(Instruction* insn) { + if (IsAnalysisUpdateRequested(IRContext::kAnalysisInstrToBlockMapping) && parent_) GetContext()->set_instr_block(insn, parent_); } - opt::IRContext* context_; - opt::BasicBlock* parent_; + IRContext* context_; + BasicBlock* parent_; InsertionPointTy insert_before_; - const opt::IRContext::Analysis preserved_analyses_; + const IRContext::Analysis preserved_analyses_; }; } // namespace opt diff --git a/source/opt/ir_context.cpp b/source/opt/ir_context.cpp index 5594ad32..ad0cad77 100644 --- a/source/opt/ir_context.cpp +++ b/source/opt/ir_context.cpp @@ -92,7 +92,7 @@ void IRContext::InvalidateAnalyses(IRContext::Analysis analyses_to_invalidate) { valid_analyses_ = Analysis(valid_analyses_ & ~analyses_to_invalidate); } -Instruction* IRContext::KillInst(opt::Instruction* inst) { +Instruction* IRContext::KillInst(Instruction* inst) { if (!inst) { return nullptr; } @@ -114,11 +114,11 @@ Instruction* IRContext::KillInst(opt::Instruction* inst) { } } - if (type_mgr_ && opt::IsTypeInst(inst->opcode())) { + if (type_mgr_ && IsTypeInst(inst->opcode())) { type_mgr_->RemoveId(inst->result_id()); } - if (constant_mgr_ && opt::IsConstantInst(inst->opcode())) { + if (constant_mgr_ && IsConstantInst(inst->opcode())) { constant_mgr_->RemoveId(inst->result_id()); } @@ -138,7 +138,7 @@ Instruction* IRContext::KillInst(opt::Instruction* inst) { } bool IRContext::KillDef(uint32_t id) { - opt::Instruction* def = get_def_use_mgr()->GetDef(id); + Instruction* def = get_def_use_mgr()->GetDef(id); if (def != nullptr) { KillInst(def); return true; @@ -153,15 +153,15 @@ bool IRContext::ReplaceAllUsesWith(uint32_t before, uint32_t after) { assert(get_def_use_mgr()->GetDef(after) && "'after' is not a registered def."); - std::vector<std::pair<opt::Instruction*, uint32_t>> uses_to_update; + std::vector<std::pair<Instruction*, uint32_t>> uses_to_update; get_def_use_mgr()->ForEachUse( - before, [&uses_to_update](opt::Instruction* user, uint32_t index) { + before, [&uses_to_update](Instruction* user, uint32_t index) { uses_to_update.emplace_back(user, index); }); - opt::Instruction* prev = nullptr; + Instruction* prev = nullptr; for (auto p : uses_to_update) { - opt::Instruction* user = p.first; + Instruction* user = p.first; uint32_t index = p.second; if (prev == nullptr || prev != user) { ForgetUses(user); @@ -202,7 +202,7 @@ bool IRContext::IsConsistent() { #endif if (AreAnalysesValid(kAnalysisDefUse)) { - opt::analysis::DefUseManager new_def_use(module()); + analysis::DefUseManager new_def_use(module()); if (*get_def_use_mgr() != new_def_use) { return false; } @@ -211,7 +211,7 @@ bool IRContext::IsConsistent() { if (AreAnalysesValid(kAnalysisInstrToBlockMapping)) { for (auto& func : *module()) { for (auto& block : func) { - if (!block.WhileEachInst([this, &block](opt::Instruction* inst) { + if (!block.WhileEachInst([this, &block](Instruction* inst) { if (get_instr_block(inst) != &block) { return false; } @@ -257,18 +257,18 @@ void IRContext::AnalyzeUses(Instruction* inst) { } void IRContext::KillNamesAndDecorates(uint32_t id) { - std::vector<opt::Instruction*> decorations = + std::vector<Instruction*> decorations = get_decoration_mgr()->GetDecorationsFor(id, true); for (Instruction* inst : decorations) { KillInst(inst); } - std::vector<opt::Instruction*> name_to_kill; + std::vector<Instruction*> name_to_kill; for (auto name : GetNames(id)) { name_to_kill.push_back(name.second); } - for (opt::Instruction* name_inst : name_to_kill) { + for (Instruction* name_inst : name_to_kill) { KillInst(name_inst); } } @@ -442,7 +442,7 @@ void IRContext::AddCombinatorsForCapability(uint32_t capability) { } } -void IRContext::AddCombinatorsForExtension(opt::Instruction* extension) { +void IRContext::AddCombinatorsForExtension(Instruction* extension) { assert(extension->opcode() == SpvOpExtInstImport && "Expecting an import of an extension's instruction set."); const char* extension_name = @@ -557,16 +557,16 @@ void IRContext::RemoveFromIdToName(const Instruction* inst) { } } -opt::LoopDescriptor* IRContext::GetLoopDescriptor(const opt::Function* f) { +LoopDescriptor* IRContext::GetLoopDescriptor(const Function* f) { if (!AreAnalysesValid(kAnalysisLoopAnalysis)) { ResetLoopAnalysis(); } - std::unordered_map<const opt::Function*, opt::LoopDescriptor>::iterator it = + std::unordered_map<const Function*, LoopDescriptor>::iterator it = loop_descriptors_.find(f); if (it == loop_descriptors_.end()) { return &loop_descriptors_ - .emplace(std::make_pair(f, opt::LoopDescriptor(this, f))) + .emplace(std::make_pair(f, LoopDescriptor(this, f))) .first->second; } @@ -574,8 +574,7 @@ opt::LoopDescriptor* IRContext::GetLoopDescriptor(const opt::Function* f) { } // Gets the dominator analysis for function |f|. -opt::DominatorAnalysis* IRContext::GetDominatorAnalysis( - const opt::Function* f) { +DominatorAnalysis* IRContext::GetDominatorAnalysis(const Function* f) { if (!AreAnalysesValid(kAnalysisDominatorAnalysis)) { ResetDominatorAnalysis(); } @@ -588,8 +587,7 @@ opt::DominatorAnalysis* IRContext::GetDominatorAnalysis( } // Gets the postdominator analysis for function |f|. -opt::PostDominatorAnalysis* IRContext::GetPostDominatorAnalysis( - const opt::Function* f) { +PostDominatorAnalysis* IRContext::GetPostDominatorAnalysis(const Function* f) { if (!AreAnalysesValid(kAnalysisDominatorAnalysis)) { ResetDominatorAnalysis(); } @@ -601,13 +599,13 @@ opt::PostDominatorAnalysis* IRContext::GetPostDominatorAnalysis( return &post_dominator_trees_[f]; } -bool opt::IRContext::CheckCFG() { +bool IRContext::CheckCFG() { std::unordered_map<uint32_t, std::vector<uint32_t>> real_preds; if (!AreAnalysesValid(kAnalysisCFG)) { return true; } - for (opt::Function& function : *module()) { + for (Function& function : *module()) { for (const auto& bb : function) { bb.ForEachSuccessorLabel([&bb, &real_preds](const uint32_t lab_id) { real_preds[lab_id].push_back(bb.id()); diff --git a/source/opt/ir_context.h b/source/opt/ir_context.h index ac4e4578..00b72dc8 100644 --- a/source/opt/ir_context.h +++ b/source/opt/ir_context.h @@ -126,8 +126,8 @@ class IRContext { inline IteratorRange<Module::const_inst_iterator> capabilities() const; // Iterators for types, constants and global variables instructions. - inline opt::Module::inst_iterator types_values_begin(); - inline opt::Module::inst_iterator types_values_end(); + inline Module::inst_iterator types_values_begin(); + inline Module::inst_iterator types_values_end(); inline IteratorRange<Module::inst_iterator> types_values(); inline IteratorRange<Module::const_inst_iterator> types_values() const; @@ -203,7 +203,7 @@ class IRContext { // Returns a pointer to a def-use manager. If the def-use manager is // invalid, it is rebuilt first. - opt::analysis::DefUseManager* get_def_use_mgr() { + analysis::DefUseManager* get_def_use_mgr() { if (!AreAnalysesValid(kAnalysisDefUse)) { BuildDefUseManager(); } @@ -212,7 +212,7 @@ class IRContext { // Returns a pointer to a value number table. If the liveness analysis is // invalid, it is rebuilt first. - opt::ValueNumberTable* GetValueNumberTable() { + ValueNumberTable* GetValueNumberTable() { if (!AreAnalysesValid(kAnalysisValueNumberTable)) { BuildValueNumberTable(); } @@ -221,7 +221,7 @@ class IRContext { // Returns a pointer to a liveness analysis. If the liveness analysis is // invalid, it is rebuilt first. - opt::LivenessAnalysis* GetLivenessAnalysis() { + LivenessAnalysis* GetLivenessAnalysis() { if (!AreAnalysesValid(kAnalysisRegisterPressure)) { BuildRegPressureAnalysis(); } @@ -230,7 +230,7 @@ class IRContext { // Returns the basic block for instruction |instr|. Re-builds the instruction // block map, if needed. - opt::BasicBlock* get_instr_block(opt::Instruction* instr) { + BasicBlock* get_instr_block(Instruction* instr) { if (!AreAnalysesValid(kAnalysisInstrToBlockMapping)) { BuildInstrToBlockMapping(); } @@ -242,14 +242,14 @@ class IRContext { // needed. // // |id| must be a registered definition. - opt::BasicBlock* get_instr_block(uint32_t id) { - opt::Instruction* def = get_def_use_mgr()->GetDef(id); + BasicBlock* get_instr_block(uint32_t id) { + Instruction* def = get_def_use_mgr()->GetDef(id); return get_instr_block(def); } // Sets the basic block for |inst|. Re-builds the mapping if it has become // invalid. - void set_instr_block(opt::Instruction* inst, opt::BasicBlock* block) { + void set_instr_block(Instruction* inst, BasicBlock* block) { if (AreAnalysesValid(kAnalysisInstrToBlockMapping)) { instr_to_block_[inst] = block; } @@ -257,7 +257,7 @@ class IRContext { // Returns a pointer the decoration manager. If the decoration manger is // invalid, it is rebuilt first. - opt::analysis::DecorationManager* get_decoration_mgr() { + analysis::DecorationManager* get_decoration_mgr() { if (!AreAnalysesValid(kAnalysisDecorations)) { BuildDecorationManager(); } @@ -267,24 +267,24 @@ class IRContext { // Returns a pointer to the constant manager. If no constant manager has been // created yet, it creates one. NOTE: Once created, the constant manager // remains active and it is never re-built. - opt::analysis::ConstantManager* get_constant_mgr() { + analysis::ConstantManager* get_constant_mgr() { if (!constant_mgr_) - constant_mgr_.reset(new opt::analysis::ConstantManager(this)); + constant_mgr_.reset(new analysis::ConstantManager(this)); return constant_mgr_.get(); } // Returns a pointer to the type manager. If no type manager has been created // yet, it creates one. NOTE: Once created, the type manager remains active it // is never re-built. - opt::analysis::TypeManager* get_type_mgr() { + analysis::TypeManager* get_type_mgr() { if (!type_mgr_) - type_mgr_.reset(new opt::analysis::TypeManager(consumer(), this)); + type_mgr_.reset(new analysis::TypeManager(consumer(), this)); return type_mgr_.get(); } // Returns a pointer to the scalar evolution analysis. If it is invalid it // will be rebuilt first. - opt::ScalarEvolutionAnalysis* GetScalarEvolutionAnalysis() { + ScalarEvolutionAnalysis* GetScalarEvolutionAnalysis() { if (!AreAnalysesValid(kAnalysisScalarEvolution)) { BuildScalarEvolutionAnalysis(); } @@ -337,7 +337,7 @@ class IRContext { // // Returns a pointer to the instruction after |inst| or |nullptr| if no such // instruction exists. - Instruction* KillInst(opt::Instruction* inst); + Instruction* KillInst(Instruction* inst); // Returns true if all of the given analyses are valid. bool AreAnalysesValid(Analysis set) { return (set & valid_analyses_) == set; } @@ -371,7 +371,7 @@ class IRContext { void KillNamesAndDecorates(uint32_t id); // Kill all name and decorate ops targeting the result id of |inst|. - void KillNamesAndDecorates(opt::Instruction* inst); + void KillNamesAndDecorates(Instruction* inst); // Returns the next unique id for use by an instruction. inline uint32_t TakeNextUniqueId() { @@ -400,7 +400,7 @@ class IRContext { } // Returns a pointer to the CFG for all the functions in |module_|. - opt::CFG* cfg() { + CFG* cfg() { if (!AreAnalysesValid(kAnalysisCFG)) { BuildCFG(); } @@ -408,28 +408,28 @@ class IRContext { } // Gets the loop descriptor for function |f|. - opt::LoopDescriptor* GetLoopDescriptor(const opt::Function* f); + LoopDescriptor* GetLoopDescriptor(const Function* f); // Gets the dominator analysis for function |f|. - opt::DominatorAnalysis* GetDominatorAnalysis(const opt::Function* f); + DominatorAnalysis* GetDominatorAnalysis(const Function* f); // Gets the postdominator analysis for function |f|. - opt::PostDominatorAnalysis* GetPostDominatorAnalysis(const opt::Function* f); + PostDominatorAnalysis* GetPostDominatorAnalysis(const Function* f); // Remove the dominator tree of |f| from the cache. - inline void RemoveDominatorAnalysis(const opt::Function* f) { + inline void RemoveDominatorAnalysis(const Function* f) { dominator_trees_.erase(f); } // Remove the postdominator tree of |f| from the cache. - inline void RemovePostDominatorAnalysis(const opt::Function* f) { + inline void RemovePostDominatorAnalysis(const Function* f) { post_dominator_trees_.erase(f); } // Return the next available SSA id and increment it. inline uint32_t TakeNextId() { return module()->TakeNextIdBound(); } - opt::FeatureManager* get_feature_mgr() { + FeatureManager* get_feature_mgr() { if (!feature_mgr_.get()) { AnalyzeFeatures(); } @@ -443,9 +443,9 @@ class IRContext { // its definitions and uses. inline void UpdateDefUse(Instruction* inst); - const opt::InstructionFolder& get_instruction_folder() { + const InstructionFolder& get_instruction_folder() { if (!inst_folder_) { - inst_folder_.reset(new opt::InstructionFolder(this)); + inst_folder_.reset(new InstructionFolder(this)); } return *inst_folder_; } @@ -453,7 +453,7 @@ class IRContext { private: // Builds the def-use manager from scratch, even if it was already valid. void BuildDefUseManager() { - def_use_mgr_.reset(new opt::analysis::DefUseManager(module())); + def_use_mgr_.reset(new analysis::DefUseManager(module())); valid_analyses_ = valid_analyses_ | kAnalysisDefUse; } @@ -462,7 +462,7 @@ class IRContext { instr_to_block_.clear(); for (auto& fn : *module_) { for (auto& block : fn) { - block.ForEachInst([this, &block](opt::Instruction* inst) { + block.ForEachInst([this, &block](Instruction* inst) { instr_to_block_[inst] = █ }); } @@ -471,30 +471,30 @@ class IRContext { } void BuildDecorationManager() { - decoration_mgr_.reset(new opt::analysis::DecorationManager(module())); + decoration_mgr_.reset(new analysis::DecorationManager(module())); valid_analyses_ = valid_analyses_ | kAnalysisDecorations; } void BuildCFG() { - cfg_.reset(new opt::CFG(module())); + cfg_.reset(new CFG(module())); valid_analyses_ = valid_analyses_ | kAnalysisCFG; } void BuildScalarEvolutionAnalysis() { - scalar_evolution_analysis_.reset(new opt::ScalarEvolutionAnalysis(this)); + scalar_evolution_analysis_.reset(new ScalarEvolutionAnalysis(this)); valid_analyses_ = valid_analyses_ | kAnalysisScalarEvolution; } // Builds the liveness analysis from scratch, even if it was already valid. void BuildRegPressureAnalysis() { - reg_pressure_.reset(new opt::LivenessAnalysis(this)); + reg_pressure_.reset(new LivenessAnalysis(this)); valid_analyses_ = valid_analyses_ | kAnalysisRegisterPressure; } // Builds the value number table analysis from scratch, even if it was already // valid. void BuildValueNumberTable() { - vn_table_.reset(new opt::ValueNumberTable(this)); + vn_table_.reset(new ValueNumberTable(this)); valid_analyses_ = valid_analyses_ | kAnalysisValueNumberTable; } @@ -516,7 +516,7 @@ class IRContext { // Analyzes the features in the owned module. Builds the manager if required. void AnalyzeFeatures() { - feature_mgr_.reset(new opt::FeatureManager(grammar_)); + feature_mgr_.reset(new FeatureManager(grammar_)); feature_mgr_->Analyze(module()); } @@ -528,7 +528,7 @@ class IRContext { void AddCombinatorsForCapability(uint32_t capability); // Add the combinator opcode for the given extension to combinator_ops_. - void AddCombinatorsForExtension(opt::Instruction* extension); + void AddCombinatorsForExtension(Instruction* extension); // Remove |inst| from |id_to_name_| if it is in map. void RemoveFromIdToName(const Instruction* inst); @@ -558,18 +558,18 @@ class IRContext { MessageConsumer consumer_; // The def-use manager for |module_|. - std::unique_ptr<opt::analysis::DefUseManager> def_use_mgr_; + std::unique_ptr<analysis::DefUseManager> def_use_mgr_; // The instruction decoration manager for |module_|. - std::unique_ptr<opt::analysis::DecorationManager> decoration_mgr_; - std::unique_ptr<opt::FeatureManager> feature_mgr_; + std::unique_ptr<analysis::DecorationManager> decoration_mgr_; + std::unique_ptr<FeatureManager> feature_mgr_; // A map from instructions the the basic block they belong to. This mapping is // built on-demand when get_instr_block() is called. // // NOTE: Do not traverse this map. Ever. Use the function and basic block // iterators to traverse instructions. - std::unordered_map<opt::Instruction*, opt::BasicBlock*> instr_to_block_; + std::unordered_map<Instruction*, BasicBlock*> instr_to_block_; // A bitset indicating which analyes are currently valid. Analysis valid_analyses_; @@ -579,59 +579,55 @@ class IRContext { std::unordered_map<uint32_t, std::unordered_set<uint32_t>> combinator_ops_; // The CFG for all the functions in |module_|. - std::unique_ptr<opt::CFG> cfg_; + std::unique_ptr<CFG> cfg_; // Each function in the module will create its own dominator tree. We cache // the result so it doesn't need to be rebuilt each time. - std::map<const opt::Function*, opt::DominatorAnalysis> dominator_trees_; - std::map<const opt::Function*, opt::PostDominatorAnalysis> - post_dominator_trees_; + std::map<const Function*, DominatorAnalysis> dominator_trees_; + std::map<const Function*, PostDominatorAnalysis> post_dominator_trees_; // Cache of loop descriptors for each function. - std::unordered_map<const opt::Function*, opt::LoopDescriptor> - loop_descriptors_; + std::unordered_map<const Function*, LoopDescriptor> loop_descriptors_; // Constant manager for |module_|. - std::unique_ptr<opt::analysis::ConstantManager> constant_mgr_; + std::unique_ptr<analysis::ConstantManager> constant_mgr_; // Type manager for |module_|. - std::unique_ptr<opt::analysis::TypeManager> type_mgr_; + std::unique_ptr<analysis::TypeManager> type_mgr_; // A map from an id to its corresponding OpName and OpMemberName instructions. std::unique_ptr<std::multimap<uint32_t, Instruction*>> id_to_name_; // The cache scalar evolution analysis node. - std::unique_ptr<opt::ScalarEvolutionAnalysis> scalar_evolution_analysis_; + std::unique_ptr<ScalarEvolutionAnalysis> scalar_evolution_analysis_; // The liveness analysis |module_|. - std::unique_ptr<opt::LivenessAnalysis> reg_pressure_; + std::unique_ptr<LivenessAnalysis> reg_pressure_; - std::unique_ptr<opt::ValueNumberTable> vn_table_; + std::unique_ptr<ValueNumberTable> vn_table_; - std::unique_ptr<opt::InstructionFolder> inst_folder_; + std::unique_ptr<InstructionFolder> inst_folder_; }; -inline opt::IRContext::Analysis operator|(opt::IRContext::Analysis lhs, - opt::IRContext::Analysis rhs) { - return static_cast<opt::IRContext::Analysis>(static_cast<int>(lhs) | - static_cast<int>(rhs)); +inline IRContext::Analysis operator|(IRContext::Analysis lhs, + IRContext::Analysis rhs) { + return static_cast<IRContext::Analysis>(static_cast<int>(lhs) | + static_cast<int>(rhs)); } -inline opt::IRContext::Analysis& operator|=(opt::IRContext::Analysis& lhs, - opt::IRContext::Analysis rhs) { - lhs = static_cast<opt::IRContext::Analysis>(static_cast<int>(lhs) | - static_cast<int>(rhs)); +inline IRContext::Analysis& operator|=(IRContext::Analysis& lhs, + IRContext::Analysis rhs) { + lhs = static_cast<IRContext::Analysis>(static_cast<int>(lhs) | + static_cast<int>(rhs)); return lhs; } -inline opt::IRContext::Analysis operator<<(opt::IRContext::Analysis a, - int shift) { - return static_cast<opt::IRContext::Analysis>(static_cast<int>(a) << shift); +inline IRContext::Analysis operator<<(IRContext::Analysis a, int shift) { + return static_cast<IRContext::Analysis>(static_cast<int>(a) << shift); } -inline opt::IRContext::Analysis& operator<<=(opt::IRContext::Analysis& a, - int shift) { - a = static_cast<opt::IRContext::Analysis>(static_cast<int>(a) << shift); +inline IRContext::Analysis& operator<<=(IRContext::Analysis& a, int shift) { + a = static_cast<IRContext::Analysis>(static_cast<int>(a) << shift); return a; } @@ -675,11 +671,11 @@ IteratorRange<Module::const_inst_iterator> IRContext::capabilities() const { return ((const Module*)module())->capabilities(); } -opt::Module::inst_iterator IRContext::types_values_begin() { +Module::inst_iterator IRContext::types_values_begin() { return module()->types_values_begin(); } -opt::Module::inst_iterator IRContext::types_values_end() { +Module::inst_iterator IRContext::types_values_end() { return module()->types_values_end(); } diff --git a/source/opt/licm_pass.cpp b/source/opt/licm_pass.cpp index 042e2a6e..84871138 100644 --- a/source/opt/licm_pass.cpp +++ b/source/opt/licm_pass.cpp @@ -29,21 +29,21 @@ Pass::Status LICMPass::Process() { bool LICMPass::ProcessIRContext() { bool modified = false; - opt::Module* module = get_module(); + Module* module = get_module(); // Process each function in the module - for (opt::Function& f : *module) { + for (Function& f : *module) { modified |= ProcessFunction(&f); } return modified; } -bool LICMPass::ProcessFunction(opt::Function* f) { +bool LICMPass::ProcessFunction(Function* f) { bool modified = false; - opt::LoopDescriptor* loop_descriptor = context()->GetLoopDescriptor(f); + LoopDescriptor* loop_descriptor = context()->GetLoopDescriptor(f); // Process each loop in the function - for (opt::Loop& loop : *loop_descriptor) { + for (Loop& loop : *loop_descriptor) { // Ignore nested loops, as we will process them in order in ProcessLoop if (loop.IsNested()) { continue; @@ -53,19 +53,19 @@ bool LICMPass::ProcessFunction(opt::Function* f) { return modified; } -bool LICMPass::ProcessLoop(opt::Loop* loop, opt::Function* f) { +bool LICMPass::ProcessLoop(Loop* loop, Function* f) { bool modified = false; // Process all nested loops first - for (opt::Loop* nested_loop : *loop) { + for (Loop* nested_loop : *loop) { modified |= ProcessLoop(nested_loop, f); } - std::vector<opt::BasicBlock*> loop_bbs{}; + std::vector<BasicBlock*> loop_bbs{}; modified |= AnalyseAndHoistFromBB(loop, f, loop->GetHeaderBlock(), &loop_bbs); for (size_t i = 0; i < loop_bbs.size(); ++i) { - opt::BasicBlock* bb = loop_bbs[i]; + BasicBlock* bb = loop_bbs[i]; // do not delete the element modified |= AnalyseAndHoistFromBB(loop, f, bb, &loop_bbs); } @@ -73,12 +73,11 @@ bool LICMPass::ProcessLoop(opt::Loop* loop, opt::Function* f) { return modified; } -bool LICMPass::AnalyseAndHoistFromBB(opt::Loop* loop, opt::Function* f, - opt::BasicBlock* bb, - std::vector<opt::BasicBlock*>* loop_bbs) { +bool LICMPass::AnalyseAndHoistFromBB(Loop* loop, Function* f, BasicBlock* bb, + std::vector<BasicBlock*>* loop_bbs) { bool modified = false; - std::function<void(opt::Instruction*)> hoist_inst = - [this, &loop, &modified](opt::Instruction* inst) { + std::function<void(Instruction*)> hoist_inst = + [this, &loop, &modified](Instruction* inst) { if (loop->ShouldHoistInstruction(this->context(), inst)) { HoistInstruction(loop, inst); modified = true; @@ -89,11 +88,10 @@ bool LICMPass::AnalyseAndHoistFromBB(opt::Loop* loop, opt::Function* f, bb->ForEachInst(hoist_inst, false); } - opt::DominatorAnalysis* dom_analysis = context()->GetDominatorAnalysis(f); - opt::DominatorTree& dom_tree = dom_analysis->GetDomTree(); + DominatorAnalysis* dom_analysis = context()->GetDominatorAnalysis(f); + DominatorTree& dom_tree = dom_analysis->GetDomTree(); - for (opt::DominatorTreeNode* child_dom_tree_node : - *dom_tree.GetTreeNode(bb)) { + for (DominatorTreeNode* child_dom_tree_node : *dom_tree.GetTreeNode(bb)) { if (loop->IsInsideLoop(child_dom_tree_node->bb_)) { loop_bbs->push_back(child_dom_tree_node->bb_); } @@ -102,14 +100,14 @@ bool LICMPass::AnalyseAndHoistFromBB(opt::Loop* loop, opt::Function* f, return modified; } -bool LICMPass::IsImmediatelyContainedInLoop(opt::Loop* loop, opt::Function* f, - opt::BasicBlock* bb) { - opt::LoopDescriptor* loop_descriptor = context()->GetLoopDescriptor(f); +bool LICMPass::IsImmediatelyContainedInLoop(Loop* loop, Function* f, + BasicBlock* bb) { + LoopDescriptor* loop_descriptor = context()->GetLoopDescriptor(f); return loop == (*loop_descriptor)[bb->id()]; } -void LICMPass::HoistInstruction(opt::Loop* loop, opt::Instruction* inst) { - opt::BasicBlock* pre_header_bb = loop->GetOrCreatePreHeaderBlock(); +void LICMPass::HoistInstruction(Loop* loop, Instruction* inst) { + BasicBlock* pre_header_bb = loop->GetOrCreatePreHeaderBlock(); inst->InsertBefore(std::move(&(*pre_header_bb->tail()))); context()->set_instr_block(inst, pre_header_bb); } diff --git a/source/opt/licm_pass.h b/source/opt/licm_pass.h index 811e54f0..c7d6bc6e 100644 --- a/source/opt/licm_pass.h +++ b/source/opt/licm_pass.h @@ -40,26 +40,24 @@ class LICMPass : public Pass { // Checks the function for loops, calling ProcessLoop on each one found. // Returns true if a change was made to the function, false otherwise. - bool ProcessFunction(opt::Function* f); + bool ProcessFunction(Function* f); // Checks for invariants in the loop and attempts to move them to the loops // preheader. Works from inner loop to outer when nested loops are found. // Returns true if a change was made to the loop, false otherwise. - bool ProcessLoop(opt::Loop* loop, opt::Function* f); + bool ProcessLoop(Loop* loop, Function* f); // Analyses each instruction in |bb|, hoisting invariants to |pre_header_bb|. // Each child of |bb| wrt to |dom_tree| is pushed to |loop_bbs| - bool AnalyseAndHoistFromBB(opt::Loop* loop, opt::Function* f, - opt::BasicBlock* bb, - std::vector<opt::BasicBlock*>* loop_bbs); + bool AnalyseAndHoistFromBB(Loop* loop, Function* f, BasicBlock* bb, + std::vector<BasicBlock*>* loop_bbs); // Returns true if |bb| is immediately contained in |loop| - bool IsImmediatelyContainedInLoop(opt::Loop* loop, opt::Function* f, - opt::BasicBlock* bb); + bool IsImmediatelyContainedInLoop(Loop* loop, Function* f, BasicBlock* bb); // Move the instruction to the given BasicBlock // This method will update the instruction to block mapping for the context - void HoistInstruction(opt::Loop* loop, opt::Instruction* inst); + void HoistInstruction(Loop* loop, Instruction* inst); }; } // namespace opt diff --git a/source/opt/local_access_chain_convert_pass.cpp b/source/opt/local_access_chain_convert_pass.cpp index 4d7fe4ea..26108a72 100644 --- a/source/opt/local_access_chain_convert_pass.cpp +++ b/source/opt/local_access_chain_convert_pass.cpp @@ -33,20 +33,20 @@ const uint32_t kTypeIntWidthInIdx = 0; void LocalAccessChainConvertPass::BuildAndAppendInst( SpvOp opcode, uint32_t typeId, uint32_t resultId, - const std::vector<opt::Operand>& in_opnds, - std::vector<std::unique_ptr<opt::Instruction>>* newInsts) { - std::unique_ptr<opt::Instruction> newInst( - new opt::Instruction(context(), opcode, typeId, resultId, in_opnds)); + const std::vector<Operand>& in_opnds, + std::vector<std::unique_ptr<Instruction>>* newInsts) { + std::unique_ptr<Instruction> newInst( + new Instruction(context(), opcode, typeId, resultId, in_opnds)); get_def_use_mgr()->AnalyzeInstDefUse(&*newInst); newInsts->emplace_back(std::move(newInst)); } uint32_t LocalAccessChainConvertPass::BuildAndAppendVarLoad( - const opt::Instruction* ptrInst, uint32_t* varId, uint32_t* varPteTypeId, - std::vector<std::unique_ptr<opt::Instruction>>* newInsts) { + const Instruction* ptrInst, uint32_t* varId, uint32_t* varPteTypeId, + std::vector<std::unique_ptr<Instruction>>* newInsts) { const uint32_t ldResultId = TakeNextId(); *varId = ptrInst->GetSingleWordInOperand(kAccessChainPtrIdInIdx); - const opt::Instruction* varInst = get_def_use_mgr()->GetDef(*varId); + const Instruction* varInst = get_def_use_mgr()->GetDef(*varId); assert(varInst->opcode() == SpvOpVariable); *varPteTypeId = GetPointeeTypeId(varInst); BuildAndAppendInst(SpvOpLoad, *varPteTypeId, ldResultId, @@ -56,11 +56,11 @@ uint32_t LocalAccessChainConvertPass::BuildAndAppendVarLoad( } void LocalAccessChainConvertPass::AppendConstantOperands( - const opt::Instruction* ptrInst, std::vector<opt::Operand>* in_opnds) { + const Instruction* ptrInst, std::vector<Operand>* in_opnds) { uint32_t iidIdx = 0; ptrInst->ForEachInId([&iidIdx, &in_opnds, this](const uint32_t* iid) { if (iidIdx > 0) { - const opt::Instruction* cInst = get_def_use_mgr()->GetDef(*iid); + const Instruction* cInst = get_def_use_mgr()->GetDef(*iid); uint32_t val = cInst->GetSingleWordInOperand(kConstantValueInIdx); in_opnds->push_back( {spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER, {val}}); @@ -70,8 +70,8 @@ void LocalAccessChainConvertPass::AppendConstantOperands( } uint32_t LocalAccessChainConvertPass::GenAccessChainLoadReplacement( - const opt::Instruction* ptrInst, - std::vector<std::unique_ptr<opt::Instruction>>* newInsts) { + const Instruction* ptrInst, + std::vector<std::unique_ptr<Instruction>>* newInsts) { // Build and append load of variable in ptrInst uint32_t varId; uint32_t varPteTypeId; @@ -81,7 +81,7 @@ uint32_t LocalAccessChainConvertPass::GenAccessChainLoadReplacement( // Build and append Extract const uint32_t extResultId = TakeNextId(); const uint32_t ptrPteTypeId = GetPointeeTypeId(ptrInst); - std::vector<opt::Operand> ext_in_opnds = { + std::vector<Operand> ext_in_opnds = { {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {ldResultId}}}; AppendConstantOperands(ptrInst, &ext_in_opnds); BuildAndAppendInst(SpvOpCompositeExtract, ptrPteTypeId, extResultId, @@ -90,8 +90,8 @@ uint32_t LocalAccessChainConvertPass::GenAccessChainLoadReplacement( } void LocalAccessChainConvertPass::GenAccessChainStoreReplacement( - const opt::Instruction* ptrInst, uint32_t valId, - std::vector<std::unique_ptr<opt::Instruction>>* newInsts) { + const Instruction* ptrInst, uint32_t valId, + std::vector<std::unique_ptr<Instruction>>* newInsts) { // Build and append load of variable in ptrInst uint32_t varId; uint32_t varPteTypeId; @@ -100,7 +100,7 @@ void LocalAccessChainConvertPass::GenAccessChainStoreReplacement( // Build and append Insert const uint32_t insResultId = TakeNextId(); - std::vector<opt::Operand> ins_in_opnds = { + std::vector<Operand> ins_in_opnds = { {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {valId}}, {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {ldResultId}}}; AppendConstantOperands(ptrInst, &ins_in_opnds); @@ -115,11 +115,11 @@ void LocalAccessChainConvertPass::GenAccessChainStoreReplacement( } bool LocalAccessChainConvertPass::IsConstantIndexAccessChain( - const opt::Instruction* acp) const { + const Instruction* acp) const { uint32_t inIdx = 0; return acp->WhileEachInId([&inIdx, this](const uint32_t* tid) { if (inIdx > 0) { - opt::Instruction* opInst = get_def_use_mgr()->GetDef(*tid); + Instruction* opInst = get_def_use_mgr()->GetDef(*tid); if (opInst->opcode() != SpvOpConstant) return false; } ++inIdx; @@ -129,7 +129,7 @@ bool LocalAccessChainConvertPass::IsConstantIndexAccessChain( bool LocalAccessChainConvertPass::HasOnlySupportedRefs(uint32_t ptrId) { if (supported_ref_ptrs_.find(ptrId) != supported_ref_ptrs_.end()) return true; - if (get_def_use_mgr()->WhileEachUser(ptrId, [this](opt::Instruction* user) { + if (get_def_use_mgr()->WhileEachUser(ptrId, [this](Instruction* user) { SpvOp op = user->opcode(); if (IsNonPtrAccessChain(op) || op == SpvOpCopyObject) { if (!HasOnlySupportedRefs(user->result_id())) { @@ -147,14 +147,14 @@ bool LocalAccessChainConvertPass::HasOnlySupportedRefs(uint32_t ptrId) { return false; } -void LocalAccessChainConvertPass::FindTargetVars(opt::Function* func) { +void LocalAccessChainConvertPass::FindTargetVars(Function* func) { for (auto bi = func->begin(); bi != func->end(); ++bi) { for (auto ii = bi->begin(); ii != bi->end(); ++ii) { switch (ii->opcode()) { case SpvOpStore: case SpvOpLoad: { uint32_t varId; - opt::Instruction* ptrInst = GetPtr(&*ii, &varId); + Instruction* ptrInst = GetPtr(&*ii, &varId); if (!IsTargetVar(varId)) break; const SpvOp op = ptrInst->opcode(); // Rule out variables with non-supported refs eg function calls @@ -185,22 +185,21 @@ void LocalAccessChainConvertPass::FindTargetVars(opt::Function* func) { } } -bool LocalAccessChainConvertPass::ConvertLocalAccessChains( - opt::Function* func) { +bool LocalAccessChainConvertPass::ConvertLocalAccessChains(Function* func) { FindTargetVars(func); // Replace access chains of all targeted variables with equivalent // extract and insert sequences bool modified = false; for (auto bi = func->begin(); bi != func->end(); ++bi) { - std::vector<opt::Instruction*> dead_instructions; + std::vector<Instruction*> dead_instructions; for (auto ii = bi->begin(); ii != bi->end(); ++ii) { switch (ii->opcode()) { case SpvOpLoad: { uint32_t varId; - opt::Instruction* ptrInst = GetPtr(&*ii, &varId); + Instruction* ptrInst = GetPtr(&*ii, &varId); if (!IsNonPtrAccessChain(ptrInst->opcode())) break; if (!IsTargetVar(varId)) break; - std::vector<std::unique_ptr<opt::Instruction>> newInsts; + std::vector<std::unique_ptr<Instruction>> newInsts; uint32_t replId = GenAccessChainLoadReplacement(ptrInst, &newInsts); context()->KillNamesAndDecorates(&*ii); context()->ReplaceAllUsesWith(ii->result_id(), replId); @@ -212,10 +211,10 @@ bool LocalAccessChainConvertPass::ConvertLocalAccessChains( } break; case SpvOpStore: { uint32_t varId; - opt::Instruction* ptrInst = GetPtr(&*ii, &varId); + Instruction* ptrInst = GetPtr(&*ii, &varId); if (!IsNonPtrAccessChain(ptrInst->opcode())) break; if (!IsTargetVar(varId)) break; - std::vector<std::unique_ptr<opt::Instruction>> newInsts; + std::vector<std::unique_ptr<Instruction>> newInsts; uint32_t valId = ii->GetSingleWordInOperand(kStoreValIdInIdx); GenAccessChainStoreReplacement(ptrInst, valId, &newInsts); dead_instructions.push_back(&*ii); @@ -231,9 +230,9 @@ bool LocalAccessChainConvertPass::ConvertLocalAccessChains( } while (!dead_instructions.empty()) { - opt::Instruction* inst = dead_instructions.back(); + Instruction* inst = dead_instructions.back(); dead_instructions.pop_back(); - DCEInst(inst, [&dead_instructions](opt::Instruction* other_inst) { + DCEInst(inst, [&dead_instructions](Instruction* other_inst) { auto i = std::find(dead_instructions.begin(), dead_instructions.end(), other_inst); if (i != dead_instructions.end()) { @@ -271,7 +270,7 @@ bool LocalAccessChainConvertPass::AllExtensionsSupported() const { Pass::Status LocalAccessChainConvertPass::ProcessImpl() { // If non-32-bit integer type in module, terminate processing // TODO(): Handle non-32-bit integer constants in access chains - for (const opt::Instruction& inst : get_module()->types_values()) + for (const Instruction& inst : get_module()->types_values()) if (inst.opcode() == SpvOpTypeInt && inst.GetSingleWordInOperand(kTypeIntWidthInIdx) != 32) return Status::SuccessWithoutChange; @@ -283,7 +282,7 @@ Pass::Status LocalAccessChainConvertPass::ProcessImpl() { // Do not process if any disallowed extensions are enabled if (!AllExtensionsSupported()) return Status::SuccessWithoutChange; // Process all entry point functions. - ProcessFunction pfn = [this](opt::Function* fp) { + ProcessFunction pfn = [this](Function* fp) { return ConvertLocalAccessChains(fp); }; bool modified = ProcessEntryPointCallTree(pfn, get_module()); diff --git a/source/opt/local_access_chain_convert_pass.h b/source/opt/local_access_chain_convert_pass.h index 26554317..a57c3022 100644 --- a/source/opt/local_access_chain_convert_pass.h +++ b/source/opt/local_access_chain_convert_pass.h @@ -40,11 +40,11 @@ class LocalAccessChainConvertPass : public MemPass { const char* name() const override { return "convert-local-access-chains"; } Status Process() override; - opt::IRContext::Analysis GetPreservedAnalyses() override { - return opt::IRContext::kAnalysisDefUse; + IRContext::Analysis GetPreservedAnalyses() override { + return IRContext::kAnalysisDefUse; } - using ProcessFunction = std::function<bool(opt::Function*)>; + using ProcessFunction = std::function<bool(Function*)>; private: // Return true if all refs through |ptrId| are only loads or stores and @@ -56,42 +56,41 @@ class LocalAccessChainConvertPass : public MemPass { // Search |func| and cache function scope variables of target type that are // not accessed with non-constant-index access chains. Also cache non-target // variables. - void FindTargetVars(opt::Function* func); + void FindTargetVars(Function* func); // Build instruction from |opcode|, |typeId|, |resultId|, and |in_opnds|. // Append to |newInsts|. - void BuildAndAppendInst( - SpvOp opcode, uint32_t typeId, uint32_t resultId, - const std::vector<opt::Operand>& in_opnds, - std::vector<std::unique_ptr<opt::Instruction>>* newInsts); + void BuildAndAppendInst(SpvOp opcode, uint32_t typeId, uint32_t resultId, + const std::vector<Operand>& in_opnds, + std::vector<std::unique_ptr<Instruction>>* newInsts); // Build load of variable in |ptrInst| and append to |newInsts|. // Return var in |varId| and its pointee type in |varPteTypeId|. uint32_t BuildAndAppendVarLoad( - const opt::Instruction* ptrInst, uint32_t* varId, uint32_t* varPteTypeId, - std::vector<std::unique_ptr<opt::Instruction>>* newInsts); + const Instruction* ptrInst, uint32_t* varId, uint32_t* varPteTypeId, + std::vector<std::unique_ptr<Instruction>>* newInsts); // Append literal integer operands to |in_opnds| corresponding to constant // integer operands from access chain |ptrInst|. Assumes all indices in // access chains are OpConstant. - void AppendConstantOperands(const opt::Instruction* ptrInst, - std::vector<opt::Operand>* in_opnds); + void AppendConstantOperands(const Instruction* ptrInst, + std::vector<Operand>* in_opnds); // Create a load/insert/store equivalent to a store of // |valId| through (constant index) access chaing |ptrInst|. // Append to |newInsts|. void GenAccessChainStoreReplacement( - const opt::Instruction* ptrInst, uint32_t valId, - std::vector<std::unique_ptr<opt::Instruction>>* newInsts); + const Instruction* ptrInst, uint32_t valId, + std::vector<std::unique_ptr<Instruction>>* newInsts); // For the (constant index) access chain |ptrInst|, create an // equivalent load and extract. Append to |newInsts|. uint32_t GenAccessChainLoadReplacement( - const opt::Instruction* ptrInst, - std::vector<std::unique_ptr<opt::Instruction>>* newInsts); + const Instruction* ptrInst, + std::vector<std::unique_ptr<Instruction>>* newInsts); // Return true if all indices of access chain |acp| are OpConstant integers - bool IsConstantIndexAccessChain(const opt::Instruction* acp) const; + bool IsConstantIndexAccessChain(const Instruction* acp) const; // Identify all function scope variables of target type which are // accessed only with loads, stores and access chains with constant @@ -102,7 +101,7 @@ class LocalAccessChainConvertPass : public MemPass { // // Nested access chains and pointer access chains are not currently // converted. - bool ConvertLocalAccessChains(opt::Function* func); + bool ConvertLocalAccessChains(Function* func); // Initialize extensions whitelist void InitExtensions(); diff --git a/source/opt/local_redundancy_elimination.cpp b/source/opt/local_redundancy_elimination.cpp index 204dd6e0..85c1a083 100644 --- a/source/opt/local_redundancy_elimination.cpp +++ b/source/opt/local_redundancy_elimination.cpp @@ -37,12 +37,11 @@ Pass::Status LocalRedundancyEliminationPass::Process() { } bool LocalRedundancyEliminationPass::EliminateRedundanciesInBB( - opt::BasicBlock* block, const ValueNumberTable& vnTable, + BasicBlock* block, const ValueNumberTable& vnTable, std::map<uint32_t, uint32_t>* value_to_ids) { bool modified = false; - auto func = [this, &vnTable, &modified, - value_to_ids](opt::Instruction* inst) { + auto func = [this, &vnTable, &modified, value_to_ids](Instruction* inst) { if (inst->result_id() == 0) { return; } diff --git a/source/opt/local_redundancy_elimination.h b/source/opt/local_redundancy_elimination.h index 8776821c..8ec3538a 100644 --- a/source/opt/local_redundancy_elimination.h +++ b/source/opt/local_redundancy_elimination.h @@ -34,13 +34,12 @@ class LocalRedundancyEliminationPass : public Pass { const char* name() const override { return "local-redundancy-elimination"; } Status Process() override; - opt::IRContext::Analysis GetPreservedAnalyses() override { - return opt::IRContext::kAnalysisDefUse | - opt::IRContext::kAnalysisInstrToBlockMapping | - opt::IRContext::kAnalysisDecorations | - opt::IRContext::kAnalysisCombinators | opt::IRContext::kAnalysisCFG | - opt::IRContext::kAnalysisDominatorAnalysis | - opt::IRContext::kAnalysisNameMap; + IRContext::Analysis GetPreservedAnalyses() override { + return IRContext::kAnalysisDefUse | + IRContext::kAnalysisInstrToBlockMapping | + IRContext::kAnalysisDecorations | IRContext::kAnalysisCombinators | + IRContext::kAnalysisCFG | IRContext::kAnalysisDominatorAnalysis | + IRContext::kAnalysisNameMap; } protected: @@ -55,7 +54,7 @@ class LocalRedundancyEliminationPass : public Pass { // dominates |bb|. // // Returns true if the module is changed. - bool EliminateRedundanciesInBB(opt::BasicBlock* block, + bool EliminateRedundanciesInBB(BasicBlock* block, const ValueNumberTable& vnTable, std::map<uint32_t, uint32_t>* value_to_ids); }; diff --git a/source/opt/local_single_block_elim_pass.cpp b/source/opt/local_single_block_elim_pass.cpp index 811af58c..5a2ec8cd 100644 --- a/source/opt/local_single_block_elim_pass.cpp +++ b/source/opt/local_single_block_elim_pass.cpp @@ -29,7 +29,7 @@ const uint32_t kStoreValIdInIdx = 1; bool LocalSingleBlockLoadStoreElimPass::HasOnlySupportedRefs(uint32_t ptrId) { if (supported_ref_ptrs_.find(ptrId) != supported_ref_ptrs_.end()) return true; - if (get_def_use_mgr()->WhileEachUser(ptrId, [this](opt::Instruction* user) { + if (get_def_use_mgr()->WhileEachUser(ptrId, [this](Instruction* user) { SpvOp op = user->opcode(); if (IsNonPtrAccessChain(op) || op == SpvOpCopyObject) { if (!HasOnlySupportedRefs(user->result_id())) { @@ -48,12 +48,12 @@ bool LocalSingleBlockLoadStoreElimPass::HasOnlySupportedRefs(uint32_t ptrId) { } bool LocalSingleBlockLoadStoreElimPass::LocalSingleBlockLoadStoreElim( - opt::Function* func) { + Function* func) { // Perform local store/load, load/load and store/store elimination // on each block bool modified = false; - std::vector<opt::Instruction*> instructions_to_kill; - std::unordered_set<opt::Instruction*> instructions_to_save; + std::vector<Instruction*> instructions_to_kill; + std::unordered_set<Instruction*> instructions_to_save; for (auto bi = func->begin(); bi != func->end(); ++bi) { var2store_.clear(); var2load_.clear(); @@ -64,7 +64,7 @@ bool LocalSingleBlockLoadStoreElimPass::LocalSingleBlockLoadStoreElim( case SpvOpStore: { // Verify store variable is target type uint32_t varId; - opt::Instruction* ptrInst = GetPtr(&*ii, &varId); + Instruction* ptrInst = GetPtr(&*ii, &varId); if (!IsTargetVar(varId)) continue; if (!HasOnlySupportedRefs(varId)) continue; // If a store to the whole variable, remember it for succeeding @@ -106,7 +106,7 @@ bool LocalSingleBlockLoadStoreElimPass::LocalSingleBlockLoadStoreElim( case SpvOpLoad: { // Verify store variable is target type uint32_t varId; - opt::Instruction* ptrInst = GetPtr(&*ii, &varId); + Instruction* ptrInst = GetPtr(&*ii, &varId); if (!IsTargetVar(varId)) continue; if (!HasOnlySupportedRefs(varId)) continue; uint32_t replId = 0; @@ -151,7 +151,7 @@ bool LocalSingleBlockLoadStoreElimPass::LocalSingleBlockLoadStoreElim( } } - for (opt::Instruction* inst : instructions_to_kill) { + for (Instruction* inst : instructions_to_kill) { context()->KillInst(inst); } @@ -194,7 +194,7 @@ Pass::Status LocalSingleBlockLoadStoreElimPass::ProcessImpl() { // return unmodified. if (!AllExtensionsSupported()) return Status::SuccessWithoutChange; // Process all entry point functions - ProcessFunction pfn = [this](opt::Function* fp) { + ProcessFunction pfn = [this](Function* fp) { return LocalSingleBlockLoadStoreElim(fp); }; diff --git a/source/opt/local_single_block_elim_pass.h b/source/opt/local_single_block_elim_pass.h index b3a94ce9..faaf1d89 100644 --- a/source/opt/local_single_block_elim_pass.h +++ b/source/opt/local_single_block_elim_pass.h @@ -40,9 +40,8 @@ class LocalSingleBlockLoadStoreElimPass : public MemPass { const char* name() const override { return "eliminate-local-single-block"; } Status Process() override; - opt::IRContext::Analysis GetPreservedAnalyses() override { - return opt::IRContext::kAnalysisDefUse | - opt::IRContext::kAnalysisInstrToBlockMapping; + IRContext::Analysis GetPreservedAnalyses() override { + return IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping; } private: @@ -59,7 +58,7 @@ class LocalSingleBlockLoadStoreElimPass : public MemPass { // load id with previous id and delete load. Finally, check if // remaining stores are useless, and delete store and variable // where possible. Assumes logical addressing. - bool LocalSingleBlockLoadStoreElim(opt::Function* func); + bool LocalSingleBlockLoadStoreElim(Function* func); // Initialize extensions whitelist void InitExtensions(); @@ -75,14 +74,14 @@ class LocalSingleBlockLoadStoreElimPass : public MemPass { // at the start of each block and incrementally updated as the block // is scanned. The stores are candidates for elimination. The map is // conservatively cleared when a function call is encountered. - std::unordered_map<uint32_t, opt::Instruction*> var2store_; + std::unordered_map<uint32_t, Instruction*> var2store_; // Map from function scope variable to a load of that variable in the // current block whose value is currently valid. This map is cleared // at the start of each block and incrementally updated as the block // is scanned. The stores are candidates for elimination. The map is // conservatively cleared when a function call is encountered. - std::unordered_map<uint32_t, opt::Instruction*> var2load_; + std::unordered_map<uint32_t, Instruction*> var2load_; // Set of variables whose most recent store in the current block cannot be // deleted, for example, if there is a load of the variable which is diff --git a/source/opt/local_single_store_elim_pass.cpp b/source/opt/local_single_store_elim_pass.cpp index 3d3d297a..225356e5 100644 --- a/source/opt/local_single_store_elim_pass.cpp +++ b/source/opt/local_single_store_elim_pass.cpp @@ -30,12 +30,12 @@ const uint32_t kVariableInitIdInIdx = 1; } // anonymous namespace -bool LocalSingleStoreElimPass::LocalSingleStoreElim(opt::Function* func) { +bool LocalSingleStoreElimPass::LocalSingleStoreElim(Function* func) { bool modified = false; // Check all function scope variables in |func|. - opt::BasicBlock* entry_block = &*func->begin(); - for (opt::Instruction& inst : *entry_block) { + BasicBlock* entry_block = &*func->begin(); + for (Instruction& inst : *entry_block) { if (inst.opcode() != SpvOpVariable) { break; } @@ -64,7 +64,7 @@ Pass::Status LocalSingleStoreElimPass::ProcessImpl() { // Do not process if any disallowed extensions are enabled if (!AllExtensionsSupported()) return Status::SuccessWithoutChange; // Process all entry point functions - ProcessFunction pfn = [this](opt::Function* fp) { + ProcessFunction pfn = [this](Function* fp) { return LocalSingleStoreElim(fp); }; bool modified = ProcessEntryPointCallTree(pfn, get_module()); @@ -115,11 +115,11 @@ void LocalSingleStoreElimPass::InitExtensionWhiteList() { "SPV_EXT_descriptor_indexing", }); } -bool LocalSingleStoreElimPass::ProcessVariable(opt::Instruction* var_inst) { - vector<opt::Instruction*> users; +bool LocalSingleStoreElimPass::ProcessVariable(Instruction* var_inst) { + vector<Instruction*> users; FindUses(var_inst, &users); - opt::Instruction* store_inst = FindSingleStoreAndCheckUses(var_inst, users); + Instruction* store_inst = FindSingleStoreAndCheckUses(var_inst, users); if (store_inst == nullptr) { return false; @@ -128,17 +128,17 @@ bool LocalSingleStoreElimPass::ProcessVariable(opt::Instruction* var_inst) { return RewriteLoads(store_inst, users); } -opt::Instruction* LocalSingleStoreElimPass::FindSingleStoreAndCheckUses( - opt::Instruction* var_inst, const vector<opt::Instruction*>& users) const { +Instruction* LocalSingleStoreElimPass::FindSingleStoreAndCheckUses( + Instruction* var_inst, const vector<Instruction*>& users) const { // Make sure there is exactly 1 store. - opt::Instruction* store_inst = nullptr; + Instruction* store_inst = nullptr; // If |var_inst| has an initializer, then that will count as a store. if (var_inst->NumInOperands() > 1) { store_inst = var_inst; } - for (opt::Instruction* user : users) { + for (Instruction* user : users) { switch (user->opcode()) { case SpvOpStore: // Since we are in the relaxed addressing mode, the use has to be the @@ -177,10 +177,9 @@ opt::Instruction* LocalSingleStoreElimPass::FindSingleStoreAndCheckUses( } void LocalSingleStoreElimPass::FindUses( - const opt::Instruction* var_inst, - std::vector<opt::Instruction*>* users) const { + const Instruction* var_inst, std::vector<Instruction*>* users) const { analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr(); - def_use_mgr->ForEachUser(var_inst, [users, this](opt::Instruction* user) { + def_use_mgr->ForEachUser(var_inst, [users, this](Instruction* user) { users->push_back(user); if (user->opcode() == SpvOpCopyObject) { FindUses(user, users); @@ -188,9 +187,9 @@ void LocalSingleStoreElimPass::FindUses( }); } -bool LocalSingleStoreElimPass::FeedsAStore(opt::Instruction* inst) const { +bool LocalSingleStoreElimPass::FeedsAStore(Instruction* inst) const { analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr(); - return !def_use_mgr->WhileEachUser(inst, [this](opt::Instruction* user) { + return !def_use_mgr->WhileEachUser(inst, [this](Instruction* user) { switch (user->opcode()) { case SpvOpStore: return false; @@ -211,9 +210,9 @@ bool LocalSingleStoreElimPass::FeedsAStore(opt::Instruction* inst) const { } bool LocalSingleStoreElimPass::RewriteLoads( - opt::Instruction* store_inst, const std::vector<opt::Instruction*>& uses) { - opt::BasicBlock* store_block = context()->get_instr_block(store_inst); - opt::DominatorAnalysis* dominator_analysis = + Instruction* store_inst, const std::vector<Instruction*>& uses) { + BasicBlock* store_block = context()->get_instr_block(store_inst); + DominatorAnalysis* dominator_analysis = context()->GetDominatorAnalysis(store_block->GetParent()); uint32_t stored_id; @@ -222,9 +221,9 @@ bool LocalSingleStoreElimPass::RewriteLoads( else stored_id = store_inst->GetSingleWordInOperand(kVariableInitIdInIdx); - std::vector<opt::Instruction*> uses_in_store_block; + std::vector<Instruction*> uses_in_store_block; bool modified = false; - for (opt::Instruction* use : uses) { + for (Instruction* use : uses) { if (use->opcode() == SpvOpLoad) { if (dominator_analysis->Dominates(store_inst, use)) { modified = true; diff --git a/source/opt/local_single_store_elim_pass.h b/source/opt/local_single_store_elim_pass.h index eaa1ec5e..8d59b162 100644 --- a/source/opt/local_single_store_elim_pass.h +++ b/source/opt/local_single_store_elim_pass.h @@ -34,7 +34,7 @@ namespace opt { // See optimizer.hpp for documentation. class LocalSingleStoreElimPass : public Pass { - using cbb_ptr = const opt::BasicBlock*; + using cbb_ptr = const BasicBlock*; public: LocalSingleStoreElimPass(); @@ -42,9 +42,8 @@ class LocalSingleStoreElimPass : public Pass { const char* name() const override { return "eliminate-local-single-store"; } Status Process() override; - opt::IRContext::Analysis GetPreservedAnalyses() override { - return opt::IRContext::kAnalysisDefUse | - opt::IRContext::kAnalysisInstrToBlockMapping; + IRContext::Analysis GetPreservedAnalyses() override { + return IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping; } private: @@ -52,7 +51,7 @@ class LocalSingleStoreElimPass : public Pass { // with a single non-access-chain store in |func|. Replace all their // non-access-chain loads with the value that is stored and eliminate // any resulting dead code. - bool LocalSingleStoreElim(opt::Function* func); + bool LocalSingleStoreElim(Function* func); // Initialize extensions whitelist void InitExtensionWhiteList(); @@ -66,30 +65,29 @@ class LocalSingleStoreElimPass : public Pass { // variable, then replace all of the loads of the entire variable that are // dominated by the store by the value that was stored. Returns true if the // module was changed. - bool ProcessVariable(opt::Instruction* var_inst); + bool ProcessVariable(Instruction* var_inst); // Collects all of the uses of |var_inst| into |uses|. This looks through // OpObjectCopy's that copy the address of the variable, and collects those // uses as well. - void FindUses(const opt::Instruction* var_inst, - std::vector<opt::Instruction*>* uses) const; + void FindUses(const Instruction* var_inst, + std::vector<Instruction*>* uses) const; // Returns a store to |var_inst| if // - it is a store to the entire variable, // - and there are no other instructions that may modify |var_inst|. - opt::Instruction* FindSingleStoreAndCheckUses( - opt::Instruction* var_inst, - const std::vector<opt::Instruction*>& users) const; + Instruction* FindSingleStoreAndCheckUses( + Instruction* var_inst, const std::vector<Instruction*>& users) const; // Returns true if the address that results from |inst| may be used as a base // address in a store instruction or may be used to compute the base address // of a store instruction. - bool FeedsAStore(opt::Instruction* inst) const; + bool FeedsAStore(Instruction* inst) const; // Replaces all of the loads in |uses| by the value stored in |store_inst|. // The load instructions are then killed. - bool RewriteLoads(opt::Instruction* store_inst, - const std::vector<opt::Instruction*>& uses); + bool RewriteLoads(Instruction* store_inst, + const std::vector<Instruction*>& uses); // Extensions supported by this pass. std::unordered_set<std::string> extensions_whitelist_; diff --git a/source/opt/local_ssa_elim_pass.cpp b/source/opt/local_ssa_elim_pass.cpp index d9d4cb29..872d26b3 100644 --- a/source/opt/local_ssa_elim_pass.cpp +++ b/source/opt/local_ssa_elim_pass.cpp @@ -47,7 +47,7 @@ Pass::Status LocalMultiStoreElimPass::ProcessImpl() { // Do not process if any disallowed extensions are enabled if (!AllExtensionsSupported()) return Status::SuccessWithoutChange; // Process functions - ProcessFunction pfn = [this](opt::Function* fp) { + ProcessFunction pfn = [this](Function* fp) { return SSARewriter(this).RewriteFunctionIntoSSA(fp); }; bool modified = ProcessEntryPointCallTree(pfn, get_module()); diff --git a/source/opt/local_ssa_elim_pass.h b/source/opt/local_ssa_elim_pass.h index b4f58da1..c9d9cb96 100644 --- a/source/opt/local_ssa_elim_pass.h +++ b/source/opt/local_ssa_elim_pass.h @@ -34,20 +34,19 @@ namespace opt { // See optimizer.hpp for documentation. class LocalMultiStoreElimPass : public MemPass { - using cbb_ptr = const opt::BasicBlock*; + using cbb_ptr = const BasicBlock*; public: using GetBlocksFunction = - std::function<std::vector<opt::BasicBlock*>*(const opt::BasicBlock*)>; + std::function<std::vector<BasicBlock*>*(const BasicBlock*)>; LocalMultiStoreElimPass(); const char* name() const override { return "eliminate-local-multi-store"; } Status Process() override; - opt::IRContext::Analysis GetPreservedAnalyses() override { - return opt::IRContext::kAnalysisDefUse | - opt::IRContext::kAnalysisInstrToBlockMapping; + IRContext::Analysis GetPreservedAnalyses() override { + return IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping; } private: diff --git a/source/opt/loop_dependence.cpp b/source/opt/loop_dependence.cpp index 0b1b2d2c..82dbd1c0 100644 --- a/source/opt/loop_dependence.cpp +++ b/source/opt/loop_dependence.cpp @@ -181,16 +181,15 @@ bool NormalizeAndCompareFractions(int64_t numerator_0, int64_t denominator_0, } // namespace -bool LoopDependenceAnalysis::GetDependence(const opt::Instruction* source, - const opt::Instruction* destination, +bool LoopDependenceAnalysis::GetDependence(const Instruction* source, + const Instruction* destination, DistanceVector* distance_vector) { // Start off by finding and marking all the loops in |loops_| that are // irrelevant to the dependence analysis. MarkUnsusedDistanceEntriesAsIrrelevant(source, destination, distance_vector); - opt::Instruction* source_access_chain = GetOperandDefinition(source, 0); - opt::Instruction* destination_access_chain = - GetOperandDefinition(destination, 0); + Instruction* source_access_chain = GetOperandDefinition(source, 0); + Instruction* destination_access_chain = GetOperandDefinition(destination, 0); auto num_access_chains = (source_access_chain->opcode() == SpvOpAccessChain) + @@ -234,8 +233,8 @@ bool LoopDependenceAnalysis::GetDependence(const opt::Instruction* source, // If the access chains aren't collecting from the same structure there is no // dependence. - opt::Instruction* source_array = GetOperandDefinition(source_access_chain, 0); - opt::Instruction* destination_array = + Instruction* source_array = GetOperandDefinition(source_access_chain, 0); + Instruction* destination_array = GetOperandDefinition(destination_access_chain, 0); // Nested access chains are not supported yet, bail out. @@ -254,16 +253,15 @@ bool LoopDependenceAnalysis::GetDependence(const opt::Instruction* source, // To handle multiple subscripts we must get every operand in the access // chains past the first. - std::vector<opt::Instruction*> source_subscripts = GetSubscripts(source); - std::vector<opt::Instruction*> destination_subscripts = - GetSubscripts(destination); + std::vector<Instruction*> source_subscripts = GetSubscripts(source); + std::vector<Instruction*> destination_subscripts = GetSubscripts(destination); auto sets_of_subscripts = PartitionSubscripts(source_subscripts, destination_subscripts); auto first_coupled = std::partition( std::begin(sets_of_subscripts), std::end(sets_of_subscripts), - [](const std::set<std::pair<opt::Instruction*, opt::Instruction*>>& set) { + [](const std::set<std::pair<Instruction*, Instruction*>>& set) { return set.size() == 1; }); @@ -284,7 +282,7 @@ bool LoopDependenceAnalysis::GetDependence(const opt::Instruction* source, // Check the loops are in a form we support. auto subscript_pair = std::make_pair(source_node, destination_node); - const opt::Loop* loop = GetLoopForSubscriptPair(subscript_pair); + const Loop* loop = GetLoopForSubscriptPair(subscript_pair); if (loop) { if (!IsSupportedLoop(loop)) { PrintDebug( @@ -371,9 +369,9 @@ bool LoopDependenceAnalysis::GetDependence(const opt::Instruction* source, for (const auto& subscript : coupled_subscripts) { auto loops = CollectLoops(std::get<0>(subscript), std::get<1>(subscript)); - auto is_subscript_supported = std::all_of( - std::begin(loops), std::end(loops), - [this](const opt::Loop* l) { return IsSupportedLoop(l); }); + auto is_subscript_supported = + std::all_of(std::begin(loops), std::end(loops), + [this](const Loop* l) { return IsSupportedLoop(l); }); supported = supported && is_subscript_supported; } @@ -541,7 +539,7 @@ bool LoopDependenceAnalysis::StrongSIVTest(SENode* source, SENode* destination, // Build an SENode for distance. std::pair<SENode*, SENode*> subscript_pair = std::make_pair(source, destination); - const opt::Loop* subscript_loop = GetLoopForSubscriptPair(subscript_pair); + const Loop* subscript_loop = GetLoopForSubscriptPair(subscript_pair); SENode* source_constant_term = GetConstantTerm(subscript_loop, source->AsSERecurrentNode()); SENode* destination_constant_term = @@ -676,7 +674,7 @@ bool LoopDependenceAnalysis::SymbolicStrongSIVTest( // outwith the bounds. std::pair<SENode*, SENode*> subscript_pair = std::make_pair(source, destination); - const opt::Loop* subscript_loop = GetLoopForSubscriptPair(subscript_pair); + const Loop* subscript_loop = GetLoopForSubscriptPair(subscript_pair); if (IsProvablyOutsideOfLoopBounds(subscript_loop, source_destination_delta, coefficient)) { PrintDebug( @@ -701,7 +699,7 @@ bool LoopDependenceAnalysis::WeakZeroSourceSIVTest( PrintDebug("Performing WeakZeroSourceSIVTest."); std::pair<SENode*, SENode*> subscript_pair = std::make_pair(source, destination); - const opt::Loop* subscript_loop = GetLoopForSubscriptPair(subscript_pair); + const Loop* subscript_loop = GetLoopForSubscriptPair(subscript_pair); // Build an SENode for distance. SENode* destination_constant_term = GetConstantTerm(subscript_loop, destination); @@ -855,7 +853,7 @@ bool LoopDependenceAnalysis::WeakZeroDestinationSIVTest( // Build an SENode for distance. std::pair<SENode*, SENode*> subscript_pair = std::make_pair(source, destination); - const opt::Loop* subscript_loop = GetLoopForSubscriptPair(subscript_pair); + const Loop* subscript_loop = GetLoopForSubscriptPair(subscript_pair); SENode* source_constant_term = GetConstantTerm(subscript_loop, source); SENode* delta = scalar_evolution_.SimplifyExpression( scalar_evolution_.CreateSubtraction(destination, source_constant_term)); @@ -1115,10 +1113,10 @@ bool LoopDependenceAnalysis::GCDMIVTest( } using PartitionedSubscripts = - std::vector<std::set<std::pair<opt::Instruction*, opt::Instruction*>>>; + std::vector<std::set<std::pair<Instruction*, Instruction*>>>; PartitionedSubscripts LoopDependenceAnalysis::PartitionSubscripts( - const std::vector<opt::Instruction*>& source_subscripts, - const std::vector<opt::Instruction*>& destination_subscripts) { + const std::vector<Instruction*>& source_subscripts, + const std::vector<Instruction*>& destination_subscripts) { PartitionedSubscripts partitions{}; auto num_subscripts = source_subscripts.size(); @@ -1139,8 +1137,7 @@ PartitionedSubscripts LoopDependenceAnalysis::PartitionSubscripts( auto it = std::find_if( current_partition.begin(), current_partition.end(), [loop, - this](const std::pair<opt::Instruction*, opt::Instruction*>& elem) - -> bool { + this](const std::pair<Instruction*, Instruction*>& elem) -> bool { auto source_recurrences = scalar_evolution_.AnalyzeInstruction(std::get<0>(elem)) ->CollectRecurrentNodes(); @@ -1177,8 +1174,9 @@ PartitionedSubscripts LoopDependenceAnalysis::PartitionSubscripts( partitions.erase( std::remove_if( partitions.begin(), partitions.end(), - [](const std::set<std::pair<opt::Instruction*, opt::Instruction*>>& - partition) { return partition.empty(); }), + [](const std::set<std::pair<Instruction*, Instruction*>>& partition) { + return partition.empty(); + }), partitions.end()); return partitions; diff --git a/source/opt/loop_dependence.h b/source/opt/loop_dependence.h index b0aed6f9..2d2d20a0 100644 --- a/source/opt/loop_dependence.h +++ b/source/opt/loop_dependence.h @@ -167,7 +167,7 @@ class DependenceEmpty; class Constraint { public: - explicit Constraint(const opt::Loop* loop) : loop_(loop) {} + explicit Constraint(const Loop* loop) : loop_(loop) {} enum ConstraintType { Line, Distance, Point, None, Empty }; virtual ConstraintType GetType() const = 0; @@ -175,7 +175,7 @@ class Constraint { virtual ~Constraint() {} // Get the loop this constraint belongs to. - const opt::Loop* GetLoop() const { return loop_; } + const Loop* GetLoop() const { return loop_; } bool operator==(const Constraint& other) const; @@ -192,12 +192,12 @@ class Constraint { #undef DeclareCastMethod protected: - const opt::Loop* loop_; + const Loop* loop_; }; class DependenceLine : public Constraint { public: - DependenceLine(SENode* a, SENode* b, SENode* c, const opt::Loop* loop) + DependenceLine(SENode* a, SENode* b, SENode* c, const Loop* loop) : Constraint(loop), a_(a), b_(b), c_(c) {} ConstraintType GetType() const final { return Line; } @@ -217,7 +217,7 @@ class DependenceLine : public Constraint { class DependenceDistance : public Constraint { public: - DependenceDistance(SENode* distance, const opt::Loop* loop) + DependenceDistance(SENode* distance, const Loop* loop) : Constraint(loop), distance_(distance) {} ConstraintType GetType() const final { return Distance; } @@ -233,7 +233,7 @@ class DependenceDistance : public Constraint { class DependencePoint : public Constraint { public: - DependencePoint(SENode* source, SENode* destination, const opt::Loop* loop) + DependencePoint(SENode* source, SENode* destination, const Loop* loop) : Constraint(loop), source_(source), destination_(destination) {} ConstraintType GetType() const final { return Point; } @@ -294,8 +294,7 @@ class DependenceEmpty : public Constraint { // is present in the pair. class LoopDependenceAnalysis { public: - LoopDependenceAnalysis(opt::IRContext* context, - std::vector<const opt::Loop*> loops) + LoopDependenceAnalysis(IRContext* context, std::vector<const Loop*> loops) : context_(context), loops_(loops), scalar_evolution_(context), @@ -308,8 +307,7 @@ class LoopDependenceAnalysis { // Any direction and distance information found will be stored in // |distance_vector|. // Returns true if independence is found, false otherwise. - bool GetDependence(const opt::Instruction* source, - const opt::Instruction* destination, + bool GetDependence(const Instruction* source, const Instruction* destination, DistanceVector* distance_vector); // Returns true if |subscript_pair| represents a Zero Index Variable pair @@ -326,11 +324,11 @@ class LoopDependenceAnalysis { // Finds the lower bound of |loop| as an SENode* and returns the result. // The lower bound is the starting value of the loops induction variable - SENode* GetLowerBound(const opt::Loop* loop); + SENode* GetLowerBound(const Loop* loop); // Finds the upper bound of |loop| as an SENode* and returns the result. // The upper bound is the last value before the loop exit condition is met. - SENode* GetUpperBound(const opt::Loop* loop); + SENode* GetUpperBound(const Loop* loop); // Returns true if |value| is between |bound_one| and |bound_two| (inclusive). bool IsWithinBounds(int64_t value, int64_t bound_one, int64_t bound_two); @@ -338,32 +336,32 @@ class LoopDependenceAnalysis { // Finds the bounds of |loop| as upper_bound - lower_bound and returns the // resulting SENode. // If the operations can not be completed a nullptr is returned. - SENode* GetTripCount(const opt::Loop* loop); + SENode* GetTripCount(const Loop* loop); // Returns the SENode* produced by building an SENode from the result of // calling GetInductionInitValue on |loop|. // If the operation can not be completed a nullptr is returned. - SENode* GetFirstTripInductionNode(const opt::Loop* loop); + SENode* GetFirstTripInductionNode(const Loop* loop); // Returns the SENode* produced by building an SENode from the result of // GetFirstTripInductionNode + (GetTripCount - 1) * induction_coefficient. // If the operation can not be completed a nullptr is returned. - SENode* GetFinalTripInductionNode(const opt::Loop* loop, + SENode* GetFinalTripInductionNode(const Loop* loop, SENode* induction_coefficient); // Returns all the distinct loops that appear in |nodes|. - std::set<const opt::Loop*> CollectLoops( + std::set<const Loop*> CollectLoops( const std::vector<SERecurrentNode*>& nodes); // Returns all the distinct loops that appear in |source| and |destination|. - std::set<const opt::Loop*> CollectLoops(SENode* source, SENode* destination); + std::set<const Loop*> CollectLoops(SENode* source, SENode* destination); // Returns true if |distance| is provably outside the loop bounds. // |coefficient| must be an SENode representing the coefficient of the // induction variable of |loop|. // This method is able to handle some symbolic cases which IsWithinBounds // can't handle. - bool IsProvablyOutsideOfLoopBounds(const opt::Loop* loop, SENode* distance, + bool IsProvablyOutsideOfLoopBounds(const Loop* loop, SENode* distance, SENode* coefficient); // Sets the ostream for debug information for the analysis. @@ -393,14 +391,14 @@ class LoopDependenceAnalysis { // Returns the partitioning of subscript pairs. Sets of size 1 indicates an // independent subscript-pair and others indicate coupled sets. using PartitionedSubscripts = - std::vector<std::set<std::pair<opt::Instruction*, opt::Instruction*>>>; + std::vector<std::set<std::pair<Instruction*, Instruction*>>>; PartitionedSubscripts PartitionSubscripts( - const std::vector<opt::Instruction*>& source_subscripts, - const std::vector<opt::Instruction*>& destination_subscripts); + const std::vector<Instruction*>& source_subscripts, + const std::vector<Instruction*>& destination_subscripts); - // Returns the opt::Loop* matching the loop for |subscript_pair|. + // Returns the Loop* matching the loop for |subscript_pair|. // |subscript_pair| must be an SIV pair. - const opt::Loop* GetLoopForSubscriptPair( + const Loop* GetLoopForSubscriptPair( const std::pair<SENode*, SENode*>& subscript_pair); // Returns the DistanceEntry matching the loop for |subscript_pair|. @@ -410,13 +408,12 @@ class LoopDependenceAnalysis { DistanceVector* distance_vector); // Returns the DistanceEntry matching |loop|. - DistanceEntry* GetDistanceEntryForLoop(const opt::Loop* loop, + DistanceEntry* GetDistanceEntryForLoop(const Loop* loop, DistanceVector* distance_vector); // Returns a vector of Instruction* which form the subscripts of the array // access defined by the access chain |instruction|. - std::vector<opt::Instruction*> GetSubscripts( - const opt::Instruction* instruction); + std::vector<Instruction*> GetSubscripts(const Instruction* instruction); // Delta test as described in Figure 3 of 'Practical Dependence // Testing' by Gina Goff, Ken Kennedy, and Chau-Wen Tseng from PLDI '91. @@ -441,18 +438,18 @@ class LoopDependenceAnalysis { // analysis. // A loop is supported if it has a single induction variable and that // induction variable has a step of +1 or -1 per loop iteration. - bool CheckSupportedLoops(std::vector<const opt::Loop*> loops); + bool CheckSupportedLoops(std::vector<const Loop*> loops); // Returns true if |loop| is in a form supported by this analysis. // A loop is supported if it has a single induction variable and that // induction variable has a step of +1 or -1 per loop iteration. - bool IsSupportedLoop(const opt::Loop* loop); + bool IsSupportedLoop(const Loop* loop); private: - opt::IRContext* context_; + IRContext* context_; // The loop nest we are analysing the dependence of. - std::vector<const opt::Loop*> loops_; + std::vector<const Loop*> loops_; // The ScalarEvolutionAnalysis used by this analysis to store and perform much // of its logic. @@ -514,8 +511,7 @@ class LoopDependenceAnalysis { // Uses the def_use_mgr to get the instruction referenced by // SingleWordInOperand(|id|) when called on |instruction|. - opt::Instruction* GetOperandDefinition(const opt::Instruction* instruction, - int id); + Instruction* GetOperandDefinition(const Instruction* instruction, int id); // Perform the GCD test if both, the source and the destination nodes, are in // the form a0*i0 + a1*i1 + ... an*in + c. @@ -533,14 +529,14 @@ class LoopDependenceAnalysis { // Takes the offset from the induction variable and subtracts the lower bound // from it to get the constant term added to the induction. // Returns the resuting constant term, or nullptr if it could not be produced. - SENode* GetConstantTerm(const opt::Loop* loop, SERecurrentNode* induction); + SENode* GetConstantTerm(const Loop* loop, SERecurrentNode* induction); // Marks all the distance entries in |distance_vector| that were relate to // loops in |loops_| but were not used in any subscripts as irrelevant to the // to the dependence test. - void MarkUnsusedDistanceEntriesAsIrrelevant( - const opt::Instruction* source, const opt::Instruction* destination, - DistanceVector* distance_vector); + void MarkUnsusedDistanceEntriesAsIrrelevant(const Instruction* source, + const Instruction* destination, + DistanceVector* distance_vector); // Converts |value| to a std::string and returns the result. // This is required because Android does not compile std::to_string. diff --git a/source/opt/loop_dependence_helpers.cpp b/source/opt/loop_dependence_helpers.cpp index 3d001363..979d03a8 100644 --- a/source/opt/loop_dependence_helpers.cpp +++ b/source/opt/loop_dependence_helpers.cpp @@ -47,12 +47,12 @@ bool LoopDependenceAnalysis::IsMIV( 1; } -SENode* LoopDependenceAnalysis::GetLowerBound(const opt::Loop* loop) { - opt::Instruction* cond_inst = loop->GetConditionInst(); +SENode* LoopDependenceAnalysis::GetLowerBound(const Loop* loop) { + Instruction* cond_inst = loop->GetConditionInst(); if (!cond_inst) { return nullptr; } - opt::Instruction* lower_inst = GetOperandDefinition(cond_inst, 0); + Instruction* lower_inst = GetOperandDefinition(cond_inst, 0); switch (cond_inst->opcode()) { case SpvOpULessThan: case SpvOpSLessThan: @@ -79,12 +79,12 @@ SENode* LoopDependenceAnalysis::GetLowerBound(const opt::Loop* loop) { } } -SENode* LoopDependenceAnalysis::GetUpperBound(const opt::Loop* loop) { - opt::Instruction* cond_inst = loop->GetConditionInst(); +SENode* LoopDependenceAnalysis::GetUpperBound(const Loop* loop) { + Instruction* cond_inst = loop->GetConditionInst(); if (!cond_inst) { return nullptr; } - opt::Instruction* upper_inst = GetOperandDefinition(cond_inst, 1); + Instruction* upper_inst = GetOperandDefinition(cond_inst, 1); switch (cond_inst->opcode()) { case SpvOpULessThan: case SpvOpSLessThan: { @@ -135,7 +135,7 @@ bool LoopDependenceAnalysis::IsWithinBounds(int64_t value, int64_t bound_one, } bool LoopDependenceAnalysis::IsProvablyOutsideOfLoopBounds( - const opt::Loop* loop, SENode* distance, SENode* coefficient) { + const Loop* loop, SENode* distance, SENode* coefficient) { // We test to see if we can reduce the coefficient to an integral constant. SEConstantNode* coefficient_constant = coefficient->AsSEConstantNode(); if (!coefficient_constant) { @@ -196,7 +196,7 @@ bool LoopDependenceAnalysis::IsProvablyOutsideOfLoopBounds( return false; } -const opt::Loop* LoopDependenceAnalysis::GetLoopForSubscriptPair( +const Loop* LoopDependenceAnalysis::GetLoopForSubscriptPair( const std::pair<SENode*, SENode*>& subscript_pair) { // Collect all the SERecurrentNodes. std::vector<SERecurrentNode*> source_nodes = @@ -205,7 +205,7 @@ const opt::Loop* LoopDependenceAnalysis::GetLoopForSubscriptPair( std::get<1>(subscript_pair)->CollectRecurrentNodes(); // Collect all the loops stored by the SERecurrentNodes. - std::unordered_set<const opt::Loop*> loops{}; + std::unordered_set<const Loop*> loops{}; for (auto source_nodes_it = source_nodes.begin(); source_nodes_it != source_nodes.end(); ++source_nodes_it) { loops.insert((*source_nodes_it)->GetLoop()); @@ -226,7 +226,7 @@ const opt::Loop* LoopDependenceAnalysis::GetLoopForSubscriptPair( } DistanceEntry* LoopDependenceAnalysis::GetDistanceEntryForLoop( - const opt::Loop* loop, DistanceVector* distance_vector) { + const Loop* loop, DistanceVector* distance_vector) { if (!loop) { return nullptr; } @@ -245,22 +245,21 @@ DistanceEntry* LoopDependenceAnalysis::GetDistanceEntryForLoop( DistanceEntry* LoopDependenceAnalysis::GetDistanceEntryForSubscriptPair( const std::pair<SENode*, SENode*>& subscript_pair, DistanceVector* distance_vector) { - const opt::Loop* loop = GetLoopForSubscriptPair(subscript_pair); + const Loop* loop = GetLoopForSubscriptPair(subscript_pair); return GetDistanceEntryForLoop(loop, distance_vector); } -SENode* LoopDependenceAnalysis::GetTripCount(const opt::Loop* loop) { - opt::BasicBlock* condition_block = loop->FindConditionBlock(); +SENode* LoopDependenceAnalysis::GetTripCount(const Loop* loop) { + BasicBlock* condition_block = loop->FindConditionBlock(); if (!condition_block) { return nullptr; } - opt::Instruction* induction_instr = - loop->FindConditionVariable(condition_block); + Instruction* induction_instr = loop->FindConditionVariable(condition_block); if (!induction_instr) { return nullptr; } - opt::Instruction* cond_instr = loop->GetConditionInst(); + Instruction* cond_instr = loop->GetConditionInst(); if (!cond_instr) { return nullptr; } @@ -280,14 +279,12 @@ SENode* LoopDependenceAnalysis::GetTripCount(const opt::Loop* loop) { return nullptr; } -SENode* LoopDependenceAnalysis::GetFirstTripInductionNode( - const opt::Loop* loop) { - opt::BasicBlock* condition_block = loop->FindConditionBlock(); +SENode* LoopDependenceAnalysis::GetFirstTripInductionNode(const Loop* loop) { + BasicBlock* condition_block = loop->FindConditionBlock(); if (!condition_block) { return nullptr; } - opt::Instruction* induction_instr = - loop->FindConditionVariable(condition_block); + Instruction* induction_instr = loop->FindConditionVariable(condition_block); if (!induction_instr) { return nullptr; } @@ -302,7 +299,7 @@ SENode* LoopDependenceAnalysis::GetFirstTripInductionNode( } SENode* LoopDependenceAnalysis::GetFinalTripInductionNode( - const opt::Loop* loop, SENode* induction_coefficient) { + const Loop* loop, SENode* induction_coefficient) { SENode* first_trip_induction_node = GetFirstTripInductionNode(loop); if (!first_trip_induction_node) { return nullptr; @@ -319,12 +316,12 @@ SENode* LoopDependenceAnalysis::GetFinalTripInductionNode( scalar_evolution_.CreateMultiplyNode(trip_count, induction_coefficient))); } -std::set<const opt::Loop*> LoopDependenceAnalysis::CollectLoops( +std::set<const Loop*> LoopDependenceAnalysis::CollectLoops( const std::vector<SERecurrentNode*>& recurrent_nodes) { // We don't handle loops with more than one induction variable. Therefore we // can identify the number of induction variables by collecting all of the // loops the collected recurrent nodes belong to. - std::set<const opt::Loop*> loops{}; + std::set<const Loop*> loops{}; for (auto recurrent_nodes_it = recurrent_nodes.begin(); recurrent_nodes_it != recurrent_nodes.end(); ++recurrent_nodes_it) { loops.insert((*recurrent_nodes_it)->GetLoop()); @@ -343,24 +340,23 @@ int64_t LoopDependenceAnalysis::CountInductionVariables(SENode* node) { // We don't handle loops with more than one induction variable. Therefore we // can identify the number of induction variables by collecting all of the // loops the collected recurrent nodes belong to. - std::set<const opt::Loop*> loops = CollectLoops(recurrent_nodes); + std::set<const Loop*> loops = CollectLoops(recurrent_nodes); return static_cast<int64_t>(loops.size()); } -std::set<const opt::Loop*> LoopDependenceAnalysis::CollectLoops( +std::set<const Loop*> LoopDependenceAnalysis::CollectLoops( SENode* source, SENode* destination) { if (!source || !destination) { - return std::set<const opt::Loop*>{}; + return std::set<const Loop*>{}; } std::vector<SERecurrentNode*> source_nodes = source->CollectRecurrentNodes(); std::vector<SERecurrentNode*> destination_nodes = destination->CollectRecurrentNodes(); - std::set<const opt::Loop*> loops = CollectLoops(source_nodes); - std::set<const opt::Loop*> destination_loops = - CollectLoops(destination_nodes); + std::set<const Loop*> loops = CollectLoops(source_nodes); + std::set<const Loop*> destination_loops = CollectLoops(destination_nodes); loops.insert(std::begin(destination_loops), std::end(destination_loops)); @@ -373,22 +369,22 @@ int64_t LoopDependenceAnalysis::CountInductionVariables(SENode* source, return -1; } - std::set<const opt::Loop*> loops = CollectLoops(source, destination); + std::set<const Loop*> loops = CollectLoops(source, destination); return static_cast<int64_t>(loops.size()); } -opt::Instruction* LoopDependenceAnalysis::GetOperandDefinition( - const opt::Instruction* instruction, int id) { +Instruction* LoopDependenceAnalysis::GetOperandDefinition( + const Instruction* instruction, int id) { return context_->get_def_use_mgr()->GetDef( instruction->GetSingleWordInOperand(id)); } -std::vector<opt::Instruction*> LoopDependenceAnalysis::GetSubscripts( - const opt::Instruction* instruction) { - opt::Instruction* access_chain = GetOperandDefinition(instruction, 0); +std::vector<Instruction*> LoopDependenceAnalysis::GetSubscripts( + const Instruction* instruction) { + Instruction* access_chain = GetOperandDefinition(instruction, 0); - std::vector<opt::Instruction*> subscripts; + std::vector<Instruction*> subscripts; for (auto i = 1u; i < access_chain->NumInOperandWords(); ++i) { subscripts.push_back(GetOperandDefinition(access_chain, i)); @@ -397,7 +393,7 @@ std::vector<opt::Instruction*> LoopDependenceAnalysis::GetSubscripts( return subscripts; } -SENode* LoopDependenceAnalysis::GetConstantTerm(const opt::Loop* loop, +SENode* LoopDependenceAnalysis::GetConstantTerm(const Loop* loop, SERecurrentNode* induction) { SENode* offset = induction->GetOffset(); SENode* lower_bound = GetLowerBound(loop); @@ -410,7 +406,7 @@ SENode* LoopDependenceAnalysis::GetConstantTerm(const opt::Loop* loop, } bool LoopDependenceAnalysis::CheckSupportedLoops( - std::vector<const opt::Loop*> loops) { + std::vector<const Loop*> loops) { for (auto loop : loops) { if (!IsSupportedLoop(loop)) { return false; @@ -420,15 +416,14 @@ bool LoopDependenceAnalysis::CheckSupportedLoops( } void LoopDependenceAnalysis::MarkUnsusedDistanceEntriesAsIrrelevant( - const opt::Instruction* source, const opt::Instruction* destination, + const Instruction* source, const Instruction* destination, DistanceVector* distance_vector) { - std::vector<opt::Instruction*> source_subscripts = GetSubscripts(source); - std::vector<opt::Instruction*> destination_subscripts = - GetSubscripts(destination); + std::vector<Instruction*> source_subscripts = GetSubscripts(source); + std::vector<Instruction*> destination_subscripts = GetSubscripts(destination); - std::set<const opt::Loop*> used_loops{}; + std::set<const Loop*> used_loops{}; - for (opt::Instruction* source_inst : source_subscripts) { + for (Instruction* source_inst : source_subscripts) { SENode* source_node = scalar_evolution_.SimplifyExpression( scalar_evolution_.AnalyzeInstruction(source_inst)); std::vector<SERecurrentNode*> recurrent_nodes = @@ -438,7 +433,7 @@ void LoopDependenceAnalysis::MarkUnsusedDistanceEntriesAsIrrelevant( } } - for (opt::Instruction* destination_inst : destination_subscripts) { + for (Instruction* destination_inst : destination_subscripts) { SENode* destination_node = scalar_evolution_.SimplifyExpression( scalar_evolution_.AnalyzeInstruction(destination_inst)); std::vector<SERecurrentNode*> recurrent_nodes = @@ -456,13 +451,13 @@ void LoopDependenceAnalysis::MarkUnsusedDistanceEntriesAsIrrelevant( } } -bool LoopDependenceAnalysis::IsSupportedLoop(const opt::Loop* loop) { - std::vector<opt::Instruction*> inductions{}; +bool LoopDependenceAnalysis::IsSupportedLoop(const Loop* loop) { + std::vector<Instruction*> inductions{}; loop->GetInductionVariables(inductions); if (inductions.size() != 1) { return false; } - opt::Instruction* induction = inductions[0]; + Instruction* induction = inductions[0]; SENode* induction_node = scalar_evolution_.SimplifyExpression( scalar_evolution_.AnalyzeInstruction(induction)); if (!induction_node->AsSERecurrentNode()) { diff --git a/source/opt/loop_descriptor.cpp b/source/opt/loop_descriptor.cpp index dce7015f..ec05ba6b 100644 --- a/source/opt/loop_descriptor.cpp +++ b/source/opt/loop_descriptor.cpp @@ -33,20 +33,20 @@ namespace opt { // Takes in a phi instruction |induction| and the loop |header| and returns the // step operation of the loop. -opt::Instruction* Loop::GetInductionStepOperation( - const opt::Instruction* induction) const { +Instruction* Loop::GetInductionStepOperation( + const Instruction* induction) const { // Induction must be a phi instruction. assert(induction->opcode() == SpvOpPhi); - opt::Instruction* step = nullptr; + Instruction* step = nullptr; - opt::analysis::DefUseManager* def_use_manager = context_->get_def_use_mgr(); + analysis::DefUseManager* def_use_manager = context_->get_def_use_mgr(); // Traverse the incoming operands of the phi instruction. for (uint32_t operand_id = 1; operand_id < induction->NumInOperands(); operand_id += 2) { // Incoming edge. - opt::BasicBlock* incoming_block = + BasicBlock* incoming_block = context_->cfg()->block(induction->GetSingleWordInOperand(operand_id)); // Check if the block is dominated by header, and thus coming from within @@ -142,17 +142,17 @@ int64_t Loop::GetResidualConditionValue(SpvOp condition, int64_t initial_value, return remainder; } -opt::Instruction* Loop::GetConditionInst() const { - opt::BasicBlock* condition_block = FindConditionBlock(); +Instruction* Loop::GetConditionInst() const { + BasicBlock* condition_block = FindConditionBlock(); if (!condition_block) { return nullptr; } - opt::Instruction* branch_conditional = &*condition_block->tail(); + Instruction* branch_conditional = &*condition_block->tail(); if (!branch_conditional || branch_conditional->opcode() != SpvOpBranchConditional) { return nullptr; } - opt::Instruction* condition_inst = context_->get_def_use_mgr()->GetDef( + Instruction* condition_inst = context_->get_def_use_mgr()->GetDef( branch_conditional->GetSingleWordInOperand(0)); if (IsSupportedCondition(condition_inst->opcode())) { return condition_inst; @@ -164,14 +164,14 @@ opt::Instruction* Loop::GetConditionInst() const { // Extract the initial value from the |induction| OpPhi instruction and store it // in |value|. If the function couldn't find the initial value of |induction| // return false. -bool Loop::GetInductionInitValue(const opt::Instruction* induction, +bool Loop::GetInductionInitValue(const Instruction* induction, int64_t* value) const { - opt::Instruction* constant_instruction = nullptr; - opt::analysis::DefUseManager* def_use_manager = context_->get_def_use_mgr(); + Instruction* constant_instruction = nullptr; + analysis::DefUseManager* def_use_manager = context_->get_def_use_mgr(); for (uint32_t operand_id = 0; operand_id < induction->NumInOperands(); operand_id += 2) { - opt::BasicBlock* bb = context_->cfg()->block( + BasicBlock* bb = context_->cfg()->block( induction->GetSingleWordInOperand(operand_id + 1)); if (!IsInsideLoop(bb)) { @@ -182,13 +182,13 @@ bool Loop::GetInductionInitValue(const opt::Instruction* induction, if (!constant_instruction) return false; - const opt::analysis::Constant* constant = + const analysis::Constant* constant = context_->get_constant_mgr()->FindDeclaredConstant( constant_instruction->result_id()); if (!constant) return false; if (value) { - const opt::analysis::Integer* type = + const analysis::Integer* type = constant->AsIntConstant()->type()->AsInteger(); if (type->IsSigned()) { @@ -201,7 +201,7 @@ bool Loop::GetInductionInitValue(const opt::Instruction* induction, return true; } -Loop::Loop(IRContext* context, opt::DominatorAnalysis* dom_analysis, +Loop::Loop(IRContext* context, DominatorAnalysis* dom_analysis, BasicBlock* header, BasicBlock* continue_target, BasicBlock* merge_target) : context_(context), @@ -217,17 +217,17 @@ Loop::Loop(IRContext* context, opt::DominatorAnalysis* dom_analysis, loop_latch_ = FindLatchBlock(); } -BasicBlock* Loop::FindLoopPreheader(opt::DominatorAnalysis* dom_analysis) { +BasicBlock* Loop::FindLoopPreheader(DominatorAnalysis* dom_analysis) { CFG* cfg = context_->cfg(); - opt::DominatorTree& dom_tree = dom_analysis->GetDomTree(); - opt::DominatorTreeNode* header_node = dom_tree.GetTreeNode(loop_header_); + DominatorTree& dom_tree = dom_analysis->GetDomTree(); + DominatorTreeNode* header_node = dom_tree.GetTreeNode(loop_header_); // The loop predecessor. BasicBlock* loop_pred = nullptr; auto header_pred = cfg->preds(loop_header_->id()); for (uint32_t p_id : header_pred) { - opt::DominatorTreeNode* node = dom_tree.GetTreeNode(p_id); + DominatorTreeNode* node = dom_tree.GetTreeNode(p_id); if (node && !dom_tree.Dominates(header_node, node)) { // The predecessor is not part of the loop, so potential loop preheader. if (loop_pred && node->bb_ != loop_pred) { @@ -264,7 +264,7 @@ bool Loop::IsInsideLoop(Instruction* inst) const { bool Loop::IsBasicBlockInLoopSlow(const BasicBlock* bb) { assert(bb->GetParent() && "The basic block does not belong to a function"); - opt::DominatorAnalysis* dom_analysis = + DominatorAnalysis* dom_analysis = context_->GetDominatorAnalysis(bb->GetParent()); if (dom_analysis->IsReachable(bb) && !dom_analysis->Dominates(GetHeaderBlock(), bb)) @@ -327,10 +327,10 @@ void Loop::SetPreHeaderBlock(BasicBlock* preheader) { loop_preheader_ = preheader; } -opt::BasicBlock* Loop::FindLatchBlock() { - opt::CFG* cfg = context_->cfg(); +BasicBlock* Loop::FindLatchBlock() { + CFG* cfg = context_->cfg(); - opt::DominatorAnalysis* dominator_analysis = + DominatorAnalysis* dominator_analysis = context_->GetDominatorAnalysis(loop_header_->GetParent()); // Look at the predecessors of the loop header to find a predecessor block @@ -350,7 +350,7 @@ opt::BasicBlock* Loop::FindLatchBlock() { } void Loop::GetExitBlocks(std::unordered_set<uint32_t>* exit_blocks) const { - opt::CFG* cfg = context_->cfg(); + CFG* cfg = context_->cfg(); exit_blocks->clear(); for (uint32_t bb_id : GetBlocks()) { @@ -366,13 +366,13 @@ void Loop::GetExitBlocks(std::unordered_set<uint32_t>* exit_blocks) const { void Loop::GetMergingBlocks( std::unordered_set<uint32_t>* merging_blocks) const { assert(GetMergeBlock() && "This loop is not structured"); - opt::CFG* cfg = context_->cfg(); + CFG* cfg = context_->cfg(); merging_blocks->clear(); - std::stack<const opt::BasicBlock*> to_visit; + std::stack<const BasicBlock*> to_visit; to_visit.push(GetMergeBlock()); while (!to_visit.empty()) { - const opt::BasicBlock* bb = to_visit.top(); + const BasicBlock* bb = to_visit.top(); to_visit.pop(); merging_blocks->insert(bb->id()); for (uint32_t pred_id : cfg->preds(bb->id())) { @@ -386,7 +386,7 @@ void Loop::GetMergingBlocks( namespace { static inline bool IsBasicBlockSafeToClone(IRContext* context, BasicBlock* bb) { - for (opt::Instruction& inst : *bb) { + for (Instruction& inst : *bb) { if (!inst.IsBranch() && !context->IsCombinatorInstruction(&inst)) return false; } @@ -397,7 +397,7 @@ static inline bool IsBasicBlockSafeToClone(IRContext* context, BasicBlock* bb) { } // namespace bool Loop::IsSafeToClone() const { - opt::CFG& cfg = *context_->cfg(); + CFG& cfg = *context_->cfg(); for (uint32_t bb_id : GetBlocks()) { BasicBlock* bb = cfg.block(bb_id); @@ -421,14 +421,14 @@ bool Loop::IsSafeToClone() const { } bool Loop::IsLCSSA() const { - opt::CFG* cfg = context_->cfg(); - opt::analysis::DefUseManager* def_use_mgr = context_->get_def_use_mgr(); + CFG* cfg = context_->cfg(); + analysis::DefUseManager* def_use_mgr = context_->get_def_use_mgr(); std::unordered_set<uint32_t> exit_blocks; GetExitBlocks(&exit_blocks); // Declare ir_context so we can capture context_ in the below lambda - opt::IRContext* ir_context = context_; + IRContext* ir_context = context_; for (uint32_t bb_id : GetBlocks()) { for (Instruction& insn : *cfg->block(bb_id)) { @@ -437,7 +437,7 @@ bool Loop::IsLCSSA() const { // - In an exit block and in a phi instruction. if (!def_use_mgr->WhileEachUser( &insn, - [&exit_blocks, ir_context, this](opt::Instruction* use) -> bool { + [&exit_blocks, ir_context, this](Instruction* use) -> bool { BasicBlock* parent = ir_context->get_instr_block(use); assert(parent && "Invalid analysis"); if (IsInsideLoop(parent)) return true; @@ -456,7 +456,7 @@ bool Loop::ShouldHoistInstruction(IRContext* context, Instruction* inst) { } bool Loop::AreAllOperandsOutsideLoop(IRContext* context, Instruction* inst) { - opt::analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr(); + analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr(); bool all_outside_loop = true; const std::function<void(uint32_t*)> operand_outside_loop = @@ -472,9 +472,9 @@ bool Loop::AreAllOperandsOutsideLoop(IRContext* context, Instruction* inst) { } void Loop::ComputeLoopStructuredOrder( - std::vector<opt::BasicBlock*>* ordered_loop_blocks, bool include_pre_header, + std::vector<BasicBlock*>* ordered_loop_blocks, bool include_pre_header, bool include_merge) const { - opt::CFG& cfg = *context_->cfg(); + CFG& cfg = *context_->cfg(); // Reserve the memory: all blocks in the loop + extra if needed. ordered_loop_blocks->reserve(GetBlocks().size() + include_pre_header + @@ -498,15 +498,15 @@ LoopDescriptor::LoopDescriptor(IRContext* context, const Function* f) LoopDescriptor::~LoopDescriptor() { ClearLoops(); } void LoopDescriptor::PopulateList(IRContext* context, const Function* f) { - opt::DominatorAnalysis* dom_analysis = context->GetDominatorAnalysis(f); + DominatorAnalysis* dom_analysis = context->GetDominatorAnalysis(f); ClearLoops(); // Post-order traversal of the dominator tree to find all the OpLoopMerge // instructions. - opt::DominatorTree& dom_tree = dom_analysis->GetDomTree(); - for (opt::DominatorTreeNode& node : - opt::make_range(dom_tree.post_begin(), dom_tree.post_end())) { + DominatorTree& dom_tree = dom_analysis->GetDomTree(); + for (DominatorTreeNode& node : + make_range(dom_tree.post_begin(), dom_tree.post_end())) { Instruction* merge_inst = node.bb_->GetLoopMergeInst(); if (merge_inst) { bool all_backedge_unreachable = true; @@ -560,8 +560,8 @@ void LoopDescriptor::PopulateList(IRContext* context, const Function* f) { current_loop->AddNestedLoop(previous_loop); } - opt::DominatorTreeNode* dom_merge_node = dom_tree.GetTreeNode(merge_bb); - for (opt::DominatorTreeNode& loop_node : + DominatorTreeNode* dom_merge_node = dom_tree.GetTreeNode(merge_bb); + for (DominatorTreeNode& loop_node : make_range(node.df_begin(), node.df_end())) { // Check if we are in the loop. if (dom_tree.Dominates(dom_merge_node, &loop_node)) continue; @@ -576,14 +576,14 @@ void LoopDescriptor::PopulateList(IRContext* context, const Function* f) { } } -std::vector<opt::Loop*> LoopDescriptor::GetLoopsInBinaryLayoutOrder() { +std::vector<Loop*> LoopDescriptor::GetLoopsInBinaryLayoutOrder() { std::vector<uint32_t> ids{}; for (size_t i = 0; i < NumLoops(); ++i) { ids.push_back(GetLoopByIndex(i).GetHeaderBlock()->id()); } - std::vector<opt::Loop*> loops{}; + std::vector<Loop*> loops{}; if (!ids.empty()) { auto function = GetLoopByIndex(0).GetHeaderBlock()->GetParent(); for (const auto& block : *function) { @@ -599,11 +599,11 @@ std::vector<opt::Loop*> LoopDescriptor::GetLoopsInBinaryLayoutOrder() { return loops; } -opt::BasicBlock* Loop::FindConditionBlock() const { +BasicBlock* Loop::FindConditionBlock() const { if (!loop_merge_) { return nullptr; } - opt::BasicBlock* condition_block = nullptr; + BasicBlock* condition_block = nullptr; uint32_t in_loop_pred = 0; for (uint32_t p : context_->cfg()->preds(loop_merge_->id())) { @@ -620,11 +620,11 @@ opt::BasicBlock* Loop::FindConditionBlock() const { return nullptr; } - opt::BasicBlock* bb = context_->cfg()->block(in_loop_pred); + BasicBlock* bb = context_->cfg()->block(in_loop_pred); if (!bb) return nullptr; - const opt::Instruction& branch = *bb->ctail(); + const Instruction& branch = *bb->ctail(); // Make sure the branch is a conditional branch. if (branch.opcode() != SpvOpBranchConditional) return nullptr; @@ -638,33 +638,33 @@ opt::BasicBlock* Loop::FindConditionBlock() const { return condition_block; } -bool Loop::FindNumberOfIterations(const opt::Instruction* induction, - const opt::Instruction* branch_inst, +bool Loop::FindNumberOfIterations(const Instruction* induction, + const Instruction* branch_inst, size_t* iterations_out, int64_t* step_value_out, int64_t* init_value_out) const { // From the branch instruction find the branch condition. - opt::analysis::DefUseManager* def_use_manager = context_->get_def_use_mgr(); + analysis::DefUseManager* def_use_manager = context_->get_def_use_mgr(); // Condition instruction from the OpConditionalBranch. - opt::Instruction* condition = + Instruction* condition = def_use_manager->GetDef(branch_inst->GetSingleWordOperand(0)); assert(IsSupportedCondition(condition->opcode())); // Get the constant manager from the ir context. - opt::analysis::ConstantManager* const_manager = context_->get_constant_mgr(); + analysis::ConstantManager* const_manager = context_->get_constant_mgr(); // Find the constant value used by the condition variable. Exit out if it // isn't a constant int. - const opt::analysis::Constant* upper_bound = + const analysis::Constant* upper_bound = const_manager->FindDeclaredConstant(condition->GetSingleWordOperand(3)); if (!upper_bound) return false; // Must be integer because of the opcode on the condition. int64_t condition_value = 0; - const opt::analysis::Integer* type = + const analysis::Integer* type = upper_bound->AsIntConstant()->type()->AsInteger(); if (type->width() > 32) { @@ -678,18 +678,18 @@ bool Loop::FindNumberOfIterations(const opt::Instruction* induction, } // Find the instruction which is stepping through the loop. - opt::Instruction* step_inst = GetInductionStepOperation(induction); + Instruction* step_inst = GetInductionStepOperation(induction); if (!step_inst) return false; // Find the constant value used by the condition variable. - const opt::analysis::Constant* step_constant = + const analysis::Constant* step_constant = const_manager->FindDeclaredConstant(step_inst->GetSingleWordOperand(3)); if (!step_constant) return false; // Must be integer because of the opcode on the condition. int64_t step_value = 0; - const opt::analysis::Integer* step_type = + const analysis::Integer* step_type = step_constant->AsIntConstant()->type()->AsInteger(); if (step_type->IsSigned()) { @@ -831,34 +831,34 @@ int64_t Loop::GetIterations(SpvOp condition, int64_t condition_value, // Returns the list of induction variables within the loop. void Loop::GetInductionVariables( - std::vector<opt::Instruction*>& induction_variables) const { - for (opt::Instruction& inst : *loop_header_) { + std::vector<Instruction*>& induction_variables) const { + for (Instruction& inst : *loop_header_) { if (inst.opcode() == SpvOp::SpvOpPhi) { induction_variables.push_back(&inst); } } } -opt::Instruction* Loop::FindConditionVariable( - const opt::BasicBlock* condition_block) const { +Instruction* Loop::FindConditionVariable( + const BasicBlock* condition_block) const { // Find the branch instruction. - const opt::Instruction& branch_inst = *condition_block->ctail(); + const Instruction& branch_inst = *condition_block->ctail(); - opt::Instruction* induction = nullptr; + Instruction* induction = nullptr; // Verify that the branch instruction is a conditional branch. if (branch_inst.opcode() == SpvOp::SpvOpBranchConditional) { // From the branch instruction find the branch condition. - opt::analysis::DefUseManager* def_use_manager = context_->get_def_use_mgr(); + analysis::DefUseManager* def_use_manager = context_->get_def_use_mgr(); // Find the instruction representing the condition used in the conditional // branch. - opt::Instruction* condition = + Instruction* condition = def_use_manager->GetDef(branch_inst.GetSingleWordOperand(0)); // Ensure that the condition is a less than operation. if (condition && IsSupportedCondition(condition->opcode())) { // The left hand side operand of the operation. - opt::Instruction* variable_inst = + Instruction* variable_inst = def_use_manager->GetDef(condition->GetSingleWordOperand(2)); // Make sure the variable instruction used is a phi. @@ -922,7 +922,7 @@ bool LoopDescriptor::CreatePreHeaderBlocksIfMissing() { // maintain the state of the loop descriptor class. void LoopDescriptor::PostModificationCleanup() { LoopContainerType loops_to_remove_; - for (opt::Loop* loop : loops_) { + for (Loop* loop : loops_) { if (loop->IsMarkedForRemoval()) { loops_to_remove_.push_back(loop); if (loop->HasParent()) { @@ -931,13 +931,13 @@ void LoopDescriptor::PostModificationCleanup() { } } - for (opt::Loop* loop : loops_to_remove_) { + for (Loop* loop : loops_to_remove_) { loops_.erase(std::find(loops_.begin(), loops_.end(), loop)); } for (auto& pair : loops_to_add_) { - opt::Loop* parent = pair.first; - opt::Loop* loop = pair.second; + Loop* parent = pair.first; + Loop* loop = pair.second; if (parent) { loop->SetParent(nullptr); @@ -962,12 +962,12 @@ void LoopDescriptor::ClearLoops() { } // Adds a new loop nest to the descriptor set. -opt::Loop* LoopDescriptor::AddLoopNest(std::unique_ptr<opt::Loop> new_loop) { - opt::Loop* loop = new_loop.release(); +Loop* LoopDescriptor::AddLoopNest(std::unique_ptr<Loop> new_loop) { + Loop* loop = new_loop.release(); if (!loop->HasParent()) dummy_top_loop_.nested_loops_.push_back(loop); // Iterate from inner to outer most loop, adding basic block to loop mapping // as we go. - for (opt::Loop& current_loop : + for (Loop& current_loop : make_range(iterator::begin(loop), iterator::end(nullptr))) { loops_.push_back(¤t_loop); for (uint32_t bb_id : current_loop.GetBlocks()) @@ -977,18 +977,18 @@ opt::Loop* LoopDescriptor::AddLoopNest(std::unique_ptr<opt::Loop> new_loop) { return loop; } -void LoopDescriptor::RemoveLoop(opt::Loop* loop) { - opt::Loop* parent = loop->GetParent() ? loop->GetParent() : &dummy_top_loop_; +void LoopDescriptor::RemoveLoop(Loop* loop) { + Loop* parent = loop->GetParent() ? loop->GetParent() : &dummy_top_loop_; parent->nested_loops_.erase(std::find(parent->nested_loops_.begin(), parent->nested_loops_.end(), loop)); std::for_each( loop->nested_loops_.begin(), loop->nested_loops_.end(), - [loop](opt::Loop* sub_loop) { sub_loop->SetParent(loop->GetParent()); }); + [loop](Loop* sub_loop) { sub_loop->SetParent(loop->GetParent()); }); parent->nested_loops_.insert(parent->nested_loops_.end(), loop->nested_loops_.begin(), loop->nested_loops_.end()); for (uint32_t bb_id : loop->GetBlocks()) { - opt::Loop* l = FindLoopForBasicBlock(bb_id); + Loop* l = FindLoopForBasicBlock(bb_id); if (l == loop) { SetBasicBlockToLoop(bb_id, l->GetParent()); } else { diff --git a/source/opt/loop_descriptor.h b/source/opt/loop_descriptor.h index e7000333..21e5bf49 100644 --- a/source/opt/loop_descriptor.h +++ b/source/opt/loop_descriptor.h @@ -55,7 +55,7 @@ class Loop { parent_(nullptr), loop_is_marked_for_removal_(false) {} - Loop(IRContext* context, opt::DominatorAnalysis* analysis, BasicBlock* header, + Loop(IRContext* context, DominatorAnalysis* analysis, BasicBlock* header, BasicBlock* continue_target, BasicBlock* merge_target); // Iterators over the immediate sub-loops. @@ -77,7 +77,7 @@ class Loop { inline void UpdateLoopMergeInst() { assert(GetHeaderBlock()->GetLoopMergeInst() && "The loop is not structured"); - opt::Instruction* merge_inst = GetHeaderBlock()->GetLoopMergeInst(); + Instruction* merge_inst = GetHeaderBlock()->GetLoopMergeInst(); merge_inst->SetInOperand(0, {GetMergeBlock()->id()}); } @@ -232,22 +232,20 @@ class Loop { } // Returns the list of induction variables within the loop. - void GetInductionVariables(std::vector<opt::Instruction*>& inductions) const; + void GetInductionVariables(std::vector<Instruction*>& inductions) const; // This function uses the |condition| to find the induction variable which is // used by the loop condition within the loop. This only works if the loop is // bound by a single condition and single induction variable. - opt::Instruction* FindConditionVariable( - const opt::BasicBlock* condition) const; + Instruction* FindConditionVariable(const BasicBlock* condition) const; // Returns the number of iterations within a loop when given the |induction| // variable and the loop |condition| check. It stores the found number of // iterations in the output parameter |iterations| and optionally, the step // value in |step_value| and the initial value of the induction variable in // |init_value|. - bool FindNumberOfIterations(const opt::Instruction* induction, - const opt::Instruction* condition, - size_t* iterations, + bool FindNumberOfIterations(const Instruction* induction, + const Instruction* condition, size_t* iterations, int64_t* step_amount = nullptr, int64_t* init_value = nullptr) const; @@ -263,7 +261,7 @@ class Loop { // Finds the conditional block with a branch to the merge and continue blocks // within the loop body. - opt::BasicBlock* FindConditionBlock() const; + BasicBlock* FindConditionBlock() const; // Remove the child loop form this loop. inline void RemoveChildLoop(Loop* loop) { @@ -307,13 +305,12 @@ class Loop { // Extract the initial value from the |induction| variable and store it in // |value|. If the function couldn't find the initial value of |induction| // return false. - bool GetInductionInitValue(const opt::Instruction* induction, + bool GetInductionInitValue(const Instruction* induction, int64_t* value) const; // Takes in a phi instruction |induction| and the loop |header| and returns // the step operation of the loop. - opt::Instruction* GetInductionStepOperation( - const opt::Instruction* induction) const; + Instruction* GetInductionStepOperation(const Instruction* induction) const; // Returns true if we can deduce the number of loop iterations in the step // operation |step|. IsSupportedCondition must also be true for the condition @@ -330,9 +327,9 @@ class Loop { // pre-header block will also be included at the beginning of the list if it // exist. If |include_merge| is true, the merge block will also be included at // the end of the list if it exist. - void ComputeLoopStructuredOrder( - std::vector<opt::BasicBlock*>* ordered_loop_blocks, - bool include_pre_header = false, bool include_merge = false) const; + void ComputeLoopStructuredOrder(std::vector<BasicBlock*>* ordered_loop_blocks, + bool include_pre_header = false, + bool include_merge = false) const; // Given the loop |condition|, |initial_value|, |step_value|, the trip count // |number_of_iterations|, and the |unroll_factor| requested, get the new @@ -345,7 +342,7 @@ class Loop { // Returns the condition instruction for entry into the loop // Returns nullptr if it can't be found. - opt::Instruction* GetConditionInst() const; + Instruction* GetConditionInst() const; // Returns the context associated this loop. IRContext* GetContext() const { return context_; } @@ -354,7 +351,7 @@ class Loop { // which is also dominated by the loop continue block. This block is the latch // block. The specification mandates that this block should exist, therefore // this function will assert if it is not found. - opt::BasicBlock* FindLatchBlock(); + BasicBlock* FindLatchBlock(); private: IRContext* context_; @@ -389,7 +386,7 @@ class Loop { bool IsBasicBlockInLoopSlow(const BasicBlock* bb); // Returns the loop preheader if it exists, returns nullptr otherwise. - BasicBlock* FindLoopPreheader(opt::DominatorAnalysis* dom_analysis); + BasicBlock* FindLoopPreheader(DominatorAnalysis* dom_analysis); // Sets |latch| as the loop unique latch block. No checks are performed // here. @@ -420,11 +417,11 @@ class Loop { class LoopDescriptor { public: // Iterator interface (depth first postorder traversal). - using iterator = opt::PostOrderTreeDFIterator<Loop>; - using const_iterator = opt::PostOrderTreeDFIterator<const Loop>; + using iterator = PostOrderTreeDFIterator<Loop>; + using const_iterator = PostOrderTreeDFIterator<const Loop>; - using pre_iterator = opt::TreeDFIterator<Loop>; - using const_pre_iterator = opt::TreeDFIterator<const Loop>; + using pre_iterator = TreeDFIterator<Loop>; + using const_pre_iterator = TreeDFIterator<const Loop>; // Creates a loop object for all loops found in |f|. LoopDescriptor(IRContext* context, const Function* f); @@ -458,7 +455,7 @@ class LoopDescriptor { // Returns the loops in |this| in the order their headers appear in the // binary. - std::vector<opt::Loop*> GetLoopsInBinaryLayoutOrder(); + std::vector<Loop*> GetLoopsInBinaryLayoutOrder(); // Returns the inner most loop that contains the basic block id |block_id|. inline Loop* operator[](uint32_t block_id) const { @@ -501,7 +498,7 @@ class LoopDescriptor { // Mark the loop |loop_to_add| as needing to be added when the user calls // PostModificationCleanup. |parent| may be null. - inline void AddLoop(opt::Loop* loop_to_add, opt::Loop* parent) { + inline void AddLoop(Loop* loop_to_add, Loop* parent) { loops_to_add_.emplace_back(std::make_pair(parent, loop_to_add)); } @@ -520,12 +517,12 @@ class LoopDescriptor { // Adds the loop |new_loop| and all its nested loops to the descriptor set. // The object takes ownership of all the loops. - opt::Loop* AddLoopNest(std::unique_ptr<opt::Loop> new_loop); + Loop* AddLoopNest(std::unique_ptr<Loop> new_loop); // Remove the loop |loop|. - void RemoveLoop(opt::Loop* loop); + void RemoveLoop(Loop* loop); - void SetAsTopLoop(opt::Loop* loop) { + void SetAsTopLoop(Loop* loop) { assert(std::find(dummy_top_loop_.begin(), dummy_top_loop_.end(), loop) == dummy_top_loop_.end() && "already registered"); diff --git a/source/opt/loop_fission.cpp b/source/opt/loop_fission.cpp index 7ff6bcef..7657ad6a 100644 --- a/source/opt/loop_fission.cpp +++ b/source/opt/loop_fission.cpp @@ -55,7 +55,7 @@ namespace opt { class LoopFissionImpl { public: - LoopFissionImpl(opt::IRContext* context, opt::Loop* loop) + LoopFissionImpl(IRContext* context, Loop* loop) : context_(context), loop_(loop), load_used_in_condition_(false) {} // Group each instruction in the loop into sets of instructions related by @@ -69,37 +69,36 @@ class LoopFissionImpl { bool CanPerformSplit(); // Split the loop and return a pointer to the new loop. - opt::Loop* SplitLoop(); + Loop* SplitLoop(); // Checks if |inst| is safe to move. We can only move instructions which don't // have any side effects and OpLoads and OpStores. - bool MovableInstruction(const opt::Instruction& inst) const; + bool MovableInstruction(const Instruction& inst) const; private: // Traverse the def use chain of |inst| and add the users and uses of |inst| // which are in the same loop to the |returned_set|. - void TraverseUseDef(opt::Instruction* inst, - std::set<opt::Instruction*>* returned_set, + void TraverseUseDef(Instruction* inst, std::set<Instruction*>* returned_set, bool ignore_phi_users = false, bool report_loads = false); // We group the instructions in the block into two different groups, the // instructions to be kept in the original loop and the ones to be cloned into // the new loop. As the cloned loop is attached to the preheader it will be // the first loop and the second loop will be the original. - std::set<opt::Instruction*> cloned_loop_instructions_; - std::set<opt::Instruction*> original_loop_instructions_; + std::set<Instruction*> cloned_loop_instructions_; + std::set<Instruction*> original_loop_instructions_; // We need a set of all the instructions to be seen so we can break any // recursion and also so we can ignore certain instructions by preemptively // adding them to this set. - std::set<opt::Instruction*> seen_instructions_; + std::set<Instruction*> seen_instructions_; // A map of instructions to their relative position in the function. - std::map<opt::Instruction*, size_t> instruction_order_; + std::map<Instruction*, size_t> instruction_order_; - opt::IRContext* context_; + IRContext* context_; - opt::Loop* loop_; + Loop* loop_; // This is set to true by TraverseUseDef when traversing the instructions // related to the loop condition and any if conditions should any of those @@ -107,27 +106,27 @@ class LoopFissionImpl { bool load_used_in_condition_; }; -bool LoopFissionImpl::MovableInstruction(const opt::Instruction& inst) const { +bool LoopFissionImpl::MovableInstruction(const Instruction& inst) const { return inst.opcode() == SpvOp::SpvOpLoad || inst.opcode() == SpvOp::SpvOpStore || inst.opcode() == SpvOp::SpvOpSelectionMerge || inst.opcode() == SpvOp::SpvOpPhi || inst.IsOpcodeCodeMotionSafe(); } -void LoopFissionImpl::TraverseUseDef(opt::Instruction* inst, - std::set<opt::Instruction*>* returned_set, +void LoopFissionImpl::TraverseUseDef(Instruction* inst, + std::set<Instruction*>* returned_set, bool ignore_phi_users, bool report_loads) { assert(returned_set && "Set to be returned cannot be null."); - opt::analysis::DefUseManager* def_use = context_->get_def_use_mgr(); - std::set<opt::Instruction*>& inst_set = *returned_set; + analysis::DefUseManager* def_use = context_->get_def_use_mgr(); + std::set<Instruction*>& inst_set = *returned_set; // We create this functor to traverse the use def chain to build the // grouping of related instructions. The lambda captures the std::function // to allow it to recurse. - std::function<void(opt::Instruction*)> traverser_functor; + std::function<void(Instruction*)> traverser_functor; traverser_functor = [this, def_use, &inst_set, &traverser_functor, - ignore_phi_users, report_loads](opt::Instruction* user) { + ignore_phi_users, report_loads](Instruction* user) { // If we've seen the instruction before or it is not inside the loop end the // traversal. if (!user || seen_instructions_.count(user) != 0 || @@ -171,7 +170,7 @@ void LoopFissionImpl::TraverseUseDef(opt::Instruction* inst, def_use->ForEachUser(user, traverser_functor); // Wrapper functor for the use traversal. - auto traverse_use = [&traverser_functor](opt::Instruction* use, uint32_t) { + auto traverse_use = [&traverser_functor](Instruction* use, uint32_t) { traverser_functor(use); }; def_use->ForEachUse(user, traverse_use); @@ -184,33 +183,33 @@ void LoopFissionImpl::TraverseUseDef(opt::Instruction* inst, } bool LoopFissionImpl::GroupInstructionsByUseDef() { - std::vector<std::set<opt::Instruction*>> sets{}; + std::vector<std::set<Instruction*>> sets{}; // We want to ignore all the instructions stemming from the loop condition // instruction. - opt::BasicBlock* condition_block = loop_->FindConditionBlock(); + BasicBlock* condition_block = loop_->FindConditionBlock(); if (!condition_block) return false; - opt::Instruction* condition = &*condition_block->tail(); + Instruction* condition = &*condition_block->tail(); // We iterate over the blocks via iterating over all the blocks in the // function, we do this so we are iterating in the same order which the blocks // appear in the binary. - opt::Function& function = *loop_->GetHeaderBlock()->GetParent(); + Function& function = *loop_->GetHeaderBlock()->GetParent(); // Create a temporary set to ignore certain groups of instructions within the // loop. We don't want any instructions related to control flow to be removed // from either loop only instructions within the control flow bodies. - std::set<opt::Instruction*> instructions_to_ignore{}; + std::set<Instruction*> instructions_to_ignore{}; TraverseUseDef(condition, &instructions_to_ignore, true, true); // Traverse control flow instructions to ensure they are added to the // seen_instructions_ set and will be ignored when it it called with actual // sets. - for (opt::BasicBlock& block : function) { + for (BasicBlock& block : function) { if (!loop_->IsInsideLoop(block.id())) continue; - for (opt::Instruction& inst : block) { + for (Instruction& inst : block) { // Ignore all instructions related to control flow. if (inst.opcode() == SpvOp::SpvOpSelectionMerge || inst.IsBranch()) { TraverseUseDef(&inst, &instructions_to_ignore, true, true); @@ -220,12 +219,12 @@ bool LoopFissionImpl::GroupInstructionsByUseDef() { // Traverse the instructions and generate the sets, automatically ignoring any // instructions in instructions_to_ignore. - for (opt::BasicBlock& block : function) { + for (BasicBlock& block : function) { if (!loop_->IsInsideLoop(block.id()) || loop_->GetHeaderBlock()->id() == block.id()) continue; - for (opt::Instruction& inst : block) { + for (Instruction& inst : block) { // Record the order that each load/store is seen. if (inst.opcode() == SpvOp::SpvOpLoad || inst.opcode() == SpvOp::SpvOpStore) { @@ -238,7 +237,7 @@ bool LoopFissionImpl::GroupInstructionsByUseDef() { } // Build the set. - std::set<opt::Instruction*> inst_set{}; + std::set<Instruction*> inst_set{}; TraverseUseDef(&inst, &inst_set); if (!inst_set.empty()) sets.push_back(std::move(inst_set)); } @@ -273,8 +272,8 @@ bool LoopFissionImpl::CanPerformSplit() { // Build a list of all parent loops of this loop. Loop dependence analysis // needs this structure. - std::vector<const opt::Loop*> loops; - opt::Loop* parent_loop = loop_; + std::vector<const Loop*> loops; + Loop* parent_loop = loop_; while (parent_loop) { loops.push_back(parent_loop); parent_loop = parent_loop->GetParent(); @@ -283,13 +282,13 @@ bool LoopFissionImpl::CanPerformSplit() { LoopDependenceAnalysis analysis{context_, loops}; // A list of all the stores in the cloned loop. - std::vector<opt::Instruction*> set_one_stores{}; + std::vector<Instruction*> set_one_stores{}; // A list of all the loads in the cloned loop. - std::vector<opt::Instruction*> set_one_loads{}; + std::vector<Instruction*> set_one_loads{}; // Populate the above lists. - for (opt::Instruction* inst : cloned_loop_instructions_) { + for (Instruction* inst : cloned_loop_instructions_) { if (inst->opcode() == SpvOp::SpvOpStore) { set_one_stores.push_back(inst); } else if (inst->opcode() == SpvOp::SpvOpLoad) { @@ -307,7 +306,7 @@ bool LoopFissionImpl::CanPerformSplit() { // Check the dependencies between loads in the cloned loop and stores in the // original and vice versa. - for (opt::Instruction* inst : original_loop_instructions_) { + for (Instruction* inst : original_loop_instructions_) { // If we find any instruction which we can't move (such as a barrier), // return false. if (!MovableInstruction(*inst)) return false; @@ -315,7 +314,7 @@ bool LoopFissionImpl::CanPerformSplit() { // Look at the dependency between the loads in the original and stores in // the cloned loops. if (inst->opcode() == SpvOp::SpvOpLoad) { - for (opt::Instruction* store : set_one_stores) { + for (Instruction* store : set_one_stores) { DistanceVector vec{loop_depth}; // If the store actually should appear after the load, return false. @@ -333,7 +332,7 @@ bool LoopFissionImpl::CanPerformSplit() { } } } else if (inst->opcode() == SpvOp::SpvOpStore) { - for (opt::Instruction* load : set_one_loads) { + for (Instruction* load : set_one_loads) { DistanceVector vec{loop_depth}; // If the load actually should appear after the store, return false. @@ -355,30 +354,30 @@ bool LoopFissionImpl::CanPerformSplit() { return true; } -opt::Loop* LoopFissionImpl::SplitLoop() { +Loop* LoopFissionImpl::SplitLoop() { // Clone the loop. LoopUtils util{context_, loop_}; LoopUtils::LoopCloningResult clone_results; - opt::Loop* cloned_loop = util.CloneAndAttachLoopToHeader(&clone_results); + Loop* cloned_loop = util.CloneAndAttachLoopToHeader(&clone_results); // Update the OpLoopMerge in the cloned loop. cloned_loop->UpdateLoopMergeInst(); // Add the loop_ to the module. - opt::Function::iterator it = + Function::iterator it = util.GetFunction()->FindBlock(loop_->GetOrCreatePreHeaderBlock()->id()); util.GetFunction()->AddBasicBlocks(clone_results.cloned_bb_.begin(), clone_results.cloned_bb_.end(), ++it); loop_->SetPreHeaderBlock(cloned_loop->GetMergeBlock()); - std::vector<opt::Instruction*> instructions_to_kill{}; + std::vector<Instruction*> instructions_to_kill{}; // Kill all the instructions which should appear in the cloned loop but not in // the original loop. for (uint32_t id : loop_->GetBlocks()) { - opt::BasicBlock* block = context_->cfg()->block(id); + BasicBlock* block = context_->cfg()->block(id); - for (opt::Instruction& inst : *block) { + for (Instruction& inst : *block) { // If the instruction appears in the cloned loop instruction group, kill // it. if (cloned_loop_instructions_.count(&inst) == 1 && @@ -395,9 +394,9 @@ opt::Loop* LoopFissionImpl::SplitLoop() { // Kill all instructions which should appear in the original loop and not in // the cloned loop. for (uint32_t id : cloned_loop->GetBlocks()) { - opt::BasicBlock* block = context_->cfg()->block(id); - for (opt::Instruction& inst : *block) { - opt::Instruction* old_inst = clone_results.ptr_map_[&inst]; + BasicBlock* block = context_->cfg()->block(id); + for (Instruction& inst : *block) { + Instruction* old_inst = clone_results.ptr_map_[&inst]; // If the instruction belongs to the original loop instruction group, kill // it. if (cloned_loop_instructions_.count(old_inst) == 0 && @@ -407,7 +406,7 @@ opt::Loop* LoopFissionImpl::SplitLoop() { } } - for (opt::Instruction* i : instructions_to_kill) { + for (Instruction* i : instructions_to_kill) { context_->KillInst(i); } @@ -433,13 +432,12 @@ LoopFissionPass::LoopFissionPass() : split_multiple_times_(false) { }; } -bool LoopFissionPass::ShouldSplitLoop(const opt::Loop& loop, - opt::IRContext* c) { +bool LoopFissionPass::ShouldSplitLoop(const Loop& loop, IRContext* c) { LivenessAnalysis* analysis = c->GetLivenessAnalysis(); RegisterLiveness::RegionRegisterLiveness liveness{}; - opt::Function* function = loop.GetHeaderBlock()->GetParent(); + Function* function = loop.GetHeaderBlock()->GetParent(); analysis->Get(function)->ComputeLoopRegisterPressure(loop, &liveness); return split_criteria_(liveness); @@ -448,23 +446,23 @@ bool LoopFissionPass::ShouldSplitLoop(const opt::Loop& loop, Pass::Status LoopFissionPass::Process() { bool changed = false; - for (opt::Function& f : *context()->module()) { + for (Function& f : *context()->module()) { // We collect all the inner most loops in the function and run the loop // splitting util on each. The reason we do this is to allow us to iterate // over each, as creating new loops will invalidate the the loop iterator. - std::vector<opt::Loop*> inner_most_loops{}; - opt::LoopDescriptor& loop_descriptor = *context()->GetLoopDescriptor(&f); - for (opt::Loop& loop : loop_descriptor) { + std::vector<Loop*> inner_most_loops{}; + LoopDescriptor& loop_descriptor = *context()->GetLoopDescriptor(&f); + for (Loop& loop : loop_descriptor) { if (!loop.HasChildren() && ShouldSplitLoop(loop, context())) { inner_most_loops.push_back(&loop); } } // List of new loops which meet the criteria to be split again. - std::vector<opt::Loop*> new_loops_to_split{}; + std::vector<Loop*> new_loops_to_split{}; while (!inner_most_loops.empty()) { - for (opt::Loop* loop : inner_most_loops) { + for (Loop* loop : inner_most_loops) { LoopFissionImpl impl{context(), loop}; // Group the instructions in the loop into two different sets of related @@ -475,10 +473,10 @@ Pass::Status LoopFissionPass::Process() { } if (impl.CanPerformSplit()) { - opt::Loop* second_loop = impl.SplitLoop(); + Loop* second_loop = impl.SplitLoop(); changed = true; context()->InvalidateAnalysesExceptFor( - opt::IRContext::kAnalysisLoopAnalysis); + IRContext::kAnalysisLoopAnalysis); // If the newly created loop meets the criteria to be split, split it // again. diff --git a/source/opt/loop_fission.h b/source/opt/loop_fission.h index 626c92ad..841d4d58 100644 --- a/source/opt/loop_fission.h +++ b/source/opt/loop_fission.h @@ -60,7 +60,7 @@ class LoopFissionPass : public Pass { Pass::Status Process() override; // Checks if |loop| meets the register pressure criteria to be split. - bool ShouldSplitLoop(const opt::Loop& loop, opt::IRContext* context); + bool ShouldSplitLoop(const Loop& loop, IRContext* context); private: // Functor to run in ShouldSplitLoop to determine if the register pressure diff --git a/source/opt/loop_fusion.cpp b/source/opt/loop_fusion.cpp index a7c4292a..350b27b8 100644 --- a/source/opt/loop_fusion.cpp +++ b/source/opt/loop_fusion.cpp @@ -27,7 +27,7 @@ namespace opt { namespace { // Append all the loops nested in |loop| to |loops|. -void CollectChildren(opt::Loop* loop, std::vector<const opt::Loop*>* loops) { +void CollectChildren(Loop* loop, std::vector<const Loop*>* loops) { for (auto child : *loop) { loops->push_back(child); if (child->NumImmediateChildren() != 0) { @@ -37,10 +37,10 @@ void CollectChildren(opt::Loop* loop, std::vector<const opt::Loop*>* loops) { } // Return the set of locations accessed by |stores| and |loads|. -std::set<opt::Instruction*> GetLocationsAccessed( - const std::map<opt::Instruction*, std::vector<opt::Instruction*>>& stores, - const std::map<opt::Instruction*, std::vector<opt::Instruction*>>& loads) { - std::set<opt::Instruction*> locations{}; +std::set<Instruction*> GetLocationsAccessed( + const std::map<Instruction*, std::vector<Instruction*>>& stores, + const std::map<Instruction*, std::vector<Instruction*>>& loads) { + std::set<Instruction*> locations{}; for (const auto& kv : stores) { locations.insert(std::get<0>(kv)); @@ -56,8 +56,8 @@ std::set<opt::Instruction*> GetLocationsAccessed( // Append all dependences from |sources| to |destinations| to |dependences|. void GetDependences(std::vector<DistanceVector>* dependences, LoopDependenceAnalysis* analysis, - const std::vector<opt::Instruction*>& sources, - const std::vector<opt::Instruction*>& destinations, + const std::vector<Instruction*>& sources, + const std::vector<Instruction*>& destinations, size_t num_entries) { for (auto source : sources) { for (auto destination : destinations) { @@ -70,8 +70,8 @@ void GetDependences(std::vector<DistanceVector>* dependences, } // Apped all instructions in |block| to |instructions|. -void AddInstructionsInBlock(std::vector<opt::Instruction*>* instructions, - opt::BasicBlock* block) { +void AddInstructionsInBlock(std::vector<Instruction*>* instructions, + BasicBlock* block) { for (auto& inst : *block) { instructions->push_back(&inst); } @@ -81,13 +81,13 @@ void AddInstructionsInBlock(std::vector<opt::Instruction*>* instructions, } // namespace -bool LoopFusion::UsedInContinueOrConditionBlock( - opt::Instruction* phi_instruction, opt::Loop* loop) { +bool LoopFusion::UsedInContinueOrConditionBlock(Instruction* phi_instruction, + Loop* loop) { auto condition_block = loop->FindConditionBlock()->id(); auto continue_block = loop->GetContinueBlock()->id(); auto not_used = context_->get_def_use_mgr()->WhileEachUser( phi_instruction, - [this, condition_block, continue_block](opt::Instruction* instruction) { + [this, condition_block, continue_block](Instruction* instruction) { auto block_id = context_->get_instr_block(instruction)->id(); return block_id != condition_block && block_id != continue_block; }); @@ -96,10 +96,10 @@ bool LoopFusion::UsedInContinueOrConditionBlock( } void LoopFusion::RemoveIfNotUsedContinueOrConditionBlock( - std::vector<opt::Instruction*>* instructions, opt::Loop* loop) { + std::vector<Instruction*>* instructions, Loop* loop) { instructions->erase( std::remove_if(std::begin(*instructions), std::end(*instructions), - [this, loop](opt::Instruction* instruction) { + [this, loop](Instruction* instruction) { return !UsedInContinueOrConditionBlock(instruction, loop); }), @@ -132,7 +132,7 @@ bool LoopFusion::AreCompatible() { // |GetInductionVariables| returns all OpPhi in the header. Check that both // loops have exactly one that is used in the continue and condition blocks. - std::vector<opt::Instruction*> inductions_0{}, inductions_1{}; + std::vector<Instruction*> inductions_0{}, inductions_1{}; loop_0_->GetInductionVariables(inductions_0); RemoveIfNotUsedContinueOrConditionBlock(&inductions_0, loop_0_); @@ -169,7 +169,7 @@ bool LoopFusion::AreCompatible() { auto pre_header_1 = loop_1_->GetPreHeaderBlock(); - std::vector<opt::BasicBlock*> block_to_check{}; + std::vector<BasicBlock*> block_to_check{}; block_to_check.push_back(pre_header_1); if (loop_0_->GetMergeBlock() != loop_1_->GetPreHeaderBlock()) { @@ -208,7 +208,7 @@ bool LoopFusion::AreCompatible() { auto is_used = false; context_->get_def_use_mgr()->ForEachUse( inst.GetSingleWordInOperand(0), - [&is_used](opt::Instruction* use_inst, uint32_t) { + [&is_used](Instruction* use_inst, uint32_t) { if (use_inst->opcode() == SpvOpLoad) { is_used = true; } @@ -230,7 +230,7 @@ bool LoopFusion::AreCompatible() { return true; } // namespace opt -bool LoopFusion::ContainsBarriersOrFunctionCalls(opt::Loop* loop) { +bool LoopFusion::ContainsBarriersOrFunctionCalls(Loop* loop) { for (const auto& block : loop->GetBlocks()) { for (const auto& inst : *containing_function_->FindBlock(block)) { auto opcode = inst.opcode(); @@ -336,9 +336,9 @@ bool LoopFusion::CheckStep() { return true; } -std::map<opt::Instruction*, std::vector<opt::Instruction*>> -LoopFusion::LocationToMemOps(const std::vector<opt::Instruction*>& mem_ops) { - std::map<opt::Instruction*, std::vector<opt::Instruction*>> location_map{}; +std::map<Instruction*, std::vector<Instruction*>> LoopFusion::LocationToMemOps( + const std::vector<Instruction*>& mem_ops) { + std::map<Instruction*, std::vector<Instruction*>> location_map{}; for (auto instruction : mem_ops) { auto access_location = context_->get_def_use_mgr()->GetDef( @@ -355,10 +355,10 @@ LoopFusion::LocationToMemOps(const std::vector<opt::Instruction*>& mem_ops) { return location_map; } -std::pair<std::vector<opt::Instruction*>, std::vector<opt::Instruction*>> -LoopFusion::GetLoadsAndStoresInLoop(opt::Loop* loop) { - std::vector<opt::Instruction*> loads{}; - std::vector<opt::Instruction*> stores{}; +std::pair<std::vector<Instruction*>, std::vector<Instruction*>> +LoopFusion::GetLoadsAndStoresInLoop(Loop* loop) { + std::vector<Instruction*> loads{}; + std::vector<Instruction*> stores{}; for (auto block_id : loop->GetBlocks()) { if (block_id == loop->GetContinueBlock()->id()) { @@ -377,9 +377,9 @@ LoopFusion::GetLoadsAndStoresInLoop(opt::Loop* loop) { return std::make_pair(loads, stores); } -bool LoopFusion::IsUsedInLoop(opt::Instruction* instruction, opt::Loop* loop) { +bool LoopFusion::IsUsedInLoop(Instruction* instruction, Loop* loop) { auto not_used = context_->get_def_use_mgr()->WhileEachUser( - instruction, [this, loop](opt::Instruction* user) { + instruction, [this, loop](Instruction* user) { auto block_id = context_->get_instr_block(user)->id(); return !loop->IsInsideLoop(block_id); }); @@ -397,7 +397,7 @@ bool LoopFusion::IsLegal() { return false; } - std::vector<opt::Instruction*> phi_instructions{}; + std::vector<Instruction*> phi_instructions{}; loop_0_->GetInductionVariables(phi_instructions); // Check no OpPhi in |loop_0_| is used in |loop_1_|. @@ -410,7 +410,7 @@ bool LoopFusion::IsLegal() { // Check no LCSSA OpPhi in merge block of |loop_0_| is used in |loop_1_|. auto phi_used = false; loop_0_->GetMergeBlock()->ForEachPhiInst( - [this, &phi_used](opt::Instruction* phi_instruction) { + [this, &phi_used](Instruction* phi_instruction) { phi_used |= IsUsedInLoop(phi_instruction, loop_1_); }); @@ -433,7 +433,7 @@ bool LoopFusion::IsLegal() { auto locations_0 = GetLocationsAccessed(store_locs_0, load_locs_0); auto locations_1 = GetLocationsAccessed(store_locs_1, load_locs_1); - std::vector<opt::Instruction*> potential_clashes{}; + std::vector<Instruction*> potential_clashes{}; std::set_intersection(std::begin(locations_0), std::end(locations_0), std::begin(locations_1), std::end(locations_1), @@ -445,7 +445,7 @@ bool LoopFusion::IsLegal() { } // Find variables that have at least one store. - std::vector<opt::Instruction*> potential_clashes_with_stores{}; + std::vector<Instruction*> potential_clashes_with_stores{}; for (auto location : potential_clashes) { if (store_locs_0.find(location) != std::end(store_locs_0) || store_locs_1.find(location) != std::end(store_locs_1)) { @@ -463,7 +463,7 @@ bool LoopFusion::IsLegal() { // distance. // Find all the loops in this loop nest for the dependency analysis. - std::vector<const opt::Loop*> loops{}; + std::vector<const Loop*> loops{}; // Find the parents. for (auto current_loop = loop_0_; current_loop != nullptr; @@ -519,7 +519,7 @@ bool LoopFusion::IsLegal() { return true; } -void ReplacePhiParentWith(opt::Instruction* inst, uint32_t orig_block, +void ReplacePhiParentWith(Instruction* inst, uint32_t orig_block, uint32_t new_block) { if (inst->GetSingleWordInOperand(1) == orig_block) { inst->SetInOperand(1, {new_block}); @@ -555,7 +555,7 @@ void LoopFusion::Fuse() { // Update merge block id in the header of |loop_0_| to the merge block of // |loop_1_|. - loop_0_->GetHeaderBlock()->ForEachInst([this](opt::Instruction* inst) { + loop_0_->GetHeaderBlock()->ForEachInst([this](Instruction* inst) { if (inst->opcode() == SpvOpLoopMerge) { inst->SetInOperand(0, {loop_1_->GetMergeBlock()->id()}); } @@ -563,7 +563,7 @@ void LoopFusion::Fuse() { // Update condition branch target in |loop_0_| to the merge block of // |loop_1_|. - condition_block_of_0->ForEachInst([this](opt::Instruction* inst) { + condition_block_of_0->ForEachInst([this](Instruction* inst) { if (inst->opcode() == SpvOpBranchConditional) { auto loop_0_merge_block_id = loop_0_->GetMergeBlock()->id(); @@ -577,7 +577,7 @@ void LoopFusion::Fuse() { // Move OpPhi instructions not corresponding to the induction variable from // the header of |loop_1_| to the header of |loop_0_|. - std::vector<opt::Instruction*> instructions_to_move{}; + std::vector<Instruction*> instructions_to_move{}; for (auto& instruction : *loop_1_->GetHeaderBlock()) { if (instruction.opcode() == SpvOpPhi && &instruction != induction_1_) { instructions_to_move.push_back(&instruction); @@ -590,7 +590,7 @@ void LoopFusion::Fuse() { } // Update the OpPhi parents to the correct blocks in |loop_0_|. - loop_0_->GetHeaderBlock()->ForEachPhiInst([this](opt::Instruction* i) { + loop_0_->GetHeaderBlock()->ForEachPhiInst([this](Instruction* i) { ReplacePhiParentWith(i, loop_1_->GetPreHeaderBlock()->id(), loop_0_->GetPreHeaderBlock()->id()); @@ -610,15 +610,14 @@ void LoopFusion::Fuse() { induction_0_->result_id()); // Replace LCSSA OpPhi in merge block of |loop_0_|. - loop_0_->GetMergeBlock()->ForEachPhiInst( - [this](opt::Instruction* instruction) { - context_->ReplaceAllUsesWith(instruction->result_id(), - instruction->GetSingleWordInOperand(0)); - }); + loop_0_->GetMergeBlock()->ForEachPhiInst([this](Instruction* instruction) { + context_->ReplaceAllUsesWith(instruction->result_id(), + instruction->GetSingleWordInOperand(0)); + }); // Update LCSSA OpPhi in merge block of |loop_1_|. loop_1_->GetMergeBlock()->ForEachPhiInst( - [condition_block_of_0](opt::Instruction* instruction) { + [condition_block_of_0](Instruction* instruction) { instruction->SetInOperand(1, {condition_block_of_0->id()}); }); @@ -627,7 +626,7 @@ void LoopFusion::Fuse() { // Gather all instructions to be killed from |loop_1_| (induction variable // initialisation, header, condition and continue blocks). - std::vector<opt::Instruction*> instr_to_delete{}; + std::vector<Instruction*> instr_to_delete{}; AddInstructionsInBlock(&instr_to_delete, loop_1_->GetPreHeaderBlock()); AddInstructionsInBlock(&instr_to_delete, loop_1_->GetHeaderBlock()); AddInstructionsInBlock(&instr_to_delete, loop_1_->FindConditionBlock()); @@ -673,7 +672,7 @@ void LoopFusion::Fuse() { auto ld = context_->GetLoopDescriptor(containing_function_); // Create a copy, so the iterator wouldn't be invalidated. - std::vector<opt::Loop*> loops_to_add_remove{}; + std::vector<Loop*> loops_to_add_remove{}; for (auto child_loop : *loop_1_) { loops_to_add_remove.push_back(child_loop); } @@ -722,10 +721,9 @@ void LoopFusion::Fuse() { // Invalidate analyses. context_->InvalidateAnalysesExceptFor( - opt::IRContext::Analysis::kAnalysisInstrToBlockMapping | - opt::IRContext::Analysis::kAnalysisLoopAnalysis | - opt::IRContext::Analysis::kAnalysisDefUse | - opt::IRContext::Analysis::kAnalysisCFG); + IRContext::Analysis::kAnalysisInstrToBlockMapping | + IRContext::Analysis::kAnalysisLoopAnalysis | + IRContext::Analysis::kAnalysisDefUse | IRContext::Analysis::kAnalysisCFG); } } // namespace opt diff --git a/source/opt/loop_fusion.h b/source/opt/loop_fusion.h index 90f2bf0b..343e023b 100644 --- a/source/opt/loop_fusion.h +++ b/source/opt/loop_fusion.h @@ -29,7 +29,7 @@ namespace opt { class LoopFusion { public: - LoopFusion(opt::IRContext* context, opt::Loop* loop_0, opt::Loop* loop_1) + LoopFusion(IRContext* context, Loop* loop_0, Loop* loop_1) : context_(context), loop_0_(loop_0), loop_1_(loop_1), @@ -70,42 +70,41 @@ class LoopFusion { // Returns |true| if |instruction| is used in the continue or condition block // of |loop|. - bool UsedInContinueOrConditionBlock(opt::Instruction* instruction, - opt::Loop* loop); + bool UsedInContinueOrConditionBlock(Instruction* instruction, Loop* loop); // Remove entries in |instructions| that are not used in the continue or // condition block of |loop|. void RemoveIfNotUsedContinueOrConditionBlock( - std::vector<opt::Instruction*>* instructions, opt::Loop* loop); + std::vector<Instruction*>* instructions, Loop* loop); // Returns |true| if |instruction| is used in |loop|. - bool IsUsedInLoop(opt::Instruction* instruction, opt::Loop* loop); + bool IsUsedInLoop(Instruction* instruction, Loop* loop); // Returns |true| if |loop| has at least one barrier or function call. - bool ContainsBarriersOrFunctionCalls(opt::Loop* loop); + bool ContainsBarriersOrFunctionCalls(Loop* loop); // Get all instructions in the |loop| (except in the latch block) that have // the opcode |opcode|. - std::pair<std::vector<opt::Instruction*>, std::vector<opt::Instruction*>> - GetLoadsAndStoresInLoop(opt::Loop* loop); + std::pair<std::vector<Instruction*>, std::vector<Instruction*>> + GetLoadsAndStoresInLoop(Loop* loop); // Given a vector of memory operations (OpLoad/OpStore), constructs a map from // variables to the loads/stores that those variables. - std::map<opt::Instruction*, std::vector<opt::Instruction*>> LocationToMemOps( - const std::vector<opt::Instruction*>& mem_ops); + std::map<Instruction*, std::vector<Instruction*>> LocationToMemOps( + const std::vector<Instruction*>& mem_ops); - opt::IRContext* context_; + IRContext* context_; // The original loops to be fused. - opt::Loop* loop_0_; - opt::Loop* loop_1_; + Loop* loop_0_; + Loop* loop_1_; // The function that contains |loop_0_| and |loop_1_|. - opt::Function* containing_function_ = nullptr; + Function* containing_function_ = nullptr; // The induction variables for |loop_0_| and |loop_1_|. - opt::Instruction* induction_0_ = nullptr; - opt::Instruction* induction_1_ = nullptr; + Instruction* induction_0_ = nullptr; + Instruction* induction_1_ = nullptr; }; } // namespace opt diff --git a/source/opt/loop_fusion_pass.cpp b/source/opt/loop_fusion_pass.cpp index 63b99c09..46bfdc67 100644 --- a/source/opt/loop_fusion_pass.cpp +++ b/source/opt/loop_fusion_pass.cpp @@ -24,18 +24,18 @@ namespace opt { Pass::Status LoopFusionPass::Process() { bool modified = false; - opt::Module* module = context()->module(); + Module* module = context()->module(); // Process each function in the module - for (opt::Function& f : *module) { + for (Function& f : *module) { modified |= ProcessFunction(&f); } return modified ? Status::SuccessWithChange : Status::SuccessWithoutChange; } -bool LoopFusionPass::ProcessFunction(opt::Function* function) { - opt::LoopDescriptor& ld = *context()->GetLoopDescriptor(function); +bool LoopFusionPass::ProcessFunction(Function* function) { + LoopDescriptor& ld = *context()->GetLoopDescriptor(function); // If a loop doesn't have a preheader needs then it needs to be created. Make // sure to return Status::SuccessWithChange in that case. diff --git a/source/opt/loop_fusion_pass.h b/source/opt/loop_fusion_pass.h index f3daf496..99dd67d7 100644 --- a/source/opt/loop_fusion_pass.h +++ b/source/opt/loop_fusion_pass.h @@ -39,7 +39,7 @@ class LoopFusionPass : public Pass { private: // Fuse loops in |function| if compatible, legal and the fused loop won't use // too many registers. - bool ProcessFunction(opt::Function* function); + bool ProcessFunction(Function* function); // The maximum number of registers a fused loop is allowed to use. size_t max_registers_per_loop_; diff --git a/source/opt/loop_peeling.cpp b/source/opt/loop_peeling.cpp index 926944b5..274aa66d 100644 --- a/source/opt/loop_peeling.cpp +++ b/source/opt/loop_peeling.cpp @@ -33,20 +33,20 @@ size_t LoopPeelingPass::code_grow_threshold_ = 1000; void LoopPeeling::DuplicateAndConnectLoop( LoopUtils::LoopCloningResult* clone_results) { - opt::CFG& cfg = *context_->cfg(); + CFG& cfg = *context_->cfg(); analysis::DefUseManager* def_use_mgr = context_->get_def_use_mgr(); assert(CanPeelLoop() && "Cannot peel loop!"); - std::vector<opt::BasicBlock*> ordered_loop_blocks; - opt::BasicBlock* pre_header = loop_->GetOrCreatePreHeaderBlock(); + std::vector<BasicBlock*> ordered_loop_blocks; + BasicBlock* pre_header = loop_->GetOrCreatePreHeaderBlock(); loop_->ComputeLoopStructuredOrder(&ordered_loop_blocks); cloned_loop_ = loop_utils_.CloneLoop(clone_results, ordered_loop_blocks); // Add the basic block to the function. - opt::Function::iterator it = + Function::iterator it = loop_utils_.GetFunction()->FindBlock(pre_header->id()); assert(it != loop_utils_.GetFunction()->end() && "Pre-header not found in the function."); @@ -54,7 +54,7 @@ void LoopPeeling::DuplicateAndConnectLoop( clone_results->cloned_bb_.begin(), clone_results->cloned_bb_.end(), ++it); // Make the |loop_|'s preheader the |cloned_loop_| one. - opt::BasicBlock* cloned_header = cloned_loop_->GetHeaderBlock(); + BasicBlock* cloned_header = cloned_loop_->GetHeaderBlock(); pre_header->ForEachSuccessorLabel( [cloned_header](uint32_t* succ) { *succ = cloned_header->id(); }); @@ -71,7 +71,7 @@ void LoopPeeling::DuplicateAndConnectLoop( uint32_t cloned_loop_exit = 0; for (uint32_t pred_id : cfg.preds(loop_->GetMergeBlock()->id())) { if (loop_->IsInsideLoop(pred_id)) continue; - opt::BasicBlock* bb = cfg.block(pred_id); + BasicBlock* bb = cfg.block(pred_id); assert(cloned_loop_exit == 0 && "The loop has multiple exits."); cloned_loop_exit = bb->id(); bb->ForEachSuccessorLabel([this](uint32_t* succ) { @@ -116,7 +116,7 @@ void LoopPeeling::DuplicateAndConnectLoop( // } loop_->GetHeaderBlock()->ForEachPhiInst([cloned_loop_exit, def_use_mgr, clone_results, - this](opt::Instruction* phi) { + this](Instruction* phi) { for (uint32_t i = 0; i < phi->NumInOperands(); i += 2) { if (!loop_->IsInsideLoop(phi->GetSingleWordInOperand(i + 1))) { phi->SetInOperand(i, @@ -143,20 +143,19 @@ void LoopPeeling::InsertCanonicalInductionVariable( return; } - opt::BasicBlock::iterator insert_point = - GetClonedLoop()->GetLatchBlock()->tail(); + BasicBlock::iterator insert_point = GetClonedLoop()->GetLatchBlock()->tail(); if (GetClonedLoop()->GetLatchBlock()->GetMergeInst()) { --insert_point; } - InstructionBuilder builder(context_, &*insert_point, - opt::IRContext::kAnalysisDefUse | - opt::IRContext::kAnalysisInstrToBlockMapping); - opt::Instruction* uint_1_cst = + InstructionBuilder builder( + context_, &*insert_point, + IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping); + Instruction* uint_1_cst = builder.Add32BitConstantInteger<uint32_t>(1, int_type_->IsSigned()); // Create the increment. // Note that we do "1 + 1" here, one of the operand should the phi // value but we don't have it yet. The operand will be set latter. - opt::Instruction* iv_inc = builder.AddIAdd( + Instruction* iv_inc = builder.AddIAdd( uint_1_cst->type_id(), uint_1_cst->result_id(), uint_1_cst->result_id()); builder.SetInsertPoint(&*GetClonedLoop()->GetHeaderBlock()->begin()); @@ -180,12 +179,12 @@ void LoopPeeling::InsertCanonicalInductionVariable( } void LoopPeeling::GetIteratorUpdateOperations( - const opt::Loop* loop, opt::Instruction* iterator, - std::unordered_set<opt::Instruction*>* operations) { - opt::analysis::DefUseManager* def_use_mgr = context_->get_def_use_mgr(); + const Loop* loop, Instruction* iterator, + std::unordered_set<Instruction*>* operations) { + analysis::DefUseManager* def_use_mgr = context_->get_def_use_mgr(); operations->insert(iterator); iterator->ForEachInId([def_use_mgr, loop, operations, this](uint32_t* id) { - opt::Instruction* insn = def_use_mgr->GetDef(*id); + Instruction* insn = def_use_mgr->GetDef(*id); if (insn->opcode() == SpvOpLabel) { return; } @@ -202,7 +201,7 @@ void LoopPeeling::GetIteratorUpdateOperations( // Gather the set of blocks for all the path from |entry| to |root|. static void GetBlocksInPath(uint32_t block, uint32_t entry, std::unordered_set<uint32_t>* blocks_in_path, - const opt::CFG& cfg) { + const CFG& cfg) { for (uint32_t pid : cfg.preds(block)) { if (blocks_in_path->insert(pid).second) { if (pid != entry) { @@ -213,7 +212,7 @@ static void GetBlocksInPath(uint32_t block, uint32_t entry, } bool LoopPeeling::IsConditionCheckSideEffectFree() const { - opt::CFG& cfg = *context_->cfg(); + CFG& cfg = *context_->cfg(); // The "do-while" form does not cause issues, the algorithm takes into account // the first iteration. @@ -227,8 +226,8 @@ bool LoopPeeling::IsConditionCheckSideEffectFree() const { &blocks_in_path, cfg); for (uint32_t bb_id : blocks_in_path) { - opt::BasicBlock* bb = cfg.block(bb_id); - if (!bb->WhileEachInst([this](opt::Instruction* insn) { + BasicBlock* bb = cfg.block(bb_id); + if (!bb->WhileEachInst([this](Instruction* insn) { if (insn->IsBranch()) return true; switch (insn->opcode()) { case SpvOpLabel: @@ -249,11 +248,10 @@ bool LoopPeeling::IsConditionCheckSideEffectFree() const { } void LoopPeeling::GetIteratingExitValues() { - opt::CFG& cfg = *context_->cfg(); + CFG& cfg = *context_->cfg(); - loop_->GetHeaderBlock()->ForEachPhiInst([this](opt::Instruction* phi) { - exit_value_[phi->result_id()] = nullptr; - }); + loop_->GetHeaderBlock()->ForEachPhiInst( + [this](Instruction* phi) { exit_value_[phi->result_id()] = nullptr; }); if (!loop_->GetMergeBlock()) { return; @@ -261,7 +259,7 @@ void LoopPeeling::GetIteratingExitValues() { if (cfg.preds(loop_->GetMergeBlock()->id()).size() != 1) { return; } - opt::analysis::DefUseManager* def_use_mgr = context_->get_def_use_mgr(); + analysis::DefUseManager* def_use_mgr = context_->get_def_use_mgr(); uint32_t condition_block_id = cfg.preds(loop_->GetMergeBlock()->id())[0]; @@ -270,8 +268,8 @@ void LoopPeeling::GetIteratingExitValues() { condition_block_id) != header_pred.end(); if (do_while_form_) { loop_->GetHeaderBlock()->ForEachPhiInst( - [condition_block_id, def_use_mgr, this](opt::Instruction* phi) { - std::unordered_set<opt::Instruction*> operations; + [condition_block_id, def_use_mgr, this](Instruction* phi) { + std::unordered_set<Instruction*> operations; for (uint32_t i = 0; i < phi->NumInOperands(); i += 2) { if (condition_block_id == phi->GetSingleWordInOperand(i + 1)) { @@ -284,17 +282,17 @@ void LoopPeeling::GetIteratingExitValues() { DominatorTree* dom_tree = &context_->GetDominatorAnalysis(loop_utils_.GetFunction()) ->GetDomTree(); - opt::BasicBlock* condition_block = cfg.block(condition_block_id); + BasicBlock* condition_block = cfg.block(condition_block_id); loop_->GetHeaderBlock()->ForEachPhiInst( - [dom_tree, condition_block, this](opt::Instruction* phi) { - std::unordered_set<opt::Instruction*> operations; + [dom_tree, condition_block, this](Instruction* phi) { + std::unordered_set<Instruction*> operations; // Not the back-edge value, check if the phi instruction is the only // possible candidate. GetIteratorUpdateOperations(loop_, phi, &operations); - for (opt::Instruction* insn : operations) { + for (Instruction* insn : operations) { if (insn == phi) { continue; } @@ -309,8 +307,8 @@ void LoopPeeling::GetIteratingExitValues() { } void LoopPeeling::FixExitCondition( - const std::function<uint32_t(opt::Instruction*)>& condition_builder) { - opt::CFG& cfg = *context_->cfg(); + const std::function<uint32_t(Instruction*)>& condition_builder) { + CFG& cfg = *context_->cfg(); uint32_t condition_block_id = 0; for (uint32_t id : cfg.preds(GetClonedLoop()->GetMergeBlock()->id())) { @@ -321,10 +319,10 @@ void LoopPeeling::FixExitCondition( } assert(condition_block_id != 0 && "2nd loop in improperly connected"); - opt::BasicBlock* condition_block = cfg.block(condition_block_id); - opt::Instruction* exit_condition = condition_block->terminator(); + BasicBlock* condition_block = cfg.block(condition_block_id); + Instruction* exit_condition = condition_block->terminator(); assert(exit_condition->opcode() == SpvOpBranchConditional); - opt::BasicBlock::iterator insert_point = condition_block->tail(); + BasicBlock::iterator insert_point = condition_block->tail(); if (condition_block->GetMergeInst()) { --insert_point; } @@ -343,17 +341,17 @@ void LoopPeeling::FixExitCondition( context_->get_def_use_mgr()->AnalyzeInstUse(exit_condition); } -opt::BasicBlock* LoopPeeling::CreateBlockBefore(opt::BasicBlock* bb) { +BasicBlock* LoopPeeling::CreateBlockBefore(BasicBlock* bb) { analysis::DefUseManager* def_use_mgr = context_->get_def_use_mgr(); - opt::CFG& cfg = *context_->cfg(); + CFG& cfg = *context_->cfg(); assert(cfg.preds(bb->id()).size() == 1 && "More than one predecessor"); - std::unique_ptr<opt::BasicBlock> new_bb = MakeUnique<opt::BasicBlock>( - std::unique_ptr<opt::Instruction>(new opt::Instruction( + std::unique_ptr<BasicBlock> new_bb = + MakeUnique<BasicBlock>(std::unique_ptr<Instruction>(new Instruction( context_, SpvOpLabel, 0, context_->TakeNextId(), {}))); new_bb->SetParent(loop_utils_.GetFunction()); // Update the loop descriptor. - opt::Loop* in_loop = (*loop_utils_.GetLoopDescriptor())[bb]; + Loop* in_loop = (*loop_utils_.GetLoopDescriptor())[bb]; if (in_loop) { in_loop->AddBasicBlock(new_bb.get()); loop_utils_.GetLoopDescriptor()->SetBasicBlockToLoop(new_bb->id(), in_loop); @@ -362,7 +360,7 @@ opt::BasicBlock* LoopPeeling::CreateBlockBefore(opt::BasicBlock* bb) { context_->set_instr_block(new_bb->GetLabelInst(), new_bb.get()); def_use_mgr->AnalyzeInstDefUse(new_bb->GetLabelInst()); - opt::BasicBlock* bb_pred = cfg.block(cfg.preds(bb->id())[0]); + BasicBlock* bb_pred = cfg.block(cfg.preds(bb->id())[0]); bb_pred->tail()->ForEachInId([bb, &new_bb](uint32_t* id) { if (*id == bb->id()) { *id = new_bb->id(); @@ -373,37 +371,36 @@ opt::BasicBlock* LoopPeeling::CreateBlockBefore(opt::BasicBlock* bb) { def_use_mgr->AnalyzeInstUse(&*bb_pred->tail()); // Update the incoming branch. - bb->ForEachPhiInst([&new_bb, def_use_mgr](opt::Instruction* phi) { + bb->ForEachPhiInst([&new_bb, def_use_mgr](Instruction* phi) { phi->SetInOperand(1, {new_bb->id()}); def_use_mgr->AnalyzeInstUse(phi); }); - InstructionBuilder(context_, new_bb.get(), - opt::IRContext::kAnalysisDefUse | - opt::IRContext::kAnalysisInstrToBlockMapping) + InstructionBuilder( + context_, new_bb.get(), + IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping) .AddBranch(bb->id()); cfg.RegisterBlock(new_bb.get()); // Add the basic block to the function. - opt::Function::iterator it = loop_utils_.GetFunction()->FindBlock(bb->id()); + Function::iterator it = loop_utils_.GetFunction()->FindBlock(bb->id()); assert(it != loop_utils_.GetFunction()->end() && "Basic block not found in the function."); - opt::BasicBlock* ret = new_bb.get(); + BasicBlock* ret = new_bb.get(); loop_utils_.GetFunction()->AddBasicBlock(std::move(new_bb), it); return ret; } -opt::BasicBlock* LoopPeeling::ProtectLoop(opt::Loop* loop, - opt::Instruction* condition, - opt::BasicBlock* if_merge) { - opt::BasicBlock* if_block = loop->GetOrCreatePreHeaderBlock(); +BasicBlock* LoopPeeling::ProtectLoop(Loop* loop, Instruction* condition, + BasicBlock* if_merge) { + BasicBlock* if_block = loop->GetOrCreatePreHeaderBlock(); // Will no longer be a pre-header because of the if. loop->SetPreHeaderBlock(nullptr); // Kill the branch to the header. context_->KillInst(&*if_block->tail()); - InstructionBuilder builder(context_, if_block, - opt::IRContext::kAnalysisDefUse | - opt::IRContext::kAnalysisInstrToBlockMapping); + InstructionBuilder builder( + context_, if_block, + IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping); builder.AddConditionalBranch(condition->result_id(), loop->GetHeaderBlock()->id(), if_merge->id(), if_merge->id()); @@ -421,27 +418,25 @@ void LoopPeeling::PeelBefore(uint32_t peel_factor) { // Add a canonical induction variable "canonical_induction_variable_". InsertCanonicalInductionVariable(&clone_results); - InstructionBuilder builder(context_, - &*cloned_loop_->GetPreHeaderBlock()->tail(), - opt::IRContext::kAnalysisDefUse | - opt::IRContext::kAnalysisInstrToBlockMapping); - opt::Instruction* factor = + InstructionBuilder builder( + context_, &*cloned_loop_->GetPreHeaderBlock()->tail(), + IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping); + Instruction* factor = builder.Add32BitConstantInteger(peel_factor, int_type_->IsSigned()); - opt::Instruction* has_remaining_iteration = builder.AddLessThan( + Instruction* has_remaining_iteration = builder.AddLessThan( factor->result_id(), loop_iteration_count_->result_id()); - opt::Instruction* max_iteration = builder.AddSelect( + Instruction* max_iteration = builder.AddSelect( factor->type_id(), has_remaining_iteration->result_id(), factor->result_id(), loop_iteration_count_->result_id()); // Change the exit condition of the cloned loop to be (exit when become // false): // "canonical_induction_variable_" < min("factor", "loop_iteration_count_") - FixExitCondition([max_iteration, - this](opt::Instruction* insert_before_point) { + FixExitCondition([max_iteration, this](Instruction* insert_before_point) { return InstructionBuilder(context_, insert_before_point, - opt::IRContext::kAnalysisDefUse | - opt::IRContext::kAnalysisInstrToBlockMapping) + IRContext::kAnalysisDefUse | + IRContext::kAnalysisInstrToBlockMapping) .AddLessThan(canonical_induction_variable_->result_id(), max_iteration->result_id()) ->result_id(); @@ -449,15 +444,15 @@ void LoopPeeling::PeelBefore(uint32_t peel_factor) { // "Protect" the second loop: the second loop can only be executed if // |has_remaining_iteration| is true (i.e. factor < loop_iteration_count_). - opt::BasicBlock* if_merge_block = loop_->GetMergeBlock(); + BasicBlock* if_merge_block = loop_->GetMergeBlock(); loop_->SetMergeBlock(CreateBlockBefore(loop_->GetMergeBlock())); // Prevent the second loop from being executed if we already executed all the // required iterations. - opt::BasicBlock* if_block = + BasicBlock* if_block = ProtectLoop(loop_, has_remaining_iteration, if_merge_block); // Patch the phi of the merge block. if_merge_block->ForEachPhiInst( - [&clone_results, if_block, this](opt::Instruction* phi) { + [&clone_results, if_block, this](Instruction* phi) { // if_merge_block had previously only 1 predecessor. uint32_t incoming_value = phi->GetSingleWordInOperand(0); auto def_in_loop = clone_results.value_map_.find(incoming_value); @@ -471,9 +466,8 @@ void LoopPeeling::PeelBefore(uint32_t peel_factor) { }); context_->InvalidateAnalysesExceptFor( - opt::IRContext::kAnalysisDefUse | - opt::IRContext::kAnalysisInstrToBlockMapping | - opt::IRContext::kAnalysisLoopAnalysis | opt::IRContext::kAnalysisCFG); + IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping | + IRContext::kAnalysisLoopAnalysis | IRContext::kAnalysisCFG); } void LoopPeeling::PeelAfter(uint32_t peel_factor) { @@ -486,24 +480,22 @@ void LoopPeeling::PeelAfter(uint32_t peel_factor) { // Add a canonical induction variable "canonical_induction_variable_". InsertCanonicalInductionVariable(&clone_results); - InstructionBuilder builder(context_, - &*cloned_loop_->GetPreHeaderBlock()->tail(), - opt::IRContext::kAnalysisDefUse | - opt::IRContext::kAnalysisInstrToBlockMapping); - opt::Instruction* factor = + InstructionBuilder builder( + context_, &*cloned_loop_->GetPreHeaderBlock()->tail(), + IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping); + Instruction* factor = builder.Add32BitConstantInteger(peel_factor, int_type_->IsSigned()); - opt::Instruction* has_remaining_iteration = builder.AddLessThan( + Instruction* has_remaining_iteration = builder.AddLessThan( factor->result_id(), loop_iteration_count_->result_id()); // Change the exit condition of the cloned loop to be (exit when become // false): // "canonical_induction_variable_" + "factor" < "loop_iteration_count_" - FixExitCondition([factor, this](opt::Instruction* insert_before_point) { + FixExitCondition([factor, this](Instruction* insert_before_point) { InstructionBuilder cond_builder( context_, insert_before_point, - opt::IRContext::kAnalysisDefUse | - opt::IRContext::kAnalysisInstrToBlockMapping); + IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping); // Build the following check: canonical_induction_variable_ + factor < // iteration_count return cond_builder @@ -525,9 +517,8 @@ void LoopPeeling::PeelAfter(uint32_t peel_factor) { // Use the second loop preheader as if merge block. // Prevent the first loop if only the peeled loop needs it. - opt::BasicBlock* if_block = - ProtectLoop(cloned_loop_, has_remaining_iteration, - GetOriginalLoop()->GetPreHeaderBlock()); + BasicBlock* if_block = ProtectLoop(cloned_loop_, has_remaining_iteration, + GetOriginalLoop()->GetPreHeaderBlock()); // Patch the phi of the header block. // We added an if to enclose the first loop and because the phi node are @@ -536,25 +527,25 @@ void LoopPeeling::PeelAfter(uint32_t peel_factor) { // We had to the preheader (our if merge block) the required phi instruction // and patch the header phi. GetOriginalLoop()->GetHeaderBlock()->ForEachPhiInst( - [&clone_results, if_block, this](opt::Instruction* phi) { - opt::analysis::DefUseManager* def_use_mgr = context_->get_def_use_mgr(); + [&clone_results, if_block, this](Instruction* phi) { + analysis::DefUseManager* def_use_mgr = context_->get_def_use_mgr(); - auto find_value_idx = [](opt::Instruction* phi_inst, opt::Loop* loop) { + auto find_value_idx = [](Instruction* phi_inst, Loop* loop) { uint32_t preheader_value_idx = !loop->IsInsideLoop(phi_inst->GetSingleWordInOperand(1)) ? 0 : 2; return preheader_value_idx; }; - opt::Instruction* cloned_phi = + Instruction* cloned_phi = def_use_mgr->GetDef(clone_results.value_map_.at(phi->result_id())); uint32_t cloned_preheader_value = cloned_phi->GetSingleWordInOperand( find_value_idx(cloned_phi, GetClonedLoop())); - opt::Instruction* new_phi = + Instruction* new_phi = InstructionBuilder(context_, &*GetOriginalLoop()->GetPreHeaderBlock()->tail(), - opt::IRContext::kAnalysisDefUse | - opt::IRContext::kAnalysisInstrToBlockMapping) + IRContext::kAnalysisDefUse | + IRContext::kAnalysisInstrToBlockMapping) .AddPhi(phi->type_id(), {phi->GetSingleWordInOperand( find_value_idx(phi, GetOriginalLoop())), @@ -567,47 +558,45 @@ void LoopPeeling::PeelAfter(uint32_t peel_factor) { }); context_->InvalidateAnalysesExceptFor( - opt::IRContext::kAnalysisDefUse | - opt::IRContext::kAnalysisInstrToBlockMapping | - opt::IRContext::kAnalysisLoopAnalysis | opt::IRContext::kAnalysisCFG); + IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping | + IRContext::kAnalysisLoopAnalysis | IRContext::kAnalysisCFG); } Pass::Status LoopPeelingPass::Process() { bool modified = false; - opt::Module* module = context()->module(); + Module* module = context()->module(); // Process each function in the module - for (opt::Function& f : *module) { + for (Function& f : *module) { modified |= ProcessFunction(&f); } return modified ? Status::SuccessWithChange : Status::SuccessWithoutChange; } -bool LoopPeelingPass::ProcessFunction(opt::Function* f) { +bool LoopPeelingPass::ProcessFunction(Function* f) { bool modified = false; - opt::LoopDescriptor& loop_descriptor = *context()->GetLoopDescriptor(f); + LoopDescriptor& loop_descriptor = *context()->GetLoopDescriptor(f); - std::vector<opt::Loop*> to_process_loop; + std::vector<Loop*> to_process_loop; to_process_loop.reserve(loop_descriptor.NumLoops()); - for (opt::Loop& l : loop_descriptor) { + for (Loop& l : loop_descriptor) { to_process_loop.push_back(&l); } - opt::ScalarEvolutionAnalysis scev_analysis(context()); + ScalarEvolutionAnalysis scev_analysis(context()); - for (opt::Loop* loop : to_process_loop) { + for (Loop* loop : to_process_loop) { CodeMetrics loop_size; loop_size.Analyze(*loop); - auto try_peel = [&loop_size, &modified, - this](opt::Loop* loop_to_peel) -> opt::Loop* { + auto try_peel = [&loop_size, &modified, this](Loop* loop_to_peel) -> Loop* { if (!loop_to_peel->IsLCSSA()) { LoopUtils(context(), loop_to_peel).MakeLoopClosedSSA(); } bool peeled_loop; - opt::Loop* still_peelable_loop; + Loop* still_peelable_loop; std::tie(peeled_loop, still_peelable_loop) = ProcessLoop(loop_to_peel, &loop_size); @@ -618,7 +607,7 @@ bool LoopPeelingPass::ProcessFunction(opt::Function* f) { return still_peelable_loop; }; - opt::Loop* still_peelable_loop = try_peel(loop); + Loop* still_peelable_loop = try_peel(loop); // The pass is working out the maximum factor by which a loop can be peeled. // If the loop can potentially be peeled again, then there is only one // possible direction, so only one call is still needed. @@ -630,19 +619,19 @@ bool LoopPeelingPass::ProcessFunction(opt::Function* f) { return modified; } -std::pair<bool, opt::Loop*> LoopPeelingPass::ProcessLoop( - opt::Loop* loop, CodeMetrics* loop_size) { - opt::ScalarEvolutionAnalysis* scev_analysis = +std::pair<bool, Loop*> LoopPeelingPass::ProcessLoop(Loop* loop, + CodeMetrics* loop_size) { + ScalarEvolutionAnalysis* scev_analysis = context()->GetScalarEvolutionAnalysis(); // Default values for bailing out. - std::pair<bool, opt::Loop*> bail_out{false, nullptr}; + std::pair<bool, Loop*> bail_out{false, nullptr}; - opt::BasicBlock* exit_block = loop->FindConditionBlock(); + BasicBlock* exit_block = loop->FindConditionBlock(); if (!exit_block) { return bail_out; } - opt::Instruction* exiting_iv = loop->FindConditionVariable(exit_block); + Instruction* exiting_iv = loop->FindConditionVariable(exit_block); if (!exiting_iv) { return bail_out; } @@ -655,11 +644,11 @@ std::pair<bool, opt::Loop*> LoopPeelingPass::ProcessLoop( return bail_out; } - opt::Instruction* canonical_induction_variable = nullptr; + Instruction* canonical_induction_variable = nullptr; loop->GetHeaderBlock()->WhileEachPhiInst([&canonical_induction_variable, scev_analysis, - this](opt::Instruction* insn) { + this](Instruction* insn) { if (const SERecurrentNode* iv = scev_analysis->AnalyzeInstruction(insn)->AsSERecurrentNode()) { const SEConstantNode* offset = iv->GetOffset()->AsSEConstantNode(); @@ -685,9 +674,9 @@ std::pair<bool, opt::Loop*> LoopPeelingPass::ProcessLoop( LoopPeeling peeler( loop, - InstructionBuilder(context(), loop->GetHeaderBlock(), - opt::IRContext::kAnalysisDefUse | - opt::IRContext::kAnalysisInstrToBlockMapping) + InstructionBuilder( + context(), loop->GetHeaderBlock(), + IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping) .Add32BitConstantInteger<uint32_t>(static_cast<uint32_t>(iterations), is_signed), canonical_induction_variable); @@ -707,7 +696,7 @@ std::pair<bool, opt::Loop*> LoopPeelingPass::ProcessLoop( if (block == exit_block->id()) { continue; } - opt::BasicBlock* bb = cfg()->block(block); + BasicBlock* bb = cfg()->block(block); PeelDirection direction; uint32_t factor; std::tie(direction, factor) = peel_info.GetPeelingInfo(bb); @@ -749,7 +738,7 @@ std::pair<bool, opt::Loop*> LoopPeelingPass::ProcessLoop( loop_size->roi_size_ *= factor; // Find if a loop should be peeled again. - opt::Loop* extra_opportunity = nullptr; + Loop* extra_opportunity = nullptr; if (direction == PeelDirection::kBefore) { peeler.PeelBefore(factor); @@ -775,9 +764,9 @@ std::pair<bool, opt::Loop*> LoopPeelingPass::ProcessLoop( } uint32_t LoopPeelingPass::LoopPeelingInfo::GetFirstLoopInvariantOperand( - opt::Instruction* condition) const { + Instruction* condition) const { for (uint32_t i = 0; i < condition->NumInOperands(); i++) { - opt::BasicBlock* bb = + BasicBlock* bb = context_->get_instr_block(condition->GetSingleWordInOperand(i)); if (bb && loop_->IsInsideLoop(bb)) { return condition->GetSingleWordInOperand(i); @@ -788,9 +777,9 @@ uint32_t LoopPeelingPass::LoopPeelingInfo::GetFirstLoopInvariantOperand( } uint32_t LoopPeelingPass::LoopPeelingInfo::GetFirstNonLoopInvariantOperand( - opt::Instruction* condition) const { + Instruction* condition) const { for (uint32_t i = 0; i < condition->NumInOperands(); i++) { - opt::BasicBlock* bb = + BasicBlock* bb = context_->get_instr_block(condition->GetSingleWordInOperand(i)); if (!bb || !loop_->IsInsideLoop(bb)) { return condition->GetSingleWordInOperand(i); @@ -819,14 +808,14 @@ static bool IsHandledCondition(SpvOp opcode) { } LoopPeelingPass::LoopPeelingInfo::Direction -LoopPeelingPass::LoopPeelingInfo::GetPeelingInfo(opt::BasicBlock* bb) const { +LoopPeelingPass::LoopPeelingInfo::GetPeelingInfo(BasicBlock* bb) const { if (bb->terminator()->opcode() != SpvOpBranchConditional) { return GetNoneDirection(); } - opt::analysis::DefUseManager* def_use_mgr = context_->get_def_use_mgr(); + analysis::DefUseManager* def_use_mgr = context_->get_def_use_mgr(); - opt::Instruction* condition = + Instruction* condition = def_use_mgr->GetDef(bb->terminator()->GetSingleWordInOperand(0)); if (!IsHandledCondition(condition->opcode())) { diff --git a/source/opt/loop_peeling.h b/source/opt/loop_peeling.h index 20fe0417..08af223b 100644 --- a/source/opt/loop_peeling.h +++ b/source/opt/loop_peeling.h @@ -75,8 +75,8 @@ class LoopPeeling { // |loop_iteration_count| and start at 0 and increase by step of one at each // iteration. The value nullptr is interpreted as no suitable variable exists // and one will be created. - LoopPeeling(opt::Loop* loop, opt::Instruction* loop_iteration_count, - opt::Instruction* canonical_induction_variable = nullptr) + LoopPeeling(Loop* loop, Instruction* loop_iteration_count, + Instruction* canonical_induction_variable = nullptr) : context_(loop->GetContext()), loop_utils_(loop->GetContext(), loop), loop_(loop), @@ -115,7 +115,7 @@ class LoopPeeling { // This restriction will not apply if a loop rotate is applied before (i.e. // becomes a do-while loop). bool CanPeelLoop() const { - opt::CFG& cfg = *context_->cfg(); + CFG& cfg = *context_->cfg(); if (!loop_iteration_count_) { return false; @@ -140,7 +140,7 @@ class LoopPeeling { } return !std::any_of(exit_value_.cbegin(), exit_value_.cend(), - [](std::pair<uint32_t, opt::Instruction*> it) { + [](std::pair<uint32_t, Instruction*> it) { return it.second == nullptr; }); } @@ -154,31 +154,31 @@ class LoopPeeling { void PeelAfter(uint32_t factor); // Returns the cloned loop. - opt::Loop* GetClonedLoop() { return cloned_loop_; } + Loop* GetClonedLoop() { return cloned_loop_; } // Returns the original loop. - opt::Loop* GetOriginalLoop() { return loop_; } + Loop* GetOriginalLoop() { return loop_; } private: - opt::IRContext* context_; + IRContext* context_; LoopUtils loop_utils_; // The original loop. - opt::Loop* loop_; + Loop* loop_; // The initial |loop_| upper bound. - opt::Instruction* loop_iteration_count_; + Instruction* loop_iteration_count_; // The int type to use for the canonical_induction_variable_. analysis::Integer* int_type_; // The cloned loop. - opt::Loop* cloned_loop_; + Loop* cloned_loop_; // This is set to true when the exit and back-edge branch instruction is the // same. bool do_while_form_; // The canonical induction variable from the original loop if it exists. - opt::Instruction* original_loop_canonical_induction_variable_; + Instruction* original_loop_canonical_induction_variable_; // The canonical induction variable of the cloned loop. The induction variable // is initialized to 0 and incremented by step of 1. - opt::Instruction* canonical_induction_variable_; + Instruction* canonical_induction_variable_; // Map between loop iterators and exit values. Loop iterators - std::unordered_map<uint32_t, opt::Instruction*> exit_value_; + std::unordered_map<uint32_t, Instruction*> exit_value_; // Duplicate |loop_| and place the new loop before the cloned loop. Iterating // values from the cloned loop are then connected to the original loop as @@ -193,16 +193,16 @@ class LoopPeeling { // Fixes the exit condition of the before loop. The function calls // |condition_builder| to get the condition to use in the conditional branch // of the loop exit. The loop will be exited if the condition evaluate to - // true. |condition_builder| takes an opt::Instruction* that represent the + // true. |condition_builder| takes an Instruction* that represent the // insertion point. void FixExitCondition( - const std::function<uint32_t(opt::Instruction*)>& condition_builder); + const std::function<uint32_t(Instruction*)>& condition_builder); // Gathers all operations involved in the update of |iterator| into // |operations|. void GetIteratorUpdateOperations( - const opt::Loop* loop, opt::Instruction* iterator, - std::unordered_set<opt::Instruction*>* operations); + const Loop* loop, Instruction* iterator, + std::unordered_set<Instruction*>* operations); // Gathers exiting iterator values. The function builds a map between each // iterating value in the loop (a phi instruction in the loop header) and its @@ -216,14 +216,14 @@ class LoopPeeling { // Creates a new basic block and insert it between |bb| and the predecessor of // |bb|. - opt::BasicBlock* CreateBlockBefore(opt::BasicBlock* bb); + BasicBlock* CreateBlockBefore(BasicBlock* bb); // Inserts code to only execute |loop| only if the given |condition| is true. // |if_merge| is a suitable basic block to be used by the if condition as // merge block. // The function returns the if block protecting the loop. - opt::BasicBlock* ProtectLoop(opt::Loop* loop, opt::Instruction* condition, - opt::BasicBlock* if_merge); + BasicBlock* ProtectLoop(Loop* loop, Instruction* condition, + BasicBlock* if_merge); }; // Implements a loop peeling optimization. @@ -241,8 +241,7 @@ class LoopPeelingPass : public Pass { // Holds some statistics about peeled function. struct LoopPeelingStats { - std::vector<std::tuple<const opt::Loop*, PeelDirection, uint32_t>> - peeled_loops_; + std::vector<std::tuple<const Loop*, PeelDirection, uint32_t>> peeled_loops_; }; LoopPeelingPass(LoopPeelingStats* stats = nullptr) : stats_(stats) {} @@ -277,8 +276,8 @@ class LoopPeelingPass : public Pass { public: using Direction = std::pair<PeelDirection, uint32_t>; - LoopPeelingInfo(opt::Loop* loop, size_t loop_max_iterations, - opt::ScalarEvolutionAnalysis* scev_analysis) + LoopPeelingInfo(Loop* loop, size_t loop_max_iterations, + ScalarEvolutionAnalysis* scev_analysis) : context_(loop->GetContext()), loop_(loop), scev_analysis_(scev_analysis), @@ -288,15 +287,15 @@ class LoopPeelingPass : public Pass { // make the conditional branch of the basic block |bb| an unconditional // branch. If |bb|'s terminator is not a conditional branch or the condition // is not workable then it returns PeelDirection::kNone and a 0 factor. - Direction GetPeelingInfo(opt::BasicBlock* bb) const; + Direction GetPeelingInfo(BasicBlock* bb) const; private: // Returns the id of the loop invariant operand of the conditional // expression |condition|. It returns if no operand is invariant. - uint32_t GetFirstLoopInvariantOperand(opt::Instruction* condition) const; + uint32_t GetFirstLoopInvariantOperand(Instruction* condition) const; // Returns the id of the non loop invariant operand of the conditional // expression |condition|. It returns if all operands are invariant. - uint32_t GetFirstNonLoopInvariantOperand(opt::Instruction* condition) const; + uint32_t GetFirstNonLoopInvariantOperand(Instruction* condition) const; // Returns the value of |rec| at the first loop iteration. SExpression GetValueAtFirstIteration(SERecurrentNode* rec) const; @@ -316,16 +315,15 @@ class LoopPeelingPass : public Pass { static Direction GetNoneDirection() { return Direction{LoopPeelingPass::PeelDirection::kNone, 0}; } - opt::IRContext* context_; - opt::Loop* loop_; - opt::ScalarEvolutionAnalysis* scev_analysis_; + IRContext* context_; + Loop* loop_; + ScalarEvolutionAnalysis* scev_analysis_; size_t loop_max_iterations_; }; // Peel profitable loops in |f|. - bool ProcessFunction(opt::Function* f); + bool ProcessFunction(Function* f); // Peel |loop| if profitable. - std::pair<bool, opt::Loop*> ProcessLoop(opt::Loop* loop, - CodeMetrics* loop_size); + std::pair<bool, Loop*> ProcessLoop(Loop* loop, CodeMetrics* loop_size); static size_t code_grow_threshold_; LoopPeelingStats* stats_; diff --git a/source/opt/loop_unroller.cpp b/source/opt/loop_unroller.cpp index 3e171edb..16bde307 100644 --- a/source/opt/loop_unroller.cpp +++ b/source/opt/loop_unroller.cpp @@ -84,9 +84,8 @@ struct LoopUnrollState { new_header_block(nullptr) {} // Initialize from the loop descriptor class. - LoopUnrollState(opt::Instruction* induction, opt::BasicBlock* latch_block, - opt::BasicBlock* condition, - std::vector<opt::Instruction*>&& phis) + LoopUnrollState(Instruction* induction, BasicBlock* latch_block, + BasicBlock* condition, std::vector<Instruction*>&& phis) : previous_phi_(induction), previous_latch_block_(latch_block), previous_condition_block_(condition), @@ -118,53 +117,53 @@ struct LoopUnrollState { } // The induction variable from the immediately preceding loop body. - opt::Instruction* previous_phi_; + Instruction* previous_phi_; // All the phi nodes from the previous loop iteration. - std::vector<opt::Instruction*> previous_phis_; + std::vector<Instruction*> previous_phis_; - std::vector<opt::Instruction*> new_phis_; + std::vector<Instruction*> new_phis_; // The previous latch block. The backedge will be removed from this and // added to the new latch block. - opt::BasicBlock* previous_latch_block_; + BasicBlock* previous_latch_block_; // The previous condition block. This may be folded to flatten the loop. - opt::BasicBlock* previous_condition_block_; + BasicBlock* previous_condition_block_; // The new induction variable. - opt::Instruction* new_phi; + Instruction* new_phi; // The new continue block. - opt::BasicBlock* new_continue_block; + BasicBlock* new_continue_block; // The new condition block. - opt::BasicBlock* new_condition_block; + BasicBlock* new_condition_block; // The new header block. - opt::BasicBlock* new_header_block; + BasicBlock* new_header_block; // The new latch block. - opt::BasicBlock* new_latch_block; + BasicBlock* new_latch_block; // A mapping of new block ids to the original blocks which they were copied // from. - std::unordered_map<uint32_t, opt::BasicBlock*> new_blocks; + std::unordered_map<uint32_t, BasicBlock*> new_blocks; // A mapping of the original instruction ids to the instruction ids to their // copies. std::unordered_map<uint32_t, uint32_t> new_inst; - std::unordered_map<uint32_t, opt::Instruction*> ids_to_new_inst; + std::unordered_map<uint32_t, Instruction*> ids_to_new_inst; }; // This class implements the actual unrolling. It uses a LoopUnrollState to // maintain the state of the unrolling inbetween steps. class LoopUnrollerUtilsImpl { public: - using BasicBlockListTy = std::vector<std::unique_ptr<opt::BasicBlock>>; + using BasicBlockListTy = std::vector<std::unique_ptr<BasicBlock>>; - LoopUnrollerUtilsImpl(opt::IRContext* c, opt::Function* function) + LoopUnrollerUtilsImpl(IRContext* c, Function* function) : context_(c), function_(*function), loop_condition_block_(nullptr), @@ -175,7 +174,7 @@ class LoopUnrollerUtilsImpl { // Unroll the |loop| by given |factor| by copying the whole body |factor| // times. The resulting basicblock structure will remain a loop. - void PartiallyUnroll(opt::Loop*, size_t factor); + void PartiallyUnroll(Loop*, size_t factor); // If partially unrolling the |loop| would leave the loop with too many bodies // for its number of iterations then this method should be used. This method @@ -183,131 +182,131 @@ class LoopUnrollerUtilsImpl { // successor of the original's merge block. The original loop will have its // condition changed to loop over the residual part and the duplicate will be // partially unrolled. The resulting structure will be two loops. - void PartiallyUnrollResidualFactor(opt::Loop* loop, size_t factor); + void PartiallyUnrollResidualFactor(Loop* loop, size_t factor); // Fully unroll the |loop| by copying the full body by the total number of // loop iterations, folding all conditions, and removing the backedge from the // continue block to the header. - void FullyUnroll(opt::Loop* loop); + void FullyUnroll(Loop* loop); // Get the ID of the variable in the |phi| paired with |label|. - uint32_t GetPhiDefID(const opt::Instruction* phi, uint32_t label) const; + uint32_t GetPhiDefID(const Instruction* phi, uint32_t label) const; // Close the loop by removing the OpLoopMerge from the |loop| header block and // making the backedge point to the merge block. - void CloseUnrolledLoop(opt::Loop* loop); + void CloseUnrolledLoop(Loop* loop); // Remove the OpConditionalBranch instruction inside |conditional_block| used // to branch to either exit or continue the loop and replace it with an // unconditional OpBranch to block |new_target|. - void FoldConditionBlock(opt::BasicBlock* condtion_block, uint32_t new_target); + void FoldConditionBlock(BasicBlock* condtion_block, uint32_t new_target); // Add all blocks_to_add_ to function_ at the |insert_point|. - void AddBlocksToFunction(const opt::BasicBlock* insert_point); + void AddBlocksToFunction(const BasicBlock* insert_point); // Duplicates the |old_loop|, cloning each body and remaping the ids without // removing instructions or changing relative structure. Result will be stored // in |new_loop|. - void DuplicateLoop(opt::Loop* old_loop, opt::Loop* new_loop); + void DuplicateLoop(Loop* old_loop, Loop* new_loop); inline size_t GetLoopIterationCount() const { return number_of_loop_iterations_; } // Extracts the initial state information from the |loop|. - void Init(opt::Loop* loop); + void Init(Loop* loop); // Replace the uses of each induction variable outside the loop with the final // value of the induction variable before the loop exit. To reflect the proper // state of a fully unrolled loop. - void ReplaceInductionUseWithFinalValue(opt::Loop* loop); + void ReplaceInductionUseWithFinalValue(Loop* loop); // Remove all the instructions in the invalidated_instructions_ vector. void RemoveDeadInstructions(); // Replace any use of induction variables outwith the loop with the final // value of the induction variable in the unrolled loop. - void ReplaceOutsideLoopUseWithFinalValue(opt::Loop* loop); + void ReplaceOutsideLoopUseWithFinalValue(Loop* loop); // Set the LoopControl operand of the OpLoopMerge instruction to be // DontUnroll. - void MarkLoopControlAsDontUnroll(opt::Loop* loop) const; + void MarkLoopControlAsDontUnroll(Loop* loop) const; private: // Remap all the in |basic_block| to new IDs and keep the mapping of new ids // to old // ids. |loop| is used to identify special loop blocks (header, continue, // ect). - void AssignNewResultIds(opt::BasicBlock* basic_block); + void AssignNewResultIds(BasicBlock* basic_block); // Using the map built by AssignNewResultIds, for each instruction in // |basic_block| use // that map to substitute the IDs used by instructions (in the operands) with // the new ids. - void RemapOperands(opt::BasicBlock* basic_block); + void RemapOperands(BasicBlock* basic_block); // Copy the whole body of the loop, all blocks dominated by the |loop| header // and not dominated by the |loop| merge. The copied body will be linked to by // the old |loop| continue block and the new body will link to the |loop| // header via the new continue block. |eliminate_conditions| is used to decide // whether or not to fold all the condition blocks other than the last one. - void CopyBody(opt::Loop* loop, bool eliminate_conditions); + void CopyBody(Loop* loop, bool eliminate_conditions); // Copy a given |block_to_copy| in the |loop| and record the mapping of the // old/new ids. |preserve_instructions| determines whether or not the method // will modify (other than result_id) instructions which are copied. - void CopyBasicBlock(opt::Loop* loop, const opt::BasicBlock* block_to_copy, + void CopyBasicBlock(Loop* loop, const BasicBlock* block_to_copy, bool preserve_instructions); // The actual implementation of the unroll step. Unrolls |loop| by given // |factor| by copying the body by |factor| times. Also propagates the // induction variable value throughout the copies. - void Unroll(opt::Loop* loop, size_t factor); + void Unroll(Loop* loop, size_t factor); // Fills the loop_blocks_inorder_ field with the ordered list of basic blocks // as computed by the method ComputeLoopOrderedBlocks. - void ComputeLoopOrderedBlocks(opt::Loop* loop); + void ComputeLoopOrderedBlocks(Loop* loop); // Adds the blocks_to_add_ to both the |loop| and to the parent of |loop| if // the parent exists. - void AddBlocksToLoop(opt::Loop* loop) const; + void AddBlocksToLoop(Loop* loop) const; // After the partially unroll step the phi instructions in the header block // will be in an illegal format. This function makes the phis legal by making // the edge from the latch block come from the new latch block and the value // to be the actual value of the phi at that point. - void LinkLastPhisToStart(opt::Loop* loop) const; + void LinkLastPhisToStart(Loop* loop) const; // A pointer to the IRContext. Used to add/remove instructions and for usedef // chains. - opt::IRContext* context_; + IRContext* context_; // A reference the function the loop is within. - opt::Function& function_; + Function& function_; // A list of basic blocks to be added to the loop at the end of an unroll // step. BasicBlockListTy blocks_to_add_; // List of instructions which are now dead and can be removed. - std::vector<opt::Instruction*> invalidated_instructions_; + std::vector<Instruction*> invalidated_instructions_; // Maintains the current state of the transform between calls to unroll. LoopUnrollState state_; // An ordered list containing the loop basic blocks. - std::vector<opt::BasicBlock*> loop_blocks_inorder_; + std::vector<BasicBlock*> loop_blocks_inorder_; // The block containing the condition check which contains a conditional // branch to the merge and continue block. - opt::BasicBlock* loop_condition_block_; + BasicBlock* loop_condition_block_; // The induction variable of the loop. - opt::Instruction* loop_induction_variable_; + Instruction* loop_induction_variable_; // Phis used in the loop need to be remapped to use the actual result values // and then be remapped at the end. - std::vector<opt::Instruction*> loop_phi_instructions_; + std::vector<Instruction*> loop_phi_instructions_; // The number of loop iterations that the loop would preform pre-unroll. size_t number_of_loop_iterations_; @@ -325,8 +324,8 @@ class LoopUnrollerUtilsImpl { // Retrieve the index of the OpPhi instruction |phi| which corresponds to the // incoming |block| id. -static uint32_t GetPhiIndexFromLabel(const opt::BasicBlock* block, - const opt::Instruction* phi) { +static uint32_t GetPhiIndexFromLabel(const BasicBlock* block, + const Instruction* phi) { for (uint32_t i = 1; i < phi->NumInOperands(); i += 2) { if (block->id() == phi->GetSingleWordInOperand(i)) { return i; @@ -336,7 +335,7 @@ static uint32_t GetPhiIndexFromLabel(const opt::BasicBlock* block, return 0; } -void LoopUnrollerUtilsImpl::Init(opt::Loop* loop) { +void LoopUnrollerUtilsImpl::Init(Loop* loop) { loop_condition_block_ = loop->FindConditionBlock(); // When we reinit the second loop during PartiallyUnrollResidualFactor we need @@ -367,12 +366,11 @@ void LoopUnrollerUtilsImpl::Init(opt::Loop* loop) { // loop it creates two loops and unrolls one and adjusts the condition on the // other. The end result being that the new loop pair iterates over the correct // number of bodies. -void LoopUnrollerUtilsImpl::PartiallyUnrollResidualFactor(opt::Loop* loop, +void LoopUnrollerUtilsImpl::PartiallyUnrollResidualFactor(Loop* loop, size_t factor) { - std::unique_ptr<opt::Instruction> new_label{new opt::Instruction( + std::unique_ptr<Instruction> new_label{new Instruction( context_, SpvOp::SpvOpLabel, 0, context_->TakeNextId(), {})}; - std::unique_ptr<opt::BasicBlock> new_exit_bb{ - new opt::BasicBlock(std::move(new_label))}; + std::unique_ptr<BasicBlock> new_exit_bb{new BasicBlock(std::move(new_label))}; // Save the id of the block before we move it. uint32_t new_merge_id = new_exit_bb->id(); @@ -380,14 +378,13 @@ void LoopUnrollerUtilsImpl::PartiallyUnrollResidualFactor(opt::Loop* loop, // Add the block the list of blocks to add, we want this merge block to be // right at the start of the new blocks. blocks_to_add_.push_back(std::move(new_exit_bb)); - opt::BasicBlock* new_exit_bb_raw = blocks_to_add_[0].get(); - opt::Instruction& original_conditional_branch = - *loop_condition_block_->tail(); + BasicBlock* new_exit_bb_raw = blocks_to_add_[0].get(); + Instruction& original_conditional_branch = *loop_condition_block_->tail(); // Duplicate the loop, providing access to the blocks of both loops. // This is a naked new due to the VS2013 requirement of not having unique // pointers in vectors, as it will be inserted into a vector with // loop_descriptor.AddLoop. - opt::Loop* new_loop = new opt::Loop(*loop); + Loop* new_loop = new Loop(*loop); // Clear the basic blocks of the new loop. new_loop->ClearBlocks(); @@ -415,18 +412,18 @@ void LoopUnrollerUtilsImpl::PartiallyUnrollResidualFactor(opt::Loop* loop, // Add the new merge block to the back of the list of blocks to be added. It // needs to be the last block added to maintain dominator order in the binary. blocks_to_add_.push_back( - std::unique_ptr<opt::BasicBlock>(new_loop->GetMergeBlock())); + std::unique_ptr<BasicBlock>(new_loop->GetMergeBlock())); // Add the blocks to the function. AddBlocksToFunction(loop->GetMergeBlock()); // Reset the usedef analysis. context_->InvalidateAnalysesExceptFor( - opt::IRContext::Analysis::kAnalysisLoopAnalysis); - opt::analysis::DefUseManager* def_use_manager = context_->get_def_use_mgr(); + IRContext::Analysis::kAnalysisLoopAnalysis); + analysis::DefUseManager* def_use_manager = context_->get_def_use_mgr(); // The loop condition. - opt::Instruction* condition_check = def_use_manager->GetDef( + Instruction* condition_check = def_use_manager->GetDef( original_conditional_branch.GetSingleWordOperand(0)); // This should have been checked by the LoopUtils::CanPerformUnroll function @@ -434,14 +431,14 @@ void LoopUnrollerUtilsImpl::PartiallyUnrollResidualFactor(opt::Loop* loop, assert(loop->IsSupportedCondition(condition_check->opcode())); // We need to account for the initial body when calculating the remainder. - int64_t remainder = opt::Loop::GetResidualConditionValue( + int64_t remainder = Loop::GetResidualConditionValue( condition_check->opcode(), loop_init_value_, loop_step_value_, number_of_loop_iterations_, factor); assert(remainder > std::numeric_limits<int32_t>::min() && remainder < std::numeric_limits<int32_t>::max()); - opt::Instruction* new_constant = nullptr; + Instruction* new_constant = nullptr; // If the remainder is negative then we add a signed constant, otherwise just // add an unsigned constant. @@ -462,14 +459,14 @@ void LoopUnrollerUtilsImpl::PartiallyUnrollResidualFactor(opt::Loop* loop, // the preheader block. For the duplicated loop we need to update the constant // to be the amount of iterations covered by the first loop and the incoming // block to be the first loops new merge block. - std::vector<opt::Instruction*> new_inductions; + std::vector<Instruction*> new_inductions; new_loop->GetInductionVariables(new_inductions); - std::vector<opt::Instruction*> old_inductions; + std::vector<Instruction*> old_inductions; loop->GetInductionVariables(old_inductions); for (size_t index = 0; index < new_inductions.size(); ++index) { - opt::Instruction* new_induction = new_inductions[index]; - opt::Instruction* old_induction = old_inductions[index]; + Instruction* new_induction = new_inductions[index]; + Instruction* old_induction = old_inductions[index]; // Get the index of the loop initalizer, the value coming in from the // preheader. uint32_t initalizer_index = @@ -484,7 +481,7 @@ void LoopUnrollerUtilsImpl::PartiallyUnrollResidualFactor(opt::Loop* loop, // then replace that use with the second loop induction variable. uint32_t second_loop_induction = new_induction->result_id(); auto replace_use_outside_of_loop = [loop, second_loop_induction]( - opt::Instruction* user, + Instruction* user, uint32_t operand_index) { if (!loop->IsInsideLoop(user)) { user->SetOperand(operand_index, {second_loop_induction}); @@ -496,12 +493,11 @@ void LoopUnrollerUtilsImpl::PartiallyUnrollResidualFactor(opt::Loop* loop, } context_->InvalidateAnalysesExceptFor( - opt::IRContext::Analysis::kAnalysisLoopAnalysis); + IRContext::Analysis::kAnalysisLoopAnalysis); context_->ReplaceAllUsesWith(loop->GetMergeBlock()->id(), new_merge_id); - opt::LoopDescriptor& loop_descriptor = - *context_->GetLoopDescriptor(&function_); + LoopDescriptor& loop_descriptor = *context_->GetLoopDescriptor(&function_); loop_descriptor.AddLoop(new_loop, loop->GetParent()); @@ -510,9 +506,8 @@ void LoopUnrollerUtilsImpl::PartiallyUnrollResidualFactor(opt::Loop* loop, // Mark this loop as DontUnroll as it will already be unrolled and it may not // be safe to unroll a previously partially unrolled loop. -void LoopUnrollerUtilsImpl::MarkLoopControlAsDontUnroll(opt::Loop* loop) const { - opt::Instruction* loop_merge_inst = - loop->GetHeaderBlock()->GetLoopMergeInst(); +void LoopUnrollerUtilsImpl::MarkLoopControlAsDontUnroll(Loop* loop) const { + Instruction* loop_merge_inst = loop->GetHeaderBlock()->GetLoopMergeInst(); assert(loop_merge_inst && "Loop merge instruction could not be found after entering unroller " "(should have exited before this)"); @@ -523,13 +518,13 @@ void LoopUnrollerUtilsImpl::MarkLoopControlAsDontUnroll(opt::Loop* loop) const { // Duplicate the |loop| body |factor| - 1 number of times while keeping the loop // backedge intact. This will leave the loop with |factor| number of bodies // after accounting for the initial body. -void LoopUnrollerUtilsImpl::Unroll(opt::Loop* loop, size_t factor) { +void LoopUnrollerUtilsImpl::Unroll(Loop* loop, size_t factor) { // If we unroll a loop partially it will not be safe to unroll it further. // This is due to the current method of calculating the number of loop // iterations. MarkLoopControlAsDontUnroll(loop); - std::vector<opt::Instruction*> inductions; + std::vector<Instruction*> inductions; loop->GetInductionVariables(inductions); state_ = LoopUnrollState{loop_induction_variable_, loop->GetLatchBlock(), loop_condition_block_, std::move(inductions)}; @@ -540,15 +535,15 @@ void LoopUnrollerUtilsImpl::Unroll(opt::Loop* loop, size_t factor) { void LoopUnrollerUtilsImpl::RemoveDeadInstructions() { // Remove the dead instructions. - for (opt::Instruction* inst : invalidated_instructions_) { + for (Instruction* inst : invalidated_instructions_) { context_->KillInst(inst); } } -void LoopUnrollerUtilsImpl::ReplaceInductionUseWithFinalValue(opt::Loop* loop) { +void LoopUnrollerUtilsImpl::ReplaceInductionUseWithFinalValue(Loop* loop) { context_->InvalidateAnalysesExceptFor( - opt::IRContext::Analysis::kAnalysisLoopAnalysis); - std::vector<opt::Instruction*> inductions; + IRContext::Analysis::kAnalysisLoopAnalysis); + std::vector<Instruction*> inductions; loop->GetInductionVariables(inductions); for (size_t index = 0; index < inductions.size(); ++index) { @@ -561,7 +556,7 @@ void LoopUnrollerUtilsImpl::ReplaceInductionUseWithFinalValue(opt::Loop* loop) { // Fully unroll the loop by partially unrolling it by the number of loop // iterations minus one for the body already accounted for. -void LoopUnrollerUtilsImpl::FullyUnroll(opt::Loop* loop) { +void LoopUnrollerUtilsImpl::FullyUnroll(Loop* loop) { // We unroll the loop by number of iterations in the loop. Unroll(loop, number_of_loop_iterations_); @@ -588,18 +583,17 @@ void LoopUnrollerUtilsImpl::FullyUnroll(opt::Loop* loop) { RemoveDeadInstructions(); // Invalidate all analyses. context_->InvalidateAnalysesExceptFor( - opt::IRContext::Analysis::kAnalysisLoopAnalysis); + IRContext::Analysis::kAnalysisLoopAnalysis); } // Copy a given basic block, give it a new result_id, and store the new block // and the id mapping in the state. |preserve_instructions| is used to determine // whether or not this function should edit instructions other than the // |result_id|. -void LoopUnrollerUtilsImpl::CopyBasicBlock(opt::Loop* loop, - const opt::BasicBlock* itr, +void LoopUnrollerUtilsImpl::CopyBasicBlock(Loop* loop, const BasicBlock* itr, bool preserve_instructions) { // Clone the block exactly, including the IDs. - opt::BasicBlock* basic_block = itr->Clone(context_); + BasicBlock* basic_block = itr->Clone(context_); basic_block->SetParent(itr->GetParent()); // Assign each result a new unique ID and keep a mapping of the old ids to @@ -610,7 +604,7 @@ void LoopUnrollerUtilsImpl::CopyBasicBlock(opt::Loop* loop, if (itr == loop->GetContinueBlock()) { // Make the OpLoopMerge point to this block for the continue. if (!preserve_instructions) { - opt::Instruction* merge_inst = loop->GetHeaderBlock()->GetLoopMergeInst(); + Instruction* merge_inst = loop->GetHeaderBlock()->GetLoopMergeInst(); merge_inst->SetInOperand(1, {basic_block->id()}); } @@ -623,7 +617,7 @@ void LoopUnrollerUtilsImpl::CopyBasicBlock(opt::Loop* loop, if (!preserve_instructions) { // Remove the loop merge instruction if it exists. - opt::Instruction* merge_inst = basic_block->GetLoopMergeInst(); + Instruction* merge_inst = basic_block->GetLoopMergeInst(); if (merge_inst) invalidated_instructions_.push_back(merge_inst); } } @@ -638,38 +632,37 @@ void LoopUnrollerUtilsImpl::CopyBasicBlock(opt::Loop* loop, // Add this block to the list of blocks to add to the function at the end of // the unrolling process. - blocks_to_add_.push_back(std::unique_ptr<opt::BasicBlock>(basic_block)); + blocks_to_add_.push_back(std::unique_ptr<BasicBlock>(basic_block)); // Keep tracking the old block via a map. state_.new_blocks[itr->id()] = basic_block; } -void LoopUnrollerUtilsImpl::CopyBody(opt::Loop* loop, - bool eliminate_conditions) { +void LoopUnrollerUtilsImpl::CopyBody(Loop* loop, bool eliminate_conditions) { // Copy each basic block in the loop, give them new ids, and save state // information. - for (const opt::BasicBlock* itr : loop_blocks_inorder_) { + for (const BasicBlock* itr : loop_blocks_inorder_) { CopyBasicBlock(loop, itr, false); } // Set the previous latch block to point to the new header. - opt::Instruction& latch_branch = *state_.previous_latch_block_->tail(); + Instruction& latch_branch = *state_.previous_latch_block_->tail(); latch_branch.SetInOperand(0, {state_.new_header_block->id()}); // As the algorithm copies the original loop blocks exactly, the tail of the // latch block on iterations after the first one will be a branch to the new // header and not the actual loop header. The last continue block in the loop // should always be a backedge to the global header. - opt::Instruction& new_latch_branch = *state_.new_latch_block->tail(); + Instruction& new_latch_branch = *state_.new_latch_block->tail(); new_latch_branch.SetInOperand(0, {loop->GetHeaderBlock()->id()}); - std::vector<opt::Instruction*> inductions; + std::vector<Instruction*> inductions; loop->GetInductionVariables(inductions); for (size_t index = 0; index < inductions.size(); ++index) { - opt::Instruction* master_copy = inductions[index]; + Instruction* master_copy = inductions[index]; assert(master_copy->result_id() != 0); - opt::Instruction* induction_clone = + Instruction* induction_clone = state_.ids_to_new_inst[state_.new_inst[master_copy->result_id()]]; state_.new_phis_.push_back(induction_clone); @@ -697,14 +690,14 @@ void LoopUnrollerUtilsImpl::CopyBody(opt::Loop* loop, RemapOperands(pair.second); } - for (opt::Instruction* dead_phi : state_.new_phis_) + for (Instruction* dead_phi : state_.new_phis_) invalidated_instructions_.push_back(dead_phi); // Swap the state so the new is now the previous. state_.NextIterationState(); } -uint32_t LoopUnrollerUtilsImpl::GetPhiDefID(const opt::Instruction* phi, +uint32_t LoopUnrollerUtilsImpl::GetPhiDefID(const Instruction* phi, uint32_t label) const { for (uint32_t operand = 3; operand < phi->NumOperands(); operand += 2) { if (phi->GetSingleWordOperand(operand) == label) { @@ -715,10 +708,10 @@ uint32_t LoopUnrollerUtilsImpl::GetPhiDefID(const opt::Instruction* phi, return 0; } -void LoopUnrollerUtilsImpl::FoldConditionBlock(opt::BasicBlock* condition_block, +void LoopUnrollerUtilsImpl::FoldConditionBlock(BasicBlock* condition_block, uint32_t operand_label) { // Remove the old conditional branch to the merge and continue blocks. - opt::Instruction& old_branch = *condition_block->tail(); + Instruction& old_branch = *condition_block->tail(); uint32_t new_target = old_branch.GetSingleWordOperand(operand_label); context_->KillInst(&old_branch); @@ -727,9 +720,9 @@ void LoopUnrollerUtilsImpl::FoldConditionBlock(opt::BasicBlock* condition_block, builder.AddBranch(new_target); } -void LoopUnrollerUtilsImpl::CloseUnrolledLoop(opt::Loop* loop) { +void LoopUnrollerUtilsImpl::CloseUnrolledLoop(Loop* loop) { // Remove the OpLoopMerge instruction from the function. - opt::Instruction* merge_inst = loop->GetHeaderBlock()->GetLoopMergeInst(); + Instruction* merge_inst = loop->GetHeaderBlock()->GetLoopMergeInst(); invalidated_instructions_.push_back(merge_inst); // Remove the final backedge to the header and make it point instead to the @@ -740,7 +733,7 @@ void LoopUnrollerUtilsImpl::CloseUnrolledLoop(opt::Loop* loop) { // Remove all induction variables as the phis will now be invalid. Replace all // uses with the constant initializer value (all uses of phis will be in // the first iteration with the subsequent phis already having been removed). - std::vector<opt::Instruction*> inductions; + std::vector<Instruction*> inductions; loop->GetInductionVariables(inductions); // We can use the state instruction mechanism to replace all internal loop @@ -749,31 +742,30 @@ void LoopUnrollerUtilsImpl::CloseUnrolledLoop(opt::Loop* loop) { // use context ReplaceAllUsesWith for the uses outside the loop with the final // trip phi value. state_.new_inst.clear(); - for (opt::Instruction* induction : inductions) { + for (Instruction* induction : inductions) { uint32_t initalizer_id = GetPhiDefID(induction, loop->GetPreHeaderBlock()->id()); state_.new_inst[induction->result_id()] = initalizer_id; } - for (opt::BasicBlock* block : loop_blocks_inorder_) { + for (BasicBlock* block : loop_blocks_inorder_) { RemapOperands(block); } } // Uses the first loop to create a copy of the loop with new IDs. -void LoopUnrollerUtilsImpl::DuplicateLoop(opt::Loop* old_loop, - opt::Loop* new_loop) { - std::vector<opt::BasicBlock*> new_block_order; +void LoopUnrollerUtilsImpl::DuplicateLoop(Loop* old_loop, Loop* new_loop) { + std::vector<BasicBlock*> new_block_order; // Copy every block in the old loop. - for (const opt::BasicBlock* itr : loop_blocks_inorder_) { + for (const BasicBlock* itr : loop_blocks_inorder_) { CopyBasicBlock(old_loop, itr, true); new_block_order.push_back(blocks_to_add_.back().get()); } // Clone the merge block, give it a new id and record it in the state. - opt::BasicBlock* new_merge = old_loop->GetMergeBlock()->Clone(context_); + BasicBlock* new_merge = old_loop->GetMergeBlock()->Clone(context_); new_merge->SetParent(old_loop->GetMergeBlock()->GetParent()); AssignNewResultIds(new_merge); state_.new_blocks[old_loop->GetMergeBlock()->id()] = new_merge; @@ -795,10 +787,10 @@ void LoopUnrollerUtilsImpl::DuplicateLoop(opt::Loop* old_loop, } // Whenever the utility copies a block it stores it in a tempory buffer, this -// function adds the buffer into the opt::Function. The blocks will be inserted +// function adds the buffer into the Function. The blocks will be inserted // after the block |insert_point|. void LoopUnrollerUtilsImpl::AddBlocksToFunction( - const opt::BasicBlock* insert_point) { + const BasicBlock* insert_point) { for (auto basic_block_iterator = function_.begin(); basic_block_iterator != function_.end(); ++basic_block_iterator) { if (basic_block_iterator->id() == insert_point->id()) { @@ -814,7 +806,7 @@ void LoopUnrollerUtilsImpl::AddBlocksToFunction( // Assign all result_ids in |basic_block| instructions to new IDs and preserve // the mapping of new ids to old ones. -void LoopUnrollerUtilsImpl::AssignNewResultIds(opt::BasicBlock* basic_block) { +void LoopUnrollerUtilsImpl::AssignNewResultIds(BasicBlock* basic_block) { // Label instructions aren't covered by normal traversal of the // instructions. uint32_t new_label_id = context_->TakeNextId(); @@ -823,7 +815,7 @@ void LoopUnrollerUtilsImpl::AssignNewResultIds(opt::BasicBlock* basic_block) { state_.new_inst[basic_block->GetLabelInst()->result_id()] = new_label_id; basic_block->GetLabelInst()->SetResultId(new_label_id); - for (opt::Instruction& inst : *basic_block) { + for (Instruction& inst : *basic_block) { uint32_t old_id = inst.result_id(); // Ignore stores etc. @@ -847,8 +839,8 @@ void LoopUnrollerUtilsImpl::AssignNewResultIds(opt::BasicBlock* basic_block) { // For all instructions in |basic_block| check if the operands used are from a // copied instruction and if so swap out the operand for the copy of it. -void LoopUnrollerUtilsImpl::RemapOperands(opt::BasicBlock* basic_block) { - for (opt::Instruction& inst : *basic_block) { +void LoopUnrollerUtilsImpl::RemapOperands(BasicBlock* basic_block) { + for (Instruction& inst : *basic_block) { auto remap_operands_to_new_ids = [this](uint32_t* id) { auto itr = state_.new_inst.find(*id); @@ -863,13 +855,13 @@ void LoopUnrollerUtilsImpl::RemapOperands(opt::BasicBlock* basic_block) { // Generate the ordered list of basic blocks in the |loop| and cache it for // later use. -void LoopUnrollerUtilsImpl::ComputeLoopOrderedBlocks(opt::Loop* loop) { +void LoopUnrollerUtilsImpl::ComputeLoopOrderedBlocks(Loop* loop) { loop_blocks_inorder_.clear(); loop->ComputeLoopStructuredOrder(&loop_blocks_inorder_); } // Adds the blocks_to_add_ to both the loop and to the parent. -void LoopUnrollerUtilsImpl::AddBlocksToLoop(opt::Loop* loop) const { +void LoopUnrollerUtilsImpl::AddBlocksToLoop(Loop* loop) const { // Add the blocks to this loop. for (auto& block_itr : blocks_to_add_) { loop->AddBasicBlock(block_itr.get()); @@ -879,12 +871,12 @@ void LoopUnrollerUtilsImpl::AddBlocksToLoop(opt::Loop* loop) const { if (loop->GetParent()) AddBlocksToLoop(loop->GetParent()); } -void LoopUnrollerUtilsImpl::LinkLastPhisToStart(opt::Loop* loop) const { - std::vector<opt::Instruction*> inductions; +void LoopUnrollerUtilsImpl::LinkLastPhisToStart(Loop* loop) const { + std::vector<Instruction*> inductions; loop->GetInductionVariables(inductions); for (size_t i = 0; i < inductions.size(); ++i) { - opt::Instruction* last_phi_in_block = state_.previous_phis_[i]; + Instruction* last_phi_in_block = state_.previous_phis_[i]; uint32_t phi_index = GetPhiIndexFromLabel(state_.previous_latch_block_, last_phi_in_block); @@ -892,7 +884,7 @@ void LoopUnrollerUtilsImpl::LinkLastPhisToStart(opt::Loop* loop) const { last_phi_in_block->GetSingleWordInOperand(phi_index - 1); uint32_t phi_label = last_phi_in_block->GetSingleWordInOperand(phi_index); - opt::Instruction* phi = inductions[i]; + Instruction* phi = inductions[i]; phi->SetInOperand(phi_index - 1, {phi_variable}); phi->SetInOperand(phi_index, {phi_label}); } @@ -900,7 +892,7 @@ void LoopUnrollerUtilsImpl::LinkLastPhisToStart(opt::Loop* loop) const { // Duplicate the |loop| body |factor| number of times while keeping the loop // backedge intact. -void LoopUnrollerUtilsImpl::PartiallyUnroll(opt::Loop* loop, size_t factor) { +void LoopUnrollerUtilsImpl::PartiallyUnroll(Loop* loop, size_t factor) { Unroll(loop, factor); LinkLastPhisToStart(loop); AddBlocksToLoop(loop); @@ -927,11 +919,11 @@ bool LoopUtils::CanPerformUnroll() { } // Find check the loop has a condition we can find and evaluate. - const opt::BasicBlock* condition = loop_->FindConditionBlock(); + const BasicBlock* condition = loop_->FindConditionBlock(); if (!condition) return false; // Check that we can find and process the induction variable. - const opt::Instruction* induction = loop_->FindConditionVariable(condition); + const Instruction* induction = loop_->FindConditionVariable(condition); if (!induction || induction->opcode() != SpvOpPhi) return false; // Check that we can find the number of loop iterations. @@ -940,7 +932,7 @@ bool LoopUtils::CanPerformUnroll() { // Make sure the latch block is a unconditional branch to the header // block. - const opt::Instruction& branch = *loop_->GetLatchBlock()->ctail(); + const Instruction& branch = *loop_->GetLatchBlock()->ctail(); bool branching_assumption = branch.opcode() == SpvOpBranch && branch.GetSingleWordInOperand(0) == loop_->GetHeaderBlock()->id(); @@ -948,7 +940,7 @@ bool LoopUtils::CanPerformUnroll() { return false; } - std::vector<opt::Instruction*> inductions; + std::vector<Instruction*> inductions; loop_->GetInductionVariables(inductions); // Ban breaks within the loop. @@ -969,7 +961,7 @@ bool LoopUtils::CanPerformUnroll() { // Iterate over all the blocks within the loop and check that none of them // exit the loop. for (uint32_t label_id : loop_->GetBlocks()) { - const opt::BasicBlock* block = context_->cfg()->block(label_id); + const BasicBlock* block = context_->cfg()->block(label_id); if (block->ctail()->opcode() == SpvOp::SpvOpKill || block->ctail()->opcode() == SpvOp::SpvOpReturn || block->ctail()->opcode() == SpvOp::SpvOpReturnValue) { @@ -1015,7 +1007,7 @@ bool LoopUtils::PartiallyUnroll(size_t factor) { bool LoopUtils::FullyUnroll() { if (!CanPerformUnroll()) return false; - std::vector<opt::Instruction*> inductions; + std::vector<Instruction*> inductions; loop_->GetInductionVariables(inductions); LoopUnrollerUtilsImpl unroller{context_, @@ -1030,7 +1022,7 @@ bool LoopUtils::FullyUnroll() { void LoopUtils::Finalize() { // Clean up the loop descriptor to preserve the analysis. - opt::LoopDescriptor* LD = context_->GetLoopDescriptor(&function_); + LoopDescriptor* LD = context_->GetLoopDescriptor(&function_); LD->PostModificationCleanup(); } @@ -1042,9 +1034,9 @@ void LoopUtils::Finalize() { Pass::Status LoopUnroller::Process() { bool changed = false; - for (opt::Function& f : *context()->module()) { - opt::LoopDescriptor* LD = context()->GetLoopDescriptor(&f); - for (opt::Loop& loop : *LD) { + for (Function& f : *context()->module()) { + LoopDescriptor* LD = context()->GetLoopDescriptor(&f); + for (Loop& loop : *LD) { LoopUtils loop_utils{context(), &loop}; if (!loop.HasUnrollLoopControl() || !loop_utils.CanPerformUnroll()) { continue; diff --git a/source/opt/loop_unswitch_pass.cpp b/source/opt/loop_unswitch_pass.cpp index 12f82a8e..b9eb61bc 100644 --- a/source/opt/loop_unswitch_pass.cpp +++ b/source/opt/loop_unswitch_pass.cpp @@ -52,8 +52,8 @@ namespace { // - The loop invariant condition is not uniform. class LoopUnswitch { public: - LoopUnswitch(opt::IRContext* context, opt::Function* function, - opt::Loop* loop, opt::LoopDescriptor* loop_desc) + LoopUnswitch(IRContext* context, Function* function, Loop* loop, + LoopDescriptor* loop_desc) : function_(function), loop_(loop), loop_desc_(*loop_desc), @@ -70,10 +70,10 @@ class LoopUnswitch { if (switch_block_) return true; if (loop_->IsSafeToClone()) return false; - opt::CFG& cfg = *context_->cfg(); + CFG& cfg = *context_->cfg(); for (uint32_t bb_id : loop_->GetBlocks()) { - opt::BasicBlock* bb = cfg.block(bb_id); + BasicBlock* bb = cfg.block(bb_id); if (bb->terminator()->IsBranch() && bb->terminator()->opcode() != SpvOpBranch) { if (IsConditionLoopInvariant(bb->terminator())) { @@ -87,8 +87,8 @@ class LoopUnswitch { } // Return the iterator to the basic block |bb|. - opt::Function::iterator FindBasicBlockPosition(opt::BasicBlock* bb_to_find) { - opt::Function::iterator it = function_->FindBlock(bb_to_find->id()); + Function::iterator FindBasicBlockPosition(BasicBlock* bb_to_find) { + Function::iterator it = function_->FindBlock(bb_to_find->id()); assert(it != function_->end() && "Basic Block not found"); return it; } @@ -96,13 +96,12 @@ class LoopUnswitch { // Creates a new basic block and insert it into the function |fn| at the // position |ip|. This function preserves the def/use and instr to block // managers. - opt::BasicBlock* CreateBasicBlock(opt::Function::iterator ip) { + BasicBlock* CreateBasicBlock(Function::iterator ip) { analysis::DefUseManager* def_use_mgr = context_->get_def_use_mgr(); - opt::BasicBlock* bb = - &*ip.InsertBefore(std::unique_ptr<opt::BasicBlock>(new opt::BasicBlock( - std::unique_ptr<opt::Instruction>(new opt::Instruction( - context_, SpvOpLabel, 0, context_->TakeNextId(), {}))))); + BasicBlock* bb = &*ip.InsertBefore(std::unique_ptr<BasicBlock>( + new BasicBlock(std::unique_ptr<Instruction>(new Instruction( + context_, SpvOpLabel, 0, context_->TakeNextId(), {}))))); bb->SetParent(function_); def_use_mgr->AnalyzeInstDef(bb->GetLabelInst()); context_->set_instr_block(bb->GetLabelInst(), bb); @@ -117,7 +116,7 @@ class LoopUnswitch { assert(loop_->GetPreHeaderBlock() && "This loop has no pre-header block"); assert(loop_->IsLCSSA() && "This loop is not in LCSSA form"); - opt::CFG& cfg = *context_->cfg(); + CFG& cfg = *context_->cfg(); DominatorTree* dom_tree = &context_->GetDominatorAnalysis(function_)->GetDomTree(); analysis::DefUseManager* def_use_mgr = context_->get_def_use_mgr(); @@ -133,29 +132,28 @@ class LoopUnswitch { ////////////////////////////////////////////////////////////////////////////// // Get the merge block if it exists. - opt::BasicBlock* if_merge_block = loop_->GetMergeBlock(); + BasicBlock* if_merge_block = loop_->GetMergeBlock(); // The merge block is only created if the loop has a unique exit block. We // have this guarantee for structured loops, for compute loop it will // trivially help maintain both a structured-like form and LCSAA. - opt::BasicBlock* loop_merge_block = + BasicBlock* loop_merge_block = if_merge_block ? CreateBasicBlock(FindBasicBlockPosition(if_merge_block)) : nullptr; if (loop_merge_block) { // Add the instruction and update managers. - opt::InstructionBuilder builder( + InstructionBuilder builder( context_, loop_merge_block, - opt::IRContext::kAnalysisDefUse | - opt::IRContext::kAnalysisInstrToBlockMapping); + IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping); builder.AddBranch(if_merge_block->id()); builder.SetInsertPoint(&*loop_merge_block->begin()); cfg.RegisterBlock(loop_merge_block); def_use_mgr->AnalyzeInstDef(loop_merge_block->GetLabelInst()); // Update CFG. if_merge_block->ForEachPhiInst( - [loop_merge_block, &builder, this](opt::Instruction* phi) { - opt::Instruction* cloned = phi->Clone(context_); - builder.AddInstruction(std::unique_ptr<opt::Instruction>(cloned)); + [loop_merge_block, &builder, this](Instruction* phi) { + Instruction* cloned = phi->Clone(context_); + builder.AddInstruction(std::unique_ptr<Instruction>(cloned)); phi->SetInOperand(0, {cloned->result_id()}); phi->SetInOperand(1, {loop_merge_block->id()}); for (uint32_t j = phi->NumInOperands() - 1; j > 1; j--) @@ -165,7 +163,7 @@ class LoopUnswitch { std::vector<uint32_t> preds = cfg.preds(if_merge_block->id()); for (uint32_t pid : preds) { if (pid == loop_merge_block->id()) continue; - opt::BasicBlock* p_bb = cfg.block(pid); + BasicBlock* p_bb = cfg.block(pid); p_bb->ForEachSuccessorLabel( [if_merge_block, loop_merge_block](uint32_t* id) { if (*id == if_merge_block->id()) *id = loop_merge_block->id(); @@ -174,7 +172,7 @@ class LoopUnswitch { } cfg.RemoveNonExistingEdges(if_merge_block->id()); // Update loop descriptor. - if (opt::Loop* ploop = loop_->GetParent()) { + if (Loop* ploop = loop_->GetParent()) { ploop->AddBasicBlock(loop_merge_block); loop_desc_.SetBasicBlockToLoop(loop_merge_block->id(), ploop); } @@ -199,20 +197,20 @@ class LoopUnswitch { // for the constant branch. //////////////////////////////////////////////////////////////////////////// - opt::BasicBlock* if_block = loop_->GetPreHeaderBlock(); + BasicBlock* if_block = loop_->GetPreHeaderBlock(); // If this preheader is the parent loop header, // we need to create a dedicated block for the if. - opt::BasicBlock* loop_pre_header = + BasicBlock* loop_pre_header = CreateBasicBlock(++FindBasicBlockPosition(if_block)); - opt::InstructionBuilder(context_, loop_pre_header, - opt::IRContext::kAnalysisDefUse | - opt::IRContext::kAnalysisInstrToBlockMapping) + InstructionBuilder( + context_, loop_pre_header, + IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping) .AddBranch(loop_->GetHeaderBlock()->id()); if_block->tail()->SetInOperand(0, {loop_pre_header->id()}); // Update loop descriptor. - if (opt::Loop* ploop = loop_desc_[if_block]) { + if (Loop* ploop = loop_desc_[if_block]) { ploop->AddBasicBlock(loop_pre_header); loop_desc_.SetBasicBlockToLoop(loop_pre_header->id(), ploop); } @@ -224,7 +222,7 @@ class LoopUnswitch { cfg.RemoveNonExistingEdges(loop_->GetHeaderBlock()->id()); loop_->GetHeaderBlock()->ForEachPhiInst( - [loop_pre_header, if_block](opt::Instruction* phi) { + [loop_pre_header, if_block](Instruction* phi) { phi->ForEachInId([loop_pre_header, if_block](uint32_t* id) { if (*id == if_block->id()) { *id = loop_pre_header->id(); @@ -260,9 +258,9 @@ class LoopUnswitch { // - Specialize the loop // ///////////////////////////// - opt::Instruction* iv_condition = &*switch_block_->tail(); + Instruction* iv_condition = &*switch_block_->tail(); SpvOp iv_opcode = iv_condition->opcode(); - opt::Instruction* condition = + Instruction* condition = def_use_mgr->GetDef(iv_condition->GetOperand(0).words[0]); analysis::ConstantManager* cst_mgr = context_->get_constant_mgr(); @@ -271,10 +269,10 @@ class LoopUnswitch { // Build the list of value for which we need to clone and specialize the // loop. - std::vector<std::pair<opt::Instruction*, opt::BasicBlock*>> constant_branch; + std::vector<std::pair<Instruction*, BasicBlock*>> constant_branch; // Special case for the original loop - opt::Instruction* original_loop_constant_value; - opt::BasicBlock* original_loop_target; + Instruction* original_loop_constant_value; + BasicBlock* original_loop_target; if (iv_opcode == SpvOpBranchConditional) { constant_branch.emplace_back( cst_mgr->GetDefiningInstruction(cst_mgr->GetConstant(cond_type, {0})), @@ -309,13 +307,13 @@ class LoopUnswitch { } for (auto& specialisation_pair : constant_branch) { - opt::Instruction* specialisation_value = specialisation_pair.first; + Instruction* specialisation_value = specialisation_pair.first; ////////////////////////////////////////////////////////// // Step 3: Duplicate |loop_|. ////////////////////////////////////////////////////////// LoopUtils::LoopCloningResult clone_result; - opt::Loop* cloned_loop = + Loop* cloned_loop = loop_utils.CloneLoop(&clone_result, ordered_loop_blocks_); specialisation_pair.second = cloned_loop->GetPreHeaderBlock(); @@ -327,11 +325,11 @@ class LoopUnswitch { std::unordered_set<uint32_t> dead_blocks; std::unordered_set<uint32_t> unreachable_merges; SimplifyLoop( - opt::make_range( - opt::UptrVectorIterator<opt::BasicBlock>( - &clone_result.cloned_bb_, clone_result.cloned_bb_.begin()), - opt::UptrVectorIterator<opt::BasicBlock>( - &clone_result.cloned_bb_, clone_result.cloned_bb_.end())), + make_range( + UptrVectorIterator<BasicBlock>(&clone_result.cloned_bb_, + clone_result.cloned_bb_.begin()), + UptrVectorIterator<BasicBlock>(&clone_result.cloned_bb_, + clone_result.cloned_bb_.end())), cloned_loop, condition, specialisation_value, &dead_blocks); // We tagged dead blocks, create the loop before we invalidate any basic @@ -339,8 +337,8 @@ class LoopUnswitch { cloned_loop = CleanLoopNest(cloned_loop, dead_blocks, &unreachable_merges); CleanUpCFG( - opt::UptrVectorIterator<opt::BasicBlock>( - &clone_result.cloned_bb_, clone_result.cloned_bb_.begin()), + UptrVectorIterator<BasicBlock>(&clone_result.cloned_bb_, + clone_result.cloned_bb_.begin()), dead_blocks, unreachable_merges); /////////////////////////////////////////////////////////// @@ -348,10 +346,10 @@ class LoopUnswitch { /////////////////////////////////////////////////////////// for (uint32_t merge_bb_id : if_merging_blocks) { - opt::BasicBlock* merge = context_->cfg()->block(merge_bb_id); + BasicBlock* merge = context_->cfg()->block(merge_bb_id); // We are in LCSSA so we only care about phi instructions. merge->ForEachPhiInst([is_from_original_loop, &dead_blocks, - &clone_result](opt::Instruction* phi) { + &clone_result](Instruction* phi) { uint32_t num_in_operands = phi->NumInOperands(); for (uint32_t i = 0; i < num_in_operands; i += 2) { uint32_t pred = phi->GetSingleWordInOperand(i + 1); @@ -382,11 +380,11 @@ class LoopUnswitch { { std::unordered_set<uint32_t> dead_blocks; std::unordered_set<uint32_t> unreachable_merges; - SimplifyLoop(opt::make_range(function_->begin(), function_->end()), loop_, + SimplifyLoop(make_range(function_->begin(), function_->end()), loop_, condition, original_loop_constant_value, &dead_blocks); for (uint32_t merge_bb_id : if_merging_blocks) { - opt::BasicBlock* merge = context_->cfg()->block(merge_bb_id); + BasicBlock* merge = context_->cfg()->block(merge_bb_id); // LCSSA, so we only care about phi instructions. // If we the phi is reduced to a single incoming branch, do not // propagate it to preserve LCSSA. @@ -417,7 +415,7 @@ class LoopUnswitch { // Delete the old jump context_->KillInst(&*if_block->tail()); - opt::InstructionBuilder builder(context_, if_block); + InstructionBuilder builder(context_, if_block); if (iv_opcode == SpvOpBranchConditional) { assert(constant_branch.size() == 1); builder.AddConditionalBranch( @@ -425,7 +423,7 @@ class LoopUnswitch { constant_branch[0].second->id(), if_merge_block ? if_merge_block->id() : kInvalidId); } else { - std::vector<std::pair<opt::Operand::OperandData, uint32_t>> targets; + std::vector<std::pair<Operand::OperandData, uint32_t>> targets; for (auto& t : constant_branch) { targets.emplace_back(t.first->GetInOperand(0).words, t.second->id()); } @@ -439,7 +437,7 @@ class LoopUnswitch { ordered_loop_blocks_.clear(); context_->InvalidateAnalysesExceptFor( - opt::IRContext::Analysis::kAnalysisLoopAnalysis); + IRContext::Analysis::kAnalysisLoopAnalysis); } // Returns true if the unswitch killed the original |loop_|. @@ -447,37 +445,37 @@ class LoopUnswitch { private: using ValueMapTy = std::unordered_map<uint32_t, uint32_t>; - using BlockMapTy = std::unordered_map<uint32_t, opt::BasicBlock*>; + using BlockMapTy = std::unordered_map<uint32_t, BasicBlock*>; - opt::Function* function_; - opt::Loop* loop_; - opt::LoopDescriptor& loop_desc_; - opt::IRContext* context_; + Function* function_; + Loop* loop_; + LoopDescriptor& loop_desc_; + IRContext* context_; - opt::BasicBlock* switch_block_; + BasicBlock* switch_block_; // Map between instructions and if they are dynamically uniform. std::unordered_map<uint32_t, bool> dynamically_uniform_; // The loop basic blocks in structured order. - std::vector<opt::BasicBlock*> ordered_loop_blocks_; + std::vector<BasicBlock*> ordered_loop_blocks_; // Returns the next usable id for the context. uint32_t TakeNextId() { return context_->TakeNextId(); } // Patches |bb|'s phi instruction by removing incoming value from unexisting // or tagged as dead branches. - void PatchPhis(opt::BasicBlock* bb, + void PatchPhis(BasicBlock* bb, const std::unordered_set<uint32_t>& dead_blocks, bool preserve_phi) { - opt::CFG& cfg = *context_->cfg(); + CFG& cfg = *context_->cfg(); - std::vector<opt::Instruction*> phi_to_kill; + std::vector<Instruction*> phi_to_kill; const std::vector<uint32_t>& bb_preds = cfg.preds(bb->id()); auto is_branch_dead = [&bb_preds, &dead_blocks](uint32_t id) { return dead_blocks.count(id) || std::find(bb_preds.begin(), bb_preds.end(), id) == bb_preds.end(); }; bb->ForEachPhiInst([&phi_to_kill, &is_branch_dead, preserve_phi, - this](opt::Instruction* insn) { + this](Instruction* insn) { uint32_t i = 0; while (i < insn->NumInOperands()) { uint32_t incoming_id = insn->GetSingleWordInOperand(i + 1); @@ -498,7 +496,7 @@ class LoopUnswitch { insn->GetSingleWordInOperand(0)); } }); - for (opt::Instruction* insn : phi_to_kill) { + for (Instruction* insn : phi_to_kill) { context_->KillInst(insn); } } @@ -506,20 +504,20 @@ class LoopUnswitch { // Removes any block that is tagged as dead, if the block is in // |unreachable_merges| then all block's instructions are replaced by a // OpUnreachable. - void CleanUpCFG(opt::UptrVectorIterator<opt::BasicBlock> bb_it, + void CleanUpCFG(UptrVectorIterator<BasicBlock> bb_it, const std::unordered_set<uint32_t>& dead_blocks, const std::unordered_set<uint32_t>& unreachable_merges) { - opt::CFG& cfg = *context_->cfg(); + CFG& cfg = *context_->cfg(); while (bb_it != bb_it.End()) { - opt::BasicBlock& bb = *bb_it; + BasicBlock& bb = *bb_it; if (unreachable_merges.count(bb.id())) { if (bb.begin() != bb.tail() || bb.terminator()->opcode() != SpvOpUnreachable) { // Make unreachable, but leave the label. bb.KillAllInsts(false); - opt::InstructionBuilder(context_, &bb).AddUnreachable(); + InstructionBuilder(context_, &bb).AddUnreachable(); cfg.RemoveNonExistingEdges(bb.id()); } ++bb_it; @@ -537,7 +535,7 @@ class LoopUnswitch { // Return true if |c_inst| is a Boolean constant and set |cond_val| with the // value that |c_inst| - bool GetConstCondition(const opt::Instruction* c_inst, bool* cond_val) { + bool GetConstCondition(const Instruction* c_inst, bool* cond_val) { bool cond_is_const; switch (c_inst->opcode()) { case SpvOpConstantFalse: { @@ -564,35 +562,36 @@ class LoopUnswitch { // - |loop| must be in the LCSSA form; // - |cst_value| must be constant or null (to represent the default target // of an OpSwitch). - void SimplifyLoop( - opt::IteratorRange<opt::UptrVectorIterator<opt::BasicBlock>> block_range, - opt::Loop* loop, opt::Instruction* to_version_insn, - opt::Instruction* cst_value, std::unordered_set<uint32_t>* dead_blocks) { - opt::CFG& cfg = *context_->cfg(); + void SimplifyLoop(IteratorRange<UptrVectorIterator<BasicBlock>> block_range, + Loop* loop, Instruction* to_version_insn, + Instruction* cst_value, + std::unordered_set<uint32_t>* dead_blocks) { + CFG& cfg = *context_->cfg(); analysis::DefUseManager* def_use_mgr = context_->get_def_use_mgr(); std::function<bool(uint32_t)> ignore_node; ignore_node = [loop](uint32_t bb_id) { return !loop->IsInsideLoop(bb_id); }; - std::vector<std::pair<opt::Instruction*, uint32_t>> use_list; - def_use_mgr->ForEachUse( - to_version_insn, [&use_list, &ignore_node, this]( - opt::Instruction* inst, uint32_t operand_index) { - opt::BasicBlock* bb = context_->get_instr_block(inst); + std::vector<std::pair<Instruction*, uint32_t>> use_list; + def_use_mgr->ForEachUse(to_version_insn, + [&use_list, &ignore_node, this]( + Instruction* inst, uint32_t operand_index) { + BasicBlock* bb = context_->get_instr_block(inst); - if (!bb || ignore_node(bb->id())) { - // Out of the loop, the specialization does not apply any more. - return; - } - use_list.emplace_back(inst, operand_index); - }); + if (!bb || ignore_node(bb->id())) { + // Out of the loop, the specialization does not + // apply any more. + return; + } + use_list.emplace_back(inst, operand_index); + }); // First pass: inject the specialized value into the loop (and only the // loop). for (auto use : use_list) { - opt::Instruction* inst = use.first; + Instruction* inst = use.first; uint32_t operand_index = use.second; - opt::BasicBlock* bb = context_->get_instr_block(inst); + BasicBlock* bb = context_->get_instr_block(inst); // If it is not a branch, simply inject the value. if (!inst->IsBranch()) { @@ -628,9 +627,9 @@ class LoopUnswitch { live_target = inst->GetSingleWordInOperand(1); if (cst_value) { if (!cst_value->IsConstant()) break; - const opt::Operand& cst = cst_value->GetInOperand(0); + const Operand& cst = cst_value->GetInOperand(0); for (uint32_t i = 2; i < inst->NumInOperands(); i += 2) { - const opt::Operand& literal = inst->GetInOperand(i); + const Operand& literal = inst->GetInOperand(i); if (literal == cst) { live_target = inst->GetSingleWordInOperand(i + 1); break; @@ -649,13 +648,11 @@ class LoopUnswitch { } if (live_target != 0) { // Check for the presence of the merge block. - if (opt::Instruction* merge = bb->GetMergeInst()) - context_->KillInst(merge); + if (Instruction* merge = bb->GetMergeInst()) context_->KillInst(merge); context_->KillInst(&*bb->tail()); - opt::InstructionBuilder builder( - context_, bb, - opt::IRContext::kAnalysisDefUse | - opt::IRContext::kAnalysisInstrToBlockMapping); + InstructionBuilder builder(context_, bb, + IRContext::kAnalysisDefUse | + IRContext::kAnalysisInstrToBlockMapping); builder.AddBranch(live_target); } } @@ -663,7 +660,7 @@ class LoopUnswitch { // Go through the loop basic block and tag all blocks that are obviously // dead. std::unordered_set<uint32_t> visited; - for (opt::BasicBlock& bb : block_range) { + for (BasicBlock& bb : block_range) { if (ignore_node(bb.id())) continue; visited.insert(bb.id()); @@ -678,12 +675,12 @@ class LoopUnswitch { } if (!has_live_pred) { dead_blocks->insert(bb.id()); - const opt::BasicBlock& cbb = bb; + const BasicBlock& cbb = bb; // Patch the phis for any back-edge. cbb.ForEachSuccessorLabel( [dead_blocks, &visited, &cfg, this](uint32_t id) { if (!visited.count(id) || dead_blocks->count(id)) return; - opt::BasicBlock* succ = cfg.block(id); + BasicBlock* succ = cfg.block(id); PatchPhis(succ, *dead_blocks, false); }); continue; @@ -695,7 +692,7 @@ class LoopUnswitch { // Returns true if the header is not reachable or tagged as dead or if we // never loop back. - bool IsLoopDead(opt::BasicBlock* header, opt::BasicBlock* latch, + bool IsLoopDead(BasicBlock* header, BasicBlock* latch, const std::unordered_set<uint32_t>& dead_blocks) { if (!header || dead_blocks.count(header->id())) return true; if (!latch || dead_blocks.count(latch->id())) return true; @@ -715,15 +712,14 @@ class LoopUnswitch { // |unreachable_merges|. // The function returns the pointer to |loop| or nullptr if the loop was // killed. - opt::Loop* CleanLoopNest(opt::Loop* loop, - const std::unordered_set<uint32_t>& dead_blocks, - std::unordered_set<uint32_t>* unreachable_merges) { + Loop* CleanLoopNest(Loop* loop, + const std::unordered_set<uint32_t>& dead_blocks, + std::unordered_set<uint32_t>* unreachable_merges) { // This represent the pair of dead loop and nearest alive parent (nullptr if // no parent). - std::unordered_map<opt::Loop*, opt::Loop*> dead_loops; - auto get_parent = [&dead_loops](opt::Loop* l) -> opt::Loop* { - std::unordered_map<opt::Loop*, opt::Loop*>::iterator it = - dead_loops.find(l); + std::unordered_map<Loop*, Loop*> dead_loops; + auto get_parent = [&dead_loops](Loop* l) -> Loop* { + std::unordered_map<Loop*, Loop*>::iterator it = dead_loops.find(l); if (it != dead_loops.end()) return it->second; return nullptr; }; @@ -731,8 +727,7 @@ class LoopUnswitch { bool is_main_loop_dead = IsLoopDead(loop->GetHeaderBlock(), loop->GetLatchBlock(), dead_blocks); if (is_main_loop_dead) { - if (opt::Instruction* merge = - loop->GetHeaderBlock()->GetLoopMergeInst()) { + if (Instruction* merge = loop->GetHeaderBlock()->GetLoopMergeInst()) { context_->KillInst(merge); } dead_loops[loop] = loop->GetParent(); @@ -740,12 +735,11 @@ class LoopUnswitch { dead_loops[loop] = loop; // For each loop, check if we killed it. If we did, find a suitable parent // for its children. - for (opt::Loop& sub_loop : - opt::make_range(++opt::TreeDFIterator<opt::Loop>(loop), - opt::TreeDFIterator<opt::Loop>())) { + for (Loop& sub_loop : + make_range(++TreeDFIterator<Loop>(loop), TreeDFIterator<Loop>())) { if (IsLoopDead(sub_loop.GetHeaderBlock(), sub_loop.GetLatchBlock(), dead_blocks)) { - if (opt::Instruction* merge = + if (Instruction* merge = sub_loop.GetHeaderBlock()->GetLoopMergeInst()) { context_->KillInst(merge); } @@ -765,7 +759,7 @@ class LoopUnswitch { // Remove dead blocks from live loops. for (uint32_t bb_id : dead_blocks) { - opt::Loop* l = loop_desc_[bb_id]; + Loop* l = loop_desc_[bb_id]; if (l) { l->RemoveBasicBlock(bb_id); loop_desc_.ForgetBasicBlock(bb_id); @@ -774,8 +768,8 @@ class LoopUnswitch { std::for_each( dead_loops.begin(), dead_loops.end(), - [&loop, this](std::unordered_map<opt::Loop*, - opt::Loop*>::iterator::reference it) { + [&loop, + this](std::unordered_map<Loop*, Loop*>::iterator::reference it) { if (it.first == loop) loop = nullptr; loop_desc_.RemoveLoop(it.first); }); @@ -785,7 +779,7 @@ class LoopUnswitch { // Returns true if |var| is dynamically uniform. // Note: this is currently approximated as uniform. - bool IsDynamicallyUniform(opt::Instruction* var, const opt::BasicBlock* entry, + bool IsDynamicallyUniform(Instruction* var, const BasicBlock* entry, const DominatorTree& post_dom_tree) { assert(post_dom_tree.IsPostDominator()); analysis::DefUseManager* def_use_mgr = context_->get_def_use_mgr(); @@ -800,7 +794,7 @@ class LoopUnswitch { is_uniform = false; dec_mgr->WhileEachDecoration(var->result_id(), SpvDecorationUniform, - [&is_uniform](const opt::Instruction&) { + [&is_uniform](const Instruction&) { is_uniform = true; return false; }); @@ -808,7 +802,7 @@ class LoopUnswitch { return is_uniform; } - opt::BasicBlock* parent = context_->get_instr_block(var); + BasicBlock* parent = context_->get_instr_block(var); if (!parent) { return is_uniform = true; } @@ -819,7 +813,7 @@ class LoopUnswitch { if (var->opcode() == SpvOpLoad) { const uint32_t PtrTypeId = def_use_mgr->GetDef(var->GetSingleWordInOperand(0))->type_id(); - const opt::Instruction* PtrTypeInst = def_use_mgr->GetDef(PtrTypeId); + const Instruction* PtrTypeInst = def_use_mgr->GetDef(PtrTypeId); uint32_t storage_class = PtrTypeInst->GetSingleWordInOperand(kTypePointerStorageClassInIdx); if (storage_class != SpvStorageClassUniform && @@ -840,13 +834,12 @@ class LoopUnswitch { } // Returns true if |insn| is constant and dynamically uniform within the loop. - bool IsConditionLoopInvariant(opt::Instruction* insn) { + bool IsConditionLoopInvariant(Instruction* insn) { assert(insn->IsBranch()); assert(insn->opcode() != SpvOpBranch); analysis::DefUseManager* def_use_mgr = context_->get_def_use_mgr(); - opt::Instruction* condition = - def_use_mgr->GetDef(insn->GetOperand(0).words[0]); + Instruction* condition = def_use_mgr->GetDef(insn->GetOperand(0).words[0]); return !loop_->IsInsideLoop(condition) && IsDynamicallyUniform( condition, function_->entry().get(), @@ -858,29 +851,28 @@ class LoopUnswitch { Pass::Status LoopUnswitchPass::Process() { bool modified = false; - opt::Module* module = context()->module(); + Module* module = context()->module(); // Process each function in the module - for (opt::Function& f : *module) { + for (Function& f : *module) { modified |= ProcessFunction(&f); } return modified ? Status::SuccessWithChange : Status::SuccessWithoutChange; } -bool LoopUnswitchPass::ProcessFunction(opt::Function* f) { +bool LoopUnswitchPass::ProcessFunction(Function* f) { bool modified = false; - std::unordered_set<opt::Loop*> processed_loop; + std::unordered_set<Loop*> processed_loop; - opt::LoopDescriptor& loop_descriptor = *context()->GetLoopDescriptor(f); + LoopDescriptor& loop_descriptor = *context()->GetLoopDescriptor(f); bool loop_changed = true; while (loop_changed) { loop_changed = false; - for (opt::Loop& loop : - opt::make_range(++opt::TreeDFIterator<opt::Loop>( - loop_descriptor.GetDummyRootLoop()), - opt::TreeDFIterator<opt::Loop>())) { + for (Loop& loop : + make_range(++TreeDFIterator<Loop>(loop_descriptor.GetDummyRootLoop()), + TreeDFIterator<Loop>())) { if (processed_loop.count(&loop)) continue; processed_loop.insert(&loop); diff --git a/source/opt/loop_unswitch_pass.h b/source/opt/loop_unswitch_pass.h index 614a89e2..b1851903 100644 --- a/source/opt/loop_unswitch_pass.h +++ b/source/opt/loop_unswitch_pass.h @@ -34,7 +34,7 @@ class LoopUnswitchPass : public Pass { Pass::Status Process() override; private: - bool ProcessFunction(opt::Function* f); + bool ProcessFunction(Function* f); }; } // namespace opt diff --git a/source/opt/loop_utils.cpp b/source/opt/loop_utils.cpp index 28f0239b..96644b5d 100644 --- a/source/opt/loop_utils.cpp +++ b/source/opt/loop_utils.cpp @@ -30,10 +30,10 @@ namespace opt { namespace { // Return true if |bb| is dominated by at least one block in |exits| -static inline bool DominatesAnExit( - opt::BasicBlock* bb, const std::unordered_set<opt::BasicBlock*>& exits, - const opt::DominatorTree& dom_tree) { - for (opt::BasicBlock* e_bb : exits) +static inline bool DominatesAnExit(BasicBlock* bb, + const std::unordered_set<BasicBlock*>& exits, + const DominatorTree& dom_tree) { + for (BasicBlock* e_bb : exits) if (dom_tree.Dominates(bb, e_bb)) return true; return false; } @@ -47,9 +47,9 @@ static inline bool DominatesAnExit( // instruction to merge the incoming value according to exit blocks definition. class LCSSARewriter { public: - LCSSARewriter(opt::IRContext* context, const opt::DominatorTree& dom_tree, - const std::unordered_set<opt::BasicBlock*>& exit_bb, - opt::BasicBlock* merge_block) + LCSSARewriter(IRContext* context, const DominatorTree& dom_tree, + const std::unordered_set<BasicBlock*>& exit_bb, + BasicBlock* merge_block) : context_(context), cfg_(context_->cfg()), dom_tree_(dom_tree), @@ -57,7 +57,7 @@ class LCSSARewriter { merge_block_id_(merge_block ? merge_block->id() : 0) {} struct UseRewriter { - explicit UseRewriter(LCSSARewriter* base, const opt::Instruction& def_insn) + explicit UseRewriter(LCSSARewriter* base, const Instruction& def_insn) : base_(base), def_insn_(def_insn) {} // Rewrites the use of |def_insn_| by the instruction |user| at the index // |operand_index| in terms of phi instruction. This recursively builds new @@ -68,8 +68,7 @@ class LCSSARewriter { // block. This operation does not update the def/use manager, instead it // records what needs to be updated. The actual update is performed by // UpdateManagers. - void RewriteUse(opt::BasicBlock* bb, opt::Instruction* user, - uint32_t operand_index) { + void RewriteUse(BasicBlock* bb, Instruction* user, uint32_t operand_index) { assert( (user->opcode() != SpvOpPhi || bb != GetParent(user)) && "The root basic block must be the incoming edge if |user| is a phi " @@ -79,7 +78,7 @@ class LCSSARewriter { "not " "phi instruction"); - opt::Instruction* new_def = GetOrBuildIncoming(bb->id()); + Instruction* new_def = GetOrBuildIncoming(bb->id()); user->SetOperand(operand_index, {new_def->result_id()}); rewritten_.insert(user); @@ -87,29 +86,28 @@ class LCSSARewriter { // In-place update of some managers (avoid full invalidation). inline void UpdateManagers() { - opt::analysis::DefUseManager* def_use_mgr = - base_->context_->get_def_use_mgr(); + analysis::DefUseManager* def_use_mgr = base_->context_->get_def_use_mgr(); // Register all new definitions. - for (opt::Instruction* insn : rewritten_) { + for (Instruction* insn : rewritten_) { def_use_mgr->AnalyzeInstDef(insn); } // Register all new uses. - for (opt::Instruction* insn : rewritten_) { + for (Instruction* insn : rewritten_) { def_use_mgr->AnalyzeInstUse(insn); } } private: // Return the basic block that |instr| belongs to. - opt::BasicBlock* GetParent(opt::Instruction* instr) { + BasicBlock* GetParent(Instruction* instr) { return base_->context_->get_instr_block(instr); } // Builds a phi instruction for the basic block |bb|. The function assumes // that |defining_blocks| contains the list of basic block that define the // usable value for each predecessor of |bb|. - inline opt::Instruction* CreatePhiInstruction( - opt::BasicBlock* bb, const std::vector<uint32_t>& defining_blocks) { + inline Instruction* CreatePhiInstruction( + BasicBlock* bb, const std::vector<uint32_t>& defining_blocks) { std::vector<uint32_t> incomings; const std::vector<uint32_t>& bb_preds = base_->cfg_->preds(bb->id()); assert(bb_preds.size() == defining_blocks.size()); @@ -118,10 +116,9 @@ class LCSSARewriter { GetOrBuildIncoming(defining_blocks[i])->result_id()); incomings.push_back(bb_preds[i]); } - opt::InstructionBuilder builder( - base_->context_, &*bb->begin(), - opt::IRContext::kAnalysisInstrToBlockMapping); - opt::Instruction* incoming_phi = + InstructionBuilder builder(base_->context_, &*bb->begin(), + IRContext::kAnalysisInstrToBlockMapping); + Instruction* incoming_phi = builder.AddPhi(def_insn_.type_id(), incomings); rewritten_.insert(incoming_phi); @@ -130,18 +127,17 @@ class LCSSARewriter { // Builds a phi instruction for the basic block |bb|, all incoming values // will be |value|. - inline opt::Instruction* CreatePhiInstruction( - opt::BasicBlock* bb, const opt::Instruction& value) { + inline Instruction* CreatePhiInstruction(BasicBlock* bb, + const Instruction& value) { std::vector<uint32_t> incomings; const std::vector<uint32_t>& bb_preds = base_->cfg_->preds(bb->id()); for (size_t i = 0; i < bb_preds.size(); i++) { incomings.push_back(value.result_id()); incomings.push_back(bb_preds[i]); } - opt::InstructionBuilder builder( - base_->context_, &*bb->begin(), - opt::IRContext::kAnalysisInstrToBlockMapping); - opt::Instruction* incoming_phi = + InstructionBuilder builder(base_->context_, &*bb->begin(), + IRContext::kAnalysisInstrToBlockMapping); + Instruction* incoming_phi = builder.AddPhi(def_insn_.type_id(), incomings); rewritten_.insert(incoming_phi); @@ -153,21 +149,21 @@ class LCSSARewriter { // - return the common def used by all predecessors; // - if there is no common def, then we build a new phi instr at the // beginning of |bb_id| and return this new instruction. - opt::Instruction* GetOrBuildIncoming(uint32_t bb_id) { + Instruction* GetOrBuildIncoming(uint32_t bb_id) { assert(base_->cfg_->block(bb_id) != nullptr && "Unknown basic block"); - opt::Instruction*& incoming_phi = bb_to_phi_[bb_id]; + Instruction*& incoming_phi = bb_to_phi_[bb_id]; if (incoming_phi) { return incoming_phi; } - opt::BasicBlock* bb = &*base_->cfg_->block(bb_id); + BasicBlock* bb = &*base_->cfg_->block(bb_id); // If this is an exit basic block, look if there already is an eligible // phi instruction. An eligible phi has |def_insn_| as all incoming // values. if (base_->exit_bb_.count(bb)) { // Look if there is an eligible phi in this block. - if (!bb->WhileEachPhiInst([&incoming_phi, this](opt::Instruction* phi) { + if (!bb->WhileEachPhiInst([&incoming_phi, this](Instruction* phi) { for (uint32_t i = 0; i < phi->NumInOperands(); i += 2) { if (phi->GetSingleWordInOperand(i) != def_insn_.result_id()) return true; @@ -208,9 +204,9 @@ class LCSSARewriter { } LCSSARewriter* base_; - const opt::Instruction& def_insn_; - std::unordered_map<uint32_t, opt::Instruction*> bb_to_phi_; - std::unordered_set<opt::Instruction*> rewritten_; + const Instruction& def_insn_; + std::unordered_map<uint32_t, Instruction*> bb_to_phi_; + std::unordered_set<Instruction*> rewritten_; }; private: @@ -226,7 +222,7 @@ class LCSSARewriter { if (defining_blocks.size()) return defining_blocks; // Check if one of the loop exit basic block dominates |bb_id|. - for (const opt::BasicBlock* e_bb : exit_bb_) { + for (const BasicBlock* e_bb : exit_bb_) { if (dom_tree_.Dominates(e_bb->id(), bb_id)) { defining_blocks.push_back(e_bb->id()); return defining_blocks; @@ -255,10 +251,10 @@ class LCSSARewriter { return defining_blocks; } - opt::IRContext* context_; - opt::CFG* cfg_; - const opt::DominatorTree& dom_tree_; - const std::unordered_set<opt::BasicBlock*>& exit_bb_; + IRContext* context_; + CFG* cfg_; + const DominatorTree& dom_tree_; + const std::unordered_set<BasicBlock*>& exit_bb_; uint32_t merge_block_id_; // This map represent the set of known paths. For each key, the vector // represent the set of blocks holding the definition to be used to build the @@ -274,26 +270,25 @@ class LCSSARewriter { // Make the set |blocks| closed SSA. The set is closed SSA if all the uses // outside the set are phi instructions in exiting basic block set (hold by // |lcssa_rewriter|). -inline void MakeSetClosedSSA( - opt::IRContext* context, opt::Function* function, - const std::unordered_set<uint32_t>& blocks, - const std::unordered_set<opt::BasicBlock*>& exit_bb, - LCSSARewriter* lcssa_rewriter) { - opt::CFG& cfg = *context->cfg(); - opt::DominatorTree& dom_tree = +inline void MakeSetClosedSSA(IRContext* context, Function* function, + const std::unordered_set<uint32_t>& blocks, + const std::unordered_set<BasicBlock*>& exit_bb, + LCSSARewriter* lcssa_rewriter) { + CFG& cfg = *context->cfg(); + DominatorTree& dom_tree = context->GetDominatorAnalysis(function)->GetDomTree(); - opt::analysis::DefUseManager* def_use_manager = context->get_def_use_mgr(); + analysis::DefUseManager* def_use_manager = context->get_def_use_mgr(); for (uint32_t bb_id : blocks) { - opt::BasicBlock* bb = cfg.block(bb_id); + BasicBlock* bb = cfg.block(bb_id); // If bb does not dominate an exit block, then it cannot have escaping defs. if (!DominatesAnExit(bb, exit_bb, dom_tree)) continue; - for (opt::Instruction& inst : *bb) { + for (Instruction& inst : *bb) { LCSSARewriter::UseRewriter rewriter(lcssa_rewriter, inst); def_use_manager->ForEachUse( &inst, [&blocks, &rewriter, &exit_bb, context]( - opt::Instruction* use, uint32_t operand_index) { - opt::BasicBlock* use_parent = context->get_instr_block(use); + Instruction* use, uint32_t operand_index) { + BasicBlock* use_parent = context->get_instr_block(use); assert(use_parent); if (blocks.count(use_parent->id())) return; @@ -321,26 +316,25 @@ inline void MakeSetClosedSSA( } // namespace void LoopUtils::CreateLoopDedicatedExits() { - opt::Function* function = loop_->GetHeaderBlock()->GetParent(); - opt::LoopDescriptor& loop_desc = *context_->GetLoopDescriptor(function); - opt::CFG& cfg = *context_->cfg(); - opt::analysis::DefUseManager* def_use_mgr = context_->get_def_use_mgr(); + Function* function = loop_->GetHeaderBlock()->GetParent(); + LoopDescriptor& loop_desc = *context_->GetLoopDescriptor(function); + CFG& cfg = *context_->cfg(); + analysis::DefUseManager* def_use_mgr = context_->get_def_use_mgr(); - const opt::IRContext::Analysis PreservedAnalyses = - opt::IRContext::kAnalysisDefUse | - opt::IRContext::kAnalysisInstrToBlockMapping; + const IRContext::Analysis PreservedAnalyses = + IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping; // Gathers the set of basic block that are not in this loop and have at least // one predecessor in the loop and one not in the loop. std::unordered_set<uint32_t> exit_bb_set; loop_->GetExitBlocks(&exit_bb_set); - std::unordered_set<opt::BasicBlock*> new_loop_exits; + std::unordered_set<BasicBlock*> new_loop_exits; bool made_change = false; // For each block, we create a new one that gathers all branches from // the loop and fall into the block. for (uint32_t non_dedicate_id : exit_bb_set) { - opt::BasicBlock* non_dedicate = cfg.block(non_dedicate_id); + BasicBlock* non_dedicate = cfg.block(non_dedicate_id); const std::vector<uint32_t>& bb_pred = cfg.preds(non_dedicate_id); // Ignore the block if all the predecessors are in the loop. if (std::all_of(bb_pred.begin(), bb_pred.end(), @@ -350,23 +344,22 @@ void LoopUtils::CreateLoopDedicatedExits() { } made_change = true; - opt::Function::iterator insert_pt = function->begin(); + Function::iterator insert_pt = function->begin(); for (; insert_pt != function->end() && &*insert_pt != non_dedicate; ++insert_pt) { } assert(insert_pt != function->end() && "Basic Block not found"); // Create the dedicate exit basic block. - opt::BasicBlock& exit = *insert_pt.InsertBefore( - std::unique_ptr<opt::BasicBlock>(new opt::BasicBlock( - std::unique_ptr<opt::Instruction>(new opt::Instruction( - context_, SpvOpLabel, 0, context_->TakeNextId(), {}))))); + BasicBlock& exit = *insert_pt.InsertBefore(std::unique_ptr<BasicBlock>( + new BasicBlock(std::unique_ptr<Instruction>(new Instruction( + context_, SpvOpLabel, 0, context_->TakeNextId(), {}))))); exit.SetParent(function); // Redirect in loop predecessors to |exit| block. for (uint32_t exit_pred_id : bb_pred) { if (loop_->IsInsideLoop(exit_pred_id)) { - opt::BasicBlock* pred_block = cfg.block(exit_pred_id); + BasicBlock* pred_block = cfg.block(exit_pred_id); pred_block->ForEachSuccessorLabel([non_dedicate, &exit](uint32_t* id) { if (*id == non_dedicate->id()) *id = exit.id(); }); @@ -381,50 +374,50 @@ void LoopUtils::CreateLoopDedicatedExits() { def_use_mgr->AnalyzeInstDefUse(exit.GetLabelInst()); context_->set_instr_block(exit.GetLabelInst(), &exit); - opt::InstructionBuilder builder(context_, &exit, PreservedAnalyses); + InstructionBuilder builder(context_, &exit, PreservedAnalyses); // Now jump from our dedicate basic block to the old exit. // We also reset the insert point so all instructions are inserted before // the branch. builder.SetInsertPoint(builder.AddBranch(non_dedicate->id())); - non_dedicate->ForEachPhiInst([&builder, &exit, def_use_mgr, - this](opt::Instruction* phi) { - // New phi operands for this instruction. - std::vector<uint32_t> new_phi_op; - // Phi operands for the dedicated exit block. - std::vector<uint32_t> exit_phi_op; - for (uint32_t i = 0; i < phi->NumInOperands(); i += 2) { - uint32_t def_id = phi->GetSingleWordInOperand(i); - uint32_t incoming_id = phi->GetSingleWordInOperand(i + 1); - if (loop_->IsInsideLoop(incoming_id)) { - exit_phi_op.push_back(def_id); - exit_phi_op.push_back(incoming_id); - } else { - new_phi_op.push_back(def_id); - new_phi_op.push_back(incoming_id); - } - } - - // Build the new phi instruction dedicated exit block. - opt::Instruction* exit_phi = builder.AddPhi(phi->type_id(), exit_phi_op); - // Build the new incoming branch. - new_phi_op.push_back(exit_phi->result_id()); - new_phi_op.push_back(exit.id()); - // Rewrite operands. - uint32_t idx = 0; - for (; idx < new_phi_op.size(); idx++) - phi->SetInOperand(idx, {new_phi_op[idx]}); - // Remove extra operands, from last to first (more efficient). - for (uint32_t j = phi->NumInOperands() - 1; j >= idx; j--) - phi->RemoveInOperand(j); - // Update the def/use manager for this |phi|. - def_use_mgr->AnalyzeInstUse(phi); - }); + non_dedicate->ForEachPhiInst( + [&builder, &exit, def_use_mgr, this](Instruction* phi) { + // New phi operands for this instruction. + std::vector<uint32_t> new_phi_op; + // Phi operands for the dedicated exit block. + std::vector<uint32_t> exit_phi_op; + for (uint32_t i = 0; i < phi->NumInOperands(); i += 2) { + uint32_t def_id = phi->GetSingleWordInOperand(i); + uint32_t incoming_id = phi->GetSingleWordInOperand(i + 1); + if (loop_->IsInsideLoop(incoming_id)) { + exit_phi_op.push_back(def_id); + exit_phi_op.push_back(incoming_id); + } else { + new_phi_op.push_back(def_id); + new_phi_op.push_back(incoming_id); + } + } + + // Build the new phi instruction dedicated exit block. + Instruction* exit_phi = builder.AddPhi(phi->type_id(), exit_phi_op); + // Build the new incoming branch. + new_phi_op.push_back(exit_phi->result_id()); + new_phi_op.push_back(exit.id()); + // Rewrite operands. + uint32_t idx = 0; + for (; idx < new_phi_op.size(); idx++) + phi->SetInOperand(idx, {new_phi_op[idx]}); + // Remove extra operands, from last to first (more efficient). + for (uint32_t j = phi->NumInOperands() - 1; j >= idx; j--) + phi->RemoveInOperand(j); + // Update the def/use manager for this |phi|. + def_use_mgr->AnalyzeInstUse(phi); + }); // Update the CFG. cfg.RegisterBlock(&exit); cfg.RemoveNonExistingEdges(non_dedicate->id()); new_loop_exits.insert(&exit); // If non_dedicate is in a loop, add the new dedicated exit in that loop. - if (opt::Loop* parent_loop = loop_desc[non_dedicate]) + if (Loop* parent_loop = loop_desc[non_dedicate]) parent_loop->AddBasicBlock(&exit); } @@ -434,20 +427,20 @@ void LoopUtils::CreateLoopDedicatedExits() { if (made_change) { context_->InvalidateAnalysesExceptFor( - PreservedAnalyses | opt::IRContext::kAnalysisCFG | - opt::IRContext::Analysis::kAnalysisLoopAnalysis); + PreservedAnalyses | IRContext::kAnalysisCFG | + IRContext::Analysis::kAnalysisLoopAnalysis); } } void LoopUtils::MakeLoopClosedSSA() { CreateLoopDedicatedExits(); - opt::Function* function = loop_->GetHeaderBlock()->GetParent(); - opt::CFG& cfg = *context_->cfg(); - opt::DominatorTree& dom_tree = + Function* function = loop_->GetHeaderBlock()->GetParent(); + CFG& cfg = *context_->cfg(); + DominatorTree& dom_tree = context_->GetDominatorAnalysis(function)->GetDomTree(); - std::unordered_set<opt::BasicBlock*> exit_bb; + std::unordered_set<BasicBlock*> exit_bb; { std::unordered_set<uint32_t> exit_bb_id; loop_->GetExitBlocks(&exit_bb_id); @@ -477,35 +470,33 @@ void LoopUtils::MakeLoopClosedSSA() { } context_->InvalidateAnalysesExceptFor( - opt::IRContext::Analysis::kAnalysisCFG | - opt::IRContext::Analysis::kAnalysisDominatorAnalysis | - opt::IRContext::Analysis::kAnalysisLoopAnalysis); + IRContext::Analysis::kAnalysisCFG | + IRContext::Analysis::kAnalysisDominatorAnalysis | + IRContext::Analysis::kAnalysisLoopAnalysis); } -opt::Loop* LoopUtils::CloneLoop(LoopCloningResult* cloning_result) const { +Loop* LoopUtils::CloneLoop(LoopCloningResult* cloning_result) const { // Compute the structured order of the loop basic blocks and store it in the // vector ordered_loop_blocks. - std::vector<opt::BasicBlock*> ordered_loop_blocks; + std::vector<BasicBlock*> ordered_loop_blocks; loop_->ComputeLoopStructuredOrder(&ordered_loop_blocks); // Clone the loop. return CloneLoop(cloning_result, ordered_loop_blocks); } -opt::Loop* LoopUtils::CloneAndAttachLoopToHeader( - LoopCloningResult* cloning_result) { +Loop* LoopUtils::CloneAndAttachLoopToHeader(LoopCloningResult* cloning_result) { // Clone the loop. - opt::Loop* new_loop = CloneLoop(cloning_result); + Loop* new_loop = CloneLoop(cloning_result); // Create a new exit block/label for the new loop. - std::unique_ptr<opt::Instruction> new_label{new opt::Instruction( + std::unique_ptr<Instruction> new_label{new Instruction( context_, SpvOp::SpvOpLabel, 0, context_->TakeNextId(), {})}; - std::unique_ptr<opt::BasicBlock> new_exit_bb{ - new opt::BasicBlock(std::move(new_label))}; + std::unique_ptr<BasicBlock> new_exit_bb{new BasicBlock(std::move(new_label))}; new_exit_bb->SetParent(loop_->GetMergeBlock()->GetParent()); // Create an unconditional branch to the header block. - opt::InstructionBuilder builder{context_, new_exit_bb.get()}; + InstructionBuilder builder{context_, new_exit_bb.get()}; builder.AddBranch(loop_->GetHeaderBlock()->id()); // Save the ids of the new and old merge block. @@ -514,9 +505,8 @@ opt::Loop* LoopUtils::CloneAndAttachLoopToHeader( // Replace the uses of the old merge block in the new loop with the new merge // block. - for (std::unique_ptr<opt::BasicBlock>& basic_block : - cloning_result->cloned_bb_) { - for (opt::Instruction& inst : *basic_block) { + for (std::unique_ptr<BasicBlock>& basic_block : cloning_result->cloned_bb_) { + for (Instruction& inst : *basic_block) { // For each operand in each instruction check if it is using the old merge // block and change it to be the new merge block. auto replace_merge_use = [old_merge_block, @@ -529,17 +519,17 @@ opt::Loop* LoopUtils::CloneAndAttachLoopToHeader( const uint32_t old_header = loop_->GetHeaderBlock()->id(); const uint32_t new_header = new_loop->GetHeaderBlock()->id(); - opt::analysis::DefUseManager* def_use = context_->get_def_use_mgr(); + analysis::DefUseManager* def_use = context_->get_def_use_mgr(); - def_use->ForEachUse( - old_header, [new_header, this](opt::Instruction* inst, uint32_t operand) { - if (!this->loop_->IsInsideLoop(inst)) - inst->SetOperand(operand, {new_header}); - }); + def_use->ForEachUse(old_header, + [new_header, this](Instruction* inst, uint32_t operand) { + if (!this->loop_->IsInsideLoop(inst)) + inst->SetOperand(operand, {new_header}); + }); def_use->ForEachUse( loop_->GetOrCreatePreHeaderBlock()->id(), - [new_merge_block, this](opt::Instruction* inst, uint32_t operand) { + [new_merge_block, this](Instruction* inst, uint32_t operand) { if (this->loop_->IsInsideLoop(inst)) inst->SetOperand(operand, {new_merge_block}); @@ -554,20 +544,20 @@ opt::Loop* LoopUtils::CloneAndAttachLoopToHeader( return new_loop; } -opt::Loop* LoopUtils::CloneLoop( +Loop* LoopUtils::CloneLoop( LoopCloningResult* cloning_result, - const std::vector<opt::BasicBlock*>& ordered_loop_blocks) const { + const std::vector<BasicBlock*>& ordered_loop_blocks) const { analysis::DefUseManager* def_use_mgr = context_->get_def_use_mgr(); - std::unique_ptr<opt::Loop> new_loop = MakeUnique<opt::Loop>(context_); + std::unique_ptr<Loop> new_loop = MakeUnique<Loop>(context_); - opt::CFG& cfg = *context_->cfg(); + CFG& cfg = *context_->cfg(); // Clone and place blocks in a SPIR-V compliant order (dominators first). - for (opt::BasicBlock* old_bb : ordered_loop_blocks) { + for (BasicBlock* old_bb : ordered_loop_blocks) { // For each basic block in the loop, we clone it and register the mapping // between old and new ids. - opt::BasicBlock* new_bb = old_bb->Clone(context_); + BasicBlock* new_bb = old_bb->Clone(context_); new_bb->SetParent(&function_); new_bb->GetLabelInst()->SetResultId(context_->TakeNextId()); def_use_mgr->AnalyzeInstDef(new_bb->GetLabelInst()); @@ -596,10 +586,10 @@ opt::Loop* LoopUtils::CloneLoop( // All instructions (including all labels) have been cloned, // remap instruction operands id with the new ones. - for (std::unique_ptr<opt::BasicBlock>& bb_ref : cloning_result->cloned_bb_) { - opt::BasicBlock* bb = bb_ref.get(); + for (std::unique_ptr<BasicBlock>& bb_ref : cloning_result->cloned_bb_) { + BasicBlock* bb = bb_ref.get(); - for (opt::Instruction& insn : *bb) { + for (Instruction& insn : *bb) { insn.ForEachInId([cloning_result](uint32_t* old_id) { // If the operand is defined in the loop, remap the id. auto id_it = cloning_result->value_map_.find(*old_id); @@ -621,32 +611,31 @@ opt::Loop* LoopUtils::CloneLoop( } void LoopUtils::PopulateLoopNest( - opt::Loop* new_loop, const LoopCloningResult& cloning_result) const { - std::unordered_map<opt::Loop*, opt::Loop*> loop_mapping; + Loop* new_loop, const LoopCloningResult& cloning_result) const { + std::unordered_map<Loop*, Loop*> loop_mapping; loop_mapping[loop_] = new_loop; if (loop_->HasParent()) loop_->GetParent()->AddNestedLoop(new_loop); PopulateLoopDesc(new_loop, loop_, cloning_result); - for (opt::Loop& sub_loop : - opt::make_range(++opt::TreeDFIterator<opt::Loop>(loop_), - opt::TreeDFIterator<opt::Loop>())) { - opt::Loop* cloned = new opt::Loop(context_); - if (opt::Loop* parent = loop_mapping[sub_loop.GetParent()]) + for (Loop& sub_loop : + make_range(++TreeDFIterator<Loop>(loop_), TreeDFIterator<Loop>())) { + Loop* cloned = new Loop(context_); + if (Loop* parent = loop_mapping[sub_loop.GetParent()]) parent->AddNestedLoop(cloned); loop_mapping[&sub_loop] = cloned; PopulateLoopDesc(cloned, &sub_loop, cloning_result); } - loop_desc_->AddLoopNest(std::unique_ptr<opt::Loop>(new_loop)); + loop_desc_->AddLoopNest(std::unique_ptr<Loop>(new_loop)); } // Populates |new_loop| descriptor according to |old_loop|'s one. void LoopUtils::PopulateLoopDesc( - opt::Loop* new_loop, opt::Loop* old_loop, + Loop* new_loop, Loop* old_loop, const LoopCloningResult& cloning_result) const { for (uint32_t bb_id : old_loop->GetBlocks()) { - opt::BasicBlock* bb = cloning_result.old_to_new_bb_.at(bb_id); + BasicBlock* bb = cloning_result.old_to_new_bb_.at(bb_id); new_loop->AddBasicBlock(bb); } new_loop->SetHeaderBlock( @@ -660,9 +649,9 @@ void LoopUtils::PopulateLoopDesc( if (old_loop->GetMergeBlock()) { auto it = cloning_result.old_to_new_bb_.find(old_loop->GetMergeBlock()->id()); - opt::BasicBlock* bb = it != cloning_result.old_to_new_bb_.end() - ? it->second - : old_loop->GetMergeBlock(); + BasicBlock* bb = it != cloning_result.old_to_new_bb_.end() + ? it->second + : old_loop->GetMergeBlock(); new_loop->SetMergeBlock(bb); } if (old_loop->GetPreHeaderBlock()) { @@ -675,16 +664,16 @@ void LoopUtils::PopulateLoopDesc( } // Class to gather some metrics about a region of interest. -void CodeMetrics::Analyze(const opt::Loop& loop) { - opt::CFG& cfg = *loop.GetContext()->cfg(); +void CodeMetrics::Analyze(const Loop& loop) { + CFG& cfg = *loop.GetContext()->cfg(); roi_size_ = 0; block_sizes_.clear(); for (uint32_t id : loop.GetBlocks()) { - const opt::BasicBlock* bb = cfg.block(id); + const BasicBlock* bb = cfg.block(id); size_t bb_size = 0; - bb->ForEachInst([&bb_size](const opt::Instruction* insn) { + bb->ForEachInst([&bb_size](const Instruction* insn) { if (insn->opcode() == SpvOpLabel) return; if (insn->IsNop()) return; if (insn->opcode() == SpvOpPhi) return; diff --git a/source/opt/loop_utils.h b/source/opt/loop_utils.h index a3845b4b..45cffd4b 100644 --- a/source/opt/loop_utils.h +++ b/source/opt/loop_utils.h @@ -28,7 +28,7 @@ namespace opt { // So far it counts the number of instructions in a ROI (excluding debug // and label instructions) per basic block and in total. struct CodeMetrics { - void Analyze(const opt::Loop& loop); + void Analyze(const Loop& loop); // The number of instructions per basic block in the ROI. std::unordered_map<uint32_t, size_t> block_sizes_; @@ -45,8 +45,8 @@ class LoopUtils { // Holds a auxiliary results of the loop cloning procedure. struct LoopCloningResult { using ValueMapTy = std::unordered_map<uint32_t, uint32_t>; - using BlockMapTy = std::unordered_map<uint32_t, opt::BasicBlock*>; - using PtrMap = std::unordered_map<opt::Instruction*, opt::Instruction*>; + using BlockMapTy = std::unordered_map<uint32_t, BasicBlock*>; + using PtrMap = std::unordered_map<Instruction*, Instruction*>; PtrMap ptr_map_; @@ -57,10 +57,10 @@ class LoopUtils { // Mapping between the cloned loop blocks to original one. BlockMapTy new_to_old_bb_; // List of cloned basic block. - std::vector<std::unique_ptr<opt::BasicBlock>> cloned_bb_; + std::vector<std::unique_ptr<BasicBlock>> cloned_bb_; }; - LoopUtils(opt::IRContext* context, opt::Loop* loop) + LoopUtils(IRContext* context, Loop* loop) : context_(context), loop_desc_( context->GetLoopDescriptor(loop->GetHeaderBlock()->GetParent())), @@ -111,15 +111,14 @@ class LoopUtils { // The function preserves the def/use, cfg and instr to block analyses. // The cloned loop nest will be added to the loop descriptor and will have // ownership. - opt::Loop* CloneLoop( - LoopCloningResult* cloning_result, - const std::vector<opt::BasicBlock*>& ordered_loop_blocks) const; + Loop* CloneLoop(LoopCloningResult* cloning_result, + const std::vector<BasicBlock*>& ordered_loop_blocks) const; // Clone |loop_| and remap its instructions, as above. Overload to compute // loop block ordering within method rather than taking in as parameter. - opt::Loop* CloneLoop(LoopCloningResult* cloning_result) const; + Loop* CloneLoop(LoopCloningResult* cloning_result) const; // Clone the |loop_| and make the new loop branch to the second loop on exit. - opt::Loop* CloneAndAttachLoopToHeader(LoopCloningResult* cloning_result); + Loop* CloneAndAttachLoopToHeader(LoopCloningResult* cloning_result); // Perfom a partial unroll of |loop| by given |factor|. This will copy the // body of the loop |factor| times. So a |factor| of one would give a new loop @@ -151,26 +150,26 @@ class LoopUtils { void Finalize(); // Returns the context associate to |loop_|. - opt::IRContext* GetContext() { return context_; } + IRContext* GetContext() { return context_; } // Returns the loop descriptor owning |loop_|. - opt::LoopDescriptor* GetLoopDescriptor() { return loop_desc_; } + LoopDescriptor* GetLoopDescriptor() { return loop_desc_; } // Returns the loop on which the object operates on. - opt::Loop* GetLoop() const { return loop_; } + Loop* GetLoop() const { return loop_; } // Returns the function that |loop_| belong to. - opt::Function* GetFunction() const { return &function_; } + Function* GetFunction() const { return &function_; } private: - opt::IRContext* context_; - opt::LoopDescriptor* loop_desc_; - opt::Loop* loop_; - opt::Function& function_; + IRContext* context_; + LoopDescriptor* loop_desc_; + Loop* loop_; + Function& function_; // Populates the loop nest of |new_loop| according to |loop_| nest. - void PopulateLoopNest(opt::Loop* new_loop, + void PopulateLoopNest(Loop* new_loop, const LoopCloningResult& cloning_result) const; // Populates |new_loop| descriptor according to |old_loop|'s one. - void PopulateLoopDesc(opt::Loop* new_loop, opt::Loop* old_loop, + void PopulateLoopDesc(Loop* new_loop, Loop* old_loop, const LoopCloningResult& cloning_result) const; }; diff --git a/source/opt/mem_pass.cpp b/source/opt/mem_pass.cpp index 5f226c4a..9292c358 100644 --- a/source/opt/mem_pass.cpp +++ b/source/opt/mem_pass.cpp @@ -33,7 +33,7 @@ const uint32_t kTypePointerTypeIdInIdx = 1; } // namespace -bool MemPass::IsBaseTargetType(const opt::Instruction* typeInst) const { +bool MemPass::IsBaseTargetType(const Instruction* typeInst) const { switch (typeInst->opcode()) { case SpvOpTypeInt: case SpvOpTypeFloat: @@ -51,7 +51,7 @@ bool MemPass::IsBaseTargetType(const opt::Instruction* typeInst) const { return false; } -bool MemPass::IsTargetType(const opt::Instruction* typeInst) const { +bool MemPass::IsTargetType(const Instruction* typeInst) const { if (IsBaseTargetType(typeInst)) return true; if (typeInst->opcode() == SpvOpTypeArray) { if (!IsTargetType( @@ -63,7 +63,7 @@ bool MemPass::IsTargetType(const opt::Instruction* typeInst) const { if (typeInst->opcode() != SpvOpTypeStruct) return false; // All struct members must be math type return typeInst->WhileEachInId([this](const uint32_t* tid) { - opt::Instruction* compTypeInst = get_def_use_mgr()->GetDef(*tid); + Instruction* compTypeInst = get_def_use_mgr()->GetDef(*tid); if (!IsTargetType(compTypeInst)) return false; return true; }); @@ -75,7 +75,7 @@ bool MemPass::IsNonPtrAccessChain(const SpvOp opcode) const { bool MemPass::IsPtr(uint32_t ptrId) { uint32_t varId = ptrId; - opt::Instruction* ptrInst = get_def_use_mgr()->GetDef(varId); + Instruction* ptrInst = get_def_use_mgr()->GetDef(varId); while (ptrInst->opcode() == SpvOpCopyObject) { varId = ptrInst->GetSingleWordInOperand(kCopyObjectOperandInIdx); ptrInst = get_def_use_mgr()->GetDef(varId); @@ -84,14 +84,14 @@ bool MemPass::IsPtr(uint32_t ptrId) { if (op == SpvOpVariable || IsNonPtrAccessChain(op)) return true; if (op != SpvOpFunctionParameter) return false; const uint32_t varTypeId = ptrInst->type_id(); - const opt::Instruction* varTypeInst = get_def_use_mgr()->GetDef(varTypeId); + const Instruction* varTypeInst = get_def_use_mgr()->GetDef(varTypeId); return varTypeInst->opcode() == SpvOpTypePointer; } -opt::Instruction* MemPass::GetPtr(uint32_t ptrId, uint32_t* varId) { +Instruction* MemPass::GetPtr(uint32_t ptrId, uint32_t* varId) { *varId = ptrId; - opt::Instruction* ptrInst = get_def_use_mgr()->GetDef(*varId); - opt::Instruction* varInst; + Instruction* ptrInst = get_def_use_mgr()->GetDef(*varId); + Instruction* varInst; if (ptrInst->opcode() != SpvOpVariable && ptrInst->opcode() != SpvOpFunctionParameter) { @@ -113,7 +113,7 @@ opt::Instruction* MemPass::GetPtr(uint32_t ptrId, uint32_t* varId) { return ptrInst; } -opt::Instruction* MemPass::GetPtr(opt::Instruction* ip, uint32_t* varId) { +Instruction* MemPass::GetPtr(Instruction* ip, uint32_t* varId) { assert(ip->opcode() == SpvOpStore || ip->opcode() == SpvOpLoad || ip->opcode() == SpvOpImageTexelPointer); @@ -123,7 +123,7 @@ opt::Instruction* MemPass::GetPtr(opt::Instruction* ip, uint32_t* varId) { } bool MemPass::HasOnlyNamesAndDecorates(uint32_t id) const { - return get_def_use_mgr()->WhileEachUser(id, [this](opt::Instruction* user) { + return get_def_use_mgr()->WhileEachUser(id, [this](Instruction* user) { SpvOp op = user->opcode(); if (op != SpvOpName && !IsNonTypeDecorate(op)) { return false; @@ -132,13 +132,12 @@ bool MemPass::HasOnlyNamesAndDecorates(uint32_t id) const { }); } -void MemPass::KillAllInsts(opt::BasicBlock* bp, bool killLabel) { +void MemPass::KillAllInsts(BasicBlock* bp, bool killLabel) { bp->KillAllInsts(killLabel); } bool MemPass::HasLoads(uint32_t varId) const { - return !get_def_use_mgr()->WhileEachUser(varId, [this]( - opt::Instruction* user) { + return !get_def_use_mgr()->WhileEachUser(varId, [this](Instruction* user) { SpvOp op = user->opcode(); // TODO(): The following is slightly conservative. Could be // better handling of non-store/name. @@ -154,12 +153,12 @@ bool MemPass::HasLoads(uint32_t varId) const { } bool MemPass::IsLiveVar(uint32_t varId) const { - const opt::Instruction* varInst = get_def_use_mgr()->GetDef(varId); + const Instruction* varInst = get_def_use_mgr()->GetDef(varId); // assume live if not a variable eg. function parameter if (varInst->opcode() != SpvOpVariable) return true; // non-function scope vars are live const uint32_t varTypeId = varInst->type_id(); - const opt::Instruction* varTypeInst = get_def_use_mgr()->GetDef(varTypeId); + const Instruction* varTypeInst = get_def_use_mgr()->GetDef(varTypeId); if (varTypeInst->GetSingleWordInOperand(kTypePointerStorageClassInIdx) != SpvStorageClassFunction) return true; @@ -167,8 +166,8 @@ bool MemPass::IsLiveVar(uint32_t varId) const { return HasLoads(varId); } -void MemPass::AddStores(uint32_t ptr_id, std::queue<opt::Instruction*>* insts) { - get_def_use_mgr()->ForEachUser(ptr_id, [this, insts](opt::Instruction* user) { +void MemPass::AddStores(uint32_t ptr_id, std::queue<Instruction*>* insts) { + get_def_use_mgr()->ForEachUser(ptr_id, [this, insts](Instruction* user) { SpvOp op = user->opcode(); if (IsNonPtrAccessChain(op)) { AddStores(user->result_id(), insts); @@ -178,12 +177,12 @@ void MemPass::AddStores(uint32_t ptr_id, std::queue<opt::Instruction*>* insts) { }); } -void MemPass::DCEInst(opt::Instruction* inst, - const function<void(opt::Instruction*)>& call_back) { - std::queue<opt::Instruction*> deadInsts; +void MemPass::DCEInst(Instruction* inst, + const function<void(Instruction*)>& call_back) { + std::queue<Instruction*> deadInsts; deadInsts.push(inst); while (!deadInsts.empty()) { - opt::Instruction* di = deadInsts.front(); + Instruction* di = deadInsts.front(); // Don't delete labels if (di->opcode() == SpvOpLabel) { deadInsts.pop(); @@ -203,7 +202,7 @@ void MemPass::DCEInst(opt::Instruction* inst, // to the dead instruction queue. for (auto id : ids) if (HasOnlyNamesAndDecorates(id)) { - opt::Instruction* odi = get_def_use_mgr()->GetDef(id); + Instruction* odi = get_def_use_mgr()->GetDef(id); if (context()->IsCombinatorInstruction(odi)) deadInsts.push(odi); } // if a load was deleted and it was the variable's @@ -216,8 +215,7 @@ void MemPass::DCEInst(opt::Instruction* inst, MemPass::MemPass() {} bool MemPass::HasOnlySupportedRefs(uint32_t varId) { - return get_def_use_mgr()->WhileEachUser(varId, [this]( - opt::Instruction* user) { + return get_def_use_mgr()->WhileEachUser(varId, [this](Instruction* user) { SpvOp op = user->opcode(); if (op != SpvOpStore && op != SpvOpLoad && op != SpvOpName && !IsNonTypeDecorate(op)) { @@ -231,8 +229,8 @@ uint32_t MemPass::Type2Undef(uint32_t type_id) { const auto uitr = type2undefs_.find(type_id); if (uitr != type2undefs_.end()) return uitr->second; const uint32_t undefId = TakeNextId(); - std::unique_ptr<opt::Instruction> undef_inst( - new opt::Instruction(context(), SpvOpUndef, type_id, undefId, {})); + std::unique_ptr<Instruction> undef_inst( + new Instruction(context(), SpvOpUndef, type_id, undefId, {})); get_def_use_mgr()->AnalyzeInstDefUse(&*undef_inst); get_module()->AddGlobalValue(std::move(undef_inst)); type2undefs_[type_id] = undefId; @@ -247,10 +245,10 @@ bool MemPass::IsTargetVar(uint32_t varId) { if (seen_non_target_vars_.find(varId) != seen_non_target_vars_.end()) return false; if (seen_target_vars_.find(varId) != seen_target_vars_.end()) return true; - const opt::Instruction* varInst = get_def_use_mgr()->GetDef(varId); + const Instruction* varInst = get_def_use_mgr()->GetDef(varId); if (varInst->opcode() != SpvOpVariable) return false; const uint32_t varTypeId = varInst->type_id(); - const opt::Instruction* varTypeInst = get_def_use_mgr()->GetDef(varTypeId); + const Instruction* varTypeInst = get_def_use_mgr()->GetDef(varTypeId); if (varTypeInst->GetSingleWordInOperand(kTypePointerStorageClassInIdx) != SpvStorageClassFunction) { seen_non_target_vars_.insert(varId); @@ -258,7 +256,7 @@ bool MemPass::IsTargetVar(uint32_t varId) { } const uint32_t varPteTypeId = varTypeInst->GetSingleWordInOperand(kTypePointerTypeIdInIdx); - opt::Instruction* varPteTypeInst = get_def_use_mgr()->GetDef(varPteTypeId); + Instruction* varPteTypeInst = get_def_use_mgr()->GetDef(varPteTypeId); if (!IsTargetType(varPteTypeInst)) { seen_non_target_vars_.insert(varId); return false; @@ -312,9 +310,8 @@ bool MemPass::IsTargetVar(uint32_t varId) { // [ ... ] // %30 = OpPhi %int %int_42 %13 %50 %14 %50 %15 void MemPass::RemovePhiOperands( - opt::Instruction* phi, - const unordered_set<opt::BasicBlock*>& reachable_blocks) { - std::vector<opt::Operand> keep_operands; + Instruction* phi, const unordered_set<BasicBlock*>& reachable_blocks) { + std::vector<Operand> keep_operands; uint32_t type_id = 0; // The id of an undefined value we've generated. uint32_t undef_id = 0; @@ -334,7 +331,7 @@ void MemPass::RemovePhiOperands( assert(i % 2 == 0 && i < phi->NumOperands() - 1 && "malformed Phi arguments"); - opt::BasicBlock* in_block = cfg()->block(phi->GetSingleWordOperand(i + 1)); + BasicBlock* in_block = cfg()->block(phi->GetSingleWordOperand(i + 1)); if (reachable_blocks.find(in_block) == reachable_blocks.end()) { // If the incoming block is unreachable, remove both operands as this // means that the |phi| has lost an incoming edge. @@ -344,8 +341,8 @@ void MemPass::RemovePhiOperands( // In all other cases, the operand must be kept but may need to be changed. uint32_t arg_id = phi->GetSingleWordOperand(i); - opt::Instruction* arg_def_instr = get_def_use_mgr()->GetDef(arg_id); - opt::BasicBlock* def_block = context()->get_instr_block(arg_def_instr); + Instruction* arg_def_instr = get_def_use_mgr()->GetDef(arg_id); + BasicBlock* def_block = context()->get_instr_block(arg_def_instr); if (def_block && reachable_blocks.find(def_block) == reachable_blocks.end()) { // If the current |phi| argument was defined in an unreachable block, it @@ -356,7 +353,7 @@ void MemPass::RemovePhiOperands( undef_id = Type2Undef(type_id); } keep_operands.push_back( - opt::Operand(spv_operand_type_t::SPV_OPERAND_TYPE_ID, {undef_id})); + Operand(spv_operand_type_t::SPV_OPERAND_TYPE_ID, {undef_id})); } else { // Otherwise, the argument comes from a reachable block or from no block // at all (meaning that it was defined in the global section of the @@ -374,11 +371,11 @@ void MemPass::RemovePhiOperands( context()->AnalyzeUses(phi); } -void MemPass::RemoveBlock(opt::Function::iterator* bi) { +void MemPass::RemoveBlock(Function::iterator* bi) { auto& rm_block = **bi; // Remove instructions from the block. - rm_block.ForEachInst([&rm_block, this](opt::Instruction* inst) { + rm_block.ForEachInst([&rm_block, this](Instruction* inst) { // Note that we do not kill the block label instruction here. The label // instruction is needed to identify the block, which is needed by the // removal of phi operands. @@ -394,13 +391,13 @@ void MemPass::RemoveBlock(opt::Function::iterator* bi) { *bi = bi->Erase(); } -bool MemPass::RemoveUnreachableBlocks(opt::Function* func) { +bool MemPass::RemoveUnreachableBlocks(Function* func) { bool modified = false; // Mark reachable all blocks reachable from the function's entry block. - std::unordered_set<opt::BasicBlock*> reachable_blocks; - std::unordered_set<opt::BasicBlock*> visited_blocks; - std::queue<opt::BasicBlock*> worklist; + std::unordered_set<BasicBlock*> reachable_blocks; + std::unordered_set<BasicBlock*> visited_blocks; + std::queue<BasicBlock*> worklist; reachable_blocks.insert(func->entry().get()); // Initially mark the function entry point as reachable. @@ -418,11 +415,11 @@ bool MemPass::RemoveUnreachableBlocks(opt::Function* func) { // Transitively mark all blocks reachable from the entry as reachable. while (!worklist.empty()) { - opt::BasicBlock* block = worklist.front(); + BasicBlock* block = worklist.front(); worklist.pop(); // All the successors of a live block are also live. - static_cast<const opt::BasicBlock*>(block)->ForEachSuccessorLabel( + static_cast<const BasicBlock*>(block)->ForEachSuccessorLabel( mark_reachable); // All the Merge and ContinueTarget blocks of a live block are also live. @@ -440,7 +437,7 @@ bool MemPass::RemoveUnreachableBlocks(opt::Function* func) { // If the block is reachable and has Phi instructions, remove all // operands from its Phi instructions that reference unreachable blocks. // If the block has no Phi instructions, this is a no-op. - block.ForEachPhiInst([&reachable_blocks, this](opt::Instruction* phi) { + block.ForEachPhiInst([&reachable_blocks, this](Instruction* phi) { RemovePhiOperands(phi, reachable_blocks); }); } @@ -458,13 +455,13 @@ bool MemPass::RemoveUnreachableBlocks(opt::Function* func) { return modified; } -bool MemPass::CFGCleanup(opt::Function* func) { +bool MemPass::CFGCleanup(Function* func) { bool modified = false; modified |= RemoveUnreachableBlocks(func); return modified; } -void MemPass::CollectTargetVars(opt::Function* func) { +void MemPass::CollectTargetVars(Function* func) { seen_target_vars_.clear(); seen_non_target_vars_.clear(); type2undefs_.clear(); diff --git a/source/opt/mem_pass.h b/source/opt/mem_pass.h index 988c4bea..a142df53 100644 --- a/source/opt/mem_pass.h +++ b/source/opt/mem_pass.h @@ -48,7 +48,7 @@ class MemPass : public Pass { // Given a load or store |ip|, return the pointer instruction. // Also return the base variable's id in |varId|. If no base variable is // found, |varId| will be 0. - opt::Instruction* GetPtr(opt::Instruction* ip, uint32_t* varId); + Instruction* GetPtr(Instruction* ip, uint32_t* varId); // Return true if |varId| is a previously identified target variable. // Return false if |varId| is a previously identified non-target variable. @@ -65,19 +65,19 @@ class MemPass : public Pass { // Collect target SSA variables. This traverses all the loads and stores in // function |func| looking for variables that can be replaced with SSA IDs. It // populates the sets |seen_target_vars_| and |seen_non_target_vars_|. - void CollectTargetVars(opt::Function* func); + void CollectTargetVars(Function* func); protected: MemPass(); // Returns true if |typeInst| is a scalar type // or a vector or matrix - bool IsBaseTargetType(const opt::Instruction* typeInst) const; + bool IsBaseTargetType(const Instruction* typeInst) const; // Returns true if |typeInst| is a math type or a struct or array // of a math type. // TODO(): Add more complex types to convert - bool IsTargetType(const opt::Instruction* typeInst) const; + bool IsTargetType(const Instruction* typeInst) const; // Returns true if |opcode| is a non-ptr access chain op bool IsNonPtrAccessChain(const SpvOp opcode) const; @@ -89,14 +89,14 @@ class MemPass : public Pass { // Given the id of a pointer |ptrId|, return the top-most non-CopyObj. // Also return the base variable's id in |varId|. If no base variable is // found, |varId| will be 0. - opt::Instruction* GetPtr(uint32_t ptrId, uint32_t* varId); + Instruction* GetPtr(uint32_t ptrId, uint32_t* varId); // Return true if all uses of |id| are only name or decorate ops. bool HasOnlyNamesAndDecorates(uint32_t id) const; // Kill all instructions in block |bp|. Whether or not to kill the label is // indicated by |killLabel|. - void KillAllInsts(opt::BasicBlock* bp, bool killLabel = true); + void KillAllInsts(BasicBlock* bp, bool killLabel = true); // Return true if any instruction loads from |varId| bool HasLoads(uint32_t varId) const; @@ -106,16 +106,15 @@ class MemPass : public Pass { bool IsLiveVar(uint32_t varId) const; // Add stores using |ptr_id| to |insts| - void AddStores(uint32_t ptr_id, std::queue<opt::Instruction*>* insts); + void AddStores(uint32_t ptr_id, std::queue<Instruction*>* insts); // Delete |inst| and iterate DCE on all its operands if they are now // useless. If a load is deleted and its variable has no other loads, // delete all its variable's stores. - void DCEInst(opt::Instruction* inst, - const std::function<void(opt::Instruction*)>&); + void DCEInst(Instruction* inst, const std::function<void(Instruction*)>&); // Call all the cleanup helper functions on |func|. - bool CFGCleanup(opt::Function* func); + bool CFGCleanup(Function* func); // Return true if |op| is supported decorate. inline bool IsNonTypeDecorate(uint32_t op) const { @@ -142,17 +141,17 @@ class MemPass : public Pass { bool HasOnlySupportedRefs(uint32_t varId); // Remove all the unreachable basic blocks in |func|. - bool RemoveUnreachableBlocks(opt::Function* func); + bool RemoveUnreachableBlocks(Function* func); // Remove the block pointed by the iterator |*bi|. This also removes // all the instructions in the pointed-to block. - void RemoveBlock(opt::Function::iterator* bi); + void RemoveBlock(Function::iterator* bi); // Remove Phi operands in |phi| that are coming from blocks not in // |reachable_blocks|. void RemovePhiOperands( - opt::Instruction* phi, - const std::unordered_set<opt::BasicBlock*>& reachable_blocks); + Instruction* phi, + const std::unordered_set<BasicBlock*>& reachable_blocks); // Map from type to undef std::unordered_map<uint32_t, uint32_t> type2undefs_; diff --git a/source/opt/merge_return_pass.cpp b/source/opt/merge_return_pass.cpp index b80ddf99..6d955527 100644 --- a/source/opt/merge_return_pass.cpp +++ b/source/opt/merge_return_pass.cpp @@ -28,8 +28,7 @@ Pass::Status MergeReturnPass::Process() { bool is_shader = context()->get_feature_mgr()->HasCapability(SpvCapabilityShader); for (auto& function : *get_module()) { - std::vector<opt::BasicBlock*> return_blocks = - CollectReturnBlocks(&function); + std::vector<BasicBlock*> return_blocks = CollectReturnBlocks(&function); if (return_blocks.size() <= 1) continue; function_ = &function; @@ -49,9 +48,8 @@ Pass::Status MergeReturnPass::Process() { } void MergeReturnPass::ProcessStructured( - opt::Function* function, - const std::vector<opt::BasicBlock*>& return_blocks) { - std::list<opt::BasicBlock*> order; + Function* function, const std::vector<BasicBlock*>& return_blocks) { + std::list<BasicBlock*> order; cfg()->ComputeStructuredOrder(function, &*function->begin(), &order); // Create the new return block @@ -78,8 +76,8 @@ void MergeReturnPass::ProcessStructured( ProcessStructuredBlock(block); // Generate state for next block - if (opt::Instruction* mergeInst = block->GetMergeInst()) { - opt::Instruction* loopMergeInst = block->GetLoopMergeInst(); + if (Instruction* mergeInst = block->GetMergeInst()) { + Instruction* loopMergeInst = block->GetLoopMergeInst(); if (!loopMergeInst) loopMergeInst = state_.back().LoopMergeInst(); state_.emplace_back(loopMergeInst, mergeInst); } @@ -96,12 +94,12 @@ void MergeReturnPass::ProcessStructured( void MergeReturnPass::CreateReturnBlock() { // Create a label for the new return block - std::unique_ptr<opt::Instruction> return_label( - new opt::Instruction(context(), SpvOpLabel, 0u, TakeNextId(), {})); + std::unique_ptr<Instruction> return_label( + new Instruction(context(), SpvOpLabel, 0u, TakeNextId(), {})); // Create the new basic block - std::unique_ptr<opt::BasicBlock> return_block( - new opt::BasicBlock(std::move(return_label))); + std::unique_ptr<BasicBlock> return_block( + new BasicBlock(std::move(return_label))); function_->AddBasicBlock(std::move(return_block)); final_return_block_ = &*(--function_->end()); context()->AnalyzeDefUse(final_return_block_->GetLabelInst()); @@ -110,33 +108,33 @@ void MergeReturnPass::CreateReturnBlock() { final_return_block_->SetParent(function_); } -void MergeReturnPass::CreateReturn(opt::BasicBlock* block) { +void MergeReturnPass::CreateReturn(BasicBlock* block) { AddReturnValue(); if (return_value_) { // Load and return the final return value uint32_t loadId = TakeNextId(); - block->AddInstruction(MakeUnique<opt::Instruction>( + block->AddInstruction(MakeUnique<Instruction>( context(), SpvOpLoad, function_->type_id(), loadId, - std::initializer_list<opt::Operand>{ + std::initializer_list<Operand>{ {SPV_OPERAND_TYPE_ID, {return_value_->result_id()}}})); - opt::Instruction* var_inst = block->terminator(); + Instruction* var_inst = block->terminator(); context()->AnalyzeDefUse(var_inst); context()->set_instr_block(var_inst, block); - block->AddInstruction(MakeUnique<opt::Instruction>( + block->AddInstruction(MakeUnique<Instruction>( context(), SpvOpReturnValue, 0, 0, - std::initializer_list<opt::Operand>{{SPV_OPERAND_TYPE_ID, {loadId}}})); + std::initializer_list<Operand>{{SPV_OPERAND_TYPE_ID, {loadId}}})); context()->AnalyzeDefUse(block->terminator()); context()->set_instr_block(block->terminator(), block); } else { - block->AddInstruction(MakeUnique<opt::Instruction>(context(), SpvOpReturn)); + block->AddInstruction(MakeUnique<Instruction>(context(), SpvOpReturn)); context()->AnalyzeDefUse(block->terminator()); context()->set_instr_block(block->terminator(), block); } } -void MergeReturnPass::ProcessStructuredBlock(opt::BasicBlock* block) { +void MergeReturnPass::ProcessStructuredBlock(BasicBlock* block) { SpvOp tail_opcode = block->tail()->opcode(); if (tail_opcode == SpvOpReturn || tail_opcode == SpvOpReturnValue) { if (!return_flag_) { @@ -157,7 +155,7 @@ void MergeReturnPass::ProcessStructuredBlock(opt::BasicBlock* block) { } } -void MergeReturnPass::BranchToBlock(opt::BasicBlock* block, uint32_t target) { +void MergeReturnPass::BranchToBlock(BasicBlock* block, uint32_t target) { if (block->tail()->opcode() == SpvOpReturn || block->tail()->opcode() == SpvOpReturnValue) { RecordReturned(block); @@ -168,8 +166,8 @@ void MergeReturnPass::BranchToBlock(opt::BasicBlock* block, uint32_t target) { // // A new edge is being added from |block| to |target|, so go through // |target|'s phi nodes add an undef incoming value for |block|. - opt::BasicBlock* target_block = context()->get_instr_block(target); - target_block->ForEachPhiInst([this, block](opt::Instruction* inst) { + BasicBlock* target_block = context()->get_instr_block(target); + target_block->ForEachPhiInst([this, block](Instruction* inst) { uint32_t undefId = Type2Undef(inst->type_id()); inst->AddOperand({SPV_OPERAND_TYPE_ID, {undefId}}); inst->AddOperand({SPV_OPERAND_TYPE_ID, {block->id()}}); @@ -182,25 +180,24 @@ void MergeReturnPass::BranchToBlock(opt::BasicBlock* block, uint32_t target) { context()->get_instr_block(target_pred[0])); } - opt::Instruction* return_inst = block->terminator(); + Instruction* return_inst = block->terminator(); return_inst->SetOpcode(SpvOpBranch); return_inst->ReplaceOperands({{SPV_OPERAND_TYPE_ID, {target}}}); context()->get_def_use_mgr()->AnalyzeInstDefUse(return_inst); cfg()->AddEdge(block->id(), target); } -void MergeReturnPass::CreatePhiNodesForInst(opt::BasicBlock* merge_block, +void MergeReturnPass::CreatePhiNodesForInst(BasicBlock* merge_block, uint32_t predecessor, - opt::Instruction& inst) { - opt::DominatorAnalysis* dom_tree = + Instruction& inst) { + DominatorAnalysis* dom_tree = context()->GetDominatorAnalysis(merge_block->GetParent()); - opt::BasicBlock* inst_bb = context()->get_instr_block(&inst); + BasicBlock* inst_bb = context()->get_instr_block(&inst); if (inst.result_id() != 0) { - std::vector<opt::Instruction*> users_to_update; + std::vector<Instruction*> users_to_update; context()->get_def_use_mgr()->ForEachUser( - &inst, - [&users_to_update, &dom_tree, inst_bb, this](opt::Instruction* user) { + &inst, [&users_to_update, &dom_tree, inst_bb, this](Instruction* user) { if (!dom_tree->Dominates(inst_bb, context()->get_instr_block(user))) { users_to_update.push_back(user); } @@ -213,7 +210,7 @@ void MergeReturnPass::CreatePhiNodesForInst(opt::BasicBlock* merge_block, // There is at least one values that needs to be replaced. // First create the OpPhi instruction. InstructionBuilder builder(context(), &*merge_block->begin(), - opt::IRContext::kAnalysisDefUse); + IRContext::kAnalysisDefUse); uint32_t undef_id = Type2Undef(inst.type_id()); std::vector<uint32_t> phi_operands; @@ -230,11 +227,11 @@ void MergeReturnPass::CreatePhiNodesForInst(opt::BasicBlock* merge_block, } } - opt::Instruction* new_phi = builder.AddPhi(inst.type_id(), phi_operands); + Instruction* new_phi = builder.AddPhi(inst.type_id(), phi_operands); uint32_t result_of_phi = new_phi->result_id(); // Update all of the users to use the result of the new OpPhi. - for (opt::Instruction* user : users_to_update) { + for (Instruction* user : users_to_update) { user->ForEachInId([&inst, result_of_phi](uint32_t* id) { if (*id == inst.result_id()) { *id = result_of_phi; @@ -246,26 +243,25 @@ void MergeReturnPass::CreatePhiNodesForInst(opt::BasicBlock* merge_block, } void MergeReturnPass::PredicateBlocks( - const std::vector<opt::BasicBlock*>& return_blocks) { + const std::vector<BasicBlock*>& return_blocks) { // The CFG is being modified as the function proceeds so avoid caching // successors. - std::vector<opt::BasicBlock*> stack; - auto add_successors = [this, &stack](opt::BasicBlock* block) { - const opt::BasicBlock* const_block = - const_cast<const opt::BasicBlock*>(block); + std::vector<BasicBlock*> stack; + auto add_successors = [this, &stack](BasicBlock* block) { + const BasicBlock* const_block = const_cast<const BasicBlock*>(block); const_block->ForEachSuccessorLabel([this, &stack](const uint32_t idx) { stack.push_back(context()->get_instr_block(idx)); }); }; - std::unordered_set<opt::BasicBlock*> seen; - std::unordered_set<opt::BasicBlock*> predicated; + std::unordered_set<BasicBlock*> seen; + std::unordered_set<BasicBlock*> predicated; for (auto b : return_blocks) { seen.clear(); add_successors(b); while (!stack.empty()) { - opt::BasicBlock* block = stack.back(); + BasicBlock* block = stack.back(); assert(block); stack.pop_back(); @@ -275,7 +271,7 @@ void MergeReturnPass::PredicateBlocks( if (!predicated.insert(block).second) continue; // Skip structured subgraphs. - opt::BasicBlock* next = block; + BasicBlock* next = block; while (next->GetMergeInst()) { next = context()->get_instr_block(next->MergeBlockIdIfAny()); } @@ -285,16 +281,16 @@ void MergeReturnPass::PredicateBlocks( } } -bool MergeReturnPass::RequiresPredication( - const opt::BasicBlock* block, const opt::BasicBlock* tail_block) const { +bool MergeReturnPass::RequiresPredication(const BasicBlock* block, + const BasicBlock* tail_block) const { // This is intentionally conservative. // TODO(alanbaker): re-visit this when more performance data is available. if (block != tail_block) return true; bool requires_predicate = false; - block->ForEachInst([&requires_predicate](const opt::Instruction* inst) { + block->ForEachInst([&requires_predicate](const Instruction* inst) { if (inst->opcode() != SpvOpPhi && inst->opcode() != SpvOpLabel && - !opt::IsTerminatorInst(inst->opcode())) { + !IsTerminatorInst(inst->opcode())) { requires_predicate = true; } }); @@ -302,15 +298,15 @@ bool MergeReturnPass::RequiresPredication( } void MergeReturnPass::PredicateBlock( - opt::BasicBlock* block, opt::BasicBlock* tail_block, - std::unordered_set<opt::BasicBlock*>* predicated) { + BasicBlock* block, BasicBlock* tail_block, + std::unordered_set<BasicBlock*>* predicated) { if (!RequiresPredication(block, tail_block)) { return; } // Make sure the cfg is build here. If we don't then it becomes very hard to // know which new blocks need to be updated. - context()->BuildInvalidAnalyses(opt::IRContext::kAnalysisCFG); + context()->BuildInvalidAnalyses(IRContext::kAnalysisCFG); // When predicating, be aware of whether this block is a header block, a merge // block or both. @@ -336,9 +332,9 @@ void MergeReturnPass::PredicateBlock( // Forget about the edges leaving block. They will be removed. cfg()->RemoveSuccessorEdges(block); - std::unique_ptr<opt::BasicBlock> new_block( + std::unique_ptr<BasicBlock> new_block( block->SplitBasicBlock(context(), TakeNextId(), iter)); - opt::BasicBlock* old_body = + BasicBlock* old_body = function_->InsertBasicBlockAfter(std::move(new_block), block); predicated->insert(old_body); @@ -346,21 +342,20 @@ void MergeReturnPass::PredicateBlock( tail_block = old_body; } - const opt::BasicBlock* const_old_body = - static_cast<const opt::BasicBlock*>(old_body); + const BasicBlock* const_old_body = static_cast<const BasicBlock*>(old_body); const_old_body->ForEachSuccessorLabel( [old_body, block, this](const uint32_t label) { - opt::BasicBlock* target_bb = context()->get_instr_block(label); + BasicBlock* target_bb = context()->get_instr_block(label); if (MarkedSinglePred(target_bb) == block) { MarkForNewPhiNodes(target_bb, old_body); } }); - std::unique_ptr<opt::BasicBlock> new_merge_block(new opt::BasicBlock( - MakeUnique<opt::Instruction>(context(), SpvOpLabel, 0, TakeNextId(), - std::initializer_list<opt::Operand>{}))); + std::unique_ptr<BasicBlock> new_merge_block(new BasicBlock( + MakeUnique<Instruction>(context(), SpvOpLabel, 0, TakeNextId(), + std::initializer_list<Operand>{}))); - opt::BasicBlock* new_merge = + BasicBlock* new_merge = function_->InsertBasicBlockAfter(std::move(new_merge_block), tail_block); predicated->insert(new_merge); new_merge->SetParent(function_); @@ -374,8 +369,8 @@ void MergeReturnPass::PredicateBlock( // Move the tail branch into the new merge and fix the mapping. If a single // block is being predicated then its branch was moved to the old body // previously. - std::unique_ptr<opt::Instruction> inst; - opt::Instruction* i = tail_block->terminator(); + std::unique_ptr<Instruction> inst; + Instruction* i = tail_block->terminator(); cfg()->RemoveSuccessorEdges(tail_block); get_def_use_mgr()->ClearInst(i); inst.reset(std::move(i)); @@ -386,10 +381,10 @@ void MergeReturnPass::PredicateBlock( // Add a branch to the new merge. If we jumped multiple blocks, the branch is // added to tail_block, otherwise the branch belongs in old_body. - tail_block->AddInstruction(MakeUnique<opt::Instruction>( - context(), SpvOpBranch, 0, 0, - std::initializer_list<opt::Operand>{ - {SPV_OPERAND_TYPE_ID, {new_merge->id()}}})); + tail_block->AddInstruction( + MakeUnique<Instruction>(context(), SpvOpBranch, 0, 0, + std::initializer_list<Operand>{ + {SPV_OPERAND_TYPE_ID, {new_merge->id()}}})); get_def_use_mgr()->AnalyzeInstUse(tail_block->terminator()); context()->set_instr_block(tail_block->terminator(), tail_block); @@ -403,30 +398,28 @@ void MergeReturnPass::PredicateBlock( uint32_t bool_id = context()->get_type_mgr()->GetId(&bool_type); assert(bool_id != 0); uint32_t load_id = TakeNextId(); - block->AddInstruction(MakeUnique<opt::Instruction>( + block->AddInstruction(MakeUnique<Instruction>( context(), SpvOpLoad, bool_id, load_id, - std::initializer_list<opt::Operand>{ + std::initializer_list<Operand>{ {SPV_OPERAND_TYPE_ID, {return_flag_->result_id()}}})); get_def_use_mgr()->AnalyzeInstDefUse(block->terminator()); context()->set_instr_block(block->terminator(), block); // 2. Declare the merge block - block->AddInstruction( - MakeUnique<opt::Instruction>(context(), SpvOpSelectionMerge, 0, 0, - std::initializer_list<opt::Operand>{ - {SPV_OPERAND_TYPE_ID, {new_merge->id()}}, - {SPV_OPERAND_TYPE_SELECTION_CONTROL, - {SpvSelectionControlMaskNone}}})); + block->AddInstruction(MakeUnique<Instruction>( + context(), SpvOpSelectionMerge, 0, 0, + std::initializer_list<Operand>{{SPV_OPERAND_TYPE_ID, {new_merge->id()}}, + {SPV_OPERAND_TYPE_SELECTION_CONTROL, + {SpvSelectionControlMaskNone}}})); get_def_use_mgr()->AnalyzeInstUse(block->terminator()); context()->set_instr_block(block->terminator(), block); // 3. Branch to new merge (true) or old body (false) - block->AddInstruction(MakeUnique<opt::Instruction>( + block->AddInstruction(MakeUnique<Instruction>( context(), SpvOpBranchConditional, 0, 0, - std::initializer_list<opt::Operand>{ - {SPV_OPERAND_TYPE_ID, {load_id}}, - {SPV_OPERAND_TYPE_ID, {new_merge->id()}}, - {SPV_OPERAND_TYPE_ID, {old_body->id()}}})); + std::initializer_list<Operand>{{SPV_OPERAND_TYPE_ID, {load_id}}, + {SPV_OPERAND_TYPE_ID, {new_merge->id()}}, + {SPV_OPERAND_TYPE_ID, {old_body->id()}}})); get_def_use_mgr()->AnalyzeInstUse(block->terminator()); context()->set_instr_block(block->terminator(), block); @@ -444,7 +437,7 @@ void MergeReturnPass::PredicateBlock( MarkForNewPhiNodes(new_merge, tail_block); } -void MergeReturnPass::RecordReturned(opt::BasicBlock* block) { +void MergeReturnPass::RecordReturned(BasicBlock* block) { if (block->tail()->opcode() != SpvOpReturn && block->tail()->opcode() != SpvOpReturnValue) return; @@ -463,19 +456,19 @@ void MergeReturnPass::RecordReturned(opt::BasicBlock* block) { context()->UpdateDefUse(constant_true_); } - std::unique_ptr<opt::Instruction> return_store(new opt::Instruction( + std::unique_ptr<Instruction> return_store(new Instruction( context(), SpvOpStore, 0, 0, - std::initializer_list<opt::Operand>{ + std::initializer_list<Operand>{ {SPV_OPERAND_TYPE_ID, {return_flag_->result_id()}}, {SPV_OPERAND_TYPE_ID, {constant_true_->result_id()}}})); - opt::Instruction* store_inst = + Instruction* store_inst = &*block->tail().InsertBefore(std::move(return_store)); context()->set_instr_block(store_inst, block); context()->AnalyzeDefUse(store_inst); } -void MergeReturnPass::RecordReturnValue(opt::BasicBlock* block) { +void MergeReturnPass::RecordReturnValue(BasicBlock* block) { auto terminator = *block->tail(); if (terminator.opcode() != SpvOpReturnValue) { return; @@ -484,13 +477,13 @@ void MergeReturnPass::RecordReturnValue(opt::BasicBlock* block) { assert(return_value_ && "Did not generate the variable to hold the return value."); - std::unique_ptr<opt::Instruction> value_store(new opt::Instruction( + std::unique_ptr<Instruction> value_store(new Instruction( context(), SpvOpStore, 0, 0, - std::initializer_list<opt::Operand>{ + std::initializer_list<Operand>{ {SPV_OPERAND_TYPE_ID, {return_value_->result_id()}}, {SPV_OPERAND_TYPE_ID, {terminator.GetSingleWordInOperand(0u)}}})); - opt::Instruction* store_inst = + Instruction* store_inst = &*block->tail().InsertBefore(std::move(value_store)); context()->set_instr_block(store_inst, block); context()->AnalyzeDefUse(store_inst); @@ -507,14 +500,14 @@ void MergeReturnPass::AddReturnValue() { return_type_id, SpvStorageClassFunction); uint32_t var_id = TakeNextId(); - std::unique_ptr<opt::Instruction> returnValue(new opt::Instruction( + std::unique_ptr<Instruction> returnValue(new Instruction( context(), SpvOpVariable, return_ptr_type, var_id, - std::initializer_list<opt::Operand>{ + std::initializer_list<Operand>{ {SPV_OPERAND_TYPE_STORAGE_CLASS, {SpvStorageClassFunction}}})); auto insert_iter = function_->begin()->begin(); insert_iter.InsertBefore(std::move(returnValue)); - opt::BasicBlock* entry_block = &*function_->begin(); + BasicBlock* entry_block = &*function_->begin(); return_value_ = &*entry_block->begin(); context()->AnalyzeDefUse(return_value_); context()->set_instr_block(return_value_, entry_block); @@ -539,26 +532,26 @@ void MergeReturnPass::AddReturnFlag() { type_mgr->FindPointerToType(bool_id, SpvStorageClassFunction); uint32_t var_id = TakeNextId(); - std::unique_ptr<opt::Instruction> returnFlag(new opt::Instruction( + std::unique_ptr<Instruction> returnFlag(new Instruction( context(), SpvOpVariable, bool_ptr_id, var_id, - std::initializer_list<opt::Operand>{ + std::initializer_list<Operand>{ {SPV_OPERAND_TYPE_STORAGE_CLASS, {SpvStorageClassFunction}}, {SPV_OPERAND_TYPE_ID, {const_false_id}}})); auto insert_iter = function_->begin()->begin(); insert_iter.InsertBefore(std::move(returnFlag)); - opt::BasicBlock* entry_block = &*function_->begin(); + BasicBlock* entry_block = &*function_->begin(); return_flag_ = &*entry_block->begin(); context()->AnalyzeDefUse(return_flag_); context()->set_instr_block(return_flag_, entry_block); } -std::vector<opt::BasicBlock*> MergeReturnPass::CollectReturnBlocks( - opt::Function* function) { - std::vector<opt::BasicBlock*> return_blocks; +std::vector<BasicBlock*> MergeReturnPass::CollectReturnBlocks( + Function* function) { + std::vector<BasicBlock*> return_blocks; for (auto& block : *function) { - opt::Instruction& terminator = *block.tail(); + Instruction& terminator = *block.tail(); if (terminator.opcode() == SpvOpReturn || terminator.opcode() == SpvOpReturnValue) { return_blocks.push_back(&block); @@ -568,8 +561,7 @@ std::vector<opt::BasicBlock*> MergeReturnPass::CollectReturnBlocks( } void MergeReturnPass::MergeReturnBlocks( - opt::Function* function, - const std::vector<opt::BasicBlock*>& return_blocks) { + Function* function, const std::vector<BasicBlock*>& return_blocks) { if (return_blocks.size() <= 1) { // No work to do. return; @@ -580,7 +572,7 @@ void MergeReturnPass::MergeReturnBlocks( auto ret_block_iter = --function->end(); // Create the PHI for the merged block (if necessary). // Create new return. - std::vector<opt::Operand> phi_ops; + std::vector<Operand> phi_ops; for (auto block : return_blocks) { if (block->tail()->opcode() == SpvOpReturnValue) { phi_ops.push_back( @@ -593,23 +585,23 @@ void MergeReturnPass::MergeReturnBlocks( // Need a PHI node to select the correct return value. uint32_t phi_result_id = TakeNextId(); uint32_t phi_type_id = function->type_id(); - std::unique_ptr<opt::Instruction> phi_inst(new opt::Instruction( + std::unique_ptr<Instruction> phi_inst(new Instruction( context(), SpvOpPhi, phi_type_id, phi_result_id, phi_ops)); ret_block_iter->AddInstruction(std::move(phi_inst)); - opt::BasicBlock::iterator phiIter = ret_block_iter->tail(); + BasicBlock::iterator phiIter = ret_block_iter->tail(); - std::unique_ptr<opt::Instruction> return_inst( - new opt::Instruction(context(), SpvOpReturnValue, 0u, 0u, - {{SPV_OPERAND_TYPE_ID, {phi_result_id}}})); + std::unique_ptr<Instruction> return_inst( + new Instruction(context(), SpvOpReturnValue, 0u, 0u, + {{SPV_OPERAND_TYPE_ID, {phi_result_id}}})); ret_block_iter->AddInstruction(std::move(return_inst)); - opt::BasicBlock::iterator ret = ret_block_iter->tail(); + BasicBlock::iterator ret = ret_block_iter->tail(); // Register the phi def and mark instructions for use updates. get_def_use_mgr()->AnalyzeInstDefUse(&*phiIter); get_def_use_mgr()->AnalyzeInstDef(&*ret); } else { - std::unique_ptr<opt::Instruction> return_inst( - new opt::Instruction(context(), SpvOpReturn)); + std::unique_ptr<Instruction> return_inst( + new Instruction(context(), SpvOpReturn)); ret_block_iter->AddInstruction(std::move(return_inst)); } @@ -626,33 +618,33 @@ void MergeReturnPass::MergeReturnBlocks( } void MergeReturnPass::AddNewPhiNodes() { - opt::DominatorAnalysis* dom_tree = context()->GetDominatorAnalysis(function_); - std::list<opt::BasicBlock*> order; + DominatorAnalysis* dom_tree = context()->GetDominatorAnalysis(function_); + std::list<BasicBlock*> order; cfg()->ComputeStructuredOrder(function_, &*function_->begin(), &order); - for (opt::BasicBlock* bb : order) { + for (BasicBlock* bb : order) { AddNewPhiNodes(bb, new_merge_nodes_[bb], dom_tree->ImmediateDominator(bb)->id()); } } -void MergeReturnPass::AddNewPhiNodes(opt::BasicBlock* bb, opt::BasicBlock* pred, +void MergeReturnPass::AddNewPhiNodes(BasicBlock* bb, BasicBlock* pred, uint32_t header_id) { - opt::DominatorAnalysis* dom_tree = context()->GetDominatorAnalysis(function_); + DominatorAnalysis* dom_tree = context()->GetDominatorAnalysis(function_); // Insert as a stopping point. We do not have to add anything in the block or // above because the header dominates |bb|. - opt::BasicBlock* current_bb = pred; + BasicBlock* current_bb = pred; while (current_bb != nullptr && current_bb->id() != header_id) { - for (opt::Instruction& inst : *current_bb) { + for (Instruction& inst : *current_bb) { CreatePhiNodesForInst(bb, pred->id(), inst); } current_bb = dom_tree->ImmediateDominator(current_bb); } } -void MergeReturnPass::MarkForNewPhiNodes( - opt::BasicBlock* block, opt::BasicBlock* single_original_pred) { +void MergeReturnPass::MarkForNewPhiNodes(BasicBlock* block, + BasicBlock* single_original_pred) { new_merge_nodes_[block] = single_original_pred; } diff --git a/source/opt/merge_return_pass.h b/source/opt/merge_return_pass.h index 72ea891e..d36f7c4b 100644 --- a/source/opt/merge_return_pass.h +++ b/source/opt/merge_return_pass.h @@ -105,9 +105,9 @@ class MergeReturnPass : public MemPass { const char* name() const override { return "merge-return"; } Status Process() override; - opt::IRContext::Analysis GetPreservedAnalyses() override { - // return opt::IRContext::kAnalysisDefUse; - return opt::IRContext::kAnalysisNone; + IRContext::Analysis GetPreservedAnalyses() override { + // return IRContext::kAnalysisDefUse; + return IRContext::kAnalysisNone; } private: @@ -116,7 +116,7 @@ class MergeReturnPass : public MemPass { // contain selection construct and the inner most loop construct. class StructuredControlState { public: - StructuredControlState(opt::Instruction* loop, opt::Instruction* merge) + StructuredControlState(Instruction* loop, Instruction* merge) : loop_merge_(loop), current_merge_(merge) {} StructuredControlState(const StructuredControlState&) = default; @@ -145,29 +145,29 @@ class MergeReturnPass : public MemPass { : 0; } - opt::Instruction* LoopMergeInst() const { return loop_merge_; } + Instruction* LoopMergeInst() const { return loop_merge_; } private: - opt::Instruction* loop_merge_; - opt::Instruction* current_merge_; + Instruction* loop_merge_; + Instruction* current_merge_; }; // Returns all BasicBlocks terminated by OpReturn or OpReturnValue in // |function|. - std::vector<opt::BasicBlock*> CollectReturnBlocks(opt::Function* function); + std::vector<BasicBlock*> CollectReturnBlocks(Function* function); // Creates a new basic block with a single return. If |function| returns a // value, a phi node is created to select the correct value to return. // Replaces old returns with an unconditional branch to the new block. - void MergeReturnBlocks(opt::Function* function, - const std::vector<opt::BasicBlock*>& returnBlocks); + void MergeReturnBlocks(Function* function, + const std::vector<BasicBlock*>& returnBlocks); // Merges the return instruction in |function| so that it has a single return // statement. It is assumed that |function| has structured control flow, and // that |return_blocks| is a list of all of the basic blocks in |function| // that have a return. - void ProcessStructured(opt::Function* function, - const std::vector<opt::BasicBlock*>& return_blocks); + void ProcessStructured(Function* function, + const std::vector<BasicBlock*>& return_blocks); // Changes an OpReturn* or OpUnreachable instruction at the end of |block| // into a store to |return_flag_|, a store to |return_value_| (if necessary), @@ -178,7 +178,7 @@ class MergeReturnPass : public MemPass { // // Note this will break the semantics. To fix this, PredicateBlock will have // to be called on the merge block the branch targets. - void ProcessStructuredBlock(opt::BasicBlock* block); + void ProcessStructuredBlock(BasicBlock* block); // Creates a variable used to store whether or not the control flow has // traversed a block that used to have a return. A pointer to the instruction @@ -192,7 +192,7 @@ class MergeReturnPass : public MemPass { // Adds a store that stores true to |return_flag_| immediately before the // terminator of |block|. It is assumed that |AddReturnFlag| has already been // called. - void RecordReturned(opt::BasicBlock* block); + void RecordReturned(BasicBlock* block); // Adds an instruction that stores the value being returned in the // OpReturnValue in |block|. The value is stored to |return_value_|, and the @@ -201,35 +201,35 @@ class MergeReturnPass : public MemPass { // If |block| does not contain an OpReturnValue, then this function has no // effect. If |block| contains an OpReturnValue, then |AddReturnValue| must // have already been called to create the variable to store to. - void RecordReturnValue(opt::BasicBlock* block); + void RecordReturnValue(BasicBlock* block); // Adds an unconditional branch in |block| that branches to |target|. It also // adds stores to |return_flag_| and |return_value_| as needed. // |AddReturnFlag| and |AddReturnValue| must have already been called. - void BranchToBlock(opt::BasicBlock* block, uint32_t target); + void BranchToBlock(BasicBlock* block, uint32_t target); // Returns true if we need to pridicate |block| where |tail_block| is the // merge point. (See |PredicateBlocks|). There is no need to predicate if // there is no code that could be executed. - bool RequiresPredication(const opt::BasicBlock* block, - const opt::BasicBlock* tail_block) const; + bool RequiresPredication(const BasicBlock* block, + const BasicBlock* tail_block) const; // For every basic block that is reachable from a basic block in // |return_blocks|, extra code is added to jump around any code that should // not be executed because the original code would have already returned. This // involves adding new selections constructs to jump around these // instructions. - void PredicateBlocks(const std::vector<opt::BasicBlock*>& return_blocks); + void PredicateBlocks(const std::vector<BasicBlock*>& return_blocks); // Add the predication code (see |PredicateBlocks|) to |tail_block| if it // requires predication. |tail_block| and any new blocks that are known to // not require predication will be added to |predicated|. - void PredicateBlock(opt::BasicBlock* block, opt::BasicBlock* tail_block, - std::unordered_set<opt::BasicBlock*>* predicated); + void PredicateBlock(BasicBlock* block, BasicBlock* tail_block, + std::unordered_set<BasicBlock*>* predicated); // Add an |OpReturn| or |OpReturnValue| to the end of |block|. If an // |OpReturnValue| is needed, the return value is loaded from |return_value_|. - void CreateReturn(opt::BasicBlock* block); + void CreateReturn(BasicBlock* block); // Creates a block at the end of the function that will become the single // return block at the end of the pass. @@ -239,8 +239,8 @@ class MergeReturnPass : public MemPass { // |predecessor|. Any uses of the result of |inst| that are no longer // dominated by |inst|, are replaced with the result of the new |OpPhi| // instruction. - void CreatePhiNodesForInst(opt::BasicBlock* merge_block, uint32_t predecessor, - opt::Instruction& inst); + void CreatePhiNodesForInst(BasicBlock* merge_block, uint32_t predecessor, + Instruction& inst); // Traverse the nodes in |new_merge_nodes_|, and adds the OpPhi instructions // that are needed to make the code correct. It is assumed that at this point @@ -250,18 +250,16 @@ class MergeReturnPass : public MemPass { // Creates any new phi nodes that are needed in |bb| now that |pred| is no // longer the only block that preceedes |bb|. |header_id| is the id of the // basic block for the loop or selection construct that merges at |bb|. - void AddNewPhiNodes(opt::BasicBlock* bb, opt::BasicBlock* pred, - uint32_t header_id); + void AddNewPhiNodes(BasicBlock* bb, BasicBlock* pred, uint32_t header_id); // Saves |block| to a list of basic block that will require OpPhi nodes to be // added by calling |AddNewPhiNodes|. It is assumed that |block| used to have // a single predecessor, |single_original_pred|, but now has more. - void MarkForNewPhiNodes(opt::BasicBlock* block, - opt::BasicBlock* single_original_pred); + void MarkForNewPhiNodes(BasicBlock* block, BasicBlock* single_original_pred); // Return the original single predcessor of |block| if it was flagged as // having a single predecessor. |nullptr| is returned otherwise. - opt::BasicBlock* MarkedSinglePred(opt::BasicBlock* block) { + BasicBlock* MarkedSinglePred(BasicBlock* block) { auto it = new_merge_nodes_.find(block); if (it != new_merge_nodes_.end()) { return it->second; @@ -277,28 +275,28 @@ class MergeReturnPass : public MemPass { std::vector<StructuredControlState> state_; // The current function being transformed. - opt::Function* function_; + Function* function_; // The |OpVariable| instruction defining a boolean variable used to keep track // of whether or not the function is trying to return. - opt::Instruction* return_flag_; + Instruction* return_flag_; // The |OpVariable| instruction defining a variabled to used to keep track of // the value that was returned when passing through a block that use to // contain an |OpReturnValue|. - opt::Instruction* return_value_; + Instruction* return_value_; // The instruction defining the boolean constant true. - opt::Instruction* constant_true_; + Instruction* constant_true_; // The basic block that is suppose to become the contain the only return value // after processing the current function. - opt::BasicBlock* final_return_block_; + BasicBlock* final_return_block_; // This map contains the set of nodes that use to have a single predcessor, // but now have more. They will need new OpPhi nodes. For each of the nodes, // it is mapped to it original single predcessor. It is assumed there are no // values that will need a phi on the new edges. - std::unordered_map<opt::BasicBlock*, opt::BasicBlock*> new_merge_nodes_; + std::unordered_map<BasicBlock*, BasicBlock*> new_merge_nodes_; }; } // namespace opt diff --git a/source/opt/module.cpp b/source/opt/module.cpp index 9c5b1d83..924d9837 100644 --- a/source/opt/module.cpp +++ b/source/opt/module.cpp @@ -65,8 +65,8 @@ uint32_t Module::GetGlobalValue(SpvOp opcode) const { void Module::AddGlobalValue(SpvOp opcode, uint32_t result_id, uint32_t type_id) { - std::unique_ptr<opt::Instruction> newGlobal( - new opt::Instruction(context(), opcode, type_id, result_id, {})); + std::unique_ptr<Instruction> newGlobal( + new Instruction(context(), opcode, type_id, result_id, {})); AddGlobalValue(std::move(newGlobal)); } @@ -160,7 +160,7 @@ uint32_t Module::GetExtInstImportId(const char* extstr) { } std::ostream& operator<<(std::ostream& str, const Module& module) { - module.ForEachInst([&str](const opt::Instruction* inst) { + module.ForEachInst([&str](const Instruction* inst) { str << *inst; if (inst->opcode() != SpvOpFunctionEnd) { str << std::endl; diff --git a/source/opt/pass.cpp b/source/opt/pass.cpp index f825bcf1..c346ac44 100644 --- a/source/opt/pass.cpp +++ b/source/opt/pass.cpp @@ -30,17 +30,16 @@ const uint32_t kTypePointerTypeIdInIdx = 1; Pass::Pass() : consumer_(nullptr), context_(nullptr), already_run_(false) {} -void Pass::AddCalls(opt::Function* func, std::queue<uint32_t>* todo) { +void Pass::AddCalls(Function* func, std::queue<uint32_t>* todo) { for (auto bi = func->begin(); bi != func->end(); ++bi) for (auto ii = bi->begin(); ii != bi->end(); ++ii) if (ii->opcode() == SpvOpFunctionCall) todo->push(ii->GetSingleWordInOperand(0)); } -bool Pass::ProcessEntryPointCallTree(ProcessFunction& pfn, - opt::Module* module) { +bool Pass::ProcessEntryPointCallTree(ProcessFunction& pfn, Module* module) { // Map from function's result id to function - std::unordered_map<uint32_t, opt::Function*> id2function; + std::unordered_map<uint32_t, Function*> id2function; for (auto& fn : *module) id2function[fn.result_id()] = &fn; // Collect all of the entry points as the roots. @@ -51,9 +50,9 @@ bool Pass::ProcessEntryPointCallTree(ProcessFunction& pfn, } bool Pass::ProcessReachableCallTree(ProcessFunction& pfn, - opt::IRContext* irContext) { + IRContext* irContext) { // Map from function's result id to function - std::unordered_map<uint32_t, opt::Function*> id2function; + std::unordered_map<uint32_t, Function*> id2function; for (auto& fn : *irContext->module()) id2function[fn.result_id()] = &fn; std::queue<uint32_t> roots; @@ -85,7 +84,7 @@ bool Pass::ProcessReachableCallTree(ProcessFunction& pfn, bool Pass::ProcessCallTreeFromRoots( ProcessFunction& pfn, - const std::unordered_map<uint32_t, opt::Function*>& id2function, + const std::unordered_map<uint32_t, Function*>& id2function, std::queue<uint32_t>* roots) { // Process call tree bool modified = false; @@ -95,7 +94,7 @@ bool Pass::ProcessCallTreeFromRoots( const uint32_t fi = roots->front(); roots->pop(); if (done.insert(fi).second) { - opt::Function* fn = id2function.at(fi); + Function* fn = id2function.at(fi); modified = pfn(fn) || modified; AddCalls(fn, roots); } @@ -103,7 +102,7 @@ bool Pass::ProcessCallTreeFromRoots( return modified; } -Pass::Status Pass::Run(opt::IRContext* ctx) { +Pass::Status Pass::Run(IRContext* ctx) { if (already_run_) { return Status::Failure; } @@ -120,9 +119,9 @@ Pass::Status Pass::Run(opt::IRContext* ctx) { return status; } -uint32_t Pass::GetPointeeTypeId(const opt::Instruction* ptrInst) const { +uint32_t Pass::GetPointeeTypeId(const Instruction* ptrInst) const { const uint32_t ptrTypeId = ptrInst->type_id(); - const opt::Instruction* ptrTypeInst = get_def_use_mgr()->GetDef(ptrTypeId); + const Instruction* ptrTypeInst = get_def_use_mgr()->GetDef(ptrTypeId); return ptrTypeInst->GetSingleWordInOperand(kTypePointerTypeIdInIdx); } diff --git a/source/opt/pass.h b/source/opt/pass.h index c79082e9..6889567e 100644 --- a/source/opt/pass.h +++ b/source/opt/pass.h @@ -45,7 +45,7 @@ class Pass { SuccessWithoutChange = 0x11, }; - using ProcessFunction = std::function<bool(opt::Function*)>; + using ProcessFunction = std::function<bool(Function*)>; // Destructs the pass. virtual ~Pass() = default; @@ -80,30 +80,29 @@ class Pass { } // Returns a pointer to the current module for this pass. - opt::Module* get_module() const { return context_->module(); } + Module* get_module() const { return context_->module(); } // Sets the pointer to the current context for this pass. void SetContextForTesting(IRContext* ctx) { context_ = ctx; } // Returns a pointer to the current context for this pass. - opt::IRContext* context() const { return context_; } + IRContext* context() const { return context_; } // Returns a pointer to the CFG for current module. - opt::CFG* cfg() const { return context()->cfg(); } + CFG* cfg() const { return context()->cfg(); } // Add to |todo| all ids of functions called in |func|. - void AddCalls(opt::Function* func, std::queue<uint32_t>* todo); + void AddCalls(Function* func, std::queue<uint32_t>* todo); // Applies |pfn| to every function in the call trees that are rooted at the // entry points. Returns true if any call |pfn| returns true. By convention // |pfn| should return true if it modified the module. - bool ProcessEntryPointCallTree(ProcessFunction& pfn, opt::Module* module); + bool ProcessEntryPointCallTree(ProcessFunction& pfn, Module* module); // Applies |pfn| to every function in the call trees rooted at the entry // points and exported functions. Returns true if any call |pfn| returns // true. By convention |pfn| should return true if it modified the module. - bool ProcessReachableCallTree(ProcessFunction& pfn, - opt::IRContext* irContext); + bool ProcessReachableCallTree(ProcessFunction& pfn, IRContext* irContext); // Applies |pfn| to every function in the call trees rooted at the elements of // |roots|. Returns true if any call to |pfn| returns true. By convention @@ -111,7 +110,7 @@ class Pass { // |roots| will be empty. bool ProcessCallTreeFromRoots( ProcessFunction& pfn, - const std::unordered_map<uint32_t, opt::Function*>& id2function, + const std::unordered_map<uint32_t, Function*>& id2function, std::queue<uint32_t>* roots); // Run the pass on the given |module|. Returns Status::Failure if errors occur @@ -122,15 +121,15 @@ class Pass { // // It is an error if |Run| is called twice with the same instance of the pass. // If this happens the return value will be |Failure|. - Status Run(opt::IRContext* ctx); + Status Run(IRContext* ctx); // Returns the set of analyses that the pass is guaranteed to preserve. - virtual opt::IRContext::Analysis GetPreservedAnalyses() { - return opt::IRContext::kAnalysisNone; + virtual IRContext::Analysis GetPreservedAnalyses() { + return IRContext::kAnalysisNone; } // Return type id for |ptrInst|'s pointee - uint32_t GetPointeeTypeId(const opt::Instruction* ptrInst) const; + uint32_t GetPointeeTypeId(const Instruction* ptrInst) const; protected: // Constructs a new pass. @@ -152,7 +151,7 @@ class Pass { MessageConsumer consumer_; // Message consumer. // The context that this pass belongs to. - opt::IRContext* context_; + IRContext* context_; // An instance of a pass can only be run once because it is too hard to // enforce proper resetting of internal state for each instance. This member diff --git a/source/opt/pass_manager.cpp b/source/opt/pass_manager.cpp index ffdf86a0..c02faeea 100644 --- a/source/opt/pass_manager.cpp +++ b/source/opt/pass_manager.cpp @@ -25,7 +25,7 @@ namespace spvtools { namespace opt { -Pass::Status PassManager::Run(opt::IRContext* context) { +Pass::Status PassManager::Run(IRContext* context) { auto status = Pass::Status::SuccessWithoutChange; // If print_all_stream_ is not null, prints the disassembly of the module diff --git a/source/opt/pass_manager.h b/source/opt/pass_manager.h index 41b73914..eb339290 100644 --- a/source/opt/pass_manager.h +++ b/source/opt/pass_manager.h @@ -70,7 +70,7 @@ class PassManager { // whether changes are made to the module. // // After running all the passes, they are removed from the list. - Pass::Status Run(opt::IRContext* context); + Pass::Status Run(IRContext* context); // Sets the option to print the disassembly before each pass and after the // last pass. Output is written to |out| if that is not null. No output diff --git a/source/opt/private_to_local_pass.cpp b/source/opt/private_to_local_pass.cpp index f8b35c6e..9f498d51 100644 --- a/source/opt/private_to_local_pass.cpp +++ b/source/opt/private_to_local_pass.cpp @@ -32,7 +32,7 @@ Pass::Status PrivateToLocalPass::Process() { if (context()->get_feature_mgr()->HasCapability(SpvCapabilityAddresses)) return Status::SuccessWithoutChange; - std::vector<std::pair<opt::Instruction*, opt::Function*>> variables_to_move; + std::vector<std::pair<Instruction*, Function*>> variables_to_move; for (auto& inst : context()->types_values()) { if (inst.opcode() != SpvOpVariable) { continue; @@ -43,7 +43,7 @@ Pass::Status PrivateToLocalPass::Process() { continue; } - opt::Function* target_function = FindLocalFunction(inst); + Function* target_function = FindLocalFunction(inst); if (target_function != nullptr) { variables_to_move.push_back({&inst, target_function}); } @@ -57,14 +57,13 @@ Pass::Status PrivateToLocalPass::Process() { return (modified ? Status::SuccessWithChange : Status::SuccessWithoutChange); } -opt::Function* PrivateToLocalPass::FindLocalFunction( - const opt::Instruction& inst) const { +Function* PrivateToLocalPass::FindLocalFunction(const Instruction& inst) const { bool found_first_use = false; - opt::Function* target_function = nullptr; + Function* target_function = nullptr; context()->get_def_use_mgr()->ForEachUser( inst.result_id(), - [&target_function, &found_first_use, this](opt::Instruction* use) { - opt::BasicBlock* current_block = context()->get_instr_block(use); + [&target_function, &found_first_use, this](Instruction* use) { + BasicBlock* current_block = context()->get_instr_block(use); if (current_block == nullptr) { return; } @@ -74,7 +73,7 @@ opt::Function* PrivateToLocalPass::FindLocalFunction( target_function = nullptr; return; } - opt::Function* current_function = current_block->GetParent(); + Function* current_function = current_block->GetParent(); if (!found_first_use) { found_first_use = true; target_function = current_function; @@ -85,12 +84,12 @@ opt::Function* PrivateToLocalPass::FindLocalFunction( return target_function; } // namespace opt -void PrivateToLocalPass::MoveVariable(opt::Instruction* variable, - opt::Function* function) { +void PrivateToLocalPass::MoveVariable(Instruction* variable, + Function* function) { // The variable needs to be removed from the global section, and placed in the // header of the function. First step remove from the global list. variable->RemoveFromList(); - std::unique_ptr<opt::Instruction> var(variable); // Take ownership. + std::unique_ptr<Instruction> var(variable); // Take ownership. context()->ForgetUses(variable); // Update the storage class of the variable. @@ -111,7 +110,7 @@ void PrivateToLocalPass::MoveVariable(opt::Instruction* variable, uint32_t PrivateToLocalPass::GetNewType(uint32_t old_type_id) { auto type_mgr = context()->get_type_mgr(); - opt::Instruction* old_type_inst = get_def_use_mgr()->GetDef(old_type_id); + Instruction* old_type_inst = get_def_use_mgr()->GetDef(old_type_id); uint32_t pointee_type_id = old_type_inst->GetSingleWordInOperand(kSpvTypePointerTypeIdInIdx); uint32_t new_type_id = @@ -120,7 +119,7 @@ uint32_t PrivateToLocalPass::GetNewType(uint32_t old_type_id) { return new_type_id; } -bool PrivateToLocalPass::IsValidUse(const opt::Instruction* inst) const { +bool PrivateToLocalPass::IsValidUse(const Instruction* inst) const { // The cases in this switch have to match the cases in |UpdateUse|. // If we don't know how to update it, it is not valid. switch (inst->opcode()) { @@ -130,7 +129,7 @@ bool PrivateToLocalPass::IsValidUse(const opt::Instruction* inst) const { return true; case SpvOpAccessChain: return context()->get_def_use_mgr()->WhileEachUser( - inst, [this](const opt::Instruction* user) { + inst, [this](const Instruction* user) { if (!IsValidUse(user)) return false; return true; }); @@ -141,7 +140,7 @@ bool PrivateToLocalPass::IsValidUse(const opt::Instruction* inst) const { } } -void PrivateToLocalPass::UpdateUse(opt::Instruction* inst) { +void PrivateToLocalPass::UpdateUse(Instruction* inst) { // The cases in this switch have to match the cases in |IsValidUse|. If we // don't think it is valid, the optimization will not view the variable as a // candidate, and therefore the use will not be updated. @@ -169,11 +168,11 @@ void PrivateToLocalPass::UpdateUse(opt::Instruction* inst) { } } void PrivateToLocalPass::UpdateUses(uint32_t id) { - std::vector<opt::Instruction*> uses; + std::vector<Instruction*> uses; context()->get_def_use_mgr()->ForEachUser( - id, [&uses](opt::Instruction* use) { uses.push_back(use); }); + id, [&uses](Instruction* use) { uses.push_back(use); }); - for (opt::Instruction* use : uses) { + for (Instruction* use : uses) { UpdateUse(use); } } diff --git a/source/opt/private_to_local_pass.h b/source/opt/private_to_local_pass.h index bdf931ba..0b716c8a 100644 --- a/source/opt/private_to_local_pass.h +++ b/source/opt/private_to_local_pass.h @@ -30,30 +30,29 @@ class PrivateToLocalPass : public Pass { const char* name() const override { return "private-to-local"; } Status Process() override; - opt::IRContext::Analysis GetPreservedAnalyses() override { - return opt::IRContext::kAnalysisDefUse | - opt::IRContext::kAnalysisInstrToBlockMapping | - opt::IRContext::kAnalysisDecorations | - opt::IRContext::kAnalysisCombinators | opt::IRContext::kAnalysisCFG | - opt::IRContext::kAnalysisDominatorAnalysis | - opt::IRContext::kAnalysisNameMap; + IRContext::Analysis GetPreservedAnalyses() override { + return IRContext::kAnalysisDefUse | + IRContext::kAnalysisInstrToBlockMapping | + IRContext::kAnalysisDecorations | IRContext::kAnalysisCombinators | + IRContext::kAnalysisCFG | IRContext::kAnalysisDominatorAnalysis | + IRContext::kAnalysisNameMap; } private: // Moves |variable| from the private storage class to the function storage // class of |function|. - void MoveVariable(opt::Instruction* variable, opt::Function* function); + void MoveVariable(Instruction* variable, Function* function); // |inst| is an instruction declaring a varible. If that variable is // referenced in a single function and all of uses are valid as defined by // |IsValidUse|, then that function is returned. Otherwise, the return // value is |nullptr|. - opt::Function* FindLocalFunction(const opt::Instruction& inst) const; + Function* FindLocalFunction(const Instruction& inst) const; // Returns true is |inst| is a valid use of a pointer. In this case, a // valid use is one where the transformation is able to rewrite the type to // match a change in storage class of the original variable. - bool IsValidUse(const opt::Instruction* inst) const; + bool IsValidUse(const Instruction* inst) const; // Given the result id of a pointer type, |old_type_id|, this function // returns the id of a the same pointer type except the storage class has @@ -63,7 +62,7 @@ class PrivateToLocalPass : public Pass { // Updates |inst|, and any instruction dependent on |inst|, to reflect the // change of the base pointer now pointing to the function storage class. - void UpdateUse(opt::Instruction* inst); + void UpdateUse(Instruction* inst); void UpdateUses(uint32_t id); }; diff --git a/source/opt/propagator.cpp b/source/opt/propagator.cpp index 4844ac33..bfaa811b 100644 --- a/source/opt/propagator.cpp +++ b/source/opt/propagator.cpp @@ -18,7 +18,7 @@ namespace spvtools { namespace opt { void SSAPropagator::AddControlEdge(const Edge& edge) { - opt::BasicBlock* dest_bb = edge.dest; + BasicBlock* dest_bb = edge.dest; // Refuse to add the exit block to the work list. if (dest_bb == ctx_->cfg()->pseudo_exit_block()) { @@ -36,14 +36,14 @@ void SSAPropagator::AddControlEdge(const Edge& edge) { blocks_.push(dest_bb); } -void SSAPropagator::AddSSAEdges(opt::Instruction* instr) { +void SSAPropagator::AddSSAEdges(Instruction* instr) { // Ignore instructions that produce no result. if (instr->result_id() == 0) { return; } get_def_use_mgr()->ForEachUser( - instr->result_id(), [this](opt::Instruction* use_instr) { + instr->result_id(), [this](Instruction* use_instr) { // If the basic block for |use_instr| has not been simulated yet, do // nothing. The instruction |use_instr| will be simulated next time the // block is scheduled. @@ -57,18 +57,17 @@ void SSAPropagator::AddSSAEdges(opt::Instruction* instr) { }); } -bool SSAPropagator::IsPhiArgExecutable(opt::Instruction* phi, - uint32_t i) const { - opt::BasicBlock* phi_bb = ctx_->get_instr_block(phi); +bool SSAPropagator::IsPhiArgExecutable(Instruction* phi, uint32_t i) const { + BasicBlock* phi_bb = ctx_->get_instr_block(phi); uint32_t in_label_id = phi->GetSingleWordOperand(i + 1); - opt::Instruction* in_label_instr = get_def_use_mgr()->GetDef(in_label_id); - opt::BasicBlock* in_bb = ctx_->get_instr_block(in_label_instr); + Instruction* in_label_instr = get_def_use_mgr()->GetDef(in_label_id); + BasicBlock* in_bb = ctx_->get_instr_block(in_label_instr); return IsEdgeExecutable(Edge(in_bb, phi_bb)); } -bool SSAPropagator::SetStatus(opt::Instruction* inst, PropStatus status) { +bool SSAPropagator::SetStatus(Instruction* inst, PropStatus status) { bool has_old_status = false; PropStatus old_status = kVarying; if (HasStatus(inst)) { @@ -85,7 +84,7 @@ bool SSAPropagator::SetStatus(opt::Instruction* inst, PropStatus status) { return status_changed; } -bool SSAPropagator::Simulate(opt::Instruction* instr) { +bool SSAPropagator::Simulate(Instruction* instr) { bool changed = false; // Don't bother visiting instructions that should not be simulated again. @@ -93,7 +92,7 @@ bool SSAPropagator::Simulate(opt::Instruction* instr) { return changed; } - opt::BasicBlock* dest_bb = nullptr; + BasicBlock* dest_bb = nullptr; PropStatus status = visit_fn_(instr, &dest_bb); bool status_changed = SetStatus(instr, status); @@ -108,7 +107,7 @@ bool SSAPropagator::Simulate(opt::Instruction* instr) { // If |instr| is a block terminator, add all the control edges out of its // block. if (instr->IsBlockTerminator()) { - opt::BasicBlock* block = ctx_->get_instr_block(instr); + BasicBlock* block = ctx_->get_instr_block(instr); for (const auto& e : bb_succs_.at(block)) { AddControlEdge(e); } @@ -146,7 +145,7 @@ bool SSAPropagator::Simulate(opt::Instruction* instr) { "malformed Phi arguments"); uint32_t arg_id = instr->GetSingleWordOperand(i); - opt::Instruction* arg_def_instr = get_def_use_mgr()->GetDef(arg_id); + Instruction* arg_def_instr = get_def_use_mgr()->GetDef(arg_id); if (!IsPhiArgExecutable(instr, i) || ShouldSimulateAgain(arg_def_instr)) { has_operands_to_simulate = true; break; @@ -158,7 +157,7 @@ bool SSAPropagator::Simulate(opt::Instruction* instr) { // also be simulated again. has_operands_to_simulate = !instr->WhileEachInId([this](const uint32_t* use) { - opt::Instruction* def_instr = get_def_use_mgr()->GetDef(*use); + Instruction* def_instr = get_def_use_mgr()->GetDef(*use); if (ShouldSimulateAgain(def_instr)) { return false; } @@ -173,7 +172,7 @@ bool SSAPropagator::Simulate(opt::Instruction* instr) { return changed; } -bool SSAPropagator::Simulate(opt::BasicBlock* block) { +bool SSAPropagator::Simulate(BasicBlock* block) { if (block == ctx_->cfg()->pseudo_exit_block()) { return false; } @@ -183,14 +182,13 @@ bool SSAPropagator::Simulate(opt::BasicBlock* block) { // incoming edges. When those edges are marked executable, the corresponding // operand can be simulated. bool changed = false; - block->ForEachPhiInst([&changed, this](opt::Instruction* instr) { - changed |= Simulate(instr); - }); + block->ForEachPhiInst( + [&changed, this](Instruction* instr) { changed |= Simulate(instr); }); // If this is the first time this block is being simulated, simulate every // statement in it. if (!BlockHasBeenSimulated(block)) { - block->ForEachInst([this, &changed](opt::Instruction* instr) { + block->ForEachInst([this, &changed](Instruction* instr) { if (instr->opcode() != SpvOpPhi) { changed |= Simulate(instr); } @@ -208,9 +206,9 @@ bool SSAPropagator::Simulate(opt::BasicBlock* block) { return changed; } -void SSAPropagator::Initialize(opt::Function* fn) { +void SSAPropagator::Initialize(Function* fn) { // Compute predecessor and successor blocks for every block in |fn|'s CFG. - // TODO(dnovillo): Move this to opt::CFG and always build them. Alternately, + // TODO(dnovillo): Move this to CFG and always build them. Alternately, // move it to IRContext and build CFG preds/succs on-demand. bb_succs_[ctx_->cfg()->pseudo_entry_block()].push_back( Edge(ctx_->cfg()->pseudo_entry_block(), fn->entry().get())); @@ -218,7 +216,7 @@ void SSAPropagator::Initialize(opt::Function* fn) { for (auto& block : *fn) { const auto& const_block = block; const_block.ForEachSuccessorLabel([this, &block](const uint32_t label_id) { - opt::BasicBlock* succ_bb = + BasicBlock* succ_bb = ctx_->get_instr_block(get_def_use_mgr()->GetDef(label_id)); bb_succs_[&block].push_back(Edge(&block, succ_bb)); bb_preds_[succ_bb].push_back(Edge(succ_bb, &block)); @@ -238,7 +236,7 @@ void SSAPropagator::Initialize(opt::Function* fn) { } } -bool SSAPropagator::Run(opt::Function* fn) { +bool SSAPropagator::Run(Function* fn) { Initialize(fn); bool changed = false; @@ -254,7 +252,7 @@ bool SSAPropagator::Run(opt::Function* fn) { // Simulate edges from the SSA queue. if (!ssa_edge_uses_.empty()) { - opt::Instruction* instr = ssa_edge_uses_.front(); + Instruction* instr = ssa_edge_uses_.front(); changed |= Simulate(instr); ssa_edge_uses_.pop(); } @@ -263,7 +261,7 @@ bool SSAPropagator::Run(opt::Function* fn) { #ifndef NDEBUG // Verify all visited values have settled. No value that has been simulated // should end on not interesting. - fn->ForEachInst([this](opt::Instruction* inst) { + fn->ForEachInst([this](Instruction* inst) { assert( (!HasStatus(inst) || Status(inst) != SSAPropagator::kNotInteresting) && "Unsettled value"); diff --git a/source/opt/propagator.h b/source/opt/propagator.h index 52e7bba7..aef21de4 100644 --- a/source/opt/propagator.h +++ b/source/opt/propagator.h @@ -30,12 +30,12 @@ namespace opt { // Represents a CFG control edge. struct Edge { - Edge(opt::BasicBlock* b1, opt::BasicBlock* b2) : source(b1), dest(b2) { + Edge(BasicBlock* b1, BasicBlock* b2) : source(b1), dest(b2) { assert(source && "CFG edges cannot have a null source block."); assert(dest && "CFG edges cannot have a null destination block."); } - opt::BasicBlock* source; - opt::BasicBlock* dest; + BasicBlock* source; + BasicBlock* dest; bool operator<(const Edge& o) const { return std::make_pair(source->id(), dest->id()) < std::make_pair(o.source->id(), o.dest->id()); @@ -150,20 +150,20 @@ struct Edge { // // auto ctx = BuildModule(...); // std::map<uint32_t, uint32_t> values; -// const auto visit_fn = [&ctx, &values](opt::Instruction* instr, -// opt::BasicBlock** dest_bb) { +// const auto visit_fn = [&ctx, &values](Instruction* instr, +// BasicBlock** dest_bb) { // if (instr->opcode() == SpvOpStore) { // uint32_t rhs_id = instr->GetSingleWordOperand(1); -// opt::Instruction* rhs_def = ctx->get_def_use_mgr()->GetDef(rhs_id); +// Instruction* rhs_def = ctx->get_def_use_mgr()->GetDef(rhs_id); // if (rhs_def->opcode() == SpvOpConstant) { // uint32_t val = rhs_def->GetSingleWordOperand(2); // values[rhs_id] = val; -// return opt::SSAPropagator::kInteresting; +// return SSAPropagator::kInteresting; // } // } -// return opt::SSAPropagator::kVarying; +// return SSAPropagator::kVarying; // }; -// opt::SSAPropagator propagator(ctx.get(), &cfg, visit_fn); +// SSAPropagator propagator(ctx.get(), &cfg, visit_fn); // propagator.Run(&fn); // // Given the code: @@ -183,66 +183,63 @@ class SSAPropagator { // a description. enum PropStatus { kNotInteresting, kInteresting, kVarying }; - using VisitFunction = - std::function<PropStatus(opt::Instruction*, opt::BasicBlock**)>; + using VisitFunction = std::function<PropStatus(Instruction*, BasicBlock**)>; - SSAPropagator(opt::IRContext* context, const VisitFunction& visit_fn) + SSAPropagator(IRContext* context, const VisitFunction& visit_fn) : ctx_(context), visit_fn_(visit_fn) {} // Runs the propagator on function |fn|. Returns true if changes were made to // the function. Otherwise, it returns false. - bool Run(opt::Function* fn); + bool Run(Function* fn); // Returns true if the |i|th argument for |phi| comes through a CFG edge that // has been marked executable. |i| should be an index value accepted by // Instruction::GetSingleWordOperand. - bool IsPhiArgExecutable(opt::Instruction* phi, uint32_t i) const; + bool IsPhiArgExecutable(Instruction* phi, uint32_t i) const; // Returns true if |inst| has a recorded status. This will be true once |inst| // has been simulated once. - bool HasStatus(opt::Instruction* inst) const { return statuses_.count(inst); } + bool HasStatus(Instruction* inst) const { return statuses_.count(inst); } // Returns the current propagation status of |inst|. Assumes // |HasStatus(inst)| returns true. - PropStatus Status(opt::Instruction* inst) const { + PropStatus Status(Instruction* inst) const { return statuses_.find(inst)->second; } // Records the propagation status |status| for |inst|. Returns true if the // status for |inst| has changed or set was set for the first time. - bool SetStatus(opt::Instruction* inst, PropStatus status); + bool SetStatus(Instruction* inst, PropStatus status); private: // Initialize processing. - void Initialize(opt::Function* fn); + void Initialize(Function* fn); // Simulate the execution |block| by calling |visit_fn_| on every instruction // in it. - bool Simulate(opt::BasicBlock* block); + bool Simulate(BasicBlock* block); // Simulate the execution of |instr| by replacing all the known values in // every operand and determining whether the result is interesting for // propagation. This invokes the callback function |visit_fn_| to determine // the value computed by |instr|. - bool Simulate(opt::Instruction* instr); + bool Simulate(Instruction* instr); // Returns true if |instr| should be simulated again. - bool ShouldSimulateAgain(opt::Instruction* instr) const { + bool ShouldSimulateAgain(Instruction* instr) const { return do_not_simulate_.find(instr) == do_not_simulate_.end(); } // Add |instr| to the set of instructions not to simulate again. - void DontSimulateAgain(opt::Instruction* instr) { - do_not_simulate_.insert(instr); - } + void DontSimulateAgain(Instruction* instr) { do_not_simulate_.insert(instr); } // Returns true if |block| has been simulated already. - bool BlockHasBeenSimulated(opt::BasicBlock* block) const { + bool BlockHasBeenSimulated(BasicBlock* block) const { return simulated_blocks_.find(block) != simulated_blocks_.end(); } // Marks block |block| as simulated. - void MarkBlockSimulated(opt::BasicBlock* block) { + void MarkBlockSimulated(BasicBlock* block) { simulated_blocks_.insert(block); } @@ -268,10 +265,10 @@ class SSAPropagator { // Adds all the instructions that use the result of |instr| to the SSA edges // work list. If |instr| produces no result id, this does nothing. - void AddSSAEdges(opt::Instruction* instr); + void AddSSAEdges(Instruction* instr); // IR context to use. - opt::IRContext* ctx_; + IRContext* ctx_; // Function that visits instructions during simulation. The output of this // function is used to determine if the simulated instruction produced a value @@ -281,33 +278,33 @@ class SSAPropagator { // SSA def-use edges to traverse. Each entry is a destination statement for an // SSA def-use edge as returned by |def_use_manager_|. - std::queue<opt::Instruction*> ssa_edge_uses_; + std::queue<Instruction*> ssa_edge_uses_; // Blocks to simulate. - std::queue<opt::BasicBlock*> blocks_; + std::queue<BasicBlock*> blocks_; // Blocks simulated during propagation. - std::unordered_set<opt::BasicBlock*> simulated_blocks_; + std::unordered_set<BasicBlock*> simulated_blocks_; // Set of instructions that should not be simulated again because they have // been found to be in the kVarying state. - std::unordered_set<opt::Instruction*> do_not_simulate_; + std::unordered_set<Instruction*> do_not_simulate_; // Map between a basic block and its predecessor edges. - // TODO(dnovillo): Move this to opt::CFG and always build them. Alternately, + // TODO(dnovillo): Move this to CFG and always build them. Alternately, // move it to IRContext and build CFG preds/succs on-demand. - std::unordered_map<opt::BasicBlock*, std::vector<Edge>> bb_preds_; + std::unordered_map<BasicBlock*, std::vector<Edge>> bb_preds_; // Map between a basic block and its successor edges. - // TODO(dnovillo): Move this to opt::CFG and always build them. Alternately, + // TODO(dnovillo): Move this to CFG and always build them. Alternately, // move it to IRContext and build CFG preds/succs on-demand. - std::unordered_map<opt::BasicBlock*, std::vector<Edge>> bb_succs_; + std::unordered_map<BasicBlock*, std::vector<Edge>> bb_succs_; // Set of executable CFG edges. std::set<Edge> executable_edges_; // Tracks instruction propagation status. - std::unordered_map<opt::Instruction*, SSAPropagator::PropStatus> statuses_; + std::unordered_map<Instruction*, SSAPropagator::PropStatus> statuses_; }; std::ostream& operator<<(std::ostream& str, diff --git a/source/opt/reduce_load_size.cpp b/source/opt/reduce_load_size.cpp index 8c48cf50..e82a9e28 100644 --- a/source/opt/reduce_load_size.cpp +++ b/source/opt/reduce_load_size.cpp @@ -33,7 +33,7 @@ Pass::Status ReduceLoadSize::Process() { bool modified = false; for (auto& func : *get_module()) { - func.ForEachInst([&modified, this](opt::Instruction* inst) { + func.ForEachInst([&modified, this](Instruction* inst) { if (inst->opcode() == SpvOpCompositeExtract) { if (ShouldReplaceExtract(inst)) { modified |= ReplaceExtract(inst); @@ -45,7 +45,7 @@ Pass::Status ReduceLoadSize::Process() { return modified ? Status::SuccessWithChange : Status::SuccessWithoutChange; } -bool ReduceLoadSize::ReplaceExtract(opt::Instruction* inst) { +bool ReduceLoadSize::ReplaceExtract(Instruction* inst) { assert(inst->opcode() == SpvOpCompositeExtract && "Wrong opcode. Should be OpCompositeExtract."); analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr(); @@ -54,7 +54,7 @@ bool ReduceLoadSize::ReplaceExtract(opt::Instruction* inst) { uint32_t composite_id = inst->GetSingleWordInOperand(kExtractCompositeIdInIdx); - opt::Instruction* composite_inst = def_use_mgr->GetDef(composite_id); + Instruction* composite_inst = def_use_mgr->GetDef(composite_id); if (composite_inst->opcode() != SpvOpLoad) { return false; @@ -66,7 +66,7 @@ bool ReduceLoadSize::ReplaceExtract(opt::Instruction* inst) { return false; } - opt::Instruction* var = composite_inst->GetBaseAddress(); + Instruction* var = composite_inst->GetBaseAddress(); if (var == nullptr || var->opcode() != SpvOpVariable) { return false; } @@ -85,9 +85,9 @@ bool ReduceLoadSize::ReplaceExtract(opt::Instruction* inst) { // Create a new access chain and load just after the old load. // We cannot create the new access chain load in the position of the extract // because the storage may have been written to in between. - InstructionBuilder ir_builder(inst->context(), composite_inst, - opt::IRContext::kAnalysisInstrToBlockMapping | - opt::IRContext::kAnalysisDefUse); + InstructionBuilder ir_builder( + inst->context(), composite_inst, + IRContext::kAnalysisInstrToBlockMapping | IRContext::kAnalysisDefUse); uint32_t pointer_to_result_type_id = type_mgr->FindPointerToType(inst->type_id(), storage_class); @@ -104,10 +104,10 @@ bool ReduceLoadSize::ReplaceExtract(opt::Instruction* inst) { ids.push_back(const_mgr->GetDefiningInstruction(index_const)->result_id()); } - opt::Instruction* new_access_chain = ir_builder.AddAccessChain( + Instruction* new_access_chain = ir_builder.AddAccessChain( pointer_to_result_type_id, composite_inst->GetSingleWordInOperand(kLoadPointerInIdx), ids); - opt::Instruction* new_laod = + Instruction* new_laod = ir_builder.AddLoad(inst->type_id(), new_access_chain->result_id()); context()->ReplaceAllUsesWith(inst->result_id(), new_laod->result_id()); @@ -115,9 +115,9 @@ bool ReduceLoadSize::ReplaceExtract(opt::Instruction* inst) { return true; } -bool ReduceLoadSize::ShouldReplaceExtract(opt::Instruction* inst) { +bool ReduceLoadSize::ShouldReplaceExtract(Instruction* inst) { analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr(); - opt::Instruction* op_inst = def_use_mgr->GetDef( + Instruction* op_inst = def_use_mgr->GetDef( inst->GetSingleWordInOperand(kExtractCompositeIdInIdx)); if (op_inst->opcode() != SpvOpLoad) { @@ -132,8 +132,8 @@ bool ReduceLoadSize::ShouldReplaceExtract(opt::Instruction* inst) { bool all_elements_used = false; std::set<uint32_t> elements_used; - all_elements_used = !def_use_mgr->WhileEachUser( - op_inst, [&elements_used](opt::Instruction* use) { + all_elements_used = + !def_use_mgr->WhileEachUser(op_inst, [&elements_used](Instruction* use) { if (use->opcode() != SpvOpCompositeExtract) { return false; } diff --git a/source/opt/reduce_load_size.h b/source/opt/reduce_load_size.h index ccecd3c0..d2402116 100644 --- a/source/opt/reduce_load_size.h +++ b/source/opt/reduce_load_size.h @@ -29,13 +29,12 @@ class ReduceLoadSize : public Pass { Status Process() override; // Return the mask of preserved Analyses. - opt::IRContext::Analysis GetPreservedAnalyses() override { - return opt::IRContext::kAnalysisDefUse | - opt::IRContext::kAnalysisInstrToBlockMapping | - opt::IRContext::kAnalysisCombinators | opt::IRContext::kAnalysisCFG | - opt::IRContext::kAnalysisDominatorAnalysis | - opt::IRContext::kAnalysisLoopAnalysis | - opt::IRContext::kAnalysisNameMap; + IRContext::Analysis GetPreservedAnalyses() override { + return IRContext::kAnalysisDefUse | + IRContext::kAnalysisInstrToBlockMapping | + IRContext::kAnalysisCombinators | IRContext::kAnalysisCFG | + IRContext::kAnalysisDominatorAnalysis | + IRContext::kAnalysisLoopAnalysis | IRContext::kAnalysisNameMap; } private: @@ -44,13 +43,13 @@ class ReduceLoadSize : public Pass { // feeding |inst|. Returns true if the substitution happened. The position // of the new instructions will be in the same place as the load feeding the // extract. - bool ReplaceExtract(opt::Instruction* inst); + bool ReplaceExtract(Instruction* inst); // Returns true if the OpCompositeExtract instruction |inst| should be replace // or not. This is determined by looking at the load that feeds |inst| if // it is a load. |should_replace_cache_| is used to cache the results based // on the load feeding |inst|. - bool ShouldReplaceExtract(opt::Instruction* inst); + bool ShouldReplaceExtract(Instruction* inst); // Maps the result id of an OpLoad instruction to the result of whether or // not the OpCompositeExtract that use the id should be replaced. diff --git a/source/opt/redundancy_elimination.cpp b/source/opt/redundancy_elimination.cpp index 4b184a69..294b84d5 100644 --- a/source/opt/redundancy_elimination.cpp +++ b/source/opt/redundancy_elimination.cpp @@ -26,7 +26,7 @@ Pass::Status RedundancyEliminationPass::Process() { for (auto& func : *get_module()) { // Build the dominator tree for this function. It is how the code is // traversed. - opt::DominatorTree& dom_tree = + DominatorTree& dom_tree = context()->GetDominatorAnalysis(&func)->GetDomTree(); // Keeps track of all ids that contain a given value number. We keep diff --git a/source/opt/register_pressure.cpp b/source/opt/register_pressure.cpp index a73a026b..729755c2 100644 --- a/source/opt/register_pressure.cpp +++ b/source/opt/register_pressure.cpp @@ -31,25 +31,25 @@ namespace { // phi instructions defined in the basic block |bb|. class ExcludePhiDefinedInBlock { public: - ExcludePhiDefinedInBlock(opt::IRContext* context, const opt::BasicBlock* bb) + ExcludePhiDefinedInBlock(IRContext* context, const BasicBlock* bb) : context_(context), bb_(bb) {} - bool operator()(opt::Instruction* insn) const { + bool operator()(Instruction* insn) const { return !(insn->opcode() == SpvOpPhi && context_->get_instr_block(insn) == bb_); } private: - opt::IRContext* context_; - const opt::BasicBlock* bb_; + IRContext* context_; + const BasicBlock* bb_; }; // Returns true if |insn| generates a SSA register that is likely to require a // physical register. -bool CreatesRegisterUsage(opt::Instruction* insn) { +bool CreatesRegisterUsage(Instruction* insn) { if (!insn->HasResultId()) return false; if (insn->opcode() == SpvOpUndef) return false; - if (opt::IsConstantInst(insn->opcode())) return false; + if (IsConstantInst(insn->opcode())) return false; if (insn->opcode() == SpvOpLabel) return false; return true; } @@ -60,7 +60,7 @@ bool CreatesRegisterUsage(opt::Instruction* insn) { // computing liveness sets in strict ssa programs" from Boissinot et al. class ComputeRegisterLiveness { public: - ComputeRegisterLiveness(RegisterLiveness* reg_pressure, opt::Function* f) + ComputeRegisterLiveness(RegisterLiveness* reg_pressure, Function* f) : reg_pressure_(reg_pressure), context_(reg_pressure->GetContext()), function_(f), @@ -77,9 +77,9 @@ class ComputeRegisterLiveness { // - Second, walk loop forest to propagate registers crossing back-edges // (add iterative values into the liveness set). void Compute() { - cfg_.ForEachBlockInPostOrder( - &*function_->begin(), - [this](opt::BasicBlock* bb) { ComputePartialLiveness(bb); }); + cfg_.ForEachBlockInPostOrder(&*function_->begin(), [this](BasicBlock* bb) { + ComputePartialLiveness(bb); + }); DoLoopLivenessUnification(); EvaluateRegisterRequirements(); } @@ -87,15 +87,15 @@ class ComputeRegisterLiveness { private: // Registers all SSA register used by successors of |bb| in their phi // instructions. - void ComputePhiUses(const opt::BasicBlock& bb, + void ComputePhiUses(const BasicBlock& bb, RegisterLiveness::RegionRegisterLiveness::LiveSet* live) { uint32_t bb_id = bb.id(); bb.ForEachSuccessorLabel([live, bb_id, this](uint32_t sid) { - opt::BasicBlock* succ_bb = cfg_.block(sid); - succ_bb->ForEachPhiInst([live, bb_id, this](const opt::Instruction* phi) { + BasicBlock* succ_bb = cfg_.block(sid); + succ_bb->ForEachPhiInst([live, bb_id, this](const Instruction* phi) { for (uint32_t i = 0; i < phi->NumInOperands(); i += 2) { if (phi->GetSingleWordInOperand(i + 1) == bb_id) { - opt::Instruction* insn_op = + Instruction* insn_op = def_use_manager_.GetDef(phi->GetSingleWordInOperand(i)); if (CreatesRegisterUsage(insn_op)) { live->insert(insn_op); @@ -109,7 +109,7 @@ class ComputeRegisterLiveness { // Computes register liveness for each basic blocks but ignores all // back-edges. - void ComputePartialLiveness(opt::BasicBlock* bb) { + void ComputePartialLiveness(BasicBlock* bb) { assert(reg_pressure_->Get(bb) == nullptr && "Basic block already processed"); @@ -117,35 +117,35 @@ class ComputeRegisterLiveness { reg_pressure_->GetOrInsert(bb->id()); ComputePhiUses(*bb, &live_inout->live_out_); - const opt::BasicBlock* cbb = bb; + const BasicBlock* cbb = bb; cbb->ForEachSuccessorLabel([&live_inout, bb, this](uint32_t sid) { // Skip back edges. if (dom_tree_.Dominates(sid, bb->id())) { return; } - opt::BasicBlock* succ_bb = cfg_.block(sid); + BasicBlock* succ_bb = cfg_.block(sid); RegisterLiveness::RegionRegisterLiveness* succ_live_inout = reg_pressure_->Get(succ_bb); assert(succ_live_inout && "Successor liveness analysis was not performed"); ExcludePhiDefinedInBlock predicate(context_, succ_bb); - auto filter = opt::MakeFilterIteratorRange( - succ_live_inout->live_in_.begin(), succ_live_inout->live_in_.end(), - predicate); + auto filter = + MakeFilterIteratorRange(succ_live_inout->live_in_.begin(), + succ_live_inout->live_in_.end(), predicate); live_inout->live_out_.insert(filter.begin(), filter.end()); }); live_inout->live_in_ = live_inout->live_out_; - for (opt::Instruction& insn : opt::make_range(bb->rbegin(), bb->rend())) { + for (Instruction& insn : make_range(bb->rbegin(), bb->rend())) { if (insn.opcode() == SpvOpPhi) { live_inout->live_in_.insert(&insn); break; } live_inout->live_in_.erase(&insn); insn.ForEachInId([live_inout, this](uint32_t* id) { - opt::Instruction* insn_op = def_use_manager_.GetDef(*id); + Instruction* insn_op = def_use_manager_.GetDef(*id); if (CreatesRegisterUsage(insn_op)) { live_inout->live_in_.insert(insn_op); } @@ -155,15 +155,15 @@ class ComputeRegisterLiveness { // Propagates the register liveness information of each loop iterators. void DoLoopLivenessUnification() { - for (const opt::Loop* loop : *loop_desc_.GetDummyRootLoop()) { + for (const Loop* loop : *loop_desc_.GetDummyRootLoop()) { DoLoopLivenessUnification(*loop); } } // Propagates the register liveness information of loop iterators trough-out // the loop body. - void DoLoopLivenessUnification(const opt::Loop& loop) { - auto blocks_in_loop = opt::MakeFilterIteratorRange( + void DoLoopLivenessUnification(const Loop& loop) { + auto blocks_in_loop = MakeFilterIteratorRange( loop.GetBlocks().begin(), loop.GetBlocks().end(), [&loop, this](uint32_t bb_id) { return bb_id != loop.GetHeaderBlock()->id() && @@ -176,12 +176,12 @@ class ComputeRegisterLiveness { "Liveness analysis was not performed for the current block"); ExcludePhiDefinedInBlock predicate(context_, loop.GetHeaderBlock()); - auto live_loop = opt::MakeFilterIteratorRange( - header_live_inout->live_in_.begin(), header_live_inout->live_in_.end(), - predicate); + auto live_loop = + MakeFilterIteratorRange(header_live_inout->live_in_.begin(), + header_live_inout->live_in_.end(), predicate); for (uint32_t bb_id : blocks_in_loop) { - opt::BasicBlock* bb = cfg_.block(bb_id); + BasicBlock* bb = cfg_.block(bb_id); RegisterLiveness::RegionRegisterLiveness* live_inout = reg_pressure_->Get(bb); @@ -189,7 +189,7 @@ class ComputeRegisterLiveness { live_inout->live_out_.insert(live_loop.begin(), live_loop.end()); } - for (const opt::Loop* inner_loop : loop) { + for (const Loop* inner_loop : loop) { RegisterLiveness::RegionRegisterLiveness* live_inout = reg_pressure_->Get(inner_loop->GetHeaderBlock()); live_inout->live_in_.insert(live_loop.begin(), live_loop.end()); @@ -201,19 +201,19 @@ class ComputeRegisterLiveness { // Get the number of required registers for this each basic block. void EvaluateRegisterRequirements() { - for (opt::BasicBlock& bb : *function_) { + for (BasicBlock& bb : *function_) { RegisterLiveness::RegionRegisterLiveness* live_inout = reg_pressure_->Get(bb.id()); assert(live_inout != nullptr && "Basic block not processed"); size_t reg_count = live_inout->live_out_.size(); - for (opt::Instruction* insn : live_inout->live_out_) { + for (Instruction* insn : live_inout->live_out_) { live_inout->AddRegisterClass(insn); } live_inout->used_registers_ = reg_count; std::unordered_set<uint32_t> die_in_block; - for (opt::Instruction& insn : opt::make_range(bb.rbegin(), bb.rend())) { + for (Instruction& insn : make_range(bb.rbegin(), bb.rend())) { // If it is a phi instruction, the register pressure will not change // anymore. if (insn.opcode() == SpvOpPhi) { @@ -222,7 +222,7 @@ class ComputeRegisterLiveness { insn.ForEachInId( [live_inout, &die_in_block, ®_count, this](uint32_t* id) { - opt::Instruction* op_insn = def_use_manager_.GetDef(*id); + Instruction* op_insn = def_use_manager_.GetDef(*id); if (!CreatesRegisterUsage(op_insn) || live_inout->live_out_.count(op_insn)) { // already taken into account. @@ -244,18 +244,18 @@ class ComputeRegisterLiveness { } RegisterLiveness* reg_pressure_; - opt::IRContext* context_; - opt::Function* function_; - opt::CFG& cfg_; + IRContext* context_; + Function* function_; + CFG& cfg_; analysis::DefUseManager& def_use_manager_; DominatorTree& dom_tree_; - opt::LoopDescriptor& loop_desc_; + LoopDescriptor& loop_desc_; }; } // namespace // Get the number of required registers for each basic block. void RegisterLiveness::RegionRegisterLiveness::AddRegisterClass( - opt::Instruction* insn) { + Instruction* insn) { assert(CreatesRegisterUsage(insn) && "Instruction does not use a register"); analysis::Type* type = insn->context()->get_type_mgr()->GetType(insn->type_id()); @@ -264,7 +264,7 @@ void RegisterLiveness::RegionRegisterLiveness::AddRegisterClass( insn->context()->get_decoration_mgr()->WhileEachDecoration( insn->result_id(), SpvDecorationUniform, - [®_class](const opt::Instruction&) { + [®_class](const Instruction&) { reg_class.is_uniform_ = true; return false; }); @@ -272,13 +272,13 @@ void RegisterLiveness::RegionRegisterLiveness::AddRegisterClass( AddRegisterClass(reg_class); } -void RegisterLiveness::Analyze(opt::Function* f) { +void RegisterLiveness::Analyze(Function* f) { block_pressure_.clear(); ComputeRegisterLiveness(this, f).Compute(); } void RegisterLiveness::ComputeLoopRegisterPressure( - const opt::Loop& loop, RegionRegisterLiveness* loop_reg_pressure) const { + const Loop& loop, RegionRegisterLiveness* loop_reg_pressure) const { loop_reg_pressure->Clear(); const RegionRegisterLiveness* header_live_inout = Get(loop.GetHeaderBlock()); @@ -294,11 +294,11 @@ void RegisterLiveness::ComputeLoopRegisterPressure( } std::unordered_set<uint32_t> seen_insn; - for (opt::Instruction* insn : loop_reg_pressure->live_out_) { + for (Instruction* insn : loop_reg_pressure->live_out_) { loop_reg_pressure->AddRegisterClass(insn); seen_insn.insert(insn->result_id()); } - for (opt::Instruction* insn : loop_reg_pressure->live_in_) { + for (Instruction* insn : loop_reg_pressure->live_in_) { if (!seen_insn.count(insn->result_id())) { continue; } @@ -309,14 +309,14 @@ void RegisterLiveness::ComputeLoopRegisterPressure( loop_reg_pressure->used_registers_ = 0; for (uint32_t bb_id : loop.GetBlocks()) { - opt::BasicBlock* bb = context_->cfg()->block(bb_id); + BasicBlock* bb = context_->cfg()->block(bb_id); const RegionRegisterLiveness* live_inout = Get(bb_id); assert(live_inout != nullptr && "Basic block not processed"); loop_reg_pressure->used_registers_ = std::max( loop_reg_pressure->used_registers_, live_inout->used_registers_); - for (opt::Instruction& insn : *bb) { + for (Instruction& insn : *bb) { if (insn.opcode() == SpvOpPhi || !CreatesRegisterUsage(&insn) || seen_insn.count(insn.result_id())) { continue; @@ -327,8 +327,7 @@ void RegisterLiveness::ComputeLoopRegisterPressure( } void RegisterLiveness::SimulateFusion( - const opt::Loop& l1, const opt::Loop& l2, - RegionRegisterLiveness* sim_result) const { + const Loop& l1, const Loop& l2, RegionRegisterLiveness* sim_result) const { sim_result->Clear(); // Compute the live-in state: @@ -354,11 +353,11 @@ void RegisterLiveness::SimulateFusion( // Compute the register usage information. std::unordered_set<uint32_t> seen_insn; - for (opt::Instruction* insn : sim_result->live_out_) { + for (Instruction* insn : sim_result->live_out_) { sim_result->AddRegisterClass(insn); seen_insn.insert(insn->result_id()); } - for (opt::Instruction* insn : sim_result->live_in_) { + for (Instruction* insn : sim_result->live_in_) { if (!seen_insn.count(insn->result_id())) { continue; } @@ -374,17 +373,17 @@ void RegisterLiveness::SimulateFusion( // l2 live-in header blocks) into the the live in/out of each basic block of // l1 to get the peak register usage. We then repeat the operation to for l2 // basic blocks but in this case we inject the live-out of the latch of l1. - auto live_loop = opt::MakeFilterIteratorRange( + auto live_loop = MakeFilterIteratorRange( sim_result->live_in_.begin(), sim_result->live_in_.end(), - [&l1, &l2](opt::Instruction* insn) { - opt::BasicBlock* bb = insn->context()->get_instr_block(insn); + [&l1, &l2](Instruction* insn) { + BasicBlock* bb = insn->context()->get_instr_block(insn); return insn->HasResultId() && !(insn->opcode() == SpvOpPhi && (bb == l1.GetHeaderBlock() || bb == l2.GetHeaderBlock())); }); for (uint32_t bb_id : l1.GetBlocks()) { - opt::BasicBlock* bb = context_->cfg()->block(bb_id); + BasicBlock* bb = context_->cfg()->block(bb_id); const RegionRegisterLiveness* live_inout_info = Get(bb_id); assert(live_inout_info != nullptr && "Basic block not processed"); @@ -395,7 +394,7 @@ void RegisterLiveness::SimulateFusion( live_inout_info->used_registers_ + live_out.size() - live_inout_info->live_out_.size()); - for (opt::Instruction& insn : *bb) { + for (Instruction& insn : *bb) { if (insn.opcode() == SpvOpPhi || !CreatesRegisterUsage(&insn) || seen_insn.count(insn.result_id())) { continue; @@ -412,10 +411,10 @@ void RegisterLiveness::SimulateFusion( l1_latch_live_out.insert(live_loop.begin(), live_loop.end()); auto live_loop_l2 = - opt::make_range(l1_latch_live_out.begin(), l1_latch_live_out.end()); + make_range(l1_latch_live_out.begin(), l1_latch_live_out.end()); for (uint32_t bb_id : l2.GetBlocks()) { - opt::BasicBlock* bb = context_->cfg()->block(bb_id); + BasicBlock* bb = context_->cfg()->block(bb_id); const RegionRegisterLiveness* live_inout_info = Get(bb_id); assert(live_inout_info != nullptr && "Basic block not processed"); @@ -426,7 +425,7 @@ void RegisterLiveness::SimulateFusion( live_inout_info->used_registers_ + live_out.size() - live_inout_info->live_out_.size()); - for (opt::Instruction& insn : *bb) { + for (Instruction& insn : *bb) { if (insn.opcode() == SpvOpPhi || !CreatesRegisterUsage(&insn) || seen_insn.count(insn.result_id())) { continue; @@ -437,9 +436,8 @@ void RegisterLiveness::SimulateFusion( } void RegisterLiveness::SimulateFission( - const opt::Loop& loop, - const std::unordered_set<opt::Instruction*>& moved_inst, - const std::unordered_set<opt::Instruction*>& copied_inst, + const Loop& loop, const std::unordered_set<Instruction*>& moved_inst, + const std::unordered_set<Instruction*>& copied_inst, RegionRegisterLiveness* l1_sim_result, RegionRegisterLiveness* l2_sim_result) const { l1_sim_result->Clear(); @@ -447,26 +445,25 @@ void RegisterLiveness::SimulateFission( // Filter predicates: consider instructions that only belong to the first and // second loop. - auto belong_to_loop1 = [&moved_inst, &copied_inst, - &loop](opt::Instruction* insn) { + auto belong_to_loop1 = [&moved_inst, &copied_inst, &loop](Instruction* insn) { return moved_inst.count(insn) || copied_inst.count(insn) || !loop.IsInsideLoop(insn); }; - auto belong_to_loop2 = [&moved_inst](opt::Instruction* insn) { + auto belong_to_loop2 = [&moved_inst](Instruction* insn) { return !moved_inst.count(insn); }; const RegionRegisterLiveness* header_live_inout = Get(loop.GetHeaderBlock()); // l1 live-in { - auto live_loop = opt::MakeFilterIteratorRange( + auto live_loop = MakeFilterIteratorRange( header_live_inout->live_in_.begin(), header_live_inout->live_in_.end(), belong_to_loop1); l1_sim_result->live_in_.insert(live_loop.begin(), live_loop.end()); } // l2 live-in { - auto live_loop = opt::MakeFilterIteratorRange( + auto live_loop = MakeFilterIteratorRange( header_live_inout->live_in_.begin(), header_live_inout->live_in_.end(), belong_to_loop2); l2_sim_result->live_in_.insert(live_loop.begin(), live_loop.end()); @@ -483,25 +480,25 @@ void RegisterLiveness::SimulateFission( } // l1 live-out. { - auto live_out = opt::MakeFilterIteratorRange( - l2_sim_result->live_out_.begin(), l2_sim_result->live_out_.end(), - belong_to_loop1); + auto live_out = MakeFilterIteratorRange(l2_sim_result->live_out_.begin(), + l2_sim_result->live_out_.end(), + belong_to_loop1); l1_sim_result->live_out_.insert(live_out.begin(), live_out.end()); } { - auto live_out = opt::MakeFilterIteratorRange( - l2_sim_result->live_in_.begin(), l2_sim_result->live_in_.end(), - belong_to_loop1); + auto live_out = + MakeFilterIteratorRange(l2_sim_result->live_in_.begin(), + l2_sim_result->live_in_.end(), belong_to_loop1); l1_sim_result->live_out_.insert(live_out.begin(), live_out.end()); } // Lives out of l1 are live out of l2 so are live in of l2 as well. l2_sim_result->live_in_.insert(l1_sim_result->live_out_.begin(), l1_sim_result->live_out_.end()); - for (opt::Instruction* insn : l1_sim_result->live_in_) { + for (Instruction* insn : l1_sim_result->live_in_) { l1_sim_result->AddRegisterClass(insn); } - for (opt::Instruction* insn : l2_sim_result->live_in_) { + for (Instruction* insn : l2_sim_result->live_in_) { l2_sim_result->AddRegisterClass(insn); } @@ -509,16 +506,16 @@ void RegisterLiveness::SimulateFission( l2_sim_result->used_registers_ = 0; for (uint32_t bb_id : loop.GetBlocks()) { - opt::BasicBlock* bb = context_->cfg()->block(bb_id); + BasicBlock* bb = context_->cfg()->block(bb_id); const RegisterLiveness::RegionRegisterLiveness* live_inout = Get(bb_id); assert(live_inout != nullptr && "Basic block not processed"); - auto l1_block_live_out = opt::MakeFilterIteratorRange( - live_inout->live_out_.begin(), live_inout->live_out_.end(), - belong_to_loop1); - auto l2_block_live_out = opt::MakeFilterIteratorRange( - live_inout->live_out_.begin(), live_inout->live_out_.end(), - belong_to_loop2); + auto l1_block_live_out = + MakeFilterIteratorRange(live_inout->live_out_.begin(), + live_inout->live_out_.end(), belong_to_loop1); + auto l2_block_live_out = + MakeFilterIteratorRange(live_inout->live_out_.begin(), + live_inout->live_out_.end(), belong_to_loop2); size_t l1_reg_count = std::distance(l1_block_live_out.begin(), l1_block_live_out.end()); @@ -526,7 +523,7 @@ void RegisterLiveness::SimulateFission( std::distance(l2_block_live_out.begin(), l2_block_live_out.end()); std::unordered_set<uint32_t> die_in_block; - for (opt::Instruction& insn : opt::make_range(bb->rbegin(), bb->rend())) { + for (Instruction& insn : make_range(bb->rbegin(), bb->rend())) { if (insn.opcode() == SpvOpPhi) { break; } @@ -536,7 +533,7 @@ void RegisterLiveness::SimulateFission( insn.ForEachInId([live_inout, &die_in_block, &l1_reg_count, &l2_reg_count, does_belong_to_loop1, does_belong_to_loop2, this](uint32_t* id) { - opt::Instruction* op_insn = context_->get_def_use_mgr()->GetDef(*id); + Instruction* op_insn = context_->get_def_use_mgr()->GetDef(*id); if (!CreatesRegisterUsage(op_insn) || live_inout->live_out_.count(op_insn)) { // already taken into account. diff --git a/source/opt/register_pressure.h b/source/opt/register_pressure.h index 77383e34..96892272 100644 --- a/source/opt/register_pressure.h +++ b/source/opt/register_pressure.h @@ -47,7 +47,7 @@ class RegisterLiveness { }; struct RegionRegisterLiveness { - using LiveSet = std::unordered_set<opt::Instruction*>; + using LiveSet = std::unordered_set<Instruction*>; using RegClassSetTy = std::vector<std::pair<RegisterClass, size_t>>; // SSA register live when entering the basic block. @@ -81,17 +81,16 @@ class RegisterLiveness { } } - void AddRegisterClass(opt::Instruction* insn); + void AddRegisterClass(Instruction* insn); }; - RegisterLiveness(opt::IRContext* context, opt::Function* f) - : context_(context) { + RegisterLiveness(IRContext* context, Function* f) : context_(context) { Analyze(f); } // Returns liveness and register information for the basic block |bb|. If no // entry exist for the basic block, the function returns null. - const RegionRegisterLiveness* Get(const opt::BasicBlock* bb) const { + const RegionRegisterLiveness* Get(const BasicBlock* bb) const { return Get(bb->id()); } @@ -105,13 +104,11 @@ class RegisterLiveness { return nullptr; } - opt::IRContext* GetContext() const { return context_; } + IRContext* GetContext() const { return context_; } // Returns liveness and register information for the basic block |bb|. If no // entry exist for the basic block, the function returns null. - RegionRegisterLiveness* Get(const opt::BasicBlock* bb) { - return Get(bb->id()); - } + RegionRegisterLiveness* Get(const BasicBlock* bb) { return Get(bb->id()); } // Returns liveness and register information for the basic block id |bb_id|. // If no entry exist for the basic block, the function returns null. @@ -133,12 +130,12 @@ class RegisterLiveness { // |reg_pressure|. The live-in set corresponds to the live-in set of the // header block, the live-out set of the loop corresponds to the union of the // live-in sets of each exit basic block. - void ComputeLoopRegisterPressure(const opt::Loop& loop, + void ComputeLoopRegisterPressure(const Loop& loop, RegionRegisterLiveness* reg_pressure) const; // Estimate the register pressure for the |l1| and |l2| as if they were making // one unique loop. The result is stored into |simulation_result|. - void SimulateFusion(const opt::Loop& l1, const opt::Loop& l2, + void SimulateFusion(const Loop& l1, const Loop& l2, RegionRegisterLiveness* simulation_result) const; // Estimate the register pressure of |loop| after it has been fissioned @@ -150,9 +147,9 @@ class RegisterLiveness { // moved instructions. The set |loop2_sim_result| store the simulation result // of the loop with the removed instructions. void SimulateFission( - const opt::Loop& loop, - const std::unordered_set<opt::Instruction*>& moved_instructions, - const std::unordered_set<opt::Instruction*>& copied_instructions, + const Loop& loop, + const std::unordered_set<Instruction*>& moved_instructions, + const std::unordered_set<Instruction*>& copied_instructions, RegionRegisterLiveness* loop1_sim_result, RegionRegisterLiveness* loop2_sim_result) const; @@ -160,10 +157,10 @@ class RegisterLiveness { using RegionRegisterLivenessMap = std::unordered_map<uint32_t, RegionRegisterLiveness>; - opt::IRContext* context_; + IRContext* context_; RegionRegisterLivenessMap block_pressure_; - void Analyze(opt::Function* f); + void Analyze(Function* f); }; // Handles the register pressure of a function for different regions (function, @@ -171,15 +168,15 @@ class RegisterLiveness { // pressure following code transformations. class LivenessAnalysis { using LivenessAnalysisMap = - std::unordered_map<const opt::Function*, RegisterLiveness>; + std::unordered_map<const Function*, RegisterLiveness>; public: - LivenessAnalysis(opt::IRContext* context) : context_(context) {} + LivenessAnalysis(IRContext* context) : context_(context) {} // Computes the liveness analysis for the function |f| and cache the result. // If the analysis was performed for this function, then the cached analysis // is returned. - const RegisterLiveness* Get(opt::Function* f) { + const RegisterLiveness* Get(Function* f) { LivenessAnalysisMap::iterator it = analysis_cache_.find(f); if (it != analysis_cache_.end()) { return &it->second; @@ -189,7 +186,7 @@ class LivenessAnalysis { } private: - opt::IRContext* context_; + IRContext* context_; LivenessAnalysisMap analysis_cache_; }; diff --git a/source/opt/remove_duplicates_pass.cpp b/source/opt/remove_duplicates_pass.cpp index 736e52f3..bfbab4d6 100644 --- a/source/opt/remove_duplicates_pass.cpp +++ b/source/opt/remove_duplicates_pass.cpp @@ -30,12 +30,6 @@ namespace spvtools { namespace opt { -using opt::Instruction; -using opt::Module; -using opt::Operand; -using opt::analysis::DecorationManager; -using opt::analysis::DefUseManager; - Pass::Status RemoveDuplicatesPass::Process() { bool modified = RemoveDuplicateCapabilities(); modified |= RemoveDuplicatesExtInstImports(); @@ -155,7 +149,7 @@ bool RemoveDuplicatesPass::RemoveDuplicateDecorations() const { std::vector<const Instruction*> visited_decorations; - opt::analysis::DecorationManager decoration_manager(context()->module()); + analysis::DecorationManager decoration_manager(context()->module()); for (auto* i = &*context()->annotation_begin(); i;) { // Is the current decoration equal to one of the decorations we have aready // visited? @@ -185,9 +179,9 @@ bool RemoveDuplicatesPass::RemoveDuplicateDecorations() const { bool RemoveDuplicatesPass::AreTypesEqual(const Instruction& inst1, const Instruction& inst2, - opt::IRContext* context) { + IRContext* context) { if (inst1.opcode() != inst2.opcode()) return false; - if (!opt::IsTypeInst(inst1.opcode())) return false; + if (!IsTypeInst(inst1.opcode())) return false; const analysis::Type* type1 = context->get_type_mgr()->GetType(inst1.result_id()); diff --git a/source/opt/remove_duplicates_pass.h b/source/opt/remove_duplicates_pass.h index 3781554d..b252fdc2 100644 --- a/source/opt/remove_duplicates_pass.h +++ b/source/opt/remove_duplicates_pass.h @@ -27,7 +27,7 @@ namespace spvtools { namespace opt { using IdDecorationsList = - std::unordered_map<uint32_t, std::vector<opt::Instruction*>>; + std::unordered_map<uint32_t, std::vector<Instruction*>>; // See optimizer.hpp for documentation. class RemoveDuplicatesPass : public Pass { @@ -38,9 +38,8 @@ class RemoveDuplicatesPass : public Pass { // TODO(pierremoreau): Move this function somewhere else (e.g. pass.h or // within the type manager) // Returns whether two types are equal, and have the same decorations. - static bool AreTypesEqual(const opt::Instruction& inst1, - const opt::Instruction& inst2, - opt::IRContext* context); + static bool AreTypesEqual(const Instruction& inst1, const Instruction& inst2, + IRContext* context); private: // Remove duplicate capabilities from the module diff --git a/source/opt/replace_invalid_opc.cpp b/source/opt/replace_invalid_opc.cpp index 49908907..711405fb 100644 --- a/source/opt/replace_invalid_opc.cpp +++ b/source/opt/replace_invalid_opc.cpp @@ -37,7 +37,7 @@ Pass::Status ReplaceInvalidOpcodePass::Process() { return Status::SuccessWithoutChange; } - for (opt::Function& func : *get_module()) { + for (Function& func : *get_module()) { modified |= RewriteFunction(&func, execution_model); } return (modified ? Status::SuccessWithChange : Status::SuccessWithoutChange); @@ -46,7 +46,7 @@ Pass::Status ReplaceInvalidOpcodePass::Process() { SpvExecutionModel ReplaceInvalidOpcodePass::GetExecutionModel() { SpvExecutionModel result = SpvExecutionModelMax; bool first = true; - for (opt::Instruction& entry_point : get_module()->entry_points()) { + for (Instruction& entry_point : get_module()->entry_points()) { if (first) { result = static_cast<SpvExecutionModel>(entry_point.GetSingleWordInOperand(0)); @@ -63,12 +63,12 @@ SpvExecutionModel ReplaceInvalidOpcodePass::GetExecutionModel() { return result; } -bool ReplaceInvalidOpcodePass::RewriteFunction(opt::Function* function, +bool ReplaceInvalidOpcodePass::RewriteFunction(Function* function, SpvExecutionModel model) { bool modified = false; - opt::Instruction* last_line_dbg_inst = nullptr; + Instruction* last_line_dbg_inst = nullptr; function->ForEachInst( - [model, &modified, &last_line_dbg_inst, this](opt::Instruction* inst) { + [model, &modified, &last_line_dbg_inst, this](Instruction* inst) { // Track the debug information so we can have a meaningful message. if (inst->opcode() == SpvOpLabel || inst->opcode() == SpvOpNoLine) { last_line_dbg_inst = nullptr; @@ -99,7 +99,7 @@ bool ReplaceInvalidOpcodePass::RewriteFunction(opt::Function* function, ReplaceInstruction(inst, nullptr, 0, 0); } else { // Get the name of the source file. - opt::Instruction* file_name = context()->get_def_use_mgr()->GetDef( + Instruction* file_name = context()->get_def_use_mgr()->GetDef( last_line_dbg_inst->GetSingleWordInOperand(0)); const char* source = reinterpret_cast<const char*>( &file_name->GetInOperand(0).words[0]); @@ -119,7 +119,7 @@ bool ReplaceInvalidOpcodePass::RewriteFunction(opt::Function* function, } bool ReplaceInvalidOpcodePass::IsFragmentShaderOnlyInstruction( - opt::Instruction* inst) { + Instruction* inst) { switch (inst->opcode()) { case SpvOpDPdx: case SpvOpDPdy: @@ -146,7 +146,7 @@ bool ReplaceInvalidOpcodePass::IsFragmentShaderOnlyInstruction( } } -void ReplaceInvalidOpcodePass::ReplaceInstruction(opt::Instruction* inst, +void ReplaceInvalidOpcodePass::ReplaceInstruction(Instruction* inst, const char* source, uint32_t line_number, uint32_t column_number) { @@ -171,7 +171,7 @@ uint32_t ReplaceInvalidOpcodePass::GetSpecialConstant(uint32_t type_id) { analysis::ConstantManager* const_mgr = context()->get_constant_mgr(); analysis::TypeManager* type_mgr = context()->get_type_mgr(); - opt::Instruction* type = context()->get_def_use_mgr()->GetDef(type_id); + Instruction* type = context()->get_def_use_mgr()->GetDef(type_id); if (type->opcode() == SpvOpTypeVector) { uint32_t component_const = GetSpecialConstant(type->GetSingleWordInOperand(0)); diff --git a/source/opt/replace_invalid_opc.h b/source/opt/replace_invalid_opc.h index 96dedd68..9c8499f6 100644 --- a/source/opt/replace_invalid_opc.h +++ b/source/opt/replace_invalid_opc.h @@ -38,16 +38,16 @@ class ReplaceInvalidOpcodePass : public Pass { // Replaces all instructions in |function| that are invalid with execution // model |mode|, but valid for another shader model, with a special constant // value. See |GetSpecialConstant|. - bool RewriteFunction(opt::Function* function, SpvExecutionModel mode); + bool RewriteFunction(Function* function, SpvExecutionModel mode); // Returns true if |inst| is valid for fragment shaders only. - bool IsFragmentShaderOnlyInstruction(opt::Instruction* inst); + bool IsFragmentShaderOnlyInstruction(Instruction* inst); // Replaces all uses of the result of |inst|, if there is one, with the id of // a special constant. Then |inst| is killed. |inst| cannot be a block // terminator because the basic block will then become invalid. |inst| is no // longer valid after calling this function. - void ReplaceInstruction(opt::Instruction* inst, const char* source, + void ReplaceInstruction(Instruction* inst, const char* source, uint32_t line_number, uint32_t column_number); // Returns the id of a constant with type |type_id|. The type must be an diff --git a/source/opt/scalar_analysis.cpp b/source/opt/scalar_analysis.cpp index 785653e8..c124a3ff 100644 --- a/source/opt/scalar_analysis.cpp +++ b/source/opt/scalar_analysis.cpp @@ -48,7 +48,7 @@ namespace opt { uint32_t SENode::NumberOfNodes = 0; -ScalarEvolutionAnalysis::ScalarEvolutionAnalysis(opt::IRContext* context) +ScalarEvolutionAnalysis::ScalarEvolutionAnalysis(IRContext* context) : context_(context), pretend_equal_{} { // Create and cached the CantComputeNode. cached_cant_compute_ = @@ -73,14 +73,14 @@ SENode* ScalarEvolutionAnalysis::CreateConstant(int64_t integer) { } SENode* ScalarEvolutionAnalysis::CreateRecurrentExpression( - const opt::Loop* loop, SENode* offset, SENode* coefficient) { + const Loop* loop, SENode* offset, SENode* coefficient) { assert(loop && "Recurrent add expressions must have a valid loop."); // If operands are can't compute then the whole graph is can't compute. if (offset->IsCantCompute() || coefficient->IsCantCompute()) return CreateCantComputeNode(); - const opt::Loop* loop_to_use = nullptr; + const Loop* loop_to_use = nullptr; if (pretend_equal_[loop]) { loop_to_use = pretend_equal_[loop]; } else { @@ -96,10 +96,10 @@ SENode* ScalarEvolutionAnalysis::CreateRecurrentExpression( } SENode* ScalarEvolutionAnalysis::AnalyzeMultiplyOp( - const opt::Instruction* multiply) { + const Instruction* multiply) { assert(multiply->opcode() == SpvOp::SpvOpIMul && "Multiply node did not come from a multiply instruction"); - opt::analysis::DefUseManager* def_use = context_->get_def_use_mgr(); + analysis::DefUseManager* def_use = context_->get_def_use_mgr(); SENode* op1 = AnalyzeInstruction(def_use->GetDef(multiply->GetSingleWordInOperand(0))); @@ -162,8 +162,7 @@ SENode* ScalarEvolutionAnalysis::CreateAddNode(SENode* operand_1, return GetCachedOrAdd(std::move(add_node)); } -SENode* ScalarEvolutionAnalysis::AnalyzeInstruction( - const opt::Instruction* inst) { +SENode* ScalarEvolutionAnalysis::AnalyzeInstruction(const Instruction* inst) { auto itr = recurrent_node_map_.find(inst); if (itr != recurrent_node_map_.end()) return itr->second; @@ -196,7 +195,7 @@ SENode* ScalarEvolutionAnalysis::AnalyzeInstruction( return output; } -SENode* ScalarEvolutionAnalysis::AnalyzeConstant(const opt::Instruction* inst) { +SENode* ScalarEvolutionAnalysis::AnalyzeConstant(const Instruction* inst) { if (inst->opcode() == SpvOp::SpvOpConstantNull) return CreateConstant(0); assert(inst->opcode() == SpvOp::SpvOpConstant); @@ -204,12 +203,12 @@ SENode* ScalarEvolutionAnalysis::AnalyzeConstant(const opt::Instruction* inst) { int64_t value = 0; // Look up the instruction in the constant manager. - const opt::analysis::Constant* constant = + const analysis::Constant* constant = context_->get_constant_mgr()->FindDeclaredConstant(inst->result_id()); if (!constant) return CreateCantComputeNode(); - const opt::analysis::IntConstant* int_constant = constant->AsIntConstant(); + const analysis::IntConstant* int_constant = constant->AsIntConstant(); // Exit out if it is a 64 bit integer. if (!int_constant || int_constant->words().size() != 1) @@ -226,12 +225,12 @@ SENode* ScalarEvolutionAnalysis::AnalyzeConstant(const opt::Instruction* inst) { // Handles both addition and subtraction. If the |sub| flag is set then the // addition will be op1+(-op2) otherwise op1+op2. -SENode* ScalarEvolutionAnalysis::AnalyzeAddOp(const opt::Instruction* inst) { +SENode* ScalarEvolutionAnalysis::AnalyzeAddOp(const Instruction* inst) { assert((inst->opcode() == SpvOp::SpvOpIAdd || inst->opcode() == SpvOp::SpvOpISub) && "Add node must be created from a OpIAdd or OpISub instruction"); - opt::analysis::DefUseManager* def_use = context_->get_def_use_mgr(); + analysis::DefUseManager* def_use = context_->get_def_use_mgr(); SENode* op1 = AnalyzeInstruction(def_use->GetDef(inst->GetSingleWordInOperand(0))); @@ -247,30 +246,29 @@ SENode* ScalarEvolutionAnalysis::AnalyzeAddOp(const opt::Instruction* inst) { return CreateAddNode(op1, op2); } -SENode* ScalarEvolutionAnalysis::AnalyzePhiInstruction( - const opt::Instruction* phi) { +SENode* ScalarEvolutionAnalysis::AnalyzePhiInstruction(const Instruction* phi) { // The phi should only have two incoming value pairs. if (phi->NumInOperands() != 4) { return CreateCantComputeNode(); } - opt::analysis::DefUseManager* def_use = context_->get_def_use_mgr(); + analysis::DefUseManager* def_use = context_->get_def_use_mgr(); // Get the basic block this instruction belongs to. - opt::BasicBlock* basic_block = - context_->get_instr_block(const_cast<opt::Instruction*>(phi)); + BasicBlock* basic_block = + context_->get_instr_block(const_cast<Instruction*>(phi)); // And then the function that the basic blocks belongs to. - opt::Function* function = basic_block->GetParent(); + Function* function = basic_block->GetParent(); // Use the function to get the loop descriptor. - opt::LoopDescriptor* loop_descriptor = context_->GetLoopDescriptor(function); + LoopDescriptor* loop_descriptor = context_->GetLoopDescriptor(function); // We only handle phis in loops at the moment. if (!loop_descriptor) return CreateCantComputeNode(); // Get the innermost loop which this block belongs to. - opt::Loop* loop = (*loop_descriptor)[basic_block->id()]; + Loop* loop = (*loop_descriptor)[basic_block->id()]; // If the loop doesn't exist or doesn't have a preheader or latch block, exit // out. @@ -278,7 +276,7 @@ SENode* ScalarEvolutionAnalysis::AnalyzePhiInstruction( loop->GetHeaderBlock() != basic_block) return recurrent_node_map_[phi] = CreateCantComputeNode(); - const opt::Loop* loop_to_use = nullptr; + const Loop* loop_to_use = nullptr; if (pretend_equal_[loop]) { loop_to_use = pretend_equal_[loop]; } else { @@ -298,7 +296,7 @@ SENode* ScalarEvolutionAnalysis::AnalyzePhiInstruction( uint32_t value_id = phi->GetSingleWordInOperand(i); uint32_t incoming_label_id = phi->GetSingleWordInOperand(i + 1); - opt::Instruction* value_inst = def_use->GetDef(value_id); + Instruction* value_inst = def_use->GetDef(value_id); SENode* value_node = AnalyzeInstruction(value_inst); // If any operand is CantCompute then the whole graph is CantCompute. @@ -352,7 +350,7 @@ SENode* ScalarEvolutionAnalysis::AnalyzePhiInstruction( } SENode* ScalarEvolutionAnalysis::CreateValueUnknownNode( - const opt::Instruction* inst) { + const Instruction* inst) { std::unique_ptr<SEValueUnknown> load_node{ new SEValueUnknown(this, inst->result_id())}; return GetCachedOrAdd(std::move(load_node)); @@ -375,11 +373,11 @@ SENode* ScalarEvolutionAnalysis::GetCachedOrAdd( return raw_ptr_to_node; } -bool ScalarEvolutionAnalysis::IsLoopInvariant(const opt::Loop* loop, +bool ScalarEvolutionAnalysis::IsLoopInvariant(const Loop* loop, const SENode* node) const { for (auto itr = node->graph_cbegin(); itr != node->graph_cend(); ++itr) { if (const SERecurrentNode* rec = itr->AsSERecurrentNode()) { - const opt::BasicBlock* header = rec->GetLoop()->GetHeaderBlock(); + const BasicBlock* header = rec->GetLoop()->GetHeaderBlock(); // If the loop which the recurrent expression belongs to is either |loop // or a nested loop inside |loop| then we assume it is variant. @@ -397,7 +395,7 @@ bool ScalarEvolutionAnalysis::IsLoopInvariant(const opt::Loop* loop, } SENode* ScalarEvolutionAnalysis::GetCoefficientFromRecurrentTerm( - SENode* node, const opt::Loop* loop) { + SENode* node, const Loop* loop) { // Traverse the DAG to find the recurrent expression belonging to |loop|. for (auto itr = node->graph_begin(); itr != node->graph_end(); ++itr) { SERecurrentNode* rec = itr->AsSERecurrentNode(); @@ -434,7 +432,7 @@ SENode* ScalarEvolutionAnalysis::UpdateChildNode(SENode* parent, // Rebuild the |node| eliminating, if it exists, the recurrent term which // belongs to the |loop|. SENode* ScalarEvolutionAnalysis::BuildGraphWithoutRecurrentTerm( - SENode* node, const opt::Loop* loop) { + SENode* node, const Loop* loop) { // If the node is already a recurrent expression belonging to loop then just // return the offset. SERecurrentNode* recurrent = node->AsSERecurrentNode(); @@ -467,8 +465,8 @@ SENode* ScalarEvolutionAnalysis::BuildGraphWithoutRecurrentTerm( // Return the recurrent term belonging to |loop| if it appears in the graph // starting at |node| or null if it doesn't. -SERecurrentNode* ScalarEvolutionAnalysis::GetRecurrentTerm( - SENode* node, const opt::Loop* loop) { +SERecurrentNode* ScalarEvolutionAnalysis::GetRecurrentTerm(SENode* node, + const Loop* loop) { for (auto itr = node->graph_begin(); itr != node->graph_end(); ++itr) { SERecurrentNode* rec = itr->AsSERecurrentNode(); if (rec && rec->GetLoop() == loop) { @@ -652,7 +650,7 @@ void SENode::DumpDot(std::ostream& out, bool recurse) const { namespace { class IsGreaterThanZero { public: - explicit IsGreaterThanZero(opt::IRContext* context) : context_(context) {} + explicit IsGreaterThanZero(IRContext* context) : context_(context) {} // Determine if the value of |node| is always strictly greater than zero if // |or_equal_zero| is false or greater or equal to zero if |or_equal_zero| is @@ -844,8 +842,7 @@ class IsGreaterThanZero { // Returns the signedness of an unknown |node| based on its type. Signedness Visit(const SEValueUnknown* node) { - opt::Instruction* insn = - context_->get_def_use_mgr()->GetDef(node->ResultId()); + Instruction* insn = context_->get_def_use_mgr()->GetDef(node->ResultId()); analysis::Type* type = context_->get_type_mgr()->GetType(insn->type_id()); assert(type && "Can't retrieve a type for the instruction"); analysis::Integer* int_type = type->AsInteger(); @@ -904,8 +901,7 @@ class IsGreaterThanZero { const SENode* node, std::function<Signedness(Signedness, Signedness)> reduce) { Signedness result = Visit(*node->begin()); - for (const SENode* operand : - opt::make_range(++node->begin(), node->end())) { + for (const SENode* operand : make_range(++node->begin(), node->end())) { if (result == Signedness::kPositiveOrNegative) { return Signedness::kPositiveOrNegative; } @@ -914,7 +910,7 @@ class IsGreaterThanZero { return result; } - opt::IRContext* context_; + IRContext* context_; }; } // namespace diff --git a/source/opt/scalar_analysis.h b/source/opt/scalar_analysis.h index 241c9d19..6f5c7615 100644 --- a/source/opt/scalar_analysis.h +++ b/source/opt/scalar_analysis.h @@ -40,7 +40,7 @@ class Loop; // usable form with SimplifyExpression. class ScalarEvolutionAnalysis { public: - explicit ScalarEvolutionAnalysis(opt::IRContext* context); + explicit ScalarEvolutionAnalysis(IRContext* context); // Create a unary negative node on |operand|. SENode* CreateNegation(SENode* operand); @@ -61,18 +61,18 @@ class ScalarEvolutionAnalysis { SENode* CreateConstant(int64_t integer); // Create a value unknown node, such as a load. - SENode* CreateValueUnknownNode(const opt::Instruction* inst); + SENode* CreateValueUnknownNode(const Instruction* inst); // Create a CantComputeNode. Used to exit out of analysis. SENode* CreateCantComputeNode(); // Create a new recurrent node with |offset| and |coefficient|, with respect // to |loop|. - SENode* CreateRecurrentExpression(const opt::Loop* loop, SENode* offset, + SENode* CreateRecurrentExpression(const Loop* loop, SENode* offset, SENode* coefficient); // Construct the DAG by traversing use def chain of |inst|. - SENode* AnalyzeInstruction(const opt::Instruction* inst); + SENode* AnalyzeInstruction(const Instruction* inst); // Simplify the |node| by grouping like terms or if contains a recurrent // expression, rewrite the graph so the whole DAG (from |node| down) is in @@ -91,7 +91,7 @@ class ScalarEvolutionAnalysis { SENode* GetCachedOrAdd(std::unique_ptr<SENode> prospective_node); // Checks that the graph starting from |node| is invariant to the |loop|. - bool IsLoopInvariant(const opt::Loop* loop, const SENode* node) const; + bool IsLoopInvariant(const Loop* loop, const SENode* node) const; // Sets |is_gt_zero| to true if |node| represent a value always strictly // greater than 0. The result of |is_gt_zero| is valid only if the function @@ -106,15 +106,15 @@ class ScalarEvolutionAnalysis { // |node| and return the coefficient of that recurrent term. Constant zero // will be returned if no recurrent could be found. |node| should be in // simplest form. - SENode* GetCoefficientFromRecurrentTerm(SENode* node, const opt::Loop* loop); + SENode* GetCoefficientFromRecurrentTerm(SENode* node, const Loop* loop); // Return a rebuilt graph starting from |node| with the recurrent expression // belonging to |loop| being zeroed out. Returned node will be simplified. - SENode* BuildGraphWithoutRecurrentTerm(SENode* node, const opt::Loop* loop); + SENode* BuildGraphWithoutRecurrentTerm(SENode* node, const Loop* loop); // Return the recurrent term belonging to |loop| if it appears in the graph // starting at |node| or null if it doesn't. - SERecurrentNode* GetRecurrentTerm(SENode* node, const opt::Loop* loop); + SERecurrentNode* GetRecurrentTerm(SENode* node, const Loop* loop); SENode* UpdateChildNode(SENode* parent, SENode* child, SENode* new_child); @@ -122,29 +122,29 @@ class ScalarEvolutionAnalysis { // SERecurrentNode objects. This enables analysing dependencies that will be // created during loop fusion. void AddLoopsToPretendAreTheSame( - const std::pair<const opt::Loop*, const opt::Loop*>& loop_pair) { + const std::pair<const Loop*, const Loop*>& loop_pair) { pretend_equal_[std::get<1>(loop_pair)] = std::get<0>(loop_pair); } private: - SENode* AnalyzeConstant(const opt::Instruction* inst); + SENode* AnalyzeConstant(const Instruction* inst); // Handles both addition and subtraction. If the |instruction| is OpISub // then the resulting node will be op1+(-op2) otherwise if it is OpIAdd then // the result will be op1+op2. |instruction| must be OpIAdd or OpISub. - SENode* AnalyzeAddOp(const opt::Instruction* instruction); + SENode* AnalyzeAddOp(const Instruction* instruction); - SENode* AnalyzeMultiplyOp(const opt::Instruction* multiply); + SENode* AnalyzeMultiplyOp(const Instruction* multiply); - SENode* AnalyzePhiInstruction(const opt::Instruction* phi); + SENode* AnalyzePhiInstruction(const Instruction* phi); - opt::IRContext* context_; + IRContext* context_; // A map of instructions to SENodes. This is used to track recurrent // expressions as they are added when analyzing instructions. Recurrent // expressions come from phi nodes which by nature can include recursion so we // check if nodes have already been built when analyzing instructions. - std::map<const opt::Instruction*, SENode*> recurrent_node_map_; + std::map<const Instruction*, SENode*> recurrent_node_map_; // On creation we create and cache the CantCompute node so we not need to // perform a needless create step. @@ -167,7 +167,7 @@ class ScalarEvolutionAnalysis { // Loops that should be considered the same for performing analysis for loop // fusion. - std::map<const opt::Loop*, const opt::Loop*> pretend_equal_; + std::map<const Loop*, const Loop*> pretend_equal_; }; // Wrapping class to manipulate SENode pointer using + - * / operators. diff --git a/source/opt/scalar_analysis_nodes.h b/source/opt/scalar_analysis_nodes.h index ee19c66b..59cd725b 100644 --- a/source/opt/scalar_analysis_nodes.h +++ b/source/opt/scalar_analysis_nodes.h @@ -53,7 +53,7 @@ class SENode { using ChildContainerType = std::vector<SENode*>; - explicit SENode(opt::ScalarEvolutionAnalysis* parent_analysis) + explicit SENode(ScalarEvolutionAnalysis* parent_analysis) : parent_analysis_(parent_analysis), unique_id_(++NumberOfNodes) {} virtual SENodeType GetType() const = 0; @@ -183,14 +183,14 @@ class SENode { #undef DeclareCastMethod // Get the analysis which has this node in its cache. - inline opt::ScalarEvolutionAnalysis* GetParentAnalysis() const { + inline ScalarEvolutionAnalysis* GetParentAnalysis() const { return parent_analysis_; } protected: ChildContainerType children_; - opt::ScalarEvolutionAnalysis* parent_analysis_; + ScalarEvolutionAnalysis* parent_analysis_; // The unique id of this node, assigned on creation by incrementing the static // node count. @@ -211,7 +211,7 @@ struct SENodeHash { // A node representing a constant integer. class SEConstantNode : public SENode { public: - SEConstantNode(opt::ScalarEvolutionAnalysis* parent_analysis, int64_t value) + SEConstantNode(ScalarEvolutionAnalysis* parent_analysis, int64_t value) : SENode(parent_analysis), literal_value_(value) {} SENodeType GetType() const final { return Constant; } @@ -237,8 +237,7 @@ class SEConstantNode : public SENode { // of zero and a coefficient of one. class SERecurrentNode : public SENode { public: - SERecurrentNode(opt::ScalarEvolutionAnalysis* parent_analysis, - const opt::Loop* loop) + SERecurrentNode(ScalarEvolutionAnalysis* parent_analysis, const Loop* loop) : SENode(parent_analysis), loop_(loop) {} SENodeType GetType() const final { return RecurrentAddExpr; } @@ -260,7 +259,7 @@ class SERecurrentNode : public SENode { inline SENode* GetOffset() { return offset_; } // Return the loop which this recurrent expression is recurring within. - const opt::Loop* GetLoop() const { return loop_; } + const Loop* GetLoop() const { return loop_; } SERecurrentNode* AsSERecurrentNode() override { return this; } const SERecurrentNode* AsSERecurrentNode() const override { return this; } @@ -268,13 +267,13 @@ class SERecurrentNode : public SENode { private: SENode* coefficient_; SENode* offset_; - const opt::Loop* loop_; + const Loop* loop_; }; // A node representing an addition operation between child nodes. class SEAddNode : public SENode { public: - explicit SEAddNode(opt::ScalarEvolutionAnalysis* parent_analysis) + explicit SEAddNode(ScalarEvolutionAnalysis* parent_analysis) : SENode(parent_analysis) {} SENodeType GetType() const final { return Add; } @@ -286,7 +285,7 @@ class SEAddNode : public SENode { // A node representing a multiply operation between child nodes. class SEMultiplyNode : public SENode { public: - explicit SEMultiplyNode(opt::ScalarEvolutionAnalysis* parent_analysis) + explicit SEMultiplyNode(ScalarEvolutionAnalysis* parent_analysis) : SENode(parent_analysis) {} SENodeType GetType() const final { return Multiply; } @@ -298,7 +297,7 @@ class SEMultiplyNode : public SENode { // A node representing a unary negative operation. class SENegative : public SENode { public: - explicit SENegative(opt::ScalarEvolutionAnalysis* parent_analysis) + explicit SENegative(ScalarEvolutionAnalysis* parent_analysis) : SENode(parent_analysis) {} SENodeType GetType() const final { return Negative; } @@ -314,8 +313,7 @@ class SEValueUnknown : public SENode { // SEValueUnknowns must come from an instruction |unique_id| is the unique id // of that instruction. This is so we cancompare value unknowns and have a // unique value unknown for each instruction. - SEValueUnknown(opt::ScalarEvolutionAnalysis* parent_analysis, - uint32_t result_id) + SEValueUnknown(ScalarEvolutionAnalysis* parent_analysis, uint32_t result_id) : SENode(parent_analysis), result_id_(result_id) {} SENodeType GetType() const final { return ValueUnknown; } @@ -332,7 +330,7 @@ class SEValueUnknown : public SENode { // A node which we cannot reason about at all. class SECantCompute : public SENode { public: - explicit SECantCompute(opt::ScalarEvolutionAnalysis* parent_analysis) + explicit SECantCompute(ScalarEvolutionAnalysis* parent_analysis) : SENode(parent_analysis) {} SENodeType GetType() const final { return CanNotCompute; } diff --git a/source/opt/scalar_analysis_simplification.cpp b/source/opt/scalar_analysis_simplification.cpp index c1dbcc99..58b08ea7 100644 --- a/source/opt/scalar_analysis_simplification.cpp +++ b/source/opt/scalar_analysis_simplification.cpp @@ -375,7 +375,7 @@ SENode* SENodeSimplifyImpl::FoldRecurrentAddExpressions(SENode* root) { // A mapping of loops to the list of recurrent expressions which are with // respect to those loops. - std::map<const opt::Loop*, std::vector<std::pair<SERecurrentNode*, bool>>> + std::map<const Loop*, std::vector<std::pair<SERecurrentNode*, bool>>> loops_to_recurrent{}; bool has_multiple_same_loop_recurrent_terms = false; @@ -389,7 +389,7 @@ SENode* SENodeSimplifyImpl::FoldRecurrentAddExpressions(SENode* root) { } if (child->GetType() == SENode::RecurrentAddExpr) { - const opt::Loop* loop = child->AsSERecurrentNode()->GetLoop(); + const Loop* loop = child->AsSERecurrentNode()->GetLoop(); SERecurrentNode* rec = child->AsSERecurrentNode(); if (loops_to_recurrent.find(loop) == loops_to_recurrent.end()) { @@ -408,7 +408,7 @@ SENode* SENodeSimplifyImpl::FoldRecurrentAddExpressions(SENode* root) { for (auto pair : loops_to_recurrent) { std::vector<std::pair<SERecurrentNode*, bool>>& recurrent_expressions = pair.second; - const opt::Loop* loop = pair.first; + const Loop* loop = pair.first; std::unique_ptr<SENode> new_coefficient{new SEAddNode(&analysis_)}; std::unique_ptr<SENode> new_offset{new SEAddNode(&analysis_)}; diff --git a/source/opt/scalar_replacement_pass.cpp b/source/opt/scalar_replacement_pass.cpp index e613e964..b3e9c52c 100644 --- a/source/opt/scalar_replacement_pass.cpp +++ b/source/opt/scalar_replacement_pass.cpp @@ -39,15 +39,15 @@ Pass::Status ScalarReplacementPass::Process() { return status; } -Pass::Status ScalarReplacementPass::ProcessFunction(opt::Function* function) { - std::queue<opt::Instruction*> worklist; - opt::BasicBlock& entry = *function->begin(); +Pass::Status ScalarReplacementPass::ProcessFunction(Function* function) { + std::queue<Instruction*> worklist; + BasicBlock& entry = *function->begin(); for (auto iter = entry.begin(); iter != entry.end(); ++iter) { // Function storage class OpVariables must appear as the first instructions // of the entry block. if (iter->opcode() != SpvOpVariable) break; - opt::Instruction* varInst = &*iter; + Instruction* varInst = &*iter; if (CanReplaceVariable(varInst)) { worklist.push(varInst); } @@ -55,7 +55,7 @@ Pass::Status ScalarReplacementPass::ProcessFunction(opt::Function* function) { Status status = Status::SuccessWithoutChange; while (!worklist.empty()) { - opt::Instruction* varInst = worklist.front(); + Instruction* varInst = worklist.front(); worklist.pop(); if (!ReplaceVariable(varInst, &worklist)) @@ -68,15 +68,15 @@ Pass::Status ScalarReplacementPass::ProcessFunction(opt::Function* function) { } bool ScalarReplacementPass::ReplaceVariable( - opt::Instruction* inst, std::queue<opt::Instruction*>* worklist) { - std::vector<opt::Instruction*> replacements; + Instruction* inst, std::queue<Instruction*>* worklist) { + std::vector<Instruction*> replacements; CreateReplacementVariables(inst, &replacements); - std::vector<opt::Instruction*> dead; + std::vector<Instruction*> dead; dead.push_back(inst); if (!get_def_use_mgr()->WhileEachUser( - inst, [this, &replacements, &dead](opt::Instruction* user) { - if (!opt::IsAnnotationInst(user->opcode())) { + inst, [this, &replacements, &dead](Instruction* user) { + if (!IsAnnotationInst(user->opcode())) { switch (user->opcode()) { case SpvOpLoad: ReplaceWholeLoad(user, replacements); @@ -105,7 +105,7 @@ bool ScalarReplacementPass::ReplaceVariable( // Clean up some dead code. while (!dead.empty()) { - opt::Instruction* toKill = dead.back(); + Instruction* toKill = dead.back(); dead.pop_back(); context()->KillInst(toKill); } @@ -125,14 +125,13 @@ bool ScalarReplacementPass::ReplaceVariable( } void ScalarReplacementPass::ReplaceWholeLoad( - opt::Instruction* load, - const std::vector<opt::Instruction*>& replacements) { + Instruction* load, const std::vector<Instruction*>& replacements) { // Replaces the load of the entire composite with a load from each replacement // variable followed by a composite construction. - opt::BasicBlock* block = context()->get_instr_block(load); - std::vector<opt::Instruction*> loads; + BasicBlock* block = context()->get_instr_block(load); + std::vector<Instruction*> loads; loads.reserve(replacements.size()); - opt::BasicBlock::iterator where(load); + BasicBlock::iterator where(load); for (auto var : replacements) { // Create a load of each replacement variable. if (var->opcode() != SpvOpVariable) { @@ -140,16 +139,16 @@ void ScalarReplacementPass::ReplaceWholeLoad( continue; } - opt::Instruction* type = GetStorageType(var); + Instruction* type = GetStorageType(var); uint32_t loadId = TakeNextId(); - std::unique_ptr<opt::Instruction> newLoad( - new opt::Instruction(context(), SpvOpLoad, type->result_id(), loadId, - std::initializer_list<opt::Operand>{ - {SPV_OPERAND_TYPE_ID, {var->result_id()}}})); + std::unique_ptr<Instruction> newLoad( + new Instruction(context(), SpvOpLoad, type->result_id(), loadId, + std::initializer_list<Operand>{ + {SPV_OPERAND_TYPE_ID, {var->result_id()}}})); // Copy memory access attributes which start at index 1. Index 0 is the // pointer to load. for (uint32_t i = 1; i < load->NumInOperands(); ++i) { - opt::Operand copy(load->GetInOperand(i)); + Operand copy(load->GetInOperand(i)); newLoad->AddOperand(std::move(copy)); } where = where.InsertBefore(std::move(newLoad)); @@ -161,11 +160,11 @@ void ScalarReplacementPass::ReplaceWholeLoad( // Construct a new composite. uint32_t compositeId = TakeNextId(); where = load; - std::unique_ptr<opt::Instruction> compositeConstruct(new opt::Instruction( + std::unique_ptr<Instruction> compositeConstruct(new Instruction( context(), SpvOpCompositeConstruct, load->type_id(), compositeId, {})); for (auto l : loads) { - opt::Operand op(SPV_OPERAND_TYPE_ID, - std::initializer_list<uint32_t>{l->result_id()}); + Operand op(SPV_OPERAND_TYPE_ID, + std::initializer_list<uint32_t>{l->result_id()}); compositeConstruct->AddOperand(std::move(op)); } where = where.InsertBefore(std::move(compositeConstruct)); @@ -175,13 +174,12 @@ void ScalarReplacementPass::ReplaceWholeLoad( } void ScalarReplacementPass::ReplaceWholeStore( - opt::Instruction* store, - const std::vector<opt::Instruction*>& replacements) { + Instruction* store, const std::vector<Instruction*>& replacements) { // Replaces a store to the whole composite with a series of extract and stores // to each element. uint32_t storeInput = store->GetSingleWordInOperand(1u); - opt::BasicBlock* block = context()->get_instr_block(store); - opt::BasicBlock::iterator where(store); + BasicBlock* block = context()->get_instr_block(store); + BasicBlock::iterator where(store); uint32_t elementIndex = 0; for (auto var : replacements) { // Create the extract. @@ -190,11 +188,11 @@ void ScalarReplacementPass::ReplaceWholeStore( continue; } - opt::Instruction* type = GetStorageType(var); + Instruction* type = GetStorageType(var); uint32_t extractId = TakeNextId(); - std::unique_ptr<opt::Instruction> extract(new opt::Instruction( + std::unique_ptr<Instruction> extract(new Instruction( context(), SpvOpCompositeExtract, type->result_id(), extractId, - std::initializer_list<opt::Operand>{ + std::initializer_list<Operand>{ {SPV_OPERAND_TYPE_ID, {storeInput}}, {SPV_OPERAND_TYPE_LITERAL_INTEGER, {elementIndex++}}})); auto iter = where.InsertBefore(std::move(extract)); @@ -202,15 +200,15 @@ void ScalarReplacementPass::ReplaceWholeStore( context()->set_instr_block(&*iter, block); // Create the store. - std::unique_ptr<opt::Instruction> newStore( - new opt::Instruction(context(), SpvOpStore, 0, 0, - std::initializer_list<opt::Operand>{ - {SPV_OPERAND_TYPE_ID, {var->result_id()}}, - {SPV_OPERAND_TYPE_ID, {extractId}}})); + std::unique_ptr<Instruction> newStore( + new Instruction(context(), SpvOpStore, 0, 0, + std::initializer_list<Operand>{ + {SPV_OPERAND_TYPE_ID, {var->result_id()}}, + {SPV_OPERAND_TYPE_ID, {extractId}}})); // Copy memory access attributes which start at index 2. Index 0 is the // pointer and index 1 is the data. for (uint32_t i = 2; i < store->NumInOperands(); ++i) { - opt::Operand copy(store->GetInOperand(i)); + Operand copy(store->GetInOperand(i)); newStore->AddOperand(std::move(copy)); } iter = where.InsertBefore(std::move(newStore)); @@ -220,29 +218,28 @@ void ScalarReplacementPass::ReplaceWholeStore( } bool ScalarReplacementPass::ReplaceAccessChain( - opt::Instruction* chain, - const std::vector<opt::Instruction*>& replacements) { + Instruction* chain, const std::vector<Instruction*>& replacements) { // Replaces the access chain with either another access chain (with one fewer // indexes) or a direct use of the replacement variable. uint32_t indexId = chain->GetSingleWordInOperand(1u); - const opt::Instruction* index = get_def_use_mgr()->GetDef(indexId); + const Instruction* index = get_def_use_mgr()->GetDef(indexId); size_t indexValue = GetConstantInteger(index); if (indexValue > replacements.size()) { // Out of bounds access, this is illegal IR. return false; } else { - const opt::Instruction* var = replacements[indexValue]; + const Instruction* var = replacements[indexValue]; if (chain->NumInOperands() > 2) { // Replace input access chain with another access chain. - opt::BasicBlock::iterator chainIter(chain); + BasicBlock::iterator chainIter(chain); uint32_t replacementId = TakeNextId(); - std::unique_ptr<opt::Instruction> replacementChain(new opt::Instruction( + std::unique_ptr<Instruction> replacementChain(new Instruction( context(), chain->opcode(), chain->type_id(), replacementId, - std::initializer_list<opt::Operand>{ + std::initializer_list<Operand>{ {SPV_OPERAND_TYPE_ID, {var->result_id()}}})); // Add the remaining indexes. for (uint32_t i = 2; i < chain->NumInOperands(); ++i) { - opt::Operand copy(chain->GetInOperand(i)); + Operand copy(chain->GetInOperand(i)); replacementChain->AddOperand(std::move(copy)); } auto iter = chainIter.InsertBefore(std::move(replacementChain)); @@ -259,8 +256,8 @@ bool ScalarReplacementPass::ReplaceAccessChain( } void ScalarReplacementPass::CreateReplacementVariables( - opt::Instruction* inst, std::vector<opt::Instruction*>* replacements) { - opt::Instruction* type = GetStorageType(inst); + Instruction* inst, std::vector<Instruction*>* replacements) { + Instruction* type = GetStorageType(inst); std::unique_ptr<std::unordered_set<uint64_t>> components_used = GetUsedComponents(inst); @@ -306,8 +303,7 @@ void ScalarReplacementPass::CreateReplacementVariables( } void ScalarReplacementPass::TransferAnnotations( - const opt::Instruction* source, - std::vector<opt::Instruction*>* replacements) { + const Instruction* source, std::vector<Instruction*>* replacements) { // Only transfer invariant and restrict decorations on the variable. There are // no type or member decorations that are necessary to transfer. for (auto inst : @@ -317,13 +313,13 @@ void ScalarReplacementPass::TransferAnnotations( if (decoration == SpvDecorationInvariant || decoration == SpvDecorationRestrict) { for (auto var : *replacements) { - std::unique_ptr<opt::Instruction> annotation(new opt::Instruction( - context(), SpvOpDecorate, 0, 0, - std::initializer_list<opt::Operand>{ - {SPV_OPERAND_TYPE_ID, {var->result_id()}}, - {SPV_OPERAND_TYPE_DECORATION, {decoration}}})); + std::unique_ptr<Instruction> annotation( + new Instruction(context(), SpvOpDecorate, 0, 0, + std::initializer_list<Operand>{ + {SPV_OPERAND_TYPE_ID, {var->result_id()}}, + {SPV_OPERAND_TYPE_DECORATION, {decoration}}})); for (uint32_t i = 2; i < inst->NumInOperands(); ++i) { - opt::Operand copy(inst->GetInOperand(i)); + Operand copy(inst->GetInOperand(i)); annotation->AddOperand(std::move(copy)); } context()->AddAnnotationInst(std::move(annotation)); @@ -334,18 +330,18 @@ void ScalarReplacementPass::TransferAnnotations( } void ScalarReplacementPass::CreateVariable( - uint32_t typeId, opt::Instruction* varInst, uint32_t index, - std::vector<opt::Instruction*>* replacements) { + uint32_t typeId, Instruction* varInst, uint32_t index, + std::vector<Instruction*>* replacements) { uint32_t ptrId = GetOrCreatePointerType(typeId); uint32_t id = TakeNextId(); - std::unique_ptr<opt::Instruction> variable(new opt::Instruction( + std::unique_ptr<Instruction> variable(new Instruction( context(), SpvOpVariable, ptrId, id, - std::initializer_list<opt::Operand>{ + std::initializer_list<Operand>{ {SPV_OPERAND_TYPE_STORAGE_CLASS, {SpvStorageClassFunction}}})); - opt::BasicBlock* block = context()->get_instr_block(varInst); + BasicBlock* block = context()->get_instr_block(varInst); block->begin().InsertBefore(std::move(variable)); - opt::Instruction* inst = &*block->begin(); + Instruction* inst = &*block->begin(); // If varInst was initialized, make sure to initialize its replacement. GetOrCreateInitialValue(varInst, index, inst); @@ -392,12 +388,12 @@ uint32_t ScalarReplacementPass::GetOrCreatePointerType(uint32_t id) { } ptrId = TakeNextId(); - context()->AddType(MakeUnique<opt::Instruction>( + context()->AddType(MakeUnique<Instruction>( context(), SpvOpTypePointer, 0, ptrId, - std::initializer_list<opt::Operand>{ + std::initializer_list<Operand>{ {SPV_OPERAND_TYPE_STORAGE_CLASS, {SpvStorageClassFunction}}, {SPV_OPERAND_TYPE_ID, {id}}})); - opt::Instruction* ptr = &*--context()->types_values_end(); + Instruction* ptr = &*--context()->types_values_end(); get_def_use_mgr()->AnalyzeInstDefUse(ptr); pointee_to_pointer_[id] = ptrId; // Register with the type manager if necessary. @@ -406,15 +402,15 @@ uint32_t ScalarReplacementPass::GetOrCreatePointerType(uint32_t id) { return ptrId; } -void ScalarReplacementPass::GetOrCreateInitialValue(opt::Instruction* source, +void ScalarReplacementPass::GetOrCreateInitialValue(Instruction* source, uint32_t index, - opt::Instruction* newVar) { + Instruction* newVar) { assert(source->opcode() == SpvOpVariable); if (source->NumInOperands() < 2) return; uint32_t initId = source->GetSingleWordInOperand(1u); uint32_t storageId = GetStorageType(newVar)->result_id(); - opt::Instruction* init = get_def_use_mgr()->GetDef(initId); + Instruction* init = get_def_use_mgr()->GetDef(initId); uint32_t newInitId = 0; // TODO(dnovillo): Refactor this with constant propagation. if (init->opcode() == SpvOpConstantNull) { @@ -423,29 +419,29 @@ void ScalarReplacementPass::GetOrCreateInitialValue(opt::Instruction* source, if (iter == type_to_null_.end()) { newInitId = TakeNextId(); type_to_null_[storageId] = newInitId; - context()->AddGlobalValue(MakeUnique<opt::Instruction>( - context(), SpvOpConstantNull, storageId, newInitId, - std::initializer_list<opt::Operand>{})); - opt::Instruction* newNull = &*--context()->types_values_end(); + context()->AddGlobalValue( + MakeUnique<Instruction>(context(), SpvOpConstantNull, storageId, + newInitId, std::initializer_list<Operand>{})); + Instruction* newNull = &*--context()->types_values_end(); get_def_use_mgr()->AnalyzeInstDefUse(newNull); } else { newInitId = iter->second; } - } else if (opt::IsSpecConstantInst(init->opcode())) { + } else if (IsSpecConstantInst(init->opcode())) { // Create a new constant extract. newInitId = TakeNextId(); - context()->AddGlobalValue(MakeUnique<opt::Instruction>( + context()->AddGlobalValue(MakeUnique<Instruction>( context(), SpvOpSpecConstantOp, storageId, newInitId, - std::initializer_list<opt::Operand>{ + std::initializer_list<Operand>{ {SPV_OPERAND_TYPE_SPEC_CONSTANT_OP_NUMBER, {SpvOpCompositeExtract}}, {SPV_OPERAND_TYPE_ID, {init->result_id()}}, {SPV_OPERAND_TYPE_LITERAL_INTEGER, {index}}})); - opt::Instruction* newSpecConst = &*--context()->types_values_end(); + Instruction* newSpecConst = &*--context()->types_values_end(); get_def_use_mgr()->AnalyzeInstDefUse(newSpecConst); } else if (init->opcode() == SpvOpConstantComposite) { // Get the appropriate index constant. newInitId = init->GetSingleWordInOperand(index); - opt::Instruction* element = get_def_use_mgr()->GetDef(newInitId); + Instruction* element = get_def_use_mgr()->GetDef(newInitId); if (element->opcode() == SpvOpUndef) { // Undef is not a valid initializer for a variable. newInitId = 0; @@ -459,7 +455,7 @@ void ScalarReplacementPass::GetOrCreateInitialValue(opt::Instruction* source, } } -size_t ScalarReplacementPass::GetIntegerLiteral(const opt::Operand& op) const { +size_t ScalarReplacementPass::GetIntegerLiteral(const Operand& op) const { assert(op.words.size() <= 2); size_t len = 0; for (uint32_t i = 0; i != op.words.size(); ++i) { @@ -469,7 +465,7 @@ size_t ScalarReplacementPass::GetIntegerLiteral(const opt::Operand& op) const { } size_t ScalarReplacementPass::GetConstantInteger( - const opt::Instruction* constant) const { + const Instruction* constant) const { assert(get_def_use_mgr()->GetDef(constant->type_id())->opcode() == SpvOpTypeInt); assert(constant->opcode() == SpvOpConstant || @@ -478,23 +474,22 @@ size_t ScalarReplacementPass::GetConstantInteger( return 0; } - const opt::Operand& op = constant->GetInOperand(0u); + const Operand& op = constant->GetInOperand(0u); return GetIntegerLiteral(op); } size_t ScalarReplacementPass::GetArrayLength( - const opt::Instruction* arrayType) const { + const Instruction* arrayType) const { assert(arrayType->opcode() == SpvOpTypeArray); - const opt::Instruction* length = + const Instruction* length = get_def_use_mgr()->GetDef(arrayType->GetSingleWordInOperand(1u)); return GetConstantInteger(length); } -size_t ScalarReplacementPass::GetNumElements( - const opt::Instruction* type) const { +size_t ScalarReplacementPass::GetNumElements(const Instruction* type) const { assert(type->opcode() == SpvOpTypeVector || type->opcode() == SpvOpTypeMatrix); - const opt::Operand& op = type->GetInOperand(1u); + const Operand& op = type->GetInOperand(1u); assert(op.words.size() <= 2); size_t len = 0; for (uint32_t i = 0; i != op.words.size(); ++i) { @@ -503,8 +498,8 @@ size_t ScalarReplacementPass::GetNumElements( return len; } -opt::Instruction* ScalarReplacementPass::GetStorageType( - const opt::Instruction* inst) const { +Instruction* ScalarReplacementPass::GetStorageType( + const Instruction* inst) const { assert(inst->opcode() == SpvOpVariable); uint32_t ptrTypeId = inst->type_id(); @@ -514,7 +509,7 @@ opt::Instruction* ScalarReplacementPass::GetStorageType( } bool ScalarReplacementPass::CanReplaceVariable( - const opt::Instruction* varInst) const { + const Instruction* varInst) const { assert(varInst->opcode() == SpvOpVariable); // Can only replace function scope variables. @@ -524,11 +519,11 @@ bool ScalarReplacementPass::CanReplaceVariable( if (!CheckTypeAnnotations(get_def_use_mgr()->GetDef(varInst->type_id()))) return false; - const opt::Instruction* typeInst = GetStorageType(varInst); + const Instruction* typeInst = GetStorageType(varInst); return CheckType(typeInst) && CheckAnnotations(varInst) && CheckUses(varInst); } -bool ScalarReplacementPass::CheckType(const opt::Instruction* typeInst) const { +bool ScalarReplacementPass::CheckType(const Instruction* typeInst) const { if (!CheckTypeAnnotations(typeInst)) return false; switch (typeInst->opcode()) { @@ -557,7 +552,7 @@ bool ScalarReplacementPass::CheckType(const opt::Instruction* typeInst) const { } bool ScalarReplacementPass::CheckTypeAnnotations( - const opt::Instruction* typeInst) const { + const Instruction* typeInst) const { for (auto inst : get_decoration_mgr()->GetDecorationsFor(typeInst->result_id(), false)) { uint32_t decoration; @@ -589,8 +584,7 @@ bool ScalarReplacementPass::CheckTypeAnnotations( return true; } -bool ScalarReplacementPass::CheckAnnotations( - const opt::Instruction* varInst) const { +bool ScalarReplacementPass::CheckAnnotations(const Instruction* varInst) const { for (auto inst : get_decoration_mgr()->GetDecorationsFor(varInst->result_id(), false)) { assert(inst->opcode() == SpvOpDecorate); @@ -610,7 +604,7 @@ bool ScalarReplacementPass::CheckAnnotations( return true; } -bool ScalarReplacementPass::CheckUses(const opt::Instruction* inst) const { +bool ScalarReplacementPass::CheckUses(const Instruction* inst) const { VariableStats stats = {0, 0}; bool ok = CheckUses(inst, &stats); @@ -621,20 +615,20 @@ bool ScalarReplacementPass::CheckUses(const opt::Instruction* inst) const { return ok; } -bool ScalarReplacementPass::CheckUses(const opt::Instruction* inst, +bool ScalarReplacementPass::CheckUses(const Instruction* inst, VariableStats* stats) const { bool ok = true; get_def_use_mgr()->ForEachUse( - inst, [this, stats, &ok](const opt::Instruction* user, uint32_t index) { + inst, [this, stats, &ok](const Instruction* user, uint32_t index) { // Annotations are check as a group separately. - if (!opt::IsAnnotationInst(user->opcode())) { + if (!IsAnnotationInst(user->opcode())) { switch (user->opcode()) { case SpvOpAccessChain: case SpvOpInBoundsAccessChain: if (index == 2u) { uint32_t id = user->GetSingleWordOperand(3u); - const opt::Instruction* opInst = get_def_use_mgr()->GetDef(id); - if (!opt::IsCompileTimeConstantInst(opInst->opcode())) { + const Instruction* opInst = get_def_use_mgr()->GetDef(id); + if (!IsCompileTimeConstantInst(opInst->opcode())) { ok = false; } else { if (!CheckUsesRelaxed(user)) ok = false; @@ -665,11 +659,10 @@ bool ScalarReplacementPass::CheckUses(const opt::Instruction* inst, return ok; } -bool ScalarReplacementPass::CheckUsesRelaxed( - const opt::Instruction* inst) const { +bool ScalarReplacementPass::CheckUsesRelaxed(const Instruction* inst) const { bool ok = true; get_def_use_mgr()->ForEachUse( - inst, [this, &ok](const opt::Instruction* user, uint32_t index) { + inst, [this, &ok](const Instruction* user, uint32_t index) { switch (user->opcode()) { case SpvOpAccessChain: case SpvOpInBoundsAccessChain: @@ -694,7 +687,7 @@ bool ScalarReplacementPass::CheckUsesRelaxed( return ok; } -bool ScalarReplacementPass::CheckLoad(const opt::Instruction* inst, +bool ScalarReplacementPass::CheckLoad(const Instruction* inst, uint32_t index) const { if (index != 2u) return false; if (inst->NumInOperands() >= 2 && @@ -703,7 +696,7 @@ bool ScalarReplacementPass::CheckLoad(const opt::Instruction* inst, return true; } -bool ScalarReplacementPass::CheckStore(const opt::Instruction* inst, +bool ScalarReplacementPass::CheckStore(const Instruction* inst, uint32_t index) const { if (index != 0u) return false; if (inst->NumInOperands() >= 3 && @@ -719,19 +712,19 @@ bool ScalarReplacementPass::IsLargerThanSizeLimit(size_t length) const { } std::unique_ptr<std::unordered_set<uint64_t>> -ScalarReplacementPass::GetUsedComponents(opt::Instruction* inst) { +ScalarReplacementPass::GetUsedComponents(Instruction* inst) { std::unique_ptr<std::unordered_set<uint64_t>> result( new std::unordered_set<uint64_t>()); analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr(); def_use_mgr->WhileEachUser(inst, [&result, def_use_mgr, - this](opt::Instruction* use) { + this](Instruction* use) { switch (use->opcode()) { case SpvOpLoad: { // Look for extract from the load. std::vector<uint32_t> t; - if (def_use_mgr->WhileEachUser(use, [&t](opt::Instruction* use2) { + if (def_use_mgr->WhileEachUser(use, [&t](Instruction* use2) { if (use2->opcode() != SpvOpCompositeExtract) { return false; } @@ -795,13 +788,13 @@ ScalarReplacementPass::GetUsedComponents(opt::Instruction* inst) { return result; } -opt::Instruction* ScalarReplacementPass::CreateNullConstant(uint32_t type_id) { +Instruction* ScalarReplacementPass::CreateNullConstant(uint32_t type_id) { analysis::TypeManager* type_mgr = context()->get_type_mgr(); analysis::ConstantManager* const_mgr = context()->get_constant_mgr(); const analysis::Type* type = type_mgr->GetType(type_id); const analysis::Constant* null_const = const_mgr->GetConstant(type, {}); - opt::Instruction* null_inst = + Instruction* null_inst = const_mgr->GetDefiningInstruction(null_const, type_id); context()->UpdateDefUse(null_inst); return null_inst; diff --git a/source/opt/scalar_replacement_pass.h b/source/opt/scalar_replacement_pass.h index 52a588cf..df08b859 100644 --- a/source/opt/scalar_replacement_pass.h +++ b/source/opt/scalar_replacement_pass.h @@ -45,12 +45,11 @@ class ScalarReplacementPass : public Pass { // SuccessWithChange if any change is made. Status Process() override; - opt::IRContext::Analysis GetPreservedAnalyses() override { - return opt::IRContext::kAnalysisDefUse | - opt::IRContext::kAnalysisInstrToBlockMapping | - opt::IRContext::kAnalysisDecorations | - opt::IRContext::kAnalysisCombinators | opt::IRContext::kAnalysisCFG | - opt::IRContext::kAnalysisNameMap; + IRContext::Analysis GetPreservedAnalyses() override { + return IRContext::kAnalysisDefUse | + IRContext::kAnalysisInstrToBlockMapping | + IRContext::kAnalysisDecorations | IRContext::kAnalysisCombinators | + IRContext::kAnalysisCFG | IRContext::kAnalysisNameMap; } private: @@ -64,27 +63,27 @@ class ScalarReplacementPass : public Pass { // Attempts to scalarize all appropriate function scope variables in // |function|. Returns SuccessWithChange if any changes are mode. - Status ProcessFunction(opt::Function* function); + Status ProcessFunction(Function* function); // Returns true if |varInst| can be scalarized. // // Examines the use chain of |varInst| to verify all uses are valid for // scalarization. - bool CanReplaceVariable(const opt::Instruction* varInst) const; + bool CanReplaceVariable(const Instruction* varInst) const; // Returns true if |typeInst| is an acceptable type to scalarize. // // Allows all aggregate types except runtime arrays. Additionally, checks the // that the number of elements that would be scalarized is within bounds. - bool CheckType(const opt::Instruction* typeInst) const; + bool CheckType(const Instruction* typeInst) const; // Returns true if all the decorations for |varInst| are acceptable for // scalarization. - bool CheckAnnotations(const opt::Instruction* varInst) const; + bool CheckAnnotations(const Instruction* varInst) const; // Returns true if all the decorations for |typeInst| are acceptable for // scalarization. - bool CheckTypeAnnotations(const opt::Instruction* typeInst) const; + bool CheckTypeAnnotations(const Instruction* typeInst) const; // Returns true if the uses of |inst| are acceptable for scalarization. // @@ -93,20 +92,20 @@ class ScalarReplacementPass : public Pass { // SpvOpStore. Access chains must have the first index be a compile-time // constant. Subsequent uses of access chains (including other access chains) // are checked in a more relaxed manner. - bool CheckUses(const opt::Instruction* inst) const; + bool CheckUses(const Instruction* inst) const; // Helper function for the above |CheckUses|. // // This version tracks some stats about the current OpVariable. These stats // are used to drive heuristics about when to scalarize. - bool CheckUses(const opt::Instruction* inst, VariableStats* stats) const; + bool CheckUses(const Instruction* inst, VariableStats* stats) const; // Relaxed helper function for |CheckUses|. - bool CheckUsesRelaxed(const opt::Instruction* inst) const; + bool CheckUsesRelaxed(const Instruction* inst) const; // Transfers appropriate decorations from |source| to |replacements|. - void TransferAnnotations(const opt::Instruction* source, - std::vector<opt::Instruction*>* replacements); + void TransferAnnotations(const Instruction* source, + std::vector<Instruction*>* replacements); // Scalarizes |inst| and updates its uses. // @@ -116,32 +115,30 @@ class ScalarReplacementPass : public Pass { // get added to |worklist| for further processing. If any replacement // variable ends up with no uses it is erased. Returns false if any // subsequent access chain is out of bounds. - bool ReplaceVariable(opt::Instruction* inst, - std::queue<opt::Instruction*>* worklist); + bool ReplaceVariable(Instruction* inst, std::queue<Instruction*>* worklist); // Returns the underlying storage type for |inst|. // // |inst| must be an OpVariable. Returns the type that is pointed to by // |inst|. - opt::Instruction* GetStorageType(const opt::Instruction* inst) const; + Instruction* GetStorageType(const Instruction* inst) const; // Returns true if the load can be scalarized. // // |inst| must be an OpLoad. Returns true if |index| is the pointer operand of // |inst| and the load is not from volatile memory. - bool CheckLoad(const opt::Instruction* inst, uint32_t index) const; + bool CheckLoad(const Instruction* inst, uint32_t index) const; // Returns true if the store can be scalarized. // // |inst| must be an OpStore. Returns true if |index| is the pointer operand // of |inst| and the store is not to volatile memory. - bool CheckStore(const opt::Instruction* inst, uint32_t index) const; + bool CheckStore(const Instruction* inst, uint32_t index) const; // Creates a variable of type |typeId| from the |index|'th element of // |varInst|. The new variable is added to |replacements|. - void CreateVariable(uint32_t typeId, opt::Instruction* varInst, - uint32_t index, - std::vector<opt::Instruction*>* replacements); + void CreateVariable(uint32_t typeId, Instruction* varInst, uint32_t index, + std::vector<Instruction*>* replacements); // Populates |replacements| with a new OpVariable for each element of |inst|. // @@ -150,24 +147,24 @@ class ScalarReplacementPass : public Pass { // will contain a variable for each element of the composite with matching // indexes (i.e. the 0'th element of |inst| is the 0'th entry of // |replacements|). - void CreateReplacementVariables(opt::Instruction* inst, - std::vector<opt::Instruction*>* replacements); + void CreateReplacementVariables(Instruction* inst, + std::vector<Instruction*>* replacements); // Returns the value of an OpConstant of integer type. // // |constant| must use two or fewer words to generate the value. - size_t GetConstantInteger(const opt::Instruction* constant) const; + size_t GetConstantInteger(const Instruction* constant) const; // Returns the integer literal for |op|. - size_t GetIntegerLiteral(const opt::Operand& op) const; + size_t GetIntegerLiteral(const Operand& op) const; // Returns the array length for |arrayInst|. - size_t GetArrayLength(const opt::Instruction* arrayInst) const; + size_t GetArrayLength(const Instruction* arrayInst) const; // Returns the number of elements in |type|. // // |type| must be a vector or matrix type. - size_t GetNumElements(const opt::Instruction* type) const; + size_t GetNumElements(const Instruction* type) const; // Returns an id for a pointer to |id|. uint32_t GetOrCreatePointerType(uint32_t id); @@ -177,8 +174,8 @@ class ScalarReplacementPass : public Pass { // If there is an initial value for |source| for element |index|, it is // appended as an operand on |newVar|. If the initial value is OpUndef, no // initial value is added to |newVar|. - void GetOrCreateInitialValue(opt::Instruction* source, uint32_t index, - opt::Instruction* newVar); + void GetOrCreateInitialValue(Instruction* source, uint32_t index, + Instruction* newVar); // Replaces the load to the entire composite. // @@ -186,32 +183,32 @@ class ScalarReplacementPass : public Pass { // composite by combining all of the loads. // // |load| must be a load. - void ReplaceWholeLoad(opt::Instruction* load, - const std::vector<opt::Instruction*>& replacements); + void ReplaceWholeLoad(Instruction* load, + const std::vector<Instruction*>& replacements); // Replaces the store to the entire composite. // // Generates a composite extract and store for each element in the scalarized // variable from the original store data input. - void ReplaceWholeStore(opt::Instruction* store, - const std::vector<opt::Instruction*>& replacements); + void ReplaceWholeStore(Instruction* store, + const std::vector<Instruction*>& replacements); // Replaces an access chain to the composite variable with either a direct use // of the appropriate replacement variable or another access chain with the // replacement variable as the base and one fewer indexes. Returns false if // the chain has an out of bounds access. - bool ReplaceAccessChain(opt::Instruction* chain, - const std::vector<opt::Instruction*>& replacements); + bool ReplaceAccessChain(Instruction* chain, + const std::vector<Instruction*>& replacements); // Returns a set containing the which components of the result of |inst| are // potentially used. If the return value is |nullptr|, then every components // is possibly used. std::unique_ptr<std::unordered_set<uint64_t>> GetUsedComponents( - opt::Instruction* inst); + Instruction* inst); // Returns an instruction defining a null constant with type |type_id|. If // one already exists, it is returned. Otherwise a new one is created. - opt::Instruction* CreateNullConstant(uint32_t type_id); + Instruction* CreateNullConstant(uint32_t type_id); // Maps storage type to a pointer type enclosing that type. std::unordered_map<uint32_t, uint32_t> pointee_to_pointer_; diff --git a/source/opt/set_spec_constant_default_value_pass.cpp b/source/opt/set_spec_constant_default_value_pass.cpp index 35f69706..fe97582b 100644 --- a/source/opt/set_spec_constant_default_value_pass.cpp +++ b/source/opt/set_spec_constant_default_value_pass.cpp @@ -112,7 +112,7 @@ std::vector<uint32_t> ParseDefaultValueBitPattern( // Returns true if the given instruction's result id could have a SpecId // decoration. -bool CanHaveSpecIdDecoration(const opt::Instruction& inst) { +bool CanHaveSpecIdDecoration(const Instruction& inst) { switch (inst.opcode()) { case SpvOp::SpvOpSpecConstant: case SpvOp::SpvOpSpecConstantFalse: @@ -127,8 +127,8 @@ bool CanHaveSpecIdDecoration(const opt::Instruction& inst) { // decoration, finds the spec constant defining instruction which is the real // target of the SpecId decoration. Returns the spec constant defining // instruction if such an instruction is found, otherwise returns a nullptr. -opt::Instruction* GetSpecIdTargetFromDecorationGroup( - const opt::Instruction& decoration_group_defining_inst, +Instruction* GetSpecIdTargetFromDecorationGroup( + const Instruction& decoration_group_defining_inst, analysis::DefUseManager* def_use_mgr) { // Find the OpGroupDecorate instruction which consumes the given decoration // group. Note that the given decoration group has SpecId decoration, which @@ -136,16 +136,16 @@ opt::Instruction* GetSpecIdTargetFromDecorationGroup( // consumed by different OpGroupDecorate instructions. Therefore we only need // the first OpGroupDecoration instruction that uses the given decoration // group. - opt::Instruction* group_decorate_inst = nullptr; - if (def_use_mgr->WhileEachUser( - &decoration_group_defining_inst, - [&group_decorate_inst](opt::Instruction* user) { - if (user->opcode() == SpvOp::SpvOpGroupDecorate) { - group_decorate_inst = user; - return false; - } - return true; - })) + Instruction* group_decorate_inst = nullptr; + if (def_use_mgr->WhileEachUser(&decoration_group_defining_inst, + [&group_decorate_inst](Instruction* user) { + if (user->opcode() == + SpvOp::SpvOpGroupDecorate) { + group_decorate_inst = user; + return false; + } + return true; + })) return nullptr; // Scan through the target ids of the OpGroupDecorate instruction. There @@ -155,12 +155,12 @@ opt::Instruction* GetSpecIdTargetFromDecorationGroup( // instruction. If the OpGroupDecorate instruction has different target ids // or a target id is not defined by an eligible spec cosntant instruction, // returns a nullptr. - opt::Instruction* target_inst = nullptr; + Instruction* target_inst = nullptr; for (uint32_t i = 1; i < group_decorate_inst->NumInOperands(); i++) { // All the operands of a OpGroupDecorate instruction should be of type // SPV_OPERAND_TYPE_ID. uint32_t candidate_id = group_decorate_inst->GetSingleWordInOperand(i); - opt::Instruction* candidate_inst = def_use_mgr->GetDef(candidate_id); + Instruction* candidate_inst = def_use_mgr->GetDef(candidate_id); if (!candidate_inst) { continue; @@ -213,7 +213,7 @@ Pass::Status SetSpecConstantDefaultValuePass::Process() { // is found for a spec id, the string will be parsed according to the target // spec constant type. The parsed value will be used to replace the original // default value of the target spec constant. - for (opt::Instruction& inst : context()->annotations()) { + for (Instruction& inst : context()->annotations()) { // Only process 'OpDecorate SpecId' instructions if (inst.opcode() != SpvOp::SpvOpDecorate) continue; if (inst.NumOperands() != kOpDecorateSpecIdNumOperands) continue; @@ -228,8 +228,8 @@ Pass::Status SetSpecConstantDefaultValuePass::Process() { // Find the spec constant defining instruction. Note that the // target_id might be a decoration group id. - opt::Instruction* spec_inst = nullptr; - if (opt::Instruction* target_inst = get_def_use_mgr()->GetDef(target_id)) { + Instruction* spec_inst = nullptr; + if (Instruction* target_inst = get_def_use_mgr()->GetDef(target_id)) { if (target_inst->opcode() == SpvOp::SpvOpDecorationGroup) { spec_inst = GetSpecIdTargetFromDecorationGroup(*target_inst, get_def_use_mgr()); diff --git a/source/opt/set_spec_constant_default_value_pass.h b/source/opt/set_spec_constant_default_value_pass.h index 0d45ce97..d048f42c 100644 --- a/source/opt/set_spec_constant_default_value_pass.h +++ b/source/opt/set_spec_constant_default_value_pass.h @@ -32,7 +32,7 @@ class SetSpecConstantDefaultValuePass : public Pass { using SpecIdToValueStrMap = std::unordered_map<uint32_t, std::string>; using SpecIdToValueBitPatternMap = std::unordered_map<uint32_t, std::vector<uint32_t>>; - using SpecIdToInstMap = std::unordered_map<uint32_t, opt::Instruction*>; + using SpecIdToInstMap = std::unordered_map<uint32_t, Instruction*>; // Constructs a pass instance with a map from spec ids to default values // in the form of string. diff --git a/source/opt/simplification_pass.cpp b/source/opt/simplification_pass.cpp index d1a74f9a..81ceb865 100644 --- a/source/opt/simplification_pass.cpp +++ b/source/opt/simplification_pass.cpp @@ -26,13 +26,13 @@ namespace opt { Pass::Status SimplificationPass::Process() { bool modified = false; - for (opt::Function& function : *get_module()) { + for (Function& function : *get_module()) { modified |= SimplifyFunction(&function); } return (modified ? Status::SuccessWithChange : Status::SuccessWithoutChange); } -bool SimplificationPass::SimplifyFunction(opt::Function* function) { +bool SimplificationPass::SimplifyFunction(Function* function) { bool modified = false; // Phase 1: Traverse all instructions in dominance order. // The second phase will only be on the instructions whose inputs have changed @@ -40,18 +40,17 @@ bool SimplificationPass::SimplifyFunction(opt::Function* function) { // only instructions whose inputs do not necessarily dominate the use, we keep // track of the OpPhi instructions already seen, and add them to the work list // for phase 2 when needed. - std::vector<opt::Instruction*> work_list; - std::unordered_set<opt::Instruction*> process_phis; - std::unordered_set<opt::Instruction*> inst_to_kill; - std::unordered_set<opt::Instruction*> in_work_list; - const opt::InstructionFolder& folder = context()->get_instruction_folder(); + std::vector<Instruction*> work_list; + std::unordered_set<Instruction*> process_phis; + std::unordered_set<Instruction*> inst_to_kill; + std::unordered_set<Instruction*> in_work_list; + const InstructionFolder& folder = context()->get_instruction_folder(); cfg()->ForEachBlockInReversePostOrder( function->entry().get(), [&modified, &process_phis, &work_list, &in_work_list, &inst_to_kill, - folder, this](opt::BasicBlock* bb) { - for (opt::Instruction* inst = &*bb->begin(); inst; - inst = inst->NextNode()) { + folder, this](BasicBlock* bb) { + for (Instruction* inst = &*bb->begin(); inst; inst = inst->NextNode()) { if (inst->opcode() == SpvOpPhi) { process_phis.insert(inst); } @@ -62,7 +61,7 @@ bool SimplificationPass::SimplifyFunction(opt::Function* function) { context()->AnalyzeUses(inst); get_def_use_mgr()->ForEachUser(inst, [&work_list, &process_phis, &in_work_list]( - opt::Instruction* use) { + Instruction* use) { if (process_phis.count(use) && in_work_list.insert(use).second) { work_list.push_back(use); } @@ -84,13 +83,13 @@ bool SimplificationPass::SimplifyFunction(opt::Function* function) { // done. This time we add all users to the work list because phase 1 // has already finished. for (size_t i = 0; i < work_list.size(); ++i) { - opt::Instruction* inst = work_list[i]; + Instruction* inst = work_list[i]; in_work_list.erase(inst); if (inst->opcode() == SpvOpCopyObject || folder.FoldInstruction(inst)) { modified = true; context()->AnalyzeUses(inst); get_def_use_mgr()->ForEachUser( - inst, [&work_list, &in_work_list](opt::Instruction* use) { + inst, [&work_list, &in_work_list](Instruction* use) { if (!use->IsDecoration() && use->opcode() != SpvOpName && in_work_list.insert(use).second) { work_list.push_back(use); @@ -110,7 +109,7 @@ bool SimplificationPass::SimplifyFunction(opt::Function* function) { } // Phase 3: Kill instructions we know are no longer needed. - for (opt::Instruction* inst : inst_to_kill) { + for (Instruction* inst : inst_to_kill) { context()->KillInst(inst); } diff --git a/source/opt/simplification_pass.h b/source/opt/simplification_pass.h index c69df841..f4c5e4f6 100644 --- a/source/opt/simplification_pass.h +++ b/source/opt/simplification_pass.h @@ -28,20 +28,19 @@ class SimplificationPass : public Pass { const char* name() const override { return "simplify-instructions"; } Status Process() override; - opt::IRContext::Analysis GetPreservedAnalyses() override { - return opt::IRContext::kAnalysisDefUse | - opt::IRContext::kAnalysisInstrToBlockMapping | - opt::IRContext::kAnalysisDecorations | - opt::IRContext::kAnalysisCombinators | opt::IRContext::kAnalysisCFG | - opt::IRContext::kAnalysisDominatorAnalysis | - opt::IRContext::kAnalysisNameMap; + IRContext::Analysis GetPreservedAnalyses() override { + return IRContext::kAnalysisDefUse | + IRContext::kAnalysisInstrToBlockMapping | + IRContext::kAnalysisDecorations | IRContext::kAnalysisCombinators | + IRContext::kAnalysisCFG | IRContext::kAnalysisDominatorAnalysis | + IRContext::kAnalysisNameMap; } private: // Returns true if the module was changed. The simplifier is called on every // instruction in |function| until nothing else in the function can be // simplified. - bool SimplifyFunction(opt::Function* function); + bool SimplifyFunction(Function* function); }; } // namespace opt diff --git a/source/opt/ssa_rewrite_pass.cpp b/source/opt/ssa_rewrite_pass.cpp index 6923d222..995b750c 100644 --- a/source/opt/ssa_rewrite_pass.cpp +++ b/source/opt/ssa_rewrite_pass.cpp @@ -66,7 +66,7 @@ const uint32_t kStoreValIdInIdx = 1; const uint32_t kVariableInitIdInIdx = 1; } // namespace -std::string SSARewriter::PhiCandidate::PrettyPrint(const opt::CFG* cfg) const { +std::string SSARewriter::PhiCandidate::PrettyPrint(const CFG* cfg) const { std::ostringstream str; str << "%" << result_id_ << " = Phi[%" << var_id_ << ", BB %" << bb_->id() << "]("; @@ -86,8 +86,8 @@ std::string SSARewriter::PhiCandidate::PrettyPrint(const opt::CFG* cfg) const { return str.str(); } -SSARewriter::PhiCandidate& SSARewriter::CreatePhiCandidate( - uint32_t var_id, opt::BasicBlock* bb) { +SSARewriter::PhiCandidate& SSARewriter::CreatePhiCandidate(uint32_t var_id, + BasicBlock* bb) { uint32_t phi_result_id = pass_->context()->TakeNextId(); auto result = phi_candidates_.emplace( phi_result_id, PhiCandidate(var_id, phi_result_id, bb)); @@ -161,7 +161,7 @@ uint32_t SSARewriter::AddPhiOperands(PhiCandidate* phi_candidate) { bool found_0_arg = false; for (uint32_t pred : pass_->cfg()->preds(phi_candidate->bb()->id())) { - opt::BasicBlock* pred_bb = pass_->cfg()->block(pred); + BasicBlock* pred_bb = pass_->cfg()->block(pred); // If |pred_bb| is not sealed, use %0 to indicate that // |phi_candidate| needs to be completed after the whole CFG has @@ -233,7 +233,7 @@ uint32_t SSARewriter::AddPhiOperands(PhiCandidate* phi_candidate) { return repl_id; } -uint32_t SSARewriter::GetReachingDef(uint32_t var_id, opt::BasicBlock* bb) { +uint32_t SSARewriter::GetReachingDef(uint32_t var_id, BasicBlock* bb) { // If |var_id| has a definition in |bb|, return it. const auto& bb_it = defs_at_block_.find(bb); if (bb_it != defs_at_block_.end()) { @@ -271,14 +271,14 @@ uint32_t SSARewriter::GetReachingDef(uint32_t var_id, opt::BasicBlock* bb) { return val_id; } -void SSARewriter::SealBlock(opt::BasicBlock* bb) { +void SSARewriter::SealBlock(BasicBlock* bb) { auto result = sealed_blocks_.insert(bb); (void)result; assert(result.second == true && "Tried to seal the same basic block more than once."); } -void SSARewriter::ProcessStore(opt::Instruction* inst, opt::BasicBlock* bb) { +void SSARewriter::ProcessStore(Instruction* inst, BasicBlock* bb) { auto opcode = inst->opcode(); assert((opcode == SpvOpStore || opcode == SpvOpVariable) && "Expecting a store or a variable definition instruction."); @@ -303,7 +303,7 @@ void SSARewriter::ProcessStore(opt::Instruction* inst, opt::BasicBlock* bb) { } } -void SSARewriter::ProcessLoad(opt::Instruction* inst, opt::BasicBlock* bb) { +void SSARewriter::ProcessLoad(Instruction* inst, BasicBlock* bb) { uint32_t var_id = 0; (void)pass_->GetPtr(inst, &var_id); if (pass_->IsTargetVar(var_id)) { @@ -346,7 +346,7 @@ void SSARewriter::PrintReplacementTable() const { std::cerr << "\n"; } -void SSARewriter::GenerateSSAReplacements(opt::BasicBlock* bb) { +void SSARewriter::GenerateSSAReplacements(BasicBlock* bb) { #if SSA_REWRITE_DEBUGGING_LEVEL > 1 std::cerr << "Generating SSA replacements for block: " << bb->id() << "\n"; std::cerr << bb->PrettyPrint(SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES) @@ -416,7 +416,7 @@ bool SSARewriter::ApplyReplacements() { #endif // Add Phi instructions from completed Phi candidates. - std::vector<opt::Instruction*> generated_phis; + std::vector<Instruction*> generated_phis; for (const PhiCandidate* phi_candidate : phis_to_generate_) { #if SSA_REWRITE_DEBUGGING_LEVEL > 2 std::cerr << "Phi candidate: " << phi_candidate->PrettyPrint(pass_->cfg()) @@ -430,7 +430,7 @@ bool SSARewriter::ApplyReplacements() { // Build the vector of operands for the new OpPhi instruction. uint32_t type_id = pass_->GetPointeeTypeId( pass_->get_def_use_mgr()->GetDef(phi_candidate->var_id())); - std::vector<opt::Operand> phi_operands; + std::vector<Operand> phi_operands; uint32_t arg_ix = 0; for (uint32_t pred_label : pass_->cfg()->preds(phi_candidate->bb()->id())) { uint32_t op_val_id = GetPhiArgument(phi_candidate, arg_ix++); @@ -442,9 +442,9 @@ bool SSARewriter::ApplyReplacements() { // Generate a new OpPhi instruction and insert it in its basic // block. - std::unique_ptr<opt::Instruction> phi_inst( - new opt::Instruction(pass_->context(), SpvOpPhi, type_id, - phi_candidate->result_id(), phi_operands)); + std::unique_ptr<Instruction> phi_inst( + new Instruction(pass_->context(), SpvOpPhi, type_id, + phi_candidate->result_id(), phi_operands)); generated_phis.push_back(phi_inst.get()); pass_->get_def_use_mgr()->AnalyzeInstDef(&*phi_inst); pass_->context()->set_instr_block(&*phi_inst, phi_candidate->bb()); @@ -456,7 +456,7 @@ bool SSARewriter::ApplyReplacements() { // Scan uses for all inserted Phi instructions. Do this separately from the // registration of the Phi instruction itself to avoid trying to analyze uses // of Phi instructions that have not been registered yet. - for (opt::Instruction* phi_inst : generated_phis) { + for (Instruction* phi_inst : generated_phis) { pass_->get_def_use_mgr()->AnalyzeInstUse(&*phi_inst); } @@ -469,7 +469,7 @@ bool SSARewriter::ApplyReplacements() { for (auto& repl : load_replacement_) { uint32_t load_id = repl.first; uint32_t val_id = GetReplacement(repl); - opt::Instruction* load_inst = + Instruction* load_inst = pass_->context()->get_def_use_mgr()->GetDef(load_id); #if SSA_REWRITE_DEBUGGING_LEVEL > 2 @@ -498,7 +498,7 @@ void SSARewriter::FinalizePhiCandidate(PhiCandidate* phi_candidate) { uint32_t ix = 0; for (uint32_t pred : pass_->cfg()->preds(phi_candidate->bb()->id())) { - opt::BasicBlock* pred_bb = pass_->cfg()->block(pred); + BasicBlock* pred_bb = pass_->cfg()->block(pred); uint32_t& arg_id = phi_candidate->phi_args()[ix++]; if (arg_id == 0) { // If |pred_bb| is still not sealed, it means it's unreachable. In this @@ -536,7 +536,7 @@ void SSARewriter::FinalizePhiCandidates() { } } -bool SSARewriter::RewriteFunctionIntoSSA(opt::Function* fp) { +bool SSARewriter::RewriteFunctionIntoSSA(Function* fp) { #if SSA_REWRITE_DEBUGGING_LEVEL > 0 std::cerr << "Function before SSA rewrite:\n" << fp->PrettyPrint(0) << "\n\n\n"; @@ -549,7 +549,7 @@ bool SSARewriter::RewriteFunctionIntoSSA(opt::Function* fp) { // generate incomplete and trivial Phis. pass_->cfg()->ForEachBlockInReversePostOrder( fp->entry().get(), - [this](opt::BasicBlock* bb) { GenerateSSAReplacements(bb); }); + [this](BasicBlock* bb) { GenerateSSAReplacements(bb); }); // Remove trivial Phis and add arguments to incomplete Phis. FinalizePhiCandidates(); diff --git a/source/opt/ssa_rewrite_pass.h b/source/opt/ssa_rewrite_pass.h index cd720d6c..d1a99cba 100644 --- a/source/opt/ssa_rewrite_pass.h +++ b/source/opt/ssa_rewrite_pass.h @@ -43,12 +43,12 @@ class SSARewriter { // // It returns true if function |fp| was modified. Otherwise, it returns // false. - bool RewriteFunctionIntoSSA(opt::Function* fp); + bool RewriteFunctionIntoSSA(Function* fp); private: class PhiCandidate { public: - explicit PhiCandidate(uint32_t var, uint32_t result, opt::BasicBlock* block) + explicit PhiCandidate(uint32_t var, uint32_t result, BasicBlock* block) : var_id_(var), result_id_(result), bb_(block), @@ -59,7 +59,7 @@ class SSARewriter { uint32_t var_id() const { return var_id_; } uint32_t result_id() const { return result_id_; } - opt::BasicBlock* bb() const { return bb_; } + BasicBlock* bb() const { return bb_; } std::vector<uint32_t>& phi_args() { return phi_args_; } const std::vector<uint32_t>& phi_args() const { return phi_args_; } uint32_t copy_of() const { return copy_of_; } @@ -81,7 +81,7 @@ class SSARewriter { // Pretty prints this Phi candidate into a string and returns it. |cfg| is // needed to lookup basic block predecessors. - std::string PrettyPrint(const opt::CFG* cfg) const; + std::string PrettyPrint(const CFG* cfg) const; // Registers |operand_id| as a user of this Phi candidate. void AddUser(uint32_t operand_id) { users_.push_back(operand_id); } @@ -95,7 +95,7 @@ class SSARewriter { uint32_t result_id_; // Basic block to hold this Phi. - opt::BasicBlock* bb_; + BasicBlock* bb_; // Vector of operands for every predecessor block of |bb|. This vector is // organized so that the Ith slot contains the argument coming from the Ith @@ -117,23 +117,21 @@ class SSARewriter { }; // Type used to keep track of store operations in each basic block. - typedef std::unordered_map<opt::BasicBlock*, + typedef std::unordered_map<BasicBlock*, std::unordered_map<uint32_t, uint32_t>> BlockDefsMap; // Generates all the SSA rewriting decisions for basic block |bb|. This // populates the Phi candidate table (|phi_candidate_|) and the load // replacement table (|load_replacement_). - void GenerateSSAReplacements(opt::BasicBlock* bb); + void GenerateSSAReplacements(BasicBlock* bb); // Seals block |bb|. Sealing a basic block means |bb| and all its // predecessors of |bb| have been scanned for loads/stores. - void SealBlock(opt::BasicBlock* bb); + void SealBlock(BasicBlock* bb); // Returns true if |bb| has been sealed. - bool IsBlockSealed(opt::BasicBlock* bb) { - return sealed_blocks_.count(bb) != 0; - } + bool IsBlockSealed(BasicBlock* bb) { return sealed_blocks_.count(bb) != 0; } // Returns the Phi candidate with result ID |id| if it exists in the table // |phi_candidates_|. If no such Phi candidate exists, it returns nullptr. @@ -183,7 +181,7 @@ class SSARewriter { // Registers a definition for variable |var_id| in basic block |bb| with // value |val_id|. - void WriteVariable(uint32_t var_id, opt::BasicBlock* bb, uint32_t val_id) { + void WriteVariable(uint32_t var_id, BasicBlock* bb, uint32_t val_id) { defs_at_block_[bb][var_id] = val_id; } @@ -191,13 +189,13 @@ class SSARewriter { // the variable ID being stored into, determines whether the variable is an // SSA-target variable, and, if it is, it stores its value in the // |defs_at_block_| map. - void ProcessStore(opt::Instruction* inst, opt::BasicBlock* bb); + void ProcessStore(Instruction* inst, BasicBlock* bb); // Processes the load operation |inst| in basic block |bb|. This extracts // the variable ID being stored into, determines whether the variable is an // SSA-target variable, and, if it is, it reads its reaching definition by // calling |GetReachingDef|. - void ProcessLoad(opt::Instruction* inst, opt::BasicBlock* bb); + void ProcessLoad(Instruction* inst, BasicBlock* bb); // Reads the current definition for variable |var_id| in basic block |bb|. // If |var_id| is not defined in block |bb| it walks up the predecessors of @@ -205,7 +203,7 @@ class SSARewriter { // // It returns the value for |var_id| from the RHS of the current reaching // definition for |var_id|. - uint32_t GetReachingDef(uint32_t var_id, opt::BasicBlock* bb); + uint32_t GetReachingDef(uint32_t var_id, BasicBlock* bb); // Adds arguments to |phi_candidate| by getting the reaching definition of // |phi_candidate|'s variable on each of the predecessors of its basic @@ -223,7 +221,7 @@ class SSARewriter { // during rewriting. // // Once the candidate Phi is created, it returns its ID. - PhiCandidate& CreatePhiCandidate(uint32_t var_id, opt::BasicBlock* bb); + PhiCandidate& CreatePhiCandidate(uint32_t var_id, BasicBlock* bb); // Attempts to remove a trivial Phi candidate |phi_cand|. Trivial Phis are // those that only reference themselves and one other value |val| any number @@ -277,7 +275,7 @@ class SSARewriter { std::unordered_map<uint32_t, uint32_t> load_replacement_; // Set of blocks that have been sealed already. - std::unordered_set<opt::BasicBlock*> sealed_blocks_; + std::unordered_set<BasicBlock*> sealed_blocks_; // Memory pass requesting the SSA rewriter. MemPass* pass_; diff --git a/source/opt/strength_reduction_pass.cpp b/source/opt/strength_reduction_pass.cpp index 9df94f9a..fa4b3217 100644 --- a/source/opt/strength_reduction_pass.cpp +++ b/source/opt/strength_reduction_pass.cpp @@ -66,7 +66,7 @@ Pass::Status StrengthReductionPass::Process() { } bool StrengthReductionPass::ReplaceMultiplyByPowerOf2( - opt::BasicBlock::iterator* inst) { + BasicBlock::iterator* inst) { assert((*inst)->opcode() == SpvOp::SpvOpIMul && "Only works for multiplication of integers."); bool modified = false; @@ -80,7 +80,7 @@ bool StrengthReductionPass::ReplaceMultiplyByPowerOf2( // Check the operands for a constant that is a power of 2. for (int i = 0; i < 2; i++) { uint32_t opId = (*inst)->GetSingleWordInOperand(i); - opt::Instruction* opInst = get_def_use_mgr()->GetDef(opId); + Instruction* opInst = get_def_use_mgr()->GetDef(opId); if (opInst->opcode() == SpvOp::SpvOpConstant) { // We found a constant operand. uint32_t constVal = opInst->GetSingleWordOperand(2); @@ -92,14 +92,14 @@ bool StrengthReductionPass::ReplaceMultiplyByPowerOf2( // Create the new instruction. uint32_t newResultId = TakeNextId(); - std::vector<opt::Operand> newOperands; + std::vector<Operand> newOperands; newOperands.push_back((*inst)->GetInOperand(1 - i)); - opt::Operand shiftOperand(spv_operand_type_t::SPV_OPERAND_TYPE_ID, - {shiftConstResultId}); + Operand shiftOperand(spv_operand_type_t::SPV_OPERAND_TYPE_ID, + {shiftConstResultId}); newOperands.push_back(shiftOperand); - std::unique_ptr<opt::Instruction> newInstruction( - new opt::Instruction(context(), SpvOp::SpvOpShiftLeftLogical, - (*inst)->type_id(), newResultId, newOperands)); + std::unique_ptr<Instruction> newInstruction( + new Instruction(context(), SpvOp::SpvOpShiftLeftLogical, + (*inst)->type_id(), newResultId, newOperands)); // Insert the new instruction and update the data structures. (*inst) = (*inst).InsertBefore(std::move(newInstruction)); @@ -108,7 +108,7 @@ bool StrengthReductionPass::ReplaceMultiplyByPowerOf2( context()->ReplaceAllUsesWith((*inst)->result_id(), newResultId); // Remove the old instruction. - opt::Instruction* inst_to_delete = &*(*inst); + Instruction* inst_to_delete = &*(*inst); --(*inst); context()->KillInst(inst_to_delete); @@ -154,11 +154,11 @@ uint32_t StrengthReductionPass::GetConstantId(uint32_t val) { // Construct the constant. uint32_t resultId = TakeNextId(); - opt::Operand constant(spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER, - {val}); - std::unique_ptr<opt::Instruction> newConstant( - new opt::Instruction(context(), SpvOp::SpvOpConstant, uint32_type_id_, - resultId, {constant})); + Operand constant(spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER, + {val}); + std::unique_ptr<Instruction> newConstant( + new Instruction(context(), SpvOp::SpvOpConstant, uint32_type_id_, + resultId, {constant})); get_module()->AddGlobalValue(std::move(newConstant)); // Notify the DefUseManager about this constant. diff --git a/source/opt/strength_reduction_pass.h b/source/opt/strength_reduction_pass.h index d57f515d..59987da1 100644 --- a/source/opt/strength_reduction_pass.h +++ b/source/opt/strength_reduction_pass.h @@ -32,7 +32,7 @@ class StrengthReductionPass : public Pass { private: // Replaces multiple by power of 2 with an equivalent bit shift. // Returns true if something changed. - bool ReplaceMultiplyByPowerOf2(opt::BasicBlock::iterator*); + bool ReplaceMultiplyByPowerOf2(BasicBlock::iterator*); // Scan the types and constants in the module looking for the the integer // types that we are diff --git a/source/opt/strip_debug_info_pass.cpp b/source/opt/strip_debug_info_pass.cpp index 9e0c6aae..c98a2274 100644 --- a/source/opt/strip_debug_info_pass.cpp +++ b/source/opt/strip_debug_info_pass.cpp @@ -24,7 +24,7 @@ Pass::Status StripDebugInfoPass::Process() { !context()->debugs3().empty(); context()->debug_clear(); - context()->module()->ForEachInst([&modified](opt::Instruction* inst) { + context()->module()->ForEachInst([&modified](Instruction* inst) { modified |= !inst->dbg_line_insts().empty(); inst->dbg_line_insts().clear(); }); diff --git a/source/opt/strip_reflect_info_pass.cpp b/source/opt/strip_reflect_info_pass.cpp index 8f723eb6..fab2e3d8 100644 --- a/source/opt/strip_reflect_info_pass.cpp +++ b/source/opt/strip_reflect_info_pass.cpp @@ -22,8 +22,6 @@ namespace spvtools { namespace opt { -using opt::Instruction; - Pass::Status StripReflectInfoPass::Process() { bool modified = false; diff --git a/source/opt/strip_reflect_info_pass.h b/source/opt/strip_reflect_info_pass.h index 761dfb1c..f4697d50 100644 --- a/source/opt/strip_reflect_info_pass.h +++ b/source/opt/strip_reflect_info_pass.h @@ -29,12 +29,11 @@ class StripReflectInfoPass : public Pass { Status Process() override; // Return the mask of preserved Analyses. - opt::IRContext::Analysis GetPreservedAnalyses() override { - return opt::IRContext::kAnalysisInstrToBlockMapping | - opt::IRContext::kAnalysisCombinators | opt::IRContext::kAnalysisCFG | - opt::IRContext::kAnalysisDominatorAnalysis | - opt::IRContext::kAnalysisLoopAnalysis | - opt::IRContext::kAnalysisNameMap; + IRContext::Analysis GetPreservedAnalyses() override { + return IRContext::kAnalysisInstrToBlockMapping | + IRContext::kAnalysisCombinators | IRContext::kAnalysisCFG | + IRContext::kAnalysisDominatorAnalysis | + IRContext::kAnalysisLoopAnalysis | IRContext::kAnalysisNameMap; } }; diff --git a/source/opt/type_manager.cpp b/source/opt/type_manager.cpp index fa60f462..7f615a28 100644 --- a/source/opt/type_manager.cpp +++ b/source/opt/type_manager.cpp @@ -23,16 +23,17 @@ #include "make_unique.h" #include "reflect.h" +namespace spvtools { +namespace opt { +namespace analysis { namespace { + const int kSpvTypePointerStorageClass = 1; const int kSpvTypePointerTypeIdInIdx = 2; -} // namespace -namespace spvtools { -namespace opt { -namespace analysis { +} // namespace -TypeManager::TypeManager(const MessageConsumer& consumer, opt::IRContext* c) +TypeManager::TypeManager(const MessageConsumer& consumer, IRContext* c) : consumer_(consumer), context_(c) { AnalyzeTypes(*c->module()); } @@ -49,9 +50,9 @@ std::pair<Type*, std::unique_ptr<Pointer>> TypeManager::GetTypeAndPointerType( uint32_t id, SpvStorageClass sc) const { Type* type = GetType(id); if (type) { - return std::make_pair(type, MakeUnique<analysis::Pointer>(type, sc)); + return std::make_pair(type, MakeUnique<Pointer>(type, sc)); } else { - return std::make_pair(type, std::unique_ptr<analysis::Pointer>()); + return std::make_pair(type, std::unique_ptr<Pointer>()); } } @@ -61,7 +62,7 @@ uint32_t TypeManager::GetId(const Type* type) const { return 0; } -void TypeManager::AnalyzeTypes(const opt::Module& module) { +void TypeManager::AnalyzeTypes(const Module& module) { // First pass through the types. Any types that reference a forward pointer // (directly or indirectly) are incomplete, and are added to incomplete types. for (const auto* inst : module.GetTypes()) { @@ -130,7 +131,7 @@ void TypeManager::AnalyzeTypes(const opt::Module& module) { // Add the remaining incomplete types to the type pool. for (auto& type : incomplete_types_) { if (type.type() && !type.type()->AsForwardPointer()) { - std::vector<opt::Instruction*> decorations = + std::vector<Instruction*> decorations = context()->get_decoration_mgr()->GetDecorationsFor(type.id(), true); for (auto dec : decorations) { AttachDecoration(*dec, type.type()); @@ -200,15 +201,14 @@ uint32_t TypeManager::GetTypeInstruction(const Type* type) { uint32_t id = GetId(type); if (id != 0) return id; - std::unique_ptr<opt::Instruction> typeInst; + std::unique_ptr<Instruction> typeInst; id = context()->TakeNextId(); RegisterType(id, *type); switch (type->kind()) { -#define DefineParameterlessCase(kind) \ - case Type::k##kind: \ - typeInst.reset( \ - new opt::Instruction(context(), SpvOpType##kind, 0, id, \ - std::initializer_list<opt::Operand>{})); \ +#define DefineParameterlessCase(kind) \ + case Type::k##kind: \ + typeInst.reset(new Instruction(context(), SpvOpType##kind, 0, id, \ + std::initializer_list<Operand>{})); \ break; DefineParameterlessCase(Void); DefineParameterlessCase(Bool); @@ -221,45 +221,45 @@ uint32_t TypeManager::GetTypeInstruction(const Type* type) { DefineParameterlessCase(NamedBarrier); #undef DefineParameterlessCase case Type::kInteger: - typeInst.reset(new opt::Instruction( + typeInst.reset(new Instruction( context(), SpvOpTypeInt, 0, id, - std::initializer_list<opt::Operand>{ + std::initializer_list<Operand>{ {SPV_OPERAND_TYPE_LITERAL_INTEGER, {type->AsInteger()->width()}}, {SPV_OPERAND_TYPE_LITERAL_INTEGER, {(type->AsInteger()->IsSigned() ? 1u : 0u)}}})); break; case Type::kFloat: - typeInst.reset(new opt::Instruction( + typeInst.reset(new Instruction( context(), SpvOpTypeFloat, 0, id, - std::initializer_list<opt::Operand>{ + std::initializer_list<Operand>{ {SPV_OPERAND_TYPE_LITERAL_INTEGER, {type->AsFloat()->width()}}})); break; case Type::kVector: { uint32_t subtype = GetTypeInstruction(type->AsVector()->element_type()); typeInst.reset( - new opt::Instruction(context(), SpvOpTypeVector, 0, id, - std::initializer_list<opt::Operand>{ - {SPV_OPERAND_TYPE_ID, {subtype}}, - {SPV_OPERAND_TYPE_LITERAL_INTEGER, - {type->AsVector()->element_count()}}})); + new Instruction(context(), SpvOpTypeVector, 0, id, + std::initializer_list<Operand>{ + {SPV_OPERAND_TYPE_ID, {subtype}}, + {SPV_OPERAND_TYPE_LITERAL_INTEGER, + {type->AsVector()->element_count()}}})); break; } case Type::kMatrix: { uint32_t subtype = GetTypeInstruction(type->AsMatrix()->element_type()); typeInst.reset( - new opt::Instruction(context(), SpvOpTypeMatrix, 0, id, - std::initializer_list<opt::Operand>{ - {SPV_OPERAND_TYPE_ID, {subtype}}, - {SPV_OPERAND_TYPE_LITERAL_INTEGER, - {type->AsMatrix()->element_count()}}})); + new Instruction(context(), SpvOpTypeMatrix, 0, id, + std::initializer_list<Operand>{ + {SPV_OPERAND_TYPE_ID, {subtype}}, + {SPV_OPERAND_TYPE_LITERAL_INTEGER, + {type->AsMatrix()->element_count()}}})); break; } case Type::kImage: { const Image* image = type->AsImage(); uint32_t subtype = GetTypeInstruction(image->sampled_type()); - typeInst.reset(new opt::Instruction( + typeInst.reset(new Instruction( context(), SpvOpTypeImage, 0, id, - std::initializer_list<opt::Operand>{ + std::initializer_list<Operand>{ {SPV_OPERAND_TYPE_ID, {subtype}}, {SPV_OPERAND_TYPE_DIMENSIONALITY, {static_cast<uint32_t>(image->dim())}}, @@ -278,17 +278,16 @@ uint32_t TypeManager::GetTypeInstruction(const Type* type) { case Type::kSampledImage: { uint32_t subtype = GetTypeInstruction(type->AsSampledImage()->image_type()); - typeInst.reset( - new opt::Instruction(context(), SpvOpTypeSampledImage, 0, id, - std::initializer_list<opt::Operand>{ - {SPV_OPERAND_TYPE_ID, {subtype}}})); + typeInst.reset(new Instruction( + context(), SpvOpTypeSampledImage, 0, id, + std::initializer_list<Operand>{{SPV_OPERAND_TYPE_ID, {subtype}}})); break; } case Type::kArray: { uint32_t subtype = GetTypeInstruction(type->AsArray()->element_type()); - typeInst.reset(new opt::Instruction( + typeInst.reset(new Instruction( context(), SpvOpTypeArray, 0, id, - std::initializer_list<opt::Operand>{ + std::initializer_list<Operand>{ {SPV_OPERAND_TYPE_ID, {subtype}}, {SPV_OPERAND_TYPE_ID, {type->AsArray()->LengthId()}}})); break; @@ -296,21 +295,18 @@ uint32_t TypeManager::GetTypeInstruction(const Type* type) { case Type::kRuntimeArray: { uint32_t subtype = GetTypeInstruction(type->AsRuntimeArray()->element_type()); - typeInst.reset( - new opt::Instruction(context(), SpvOpTypeRuntimeArray, 0, id, - std::initializer_list<opt::Operand>{ - {SPV_OPERAND_TYPE_ID, {subtype}}})); + typeInst.reset(new Instruction( + context(), SpvOpTypeRuntimeArray, 0, id, + std::initializer_list<Operand>{{SPV_OPERAND_TYPE_ID, {subtype}}})); break; } case Type::kStruct: { - std::vector<opt::Operand> ops; + std::vector<Operand> ops; const Struct* structTy = type->AsStruct(); for (auto ty : structTy->element_types()) { - ops.push_back( - opt::Operand(SPV_OPERAND_TYPE_ID, {GetTypeInstruction(ty)})); + ops.push_back(Operand(SPV_OPERAND_TYPE_ID, {GetTypeInstruction(ty)})); } - typeInst.reset( - new opt::Instruction(context(), SpvOpTypeStruct, 0, id, ops)); + typeInst.reset(new Instruction(context(), SpvOpTypeStruct, 0, id, ops)); break; } case Type::kOpaque: { @@ -321,46 +317,44 @@ uint32_t TypeManager::GetTypeInstruction(const Type* type) { char* dst = reinterpret_cast<char*>(words.data()); strncpy(dst, opaque->name().c_str(), size); typeInst.reset( - new opt::Instruction(context(), SpvOpTypeOpaque, 0, id, - std::initializer_list<opt::Operand>{ - {SPV_OPERAND_TYPE_LITERAL_STRING, words}})); + new Instruction(context(), SpvOpTypeOpaque, 0, id, + std::initializer_list<Operand>{ + {SPV_OPERAND_TYPE_LITERAL_STRING, words}})); break; } case Type::kPointer: { const Pointer* pointer = type->AsPointer(); uint32_t subtype = GetTypeInstruction(pointer->pointee_type()); - typeInst.reset(new opt::Instruction( + typeInst.reset(new Instruction( context(), SpvOpTypePointer, 0, id, - std::initializer_list<opt::Operand>{ + std::initializer_list<Operand>{ {SPV_OPERAND_TYPE_STORAGE_CLASS, {static_cast<uint32_t>(pointer->storage_class())}}, {SPV_OPERAND_TYPE_ID, {subtype}}})); break; } case Type::kFunction: { - std::vector<opt::Operand> ops; + std::vector<Operand> ops; const Function* function = type->AsFunction(); - ops.push_back(opt::Operand( - SPV_OPERAND_TYPE_ID, {GetTypeInstruction(function->return_type())})); + ops.push_back(Operand(SPV_OPERAND_TYPE_ID, + {GetTypeInstruction(function->return_type())})); for (auto ty : function->param_types()) { - ops.push_back( - opt::Operand(SPV_OPERAND_TYPE_ID, {GetTypeInstruction(ty)})); + ops.push_back(Operand(SPV_OPERAND_TYPE_ID, {GetTypeInstruction(ty)})); } - typeInst.reset( - new opt::Instruction(context(), SpvOpTypeFunction, 0, id, ops)); + typeInst.reset(new Instruction(context(), SpvOpTypeFunction, 0, id, ops)); break; } case Type::kPipe: - typeInst.reset(new opt::Instruction( + typeInst.reset(new Instruction( context(), SpvOpTypePipe, 0, id, - std::initializer_list<opt::Operand>{ + std::initializer_list<Operand>{ {SPV_OPERAND_TYPE_ACCESS_QUALIFIER, {static_cast<uint32_t>(type->AsPipe()->access_qualifier())}}})); break; case Type::kForwardPointer: - typeInst.reset(new opt::Instruction( + typeInst.reset(new Instruction( context(), SpvOpTypeForwardPointer, 0, 0, - std::initializer_list<opt::Operand>{ + std::initializer_list<Operand>{ {SPV_OPERAND_TYPE_ID, {type->AsForwardPointer()->target_id()}}, {SPV_OPERAND_TYPE_STORAGE_CLASS, {static_cast<uint32_t>( @@ -378,18 +372,17 @@ uint32_t TypeManager::GetTypeInstruction(const Type* type) { uint32_t TypeManager::FindPointerToType(uint32_t type_id, SpvStorageClass storage_class) { - opt::analysis::Type* pointeeTy = GetType(type_id); - opt::analysis::Pointer pointerTy(pointeeTy, storage_class); + Type* pointeeTy = GetType(type_id); + Pointer pointerTy(pointeeTy, storage_class); if (pointeeTy->IsUniqueType(true)) { // Non-ambiguous type. Get the pointer type through the type manager. return GetTypeInstruction(&pointerTy); } // Ambiguous type, do a linear search. - opt::Module::inst_iterator type_itr = - context()->module()->types_values_begin(); + Module::inst_iterator type_itr = context()->module()->types_values_begin(); for (; type_itr != context()->module()->types_values_end(); ++type_itr) { - const opt::Instruction* type_inst = &*type_itr; + const Instruction* type_inst = &*type_itr; if (type_inst->opcode() == SpvOpTypePointer && type_inst->GetSingleWordOperand(kSpvTypePointerTypeIdInIdx) == type_id && @@ -400,11 +393,11 @@ uint32_t TypeManager::FindPointerToType(uint32_t type_id, // Must create the pointer type. uint32_t resultId = context()->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)); context()->get_type_mgr()->RegisterType(resultId, pointerTy); return resultId; @@ -427,20 +420,19 @@ void TypeManager::AttachDecorations(uint32_t id, const Type* type) { void TypeManager::CreateDecoration(uint32_t target, const std::vector<uint32_t>& decoration, uint32_t element) { - std::vector<opt::Operand> ops; - ops.push_back(opt::Operand(SPV_OPERAND_TYPE_ID, {target})); + std::vector<Operand> ops; + ops.push_back(Operand(SPV_OPERAND_TYPE_ID, {target})); if (element != 0) { - ops.push_back(opt::Operand(SPV_OPERAND_TYPE_LITERAL_INTEGER, {element})); + ops.push_back(Operand(SPV_OPERAND_TYPE_LITERAL_INTEGER, {element})); } - ops.push_back(opt::Operand(SPV_OPERAND_TYPE_DECORATION, {decoration[0]})); + ops.push_back(Operand(SPV_OPERAND_TYPE_DECORATION, {decoration[0]})); for (size_t i = 1; i < decoration.size(); ++i) { - ops.push_back( - opt::Operand(SPV_OPERAND_TYPE_LITERAL_INTEGER, {decoration[i]})); + ops.push_back(Operand(SPV_OPERAND_TYPE_LITERAL_INTEGER, {decoration[i]})); } - context()->AddAnnotationInst(MakeUnique<opt::Instruction>( + context()->AddAnnotationInst(MakeUnique<Instruction>( context(), (element == 0 ? SpvOpDecorate : SpvOpMemberDecorate), 0, 0, ops)); - opt::Instruction* inst = &*--context()->annotation_end(); + Instruction* inst = &*--context()->annotation_end(); context()->get_def_use_mgr()->AnalyzeInstUse(inst); } @@ -591,8 +583,8 @@ Type* TypeManager::GetRegisteredType(const Type* type) { return GetType(id); } -Type* TypeManager::RecordIfTypeDefinition(const opt::Instruction& inst) { - if (!opt::IsTypeInst(inst.opcode())) return nullptr; +Type* TypeManager::RecordIfTypeDefinition(const Instruction& inst) { + if (!IsTypeInst(inst.opcode())) return nullptr; Type* type = nullptr; switch (inst.opcode()) { @@ -752,7 +744,7 @@ Type* TypeManager::RecordIfTypeDefinition(const opt::Instruction& inst) { SPIRV_ASSERT(consumer_, id != 0, "instruction without result id found"); SPIRV_ASSERT(consumer_, type != nullptr, "type should not be nullptr at this point"); - std::vector<opt::Instruction*> decorations = + std::vector<Instruction*> decorations = context()->get_decoration_mgr()->GetDecorationsFor(id, true); for (auto dec : decorations) { AttachDecoration(*dec, type); @@ -764,9 +756,9 @@ Type* TypeManager::RecordIfTypeDefinition(const opt::Instruction& inst) { return type; } -void TypeManager::AttachDecoration(const opt::Instruction& inst, Type* type) { +void TypeManager::AttachDecoration(const Instruction& inst, Type* type) { const SpvOp opcode = inst.opcode(); - if (!opt::IsAnnotationInst(opcode)) return; + if (!IsAnnotationInst(opcode)) return; switch (opcode) { case SpvOpDecorate: { @@ -799,16 +791,16 @@ void TypeManager::AttachDecoration(const opt::Instruction& inst, Type* type) { const Type* TypeManager::GetMemberType( const Type* parent_type, const std::vector<uint32_t>& access_chain) { for (uint32_t element_index : access_chain) { - if (const analysis::Struct* struct_type = parent_type->AsStruct()) { + if (const Struct* struct_type = parent_type->AsStruct()) { parent_type = struct_type->element_types()[element_index]; - } else if (const analysis::Array* array_type = parent_type->AsArray()) { + } else if (const Array* array_type = parent_type->AsArray()) { parent_type = array_type->element_type(); - } else if (const analysis::RuntimeArray* runtime_array_type = + } else if (const RuntimeArray* runtime_array_type = parent_type->AsRuntimeArray()) { parent_type = runtime_array_type->element_type(); - } else if (const analysis::Vector* vector_type = parent_type->AsVector()) { + } else if (const Vector* vector_type = parent_type->AsVector()) { parent_type = vector_type->element_type(); - } else if (const analysis::Matrix* matrix_type = parent_type->AsMatrix()) { + } else if (const Matrix* matrix_type = parent_type->AsMatrix()) { parent_type = matrix_type->element_type(); } else { assert(false && "Trying to get a member of a type without members."); @@ -820,14 +812,14 @@ const Type* TypeManager::GetMemberType( void TypeManager::ReplaceForwardPointers(Type* type) { switch (type->kind()) { case Type::kArray: { - const analysis::ForwardPointer* element_type = + const ForwardPointer* element_type = type->AsArray()->element_type()->AsForwardPointer(); if (element_type) { type->AsArray()->ReplaceElementType(element_type->target_pointer()); } } break; case Type::kRuntimeArray: { - const analysis::ForwardPointer* element_type = + const ForwardPointer* element_type = type->AsRuntimeArray()->element_type()->AsForwardPointer(); if (element_type) { type->AsRuntimeArray()->ReplaceElementType( @@ -844,7 +836,7 @@ void TypeManager::ReplaceForwardPointers(Type* type) { } } break; case Type::kPointer: { - const analysis::ForwardPointer* pointee_type = + const ForwardPointer* pointee_type = type->AsPointer()->pointee_type()->AsForwardPointer(); if (pointee_type) { type->AsPointer()->SetPointeeType(pointee_type->target_pointer()); @@ -852,7 +844,7 @@ void TypeManager::ReplaceForwardPointers(Type* type) { } break; case Type::kFunction: { Function* func_type = type->AsFunction(); - const analysis::ForwardPointer* return_type = + const ForwardPointer* return_type = func_type->return_type()->AsForwardPointer(); if (return_type) { func_type->SetReturnType(return_type->target_pointer()); diff --git a/source/opt/type_manager.h b/source/opt/type_manager.h index 358ef939..7e124e9f 100644 --- a/source/opt/type_manager.h +++ b/source/opt/type_manager.h @@ -75,7 +75,7 @@ class TypeManager { // will be communicated to the outside via the given message |consumer|. // This instance only keeps a reference to the |consumer|, so the |consumer| // should outlive this instance. - TypeManager(const MessageConsumer& consumer, opt::IRContext* c); + TypeManager(const MessageConsumer& consumer, IRContext* c); TypeManager(const TypeManager&) = delete; TypeManager(TypeManager&&) = delete; @@ -161,9 +161,9 @@ class TypeManager { using IdToUnresolvedType = std::vector<UnresolvedType>; // Analyzes the types and decorations on types in the given |module|. - void AnalyzeTypes(const opt::Module& module); + void AnalyzeTypes(const Module& module); - opt::IRContext* context() { return context_; } + IRContext* context() { return context_; } // Attaches the decorations on |type| to |id|. void AttachDecorations(uint32_t id, const Type* type); @@ -178,11 +178,11 @@ class TypeManager { // Creates and returns a type from the given SPIR-V |inst|. Returns nullptr if // the given instruction is not for defining a type. - Type* RecordIfTypeDefinition(const opt::Instruction& inst); + Type* RecordIfTypeDefinition(const Instruction& inst); // Attaches the decoration encoded in |inst| to |type|. Does nothing if the // given instruction is not a decoration instruction. Assumes the target is // |type| (e.g. should be called in loop of |type|'s decorations). - void AttachDecoration(const opt::Instruction& inst, Type* type); + void AttachDecoration(const Instruction& inst, Type* type); // Returns an equivalent pointer to |type| built in terms of pointers owned by // |type_pool_|. For example, if |type| is a vec3 of bool, it will be rebuilt @@ -198,7 +198,7 @@ class TypeManager { void ReplaceType(Type* new_type, Type* original_type); const MessageConsumer& consumer_; // Message consumer. - opt::IRContext* context_; + IRContext* context_; IdToTypeMap id_to_type_; // Mapping from ids to their type representations. TypeToIdMap type_to_id_; // Mapping from types to their defining ids. TypePool type_pool_; // Memory owner of type pointers. diff --git a/source/opt/unify_const_pass.cpp b/source/opt/unify_const_pass.cpp index eaf7df5d..83bd6c0f 100644 --- a/source/opt/unify_const_pass.cpp +++ b/source/opt/unify_const_pass.cpp @@ -39,7 +39,7 @@ class ResultIdTrie { // is found, creates a trie node with those keys, stores the instruction's // result id and returns that result id. If an existing result id is found, // returns the existing result id. - uint32_t LookupEquivalentResultFor(const opt::Instruction& inst) { + uint32_t LookupEquivalentResultFor(const Instruction& inst) { auto keys = GetLookUpKeys(inst); auto* node = root_.get(); for (uint32_t key : keys) { @@ -85,7 +85,7 @@ class ResultIdTrie { // Returns a vector of the opcode followed by the words in the raw SPIR-V // instruction encoding but without the result id. - std::vector<uint32_t> GetLookUpKeys(const opt::Instruction& inst) { + std::vector<uint32_t> GetLookUpKeys(const Instruction& inst) { std::vector<uint32_t> keys; // Need to use the opcode, otherwise there might be a conflict with the // following case when <op>'s binary value equals xx's id: @@ -107,7 +107,7 @@ Pass::Status UnifyConstantPass::Process() { bool modified = false; ResultIdTrie defined_constants; - for (opt::Instruction *next_instruction, + for (Instruction *next_instruction, *inst = &*(context()->types_values_begin()); inst; inst = next_instruction) { next_instruction = inst->NextNode(); diff --git a/source/opt/value_number_table.cpp b/source/opt/value_number_table.cpp index c78f23ed..165540f5 100644 --- a/source/opt/value_number_table.cpp +++ b/source/opt/value_number_table.cpp @@ -22,7 +22,7 @@ namespace spvtools { namespace opt { -uint32_t ValueNumberTable::GetValueNumber(opt::Instruction* inst) const { +uint32_t ValueNumberTable::GetValueNumber(Instruction* inst) const { assert(inst->result_id() != 0 && "inst must have a result id to get a value number."); @@ -38,7 +38,7 @@ uint32_t ValueNumberTable::GetValueNumber(uint32_t id) const { return GetValueNumber(context()->get_def_use_mgr()->GetDef(id)); } -uint32_t ValueNumberTable::AssignValueNumber(opt::Instruction* inst) { +uint32_t ValueNumberTable::AssignValueNumber(Instruction* inst) { // If it already has a value return that. uint32_t value = GetValueNumber(inst); if (value != 0) { @@ -107,19 +107,19 @@ uint32_t ValueNumberTable::AssignValueNumber(opt::Instruction* inst) { // Replace all of the operands by their value number. The sign bit will be // set to distinguish between an id and a value number. - opt::Instruction value_ins(context(), inst->opcode(), inst->type_id(), - inst->result_id(), {}); + Instruction value_ins(context(), inst->opcode(), inst->type_id(), + inst->result_id(), {}); for (uint32_t o = 0; o < inst->NumInOperands(); ++o) { - const opt::Operand& op = inst->GetInOperand(o); + const Operand& op = inst->GetInOperand(o); if (spvIsIdType(op.type)) { uint32_t id_value = op.words[0]; auto use_id_to_val = id_to_value_.find(id_value); if (use_id_to_val != id_to_value_.end()) { id_value = (1 << 31) | use_id_to_val->second; } - value_ins.AddOperand(opt::Operand(op.type, {id_value})); + value_ins.AddOperand(Operand(op.type, {id_value})); } else { - value_ins.AddOperand(opt::Operand(op.type, op.words)); + value_ins.AddOperand(Operand(op.type, op.words)); } } @@ -167,11 +167,11 @@ void ValueNumberTable::BuildDominatorTreeValueNumberTable() { } } - for (opt::Function& func : *context()->module()) { + for (Function& func : *context()->module()) { // For best results we want to traverse the code in reverse post order. // This happens naturally because of the forward referencing rules. - for (opt::BasicBlock& block : func) { - for (opt::Instruction& inst : block) { + for (BasicBlock& block : func) { + for (Instruction& inst : block) { if (inst.result_id() != 0) { AssignValueNumber(&inst); } @@ -180,8 +180,8 @@ void ValueNumberTable::BuildDominatorTreeValueNumberTable() { } } -bool ComputeSameValue::operator()(const opt::Instruction& lhs, - const opt::Instruction& rhs) const { +bool ComputeSameValue::operator()(const Instruction& lhs, + const Instruction& rhs) const { if (lhs.result_id() == 0 || rhs.result_id() == 0) { return false; } @@ -208,7 +208,7 @@ bool ComputeSameValue::operator()(const opt::Instruction& lhs, lhs.result_id(), rhs.result_id()); } -std::size_t ValueTableHash::operator()(const opt::Instruction& inst) const { +std::size_t ValueTableHash::operator()(const Instruction& inst) const { // We hash the opcode and in-operands, not the result, because we want // instructions that are the same except for the result to hash to the // same value. diff --git a/source/opt/value_number_table.h b/source/opt/value_number_table.h index 73ce596b..ec25099e 100644 --- a/source/opt/value_number_table.h +++ b/source/opt/value_number_table.h @@ -28,14 +28,13 @@ class IRContext; // value number table to compare two instructions. class ComputeSameValue { public: - bool operator()(const opt::Instruction& lhs, - const opt::Instruction& rhs) const; + bool operator()(const Instruction& lhs, const Instruction& rhs) const; }; // The hash function used in the value number table. class ValueTableHash { public: - std::size_t operator()(const opt::Instruction& inst) const; + std::size_t operator()(const Instruction& inst) const; }; // This class implements the value number analysis. It is using a hash-based @@ -51,20 +50,20 @@ class ValueTableHash { // the scope. class ValueNumberTable { public: - ValueNumberTable(opt::IRContext* ctx) : context_(ctx), next_value_number_(1) { + ValueNumberTable(IRContext* ctx) : context_(ctx), next_value_number_(1) { BuildDominatorTreeValueNumberTable(); } // Returns the value number of the value computed by |inst|. |inst| must have // a result id that will hold the computed value. If no value number has been // assigned to the result id, then the return value is 0. - uint32_t GetValueNumber(opt::Instruction* inst) const; + uint32_t GetValueNumber(Instruction* inst) const; // Returns the value number of the value contain in |id|. Returns 0 if it // has not been assigned a value number. uint32_t GetValueNumber(uint32_t id) const; - opt::IRContext* context() const { return context_; } + IRContext* context() const { return context_; } private: // Assigns a value number to every result id in the module. @@ -76,13 +75,12 @@ class ValueNumberTable { // Assigns a new value number to the result of |inst| if it does not already // have one. Return the value number for |inst|. |inst| must have a result // id. - uint32_t AssignValueNumber(opt::Instruction* inst); + uint32_t AssignValueNumber(Instruction* inst); - std::unordered_map<opt::Instruction, uint32_t, ValueTableHash, - ComputeSameValue> + std::unordered_map<Instruction, uint32_t, ValueTableHash, ComputeSameValue> instruction_to_value_; std::unordered_map<uint32_t, uint32_t> id_to_value_; - opt::IRContext* context_; + IRContext* context_; uint32_t next_value_number_; }; diff --git a/source/opt/vector_dce.cpp b/source/opt/vector_dce.cpp index d93ed4ab..8738fccf 100644 --- a/source/opt/vector_dce.cpp +++ b/source/opt/vector_dce.cpp @@ -25,19 +25,19 @@ namespace opt { Pass::Status VectorDCE::Process() { bool modified = false; - for (opt::Function& function : *get_module()) { + for (Function& function : *get_module()) { modified |= VectorDCEFunction(&function); } return (modified ? Status::SuccessWithChange : Status::SuccessWithoutChange); } -bool VectorDCE::VectorDCEFunction(opt::Function* function) { +bool VectorDCE::VectorDCEFunction(Function* function) { LiveComponentMap live_components; FindLiveComponents(function, &live_components); return RewriteInstructions(function, live_components); } -void VectorDCE::FindLiveComponents(opt::Function* function, +void VectorDCE::FindLiveComponents(Function* function, LiveComponentMap* live_components) { std::vector<WorkListItem> work_list; @@ -48,7 +48,7 @@ void VectorDCE::FindLiveComponents(opt::Function* function, // the nesting. We cannot simply us a bit vector to keep track of which // components are live because of arbitrary nesting of structs. function->ForEachInst( - [&work_list, this, live_components](opt::Instruction* current_inst) { + [&work_list, this, live_components](Instruction* current_inst) { if (!HasVectorOrScalarResult(current_inst) || !context()->IsCombinatorInstruction(current_inst)) { MarkUsesAsLive(current_inst, all_components_live_, live_components, @@ -59,7 +59,7 @@ void VectorDCE::FindLiveComponents(opt::Function* function, // Process the work list propagating liveness. for (uint32_t i = 0; i < work_list.size(); i++) { WorkListItem current_item = work_list[i]; - opt::Instruction* current_inst = current_item.instruction; + Instruction* current_inst = current_item.instruction; switch (current_inst->opcode()) { case SpvOpCompositeExtract: @@ -88,13 +88,13 @@ void VectorDCE::FindLiveComponents(opt::Function* function, } } -void VectorDCE::MarkExtractUseAsLive(const opt::Instruction* current_inst, +void VectorDCE::MarkExtractUseAsLive(const Instruction* current_inst, LiveComponentMap* live_components, std::vector<WorkListItem>* work_list) { analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr(); uint32_t operand_id = current_inst->GetSingleWordInOperand(kExtractCompositeIdInIdx); - opt::Instruction* operand_inst = def_use_mgr->GetDef(operand_id); + Instruction* operand_inst = def_use_mgr->GetDef(operand_id); if (HasVectorOrScalarResult(operand_inst)) { WorkListItem new_item; @@ -116,7 +116,7 @@ void VectorDCE::MarkInsertUsesAsLive( // Add the elements of the composite object that are used. uint32_t operand_id = current_item.instruction->GetSingleWordInOperand(kInsertCompositeIdInIdx); - opt::Instruction* operand_inst = def_use_mgr->GetDef(operand_id); + Instruction* operand_inst = def_use_mgr->GetDef(operand_id); WorkListItem new_item; new_item.instruction = operand_inst; @@ -129,7 +129,7 @@ void VectorDCE::MarkInsertUsesAsLive( if (current_item.components.Get(insert_position)) { uint32_t obj_operand_id = current_item.instruction->GetSingleWordInOperand(kInsertObjectIdInIdx); - opt::Instruction* obj_operand_inst = def_use_mgr->GetDef(obj_operand_id); + Instruction* obj_operand_inst = def_use_mgr->GetDef(obj_operand_id); WorkListItem new_item_for_obj; new_item_for_obj.instruction = obj_operand_inst; new_item_for_obj.components.Set(0); @@ -179,11 +179,11 @@ void VectorDCE::MarkCompositeContructUsesAsLive( analysis::TypeManager* type_mgr = context()->get_type_mgr(); uint32_t current_component = 0; - opt::Instruction* current_inst = work_item.instruction; + Instruction* current_inst = work_item.instruction; uint32_t num_in_operands = current_inst->NumInOperands(); for (uint32_t i = 0; i < num_in_operands; ++i) { uint32_t id = current_inst->GetSingleWordInOperand(i); - opt::Instruction* op_inst = def_use_mgr->GetDef(id); + Instruction* op_inst = def_use_mgr->GetDef(id); if (HasScalarResult(op_inst)) { WorkListItem new_work_item; @@ -212,14 +212,14 @@ void VectorDCE::MarkCompositeContructUsesAsLive( } void VectorDCE::MarkUsesAsLive( - opt::Instruction* current_inst, const utils::BitVector& live_elements, + Instruction* current_inst, const utils::BitVector& live_elements, LiveComponentMap* live_components, std::vector<VectorDCE::WorkListItem>* work_list) { analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr(); current_inst->ForEachInId([&work_list, &live_elements, this, live_components, def_use_mgr](uint32_t* operand_id) { - opt::Instruction* operand_inst = def_use_mgr->GetDef(*operand_id); + Instruction* operand_inst = def_use_mgr->GetDef(*operand_id); if (HasVectorResult(operand_inst)) { WorkListItem new_item; @@ -235,11 +235,11 @@ void VectorDCE::MarkUsesAsLive( }); } -bool VectorDCE::HasVectorOrScalarResult(const opt::Instruction* inst) const { +bool VectorDCE::HasVectorOrScalarResult(const Instruction* inst) const { return HasScalarResult(inst) || HasVectorResult(inst); } -bool VectorDCE::HasVectorResult(const opt::Instruction* inst) const { +bool VectorDCE::HasVectorResult(const Instruction* inst) const { analysis::TypeManager* type_mgr = context()->get_type_mgr(); if (inst->type_id() == 0) { return false; @@ -254,7 +254,7 @@ bool VectorDCE::HasVectorResult(const opt::Instruction* inst) const { } } -bool VectorDCE::HasScalarResult(const opt::Instruction* inst) const { +bool VectorDCE::HasScalarResult(const Instruction* inst) const { analysis::TypeManager* type_mgr = context()->get_type_mgr(); if (inst->type_id() == 0) { return false; @@ -272,11 +272,10 @@ bool VectorDCE::HasScalarResult(const opt::Instruction* inst) const { } bool VectorDCE::RewriteInstructions( - opt::Function* function, - const VectorDCE::LiveComponentMap& live_components) { + Function* function, const VectorDCE::LiveComponentMap& live_components) { bool modified = false; function->ForEachInst( - [&modified, this, live_components](opt::Instruction* current_inst) { + [&modified, this, live_components](Instruction* current_inst) { if (!context()->IsCombinatorInstruction(current_inst)) { return; } @@ -319,7 +318,7 @@ bool VectorDCE::RewriteInstructions( } bool VectorDCE::RewriteInsertInstruction( - opt::Instruction* current_inst, const utils::BitVector& live_components) { + Instruction* current_inst, const utils::BitVector& live_components) { // If the value being inserted is not live, then we can skip the insert. bool modified = false; uint32_t insert_index = current_inst->GetSingleWordInOperand(2); @@ -348,7 +347,7 @@ bool VectorDCE::RewriteInsertInstruction( void VectorDCE::AddItemToWorkListIfNeeded( WorkListItem work_item, VectorDCE::LiveComponentMap* live_components, std::vector<WorkListItem>* work_list) { - opt::Instruction* current_inst = work_item.instruction; + Instruction* current_inst = work_item.instruction; auto it = live_components->find(current_inst->result_id()); if (it == live_components->end()) { live_components->emplace( diff --git a/source/opt/vector_dce.h b/source/opt/vector_dce.h index a8d1bca6..b7d8bd25 100644 --- a/source/opt/vector_dce.h +++ b/source/opt/vector_dce.h @@ -32,7 +32,7 @@ class VectorDCE : public MemPass { struct WorkListItem { WorkListItem() : instruction(nullptr), components(kMaxVectorSize) {} - opt::Instruction* instruction; + Instruction* instruction; utils::BitVector components; }; @@ -46,29 +46,27 @@ class VectorDCE : public MemPass { const char* name() const override { return "vector-dce"; } Status Process() override; - opt::IRContext::Analysis GetPreservedAnalyses() override { - return opt::IRContext::kAnalysisDefUse | opt::IRContext::kAnalysisCFG | - opt::IRContext::kAnalysisInstrToBlockMapping | - opt::IRContext::kAnalysisLoopAnalysis | - opt::IRContext::kAnalysisDecorations | - opt::IRContext::kAnalysisDominatorAnalysis | - opt::IRContext::kAnalysisNameMap; + IRContext::Analysis GetPreservedAnalyses() override { + return IRContext::kAnalysisDefUse | IRContext::kAnalysisCFG | + IRContext::kAnalysisInstrToBlockMapping | + IRContext::kAnalysisLoopAnalysis | IRContext::kAnalysisDecorations | + IRContext::kAnalysisDominatorAnalysis | IRContext::kAnalysisNameMap; } private: // Runs the vector dce pass on |function|. Returns true if |function| was // modified. - bool VectorDCEFunction(opt::Function* function); + bool VectorDCEFunction(Function* function); // Identifies the live components of the vectors that are results of // instructions in |function|. The results are stored in |live_components|. - void FindLiveComponents(opt::Function* function, + void FindLiveComponents(Function* function, LiveComponentMap* live_components); // Rewrites instructions in |function| that are dead or partially dead. If an // instruction does not have an entry in |live_components|, then it is not // changed. Returns true if |function| was modified. - bool RewriteInstructions(opt::Function* function, + bool RewriteInstructions(Function* function, const LiveComponentMap& live_components); // Rewrites the OpCompositeInsert instruction |current_inst| to avoid @@ -80,17 +78,17 @@ class VectorDCE : public MemPass { // // If the composite input to |current_inst| is not live, then it is replaced // by and OpUndef in |current_inst|. - bool RewriteInsertInstruction(opt::Instruction* current_inst, + bool RewriteInsertInstruction(Instruction* current_inst, const utils::BitVector& live_components); // Returns true if the result of |inst| is a vector or a scalar. - bool HasVectorOrScalarResult(const opt::Instruction* inst) const; + bool HasVectorOrScalarResult(const Instruction* inst) const; // Returns true if the result of |inst| is a scalar. - bool HasVectorResult(const opt::Instruction* inst) const; + bool HasVectorResult(const Instruction* inst) const; // Returns true if the result of |inst| is a vector. - bool HasScalarResult(const opt::Instruction* inst) const; + bool HasScalarResult(const Instruction* inst) const; // Adds |work_item| to |work_list| if it is not already live according to // |live_components|. |live_components| is updated to indicate that @@ -102,7 +100,7 @@ class VectorDCE : public MemPass { // Marks the components |live_elements| of the uses in |current_inst| as live // according to |live_components|. If they were not live before, then they are // added to |work_list|. - void MarkUsesAsLive(opt::Instruction* current_inst, + void MarkUsesAsLive(Instruction* current_inst, const utils::BitVector& live_elements, LiveComponentMap* live_components, std::vector<WorkListItem>* work_list); @@ -126,7 +124,7 @@ class VectorDCE : public MemPass { // Marks the uses in the OpCompositeExtract instruction |current_inst| as // live. If anything becomes live they are added to |work_list| and // |live_components| is updated accordingly. - void MarkExtractUseAsLive(const opt::Instruction* current_inst, + void MarkExtractUseAsLive(const Instruction* current_inst, LiveComponentMap* live_components, std::vector<WorkListItem>* work_list); diff --git a/source/opt/workaround1209.cpp b/source/opt/workaround1209.cpp index a83cd8e3..fae08b83 100644 --- a/source/opt/workaround1209.cpp +++ b/source/opt/workaround1209.cpp @@ -29,14 +29,14 @@ Pass::Status Workaround1209::Process() { bool Workaround1209::RemoveOpUnreachableInLoops() { bool modified = false; for (auto& func : *get_module()) { - std::list<opt::BasicBlock*> structured_order; + std::list<BasicBlock*> structured_order; cfg()->ComputeStructuredOrder(&func, &*func.begin(), &structured_order); // Keep track of the loop merges. The top of the stack will always be the // loop merge for the loop that immediately contains the basic block being // processed. std::stack<uint32_t> loop_merges; - for (opt::BasicBlock* bb : structured_order) { + for (BasicBlock* bb : structured_order) { if (!loop_merges.empty() && bb->id() == loop_merges.top()) { loop_merges.pop(); } @@ -46,10 +46,10 @@ bool Workaround1209::RemoveOpUnreachableInLoops() { // We found an OpUnreachable inside a loop. // Replace it with an unconditional branch to the loop merge. context()->KillInst(&*bb->tail()); - std::unique_ptr<opt::Instruction> new_branch( - new opt::Instruction(context(), SpvOpBranch, 0, 0, - {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, - {loop_merges.top()}}})); + std::unique_ptr<Instruction> new_branch( + new Instruction(context(), SpvOpBranch, 0, 0, + {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, + {loop_merges.top()}}})); context()->AnalyzeDefUse(&*new_branch); bb->AddInstruction(std::move(new_branch)); modified = true; |