return ir::IRContext::kAnalysisDefUse |
ir::IRContext::kAnalysisDominatorAnalysis |
ir::IRContext::kAnalysisInstrToBlockMapping |
- ir::IRContext::kAnalysisCFG;
+ ir::IRContext::kAnalysisCFG | ir::IRContext::kAnalysisNameMap;
}
private:
if (set & kAnalysisLoopAnalysis) {
ResetLoopAnalysis();
}
+ if (set & kAnalysisNameMap) {
+ BuildIdToNameMap();
+ }
}
void IRContext::InvalidateAnalysesExceptFor(
dominator_trees_.clear();
post_dominator_trees_.clear();
}
+ if (analyses_to_invalidate & kAnalysisNameMap) {
+ id_to_name_.reset(nullptr);
+ }
valid_analyses_ = Analysis(valid_analyses_ & ~analyses_to_invalidate);
}
type_mgr_->RemoveId(inst->result_id());
}
+ RemoveFromIdToName(inst);
+
Instruction* next_instruction = nullptr;
if (inst->IsInAList()) {
next_instruction = inst->NextNode();
get_decoration_mgr()->RemoveDecoration(inst);
}
}
+ RemoveFromIdToName(inst);
}
void IRContext::AnalyzeUses(Instruction* inst) {
get_decoration_mgr()->AddDecoration(inst);
}
}
+ if (id_to_name_ &&
+ (inst->opcode() == SpvOpName || inst->opcode() == SpvOpMemberName)) {
+ id_to_name_->insert({inst->GetSingleWordInOperand(0), inst});
+ }
}
void IRContext::KillNamesAndDecorates(uint32_t id) {
KillInst(inst);
}
- Instruction* debug_inst = &*debug2_begin();
- while (debug_inst) {
- bool killed_inst = false;
- if (debug_inst->opcode() == SpvOpMemberName ||
- debug_inst->opcode() == SpvOpName) {
- if (debug_inst->GetSingleWordInOperand(0) == id) {
- debug_inst = KillInst(debug_inst);
- killed_inst = true;
- }
- }
- if (!killed_inst) {
- debug_inst = debug_inst->NextNode();
- }
+ std::vector<ir::Instruction*> name_to_kill;
+ for (auto name : GetNames(id)) {
+ name_to_kill.push_back(name.second);
+ }
+ for (ir::Instruction* name_inst : name_to_kill) {
+ KillInst(name_inst);
}
}
valid_analyses_ |= kAnalysisCombinators;
}
+void IRContext::RemoveFromIdToName(const Instruction* inst) {
+ if (id_to_name_ &&
+ (inst->opcode() == SpvOpName || inst->opcode() == SpvOpMemberName)) {
+ auto range = id_to_name_->equal_range(inst->GetSingleWordInOperand(0));
+ for (auto it = range.first; it != range.second; ++it) {
+ if (it->second == inst) {
+ id_to_name_->erase(it);
+ break;
+ }
+ }
+ }
+}
+
ir::LoopDescriptor* IRContext::GetLoopDescriptor(const ir::Function* f) {
if (!AreAnalysesValid(kAnalysisLoopAnalysis)) {
ResetLoopAnalysis();
kAnalysisCFG = 1 << 4,
kAnalysisDominatorAnalysis = 1 << 5,
kAnalysisLoopAnalysis = 1 << 6,
- kAnalysisEnd = 1 << 7
+ kAnalysisNameMap = 1 << 7,
+ kAnalysisEnd = 1 << 8
};
friend inline Analysis operator|(Analysis lhs, Analysis rhs);
def_use_mgr_(nullptr),
valid_analyses_(kAnalysisNone),
constant_mgr_(nullptr),
- type_mgr_(nullptr) {
+ type_mgr_(nullptr),
+ id_to_name_(nullptr) {
libspirv::SetContextMessageConsumer(syntax_context_, consumer_);
module_->SetContext(this);
}
consumer_(std::move(c)),
def_use_mgr_(nullptr),
valid_analyses_(kAnalysisNone),
- constant_mgr_(nullptr),
- type_mgr_(nullptr) {
+ type_mgr_(nullptr),
+ id_to_name_(nullptr) {
libspirv::SetContextMessageConsumer(syntax_context_, consumer_);
module_->SetContext(this);
InitializeCombinators();
return type_mgr_.get();
}
+ // Build the map from the ids to the OpName and OpMemberName instruction
+ // associated with it.
+ inline void BuildIdToNameMap();
+
+ // Returns a range of instrucions that contain all of the OpName and
+ // OpMemberNames associated with the given id.
+ inline IteratorRange<std::multimap<uint32_t, Instruction*>::iterator>
+ GetNames(uint32_t id);
+
// Sets the message consumer to the given |consumer|. |consumer| which will be
// invoked every time there is a message to be communicated to the outside.
void SetMessageConsumer(spvtools::MessageConsumer c) {
// Add the combinator opcode for the given extension to combinator_ops_.
void AddCombinatorsForExtension(ir::Instruction* extension);
+ // Remove |inst| from |id_to_name_| if it is in map.
+ void RemoveFromIdToName(const Instruction* inst);
+
// The SPIR-V syntax context containing grammar tables for opcodes and
// operands.
spv_context syntax_context_;
// Type manager for |module_|.
std::unique_ptr<opt::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_;
};
inline ir::IRContext::Analysis operator|(ir::IRContext::Analysis lhs,
}
void IRContext::AddDebug2Inst(std::unique_ptr<Instruction>&& d) {
+ if (AreAnalysesValid(kAnalysisNameMap)) {
+ if (d->opcode() == SpvOpName || d->opcode() == SpvOpMemberName) {
+ id_to_name_->insert({d->result_id(), d.get()});
+ }
+ }
module()->AddDebug2Inst(std::move(d));
}
}
}
+void IRContext::BuildIdToNameMap() {
+ id_to_name_.reset(new std::multimap<uint32_t, Instruction*>());
+ for (Instruction& debug_inst : debugs2()) {
+ if (debug_inst.opcode() == SpvOpMemberName ||
+ debug_inst.opcode() == SpvOpName) {
+ id_to_name_->insert({debug_inst.GetSingleWordInOperand(0), &debug_inst});
+ }
+ }
+ valid_analyses_ = valid_analyses_ | kAnalysisNameMap;
+}
+
+IteratorRange<std::multimap<uint32_t, Instruction*>::iterator>
+IRContext::GetNames(uint32_t id) {
+ if (!AreAnalysesValid(kAnalysisNameMap)) {
+ BuildIdToNameMap();
+ }
+ auto result = id_to_name_->equal_range(id);
+ return make_range(std::move(result.first), std::move(result.second));
+}
+
} // namespace ir
} // namespace spvtools
#endif // SPIRV_TOOLS_IR_CONTEXT_H
ir::IRContext::kAnalysisInstrToBlockMapping |
ir::IRContext::kAnalysisDecorations |
ir::IRContext::kAnalysisCombinators | ir::IRContext::kAnalysisCFG |
- ir::IRContext::kAnalysisDominatorAnalysis;
+ ir::IRContext::kAnalysisDominatorAnalysis |
+ ir::IRContext::kAnalysisNameMap;
}
protected:
return ir::IRContext::kAnalysisDefUse |
ir::IRContext::kAnalysisDecorations |
ir::IRContext::kAnalysisCombinators | ir::IRContext::kAnalysisCFG |
- ir::IRContext::kAnalysisDominatorAnalysis;
+ ir::IRContext::kAnalysisDominatorAnalysis |
+ ir::IRContext::kAnalysisNameMap;
}
private:
// |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|.
+ // |IsValidUse|, then that function is returned. Otherwise, the return
+ // value is |nullptr|.
ir::Function* FindLocalFunction(const ir::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.
+ // 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 ir::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 been changed
- // to function. If the type does not already exist, it will be created.
+ // 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
+ // been changed to function. If the type does not already exist, it will be
+ // created.
uint32_t GetNewType(uint32_t old_type_id);
// Updates |inst|, and any instruction dependent on |inst|, to reflect the
return ir::IRContext::kAnalysisDefUse |
ir::IRContext::kAnalysisInstrToBlockMapping |
ir::IRContext::kAnalysisDecorations |
- ir::IRContext::kAnalysisCombinators | ir::IRContext::kAnalysisCFG;
+ ir::IRContext::kAnalysisCombinators | ir::IRContext::kAnalysisCFG |
+ ir::IRContext::kAnalysisNameMap;
}
private: