scalar_replacement_test.cpp 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626
  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 "test/opt/assembly_builder.h"
  17. #include "test/opt/pass_fixture.h"
  18. #include "test/opt/pass_utils.h"
  19. namespace spvtools {
  20. namespace opt {
  21. namespace {
  22. using ScalarReplacementTest = PassTest<::testing::Test>;
  23. TEST_F(ScalarReplacementTest, SimpleStruct) {
  24. const std::string text = R"(
  25. ;
  26. ; CHECK: [[struct:%\w+]] = OpTypeStruct [[elem:%\w+]]
  27. ; CHECK: [[struct_ptr:%\w+]] = OpTypePointer Function [[struct]]
  28. ; CHECK: [[elem_ptr:%\w+]] = OpTypePointer Function [[elem]]
  29. ; CHECK: OpConstantNull [[struct]]
  30. ; CHECK: [[null:%\w+]] = OpConstantNull [[elem]]
  31. ; CHECK-NOT: OpVariable [[struct_ptr]]
  32. ; CHECK: [[one:%\w+]] = OpVariable [[elem_ptr]] Function [[null]]
  33. ; CHECK-NEXT: [[two:%\w+]] = OpVariable [[elem_ptr]] Function [[null]]
  34. ; CHECK-NOT: OpVariable [[elem_ptr]] Function [[null]]
  35. ; CHECK-NOT: OpVariable [[struct_ptr]]
  36. ; CHECK-NOT: OpInBoundsAccessChain
  37. ; CHECK: [[l1:%\w+]] = OpLoad [[elem]] [[two]]
  38. ; CHECK-NOT: OpAccessChain
  39. ; CHECK: [[l2:%\w+]] = OpLoad [[elem]] [[one]]
  40. ; CHECK: OpIAdd [[elem]] [[l1]] [[l2]]
  41. ;
  42. OpCapability Shader
  43. OpCapability Linkage
  44. OpMemoryModel Logical GLSL450
  45. OpName %6 "simple_struct"
  46. %1 = OpTypeVoid
  47. %2 = OpTypeInt 32 0
  48. %3 = OpTypeStruct %2 %2 %2 %2
  49. %4 = OpTypePointer Function %3
  50. %5 = OpTypePointer Function %2
  51. %6 = OpTypeFunction %2
  52. %7 = OpConstantNull %3
  53. %8 = OpConstant %2 0
  54. %9 = OpConstant %2 1
  55. %10 = OpConstant %2 2
  56. %11 = OpConstant %2 3
  57. %12 = OpFunction %2 None %6
  58. %13 = OpLabel
  59. %14 = OpVariable %4 Function %7
  60. %15 = OpInBoundsAccessChain %5 %14 %8
  61. %16 = OpLoad %2 %15
  62. %17 = OpAccessChain %5 %14 %10
  63. %18 = OpLoad %2 %17
  64. %19 = OpIAdd %2 %16 %18
  65. OpReturnValue %19
  66. OpFunctionEnd
  67. )";
  68. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  69. }
  70. TEST_F(ScalarReplacementTest, StructInitialization) {
  71. const std::string text = R"(
  72. ;
  73. ; CHECK: [[elem:%\w+]] = OpTypeInt 32 0
  74. ; CHECK: [[struct:%\w+]] = OpTypeStruct [[elem]] [[elem]] [[elem]] [[elem]]
  75. ; CHECK: [[struct_ptr:%\w+]] = OpTypePointer Function [[struct]]
  76. ; CHECK: [[elem_ptr:%\w+]] = OpTypePointer Function [[elem]]
  77. ; CHECK: [[zero:%\w+]] = OpConstant [[elem]] 0
  78. ; CHECK: [[undef:%\w+]] = OpUndef [[elem]]
  79. ; CHECK: [[two:%\w+]] = OpConstant [[elem]] 2
  80. ; CHECK: [[null:%\w+]] = OpConstantNull [[elem]]
  81. ; CHECK-NOT: OpVariable [[struct_ptr]]
  82. ; CHECK: OpVariable [[elem_ptr]] Function [[null]]
  83. ; CHECK-NEXT: OpVariable [[elem_ptr]] Function [[two]]
  84. ; CHECK-NOT: OpVariable [[elem_ptr]] Function [[undef]]
  85. ; CHECK-NEXT: OpVariable [[elem_ptr]] Function
  86. ; CHECK-NEXT: OpVariable [[elem_ptr]] Function [[zero]]
  87. ; CHECK-NOT: OpVariable [[elem_ptr]] Function [[undef]]
  88. ;
  89. OpCapability Shader
  90. OpCapability Linkage
  91. OpMemoryModel Logical GLSL450
  92. OpName %6 "struct_init"
  93. %1 = OpTypeVoid
  94. %2 = OpTypeInt 32 0
  95. %3 = OpTypeStruct %2 %2 %2 %2
  96. %4 = OpTypePointer Function %3
  97. %20 = OpTypePointer Function %2
  98. %6 = OpTypeFunction %1
  99. %7 = OpConstant %2 0
  100. %8 = OpUndef %2
  101. %9 = OpConstant %2 2
  102. %30 = OpConstant %2 1
  103. %31 = OpConstant %2 3
  104. %10 = OpConstantNull %2
  105. %11 = OpConstantComposite %3 %7 %8 %9 %10
  106. %12 = OpFunction %1 None %6
  107. %13 = OpLabel
  108. %14 = OpVariable %4 Function %11
  109. %15 = OpAccessChain %20 %14 %7
  110. OpStore %15 %10
  111. %16 = OpAccessChain %20 %14 %9
  112. OpStore %16 %10
  113. %17 = OpAccessChain %20 %14 %30
  114. OpStore %17 %10
  115. %18 = OpAccessChain %20 %14 %31
  116. OpStore %18 %10
  117. OpReturn
  118. OpFunctionEnd
  119. )";
  120. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  121. }
  122. TEST_F(ScalarReplacementTest, SpecConstantInitialization) {
  123. const std::string text = R"(
  124. ;
  125. ; CHECK: [[int:%\w+]] = OpTypeInt 32 0
  126. ; CHECK: [[struct:%\w+]] = OpTypeStruct [[int]] [[int]]
  127. ; CHECK: [[struct_ptr:%\w+]] = OpTypePointer Function [[struct]]
  128. ; CHECK: [[int_ptr:%\w+]] = OpTypePointer Function [[int]]
  129. ; CHECK: [[spec_comp:%\w+]] = OpSpecConstantComposite [[struct]]
  130. ; CHECK: [[ex0:%\w+]] = OpSpecConstantOp [[int]] CompositeExtract [[spec_comp]] 0
  131. ; CHECK: [[ex1:%\w+]] = OpSpecConstantOp [[int]] CompositeExtract [[spec_comp]] 1
  132. ; CHECK-NOT: OpVariable [[struct]]
  133. ; CHECK: OpVariable [[int_ptr]] Function [[ex1]]
  134. ; CHECK-NEXT: OpVariable [[int_ptr]] Function [[ex0]]
  135. ; CHECK-NOT: OpVariable [[struct]]
  136. ;
  137. OpCapability Shader
  138. OpCapability Linkage
  139. OpMemoryModel Logical GLSL450
  140. OpName %6 "spec_const"
  141. %1 = OpTypeVoid
  142. %2 = OpTypeInt 32 0
  143. %3 = OpTypeStruct %2 %2
  144. %4 = OpTypePointer Function %3
  145. %20 = OpTypePointer Function %2
  146. %5 = OpTypeFunction %1
  147. %6 = OpConstant %2 0
  148. %30 = OpConstant %2 1
  149. %7 = OpSpecConstant %2 0
  150. %8 = OpSpecConstantOp %2 IAdd %7 %7
  151. %9 = OpSpecConstantComposite %3 %7 %8
  152. %10 = OpFunction %1 None %5
  153. %11 = OpLabel
  154. %12 = OpVariable %4 Function %9
  155. %13 = OpAccessChain %20 %12 %6
  156. %14 = OpLoad %2 %13
  157. %15 = OpAccessChain %20 %12 %30
  158. %16 = OpLoad %2 %15
  159. OpReturn
  160. OpFunctionEnd
  161. )";
  162. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  163. }
  164. // TODO(alanbaker): Re-enable when vector and matrix scalarization is supported.
  165. // TEST_F(ScalarReplacementTest, VectorInitialization) {
  166. // const std::string text = R"(
  167. // ;
  168. // ; CHECK: [[elem:%\w+]] = OpTypeInt 32 0
  169. // ; CHECK: [[vector:%\w+]] = OpTypeVector [[elem]] 4
  170. // ; CHECK: [[vector_ptr:%\w+]] = OpTypePointer Function [[vector]]
  171. // ; CHECK: [[elem_ptr:%\w+]] = OpTypePointer Function [[elem]]
  172. // ; CHECK: [[zero:%\w+]] = OpConstant [[elem]] 0
  173. // ; CHECK: [[undef:%\w+]] = OpUndef [[elem]]
  174. // ; CHECK: [[two:%\w+]] = OpConstant [[elem]] 2
  175. // ; CHECK: [[null:%\w+]] = OpConstantNull [[elem]]
  176. // ; CHECK-NOT: OpVariable [[vector_ptr]]
  177. // ; CHECK: OpVariable [[elem_ptr]] Function [[zero]]
  178. // ; CHECK-NOT: OpVariable [[elem_ptr]] Function [[undef]]
  179. // ; CHECK-NEXT: OpVariable [[elem_ptr]] Function
  180. // ; CHECK-NEXT: OpVariable [[elem_ptr]] Function [[two]]
  181. // ; CHECK-NEXT: OpVariable [[elem_ptr]] Function [[null]]
  182. // ; CHECK-NOT: OpVariable [[elem_ptr]] Function [[undef]]
  183. // ;
  184. // OpCapability Shader
  185. // OpCapability Linkage
  186. // OpMemoryModel Logical GLSL450
  187. // OpName %6 "vector_init"
  188. // %1 = OpTypeVoid
  189. // %2 = OpTypeInt 32 0
  190. // %3 = OpTypeVector %2 4
  191. // %4 = OpTypePointer Function %3
  192. // %20 = OpTypePointer Function %2
  193. // %6 = OpTypeFunction %1
  194. // %7 = OpConstant %2 0
  195. // %8 = OpUndef %2
  196. // %9 = OpConstant %2 2
  197. // %30 = OpConstant %2 1
  198. // %31 = OpConstant %2 3
  199. // %10 = OpConstantNull %2
  200. // %11 = OpConstantComposite %3 %10 %9 %8 %7
  201. // %12 = OpFunction %1 None %6
  202. // %13 = OpLabel
  203. // %14 = OpVariable %4 Function %11
  204. // %15 = OpAccessChain %20 %14 %7
  205. // OpStore %15 %10
  206. // %16 = OpAccessChain %20 %14 %9
  207. // OpStore %16 %10
  208. // %17 = OpAccessChain %20 %14 %30
  209. // OpStore %17 %10
  210. // %18 = OpAccessChain %20 %14 %31
  211. // OpStore %18 %10
  212. // OpReturn
  213. // OpFunctionEnd
  214. // )";
  215. //
  216. // SinglePassRunAndMatch<opt::ScalarReplacementPass>(text, true);
  217. // }
  218. //
  219. // TEST_F(ScalarReplacementTest, MatrixInitialization) {
  220. // const std::string text = R"(
  221. // ;
  222. // ; CHECK: [[float:%\w+]] = OpTypeFloat 32
  223. // ; CHECK: [[vector:%\w+]] = OpTypeVector [[float]] 2
  224. // ; CHECK: [[matrix:%\w+]] = OpTypeMatrix [[vector]] 2
  225. // ; CHECK: [[matrix_ptr:%\w+]] = OpTypePointer Function [[matrix]]
  226. // ; CHECK: [[float_ptr:%\w+]] = OpTypePointer Function [[float]]
  227. // ; CHECK: [[vec_ptr:%\w+]] = OpTypePointer Function [[vector]]
  228. // ; CHECK: [[zerof:%\w+]] = OpConstant [[float]] 0
  229. // ; CHECK: [[onef:%\w+]] = OpConstant [[float]] 1
  230. // ; CHECK: [[one_zero:%\w+]] = OpConstantComposite [[vector]] [[onef]]
  231. // [[zerof]] ; CHECK: [[zero_one:%\w+]] = OpConstantComposite [[vector]]
  232. // [[zerof]] [[onef]] ; CHECK: [[const_mat:%\w+]] = OpConstantComposite
  233. // [[matrix]] [[one_zero]]
  234. // [[zero_one]] ; CHECK-NOT: OpVariable [[matrix]] ; CHECK-NOT: OpVariable
  235. // [[vector]] Function [[one_zero]] ; CHECK: [[f1:%\w+]] = OpVariable
  236. // [[float_ptr]] Function [[zerof]] ; CHECK-NEXT: [[f2:%\w+]] = OpVariable
  237. // [[float_ptr]] Function [[onef]] ; CHECK-NEXT: [[vec_var:%\w+]] = OpVariable
  238. // [[vec_ptr]] Function [[zero_one]] ; CHECK-NOT: OpVariable [[matrix]] ;
  239. // CHECK-NOT: OpVariable [[vector]] Function [[one_zero]]
  240. // ;
  241. // OpCapability Shader
  242. // OpCapability Linkage
  243. // OpMemoryModel Logical GLSL450
  244. // OpName %7 "matrix_init"
  245. // %1 = OpTypeVoid
  246. // %2 = OpTypeFloat 32
  247. // %3 = OpTypeVector %2 2
  248. // %4 = OpTypeMatrix %3 2
  249. // %5 = OpTypePointer Function %4
  250. // %6 = OpTypePointer Function %2
  251. // %30 = OpTypePointer Function %3
  252. // %10 = OpTypeInt 32 0
  253. // %7 = OpTypeFunction %1 %10
  254. // %8 = OpConstant %2 0.0
  255. // %9 = OpConstant %2 1.0
  256. // %11 = OpConstant %10 0
  257. // %12 = OpConstant %10 1
  258. // %13 = OpConstantComposite %3 %9 %8
  259. // %14 = OpConstantComposite %3 %8 %9
  260. // %15 = OpConstantComposite %4 %13 %14
  261. // %16 = OpFunction %1 None %7
  262. // %31 = OpFunctionParameter %10
  263. // %17 = OpLabel
  264. // %18 = OpVariable %5 Function %15
  265. // %19 = OpAccessChain %6 %18 %11 %12
  266. // OpStore %19 %8
  267. // %20 = OpAccessChain %6 %18 %11 %11
  268. // OpStore %20 %8
  269. // %21 = OpAccessChain %30 %18 %12
  270. // OpStore %21 %14
  271. // OpReturn
  272. // OpFunctionEnd
  273. // )";
  274. //
  275. // SinglePassRunAndMatch<opt::ScalarReplacementPass>(text, true);
  276. // }
  277. TEST_F(ScalarReplacementTest, ElideAccessChain) {
  278. const std::string text = R"(
  279. ;
  280. ; CHECK: [[var:%\w+]] = OpVariable
  281. ; CHECK-NOT: OpAccessChain
  282. ; CHECK: OpStore [[var]]
  283. ;
  284. OpCapability Shader
  285. OpCapability Linkage
  286. OpMemoryModel Logical GLSL450
  287. OpName %6 "elide_access_chain"
  288. %1 = OpTypeVoid
  289. %2 = OpTypeInt 32 0
  290. %3 = OpTypeStruct %2 %2 %2 %2
  291. %4 = OpTypePointer Function %3
  292. %20 = OpTypePointer Function %2
  293. %6 = OpTypeFunction %1
  294. %7 = OpConstant %2 0
  295. %8 = OpUndef %2
  296. %9 = OpConstant %2 2
  297. %10 = OpConstantNull %2
  298. %11 = OpConstantComposite %3 %7 %8 %9 %10
  299. %12 = OpFunction %1 None %6
  300. %13 = OpLabel
  301. %14 = OpVariable %4 Function %11
  302. %15 = OpAccessChain %20 %14 %7
  303. OpStore %15 %10
  304. OpReturn
  305. OpFunctionEnd
  306. )";
  307. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  308. }
  309. TEST_F(ScalarReplacementTest, ElideMultipleAccessChains) {
  310. const std::string text = R"(
  311. ;
  312. ; CHECK: [[var:%\w+]] = OpVariable
  313. ; CHECK-NOT: OpInBoundsAccessChain
  314. ; CHECK OpStore [[var]]
  315. ;
  316. OpCapability Shader
  317. OpCapability Linkage
  318. OpMemoryModel Logical GLSL450
  319. OpName %6 "elide_two_access_chains"
  320. %1 = OpTypeVoid
  321. %2 = OpTypeFloat 32
  322. %3 = OpTypeStruct %2 %2
  323. %4 = OpTypeStruct %3 %3
  324. %5 = OpTypePointer Function %4
  325. %6 = OpTypePointer Function %2
  326. %7 = OpTypeFunction %1
  327. %8 = OpConstant %2 0.0
  328. %9 = OpConstant %2 1.0
  329. %10 = OpTypeInt 32 0
  330. %11 = OpConstant %10 0
  331. %12 = OpConstant %10 1
  332. %13 = OpConstantComposite %3 %9 %8
  333. %14 = OpConstantComposite %3 %8 %9
  334. %15 = OpConstantComposite %4 %13 %14
  335. %16 = OpFunction %1 None %7
  336. %17 = OpLabel
  337. %18 = OpVariable %5 Function %15
  338. %19 = OpInBoundsAccessChain %6 %18 %11 %12
  339. OpStore %19 %8
  340. OpReturn
  341. OpFunctionEnd
  342. )";
  343. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  344. }
  345. TEST_F(ScalarReplacementTest, ReplaceAccessChain) {
  346. const std::string text = R"(
  347. ;
  348. ; CHECK: [[param:%\w+]] = OpFunctionParameter
  349. ; CHECK: [[var:%\w+]] = OpVariable
  350. ; CHECK: [[access:%\w+]] = OpAccessChain {{%\w+}} [[var]] [[param]]
  351. ; CHECK: OpStore [[access]]
  352. ;
  353. OpCapability Shader
  354. OpCapability Linkage
  355. OpMemoryModel Logical GLSL450
  356. OpName %7 "replace_access_chain"
  357. %1 = OpTypeVoid
  358. %2 = OpTypeFloat 32
  359. %10 = OpTypeInt 32 0
  360. %uint_2 = OpConstant %10 2
  361. %3 = OpTypeArray %2 %uint_2
  362. %4 = OpTypeStruct %3 %3
  363. %5 = OpTypePointer Function %4
  364. %20 = OpTypePointer Function %3
  365. %6 = OpTypePointer Function %2
  366. %7 = OpTypeFunction %1 %10
  367. %8 = OpConstant %2 0.0
  368. %9 = OpConstant %2 1.0
  369. %11 = OpConstant %10 0
  370. %12 = OpConstant %10 1
  371. %13 = OpConstantComposite %3 %9 %8
  372. %14 = OpConstantComposite %3 %8 %9
  373. %15 = OpConstantComposite %4 %13 %14
  374. %16 = OpFunction %1 None %7
  375. %32 = OpFunctionParameter %10
  376. %17 = OpLabel
  377. %18 = OpVariable %5 Function %15
  378. %19 = OpAccessChain %6 %18 %11 %32
  379. OpStore %19 %8
  380. OpReturn
  381. OpFunctionEnd
  382. )";
  383. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  384. }
  385. TEST_F(ScalarReplacementTest, ArrayInitialization) {
  386. const std::string text = R"(
  387. ;
  388. ; CHECK: [[float:%\w+]] = OpTypeFloat 32
  389. ; CHECK: [[array:%\w+]] = OpTypeArray
  390. ; CHECK: [[array_ptr:%\w+]] = OpTypePointer Function [[array]]
  391. ; CHECK: [[float_ptr:%\w+]] = OpTypePointer Function [[float]]
  392. ; CHECK: [[float0:%\w+]] = OpConstant [[float]] 0
  393. ; CHECK: [[float1:%\w+]] = OpConstant [[float]] 1
  394. ; CHECK: [[float2:%\w+]] = OpConstant [[float]] 2
  395. ; CHECK-NOT: OpVariable [[array_ptr]]
  396. ; CHECK: [[var0:%\w+]] = OpVariable [[float_ptr]] Function [[float0]]
  397. ; CHECK-NEXT: [[var1:%\w+]] = OpVariable [[float_ptr]] Function [[float1]]
  398. ; CHECK-NEXT: [[var2:%\w+]] = OpVariable [[float_ptr]] Function [[float2]]
  399. ; CHECK-NOT: OpVariable [[array_ptr]]
  400. ;
  401. OpCapability Shader
  402. OpCapability Linkage
  403. OpMemoryModel Logical GLSL450
  404. OpName %func "array_init"
  405. %void = OpTypeVoid
  406. %uint = OpTypeInt 32 0
  407. %float = OpTypeFloat 32
  408. %uint_0 = OpConstant %uint 0
  409. %uint_1 = OpConstant %uint 1
  410. %uint_2 = OpConstant %uint 2
  411. %uint_3 = OpConstant %uint 3
  412. %float_array = OpTypeArray %float %uint_3
  413. %array_ptr = OpTypePointer Function %float_array
  414. %float_ptr = OpTypePointer Function %float
  415. %float_0 = OpConstant %float 0
  416. %float_1 = OpConstant %float 1
  417. %float_2 = OpConstant %float 2
  418. %const_array = OpConstantComposite %float_array %float_2 %float_1 %float_0
  419. %func = OpTypeFunction %void
  420. %1 = OpFunction %void None %func
  421. %2 = OpLabel
  422. %3 = OpVariable %array_ptr Function %const_array
  423. %4 = OpInBoundsAccessChain %float_ptr %3 %uint_0
  424. OpStore %4 %float_0
  425. %5 = OpInBoundsAccessChain %float_ptr %3 %uint_1
  426. OpStore %5 %float_0
  427. %6 = OpInBoundsAccessChain %float_ptr %3 %uint_2
  428. OpStore %6 %float_0
  429. OpReturn
  430. OpFunctionEnd
  431. )";
  432. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  433. }
  434. TEST_F(ScalarReplacementTest, NonUniformCompositeInitialization) {
  435. const std::string text = R"(
  436. ;
  437. ; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
  438. ; CHECK: [[long:%\w+]] = OpTypeInt 64 1
  439. ; CHECK: [[dvector:%\w+]] = OpTypeVector
  440. ; CHECK: [[vector:%\w+]] = OpTypeVector
  441. ; CHECK: [[array:%\w+]] = OpTypeArray
  442. ; CHECK: [[matrix:%\w+]] = OpTypeMatrix
  443. ; CHECK: [[struct1:%\w+]] = OpTypeStruct [[uint]] [[vector]]
  444. ; CHECK: [[struct2:%\w+]] = OpTypeStruct [[struct1]] [[matrix]] [[array]] [[uint]]
  445. ; CHECK: [[struct1_ptr:%\w+]] = OpTypePointer Function [[struct1]]
  446. ; CHECK: [[matrix_ptr:%\w+]] = OpTypePointer Function [[matrix]]
  447. ; CHECK: [[array_ptr:%\w+]] = OpTypePointer Function [[array]]
  448. ; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]]
  449. ; CHECK: [[struct2_ptr:%\w+]] = OpTypePointer Function [[struct2]]
  450. ; CHECK: [[const_array:%\w+]] = OpConstantComposite [[array]]
  451. ; CHECK: [[const_matrix:%\w+]] = OpConstantNull [[matrix]]
  452. ; CHECK: [[const_struct1:%\w+]] = OpConstantComposite [[struct1]]
  453. ; CHECK: OpConstantNull [[uint]]
  454. ; CHECK: OpConstantNull [[vector]]
  455. ; CHECK: OpConstantNull [[long]]
  456. ; CHECK: OpFunction
  457. ; CHECK-NOT: OpVariable [[struct2_ptr]] Function
  458. ; CHECK: OpVariable [[uint_ptr]] Function
  459. ; CHECK-NEXT: OpVariable [[matrix_ptr]] Function [[const_matrix]]
  460. ; CHECK-NOT: OpVariable [[struct1_ptr]] Function [[const_struct1]]
  461. ; CHECK-NOT: OpVariable [[struct2_ptr]] Function
  462. ;
  463. OpCapability Shader
  464. OpCapability Linkage
  465. OpCapability Int64
  466. OpCapability Float64
  467. OpMemoryModel Logical GLSL450
  468. OpName %func "non_uniform_composite_init"
  469. %void = OpTypeVoid
  470. %uint = OpTypeInt 32 0
  471. %int64 = OpTypeInt 64 1
  472. %float = OpTypeFloat 32
  473. %double = OpTypeFloat 64
  474. %double2 = OpTypeVector %double 2
  475. %float4 = OpTypeVector %float 4
  476. %int64_0 = OpConstant %int64 0
  477. %int64_1 = OpConstant %int64 1
  478. %int64_2 = OpConstant %int64 2
  479. %int64_3 = OpConstant %int64 3
  480. %int64_array3 = OpTypeArray %int64 %int64_3
  481. %matrix_double2 = OpTypeMatrix %double2 2
  482. %struct1 = OpTypeStruct %uint %float4
  483. %struct2 = OpTypeStruct %struct1 %matrix_double2 %int64_array3 %uint
  484. %struct1_ptr = OpTypePointer Function %struct1
  485. %matrix_double2_ptr = OpTypePointer Function %matrix_double2
  486. %int64_array_ptr = OpTypePointer Function %int64_array3
  487. %uint_ptr = OpTypePointer Function %uint
  488. %struct2_ptr = OpTypePointer Function %struct2
  489. %const_uint = OpConstant %uint 0
  490. %const_int64_array = OpConstantComposite %int64_array3 %int64_0 %int64_1 %int64_2
  491. %const_double2 = OpConstantNull %double2
  492. %const_matrix_double2 = OpConstantNull %matrix_double2
  493. %undef_float4 = OpUndef %float4
  494. %const_struct1 = OpConstantComposite %struct1 %const_uint %undef_float4
  495. %const_struct2 = OpConstantComposite %struct2 %const_struct1 %const_matrix_double2 %const_int64_array %const_uint
  496. %func = OpTypeFunction %void
  497. %1 = OpFunction %void None %func
  498. %2 = OpLabel
  499. %var = OpVariable %struct2_ptr Function %const_struct2
  500. %3 = OpAccessChain %struct1_ptr %var %int64_0
  501. OpStore %3 %const_struct1
  502. %4 = OpAccessChain %matrix_double2_ptr %var %int64_1
  503. OpStore %4 %const_matrix_double2
  504. %5 = OpAccessChain %int64_array_ptr %var %int64_2
  505. OpStore %5 %const_int64_array
  506. %6 = OpAccessChain %uint_ptr %var %int64_3
  507. OpStore %6 %const_uint
  508. OpReturn
  509. OpFunctionEnd
  510. )";
  511. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  512. }
  513. TEST_F(ScalarReplacementTest, ElideUncombinedAccessChains) {
  514. const std::string text = R"(
  515. ;
  516. ; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
  517. ; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]]
  518. ; CHECK: [[const:%\w+]] = OpConstant [[uint]] 0
  519. ; CHECK: [[var:%\w+]] = OpVariable [[uint_ptr]] Function
  520. ; CHECK-NOT: OpAccessChain
  521. ; CHECK: OpStore [[var]] [[const]]
  522. ;
  523. OpCapability Shader
  524. OpCapability Linkage
  525. OpMemoryModel Logical GLSL450
  526. OpName %func "elide_uncombined_access_chains"
  527. %void = OpTypeVoid
  528. %uint = OpTypeInt 32 0
  529. %struct1 = OpTypeStruct %uint
  530. %struct2 = OpTypeStruct %struct1
  531. %uint_ptr = OpTypePointer Function %uint
  532. %struct1_ptr = OpTypePointer Function %struct1
  533. %struct2_ptr = OpTypePointer Function %struct2
  534. %uint_0 = OpConstant %uint 0
  535. %func = OpTypeFunction %void
  536. %1 = OpFunction %void None %func
  537. %2 = OpLabel
  538. %var = OpVariable %struct2_ptr Function
  539. %3 = OpAccessChain %struct1_ptr %var %uint_0
  540. %4 = OpAccessChain %uint_ptr %3 %uint_0
  541. OpStore %4 %uint_0
  542. OpReturn
  543. OpFunctionEnd
  544. )";
  545. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  546. }
  547. TEST_F(ScalarReplacementTest, ElideSingleUncombinedAccessChains) {
  548. const std::string text = R"(
  549. ;
  550. ; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
  551. ; CHECK: [[array:%\w+]] = OpTypeArray [[uint]]
  552. ; CHECK: [[array_ptr:%\w+]] = OpTypePointer Function [[array]]
  553. ; CHECK: [[const:%\w+]] = OpConstant [[uint]] 0
  554. ; CHECK: [[param:%\w+]] = OpFunctionParameter [[uint]]
  555. ; CHECK: [[var:%\w+]] = OpVariable [[array_ptr]] Function
  556. ; CHECK: [[access:%\w+]] = OpAccessChain {{.*}} [[var]] [[param]]
  557. ; CHECK: OpStore [[access]] [[const]]
  558. ;
  559. OpCapability Shader
  560. OpCapability Linkage
  561. OpMemoryModel Logical GLSL450
  562. OpName %func "elide_single_uncombined_access_chains"
  563. %void = OpTypeVoid
  564. %uint = OpTypeInt 32 0
  565. %uint_1 = OpConstant %uint 1
  566. %array = OpTypeArray %uint %uint_1
  567. %struct2 = OpTypeStruct %array
  568. %uint_ptr = OpTypePointer Function %uint
  569. %array_ptr = OpTypePointer Function %array
  570. %struct2_ptr = OpTypePointer Function %struct2
  571. %uint_0 = OpConstant %uint 0
  572. %func = OpTypeFunction %void %uint
  573. %1 = OpFunction %void None %func
  574. %param = OpFunctionParameter %uint
  575. %2 = OpLabel
  576. %var = OpVariable %struct2_ptr Function
  577. %3 = OpAccessChain %array_ptr %var %uint_0
  578. %4 = OpAccessChain %uint_ptr %3 %param
  579. OpStore %4 %uint_0
  580. OpReturn
  581. OpFunctionEnd
  582. )";
  583. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  584. }
  585. TEST_F(ScalarReplacementTest, ReplaceWholeLoad) {
  586. const std::string text = R"(
  587. ;
  588. ; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
  589. ; CHECK: [[struct1:%\w+]] = OpTypeStruct [[uint]] [[uint]]
  590. ; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]]
  591. ; CHECK: [[const:%\w+]] = OpConstant [[uint]] 0
  592. ; CHECK: [[var1:%\w+]] = OpVariable [[uint_ptr]] Function
  593. ; CHECK: [[var0:%\w+]] = OpVariable [[uint_ptr]] Function
  594. ; CHECK: [[l1:%\w+]] = OpLoad [[uint]] [[var1]]
  595. ; CHECK: [[l0:%\w+]] = OpLoad [[uint]] [[var0]]
  596. ; CHECK: OpCompositeConstruct [[struct1]] [[l0]] [[l1]]
  597. ;
  598. OpCapability Shader
  599. OpCapability Linkage
  600. OpMemoryModel Logical GLSL450
  601. OpName %func "replace_whole_load"
  602. %void = OpTypeVoid
  603. %uint = OpTypeInt 32 0
  604. %struct1 = OpTypeStruct %uint %uint
  605. %uint_ptr = OpTypePointer Function %uint
  606. %struct1_ptr = OpTypePointer Function %struct1
  607. %uint_0 = OpConstant %uint 0
  608. %uint_1 = OpConstant %uint 1
  609. %func = OpTypeFunction %void
  610. %1 = OpFunction %void None %func
  611. %2 = OpLabel
  612. %var = OpVariable %struct1_ptr Function
  613. %load = OpLoad %struct1 %var
  614. %3 = OpAccessChain %uint_ptr %var %uint_0
  615. OpStore %3 %uint_0
  616. %4 = OpAccessChain %uint_ptr %var %uint_1
  617. OpStore %4 %uint_0
  618. OpReturn
  619. OpFunctionEnd
  620. )";
  621. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  622. }
  623. TEST_F(ScalarReplacementTest, ReplaceWholeLoadCopyMemoryAccess) {
  624. const std::string text = R"(
  625. ;
  626. ; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
  627. ; CHECK: [[struct1:%\w+]] = OpTypeStruct [[uint]] [[uint]]
  628. ; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]]
  629. ; CHECK: [[const:%\w+]] = OpConstant [[uint]] 0
  630. ; CHECK: [[null:%\w+]] = OpConstantNull [[uint]]
  631. ; CHECK: [[var0:%\w+]] = OpVariable [[uint_ptr]] Function
  632. ; CHECK: [[l0:%\w+]] = OpLoad [[uint]] [[var0]] Nontemporal
  633. ; CHECK: OpCompositeConstruct [[struct1]] [[l0]] [[null]]
  634. ;
  635. OpCapability Shader
  636. OpCapability Linkage
  637. OpMemoryModel Logical GLSL450
  638. OpName %func "replace_whole_load_copy_memory_access"
  639. %void = OpTypeVoid
  640. %uint = OpTypeInt 32 0
  641. %struct1 = OpTypeStruct %uint %uint
  642. %uint_ptr = OpTypePointer Function %uint
  643. %struct1_ptr = OpTypePointer Function %struct1
  644. %uint_0 = OpConstant %uint 0
  645. %func = OpTypeFunction %void
  646. %1 = OpFunction %void None %func
  647. %2 = OpLabel
  648. %var = OpVariable %struct1_ptr Function
  649. %load = OpLoad %struct1 %var Nontemporal
  650. %3 = OpAccessChain %uint_ptr %var %uint_0
  651. OpStore %3 %uint_0
  652. OpReturn
  653. OpFunctionEnd
  654. )";
  655. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  656. }
  657. TEST_F(ScalarReplacementTest, ReplaceWholeStore) {
  658. const std::string text = R"(
  659. ;
  660. ; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
  661. ; CHECK: [[struct1:%\w+]] = OpTypeStruct [[uint]] [[uint]]
  662. ; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]]
  663. ; CHECK: [[const:%\w+]] = OpConstant [[uint]] 0
  664. ; CHECK: [[const_struct:%\w+]] = OpConstantComposite [[struct1]] [[const]] [[const]]
  665. ; CHECK: [[var0:%\w+]] = OpVariable [[uint_ptr]] Function
  666. ; CHECK: [[ex0:%\w+]] = OpCompositeExtract [[uint]] [[const_struct]] 0
  667. ; CHECK: OpStore [[var0]] [[ex0]]
  668. ;
  669. OpCapability Shader
  670. OpCapability Linkage
  671. OpMemoryModel Logical GLSL450
  672. OpName %func "replace_whole_store"
  673. %void = OpTypeVoid
  674. %uint = OpTypeInt 32 0
  675. %struct1 = OpTypeStruct %uint %uint
  676. %uint_ptr = OpTypePointer Function %uint
  677. %struct1_ptr = OpTypePointer Function %struct1
  678. %uint_0 = OpConstant %uint 0
  679. %const_struct = OpConstantComposite %struct1 %uint_0 %uint_0
  680. %func = OpTypeFunction %void
  681. %1 = OpFunction %void None %func
  682. %2 = OpLabel
  683. %var = OpVariable %struct1_ptr Function
  684. OpStore %var %const_struct
  685. %3 = OpAccessChain %uint_ptr %var %uint_0
  686. %4 = OpLoad %uint %3
  687. OpReturn
  688. OpFunctionEnd
  689. )";
  690. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  691. }
  692. TEST_F(ScalarReplacementTest, ReplaceWholeStoreCopyMemoryAccess) {
  693. const std::string text = R"(
  694. ;
  695. ; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
  696. ; CHECK: [[struct1:%\w+]] = OpTypeStruct [[uint]] [[uint]]
  697. ; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]]
  698. ; CHECK: [[const:%\w+]] = OpConstant [[uint]] 0
  699. ; CHECK: [[const_struct:%\w+]] = OpConstantComposite [[struct1]] [[const]] [[const]]
  700. ; CHECK: [[var0:%\w+]] = OpVariable [[uint_ptr]] Function
  701. ; CHECK-NOT: OpVariable
  702. ; CHECK: [[ex0:%\w+]] = OpCompositeExtract [[uint]] [[const_struct]] 0
  703. ; CHECK: OpStore [[var0]] [[ex0]] Aligned 4
  704. ;
  705. OpCapability Shader
  706. OpCapability Linkage
  707. OpMemoryModel Logical GLSL450
  708. OpName %func "replace_whole_store_copy_memory_access"
  709. %void = OpTypeVoid
  710. %uint = OpTypeInt 32 0
  711. %struct1 = OpTypeStruct %uint %uint
  712. %uint_ptr = OpTypePointer Function %uint
  713. %struct1_ptr = OpTypePointer Function %struct1
  714. %uint_0 = OpConstant %uint 0
  715. %const_struct = OpConstantComposite %struct1 %uint_0 %uint_0
  716. %func = OpTypeFunction %void
  717. %1 = OpFunction %void None %func
  718. %2 = OpLabel
  719. %var = OpVariable %struct1_ptr Function
  720. OpStore %var %const_struct Aligned 4
  721. %3 = OpAccessChain %uint_ptr %var %uint_0
  722. %4 = OpLoad %uint %3
  723. OpReturn
  724. OpFunctionEnd
  725. )";
  726. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  727. }
  728. TEST_F(ScalarReplacementTest, DontTouchVolatileLoad) {
  729. const std::string text = R"(
  730. ;
  731. ; CHECK: [[struct:%\w+]] = OpTypeStruct
  732. ; CHECK: [[struct_ptr:%\w+]] = OpTypePointer Function [[struct]]
  733. ; CHECK: OpLabel
  734. ; CHECK-NEXT: OpVariable [[struct_ptr]]
  735. ; CHECK-NOT: OpVariable
  736. ;
  737. OpCapability Shader
  738. OpCapability Linkage
  739. OpMemoryModel Logical GLSL450
  740. OpName %func "dont_touch_volatile_load"
  741. %void = OpTypeVoid
  742. %uint = OpTypeInt 32 0
  743. %struct1 = OpTypeStruct %uint
  744. %uint_ptr = OpTypePointer Function %uint
  745. %struct1_ptr = OpTypePointer Function %struct1
  746. %uint_0 = OpConstant %uint 0
  747. %func = OpTypeFunction %void
  748. %1 = OpFunction %void None %func
  749. %2 = OpLabel
  750. %var = OpVariable %struct1_ptr Function
  751. %3 = OpAccessChain %uint_ptr %var %uint_0
  752. %4 = OpLoad %uint %3 Volatile
  753. OpReturn
  754. OpFunctionEnd
  755. )";
  756. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  757. }
  758. TEST_F(ScalarReplacementTest, DontTouchVolatileStore) {
  759. const std::string text = R"(
  760. ;
  761. ; CHECK: [[struct:%\w+]] = OpTypeStruct
  762. ; CHECK: [[struct_ptr:%\w+]] = OpTypePointer Function [[struct]]
  763. ; CHECK: OpLabel
  764. ; CHECK-NEXT: OpVariable [[struct_ptr]]
  765. ; CHECK-NOT: OpVariable
  766. ;
  767. OpCapability Shader
  768. OpCapability Linkage
  769. OpMemoryModel Logical GLSL450
  770. OpName %func "dont_touch_volatile_store"
  771. %void = OpTypeVoid
  772. %uint = OpTypeInt 32 0
  773. %struct1 = OpTypeStruct %uint
  774. %uint_ptr = OpTypePointer Function %uint
  775. %struct1_ptr = OpTypePointer Function %struct1
  776. %uint_0 = OpConstant %uint 0
  777. %func = OpTypeFunction %void
  778. %1 = OpFunction %void None %func
  779. %2 = OpLabel
  780. %var = OpVariable %struct1_ptr Function
  781. %3 = OpAccessChain %uint_ptr %var %uint_0
  782. OpStore %3 %uint_0 Volatile
  783. OpReturn
  784. OpFunctionEnd
  785. )";
  786. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  787. }
  788. TEST_F(ScalarReplacementTest, DontTouchSpecNonFunctionVariable) {
  789. const std::string text = R"(
  790. ;
  791. ; CHECK: [[struct:%\w+]] = OpTypeStruct
  792. ; CHECK: [[struct_ptr:%\w+]] = OpTypePointer Uniform [[struct]]
  793. ; CHECK: OpConstant
  794. ; CHECK-NEXT: OpVariable [[struct_ptr]]
  795. ; CHECK-NOT: OpVariable
  796. ;
  797. OpCapability Shader
  798. OpCapability Linkage
  799. OpMemoryModel Logical GLSL450
  800. OpName %func "dont_touch_spec_constant_access_chain"
  801. %void = OpTypeVoid
  802. %uint = OpTypeInt 32 0
  803. %struct1 = OpTypeStruct %uint
  804. %uint_ptr = OpTypePointer Uniform %uint
  805. %struct1_ptr = OpTypePointer Uniform %struct1
  806. %uint_0 = OpConstant %uint 0
  807. %var = OpVariable %struct1_ptr Uniform
  808. %func = OpTypeFunction %void
  809. %1 = OpFunction %void None %func
  810. %2 = OpLabel
  811. %3 = OpAccessChain %uint_ptr %var %uint_0
  812. OpStore %3 %uint_0 Volatile
  813. OpReturn
  814. OpFunctionEnd
  815. )";
  816. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  817. }
  818. TEST_F(ScalarReplacementTest, DontTouchSpecConstantAccessChain) {
  819. const std::string text = R"(
  820. ;
  821. ; CHECK: [[array:%\w+]] = OpTypeArray
  822. ; CHECK: [[array_ptr:%\w+]] = OpTypePointer Function [[array]]
  823. ; CHECK: OpLabel
  824. ; CHECK-NEXT: OpVariable [[array_ptr]]
  825. ; CHECK-NOT: OpVariable
  826. ;
  827. OpCapability Shader
  828. OpCapability Linkage
  829. OpMemoryModel Logical GLSL450
  830. OpName %func "dont_touch_spec_constant_access_chain"
  831. %void = OpTypeVoid
  832. %uint = OpTypeInt 32 0
  833. %uint_1 = OpConstant %uint 1
  834. %array = OpTypeArray %uint %uint_1
  835. %uint_ptr = OpTypePointer Function %uint
  836. %array_ptr = OpTypePointer Function %array
  837. %uint_0 = OpConstant %uint 0
  838. %spec_const = OpSpecConstant %uint 0
  839. %func = OpTypeFunction %void
  840. %1 = OpFunction %void None %func
  841. %2 = OpLabel
  842. %var = OpVariable %array_ptr Function
  843. %3 = OpAccessChain %uint_ptr %var %spec_const
  844. OpStore %3 %uint_0 Volatile
  845. OpReturn
  846. OpFunctionEnd
  847. )";
  848. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  849. }
  850. TEST_F(ScalarReplacementTest, NoPartialAccesses) {
  851. const std::string text = R"(
  852. ;
  853. ; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
  854. ; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]]
  855. ; CHECK: OpLabel
  856. ; CHECK-NOT: OpVariable
  857. ;
  858. OpCapability Shader
  859. OpCapability Linkage
  860. OpMemoryModel Logical GLSL450
  861. OpName %func "no_partial_accesses"
  862. %void = OpTypeVoid
  863. %uint = OpTypeInt 32 0
  864. %struct1 = OpTypeStruct %uint
  865. %uint_ptr = OpTypePointer Function %uint
  866. %struct1_ptr = OpTypePointer Function %struct1
  867. %const = OpConstantNull %struct1
  868. %func = OpTypeFunction %void
  869. %1 = OpFunction %void None %func
  870. %2 = OpLabel
  871. %var = OpVariable %struct1_ptr Function
  872. OpStore %var %const
  873. OpReturn
  874. OpFunctionEnd
  875. )";
  876. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  877. }
  878. TEST_F(ScalarReplacementTest, DontTouchPtrAccessChain) {
  879. const std::string text = R"(
  880. ;
  881. ; CHECK: [[struct:%\w+]] = OpTypeStruct
  882. ; CHECK: [[struct_ptr:%\w+]] = OpTypePointer Function [[struct]]
  883. ; CHECK: OpLabel
  884. ; CHECK-NEXT: OpVariable [[struct_ptr]]
  885. ; CHECK-NOT: OpVariable
  886. ;
  887. OpCapability Shader
  888. OpCapability Linkage
  889. OpMemoryModel Logical GLSL450
  890. OpName %func "dont_touch_ptr_access_chain"
  891. %void = OpTypeVoid
  892. %uint = OpTypeInt 32 0
  893. %struct1 = OpTypeStruct %uint
  894. %uint_ptr = OpTypePointer Function %uint
  895. %struct1_ptr = OpTypePointer Function %struct1
  896. %uint_0 = OpConstant %uint 0
  897. %func = OpTypeFunction %void
  898. %1 = OpFunction %void None %func
  899. %2 = OpLabel
  900. %var = OpVariable %struct1_ptr Function
  901. %3 = OpPtrAccessChain %uint_ptr %var %uint_0 %uint_0
  902. OpStore %3 %uint_0
  903. %4 = OpAccessChain %uint_ptr %var %uint_0
  904. OpStore %4 %uint_0
  905. OpReturn
  906. OpFunctionEnd
  907. )";
  908. SinglePassRunAndMatch<ScalarReplacementPass>(text, false);
  909. }
  910. TEST_F(ScalarReplacementTest, DontTouchInBoundsPtrAccessChain) {
  911. const std::string text = R"(
  912. ;
  913. ; CHECK: [[struct:%\w+]] = OpTypeStruct
  914. ; CHECK: [[struct_ptr:%\w+]] = OpTypePointer Function [[struct]]
  915. ; CHECK: OpLabel
  916. ; CHECK-NEXT: OpVariable [[struct_ptr]]
  917. ; CHECK-NOT: OpVariable
  918. ;
  919. OpCapability Shader
  920. OpCapability Linkage
  921. OpMemoryModel Logical GLSL450
  922. OpName %func "dont_touch_in_bounds_ptr_access_chain"
  923. %void = OpTypeVoid
  924. %uint = OpTypeInt 32 0
  925. %struct1 = OpTypeStruct %uint
  926. %uint_ptr = OpTypePointer Function %uint
  927. %struct1_ptr = OpTypePointer Function %struct1
  928. %uint_0 = OpConstant %uint 0
  929. %func = OpTypeFunction %void
  930. %1 = OpFunction %void None %func
  931. %2 = OpLabel
  932. %var = OpVariable %struct1_ptr Function
  933. %3 = OpInBoundsPtrAccessChain %uint_ptr %var %uint_0 %uint_0
  934. OpStore %3 %uint_0
  935. %4 = OpInBoundsAccessChain %uint_ptr %var %uint_0
  936. OpStore %4 %uint_0
  937. OpReturn
  938. OpFunctionEnd
  939. )";
  940. SinglePassRunAndMatch<ScalarReplacementPass>(text, false);
  941. }
  942. TEST_F(ScalarReplacementTest, DonTouchAliasedDecoration) {
  943. const std::string text = R"(
  944. ;
  945. ; CHECK: [[struct:%\w+]] = OpTypeStruct
  946. ; CHECK: [[struct_ptr:%\w+]] = OpTypePointer Function [[struct]]
  947. ; CHECK: OpLabel
  948. ; CHECK-NEXT: OpVariable [[struct_ptr]]
  949. ; CHECK-NOT: OpVariable
  950. ;
  951. OpCapability Shader
  952. OpCapability Linkage
  953. OpMemoryModel Logical GLSL450
  954. OpName %func "aliased"
  955. OpDecorate %var Aliased
  956. %void = OpTypeVoid
  957. %uint = OpTypeInt 32 0
  958. %struct1 = OpTypeStruct %uint
  959. %uint_ptr = OpTypePointer Function %uint
  960. %struct1_ptr = OpTypePointer Function %struct1
  961. %uint_0 = OpConstant %uint 0
  962. %func = OpTypeFunction %void
  963. %1 = OpFunction %void None %func
  964. %2 = OpLabel
  965. %var = OpVariable %struct1_ptr Function
  966. %3 = OpAccessChain %uint_ptr %var %uint_0
  967. %4 = OpLoad %uint %3
  968. OpReturn
  969. OpFunctionEnd
  970. )";
  971. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  972. }
  973. TEST_F(ScalarReplacementTest, CopyRestrictDecoration) {
  974. const std::string text = R"(
  975. ;
  976. ; CHECK: OpName
  977. ; CHECK-NEXT: OpDecorate [[var0:%\w+]] Restrict
  978. ; CHECK-NEXT: OpDecorate [[var1:%\w+]] Restrict
  979. ; CHECK: [[int:%\w+]] = OpTypeInt
  980. ; CHECK: [[struct:%\w+]] = OpTypeStruct
  981. ; CHECK: [[int_ptr:%\w+]] = OpTypePointer Function [[int]]
  982. ; CHECK: [[struct_ptr:%\w+]] = OpTypePointer Function [[struct]]
  983. ; CHECK: OpLabel
  984. ; CHECK-NEXT: [[var1]] = OpVariable [[int_ptr]]
  985. ; CHECK-NEXT: [[var0]] = OpVariable [[int_ptr]]
  986. ; CHECK-NOT: OpVariable [[struct_ptr]]
  987. ;
  988. OpCapability Shader
  989. OpCapability Linkage
  990. OpMemoryModel Logical GLSL450
  991. OpName %func "restrict"
  992. OpDecorate %var Restrict
  993. %void = OpTypeVoid
  994. %uint = OpTypeInt 32 0
  995. %struct1 = OpTypeStruct %uint %uint
  996. %uint_ptr = OpTypePointer Function %uint
  997. %struct1_ptr = OpTypePointer Function %struct1
  998. %uint_0 = OpConstant %uint 0
  999. %uint_1 = OpConstant %uint 1
  1000. %func = OpTypeFunction %void
  1001. %1 = OpFunction %void None %func
  1002. %2 = OpLabel
  1003. %var = OpVariable %struct1_ptr Function
  1004. %3 = OpAccessChain %uint_ptr %var %uint_0
  1005. %4 = OpLoad %uint %3
  1006. %5 = OpAccessChain %uint_ptr %var %uint_1
  1007. %6 = OpLoad %uint %5
  1008. OpReturn
  1009. OpFunctionEnd
  1010. )";
  1011. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  1012. }
  1013. TEST_F(ScalarReplacementTest, DontClobberDecoratesOnSubtypes) {
  1014. const std::string text = R"(
  1015. ;
  1016. ; CHECK: OpDecorate [[array:%\w+]] ArrayStride 1
  1017. ; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
  1018. ; CHECK: [[array]] = OpTypeArray [[uint]]
  1019. ; CHECK: [[array_ptr:%\w+]] = OpTypePointer Function [[array]]
  1020. ; CHECK: OpLabel
  1021. ; CHECK-NEXT: OpVariable [[array_ptr]] Function
  1022. ; CHECK-NOT: OpVariable
  1023. ;
  1024. OpCapability Shader
  1025. OpCapability Linkage
  1026. OpMemoryModel Logical GLSL450
  1027. OpName %func "array_stride"
  1028. OpDecorate %array ArrayStride 1
  1029. %void = OpTypeVoid
  1030. %uint = OpTypeInt 32 0
  1031. %uint_1 = OpConstant %uint 1
  1032. %array = OpTypeArray %uint %uint_1
  1033. %struct1 = OpTypeStruct %array
  1034. %uint_ptr = OpTypePointer Function %uint
  1035. %struct1_ptr = OpTypePointer Function %struct1
  1036. %uint_0 = OpConstant %uint 0
  1037. %func = OpTypeFunction %void %uint
  1038. %1 = OpFunction %void None %func
  1039. %param = OpFunctionParameter %uint
  1040. %2 = OpLabel
  1041. %var = OpVariable %struct1_ptr Function
  1042. %3 = OpAccessChain %uint_ptr %var %uint_0 %param
  1043. %4 = OpLoad %uint %3
  1044. OpReturn
  1045. OpFunctionEnd
  1046. )";
  1047. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  1048. }
  1049. TEST_F(ScalarReplacementTest, DontCopyMemberDecorate) {
  1050. const std::string text = R"(
  1051. ;
  1052. ; CHECK-NOT: OpDecorate
  1053. ; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
  1054. ; CHECK: [[struct:%\w+]] = OpTypeStruct [[uint]]
  1055. ; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]]
  1056. ; CHECK: [[struct_ptr:%\w+]] = OpTypePointer Function [[struct]]
  1057. ; CHECK: OpLabel
  1058. ; CHECK-NEXT: OpVariable [[uint_ptr]] Function
  1059. ; CHECK-NOT: OpVariable
  1060. ;
  1061. OpCapability Shader
  1062. OpCapability Linkage
  1063. OpMemoryModel Logical GLSL450
  1064. OpName %func "member_decorate"
  1065. OpMemberDecorate %struct1 0 Offset 1
  1066. %void = OpTypeVoid
  1067. %uint = OpTypeInt 32 0
  1068. %uint_1 = OpConstant %uint 1
  1069. %struct1 = OpTypeStruct %uint
  1070. %uint_ptr = OpTypePointer Function %uint
  1071. %struct1_ptr = OpTypePointer Function %struct1
  1072. %uint_0 = OpConstant %uint 0
  1073. %func = OpTypeFunction %void %uint
  1074. %1 = OpFunction %void None %func
  1075. %2 = OpLabel
  1076. %var = OpVariable %struct1_ptr Function
  1077. %3 = OpAccessChain %uint_ptr %var %uint_0
  1078. %4 = OpLoad %uint %3
  1079. OpReturn
  1080. OpFunctionEnd
  1081. )";
  1082. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  1083. }
  1084. TEST_F(ScalarReplacementTest, NoPartialAccesses2) {
  1085. const std::string text = R"(
  1086. ;
  1087. ; CHECK: [[float:%\w+]] = OpTypeFloat 32
  1088. ; CHECK: [[float_ptr:%\w+]] = OpTypePointer Function [[float]]
  1089. ; CHECK: OpVariable [[float_ptr]] Function
  1090. ; CHECK: OpVariable [[float_ptr]] Function
  1091. ; CHECK: OpVariable [[float_ptr]] Function
  1092. ; CHECK: OpVariable [[float_ptr]] Function
  1093. ; CHECK: OpVariable [[float_ptr]] Function
  1094. ; CHECK: OpVariable [[float_ptr]] Function
  1095. ; CHECK: OpVariable [[float_ptr]] Function
  1096. ; CHECK-NOT: OpVariable
  1097. ;
  1098. OpCapability Shader
  1099. %1 = OpExtInstImport "GLSL.std.450"
  1100. OpMemoryModel Logical GLSL450
  1101. OpEntryPoint Fragment %main "main" %fo
  1102. OpExecutionMode %main OriginUpperLeft
  1103. OpSource GLSL 430
  1104. OpName %main "main"
  1105. OpName %S "S"
  1106. OpMemberName %S 0 "x"
  1107. OpMemberName %S 1 "y"
  1108. OpName %ts1 "ts1"
  1109. OpName %S_0 "S"
  1110. OpMemberName %S_0 0 "x"
  1111. OpMemberName %S_0 1 "y"
  1112. OpName %U_t "U_t"
  1113. OpMemberName %U_t 0 "g_s1"
  1114. OpMemberName %U_t 1 "g_s2"
  1115. OpMemberName %U_t 2 "g_s3"
  1116. OpName %_ ""
  1117. OpName %ts2 "ts2"
  1118. OpName %_Globals_ "_Globals_"
  1119. OpMemberName %_Globals_ 0 "g_b"
  1120. OpName %__0 ""
  1121. OpName %ts3 "ts3"
  1122. OpName %ts4 "ts4"
  1123. OpName %fo "fo"
  1124. OpMemberDecorate %S_0 0 Offset 0
  1125. OpMemberDecorate %S_0 1 Offset 4
  1126. OpMemberDecorate %U_t 0 Offset 0
  1127. OpMemberDecorate %U_t 1 Offset 8
  1128. OpMemberDecorate %U_t 2 Offset 16
  1129. OpDecorate %U_t BufferBlock
  1130. OpDecorate %_ DescriptorSet 0
  1131. OpMemberDecorate %_Globals_ 0 Offset 0
  1132. OpDecorate %_Globals_ Block
  1133. OpDecorate %__0 DescriptorSet 0
  1134. OpDecorate %__0 Binding 0
  1135. OpDecorate %fo Location 0
  1136. %void = OpTypeVoid
  1137. %15 = OpTypeFunction %void
  1138. %float = OpTypeFloat 32
  1139. %S = OpTypeStruct %float %float
  1140. %_ptr_Function_S = OpTypePointer Function %S
  1141. %S_0 = OpTypeStruct %float %float
  1142. %U_t = OpTypeStruct %S_0 %S_0 %S_0
  1143. %_ptr_Uniform_U_t = OpTypePointer Uniform %U_t
  1144. %_ = OpVariable %_ptr_Uniform_U_t Uniform
  1145. %int = OpTypeInt 32 1
  1146. %int_0 = OpConstant %int 0
  1147. %_ptr_Uniform_S_0 = OpTypePointer Uniform %S_0
  1148. %_ptr_Function_float = OpTypePointer Function %float
  1149. %int_1 = OpConstant %int 1
  1150. %uint = OpTypeInt 32 0
  1151. %_Globals_ = OpTypeStruct %uint
  1152. %_ptr_Uniform__Globals_ = OpTypePointer Uniform %_Globals_
  1153. %__0 = OpVariable %_ptr_Uniform__Globals_ Uniform
  1154. %_ptr_Uniform_uint = OpTypePointer Uniform %uint
  1155. %bool = OpTypeBool
  1156. %uint_0 = OpConstant %uint 0
  1157. %_ptr_Output_float = OpTypePointer Output %float
  1158. %fo = OpVariable %_ptr_Output_float Output
  1159. %main = OpFunction %void None %15
  1160. %30 = OpLabel
  1161. %ts1 = OpVariable %_ptr_Function_S Function
  1162. %ts2 = OpVariable %_ptr_Function_S Function
  1163. %ts3 = OpVariable %_ptr_Function_S Function
  1164. %ts4 = OpVariable %_ptr_Function_S Function
  1165. %31 = OpAccessChain %_ptr_Uniform_S_0 %_ %int_0
  1166. %32 = OpLoad %S_0 %31
  1167. %33 = OpCompositeExtract %float %32 0
  1168. %34 = OpAccessChain %_ptr_Function_float %ts1 %int_0
  1169. OpStore %34 %33
  1170. %35 = OpCompositeExtract %float %32 1
  1171. %36 = OpAccessChain %_ptr_Function_float %ts1 %int_1
  1172. OpStore %36 %35
  1173. %37 = OpAccessChain %_ptr_Uniform_S_0 %_ %int_1
  1174. %38 = OpLoad %S_0 %37
  1175. %39 = OpCompositeExtract %float %38 0
  1176. %40 = OpAccessChain %_ptr_Function_float %ts2 %int_0
  1177. OpStore %40 %39
  1178. %41 = OpCompositeExtract %float %38 1
  1179. %42 = OpAccessChain %_ptr_Function_float %ts2 %int_1
  1180. OpStore %42 %41
  1181. %43 = OpAccessChain %_ptr_Uniform_uint %__0 %int_0
  1182. %44 = OpLoad %uint %43
  1183. %45 = OpINotEqual %bool %44 %uint_0
  1184. OpSelectionMerge %46 None
  1185. OpBranchConditional %45 %47 %48
  1186. %47 = OpLabel
  1187. %49 = OpLoad %S %ts1
  1188. OpStore %ts3 %49
  1189. OpBranch %46
  1190. %48 = OpLabel
  1191. %50 = OpLoad %S %ts2
  1192. OpStore %ts3 %50
  1193. OpBranch %46
  1194. %46 = OpLabel
  1195. %51 = OpLoad %S %ts3
  1196. OpStore %ts4 %51
  1197. %52 = OpAccessChain %_ptr_Function_float %ts4 %int_1
  1198. %53 = OpLoad %float %52
  1199. OpStore %fo %53
  1200. OpReturn
  1201. OpFunctionEnd
  1202. )";
  1203. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  1204. }
  1205. TEST_F(ScalarReplacementTest, ReplaceWholeLoadAndStore) {
  1206. const std::string text = R"(
  1207. ;
  1208. ; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
  1209. ; CHECK: [[struct1:%\w+]] = OpTypeStruct [[uint]] [[uint]]
  1210. ; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]]
  1211. ; CHECK: [[const:%\w+]] = OpConstant [[uint]] 0
  1212. ; CHECK: [[null:%\w+]] = OpConstantNull [[uint]]
  1213. ; CHECK: [[var0:%\w+]] = OpVariable [[uint_ptr]] Function
  1214. ; CHECK: [[var1:%\w+]] = OpVariable [[uint_ptr]] Function
  1215. ; CHECK-NOT: OpVariable
  1216. ; CHECK: [[l0:%\w+]] = OpLoad [[uint]] [[var0]]
  1217. ; CHECK: [[c0:%\w+]] = OpCompositeConstruct [[struct1]] [[l0]] [[null]]
  1218. ; CHECK: [[e0:%\w+]] = OpCompositeExtract [[uint]] [[c0]] 0
  1219. ; CHECK: OpStore [[var1]] [[e0]]
  1220. ; CHECK: [[l1:%\w+]] = OpLoad [[uint]] [[var1]]
  1221. ; CHECK: [[c1:%\w+]] = OpCompositeConstruct [[struct1]] [[l1]] [[null]]
  1222. ; CHECK: [[e1:%\w+]] = OpCompositeExtract [[uint]] [[c1]] 0
  1223. ;
  1224. OpCapability Shader
  1225. OpCapability Linkage
  1226. OpMemoryModel Logical GLSL450
  1227. OpName %func "replace_whole_load"
  1228. %void = OpTypeVoid
  1229. %uint = OpTypeInt 32 0
  1230. %struct1 = OpTypeStruct %uint %uint
  1231. %uint_ptr = OpTypePointer Function %uint
  1232. %struct1_ptr = OpTypePointer Function %struct1
  1233. %uint_0 = OpConstant %uint 0
  1234. %uint_1 = OpConstant %uint 1
  1235. %func = OpTypeFunction %void
  1236. %1 = OpFunction %void None %func
  1237. %2 = OpLabel
  1238. %var2 = OpVariable %struct1_ptr Function
  1239. %var1 = OpVariable %struct1_ptr Function
  1240. %load1 = OpLoad %struct1 %var1
  1241. OpStore %var2 %load1
  1242. %load2 = OpLoad %struct1 %var2
  1243. %3 = OpCompositeExtract %uint %load2 0
  1244. OpReturn
  1245. OpFunctionEnd
  1246. )";
  1247. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  1248. }
  1249. TEST_F(ScalarReplacementTest, ReplaceWholeLoadAndStore2) {
  1250. // TODO: We can improve this case by ensuring that |var2| is processed first.
  1251. const std::string text = R"(
  1252. ;
  1253. ; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
  1254. ; CHECK: [[struct1:%\w+]] = OpTypeStruct [[uint]] [[uint]]
  1255. ; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]]
  1256. ; CHECK: [[const:%\w+]] = OpConstant [[uint]] 0
  1257. ; CHECK: [[null:%\w+]] = OpConstantNull [[uint]]
  1258. ; CHECK: [[var1:%\w+]] = OpVariable [[uint_ptr]] Function
  1259. ; CHECK: [[var0a:%\w+]] = OpVariable [[uint_ptr]] Function
  1260. ; CHECK: [[var0b:%\w+]] = OpVariable [[uint_ptr]] Function
  1261. ; CHECK-NOT: OpVariable
  1262. ; CHECK: [[l0a:%\w+]] = OpLoad [[uint]] [[var0a]]
  1263. ; CHECK: [[l0b:%\w+]] = OpLoad [[uint]] [[var0b]]
  1264. ; CHECK: [[c0:%\w+]] = OpCompositeConstruct [[struct1]] [[l0b]] [[l0a]]
  1265. ; CHECK: [[e0:%\w+]] = OpCompositeExtract [[uint]] [[c0]] 0
  1266. ; CHECK: OpStore [[var1]] [[e0]]
  1267. ; CHECK: [[l1:%\w+]] = OpLoad [[uint]] [[var1]]
  1268. ; CHECK: [[c1:%\w+]] = OpCompositeConstruct [[struct1]] [[l1]] [[null]]
  1269. ; CHECK: [[e1:%\w+]] = OpCompositeExtract [[uint]] [[c1]] 0
  1270. ;
  1271. OpCapability Shader
  1272. OpCapability Linkage
  1273. OpMemoryModel Logical GLSL450
  1274. OpName %func "replace_whole_load"
  1275. %void = OpTypeVoid
  1276. %uint = OpTypeInt 32 0
  1277. %struct1 = OpTypeStruct %uint %uint
  1278. %uint_ptr = OpTypePointer Function %uint
  1279. %struct1_ptr = OpTypePointer Function %struct1
  1280. %uint_0 = OpConstant %uint 0
  1281. %uint_1 = OpConstant %uint 1
  1282. %func = OpTypeFunction %void
  1283. %1 = OpFunction %void None %func
  1284. %2 = OpLabel
  1285. %var1 = OpVariable %struct1_ptr Function
  1286. %var2 = OpVariable %struct1_ptr Function
  1287. %load1 = OpLoad %struct1 %var1
  1288. OpStore %var2 %load1
  1289. %load2 = OpLoad %struct1 %var2
  1290. %3 = OpCompositeExtract %uint %load2 0
  1291. OpReturn
  1292. OpFunctionEnd
  1293. )";
  1294. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  1295. }
  1296. TEST_F(ScalarReplacementTest, CreateAmbiguousNullConstant1) {
  1297. const std::string text = R"(
  1298. ;
  1299. ; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
  1300. ; CHECK: [[struct1:%\w+]] = OpTypeStruct [[uint]] [[struct_member:%\w+]]
  1301. ; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]]
  1302. ; CHECK: [[const:%\w+]] = OpConstant [[uint]] 0
  1303. ; CHECK: [[null:%\w+]] = OpConstantNull [[struct_member]]
  1304. ; CHECK: [[var0a:%\w+]] = OpVariable [[uint_ptr]] Function
  1305. ; CHECK: [[var1:%\w+]] = OpVariable [[uint_ptr]] Function
  1306. ; CHECK: [[var0b:%\w+]] = OpVariable [[uint_ptr]] Function
  1307. ; CHECK-NOT: OpVariable
  1308. ; CHECK: OpStore [[var1]]
  1309. ; CHECK: [[l1:%\w+]] = OpLoad [[uint]] [[var1]]
  1310. ; CHECK: [[c1:%\w+]] = OpCompositeConstruct [[struct1]] [[l1]] [[null]]
  1311. ; CHECK: [[e1:%\w+]] = OpCompositeExtract [[uint]] [[c1]] 0
  1312. ;
  1313. OpCapability Shader
  1314. OpCapability Linkage
  1315. OpMemoryModel Logical GLSL450
  1316. OpName %func "replace_whole_load"
  1317. %void = OpTypeVoid
  1318. %uint = OpTypeInt 32 0
  1319. %struct2 = OpTypeStruct %uint
  1320. %struct3 = OpTypeStruct %uint
  1321. %struct1 = OpTypeStruct %uint %struct2
  1322. %uint_ptr = OpTypePointer Function %uint
  1323. %struct1_ptr = OpTypePointer Function %struct1
  1324. %uint_0 = OpConstant %uint 0
  1325. %uint_1 = OpConstant %uint 1
  1326. %func = OpTypeFunction %void
  1327. %1 = OpFunction %void None %func
  1328. %2 = OpLabel
  1329. %var1 = OpVariable %struct1_ptr Function
  1330. %var2 = OpVariable %struct1_ptr Function
  1331. %load1 = OpLoad %struct1 %var1
  1332. OpStore %var2 %load1
  1333. %load2 = OpLoad %struct1 %var2
  1334. %3 = OpCompositeExtract %uint %load2 0
  1335. OpReturn
  1336. OpFunctionEnd
  1337. )";
  1338. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  1339. }
  1340. TEST_F(ScalarReplacementTest, SpecConstantArray) {
  1341. const std::string text = R"(
  1342. ; CHECK: [[int:%\w+]] = OpTypeInt
  1343. ; CHECK: [[spec_const:%\w+]] = OpSpecConstant [[int]] 4
  1344. ; CHECK: [[spec_op:%\w+]] = OpSpecConstantOp [[int]] IAdd [[spec_const]] [[spec_const]]
  1345. ; CHECK: [[array1:%\w+]] = OpTypeArray [[int]] [[spec_const]]
  1346. ; CHECK: [[array2:%\w+]] = OpTypeArray [[int]] [[spec_op]]
  1347. ; CHECK: [[ptr_array1:%\w+]] = OpTypePointer Function [[array1]]
  1348. ; CHECK: [[ptr_array2:%\w+]] = OpTypePointer Function [[array2]]
  1349. ; CHECK: OpLabel
  1350. ; CHECK-NEXT: OpVariable [[ptr_array1]] Function
  1351. ; CHECK-NEXT: OpVariable [[ptr_array2]] Function
  1352. ; CHECK-NOT: OpVariable
  1353. OpCapability Shader
  1354. OpCapability Linkage
  1355. OpMemoryModel Logical GLSL450
  1356. %void = OpTypeVoid
  1357. %void_fn = OpTypeFunction %void
  1358. %int = OpTypeInt 32 0
  1359. %spec_const = OpSpecConstant %int 4
  1360. %spec_op = OpSpecConstantOp %int IAdd %spec_const %spec_const
  1361. %array_1 = OpTypeArray %int %spec_const
  1362. %array_2 = OpTypeArray %int %spec_op
  1363. %ptr_array_1_Function = OpTypePointer Function %array_1
  1364. %ptr_array_2_Function = OpTypePointer Function %array_2
  1365. %func = OpFunction %void None %void_fn
  1366. %1 = OpLabel
  1367. %var_1 = OpVariable %ptr_array_1_Function Function
  1368. %var_2 = OpVariable %ptr_array_2_Function Function
  1369. OpReturn
  1370. OpFunctionEnd
  1371. )";
  1372. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  1373. }
  1374. TEST_F(ScalarReplacementTest, CreateAmbiguousNullConstant2) {
  1375. const std::string text = R"(
  1376. ;
  1377. ; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
  1378. ; CHECK: [[struct1:%\w+]] = OpTypeStruct [[uint]] [[struct_member:%\w+]]
  1379. ; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]]
  1380. ; CHECK: [[const:%\w+]] = OpConstant [[uint]] 0
  1381. ; CHECK: [[null:%\w+]] = OpConstantNull [[struct_member]]
  1382. ; CHECK: [[var0a:%\w+]] = OpVariable [[uint_ptr]] Function
  1383. ; CHECK: [[var1:%\w+]] = OpVariable [[uint_ptr]] Function
  1384. ; CHECK: [[var0b:%\w+]] = OpVariable [[uint_ptr]] Function
  1385. ; CHECK: OpStore [[var1]]
  1386. ; CHECK: [[l1:%\w+]] = OpLoad [[uint]] [[var1]]
  1387. ; CHECK: [[c1:%\w+]] = OpCompositeConstruct [[struct1]] [[l1]] [[null]]
  1388. ; CHECK: [[e1:%\w+]] = OpCompositeExtract [[uint]] [[c1]] 0
  1389. ;
  1390. OpCapability Shader
  1391. OpCapability Linkage
  1392. OpMemoryModel Logical GLSL450
  1393. OpName %func "replace_whole_load"
  1394. %void = OpTypeVoid
  1395. %uint = OpTypeInt 32 0
  1396. %struct3 = OpTypeStruct %uint
  1397. %struct2 = OpTypeStruct %uint
  1398. %struct1 = OpTypeStruct %uint %struct2
  1399. %uint_ptr = OpTypePointer Function %uint
  1400. %struct1_ptr = OpTypePointer Function %struct1
  1401. %uint_0 = OpConstant %uint 0
  1402. %uint_1 = OpConstant %uint 1
  1403. %func = OpTypeFunction %void
  1404. %1 = OpFunction %void None %func
  1405. %2 = OpLabel
  1406. %var1 = OpVariable %struct1_ptr Function
  1407. %var2 = OpVariable %struct1_ptr Function
  1408. %load1 = OpLoad %struct1 %var1
  1409. OpStore %var2 %load1
  1410. %load2 = OpLoad %struct1 %var2
  1411. %3 = OpCompositeExtract %uint %load2 0
  1412. OpReturn
  1413. OpFunctionEnd
  1414. )";
  1415. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  1416. }
  1417. // Test that a struct of size 4 is not replaced when there is a limit of 2.
  1418. TEST_F(ScalarReplacementTest, TestLimit) {
  1419. const std::string text = R"(
  1420. OpCapability Shader
  1421. OpCapability Linkage
  1422. OpMemoryModel Logical GLSL450
  1423. OpName %6 "simple_struct"
  1424. %1 = OpTypeVoid
  1425. %2 = OpTypeInt 32 0
  1426. %3 = OpTypeStruct %2 %2 %2 %2
  1427. %4 = OpTypePointer Function %3
  1428. %5 = OpTypePointer Function %2
  1429. %6 = OpTypeFunction %2
  1430. %7 = OpConstantNull %3
  1431. %8 = OpConstant %2 0
  1432. %9 = OpConstant %2 1
  1433. %10 = OpConstant %2 2
  1434. %11 = OpConstant %2 3
  1435. %12 = OpFunction %2 None %6
  1436. %13 = OpLabel
  1437. %14 = OpVariable %4 Function %7
  1438. %15 = OpInBoundsAccessChain %5 %14 %8
  1439. %16 = OpLoad %2 %15
  1440. %17 = OpAccessChain %5 %14 %10
  1441. %18 = OpLoad %2 %17
  1442. %19 = OpIAdd %2 %16 %18
  1443. OpReturnValue %19
  1444. OpFunctionEnd
  1445. )";
  1446. auto result =
  1447. SinglePassRunAndDisassemble<ScalarReplacementPass>(text, true, false, 2);
  1448. EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
  1449. }
  1450. // Test that a struct of size 4 is replaced when there is a limit of 0 (no
  1451. // limit). This is the same spir-v as a test above, so we do not check that it
  1452. // is correctly transformed. We leave that to the test above.
  1453. TEST_F(ScalarReplacementTest, TestUnimited) {
  1454. const std::string text = R"(
  1455. OpCapability Shader
  1456. OpCapability Linkage
  1457. OpMemoryModel Logical GLSL450
  1458. OpName %6 "simple_struct"
  1459. %1 = OpTypeVoid
  1460. %2 = OpTypeInt 32 0
  1461. %3 = OpTypeStruct %2 %2 %2 %2
  1462. %4 = OpTypePointer Function %3
  1463. %5 = OpTypePointer Function %2
  1464. %6 = OpTypeFunction %2
  1465. %7 = OpConstantNull %3
  1466. %8 = OpConstant %2 0
  1467. %9 = OpConstant %2 1
  1468. %10 = OpConstant %2 2
  1469. %11 = OpConstant %2 3
  1470. %12 = OpFunction %2 None %6
  1471. %13 = OpLabel
  1472. %14 = OpVariable %4 Function %7
  1473. %15 = OpInBoundsAccessChain %5 %14 %8
  1474. %16 = OpLoad %2 %15
  1475. %17 = OpAccessChain %5 %14 %10
  1476. %18 = OpLoad %2 %17
  1477. %19 = OpIAdd %2 %16 %18
  1478. OpReturnValue %19
  1479. OpFunctionEnd
  1480. )";
  1481. auto result =
  1482. SinglePassRunAndDisassemble<ScalarReplacementPass>(text, true, false, 0);
  1483. EXPECT_EQ(Pass::Status::SuccessWithChange, std::get<1>(result));
  1484. }
  1485. TEST_F(ScalarReplacementTest, AmbigousPointer) {
  1486. const std::string text = R"(
  1487. ; CHECK: [[s1:%\w+]] = OpTypeStruct %uint
  1488. ; CHECK: [[s2:%\w+]] = OpTypeStruct %uint
  1489. ; CHECK: [[s3:%\w+]] = OpTypeStruct [[s2]]
  1490. ; CHECK: [[s3_const:%\w+]] = OpConstantComposite [[s3]]
  1491. ; CHECK: [[s2_ptr:%\w+]] = OpTypePointer Function [[s2]]
  1492. ; CHECK: OpCompositeExtract [[s2]] [[s3_const]]
  1493. OpCapability Shader
  1494. %1 = OpExtInstImport "GLSL.std.450"
  1495. OpMemoryModel Logical GLSL450
  1496. OpEntryPoint Fragment %2 "main"
  1497. OpExecutionMode %2 OriginUpperLeft
  1498. OpSource ESSL 310
  1499. %void = OpTypeVoid
  1500. %5 = OpTypeFunction %void
  1501. %uint = OpTypeInt 32 0
  1502. %_struct_7 = OpTypeStruct %uint
  1503. %_struct_8 = OpTypeStruct %uint
  1504. %_struct_9 = OpTypeStruct %_struct_8
  1505. %uint_1 = OpConstant %uint 1
  1506. %11 = OpConstantComposite %_struct_8 %uint_1
  1507. %12 = OpConstantComposite %_struct_9 %11
  1508. %_ptr_Function__struct_9 = OpTypePointer Function %_struct_9
  1509. %_ptr_Function__struct_7 = OpTypePointer Function %_struct_7
  1510. %2 = OpFunction %void None %5
  1511. %15 = OpLabel
  1512. %var = OpVariable %_ptr_Function__struct_9 Function
  1513. OpStore %var %12
  1514. %ld = OpLoad %_struct_9 %var
  1515. %ex = OpCompositeExtract %_struct_8 %ld 0
  1516. OpReturn
  1517. OpFunctionEnd
  1518. )";
  1519. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  1520. }
  1521. // Test that scalar replacement does not crash when there is an OpAccessChain
  1522. // with no index. If we choose to handle this case in the future, then the
  1523. // result can change.
  1524. TEST_F(ScalarReplacementTest, TestAccessChainWithNoIndexes) {
  1525. const std::string text = R"(
  1526. OpCapability Shader
  1527. OpMemoryModel Logical GLSL450
  1528. OpEntryPoint Fragment %1 "main"
  1529. OpExecutionMode %1 OriginLowerLeft
  1530. %void = OpTypeVoid
  1531. %3 = OpTypeFunction %void
  1532. %float = OpTypeFloat 32
  1533. %_struct_5 = OpTypeStruct %float
  1534. %_ptr_Function__struct_5 = OpTypePointer Function %_struct_5
  1535. %1 = OpFunction %void None %3
  1536. %7 = OpLabel
  1537. %8 = OpVariable %_ptr_Function__struct_5 Function
  1538. %9 = OpAccessChain %_ptr_Function__struct_5 %8
  1539. OpReturn
  1540. OpFunctionEnd
  1541. )";
  1542. auto result =
  1543. SinglePassRunAndDisassemble<ScalarReplacementPass>(text, true, false);
  1544. EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
  1545. }
  1546. } // namespace
  1547. } // namespace opt
  1548. } // namespace spvtools