ir_context.cpp 37 KB

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