common_uniform_elim_test.cpp 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395
  1. // Copyright (c) 2017 Valve Corporation
  2. // Copyright (c) 2017 LunarG Inc.
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software
  11. // distributed under the License is distributed on an "AS IS" BASIS,
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. // See the License for the specific language governing permissions and
  14. // limitations under the License.
  15. #include <string>
  16. #include "test/opt/pass_fixture.h"
  17. namespace spvtools {
  18. namespace opt {
  19. namespace {
  20. using CommonUniformElimTest = PassTest<::testing::Test>;
  21. TEST_F(CommonUniformElimTest, Basic1) {
  22. // Note: This test exemplifies the following:
  23. // - Common uniform (%_) load floated to nearest non-controlled block
  24. // - Common extract (g_F) floated to non-controlled block
  25. // - Non-common extract (g_F2) not floated, but common uniform load shared
  26. //
  27. // #version 140
  28. // in vec4 BaseColor;
  29. // in float fi;
  30. //
  31. // layout(std140) uniform U_t
  32. // {
  33. // float g_F;
  34. // float g_F2;
  35. // } ;
  36. //
  37. // void main()
  38. // {
  39. // vec4 v = BaseColor;
  40. // if (fi > 0) {
  41. // v = v * g_F;
  42. // }
  43. // else {
  44. // float f2 = g_F2 - g_F;
  45. // v = v * f2;
  46. // }
  47. // gl_FragColor = v;
  48. // }
  49. const std::string predefs =
  50. R"(OpCapability Shader
  51. %1 = OpExtInstImport "GLSL.std.450"
  52. OpMemoryModel Logical GLSL450
  53. OpEntryPoint Fragment %main "main" %BaseColor %fi %gl_FragColor
  54. OpExecutionMode %main OriginUpperLeft
  55. OpSource GLSL 140
  56. OpName %main "main"
  57. OpName %v "v"
  58. OpName %BaseColor "BaseColor"
  59. OpName %fi "fi"
  60. OpName %U_t "U_t"
  61. OpMemberName %U_t 0 "g_F"
  62. OpMemberName %U_t 1 "g_F2"
  63. OpName %_ ""
  64. OpName %f2 "f2"
  65. OpName %gl_FragColor "gl_FragColor"
  66. OpMemberDecorate %U_t 0 Offset 0
  67. OpMemberDecorate %U_t 1 Offset 4
  68. OpDecorate %U_t Block
  69. OpDecorate %_ DescriptorSet 0
  70. %void = OpTypeVoid
  71. %11 = OpTypeFunction %void
  72. %float = OpTypeFloat 32
  73. %v4float = OpTypeVector %float 4
  74. %_ptr_Function_v4float = OpTypePointer Function %v4float
  75. %_ptr_Input_v4float = OpTypePointer Input %v4float
  76. %BaseColor = OpVariable %_ptr_Input_v4float Input
  77. %_ptr_Input_float = OpTypePointer Input %float
  78. %fi = OpVariable %_ptr_Input_float Input
  79. %float_0 = OpConstant %float 0
  80. %bool = OpTypeBool
  81. %U_t = OpTypeStruct %float %float
  82. %_ptr_Uniform_U_t = OpTypePointer Uniform %U_t
  83. %_ = OpVariable %_ptr_Uniform_U_t Uniform
  84. %int = OpTypeInt 32 1
  85. %int_0 = OpConstant %int 0
  86. %_ptr_Uniform_float = OpTypePointer Uniform %float
  87. %_ptr_Function_float = OpTypePointer Function %float
  88. %int_1 = OpConstant %int 1
  89. %_ptr_Output_v4float = OpTypePointer Output %v4float
  90. %gl_FragColor = OpVariable %_ptr_Output_v4float Output
  91. )";
  92. const std::string before =
  93. R"(%main = OpFunction %void None %11
  94. %26 = OpLabel
  95. %v = OpVariable %_ptr_Function_v4float Function
  96. %f2 = OpVariable %_ptr_Function_float Function
  97. %27 = OpLoad %v4float %BaseColor
  98. OpStore %v %27
  99. %28 = OpLoad %float %fi
  100. %29 = OpFOrdGreaterThan %bool %28 %float_0
  101. OpSelectionMerge %30 None
  102. OpBranchConditional %29 %31 %32
  103. %31 = OpLabel
  104. %33 = OpLoad %v4float %v
  105. %34 = OpAccessChain %_ptr_Uniform_float %_ %int_0
  106. %35 = OpLoad %float %34
  107. %36 = OpVectorTimesScalar %v4float %33 %35
  108. OpStore %v %36
  109. OpBranch %30
  110. %32 = OpLabel
  111. %37 = OpAccessChain %_ptr_Uniform_float %_ %int_1
  112. %38 = OpLoad %float %37
  113. %39 = OpAccessChain %_ptr_Uniform_float %_ %int_0
  114. %40 = OpLoad %float %39
  115. %41 = OpFSub %float %38 %40
  116. OpStore %f2 %41
  117. %42 = OpLoad %v4float %v
  118. %43 = OpLoad %float %f2
  119. %44 = OpVectorTimesScalar %v4float %42 %43
  120. OpStore %v %44
  121. OpBranch %30
  122. %30 = OpLabel
  123. %45 = OpLoad %v4float %v
  124. OpStore %gl_FragColor %45
  125. OpReturn
  126. OpFunctionEnd
  127. )";
  128. const std::string after =
  129. R"(%main = OpFunction %void None %11
  130. %26 = OpLabel
  131. %v = OpVariable %_ptr_Function_v4float Function
  132. %f2 = OpVariable %_ptr_Function_float Function
  133. %52 = OpLoad %U_t %_
  134. %53 = OpCompositeExtract %float %52 0
  135. %27 = OpLoad %v4float %BaseColor
  136. OpStore %v %27
  137. %28 = OpLoad %float %fi
  138. %29 = OpFOrdGreaterThan %bool %28 %float_0
  139. OpSelectionMerge %30 None
  140. OpBranchConditional %29 %31 %32
  141. %31 = OpLabel
  142. %33 = OpLoad %v4float %v
  143. %36 = OpVectorTimesScalar %v4float %33 %53
  144. OpStore %v %36
  145. OpBranch %30
  146. %32 = OpLabel
  147. %49 = OpCompositeExtract %float %52 1
  148. %41 = OpFSub %float %49 %53
  149. OpStore %f2 %41
  150. %42 = OpLoad %v4float %v
  151. %43 = OpLoad %float %f2
  152. %44 = OpVectorTimesScalar %v4float %42 %43
  153. OpStore %v %44
  154. OpBranch %30
  155. %30 = OpLabel
  156. %45 = OpLoad %v4float %v
  157. OpStore %gl_FragColor %45
  158. OpReturn
  159. OpFunctionEnd
  160. )";
  161. SinglePassRunAndCheck<CommonUniformElimPass>(predefs + before,
  162. predefs + after, true, true);
  163. }
  164. TEST_F(CommonUniformElimTest, Basic2) {
  165. // Note: This test exemplifies the following:
  166. // - Common uniform (%_) load floated to nearest non-controlled block
  167. // - Common extract (g_F) floated to non-controlled block
  168. // - Non-common extract (g_F2) not floated, but common uniform load shared
  169. //
  170. // #version 140
  171. // in vec4 BaseColor;
  172. // in float fi;
  173. // in float fi2;
  174. //
  175. // layout(std140) uniform U_t
  176. // {
  177. // float g_F;
  178. // float g_F2;
  179. // } ;
  180. //
  181. // void main()
  182. // {
  183. // float f = fi;
  184. // if (f < 0)
  185. // f = -f;
  186. // if (fi2 > 0) {
  187. // f = f * g_F;
  188. // }
  189. // else {
  190. // f = g_F2 - g_F;
  191. // }
  192. // gl_FragColor = f * BaseColor;
  193. // }
  194. const std::string predefs =
  195. R"(OpCapability Shader
  196. %1 = OpExtInstImport "GLSL.std.450"
  197. OpMemoryModel Logical GLSL450
  198. OpEntryPoint Fragment %main "main" %fi %fi2 %gl_FragColor %BaseColor
  199. OpExecutionMode %main OriginUpperLeft
  200. OpSource GLSL 140
  201. OpName %main "main"
  202. OpName %f "f"
  203. OpName %fi "fi"
  204. OpName %fi2 "fi2"
  205. OpName %U_t "U_t"
  206. OpMemberName %U_t 0 "g_F"
  207. OpMemberName %U_t 1 "g_F2"
  208. OpName %_ ""
  209. OpName %gl_FragColor "gl_FragColor"
  210. OpName %BaseColor "BaseColor"
  211. OpMemberDecorate %U_t 0 Offset 0
  212. OpMemberDecorate %U_t 1 Offset 4
  213. OpDecorate %U_t Block
  214. OpDecorate %_ DescriptorSet 0
  215. %void = OpTypeVoid
  216. %11 = OpTypeFunction %void
  217. %float = OpTypeFloat 32
  218. %_ptr_Function_float = OpTypePointer Function %float
  219. %_ptr_Input_float = OpTypePointer Input %float
  220. %fi = OpVariable %_ptr_Input_float Input
  221. %float_0 = OpConstant %float 0
  222. %bool = OpTypeBool
  223. %fi2 = OpVariable %_ptr_Input_float Input
  224. %U_t = OpTypeStruct %float %float
  225. %_ptr_Uniform_U_t = OpTypePointer Uniform %U_t
  226. %_ = OpVariable %_ptr_Uniform_U_t Uniform
  227. %int = OpTypeInt 32 1
  228. %int_0 = OpConstant %int 0
  229. %_ptr_Uniform_float = OpTypePointer Uniform %float
  230. %int_1 = OpConstant %int 1
  231. %v4float = OpTypeVector %float 4
  232. %_ptr_Output_v4float = OpTypePointer Output %v4float
  233. %gl_FragColor = OpVariable %_ptr_Output_v4float Output
  234. %_ptr_Input_v4float = OpTypePointer Input %v4float
  235. %BaseColor = OpVariable %_ptr_Input_v4float Input
  236. )";
  237. const std::string before =
  238. R"(%main = OpFunction %void None %11
  239. %25 = OpLabel
  240. %f = OpVariable %_ptr_Function_float Function
  241. %26 = OpLoad %float %fi
  242. OpStore %f %26
  243. %27 = OpLoad %float %f
  244. %28 = OpFOrdLessThan %bool %27 %float_0
  245. OpSelectionMerge %29 None
  246. OpBranchConditional %28 %30 %29
  247. %30 = OpLabel
  248. %31 = OpLoad %float %f
  249. %32 = OpFNegate %float %31
  250. OpStore %f %32
  251. OpBranch %29
  252. %29 = OpLabel
  253. %33 = OpLoad %float %fi2
  254. %34 = OpFOrdGreaterThan %bool %33 %float_0
  255. OpSelectionMerge %35 None
  256. OpBranchConditional %34 %36 %37
  257. %36 = OpLabel
  258. %38 = OpLoad %float %f
  259. %39 = OpAccessChain %_ptr_Uniform_float %_ %int_0
  260. %40 = OpLoad %float %39
  261. %41 = OpFMul %float %38 %40
  262. OpStore %f %41
  263. OpBranch %35
  264. %37 = OpLabel
  265. %42 = OpAccessChain %_ptr_Uniform_float %_ %int_1
  266. %43 = OpLoad %float %42
  267. %44 = OpAccessChain %_ptr_Uniform_float %_ %int_0
  268. %45 = OpLoad %float %44
  269. %46 = OpFSub %float %43 %45
  270. OpStore %f %46
  271. OpBranch %35
  272. %35 = OpLabel
  273. %47 = OpLoad %v4float %BaseColor
  274. %48 = OpLoad %float %f
  275. %49 = OpVectorTimesScalar %v4float %47 %48
  276. OpStore %gl_FragColor %49
  277. OpReturn
  278. OpFunctionEnd
  279. )";
  280. const std::string after =
  281. R"(%main = OpFunction %void None %11
  282. %25 = OpLabel
  283. %f = OpVariable %_ptr_Function_float Function
  284. %26 = OpLoad %float %fi
  285. OpStore %f %26
  286. %27 = OpLoad %float %f
  287. %28 = OpFOrdLessThan %bool %27 %float_0
  288. OpSelectionMerge %29 None
  289. OpBranchConditional %28 %30 %29
  290. %30 = OpLabel
  291. %31 = OpLoad %float %f
  292. %32 = OpFNegate %float %31
  293. OpStore %f %32
  294. OpBranch %29
  295. %29 = OpLabel
  296. %56 = OpLoad %U_t %_
  297. %57 = OpCompositeExtract %float %56 0
  298. %33 = OpLoad %float %fi2
  299. %34 = OpFOrdGreaterThan %bool %33 %float_0
  300. OpSelectionMerge %35 None
  301. OpBranchConditional %34 %36 %37
  302. %36 = OpLabel
  303. %38 = OpLoad %float %f
  304. %41 = OpFMul %float %38 %57
  305. OpStore %f %41
  306. OpBranch %35
  307. %37 = OpLabel
  308. %53 = OpCompositeExtract %float %56 1
  309. %46 = OpFSub %float %53 %57
  310. OpStore %f %46
  311. OpBranch %35
  312. %35 = OpLabel
  313. %47 = OpLoad %v4float %BaseColor
  314. %48 = OpLoad %float %f
  315. %49 = OpVectorTimesScalar %v4float %47 %48
  316. OpStore %gl_FragColor %49
  317. OpReturn
  318. OpFunctionEnd
  319. )";
  320. SinglePassRunAndCheck<CommonUniformElimPass>(predefs + before,
  321. predefs + after, true, true);
  322. }
  323. TEST_F(CommonUniformElimTest, Basic3) {
  324. // Note: This test exemplifies the following:
  325. // - Existing common uniform (%_) load kept in place and shared
  326. //
  327. // #version 140
  328. // in vec4 BaseColor;
  329. // in float fi;
  330. //
  331. // layout(std140) uniform U_t
  332. // {
  333. // bool g_B;
  334. // float g_F;
  335. // } ;
  336. //
  337. // void main()
  338. // {
  339. // vec4 v = BaseColor;
  340. // if (g_B)
  341. // v = v * g_F;
  342. // gl_FragColor = v;
  343. // }
  344. const std::string predefs =
  345. R"(OpCapability Shader
  346. %1 = OpExtInstImport "GLSL.std.450"
  347. OpMemoryModel Logical GLSL450
  348. OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor %fi
  349. OpExecutionMode %main OriginUpperLeft
  350. OpSource GLSL 140
  351. OpName %main "main"
  352. OpName %v "v"
  353. OpName %BaseColor "BaseColor"
  354. OpName %U_t "U_t"
  355. OpMemberName %U_t 0 "g_B"
  356. OpMemberName %U_t 1 "g_F"
  357. OpName %_ ""
  358. OpName %gl_FragColor "gl_FragColor"
  359. OpName %fi "fi"
  360. OpMemberDecorate %U_t 0 Offset 0
  361. OpMemberDecorate %U_t 1 Offset 4
  362. OpDecorate %U_t Block
  363. OpDecorate %_ DescriptorSet 0
  364. %void = OpTypeVoid
  365. %10 = OpTypeFunction %void
  366. %float = OpTypeFloat 32
  367. %v4float = OpTypeVector %float 4
  368. %_ptr_Function_v4float = OpTypePointer Function %v4float
  369. %_ptr_Input_v4float = OpTypePointer Input %v4float
  370. %BaseColor = OpVariable %_ptr_Input_v4float Input
  371. %uint = OpTypeInt 32 0
  372. %U_t = OpTypeStruct %uint %float
  373. %_ptr_Uniform_U_t = OpTypePointer Uniform %U_t
  374. %_ = OpVariable %_ptr_Uniform_U_t Uniform
  375. %int = OpTypeInt 32 1
  376. %int_0 = OpConstant %int 0
  377. %_ptr_Uniform_uint = OpTypePointer Uniform %uint
  378. %bool = OpTypeBool
  379. %uint_0 = OpConstant %uint 0
  380. %int_1 = OpConstant %int 1
  381. %_ptr_Uniform_float = OpTypePointer Uniform %float
  382. %_ptr_Output_v4float = OpTypePointer Output %v4float
  383. %gl_FragColor = OpVariable %_ptr_Output_v4float Output
  384. %_ptr_Input_float = OpTypePointer Input %float
  385. %fi = OpVariable %_ptr_Input_float Input
  386. )";
  387. const std::string before =
  388. R"(%main = OpFunction %void None %10
  389. %26 = OpLabel
  390. %v = OpVariable %_ptr_Function_v4float Function
  391. %27 = OpLoad %v4float %BaseColor
  392. OpStore %v %27
  393. %28 = OpAccessChain %_ptr_Uniform_uint %_ %int_0
  394. %29 = OpLoad %uint %28
  395. %30 = OpINotEqual %bool %29 %uint_0
  396. OpSelectionMerge %31 None
  397. OpBranchConditional %30 %32 %31
  398. %32 = OpLabel
  399. %33 = OpLoad %v4float %v
  400. %34 = OpAccessChain %_ptr_Uniform_float %_ %int_1
  401. %35 = OpLoad %float %34
  402. %36 = OpVectorTimesScalar %v4float %33 %35
  403. OpStore %v %36
  404. OpBranch %31
  405. %31 = OpLabel
  406. %37 = OpLoad %v4float %v
  407. OpStore %gl_FragColor %37
  408. OpReturn
  409. OpFunctionEnd
  410. )";
  411. const std::string after =
  412. R"(%main = OpFunction %void None %10
  413. %26 = OpLabel
  414. %v = OpVariable %_ptr_Function_v4float Function
  415. %27 = OpLoad %v4float %BaseColor
  416. OpStore %v %27
  417. %38 = OpLoad %U_t %_
  418. %39 = OpCompositeExtract %uint %38 0
  419. %30 = OpINotEqual %bool %39 %uint_0
  420. OpSelectionMerge %31 None
  421. OpBranchConditional %30 %32 %31
  422. %32 = OpLabel
  423. %33 = OpLoad %v4float %v
  424. %41 = OpCompositeExtract %float %38 1
  425. %36 = OpVectorTimesScalar %v4float %33 %41
  426. OpStore %v %36
  427. OpBranch %31
  428. %31 = OpLabel
  429. %37 = OpLoad %v4float %v
  430. OpStore %gl_FragColor %37
  431. OpReturn
  432. OpFunctionEnd
  433. )";
  434. SinglePassRunAndCheck<CommonUniformElimPass>(predefs + before,
  435. predefs + after, true, true);
  436. }
  437. TEST_F(CommonUniformElimTest, Loop) {
  438. // Note: This test exemplifies the following:
  439. // - Common extract (g_F) shared between two loops
  440. // #version 140
  441. // in vec4 BC;
  442. // in vec4 BC2;
  443. //
  444. // layout(std140) uniform U_t
  445. // {
  446. // float g_F;
  447. // } ;
  448. //
  449. // void main()
  450. // {
  451. // vec4 v = BC;
  452. // for (int i = 0; i < 4; i++)
  453. // v[i] = v[i] / g_F;
  454. // vec4 v2 = BC2;
  455. // for (int i = 0; i < 4; i++)
  456. // v2[i] = v2[i] * g_F;
  457. // gl_FragColor = v + v2;
  458. // }
  459. const std::string predefs =
  460. R"(OpCapability Shader
  461. %1 = OpExtInstImport "GLSL.std.450"
  462. OpMemoryModel Logical GLSL450
  463. OpEntryPoint Fragment %main "main" %BC %BC2 %gl_FragColor
  464. OpExecutionMode %main OriginUpperLeft
  465. OpSource GLSL 140
  466. OpName %main "main"
  467. OpName %v "v"
  468. OpName %BC "BC"
  469. OpName %i "i"
  470. OpName %U_t "U_t"
  471. OpMemberName %U_t 0 "g_F"
  472. OpName %_ ""
  473. OpName %v2 "v2"
  474. OpName %BC2 "BC2"
  475. OpName %i_0 "i"
  476. OpName %gl_FragColor "gl_FragColor"
  477. OpMemberDecorate %U_t 0 Offset 0
  478. OpDecorate %U_t Block
  479. OpDecorate %_ DescriptorSet 0
  480. %void = OpTypeVoid
  481. %13 = OpTypeFunction %void
  482. %float = OpTypeFloat 32
  483. %v4float = OpTypeVector %float 4
  484. %_ptr_Function_v4float = OpTypePointer Function %v4float
  485. %_ptr_Input_v4float = OpTypePointer Input %v4float
  486. %BC = OpVariable %_ptr_Input_v4float Input
  487. %int = OpTypeInt 32 1
  488. %_ptr_Function_int = OpTypePointer Function %int
  489. %int_0 = OpConstant %int 0
  490. %int_4 = OpConstant %int 4
  491. %bool = OpTypeBool
  492. %_ptr_Function_float = OpTypePointer Function %float
  493. %U_t = OpTypeStruct %float
  494. %_ptr_Uniform_U_t = OpTypePointer Uniform %U_t
  495. %_ = OpVariable %_ptr_Uniform_U_t Uniform
  496. %_ptr_Uniform_float = OpTypePointer Uniform %float
  497. %int_1 = OpConstant %int 1
  498. %BC2 = OpVariable %_ptr_Input_v4float Input
  499. %_ptr_Output_v4float = OpTypePointer Output %v4float
  500. %gl_FragColor = OpVariable %_ptr_Output_v4float Output
  501. )";
  502. const std::string before =
  503. R"(%main = OpFunction %void None %13
  504. %28 = OpLabel
  505. %v = OpVariable %_ptr_Function_v4float Function
  506. %i = OpVariable %_ptr_Function_int Function
  507. %v2 = OpVariable %_ptr_Function_v4float Function
  508. %i_0 = OpVariable %_ptr_Function_int Function
  509. %29 = OpLoad %v4float %BC
  510. OpStore %v %29
  511. OpStore %i %int_0
  512. OpBranch %30
  513. %30 = OpLabel
  514. OpLoopMerge %31 %32 None
  515. OpBranch %33
  516. %33 = OpLabel
  517. %34 = OpLoad %int %i
  518. %35 = OpSLessThan %bool %34 %int_4
  519. OpBranchConditional %35 %36 %31
  520. %36 = OpLabel
  521. %37 = OpLoad %int %i
  522. %38 = OpLoad %int %i
  523. %39 = OpAccessChain %_ptr_Function_float %v %38
  524. %40 = OpLoad %float %39
  525. %41 = OpAccessChain %_ptr_Uniform_float %_ %int_0
  526. %42 = OpLoad %float %41
  527. %43 = OpFDiv %float %40 %42
  528. %44 = OpAccessChain %_ptr_Function_float %v %37
  529. OpStore %44 %43
  530. OpBranch %32
  531. %32 = OpLabel
  532. %45 = OpLoad %int %i
  533. %46 = OpIAdd %int %45 %int_1
  534. OpStore %i %46
  535. OpBranch %30
  536. %31 = OpLabel
  537. %47 = OpLoad %v4float %BC2
  538. OpStore %v2 %47
  539. OpStore %i_0 %int_0
  540. OpBranch %48
  541. %48 = OpLabel
  542. OpLoopMerge %49 %50 None
  543. OpBranch %51
  544. %51 = OpLabel
  545. %52 = OpLoad %int %i_0
  546. %53 = OpSLessThan %bool %52 %int_4
  547. OpBranchConditional %53 %54 %49
  548. %54 = OpLabel
  549. %55 = OpLoad %int %i_0
  550. %56 = OpLoad %int %i_0
  551. %57 = OpAccessChain %_ptr_Function_float %v2 %56
  552. %58 = OpLoad %float %57
  553. %59 = OpAccessChain %_ptr_Uniform_float %_ %int_0
  554. %60 = OpLoad %float %59
  555. %61 = OpFMul %float %58 %60
  556. %62 = OpAccessChain %_ptr_Function_float %v2 %55
  557. OpStore %62 %61
  558. OpBranch %50
  559. %50 = OpLabel
  560. %63 = OpLoad %int %i_0
  561. %64 = OpIAdd %int %63 %int_1
  562. OpStore %i_0 %64
  563. OpBranch %48
  564. %49 = OpLabel
  565. %65 = OpLoad %v4float %v
  566. %66 = OpLoad %v4float %v2
  567. %67 = OpFAdd %v4float %65 %66
  568. OpStore %gl_FragColor %67
  569. OpReturn
  570. OpFunctionEnd
  571. )";
  572. const std::string after =
  573. R"(%main = OpFunction %void None %13
  574. %28 = OpLabel
  575. %v = OpVariable %_ptr_Function_v4float Function
  576. %i = OpVariable %_ptr_Function_int Function
  577. %v2 = OpVariable %_ptr_Function_v4float Function
  578. %i_0 = OpVariable %_ptr_Function_int Function
  579. %72 = OpLoad %U_t %_
  580. %73 = OpCompositeExtract %float %72 0
  581. %29 = OpLoad %v4float %BC
  582. OpStore %v %29
  583. OpStore %i %int_0
  584. OpBranch %30
  585. %30 = OpLabel
  586. OpLoopMerge %31 %32 None
  587. OpBranch %33
  588. %33 = OpLabel
  589. %34 = OpLoad %int %i
  590. %35 = OpSLessThan %bool %34 %int_4
  591. OpBranchConditional %35 %36 %31
  592. %36 = OpLabel
  593. %37 = OpLoad %int %i
  594. %38 = OpLoad %int %i
  595. %39 = OpAccessChain %_ptr_Function_float %v %38
  596. %40 = OpLoad %float %39
  597. %43 = OpFDiv %float %40 %73
  598. %44 = OpAccessChain %_ptr_Function_float %v %37
  599. OpStore %44 %43
  600. OpBranch %32
  601. %32 = OpLabel
  602. %45 = OpLoad %int %i
  603. %46 = OpIAdd %int %45 %int_1
  604. OpStore %i %46
  605. OpBranch %30
  606. %31 = OpLabel
  607. %47 = OpLoad %v4float %BC2
  608. OpStore %v2 %47
  609. OpStore %i_0 %int_0
  610. OpBranch %48
  611. %48 = OpLabel
  612. OpLoopMerge %49 %50 None
  613. OpBranch %51
  614. %51 = OpLabel
  615. %52 = OpLoad %int %i_0
  616. %53 = OpSLessThan %bool %52 %int_4
  617. OpBranchConditional %53 %54 %49
  618. %54 = OpLabel
  619. %55 = OpLoad %int %i_0
  620. %56 = OpLoad %int %i_0
  621. %57 = OpAccessChain %_ptr_Function_float %v2 %56
  622. %58 = OpLoad %float %57
  623. %61 = OpFMul %float %58 %73
  624. %62 = OpAccessChain %_ptr_Function_float %v2 %55
  625. OpStore %62 %61
  626. OpBranch %50
  627. %50 = OpLabel
  628. %63 = OpLoad %int %i_0
  629. %64 = OpIAdd %int %63 %int_1
  630. OpStore %i_0 %64
  631. OpBranch %48
  632. %49 = OpLabel
  633. %65 = OpLoad %v4float %v
  634. %66 = OpLoad %v4float %v2
  635. %67 = OpFAdd %v4float %65 %66
  636. OpStore %gl_FragColor %67
  637. OpReturn
  638. OpFunctionEnd
  639. )";
  640. SinglePassRunAndCheck<CommonUniformElimPass>(predefs + before,
  641. predefs + after, true, true);
  642. }
  643. TEST_F(CommonUniformElimTest, Volatile1) {
  644. // Note: This test exemplifies the following:
  645. // - Same test as Basic1 with the exception that
  646. // the Load of g_F in else-branch is volatile
  647. // - Common uniform (%_) load floated to nearest non-controlled block
  648. //
  649. // #version 140
  650. // in vec4 BaseColor;
  651. // in float fi;
  652. //
  653. // layout(std140) uniform U_t
  654. // {
  655. // float g_F;
  656. // float g_F2;
  657. // } ;
  658. //
  659. // void main()
  660. // {
  661. // vec4 v = BaseColor;
  662. // if (fi > 0) {
  663. // v = v * g_F;
  664. // }
  665. // else {
  666. // float f2 = g_F2 - g_F;
  667. // v = v * f2;
  668. // }
  669. // gl_FragColor = v;
  670. // }
  671. const std::string predefs =
  672. R"(OpCapability Shader
  673. %1 = OpExtInstImport "GLSL.std.450"
  674. OpMemoryModel Logical GLSL450
  675. OpEntryPoint Fragment %main "main" %BaseColor %fi %gl_FragColor
  676. OpExecutionMode %main OriginUpperLeft
  677. OpSource GLSL 140
  678. OpName %main "main"
  679. OpName %v "v"
  680. OpName %BaseColor "BaseColor"
  681. OpName %fi "fi"
  682. OpName %U_t "U_t"
  683. OpMemberName %U_t 0 "g_F"
  684. OpMemberName %U_t 1 "g_F2"
  685. OpName %_ ""
  686. OpName %f2 "f2"
  687. OpName %gl_FragColor "gl_FragColor"
  688. OpMemberDecorate %U_t 0 Offset 0
  689. OpMemberDecorate %U_t 1 Offset 4
  690. OpDecorate %U_t Block
  691. OpDecorate %_ DescriptorSet 0
  692. %void = OpTypeVoid
  693. %11 = OpTypeFunction %void
  694. %float = OpTypeFloat 32
  695. %v4float = OpTypeVector %float 4
  696. %_ptr_Function_v4float = OpTypePointer Function %v4float
  697. %_ptr_Input_v4float = OpTypePointer Input %v4float
  698. %BaseColor = OpVariable %_ptr_Input_v4float Input
  699. %_ptr_Input_float = OpTypePointer Input %float
  700. %fi = OpVariable %_ptr_Input_float Input
  701. %float_0 = OpConstant %float 0
  702. %bool = OpTypeBool
  703. %U_t = OpTypeStruct %float %float
  704. %_ptr_Uniform_U_t = OpTypePointer Uniform %U_t
  705. %_ = OpVariable %_ptr_Uniform_U_t Uniform
  706. %int = OpTypeInt 32 1
  707. %int_0 = OpConstant %int 0
  708. %_ptr_Uniform_float = OpTypePointer Uniform %float
  709. %_ptr_Function_float = OpTypePointer Function %float
  710. %int_1 = OpConstant %int 1
  711. %_ptr_Output_v4float = OpTypePointer Output %v4float
  712. %gl_FragColor = OpVariable %_ptr_Output_v4float Output
  713. )";
  714. const std::string before =
  715. R"(%main = OpFunction %void None %11
  716. %26 = OpLabel
  717. %v = OpVariable %_ptr_Function_v4float Function
  718. %f2 = OpVariable %_ptr_Function_float Function
  719. %27 = OpLoad %v4float %BaseColor
  720. OpStore %v %27
  721. %28 = OpLoad %float %fi
  722. %29 = OpFOrdGreaterThan %bool %28 %float_0
  723. OpSelectionMerge %30 None
  724. OpBranchConditional %29 %31 %32
  725. %31 = OpLabel
  726. %33 = OpLoad %v4float %v
  727. %34 = OpAccessChain %_ptr_Uniform_float %_ %int_0
  728. %35 = OpLoad %float %34
  729. %36 = OpVectorTimesScalar %v4float %33 %35
  730. OpStore %v %36
  731. OpBranch %30
  732. %32 = OpLabel
  733. %37 = OpAccessChain %_ptr_Uniform_float %_ %int_1
  734. %38 = OpLoad %float %37
  735. %39 = OpAccessChain %_ptr_Uniform_float %_ %int_0
  736. %40 = OpLoad %float %39 Volatile
  737. %41 = OpFSub %float %38 %40
  738. OpStore %f2 %41
  739. %42 = OpLoad %v4float %v
  740. %43 = OpLoad %float %f2
  741. %44 = OpVectorTimesScalar %v4float %42 %43
  742. OpStore %v %44
  743. OpBranch %30
  744. %30 = OpLabel
  745. %45 = OpLoad %v4float %v
  746. OpStore %gl_FragColor %45
  747. OpReturn
  748. OpFunctionEnd
  749. )";
  750. const std::string after =
  751. R"(%main = OpFunction %void None %11
  752. %26 = OpLabel
  753. %v = OpVariable %_ptr_Function_v4float Function
  754. %f2 = OpVariable %_ptr_Function_float Function
  755. %50 = OpLoad %U_t %_
  756. %27 = OpLoad %v4float %BaseColor
  757. OpStore %v %27
  758. %28 = OpLoad %float %fi
  759. %29 = OpFOrdGreaterThan %bool %28 %float_0
  760. OpSelectionMerge %30 None
  761. OpBranchConditional %29 %31 %32
  762. %31 = OpLabel
  763. %33 = OpLoad %v4float %v
  764. %47 = OpCompositeExtract %float %50 0
  765. %36 = OpVectorTimesScalar %v4float %33 %47
  766. OpStore %v %36
  767. OpBranch %30
  768. %32 = OpLabel
  769. %49 = OpCompositeExtract %float %50 1
  770. %39 = OpAccessChain %_ptr_Uniform_float %_ %int_0
  771. %40 = OpLoad %float %39 Volatile
  772. %41 = OpFSub %float %49 %40
  773. OpStore %f2 %41
  774. %42 = OpLoad %v4float %v
  775. %43 = OpLoad %float %f2
  776. %44 = OpVectorTimesScalar %v4float %42 %43
  777. OpStore %v %44
  778. OpBranch %30
  779. %30 = OpLabel
  780. %45 = OpLoad %v4float %v
  781. OpStore %gl_FragColor %45
  782. OpReturn
  783. OpFunctionEnd
  784. )";
  785. SinglePassRunAndCheck<CommonUniformElimPass>(predefs + before,
  786. predefs + after, true, true);
  787. }
  788. TEST_F(CommonUniformElimTest, Volatile2) {
  789. // Note: This test exemplifies the following:
  790. // - Same test as Basic1 with the exception that
  791. // U_t is Volatile.
  792. // - No optimizations are applied
  793. //
  794. // #version 430
  795. // in vec4 BaseColor;
  796. // in float fi;
  797. //
  798. // layout(std430) volatile buffer U_t
  799. // {
  800. // float g_F;
  801. // float g_F2;
  802. // };
  803. //
  804. //
  805. // void main(void)
  806. // {
  807. // vec4 v = BaseColor;
  808. // if (fi > 0) {
  809. // v = v * g_F;
  810. // } else {
  811. // float f2 = g_F2 - g_F;
  812. // v = v * f2;
  813. // }
  814. // }
  815. const std::string text =
  816. R"(OpCapability Shader
  817. %1 = OpExtInstImport "GLSL.std.450"
  818. OpMemoryModel Logical GLSL450
  819. OpEntryPoint Fragment %main "main" %BaseColor %fi
  820. OpExecutionMode %main OriginUpperLeft
  821. OpSource GLSL 430
  822. OpName %main "main"
  823. OpName %v "v"
  824. OpName %BaseColor "BaseColor"
  825. OpName %fi "fi"
  826. OpName %U_t "U_t"
  827. OpMemberName %U_t 0 "g_F"
  828. OpMemberName %U_t 1 "g_F2"
  829. OpName %_ ""
  830. OpName %f2 "f2"
  831. OpDecorate %BaseColor Location 0
  832. OpDecorate %fi Location 0
  833. OpMemberDecorate %U_t 0 Volatile
  834. OpMemberDecorate %U_t 0 Offset 0
  835. OpMemberDecorate %U_t 1 Volatile
  836. OpMemberDecorate %U_t 1 Offset 4
  837. OpDecorate %U_t BufferBlock
  838. OpDecorate %_ DescriptorSet 0
  839. %void = OpTypeVoid
  840. %3 = OpTypeFunction %void
  841. %float = OpTypeFloat 32
  842. %v4float = OpTypeVector %float 4
  843. %_ptr_Function_v4float = OpTypePointer Function %v4float
  844. %_ptr_Input_v4float = OpTypePointer Input %v4float
  845. %BaseColor = OpVariable %_ptr_Input_v4float Input
  846. %_ptr_Input_float = OpTypePointer Input %float
  847. %fi = OpVariable %_ptr_Input_float Input
  848. %float_0 = OpConstant %float 0
  849. %bool = OpTypeBool
  850. %U_t = OpTypeStruct %float %float
  851. %_ptr_Uniform_U_t = OpTypePointer Uniform %U_t
  852. %_ = OpVariable %_ptr_Uniform_U_t Uniform
  853. %int = OpTypeInt 32 1
  854. %int_0 = OpConstant %int 0
  855. %_ptr_Uniform_float = OpTypePointer Uniform %float
  856. %_ptr_Function_float = OpTypePointer Function %float
  857. %int_1 = OpConstant %int 1
  858. %main = OpFunction %void None %3
  859. %5 = OpLabel
  860. %v = OpVariable %_ptr_Function_v4float Function
  861. %f2 = OpVariable %_ptr_Function_float Function
  862. %12 = OpLoad %v4float %BaseColor
  863. OpStore %v %12
  864. %15 = OpLoad %float %fi
  865. %18 = OpFOrdGreaterThan %bool %15 %float_0
  866. OpSelectionMerge %20 None
  867. OpBranchConditional %18 %19 %31
  868. %19 = OpLabel
  869. %21 = OpLoad %v4float %v
  870. %28 = OpAccessChain %_ptr_Uniform_float %_ %int_0
  871. %29 = OpLoad %float %28
  872. %30 = OpVectorTimesScalar %v4float %21 %29
  873. OpStore %v %30
  874. OpBranch %20
  875. %31 = OpLabel
  876. %35 = OpAccessChain %_ptr_Uniform_float %_ %int_1
  877. %36 = OpLoad %float %35
  878. %37 = OpAccessChain %_ptr_Uniform_float %_ %int_0
  879. %38 = OpLoad %float %37
  880. %39 = OpFSub %float %36 %38
  881. OpStore %f2 %39
  882. %40 = OpLoad %v4float %v
  883. %41 = OpLoad %float %f2
  884. %42 = OpVectorTimesScalar %v4float %40 %41
  885. OpStore %v %42
  886. OpBranch %20
  887. %20 = OpLabel
  888. OpReturn
  889. OpFunctionEnd
  890. )";
  891. Pass::Status res = std::get<1>(
  892. SinglePassRunAndDisassemble<CommonUniformElimPass>(text, true, false));
  893. EXPECT_EQ(res, Pass::Status::SuccessWithoutChange);
  894. }
  895. TEST_F(CommonUniformElimTest, Volatile3) {
  896. // Note: This test exemplifies the following:
  897. // - Same test as Volatile2 with the exception that
  898. // the nested struct S is volatile
  899. // - No optimizations are applied
  900. //
  901. // #version 430
  902. // in vec4 BaseColor;
  903. // in float fi;
  904. //
  905. // struct S {
  906. // volatile float a;
  907. // };
  908. //
  909. // layout(std430) buffer U_t
  910. // {
  911. // S g_F;
  912. // S g_F2;
  913. // };
  914. //
  915. //
  916. // void main(void)
  917. // {
  918. // vec4 v = BaseColor;
  919. // if (fi > 0) {
  920. // v = v * g_F.a;
  921. // } else {
  922. // float f2 = g_F2.a - g_F.a;
  923. // v = v * f2;
  924. // }
  925. // }
  926. const std::string text =
  927. R"(OpCapability Shader
  928. %1 = OpExtInstImport "GLSL.std.450"
  929. OpMemoryModel Logical GLSL450
  930. OpEntryPoint Fragment %main "main" %BaseColor %fi
  931. OpExecutionMode %main OriginUpperLeft
  932. OpSource GLSL 430
  933. OpName %main "main"
  934. OpName %v "v"
  935. OpName %BaseColor "BaseColor"
  936. OpName %fi "fi"
  937. OpName %S "S"
  938. OpMemberName %S 0 "a"
  939. OpName %U_t "U_t"
  940. OpMemberName %U_t 0 "g_F"
  941. OpMemberName %U_t 1 "g_F2"
  942. OpName %_ ""
  943. OpName %f2 "f2"
  944. OpDecorate %BaseColor Location 0
  945. OpDecorate %fi Location 0
  946. OpMemberDecorate %S 0 Offset 0
  947. OpMemberDecorate %S 0 Volatile
  948. OpMemberDecorate %U_t 0 Offset 0
  949. OpMemberDecorate %U_t 1 Offset 4
  950. OpDecorate %U_t BufferBlock
  951. OpDecorate %_ DescriptorSet 0
  952. %void = OpTypeVoid
  953. %3 = OpTypeFunction %void
  954. %float = OpTypeFloat 32
  955. %v4float = OpTypeVector %float 4
  956. %_ptr_Function_v4float = OpTypePointer Function %v4float
  957. %_ptr_Input_v4float = OpTypePointer Input %v4float
  958. %BaseColor = OpVariable %_ptr_Input_v4float Input
  959. %_ptr_Input_float = OpTypePointer Input %float
  960. %fi = OpVariable %_ptr_Input_float Input
  961. %float_0 = OpConstant %float 0
  962. %bool = OpTypeBool
  963. %S = OpTypeStruct %float
  964. %U_t = OpTypeStruct %S %S
  965. %_ptr_Uniform_U_t = OpTypePointer Uniform %U_t
  966. %_ = OpVariable %_ptr_Uniform_U_t Uniform
  967. %int = OpTypeInt 32 1
  968. %int_0 = OpConstant %int 0
  969. %_ptr_Uniform_float = OpTypePointer Uniform %float
  970. %_ptr_Function_float = OpTypePointer Function %float
  971. %int_1 = OpConstant %int 1
  972. %main = OpFunction %void None %3
  973. %5 = OpLabel
  974. %v = OpVariable %_ptr_Function_v4float Function
  975. %f2 = OpVariable %_ptr_Function_float Function
  976. %12 = OpLoad %v4float %BaseColor
  977. OpStore %v %12
  978. %15 = OpLoad %float %fi
  979. %18 = OpFOrdGreaterThan %bool %15 %float_0
  980. OpSelectionMerge %20 None
  981. OpBranchConditional %18 %19 %32
  982. %19 = OpLabel
  983. %21 = OpLoad %v4float %v
  984. %29 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %int_0
  985. %30 = OpLoad %float %29
  986. %31 = OpVectorTimesScalar %v4float %21 %30
  987. OpStore %v %31
  988. OpBranch %20
  989. %32 = OpLabel
  990. %36 = OpAccessChain %_ptr_Uniform_float %_ %int_1 %int_0
  991. %37 = OpLoad %float %36
  992. %38 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %int_0
  993. %39 = OpLoad %float %38
  994. %40 = OpFSub %float %37 %39
  995. OpStore %f2 %40
  996. %41 = OpLoad %v4float %v
  997. %42 = OpLoad %float %f2
  998. %43 = OpVectorTimesScalar %v4float %41 %42
  999. OpStore %v %43
  1000. OpBranch %20
  1001. %20 = OpLabel
  1002. OpReturn
  1003. OpFunctionEnd
  1004. )";
  1005. Pass::Status res = std::get<1>(
  1006. SinglePassRunAndDisassemble<CommonUniformElimPass>(text, true, false));
  1007. EXPECT_EQ(res, Pass::Status::SuccessWithoutChange);
  1008. }
  1009. TEST_F(CommonUniformElimTest, IteratorDanglingPointer) {
  1010. // Note: This test exemplifies the following:
  1011. // - Existing common uniform (%_) load kept in place and shared
  1012. //
  1013. // #version 140
  1014. // in vec4 BaseColor;
  1015. // in float fi;
  1016. //
  1017. // layout(std140) uniform U_t
  1018. // {
  1019. // bool g_B;
  1020. // float g_F;
  1021. // } ;
  1022. //
  1023. // uniform float alpha;
  1024. // uniform bool alpha_B;
  1025. //
  1026. // void main()
  1027. // {
  1028. // vec4 v = BaseColor;
  1029. // if (g_B) {
  1030. // v = v * g_F;
  1031. // if (alpha_B)
  1032. // v = v * alpha;
  1033. // else
  1034. // v = v * fi;
  1035. // }
  1036. // gl_FragColor = v;
  1037. // }
  1038. const std::string predefs =
  1039. R"(OpCapability Shader
  1040. %1 = OpExtInstImport "GLSL.std.450"
  1041. OpMemoryModel Logical GLSL450
  1042. OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor %fi
  1043. OpExecutionMode %main OriginUpperLeft
  1044. OpSource GLSL 140
  1045. OpName %main "main"
  1046. OpName %v "v"
  1047. OpName %BaseColor "BaseColor"
  1048. OpName %U_t "U_t"
  1049. OpMemberName %U_t 0 "g_B"
  1050. OpMemberName %U_t 1 "g_F"
  1051. OpName %alpha "alpha"
  1052. OpName %alpha_B "alpha_B"
  1053. OpName %_ ""
  1054. OpName %gl_FragColor "gl_FragColor"
  1055. OpName %fi "fi"
  1056. OpMemberDecorate %U_t 0 Offset 0
  1057. OpMemberDecorate %U_t 1 Offset 4
  1058. OpDecorate %U_t Block
  1059. OpDecorate %_ DescriptorSet 0
  1060. %void = OpTypeVoid
  1061. %12 = OpTypeFunction %void
  1062. %float = OpTypeFloat 32
  1063. %v4float = OpTypeVector %float 4
  1064. %_ptr_Function_v4float = OpTypePointer Function %v4float
  1065. %_ptr_Input_v4float = OpTypePointer Input %v4float
  1066. %BaseColor = OpVariable %_ptr_Input_v4float Input
  1067. %uint = OpTypeInt 32 0
  1068. %U_t = OpTypeStruct %uint %float
  1069. %_ptr_Uniform_U_t = OpTypePointer Uniform %U_t
  1070. %_ = OpVariable %_ptr_Uniform_U_t Uniform
  1071. %int = OpTypeInt 32 1
  1072. %int_0 = OpConstant %int 0
  1073. %_ptr_Uniform_uint = OpTypePointer Uniform %uint
  1074. %bool = OpTypeBool
  1075. %uint_0 = OpConstant %uint 0
  1076. %int_1 = OpConstant %int 1
  1077. %_ptr_Uniform_float = OpTypePointer Uniform %float
  1078. %_ptr_Output_v4float = OpTypePointer Output %v4float
  1079. %gl_FragColor = OpVariable %_ptr_Output_v4float Output
  1080. %_ptr_Input_float = OpTypePointer Input %float
  1081. %fi = OpVariable %_ptr_Input_float Input
  1082. %alpha = OpVariable %_ptr_Uniform_float Uniform
  1083. %alpha_B = OpVariable %_ptr_Uniform_uint Uniform
  1084. )";
  1085. const std::string before =
  1086. R"(%main = OpFunction %void None %12
  1087. %26 = OpLabel
  1088. %v = OpVariable %_ptr_Function_v4float Function
  1089. %27 = OpLoad %v4float %BaseColor
  1090. OpStore %v %27
  1091. %28 = OpAccessChain %_ptr_Uniform_uint %_ %int_0
  1092. %29 = OpLoad %uint %28
  1093. %30 = OpINotEqual %bool %29 %uint_0
  1094. OpSelectionMerge %31 None
  1095. OpBranchConditional %30 %31 %32
  1096. %32 = OpLabel
  1097. %47 = OpLoad %v4float %v
  1098. OpStore %gl_FragColor %47
  1099. OpReturn
  1100. %31 = OpLabel
  1101. %33 = OpAccessChain %_ptr_Uniform_float %_ %int_1
  1102. %34 = OpLoad %float %33
  1103. %35 = OpLoad %v4float %v
  1104. %36 = OpVectorTimesScalar %v4float %35 %34
  1105. OpStore %v %36
  1106. %37 = OpLoad %uint %alpha_B
  1107. %38 = OpIEqual %bool %37 %uint_0
  1108. OpSelectionMerge %43 None
  1109. OpBranchConditional %38 %43 %39
  1110. %39 = OpLabel
  1111. %40 = OpLoad %float %alpha
  1112. %41 = OpLoad %v4float %v
  1113. %42 = OpVectorTimesScalar %v4float %41 %40
  1114. OpStore %v %42
  1115. OpBranch %50
  1116. %50 = OpLabel
  1117. %51 = OpLoad %v4float %v
  1118. OpStore %gl_FragColor %51
  1119. OpReturn
  1120. %43 = OpLabel
  1121. %44 = OpLoad %float %fi
  1122. %45 = OpLoad %v4float %v
  1123. %46 = OpVectorTimesScalar %v4float %45 %44
  1124. OpStore %v %46
  1125. OpBranch %60
  1126. %60 = OpLabel
  1127. %61 = OpLoad %v4float %v
  1128. OpStore %gl_FragColor %61
  1129. OpReturn
  1130. OpFunctionEnd
  1131. )";
  1132. const std::string after =
  1133. R"(%main = OpFunction %void None %12
  1134. %28 = OpLabel
  1135. %v = OpVariable %_ptr_Function_v4float Function
  1136. %29 = OpLoad %v4float %BaseColor
  1137. OpStore %v %29
  1138. %54 = OpLoad %U_t %_
  1139. %55 = OpCompositeExtract %uint %54 0
  1140. %32 = OpINotEqual %bool %55 %uint_0
  1141. OpSelectionMerge %33 None
  1142. OpBranchConditional %32 %33 %34
  1143. %34 = OpLabel
  1144. %35 = OpLoad %v4float %v
  1145. OpStore %gl_FragColor %35
  1146. OpReturn
  1147. %33 = OpLabel
  1148. %58 = OpLoad %float %alpha
  1149. %57 = OpCompositeExtract %float %54 1
  1150. %38 = OpLoad %v4float %v
  1151. %39 = OpVectorTimesScalar %v4float %38 %57
  1152. OpStore %v %39
  1153. %40 = OpLoad %uint %alpha_B
  1154. %41 = OpIEqual %bool %40 %uint_0
  1155. OpSelectionMerge %42 None
  1156. OpBranchConditional %41 %42 %43
  1157. %43 = OpLabel
  1158. %45 = OpLoad %v4float %v
  1159. %46 = OpVectorTimesScalar %v4float %45 %58
  1160. OpStore %v %46
  1161. OpBranch %47
  1162. %47 = OpLabel
  1163. %48 = OpLoad %v4float %v
  1164. OpStore %gl_FragColor %48
  1165. OpReturn
  1166. %42 = OpLabel
  1167. %49 = OpLoad %float %fi
  1168. %50 = OpLoad %v4float %v
  1169. %51 = OpVectorTimesScalar %v4float %50 %49
  1170. OpStore %v %51
  1171. OpBranch %52
  1172. %52 = OpLabel
  1173. %53 = OpLoad %v4float %v
  1174. OpStore %gl_FragColor %53
  1175. OpReturn
  1176. OpFunctionEnd
  1177. )";
  1178. SinglePassRunAndCheck<CommonUniformElimPass>(predefs + before,
  1179. predefs + after, true, true);
  1180. }
  1181. TEST_F(CommonUniformElimTest, MixedConstantAndNonConstantIndexes) {
  1182. const std::string text = R"(
  1183. ; CHECK: [[var:%\w+]] = OpVariable {{%\w+}} Uniform
  1184. ; CHECK: %501 = OpLabel
  1185. ; CHECK: [[ld:%\w+]] = OpLoad
  1186. ; CHECK-NOT: OpCompositeExtract {{%\w+}} {{%\w+}} 0 2 484
  1187. ; CHECK: OpAccessChain {{%\w+}} [[var]] %int_0 %int_2 [[ld]]
  1188. OpCapability Shader
  1189. %1 = OpExtInstImport "GLSL.std.450"
  1190. OpMemoryModel Logical GLSL450
  1191. OpEntryPoint Fragment %4 "ringeffectLayer_px" %gl_FragCoord %178 %182
  1192. OpExecutionMode %4 OriginUpperLeft
  1193. OpSource HLSL 500
  1194. OpDecorate %_arr_v4float_uint_10 ArrayStride 16
  1195. OpMemberDecorate %_struct_20 0 Offset 0
  1196. OpMemberDecorate %_struct_20 1 Offset 16
  1197. OpMemberDecorate %_struct_20 2 Offset 32
  1198. OpMemberDecorate %_struct_21 0 Offset 0
  1199. OpDecorate %_struct_21 Block
  1200. OpDecorate %23 DescriptorSet 0
  1201. OpDecorate %gl_FragCoord BuiltIn FragCoord
  1202. OpDecorate %178 Location 0
  1203. OpDecorate %182 Location 0
  1204. %void = OpTypeVoid
  1205. %3 = OpTypeFunction %void
  1206. %float = OpTypeFloat 32
  1207. %v4float = OpTypeVector %float 4
  1208. %v2float = OpTypeVector %float 2
  1209. %_ptr_Function_v2float = OpTypePointer Function %v2float
  1210. %uint = OpTypeInt 32 0
  1211. %uint_10 = OpConstant %uint 10
  1212. %_arr_v4float_uint_10 = OpTypeArray %v4float %uint_10
  1213. %_struct_20 = OpTypeStruct %v4float %v4float %_arr_v4float_uint_10
  1214. %_struct_21 = OpTypeStruct %_struct_20
  1215. %_ptr_Uniform__struct_21 = OpTypePointer Uniform %_struct_21
  1216. %23 = OpVariable %_ptr_Uniform__struct_21 Uniform
  1217. %int = OpTypeInt 32 1
  1218. %int_0 = OpConstant %int 0
  1219. %_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
  1220. %_ptr_Uniform_float = OpTypePointer Uniform %float
  1221. %uint_3 = OpConstant %uint 3
  1222. %_ptr_Function_v4float = OpTypePointer Function %v4float
  1223. %float_0 = OpConstant %float 0
  1224. %43 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
  1225. %_ptr_Function_int = OpTypePointer Function %int
  1226. %int_5 = OpConstant %int 5
  1227. %bool = OpTypeBool
  1228. %int_1 = OpConstant %int 1
  1229. %int_2 = OpConstant %int 2
  1230. %uint_5 = OpConstant %uint 5
  1231. %_arr_v2float_uint_5 = OpTypeArray %v2float %uint_5
  1232. %_ptr_Function__arr_v2float_uint_5 = OpTypePointer Function %_arr_v2float_uint_5
  1233. %82 = OpTypeImage %float 2D 0 0 0 1 Unknown
  1234. %_ptr_UniformConstant_82 = OpTypePointer UniformConstant %82
  1235. %86 = OpTypeSampler
  1236. %_ptr_UniformConstant_86 = OpTypePointer UniformConstant %86
  1237. %90 = OpTypeSampledImage %82
  1238. %v3float = OpTypeVector %float 3
  1239. %_ptr_Input_v4float = OpTypePointer Input %v4float
  1240. %gl_FragCoord = OpVariable %_ptr_Input_v4float Input
  1241. %178 = OpVariable %_ptr_Input_v4float Input
  1242. %_ptr_Output_v4float = OpTypePointer Output %v4float
  1243. %182 = OpVariable %_ptr_Output_v4float Output
  1244. %4 = OpFunction %void None %3
  1245. %5 = OpLabel
  1246. %483 = OpVariable %_ptr_Function_v4float Function
  1247. %484 = OpVariable %_ptr_Function_int Function
  1248. %486 = OpVariable %_ptr_Function__arr_v2float_uint_5 Function
  1249. %179 = OpLoad %v4float %178
  1250. %493 = OpAccessChain %_ptr_Uniform_float %23 %int_0 %int_0 %uint_3
  1251. %494 = OpLoad %float %493
  1252. OpStore %483 %43
  1253. OpStore %484 %int_0
  1254. OpBranch %495
  1255. %495 = OpLabel
  1256. OpLoopMerge %496 %497 None
  1257. OpBranch %498
  1258. %498 = OpLabel
  1259. %499 = OpLoad %int %484
  1260. %500 = OpSLessThan %bool %499 %int_5
  1261. OpBranchConditional %500 %501 %496
  1262. %501 = OpLabel
  1263. %504 = OpVectorShuffle %v2float %179 %179 0 1
  1264. %505 = OpLoad %int %484
  1265. %506 = OpAccessChain %_ptr_Uniform_v4float %23 %int_0 %int_2 %505
  1266. %507 = OpLoad %v4float %506
  1267. %508 = OpVectorShuffle %v2float %507 %507 0 1
  1268. %509 = OpFAdd %v2float %504 %508
  1269. %512 = OpAccessChain %_ptr_Uniform_v4float %23 %int_0 %int_1
  1270. %513 = OpLoad %v4float %512
  1271. %514 = OpVectorShuffle %v2float %513 %513 0 1
  1272. %517 = OpVectorShuffle %v2float %513 %513 2 3
  1273. %518 = OpExtInst %v2float %1 FClamp %509 %514 %517
  1274. %519 = OpAccessChain %_ptr_Function_v2float %486 %505
  1275. OpStore %519 %518
  1276. OpBranch %497
  1277. %497 = OpLabel
  1278. %520 = OpLoad %int %484
  1279. %521 = OpIAdd %int %520 %int_1
  1280. OpStore %484 %521
  1281. OpBranch %495
  1282. %496 = OpLabel
  1283. OpReturn
  1284. OpFunctionEnd
  1285. )";
  1286. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  1287. SinglePassRunAndMatch<CommonUniformElimPass>(text, true);
  1288. }
  1289. TEST_F(CommonUniformElimTest, LoadPlacedAfterPhi) {
  1290. const std::string text = R"(
  1291. ; CHECK: [[var:%\w+]] = OpVariable {{%\w+}} Uniform
  1292. ; CHECK: OpSelectionMerge [[merge:%\w+]]
  1293. ; CHECK: [[merge]] = OpLabel
  1294. ; CHECK-NEXT: OpPhi
  1295. ; CHECK-NEXT: OpLoad {{%\w+}} [[var]]
  1296. OpCapability Shader
  1297. %1 = OpExtInstImport "GLSL.std.450"
  1298. OpMemoryModel Logical GLSL450
  1299. OpEntryPoint Fragment %2 "main"
  1300. OpExecutionMode %2 OriginUpperLeft
  1301. OpSource ESSL 310
  1302. OpMemberDecorate %_struct_3 0 Offset 0
  1303. OpDecorate %_struct_3 Block
  1304. OpDecorate %4 DescriptorSet 0
  1305. OpDecorate %4 Binding 0
  1306. %void = OpTypeVoid
  1307. %6 = OpTypeFunction %void
  1308. %bool = OpTypeBool
  1309. %false = OpConstantFalse %bool
  1310. %uint = OpTypeInt 32 0
  1311. %v2uint = OpTypeVector %uint 2
  1312. %_struct_3 = OpTypeStruct %v2uint
  1313. %_ptr_Uniform__struct_3 = OpTypePointer Uniform %_struct_3
  1314. %4 = OpVariable %_ptr_Uniform__struct_3 Uniform
  1315. %uint_0 = OpConstant %uint 0
  1316. %_ptr_Uniform_uint = OpTypePointer Uniform %uint
  1317. %uint_2 = OpConstant %uint 2
  1318. %2 = OpFunction %void None %6
  1319. %15 = OpLabel
  1320. OpSelectionMerge %16 None
  1321. OpBranchConditional %false %17 %16
  1322. %17 = OpLabel
  1323. OpBranch %16
  1324. %16 = OpLabel
  1325. %18 = OpPhi %bool %false %15 %false %17
  1326. OpSelectionMerge %19 None
  1327. OpBranchConditional %false %20 %21
  1328. %20 = OpLabel
  1329. %22 = OpAccessChain %_ptr_Uniform_uint %4 %uint_0 %uint_0
  1330. %23 = OpLoad %uint %22
  1331. OpBranch %19
  1332. %21 = OpLabel
  1333. OpBranch %19
  1334. %19 = OpLabel
  1335. OpReturn
  1336. OpFunctionEnd
  1337. )";
  1338. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  1339. SinglePassRunAndMatch<CommonUniformElimPass>(text, true);
  1340. }
  1341. // TODO(greg-lunarg): Add tests to verify handling of these cases:
  1342. //
  1343. // Disqualifying cases: extensions, decorations, non-logical addressing,
  1344. // non-structured control flow
  1345. // Others?
  1346. } // namespace
  1347. } // namespace opt
  1348. } // namespace spvtools