value_table_test.cpp 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831
  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 <string>
  15. #include "gmock/gmock.h"
  16. #include "source/opt/build_module.h"
  17. #include "source/opt/value_number_table.h"
  18. #include "test/opt/pass_fixture.h"
  19. namespace spvtools {
  20. namespace opt {
  21. namespace {
  22. using ::testing::HasSubstr;
  23. using ::testing::MatchesRegex;
  24. using ValueTableTest = PassTest<::testing::Test>;
  25. TEST_F(ValueTableTest, SameInstructionSameValue) {
  26. const std::string text = R"(
  27. OpCapability Shader
  28. %1 = OpExtInstImport "GLSL.std.450"
  29. OpMemoryModel Logical GLSL450
  30. OpEntryPoint Fragment %2 "main"
  31. OpExecutionMode %2 OriginUpperLeft
  32. OpSource GLSL 430
  33. %3 = OpTypeVoid
  34. %4 = OpTypeFunction %3
  35. %5 = OpTypeFloat 32
  36. %6 = OpTypePointer Function %5
  37. %2 = OpFunction %3 None %4
  38. %7 = OpLabel
  39. %8 = OpVariable %6 Function
  40. %9 = OpLoad %5 %8
  41. %10 = OpFAdd %5 %9 %9
  42. OpReturn
  43. OpFunctionEnd
  44. )";
  45. auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
  46. ValueNumberTable vtable(context.get());
  47. Instruction* inst = context->get_def_use_mgr()->GetDef(10);
  48. EXPECT_EQ(vtable.GetValueNumber(inst), vtable.GetValueNumber(inst));
  49. }
  50. TEST_F(ValueTableTest, DifferentInstructionSameValue) {
  51. const std::string text = R"(
  52. OpCapability Shader
  53. %1 = OpExtInstImport "GLSL.std.450"
  54. OpMemoryModel Logical GLSL450
  55. OpEntryPoint Fragment %2 "main"
  56. OpExecutionMode %2 OriginUpperLeft
  57. OpSource GLSL 430
  58. %3 = OpTypeVoid
  59. %4 = OpTypeFunction %3
  60. %5 = OpTypeFloat 32
  61. %6 = OpTypePointer Function %5
  62. %2 = OpFunction %3 None %4
  63. %7 = OpLabel
  64. %8 = OpVariable %6 Function
  65. %9 = OpLoad %5 %8
  66. %10 = OpFAdd %5 %9 %9
  67. %11 = OpFAdd %5 %9 %9
  68. OpReturn
  69. OpFunctionEnd
  70. )";
  71. auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
  72. ValueNumberTable vtable(context.get());
  73. Instruction* inst1 = context->get_def_use_mgr()->GetDef(10);
  74. Instruction* inst2 = context->get_def_use_mgr()->GetDef(11);
  75. EXPECT_EQ(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2));
  76. }
  77. TEST_F(ValueTableTest, SameValueDifferentBlock) {
  78. const std::string text = R"(
  79. OpCapability Shader
  80. %1 = OpExtInstImport "GLSL.std.450"
  81. OpMemoryModel Logical GLSL450
  82. OpEntryPoint Fragment %2 "main"
  83. OpExecutionMode %2 OriginUpperLeft
  84. OpSource GLSL 430
  85. %3 = OpTypeVoid
  86. %4 = OpTypeFunction %3
  87. %5 = OpTypeFloat 32
  88. %6 = OpTypePointer Function %5
  89. %2 = OpFunction %3 None %4
  90. %7 = OpLabel
  91. %8 = OpVariable %6 Function
  92. %9 = OpLoad %5 %8
  93. %10 = OpFAdd %5 %9 %9
  94. OpBranch %11
  95. %11 = OpLabel
  96. %12 = OpFAdd %5 %9 %9
  97. OpReturn
  98. OpFunctionEnd
  99. )";
  100. auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
  101. ValueNumberTable vtable(context.get());
  102. Instruction* inst1 = context->get_def_use_mgr()->GetDef(10);
  103. Instruction* inst2 = context->get_def_use_mgr()->GetDef(12);
  104. EXPECT_EQ(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2));
  105. }
  106. TEST_F(ValueTableTest, DifferentValue) {
  107. const std::string text = R"(
  108. OpCapability Shader
  109. %1 = OpExtInstImport "GLSL.std.450"
  110. OpMemoryModel Logical GLSL450
  111. OpEntryPoint Fragment %2 "main"
  112. OpExecutionMode %2 OriginUpperLeft
  113. OpSource GLSL 430
  114. %3 = OpTypeVoid
  115. %4 = OpTypeFunction %3
  116. %5 = OpTypeFloat 32
  117. %6 = OpTypePointer Function %5
  118. %2 = OpFunction %3 None %4
  119. %7 = OpLabel
  120. %8 = OpVariable %6 Function
  121. %9 = OpLoad %5 %8
  122. %10 = OpFAdd %5 %9 %9
  123. %11 = OpFAdd %5 %9 %10
  124. OpReturn
  125. OpFunctionEnd
  126. )";
  127. auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
  128. ValueNumberTable vtable(context.get());
  129. Instruction* inst1 = context->get_def_use_mgr()->GetDef(10);
  130. Instruction* inst2 = context->get_def_use_mgr()->GetDef(11);
  131. EXPECT_NE(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2));
  132. }
  133. TEST_F(ValueTableTest, DifferentValueDifferentBlock) {
  134. const std::string text = R"(
  135. OpCapability Shader
  136. %1 = OpExtInstImport "GLSL.std.450"
  137. OpMemoryModel Logical GLSL450
  138. OpEntryPoint Fragment %2 "main"
  139. OpExecutionMode %2 OriginUpperLeft
  140. OpSource GLSL 430
  141. %3 = OpTypeVoid
  142. %4 = OpTypeFunction %3
  143. %5 = OpTypeFloat 32
  144. %6 = OpTypePointer Function %5
  145. %2 = OpFunction %3 None %4
  146. %7 = OpLabel
  147. %8 = OpVariable %6 Function
  148. %9 = OpLoad %5 %8
  149. %10 = OpFAdd %5 %9 %9
  150. OpBranch %11
  151. %11 = OpLabel
  152. %12 = OpFAdd %5 %9 %10
  153. OpReturn
  154. OpFunctionEnd
  155. )";
  156. auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
  157. ValueNumberTable vtable(context.get());
  158. Instruction* inst1 = context->get_def_use_mgr()->GetDef(10);
  159. Instruction* inst2 = context->get_def_use_mgr()->GetDef(12);
  160. EXPECT_NE(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2));
  161. }
  162. TEST_F(ValueTableTest, SameLoad) {
  163. const std::string text = R"(
  164. OpCapability Shader
  165. %1 = OpExtInstImport "GLSL.std.450"
  166. OpMemoryModel Logical GLSL450
  167. OpEntryPoint Fragment %2 "main"
  168. OpExecutionMode %2 OriginUpperLeft
  169. OpSource GLSL 430
  170. %3 = OpTypeVoid
  171. %4 = OpTypeFunction %3
  172. %5 = OpTypeFloat 32
  173. %6 = OpTypePointer Function %5
  174. %2 = OpFunction %3 None %4
  175. %7 = OpLabel
  176. %8 = OpVariable %6 Function
  177. %9 = OpLoad %5 %8
  178. OpReturn
  179. OpFunctionEnd
  180. )";
  181. auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
  182. ValueNumberTable vtable(context.get());
  183. Instruction* inst = context->get_def_use_mgr()->GetDef(9);
  184. EXPECT_EQ(vtable.GetValueNumber(inst), vtable.GetValueNumber(inst));
  185. }
  186. // Two different loads, even from the same memory, must given different value
  187. // numbers if the memory is not read-only.
  188. TEST_F(ValueTableTest, DifferentFunctionLoad) {
  189. const std::string text = R"(
  190. OpCapability Shader
  191. %1 = OpExtInstImport "GLSL.std.450"
  192. OpMemoryModel Logical GLSL450
  193. OpEntryPoint Fragment %2 "main"
  194. OpExecutionMode %2 OriginUpperLeft
  195. OpSource GLSL 430
  196. %3 = OpTypeVoid
  197. %4 = OpTypeFunction %3
  198. %5 = OpTypeFloat 32
  199. %6 = OpTypePointer Function %5
  200. %2 = OpFunction %3 None %4
  201. %7 = OpLabel
  202. %8 = OpVariable %6 Function
  203. %9 = OpLoad %5 %8
  204. %10 = OpLoad %5 %8
  205. OpReturn
  206. OpFunctionEnd
  207. )";
  208. auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
  209. ValueNumberTable vtable(context.get());
  210. Instruction* inst1 = context->get_def_use_mgr()->GetDef(9);
  211. Instruction* inst2 = context->get_def_use_mgr()->GetDef(10);
  212. EXPECT_NE(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2));
  213. }
  214. TEST_F(ValueTableTest, DifferentUniformLoad) {
  215. const std::string text = R"(
  216. OpCapability Shader
  217. %1 = OpExtInstImport "GLSL.std.450"
  218. OpMemoryModel Logical GLSL450
  219. OpEntryPoint Fragment %2 "main"
  220. OpExecutionMode %2 OriginUpperLeft
  221. OpSource GLSL 430
  222. %3 = OpTypeVoid
  223. %4 = OpTypeFunction %3
  224. %5 = OpTypeFloat 32
  225. %6 = OpTypePointer Uniform %5
  226. %8 = OpVariable %6 Uniform
  227. %2 = OpFunction %3 None %4
  228. %7 = OpLabel
  229. %9 = OpLoad %5 %8
  230. %10 = OpLoad %5 %8
  231. OpReturn
  232. OpFunctionEnd
  233. )";
  234. auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
  235. ValueNumberTable vtable(context.get());
  236. Instruction* inst1 = context->get_def_use_mgr()->GetDef(9);
  237. Instruction* inst2 = context->get_def_use_mgr()->GetDef(10);
  238. EXPECT_EQ(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2));
  239. }
  240. TEST_F(ValueTableTest, DifferentInputLoad) {
  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 = OpTypeVoid
  249. %4 = OpTypeFunction %3
  250. %5 = OpTypeFloat 32
  251. %6 = OpTypePointer Input %5
  252. %8 = OpVariable %6 Input
  253. %2 = OpFunction %3 None %4
  254. %7 = OpLabel
  255. %9 = OpLoad %5 %8
  256. %10 = OpLoad %5 %8
  257. OpReturn
  258. OpFunctionEnd
  259. )";
  260. auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
  261. ValueNumberTable vtable(context.get());
  262. Instruction* inst1 = context->get_def_use_mgr()->GetDef(9);
  263. Instruction* inst2 = context->get_def_use_mgr()->GetDef(10);
  264. EXPECT_EQ(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2));
  265. }
  266. TEST_F(ValueTableTest, DifferentUniformConstantLoad) {
  267. const std::string text = R"(
  268. OpCapability Shader
  269. %1 = OpExtInstImport "GLSL.std.450"
  270. OpMemoryModel Logical GLSL450
  271. OpEntryPoint Fragment %2 "main"
  272. OpExecutionMode %2 OriginUpperLeft
  273. OpSource GLSL 430
  274. %3 = OpTypeVoid
  275. %4 = OpTypeFunction %3
  276. %5 = OpTypeFloat 32
  277. %6 = OpTypePointer UniformConstant %5
  278. %8 = OpVariable %6 UniformConstant
  279. %2 = OpFunction %3 None %4
  280. %7 = OpLabel
  281. %9 = OpLoad %5 %8
  282. %10 = OpLoad %5 %8
  283. OpReturn
  284. OpFunctionEnd
  285. )";
  286. auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
  287. ValueNumberTable vtable(context.get());
  288. Instruction* inst1 = context->get_def_use_mgr()->GetDef(9);
  289. Instruction* inst2 = context->get_def_use_mgr()->GetDef(10);
  290. EXPECT_EQ(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2));
  291. }
  292. TEST_F(ValueTableTest, DifferentPushConstantLoad) {
  293. const std::string text = R"(
  294. OpCapability Shader
  295. %1 = OpExtInstImport "GLSL.std.450"
  296. OpMemoryModel Logical GLSL450
  297. OpEntryPoint Fragment %2 "main"
  298. OpExecutionMode %2 OriginUpperLeft
  299. OpSource GLSL 430
  300. %3 = OpTypeVoid
  301. %4 = OpTypeFunction %3
  302. %5 = OpTypeFloat 32
  303. %6 = OpTypePointer PushConstant %5
  304. %8 = OpVariable %6 PushConstant
  305. %2 = OpFunction %3 None %4
  306. %7 = OpLabel
  307. %9 = OpLoad %5 %8
  308. %10 = OpLoad %5 %8
  309. OpReturn
  310. OpFunctionEnd
  311. )";
  312. auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
  313. ValueNumberTable vtable(context.get());
  314. Instruction* inst1 = context->get_def_use_mgr()->GetDef(9);
  315. Instruction* inst2 = context->get_def_use_mgr()->GetDef(10);
  316. EXPECT_EQ(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2));
  317. }
  318. TEST_F(ValueTableTest, SameCall) {
  319. const std::string text = R"(
  320. OpCapability Shader
  321. %1 = OpExtInstImport "GLSL.std.450"
  322. OpMemoryModel Logical GLSL450
  323. OpEntryPoint Fragment %2 "main"
  324. OpExecutionMode %2 OriginUpperLeft
  325. OpSource GLSL 430
  326. %3 = OpTypeVoid
  327. %4 = OpTypeFunction %3
  328. %5 = OpTypeFloat 32
  329. %6 = OpTypeFunction %5
  330. %7 = OpTypePointer Function %5
  331. %8 = OpVariable %7 Private
  332. %2 = OpFunction %3 None %4
  333. %9 = OpLabel
  334. %10 = OpFunctionCall %5 %11
  335. OpReturn
  336. OpFunctionEnd
  337. %11 = OpFunction %5 None %6
  338. %12 = OpLabel
  339. %13 = OpLoad %5 %8
  340. OpReturnValue %13
  341. OpFunctionEnd
  342. )";
  343. auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
  344. ValueNumberTable vtable(context.get());
  345. Instruction* inst = context->get_def_use_mgr()->GetDef(10);
  346. EXPECT_EQ(vtable.GetValueNumber(inst), vtable.GetValueNumber(inst));
  347. }
  348. // Function calls should be given a new value number, even if they are the same.
  349. TEST_F(ValueTableTest, DifferentCall) {
  350. const std::string text = R"(
  351. OpCapability Shader
  352. %1 = OpExtInstImport "GLSL.std.450"
  353. OpMemoryModel Logical GLSL450
  354. OpEntryPoint Fragment %2 "main"
  355. OpExecutionMode %2 OriginUpperLeft
  356. OpSource GLSL 430
  357. %3 = OpTypeVoid
  358. %4 = OpTypeFunction %3
  359. %5 = OpTypeFloat 32
  360. %6 = OpTypeFunction %5
  361. %7 = OpTypePointer Function %5
  362. %8 = OpVariable %7 Private
  363. %2 = OpFunction %3 None %4
  364. %9 = OpLabel
  365. %10 = OpFunctionCall %5 %11
  366. %12 = OpFunctionCall %5 %11
  367. OpReturn
  368. OpFunctionEnd
  369. %11 = OpFunction %5 None %6
  370. %13 = OpLabel
  371. %14 = OpLoad %5 %8
  372. OpReturnValue %14
  373. OpFunctionEnd
  374. )";
  375. auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
  376. ValueNumberTable vtable(context.get());
  377. Instruction* inst1 = context->get_def_use_mgr()->GetDef(10);
  378. Instruction* inst2 = context->get_def_use_mgr()->GetDef(12);
  379. EXPECT_NE(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2));
  380. }
  381. // It is possible to have two instruction that compute the same numerical value,
  382. // but with different types. They should have different value numbers.
  383. TEST_F(ValueTableTest, DifferentTypes) {
  384. const std::string text = R"(
  385. OpCapability Shader
  386. %1 = OpExtInstImport "GLSL.std.450"
  387. OpMemoryModel Logical GLSL450
  388. OpEntryPoint Fragment %2 "main"
  389. OpExecutionMode %2 OriginUpperLeft
  390. OpSource GLSL 430
  391. %3 = OpTypeVoid
  392. %4 = OpTypeFunction %3
  393. %5 = OpTypeInt 32 0
  394. %6 = OpTypeInt 32 1
  395. %7 = OpTypePointer Function %5
  396. %2 = OpFunction %3 None %4
  397. %8 = OpLabel
  398. %9 = OpVariable %7 Function
  399. %10 = OpLoad %5 %9
  400. %11 = OpIAdd %5 %10 %10
  401. %12 = OpIAdd %6 %10 %10
  402. OpReturn
  403. OpFunctionEnd
  404. )";
  405. auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
  406. ValueNumberTable vtable(context.get());
  407. Instruction* inst1 = context->get_def_use_mgr()->GetDef(11);
  408. Instruction* inst2 = context->get_def_use_mgr()->GetDef(12);
  409. EXPECT_NE(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2));
  410. }
  411. TEST_F(ValueTableTest, CopyObject) {
  412. const std::string text = R"(
  413. OpCapability Shader
  414. %1 = OpExtInstImport "GLSL.std.450"
  415. OpMemoryModel Logical GLSL450
  416. OpEntryPoint Fragment %2 "main"
  417. OpExecutionMode %2 OriginUpperLeft
  418. OpSource GLSL 430
  419. %3 = OpTypeVoid
  420. %4 = OpTypeFunction %3
  421. %5 = OpTypeFloat 32
  422. %6 = OpTypePointer Function %5
  423. %2 = OpFunction %3 None %4
  424. %7 = OpLabel
  425. %8 = OpVariable %6 Function
  426. %9 = OpLoad %5 %8
  427. %10 = OpCopyObject %5 %9
  428. OpReturn
  429. OpFunctionEnd
  430. )";
  431. auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
  432. ValueNumberTable vtable(context.get());
  433. Instruction* inst1 = context->get_def_use_mgr()->GetDef(9);
  434. Instruction* inst2 = context->get_def_use_mgr()->GetDef(10);
  435. EXPECT_EQ(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2));
  436. }
  437. TEST_F(ValueTableTest, CopyObjectWitDecoration) {
  438. const std::string text = R"(
  439. OpCapability Shader
  440. %1 = OpExtInstImport "GLSL.std.450"
  441. OpMemoryModel Logical GLSL450
  442. OpEntryPoint Fragment %2 "main"
  443. OpExecutionMode %2 OriginUpperLeft
  444. OpSource GLSL 430
  445. OpDecorate %3 NonUniformEXT
  446. %4 = OpTypeVoid
  447. %5 = OpTypeFunction %4
  448. %6 = OpTypeFloat 32
  449. %7 = OpTypePointer Function %6
  450. %2 = OpFunction %4 None %5
  451. %8 = OpLabel
  452. %9 = OpVariable %7 Function
  453. %10 = OpLoad %6 %9
  454. %3 = OpCopyObject %6 %10
  455. OpReturn
  456. OpFunctionEnd
  457. )";
  458. auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
  459. ValueNumberTable vtable(context.get());
  460. Instruction* inst1 = context->get_def_use_mgr()->GetDef(10);
  461. Instruction* inst2 = context->get_def_use_mgr()->GetDef(3);
  462. EXPECT_NE(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2));
  463. }
  464. // Test that a phi where the operands have the same value assigned that value
  465. // to the result of the phi.
  466. TEST_F(ValueTableTest, PhiTest1) {
  467. const std::string text = R"(
  468. OpCapability Shader
  469. %1 = OpExtInstImport "GLSL.std.450"
  470. OpMemoryModel Logical GLSL450
  471. OpEntryPoint Fragment %2 "main"
  472. OpExecutionMode %2 OriginUpperLeft
  473. OpSource GLSL 430
  474. %3 = OpTypeVoid
  475. %4 = OpTypeFunction %3
  476. %5 = OpTypeFloat 32
  477. %6 = OpTypePointer Uniform %5
  478. %7 = OpTypeBool
  479. %8 = OpConstantTrue %7
  480. %9 = OpVariable %6 Uniform
  481. %2 = OpFunction %3 None %4
  482. %10 = OpLabel
  483. OpBranchConditional %8 %11 %12
  484. %11 = OpLabel
  485. %13 = OpLoad %5 %9
  486. OpBranch %14
  487. %12 = OpLabel
  488. %15 = OpLoad %5 %9
  489. OpBranch %14
  490. %14 = OpLabel
  491. %16 = OpPhi %5 %13 %11 %15 %12
  492. OpReturn
  493. OpFunctionEnd
  494. )";
  495. auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
  496. ValueNumberTable vtable(context.get());
  497. Instruction* inst1 = context->get_def_use_mgr()->GetDef(13);
  498. Instruction* inst2 = context->get_def_use_mgr()->GetDef(15);
  499. Instruction* phi = context->get_def_use_mgr()->GetDef(16);
  500. EXPECT_EQ(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2));
  501. EXPECT_EQ(vtable.GetValueNumber(inst1), vtable.GetValueNumber(phi));
  502. }
  503. TEST_F(ValueTableTest, PhiTest1WithDecoration) {
  504. const std::string text = R"(
  505. OpCapability Shader
  506. %1 = OpExtInstImport "GLSL.std.450"
  507. OpMemoryModel Logical GLSL450
  508. OpEntryPoint Fragment %2 "main"
  509. OpExecutionMode %2 OriginUpperLeft
  510. OpSource GLSL 430
  511. OpDecorate %3 NonUniformEXT
  512. %4 = OpTypeVoid
  513. %5 = OpTypeFunction %5
  514. %6 = OpTypeFloat 32
  515. %7 = OpTypePointer Uniform %6
  516. %8 = OpTypeBool
  517. %9 = OpConstantTrue %8
  518. %10 = OpVariable %7 Uniform
  519. %2 = OpFunction %4 None %5
  520. %11 = OpLabel
  521. OpBranchConditional %9 %12 %13
  522. %12 = OpLabel
  523. %14 = OpLoad %6 %10
  524. OpBranch %15
  525. %13 = OpLabel
  526. %16 = OpLoad %6 %10
  527. OpBranch %15
  528. %15 = OpLabel
  529. %3 = OpPhi %6 %14 %12 %16 %13
  530. OpReturn
  531. OpFunctionEnd
  532. )";
  533. auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
  534. ValueNumberTable vtable(context.get());
  535. Instruction* inst1 = context->get_def_use_mgr()->GetDef(14);
  536. Instruction* inst2 = context->get_def_use_mgr()->GetDef(16);
  537. Instruction* phi = context->get_def_use_mgr()->GetDef(3);
  538. EXPECT_EQ(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2));
  539. EXPECT_NE(vtable.GetValueNumber(inst1), vtable.GetValueNumber(phi));
  540. }
  541. // When the values for the inputs to a phi do not match, then the phi should
  542. // have its own value number.
  543. TEST_F(ValueTableTest, PhiTest2) {
  544. const std::string text = R"(
  545. OpCapability Shader
  546. %1 = OpExtInstImport "GLSL.std.450"
  547. OpMemoryModel Logical GLSL450
  548. OpEntryPoint Fragment %2 "main"
  549. OpExecutionMode %2 OriginUpperLeft
  550. OpSource GLSL 430
  551. %3 = OpTypeVoid
  552. %4 = OpTypeFunction %3
  553. %5 = OpTypeFloat 32
  554. %6 = OpTypePointer Uniform %5
  555. %7 = OpTypeBool
  556. %8 = OpConstantTrue %7
  557. %9 = OpVariable %6 Uniform
  558. %10 = OpVariable %6 Uniform
  559. %2 = OpFunction %3 None %4
  560. %11 = OpLabel
  561. OpBranchConditional %8 %12 %13
  562. %12 = OpLabel
  563. %14 = OpLoad %5 %9
  564. OpBranch %15
  565. %13 = OpLabel
  566. %16 = OpLoad %5 %10
  567. OpBranch %15
  568. %15 = OpLabel
  569. %17 = OpPhi %14 %12 %16 %13
  570. OpReturn
  571. OpFunctionEnd
  572. )";
  573. auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
  574. ValueNumberTable vtable(context.get());
  575. Instruction* inst1 = context->get_def_use_mgr()->GetDef(14);
  576. Instruction* inst2 = context->get_def_use_mgr()->GetDef(16);
  577. Instruction* phi = context->get_def_use_mgr()->GetDef(17);
  578. EXPECT_NE(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2));
  579. EXPECT_NE(vtable.GetValueNumber(inst1), vtable.GetValueNumber(phi));
  580. EXPECT_NE(vtable.GetValueNumber(inst2), vtable.GetValueNumber(phi));
  581. }
  582. // Test that a phi node in a loop header gets a new value because one of its
  583. // inputs comes from later in the loop.
  584. TEST_F(ValueTableTest, PhiLoopTest) {
  585. const std::string text = R"(
  586. OpCapability Shader
  587. %1 = OpExtInstImport "GLSL.std.450"
  588. OpMemoryModel Logical GLSL450
  589. OpEntryPoint Fragment %2 "main"
  590. OpExecutionMode %2 OriginUpperLeft
  591. OpSource GLSL 430
  592. %3 = OpTypeVoid
  593. %4 = OpTypeFunction %3
  594. %5 = OpTypeFloat 32
  595. %6 = OpTypePointer Uniform %5
  596. %7 = OpTypeBool
  597. %8 = OpConstantTrue %7
  598. %9 = OpVariable %6 Uniform
  599. %10 = OpVariable %6 Uniform
  600. %2 = OpFunction %3 None %4
  601. %11 = OpLabel
  602. %12 = OpLoad %5 %9
  603. OpSelectionMerge %13 None
  604. OpBranchConditional %8 %14 %13
  605. %14 = OpLabel
  606. %15 = OpPhi %5 %12 %11 %16 %14
  607. %16 = OpLoad %5 %9
  608. OpLoopMerge %17 %14 None
  609. OpBranchConditional %8 %14 %17
  610. %17 = OpLabel
  611. OpBranch %13
  612. %13 = OpLabel
  613. %18 = OpPhi %5 %12 %11 %16 %17
  614. OpReturn
  615. OpFunctionEnd
  616. )";
  617. auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
  618. ValueNumberTable vtable(context.get());
  619. Instruction* inst1 = context->get_def_use_mgr()->GetDef(12);
  620. Instruction* inst2 = context->get_def_use_mgr()->GetDef(16);
  621. EXPECT_EQ(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2));
  622. Instruction* phi1 = context->get_def_use_mgr()->GetDef(15);
  623. EXPECT_NE(vtable.GetValueNumber(inst1), vtable.GetValueNumber(phi1));
  624. Instruction* phi2 = context->get_def_use_mgr()->GetDef(18);
  625. EXPECT_EQ(vtable.GetValueNumber(inst1), vtable.GetValueNumber(phi2));
  626. EXPECT_NE(vtable.GetValueNumber(phi1), vtable.GetValueNumber(phi2));
  627. }
  628. // Test to make sure that OpPhi instructions with no in operands are handled
  629. // correctly.
  630. TEST_F(ValueTableTest, EmptyPhiTest) {
  631. const std::string text = R"(
  632. OpCapability Shader
  633. %1 = OpExtInstImport "GLSL.std.450"
  634. OpMemoryModel Logical GLSL450
  635. OpEntryPoint Fragment %2 "main"
  636. OpExecutionMode %2 OriginUpperLeft
  637. OpSource GLSL 430
  638. %void = OpTypeVoid
  639. %4 = OpTypeFunction %void
  640. %bool = OpTypeBool
  641. %true = OpConstantTrue %bool
  642. %2 = OpFunction %void None %4
  643. %7 = OpLabel
  644. OpSelectionMerge %8 None
  645. OpBranchConditional %true %9 %8
  646. %9 = OpLabel
  647. OpKill
  648. %8 = OpLabel
  649. %10 = OpPhi %bool
  650. OpReturn
  651. OpFunctionEnd
  652. )";
  653. auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
  654. ValueNumberTable vtable(context.get());
  655. Instruction* inst = context->get_def_use_mgr()->GetDef(10);
  656. vtable.GetValueNumber(inst);
  657. }
  658. TEST_F(ValueTableTest, RedundantSampledImageLoad) {
  659. const std::string text = R"(
  660. OpCapability Shader
  661. %1 = OpExtInstImport "GLSL.std.450"
  662. OpMemoryModel Logical GLSL450
  663. OpEntryPoint Fragment %main "main" %gl_FragColor
  664. OpExecutionMode %main OriginLowerLeft
  665. OpSource GLSL 330
  666. OpName %main "main"
  667. OpName %tex0 "tex0"
  668. OpName %gl_FragColor "gl_FragColor"
  669. OpDecorate %tex0 Location 0
  670. OpDecorate %tex0 DescriptorSet 0
  671. OpDecorate %tex0 Binding 0
  672. OpDecorate %gl_FragColor Location 0
  673. %void = OpTypeVoid
  674. %6 = OpTypeFunction %void
  675. %float = OpTypeFloat 32
  676. %v4float = OpTypeVector %float 4
  677. %9 = OpTypeImage %float 2D 0 0 0 1 Unknown
  678. %10 = OpTypeSampledImage %9
  679. %_ptr_UniformConstant_10 = OpTypePointer UniformConstant %10
  680. %tex0 = OpVariable %_ptr_UniformConstant_10 UniformConstant
  681. %_ptr_Output_v4float = OpTypePointer Output %v4float
  682. %13 = OpConstantNull %v4float
  683. %gl_FragColor = OpVariable %_ptr_Output_v4float Output
  684. %14 = OpUndef %v4float
  685. %main = OpFunction %void None %6
  686. %15 = OpLabel
  687. %16 = OpLoad %10 %tex0
  688. %17 = OpImageSampleProjImplicitLod %v4float %16 %13
  689. %18 = OpImageSampleProjImplicitLod %v4float %16 %13
  690. %19 = OpFAdd %v4float %18 %17
  691. OpStore %gl_FragColor %19
  692. OpReturn
  693. OpFunctionEnd
  694. )";
  695. auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
  696. ValueNumberTable vtable(context.get());
  697. Instruction* load1 = context->get_def_use_mgr()->GetDef(17);
  698. Instruction* load2 = context->get_def_use_mgr()->GetDef(18);
  699. EXPECT_EQ(vtable.GetValueNumber(load1), vtable.GetValueNumber(load2));
  700. }
  701. TEST_F(ValueTableTest, DifferentDebugLocalVariableSameValue) {
  702. const std::string text = R"(
  703. OpCapability Shader
  704. %1 = OpExtInstImport "GLSL.std.450"
  705. %2 = OpExtInstImport "OpenCL.DebugInfo.100"
  706. OpMemoryModel Logical GLSL450
  707. OpEntryPoint Fragment %3 "main"
  708. OpExecutionMode %3 OriginUpperLeft
  709. OpSource GLSL 430
  710. %4 = OpString "test"
  711. %5 = OpTypeVoid
  712. %6 = OpTypeFunction %5
  713. %7 = OpTypeInt 32 0
  714. %8 = OpConstant %7 32
  715. %9 = OpExtInst %5 %2 DebugSource %4
  716. %10 = OpExtInst %5 %2 DebugCompilationUnit 1 4 %9 HLSL
  717. %11 = OpExtInst %5 %2 DebugTypeBasic %4 %8 Float
  718. %12 = OpExtInst %5 %2 DebugLocalVariable %4 %11 %9 0 0 %10 FlagIsLocal
  719. %13 = OpExtInst %5 %2 DebugLocalVariable %4 %11 %9 0 0 %10 FlagIsLocal
  720. %3 = OpFunction %5 None %6
  721. %14 = OpLabel
  722. OpReturn
  723. OpFunctionEnd
  724. )";
  725. auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
  726. ValueNumberTable vtable(context.get());
  727. Instruction* inst1 = context->get_def_use_mgr()->GetDef(12);
  728. Instruction* inst2 = context->get_def_use_mgr()->GetDef(13);
  729. EXPECT_EQ(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2));
  730. }
  731. TEST_F(ValueTableTest, DifferentDebugValueSameValue) {
  732. const std::string text = R"(
  733. OpCapability Shader
  734. %1 = OpExtInstImport "GLSL.std.450"
  735. %2 = OpExtInstImport "OpenCL.DebugInfo.100"
  736. OpMemoryModel Logical GLSL450
  737. OpEntryPoint Fragment %3 "main"
  738. OpExecutionMode %3 OriginUpperLeft
  739. OpSource GLSL 430
  740. %4 = OpString "test"
  741. %5 = OpTypeVoid
  742. %6 = OpTypeFunction %5
  743. %7 = OpTypeInt 32 0
  744. %8 = OpConstant %7 32
  745. %9 = OpExtInst %5 %2 DebugSource %4
  746. %10 = OpExtInst %5 %2 DebugCompilationUnit 1 4 %9 HLSL
  747. %11 = OpExtInst %5 %2 DebugTypeBasic %4 %8 Float
  748. %12 = OpExtInst %5 %2 DebugLocalVariable %4 %11 %9 0 0 %10 FlagIsLocal
  749. %13 = OpExtInst %5 %2 DebugExpression
  750. %3 = OpFunction %5 None %6
  751. %14 = OpLabel
  752. %15 = OpExtInst %5 %2 DebugValue %12 %8 %13
  753. %16 = OpExtInst %5 %2 DebugValue %12 %8 %13
  754. OpReturn
  755. OpFunctionEnd
  756. )";
  757. auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
  758. ValueNumberTable vtable(context.get());
  759. Instruction* inst1 = context->get_def_use_mgr()->GetDef(15);
  760. Instruction* inst2 = context->get_def_use_mgr()->GetDef(16);
  761. EXPECT_EQ(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2));
  762. }
  763. TEST_F(ValueTableTest, DifferentDebugDeclareSameValue) {
  764. const std::string text = R"(
  765. OpCapability Shader
  766. %1 = OpExtInstImport "GLSL.std.450"
  767. %2 = OpExtInstImport "OpenCL.DebugInfo.100"
  768. OpMemoryModel Logical GLSL450
  769. OpEntryPoint Fragment %3 "main"
  770. OpExecutionMode %3 OriginUpperLeft
  771. OpSource GLSL 430
  772. %4 = OpString "test"
  773. %void = OpTypeVoid
  774. %6 = OpTypeFunction %void
  775. %uint = OpTypeInt 32 0
  776. %_ptr_Function_uint = OpTypePointer Function %uint
  777. %uint_32 = OpConstant %uint 32
  778. %10 = OpExtInst %void %2 DebugSource %4
  779. %11 = OpExtInst %void %2 DebugCompilationUnit 1 4 %10 HLSL
  780. %12 = OpExtInst %void %2 DebugTypeBasic %4 %uint_32 Float
  781. %13 = OpExtInst %void %2 DebugLocalVariable %4 %12 %10 0 0 %11 FlagIsLocal
  782. %14 = OpExtInst %void %2 DebugExpression
  783. %3 = OpFunction %void None %6
  784. %15 = OpLabel
  785. %16 = OpVariable %_ptr_Function_uint Function
  786. %17 = OpExtInst %void %2 DebugDeclare %13 %16 %14
  787. %18 = OpExtInst %void %2 DebugDeclare %13 %16 %14
  788. OpReturn
  789. OpFunctionEnd
  790. )";
  791. auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
  792. ValueNumberTable vtable(context.get());
  793. Instruction* inst1 = context->get_def_use_mgr()->GetDef(17);
  794. Instruction* inst2 = context->get_def_use_mgr()->GetDef(18);
  795. EXPECT_EQ(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2));
  796. }
  797. } // namespace
  798. } // namespace opt
  799. } // namespace spvtools