}
}
+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
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
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) {
seen_target_vars_.clear();
seen_non_target_vars_.clear();
+ // Clear collections
+ supported_ref_ptrs_.clear();
+
// TODO(greg-lunarg): Reuse def/use from previous passes
def_use_mgr_.reset(new analysis::DefUseManager(consumer(), module_));
// 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
// Extensions supported by this pass.
std::unordered_set<std::string> extensions_whitelist_;
+ // 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_;
};
// 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);
}