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