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