ir_context_test.cpp 40 KB

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