ir_context_test.cpp 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154
  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 <algorithm>
  16. #include <memory>
  17. #include <string>
  18. #include <utility>
  19. #include "OpenCLDebugInfo100.h"
  20. #include "gmock/gmock.h"
  21. #include "gtest/gtest.h"
  22. #include "source/opt/pass.h"
  23. #include "test/opt/pass_fixture.h"
  24. #include "test/opt/pass_utils.h"
  25. static const uint32_t kDebugDeclareOperandVariableIndex = 5;
  26. static const uint32_t kDebugValueOperandValueIndex = 5;
  27. namespace spvtools {
  28. namespace opt {
  29. namespace {
  30. using Analysis = IRContext::Analysis;
  31. using ::testing::Each;
  32. using ::testing::UnorderedElementsAre;
  33. class NoopPassPreservesNothing : public Pass {
  34. public:
  35. NoopPassPreservesNothing(Status s) : Pass(), status_to_return_(s) {}
  36. const char* name() const override { return "noop-pass"; }
  37. Status Process() override { return status_to_return_; }
  38. private:
  39. Status status_to_return_;
  40. };
  41. class NoopPassPreservesAll : public Pass {
  42. public:
  43. NoopPassPreservesAll(Status s) : Pass(), status_to_return_(s) {}
  44. const char* name() const override { return "noop-pass"; }
  45. Status Process() override { return status_to_return_; }
  46. Analysis GetPreservedAnalyses() override {
  47. return Analysis(IRContext::kAnalysisEnd - 1);
  48. }
  49. private:
  50. Status status_to_return_;
  51. };
  52. class NoopPassPreservesFirst : public Pass {
  53. public:
  54. NoopPassPreservesFirst(Status s) : Pass(), status_to_return_(s) {}
  55. const char* name() const override { return "noop-pass"; }
  56. Status Process() override { return status_to_return_; }
  57. Analysis GetPreservedAnalyses() override { return IRContext::kAnalysisBegin; }
  58. private:
  59. Status status_to_return_;
  60. };
  61. using IRContextTest = PassTest<::testing::Test>;
  62. TEST_F(IRContextTest, IndividualValidAfterBuild) {
  63. std::unique_ptr<Module> module(new Module());
  64. IRContext localContext(SPV_ENV_UNIVERSAL_1_2, std::move(module),
  65. spvtools::MessageConsumer());
  66. for (Analysis i = IRContext::kAnalysisBegin; i < IRContext::kAnalysisEnd;
  67. i <<= 1) {
  68. localContext.BuildInvalidAnalyses(i);
  69. EXPECT_TRUE(localContext.AreAnalysesValid(i));
  70. }
  71. }
  72. TEST_F(IRContextTest, DontRebuildValidAnalysis) {
  73. std::unique_ptr<Module> module(new Module());
  74. IRContext localContext(SPV_ENV_UNIVERSAL_1_2, std::move(module),
  75. spvtools::MessageConsumer());
  76. auto* oldCfg = localContext.cfg();
  77. auto* oldDefUse = localContext.get_def_use_mgr();
  78. localContext.BuildInvalidAnalyses(IRContext::kAnalysisCFG |
  79. IRContext::kAnalysisDefUse);
  80. auto* newCfg = localContext.cfg();
  81. auto* newDefUse = localContext.get_def_use_mgr();
  82. EXPECT_EQ(oldCfg, newCfg);
  83. EXPECT_EQ(oldDefUse, newDefUse);
  84. }
  85. TEST_F(IRContextTest, AllValidAfterBuild) {
  86. std::unique_ptr<Module> module = MakeUnique<Module>();
  87. IRContext localContext(SPV_ENV_UNIVERSAL_1_2, std::move(module),
  88. spvtools::MessageConsumer());
  89. Analysis built_analyses = IRContext::kAnalysisNone;
  90. for (Analysis i = IRContext::kAnalysisBegin; i < IRContext::kAnalysisEnd;
  91. i <<= 1) {
  92. localContext.BuildInvalidAnalyses(i);
  93. built_analyses |= i;
  94. }
  95. EXPECT_TRUE(localContext.AreAnalysesValid(built_analyses));
  96. }
  97. TEST_F(IRContextTest, AllValidAfterPassNoChange) {
  98. std::unique_ptr<Module> module = MakeUnique<Module>();
  99. IRContext localContext(SPV_ENV_UNIVERSAL_1_2, std::move(module),
  100. spvtools::MessageConsumer());
  101. Analysis built_analyses = IRContext::kAnalysisNone;
  102. for (Analysis i = IRContext::kAnalysisBegin; i < IRContext::kAnalysisEnd;
  103. i <<= 1) {
  104. localContext.BuildInvalidAnalyses(i);
  105. built_analyses |= i;
  106. }
  107. NoopPassPreservesNothing pass(Pass::Status::SuccessWithoutChange);
  108. Pass::Status s = pass.Run(&localContext);
  109. EXPECT_EQ(s, Pass::Status::SuccessWithoutChange);
  110. EXPECT_TRUE(localContext.AreAnalysesValid(built_analyses));
  111. }
  112. TEST_F(IRContextTest, NoneValidAfterPassWithChange) {
  113. std::unique_ptr<Module> module = MakeUnique<Module>();
  114. IRContext localContext(SPV_ENV_UNIVERSAL_1_2, std::move(module),
  115. spvtools::MessageConsumer());
  116. for (Analysis i = IRContext::kAnalysisBegin; i < IRContext::kAnalysisEnd;
  117. i <<= 1) {
  118. localContext.BuildInvalidAnalyses(i);
  119. }
  120. NoopPassPreservesNothing pass(Pass::Status::SuccessWithChange);
  121. Pass::Status s = pass.Run(&localContext);
  122. EXPECT_EQ(s, Pass::Status::SuccessWithChange);
  123. for (Analysis i = IRContext::kAnalysisBegin; i < IRContext::kAnalysisEnd;
  124. i <<= 1) {
  125. EXPECT_FALSE(localContext.AreAnalysesValid(i));
  126. }
  127. }
  128. TEST_F(IRContextTest, AllPreservedAfterPassWithChange) {
  129. std::unique_ptr<Module> module = MakeUnique<Module>();
  130. IRContext localContext(SPV_ENV_UNIVERSAL_1_2, std::move(module),
  131. spvtools::MessageConsumer());
  132. for (Analysis i = IRContext::kAnalysisBegin; i < IRContext::kAnalysisEnd;
  133. i <<= 1) {
  134. localContext.BuildInvalidAnalyses(i);
  135. }
  136. NoopPassPreservesAll pass(Pass::Status::SuccessWithChange);
  137. Pass::Status s = pass.Run(&localContext);
  138. EXPECT_EQ(s, Pass::Status::SuccessWithChange);
  139. for (Analysis i = IRContext::kAnalysisBegin; i < IRContext::kAnalysisEnd;
  140. i <<= 1) {
  141. EXPECT_TRUE(localContext.AreAnalysesValid(i));
  142. }
  143. }
  144. TEST_F(IRContextTest, PreserveFirstOnlyAfterPassWithChange) {
  145. std::unique_ptr<Module> module = MakeUnique<Module>();
  146. IRContext localContext(SPV_ENV_UNIVERSAL_1_2, std::move(module),
  147. spvtools::MessageConsumer());
  148. for (Analysis i = IRContext::kAnalysisBegin; i < IRContext::kAnalysisEnd;
  149. i <<= 1) {
  150. localContext.BuildInvalidAnalyses(i);
  151. }
  152. NoopPassPreservesFirst pass(Pass::Status::SuccessWithChange);
  153. Pass::Status s = pass.Run(&localContext);
  154. EXPECT_EQ(s, Pass::Status::SuccessWithChange);
  155. EXPECT_TRUE(localContext.AreAnalysesValid(IRContext::kAnalysisBegin));
  156. for (Analysis i = IRContext::kAnalysisBegin << 1; i < IRContext::kAnalysisEnd;
  157. i <<= 1) {
  158. EXPECT_FALSE(localContext.AreAnalysesValid(i));
  159. }
  160. }
  161. TEST_F(IRContextTest, KillMemberName) {
  162. const std::string text = R"(
  163. OpCapability Shader
  164. %1 = OpExtInstImport "GLSL.std.450"
  165. OpMemoryModel Logical GLSL450
  166. OpEntryPoint Fragment %2 "main"
  167. OpExecutionMode %2 OriginUpperLeft
  168. OpSource GLSL 430
  169. OpName %3 "stuff"
  170. OpMemberName %3 0 "refZ"
  171. OpMemberDecorate %3 0 Offset 0
  172. OpDecorate %3 Block
  173. %4 = OpTypeFloat 32
  174. %3 = OpTypeStruct %4
  175. %5 = OpTypeVoid
  176. %6 = OpTypeFunction %5
  177. %2 = OpFunction %5 None %6
  178. %7 = OpLabel
  179. OpReturn
  180. OpFunctionEnd
  181. )";
  182. std::unique_ptr<IRContext> context =
  183. BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
  184. // Build the decoration manager.
  185. context->get_decoration_mgr();
  186. // Delete the OpTypeStruct. Should delete the OpName, OpMemberName, and
  187. // OpMemberDecorate associated with it.
  188. context->KillDef(3);
  189. // Make sure all of the name are removed.
  190. for (auto& inst : context->debugs2()) {
  191. EXPECT_EQ(inst.opcode(), spv::Op::OpNop);
  192. }
  193. // Make sure all of the decorations are removed.
  194. for (auto& inst : context->annotations()) {
  195. EXPECT_EQ(inst.opcode(), spv::Op::OpNop);
  196. }
  197. }
  198. TEST_F(IRContextTest, KillGroupDecoration) {
  199. const std::string text = R"(
  200. OpCapability Shader
  201. %1 = OpExtInstImport "GLSL.std.450"
  202. OpMemoryModel Logical GLSL450
  203. OpEntryPoint Fragment %2 "main"
  204. OpExecutionMode %2 OriginUpperLeft
  205. OpSource GLSL 430
  206. OpDecorate %3 Restrict
  207. %3 = OpDecorationGroup
  208. OpGroupDecorate %3 %4 %5
  209. %6 = OpTypeFloat 32
  210. %7 = OpTypePointer Function %6
  211. %8 = OpTypeStruct %6
  212. %9 = OpTypeVoid
  213. %10 = OpTypeFunction %9
  214. %2 = OpFunction %9 None %10
  215. %11 = OpLabel
  216. %4 = OpVariable %7 Function
  217. %5 = OpVariable %7 Function
  218. OpReturn
  219. OpFunctionEnd
  220. )";
  221. std::unique_ptr<IRContext> context =
  222. BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
  223. // Build the decoration manager.
  224. context->get_decoration_mgr();
  225. // Delete the second variable.
  226. context->KillDef(5);
  227. // The three decorations instructions should still be there. The first two
  228. // should be the same, but the third should have %5 removed.
  229. // Check the OpDecorate instruction
  230. auto inst = context->annotation_begin();
  231. EXPECT_EQ(inst->opcode(), spv::Op::OpDecorate);
  232. EXPECT_EQ(inst->GetSingleWordInOperand(0), 3);
  233. // Check the OpDecorationGroup Instruction
  234. ++inst;
  235. EXPECT_EQ(inst->opcode(), spv::Op::OpDecorationGroup);
  236. EXPECT_EQ(inst->result_id(), 3);
  237. // Check that %5 is no longer part of the group.
  238. ++inst;
  239. EXPECT_EQ(inst->opcode(), spv::Op::OpGroupDecorate);
  240. EXPECT_EQ(inst->NumInOperands(), 2);
  241. EXPECT_EQ(inst->GetSingleWordInOperand(0), 3);
  242. EXPECT_EQ(inst->GetSingleWordInOperand(1), 4);
  243. // Check that we are at the end.
  244. ++inst;
  245. EXPECT_EQ(inst, context->annotation_end());
  246. }
  247. TEST_F(IRContextTest, TakeNextUniqueIdIncrementing) {
  248. const uint32_t NUM_TESTS = 1000;
  249. IRContext localContext(SPV_ENV_UNIVERSAL_1_2, nullptr);
  250. for (uint32_t i = 1; i < NUM_TESTS; ++i)
  251. EXPECT_EQ(i, localContext.TakeNextUniqueId());
  252. }
  253. TEST_F(IRContextTest, KillGroupDecorationWitNoDecorations) {
  254. const std::string text = R"(
  255. OpCapability Shader
  256. %1 = OpExtInstImport "GLSL.std.450"
  257. OpMemoryModel Logical GLSL450
  258. OpEntryPoint Fragment %2 "main"
  259. OpExecutionMode %2 OriginUpperLeft
  260. OpSource GLSL 430
  261. %3 = OpDecorationGroup
  262. OpGroupDecorate %3 %4 %5
  263. %6 = OpTypeFloat 32
  264. %7 = OpTypePointer Function %6
  265. %8 = OpTypeStruct %6
  266. %9 = OpTypeVoid
  267. %10 = OpTypeFunction %9
  268. %2 = OpFunction %9 None %10
  269. %11 = OpLabel
  270. %4 = OpVariable %7 Function
  271. %5 = OpVariable %7 Function
  272. OpReturn
  273. OpFunctionEnd
  274. )";
  275. std::unique_ptr<IRContext> context =
  276. BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
  277. // Build the decoration manager.
  278. context->get_decoration_mgr();
  279. // Delete the second variable.
  280. context->KillDef(5);
  281. // The two decoration instructions should still be there. The first one
  282. // should be the same, but the second should have %5 removed.
  283. // Check the OpDecorationGroup Instruction
  284. auto inst = context->annotation_begin();
  285. EXPECT_EQ(inst->opcode(), spv::Op::OpDecorationGroup);
  286. EXPECT_EQ(inst->result_id(), 3);
  287. // Check that %5 is no longer part of the group.
  288. ++inst;
  289. EXPECT_EQ(inst->opcode(), spv::Op::OpGroupDecorate);
  290. EXPECT_EQ(inst->NumInOperands(), 2);
  291. EXPECT_EQ(inst->GetSingleWordInOperand(0), 3);
  292. EXPECT_EQ(inst->GetSingleWordInOperand(1), 4);
  293. // Check that we are at the end.
  294. ++inst;
  295. EXPECT_EQ(inst, context->annotation_end());
  296. }
  297. TEST_F(IRContextTest, KillDecorationGroup) {
  298. const std::string text = R"(
  299. OpCapability Shader
  300. %1 = OpExtInstImport "GLSL.std.450"
  301. OpMemoryModel Logical GLSL450
  302. OpEntryPoint Fragment %2 "main"
  303. OpExecutionMode %2 OriginUpperLeft
  304. OpSource GLSL 430
  305. %3 = OpDecorationGroup
  306. OpGroupDecorate %3 %4 %5
  307. %6 = OpTypeFloat 32
  308. %7 = OpTypePointer Function %6
  309. %8 = OpTypeStruct %6
  310. %9 = OpTypeVoid
  311. %10 = OpTypeFunction %9
  312. %2 = OpFunction %9 None %10
  313. %11 = OpLabel
  314. %4 = OpVariable %7 Function
  315. %5 = OpVariable %7 Function
  316. OpReturn
  317. OpFunctionEnd
  318. )";
  319. std::unique_ptr<IRContext> context =
  320. BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
  321. // Build the decoration manager.
  322. context->get_decoration_mgr();
  323. // Delete the second variable.
  324. context->KillDef(3);
  325. // Check the OpDecorationGroup Instruction is still there.
  326. EXPECT_TRUE(context->annotations().empty());
  327. }
  328. TEST_F(IRContextTest, KillFunctionFromDebugFunction) {
  329. const std::string text = R"(
  330. OpCapability Shader
  331. %1 = OpExtInstImport "OpenCL.DebugInfo.100"
  332. OpMemoryModel Logical GLSL450
  333. OpEntryPoint Fragment %2 "main"
  334. OpExecutionMode %2 OriginUpperLeft
  335. %3 = OpString "ps.hlsl"
  336. %4 = OpString "foo"
  337. OpSource HLSL 600
  338. %void = OpTypeVoid
  339. %6 = OpTypeFunction %void
  340. %7 = OpExtInst %void %1 DebugSource %3
  341. %8 = OpExtInst %void %1 DebugCompilationUnit 1 4 %7 HLSL
  342. %9 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %void
  343. %10 = OpExtInst %void %1 DebugFunction %4 %9 %7 1 1 %8 %4 FlagIsProtected|FlagIsPrivate 1 %11
  344. %2 = OpFunction %void None %6
  345. %12 = OpLabel
  346. OpReturn
  347. OpFunctionEnd
  348. %11 = OpFunction %void None %6
  349. %13 = OpLabel
  350. OpReturn
  351. OpFunctionEnd
  352. )";
  353. std::unique_ptr<IRContext> context =
  354. BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
  355. // Delete the second variable.
  356. context->KillDef(11);
  357. // Get DebugInfoNone id.
  358. uint32_t debug_info_none_id = 0;
  359. for (auto it = context->ext_inst_debuginfo_begin();
  360. it != context->ext_inst_debuginfo_end(); ++it) {
  361. if (it->GetOpenCL100DebugOpcode() == OpenCLDebugInfo100DebugInfoNone) {
  362. debug_info_none_id = it->result_id();
  363. }
  364. }
  365. EXPECT_NE(0, debug_info_none_id);
  366. // Check the Function operand of DebugFunction is DebugInfoNone.
  367. const uint32_t kDebugFunctionOperandFunctionIndex = 13;
  368. bool checked = false;
  369. for (auto it = context->ext_inst_debuginfo_begin();
  370. it != context->ext_inst_debuginfo_end(); ++it) {
  371. if (it->GetOpenCL100DebugOpcode() == OpenCLDebugInfo100DebugFunction) {
  372. EXPECT_FALSE(checked);
  373. EXPECT_EQ(it->GetOperand(kDebugFunctionOperandFunctionIndex).words[0],
  374. debug_info_none_id);
  375. checked = true;
  376. }
  377. }
  378. EXPECT_TRUE(checked);
  379. }
  380. TEST_F(IRContextTest, KillVariableFromDebugGlobalVariable) {
  381. const std::string text = R"(
  382. OpCapability Shader
  383. %1 = OpExtInstImport "OpenCL.DebugInfo.100"
  384. OpMemoryModel Logical GLSL450
  385. OpEntryPoint Fragment %2 "main"
  386. OpExecutionMode %2 OriginUpperLeft
  387. %3 = OpString "ps.hlsl"
  388. %4 = OpString "foo"
  389. %5 = OpString "int"
  390. OpSource HLSL 600
  391. %uint = OpTypeInt 32 0
  392. %uint_32 = OpConstant %uint 32
  393. %_ptr_Private_uint = OpTypePointer Private %uint
  394. %void = OpTypeVoid
  395. %10 = OpTypeFunction %void
  396. %11 = OpVariable %_ptr_Private_uint Private
  397. %12 = OpExtInst %void %1 DebugSource %3
  398. %13 = OpExtInst %void %1 DebugCompilationUnit 1 4 %12 HLSL
  399. %14 = OpExtInst %void %1 DebugTypeBasic %5 %uint_32 Signed
  400. %15 = OpExtInst %void %1 DebugGlobalVariable %4 %14 %12 1 12 %13 %4 %11 FlagIsDefinition
  401. %2 = OpFunction %void None %10
  402. %16 = OpLabel
  403. OpReturn
  404. OpFunctionEnd
  405. )";
  406. std::unique_ptr<IRContext> context =
  407. BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
  408. // Delete the second variable.
  409. context->KillDef(11);
  410. // Get DebugInfoNone id.
  411. uint32_t debug_info_none_id = 0;
  412. for (auto it = context->ext_inst_debuginfo_begin();
  413. it != context->ext_inst_debuginfo_end(); ++it) {
  414. if (it->GetOpenCL100DebugOpcode() == OpenCLDebugInfo100DebugInfoNone) {
  415. debug_info_none_id = it->result_id();
  416. }
  417. }
  418. EXPECT_NE(0, debug_info_none_id);
  419. // Check the Function operand of DebugFunction is DebugInfoNone.
  420. const uint32_t kDebugGlobalVariableOperandVariableIndex = 11;
  421. bool checked = false;
  422. for (auto it = context->ext_inst_debuginfo_begin();
  423. it != context->ext_inst_debuginfo_end(); ++it) {
  424. if (it->GetOpenCL100DebugOpcode() ==
  425. OpenCLDebugInfo100DebugGlobalVariable) {
  426. EXPECT_FALSE(checked);
  427. EXPECT_EQ(
  428. it->GetOperand(kDebugGlobalVariableOperandVariableIndex).words[0],
  429. debug_info_none_id);
  430. checked = true;
  431. }
  432. }
  433. EXPECT_TRUE(checked);
  434. }
  435. TEST_F(IRContextTest, BasicVisitFromEntryPoint) {
  436. // Make sure we visit the entry point, and the function it calls.
  437. // Do not visit Dead or Exported.
  438. const std::string text = R"(
  439. OpCapability Shader
  440. OpMemoryModel Logical GLSL450
  441. OpEntryPoint Fragment %10 "main"
  442. OpName %10 "main"
  443. OpName %Dead "Dead"
  444. OpName %11 "Constant"
  445. OpName %ExportedFunc "ExportedFunc"
  446. OpDecorate %ExportedFunc LinkageAttributes "ExportedFunc" Export
  447. %void = OpTypeVoid
  448. %6 = OpTypeFunction %void
  449. %10 = OpFunction %void None %6
  450. %14 = OpLabel
  451. %15 = OpFunctionCall %void %11
  452. %16 = OpFunctionCall %void %11
  453. OpReturn
  454. OpFunctionEnd
  455. %11 = OpFunction %void None %6
  456. %18 = OpLabel
  457. OpReturn
  458. OpFunctionEnd
  459. %Dead = OpFunction %void None %6
  460. %19 = OpLabel
  461. OpReturn
  462. OpFunctionEnd
  463. %ExportedFunc = OpFunction %void None %7
  464. %20 = OpLabel
  465. %21 = OpFunctionCall %void %11
  466. OpReturn
  467. OpFunctionEnd
  468. )";
  469. // clang-format on
  470. std::unique_ptr<IRContext> localContext =
  471. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
  472. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  473. EXPECT_NE(nullptr, localContext) << "Assembling failed for shader:\n"
  474. << text << std::endl;
  475. std::vector<uint32_t> processed;
  476. Pass::ProcessFunction mark_visited = [&processed](Function* fp) {
  477. processed.push_back(fp->result_id());
  478. return false;
  479. };
  480. localContext->ProcessEntryPointCallTree(mark_visited);
  481. EXPECT_THAT(processed, UnorderedElementsAre(10, 11));
  482. }
  483. TEST_F(IRContextTest, BasicVisitReachable) {
  484. // Make sure we visit the entry point, exported function, and the function
  485. // they call. Do not visit Dead.
  486. const std::string text = R"(
  487. OpCapability Shader
  488. OpMemoryModel Logical GLSL450
  489. OpEntryPoint Fragment %10 "main"
  490. OpName %10 "main"
  491. OpName %Dead "Dead"
  492. OpName %11 "Constant"
  493. OpName %12 "ExportedFunc"
  494. OpName %13 "Constant2"
  495. OpDecorate %12 LinkageAttributes "ExportedFunc" Export
  496. %void = OpTypeVoid
  497. %6 = OpTypeFunction %void
  498. %10 = OpFunction %void None %6
  499. %14 = OpLabel
  500. %15 = OpFunctionCall %void %11
  501. %16 = OpFunctionCall %void %11
  502. OpReturn
  503. OpFunctionEnd
  504. %11 = OpFunction %void None %6
  505. %18 = OpLabel
  506. OpReturn
  507. OpFunctionEnd
  508. %Dead = OpFunction %void None %6
  509. %19 = OpLabel
  510. OpReturn
  511. OpFunctionEnd
  512. %12 = OpFunction %void None %6
  513. %20 = OpLabel
  514. %21 = OpFunctionCall %void %13
  515. OpReturn
  516. OpFunctionEnd
  517. %13 = OpFunction %void None %6
  518. %22 = OpLabel
  519. OpReturn
  520. OpFunctionEnd
  521. )";
  522. // clang-format on
  523. std::unique_ptr<IRContext> localContext =
  524. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
  525. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  526. EXPECT_NE(nullptr, localContext) << "Assembling failed for shader:\n"
  527. << text << std::endl;
  528. std::vector<uint32_t> processed;
  529. Pass::ProcessFunction mark_visited = [&processed](Function* fp) {
  530. processed.push_back(fp->result_id());
  531. return false;
  532. };
  533. localContext->ProcessReachableCallTree(mark_visited);
  534. EXPECT_THAT(processed, UnorderedElementsAre(10, 11, 12, 13));
  535. }
  536. TEST_F(IRContextTest, BasicVisitOnlyOnce) {
  537. // Make sure we visit %12 only once, even if it is called from two different
  538. // functions.
  539. const std::string text = R"(
  540. OpCapability Shader
  541. OpMemoryModel Logical GLSL450
  542. OpEntryPoint Fragment %10 "main"
  543. OpName %10 "main"
  544. OpName %Dead "Dead"
  545. OpName %11 "Constant"
  546. OpName %12 "ExportedFunc"
  547. OpDecorate %12 LinkageAttributes "ExportedFunc" Export
  548. %void = OpTypeVoid
  549. %6 = OpTypeFunction %void
  550. %10 = OpFunction %void None %6
  551. %14 = OpLabel
  552. %15 = OpFunctionCall %void %11
  553. %16 = OpFunctionCall %void %12
  554. OpReturn
  555. OpFunctionEnd
  556. %11 = OpFunction %void None %6
  557. %18 = OpLabel
  558. %19 = OpFunctionCall %void %12
  559. OpReturn
  560. OpFunctionEnd
  561. %Dead = OpFunction %void None %6
  562. %20 = OpLabel
  563. OpReturn
  564. OpFunctionEnd
  565. %12 = OpFunction %void None %6
  566. %21 = OpLabel
  567. OpReturn
  568. OpFunctionEnd
  569. )";
  570. // clang-format on
  571. std::unique_ptr<IRContext> localContext =
  572. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
  573. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  574. EXPECT_NE(nullptr, localContext) << "Assembling failed for shader:\n"
  575. << text << std::endl;
  576. std::vector<uint32_t> processed;
  577. Pass::ProcessFunction mark_visited = [&processed](Function* fp) {
  578. processed.push_back(fp->result_id());
  579. return false;
  580. };
  581. localContext->ProcessReachableCallTree(mark_visited);
  582. EXPECT_THAT(processed, UnorderedElementsAre(10, 11, 12));
  583. }
  584. TEST_F(IRContextTest, BasicDontVisitExportedVariable) {
  585. // Make sure we only visit functions and not exported variables.
  586. const std::string text = R"(
  587. OpCapability Shader
  588. OpMemoryModel Logical GLSL450
  589. OpEntryPoint Fragment %10 "main"
  590. OpExecutionMode %10 OriginUpperLeft
  591. OpSource GLSL 150
  592. OpName %10 "main"
  593. OpName %12 "export_var"
  594. OpDecorate %12 LinkageAttributes "export_var" Export
  595. %void = OpTypeVoid
  596. %6 = OpTypeFunction %void
  597. %float = OpTypeFloat 32
  598. %float_1 = OpConstant %float 1
  599. %12 = OpVariable %float Output
  600. %10 = OpFunction %void None %6
  601. %14 = OpLabel
  602. OpStore %12 %float_1
  603. OpReturn
  604. OpFunctionEnd
  605. )";
  606. // clang-format on
  607. std::unique_ptr<IRContext> localContext =
  608. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
  609. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  610. EXPECT_NE(nullptr, localContext) << "Assembling failed for shader:\n"
  611. << text << std::endl;
  612. std::vector<uint32_t> processed;
  613. Pass::ProcessFunction mark_visited = [&processed](Function* fp) {
  614. processed.push_back(fp->result_id());
  615. return false;
  616. };
  617. localContext->ProcessReachableCallTree(mark_visited);
  618. EXPECT_THAT(processed, UnorderedElementsAre(10));
  619. }
  620. TEST_F(IRContextTest, IdBoundTestAtLimit) {
  621. const std::string text = R"(
  622. OpCapability Shader
  623. OpCapability Linkage
  624. OpMemoryModel Logical GLSL450
  625. %1 = OpTypeVoid
  626. %2 = OpTypeFunction %1
  627. %3 = OpFunction %1 None %2
  628. %4 = OpLabel
  629. OpReturn
  630. OpFunctionEnd)";
  631. std::unique_ptr<IRContext> context =
  632. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
  633. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  634. uint32_t current_bound = context->module()->id_bound();
  635. context->set_max_id_bound(current_bound);
  636. uint32_t next_id_bound = context->TakeNextId();
  637. EXPECT_EQ(next_id_bound, 0);
  638. EXPECT_EQ(current_bound, context->module()->id_bound());
  639. next_id_bound = context->TakeNextId();
  640. EXPECT_EQ(next_id_bound, 0);
  641. }
  642. TEST_F(IRContextTest, IdBoundTestBelowLimit) {
  643. const std::string text = R"(
  644. OpCapability Shader
  645. OpCapability Linkage
  646. OpMemoryModel Logical GLSL450
  647. %1 = OpTypeVoid
  648. %2 = OpTypeFunction %1
  649. %3 = OpFunction %1 None %2
  650. %4 = OpLabel
  651. OpReturn
  652. OpFunctionEnd)";
  653. std::unique_ptr<IRContext> context =
  654. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
  655. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  656. uint32_t current_bound = context->module()->id_bound();
  657. context->set_max_id_bound(current_bound + 100);
  658. uint32_t next_id_bound = context->TakeNextId();
  659. EXPECT_EQ(next_id_bound, current_bound);
  660. EXPECT_EQ(current_bound + 1, context->module()->id_bound());
  661. next_id_bound = context->TakeNextId();
  662. EXPECT_EQ(next_id_bound, current_bound + 1);
  663. }
  664. TEST_F(IRContextTest, IdBoundTestNearLimit) {
  665. const std::string text = R"(
  666. OpCapability Shader
  667. OpCapability Linkage
  668. OpMemoryModel Logical GLSL450
  669. %1 = OpTypeVoid
  670. %2 = OpTypeFunction %1
  671. %3 = OpFunction %1 None %2
  672. %4 = OpLabel
  673. OpReturn
  674. OpFunctionEnd)";
  675. std::unique_ptr<IRContext> context =
  676. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
  677. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  678. uint32_t current_bound = context->module()->id_bound();
  679. context->set_max_id_bound(current_bound + 1);
  680. uint32_t next_id_bound = context->TakeNextId();
  681. EXPECT_EQ(next_id_bound, current_bound);
  682. EXPECT_EQ(current_bound + 1, context->module()->id_bound());
  683. next_id_bound = context->TakeNextId();
  684. EXPECT_EQ(next_id_bound, 0);
  685. }
  686. TEST_F(IRContextTest, IdBoundTestUIntMax) {
  687. const std::string text = R"(
  688. OpCapability Shader
  689. OpCapability Linkage
  690. OpMemoryModel Logical GLSL450
  691. %1 = OpTypeVoid
  692. %2 = OpTypeFunction %1
  693. %3 = OpFunction %1 None %2
  694. %4294967294 = OpLabel ; ID is UINT_MAX-1
  695. OpReturn
  696. OpFunctionEnd)";
  697. std::unique_ptr<IRContext> context =
  698. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
  699. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  700. uint32_t current_bound = context->module()->id_bound();
  701. // Expecting |BuildModule| to preserve the numeric ids.
  702. EXPECT_EQ(current_bound, std::numeric_limits<uint32_t>::max());
  703. context->set_max_id_bound(current_bound);
  704. uint32_t next_id_bound = context->TakeNextId();
  705. EXPECT_EQ(next_id_bound, 0);
  706. EXPECT_EQ(current_bound, context->module()->id_bound());
  707. }
  708. TEST_F(IRContextTest, CfgAndDomAnalysis) {
  709. const std::string text = R"(
  710. OpCapability Shader
  711. OpCapability Linkage
  712. OpMemoryModel Logical GLSL450
  713. %1 = OpTypeVoid
  714. %2 = OpTypeFunction %1
  715. %3 = OpFunction %1 None %2
  716. %4 = OpLabel
  717. OpReturn
  718. OpFunctionEnd)";
  719. std::unique_ptr<IRContext> ctx =
  720. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
  721. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  722. // Building the dominator analysis should build the CFG.
  723. ASSERT_TRUE(ctx->module()->begin() != ctx->module()->end());
  724. ctx->GetDominatorAnalysis(&*ctx->module()->begin());
  725. EXPECT_TRUE(ctx->AreAnalysesValid(IRContext::kAnalysisCFG));
  726. EXPECT_TRUE(ctx->AreAnalysesValid(IRContext::kAnalysisDominatorAnalysis));
  727. // Invalidating the CFG analysis should invalidate the dominator analysis.
  728. ctx->InvalidateAnalyses(IRContext::kAnalysisCFG);
  729. EXPECT_FALSE(ctx->AreAnalysesValid(IRContext::kAnalysisCFG));
  730. EXPECT_FALSE(ctx->AreAnalysesValid(IRContext::kAnalysisDominatorAnalysis));
  731. }
  732. TEST_F(IRContextTest, AsanErrorTest) {
  733. std::string shader = R"(
  734. OpCapability Shader
  735. %1 = OpExtInstImport "GLSL.std.450"
  736. OpMemoryModel Logical GLSL450
  737. OpEntryPoint Fragment %4 "main"
  738. OpExecutionMode %4 OriginUpperLeft
  739. OpSource ESSL 310
  740. OpName %4 "main"
  741. OpName %8 "x"
  742. OpName %10 "y"
  743. OpDecorate %8 RelaxedPrecision
  744. OpDecorate %10 RelaxedPrecision
  745. OpDecorate %11 RelaxedPrecision
  746. %2 = OpTypeVoid
  747. %3 = OpTypeFunction %2
  748. %6 = OpTypeInt 32 1
  749. %7 = OpTypePointer Function %6
  750. %9 = OpConstant %6 1
  751. %4 = OpFunction %2 None %3
  752. %5 = OpLabel
  753. %8 = OpVariable %7 Function
  754. %10 = OpVariable %7 Function
  755. OpStore %8 %9
  756. %11 = OpLoad %6 %8
  757. OpBranch %20
  758. %20 = OpLabel
  759. %21 = OpPhi %6 %11 %5
  760. OpStore %10 %21
  761. OpReturn
  762. OpFunctionEnd
  763. )";
  764. const auto env = SPV_ENV_UNIVERSAL_1_3;
  765. const auto consumer = nullptr;
  766. const auto context = BuildModule(
  767. env, consumer, shader, SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  768. opt::Function* fun =
  769. context->cfg()->block(5)->GetParent(); // Computes the CFG analysis
  770. opt::DominatorAnalysis* dom = nullptr;
  771. dom = context->GetDominatorAnalysis(fun); // Computes the dominator analysis,
  772. // which depends on the CFG
  773. // analysis
  774. context->InvalidateAnalysesExceptFor(
  775. opt::IRContext::Analysis::kAnalysisDominatorAnalysis); // Invalidates the
  776. // CFG analysis
  777. dom = context->GetDominatorAnalysis(
  778. fun); // Recompute the CFG analysis because the Dominator tree uses it.
  779. auto bb = dom->ImmediateDominator(5);
  780. std::cout
  781. << bb->id(); // Make sure asan does not complain about use after free.
  782. }
  783. TEST_F(IRContextTest, DebugInstructionReplaceSingleUse) {
  784. const std::string text = R"(
  785. OpCapability Shader
  786. OpCapability Linkage
  787. %1 = OpExtInstImport "OpenCL.DebugInfo.100"
  788. OpMemoryModel Logical GLSL450
  789. %2 = OpString "test"
  790. %3 = OpTypeVoid
  791. %4 = OpTypeFunction %3
  792. %5 = OpTypeFloat 32
  793. %6 = OpTypePointer Function %5
  794. %7 = OpConstant %5 0
  795. %8 = OpTypeInt 32 0
  796. %9 = OpConstant %8 32
  797. %10 = OpExtInst %3 %1 DebugExpression
  798. %11 = OpExtInst %3 %1 DebugSource %2
  799. %12 = OpExtInst %3 %1 DebugCompilationUnit 1 4 %11 HLSL
  800. %13 = OpExtInst %3 %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %3
  801. %14 = OpExtInst %3 %1 DebugFunction %2 %13 %11 0 0 %12 %2 FlagIsProtected|FlagIsPrivate 0 %17
  802. %15 = OpExtInst %3 %1 DebugTypeBasic %2 %9 Float
  803. %16 = OpExtInst %3 %1 DebugLocalVariable %2 %15 %11 0 0 %14 FlagIsLocal
  804. %17 = OpFunction %3 None %4
  805. %18 = OpLabel
  806. %19 = OpExtInst %3 %1 DebugScope %14
  807. %20 = OpVariable %6 Function
  808. %26 = OpVariable %6 Function
  809. OpBranch %21
  810. %21 = OpLabel
  811. %22 = OpPhi %5 %7 %18
  812. OpBranch %23
  813. %23 = OpLabel
  814. OpLine %2 0 0
  815. OpStore %20 %7
  816. %24 = OpExtInst %3 %1 DebugValue %16 %22 %10
  817. %25 = OpExtInst %3 %1 DebugDeclare %16 %26 %10
  818. OpReturn
  819. OpFunctionEnd)";
  820. std::unique_ptr<IRContext> ctx =
  821. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
  822. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  823. ctx->BuildInvalidAnalyses(IRContext::kAnalysisDebugInfo);
  824. NoopPassPreservesAll pass(Pass::Status::SuccessWithChange);
  825. pass.Run(ctx.get());
  826. EXPECT_TRUE(ctx->AreAnalysesValid(IRContext::kAnalysisDebugInfo));
  827. auto* dbg_value = ctx->get_def_use_mgr()->GetDef(24);
  828. EXPECT_TRUE(dbg_value->GetSingleWordOperand(kDebugValueOperandValueIndex) ==
  829. 22);
  830. EXPECT_TRUE(ctx->ReplaceAllUsesWith(22, 7));
  831. dbg_value = ctx->get_def_use_mgr()->GetDef(24);
  832. EXPECT_TRUE(dbg_value->GetSingleWordOperand(kDebugValueOperandValueIndex) ==
  833. 7);
  834. auto* dbg_decl = ctx->get_def_use_mgr()->GetDef(25);
  835. EXPECT_TRUE(
  836. dbg_decl->GetSingleWordOperand(kDebugDeclareOperandVariableIndex) == 26);
  837. EXPECT_TRUE(ctx->ReplaceAllUsesWith(26, 20));
  838. dbg_decl = ctx->get_def_use_mgr()->GetDef(25);
  839. EXPECT_TRUE(
  840. dbg_decl->GetSingleWordOperand(kDebugDeclareOperandVariableIndex) == 20);
  841. }
  842. TEST_F(IRContextTest, DebugInstructionReplaceAllUses) {
  843. const std::string text = R"(
  844. OpCapability Shader
  845. OpCapability Linkage
  846. %1 = OpExtInstImport "OpenCL.DebugInfo.100"
  847. OpMemoryModel Logical GLSL450
  848. %2 = OpString "test"
  849. %3 = OpTypeVoid
  850. %4 = OpTypeFunction %3
  851. %5 = OpTypeFloat 32
  852. %6 = OpTypePointer Function %5
  853. %7 = OpConstant %5 0
  854. %8 = OpTypeInt 32 0
  855. %9 = OpConstant %8 32
  856. %10 = OpExtInst %3 %1 DebugExpression
  857. %11 = OpExtInst %3 %1 DebugSource %2
  858. %12 = OpExtInst %3 %1 DebugCompilationUnit 1 4 %11 HLSL
  859. %13 = OpExtInst %3 %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %3
  860. %14 = OpExtInst %3 %1 DebugFunction %2 %13 %11 0 0 %12 %2 FlagIsProtected|FlagIsPrivate 0 %17
  861. %15 = OpExtInst %3 %1 DebugTypeBasic %2 %9 Float
  862. %16 = OpExtInst %3 %1 DebugLocalVariable %2 %15 %11 0 0 %14 FlagIsLocal
  863. %27 = OpExtInst %3 %1 DebugLocalVariable %2 %15 %11 1 0 %14 FlagIsLocal
  864. %17 = OpFunction %3 None %4
  865. %18 = OpLabel
  866. %19 = OpExtInst %3 %1 DebugScope %14
  867. %20 = OpVariable %6 Function
  868. %26 = OpVariable %6 Function
  869. OpBranch %21
  870. %21 = OpLabel
  871. %22 = OpPhi %5 %7 %18
  872. OpBranch %23
  873. %23 = OpLabel
  874. OpLine %2 0 0
  875. OpStore %20 %7
  876. %24 = OpExtInst %3 %1 DebugValue %16 %22 %10
  877. %25 = OpExtInst %3 %1 DebugDeclare %16 %26 %10
  878. %28 = OpExtInst %3 %1 DebugValue %27 %22 %10
  879. %29 = OpExtInst %3 %1 DebugDeclare %27 %26 %10
  880. OpReturn
  881. OpFunctionEnd)";
  882. std::unique_ptr<IRContext> ctx =
  883. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
  884. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  885. ctx->BuildInvalidAnalyses(IRContext::kAnalysisDebugInfo);
  886. NoopPassPreservesAll pass(Pass::Status::SuccessWithChange);
  887. pass.Run(ctx.get());
  888. EXPECT_TRUE(ctx->AreAnalysesValid(IRContext::kAnalysisDebugInfo));
  889. auto* dbg_value0 = ctx->get_def_use_mgr()->GetDef(24);
  890. auto* dbg_value1 = ctx->get_def_use_mgr()->GetDef(28);
  891. EXPECT_TRUE(dbg_value0->GetSingleWordOperand(kDebugValueOperandValueIndex) ==
  892. 22);
  893. EXPECT_TRUE(dbg_value1->GetSingleWordOperand(kDebugValueOperandValueIndex) ==
  894. 22);
  895. EXPECT_TRUE(ctx->ReplaceAllUsesWith(22, 7));
  896. dbg_value0 = ctx->get_def_use_mgr()->GetDef(24);
  897. dbg_value1 = ctx->get_def_use_mgr()->GetDef(28);
  898. EXPECT_TRUE(dbg_value0->GetSingleWordOperand(kDebugValueOperandValueIndex) ==
  899. 7);
  900. EXPECT_TRUE(dbg_value1->GetSingleWordOperand(kDebugValueOperandValueIndex) ==
  901. 7);
  902. auto* dbg_decl0 = ctx->get_def_use_mgr()->GetDef(25);
  903. auto* dbg_decl1 = ctx->get_def_use_mgr()->GetDef(29);
  904. EXPECT_TRUE(
  905. dbg_decl0->GetSingleWordOperand(kDebugDeclareOperandVariableIndex) == 26);
  906. EXPECT_TRUE(
  907. dbg_decl1->GetSingleWordOperand(kDebugDeclareOperandVariableIndex) == 26);
  908. EXPECT_TRUE(ctx->ReplaceAllUsesWith(26, 20));
  909. dbg_decl0 = ctx->get_def_use_mgr()->GetDef(25);
  910. dbg_decl1 = ctx->get_def_use_mgr()->GetDef(29);
  911. EXPECT_TRUE(
  912. dbg_decl0->GetSingleWordOperand(kDebugDeclareOperandVariableIndex) == 20);
  913. EXPECT_TRUE(
  914. dbg_decl1->GetSingleWordOperand(kDebugDeclareOperandVariableIndex) == 20);
  915. }
  916. TEST_F(IRContextTest, DebugInstructionReplaceDebugScopeAndDebugInlinedAt) {
  917. const std::string text = R"(
  918. OpCapability Shader
  919. OpCapability Linkage
  920. %1 = OpExtInstImport "OpenCL.DebugInfo.100"
  921. OpMemoryModel Logical GLSL450
  922. %2 = OpString "test"
  923. %3 = OpTypeVoid
  924. %4 = OpTypeFunction %3
  925. %5 = OpTypeFloat 32
  926. %6 = OpTypePointer Function %5
  927. %7 = OpConstant %5 0
  928. %8 = OpTypeInt 32 0
  929. %9 = OpConstant %8 32
  930. %10 = OpExtInst %3 %1 DebugExpression
  931. %11 = OpExtInst %3 %1 DebugSource %2
  932. %12 = OpExtInst %3 %1 DebugCompilationUnit 1 4 %11 HLSL
  933. %13 = OpExtInst %3 %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %3
  934. %14 = OpExtInst %3 %1 DebugFunction %2 %13 %11 0 0 %12 %2 FlagIsProtected|FlagIsPrivate 0 %17
  935. %15 = OpExtInst %3 %1 DebugInfoNone
  936. %16 = OpExtInst %3 %1 DebugFunction %2 %13 %11 10 10 %12 %2 FlagIsProtected|FlagIsPrivate 0 %15
  937. %25 = OpExtInst %3 %1 DebugInlinedAt 0 %14
  938. %26 = OpExtInst %3 %1 DebugInlinedAt 2 %14
  939. %17 = OpFunction %3 None %4
  940. %18 = OpLabel
  941. %19 = OpExtInst %3 %1 DebugScope %14
  942. %20 = OpVariable %6 Function
  943. OpBranch %21
  944. %21 = OpLabel
  945. %24 = OpExtInst %3 %1 DebugScope %16
  946. %22 = OpPhi %5 %7 %18
  947. OpBranch %23
  948. %23 = OpLabel
  949. %27 = OpExtInst %3 %1 DebugScope %16 %25
  950. OpLine %2 0 0
  951. %28 = OpFAdd %5 %7 %7
  952. OpStore %20 %28
  953. OpReturn
  954. OpFunctionEnd)";
  955. std::unique_ptr<IRContext> ctx =
  956. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
  957. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  958. ctx->BuildInvalidAnalyses(IRContext::kAnalysisDebugInfo);
  959. NoopPassPreservesAll pass(Pass::Status::SuccessWithChange);
  960. pass.Run(ctx.get());
  961. EXPECT_TRUE(ctx->AreAnalysesValid(IRContext::kAnalysisDebugInfo));
  962. auto* inst0 = ctx->get_def_use_mgr()->GetDef(20);
  963. auto* inst1 = ctx->get_def_use_mgr()->GetDef(22);
  964. auto* inst2 = ctx->get_def_use_mgr()->GetDef(28);
  965. EXPECT_EQ(inst0->GetDebugScope().GetLexicalScope(), 14);
  966. EXPECT_EQ(inst1->GetDebugScope().GetLexicalScope(), 16);
  967. EXPECT_EQ(inst2->GetDebugScope().GetLexicalScope(), 16);
  968. EXPECT_EQ(inst2->GetDebugInlinedAt(), 25);
  969. EXPECT_TRUE(ctx->ReplaceAllUsesWith(14, 12));
  970. EXPECT_TRUE(ctx->ReplaceAllUsesWith(16, 14));
  971. EXPECT_TRUE(ctx->ReplaceAllUsesWith(25, 26));
  972. EXPECT_EQ(inst0->GetDebugScope().GetLexicalScope(), 12);
  973. EXPECT_EQ(inst1->GetDebugScope().GetLexicalScope(), 14);
  974. EXPECT_EQ(inst2->GetDebugScope().GetLexicalScope(), 14);
  975. EXPECT_EQ(inst2->GetDebugInlinedAt(), 26);
  976. }
  977. TEST_F(IRContextTest, AddDebugValueAfterReplaceUse) {
  978. const std::string text = R"(
  979. OpCapability Shader
  980. OpCapability Linkage
  981. %1 = OpExtInstImport "OpenCL.DebugInfo.100"
  982. OpMemoryModel Logical GLSL450
  983. %2 = OpString "test"
  984. %3 = OpTypeVoid
  985. %4 = OpTypeFunction %3
  986. %5 = OpTypeFloat 32
  987. %6 = OpTypePointer Function %5
  988. %7 = OpConstant %5 0
  989. %8 = OpTypeInt 32 0
  990. %9 = OpConstant %8 32
  991. %10 = OpExtInst %3 %1 DebugExpression
  992. %11 = OpExtInst %3 %1 DebugSource %2
  993. %12 = OpExtInst %3 %1 DebugCompilationUnit 1 4 %11 HLSL
  994. %13 = OpExtInst %3 %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %3
  995. %14 = OpExtInst %3 %1 DebugFunction %2 %13 %11 0 0 %12 %2 FlagIsProtected|FlagIsPrivate 0 %17
  996. %15 = OpExtInst %3 %1 DebugTypeBasic %2 %9 Float
  997. %16 = OpExtInst %3 %1 DebugLocalVariable %2 %15 %11 0 0 %14 FlagIsLocal
  998. %17 = OpFunction %3 None %4
  999. %18 = OpLabel
  1000. %19 = OpExtInst %3 %1 DebugScope %14
  1001. %20 = OpVariable %6 Function
  1002. %26 = OpVariable %6 Function
  1003. OpBranch %21
  1004. %21 = OpLabel
  1005. %27 = OpExtInst %3 %1 DebugScope %14
  1006. %22 = OpPhi %5 %7 %18
  1007. OpBranch %23
  1008. %23 = OpLabel
  1009. %28 = OpExtInst %3 %1 DebugScope %14
  1010. OpLine %2 0 0
  1011. OpStore %20 %7
  1012. %24 = OpExtInst %3 %1 DebugValue %16 %22 %10
  1013. %25 = OpExtInst %3 %1 DebugDeclare %16 %26 %10
  1014. OpReturn
  1015. OpFunctionEnd)";
  1016. std::unique_ptr<IRContext> ctx =
  1017. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
  1018. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  1019. ctx->BuildInvalidAnalyses(IRContext::kAnalysisDebugInfo);
  1020. NoopPassPreservesAll pass(Pass::Status::SuccessWithChange);
  1021. pass.Run(ctx.get());
  1022. EXPECT_TRUE(ctx->AreAnalysesValid(IRContext::kAnalysisDebugInfo));
  1023. // Replace all uses of result it '26' with '20'
  1024. auto* dbg_decl = ctx->get_def_use_mgr()->GetDef(25);
  1025. EXPECT_EQ(dbg_decl->GetSingleWordOperand(kDebugDeclareOperandVariableIndex),
  1026. 26);
  1027. EXPECT_TRUE(ctx->ReplaceAllUsesWith(26, 20));
  1028. dbg_decl = ctx->get_def_use_mgr()->GetDef(25);
  1029. EXPECT_EQ(dbg_decl->GetSingleWordOperand(kDebugDeclareOperandVariableIndex),
  1030. 20);
  1031. }
  1032. } // namespace
  1033. } // namespace opt
  1034. } // namespace spvtools