• 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 #include "source/opt/ir_context.h"
16 
17 #include <cstring>
18 
19 #include "OpenCLDebugInfo100.h"
20 #include "source/latest_version_glsl_std_450_header.h"
21 #include "source/opt/log.h"
22 #include "source/opt/mem_pass.h"
23 #include "source/opt/reflect.h"
24 
25 namespace {
26 
27 static const int kSpvDecorateTargetIdInIdx = 0;
28 static const int kSpvDecorateDecorationInIdx = 1;
29 static const int kSpvDecorateBuiltinInIdx = 2;
30 static const int kEntryPointInterfaceInIdx = 3;
31 static const int kEntryPointFunctionIdInIdx = 1;
32 
33 // Constants for OpenCL.DebugInfo.100 extension instructions.
34 static const uint32_t kDebugFunctionOperandFunctionIndex = 13;
35 static const uint32_t kDebugGlobalVariableOperandVariableIndex = 11;
36 
37 }  // anonymous namespace
38 
39 namespace spvtools {
40 namespace opt {
41 
BuildInvalidAnalyses(IRContext::Analysis set)42 void IRContext::BuildInvalidAnalyses(IRContext::Analysis set) {
43   if (set & kAnalysisDefUse) {
44     BuildDefUseManager();
45   }
46   if (set & kAnalysisInstrToBlockMapping) {
47     BuildInstrToBlockMapping();
48   }
49   if (set & kAnalysisDecorations) {
50     BuildDecorationManager();
51   }
52   if (set & kAnalysisCFG) {
53     BuildCFG();
54   }
55   if (set & kAnalysisDominatorAnalysis) {
56     ResetDominatorAnalysis();
57   }
58   if (set & kAnalysisLoopAnalysis) {
59     ResetLoopAnalysis();
60   }
61   if (set & kAnalysisBuiltinVarId) {
62     ResetBuiltinAnalysis();
63   }
64   if (set & kAnalysisNameMap) {
65     BuildIdToNameMap();
66   }
67   if (set & kAnalysisScalarEvolution) {
68     BuildScalarEvolutionAnalysis();
69   }
70   if (set & kAnalysisRegisterPressure) {
71     BuildRegPressureAnalysis();
72   }
73   if (set & kAnalysisValueNumberTable) {
74     BuildValueNumberTable();
75   }
76   if (set & kAnalysisStructuredCFG) {
77     BuildStructuredCFGAnalysis();
78   }
79   if (set & kAnalysisIdToFuncMapping) {
80     BuildIdToFuncMapping();
81   }
82   if (set & kAnalysisConstants) {
83     BuildConstantManager();
84   }
85   if (set & kAnalysisTypes) {
86     BuildTypeManager();
87   }
88 }
89 
InvalidateAnalysesExceptFor(IRContext::Analysis preserved_analyses)90 void IRContext::InvalidateAnalysesExceptFor(
91     IRContext::Analysis preserved_analyses) {
92   uint32_t analyses_to_invalidate = valid_analyses_ & (~preserved_analyses);
93   InvalidateAnalyses(static_cast<IRContext::Analysis>(analyses_to_invalidate));
94 }
95 
InvalidateAnalyses(IRContext::Analysis analyses_to_invalidate)96 void IRContext::InvalidateAnalyses(IRContext::Analysis analyses_to_invalidate) {
97   // The ConstantManager contains Type pointers. If the TypeManager goes
98   // away, the ConstantManager has to go away.
99   if (analyses_to_invalidate & kAnalysisTypes) {
100     analyses_to_invalidate |= kAnalysisConstants;
101   }
102 
103   // The dominator analysis hold the psuedo entry and exit nodes from the CFG.
104   // Also if the CFG change the dominators many changed as well, so the
105   // dominator analysis should be invalidated as well.
106   if (analyses_to_invalidate & kAnalysisCFG) {
107     analyses_to_invalidate |= kAnalysisDominatorAnalysis;
108   }
109 
110   if (analyses_to_invalidate & kAnalysisDefUse) {
111     def_use_mgr_.reset(nullptr);
112   }
113   if (analyses_to_invalidate & kAnalysisInstrToBlockMapping) {
114     instr_to_block_.clear();
115   }
116   if (analyses_to_invalidate & kAnalysisDecorations) {
117     decoration_mgr_.reset(nullptr);
118   }
119   if (analyses_to_invalidate & kAnalysisCombinators) {
120     combinator_ops_.clear();
121   }
122   if (analyses_to_invalidate & kAnalysisBuiltinVarId) {
123     builtin_var_id_map_.clear();
124   }
125   if (analyses_to_invalidate & kAnalysisCFG) {
126     cfg_.reset(nullptr);
127   }
128   if (analyses_to_invalidate & kAnalysisDominatorAnalysis) {
129     dominator_trees_.clear();
130     post_dominator_trees_.clear();
131   }
132   if (analyses_to_invalidate & kAnalysisNameMap) {
133     id_to_name_.reset(nullptr);
134   }
135   if (analyses_to_invalidate & kAnalysisValueNumberTable) {
136     vn_table_.reset(nullptr);
137   }
138   if (analyses_to_invalidate & kAnalysisStructuredCFG) {
139     struct_cfg_analysis_.reset(nullptr);
140   }
141   if (analyses_to_invalidate & kAnalysisIdToFuncMapping) {
142     id_to_func_.clear();
143   }
144   if (analyses_to_invalidate & kAnalysisConstants) {
145     constant_mgr_.reset(nullptr);
146   }
147   if (analyses_to_invalidate & kAnalysisTypes) {
148     type_mgr_.reset(nullptr);
149   }
150 
151   valid_analyses_ = Analysis(valid_analyses_ & ~analyses_to_invalidate);
152 }
153 
KillInst(Instruction * inst)154 Instruction* IRContext::KillInst(Instruction* inst) {
155   if (!inst) {
156     return nullptr;
157   }
158 
159   KillNamesAndDecorates(inst);
160 
161   KillOperandFromDebugInstructions(inst);
162 
163   if (AreAnalysesValid(kAnalysisDefUse)) {
164     get_def_use_mgr()->ClearInst(inst);
165   }
166   if (AreAnalysesValid(kAnalysisInstrToBlockMapping)) {
167     instr_to_block_.erase(inst);
168   }
169   if (AreAnalysesValid(kAnalysisDecorations)) {
170     if (inst->IsDecoration()) {
171       decoration_mgr_->RemoveDecoration(inst);
172     }
173   }
174   if (type_mgr_ && IsTypeInst(inst->opcode())) {
175     type_mgr_->RemoveId(inst->result_id());
176   }
177   if (constant_mgr_ && IsConstantInst(inst->opcode())) {
178     constant_mgr_->RemoveId(inst->result_id());
179   }
180   if (inst->opcode() == SpvOpCapability || inst->opcode() == SpvOpExtension) {
181     // We reset the feature manager, instead of updating it, because it is just
182     // as much work.  We would have to remove all capabilities implied by this
183     // capability that are not also implied by the remaining OpCapability
184     // instructions. We could update extensions, but we will see if it is
185     // needed.
186     ResetFeatureManager();
187   }
188 
189   RemoveFromIdToName(inst);
190 
191   Instruction* next_instruction = nullptr;
192   if (inst->IsInAList()) {
193     next_instruction = inst->NextNode();
194     inst->RemoveFromList();
195     delete inst;
196   } else {
197     // Needed for instructions that are not part of a list like OpLabels,
198     // OpFunction, OpFunctionEnd, etc..
199     inst->ToNop();
200   }
201   return next_instruction;
202 }
203 
KillDef(uint32_t id)204 bool IRContext::KillDef(uint32_t id) {
205   Instruction* def = get_def_use_mgr()->GetDef(id);
206   if (def != nullptr) {
207     KillInst(def);
208     return true;
209   }
210   return false;
211 }
212 
ReplaceAllUsesWith(uint32_t before,uint32_t after)213 bool IRContext::ReplaceAllUsesWith(uint32_t before, uint32_t after) {
214   return ReplaceAllUsesWithPredicate(
215       before, after, [](Instruction*, uint32_t) { return true; });
216 }
217 
ReplaceAllUsesWithPredicate(uint32_t before,uint32_t after,const std::function<bool (Instruction *,uint32_t)> & predicate)218 bool IRContext::ReplaceAllUsesWithPredicate(
219     uint32_t before, uint32_t after,
220     const std::function<bool(Instruction*, uint32_t)>& predicate) {
221   if (before == after) return false;
222 
223   // Ensure that |after| has been registered as def.
224   assert(get_def_use_mgr()->GetDef(after) &&
225          "'after' is not a registered def.");
226 
227   std::vector<std::pair<Instruction*, uint32_t>> uses_to_update;
228   get_def_use_mgr()->ForEachUse(
229       before, [&predicate, &uses_to_update](Instruction* user, uint32_t index) {
230         if (predicate(user, index)) {
231           uses_to_update.emplace_back(user, index);
232         }
233       });
234 
235   Instruction* prev = nullptr;
236   for (auto p : uses_to_update) {
237     Instruction* user = p.first;
238     uint32_t index = p.second;
239     if (prev == nullptr || prev != user) {
240       ForgetUses(user);
241       prev = user;
242     }
243     const uint32_t type_result_id_count =
244         (user->result_id() != 0) + (user->type_id() != 0);
245 
246     if (index < type_result_id_count) {
247       // Update the type_id. Note that result id is immutable so it should
248       // never be updated.
249       if (user->type_id() != 0 && index == 0) {
250         user->SetResultType(after);
251       } else if (user->type_id() == 0) {
252         SPIRV_ASSERT(consumer_, false,
253                      "Result type id considered as use while the instruction "
254                      "doesn't have a result type id.");
255         (void)consumer_;  // Makes the compiler happy for release build.
256       } else {
257         SPIRV_ASSERT(consumer_, false,
258                      "Trying setting the immutable result id.");
259       }
260     } else {
261       // Update an in-operand.
262       uint32_t in_operand_pos = index - type_result_id_count;
263       // Make the modification in the instruction.
264       user->SetInOperand(in_operand_pos, {after});
265     }
266     AnalyzeUses(user);
267   }
268 
269   return true;
270 }
271 
IsConsistent()272 bool IRContext::IsConsistent() {
273 #ifndef SPIRV_CHECK_CONTEXT
274   return true;
275 #else
276   if (AreAnalysesValid(kAnalysisDefUse)) {
277     analysis::DefUseManager new_def_use(module());
278     if (*get_def_use_mgr() != new_def_use) {
279       return false;
280     }
281   }
282 
283   if (AreAnalysesValid(kAnalysisIdToFuncMapping)) {
284     for (auto& fn : *module_) {
285       if (id_to_func_[fn.result_id()] != &fn) {
286         return false;
287       }
288     }
289   }
290 
291   if (AreAnalysesValid(kAnalysisInstrToBlockMapping)) {
292     for (auto& func : *module()) {
293       for (auto& block : func) {
294         if (!block.WhileEachInst([this, &block](Instruction* inst) {
295               if (get_instr_block(inst) != &block) {
296                 return false;
297               }
298               return true;
299             }))
300           return false;
301       }
302     }
303   }
304 
305   if (!CheckCFG()) {
306     return false;
307   }
308 
309   if (AreAnalysesValid(kAnalysisDecorations)) {
310     analysis::DecorationManager* dec_mgr = get_decoration_mgr();
311     analysis::DecorationManager current(module());
312 
313     if (*dec_mgr != current) {
314       return false;
315     }
316   }
317 
318   if (feature_mgr_ != nullptr) {
319     FeatureManager current(grammar_);
320     current.Analyze(module());
321 
322     if (current != *feature_mgr_) {
323       return false;
324     }
325   }
326   return true;
327 #endif
328 }
329 
ForgetUses(Instruction * inst)330 void IRContext::ForgetUses(Instruction* inst) {
331   if (AreAnalysesValid(kAnalysisDefUse)) {
332     get_def_use_mgr()->EraseUseRecordsOfOperandIds(inst);
333   }
334   if (AreAnalysesValid(kAnalysisDecorations)) {
335     if (inst->IsDecoration()) {
336       get_decoration_mgr()->RemoveDecoration(inst);
337     }
338   }
339   RemoveFromIdToName(inst);
340 }
341 
AnalyzeUses(Instruction * inst)342 void IRContext::AnalyzeUses(Instruction* inst) {
343   if (AreAnalysesValid(kAnalysisDefUse)) {
344     get_def_use_mgr()->AnalyzeInstUse(inst);
345   }
346   if (AreAnalysesValid(kAnalysisDecorations)) {
347     if (inst->IsDecoration()) {
348       get_decoration_mgr()->AddDecoration(inst);
349     }
350   }
351   if (id_to_name_ &&
352       (inst->opcode() == SpvOpName || inst->opcode() == SpvOpMemberName)) {
353     id_to_name_->insert({inst->GetSingleWordInOperand(0), inst});
354   }
355 }
356 
KillNamesAndDecorates(uint32_t id)357 void IRContext::KillNamesAndDecorates(uint32_t id) {
358   analysis::DecorationManager* dec_mgr = get_decoration_mgr();
359   dec_mgr->RemoveDecorationsFrom(id);
360 
361   std::vector<Instruction*> name_to_kill;
362   for (auto name : GetNames(id)) {
363     name_to_kill.push_back(name.second);
364   }
365   for (Instruction* name_inst : name_to_kill) {
366     KillInst(name_inst);
367   }
368 }
369 
KillNamesAndDecorates(Instruction * inst)370 void IRContext::KillNamesAndDecorates(Instruction* inst) {
371   const uint32_t rId = inst->result_id();
372   if (rId == 0) return;
373   KillNamesAndDecorates(rId);
374 }
375 
GetOpenCL100DebugInfoNone()376 Instruction* IRContext::GetOpenCL100DebugInfoNone() {
377   if (debug_info_none_inst_) return debug_info_none_inst_;
378   assert(get_feature_mgr()->GetExtInstImportId_OpenCL100DebugInfo() &&
379          "Module does not include debug info extension instruction.");
380 
381   // Create a new DebugInfoNone.
382   std::unique_ptr<Instruction> dbg_info_none(new Instruction(
383       this, SpvOpExtInst, get_type_mgr()->GetVoidTypeId(), TakeNextId(),
384       {
385           {SPV_OPERAND_TYPE_RESULT_ID,
386            {get_feature_mgr()->GetExtInstImportId_OpenCL100DebugInfo()}},
387           {SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER,
388            {static_cast<uint32_t>(OpenCLDebugInfo100DebugInfoNone)}},
389       }));
390 
391   // Add to the front of |ext_inst_debuginfo_|.
392   debug_info_none_inst_ = module()->ext_inst_debuginfo_begin()->InsertBefore(
393       std::move(dbg_info_none));
394   return debug_info_none_inst_;
395 }
396 
KillOperandFromDebugInstructions(Instruction * inst)397 void IRContext::KillOperandFromDebugInstructions(Instruction* inst) {
398   const auto opcode = inst->opcode();
399   const uint32_t id = inst->result_id();
400   // Kill id of OpFunction from DebugFunction.
401   if (opcode == SpvOpFunction) {
402     for (auto it = module()->ext_inst_debuginfo_begin();
403          it != module()->ext_inst_debuginfo_end(); ++it) {
404       if (it->GetOpenCL100DebugOpcode() != OpenCLDebugInfo100DebugFunction)
405         continue;
406       auto& operand = it->GetOperand(kDebugFunctionOperandFunctionIndex);
407       if (operand.words[0] == id) {
408         operand.words[0] = GetOpenCL100DebugInfoNone()->result_id();
409       }
410     }
411   }
412   // Kill id of OpVariable for global variable from DebugGlobalVariable.
413   if (opcode == SpvOpVariable || IsConstantInst(opcode)) {
414     for (auto it = module()->ext_inst_debuginfo_begin();
415          it != module()->ext_inst_debuginfo_end(); ++it) {
416       if (it->GetOpenCL100DebugOpcode() !=
417           OpenCLDebugInfo100DebugGlobalVariable)
418         continue;
419       auto& operand = it->GetOperand(kDebugGlobalVariableOperandVariableIndex);
420       if (operand.words[0] == id) {
421         operand.words[0] = GetOpenCL100DebugInfoNone()->result_id();
422       }
423     }
424   }
425   // Notice that we do not need anythings to do for local variables.
426   // DebugLocalVariable does not have an OpVariable operand. Instead,
427   // DebugDeclare/DebugValue has an OpVariable operand for a local
428   // variable. The function inlining pass handles it properly.
429 }
430 
AddCombinatorsForCapability(uint32_t capability)431 void IRContext::AddCombinatorsForCapability(uint32_t capability) {
432   if (capability == SpvCapabilityShader) {
433     combinator_ops_[0].insert({SpvOpNop,
434                                SpvOpUndef,
435                                SpvOpConstant,
436                                SpvOpConstantTrue,
437                                SpvOpConstantFalse,
438                                SpvOpConstantComposite,
439                                SpvOpConstantSampler,
440                                SpvOpConstantNull,
441                                SpvOpTypeVoid,
442                                SpvOpTypeBool,
443                                SpvOpTypeInt,
444                                SpvOpTypeFloat,
445                                SpvOpTypeVector,
446                                SpvOpTypeMatrix,
447                                SpvOpTypeImage,
448                                SpvOpTypeSampler,
449                                SpvOpTypeSampledImage,
450                                SpvOpTypeAccelerationStructureNV,
451                                SpvOpTypeAccelerationStructureKHR,
452                                SpvOpTypeRayQueryProvisionalKHR,
453                                SpvOpTypeArray,
454                                SpvOpTypeRuntimeArray,
455                                SpvOpTypeStruct,
456                                SpvOpTypeOpaque,
457                                SpvOpTypePointer,
458                                SpvOpTypeFunction,
459                                SpvOpTypeEvent,
460                                SpvOpTypeDeviceEvent,
461                                SpvOpTypeReserveId,
462                                SpvOpTypeQueue,
463                                SpvOpTypePipe,
464                                SpvOpTypeForwardPointer,
465                                SpvOpVariable,
466                                SpvOpImageTexelPointer,
467                                SpvOpLoad,
468                                SpvOpAccessChain,
469                                SpvOpInBoundsAccessChain,
470                                SpvOpArrayLength,
471                                SpvOpVectorExtractDynamic,
472                                SpvOpVectorInsertDynamic,
473                                SpvOpVectorShuffle,
474                                SpvOpCompositeConstruct,
475                                SpvOpCompositeExtract,
476                                SpvOpCompositeInsert,
477                                SpvOpCopyObject,
478                                SpvOpTranspose,
479                                SpvOpSampledImage,
480                                SpvOpImageSampleImplicitLod,
481                                SpvOpImageSampleExplicitLod,
482                                SpvOpImageSampleDrefImplicitLod,
483                                SpvOpImageSampleDrefExplicitLod,
484                                SpvOpImageSampleProjImplicitLod,
485                                SpvOpImageSampleProjExplicitLod,
486                                SpvOpImageSampleProjDrefImplicitLod,
487                                SpvOpImageSampleProjDrefExplicitLod,
488                                SpvOpImageFetch,
489                                SpvOpImageGather,
490                                SpvOpImageDrefGather,
491                                SpvOpImageRead,
492                                SpvOpImage,
493                                SpvOpImageQueryFormat,
494                                SpvOpImageQueryOrder,
495                                SpvOpImageQuerySizeLod,
496                                SpvOpImageQuerySize,
497                                SpvOpImageQueryLevels,
498                                SpvOpImageQuerySamples,
499                                SpvOpConvertFToU,
500                                SpvOpConvertFToS,
501                                SpvOpConvertSToF,
502                                SpvOpConvertUToF,
503                                SpvOpUConvert,
504                                SpvOpSConvert,
505                                SpvOpFConvert,
506                                SpvOpQuantizeToF16,
507                                SpvOpBitcast,
508                                SpvOpSNegate,
509                                SpvOpFNegate,
510                                SpvOpIAdd,
511                                SpvOpFAdd,
512                                SpvOpISub,
513                                SpvOpFSub,
514                                SpvOpIMul,
515                                SpvOpFMul,
516                                SpvOpUDiv,
517                                SpvOpSDiv,
518                                SpvOpFDiv,
519                                SpvOpUMod,
520                                SpvOpSRem,
521                                SpvOpSMod,
522                                SpvOpFRem,
523                                SpvOpFMod,
524                                SpvOpVectorTimesScalar,
525                                SpvOpMatrixTimesScalar,
526                                SpvOpVectorTimesMatrix,
527                                SpvOpMatrixTimesVector,
528                                SpvOpMatrixTimesMatrix,
529                                SpvOpOuterProduct,
530                                SpvOpDot,
531                                SpvOpIAddCarry,
532                                SpvOpISubBorrow,
533                                SpvOpUMulExtended,
534                                SpvOpSMulExtended,
535                                SpvOpAny,
536                                SpvOpAll,
537                                SpvOpIsNan,
538                                SpvOpIsInf,
539                                SpvOpLogicalEqual,
540                                SpvOpLogicalNotEqual,
541                                SpvOpLogicalOr,
542                                SpvOpLogicalAnd,
543                                SpvOpLogicalNot,
544                                SpvOpSelect,
545                                SpvOpIEqual,
546                                SpvOpINotEqual,
547                                SpvOpUGreaterThan,
548                                SpvOpSGreaterThan,
549                                SpvOpUGreaterThanEqual,
550                                SpvOpSGreaterThanEqual,
551                                SpvOpULessThan,
552                                SpvOpSLessThan,
553                                SpvOpULessThanEqual,
554                                SpvOpSLessThanEqual,
555                                SpvOpFOrdEqual,
556                                SpvOpFUnordEqual,
557                                SpvOpFOrdNotEqual,
558                                SpvOpFUnordNotEqual,
559                                SpvOpFOrdLessThan,
560                                SpvOpFUnordLessThan,
561                                SpvOpFOrdGreaterThan,
562                                SpvOpFUnordGreaterThan,
563                                SpvOpFOrdLessThanEqual,
564                                SpvOpFUnordLessThanEqual,
565                                SpvOpFOrdGreaterThanEqual,
566                                SpvOpFUnordGreaterThanEqual,
567                                SpvOpShiftRightLogical,
568                                SpvOpShiftRightArithmetic,
569                                SpvOpShiftLeftLogical,
570                                SpvOpBitwiseOr,
571                                SpvOpBitwiseXor,
572                                SpvOpBitwiseAnd,
573                                SpvOpNot,
574                                SpvOpBitFieldInsert,
575                                SpvOpBitFieldSExtract,
576                                SpvOpBitFieldUExtract,
577                                SpvOpBitReverse,
578                                SpvOpBitCount,
579                                SpvOpPhi,
580                                SpvOpImageSparseSampleImplicitLod,
581                                SpvOpImageSparseSampleExplicitLod,
582                                SpvOpImageSparseSampleDrefImplicitLod,
583                                SpvOpImageSparseSampleDrefExplicitLod,
584                                SpvOpImageSparseSampleProjImplicitLod,
585                                SpvOpImageSparseSampleProjExplicitLod,
586                                SpvOpImageSparseSampleProjDrefImplicitLod,
587                                SpvOpImageSparseSampleProjDrefExplicitLod,
588                                SpvOpImageSparseFetch,
589                                SpvOpImageSparseGather,
590                                SpvOpImageSparseDrefGather,
591                                SpvOpImageSparseTexelsResident,
592                                SpvOpImageSparseRead,
593                                SpvOpSizeOf});
594   }
595 }
596 
AddCombinatorsForExtension(Instruction * extension)597 void IRContext::AddCombinatorsForExtension(Instruction* extension) {
598   assert(extension->opcode() == SpvOpExtInstImport &&
599          "Expecting an import of an extension's instruction set.");
600   const char* extension_name =
601       reinterpret_cast<const char*>(&extension->GetInOperand(0).words[0]);
602   if (!strcmp(extension_name, "GLSL.std.450")) {
603     combinator_ops_[extension->result_id()] = {GLSLstd450Round,
604                                                GLSLstd450RoundEven,
605                                                GLSLstd450Trunc,
606                                                GLSLstd450FAbs,
607                                                GLSLstd450SAbs,
608                                                GLSLstd450FSign,
609                                                GLSLstd450SSign,
610                                                GLSLstd450Floor,
611                                                GLSLstd450Ceil,
612                                                GLSLstd450Fract,
613                                                GLSLstd450Radians,
614                                                GLSLstd450Degrees,
615                                                GLSLstd450Sin,
616                                                GLSLstd450Cos,
617                                                GLSLstd450Tan,
618                                                GLSLstd450Asin,
619                                                GLSLstd450Acos,
620                                                GLSLstd450Atan,
621                                                GLSLstd450Sinh,
622                                                GLSLstd450Cosh,
623                                                GLSLstd450Tanh,
624                                                GLSLstd450Asinh,
625                                                GLSLstd450Acosh,
626                                                GLSLstd450Atanh,
627                                                GLSLstd450Atan2,
628                                                GLSLstd450Pow,
629                                                GLSLstd450Exp,
630                                                GLSLstd450Log,
631                                                GLSLstd450Exp2,
632                                                GLSLstd450Log2,
633                                                GLSLstd450Sqrt,
634                                                GLSLstd450InverseSqrt,
635                                                GLSLstd450Determinant,
636                                                GLSLstd450MatrixInverse,
637                                                GLSLstd450ModfStruct,
638                                                GLSLstd450FMin,
639                                                GLSLstd450UMin,
640                                                GLSLstd450SMin,
641                                                GLSLstd450FMax,
642                                                GLSLstd450UMax,
643                                                GLSLstd450SMax,
644                                                GLSLstd450FClamp,
645                                                GLSLstd450UClamp,
646                                                GLSLstd450SClamp,
647                                                GLSLstd450FMix,
648                                                GLSLstd450IMix,
649                                                GLSLstd450Step,
650                                                GLSLstd450SmoothStep,
651                                                GLSLstd450Fma,
652                                                GLSLstd450FrexpStruct,
653                                                GLSLstd450Ldexp,
654                                                GLSLstd450PackSnorm4x8,
655                                                GLSLstd450PackUnorm4x8,
656                                                GLSLstd450PackSnorm2x16,
657                                                GLSLstd450PackUnorm2x16,
658                                                GLSLstd450PackHalf2x16,
659                                                GLSLstd450PackDouble2x32,
660                                                GLSLstd450UnpackSnorm2x16,
661                                                GLSLstd450UnpackUnorm2x16,
662                                                GLSLstd450UnpackHalf2x16,
663                                                GLSLstd450UnpackSnorm4x8,
664                                                GLSLstd450UnpackUnorm4x8,
665                                                GLSLstd450UnpackDouble2x32,
666                                                GLSLstd450Length,
667                                                GLSLstd450Distance,
668                                                GLSLstd450Cross,
669                                                GLSLstd450Normalize,
670                                                GLSLstd450FaceForward,
671                                                GLSLstd450Reflect,
672                                                GLSLstd450Refract,
673                                                GLSLstd450FindILsb,
674                                                GLSLstd450FindSMsb,
675                                                GLSLstd450FindUMsb,
676                                                GLSLstd450InterpolateAtCentroid,
677                                                GLSLstd450InterpolateAtSample,
678                                                GLSLstd450InterpolateAtOffset,
679                                                GLSLstd450NMin,
680                                                GLSLstd450NMax,
681                                                GLSLstd450NClamp};
682   } else {
683     // Map the result id to the empty set.
684     combinator_ops_[extension->result_id()];
685   }
686 }
687 
InitializeCombinators()688 void IRContext::InitializeCombinators() {
689   get_feature_mgr()->GetCapabilities()->ForEach(
690       [this](SpvCapability cap) { AddCombinatorsForCapability(cap); });
691 
692   for (auto& extension : module()->ext_inst_imports()) {
693     AddCombinatorsForExtension(&extension);
694   }
695 
696   valid_analyses_ |= kAnalysisCombinators;
697 }
698 
RemoveFromIdToName(const Instruction * inst)699 void IRContext::RemoveFromIdToName(const Instruction* inst) {
700   if (id_to_name_ &&
701       (inst->opcode() == SpvOpName || inst->opcode() == SpvOpMemberName)) {
702     auto range = id_to_name_->equal_range(inst->GetSingleWordInOperand(0));
703     for (auto it = range.first; it != range.second; ++it) {
704       if (it->second == inst) {
705         id_to_name_->erase(it);
706         break;
707       }
708     }
709   }
710 }
711 
GetLoopDescriptor(const Function * f)712 LoopDescriptor* IRContext::GetLoopDescriptor(const Function* f) {
713   if (!AreAnalysesValid(kAnalysisLoopAnalysis)) {
714     ResetLoopAnalysis();
715   }
716 
717   std::unordered_map<const Function*, LoopDescriptor>::iterator it =
718       loop_descriptors_.find(f);
719   if (it == loop_descriptors_.end()) {
720     return &loop_descriptors_
721                 .emplace(std::make_pair(f, LoopDescriptor(this, f)))
722                 .first->second;
723   }
724 
725   return &it->second;
726 }
727 
FindBuiltinInputVar(uint32_t builtin)728 uint32_t IRContext::FindBuiltinInputVar(uint32_t builtin) {
729   for (auto& a : module_->annotations()) {
730     if (a.opcode() != SpvOpDecorate) continue;
731     if (a.GetSingleWordInOperand(kSpvDecorateDecorationInIdx) !=
732         SpvDecorationBuiltIn)
733       continue;
734     if (a.GetSingleWordInOperand(kSpvDecorateBuiltinInIdx) != builtin) continue;
735     uint32_t target_id = a.GetSingleWordInOperand(kSpvDecorateTargetIdInIdx);
736     Instruction* b_var = get_def_use_mgr()->GetDef(target_id);
737     if (b_var->opcode() != SpvOpVariable) continue;
738     if (b_var->GetSingleWordInOperand(0) != SpvStorageClassInput) continue;
739     return target_id;
740   }
741   return 0;
742 }
743 
AddVarToEntryPoints(uint32_t var_id)744 void IRContext::AddVarToEntryPoints(uint32_t var_id) {
745   uint32_t ocnt = 0;
746   for (auto& e : module()->entry_points()) {
747     bool found = false;
748     e.ForEachInOperand([&ocnt, &found, &var_id](const uint32_t* idp) {
749       if (ocnt >= kEntryPointInterfaceInIdx) {
750         if (*idp == var_id) found = true;
751       }
752       ++ocnt;
753     });
754     if (!found) {
755       e.AddOperand({SPV_OPERAND_TYPE_ID, {var_id}});
756       get_def_use_mgr()->AnalyzeInstDefUse(&e);
757     }
758   }
759 }
760 
GetBuiltinInputVarId(uint32_t builtin)761 uint32_t IRContext::GetBuiltinInputVarId(uint32_t builtin) {
762   if (!AreAnalysesValid(kAnalysisBuiltinVarId)) ResetBuiltinAnalysis();
763   // If cached, return it.
764   std::unordered_map<uint32_t, uint32_t>::iterator it =
765       builtin_var_id_map_.find(builtin);
766   if (it != builtin_var_id_map_.end()) return it->second;
767   // Look for one in shader
768   uint32_t var_id = FindBuiltinInputVar(builtin);
769   if (var_id == 0) {
770     // If not found, create it
771     // TODO(greg-lunarg): Add support for all builtins
772     analysis::TypeManager* type_mgr = get_type_mgr();
773     analysis::Type* reg_type;
774     switch (builtin) {
775       case SpvBuiltInFragCoord: {
776         analysis::Float float_ty(32);
777         analysis::Type* reg_float_ty = type_mgr->GetRegisteredType(&float_ty);
778         analysis::Vector v4float_ty(reg_float_ty, 4);
779         reg_type = type_mgr->GetRegisteredType(&v4float_ty);
780         break;
781       }
782       case SpvBuiltInVertexIndex:
783       case SpvBuiltInInstanceIndex:
784       case SpvBuiltInPrimitiveId:
785       case SpvBuiltInInvocationId:
786       case SpvBuiltInSubgroupLocalInvocationId: {
787         analysis::Integer uint_ty(32, false);
788         reg_type = type_mgr->GetRegisteredType(&uint_ty);
789         break;
790       }
791       case SpvBuiltInGlobalInvocationId:
792       case SpvBuiltInLaunchIdNV: {
793         analysis::Integer uint_ty(32, false);
794         analysis::Type* reg_uint_ty = type_mgr->GetRegisteredType(&uint_ty);
795         analysis::Vector v3uint_ty(reg_uint_ty, 3);
796         reg_type = type_mgr->GetRegisteredType(&v3uint_ty);
797         break;
798       }
799       case SpvBuiltInTessCoord: {
800         analysis::Float float_ty(32);
801         analysis::Type* reg_float_ty = type_mgr->GetRegisteredType(&float_ty);
802         analysis::Vector v3float_ty(reg_float_ty, 3);
803         reg_type = type_mgr->GetRegisteredType(&v3float_ty);
804         break;
805       }
806       case SpvBuiltInSubgroupLtMask: {
807         analysis::Integer uint_ty(32, false);
808         analysis::Type* reg_uint_ty = type_mgr->GetRegisteredType(&uint_ty);
809         analysis::Vector v4uint_ty(reg_uint_ty, 4);
810         reg_type = type_mgr->GetRegisteredType(&v4uint_ty);
811         break;
812       }
813       default: {
814         assert(false && "unhandled builtin");
815         return 0;
816       }
817     }
818     uint32_t type_id = type_mgr->GetTypeInstruction(reg_type);
819     uint32_t varTyPtrId =
820         type_mgr->FindPointerToType(type_id, SpvStorageClassInput);
821     // TODO(1841): Handle id overflow.
822     var_id = TakeNextId();
823     std::unique_ptr<Instruction> newVarOp(
824         new Instruction(this, SpvOpVariable, varTyPtrId, var_id,
825                         {{spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER,
826                           {SpvStorageClassInput}}}));
827     get_def_use_mgr()->AnalyzeInstDefUse(&*newVarOp);
828     module()->AddGlobalValue(std::move(newVarOp));
829     get_decoration_mgr()->AddDecorationVal(var_id, SpvDecorationBuiltIn,
830                                            builtin);
831     AddVarToEntryPoints(var_id);
832   }
833   builtin_var_id_map_[builtin] = var_id;
834   return var_id;
835 }
836 
AddCalls(const Function * func,std::queue<uint32_t> * todo)837 void IRContext::AddCalls(const Function* func, std::queue<uint32_t>* todo) {
838   for (auto bi = func->begin(); bi != func->end(); ++bi)
839     for (auto ii = bi->begin(); ii != bi->end(); ++ii)
840       if (ii->opcode() == SpvOpFunctionCall)
841         todo->push(ii->GetSingleWordInOperand(0));
842 }
843 
ProcessEntryPointCallTree(ProcessFunction & pfn)844 bool IRContext::ProcessEntryPointCallTree(ProcessFunction& pfn) {
845   // Collect all of the entry points as the roots.
846   std::queue<uint32_t> roots;
847   for (auto& e : module()->entry_points()) {
848     roots.push(e.GetSingleWordInOperand(kEntryPointFunctionIdInIdx));
849   }
850   return ProcessCallTreeFromRoots(pfn, &roots);
851 }
852 
ProcessReachableCallTree(ProcessFunction & pfn)853 bool IRContext::ProcessReachableCallTree(ProcessFunction& pfn) {
854   std::queue<uint32_t> roots;
855 
856   // Add all entry points since they can be reached from outside the module.
857   for (auto& e : module()->entry_points())
858     roots.push(e.GetSingleWordInOperand(kEntryPointFunctionIdInIdx));
859 
860   // Add all exported functions since they can be reached from outside the
861   // module.
862   for (auto& a : annotations()) {
863     // TODO: Handle group decorations as well.  Currently not generate by any
864     // front-end, but could be coming.
865     if (a.opcode() == SpvOp::SpvOpDecorate) {
866       if (a.GetSingleWordOperand(1) ==
867           SpvDecoration::SpvDecorationLinkageAttributes) {
868         uint32_t lastOperand = a.NumOperands() - 1;
869         if (a.GetSingleWordOperand(lastOperand) ==
870             SpvLinkageType::SpvLinkageTypeExport) {
871           uint32_t id = a.GetSingleWordOperand(0);
872           if (GetFunction(id)) {
873             roots.push(id);
874           }
875         }
876       }
877     }
878   }
879 
880   return ProcessCallTreeFromRoots(pfn, &roots);
881 }
882 
ProcessCallTreeFromRoots(ProcessFunction & pfn,std::queue<uint32_t> * roots)883 bool IRContext::ProcessCallTreeFromRoots(ProcessFunction& pfn,
884                                          std::queue<uint32_t>* roots) {
885   // Process call tree
886   bool modified = false;
887   std::unordered_set<uint32_t> done;
888 
889   while (!roots->empty()) {
890     const uint32_t fi = roots->front();
891     roots->pop();
892     if (done.insert(fi).second) {
893       Function* fn = GetFunction(fi);
894       assert(fn && "Trying to process a function that does not exist.");
895       modified = pfn(fn) || modified;
896       AddCalls(fn, roots);
897     }
898   }
899   return modified;
900 }
901 
EmitErrorMessage(std::string message,Instruction * inst)902 void IRContext::EmitErrorMessage(std::string message, Instruction* inst) {
903   if (!consumer()) {
904     return;
905   }
906 
907   Instruction* line_inst = inst;
908   while (line_inst != nullptr) {  // Stop at the beginning of the basic block.
909     if (!line_inst->dbg_line_insts().empty()) {
910       line_inst = &line_inst->dbg_line_insts().back();
911       if (line_inst->opcode() == SpvOpNoLine) {
912         line_inst = nullptr;
913       }
914       break;
915     }
916     line_inst = line_inst->PreviousNode();
917   }
918 
919   uint32_t line_number = 0;
920   uint32_t col_number = 0;
921   char* source = nullptr;
922   if (line_inst != nullptr) {
923     Instruction* file_name =
924         get_def_use_mgr()->GetDef(line_inst->GetSingleWordInOperand(0));
925     source = reinterpret_cast<char*>(&file_name->GetInOperand(0).words[0]);
926 
927     // Get the line number and column number.
928     line_number = line_inst->GetSingleWordInOperand(1);
929     col_number = line_inst->GetSingleWordInOperand(2);
930   }
931 
932   message +=
933       "\n  " + inst->PrettyPrint(SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES);
934   consumer()(SPV_MSG_ERROR, source, {line_number, col_number, 0},
935              message.c_str());
936 }
937 
938 // Gets the dominator analysis for function |f|.
GetDominatorAnalysis(const Function * f)939 DominatorAnalysis* IRContext::GetDominatorAnalysis(const Function* f) {
940   if (!AreAnalysesValid(kAnalysisDominatorAnalysis)) {
941     ResetDominatorAnalysis();
942   }
943 
944   if (dominator_trees_.find(f) == dominator_trees_.end()) {
945     dominator_trees_[f].InitializeTree(*cfg(), f);
946   }
947 
948   return &dominator_trees_[f];
949 }
950 
951 // Gets the postdominator analysis for function |f|.
GetPostDominatorAnalysis(const Function * f)952 PostDominatorAnalysis* IRContext::GetPostDominatorAnalysis(const Function* f) {
953   if (!AreAnalysesValid(kAnalysisDominatorAnalysis)) {
954     ResetDominatorAnalysis();
955   }
956 
957   if (post_dominator_trees_.find(f) == post_dominator_trees_.end()) {
958     post_dominator_trees_[f].InitializeTree(*cfg(), f);
959   }
960 
961   return &post_dominator_trees_[f];
962 }
963 
CheckCFG()964 bool IRContext::CheckCFG() {
965   std::unordered_map<uint32_t, std::vector<uint32_t>> real_preds;
966   if (!AreAnalysesValid(kAnalysisCFG)) {
967     return true;
968   }
969 
970   for (Function& function : *module()) {
971     for (const auto& bb : function) {
972       bb.ForEachSuccessorLabel([&bb, &real_preds](const uint32_t lab_id) {
973         real_preds[lab_id].push_back(bb.id());
974       });
975     }
976 
977     for (auto& bb : function) {
978       std::vector<uint32_t> preds = cfg()->preds(bb.id());
979       std::vector<uint32_t> real = real_preds[bb.id()];
980       std::sort(preds.begin(), preds.end());
981       std::sort(real.begin(), real.end());
982 
983       bool same = true;
984       if (preds.size() != real.size()) {
985         same = false;
986       }
987 
988       for (size_t i = 0; i < real.size() && same; i++) {
989         if (preds[i] != real[i]) {
990           same = false;
991         }
992       }
993 
994       if (!same) {
995         std::cerr << "Predecessors for " << bb.id() << " are different:\n";
996 
997         std::cerr << "Real:";
998         for (uint32_t i : real) {
999           std::cerr << ' ' << i;
1000         }
1001         std::cerr << std::endl;
1002 
1003         std::cerr << "Recorded:";
1004         for (uint32_t i : preds) {
1005           std::cerr << ' ' << i;
1006         }
1007         std::cerr << std::endl;
1008       }
1009       if (!same) return false;
1010     }
1011   }
1012 
1013   return true;
1014 }
1015 }  // namespace opt
1016 }  // namespace spvtools
1017