1 // Copyright (c) 2017 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef SOURCE_OPT_IR_CONTEXT_H_
16 #define SOURCE_OPT_IR_CONTEXT_H_
17 
18 #include <algorithm>
19 #include <iostream>
20 #include <limits>
21 #include <map>
22 #include <memory>
23 #include <queue>
24 #include <unordered_map>
25 #include <unordered_set>
26 #include <utility>
27 #include <vector>
28 
29 #include "source/assembly_grammar.h"
30 #include "source/opt/cfg.h"
31 #include "source/opt/constants.h"
32 #include "source/opt/debug_info_manager.h"
33 #include "source/opt/decoration_manager.h"
34 #include "source/opt/def_use_manager.h"
35 #include "source/opt/dominator_analysis.h"
36 #include "source/opt/feature_manager.h"
37 #include "source/opt/fold.h"
38 #include "source/opt/loop_descriptor.h"
39 #include "source/opt/module.h"
40 #include "source/opt/register_pressure.h"
41 #include "source/opt/scalar_analysis.h"
42 #include "source/opt/struct_cfg_analysis.h"
43 #include "source/opt/type_manager.h"
44 #include "source/opt/value_number_table.h"
45 #include "source/util/make_unique.h"
46 
47 namespace spvtools {
48 namespace opt {
49 
50 class IRContext {
51  public:
52   // Available analyses.
53   //
54   // When adding a new analysis:
55   //
56   // 1. Enum values should be powers of 2. These are cast into uint32_t
57   //    bitmasks, so we can have at most 31 analyses represented.
58   //
59   // 2. Make sure it gets invalidated or preserved by IRContext methods that add
60   //    or remove IR elements (e.g., KillDef, KillInst, ReplaceAllUsesWith).
61   //
62   // 3. Add handling code in BuildInvalidAnalyses and InvalidateAnalyses
63   enum Analysis {
64     kAnalysisNone = 0 << 0,
65     kAnalysisBegin = 1 << 0,
66     kAnalysisDefUse = kAnalysisBegin,
67     kAnalysisInstrToBlockMapping = 1 << 1,
68     kAnalysisDecorations = 1 << 2,
69     kAnalysisCombinators = 1 << 3,
70     kAnalysisCFG = 1 << 4,
71     kAnalysisDominatorAnalysis = 1 << 5,
72     kAnalysisLoopAnalysis = 1 << 6,
73     kAnalysisNameMap = 1 << 7,
74     kAnalysisScalarEvolution = 1 << 8,
75     kAnalysisRegisterPressure = 1 << 9,
76     kAnalysisValueNumberTable = 1 << 10,
77     kAnalysisStructuredCFG = 1 << 11,
78     kAnalysisBuiltinVarId = 1 << 12,
79     kAnalysisIdToFuncMapping = 1 << 13,
80     kAnalysisConstants = 1 << 14,
81     kAnalysisTypes = 1 << 15,
82     kAnalysisDebugInfo = 1 << 16,
83     kAnalysisEnd = 1 << 17
84   };
85 
86   using ProcessFunction = std::function<bool(Function*)>;
87 
88   friend inline Analysis operator|(Analysis lhs, Analysis rhs);
89   friend inline Analysis& operator|=(Analysis& lhs, Analysis rhs);
90   friend inline Analysis operator<<(Analysis a, int shift);
91   friend inline Analysis& operator<<=(Analysis& a, int shift);
92 
93   // Creates an |IRContext| that contains an owned |Module|
IRContext(spv_target_env env,MessageConsumer c)94   IRContext(spv_target_env env, MessageConsumer c)
95       : syntax_context_(spvContextCreate(env)),
96         grammar_(syntax_context_),
97         unique_id_(0),
98         module_(new Module()),
99         consumer_(std::move(c)),
100         def_use_mgr_(nullptr),
101         valid_analyses_(kAnalysisNone),
102         constant_mgr_(nullptr),
103         type_mgr_(nullptr),
104         id_to_name_(nullptr),
105         max_id_bound_(kDefaultMaxIdBound),
106         preserve_bindings_(false),
107         preserve_spec_constants_(false) {
108     SetContextMessageConsumer(syntax_context_, consumer_);
109     module_->SetContext(this);
110   }
111 
IRContext(spv_target_env env,std::unique_ptr<Module> && m,MessageConsumer c)112   IRContext(spv_target_env env, std::unique_ptr<Module>&& m, MessageConsumer c)
113       : syntax_context_(spvContextCreate(env)),
114         grammar_(syntax_context_),
115         unique_id_(0),
116         module_(std::move(m)),
117         consumer_(std::move(c)),
118         def_use_mgr_(nullptr),
119         valid_analyses_(kAnalysisNone),
120         type_mgr_(nullptr),
121         id_to_name_(nullptr),
122         max_id_bound_(kDefaultMaxIdBound),
123         preserve_bindings_(false),
124         preserve_spec_constants_(false) {
125     SetContextMessageConsumer(syntax_context_, consumer_);
126     module_->SetContext(this);
127     InitializeCombinators();
128   }
129 
~IRContext()130   ~IRContext() { spvContextDestroy(syntax_context_); }
131 
module()132   Module* module() const { return module_.get(); }
133 
134   // Returns a vector of pointers to constant-creation instructions in this
135   // context.
136   inline std::vector<Instruction*> GetConstants();
137   inline std::vector<const Instruction*> GetConstants() const;
138 
139   // Iterators for annotation instructions contained in this context.
140   inline Module::inst_iterator annotation_begin();
141   inline Module::inst_iterator annotation_end();
142   inline IteratorRange<Module::inst_iterator> annotations();
143   inline IteratorRange<Module::const_inst_iterator> annotations() const;
144 
145   // Iterators for capabilities instructions contained in this module.
146   inline Module::inst_iterator capability_begin();
147   inline Module::inst_iterator capability_end();
148   inline IteratorRange<Module::inst_iterator> capabilities();
149   inline IteratorRange<Module::const_inst_iterator> capabilities() const;
150 
151   // Iterators for types, constants and global variables instructions.
152   inline Module::inst_iterator types_values_begin();
153   inline Module::inst_iterator types_values_end();
154   inline IteratorRange<Module::inst_iterator> types_values();
155   inline IteratorRange<Module::const_inst_iterator> types_values() const;
156 
157   // Iterators for extension instructions contained in this module.
158   inline Module::inst_iterator ext_inst_import_begin();
159   inline Module::inst_iterator ext_inst_import_end();
160   inline IteratorRange<Module::inst_iterator> ext_inst_imports();
161   inline IteratorRange<Module::const_inst_iterator> ext_inst_imports() const;
162 
163   // There are several kinds of debug instructions, according to where they can
164   // appear in the logical layout of a module:
165   //  - Section 7a:  OpString, OpSourceExtension, OpSource, OpSourceContinued
166   //  - Section 7b:  OpName, OpMemberName
167   //  - Section 7c:  OpModuleProcessed
168   //  - Mostly anywhere: OpLine and OpNoLine
169   //
170 
171   // Iterators for debug 1 instructions (excluding OpLine & OpNoLine) contained
172   // in this module.  These are for layout section 7a.
173   inline Module::inst_iterator debug1_begin();
174   inline Module::inst_iterator debug1_end();
175   inline IteratorRange<Module::inst_iterator> debugs1();
176   inline IteratorRange<Module::const_inst_iterator> debugs1() const;
177 
178   // Iterators for debug 2 instructions (excluding OpLine & OpNoLine) contained
179   // in this module.  These are for layout section 7b.
180   inline Module::inst_iterator debug2_begin();
181   inline Module::inst_iterator debug2_end();
182   inline IteratorRange<Module::inst_iterator> debugs2();
183   inline IteratorRange<Module::const_inst_iterator> debugs2() const;
184 
185   // Iterators for debug 3 instructions (excluding OpLine & OpNoLine) contained
186   // in this module.  These are for layout section 7c.
187   inline Module::inst_iterator debug3_begin();
188   inline Module::inst_iterator debug3_end();
189   inline IteratorRange<Module::inst_iterator> debugs3();
190   inline IteratorRange<Module::const_inst_iterator> debugs3() const;
191 
192   // Iterators for debug info instructions (excluding OpLine & OpNoLine)
193   // contained in this module.  These are OpExtInst for OpenCL.DebugInfo.100
194   // or DebugInfo extension placed between section 9 and 10.
195   inline Module::inst_iterator ext_inst_debuginfo_begin();
196   inline Module::inst_iterator ext_inst_debuginfo_end();
197   inline IteratorRange<Module::inst_iterator> ext_inst_debuginfo();
198   inline IteratorRange<Module::const_inst_iterator> ext_inst_debuginfo() const;
199 
200   // Add |capability| to the module, if it is not already enabled.
201   inline void AddCapability(SpvCapability capability);
202 
203   // Appends a capability instruction to this module.
204   inline void AddCapability(std::unique_ptr<Instruction>&& c);
205   // Appends an extension instruction to this module.
206   inline void AddExtension(const std::string& ext_name);
207   inline void AddExtension(std::unique_ptr<Instruction>&& e);
208   // Appends an extended instruction set instruction to this module.
209   inline void AddExtInstImport(const std::string& name);
210   inline void AddExtInstImport(std::unique_ptr<Instruction>&& e);
211   // Set the memory model for this module.
212   inline void SetMemoryModel(std::unique_ptr<Instruction>&& m);
213   // Appends an entry point instruction to this module.
214   inline void AddEntryPoint(std::unique_ptr<Instruction>&& e);
215   // Appends an execution mode instruction to this module.
216   inline void AddExecutionMode(std::unique_ptr<Instruction>&& e);
217   // Appends a debug 1 instruction (excluding OpLine & OpNoLine) to this module.
218   // "debug 1" instructions are the ones in layout section 7.a), see section
219   // 2.4 Logical Layout of a Module from the SPIR-V specification.
220   inline void AddDebug1Inst(std::unique_ptr<Instruction>&& d);
221   // Appends a debug 2 instruction (excluding OpLine & OpNoLine) to this module.
222   // "debug 2" instructions are the ones in layout section 7.b), see section
223   // 2.4 Logical Layout of a Module from the SPIR-V specification.
224   inline void AddDebug2Inst(std::unique_ptr<Instruction>&& d);
225   // Appends a debug 3 instruction (OpModuleProcessed) to this module.
226   // This is due to decision by the SPIR Working Group, pending publication.
227   inline void AddDebug3Inst(std::unique_ptr<Instruction>&& d);
228   // Appends a OpExtInst for DebugInfo to this module.
229   inline void AddExtInstDebugInfo(std::unique_ptr<Instruction>&& d);
230   // Appends an annotation instruction to this module.
231   inline void AddAnnotationInst(std::unique_ptr<Instruction>&& a);
232   // Appends a type-declaration instruction to this module.
233   inline void AddType(std::unique_ptr<Instruction>&& t);
234   // Appends a constant, global variable, or OpUndef instruction to this module.
235   inline void AddGlobalValue(std::unique_ptr<Instruction>&& v);
236   // Appends a function to this module.
237   inline void AddFunction(std::unique_ptr<Function>&& f);
238 
239   // Returns a pointer to a def-use manager.  If the def-use manager is
240   // invalid, it is rebuilt first.
get_def_use_mgr()241   analysis::DefUseManager* get_def_use_mgr() {
242     if (!AreAnalysesValid(kAnalysisDefUse)) {
243       BuildDefUseManager();
244     }
245     return def_use_mgr_.get();
246   }
247 
248   // Returns a pointer to a value number table.  If the liveness analysis is
249   // invalid, it is rebuilt first.
GetValueNumberTable()250   ValueNumberTable* GetValueNumberTable() {
251     if (!AreAnalysesValid(kAnalysisValueNumberTable)) {
252       BuildValueNumberTable();
253     }
254     return vn_table_.get();
255   }
256 
257   // Returns a pointer to a StructuredCFGAnalysis.  If the analysis is invalid,
258   // it is rebuilt first.
GetStructuredCFGAnalysis()259   StructuredCFGAnalysis* GetStructuredCFGAnalysis() {
260     if (!AreAnalysesValid(kAnalysisStructuredCFG)) {
261       BuildStructuredCFGAnalysis();
262     }
263     return struct_cfg_analysis_.get();
264   }
265 
266   // Returns a pointer to a liveness analysis.  If the liveness analysis is
267   // invalid, it is rebuilt first.
GetLivenessAnalysis()268   LivenessAnalysis* GetLivenessAnalysis() {
269     if (!AreAnalysesValid(kAnalysisRegisterPressure)) {
270       BuildRegPressureAnalysis();
271     }
272     return reg_pressure_.get();
273   }
274 
275   // Returns the basic block for instruction |instr|. Re-builds the instruction
276   // block map, if needed.
get_instr_block(Instruction * instr)277   BasicBlock* get_instr_block(Instruction* instr) {
278     if (!AreAnalysesValid(kAnalysisInstrToBlockMapping)) {
279       BuildInstrToBlockMapping();
280     }
281     auto entry = instr_to_block_.find(instr);
282     return (entry != instr_to_block_.end()) ? entry->second : nullptr;
283   }
284 
285   // Returns the basic block for |id|. Re-builds the instruction block map, if
286   // needed.
287   //
288   // |id| must be a registered definition.
get_instr_block(uint32_t id)289   BasicBlock* get_instr_block(uint32_t id) {
290     Instruction* def = get_def_use_mgr()->GetDef(id);
291     return get_instr_block(def);
292   }
293 
294   // Sets the basic block for |inst|. Re-builds the mapping if it has become
295   // invalid.
set_instr_block(Instruction * inst,BasicBlock * block)296   void set_instr_block(Instruction* inst, BasicBlock* block) {
297     if (AreAnalysesValid(kAnalysisInstrToBlockMapping)) {
298       instr_to_block_[inst] = block;
299     }
300   }
301 
302   // Returns a pointer the decoration manager.  If the decoration manger is
303   // invalid, it is rebuilt first.
get_decoration_mgr()304   analysis::DecorationManager* get_decoration_mgr() {
305     if (!AreAnalysesValid(kAnalysisDecorations)) {
306       BuildDecorationManager();
307     }
308     return decoration_mgr_.get();
309   }
310 
311   // Returns a pointer to the constant manager.  If no constant manager has been
312   // created yet, it creates one.  NOTE: Once created, the constant manager
313   // remains active and it is never re-built.
get_constant_mgr()314   analysis::ConstantManager* get_constant_mgr() {
315     if (!AreAnalysesValid(kAnalysisConstants)) {
316       BuildConstantManager();
317     }
318     return constant_mgr_.get();
319   }
320 
321   // Returns a pointer to the type manager.  If no type manager has been created
322   // yet, it creates one. NOTE: Once created, the type manager remains active it
323   // is never re-built.
get_type_mgr()324   analysis::TypeManager* get_type_mgr() {
325     if (!AreAnalysesValid(kAnalysisTypes)) {
326       BuildTypeManager();
327     }
328     return type_mgr_.get();
329   }
330 
331   // Returns a pointer to the debug information manager.  If no debug
332   // information manager has been created yet, it creates one.
333   // NOTE: Once created, the debug information manager remains active
334   // it is never re-built.
get_debug_info_mgr()335   analysis::DebugInfoManager* get_debug_info_mgr() {
336     if (!AreAnalysesValid(kAnalysisDebugInfo)) {
337       BuildDebugInfoManager();
338     }
339     return debug_info_mgr_.get();
340   }
341 
342   // Returns a pointer to the scalar evolution analysis. If it is invalid it
343   // will be rebuilt first.
GetScalarEvolutionAnalysis()344   ScalarEvolutionAnalysis* GetScalarEvolutionAnalysis() {
345     if (!AreAnalysesValid(kAnalysisScalarEvolution)) {
346       BuildScalarEvolutionAnalysis();
347     }
348     return scalar_evolution_analysis_.get();
349   }
350 
351   // Build the map from the ids to the OpName and OpMemberName instruction
352   // associated with it.
353   inline void BuildIdToNameMap();
354 
355   // Returns a range of instrucions that contain all of the OpName and
356   // OpMemberNames associated with the given id.
357   inline IteratorRange<std::multimap<uint32_t, Instruction*>::iterator>
358   GetNames(uint32_t id);
359 
360   // Returns an OpMemberName instruction that targets |struct_type_id| at
361   // index |index|. Returns nullptr if no such instruction exists.
362   // While the SPIR-V spec does not prohibit having multiple OpMemberName
363   // instructions for the same structure member, it is hard to imagine a member
364   // having more than one name. This method returns the first one it finds.
365   inline Instruction* GetMemberName(uint32_t struct_type_id, uint32_t index);
366 
367   // Sets the message consumer to the given |consumer|. |consumer| which will be
368   // invoked every time there is a message to be communicated to the outside.
SetMessageConsumer(MessageConsumer c)369   void SetMessageConsumer(MessageConsumer c) { consumer_ = std::move(c); }
370 
371   // Returns the reference to the message consumer for this pass.
consumer()372   const MessageConsumer& consumer() const { return consumer_; }
373 
374   // Rebuilds the analyses in |set| that are invalid.
375   void BuildInvalidAnalyses(Analysis set);
376 
377   // Invalidates all of the analyses except for those in |preserved_analyses|.
378   void InvalidateAnalysesExceptFor(Analysis preserved_analyses);
379 
380   // Invalidates the analyses marked in |analyses_to_invalidate|.
381   void InvalidateAnalyses(Analysis analyses_to_invalidate);
382 
383   // Deletes the instruction defining the given |id|. Returns true on
384   // success, false if the given |id| is not defined at all. This method also
385   // erases the name, decorations, and defintion of |id|.
386   //
387   // Pointers and iterators pointing to the deleted instructions become invalid.
388   // However other pointers and iterators are still valid.
389   bool KillDef(uint32_t id);
390 
391   // Deletes the given instruction |inst|. This method erases the
392   // information of the given instruction's uses of its operands. If |inst|
393   // defines a result id, its name and decorations will also be deleted.
394   //
395   // Pointer and iterator pointing to the deleted instructions become invalid.
396   // However other pointers and iterators are still valid.
397   //
398   // Note that if an instruction is not in an instruction list, the memory may
399   // not be safe to delete, so the instruction is turned into a OpNop instead.
400   // This can happen with OpLabel.
401   //
402   // Returns a pointer to the instruction after |inst| or |nullptr| if no such
403   // instruction exists.
404   Instruction* KillInst(Instruction* inst);
405 
406   // Removes the non-semantic instruction tree that uses |inst|'s result id.
407   void KillNonSemanticInfo(Instruction* inst);
408 
409   // Returns true if all of the given analyses are valid.
AreAnalysesValid(Analysis set)410   bool AreAnalysesValid(Analysis set) { return (set & valid_analyses_) == set; }
411 
412   // Replaces all uses of |before| id with |after| id. Returns true if any
413   // replacement happens. This method does not kill the definition of the
414   // |before| id. If |after| is the same as |before|, does nothing and returns
415   // false.
416   //
417   // |before| and |after| must be registered definitions in the DefUseManager.
418   bool ReplaceAllUsesWith(uint32_t before, uint32_t after);
419 
420   // Replace all uses of |before| id with |after| id if those uses
421   // (instruction) return true for |predicate|. Returns true if
422   // any replacement happens. This method does not kill the definition of the
423   // |before| id. If |after| is the same as |before|, does nothing and return
424   // false.
425   bool ReplaceAllUsesWithPredicate(
426       uint32_t before, uint32_t after,
427       const std::function<bool(Instruction*)>& predicate);
428 
429   // Returns true if all of the analyses that are suppose to be valid are
430   // actually valid.
431   bool IsConsistent();
432 
433   // The IRContext will look at the def and uses of |inst| and update any valid
434   // analyses will be updated accordingly.
435   inline void AnalyzeDefUse(Instruction* inst);
436 
437   // Informs the IRContext that the uses of |inst| are going to change, and that
438   // is should forget everything it know about the current uses.  Any valid
439   // analyses will be updated accordingly.
440   void ForgetUses(Instruction* inst);
441 
442   // The IRContext will look at the uses of |inst| and update any valid analyses
443   // will be updated accordingly.
444   void AnalyzeUses(Instruction* inst);
445 
446   // Kill all name and decorate ops targeting |id|.
447   void KillNamesAndDecorates(uint32_t id);
448 
449   // Kill all name and decorate ops targeting the result id of |inst|.
450   void KillNamesAndDecorates(Instruction* inst);
451 
452   // Change operands of debug instruction to DebugInfoNone.
453   void KillOperandFromDebugInstructions(Instruction* inst);
454 
455   // Returns the next unique id for use by an instruction.
TakeNextUniqueId()456   inline uint32_t TakeNextUniqueId() {
457     assert(unique_id_ != std::numeric_limits<uint32_t>::max());
458 
459     // Skip zero.
460     return ++unique_id_;
461   }
462 
463   // Returns true if |inst| is a combinator in the current context.
464   // |combinator_ops_| is built if it has not been already.
IsCombinatorInstruction(const Instruction * inst)465   inline bool IsCombinatorInstruction(const Instruction* inst) {
466     if (!AreAnalysesValid(kAnalysisCombinators)) {
467       InitializeCombinators();
468     }
469     const uint32_t kExtInstSetIdInIndx = 0;
470     const uint32_t kExtInstInstructionInIndx = 1;
471 
472     if (inst->opcode() != SpvOpExtInst) {
473       return combinator_ops_[0].count(inst->opcode()) != 0;
474     } else {
475       uint32_t set = inst->GetSingleWordInOperand(kExtInstSetIdInIndx);
476       uint32_t op = inst->GetSingleWordInOperand(kExtInstInstructionInIndx);
477       return combinator_ops_[set].count(op) != 0;
478     }
479   }
480 
481   // Returns a pointer to the CFG for all the functions in |module_|.
cfg()482   CFG* cfg() {
483     if (!AreAnalysesValid(kAnalysisCFG)) {
484       BuildCFG();
485     }
486     return cfg_.get();
487   }
488 
489   // Gets the loop descriptor for function |f|.
490   LoopDescriptor* GetLoopDescriptor(const Function* f);
491 
492   // Gets the dominator analysis for function |f|.
493   DominatorAnalysis* GetDominatorAnalysis(const Function* f);
494 
495   // Gets the postdominator analysis for function |f|.
496   PostDominatorAnalysis* GetPostDominatorAnalysis(const Function* f);
497 
498   // Remove the dominator tree of |f| from the cache.
RemoveDominatorAnalysis(const Function * f)499   inline void RemoveDominatorAnalysis(const Function* f) {
500     dominator_trees_.erase(f);
501   }
502 
503   // Remove the postdominator tree of |f| from the cache.
RemovePostDominatorAnalysis(const Function * f)504   inline void RemovePostDominatorAnalysis(const Function* f) {
505     post_dominator_trees_.erase(f);
506   }
507 
508   // Return the next available SSA id and increment it.  Returns 0 if the
509   // maximum SSA id has been reached.
TakeNextId()510   inline uint32_t TakeNextId() {
511     uint32_t next_id = module()->TakeNextIdBound();
512     if (next_id == 0) {
513       if (consumer()) {
514         std::string message = "ID overflow. Try running compact-ids.";
515         consumer()(SPV_MSG_ERROR, "", {0, 0, 0}, message.c_str());
516       }
517     }
518     return next_id;
519   }
520 
get_feature_mgr()521   FeatureManager* get_feature_mgr() {
522     if (!feature_mgr_.get()) {
523       AnalyzeFeatures();
524     }
525     return feature_mgr_.get();
526   }
527 
ResetFeatureManager()528   void ResetFeatureManager() { feature_mgr_.reset(nullptr); }
529 
530   // Returns the grammar for this context.
grammar()531   const AssemblyGrammar& grammar() const { return grammar_; }
532 
533   // If |inst| has not yet been analysed by the def-use manager, then analyse
534   // its definitions and uses.
535   inline void UpdateDefUse(Instruction* inst);
536 
get_instruction_folder()537   const InstructionFolder& get_instruction_folder() {
538     if (!inst_folder_) {
539       inst_folder_ = MakeUnique<InstructionFolder>(this);
540     }
541     return *inst_folder_;
542   }
543 
max_id_bound()544   uint32_t max_id_bound() const { return max_id_bound_; }
set_max_id_bound(uint32_t new_bound)545   void set_max_id_bound(uint32_t new_bound) { max_id_bound_ = new_bound; }
546 
preserve_bindings()547   bool preserve_bindings() const { return preserve_bindings_; }
set_preserve_bindings(bool should_preserve_bindings)548   void set_preserve_bindings(bool should_preserve_bindings) {
549     preserve_bindings_ = should_preserve_bindings;
550   }
551 
preserve_spec_constants()552   bool preserve_spec_constants() const { return preserve_spec_constants_; }
set_preserve_spec_constants(bool should_preserve_spec_constants)553   void set_preserve_spec_constants(bool should_preserve_spec_constants) {
554     preserve_spec_constants_ = should_preserve_spec_constants;
555   }
556 
557   // Return id of input variable only decorated with |builtin|, if in module.
558   // Create variable and return its id otherwise. If builtin not currently
559   // supported, return 0.
560   uint32_t GetBuiltinInputVarId(uint32_t builtin);
561 
562   // Returns the function whose id is |id|, if one exists.  Returns |nullptr|
563   // otherwise.
GetFunction(uint32_t id)564   Function* GetFunction(uint32_t id) {
565     if (!AreAnalysesValid(kAnalysisIdToFuncMapping)) {
566       BuildIdToFuncMapping();
567     }
568     auto entry = id_to_func_.find(id);
569     return (entry != id_to_func_.end()) ? entry->second : nullptr;
570   }
571 
GetFunction(Instruction * inst)572   Function* GetFunction(Instruction* inst) {
573     if (inst->opcode() != SpvOpFunction) {
574       return nullptr;
575     }
576     return GetFunction(inst->result_id());
577   }
578 
579   // Add to |todo| all ids of functions called directly from |func|.
580   void AddCalls(const Function* func, std::queue<uint32_t>* todo);
581 
582   // Applies |pfn| to every function in the call trees that are rooted at the
583   // entry points.  Returns true if any call |pfn| returns true.  By convention
584   // |pfn| should return true if it modified the module.
585   bool ProcessEntryPointCallTree(ProcessFunction& pfn);
586 
587   // Applies |pfn| to every function in the call trees rooted at the entry
588   // points and exported functions.  Returns true if any call |pfn| returns
589   // true.  By convention |pfn| should return true if it modified the module.
590   bool ProcessReachableCallTree(ProcessFunction& pfn);
591 
592   // Applies |pfn| to every function in the call trees rooted at the elements of
593   // |roots|.  Returns true if any call to |pfn| returns true.  By convention
594   // |pfn| should return true if it modified the module.  After returning
595   // |roots| will be empty.
596   bool ProcessCallTreeFromRoots(ProcessFunction& pfn,
597                                 std::queue<uint32_t>* roots);
598 
599   // Emmits a error message to the message consumer indicating the error
600   // described by |message| occurred in |inst|.
601   void EmitErrorMessage(std::string message, Instruction* inst);
602 
603  private:
604   // Builds the def-use manager from scratch, even if it was already valid.
BuildDefUseManager()605   void BuildDefUseManager() {
606     def_use_mgr_ = MakeUnique<analysis::DefUseManager>(module());
607     valid_analyses_ = valid_analyses_ | kAnalysisDefUse;
608   }
609 
610   // Builds the instruction-block map for the whole module.
BuildInstrToBlockMapping()611   void BuildInstrToBlockMapping() {
612     instr_to_block_.clear();
613     for (auto& fn : *module_) {
614       for (auto& block : fn) {
615         block.ForEachInst([this, &block](Instruction* inst) {
616           instr_to_block_[inst] = &block;
617         });
618       }
619     }
620     valid_analyses_ = valid_analyses_ | kAnalysisInstrToBlockMapping;
621   }
622 
623   // Builds the instruction-function map for the whole module.
BuildIdToFuncMapping()624   void BuildIdToFuncMapping() {
625     id_to_func_.clear();
626     for (auto& fn : *module_) {
627       id_to_func_[fn.result_id()] = &fn;
628     }
629     valid_analyses_ = valid_analyses_ | kAnalysisIdToFuncMapping;
630   }
631 
BuildDecorationManager()632   void BuildDecorationManager() {
633     decoration_mgr_ = MakeUnique<analysis::DecorationManager>(module());
634     valid_analyses_ = valid_analyses_ | kAnalysisDecorations;
635   }
636 
BuildCFG()637   void BuildCFG() {
638     cfg_ = MakeUnique<CFG>(module());
639     valid_analyses_ = valid_analyses_ | kAnalysisCFG;
640   }
641 
BuildScalarEvolutionAnalysis()642   void BuildScalarEvolutionAnalysis() {
643     scalar_evolution_analysis_ = MakeUnique<ScalarEvolutionAnalysis>(this);
644     valid_analyses_ = valid_analyses_ | kAnalysisScalarEvolution;
645   }
646 
647   // Builds the liveness analysis from scratch, even if it was already valid.
BuildRegPressureAnalysis()648   void BuildRegPressureAnalysis() {
649     reg_pressure_ = MakeUnique<LivenessAnalysis>(this);
650     valid_analyses_ = valid_analyses_ | kAnalysisRegisterPressure;
651   }
652 
653   // Builds the value number table analysis from scratch, even if it was already
654   // valid.
BuildValueNumberTable()655   void BuildValueNumberTable() {
656     vn_table_ = MakeUnique<ValueNumberTable>(this);
657     valid_analyses_ = valid_analyses_ | kAnalysisValueNumberTable;
658   }
659 
660   // Builds the structured CFG analysis from scratch, even if it was already
661   // valid.
BuildStructuredCFGAnalysis()662   void BuildStructuredCFGAnalysis() {
663     struct_cfg_analysis_ = MakeUnique<StructuredCFGAnalysis>(this);
664     valid_analyses_ = valid_analyses_ | kAnalysisStructuredCFG;
665   }
666 
667   // Builds the constant manager from scratch, even if it was already
668   // valid.
BuildConstantManager()669   void BuildConstantManager() {
670     constant_mgr_ = MakeUnique<analysis::ConstantManager>(this);
671     valid_analyses_ = valid_analyses_ | kAnalysisConstants;
672   }
673 
674   // Builds the type manager from scratch, even if it was already
675   // valid.
BuildTypeManager()676   void BuildTypeManager() {
677     type_mgr_ = MakeUnique<analysis::TypeManager>(consumer(), this);
678     valid_analyses_ = valid_analyses_ | kAnalysisTypes;
679   }
680 
681   // Builds the debug information manager from scratch, even if it was
682   // already valid.
BuildDebugInfoManager()683   void BuildDebugInfoManager() {
684     debug_info_mgr_ = MakeUnique<analysis::DebugInfoManager>(this);
685     valid_analyses_ = valid_analyses_ | kAnalysisDebugInfo;
686   }
687 
688   // Removes all computed dominator and post-dominator trees. This will force
689   // the context to rebuild the trees on demand.
ResetDominatorAnalysis()690   void ResetDominatorAnalysis() {
691     // Clear the cache.
692     dominator_trees_.clear();
693     post_dominator_trees_.clear();
694     valid_analyses_ = valid_analyses_ | kAnalysisDominatorAnalysis;
695   }
696 
697   // Removes all computed loop descriptors.
ResetLoopAnalysis()698   void ResetLoopAnalysis() {
699     // Clear the cache.
700     loop_descriptors_.clear();
701     valid_analyses_ = valid_analyses_ | kAnalysisLoopAnalysis;
702   }
703 
704   // Removes all computed loop descriptors.
ResetBuiltinAnalysis()705   void ResetBuiltinAnalysis() {
706     // Clear the cache.
707     builtin_var_id_map_.clear();
708     valid_analyses_ = valid_analyses_ | kAnalysisBuiltinVarId;
709   }
710 
711   // Analyzes the features in the owned module. Builds the manager if required.
AnalyzeFeatures()712   void AnalyzeFeatures() {
713     feature_mgr_ = MakeUnique<FeatureManager>(grammar_);
714     feature_mgr_->Analyze(module());
715   }
716 
717   // Scans a module looking for it capabilities, and initializes combinator_ops_
718   // accordingly.
719   void InitializeCombinators();
720 
721   // Add the combinator opcode for the given capability to combinator_ops_.
722   void AddCombinatorsForCapability(uint32_t capability);
723 
724   // Add the combinator opcode for the given extension to combinator_ops_.
725   void AddCombinatorsForExtension(Instruction* extension);
726 
727   // Remove |inst| from |id_to_name_| if it is in map.
728   void RemoveFromIdToName(const Instruction* inst);
729 
730   // Returns true if it is suppose to be valid but it is incorrect.  Returns
731   // true if the cfg is invalidated.
732   bool CheckCFG();
733 
734   // Return id of input variable only decorated with |builtin|, if in module.
735   // Return 0 otherwise.
736   uint32_t FindBuiltinInputVar(uint32_t builtin);
737 
738   // Add |var_id| to all entry points in module.
739   void AddVarToEntryPoints(uint32_t var_id);
740 
741   // The SPIR-V syntax context containing grammar tables for opcodes and
742   // operands.
743   spv_context syntax_context_;
744 
745   // Auxiliary object for querying SPIR-V grammar facts.
746   AssemblyGrammar grammar_;
747 
748   // An unique identifier for instructions in |module_|. Can be used to order
749   // instructions in a container.
750   //
751   // This member is initialized to 0, but always issues this value plus one.
752   // Therefore, 0 is not a valid unique id for an instruction.
753   uint32_t unique_id_;
754 
755   // The module being processed within this IR context.
756   std::unique_ptr<Module> module_;
757 
758   // A message consumer for diagnostics.
759   MessageConsumer consumer_;
760 
761   // The def-use manager for |module_|.
762   std::unique_ptr<analysis::DefUseManager> def_use_mgr_;
763 
764   // The instruction decoration manager for |module_|.
765   std::unique_ptr<analysis::DecorationManager> decoration_mgr_;
766   std::unique_ptr<FeatureManager> feature_mgr_;
767 
768   // A map from instructions to the basic block they belong to. This mapping is
769   // built on-demand when get_instr_block() is called.
770   //
771   // NOTE: Do not traverse this map. Ever. Use the function and basic block
772   // iterators to traverse instructions.
773   std::unordered_map<Instruction*, BasicBlock*> instr_to_block_;
774 
775   // A map from ids to the function they define. This mapping is
776   // built on-demand when GetFunction() is called.
777   //
778   // NOTE: Do not traverse this map. Ever. Use the function and basic block
779   // iterators to traverse instructions.
780   std::unordered_map<uint32_t, Function*> id_to_func_;
781 
782   // A bitset indicating which analyes are currently valid.
783   Analysis valid_analyses_;
784 
785   // Opcodes of shader capability core executable instructions
786   // without side-effect.
787   std::unordered_map<uint32_t, std::unordered_set<uint32_t>> combinator_ops_;
788 
789   // Opcodes of shader capability core executable instructions
790   // without side-effect.
791   std::unordered_map<uint32_t, uint32_t> builtin_var_id_map_;
792 
793   // The CFG for all the functions in |module_|.
794   std::unique_ptr<CFG> cfg_;
795 
796   // Each function in the module will create its own dominator tree. We cache
797   // the result so it doesn't need to be rebuilt each time.
798   std::map<const Function*, DominatorAnalysis> dominator_trees_;
799   std::map<const Function*, PostDominatorAnalysis> post_dominator_trees_;
800 
801   // Cache of loop descriptors for each function.
802   std::unordered_map<const Function*, LoopDescriptor> loop_descriptors_;
803 
804   // Constant manager for |module_|.
805   std::unique_ptr<analysis::ConstantManager> constant_mgr_;
806 
807   // Type manager for |module_|.
808   std::unique_ptr<analysis::TypeManager> type_mgr_;
809 
810   // Debug information manager for |module_|.
811   std::unique_ptr<analysis::DebugInfoManager> debug_info_mgr_;
812 
813   // A map from an id to its corresponding OpName and OpMemberName instructions.
814   std::unique_ptr<std::multimap<uint32_t, Instruction*>> id_to_name_;
815 
816   // The cache scalar evolution analysis node.
817   std::unique_ptr<ScalarEvolutionAnalysis> scalar_evolution_analysis_;
818 
819   // The liveness analysis |module_|.
820   std::unique_ptr<LivenessAnalysis> reg_pressure_;
821 
822   std::unique_ptr<ValueNumberTable> vn_table_;
823 
824   std::unique_ptr<InstructionFolder> inst_folder_;
825 
826   std::unique_ptr<StructuredCFGAnalysis> struct_cfg_analysis_;
827 
828   // The maximum legal value for the id bound.
829   uint32_t max_id_bound_;
830 
831   // Whether all bindings within |module_| should be preserved.
832   bool preserve_bindings_;
833 
834   // Whether all specialization constants within |module_|
835   // should be preserved.
836   bool preserve_spec_constants_;
837 };
838 
839 inline IRContext::Analysis operator|(IRContext::Analysis lhs,
840                                      IRContext::Analysis rhs) {
841   return static_cast<IRContext::Analysis>(static_cast<int>(lhs) |
842                                           static_cast<int>(rhs));
843 }
844 
845 inline IRContext::Analysis& operator|=(IRContext::Analysis& lhs,
846                                        IRContext::Analysis rhs) {
847   lhs = static_cast<IRContext::Analysis>(static_cast<int>(lhs) |
848                                          static_cast<int>(rhs));
849   return lhs;
850 }
851 
852 inline IRContext::Analysis operator<<(IRContext::Analysis a, int shift) {
853   return static_cast<IRContext::Analysis>(static_cast<int>(a) << shift);
854 }
855 
856 inline IRContext::Analysis& operator<<=(IRContext::Analysis& a, int shift) {
857   a = static_cast<IRContext::Analysis>(static_cast<int>(a) << shift);
858   return a;
859 }
860 
GetConstants()861 std::vector<Instruction*> IRContext::GetConstants() {
862   return module()->GetConstants();
863 }
864 
GetConstants()865 std::vector<const Instruction*> IRContext::GetConstants() const {
866   return ((const Module*)module())->GetConstants();
867 }
868 
annotation_begin()869 Module::inst_iterator IRContext::annotation_begin() {
870   return module()->annotation_begin();
871 }
872 
annotation_end()873 Module::inst_iterator IRContext::annotation_end() {
874   return module()->annotation_end();
875 }
876 
annotations()877 IteratorRange<Module::inst_iterator> IRContext::annotations() {
878   return module_->annotations();
879 }
880 
annotations()881 IteratorRange<Module::const_inst_iterator> IRContext::annotations() const {
882   return ((const Module*)module_.get())->annotations();
883 }
884 
capability_begin()885 Module::inst_iterator IRContext::capability_begin() {
886   return module()->capability_begin();
887 }
888 
capability_end()889 Module::inst_iterator IRContext::capability_end() {
890   return module()->capability_end();
891 }
892 
capabilities()893 IteratorRange<Module::inst_iterator> IRContext::capabilities() {
894   return module()->capabilities();
895 }
896 
capabilities()897 IteratorRange<Module::const_inst_iterator> IRContext::capabilities() const {
898   return ((const Module*)module())->capabilities();
899 }
900 
types_values_begin()901 Module::inst_iterator IRContext::types_values_begin() {
902   return module()->types_values_begin();
903 }
904 
types_values_end()905 Module::inst_iterator IRContext::types_values_end() {
906   return module()->types_values_end();
907 }
908 
types_values()909 IteratorRange<Module::inst_iterator> IRContext::types_values() {
910   return module()->types_values();
911 }
912 
types_values()913 IteratorRange<Module::const_inst_iterator> IRContext::types_values() const {
914   return ((const Module*)module_.get())->types_values();
915 }
916 
ext_inst_import_begin()917 Module::inst_iterator IRContext::ext_inst_import_begin() {
918   return module()->ext_inst_import_begin();
919 }
920 
ext_inst_import_end()921 Module::inst_iterator IRContext::ext_inst_import_end() {
922   return module()->ext_inst_import_end();
923 }
924 
ext_inst_imports()925 IteratorRange<Module::inst_iterator> IRContext::ext_inst_imports() {
926   return module()->ext_inst_imports();
927 }
928 
ext_inst_imports()929 IteratorRange<Module::const_inst_iterator> IRContext::ext_inst_imports() const {
930   return ((const Module*)module_.get())->ext_inst_imports();
931 }
932 
debug1_begin()933 Module::inst_iterator IRContext::debug1_begin() {
934   return module()->debug1_begin();
935 }
936 
debug1_end()937 Module::inst_iterator IRContext::debug1_end() { return module()->debug1_end(); }
938 
debugs1()939 IteratorRange<Module::inst_iterator> IRContext::debugs1() {
940   return module()->debugs1();
941 }
942 
debugs1()943 IteratorRange<Module::const_inst_iterator> IRContext::debugs1() const {
944   return ((const Module*)module_.get())->debugs1();
945 }
946 
debug2_begin()947 Module::inst_iterator IRContext::debug2_begin() {
948   return module()->debug2_begin();
949 }
debug2_end()950 Module::inst_iterator IRContext::debug2_end() { return module()->debug2_end(); }
951 
debugs2()952 IteratorRange<Module::inst_iterator> IRContext::debugs2() {
953   return module()->debugs2();
954 }
955 
debugs2()956 IteratorRange<Module::const_inst_iterator> IRContext::debugs2() const {
957   return ((const Module*)module_.get())->debugs2();
958 }
959 
debug3_begin()960 Module::inst_iterator IRContext::debug3_begin() {
961   return module()->debug3_begin();
962 }
963 
debug3_end()964 Module::inst_iterator IRContext::debug3_end() { return module()->debug3_end(); }
965 
debugs3()966 IteratorRange<Module::inst_iterator> IRContext::debugs3() {
967   return module()->debugs3();
968 }
969 
debugs3()970 IteratorRange<Module::const_inst_iterator> IRContext::debugs3() const {
971   return ((const Module*)module_.get())->debugs3();
972 }
973 
ext_inst_debuginfo_begin()974 Module::inst_iterator IRContext::ext_inst_debuginfo_begin() {
975   return module()->ext_inst_debuginfo_begin();
976 }
977 
ext_inst_debuginfo_end()978 Module::inst_iterator IRContext::ext_inst_debuginfo_end() {
979   return module()->ext_inst_debuginfo_end();
980 }
981 
ext_inst_debuginfo()982 IteratorRange<Module::inst_iterator> IRContext::ext_inst_debuginfo() {
983   return module()->ext_inst_debuginfo();
984 }
985 
ext_inst_debuginfo()986 IteratorRange<Module::const_inst_iterator> IRContext::ext_inst_debuginfo()
987     const {
988   return ((const Module*)module_.get())->ext_inst_debuginfo();
989 }
990 
AddCapability(SpvCapability capability)991 void IRContext::AddCapability(SpvCapability capability) {
992   if (!get_feature_mgr()->HasCapability(capability)) {
993     std::unique_ptr<Instruction> capability_inst(new Instruction(
994         this, SpvOpCapability, 0, 0,
995         {{SPV_OPERAND_TYPE_CAPABILITY, {static_cast<uint32_t>(capability)}}}));
996     AddCapability(std::move(capability_inst));
997   }
998 }
999 
AddCapability(std::unique_ptr<Instruction> && c)1000 void IRContext::AddCapability(std::unique_ptr<Instruction>&& c) {
1001   AddCombinatorsForCapability(c->GetSingleWordInOperand(0));
1002   if (feature_mgr_ != nullptr) {
1003     feature_mgr_->AddCapability(
1004         static_cast<SpvCapability>(c->GetSingleWordInOperand(0)));
1005   }
1006   if (AreAnalysesValid(kAnalysisDefUse)) {
1007     get_def_use_mgr()->AnalyzeInstDefUse(c.get());
1008   }
1009   module()->AddCapability(std::move(c));
1010 }
1011 
AddExtension(const std::string & ext_name)1012 void IRContext::AddExtension(const std::string& ext_name) {
1013   const auto num_chars = ext_name.size();
1014   // Compute num words, accommodate the terminating null character.
1015   const auto num_words = (num_chars + 1 + 3) / 4;
1016   std::vector<uint32_t> ext_words(num_words, 0u);
1017   std::memcpy(ext_words.data(), ext_name.data(), num_chars);
1018   AddExtension(std::unique_ptr<Instruction>(
1019       new Instruction(this, SpvOpExtension, 0u, 0u,
1020                       {{SPV_OPERAND_TYPE_LITERAL_STRING, ext_words}})));
1021 }
1022 
AddExtension(std::unique_ptr<Instruction> && e)1023 void IRContext::AddExtension(std::unique_ptr<Instruction>&& e) {
1024   if (AreAnalysesValid(kAnalysisDefUse)) {
1025     get_def_use_mgr()->AnalyzeInstDefUse(e.get());
1026   }
1027   if (feature_mgr_ != nullptr) {
1028     feature_mgr_->AddExtension(&*e);
1029   }
1030   module()->AddExtension(std::move(e));
1031 }
1032 
AddExtInstImport(const std::string & name)1033 void IRContext::AddExtInstImport(const std::string& name) {
1034   const auto num_chars = name.size();
1035   // Compute num words, accommodate the terminating null character.
1036   const auto num_words = (num_chars + 1 + 3) / 4;
1037   std::vector<uint32_t> ext_words(num_words, 0u);
1038   std::memcpy(ext_words.data(), name.data(), num_chars);
1039   AddExtInstImport(std::unique_ptr<Instruction>(
1040       new Instruction(this, SpvOpExtInstImport, 0u, TakeNextId(),
1041                       {{SPV_OPERAND_TYPE_LITERAL_STRING, ext_words}})));
1042 }
1043 
AddExtInstImport(std::unique_ptr<Instruction> && e)1044 void IRContext::AddExtInstImport(std::unique_ptr<Instruction>&& e) {
1045   AddCombinatorsForExtension(e.get());
1046   if (AreAnalysesValid(kAnalysisDefUse)) {
1047     get_def_use_mgr()->AnalyzeInstDefUse(e.get());
1048   }
1049   module()->AddExtInstImport(std::move(e));
1050   if (feature_mgr_ != nullptr) {
1051     feature_mgr_->AddExtInstImportIds(module());
1052   }
1053 }
1054 
SetMemoryModel(std::unique_ptr<Instruction> && m)1055 void IRContext::SetMemoryModel(std::unique_ptr<Instruction>&& m) {
1056   module()->SetMemoryModel(std::move(m));
1057 }
1058 
AddEntryPoint(std::unique_ptr<Instruction> && e)1059 void IRContext::AddEntryPoint(std::unique_ptr<Instruction>&& e) {
1060   module()->AddEntryPoint(std::move(e));
1061 }
1062 
AddExecutionMode(std::unique_ptr<Instruction> && e)1063 void IRContext::AddExecutionMode(std::unique_ptr<Instruction>&& e) {
1064   module()->AddExecutionMode(std::move(e));
1065 }
1066 
AddDebug1Inst(std::unique_ptr<Instruction> && d)1067 void IRContext::AddDebug1Inst(std::unique_ptr<Instruction>&& d) {
1068   module()->AddDebug1Inst(std::move(d));
1069 }
1070 
AddDebug2Inst(std::unique_ptr<Instruction> && d)1071 void IRContext::AddDebug2Inst(std::unique_ptr<Instruction>&& d) {
1072   if (AreAnalysesValid(kAnalysisNameMap)) {
1073     if (d->opcode() == SpvOpName || d->opcode() == SpvOpMemberName) {
1074       // OpName and OpMemberName do not have result-ids. The target of the
1075       // instruction is at InOperand index 0.
1076       id_to_name_->insert({d->GetSingleWordInOperand(0), d.get()});
1077     }
1078   }
1079   module()->AddDebug2Inst(std::move(d));
1080 }
1081 
AddDebug3Inst(std::unique_ptr<Instruction> && d)1082 void IRContext::AddDebug3Inst(std::unique_ptr<Instruction>&& d) {
1083   module()->AddDebug3Inst(std::move(d));
1084 }
1085 
AddExtInstDebugInfo(std::unique_ptr<Instruction> && d)1086 void IRContext::AddExtInstDebugInfo(std::unique_ptr<Instruction>&& d) {
1087   module()->AddExtInstDebugInfo(std::move(d));
1088 }
1089 
AddAnnotationInst(std::unique_ptr<Instruction> && a)1090 void IRContext::AddAnnotationInst(std::unique_ptr<Instruction>&& a) {
1091   if (AreAnalysesValid(kAnalysisDecorations)) {
1092     get_decoration_mgr()->AddDecoration(a.get());
1093   }
1094   if (AreAnalysesValid(kAnalysisDefUse)) {
1095     get_def_use_mgr()->AnalyzeInstDefUse(a.get());
1096   }
1097   module()->AddAnnotationInst(std::move(a));
1098 }
1099 
AddType(std::unique_ptr<Instruction> && t)1100 void IRContext::AddType(std::unique_ptr<Instruction>&& t) {
1101   module()->AddType(std::move(t));
1102   if (AreAnalysesValid(kAnalysisDefUse)) {
1103     get_def_use_mgr()->AnalyzeInstDefUse(&*(--types_values_end()));
1104   }
1105 }
1106 
AddGlobalValue(std::unique_ptr<Instruction> && v)1107 void IRContext::AddGlobalValue(std::unique_ptr<Instruction>&& v) {
1108   if (AreAnalysesValid(kAnalysisDefUse)) {
1109     get_def_use_mgr()->AnalyzeInstDefUse(&*v);
1110   }
1111   module()->AddGlobalValue(std::move(v));
1112 }
1113 
AddFunction(std::unique_ptr<Function> && f)1114 void IRContext::AddFunction(std::unique_ptr<Function>&& f) {
1115   module()->AddFunction(std::move(f));
1116 }
1117 
AnalyzeDefUse(Instruction * inst)1118 void IRContext::AnalyzeDefUse(Instruction* inst) {
1119   if (AreAnalysesValid(kAnalysisDefUse)) {
1120     get_def_use_mgr()->AnalyzeInstDefUse(inst);
1121   }
1122 }
1123 
UpdateDefUse(Instruction * inst)1124 void IRContext::UpdateDefUse(Instruction* inst) {
1125   if (AreAnalysesValid(kAnalysisDefUse)) {
1126     get_def_use_mgr()->UpdateDefUse(inst);
1127   }
1128 }
1129 
BuildIdToNameMap()1130 void IRContext::BuildIdToNameMap() {
1131   id_to_name_ = MakeUnique<std::multimap<uint32_t, Instruction*>>();
1132   for (Instruction& debug_inst : debugs2()) {
1133     if (debug_inst.opcode() == SpvOpMemberName ||
1134         debug_inst.opcode() == SpvOpName) {
1135       id_to_name_->insert({debug_inst.GetSingleWordInOperand(0), &debug_inst});
1136     }
1137   }
1138   valid_analyses_ = valid_analyses_ | kAnalysisNameMap;
1139 }
1140 
1141 IteratorRange<std::multimap<uint32_t, Instruction*>::iterator>
GetNames(uint32_t id)1142 IRContext::GetNames(uint32_t id) {
1143   if (!AreAnalysesValid(kAnalysisNameMap)) {
1144     BuildIdToNameMap();
1145   }
1146   auto result = id_to_name_->equal_range(id);
1147   return make_range(std::move(result.first), std::move(result.second));
1148 }
1149 
GetMemberName(uint32_t struct_type_id,uint32_t index)1150 Instruction* IRContext::GetMemberName(uint32_t struct_type_id, uint32_t index) {
1151   if (!AreAnalysesValid(kAnalysisNameMap)) {
1152     BuildIdToNameMap();
1153   }
1154   auto result = id_to_name_->equal_range(struct_type_id);
1155   for (auto i = result.first; i != result.second; ++i) {
1156     auto* name_instr = i->second;
1157     if (name_instr->opcode() == SpvOpMemberName &&
1158         name_instr->GetSingleWordInOperand(1) == index) {
1159       return name_instr;
1160     }
1161   }
1162   return nullptr;
1163 }
1164 
1165 }  // namespace opt
1166 }  // namespace spvtools
1167 
1168 #endif  // SOURCE_OPT_IR_CONTEXT_H_
1169