value_table_test.cpp 30 KB

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