generated.cpp 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019
  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 <array>
  15. #include <memory>
  16. #include <string>
  17. #include <vector>
  18. #include "gmock/gmock.h"
  19. #include "source/opt/dominator_analysis.h"
  20. #include "source/opt/iterator.h"
  21. #include "source/opt/pass.h"
  22. #include "test/opt/assembly_builder.h"
  23. #include "test/opt/function_utils.h"
  24. #include "test/opt/pass_fixture.h"
  25. #include "test/opt/pass_utils.h"
  26. namespace spvtools {
  27. namespace opt {
  28. namespace {
  29. using ::testing::UnorderedElementsAre;
  30. using PassClassTest = PassTest<::testing::Test>;
  31. // Check that x dominates y, and
  32. // if x != y then
  33. // x strictly dominates y and
  34. // y does not dominate x and
  35. // y does not strictly dominate x
  36. // if x == x then
  37. // x does not strictly dominate itself
  38. void check_dominance(const DominatorAnalysisBase& dom_tree, const Function* fn,
  39. uint32_t x, uint32_t y) {
  40. SCOPED_TRACE("Check dominance properties for Basic Block " +
  41. std::to_string(x) + " and " + std::to_string(y));
  42. EXPECT_TRUE(dom_tree.Dominates(spvtest::GetBasicBlock(fn, x),
  43. spvtest::GetBasicBlock(fn, y)));
  44. EXPECT_TRUE(dom_tree.Dominates(x, y));
  45. if (x == y) {
  46. EXPECT_FALSE(dom_tree.StrictlyDominates(x, x));
  47. } else {
  48. EXPECT_TRUE(dom_tree.StrictlyDominates(x, y));
  49. EXPECT_FALSE(dom_tree.Dominates(y, x));
  50. EXPECT_FALSE(dom_tree.StrictlyDominates(y, x));
  51. }
  52. }
  53. // Check that x does not dominates y and vice versa
  54. void check_no_dominance(const DominatorAnalysisBase& dom_tree,
  55. const Function* fn, uint32_t x, uint32_t y) {
  56. SCOPED_TRACE("Check no domination for Basic Block " + std::to_string(x) +
  57. " and " + std::to_string(y));
  58. EXPECT_FALSE(dom_tree.Dominates(spvtest::GetBasicBlock(fn, x),
  59. spvtest::GetBasicBlock(fn, y)));
  60. EXPECT_FALSE(dom_tree.Dominates(x, y));
  61. EXPECT_FALSE(dom_tree.StrictlyDominates(spvtest::GetBasicBlock(fn, x),
  62. spvtest::GetBasicBlock(fn, y)));
  63. EXPECT_FALSE(dom_tree.StrictlyDominates(x, y));
  64. EXPECT_FALSE(dom_tree.Dominates(spvtest::GetBasicBlock(fn, y),
  65. spvtest::GetBasicBlock(fn, x)));
  66. EXPECT_FALSE(dom_tree.Dominates(y, x));
  67. EXPECT_FALSE(dom_tree.StrictlyDominates(spvtest::GetBasicBlock(fn, y),
  68. spvtest::GetBasicBlock(fn, x)));
  69. EXPECT_FALSE(dom_tree.StrictlyDominates(y, x));
  70. }
  71. TEST_F(PassClassTest, DominatorSimpleCFG) {
  72. const std::string text = R"(
  73. OpCapability Addresses
  74. OpCapability Kernel
  75. OpMemoryModel Physical64 OpenCL
  76. OpEntryPoint Kernel %1 "main"
  77. %2 = OpTypeVoid
  78. %3 = OpTypeFunction %2
  79. %4 = OpTypeBool
  80. %5 = OpTypeInt 32 0
  81. %6 = OpConstant %5 0
  82. %7 = OpConstantFalse %4
  83. %8 = OpConstantTrue %4
  84. %9 = OpConstant %5 1
  85. %1 = OpFunction %2 None %3
  86. %10 = OpLabel
  87. OpBranch %11
  88. %11 = OpLabel
  89. OpSwitch %6 %12 1 %13
  90. %12 = OpLabel
  91. OpBranch %14
  92. %13 = OpLabel
  93. OpBranch %14
  94. %14 = OpLabel
  95. OpBranchConditional %8 %11 %15
  96. %15 = OpLabel
  97. OpReturn
  98. OpFunctionEnd
  99. )";
  100. // clang-format on
  101. std::unique_ptr<IRContext> context =
  102. BuildModule(SPV_ENV_UNIVERSAL_1_0, nullptr, text,
  103. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  104. Module* module = context->module();
  105. EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n"
  106. << text << std::endl;
  107. const Function* fn = spvtest::GetFunction(module, 1);
  108. const BasicBlock* entry = spvtest::GetBasicBlock(fn, 10);
  109. EXPECT_EQ(entry, fn->entry().get())
  110. << "The entry node is not the expected one";
  111. // Test normal dominator tree
  112. {
  113. DominatorAnalysis dom_tree;
  114. const CFG& cfg = *context->cfg();
  115. dom_tree.InitializeTree(cfg, fn);
  116. // Inspect the actual tree
  117. DominatorTree& tree = dom_tree.GetDomTree();
  118. EXPECT_EQ(tree.GetRoot()->bb_, cfg.pseudo_entry_block());
  119. EXPECT_TRUE(
  120. dom_tree.Dominates(cfg.pseudo_entry_block()->id(), entry->id()));
  121. // (strict) dominance checks
  122. for (uint32_t id : {10, 11, 12, 13, 14, 15})
  123. check_dominance(dom_tree, fn, id, id);
  124. check_dominance(dom_tree, fn, 10, 11);
  125. check_dominance(dom_tree, fn, 10, 12);
  126. check_dominance(dom_tree, fn, 10, 13);
  127. check_dominance(dom_tree, fn, 10, 14);
  128. check_dominance(dom_tree, fn, 10, 15);
  129. check_dominance(dom_tree, fn, 11, 12);
  130. check_dominance(dom_tree, fn, 11, 13);
  131. check_dominance(dom_tree, fn, 11, 14);
  132. check_dominance(dom_tree, fn, 11, 15);
  133. check_dominance(dom_tree, fn, 14, 15);
  134. check_no_dominance(dom_tree, fn, 12, 13);
  135. check_no_dominance(dom_tree, fn, 12, 14);
  136. check_no_dominance(dom_tree, fn, 13, 14);
  137. // check with some invalid inputs
  138. EXPECT_FALSE(dom_tree.Dominates(nullptr, entry));
  139. EXPECT_FALSE(dom_tree.Dominates(entry, nullptr));
  140. EXPECT_FALSE(dom_tree.Dominates(static_cast<BasicBlock*>(nullptr),
  141. static_cast<BasicBlock*>(nullptr)));
  142. EXPECT_FALSE(dom_tree.Dominates(10, 1));
  143. EXPECT_FALSE(dom_tree.Dominates(1, 10));
  144. EXPECT_FALSE(dom_tree.Dominates(1, 1));
  145. EXPECT_FALSE(dom_tree.StrictlyDominates(nullptr, entry));
  146. EXPECT_FALSE(dom_tree.StrictlyDominates(entry, nullptr));
  147. EXPECT_FALSE(dom_tree.StrictlyDominates(nullptr, nullptr));
  148. EXPECT_FALSE(dom_tree.StrictlyDominates(10, 1));
  149. EXPECT_FALSE(dom_tree.StrictlyDominates(1, 10));
  150. EXPECT_FALSE(dom_tree.StrictlyDominates(1, 1));
  151. EXPECT_EQ(dom_tree.ImmediateDominator(cfg.pseudo_entry_block()), nullptr);
  152. EXPECT_EQ(dom_tree.ImmediateDominator(entry), cfg.pseudo_entry_block());
  153. EXPECT_EQ(dom_tree.ImmediateDominator(nullptr), nullptr);
  154. EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 11)),
  155. spvtest::GetBasicBlock(fn, 10));
  156. EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 12)),
  157. spvtest::GetBasicBlock(fn, 11));
  158. EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 13)),
  159. spvtest::GetBasicBlock(fn, 11));
  160. EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 14)),
  161. spvtest::GetBasicBlock(fn, 11));
  162. EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 15)),
  163. spvtest::GetBasicBlock(fn, 14));
  164. }
  165. // Test post dominator tree
  166. {
  167. PostDominatorAnalysis dom_tree;
  168. const CFG& cfg = *context->cfg();
  169. dom_tree.InitializeTree(cfg, fn);
  170. // Inspect the actual tree
  171. DominatorTree& tree = dom_tree.GetDomTree();
  172. EXPECT_EQ(tree.GetRoot()->bb_, cfg.pseudo_exit_block());
  173. EXPECT_TRUE(dom_tree.Dominates(cfg.pseudo_exit_block()->id(), 15));
  174. // (strict) dominance checks
  175. for (uint32_t id : {10, 11, 12, 13, 14, 15})
  176. check_dominance(dom_tree, fn, id, id);
  177. check_dominance(dom_tree, fn, 14, 10);
  178. check_dominance(dom_tree, fn, 14, 11);
  179. check_dominance(dom_tree, fn, 14, 12);
  180. check_dominance(dom_tree, fn, 14, 13);
  181. check_dominance(dom_tree, fn, 15, 10);
  182. check_dominance(dom_tree, fn, 15, 11);
  183. check_dominance(dom_tree, fn, 15, 12);
  184. check_dominance(dom_tree, fn, 15, 13);
  185. check_dominance(dom_tree, fn, 15, 14);
  186. check_no_dominance(dom_tree, fn, 13, 12);
  187. check_no_dominance(dom_tree, fn, 12, 11);
  188. check_no_dominance(dom_tree, fn, 13, 11);
  189. // check with some invalid inputs
  190. EXPECT_FALSE(dom_tree.Dominates(nullptr, entry));
  191. EXPECT_FALSE(dom_tree.Dominates(entry, nullptr));
  192. EXPECT_FALSE(dom_tree.Dominates(static_cast<BasicBlock*>(nullptr),
  193. static_cast<BasicBlock*>(nullptr)));
  194. EXPECT_FALSE(dom_tree.Dominates(10, 1));
  195. EXPECT_FALSE(dom_tree.Dominates(1, 10));
  196. EXPECT_FALSE(dom_tree.Dominates(1, 1));
  197. EXPECT_FALSE(dom_tree.StrictlyDominates(nullptr, entry));
  198. EXPECT_FALSE(dom_tree.StrictlyDominates(entry, nullptr));
  199. EXPECT_FALSE(dom_tree.StrictlyDominates(nullptr, nullptr));
  200. EXPECT_FALSE(dom_tree.StrictlyDominates(10, 1));
  201. EXPECT_FALSE(dom_tree.StrictlyDominates(1, 10));
  202. EXPECT_FALSE(dom_tree.StrictlyDominates(1, 1));
  203. EXPECT_EQ(dom_tree.ImmediateDominator(nullptr), nullptr);
  204. EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 11)),
  205. spvtest::GetBasicBlock(fn, 14));
  206. EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 12)),
  207. spvtest::GetBasicBlock(fn, 14));
  208. EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 13)),
  209. spvtest::GetBasicBlock(fn, 14));
  210. EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 14)),
  211. spvtest::GetBasicBlock(fn, 15));
  212. EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 15)),
  213. cfg.pseudo_exit_block());
  214. EXPECT_EQ(dom_tree.ImmediateDominator(cfg.pseudo_exit_block()), nullptr);
  215. }
  216. }
  217. TEST_F(PassClassTest, DominatorIrreducibleCFG) {
  218. const std::string text = R"(
  219. OpCapability Addresses
  220. OpCapability Kernel
  221. OpMemoryModel Physical64 OpenCL
  222. OpEntryPoint Kernel %1 "main"
  223. %2 = OpTypeVoid
  224. %3 = OpTypeFunction %2
  225. %4 = OpTypeBool
  226. %5 = OpTypeInt 32 0
  227. %6 = OpConstantFalse %4
  228. %7 = OpConstantTrue %4
  229. %1 = OpFunction %2 None %3
  230. %8 = OpLabel
  231. OpBranch %9
  232. %9 = OpLabel
  233. OpBranchConditional %7 %10 %11
  234. %10 = OpLabel
  235. OpBranch %11
  236. %11 = OpLabel
  237. OpBranchConditional %7 %10 %12
  238. %12 = OpLabel
  239. OpReturn
  240. OpFunctionEnd
  241. )";
  242. // clang-format on
  243. std::unique_ptr<IRContext> context =
  244. BuildModule(SPV_ENV_UNIVERSAL_1_0, nullptr, text,
  245. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  246. Module* module = context->module();
  247. EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n"
  248. << text << std::endl;
  249. const Function* fn = spvtest::GetFunction(module, 1);
  250. const BasicBlock* entry = spvtest::GetBasicBlock(fn, 8);
  251. EXPECT_EQ(entry, fn->entry().get())
  252. << "The entry node is not the expected one";
  253. // Check normal dominator tree
  254. {
  255. DominatorAnalysis dom_tree;
  256. const CFG& cfg = *context->cfg();
  257. dom_tree.InitializeTree(cfg, fn);
  258. // Inspect the actual tree
  259. DominatorTree& tree = dom_tree.GetDomTree();
  260. EXPECT_EQ(tree.GetRoot()->bb_, cfg.pseudo_entry_block());
  261. EXPECT_TRUE(
  262. dom_tree.Dominates(cfg.pseudo_entry_block()->id(), entry->id()));
  263. // (strict) dominance checks
  264. for (uint32_t id : {8, 9, 10, 11, 12})
  265. check_dominance(dom_tree, fn, id, id);
  266. check_dominance(dom_tree, fn, 8, 9);
  267. check_dominance(dom_tree, fn, 8, 10);
  268. check_dominance(dom_tree, fn, 8, 11);
  269. check_dominance(dom_tree, fn, 8, 12);
  270. check_dominance(dom_tree, fn, 9, 10);
  271. check_dominance(dom_tree, fn, 9, 11);
  272. check_dominance(dom_tree, fn, 9, 12);
  273. check_dominance(dom_tree, fn, 11, 12);
  274. check_no_dominance(dom_tree, fn, 10, 11);
  275. EXPECT_EQ(dom_tree.ImmediateDominator(cfg.pseudo_entry_block()), nullptr);
  276. EXPECT_EQ(dom_tree.ImmediateDominator(entry), cfg.pseudo_entry_block());
  277. EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 9)),
  278. spvtest::GetBasicBlock(fn, 8));
  279. EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 10)),
  280. spvtest::GetBasicBlock(fn, 9));
  281. EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 11)),
  282. spvtest::GetBasicBlock(fn, 9));
  283. EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 12)),
  284. spvtest::GetBasicBlock(fn, 11));
  285. }
  286. // Check post dominator tree
  287. {
  288. PostDominatorAnalysis dom_tree;
  289. const CFG& cfg = *context->cfg();
  290. dom_tree.InitializeTree(cfg, fn);
  291. // Inspect the actual tree
  292. DominatorTree& tree = dom_tree.GetDomTree();
  293. EXPECT_EQ(tree.GetRoot()->bb_, cfg.pseudo_exit_block());
  294. EXPECT_TRUE(dom_tree.Dominates(cfg.pseudo_exit_block()->id(), 12));
  295. // (strict) dominance checks
  296. for (uint32_t id : {8, 9, 10, 11, 12})
  297. check_dominance(dom_tree, fn, id, id);
  298. check_dominance(dom_tree, fn, 12, 8);
  299. check_dominance(dom_tree, fn, 12, 10);
  300. check_dominance(dom_tree, fn, 12, 11);
  301. check_dominance(dom_tree, fn, 12, 12);
  302. check_dominance(dom_tree, fn, 11, 8);
  303. check_dominance(dom_tree, fn, 11, 9);
  304. check_dominance(dom_tree, fn, 11, 10);
  305. check_dominance(dom_tree, fn, 9, 8);
  306. EXPECT_EQ(dom_tree.ImmediateDominator(entry),
  307. spvtest::GetBasicBlock(fn, 9));
  308. EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 9)),
  309. spvtest::GetBasicBlock(fn, 11));
  310. EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 10)),
  311. spvtest::GetBasicBlock(fn, 11));
  312. EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 11)),
  313. spvtest::GetBasicBlock(fn, 12));
  314. EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 12)),
  315. cfg.pseudo_exit_block());
  316. EXPECT_EQ(dom_tree.ImmediateDominator(cfg.pseudo_exit_block()), nullptr);
  317. }
  318. }
  319. TEST_F(PassClassTest, DominatorLoopToSelf) {
  320. const std::string text = R"(
  321. OpCapability Addresses
  322. OpCapability Kernel
  323. OpMemoryModel Physical64 OpenCL
  324. OpEntryPoint Kernel %1 "main"
  325. %2 = OpTypeVoid
  326. %3 = OpTypeFunction %2
  327. %4 = OpTypeBool
  328. %5 = OpTypeInt 32 0
  329. %6 = OpConstant %5 0
  330. %7 = OpConstantFalse %4
  331. %8 = OpConstantTrue %4
  332. %9 = OpConstant %5 1
  333. %1 = OpFunction %2 None %3
  334. %10 = OpLabel
  335. OpBranch %11
  336. %11 = OpLabel
  337. OpSwitch %6 %12 1 %11
  338. %12 = OpLabel
  339. OpReturn
  340. OpFunctionEnd
  341. )";
  342. // clang-format on
  343. std::unique_ptr<IRContext> context =
  344. BuildModule(SPV_ENV_UNIVERSAL_1_0, nullptr, text,
  345. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  346. Module* module = context->module();
  347. EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n"
  348. << text << std::endl;
  349. const Function* fn = spvtest::GetFunction(module, 1);
  350. const BasicBlock* entry = spvtest::GetBasicBlock(fn, 10);
  351. EXPECT_EQ(entry, fn->entry().get())
  352. << "The entry node is not the expected one";
  353. // Check normal dominator tree
  354. {
  355. DominatorAnalysis dom_tree;
  356. const CFG& cfg = *context->cfg();
  357. dom_tree.InitializeTree(cfg, fn);
  358. // Inspect the actual tree
  359. DominatorTree& tree = dom_tree.GetDomTree();
  360. EXPECT_EQ(tree.GetRoot()->bb_, cfg.pseudo_entry_block());
  361. EXPECT_TRUE(
  362. dom_tree.Dominates(cfg.pseudo_entry_block()->id(), entry->id()));
  363. // (strict) dominance checks
  364. for (uint32_t id : {10, 11, 12}) check_dominance(dom_tree, fn, id, id);
  365. check_dominance(dom_tree, fn, 10, 11);
  366. check_dominance(dom_tree, fn, 10, 12);
  367. check_dominance(dom_tree, fn, 11, 12);
  368. EXPECT_EQ(dom_tree.ImmediateDominator(cfg.pseudo_entry_block()), nullptr);
  369. EXPECT_EQ(dom_tree.ImmediateDominator(entry), cfg.pseudo_entry_block());
  370. EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 11)),
  371. spvtest::GetBasicBlock(fn, 10));
  372. EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 12)),
  373. spvtest::GetBasicBlock(fn, 11));
  374. std::array<uint32_t, 3> node_order = {{10, 11, 12}};
  375. {
  376. // Test dominator tree iteration order.
  377. DominatorTree::iterator node_it = dom_tree.GetDomTree().begin();
  378. DominatorTree::iterator node_end = dom_tree.GetDomTree().end();
  379. for (uint32_t id : node_order) {
  380. EXPECT_NE(node_it, node_end);
  381. EXPECT_EQ(node_it->id(), id);
  382. node_it++;
  383. }
  384. EXPECT_EQ(node_it, node_end);
  385. }
  386. {
  387. // Same as above, but with const iterators.
  388. DominatorTree::const_iterator node_it = dom_tree.GetDomTree().cbegin();
  389. DominatorTree::const_iterator node_end = dom_tree.GetDomTree().cend();
  390. for (uint32_t id : node_order) {
  391. EXPECT_NE(node_it, node_end);
  392. EXPECT_EQ(node_it->id(), id);
  393. node_it++;
  394. }
  395. EXPECT_EQ(node_it, node_end);
  396. }
  397. {
  398. // Test dominator tree iteration order.
  399. DominatorTree::post_iterator node_it = dom_tree.GetDomTree().post_begin();
  400. DominatorTree::post_iterator node_end = dom_tree.GetDomTree().post_end();
  401. for (uint32_t id : make_range(node_order.rbegin(), node_order.rend())) {
  402. EXPECT_NE(node_it, node_end);
  403. EXPECT_EQ(node_it->id(), id);
  404. node_it++;
  405. }
  406. EXPECT_EQ(node_it, node_end);
  407. }
  408. {
  409. // Same as above, but with const iterators.
  410. DominatorTree::const_post_iterator node_it =
  411. dom_tree.GetDomTree().post_cbegin();
  412. DominatorTree::const_post_iterator node_end =
  413. dom_tree.GetDomTree().post_cend();
  414. for (uint32_t id : make_range(node_order.rbegin(), node_order.rend())) {
  415. EXPECT_NE(node_it, node_end);
  416. EXPECT_EQ(node_it->id(), id);
  417. node_it++;
  418. }
  419. EXPECT_EQ(node_it, node_end);
  420. }
  421. }
  422. // Check post dominator tree
  423. {
  424. PostDominatorAnalysis dom_tree;
  425. const CFG& cfg = *context->cfg();
  426. dom_tree.InitializeTree(cfg, fn);
  427. // Inspect the actual tree
  428. DominatorTree& tree = dom_tree.GetDomTree();
  429. EXPECT_EQ(tree.GetRoot()->bb_, cfg.pseudo_exit_block());
  430. EXPECT_TRUE(dom_tree.Dominates(cfg.pseudo_exit_block()->id(), 12));
  431. // (strict) dominance checks
  432. for (uint32_t id : {10, 11, 12}) check_dominance(dom_tree, fn, id, id);
  433. check_dominance(dom_tree, fn, 12, 10);
  434. check_dominance(dom_tree, fn, 12, 11);
  435. check_dominance(dom_tree, fn, 12, 12);
  436. EXPECT_EQ(dom_tree.ImmediateDominator(entry),
  437. spvtest::GetBasicBlock(fn, 11));
  438. EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 11)),
  439. spvtest::GetBasicBlock(fn, 12));
  440. EXPECT_EQ(dom_tree.ImmediateDominator(cfg.pseudo_exit_block()), nullptr);
  441. EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 12)),
  442. cfg.pseudo_exit_block());
  443. std::array<uint32_t, 3> node_order = {{12, 11, 10}};
  444. {
  445. // Test dominator tree iteration order.
  446. DominatorTree::iterator node_it = tree.begin();
  447. DominatorTree::iterator node_end = tree.end();
  448. for (uint32_t id : node_order) {
  449. EXPECT_NE(node_it, node_end);
  450. EXPECT_EQ(node_it->id(), id);
  451. node_it++;
  452. }
  453. EXPECT_EQ(node_it, node_end);
  454. }
  455. {
  456. // Same as above, but with const iterators.
  457. DominatorTree::const_iterator node_it = tree.cbegin();
  458. DominatorTree::const_iterator node_end = tree.cend();
  459. for (uint32_t id : node_order) {
  460. EXPECT_NE(node_it, node_end);
  461. EXPECT_EQ(node_it->id(), id);
  462. node_it++;
  463. }
  464. EXPECT_EQ(node_it, node_end);
  465. }
  466. {
  467. // Test dominator tree iteration order.
  468. DominatorTree::post_iterator node_it = dom_tree.GetDomTree().post_begin();
  469. DominatorTree::post_iterator node_end = dom_tree.GetDomTree().post_end();
  470. for (uint32_t id : make_range(node_order.rbegin(), node_order.rend())) {
  471. EXPECT_NE(node_it, node_end);
  472. EXPECT_EQ(node_it->id(), id);
  473. node_it++;
  474. }
  475. EXPECT_EQ(node_it, node_end);
  476. }
  477. {
  478. // Same as above, but with const iterators.
  479. DominatorTree::const_post_iterator node_it =
  480. dom_tree.GetDomTree().post_cbegin();
  481. DominatorTree::const_post_iterator node_end =
  482. dom_tree.GetDomTree().post_cend();
  483. for (uint32_t id : make_range(node_order.rbegin(), node_order.rend())) {
  484. EXPECT_NE(node_it, node_end);
  485. EXPECT_EQ(node_it->id(), id);
  486. node_it++;
  487. }
  488. EXPECT_EQ(node_it, node_end);
  489. }
  490. }
  491. }
  492. TEST_F(PassClassTest, DominatorUnreachableInLoop) {
  493. const std::string text = R"(
  494. OpCapability Addresses
  495. OpCapability Kernel
  496. OpMemoryModel Physical64 OpenCL
  497. OpEntryPoint Kernel %1 "main"
  498. %2 = OpTypeVoid
  499. %3 = OpTypeFunction %2
  500. %4 = OpTypeBool
  501. %5 = OpTypeInt 32 0
  502. %6 = OpConstant %5 0
  503. %7 = OpConstantFalse %4
  504. %8 = OpConstantTrue %4
  505. %9 = OpConstant %5 1
  506. %1 = OpFunction %2 None %3
  507. %10 = OpLabel
  508. OpBranch %11
  509. %11 = OpLabel
  510. OpSwitch %6 %12 1 %13
  511. %12 = OpLabel
  512. OpBranch %14
  513. %13 = OpLabel
  514. OpUnreachable
  515. %14 = OpLabel
  516. OpBranchConditional %8 %11 %15
  517. %15 = OpLabel
  518. OpReturn
  519. OpFunctionEnd
  520. )";
  521. // clang-format on
  522. std::unique_ptr<IRContext> context =
  523. BuildModule(SPV_ENV_UNIVERSAL_1_0, nullptr, text,
  524. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  525. Module* module = context->module();
  526. EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n"
  527. << text << std::endl;
  528. const Function* fn = spvtest::GetFunction(module, 1);
  529. const BasicBlock* entry = spvtest::GetBasicBlock(fn, 10);
  530. EXPECT_EQ(entry, fn->entry().get())
  531. << "The entry node is not the expected one";
  532. // Check normal dominator tree
  533. {
  534. DominatorAnalysis dom_tree;
  535. const CFG& cfg = *context->cfg();
  536. dom_tree.InitializeTree(cfg, fn);
  537. // Inspect the actual tree
  538. DominatorTree& tree = dom_tree.GetDomTree();
  539. EXPECT_EQ(tree.GetRoot()->bb_, cfg.pseudo_entry_block());
  540. EXPECT_TRUE(
  541. dom_tree.Dominates(cfg.pseudo_entry_block()->id(), entry->id()));
  542. // (strict) dominance checks
  543. for (uint32_t id : {10, 11, 12, 13, 14, 15})
  544. check_dominance(dom_tree, fn, id, id);
  545. check_dominance(dom_tree, fn, 10, 11);
  546. check_dominance(dom_tree, fn, 10, 13);
  547. check_dominance(dom_tree, fn, 10, 12);
  548. check_dominance(dom_tree, fn, 10, 14);
  549. check_dominance(dom_tree, fn, 10, 15);
  550. check_dominance(dom_tree, fn, 11, 12);
  551. check_dominance(dom_tree, fn, 11, 13);
  552. check_dominance(dom_tree, fn, 11, 14);
  553. check_dominance(dom_tree, fn, 11, 15);
  554. check_dominance(dom_tree, fn, 12, 14);
  555. check_dominance(dom_tree, fn, 12, 15);
  556. check_dominance(dom_tree, fn, 14, 15);
  557. check_no_dominance(dom_tree, fn, 13, 12);
  558. check_no_dominance(dom_tree, fn, 13, 14);
  559. check_no_dominance(dom_tree, fn, 13, 15);
  560. EXPECT_EQ(dom_tree.ImmediateDominator(cfg.pseudo_entry_block()), nullptr);
  561. EXPECT_EQ(dom_tree.ImmediateDominator(entry), cfg.pseudo_entry_block());
  562. EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 11)),
  563. spvtest::GetBasicBlock(fn, 10));
  564. EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 12)),
  565. spvtest::GetBasicBlock(fn, 11));
  566. EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 13)),
  567. spvtest::GetBasicBlock(fn, 11));
  568. EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 14)),
  569. spvtest::GetBasicBlock(fn, 12));
  570. EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 15)),
  571. spvtest::GetBasicBlock(fn, 14));
  572. }
  573. // Check post dominator tree.
  574. {
  575. PostDominatorAnalysis dom_tree;
  576. const CFG& cfg = *context->cfg();
  577. dom_tree.InitializeTree(cfg, fn);
  578. // (strict) dominance checks.
  579. for (uint32_t id : {10, 11, 12, 13, 14, 15})
  580. check_dominance(dom_tree, fn, id, id);
  581. check_no_dominance(dom_tree, fn, 15, 10);
  582. check_no_dominance(dom_tree, fn, 15, 11);
  583. check_no_dominance(dom_tree, fn, 15, 12);
  584. check_no_dominance(dom_tree, fn, 15, 13);
  585. check_no_dominance(dom_tree, fn, 15, 14);
  586. check_dominance(dom_tree, fn, 14, 12);
  587. check_no_dominance(dom_tree, fn, 13, 10);
  588. check_no_dominance(dom_tree, fn, 13, 11);
  589. check_no_dominance(dom_tree, fn, 13, 12);
  590. check_no_dominance(dom_tree, fn, 13, 14);
  591. check_no_dominance(dom_tree, fn, 13, 15);
  592. EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 10)),
  593. spvtest::GetBasicBlock(fn, 11));
  594. EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 12)),
  595. spvtest::GetBasicBlock(fn, 14));
  596. EXPECT_EQ(dom_tree.ImmediateDominator(cfg.pseudo_exit_block()), nullptr);
  597. EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 15)),
  598. cfg.pseudo_exit_block());
  599. EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 13)),
  600. cfg.pseudo_exit_block());
  601. EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 14)),
  602. cfg.pseudo_exit_block());
  603. EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 11)),
  604. cfg.pseudo_exit_block());
  605. }
  606. }
  607. TEST_F(PassClassTest, DominatorInfinitLoop) {
  608. const std::string text = R"(
  609. OpCapability Addresses
  610. OpCapability Kernel
  611. OpMemoryModel Physical64 OpenCL
  612. OpEntryPoint Kernel %1 "main"
  613. %2 = OpTypeVoid
  614. %3 = OpTypeFunction %2
  615. %4 = OpTypeBool
  616. %5 = OpTypeInt 32 0
  617. %6 = OpConstant %5 0
  618. %7 = OpConstantFalse %4
  619. %8 = OpConstantTrue %4
  620. %9 = OpConstant %5 1
  621. %1 = OpFunction %2 None %3
  622. %10 = OpLabel
  623. OpBranch %11
  624. %11 = OpLabel
  625. OpSwitch %6 %12 1 %13
  626. %12 = OpLabel
  627. OpReturn
  628. %13 = OpLabel
  629. OpBranch %13
  630. OpFunctionEnd
  631. )";
  632. // clang-format on
  633. std::unique_ptr<IRContext> context =
  634. BuildModule(SPV_ENV_UNIVERSAL_1_0, nullptr, text,
  635. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  636. Module* module = context->module();
  637. EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n"
  638. << text << std::endl;
  639. const Function* fn = spvtest::GetFunction(module, 1);
  640. const BasicBlock* entry = spvtest::GetBasicBlock(fn, 10);
  641. EXPECT_EQ(entry, fn->entry().get())
  642. << "The entry node is not the expected one";
  643. // Check normal dominator tree
  644. {
  645. DominatorAnalysis dom_tree;
  646. const CFG& cfg = *context->cfg();
  647. dom_tree.InitializeTree(cfg, fn);
  648. // Inspect the actual tree
  649. DominatorTree& tree = dom_tree.GetDomTree();
  650. EXPECT_EQ(tree.GetRoot()->bb_, cfg.pseudo_entry_block());
  651. EXPECT_TRUE(
  652. dom_tree.Dominates(cfg.pseudo_entry_block()->id(), entry->id()));
  653. // (strict) dominance checks
  654. for (uint32_t id : {10, 11, 12, 13}) check_dominance(dom_tree, fn, id, id);
  655. check_dominance(dom_tree, fn, 10, 11);
  656. check_dominance(dom_tree, fn, 10, 12);
  657. check_dominance(dom_tree, fn, 10, 13);
  658. check_dominance(dom_tree, fn, 11, 12);
  659. check_dominance(dom_tree, fn, 11, 13);
  660. check_no_dominance(dom_tree, fn, 13, 12);
  661. EXPECT_EQ(dom_tree.ImmediateDominator(cfg.pseudo_entry_block()), nullptr);
  662. EXPECT_EQ(dom_tree.ImmediateDominator(entry), cfg.pseudo_entry_block());
  663. EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 11)),
  664. spvtest::GetBasicBlock(fn, 10));
  665. EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 12)),
  666. spvtest::GetBasicBlock(fn, 11));
  667. EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 13)),
  668. spvtest::GetBasicBlock(fn, 11));
  669. }
  670. // Check post dominator tree
  671. {
  672. PostDominatorAnalysis dom_tree;
  673. const CFG& cfg = *context->cfg();
  674. dom_tree.InitializeTree(cfg, fn);
  675. // Inspect the actual tree
  676. DominatorTree& tree = dom_tree.GetDomTree();
  677. EXPECT_EQ(tree.GetRoot()->bb_, cfg.pseudo_exit_block());
  678. EXPECT_TRUE(dom_tree.Dominates(cfg.pseudo_exit_block()->id(), 12));
  679. // (strict) dominance checks
  680. for (uint32_t id : {10, 11, 12}) check_dominance(dom_tree, fn, id, id);
  681. check_dominance(dom_tree, fn, 12, 11);
  682. check_dominance(dom_tree, fn, 12, 10);
  683. // 13 should be completely out of tree as it's unreachable from exit nodes
  684. check_no_dominance(dom_tree, fn, 12, 13);
  685. check_no_dominance(dom_tree, fn, 11, 13);
  686. check_no_dominance(dom_tree, fn, 10, 13);
  687. EXPECT_EQ(dom_tree.ImmediateDominator(cfg.pseudo_exit_block()), nullptr);
  688. EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 12)),
  689. cfg.pseudo_exit_block());
  690. EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 10)),
  691. spvtest::GetBasicBlock(fn, 11));
  692. EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 11)),
  693. spvtest::GetBasicBlock(fn, 12));
  694. }
  695. }
  696. TEST_F(PassClassTest, DominatorUnreachableFromEntry) {
  697. const std::string text = R"(
  698. OpCapability Addresses
  699. OpCapability Addresses
  700. OpCapability Kernel
  701. OpMemoryModel Physical64 OpenCL
  702. OpEntryPoint Kernel %1 "main"
  703. %2 = OpTypeVoid
  704. %3 = OpTypeFunction %2
  705. %4 = OpTypeBool
  706. %5 = OpTypeInt 32 0
  707. %6 = OpConstantFalse %4
  708. %7 = OpConstantTrue %4
  709. %1 = OpFunction %2 None %3
  710. %8 = OpLabel
  711. OpBranch %9
  712. %9 = OpLabel
  713. OpReturn
  714. %10 = OpLabel
  715. OpBranch %9
  716. OpFunctionEnd
  717. )";
  718. // clang-format on
  719. std::unique_ptr<IRContext> context =
  720. BuildModule(SPV_ENV_UNIVERSAL_1_0, nullptr, text,
  721. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  722. Module* module = context->module();
  723. EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n"
  724. << text << std::endl;
  725. const Function* fn = spvtest::GetFunction(module, 1);
  726. const BasicBlock* entry = spvtest::GetBasicBlock(fn, 8);
  727. EXPECT_EQ(entry, fn->entry().get())
  728. << "The entry node is not the expected one";
  729. // Check dominator tree
  730. {
  731. DominatorAnalysis dom_tree;
  732. const CFG& cfg = *context->cfg();
  733. dom_tree.InitializeTree(cfg, fn);
  734. // Inspect the actual tree
  735. DominatorTree& tree = dom_tree.GetDomTree();
  736. EXPECT_EQ(tree.GetRoot()->bb_, cfg.pseudo_entry_block());
  737. EXPECT_TRUE(
  738. dom_tree.Dominates(cfg.pseudo_entry_block()->id(), entry->id()));
  739. // (strict) dominance checks
  740. for (uint32_t id : {8, 9}) check_dominance(dom_tree, fn, id, id);
  741. check_dominance(dom_tree, fn, 8, 9);
  742. check_no_dominance(dom_tree, fn, 10, 8);
  743. check_no_dominance(dom_tree, fn, 10, 9);
  744. EXPECT_EQ(dom_tree.ImmediateDominator(cfg.pseudo_entry_block()), nullptr);
  745. EXPECT_EQ(dom_tree.ImmediateDominator(entry), cfg.pseudo_entry_block());
  746. EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 9)),
  747. spvtest::GetBasicBlock(fn, 8));
  748. EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 10)),
  749. nullptr);
  750. }
  751. // Check post dominator tree
  752. {
  753. PostDominatorAnalysis dom_tree;
  754. const CFG& cfg = *context->cfg();
  755. dom_tree.InitializeTree(cfg, fn);
  756. // Inspect the actual tree
  757. DominatorTree& tree = dom_tree.GetDomTree();
  758. EXPECT_EQ(tree.GetRoot()->bb_, cfg.pseudo_exit_block());
  759. EXPECT_TRUE(dom_tree.Dominates(cfg.pseudo_exit_block()->id(), 9));
  760. // (strict) dominance checks
  761. for (uint32_t id : {8, 9, 10}) check_dominance(dom_tree, fn, id, id);
  762. check_dominance(dom_tree, fn, 9, 8);
  763. check_dominance(dom_tree, fn, 9, 10);
  764. EXPECT_EQ(dom_tree.ImmediateDominator(entry),
  765. spvtest::GetBasicBlock(fn, 9));
  766. EXPECT_EQ(dom_tree.ImmediateDominator(cfg.pseudo_exit_block()), nullptr);
  767. EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 9)),
  768. cfg.pseudo_exit_block());
  769. EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 10)),
  770. spvtest::GetBasicBlock(fn, 9));
  771. }
  772. }
  773. TEST_F(PassClassTest, DominationForInstructions) {
  774. const std::string text = R"(
  775. OpCapability Shader
  776. %1 = OpExtInstImport "GLSL.std.450"
  777. OpMemoryModel Logical GLSL450
  778. OpEntryPoint Fragment %4 "main"
  779. OpExecutionMode %4 OriginUpperLeft
  780. OpSource ESSL 310
  781. %2 = OpTypeVoid
  782. %3 = OpTypeFunction %2
  783. %6 = OpTypeInt 32 1
  784. %7 = OpTypeBool
  785. %8 = OpConstantTrue %7
  786. %9 = OpConstant %6 37
  787. %10 = OpConstant %6 3
  788. %13 = OpConstant %6 5
  789. %4 = OpFunction %2 None %3
  790. %5 = OpLabel
  791. %12 = OpIAdd %6 %9 %10
  792. %15 = OpISub %6 %12 %13
  793. OpSelectionMerge %18 None
  794. OpBranchConditional %8 %16 %17
  795. %16 = OpLabel
  796. %20 = OpISub %6 %12 %13
  797. OpBranch %18
  798. %17 = OpLabel
  799. %21 = OpISub %6 %12 %13
  800. OpBranch %18
  801. %18 = OpLabel
  802. %22 = OpISub %6 %12 %13
  803. OpReturn
  804. OpFunctionEnd
  805. )";
  806. // clang-format on
  807. std::unique_ptr<IRContext> context =
  808. BuildModule(SPV_ENV_UNIVERSAL_1_0, nullptr, text,
  809. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  810. EXPECT_NE(nullptr, context->module()) << "Assembling failed for shader:\n"
  811. << text << std::endl;
  812. {
  813. const DominatorAnalysis* dominator_analysis = context->GetDominatorAnalysis(
  814. spvtest::GetFunction(context->module(), 4));
  815. EXPECT_TRUE(
  816. dominator_analysis->Dominates(context->get_def_use_mgr()->GetDef(12),
  817. context->get_def_use_mgr()->GetDef(15)));
  818. EXPECT_FALSE(
  819. dominator_analysis->Dominates(context->get_def_use_mgr()->GetDef(15),
  820. context->get_def_use_mgr()->GetDef(12)));
  821. EXPECT_TRUE(
  822. dominator_analysis->Dominates(context->get_def_use_mgr()->GetDef(5),
  823. context->get_def_use_mgr()->GetDef(12)));
  824. EXPECT_FALSE(
  825. dominator_analysis->Dominates(context->get_def_use_mgr()->GetDef(12),
  826. context->get_def_use_mgr()->GetDef(5)));
  827. EXPECT_TRUE(
  828. dominator_analysis->Dominates(context->get_def_use_mgr()->GetDef(15),
  829. context->get_def_use_mgr()->GetDef(16)));
  830. EXPECT_TRUE(
  831. dominator_analysis->Dominates(context->get_def_use_mgr()->GetDef(15),
  832. context->get_def_use_mgr()->GetDef(21)));
  833. EXPECT_TRUE(
  834. dominator_analysis->Dominates(context->get_def_use_mgr()->GetDef(15),
  835. context->get_def_use_mgr()->GetDef(18)));
  836. EXPECT_TRUE(
  837. dominator_analysis->Dominates(context->get_def_use_mgr()->GetDef(15),
  838. context->get_def_use_mgr()->GetDef(22)));
  839. EXPECT_FALSE(
  840. dominator_analysis->Dominates(context->get_def_use_mgr()->GetDef(20),
  841. context->get_def_use_mgr()->GetDef(22)));
  842. EXPECT_FALSE(
  843. dominator_analysis->Dominates(context->get_def_use_mgr()->GetDef(21),
  844. context->get_def_use_mgr()->GetDef(22)));
  845. EXPECT_TRUE(
  846. dominator_analysis->Dominates(context->get_def_use_mgr()->GetDef(15),
  847. context->get_def_use_mgr()->GetDef(15)));
  848. }
  849. {
  850. const PostDominatorAnalysis* post_dominator_analysis =
  851. context->GetPostDominatorAnalysis(
  852. spvtest::GetFunction(context->module(), 4));
  853. EXPECT_TRUE(post_dominator_analysis->Dominates(
  854. context->get_def_use_mgr()->GetDef(15),
  855. context->get_def_use_mgr()->GetDef(12)));
  856. EXPECT_FALSE(post_dominator_analysis->Dominates(
  857. context->get_def_use_mgr()->GetDef(12),
  858. context->get_def_use_mgr()->GetDef(15)));
  859. EXPECT_TRUE(post_dominator_analysis->Dominates(
  860. context->get_def_use_mgr()->GetDef(12),
  861. context->get_def_use_mgr()->GetDef(5)));
  862. EXPECT_FALSE(post_dominator_analysis->Dominates(
  863. context->get_def_use_mgr()->GetDef(5),
  864. context->get_def_use_mgr()->GetDef(12)));
  865. EXPECT_FALSE(post_dominator_analysis->Dominates(
  866. context->get_def_use_mgr()->GetDef(16),
  867. context->get_def_use_mgr()->GetDef(15)));
  868. EXPECT_FALSE(post_dominator_analysis->Dominates(
  869. context->get_def_use_mgr()->GetDef(21),
  870. context->get_def_use_mgr()->GetDef(15)));
  871. EXPECT_TRUE(post_dominator_analysis->Dominates(
  872. context->get_def_use_mgr()->GetDef(18),
  873. context->get_def_use_mgr()->GetDef(15)));
  874. EXPECT_TRUE(post_dominator_analysis->Dominates(
  875. context->get_def_use_mgr()->GetDef(22),
  876. context->get_def_use_mgr()->GetDef(15)));
  877. EXPECT_TRUE(post_dominator_analysis->Dominates(
  878. context->get_def_use_mgr()->GetDef(22),
  879. context->get_def_use_mgr()->GetDef(20)));
  880. EXPECT_TRUE(post_dominator_analysis->Dominates(
  881. context->get_def_use_mgr()->GetDef(22),
  882. context->get_def_use_mgr()->GetDef(21)));
  883. EXPECT_TRUE(post_dominator_analysis->Dominates(
  884. context->get_def_use_mgr()->GetDef(15),
  885. context->get_def_use_mgr()->GetDef(15)));
  886. }
  887. }
  888. } // namespace
  889. } // namespace opt
  890. } // namespace spvtools