scalar_replacement_test.cpp 77 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361
  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 "source/opt/scalar_replacement_pass.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 ScalarReplacementPassName = ::testing::Test;
  23. TEST_F(ScalarReplacementPassName, Default) {
  24. auto srp = ScalarReplacementPass();
  25. EXPECT_STREQ(srp.name(), "scalar-replacement=0");
  26. }
  27. TEST_F(ScalarReplacementPassName, Large) {
  28. auto srp = ScalarReplacementPass(0xffffffffu);
  29. EXPECT_STREQ(srp.name(), "scalar-replacement=4294967295");
  30. }
  31. using ScalarReplacementTest = PassTest<::testing::Test>;
  32. TEST_F(ScalarReplacementTest, SimpleStruct) {
  33. const std::string text = R"(
  34. ;
  35. ; CHECK: [[struct:%\w+]] = OpTypeStruct [[elem:%\w+]]
  36. ; CHECK: [[struct_ptr:%\w+]] = OpTypePointer Function [[struct]]
  37. ; CHECK: [[elem_ptr:%\w+]] = OpTypePointer Function [[elem]]
  38. ; CHECK: OpConstantNull [[struct]]
  39. ; CHECK: [[null:%\w+]] = OpConstantNull [[elem]]
  40. ; CHECK-NOT: OpVariable [[struct_ptr]]
  41. ; CHECK: [[one:%\w+]] = OpVariable [[elem_ptr]] Function [[null]]
  42. ; CHECK-NEXT: [[two:%\w+]] = OpVariable [[elem_ptr]] Function [[null]]
  43. ; CHECK-NOT: OpVariable [[elem_ptr]] Function [[null]]
  44. ; CHECK-NOT: OpVariable [[struct_ptr]]
  45. ; CHECK-NOT: OpInBoundsAccessChain
  46. ; CHECK: [[l1:%\w+]] = OpLoad [[elem]] [[two]]
  47. ; CHECK-NOT: OpAccessChain
  48. ; CHECK: [[l2:%\w+]] = OpLoad [[elem]] [[one]]
  49. ; CHECK: OpIAdd [[elem]] [[l1]] [[l2]]
  50. ;
  51. OpCapability Shader
  52. OpCapability Linkage
  53. OpMemoryModel Logical GLSL450
  54. OpName %6 "simple_struct"
  55. %1 = OpTypeVoid
  56. %2 = OpTypeInt 32 0
  57. %3 = OpTypeStruct %2 %2 %2 %2
  58. %4 = OpTypePointer Function %3
  59. %5 = OpTypePointer Function %2
  60. %6 = OpTypeFunction %2
  61. %7 = OpConstantNull %3
  62. %8 = OpConstant %2 0
  63. %9 = OpConstant %2 1
  64. %10 = OpConstant %2 2
  65. %11 = OpConstant %2 3
  66. %12 = OpFunction %2 None %6
  67. %13 = OpLabel
  68. %14 = OpVariable %4 Function %7
  69. %15 = OpInBoundsAccessChain %5 %14 %8
  70. %16 = OpLoad %2 %15
  71. %17 = OpAccessChain %5 %14 %10
  72. %18 = OpLoad %2 %17
  73. %19 = OpIAdd %2 %16 %18
  74. OpReturnValue %19
  75. OpFunctionEnd
  76. )";
  77. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  78. }
  79. TEST_F(ScalarReplacementTest, StructInitialization) {
  80. const std::string text = R"(
  81. ;
  82. ; CHECK: [[elem:%\w+]] = OpTypeInt 32 0
  83. ; CHECK: [[struct:%\w+]] = OpTypeStruct [[elem]] [[elem]] [[elem]] [[elem]]
  84. ; CHECK: [[struct_ptr:%\w+]] = OpTypePointer Function [[struct]]
  85. ; CHECK: [[elem_ptr:%\w+]] = OpTypePointer Function [[elem]]
  86. ; CHECK: [[zero:%\w+]] = OpConstant [[elem]] 0
  87. ; CHECK: [[undef:%\w+]] = OpUndef [[elem]]
  88. ; CHECK: [[two:%\w+]] = OpConstant [[elem]] 2
  89. ; CHECK: [[null:%\w+]] = OpConstantNull [[elem]]
  90. ; CHECK-NOT: OpVariable [[struct_ptr]]
  91. ; CHECK: OpVariable [[elem_ptr]] Function [[null]]
  92. ; CHECK-NEXT: OpVariable [[elem_ptr]] Function [[two]]
  93. ; CHECK-NOT: OpVariable [[elem_ptr]] Function [[undef]]
  94. ; CHECK-NEXT: OpVariable [[elem_ptr]] Function
  95. ; CHECK-NEXT: OpVariable [[elem_ptr]] Function [[zero]]
  96. ; CHECK-NOT: OpVariable [[elem_ptr]] Function [[undef]]
  97. ;
  98. OpCapability Shader
  99. OpCapability Linkage
  100. OpMemoryModel Logical GLSL450
  101. OpName %6 "struct_init"
  102. %1 = OpTypeVoid
  103. %2 = OpTypeInt 32 0
  104. %3 = OpTypeStruct %2 %2 %2 %2
  105. %4 = OpTypePointer Function %3
  106. %20 = OpTypePointer Function %2
  107. %6 = OpTypeFunction %1
  108. %7 = OpConstant %2 0
  109. %8 = OpUndef %2
  110. %9 = OpConstant %2 2
  111. %30 = OpConstant %2 1
  112. %31 = OpConstant %2 3
  113. %10 = OpConstantNull %2
  114. %11 = OpConstantComposite %3 %7 %8 %9 %10
  115. %12 = OpFunction %1 None %6
  116. %13 = OpLabel
  117. %14 = OpVariable %4 Function %11
  118. %15 = OpAccessChain %20 %14 %7
  119. OpStore %15 %10
  120. %16 = OpAccessChain %20 %14 %9
  121. OpStore %16 %10
  122. %17 = OpAccessChain %20 %14 %30
  123. OpStore %17 %10
  124. %18 = OpAccessChain %20 %14 %31
  125. OpStore %18 %10
  126. OpReturn
  127. OpFunctionEnd
  128. )";
  129. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  130. }
  131. TEST_F(ScalarReplacementTest, SpecConstantInitialization) {
  132. const std::string text = R"(
  133. ;
  134. ; CHECK: [[int:%\w+]] = OpTypeInt 32 0
  135. ; CHECK: [[struct:%\w+]] = OpTypeStruct [[int]] [[int]]
  136. ; CHECK: [[struct_ptr:%\w+]] = OpTypePointer Function [[struct]]
  137. ; CHECK: [[int_ptr:%\w+]] = OpTypePointer Function [[int]]
  138. ; CHECK: [[spec_comp:%\w+]] = OpSpecConstantComposite [[struct]]
  139. ; CHECK: [[ex0:%\w+]] = OpSpecConstantOp [[int]] CompositeExtract [[spec_comp]] 0
  140. ; CHECK: [[ex1:%\w+]] = OpSpecConstantOp [[int]] CompositeExtract [[spec_comp]] 1
  141. ; CHECK-NOT: OpVariable [[struct]]
  142. ; CHECK: OpVariable [[int_ptr]] Function [[ex1]]
  143. ; CHECK-NEXT: OpVariable [[int_ptr]] Function [[ex0]]
  144. ; CHECK-NOT: OpVariable [[struct]]
  145. ;
  146. OpCapability Shader
  147. OpCapability Linkage
  148. OpMemoryModel Logical GLSL450
  149. OpName %6 "spec_const"
  150. %1 = OpTypeVoid
  151. %2 = OpTypeInt 32 0
  152. %3 = OpTypeStruct %2 %2
  153. %4 = OpTypePointer Function %3
  154. %20 = OpTypePointer Function %2
  155. %5 = OpTypeFunction %1
  156. %6 = OpConstant %2 0
  157. %30 = OpConstant %2 1
  158. %7 = OpSpecConstant %2 0
  159. %8 = OpSpecConstantOp %2 IAdd %7 %7
  160. %9 = OpSpecConstantComposite %3 %7 %8
  161. %10 = OpFunction %1 None %5
  162. %11 = OpLabel
  163. %12 = OpVariable %4 Function %9
  164. %13 = OpAccessChain %20 %12 %6
  165. %14 = OpLoad %2 %13
  166. %15 = OpAccessChain %20 %12 %30
  167. %16 = OpLoad %2 %15
  168. OpReturn
  169. OpFunctionEnd
  170. )";
  171. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  172. }
  173. // TODO(alanbaker): Re-enable when vector and matrix scalarization is supported.
  174. // TEST_F(ScalarReplacementTest, VectorInitialization) {
  175. // const std::string text = R"(
  176. // ;
  177. // ; CHECK: [[elem:%\w+]] = OpTypeInt 32 0
  178. // ; CHECK: [[vector:%\w+]] = OpTypeVector [[elem]] 4
  179. // ; CHECK: [[vector_ptr:%\w+]] = OpTypePointer Function [[vector]]
  180. // ; CHECK: [[elem_ptr:%\w+]] = OpTypePointer Function [[elem]]
  181. // ; CHECK: [[zero:%\w+]] = OpConstant [[elem]] 0
  182. // ; CHECK: [[undef:%\w+]] = OpUndef [[elem]]
  183. // ; CHECK: [[two:%\w+]] = OpConstant [[elem]] 2
  184. // ; CHECK: [[null:%\w+]] = OpConstantNull [[elem]]
  185. // ; CHECK-NOT: OpVariable [[vector_ptr]]
  186. // ; CHECK: OpVariable [[elem_ptr]] Function [[zero]]
  187. // ; CHECK-NOT: OpVariable [[elem_ptr]] Function [[undef]]
  188. // ; CHECK-NEXT: OpVariable [[elem_ptr]] Function
  189. // ; CHECK-NEXT: OpVariable [[elem_ptr]] Function [[two]]
  190. // ; CHECK-NEXT: OpVariable [[elem_ptr]] Function [[null]]
  191. // ; CHECK-NOT: OpVariable [[elem_ptr]] Function [[undef]]
  192. // ;
  193. // OpCapability Shader
  194. // OpCapability Linkage
  195. // OpMemoryModel Logical GLSL450
  196. // OpName %6 "vector_init"
  197. // %1 = OpTypeVoid
  198. // %2 = OpTypeInt 32 0
  199. // %3 = OpTypeVector %2 4
  200. // %4 = OpTypePointer Function %3
  201. // %20 = OpTypePointer Function %2
  202. // %6 = OpTypeFunction %1
  203. // %7 = OpConstant %2 0
  204. // %8 = OpUndef %2
  205. // %9 = OpConstant %2 2
  206. // %30 = OpConstant %2 1
  207. // %31 = OpConstant %2 3
  208. // %10 = OpConstantNull %2
  209. // %11 = OpConstantComposite %3 %10 %9 %8 %7
  210. // %12 = OpFunction %1 None %6
  211. // %13 = OpLabel
  212. // %14 = OpVariable %4 Function %11
  213. // %15 = OpAccessChain %20 %14 %7
  214. // OpStore %15 %10
  215. // %16 = OpAccessChain %20 %14 %9
  216. // OpStore %16 %10
  217. // %17 = OpAccessChain %20 %14 %30
  218. // OpStore %17 %10
  219. // %18 = OpAccessChain %20 %14 %31
  220. // OpStore %18 %10
  221. // OpReturn
  222. // OpFunctionEnd
  223. // )";
  224. //
  225. // SinglePassRunAndMatch<opt::ScalarReplacementPass>(text, true);
  226. // }
  227. //
  228. // TEST_F(ScalarReplacementTest, MatrixInitialization) {
  229. // const std::string text = R"(
  230. // ;
  231. // ; CHECK: [[float:%\w+]] = OpTypeFloat 32
  232. // ; CHECK: [[vector:%\w+]] = OpTypeVector [[float]] 2
  233. // ; CHECK: [[matrix:%\w+]] = OpTypeMatrix [[vector]] 2
  234. // ; CHECK: [[matrix_ptr:%\w+]] = OpTypePointer Function [[matrix]]
  235. // ; CHECK: [[float_ptr:%\w+]] = OpTypePointer Function [[float]]
  236. // ; CHECK: [[vec_ptr:%\w+]] = OpTypePointer Function [[vector]]
  237. // ; CHECK: [[zerof:%\w+]] = OpConstant [[float]] 0
  238. // ; CHECK: [[onef:%\w+]] = OpConstant [[float]] 1
  239. // ; CHECK: [[one_zero:%\w+]] = OpConstantComposite [[vector]] [[onef]]
  240. // [[zerof]] ; CHECK: [[zero_one:%\w+]] = OpConstantComposite [[vector]]
  241. // [[zerof]] [[onef]] ; CHECK: [[const_mat:%\w+]] = OpConstantComposite
  242. // [[matrix]] [[one_zero]]
  243. // [[zero_one]] ; CHECK-NOT: OpVariable [[matrix]] ; CHECK-NOT: OpVariable
  244. // [[vector]] Function [[one_zero]] ; CHECK: [[f1:%\w+]] = OpVariable
  245. // [[float_ptr]] Function [[zerof]] ; CHECK-NEXT: [[f2:%\w+]] = OpVariable
  246. // [[float_ptr]] Function [[onef]] ; CHECK-NEXT: [[vec_var:%\w+]] = OpVariable
  247. // [[vec_ptr]] Function [[zero_one]] ; CHECK-NOT: OpVariable [[matrix]] ;
  248. // CHECK-NOT: OpVariable [[vector]] Function [[one_zero]]
  249. // ;
  250. // OpCapability Shader
  251. // OpCapability Linkage
  252. // OpMemoryModel Logical GLSL450
  253. // OpName %7 "matrix_init"
  254. // %1 = OpTypeVoid
  255. // %2 = OpTypeFloat 32
  256. // %3 = OpTypeVector %2 2
  257. // %4 = OpTypeMatrix %3 2
  258. // %5 = OpTypePointer Function %4
  259. // %6 = OpTypePointer Function %2
  260. // %30 = OpTypePointer Function %3
  261. // %10 = OpTypeInt 32 0
  262. // %7 = OpTypeFunction %1 %10
  263. // %8 = OpConstant %2 0.0
  264. // %9 = OpConstant %2 1.0
  265. // %11 = OpConstant %10 0
  266. // %12 = OpConstant %10 1
  267. // %13 = OpConstantComposite %3 %9 %8
  268. // %14 = OpConstantComposite %3 %8 %9
  269. // %15 = OpConstantComposite %4 %13 %14
  270. // %16 = OpFunction %1 None %7
  271. // %31 = OpFunctionParameter %10
  272. // %17 = OpLabel
  273. // %18 = OpVariable %5 Function %15
  274. // %19 = OpAccessChain %6 %18 %11 %12
  275. // OpStore %19 %8
  276. // %20 = OpAccessChain %6 %18 %11 %11
  277. // OpStore %20 %8
  278. // %21 = OpAccessChain %30 %18 %12
  279. // OpStore %21 %14
  280. // OpReturn
  281. // OpFunctionEnd
  282. // )";
  283. //
  284. // SinglePassRunAndMatch<opt::ScalarReplacementPass>(text, true);
  285. // }
  286. TEST_F(ScalarReplacementTest, ElideAccessChain) {
  287. const std::string text = R"(
  288. ;
  289. ; CHECK: [[var:%\w+]] = OpVariable
  290. ; CHECK-NOT: OpAccessChain
  291. ; CHECK: OpStore [[var]]
  292. ;
  293. OpCapability Shader
  294. OpCapability Linkage
  295. OpMemoryModel Logical GLSL450
  296. OpName %6 "elide_access_chain"
  297. %1 = OpTypeVoid
  298. %2 = OpTypeInt 32 0
  299. %3 = OpTypeStruct %2 %2 %2 %2
  300. %4 = OpTypePointer Function %3
  301. %20 = OpTypePointer Function %2
  302. %6 = OpTypeFunction %1
  303. %7 = OpConstant %2 0
  304. %8 = OpUndef %2
  305. %9 = OpConstant %2 2
  306. %10 = OpConstantNull %2
  307. %11 = OpConstantComposite %3 %7 %8 %9 %10
  308. %12 = OpFunction %1 None %6
  309. %13 = OpLabel
  310. %14 = OpVariable %4 Function %11
  311. %15 = OpAccessChain %20 %14 %7
  312. OpStore %15 %10
  313. OpReturn
  314. OpFunctionEnd
  315. )";
  316. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  317. }
  318. TEST_F(ScalarReplacementTest, ElideMultipleAccessChains) {
  319. const std::string text = R"(
  320. ;
  321. ; CHECK: [[var:%\w+]] = OpVariable
  322. ; CHECK-NOT: OpInBoundsAccessChain
  323. ; CHECK OpStore [[var]]
  324. ;
  325. OpCapability Shader
  326. OpCapability Linkage
  327. OpMemoryModel Logical GLSL450
  328. OpName %6 "elide_two_access_chains"
  329. %1 = OpTypeVoid
  330. %2 = OpTypeFloat 32
  331. %3 = OpTypeStruct %2 %2
  332. %4 = OpTypeStruct %3 %3
  333. %5 = OpTypePointer Function %4
  334. %6 = OpTypePointer Function %2
  335. %7 = OpTypeFunction %1
  336. %8 = OpConstant %2 0.0
  337. %9 = OpConstant %2 1.0
  338. %10 = OpTypeInt 32 0
  339. %11 = OpConstant %10 0
  340. %12 = OpConstant %10 1
  341. %13 = OpConstantComposite %3 %9 %8
  342. %14 = OpConstantComposite %3 %8 %9
  343. %15 = OpConstantComposite %4 %13 %14
  344. %16 = OpFunction %1 None %7
  345. %17 = OpLabel
  346. %18 = OpVariable %5 Function %15
  347. %19 = OpInBoundsAccessChain %6 %18 %11 %12
  348. OpStore %19 %8
  349. OpReturn
  350. OpFunctionEnd
  351. )";
  352. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  353. }
  354. TEST_F(ScalarReplacementTest, ReplaceAccessChain) {
  355. const std::string text = R"(
  356. ;
  357. ; CHECK: [[param:%\w+]] = OpFunctionParameter
  358. ; CHECK: [[var:%\w+]] = OpVariable
  359. ; CHECK: [[access:%\w+]] = OpAccessChain {{%\w+}} [[var]] [[param]]
  360. ; CHECK: OpStore [[access]]
  361. ;
  362. OpCapability Shader
  363. OpCapability Linkage
  364. OpMemoryModel Logical GLSL450
  365. OpName %7 "replace_access_chain"
  366. %1 = OpTypeVoid
  367. %2 = OpTypeFloat 32
  368. %10 = OpTypeInt 32 0
  369. %uint_2 = OpConstant %10 2
  370. %3 = OpTypeArray %2 %uint_2
  371. %4 = OpTypeStruct %3 %3
  372. %5 = OpTypePointer Function %4
  373. %20 = OpTypePointer Function %3
  374. %6 = OpTypePointer Function %2
  375. %7 = OpTypeFunction %1 %10
  376. %8 = OpConstant %2 0.0
  377. %9 = OpConstant %2 1.0
  378. %11 = OpConstant %10 0
  379. %12 = OpConstant %10 1
  380. %13 = OpConstantComposite %3 %9 %8
  381. %14 = OpConstantComposite %3 %8 %9
  382. %15 = OpConstantComposite %4 %13 %14
  383. %16 = OpFunction %1 None %7
  384. %32 = OpFunctionParameter %10
  385. %17 = OpLabel
  386. %18 = OpVariable %5 Function %15
  387. %19 = OpAccessChain %6 %18 %11 %32
  388. OpStore %19 %8
  389. OpReturn
  390. OpFunctionEnd
  391. )";
  392. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  393. }
  394. TEST_F(ScalarReplacementTest, ArrayInitialization) {
  395. const std::string text = R"(
  396. ;
  397. ; CHECK: [[float:%\w+]] = OpTypeFloat 32
  398. ; CHECK: [[array:%\w+]] = OpTypeArray
  399. ; CHECK: [[array_ptr:%\w+]] = OpTypePointer Function [[array]]
  400. ; CHECK: [[float_ptr:%\w+]] = OpTypePointer Function [[float]]
  401. ; CHECK: [[float0:%\w+]] = OpConstant [[float]] 0
  402. ; CHECK: [[float1:%\w+]] = OpConstant [[float]] 1
  403. ; CHECK: [[float2:%\w+]] = OpConstant [[float]] 2
  404. ; CHECK-NOT: OpVariable [[array_ptr]]
  405. ; CHECK: [[var0:%\w+]] = OpVariable [[float_ptr]] Function [[float0]]
  406. ; CHECK-NEXT: [[var1:%\w+]] = OpVariable [[float_ptr]] Function [[float1]]
  407. ; CHECK-NEXT: [[var2:%\w+]] = OpVariable [[float_ptr]] Function [[float2]]
  408. ; CHECK-NOT: OpVariable [[array_ptr]]
  409. ;
  410. OpCapability Shader
  411. OpCapability Linkage
  412. OpMemoryModel Logical GLSL450
  413. OpName %func "array_init"
  414. %void = OpTypeVoid
  415. %uint = OpTypeInt 32 0
  416. %float = OpTypeFloat 32
  417. %uint_0 = OpConstant %uint 0
  418. %uint_1 = OpConstant %uint 1
  419. %uint_2 = OpConstant %uint 2
  420. %uint_3 = OpConstant %uint 3
  421. %float_array = OpTypeArray %float %uint_3
  422. %array_ptr = OpTypePointer Function %float_array
  423. %float_ptr = OpTypePointer Function %float
  424. %float_0 = OpConstant %float 0
  425. %float_1 = OpConstant %float 1
  426. %float_2 = OpConstant %float 2
  427. %const_array = OpConstantComposite %float_array %float_2 %float_1 %float_0
  428. %func = OpTypeFunction %void
  429. %1 = OpFunction %void None %func
  430. %2 = OpLabel
  431. %3 = OpVariable %array_ptr Function %const_array
  432. %4 = OpInBoundsAccessChain %float_ptr %3 %uint_0
  433. OpStore %4 %float_0
  434. %5 = OpInBoundsAccessChain %float_ptr %3 %uint_1
  435. OpStore %5 %float_0
  436. %6 = OpInBoundsAccessChain %float_ptr %3 %uint_2
  437. OpStore %6 %float_0
  438. OpReturn
  439. OpFunctionEnd
  440. )";
  441. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  442. }
  443. TEST_F(ScalarReplacementTest, NonUniformCompositeInitialization) {
  444. const std::string text = R"(
  445. ;
  446. ; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
  447. ; CHECK: [[long:%\w+]] = OpTypeInt 64 1
  448. ; CHECK: [[dvector:%\w+]] = OpTypeVector
  449. ; CHECK: [[vector:%\w+]] = OpTypeVector
  450. ; CHECK: [[array:%\w+]] = OpTypeArray
  451. ; CHECK: [[matrix:%\w+]] = OpTypeMatrix
  452. ; CHECK: [[struct1:%\w+]] = OpTypeStruct [[uint]] [[vector]]
  453. ; CHECK: [[struct2:%\w+]] = OpTypeStruct [[struct1]] [[matrix]] [[array]] [[uint]]
  454. ; CHECK: [[struct1_ptr:%\w+]] = OpTypePointer Function [[struct1]]
  455. ; CHECK: [[matrix_ptr:%\w+]] = OpTypePointer Function [[matrix]]
  456. ; CHECK: [[array_ptr:%\w+]] = OpTypePointer Function [[array]]
  457. ; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]]
  458. ; CHECK: [[struct2_ptr:%\w+]] = OpTypePointer Function [[struct2]]
  459. ; CHECK: [[const_array:%\w+]] = OpConstantComposite [[array]]
  460. ; CHECK: [[const_matrix:%\w+]] = OpConstantNull [[matrix]]
  461. ; CHECK: [[const_struct1:%\w+]] = OpConstantComposite [[struct1]]
  462. ; CHECK: OpUndef [[uint]]
  463. ; CHECK: OpUndef [[vector]]
  464. ; CHECK: OpUndef [[long]]
  465. ; CHECK: OpFunction
  466. ; CHECK-NOT: OpVariable [[struct2_ptr]] Function
  467. ; CHECK: OpVariable [[uint_ptr]] Function
  468. ; CHECK-NEXT: OpVariable [[matrix_ptr]] Function [[const_matrix]]
  469. ; CHECK-NOT: OpVariable [[struct1_ptr]] Function [[const_struct1]]
  470. ; CHECK-NOT: OpVariable [[struct2_ptr]] Function
  471. ;
  472. OpCapability Shader
  473. OpCapability Linkage
  474. OpCapability Int64
  475. OpCapability Float64
  476. OpMemoryModel Logical GLSL450
  477. OpName %func "non_uniform_composite_init"
  478. %void = OpTypeVoid
  479. %uint = OpTypeInt 32 0
  480. %int64 = OpTypeInt 64 1
  481. %float = OpTypeFloat 32
  482. %double = OpTypeFloat 64
  483. %double2 = OpTypeVector %double 2
  484. %float4 = OpTypeVector %float 4
  485. %int64_0 = OpConstant %int64 0
  486. %int64_1 = OpConstant %int64 1
  487. %int64_2 = OpConstant %int64 2
  488. %int64_3 = OpConstant %int64 3
  489. %int64_array3 = OpTypeArray %int64 %int64_3
  490. %matrix_double2 = OpTypeMatrix %double2 2
  491. %struct1 = OpTypeStruct %uint %float4
  492. %struct2 = OpTypeStruct %struct1 %matrix_double2 %int64_array3 %uint
  493. %struct1_ptr = OpTypePointer Function %struct1
  494. %matrix_double2_ptr = OpTypePointer Function %matrix_double2
  495. %int64_array_ptr = OpTypePointer Function %int64_array3
  496. %uint_ptr = OpTypePointer Function %uint
  497. %struct2_ptr = OpTypePointer Function %struct2
  498. %const_uint = OpConstant %uint 0
  499. %const_int64_array = OpConstantComposite %int64_array3 %int64_0 %int64_1 %int64_2
  500. %const_double2 = OpConstantNull %double2
  501. %const_matrix_double2 = OpConstantNull %matrix_double2
  502. %undef_float4 = OpUndef %float4
  503. %const_struct1 = OpConstantComposite %struct1 %const_uint %undef_float4
  504. %const_struct2 = OpConstantComposite %struct2 %const_struct1 %const_matrix_double2 %const_int64_array %const_uint
  505. %func = OpTypeFunction %void
  506. %1 = OpFunction %void None %func
  507. %2 = OpLabel
  508. %var = OpVariable %struct2_ptr Function %const_struct2
  509. %3 = OpAccessChain %struct1_ptr %var %int64_0
  510. OpStore %3 %const_struct1
  511. %4 = OpAccessChain %matrix_double2_ptr %var %int64_1
  512. OpStore %4 %const_matrix_double2
  513. %5 = OpAccessChain %int64_array_ptr %var %int64_2
  514. OpStore %5 %const_int64_array
  515. %6 = OpAccessChain %uint_ptr %var %int64_3
  516. OpStore %6 %const_uint
  517. OpReturn
  518. OpFunctionEnd
  519. )";
  520. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  521. }
  522. TEST_F(ScalarReplacementTest, ElideUncombinedAccessChains) {
  523. const std::string text = R"(
  524. ;
  525. ; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
  526. ; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]]
  527. ; CHECK: [[const:%\w+]] = OpConstant [[uint]] 0
  528. ; CHECK: [[var:%\w+]] = OpVariable [[uint_ptr]] Function
  529. ; CHECK-NOT: OpAccessChain
  530. ; CHECK: OpStore [[var]] [[const]]
  531. ;
  532. OpCapability Shader
  533. OpCapability Linkage
  534. OpMemoryModel Logical GLSL450
  535. OpName %func "elide_uncombined_access_chains"
  536. %void = OpTypeVoid
  537. %uint = OpTypeInt 32 0
  538. %struct1 = OpTypeStruct %uint
  539. %struct2 = OpTypeStruct %struct1
  540. %uint_ptr = OpTypePointer Function %uint
  541. %struct1_ptr = OpTypePointer Function %struct1
  542. %struct2_ptr = OpTypePointer Function %struct2
  543. %uint_0 = OpConstant %uint 0
  544. %func = OpTypeFunction %void
  545. %1 = OpFunction %void None %func
  546. %2 = OpLabel
  547. %var = OpVariable %struct2_ptr Function
  548. %3 = OpAccessChain %struct1_ptr %var %uint_0
  549. %4 = OpAccessChain %uint_ptr %3 %uint_0
  550. OpStore %4 %uint_0
  551. OpReturn
  552. OpFunctionEnd
  553. )";
  554. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  555. }
  556. TEST_F(ScalarReplacementTest, ElideSingleUncombinedAccessChains) {
  557. const std::string text = R"(
  558. ;
  559. ; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
  560. ; CHECK: [[array:%\w+]] = OpTypeArray [[uint]]
  561. ; CHECK: [[array_ptr:%\w+]] = OpTypePointer Function [[array]]
  562. ; CHECK: [[const:%\w+]] = OpConstant [[uint]] 0
  563. ; CHECK: [[param:%\w+]] = OpFunctionParameter [[uint]]
  564. ; CHECK: [[var:%\w+]] = OpVariable [[array_ptr]] Function
  565. ; CHECK: [[access:%\w+]] = OpAccessChain {{.*}} [[var]] [[param]]
  566. ; CHECK: OpStore [[access]] [[const]]
  567. ;
  568. OpCapability Shader
  569. OpCapability Linkage
  570. OpMemoryModel Logical GLSL450
  571. OpName %func "elide_single_uncombined_access_chains"
  572. %void = OpTypeVoid
  573. %uint = OpTypeInt 32 0
  574. %uint_1 = OpConstant %uint 1
  575. %array = OpTypeArray %uint %uint_1
  576. %struct2 = OpTypeStruct %array
  577. %uint_ptr = OpTypePointer Function %uint
  578. %array_ptr = OpTypePointer Function %array
  579. %struct2_ptr = OpTypePointer Function %struct2
  580. %uint_0 = OpConstant %uint 0
  581. %func = OpTypeFunction %void %uint
  582. %1 = OpFunction %void None %func
  583. %param = OpFunctionParameter %uint
  584. %2 = OpLabel
  585. %var = OpVariable %struct2_ptr Function
  586. %3 = OpAccessChain %array_ptr %var %uint_0
  587. %4 = OpAccessChain %uint_ptr %3 %param
  588. OpStore %4 %uint_0
  589. OpReturn
  590. OpFunctionEnd
  591. )";
  592. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  593. }
  594. TEST_F(ScalarReplacementTest, ReplaceWholeLoad) {
  595. const std::string text = R"(
  596. ;
  597. ; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
  598. ; CHECK: [[struct1:%\w+]] = OpTypeStruct [[uint]] [[uint]]
  599. ; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]]
  600. ; CHECK: [[const:%\w+]] = OpConstant [[uint]] 0
  601. ; CHECK: [[var1:%\w+]] = OpVariable [[uint_ptr]] Function
  602. ; CHECK: [[var0:%\w+]] = OpVariable [[uint_ptr]] Function
  603. ; CHECK: [[l1:%\w+]] = OpLoad [[uint]] [[var1]]
  604. ; CHECK: [[l0:%\w+]] = OpLoad [[uint]] [[var0]]
  605. ; CHECK: OpCompositeConstruct [[struct1]] [[l0]] [[l1]]
  606. ;
  607. OpCapability Shader
  608. OpCapability Linkage
  609. OpMemoryModel Logical GLSL450
  610. OpName %func "replace_whole_load"
  611. %void = OpTypeVoid
  612. %uint = OpTypeInt 32 0
  613. %struct1 = OpTypeStruct %uint %uint
  614. %uint_ptr = OpTypePointer Function %uint
  615. %struct1_ptr = OpTypePointer Function %struct1
  616. %uint_0 = OpConstant %uint 0
  617. %uint_1 = OpConstant %uint 1
  618. %func = OpTypeFunction %void
  619. %1 = OpFunction %void None %func
  620. %2 = OpLabel
  621. %var = OpVariable %struct1_ptr Function
  622. %load = OpLoad %struct1 %var
  623. %3 = OpAccessChain %uint_ptr %var %uint_0
  624. OpStore %3 %uint_0
  625. %4 = OpAccessChain %uint_ptr %var %uint_1
  626. OpStore %4 %uint_0
  627. OpReturn
  628. OpFunctionEnd
  629. )";
  630. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  631. }
  632. TEST_F(ScalarReplacementTest, ReplaceWholeLoadCopyMemoryAccess) {
  633. const std::string text = R"(
  634. ;
  635. ; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
  636. ; CHECK: [[struct1:%\w+]] = OpTypeStruct [[uint]] [[uint]]
  637. ; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]]
  638. ; CHECK: [[undef:%\w+]] = OpUndef [[uint]]
  639. ; CHECK: [[var0:%\w+]] = OpVariable [[uint_ptr]] Function
  640. ; CHECK: [[l0:%\w+]] = OpLoad [[uint]] [[var0]] Nontemporal
  641. ; CHECK: OpCompositeConstruct [[struct1]] [[l0]] [[undef]]
  642. ;
  643. OpCapability Shader
  644. OpCapability Linkage
  645. OpMemoryModel Logical GLSL450
  646. OpName %func "replace_whole_load_copy_memory_access"
  647. %void = OpTypeVoid
  648. %uint = OpTypeInt 32 0
  649. %struct1 = OpTypeStruct %uint %uint
  650. %uint_ptr = OpTypePointer Function %uint
  651. %struct1_ptr = OpTypePointer Function %struct1
  652. %uint_0 = OpConstant %uint 0
  653. %func = OpTypeFunction %void
  654. %1 = OpFunction %void None %func
  655. %2 = OpLabel
  656. %var = OpVariable %struct1_ptr Function
  657. %load = OpLoad %struct1 %var Nontemporal
  658. %3 = OpAccessChain %uint_ptr %var %uint_0
  659. OpStore %3 %uint_0
  660. OpReturn
  661. OpFunctionEnd
  662. )";
  663. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  664. }
  665. TEST_F(ScalarReplacementTest, ReplaceWholeStore) {
  666. const std::string text = R"(
  667. ;
  668. ; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
  669. ; CHECK: [[struct1:%\w+]] = OpTypeStruct [[uint]] [[uint]]
  670. ; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]]
  671. ; CHECK: [[const:%\w+]] = OpConstant [[uint]] 0
  672. ; CHECK: [[const_struct:%\w+]] = OpConstantComposite [[struct1]] [[const]] [[const]]
  673. ; CHECK: [[var0:%\w+]] = OpVariable [[uint_ptr]] Function
  674. ; CHECK: [[ex0:%\w+]] = OpCompositeExtract [[uint]] [[const_struct]] 0
  675. ; CHECK: OpStore [[var0]] [[ex0]]
  676. ;
  677. OpCapability Shader
  678. OpCapability Linkage
  679. OpMemoryModel Logical GLSL450
  680. OpName %func "replace_whole_store"
  681. %void = OpTypeVoid
  682. %uint = OpTypeInt 32 0
  683. %struct1 = OpTypeStruct %uint %uint
  684. %uint_ptr = OpTypePointer Function %uint
  685. %struct1_ptr = OpTypePointer Function %struct1
  686. %uint_0 = OpConstant %uint 0
  687. %const_struct = OpConstantComposite %struct1 %uint_0 %uint_0
  688. %func = OpTypeFunction %void
  689. %1 = OpFunction %void None %func
  690. %2 = OpLabel
  691. %var = OpVariable %struct1_ptr Function
  692. OpStore %var %const_struct
  693. %3 = OpAccessChain %uint_ptr %var %uint_0
  694. %4 = OpLoad %uint %3
  695. OpReturn
  696. OpFunctionEnd
  697. )";
  698. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  699. }
  700. TEST_F(ScalarReplacementTest, ReplaceWholeStoreCopyMemoryAccess) {
  701. const std::string text = R"(
  702. ;
  703. ; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
  704. ; CHECK: [[struct1:%\w+]] = OpTypeStruct [[uint]] [[uint]]
  705. ; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]]
  706. ; CHECK: [[const:%\w+]] = OpConstant [[uint]] 0
  707. ; CHECK: [[const_struct:%\w+]] = OpConstantComposite [[struct1]] [[const]] [[const]]
  708. ; CHECK: [[var0:%\w+]] = OpVariable [[uint_ptr]] Function
  709. ; CHECK-NOT: OpVariable
  710. ; CHECK: [[ex0:%\w+]] = OpCompositeExtract [[uint]] [[const_struct]] 0
  711. ; CHECK: OpStore [[var0]] [[ex0]] Aligned 4
  712. ;
  713. OpCapability Shader
  714. OpCapability Linkage
  715. OpMemoryModel Logical GLSL450
  716. OpName %func "replace_whole_store_copy_memory_access"
  717. %void = OpTypeVoid
  718. %uint = OpTypeInt 32 0
  719. %struct1 = OpTypeStruct %uint %uint
  720. %uint_ptr = OpTypePointer Function %uint
  721. %struct1_ptr = OpTypePointer Function %struct1
  722. %uint_0 = OpConstant %uint 0
  723. %const_struct = OpConstantComposite %struct1 %uint_0 %uint_0
  724. %func = OpTypeFunction %void
  725. %1 = OpFunction %void None %func
  726. %2 = OpLabel
  727. %var = OpVariable %struct1_ptr Function
  728. OpStore %var %const_struct Aligned 4
  729. %3 = OpAccessChain %uint_ptr %var %uint_0
  730. %4 = OpLoad %uint %3
  731. OpReturn
  732. OpFunctionEnd
  733. )";
  734. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  735. }
  736. TEST_F(ScalarReplacementTest, DontTouchVolatileLoad) {
  737. const std::string text = R"(
  738. ;
  739. ; CHECK: [[struct:%\w+]] = OpTypeStruct
  740. ; CHECK: [[struct_ptr:%\w+]] = OpTypePointer Function [[struct]]
  741. ; CHECK: OpLabel
  742. ; CHECK-NEXT: OpVariable [[struct_ptr]]
  743. ; CHECK-NOT: OpVariable
  744. ;
  745. OpCapability Shader
  746. OpCapability Linkage
  747. OpMemoryModel Logical GLSL450
  748. OpName %func "dont_touch_volatile_load"
  749. %void = OpTypeVoid
  750. %uint = OpTypeInt 32 0
  751. %struct1 = OpTypeStruct %uint
  752. %uint_ptr = OpTypePointer Function %uint
  753. %struct1_ptr = OpTypePointer Function %struct1
  754. %uint_0 = OpConstant %uint 0
  755. %func = OpTypeFunction %void
  756. %1 = OpFunction %void None %func
  757. %2 = OpLabel
  758. %var = OpVariable %struct1_ptr Function
  759. %3 = OpAccessChain %uint_ptr %var %uint_0
  760. %4 = OpLoad %uint %3 Volatile
  761. OpReturn
  762. OpFunctionEnd
  763. )";
  764. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  765. }
  766. TEST_F(ScalarReplacementTest, DontTouchVolatileStore) {
  767. const std::string text = R"(
  768. ;
  769. ; CHECK: [[struct:%\w+]] = OpTypeStruct
  770. ; CHECK: [[struct_ptr:%\w+]] = OpTypePointer Function [[struct]]
  771. ; CHECK: OpLabel
  772. ; CHECK-NEXT: OpVariable [[struct_ptr]]
  773. ; CHECK-NOT: OpVariable
  774. ;
  775. OpCapability Shader
  776. OpCapability Linkage
  777. OpMemoryModel Logical GLSL450
  778. OpName %func "dont_touch_volatile_store"
  779. %void = OpTypeVoid
  780. %uint = OpTypeInt 32 0
  781. %struct1 = OpTypeStruct %uint
  782. %uint_ptr = OpTypePointer Function %uint
  783. %struct1_ptr = OpTypePointer Function %struct1
  784. %uint_0 = OpConstant %uint 0
  785. %func = OpTypeFunction %void
  786. %1 = OpFunction %void None %func
  787. %2 = OpLabel
  788. %var = OpVariable %struct1_ptr Function
  789. %3 = OpAccessChain %uint_ptr %var %uint_0
  790. OpStore %3 %uint_0 Volatile
  791. OpReturn
  792. OpFunctionEnd
  793. )";
  794. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  795. }
  796. TEST_F(ScalarReplacementTest, DontTouchSpecNonFunctionVariable) {
  797. const std::string text = R"(
  798. ;
  799. ; CHECK: [[struct:%\w+]] = OpTypeStruct
  800. ; CHECK: [[struct_ptr:%\w+]] = OpTypePointer Uniform [[struct]]
  801. ; CHECK: OpConstant
  802. ; CHECK-NEXT: OpVariable [[struct_ptr]]
  803. ; CHECK-NOT: OpVariable
  804. ;
  805. OpCapability Shader
  806. OpCapability Linkage
  807. OpMemoryModel Logical GLSL450
  808. OpName %func "dont_touch_spec_constant_access_chain"
  809. %void = OpTypeVoid
  810. %uint = OpTypeInt 32 0
  811. %struct1 = OpTypeStruct %uint
  812. %uint_ptr = OpTypePointer Uniform %uint
  813. %struct1_ptr = OpTypePointer Uniform %struct1
  814. %uint_0 = OpConstant %uint 0
  815. %var = OpVariable %struct1_ptr Uniform
  816. %func = OpTypeFunction %void
  817. %1 = OpFunction %void None %func
  818. %2 = OpLabel
  819. %3 = OpAccessChain %uint_ptr %var %uint_0
  820. OpStore %3 %uint_0 Volatile
  821. OpReturn
  822. OpFunctionEnd
  823. )";
  824. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  825. }
  826. TEST_F(ScalarReplacementTest, DontTouchSpecConstantAccessChain) {
  827. const std::string text = R"(
  828. ;
  829. ; CHECK: [[array:%\w+]] = OpTypeArray
  830. ; CHECK: [[array_ptr:%\w+]] = OpTypePointer Function [[array]]
  831. ; CHECK: OpLabel
  832. ; CHECK-NEXT: OpVariable [[array_ptr]]
  833. ; CHECK-NOT: OpVariable
  834. ;
  835. OpCapability Shader
  836. OpCapability Linkage
  837. OpMemoryModel Logical GLSL450
  838. OpName %func "dont_touch_spec_constant_access_chain"
  839. %void = OpTypeVoid
  840. %uint = OpTypeInt 32 0
  841. %uint_1 = OpConstant %uint 1
  842. %array = OpTypeArray %uint %uint_1
  843. %uint_ptr = OpTypePointer Function %uint
  844. %array_ptr = OpTypePointer Function %array
  845. %uint_0 = OpConstant %uint 0
  846. %spec_const = OpSpecConstant %uint 0
  847. %func = OpTypeFunction %void
  848. %1 = OpFunction %void None %func
  849. %2 = OpLabel
  850. %var = OpVariable %array_ptr Function
  851. %3 = OpAccessChain %uint_ptr %var %spec_const
  852. OpStore %3 %uint_0 Volatile
  853. OpReturn
  854. OpFunctionEnd
  855. )";
  856. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  857. }
  858. TEST_F(ScalarReplacementTest, NoPartialAccesses) {
  859. const std::string text = R"(
  860. ;
  861. ; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
  862. ; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]]
  863. ; CHECK: OpLabel
  864. ; CHECK-NOT: OpVariable
  865. ;
  866. OpCapability Shader
  867. OpCapability Linkage
  868. OpMemoryModel Logical GLSL450
  869. OpName %func "no_partial_accesses"
  870. %void = OpTypeVoid
  871. %uint = OpTypeInt 32 0
  872. %struct1 = OpTypeStruct %uint
  873. %uint_ptr = OpTypePointer Function %uint
  874. %struct1_ptr = OpTypePointer Function %struct1
  875. %const = OpConstantNull %struct1
  876. %func = OpTypeFunction %void
  877. %1 = OpFunction %void None %func
  878. %2 = OpLabel
  879. %var = OpVariable %struct1_ptr Function
  880. OpStore %var %const
  881. OpReturn
  882. OpFunctionEnd
  883. )";
  884. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  885. }
  886. TEST_F(ScalarReplacementTest, DontTouchPtrAccessChain) {
  887. const std::string text = R"(
  888. ;
  889. ; CHECK: [[struct:%\w+]] = OpTypeStruct
  890. ; CHECK: [[struct_ptr:%\w+]] = OpTypePointer Function [[struct]]
  891. ; CHECK: OpLabel
  892. ; CHECK-NEXT: OpVariable [[struct_ptr]]
  893. ; CHECK-NOT: OpVariable
  894. ;
  895. OpCapability Shader
  896. OpCapability Linkage
  897. OpMemoryModel Logical GLSL450
  898. OpName %func "dont_touch_ptr_access_chain"
  899. %void = OpTypeVoid
  900. %uint = OpTypeInt 32 0
  901. %struct1 = OpTypeStruct %uint
  902. %uint_ptr = OpTypePointer Function %uint
  903. %struct1_ptr = OpTypePointer Function %struct1
  904. %uint_0 = OpConstant %uint 0
  905. %func = OpTypeFunction %void
  906. %1 = OpFunction %void None %func
  907. %2 = OpLabel
  908. %var = OpVariable %struct1_ptr Function
  909. %3 = OpPtrAccessChain %uint_ptr %var %uint_0 %uint_0
  910. OpStore %3 %uint_0
  911. %4 = OpAccessChain %uint_ptr %var %uint_0
  912. OpStore %4 %uint_0
  913. OpReturn
  914. OpFunctionEnd
  915. )";
  916. SinglePassRunAndMatch<ScalarReplacementPass>(text, false);
  917. }
  918. TEST_F(ScalarReplacementTest, DontTouchInBoundsPtrAccessChain) {
  919. const std::string text = R"(
  920. ;
  921. ; CHECK: [[struct:%\w+]] = OpTypeStruct
  922. ; CHECK: [[struct_ptr:%\w+]] = OpTypePointer Function [[struct]]
  923. ; CHECK: OpLabel
  924. ; CHECK-NEXT: OpVariable [[struct_ptr]]
  925. ; CHECK-NOT: OpVariable
  926. ;
  927. OpCapability Shader
  928. OpCapability Linkage
  929. OpMemoryModel Logical GLSL450
  930. OpName %func "dont_touch_in_bounds_ptr_access_chain"
  931. %void = OpTypeVoid
  932. %uint = OpTypeInt 32 0
  933. %struct1 = OpTypeStruct %uint
  934. %uint_ptr = OpTypePointer Function %uint
  935. %struct1_ptr = OpTypePointer Function %struct1
  936. %uint_0 = OpConstant %uint 0
  937. %func = OpTypeFunction %void
  938. %1 = OpFunction %void None %func
  939. %2 = OpLabel
  940. %var = OpVariable %struct1_ptr Function
  941. %3 = OpInBoundsPtrAccessChain %uint_ptr %var %uint_0 %uint_0
  942. OpStore %3 %uint_0
  943. %4 = OpInBoundsAccessChain %uint_ptr %var %uint_0
  944. OpStore %4 %uint_0
  945. OpReturn
  946. OpFunctionEnd
  947. )";
  948. SinglePassRunAndMatch<ScalarReplacementPass>(text, false);
  949. }
  950. TEST_F(ScalarReplacementTest, DonTouchAliasedDecoration) {
  951. const std::string text = R"(
  952. ;
  953. ; CHECK: [[struct:%\w+]] = OpTypeStruct
  954. ; CHECK: [[struct_ptr:%\w+]] = OpTypePointer Function [[struct]]
  955. ; CHECK: OpLabel
  956. ; CHECK-NEXT: OpVariable [[struct_ptr]]
  957. ; CHECK-NOT: OpVariable
  958. ;
  959. OpCapability Shader
  960. OpCapability Linkage
  961. OpMemoryModel Logical GLSL450
  962. OpName %func "aliased"
  963. OpDecorate %var Aliased
  964. %void = OpTypeVoid
  965. %uint = OpTypeInt 32 0
  966. %struct1 = OpTypeStruct %uint
  967. %uint_ptr = OpTypePointer Function %uint
  968. %struct1_ptr = OpTypePointer Function %struct1
  969. %uint_0 = OpConstant %uint 0
  970. %func = OpTypeFunction %void
  971. %1 = OpFunction %void None %func
  972. %2 = OpLabel
  973. %var = OpVariable %struct1_ptr Function
  974. %3 = OpAccessChain %uint_ptr %var %uint_0
  975. %4 = OpLoad %uint %3
  976. OpReturn
  977. OpFunctionEnd
  978. )";
  979. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  980. }
  981. TEST_F(ScalarReplacementTest, CopyRestrictDecoration) {
  982. const std::string text = R"(
  983. ;
  984. ; CHECK: OpName
  985. ; CHECK-NEXT: OpDecorate [[var0:%\w+]] Restrict
  986. ; CHECK-NEXT: OpDecorate [[var1:%\w+]] Restrict
  987. ; CHECK: [[int:%\w+]] = OpTypeInt
  988. ; CHECK: [[struct:%\w+]] = OpTypeStruct
  989. ; CHECK: [[int_ptr:%\w+]] = OpTypePointer Function [[int]]
  990. ; CHECK: [[struct_ptr:%\w+]] = OpTypePointer Function [[struct]]
  991. ; CHECK: OpLabel
  992. ; CHECK-NEXT: [[var1]] = OpVariable [[int_ptr]]
  993. ; CHECK-NEXT: [[var0]] = OpVariable [[int_ptr]]
  994. ; CHECK-NOT: OpVariable [[struct_ptr]]
  995. ;
  996. OpCapability Shader
  997. OpCapability Linkage
  998. OpMemoryModel Logical GLSL450
  999. OpName %func "restrict"
  1000. OpDecorate %var Restrict
  1001. %void = OpTypeVoid
  1002. %uint = OpTypeInt 32 0
  1003. %struct1 = OpTypeStruct %uint %uint
  1004. %uint_ptr = OpTypePointer Function %uint
  1005. %struct1_ptr = OpTypePointer Function %struct1
  1006. %uint_0 = OpConstant %uint 0
  1007. %uint_1 = OpConstant %uint 1
  1008. %func = OpTypeFunction %void
  1009. %1 = OpFunction %void None %func
  1010. %2 = OpLabel
  1011. %var = OpVariable %struct1_ptr Function
  1012. %3 = OpAccessChain %uint_ptr %var %uint_0
  1013. %4 = OpLoad %uint %3
  1014. %5 = OpAccessChain %uint_ptr %var %uint_1
  1015. %6 = OpLoad %uint %5
  1016. OpReturn
  1017. OpFunctionEnd
  1018. )";
  1019. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  1020. }
  1021. TEST_F(ScalarReplacementTest, DontClobberDecoratesOnSubtypes) {
  1022. const std::string text = R"(
  1023. ;
  1024. ; CHECK: OpDecorate [[array:%\w+]] ArrayStride 1
  1025. ; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
  1026. ; CHECK: [[array]] = OpTypeArray [[uint]]
  1027. ; CHECK: [[array_ptr:%\w+]] = OpTypePointer Function [[array]]
  1028. ; CHECK: OpLabel
  1029. ; CHECK-NEXT: OpVariable [[array_ptr]] Function
  1030. ; CHECK-NOT: OpVariable
  1031. ;
  1032. OpCapability Shader
  1033. OpCapability Linkage
  1034. OpMemoryModel Logical GLSL450
  1035. OpName %func "array_stride"
  1036. OpDecorate %array ArrayStride 1
  1037. %void = OpTypeVoid
  1038. %uint = OpTypeInt 32 0
  1039. %uint_1 = OpConstant %uint 1
  1040. %array = OpTypeArray %uint %uint_1
  1041. %struct1 = OpTypeStruct %array
  1042. %uint_ptr = OpTypePointer Function %uint
  1043. %struct1_ptr = OpTypePointer Function %struct1
  1044. %uint_0 = OpConstant %uint 0
  1045. %func = OpTypeFunction %void %uint
  1046. %1 = OpFunction %void None %func
  1047. %param = OpFunctionParameter %uint
  1048. %2 = OpLabel
  1049. %var = OpVariable %struct1_ptr Function
  1050. %3 = OpAccessChain %uint_ptr %var %uint_0 %param
  1051. %4 = OpLoad %uint %3
  1052. OpReturn
  1053. OpFunctionEnd
  1054. )";
  1055. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  1056. }
  1057. TEST_F(ScalarReplacementTest, DontCopyMemberDecorate) {
  1058. const std::string text = R"(
  1059. ;
  1060. ; CHECK-NOT: OpDecorate
  1061. ; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
  1062. ; CHECK: [[struct:%\w+]] = OpTypeStruct [[uint]]
  1063. ; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]]
  1064. ; CHECK: [[struct_ptr:%\w+]] = OpTypePointer Function [[struct]]
  1065. ; CHECK: OpLabel
  1066. ; CHECK-NEXT: OpVariable [[uint_ptr]] Function
  1067. ; CHECK-NOT: OpVariable
  1068. ;
  1069. OpCapability Shader
  1070. OpCapability Linkage
  1071. OpMemoryModel Logical GLSL450
  1072. OpName %func "member_decorate"
  1073. OpMemberDecorate %struct1 0 Offset 1
  1074. %void = OpTypeVoid
  1075. %uint = OpTypeInt 32 0
  1076. %uint_1 = OpConstant %uint 1
  1077. %struct1 = OpTypeStruct %uint
  1078. %uint_ptr = OpTypePointer Function %uint
  1079. %struct1_ptr = OpTypePointer Function %struct1
  1080. %uint_0 = OpConstant %uint 0
  1081. %func = OpTypeFunction %void %uint
  1082. %1 = OpFunction %void None %func
  1083. %2 = OpLabel
  1084. %var = OpVariable %struct1_ptr Function
  1085. %3 = OpAccessChain %uint_ptr %var %uint_0
  1086. %4 = OpLoad %uint %3
  1087. OpReturn
  1088. OpFunctionEnd
  1089. )";
  1090. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  1091. }
  1092. TEST_F(ScalarReplacementTest, NoPartialAccesses2) {
  1093. const std::string text = R"(
  1094. ;
  1095. ; CHECK: [[float:%\w+]] = OpTypeFloat 32
  1096. ; CHECK: [[float_ptr:%\w+]] = OpTypePointer Function [[float]]
  1097. ; CHECK: OpVariable [[float_ptr]] Function
  1098. ; CHECK: OpVariable [[float_ptr]] Function
  1099. ; CHECK: OpVariable [[float_ptr]] Function
  1100. ; CHECK: OpVariable [[float_ptr]] Function
  1101. ; CHECK: OpVariable [[float_ptr]] Function
  1102. ; CHECK: OpVariable [[float_ptr]] Function
  1103. ; CHECK: OpVariable [[float_ptr]] Function
  1104. ; CHECK-NOT: OpVariable
  1105. ;
  1106. OpCapability Shader
  1107. %1 = OpExtInstImport "GLSL.std.450"
  1108. OpMemoryModel Logical GLSL450
  1109. OpEntryPoint Fragment %main "main" %fo
  1110. OpExecutionMode %main OriginUpperLeft
  1111. OpSource GLSL 430
  1112. OpName %main "main"
  1113. OpName %S "S"
  1114. OpMemberName %S 0 "x"
  1115. OpMemberName %S 1 "y"
  1116. OpName %ts1 "ts1"
  1117. OpName %S_0 "S"
  1118. OpMemberName %S_0 0 "x"
  1119. OpMemberName %S_0 1 "y"
  1120. OpName %U_t "U_t"
  1121. OpMemberName %U_t 0 "g_s1"
  1122. OpMemberName %U_t 1 "g_s2"
  1123. OpMemberName %U_t 2 "g_s3"
  1124. OpName %_ ""
  1125. OpName %ts2 "ts2"
  1126. OpName %_Globals_ "_Globals_"
  1127. OpMemberName %_Globals_ 0 "g_b"
  1128. OpName %__0 ""
  1129. OpName %ts3 "ts3"
  1130. OpName %ts4 "ts4"
  1131. OpName %fo "fo"
  1132. OpMemberDecorate %S_0 0 Offset 0
  1133. OpMemberDecorate %S_0 1 Offset 4
  1134. OpMemberDecorate %U_t 0 Offset 0
  1135. OpMemberDecorate %U_t 1 Offset 8
  1136. OpMemberDecorate %U_t 2 Offset 16
  1137. OpDecorate %U_t BufferBlock
  1138. OpDecorate %_ DescriptorSet 0
  1139. OpMemberDecorate %_Globals_ 0 Offset 0
  1140. OpDecorate %_Globals_ Block
  1141. OpDecorate %__0 DescriptorSet 0
  1142. OpDecorate %__0 Binding 0
  1143. OpDecorate %fo Location 0
  1144. %void = OpTypeVoid
  1145. %15 = OpTypeFunction %void
  1146. %float = OpTypeFloat 32
  1147. %S = OpTypeStruct %float %float
  1148. %_ptr_Function_S = OpTypePointer Function %S
  1149. %S_0 = OpTypeStruct %float %float
  1150. %U_t = OpTypeStruct %S_0 %S_0 %S_0
  1151. %_ptr_Uniform_U_t = OpTypePointer Uniform %U_t
  1152. %_ = OpVariable %_ptr_Uniform_U_t Uniform
  1153. %int = OpTypeInt 32 1
  1154. %int_0 = OpConstant %int 0
  1155. %_ptr_Uniform_S_0 = OpTypePointer Uniform %S_0
  1156. %_ptr_Function_float = OpTypePointer Function %float
  1157. %int_1 = OpConstant %int 1
  1158. %uint = OpTypeInt 32 0
  1159. %_Globals_ = OpTypeStruct %uint
  1160. %_ptr_Uniform__Globals_ = OpTypePointer Uniform %_Globals_
  1161. %__0 = OpVariable %_ptr_Uniform__Globals_ Uniform
  1162. %_ptr_Uniform_uint = OpTypePointer Uniform %uint
  1163. %bool = OpTypeBool
  1164. %uint_0 = OpConstant %uint 0
  1165. %_ptr_Output_float = OpTypePointer Output %float
  1166. %fo = OpVariable %_ptr_Output_float Output
  1167. %main = OpFunction %void None %15
  1168. %30 = OpLabel
  1169. %ts1 = OpVariable %_ptr_Function_S Function
  1170. %ts2 = OpVariable %_ptr_Function_S Function
  1171. %ts3 = OpVariable %_ptr_Function_S Function
  1172. %ts4 = OpVariable %_ptr_Function_S Function
  1173. %31 = OpAccessChain %_ptr_Uniform_S_0 %_ %int_0
  1174. %32 = OpLoad %S_0 %31
  1175. %33 = OpCompositeExtract %float %32 0
  1176. %34 = OpAccessChain %_ptr_Function_float %ts1 %int_0
  1177. OpStore %34 %33
  1178. %35 = OpCompositeExtract %float %32 1
  1179. %36 = OpAccessChain %_ptr_Function_float %ts1 %int_1
  1180. OpStore %36 %35
  1181. %37 = OpAccessChain %_ptr_Uniform_S_0 %_ %int_1
  1182. %38 = OpLoad %S_0 %37
  1183. %39 = OpCompositeExtract %float %38 0
  1184. %40 = OpAccessChain %_ptr_Function_float %ts2 %int_0
  1185. OpStore %40 %39
  1186. %41 = OpCompositeExtract %float %38 1
  1187. %42 = OpAccessChain %_ptr_Function_float %ts2 %int_1
  1188. OpStore %42 %41
  1189. %43 = OpAccessChain %_ptr_Uniform_uint %__0 %int_0
  1190. %44 = OpLoad %uint %43
  1191. %45 = OpINotEqual %bool %44 %uint_0
  1192. OpSelectionMerge %46 None
  1193. OpBranchConditional %45 %47 %48
  1194. %47 = OpLabel
  1195. %49 = OpLoad %S %ts1
  1196. OpStore %ts3 %49
  1197. OpBranch %46
  1198. %48 = OpLabel
  1199. %50 = OpLoad %S %ts2
  1200. OpStore %ts3 %50
  1201. OpBranch %46
  1202. %46 = OpLabel
  1203. %51 = OpLoad %S %ts3
  1204. OpStore %ts4 %51
  1205. %52 = OpAccessChain %_ptr_Function_float %ts4 %int_1
  1206. %53 = OpLoad %float %52
  1207. OpStore %fo %53
  1208. OpReturn
  1209. OpFunctionEnd
  1210. )";
  1211. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  1212. }
  1213. TEST_F(ScalarReplacementTest, ReplaceWholeLoadAndStore) {
  1214. const std::string text = R"(
  1215. ;
  1216. ; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
  1217. ; CHECK: [[struct1:%\w+]] = OpTypeStruct [[uint]] [[uint]]
  1218. ; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]]
  1219. ; CHECK: [[const:%\w+]] = OpConstant [[uint]] 0
  1220. ; CHECK: [[undef:%\w+]] = OpUndef [[uint]]
  1221. ; CHECK: [[var0:%\w+]] = OpVariable [[uint_ptr]] Function
  1222. ; CHECK: [[var1:%\w+]] = OpVariable [[uint_ptr]] Function
  1223. ; CHECK-NOT: OpVariable
  1224. ; CHECK: [[l0:%\w+]] = OpLoad [[uint]] [[var0]]
  1225. ; CHECK: [[c0:%\w+]] = OpCompositeConstruct [[struct1]] [[l0]] [[undef]]
  1226. ; CHECK: [[e0:%\w+]] = OpCompositeExtract [[uint]] [[c0]] 0
  1227. ; CHECK: OpStore [[var1]] [[e0]]
  1228. ; CHECK: [[l1:%\w+]] = OpLoad [[uint]] [[var1]]
  1229. ; CHECK: [[c1:%\w+]] = OpCompositeConstruct [[struct1]] [[l1]] [[undef]]
  1230. ; CHECK: [[e1:%\w+]] = OpCompositeExtract [[uint]] [[c1]] 0
  1231. ;
  1232. OpCapability Shader
  1233. OpCapability Linkage
  1234. OpMemoryModel Logical GLSL450
  1235. OpName %func "replace_whole_load"
  1236. %void = OpTypeVoid
  1237. %uint = OpTypeInt 32 0
  1238. %struct1 = OpTypeStruct %uint %uint
  1239. %uint_ptr = OpTypePointer Function %uint
  1240. %struct1_ptr = OpTypePointer Function %struct1
  1241. %uint_0 = OpConstant %uint 0
  1242. %uint_1 = OpConstant %uint 1
  1243. %func = OpTypeFunction %void
  1244. %1 = OpFunction %void None %func
  1245. %2 = OpLabel
  1246. %var2 = OpVariable %struct1_ptr Function
  1247. %var1 = OpVariable %struct1_ptr Function
  1248. %load1 = OpLoad %struct1 %var1
  1249. OpStore %var2 %load1
  1250. %load2 = OpLoad %struct1 %var2
  1251. %3 = OpCompositeExtract %uint %load2 0
  1252. OpReturn
  1253. OpFunctionEnd
  1254. )";
  1255. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  1256. }
  1257. TEST_F(ScalarReplacementTest, ReplaceWholeLoadAndStore2) {
  1258. // TODO: We can improve this case by ensuring that |var2| is processed first.
  1259. const std::string text = R"(
  1260. ;
  1261. ; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
  1262. ; CHECK: [[struct1:%\w+]] = OpTypeStruct [[uint]] [[uint]]
  1263. ; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]]
  1264. ; CHECK: [[const:%\w+]] = OpConstant [[uint]] 0
  1265. ; CHECK: [[undef:%\w+]] = OpUndef [[uint]]
  1266. ; CHECK: [[var1:%\w+]] = OpVariable [[uint_ptr]] Function
  1267. ; CHECK: [[var0a:%\w+]] = OpVariable [[uint_ptr]] Function
  1268. ; CHECK: [[var0b:%\w+]] = OpVariable [[uint_ptr]] Function
  1269. ; CHECK-NOT: OpVariable
  1270. ; CHECK: [[l0a:%\w+]] = OpLoad [[uint]] [[var0a]]
  1271. ; CHECK: [[l0b:%\w+]] = OpLoad [[uint]] [[var0b]]
  1272. ; CHECK: [[c0:%\w+]] = OpCompositeConstruct [[struct1]] [[l0b]] [[l0a]]
  1273. ; CHECK: [[e0:%\w+]] = OpCompositeExtract [[uint]] [[c0]] 0
  1274. ; CHECK: OpStore [[var1]] [[e0]]
  1275. ; CHECK: [[l1:%\w+]] = OpLoad [[uint]] [[var1]]
  1276. ; CHECK: [[c1:%\w+]] = OpCompositeConstruct [[struct1]] [[l1]] [[undef]]
  1277. ; CHECK: [[e1:%\w+]] = OpCompositeExtract [[uint]] [[c1]] 0
  1278. ;
  1279. OpCapability Shader
  1280. OpCapability Linkage
  1281. OpMemoryModel Logical GLSL450
  1282. OpName %func "replace_whole_load"
  1283. %void = OpTypeVoid
  1284. %uint = OpTypeInt 32 0
  1285. %struct1 = OpTypeStruct %uint %uint
  1286. %uint_ptr = OpTypePointer Function %uint
  1287. %struct1_ptr = OpTypePointer Function %struct1
  1288. %uint_0 = OpConstant %uint 0
  1289. %uint_1 = OpConstant %uint 1
  1290. %func = OpTypeFunction %void
  1291. %1 = OpFunction %void None %func
  1292. %2 = OpLabel
  1293. %var1 = OpVariable %struct1_ptr Function
  1294. %var2 = OpVariable %struct1_ptr Function
  1295. %load1 = OpLoad %struct1 %var1
  1296. OpStore %var2 %load1
  1297. %load2 = OpLoad %struct1 %var2
  1298. %3 = OpCompositeExtract %uint %load2 0
  1299. OpReturn
  1300. OpFunctionEnd
  1301. )";
  1302. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  1303. }
  1304. TEST_F(ScalarReplacementTest, CreateAmbiguousNullConstant1) {
  1305. const std::string text = R"(
  1306. ;
  1307. ; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
  1308. ; CHECK: [[struct1:%\w+]] = OpTypeStruct [[uint]] [[struct_member:%\w+]]
  1309. ; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]]
  1310. ; CHECK: [[const:%\w+]] = OpConstant [[uint]] 0
  1311. ; CHECK: [[undef:%\w+]] = OpUndef [[struct_member]]
  1312. ; CHECK: [[var0a:%\w+]] = OpVariable [[uint_ptr]] Function
  1313. ; CHECK: [[var1:%\w+]] = OpVariable [[uint_ptr]] Function
  1314. ; CHECK: [[var0b:%\w+]] = OpVariable [[uint_ptr]] Function
  1315. ; CHECK-NOT: OpVariable
  1316. ; CHECK: OpStore [[var1]]
  1317. ; CHECK: [[l1:%\w+]] = OpLoad [[uint]] [[var1]]
  1318. ; CHECK: [[c1:%\w+]] = OpCompositeConstruct [[struct1]] [[l1]] [[undef]]
  1319. ; CHECK: [[e1:%\w+]] = OpCompositeExtract [[uint]] [[c1]] 0
  1320. ;
  1321. OpCapability Shader
  1322. OpCapability Linkage
  1323. OpMemoryModel Logical GLSL450
  1324. OpName %func "replace_whole_load"
  1325. %void = OpTypeVoid
  1326. %uint = OpTypeInt 32 0
  1327. %struct2 = OpTypeStruct %uint
  1328. %struct3 = OpTypeStruct %uint
  1329. %struct1 = OpTypeStruct %uint %struct2
  1330. %uint_ptr = OpTypePointer Function %uint
  1331. %struct1_ptr = OpTypePointer Function %struct1
  1332. %uint_0 = OpConstant %uint 0
  1333. %uint_1 = OpConstant %uint 1
  1334. %func = OpTypeFunction %void
  1335. %1 = OpFunction %void None %func
  1336. %2 = OpLabel
  1337. %var1 = OpVariable %struct1_ptr Function
  1338. %var2 = OpVariable %struct1_ptr Function
  1339. %load1 = OpLoad %struct1 %var1
  1340. OpStore %var2 %load1
  1341. %load2 = OpLoad %struct1 %var2
  1342. %3 = OpCompositeExtract %uint %load2 0
  1343. OpReturn
  1344. OpFunctionEnd
  1345. )";
  1346. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  1347. }
  1348. TEST_F(ScalarReplacementTest, SpecConstantArray) {
  1349. const std::string text = R"(
  1350. ; CHECK: [[int:%\w+]] = OpTypeInt
  1351. ; CHECK: [[spec_const:%\w+]] = OpSpecConstant [[int]] 4
  1352. ; CHECK: [[spec_op:%\w+]] = OpSpecConstantOp [[int]] IAdd [[spec_const]] [[spec_const]]
  1353. ; CHECK: [[array1:%\w+]] = OpTypeArray [[int]] [[spec_const]]
  1354. ; CHECK: [[array2:%\w+]] = OpTypeArray [[int]] [[spec_op]]
  1355. ; CHECK: [[ptr_array1:%\w+]] = OpTypePointer Function [[array1]]
  1356. ; CHECK: [[ptr_array2:%\w+]] = OpTypePointer Function [[array2]]
  1357. ; CHECK: OpLabel
  1358. ; CHECK-NEXT: OpVariable [[ptr_array1]] Function
  1359. ; CHECK-NEXT: OpVariable [[ptr_array2]] Function
  1360. ; CHECK-NOT: OpVariable
  1361. OpCapability Shader
  1362. OpCapability Linkage
  1363. OpMemoryModel Logical GLSL450
  1364. %void = OpTypeVoid
  1365. %void_fn = OpTypeFunction %void
  1366. %int = OpTypeInt 32 0
  1367. %spec_const = OpSpecConstant %int 4
  1368. %spec_op = OpSpecConstantOp %int IAdd %spec_const %spec_const
  1369. %array_1 = OpTypeArray %int %spec_const
  1370. %array_2 = OpTypeArray %int %spec_op
  1371. %ptr_array_1_Function = OpTypePointer Function %array_1
  1372. %ptr_array_2_Function = OpTypePointer Function %array_2
  1373. %func = OpFunction %void None %void_fn
  1374. %1 = OpLabel
  1375. %var_1 = OpVariable %ptr_array_1_Function Function
  1376. %var_2 = OpVariable %ptr_array_2_Function Function
  1377. OpReturn
  1378. OpFunctionEnd
  1379. )";
  1380. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  1381. }
  1382. TEST_F(ScalarReplacementTest, CreateAmbiguousNullConstant2) {
  1383. const std::string text = R"(
  1384. ;
  1385. ; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
  1386. ; CHECK: [[struct1:%\w+]] = OpTypeStruct [[uint]] [[struct_member:%\w+]]
  1387. ; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]]
  1388. ; CHECK: [[const:%\w+]] = OpConstant [[uint]] 0
  1389. ; CHECK: [[undef:%\w+]] = OpUndef [[struct_member]]
  1390. ; CHECK: [[var0a:%\w+]] = OpVariable [[uint_ptr]] Function
  1391. ; CHECK: [[var1:%\w+]] = OpVariable [[uint_ptr]] Function
  1392. ; CHECK: [[var0b:%\w+]] = OpVariable [[uint_ptr]] Function
  1393. ; CHECK: OpStore [[var1]]
  1394. ; CHECK: [[l1:%\w+]] = OpLoad [[uint]] [[var1]]
  1395. ; CHECK: [[c1:%\w+]] = OpCompositeConstruct [[struct1]] [[l1]] [[undef]]
  1396. ; CHECK: [[e1:%\w+]] = OpCompositeExtract [[uint]] [[c1]] 0
  1397. ;
  1398. OpCapability Shader
  1399. OpCapability Linkage
  1400. OpMemoryModel Logical GLSL450
  1401. OpName %func "replace_whole_load"
  1402. %void = OpTypeVoid
  1403. %uint = OpTypeInt 32 0
  1404. %struct3 = OpTypeStruct %uint
  1405. %struct2 = OpTypeStruct %uint
  1406. %struct1 = OpTypeStruct %uint %struct2
  1407. %uint_ptr = OpTypePointer Function %uint
  1408. %struct1_ptr = OpTypePointer Function %struct1
  1409. %uint_0 = OpConstant %uint 0
  1410. %uint_1 = OpConstant %uint 1
  1411. %func = OpTypeFunction %void
  1412. %1 = OpFunction %void None %func
  1413. %2 = OpLabel
  1414. %var1 = OpVariable %struct1_ptr Function
  1415. %var2 = OpVariable %struct1_ptr Function
  1416. %load1 = OpLoad %struct1 %var1
  1417. OpStore %var2 %load1
  1418. %load2 = OpLoad %struct1 %var2
  1419. %3 = OpCompositeExtract %uint %load2 0
  1420. OpReturn
  1421. OpFunctionEnd
  1422. )";
  1423. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  1424. }
  1425. // Test that a struct of size 4 is not replaced when there is a limit of 2.
  1426. TEST_F(ScalarReplacementTest, TestLimit) {
  1427. const std::string text = R"(
  1428. OpCapability Shader
  1429. OpCapability Linkage
  1430. OpMemoryModel Logical GLSL450
  1431. OpName %6 "simple_struct"
  1432. %1 = OpTypeVoid
  1433. %2 = OpTypeInt 32 0
  1434. %3 = OpTypeStruct %2 %2 %2 %2
  1435. %4 = OpTypePointer Function %3
  1436. %5 = OpTypePointer Function %2
  1437. %6 = OpTypeFunction %2
  1438. %7 = OpConstantNull %3
  1439. %8 = OpConstant %2 0
  1440. %9 = OpConstant %2 1
  1441. %10 = OpConstant %2 2
  1442. %11 = OpConstant %2 3
  1443. %12 = OpFunction %2 None %6
  1444. %13 = OpLabel
  1445. %14 = OpVariable %4 Function %7
  1446. %15 = OpInBoundsAccessChain %5 %14 %8
  1447. %16 = OpLoad %2 %15
  1448. %17 = OpAccessChain %5 %14 %10
  1449. %18 = OpLoad %2 %17
  1450. %19 = OpIAdd %2 %16 %18
  1451. OpReturnValue %19
  1452. OpFunctionEnd
  1453. )";
  1454. auto result =
  1455. SinglePassRunAndDisassemble<ScalarReplacementPass>(text, true, false, 2);
  1456. EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
  1457. }
  1458. // Test that a struct of size 4 is replaced when there is a limit of 0 (no
  1459. // limit). This is the same spir-v as a test above, so we do not check that it
  1460. // is correctly transformed. We leave that to the test above.
  1461. TEST_F(ScalarReplacementTest, TestUnimited) {
  1462. const std::string text = R"(
  1463. OpCapability Shader
  1464. OpCapability Linkage
  1465. OpMemoryModel Logical GLSL450
  1466. OpName %6 "simple_struct"
  1467. %1 = OpTypeVoid
  1468. %2 = OpTypeInt 32 0
  1469. %3 = OpTypeStruct %2 %2 %2 %2
  1470. %4 = OpTypePointer Function %3
  1471. %5 = OpTypePointer Function %2
  1472. %6 = OpTypeFunction %2
  1473. %7 = OpConstantNull %3
  1474. %8 = OpConstant %2 0
  1475. %9 = OpConstant %2 1
  1476. %10 = OpConstant %2 2
  1477. %11 = OpConstant %2 3
  1478. %12 = OpFunction %2 None %6
  1479. %13 = OpLabel
  1480. %14 = OpVariable %4 Function %7
  1481. %15 = OpInBoundsAccessChain %5 %14 %8
  1482. %16 = OpLoad %2 %15
  1483. %17 = OpAccessChain %5 %14 %10
  1484. %18 = OpLoad %2 %17
  1485. %19 = OpIAdd %2 %16 %18
  1486. OpReturnValue %19
  1487. OpFunctionEnd
  1488. )";
  1489. auto result =
  1490. SinglePassRunAndDisassemble<ScalarReplacementPass>(text, true, false, 0);
  1491. EXPECT_EQ(Pass::Status::SuccessWithChange, std::get<1>(result));
  1492. }
  1493. TEST_F(ScalarReplacementTest, AmbigousPointer) {
  1494. const std::string text = R"(
  1495. ; CHECK: [[s1:%\w+]] = OpTypeStruct %uint
  1496. ; CHECK: [[s2:%\w+]] = OpTypeStruct %uint
  1497. ; CHECK: [[s3:%\w+]] = OpTypeStruct [[s2]]
  1498. ; CHECK: [[s3_const:%\w+]] = OpConstantComposite [[s3]]
  1499. ; CHECK: [[s2_ptr:%\w+]] = OpTypePointer Function [[s2]]
  1500. ; CHECK: OpCompositeExtract [[s2]] [[s3_const]]
  1501. OpCapability Shader
  1502. %1 = OpExtInstImport "GLSL.std.450"
  1503. OpMemoryModel Logical GLSL450
  1504. OpEntryPoint Fragment %2 "main"
  1505. OpExecutionMode %2 OriginUpperLeft
  1506. OpSource ESSL 310
  1507. %void = OpTypeVoid
  1508. %5 = OpTypeFunction %void
  1509. %uint = OpTypeInt 32 0
  1510. %_struct_7 = OpTypeStruct %uint
  1511. %_struct_8 = OpTypeStruct %uint
  1512. %_struct_9 = OpTypeStruct %_struct_8
  1513. %uint_1 = OpConstant %uint 1
  1514. %11 = OpConstantComposite %_struct_8 %uint_1
  1515. %12 = OpConstantComposite %_struct_9 %11
  1516. %_ptr_Function__struct_9 = OpTypePointer Function %_struct_9
  1517. %_ptr_Function__struct_7 = OpTypePointer Function %_struct_7
  1518. %2 = OpFunction %void None %5
  1519. %15 = OpLabel
  1520. %var = OpVariable %_ptr_Function__struct_9 Function
  1521. OpStore %var %12
  1522. %ld = OpLoad %_struct_9 %var
  1523. %ex = OpCompositeExtract %_struct_8 %ld 0
  1524. OpReturn
  1525. OpFunctionEnd
  1526. )";
  1527. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  1528. }
  1529. // Test that scalar replacement does not crash when there is an OpAccessChain
  1530. // with no index. If we choose to handle this case in the future, then the
  1531. // result can change.
  1532. TEST_F(ScalarReplacementTest, TestAccessChainWithNoIndexes) {
  1533. const std::string text = R"(
  1534. OpCapability Shader
  1535. OpMemoryModel Logical GLSL450
  1536. OpEntryPoint Fragment %1 "main"
  1537. OpExecutionMode %1 OriginLowerLeft
  1538. %void = OpTypeVoid
  1539. %3 = OpTypeFunction %void
  1540. %float = OpTypeFloat 32
  1541. %_struct_5 = OpTypeStruct %float
  1542. %_ptr_Function__struct_5 = OpTypePointer Function %_struct_5
  1543. %1 = OpFunction %void None %3
  1544. %7 = OpLabel
  1545. %8 = OpVariable %_ptr_Function__struct_5 Function
  1546. %9 = OpAccessChain %_ptr_Function__struct_5 %8
  1547. OpReturn
  1548. OpFunctionEnd
  1549. )";
  1550. auto result =
  1551. SinglePassRunAndDisassemble<ScalarReplacementPass>(text, true, false);
  1552. EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
  1553. }
  1554. // Test that id overflow is handled gracefully.
  1555. TEST_F(ScalarReplacementTest, IdBoundOverflow1) {
  1556. const std::string text = R"(
  1557. OpCapability ImageQuery
  1558. OpMemoryModel Logical GLSL450
  1559. OpEntryPoint Fragment %4 "main"
  1560. OpExecutionMode %4 OriginUpperLeft
  1561. OpDecorate %4194302 DescriptorSet 1073495039
  1562. %2 = OpTypeVoid
  1563. %3 = OpTypeFunction %2
  1564. %6 = OpTypeFloat 32
  1565. %7 = OpTypeStruct %6 %6
  1566. %557056 = OpTypeStruct %7
  1567. %9 = OpTypePointer Function %7
  1568. %18 = OpTypeFunction %7 %9
  1569. %4 = OpFunction %2 Pure|Const %3
  1570. %1836763 = OpLabel
  1571. %4194302 = OpVariable %9 Function
  1572. %10 = OpVariable %9 Function
  1573. OpKill
  1574. %4194301 = OpLabel
  1575. %524296 = OpLoad %7 %4194302
  1576. OpKill
  1577. OpFunctionEnd
  1578. )";
  1579. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  1580. std::vector<Message> messages = {
  1581. {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."},
  1582. {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}};
  1583. SetMessageConsumer(GetTestMessageConsumer(messages));
  1584. auto result = SinglePassRunToBinary<ScalarReplacementPass>(text, true, false);
  1585. EXPECT_EQ(Pass::Status::Failure, std::get<1>(result));
  1586. }
  1587. // Test that id overflow is handled gracefully.
  1588. TEST_F(ScalarReplacementTest, IdBoundOverflow2) {
  1589. const std::string text = R"(
  1590. OpCapability Shader
  1591. OpMemoryModel Logical GLSL450
  1592. OpEntryPoint Fragment %4 "main" %17
  1593. OpExecutionMode %4 OriginUpperLeft
  1594. %2 = OpTypeVoid
  1595. %3 = OpTypeFunction %2
  1596. %6 = OpTypeFloat 32
  1597. %7 = OpTypeVector %6 4
  1598. %8 = OpTypeStruct %7
  1599. %9 = OpTypePointer Function %8
  1600. %16 = OpTypePointer Output %7
  1601. %21 = OpTypeInt 32 1
  1602. %22 = OpConstant %21 0
  1603. %23 = OpTypePointer Function %7
  1604. %17 = OpVariable %16 Output
  1605. %4 = OpFunction %2 None %3
  1606. %5 = OpLabel
  1607. %4194300 = OpVariable %23 Function
  1608. %10 = OpVariable %9 Function
  1609. %4194301 = OpAccessChain %23 %10 %22
  1610. %4194302 = OpLoad %7 %4194301
  1611. OpStore %4194300 %4194302
  1612. %15 = OpLoad %7 %4194300
  1613. OpStore %17 %15
  1614. OpReturn
  1615. OpFunctionEnd
  1616. )";
  1617. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  1618. std::vector<Message> messages = {
  1619. {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}};
  1620. SetMessageConsumer(GetTestMessageConsumer(messages));
  1621. auto result = SinglePassRunToBinary<ScalarReplacementPass>(text, true, false);
  1622. EXPECT_EQ(Pass::Status::Failure, std::get<1>(result));
  1623. }
  1624. // Test that id overflow is handled gracefully.
  1625. TEST_F(ScalarReplacementTest, IdBoundOverflow3) {
  1626. const std::string text = R"(
  1627. OpCapability InterpolationFunction
  1628. OpExtension "z"
  1629. OpMemoryModel Logical GLSL450
  1630. OpEntryPoint Fragment %4 "main"
  1631. OpExecutionMode %4 OriginUpperLeft
  1632. %2 = OpTypeVoid
  1633. %3 = OpTypeFunction %2
  1634. %6 = OpTypeFloat 32
  1635. %7 = OpTypeStruct %6 %6
  1636. %9 = OpTypePointer Function %7
  1637. %18 = OpTypeFunction %7 %9
  1638. %21 = OpTypeInt 32 0
  1639. %22 = OpConstant %21 4293000676
  1640. %4194302 = OpConstantNull %6
  1641. %4 = OpFunction %2 Inline|Pure %3
  1642. %786464 = OpLabel
  1643. %4194298 = OpVariable %9 Function
  1644. %10 = OpVariable %9 Function
  1645. %4194299 = OpUDiv %21 %22 %22
  1646. %4194300 = OpLoad %7 %10
  1647. %50959 = OpLoad %7 %4194298
  1648. OpKill
  1649. OpFunctionEnd
  1650. %1 = OpFunction %7 None %18
  1651. %19 = OpFunctionParameter %9
  1652. %147667 = OpLabel
  1653. %2044391 = OpUDiv %21 %22 %22
  1654. %25 = OpLoad %7 %19
  1655. OpReturnValue %25
  1656. OpFunctionEnd
  1657. %4194295 = OpFunction %2 None %3
  1658. %4194296 = OpLabel
  1659. OpKill
  1660. OpFunctionEnd
  1661. )";
  1662. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  1663. std::vector<Message> messages = {
  1664. {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."},
  1665. {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."},
  1666. {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."},
  1667. {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."},
  1668. {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."},
  1669. {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."},
  1670. {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."},
  1671. {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."},
  1672. {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}};
  1673. SetMessageConsumer(GetTestMessageConsumer(messages));
  1674. auto result = SinglePassRunToBinary<ScalarReplacementPass>(text, true, false);
  1675. EXPECT_EQ(Pass::Status::Failure, std::get<1>(result));
  1676. }
  1677. // Test that replacements for OpAccessChain do not go out of bounds.
  1678. // https://github.com/KhronosGroup/SPIRV-Tools/issues/2609.
  1679. TEST_F(ScalarReplacementTest, OutOfBoundOpAccessChain) {
  1680. const std::string text = R"(
  1681. OpCapability Shader
  1682. %1 = OpExtInstImport "GLSL.std.450"
  1683. OpMemoryModel Logical GLSL450
  1684. OpEntryPoint Fragment %main "main" %_GLF_color
  1685. OpExecutionMode %main OriginUpperLeft
  1686. OpSource ESSL 310
  1687. OpName %main "main"
  1688. OpName %a "a"
  1689. OpName %_GLF_color "_GLF_color"
  1690. OpDecorate %_GLF_color Location 0
  1691. %void = OpTypeVoid
  1692. %3 = OpTypeFunction %void
  1693. %int = OpTypeInt 32 1
  1694. %_ptr_Function_int = OpTypePointer Function %int
  1695. %int_1 = OpConstant %int 1
  1696. %float = OpTypeFloat 32
  1697. %uint = OpTypeInt 32 0
  1698. %uint_1 = OpConstant %uint 1
  1699. %_arr_float_uint_1 = OpTypeArray %float %uint_1
  1700. %_ptr_Function__arr_float_uint_1 = OpTypePointer Function %_arr_float_uint_1
  1701. %_ptr_Function_float = OpTypePointer Function %float
  1702. %_ptr_Output_float = OpTypePointer Output %float
  1703. %_GLF_color = OpVariable %_ptr_Output_float Output
  1704. %main = OpFunction %void None %3
  1705. %5 = OpLabel
  1706. %a = OpVariable %_ptr_Function__arr_float_uint_1 Function
  1707. %21 = OpAccessChain %_ptr_Function_float %a %int_1
  1708. %22 = OpLoad %float %21
  1709. OpStore %_GLF_color %22
  1710. OpReturn
  1711. OpFunctionEnd
  1712. )";
  1713. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  1714. auto result =
  1715. SinglePassRunAndDisassemble<ScalarReplacementPass>(text, true, false);
  1716. EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
  1717. }
  1718. TEST_F(ScalarReplacementTest, CharIndex) {
  1719. const std::string text = R"(
  1720. ; CHECK: [[int:%\w+]] = OpTypeInt 32 0
  1721. ; CHECK: [[ptr:%\w+]] = OpTypePointer Function [[int]]
  1722. ; CHECK: OpVariable [[ptr]] Function
  1723. OpCapability Shader
  1724. OpCapability Int8
  1725. OpMemoryModel Logical GLSL450
  1726. OpEntryPoint GLCompute %main "main"
  1727. OpExecutionMode %main LocalSize 1 1 1
  1728. %void = OpTypeVoid
  1729. %int = OpTypeInt 32 0
  1730. %int_1024 = OpConstant %int 1024
  1731. %char = OpTypeInt 8 0
  1732. %char_1 = OpConstant %char 1
  1733. %array = OpTypeArray %int %int_1024
  1734. %ptr_func_array = OpTypePointer Function %array
  1735. %ptr_func_int = OpTypePointer Function %int
  1736. %void_fn = OpTypeFunction %void
  1737. %main = OpFunction %void None %void_fn
  1738. %entry = OpLabel
  1739. %var = OpVariable %ptr_func_array Function
  1740. %gep = OpAccessChain %ptr_func_int %var %char_1
  1741. OpStore %gep %int_1024
  1742. OpReturn
  1743. OpFunctionEnd
  1744. )";
  1745. SinglePassRunAndMatch<ScalarReplacementPass>(text, true, 0);
  1746. }
  1747. TEST_F(ScalarReplacementTest, OutOfBoundsOpAccessChainNegative) {
  1748. const std::string text = R"(
  1749. OpCapability Shader
  1750. OpCapability Int8
  1751. OpMemoryModel Logical GLSL450
  1752. OpEntryPoint GLCompute %main "main"
  1753. OpExecutionMode %main LocalSize 1 1 1
  1754. %void = OpTypeVoid
  1755. %int = OpTypeInt 32 0
  1756. %int_1024 = OpConstant %int 1024
  1757. %char = OpTypeInt 8 1
  1758. %char_n1 = OpConstant %char -1
  1759. %array = OpTypeArray %int %int_1024
  1760. %ptr_func_array = OpTypePointer Function %array
  1761. %ptr_func_int = OpTypePointer Function %int
  1762. %void_fn = OpTypeFunction %void
  1763. %main = OpFunction %void None %void_fn
  1764. %entry = OpLabel
  1765. %var = OpVariable %ptr_func_array Function
  1766. %gep = OpAccessChain %ptr_func_int %var %char_n1
  1767. OpStore %gep %int_1024
  1768. OpReturn
  1769. OpFunctionEnd
  1770. )";
  1771. auto result =
  1772. SinglePassRunAndDisassemble<ScalarReplacementPass>(text, true, true, 0);
  1773. EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
  1774. }
  1775. TEST_F(ScalarReplacementTest, RelaxedPrecisionMemberDecoration) {
  1776. const std::string text = R"(
  1777. ; CHECK: OpDecorate {{%\w+}} RelaxedPrecision
  1778. ; CHECK: OpDecorate [[new_var:%\w+]] RelaxedPrecision
  1779. ; CHECK: [[new_var]] = OpVariable %_ptr_Function_v3float Function
  1780. ; CHECK: OpLoad %v3float [[new_var]]
  1781. OpCapability Shader
  1782. OpMemoryModel Logical GLSL450
  1783. OpEntryPoint Vertex %1 "Draw2DTexCol_VS" %2 %3
  1784. OpSource HLSL 600
  1785. OpDecorate %2 Location 0
  1786. OpDecorate %3 Location 1
  1787. OpDecorate %3 RelaxedPrecision
  1788. OpMemberDecorate %_struct_4 1 RelaxedPrecision
  1789. %float = OpTypeFloat 32
  1790. %int = OpTypeInt 32 1
  1791. %int_1 = OpConstant %int 1
  1792. %v3float = OpTypeVector %float 3
  1793. %_ptr_Input_v3float = OpTypePointer Input %v3float
  1794. %void = OpTypeVoid
  1795. %11 = OpTypeFunction %void
  1796. %_struct_4 = OpTypeStruct %v3float %v3float
  1797. %_ptr_Function__struct_4 = OpTypePointer Function %_struct_4
  1798. %_ptr_Function_v3float = OpTypePointer Function %v3float
  1799. %2 = OpVariable %_ptr_Input_v3float Input
  1800. %3 = OpVariable %_ptr_Input_v3float Input
  1801. %1 = OpFunction %void None %11
  1802. %14 = OpLabel
  1803. %15 = OpVariable %_ptr_Function__struct_4 Function
  1804. %16 = OpLoad %v3float %2
  1805. %17 = OpLoad %v3float %3
  1806. %18 = OpCompositeConstruct %_struct_4 %16 %17
  1807. OpStore %15 %18
  1808. %19 = OpAccessChain %_ptr_Function_v3float %15 %int_1
  1809. %20 = OpLoad %v3float %19
  1810. OpReturn
  1811. OpFunctionEnd
  1812. )";
  1813. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  1814. }
  1815. TEST_F(ScalarReplacementTest, DebugDeclare) {
  1816. const std::string text = R"(
  1817. OpCapability Shader
  1818. OpCapability Linkage
  1819. %ext = OpExtInstImport "OpenCL.DebugInfo.100"
  1820. OpMemoryModel Logical GLSL450
  1821. %test = OpString "test"
  1822. OpName %6 "simple_struct"
  1823. %1 = OpTypeVoid
  1824. %2 = OpTypeInt 32 0
  1825. %uint_32 = OpConstant %2 32
  1826. %3 = OpTypeStruct %2 %2 %2 %2
  1827. %4 = OpTypePointer Function %3
  1828. %5 = OpTypePointer Function %2
  1829. %6 = OpTypeFunction %2
  1830. %7 = OpConstantNull %3
  1831. %8 = OpConstant %2 0
  1832. %9 = OpConstant %2 1
  1833. %10 = OpConstant %2 2
  1834. %11 = OpConstant %2 3
  1835. %null_expr = OpExtInst %1 %ext DebugExpression
  1836. %src = OpExtInst %1 %ext DebugSource %test
  1837. %cu = OpExtInst %1 %ext DebugCompilationUnit 1 4 %src HLSL
  1838. %dbg_tf = OpExtInst %1 %ext DebugTypeBasic %test %uint_32 Float
  1839. %main_ty = OpExtInst %1 %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %1
  1840. %dbg_main = OpExtInst %1 %ext DebugFunction %test %main_ty %src 0 0 %cu %test FlagIsProtected|FlagIsPrivate 0 %12
  1841. %dbg_foo = OpExtInst %1 %ext DebugLocalVariable %test %dbg_tf %src 0 0 %dbg_main FlagIsLocal
  1842. %12 = OpFunction %2 None %6
  1843. %13 = OpLabel
  1844. %scope = OpExtInst %1 %ext DebugScope %dbg_main
  1845. %14 = OpVariable %4 Function %7
  1846. ; CHECK: [[deref:%\w+]] = OpExtInst %void [[ext:%\w+]] DebugOperation Deref
  1847. ; CHECK: [[dbg_local_var:%\w+]] = OpExtInst %void [[ext]] DebugLocalVariable
  1848. ; CHECK: [[deref_expr:%\w+]] = OpExtInst %void [[ext]] DebugExpression [[deref]]
  1849. ; CHECK: [[repl3:%\w+]] = OpVariable %_ptr_Function_uint Function
  1850. ; CHECK: [[repl2:%\w+]] = OpVariable %_ptr_Function_uint Function
  1851. ; CHECK: [[repl1:%\w+]] = OpVariable %_ptr_Function_uint Function
  1852. ; CHECK: [[repl0:%\w+]] = OpVariable %_ptr_Function_uint Function
  1853. ; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl3]] [[deref_expr]] %int_3
  1854. ; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl2]] [[deref_expr]] %int_2
  1855. ; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl1]] [[deref_expr]] %int_1
  1856. ; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl0]] [[deref_expr]] %int_0
  1857. ; CHECK-NOT: DebugDeclare
  1858. %decl = OpExtInst %1 %ext DebugDeclare %dbg_foo %14 %null_expr
  1859. %15 = OpInBoundsAccessChain %5 %14 %8
  1860. %16 = OpLoad %2 %15
  1861. %17 = OpAccessChain %5 %14 %10
  1862. %18 = OpLoad %2 %17
  1863. %19 = OpIAdd %2 %16 %18
  1864. OpReturnValue %19
  1865. OpFunctionEnd
  1866. )";
  1867. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  1868. }
  1869. TEST_F(ScalarReplacementTest, DebugValue) {
  1870. const std::string text = R"(
  1871. OpCapability Shader
  1872. OpCapability Linkage
  1873. %ext = OpExtInstImport "OpenCL.DebugInfo.100"
  1874. OpMemoryModel Logical GLSL450
  1875. %test = OpString "test"
  1876. OpName %6 "simple_struct"
  1877. %1 = OpTypeVoid
  1878. %2 = OpTypeInt 32 0
  1879. %uint_32 = OpConstant %2 32
  1880. %3 = OpTypeStruct %2 %2 %2 %2
  1881. %4 = OpTypePointer Function %3
  1882. %5 = OpTypePointer Function %2
  1883. %6 = OpTypeFunction %2
  1884. %7 = OpConstantNull %3
  1885. %8 = OpConstant %2 0
  1886. %9 = OpConstant %2 1
  1887. %10 = OpConstant %2 2
  1888. %11 = OpConstant %2 3
  1889. %deref = OpExtInst %1 %ext DebugOperation Deref
  1890. %deref_expr = OpExtInst %1 %ext DebugExpression %deref
  1891. %null_expr = OpExtInst %1 %ext DebugExpression
  1892. %src = OpExtInst %1 %ext DebugSource %test
  1893. %cu = OpExtInst %1 %ext DebugCompilationUnit 1 4 %src HLSL
  1894. %dbg_tf = OpExtInst %1 %ext DebugTypeBasic %test %uint_32 Float
  1895. %main_ty = OpExtInst %1 %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %1
  1896. %dbg_main = OpExtInst %1 %ext DebugFunction %test %main_ty %src 0 0 %cu %test FlagIsProtected|FlagIsPrivate 0 %12
  1897. %dbg_foo = OpExtInst %1 %ext DebugLocalVariable %test %dbg_tf %src 0 0 %dbg_main FlagIsLocal
  1898. %12 = OpFunction %2 None %6
  1899. %13 = OpLabel
  1900. %scope = OpExtInst %1 %ext DebugScope %dbg_main
  1901. %14 = OpVariable %4 Function %7
  1902. ; CHECK: [[deref:%\w+]] = OpExtInst %void [[ext:%\w+]] DebugOperation Deref
  1903. ; CHECK: [[deref_expr:%\w+]] = OpExtInst %void [[ext]] DebugExpression [[deref]]
  1904. ; CHECK: [[dbg_local_var:%\w+]] = OpExtInst %void [[ext]] DebugLocalVariable
  1905. ; CHECK: [[repl3:%\w+]] = OpVariable %_ptr_Function_uint Function
  1906. ; CHECK: [[repl2:%\w+]] = OpVariable %_ptr_Function_uint Function
  1907. ; CHECK: [[repl1:%\w+]] = OpVariable %_ptr_Function_uint Function
  1908. ; CHECK: [[repl0:%\w+]] = OpVariable %_ptr_Function_uint Function
  1909. ; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl0]] [[deref_expr]] %int_0
  1910. ; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl1]] [[deref_expr]] %int_1
  1911. ; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl2]] [[deref_expr]] %int_2
  1912. ; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl3]] [[deref_expr]] %int_3
  1913. %value = OpExtInst %1 %ext DebugValue %dbg_foo %14 %deref_expr
  1914. %15 = OpInBoundsAccessChain %5 %14 %8
  1915. %16 = OpLoad %2 %15
  1916. %17 = OpAccessChain %5 %14 %10
  1917. %18 = OpLoad %2 %17
  1918. %19 = OpIAdd %2 %16 %18
  1919. OpReturnValue %19
  1920. OpFunctionEnd
  1921. )";
  1922. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  1923. }
  1924. TEST_F(ScalarReplacementTest, DebugDeclareRecursive) {
  1925. const std::string text = R"(
  1926. OpCapability Shader
  1927. OpCapability Linkage
  1928. %ext = OpExtInstImport "OpenCL.DebugInfo.100"
  1929. OpMemoryModel Logical GLSL450
  1930. %test = OpString "test"
  1931. OpName %6 "simple_struct"
  1932. %1 = OpTypeVoid
  1933. %2 = OpTypeInt 32 0
  1934. %uint_32 = OpConstant %2 32
  1935. %float = OpTypeFloat 32
  1936. %float_1 = OpConstant %float 1
  1937. %member = OpTypeStruct %2 %float
  1938. %3 = OpTypeStruct %2 %member %float
  1939. %4 = OpTypePointer Function %3
  1940. %5 = OpTypePointer Function %2
  1941. %ptr_float_Function = OpTypePointer Function %float
  1942. %6 = OpTypeFunction %2
  1943. %cmember = OpConstantComposite %member %uint_32 %float_1
  1944. %7 = OpConstantComposite %3 %uint_32 %cmember %float_1
  1945. %8 = OpConstant %2 0
  1946. %9 = OpConstant %2 1
  1947. %10 = OpConstant %2 2
  1948. %null_expr = OpExtInst %1 %ext DebugExpression
  1949. %src = OpExtInst %1 %ext DebugSource %test
  1950. %cu = OpExtInst %1 %ext DebugCompilationUnit 1 4 %src HLSL
  1951. %dbg_tf = OpExtInst %1 %ext DebugTypeBasic %test %uint_32 Float
  1952. %main_ty = OpExtInst %1 %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %1
  1953. %dbg_main = OpExtInst %1 %ext DebugFunction %test %main_ty %src 0 0 %cu %test FlagIsProtected|FlagIsPrivate 0 %12
  1954. %dbg_foo = OpExtInst %1 %ext DebugLocalVariable %test %dbg_tf %src 0 0 %dbg_main FlagIsLocal
  1955. %12 = OpFunction %2 None %6
  1956. %13 = OpLabel
  1957. %scope = OpExtInst %1 %ext DebugScope %dbg_main
  1958. %14 = OpVariable %4 Function %7
  1959. ; CHECK: [[deref:%\w+]] = OpExtInst %void [[ext:%\w+]] DebugOperation Deref
  1960. ; CHECK: [[dbg_local_var:%\w+]] = OpExtInst %void [[ext]] DebugLocalVariable
  1961. ; CHECK: [[deref_expr:%\w+]] = OpExtInst %void [[ext]] DebugExpression [[deref]]
  1962. ; CHECK: [[repl2:%\w+]] = OpVariable %_ptr_Function_float Function %float_1
  1963. ; CHECK: [[repl1:%\w+]] = OpVariable %_ptr_Function_uint Function %uint_32
  1964. ; CHECK: [[repl3:%\w+]] = OpVariable %_ptr_Function_float Function %float_1
  1965. ; CHECK: [[repl0:%\w+]] = OpVariable %_ptr_Function_uint Function %uint_32
  1966. ; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl3]] [[deref_expr]] %int_2
  1967. ; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl1]] [[deref_expr]] %int_1 %int_0
  1968. ; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl2]] [[deref_expr]] %int_1 %int_1
  1969. ; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl0]] [[deref_expr]] %int_0
  1970. ; CHECK-NOT: DebugDeclare
  1971. %decl = OpExtInst %1 %ext DebugDeclare %dbg_foo %14 %null_expr
  1972. %15 = OpInBoundsAccessChain %5 %14 %8
  1973. %16 = OpLoad %2 %15
  1974. %17 = OpAccessChain %ptr_float_Function %14 %10
  1975. %18 = OpLoad %float %17
  1976. %value = OpConvertFToU %2 %18
  1977. %19 = OpIAdd %2 %16 %value
  1978. OpReturnValue %19
  1979. OpFunctionEnd
  1980. )";
  1981. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  1982. }
  1983. TEST_F(ScalarReplacementTest, DebugValueWithIndex) {
  1984. const std::string text = R"(
  1985. OpCapability Shader
  1986. OpCapability Linkage
  1987. %ext = OpExtInstImport "OpenCL.DebugInfo.100"
  1988. OpMemoryModel Logical GLSL450
  1989. %test = OpString "test"
  1990. OpName %6 "simple_struct"
  1991. %1 = OpTypeVoid
  1992. %2 = OpTypeInt 32 0
  1993. %uint_32 = OpConstant %2 32
  1994. %3 = OpTypeStruct %2 %2 %2 %2
  1995. %4 = OpTypePointer Function %3
  1996. %5 = OpTypePointer Function %2
  1997. %6 = OpTypeFunction %2
  1998. %7 = OpConstantNull %3
  1999. %8 = OpConstant %2 0
  2000. %9 = OpConstant %2 1
  2001. %10 = OpConstant %2 2
  2002. %11 = OpConstant %2 3
  2003. %deref = OpExtInst %1 %ext DebugOperation Deref
  2004. %deref_expr = OpExtInst %1 %ext DebugExpression %deref
  2005. %null_expr = OpExtInst %1 %ext DebugExpression
  2006. %src = OpExtInst %1 %ext DebugSource %test
  2007. %cu = OpExtInst %1 %ext DebugCompilationUnit 1 4 %src HLSL
  2008. %dbg_tf = OpExtInst %1 %ext DebugTypeBasic %test %uint_32 Float
  2009. %main_ty = OpExtInst %1 %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %1
  2010. %dbg_main = OpExtInst %1 %ext DebugFunction %test %main_ty %src 0 0 %cu %test FlagIsProtected|FlagIsPrivate 0 %12
  2011. %dbg_foo = OpExtInst %1 %ext DebugLocalVariable %test %dbg_tf %src 0 0 %dbg_main FlagIsLocal
  2012. %12 = OpFunction %2 None %6
  2013. %13 = OpLabel
  2014. %scope = OpExtInst %1 %ext DebugScope %dbg_main
  2015. %14 = OpVariable %4 Function %7
  2016. ; CHECK: [[deref:%\w+]] = OpExtInst %void [[ext:%\w+]] DebugOperation Deref
  2017. ; CHECK: [[deref_expr:%\w+]] = OpExtInst %void [[ext]] DebugExpression [[deref]]
  2018. ; CHECK: [[dbg_local_var:%\w+]] = OpExtInst %void [[ext]] DebugLocalVariable
  2019. ; CHECK: [[repl3:%\w+]] = OpVariable %_ptr_Function_uint Function
  2020. ; CHECK: [[repl2:%\w+]] = OpVariable %_ptr_Function_uint Function
  2021. ; CHECK: [[repl1:%\w+]] = OpVariable %_ptr_Function_uint Function
  2022. ; CHECK: [[repl0:%\w+]] = OpVariable %_ptr_Function_uint Function
  2023. ; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl0]] [[deref_expr]] %uint_0 %uint_1 %uint_2 %int_0
  2024. ; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl1]] [[deref_expr]] %uint_0 %uint_1 %uint_2 %int_1
  2025. ; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl2]] [[deref_expr]] %uint_0 %uint_1 %uint_2 %int_2
  2026. ; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl3]] [[deref_expr]] %uint_0 %uint_1 %uint_2 %int_3
  2027. %value = OpExtInst %1 %ext DebugValue %dbg_foo %14 %deref_expr %8 %9 %10
  2028. %15 = OpInBoundsAccessChain %5 %14 %8
  2029. %16 = OpLoad %2 %15
  2030. %17 = OpAccessChain %5 %14 %10
  2031. %18 = OpLoad %2 %17
  2032. %19 = OpIAdd %2 %16 %18
  2033. OpReturnValue %19
  2034. OpFunctionEnd
  2035. )";
  2036. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  2037. }
  2038. TEST_F(ScalarReplacementTest, DebugDeclareForVariableInOtherBB) {
  2039. const std::string text = R"(
  2040. OpCapability Shader
  2041. OpCapability Linkage
  2042. %ext = OpExtInstImport "OpenCL.DebugInfo.100"
  2043. OpMemoryModel Logical GLSL450
  2044. %test = OpString "test"
  2045. OpName %6 "simple_struct"
  2046. %1 = OpTypeVoid
  2047. %2 = OpTypeInt 32 0
  2048. %uint_32 = OpConstant %2 32
  2049. %3 = OpTypeStruct %2 %2 %2 %2
  2050. %4 = OpTypePointer Function %3
  2051. %5 = OpTypePointer Function %2
  2052. %6 = OpTypeFunction %2
  2053. %7 = OpConstantNull %3
  2054. %8 = OpConstant %2 0
  2055. %9 = OpConstant %2 1
  2056. %10 = OpConstant %2 2
  2057. %11 = OpConstant %2 3
  2058. %deref = OpExtInst %1 %ext DebugOperation Deref
  2059. %deref_expr = OpExtInst %1 %ext DebugExpression %deref
  2060. %null_expr = OpExtInst %1 %ext DebugExpression
  2061. %src = OpExtInst %1 %ext DebugSource %test
  2062. %cu = OpExtInst %1 %ext DebugCompilationUnit 1 4 %src HLSL
  2063. %dbg_tf = OpExtInst %1 %ext DebugTypeBasic %test %uint_32 Float
  2064. %main_ty = OpExtInst %1 %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %1
  2065. %dbg_main = OpExtInst %1 %ext DebugFunction %test %main_ty %src 0 0 %cu %test FlagIsProtected|FlagIsPrivate 0 %12
  2066. %dbg_foo = OpExtInst %1 %ext DebugLocalVariable %test %dbg_tf %src 0 0 %dbg_main FlagIsLocal
  2067. %12 = OpFunction %2 None %6
  2068. %13 = OpLabel
  2069. %scope = OpExtInst %1 %ext DebugScope %dbg_main
  2070. %14 = OpVariable %4 Function %7
  2071. ; CHECK: [[dbg_local_var:%\w+]] = OpExtInst %void [[ext:%\w+]] DebugLocalVariable
  2072. ; CHECK: [[repl3:%\w+]] = OpVariable %_ptr_Function_uint Function
  2073. ; CHECK: [[repl2:%\w+]] = OpVariable %_ptr_Function_uint Function
  2074. ; CHECK: [[repl1:%\w+]] = OpVariable %_ptr_Function_uint Function
  2075. ; CHECK: [[repl0:%\w+]] = OpVariable %_ptr_Function_uint Function
  2076. ; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl3]] [[deref_expr:%\w+]] %int_3
  2077. ; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl2]] [[deref_expr]] %int_2
  2078. ; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl1]] [[deref_expr]] %int_1
  2079. ; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl0]] [[deref_expr]] %int_0
  2080. OpBranch %20
  2081. %20 = OpLabel
  2082. %value = OpExtInst %1 %ext DebugDeclare %dbg_foo %14 %null_expr
  2083. %15 = OpInBoundsAccessChain %5 %14 %8
  2084. %16 = OpLoad %2 %15
  2085. %17 = OpAccessChain %5 %14 %10
  2086. %18 = OpLoad %2 %17
  2087. %19 = OpIAdd %2 %16 %18
  2088. OpReturnValue %19
  2089. OpFunctionEnd
  2090. )";
  2091. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  2092. }
  2093. TEST_F(ScalarReplacementTest, ImageTexelPointer) {
  2094. // Test whether the scalar replacement correctly checks the
  2095. // OpImageTexelPointer user of an aggregate with an image type.
  2096. const std::string text = R"(
  2097. ;
  2098. ; CHECK: [[imgTy:%\w+]] = OpTypeImage %uint Buffer 2 0 0 2 R32ui
  2099. ; CHECK: [[ptrImgTy:%\w+]] = OpTypePointer Function [[imgTy]]
  2100. ; CHECK: [[img:%\w+]] = OpVariable [[ptrImgTy]] Function
  2101. ; CHECK: [[imgTexelPtr:%\w+]] = OpImageTexelPointer {{%\w+}} [[img]] %uint_0 %uint_0
  2102. ; CHECK: OpAtomicIAdd %uint [[imgTexelPtr]] %uint_1 %uint_0 %uint_1
  2103. ;
  2104. OpCapability Shader
  2105. OpCapability SampledBuffer
  2106. OpCapability ImageBuffer
  2107. OpMemoryModel Logical GLSL450
  2108. OpEntryPoint GLCompute %1 "main"
  2109. OpExecutionMode %1 LocalSize 64 1 1
  2110. %void = OpTypeVoid
  2111. %uint = OpTypeInt 32 0
  2112. %uint_0 = OpConstant %uint 0
  2113. %uint_1 = OpConstant %uint 1
  2114. %_ptr_Image_uint = OpTypePointer Image %uint
  2115. %type_buffer_image = OpTypeImage %uint Buffer 2 0 0 2 R32ui
  2116. %_ptr_Function_type_buffer_image = OpTypePointer Function %type_buffer_image
  2117. %image_struct = OpTypeStruct %type_buffer_image %type_buffer_image
  2118. %_ptr_Function_image_struct = OpTypePointer Function %image_struct
  2119. %func = OpTypeFunction %void
  2120. %1 = OpFunction %void None %func
  2121. %2 = OpLabel
  2122. %3 = OpVariable %_ptr_Function_image_struct Function
  2123. %4 = OpAccessChain %_ptr_Function_type_buffer_image %3 %uint_1
  2124. %5 = OpImageTexelPointer %_ptr_Image_uint %4 %uint_0 %uint_0
  2125. %6 = OpAtomicIAdd %uint %5 %uint_1 %uint_0 %uint_1
  2126. OpReturn
  2127. OpFunctionEnd
  2128. )";
  2129. SinglePassRunAndMatch<ScalarReplacementPass>(text, false);
  2130. }
  2131. TEST_F(ScalarReplacementTest, FunctionDeclaration) {
  2132. // Make sure the pass works with a function declaration that is called.
  2133. const std::string text = R"(OpCapability Addresses
  2134. OpCapability Linkage
  2135. OpCapability Kernel
  2136. OpCapability Int8
  2137. %1 = OpExtInstImport "OpenCL.std"
  2138. OpMemoryModel Physical64 OpenCL
  2139. OpEntryPoint Kernel %2 "_Z23julia__1166_kernel_77094Bool"
  2140. OpExecutionMode %2 ContractionOff
  2141. OpSource Unknown 0
  2142. OpDecorate %3 LinkageAttributes "julia_error_7712" Import
  2143. %void = OpTypeVoid
  2144. %5 = OpTypeFunction %void
  2145. %3 = OpFunction %void None %5
  2146. OpFunctionEnd
  2147. %2 = OpFunction %void None %5
  2148. %6 = OpLabel
  2149. %7 = OpFunctionCall %void %3
  2150. OpReturn
  2151. OpFunctionEnd
  2152. )";
  2153. SinglePassRunAndCheck<ScalarReplacementPass>(text, text, false);
  2154. }
  2155. TEST_F(ScalarReplacementTest, UndefImageMember) {
  2156. // Test that scalar replacement creates an undef for a type that cannot have
  2157. // and OpConstantNull.
  2158. const std::string text = R"(
  2159. ; CHECK: [[image_type:%\w+]] = OpTypeSampledImage {{%\w+}}
  2160. ; CHECK: [[struct_type:%\w+]] = OpTypeStruct [[image_type]]
  2161. ; CHECK: [[undef:%\w+]] = OpUndef [[image_type]]
  2162. ; CHECK: {{%\w+}} = OpCompositeConstruct [[struct_type]] [[undef]]
  2163. OpCapability Shader
  2164. %1 = OpExtInstImport "GLSL.std.450"
  2165. OpMemoryModel Logical GLSL450
  2166. OpEntryPoint Fragment %2 "main"
  2167. OpExecutionMode %2 OriginUpperLeft
  2168. %void = OpTypeVoid
  2169. %4 = OpTypeFunction %void
  2170. %float = OpTypeFloat 32
  2171. %6 = OpTypeImage %float 2D 0 0 0 1 Unknown
  2172. %7 = OpTypeSampledImage %6
  2173. %_struct_8 = OpTypeStruct %7
  2174. %9 = OpTypeFunction %_struct_8
  2175. %10 = OpUndef %_struct_8
  2176. %_ptr_Function__struct_8 = OpTypePointer Function %_struct_8
  2177. %2 = OpFunction %void None %4
  2178. %11 = OpLabel
  2179. %16 = OpVariable %_ptr_Function__struct_8 Function
  2180. OpStore %16 %10
  2181. %12 = OpLoad %_struct_8 %16
  2182. OpReturn
  2183. OpFunctionEnd
  2184. )";
  2185. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  2186. }
  2187. TEST_F(ScalarReplacementTest, RestrictPointer) {
  2188. // This test makes sure that a variable with the restrict pointer decoration
  2189. // is replaced, and that the pointer is applied to the new variable.
  2190. const std::string text = R"(
  2191. ; CHECK: OpDecorate [[new_var:%\w+]] RestrictPointer
  2192. ; CHECK: [[struct_type:%\w+]] = OpTypeStruct %int
  2193. ; CHECK: [[ptr_type:%\w+]] = OpTypePointer PhysicalStorageBuffer [[struct_type]]
  2194. ; CHECK: [[dup_struct_type:%\w+]] = OpTypeStruct %int
  2195. ; CHECK: {{%\w+}} = OpTypePointer PhysicalStorageBuffer [[dup_struct_type]]
  2196. ; CHECK: [[var_type:%\w+]] = OpTypePointer Function [[ptr_type]]
  2197. ; CHECK: [[new_var]] = OpVariable [[var_type]] Function
  2198. OpCapability Shader
  2199. OpCapability PhysicalStorageBufferAddresses
  2200. %1 = OpExtInstImport "GLSL.std.450"
  2201. OpMemoryModel PhysicalStorageBuffer64 GLSL450
  2202. OpEntryPoint Fragment %2 "main"
  2203. OpExecutionMode %2 OriginUpperLeft
  2204. OpMemberDecorate %3 0 Offset 0
  2205. OpDecorate %3 Block
  2206. OpMemberDecorate %4 0 Offset 0
  2207. OpDecorate %4 Block
  2208. OpDecorate %5 RestrictPointer
  2209. %6 = OpTypeVoid
  2210. %7 = OpTypeFunction %6
  2211. %8 = OpTypeInt 32 1
  2212. %9 = OpConstant %8 0
  2213. %3 = OpTypeStruct %8
  2214. %10 = OpTypePointer PhysicalStorageBuffer %3
  2215. %11 = OpTypeStruct %10
  2216. %4 = OpTypeStruct %8
  2217. %12 = OpTypePointer PhysicalStorageBuffer %4
  2218. %13 = OpTypePointer Function %11
  2219. %14 = OpTypePointer Function %10
  2220. %15 = OpTypePointer Function %12
  2221. %16 = OpUndef %11
  2222. %2 = OpFunction %6 None %7
  2223. %17 = OpLabel
  2224. %5 = OpVariable %13 Function
  2225. OpStore %5 %16
  2226. %18 = OpAccessChain %14 %5 %9
  2227. OpReturn
  2228. OpFunctionEnd
  2229. )";
  2230. SetTargetEnv(SPV_ENV_UNIVERSAL_1_6);
  2231. SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
  2232. }
  2233. } // namespace
  2234. } // namespace opt
  2235. } // namespace spvtools