Opt: LocalBlockElim: Add HasOnlySupportedRefs

Verifies that targeted variables have only access chain and direct
loads and stores as references.
This commit is contained in:
greg-lunarg 2017-07-22 08:32:19 -06:00 committed by Lei Zhang
parent adb237f3bd
commit 2d0f7fbc11
4 changed files with 34 additions and 3 deletions

View File

@ -231,7 +231,6 @@ bool AggressiveDCEPass::AggressiveDCE(ir::Function* func) {
}
void AggressiveDCEPass::Initialize(ir::Module* module) {
module_ = module;
// Initialize id-to-function map

View File

@ -218,6 +218,24 @@ void LocalSingleBlockLoadStoreElimPass::DCEInst(ir::Instruction* inst) {
}
}
bool LocalSingleBlockLoadStoreElimPass::HasOnlySupportedRefs(uint32_t ptrId) {
if (supported_ref_ptrs_.find(ptrId) != supported_ref_ptrs_.end())
return true;
analysis::UseList* uses = def_use_mgr_->GetUses(ptrId);
assert(uses != nullptr);
for (auto u : *uses) {
SpvOp op = u.inst->opcode();
if (IsNonPtrAccessChain(op)) {
if (!HasOnlySupportedRefs(u.inst->result_id()))
return false;
}
else if (op != SpvOpStore && op != SpvOpLoad && op != SpvOpName)
return false;
}
supported_ref_ptrs_.insert(ptrId);
return true;
}
bool LocalSingleBlockLoadStoreElimPass::LocalSingleBlockLoadStoreElim(
ir::Function* func) {
// Perform local store/load and load/load elimination on each block
@ -234,6 +252,8 @@ bool LocalSingleBlockLoadStoreElimPass::LocalSingleBlockLoadStoreElim(
ir::Instruction* ptrInst = GetPtr(&*ii, &varId);
if (!IsTargetVar(varId))
continue;
if (!HasOnlySupportedRefs(varId))
continue;
// Register the store
if (ptrInst->opcode() == SpvOpVariable) {
// if not pinned, look for WAW
@ -258,6 +278,8 @@ bool LocalSingleBlockLoadStoreElimPass::LocalSingleBlockLoadStoreElim(
ir::Instruction* ptrInst = GetPtr(&*ii, &varId);
if (!IsTargetVar(varId))
continue;
if (!HasOnlySupportedRefs(varId))
continue;
// Look for previous store or load
uint32_t replId = 0;
if (ptrInst->opcode() == SpvOpVariable) {
@ -320,6 +342,9 @@ void LocalSingleBlockLoadStoreElimPass::Initialize(ir::Module* module) {
seen_target_vars_.clear();
seen_non_target_vars_.clear();
// Clear collections
supported_ref_ptrs_.clear();
// TODO(): Reuse def/use from previous passes
def_use_mgr_.reset(new analysis::DefUseManager(consumer(), module_));

View File

@ -85,6 +85,10 @@ class LocalSingleBlockLoadStoreElimPass : public Pass {
// labels.
void DCEInst(ir::Instruction* inst);
// Return true if all uses of |varId| are only through supported reference
// operations ie. loads and store. Also cache in supported_ref_ptrs_;
bool HasOnlySupportedRefs(uint32_t varId);
// On all entry point functions, within each basic block, eliminate
// loads and stores to function variables where possible. For
// loads, if previous load or store to same variable, replace
@ -142,6 +146,10 @@ class LocalSingleBlockLoadStoreElimPass : public Pass {
// from this set each time a new store of that variable is encountered.
std::unordered_set<uint32_t> pinned_vars_;
// Variables that are only referenced by supported operations for this
// pass ie. loads and stores.
std::unordered_set<uint32_t> supported_ref_ptrs_;
// Next unused ID
uint32_t next_id_;
};

View File

@ -184,8 +184,7 @@ class LocalMultiStoreElimPass : public Pass {
// the runtime and effectiveness of this function.
bool EliminateMultiStoreLocal(ir::Function* func);
// Return true if all uses of varId are only through supported reference
// operations ie. loads and store. Also cache in supported_ref_vars_;
// Return true if |op| is decorate.
inline bool IsDecorate(uint32_t op) const {
return (op == SpvOpDecorate || op == SpvOpDecorateId);
}