copy_prop_array_test.cpp 88 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231
  1. // Copyright (c) 2018 Google LLC
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include <string>
  15. #include "gmock/gmock.h"
  16. #include "test/opt/assembly_builder.h"
  17. #include "test/opt/pass_fixture.h"
  18. namespace spvtools {
  19. namespace opt {
  20. namespace {
  21. using CopyPropArrayPassTest = PassTest<::testing::Test>;
  22. TEST_F(CopyPropArrayPassTest, BasicPropagateArray) {
  23. const std::string before =
  24. R"(
  25. OpCapability Shader
  26. OpMemoryModel Logical GLSL450
  27. OpEntryPoint Fragment %main "main" %in_var_INDEX %out_var_SV_Target
  28. OpExecutionMode %main OriginUpperLeft
  29. OpSource HLSL 600
  30. OpName %type_MyCBuffer "type.MyCBuffer"
  31. OpMemberName %type_MyCBuffer 0 "Data"
  32. OpName %MyCBuffer "MyCBuffer"
  33. OpName %main "main"
  34. OpName %in_var_INDEX "in.var.INDEX"
  35. OpName %out_var_SV_Target "out.var.SV_Target"
  36. OpDecorate %_arr_v4float_uint_8 ArrayStride 16
  37. OpMemberDecorate %type_MyCBuffer 0 Offset 0
  38. OpDecorate %type_MyCBuffer Block
  39. OpDecorate %in_var_INDEX Flat
  40. OpDecorate %in_var_INDEX Location 0
  41. OpDecorate %out_var_SV_Target Location 0
  42. OpDecorate %MyCBuffer DescriptorSet 0
  43. OpDecorate %MyCBuffer Binding 0
  44. %float = OpTypeFloat 32
  45. %v4float = OpTypeVector %float 4
  46. %uint = OpTypeInt 32 0
  47. %uint_8 = OpConstant %uint 8
  48. %_arr_v4float_uint_8 = OpTypeArray %v4float %uint_8
  49. %type_MyCBuffer = OpTypeStruct %_arr_v4float_uint_8
  50. %_ptr_Uniform_type_MyCBuffer = OpTypePointer Uniform %type_MyCBuffer
  51. %void = OpTypeVoid
  52. %13 = OpTypeFunction %void
  53. %int = OpTypeInt 32 1
  54. %_ptr_Input_int = OpTypePointer Input %int
  55. %_ptr_Output_v4float = OpTypePointer Output %v4float
  56. %_arr_v4float_uint_8_0 = OpTypeArray %v4float %uint_8
  57. %_ptr_Function__arr_v4float_uint_8_0 = OpTypePointer Function %_arr_v4float_uint_8_0
  58. %int_0 = OpConstant %int 0
  59. %_ptr_Uniform__arr_v4float_uint_8 = OpTypePointer Uniform %_arr_v4float_uint_8
  60. %_ptr_Function_v4float = OpTypePointer Function %v4float
  61. %MyCBuffer = OpVariable %_ptr_Uniform_type_MyCBuffer Uniform
  62. %in_var_INDEX = OpVariable %_ptr_Input_int Input
  63. %out_var_SV_Target = OpVariable %_ptr_Output_v4float Output
  64. ; CHECK: OpFunction
  65. ; CHECK: OpLabel
  66. ; CHECK: OpVariable
  67. ; CHECK: OpAccessChain
  68. ; CHECK: [[new_address:%\w+]] = OpAccessChain %_ptr_Uniform__arr_v4float_uint_8 %MyCBuffer %int_0
  69. ; CHECK: [[element_ptr:%\w+]] = OpAccessChain %_ptr_Uniform_v4float [[new_address]] %24
  70. ; CHECK: [[load:%\w+]] = OpLoad %v4float [[element_ptr]]
  71. ; CHECK: OpStore %out_var_SV_Target [[load]]
  72. %main = OpFunction %void None %13
  73. %22 = OpLabel
  74. %23 = OpVariable %_ptr_Function__arr_v4float_uint_8_0 Function
  75. %24 = OpLoad %int %in_var_INDEX
  76. %25 = OpAccessChain %_ptr_Uniform__arr_v4float_uint_8 %MyCBuffer %int_0
  77. %26 = OpLoad %_arr_v4float_uint_8 %25
  78. %27 = OpCompositeExtract %v4float %26 0
  79. %28 = OpCompositeExtract %v4float %26 1
  80. %29 = OpCompositeExtract %v4float %26 2
  81. %30 = OpCompositeExtract %v4float %26 3
  82. %31 = OpCompositeExtract %v4float %26 4
  83. %32 = OpCompositeExtract %v4float %26 5
  84. %33 = OpCompositeExtract %v4float %26 6
  85. %34 = OpCompositeExtract %v4float %26 7
  86. %35 = OpCompositeConstruct %_arr_v4float_uint_8_0 %27 %28 %29 %30 %31 %32 %33 %34
  87. OpStore %23 %35
  88. %36 = OpAccessChain %_ptr_Function_v4float %23 %24
  89. %37 = OpLoad %v4float %36
  90. OpStore %out_var_SV_Target %37
  91. OpReturn
  92. OpFunctionEnd
  93. )";
  94. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  95. SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER |
  96. SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES);
  97. SinglePassRunAndMatch<CopyPropagateArrays>(before, false);
  98. }
  99. TEST_F(CopyPropArrayPassTest, BasicPropagateArrayWithName) {
  100. const std::string before =
  101. R"(
  102. OpCapability Shader
  103. OpMemoryModel Logical GLSL450
  104. OpEntryPoint Fragment %main "main" %in_var_INDEX %out_var_SV_Target
  105. OpExecutionMode %main OriginUpperLeft
  106. OpSource HLSL 600
  107. OpName %type_MyCBuffer "type.MyCBuffer"
  108. OpMemberName %type_MyCBuffer 0 "Data"
  109. OpName %MyCBuffer "MyCBuffer"
  110. OpName %main "main"
  111. OpName %local "local"
  112. OpName %in_var_INDEX "in.var.INDEX"
  113. OpName %out_var_SV_Target "out.var.SV_Target"
  114. OpDecorate %_arr_v4float_uint_8 ArrayStride 16
  115. OpMemberDecorate %type_MyCBuffer 0 Offset 0
  116. OpDecorate %type_MyCBuffer Block
  117. OpDecorate %in_var_INDEX Flat
  118. OpDecorate %in_var_INDEX Location 0
  119. OpDecorate %out_var_SV_Target Location 0
  120. OpDecorate %MyCBuffer DescriptorSet 0
  121. OpDecorate %MyCBuffer Binding 0
  122. %float = OpTypeFloat 32
  123. %v4float = OpTypeVector %float 4
  124. %uint = OpTypeInt 32 0
  125. %uint_8 = OpConstant %uint 8
  126. %_arr_v4float_uint_8 = OpTypeArray %v4float %uint_8
  127. %type_MyCBuffer = OpTypeStruct %_arr_v4float_uint_8
  128. %_ptr_Uniform_type_MyCBuffer = OpTypePointer Uniform %type_MyCBuffer
  129. %void = OpTypeVoid
  130. %13 = OpTypeFunction %void
  131. %int = OpTypeInt 32 1
  132. %_ptr_Input_int = OpTypePointer Input %int
  133. %_ptr_Output_v4float = OpTypePointer Output %v4float
  134. %_arr_v4float_uint_8_0 = OpTypeArray %v4float %uint_8
  135. %_ptr_Function__arr_v4float_uint_8_0 = OpTypePointer Function %_arr_v4float_uint_8_0
  136. %int_0 = OpConstant %int 0
  137. %_ptr_Uniform__arr_v4float_uint_8 = OpTypePointer Uniform %_arr_v4float_uint_8
  138. %_ptr_Function_v4float = OpTypePointer Function %v4float
  139. %MyCBuffer = OpVariable %_ptr_Uniform_type_MyCBuffer Uniform
  140. %in_var_INDEX = OpVariable %_ptr_Input_int Input
  141. %out_var_SV_Target = OpVariable %_ptr_Output_v4float Output
  142. ; CHECK: OpFunction
  143. ; CHECK: OpLabel
  144. ; CHECK: OpVariable
  145. ; CHECK: OpAccessChain
  146. ; CHECK: [[new_address:%\w+]] = OpAccessChain %_ptr_Uniform__arr_v4float_uint_8 %MyCBuffer %int_0
  147. ; CHECK: [[element_ptr:%\w+]] = OpAccessChain %_ptr_Uniform_v4float [[new_address]] %24
  148. ; CHECK: [[load:%\w+]] = OpLoad %v4float [[element_ptr]]
  149. ; CHECK: OpStore %out_var_SV_Target [[load]]
  150. %main = OpFunction %void None %13
  151. %22 = OpLabel
  152. %local = OpVariable %_ptr_Function__arr_v4float_uint_8_0 Function
  153. %24 = OpLoad %int %in_var_INDEX
  154. %25 = OpAccessChain %_ptr_Uniform__arr_v4float_uint_8 %MyCBuffer %int_0
  155. %26 = OpLoad %_arr_v4float_uint_8 %25
  156. %27 = OpCompositeExtract %v4float %26 0
  157. %28 = OpCompositeExtract %v4float %26 1
  158. %29 = OpCompositeExtract %v4float %26 2
  159. %30 = OpCompositeExtract %v4float %26 3
  160. %31 = OpCompositeExtract %v4float %26 4
  161. %32 = OpCompositeExtract %v4float %26 5
  162. %33 = OpCompositeExtract %v4float %26 6
  163. %34 = OpCompositeExtract %v4float %26 7
  164. %35 = OpCompositeConstruct %_arr_v4float_uint_8_0 %27 %28 %29 %30 %31 %32 %33 %34
  165. OpStore %local %35
  166. %36 = OpAccessChain %_ptr_Function_v4float %local %24
  167. %37 = OpLoad %v4float %36
  168. OpStore %out_var_SV_Target %37
  169. OpReturn
  170. OpFunctionEnd
  171. )";
  172. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  173. SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER |
  174. SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES);
  175. SinglePassRunAndMatch<CopyPropagateArrays>(before, false);
  176. }
  177. // Propagate 2d array. This test identifying a copy through multiple levels.
  178. // Also has to traverse multiple OpAccessChains.
  179. TEST_F(CopyPropArrayPassTest, Propagate2DArray) {
  180. const std::string text =
  181. R"(OpCapability Shader
  182. OpMemoryModel Logical GLSL450
  183. OpEntryPoint Fragment %main "main" %in_var_INDEX %out_var_SV_Target
  184. OpExecutionMode %main OriginUpperLeft
  185. OpSource HLSL 600
  186. OpName %type_MyCBuffer "type.MyCBuffer"
  187. OpMemberName %type_MyCBuffer 0 "Data"
  188. OpName %MyCBuffer "MyCBuffer"
  189. OpName %main "main"
  190. OpName %in_var_INDEX "in.var.INDEX"
  191. OpName %out_var_SV_Target "out.var.SV_Target"
  192. OpDecorate %_arr_v4float_uint_2 ArrayStride 16
  193. OpDecorate %_arr__arr_v4float_uint_2_uint_2 ArrayStride 32
  194. OpMemberDecorate %type_MyCBuffer 0 Offset 0
  195. OpDecorate %type_MyCBuffer Block
  196. OpDecorate %in_var_INDEX Flat
  197. OpDecorate %in_var_INDEX Location 0
  198. OpDecorate %out_var_SV_Target Location 0
  199. OpDecorate %MyCBuffer DescriptorSet 0
  200. OpDecorate %MyCBuffer Binding 0
  201. %float = OpTypeFloat 32
  202. %v4float = OpTypeVector %float 4
  203. %uint = OpTypeInt 32 0
  204. %uint_2 = OpConstant %uint 2
  205. %_arr_v4float_uint_2 = OpTypeArray %v4float %uint_2
  206. %_arr__arr_v4float_uint_2_uint_2 = OpTypeArray %_arr_v4float_uint_2 %uint_2
  207. %type_MyCBuffer = OpTypeStruct %_arr__arr_v4float_uint_2_uint_2
  208. %_ptr_Uniform_type_MyCBuffer = OpTypePointer Uniform %type_MyCBuffer
  209. %void = OpTypeVoid
  210. %14 = OpTypeFunction %void
  211. %int = OpTypeInt 32 1
  212. %_ptr_Input_int = OpTypePointer Input %int
  213. %_ptr_Output_v4float = OpTypePointer Output %v4float
  214. %_arr_v4float_uint_2_0 = OpTypeArray %v4float %uint_2
  215. %_arr__arr_v4float_uint_2_0_uint_2 = OpTypeArray %_arr_v4float_uint_2_0 %uint_2
  216. %_ptr_Function__arr__arr_v4float_uint_2_0_uint_2 = OpTypePointer Function %_arr__arr_v4float_uint_2_0_uint_2
  217. %int_0 = OpConstant %int 0
  218. %_ptr_Uniform__arr__arr_v4float_uint_2_uint_2 = OpTypePointer Uniform %_arr__arr_v4float_uint_2_uint_2
  219. %_ptr_Function__arr_v4float_uint_2_0 = OpTypePointer Function %_arr_v4float_uint_2_0
  220. %_ptr_Function_v4float = OpTypePointer Function %v4float
  221. %MyCBuffer = OpVariable %_ptr_Uniform_type_MyCBuffer Uniform
  222. %in_var_INDEX = OpVariable %_ptr_Input_int Input
  223. %out_var_SV_Target = OpVariable %_ptr_Output_v4float Output
  224. ; CHECK: OpFunction
  225. ; CHECK: OpLabel
  226. ; CHECK: OpVariable
  227. ; CHECK: OpVariable
  228. ; CHECK: OpAccessChain
  229. ; CHECK: [[new_address:%\w+]] = OpAccessChain %_ptr_Uniform__arr__arr_v4float_uint_2_uint_2 %MyCBuffer %int_0
  230. %main = OpFunction %void None %14
  231. %25 = OpLabel
  232. %26 = OpVariable %_ptr_Function__arr_v4float_uint_2_0 Function
  233. %27 = OpVariable %_ptr_Function__arr__arr_v4float_uint_2_0_uint_2 Function
  234. %28 = OpLoad %int %in_var_INDEX
  235. %29 = OpAccessChain %_ptr_Uniform__arr__arr_v4float_uint_2_uint_2 %MyCBuffer %int_0
  236. %30 = OpLoad %_arr__arr_v4float_uint_2_uint_2 %29
  237. %31 = OpCompositeExtract %_arr_v4float_uint_2 %30 0
  238. %32 = OpCompositeExtract %v4float %31 0
  239. %33 = OpCompositeExtract %v4float %31 1
  240. %34 = OpCompositeConstruct %_arr_v4float_uint_2_0 %32 %33
  241. %35 = OpCompositeExtract %_arr_v4float_uint_2 %30 1
  242. %36 = OpCompositeExtract %v4float %35 0
  243. %37 = OpCompositeExtract %v4float %35 1
  244. %38 = OpCompositeConstruct %_arr_v4float_uint_2_0 %36 %37
  245. %39 = OpCompositeConstruct %_arr__arr_v4float_uint_2_0_uint_2 %34 %38
  246. ; CHECK: OpStore
  247. OpStore %27 %39
  248. %40 = OpAccessChain %_ptr_Function__arr_v4float_uint_2_0 %27 %28
  249. %42 = OpAccessChain %_ptr_Function_v4float %40 %28
  250. %43 = OpLoad %v4float %42
  251. ; CHECK: [[ac1:%\w+]] = OpAccessChain %_ptr_Uniform__arr_v4float_uint_2 [[new_address]] %28
  252. ; CHECK: [[ac2:%\w+]] = OpAccessChain %_ptr_Uniform_v4float [[ac1]] %28
  253. ; CHECK: [[load:%\w+]] = OpLoad %v4float [[ac2]]
  254. ; CHECK: OpStore %out_var_SV_Target [[load]]
  255. OpStore %out_var_SV_Target %43
  256. OpReturn
  257. OpFunctionEnd
  258. )";
  259. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  260. SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER |
  261. SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES);
  262. SinglePassRunAndMatch<CopyPropagateArrays>(text, false);
  263. }
  264. // Propagate 2d array. This test identifying a copy through multiple levels.
  265. // Also has to traverse multiple OpAccessChains.
  266. TEST_F(CopyPropArrayPassTest, Propagate2DArrayWithMultiLevelExtract) {
  267. const std::string text =
  268. R"(OpCapability Shader
  269. OpMemoryModel Logical GLSL450
  270. OpEntryPoint Fragment %main "main" %in_var_INDEX %out_var_SV_Target
  271. OpExecutionMode %main OriginUpperLeft
  272. OpSource HLSL 600
  273. OpName %type_MyCBuffer "type.MyCBuffer"
  274. OpMemberName %type_MyCBuffer 0 "Data"
  275. OpName %MyCBuffer "MyCBuffer"
  276. OpName %main "main"
  277. OpName %in_var_INDEX "in.var.INDEX"
  278. OpName %out_var_SV_Target "out.var.SV_Target"
  279. OpDecorate %_arr_v4float_uint_2 ArrayStride 16
  280. OpDecorate %_arr__arr_v4float_uint_2_uint_2 ArrayStride 32
  281. OpMemberDecorate %type_MyCBuffer 0 Offset 0
  282. OpDecorate %type_MyCBuffer Block
  283. OpDecorate %in_var_INDEX Flat
  284. OpDecorate %in_var_INDEX Location 0
  285. OpDecorate %out_var_SV_Target Location 0
  286. OpDecorate %MyCBuffer DescriptorSet 0
  287. OpDecorate %MyCBuffer Binding 0
  288. %float = OpTypeFloat 32
  289. %v4float = OpTypeVector %float 4
  290. %uint = OpTypeInt 32 0
  291. %uint_2 = OpConstant %uint 2
  292. %_arr_v4float_uint_2 = OpTypeArray %v4float %uint_2
  293. %_arr__arr_v4float_uint_2_uint_2 = OpTypeArray %_arr_v4float_uint_2 %uint_2
  294. %type_MyCBuffer = OpTypeStruct %_arr__arr_v4float_uint_2_uint_2
  295. %_ptr_Uniform_type_MyCBuffer = OpTypePointer Uniform %type_MyCBuffer
  296. %void = OpTypeVoid
  297. %14 = OpTypeFunction %void
  298. %int = OpTypeInt 32 1
  299. %_ptr_Input_int = OpTypePointer Input %int
  300. %_ptr_Output_v4float = OpTypePointer Output %v4float
  301. %_arr_v4float_uint_2_0 = OpTypeArray %v4float %uint_2
  302. %_arr__arr_v4float_uint_2_0_uint_2 = OpTypeArray %_arr_v4float_uint_2_0 %uint_2
  303. %_ptr_Function__arr__arr_v4float_uint_2_0_uint_2 = OpTypePointer Function %_arr__arr_v4float_uint_2_0_uint_2
  304. %int_0 = OpConstant %int 0
  305. %_ptr_Uniform__arr__arr_v4float_uint_2_uint_2 = OpTypePointer Uniform %_arr__arr_v4float_uint_2_uint_2
  306. %_ptr_Function__arr_v4float_uint_2_0 = OpTypePointer Function %_arr_v4float_uint_2_0
  307. %_ptr_Function_v4float = OpTypePointer Function %v4float
  308. %MyCBuffer = OpVariable %_ptr_Uniform_type_MyCBuffer Uniform
  309. %in_var_INDEX = OpVariable %_ptr_Input_int Input
  310. %out_var_SV_Target = OpVariable %_ptr_Output_v4float Output
  311. ; CHECK: OpFunction
  312. ; CHECK: OpLabel
  313. ; CHECK: OpVariable
  314. ; CHECK: OpVariable
  315. ; CHECK: OpAccessChain
  316. ; CHECK: [[new_address:%\w+]] = OpAccessChain %_ptr_Uniform__arr__arr_v4float_uint_2_uint_2 %MyCBuffer %int_0
  317. %main = OpFunction %void None %14
  318. %25 = OpLabel
  319. %26 = OpVariable %_ptr_Function__arr_v4float_uint_2_0 Function
  320. %27 = OpVariable %_ptr_Function__arr__arr_v4float_uint_2_0_uint_2 Function
  321. %28 = OpLoad %int %in_var_INDEX
  322. %29 = OpAccessChain %_ptr_Uniform__arr__arr_v4float_uint_2_uint_2 %MyCBuffer %int_0
  323. %30 = OpLoad %_arr__arr_v4float_uint_2_uint_2 %29
  324. %32 = OpCompositeExtract %v4float %30 0 0
  325. %33 = OpCompositeExtract %v4float %30 0 1
  326. %34 = OpCompositeConstruct %_arr_v4float_uint_2_0 %32 %33
  327. %36 = OpCompositeExtract %v4float %30 1 0
  328. %37 = OpCompositeExtract %v4float %30 1 1
  329. %38 = OpCompositeConstruct %_arr_v4float_uint_2_0 %36 %37
  330. %39 = OpCompositeConstruct %_arr__arr_v4float_uint_2_0_uint_2 %34 %38
  331. ; CHECK: OpStore
  332. OpStore %27 %39
  333. %40 = OpAccessChain %_ptr_Function__arr_v4float_uint_2_0 %27 %28
  334. %42 = OpAccessChain %_ptr_Function_v4float %40 %28
  335. %43 = OpLoad %v4float %42
  336. ; CHECK: [[ac1:%\w+]] = OpAccessChain %_ptr_Uniform__arr_v4float_uint_2 [[new_address]] %28
  337. ; CHECK: [[ac2:%\w+]] = OpAccessChain %_ptr_Uniform_v4float [[ac1]] %28
  338. ; CHECK: [[load:%\w+]] = OpLoad %v4float [[ac2]]
  339. ; CHECK: OpStore %out_var_SV_Target [[load]]
  340. OpStore %out_var_SV_Target %43
  341. OpReturn
  342. OpFunctionEnd
  343. )";
  344. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  345. SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER |
  346. SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES);
  347. SinglePassRunAndMatch<CopyPropagateArrays>(text, false);
  348. }
  349. // Test decomposing an object when we need to "rewrite" a store.
  350. TEST_F(CopyPropArrayPassTest, DecomposeObjectForArrayStore) {
  351. const std::string text =
  352. R"( OpCapability Shader
  353. OpMemoryModel Logical GLSL450
  354. OpEntryPoint Fragment %main "main" %in_var_INDEX %out_var_SV_Target
  355. OpExecutionMode %main OriginUpperLeft
  356. OpSource HLSL 600
  357. OpName %type_MyCBuffer "type.MyCBuffer"
  358. OpMemberName %type_MyCBuffer 0 "Data"
  359. OpName %MyCBuffer "MyCBuffer"
  360. OpName %main "main"
  361. OpName %in_var_INDEX "in.var.INDEX"
  362. OpName %out_var_SV_Target "out.var.SV_Target"
  363. OpDecorate %_arr_v4float_uint_2 ArrayStride 16
  364. OpDecorate %_arr__arr_v4float_uint_2_uint_2 ArrayStride 32
  365. OpMemberDecorate %type_MyCBuffer 0 Offset 0
  366. OpDecorate %type_MyCBuffer Block
  367. OpDecorate %in_var_INDEX Flat
  368. OpDecorate %in_var_INDEX Location 0
  369. OpDecorate %out_var_SV_Target Location 0
  370. OpDecorate %MyCBuffer DescriptorSet 0
  371. OpDecorate %MyCBuffer Binding 0
  372. %float = OpTypeFloat 32
  373. %v4float = OpTypeVector %float 4
  374. %uint = OpTypeInt 32 0
  375. %uint_2 = OpConstant %uint 2
  376. %_arr_v4float_uint_2 = OpTypeArray %v4float %uint_2
  377. %_arr__arr_v4float_uint_2_uint_2 = OpTypeArray %_arr_v4float_uint_2 %uint_2
  378. %type_MyCBuffer = OpTypeStruct %_arr__arr_v4float_uint_2_uint_2
  379. %_ptr_Uniform_type_MyCBuffer = OpTypePointer Uniform %type_MyCBuffer
  380. %void = OpTypeVoid
  381. %14 = OpTypeFunction %void
  382. %int = OpTypeInt 32 1
  383. %_ptr_Input_int = OpTypePointer Input %int
  384. %_ptr_Output_v4float = OpTypePointer Output %v4float
  385. %_arr_v4float_uint_2_0 = OpTypeArray %v4float %uint_2
  386. %_arr__arr_v4float_uint_2_0_uint_2 = OpTypeArray %_arr_v4float_uint_2_0 %uint_2
  387. %_ptr_Function__arr__arr_v4float_uint_2_0_uint_2 = OpTypePointer Function %_arr__arr_v4float_uint_2_0_uint_2
  388. %int_0 = OpConstant %int 0
  389. %_ptr_Uniform__arr__arr_v4float_uint_2_uint_2 = OpTypePointer Uniform %_arr__arr_v4float_uint_2_uint_2
  390. %_ptr_Function__arr_v4float_uint_2_0 = OpTypePointer Function %_arr_v4float_uint_2_0
  391. %_ptr_Function_v4float = OpTypePointer Function %v4float
  392. %MyCBuffer = OpVariable %_ptr_Uniform_type_MyCBuffer Uniform
  393. %in_var_INDEX = OpVariable %_ptr_Input_int Input
  394. %out_var_SV_Target = OpVariable %_ptr_Output_v4float Output
  395. %main = OpFunction %void None %14
  396. %25 = OpLabel
  397. %26 = OpVariable %_ptr_Function__arr_v4float_uint_2_0 Function
  398. %27 = OpVariable %_ptr_Function__arr__arr_v4float_uint_2_0_uint_2 Function
  399. %28 = OpLoad %int %in_var_INDEX
  400. %29 = OpAccessChain %_ptr_Uniform__arr__arr_v4float_uint_2_uint_2 %MyCBuffer %int_0
  401. %30 = OpLoad %_arr__arr_v4float_uint_2_uint_2 %29
  402. %31 = OpCompositeExtract %_arr_v4float_uint_2 %30 0
  403. %32 = OpCompositeExtract %v4float %31 0
  404. %33 = OpCompositeExtract %v4float %31 1
  405. %34 = OpCompositeConstruct %_arr_v4float_uint_2_0 %32 %33
  406. %35 = OpCompositeExtract %_arr_v4float_uint_2 %30 1
  407. %36 = OpCompositeExtract %v4float %35 0
  408. %37 = OpCompositeExtract %v4float %35 1
  409. %38 = OpCompositeConstruct %_arr_v4float_uint_2_0 %36 %37
  410. %39 = OpCompositeConstruct %_arr__arr_v4float_uint_2_0_uint_2 %34 %38
  411. OpStore %27 %39
  412. ; CHECK: [[access_chain:%\w+]] = OpAccessChain %_ptr_Uniform__arr_v4float_uint_2
  413. %40 = OpAccessChain %_ptr_Function__arr_v4float_uint_2_0 %27 %28
  414. ; CHECK: [[load:%\w+]] = OpLoad %_arr_v4float_uint_2 [[access_chain]]
  415. %41 = OpLoad %_arr_v4float_uint_2_0 %40
  416. ; CHECK: [[extract1:%\w+]] = OpCompositeExtract %v4float [[load]] 0
  417. ; CHECK: [[extract2:%\w+]] = OpCompositeExtract %v4float [[load]] 1
  418. ; CHECK: [[construct:%\w+]] = OpCompositeConstruct %_arr_v4float_uint_2_0 [[extract1]] [[extract2]]
  419. ; CHECK: OpStore %26 [[construct]]
  420. OpStore %26 %41
  421. %42 = OpAccessChain %_ptr_Function_v4float %26 %28
  422. %43 = OpLoad %v4float %42
  423. OpStore %out_var_SV_Target %43
  424. OpReturn
  425. OpFunctionEnd
  426. )";
  427. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  428. SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER |
  429. SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES);
  430. SinglePassRunAndMatch<CopyPropagateArrays>(text, false);
  431. }
  432. // Test decomposing an object when we need to "rewrite" a store.
  433. TEST_F(CopyPropArrayPassTest, DecomposeObjectForStructStore) {
  434. const std::string text =
  435. R"( OpCapability Shader
  436. OpMemoryModel Logical GLSL450
  437. OpEntryPoint Fragment %main "main" %in_var_INDEX %out_var_SV_Target
  438. OpExecutionMode %main OriginUpperLeft
  439. OpSource HLSL 600
  440. OpName %type_MyCBuffer "type.MyCBuffer"
  441. OpMemberName %type_MyCBuffer 0 "Data"
  442. OpName %MyCBuffer "MyCBuffer"
  443. OpName %main "main"
  444. OpName %in_var_INDEX "in.var.INDEX"
  445. OpName %out_var_SV_Target "out.var.SV_Target"
  446. OpMemberDecorate %type_MyCBuffer 0 Offset 0
  447. OpDecorate %type_MyCBuffer Block
  448. OpDecorate %in_var_INDEX Flat
  449. OpDecorate %in_var_INDEX Location 0
  450. OpDecorate %out_var_SV_Target Location 0
  451. OpDecorate %MyCBuffer DescriptorSet 0
  452. OpDecorate %MyCBuffer Binding 0
  453. ; CHECK: OpDecorate [[decorated_type:%\w+]] GLSLPacked
  454. OpDecorate %struct GLSLPacked
  455. %float = OpTypeFloat 32
  456. %v4float = OpTypeVector %float 4
  457. %uint = OpTypeInt 32 0
  458. %uint_2 = OpConstant %uint 2
  459. ; CHECK: [[decorated_type]] = OpTypeStruct
  460. %struct = OpTypeStruct %float %uint
  461. %_arr_struct_uint_2 = OpTypeArray %struct %uint_2
  462. %type_MyCBuffer = OpTypeStruct %_arr_struct_uint_2
  463. %_ptr_Uniform_type_MyCBuffer = OpTypePointer Uniform %type_MyCBuffer
  464. %void = OpTypeVoid
  465. %14 = OpTypeFunction %void
  466. %int = OpTypeInt 32 1
  467. %_ptr_Input_int = OpTypePointer Input %int
  468. %_ptr_Output_v4float = OpTypePointer Output %v4float
  469. ; CHECK: [[struct:%\w+]] = OpTypeStruct %float %uint
  470. %struct_0 = OpTypeStruct %float %uint
  471. %_arr_struct_0_uint_2 = OpTypeArray %struct_0 %uint_2
  472. %_ptr_Function__arr_struct_0_uint_2 = OpTypePointer Function %_arr_struct_0_uint_2
  473. %int_0 = OpConstant %int 0
  474. %_ptr_Uniform__arr_struct_uint_2 = OpTypePointer Uniform %_arr_struct_uint_2
  475. ; CHECK: [[decorated_ptr:%\w+]] = OpTypePointer Uniform [[decorated_type]]
  476. %_ptr_Function_struct_0 = OpTypePointer Function %struct_0
  477. %_ptr_Function_v4float = OpTypePointer Function %v4float
  478. %MyCBuffer = OpVariable %_ptr_Uniform_type_MyCBuffer Uniform
  479. %in_var_INDEX = OpVariable %_ptr_Input_int Input
  480. %out_var_SV_Target = OpVariable %_ptr_Output_v4float Output
  481. %main = OpFunction %void None %14
  482. %25 = OpLabel
  483. %26 = OpVariable %_ptr_Function_struct_0 Function
  484. %27 = OpVariable %_ptr_Function__arr_struct_0_uint_2 Function
  485. %28 = OpLoad %int %in_var_INDEX
  486. %29 = OpAccessChain %_ptr_Uniform__arr_struct_uint_2 %MyCBuffer %int_0
  487. %30 = OpLoad %_arr_struct_uint_2 %29
  488. %31 = OpCompositeExtract %struct %30 0
  489. %32 = OpCompositeExtract %v4float %31 0
  490. %33 = OpCompositeExtract %v4float %31 1
  491. %34 = OpCompositeConstruct %struct_0 %32 %33
  492. %35 = OpCompositeExtract %struct %30 1
  493. %36 = OpCompositeExtract %float %35 0
  494. %37 = OpCompositeExtract %uint %35 1
  495. %38 = OpCompositeConstruct %struct_0 %36 %37
  496. %39 = OpCompositeConstruct %_arr_struct_0_uint_2 %34 %38
  497. OpStore %27 %39
  498. ; CHECK: [[access_chain:%\w+]] = OpAccessChain [[decorated_ptr]]
  499. %40 = OpAccessChain %_ptr_Function_struct_0 %27 %28
  500. ; CHECK: [[load:%\w+]] = OpLoad [[decorated_type]] [[access_chain]]
  501. %41 = OpLoad %struct_0 %40
  502. ; CHECK: [[extract1:%\w+]] = OpCompositeExtract %float [[load]] 0
  503. ; CHECK: [[extract2:%\w+]] = OpCompositeExtract %uint [[load]] 1
  504. ; CHECK: [[construct:%\w+]] = OpCompositeConstruct [[struct]] [[extract1]] [[extract2]]
  505. ; CHECK: OpStore %26 [[construct]]
  506. OpStore %26 %41
  507. %42 = OpAccessChain %_ptr_Function_v4float %26 %28
  508. %43 = OpLoad %v4float %42
  509. OpStore %out_var_SV_Target %43
  510. OpReturn
  511. OpFunctionEnd
  512. )";
  513. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  514. SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER |
  515. SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES);
  516. SinglePassRunAndMatch<CopyPropagateArrays>(text, false);
  517. }
  518. TEST_F(CopyPropArrayPassTest, CopyViaInserts) {
  519. const std::string before =
  520. R"(
  521. OpCapability Shader
  522. OpMemoryModel Logical GLSL450
  523. OpEntryPoint Fragment %main "main" %in_var_INDEX %out_var_SV_Target
  524. OpExecutionMode %main OriginUpperLeft
  525. OpSource HLSL 600
  526. OpName %type_MyCBuffer "type.MyCBuffer"
  527. OpMemberName %type_MyCBuffer 0 "Data"
  528. OpName %MyCBuffer "MyCBuffer"
  529. OpName %main "main"
  530. OpName %in_var_INDEX "in.var.INDEX"
  531. OpName %out_var_SV_Target "out.var.SV_Target"
  532. OpDecorate %_arr_v4float_uint_8 ArrayStride 16
  533. OpMemberDecorate %type_MyCBuffer 0 Offset 0
  534. OpDecorate %type_MyCBuffer Block
  535. OpDecorate %in_var_INDEX Flat
  536. OpDecorate %in_var_INDEX Location 0
  537. OpDecorate %out_var_SV_Target Location 0
  538. OpDecorate %MyCBuffer DescriptorSet 0
  539. OpDecorate %MyCBuffer Binding 0
  540. %float = OpTypeFloat 32
  541. %v4float = OpTypeVector %float 4
  542. %uint = OpTypeInt 32 0
  543. %uint_8 = OpConstant %uint 8
  544. %_arr_v4float_uint_8 = OpTypeArray %v4float %uint_8
  545. %type_MyCBuffer = OpTypeStruct %_arr_v4float_uint_8
  546. %_ptr_Uniform_type_MyCBuffer = OpTypePointer Uniform %type_MyCBuffer
  547. %void = OpTypeVoid
  548. %13 = OpTypeFunction %void
  549. %int = OpTypeInt 32 1
  550. %_ptr_Input_int = OpTypePointer Input %int
  551. %_ptr_Output_v4float = OpTypePointer Output %v4float
  552. %_arr_v4float_uint_8_0 = OpTypeArray %v4float %uint_8
  553. %_ptr_Function__arr_v4float_uint_8_0 = OpTypePointer Function %_arr_v4float_uint_8_0
  554. %int_0 = OpConstant %int 0
  555. %_ptr_Uniform__arr_v4float_uint_8 = OpTypePointer Uniform %_arr_v4float_uint_8
  556. %_ptr_Function_v4float = OpTypePointer Function %v4float
  557. %MyCBuffer = OpVariable %_ptr_Uniform_type_MyCBuffer Uniform
  558. %in_var_INDEX = OpVariable %_ptr_Input_int Input
  559. %out_var_SV_Target = OpVariable %_ptr_Output_v4float Output
  560. ; CHECK: OpFunction
  561. ; CHECK: OpLabel
  562. ; CHECK: OpVariable
  563. ; CHECK: OpAccessChain
  564. ; CHECK: [[new_address:%\w+]] = OpAccessChain %_ptr_Uniform__arr_v4float_uint_8 %MyCBuffer %int_0
  565. ; CHECK: [[element_ptr:%\w+]] = OpAccessChain %_ptr_Uniform_v4float [[new_address]] %24
  566. ; CHECK: [[load:%\w+]] = OpLoad %v4float [[element_ptr]]
  567. ; CHECK: OpStore %out_var_SV_Target [[load]]
  568. %main = OpFunction %void None %13
  569. %22 = OpLabel
  570. %23 = OpVariable %_ptr_Function__arr_v4float_uint_8_0 Function
  571. %undef = OpUndef %_arr_v4float_uint_8_0
  572. %24 = OpLoad %int %in_var_INDEX
  573. %25 = OpAccessChain %_ptr_Uniform__arr_v4float_uint_8 %MyCBuffer %int_0
  574. %26 = OpLoad %_arr_v4float_uint_8 %25
  575. %27 = OpCompositeExtract %v4float %26 0
  576. %i0 = OpCompositeInsert %_arr_v4float_uint_8_0 %27 %undef 0
  577. %28 = OpCompositeExtract %v4float %26 1
  578. %i1 = OpCompositeInsert %_arr_v4float_uint_8_0 %28 %i0 1
  579. %29 = OpCompositeExtract %v4float %26 2
  580. %i2 = OpCompositeInsert %_arr_v4float_uint_8_0 %29 %i1 2
  581. %30 = OpCompositeExtract %v4float %26 3
  582. %i3 = OpCompositeInsert %_arr_v4float_uint_8_0 %30 %i2 3
  583. %31 = OpCompositeExtract %v4float %26 4
  584. %i4 = OpCompositeInsert %_arr_v4float_uint_8_0 %31 %i3 4
  585. %32 = OpCompositeExtract %v4float %26 5
  586. %i5 = OpCompositeInsert %_arr_v4float_uint_8_0 %32 %i4 5
  587. %33 = OpCompositeExtract %v4float %26 6
  588. %i6 = OpCompositeInsert %_arr_v4float_uint_8_0 %33 %i5 6
  589. %34 = OpCompositeExtract %v4float %26 7
  590. %i7 = OpCompositeInsert %_arr_v4float_uint_8_0 %34 %i6 7
  591. OpStore %23 %i7
  592. %36 = OpAccessChain %_ptr_Function_v4float %23 %24
  593. %37 = OpLoad %v4float %36
  594. OpStore %out_var_SV_Target %37
  595. OpReturn
  596. OpFunctionEnd
  597. )";
  598. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  599. SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER |
  600. SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES);
  601. SinglePassRunAndMatch<CopyPropagateArrays>(before, false);
  602. }
  603. TEST_F(CopyPropArrayPassTest, IsomorphicTypes1) {
  604. const std::string before =
  605. R"(
  606. ; CHECK: [[int:%\w+]] = OpTypeInt 32 0
  607. ; CHECK: [[s1:%\w+]] = OpTypeStruct [[int]]
  608. ; CHECK: [[s2:%\w+]] = OpTypeStruct [[s1]]
  609. ; CHECK: [[a1:%\w+]] = OpTypeArray [[s2]]
  610. ; CHECK: [[s3:%\w+]] = OpTypeStruct [[a1]]
  611. ; CHECK: [[p_s3:%\w+]] = OpTypePointer Uniform [[s3]]
  612. ; CHECK: [[global_var:%\w+]] = OpVariable [[p_s3]] Uniform
  613. ; CHECK: [[p_a1:%\w+]] = OpTypePointer Uniform [[a1]]
  614. ; CHECK: [[p_s2:%\w+]] = OpTypePointer Uniform [[s2]]
  615. ; CHECK: [[ac1:%\w+]] = OpAccessChain [[p_a1]] [[global_var]] %uint_0
  616. ; CHECK: [[ac2:%\w+]] = OpAccessChain [[p_s2]] [[ac1]] %uint_0
  617. ; CHECK: [[ld:%\w+]] = OpLoad [[s2]] [[ac2]]
  618. ; CHECK: [[ex:%\w+]] = OpCompositeExtract [[s1]] [[ld]]
  619. OpCapability Shader
  620. %1 = OpExtInstImport "GLSL.std.450"
  621. OpMemoryModel Logical GLSL450
  622. OpEntryPoint Fragment %2 "PS_main"
  623. OpExecutionMode %2 OriginUpperLeft
  624. OpSource HLSL 600
  625. OpDecorate %3 DescriptorSet 0
  626. OpDecorate %3 Binding 101
  627. %uint = OpTypeInt 32 0
  628. %uint_1 = OpConstant %uint 1
  629. %s1 = OpTypeStruct %uint
  630. %s2 = OpTypeStruct %s1
  631. %a1 = OpTypeArray %s2 %uint_1
  632. %s3 = OpTypeStruct %a1
  633. %s1_1 = OpTypeStruct %uint
  634. %_ptr_Uniform_uint = OpTypePointer Uniform %uint
  635. %void = OpTypeVoid
  636. %13 = OpTypeFunction %void
  637. %uint_0 = OpConstant %uint 0
  638. %s1_0 = OpTypeStruct %uint
  639. %s2_0 = OpTypeStruct %s1_0
  640. %a1_0 = OpTypeArray %s2_0 %uint_1
  641. %s3_0 = OpTypeStruct %a1_0
  642. %p_s3 = OpTypePointer Uniform %s3
  643. %p_s3_0 = OpTypePointer Function %s3_0
  644. %3 = OpVariable %p_s3 Uniform
  645. %p_a1_0 = OpTypePointer Function %a1_0
  646. %p_s2_0 = OpTypePointer Function %s2_0
  647. %2 = OpFunction %void None %13
  648. %20 = OpLabel
  649. %21 = OpVariable %p_a1_0 Function
  650. %22 = OpLoad %s3 %3
  651. %23 = OpCompositeExtract %a1 %22 0
  652. %24 = OpCompositeExtract %s2 %23 0
  653. %25 = OpCompositeExtract %s1 %24 0
  654. %26 = OpCompositeExtract %uint %25 0
  655. %27 = OpCompositeConstruct %s1_0 %26
  656. %32 = OpCompositeConstruct %s2_0 %27
  657. %28 = OpCompositeConstruct %a1_0 %32
  658. OpStore %21 %28
  659. %29 = OpAccessChain %p_s2_0 %21 %uint_0
  660. %30 = OpLoad %s2 %29
  661. %31 = OpCompositeExtract %s1 %30 0
  662. OpReturn
  663. OpFunctionEnd
  664. )";
  665. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  666. SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER |
  667. SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES);
  668. SinglePassRunAndMatch<CopyPropagateArrays>(before, false);
  669. }
  670. TEST_F(CopyPropArrayPassTest, IsomorphicTypes2) {
  671. const std::string before =
  672. R"(
  673. ; CHECK: [[int:%\w+]] = OpTypeInt 32 0
  674. ; CHECK: [[s1:%\w+]] = OpTypeStruct [[int]]
  675. ; CHECK: [[s2:%\w+]] = OpTypeStruct [[s1]]
  676. ; CHECK: [[a1:%\w+]] = OpTypeArray [[s2]]
  677. ; CHECK: [[s3:%\w+]] = OpTypeStruct [[a1]]
  678. ; CHECK: [[p_s3:%\w+]] = OpTypePointer Uniform [[s3]]
  679. ; CHECK: [[global_var:%\w+]] = OpVariable [[p_s3]] Uniform
  680. ; CHECK: [[p_s2:%\w+]] = OpTypePointer Uniform [[s2]]
  681. ; CHECK: [[p_s1:%\w+]] = OpTypePointer Uniform [[s1]]
  682. ; CHECK: [[ac1:%\w+]] = OpAccessChain [[p_s2]] [[global_var]] %uint_0 %uint_0
  683. ; CHECK: [[ac2:%\w+]] = OpAccessChain [[p_s1]] [[ac1]] %uint_0
  684. ; CHECK: [[ld:%\w+]] = OpLoad [[s1]] [[ac2]]
  685. ; CHECK: [[ex:%\w+]] = OpCompositeExtract [[int]] [[ld]]
  686. OpCapability Shader
  687. %1 = OpExtInstImport "GLSL.std.450"
  688. OpMemoryModel Logical GLSL450
  689. OpEntryPoint Fragment %2 "PS_main"
  690. OpExecutionMode %2 OriginUpperLeft
  691. OpSource HLSL 600
  692. OpDecorate %3 DescriptorSet 0
  693. OpDecorate %3 Binding 101
  694. %uint = OpTypeInt 32 0
  695. %uint_1 = OpConstant %uint 1
  696. %_struct_6 = OpTypeStruct %uint
  697. %_struct_7 = OpTypeStruct %_struct_6
  698. %_arr__struct_7_uint_1 = OpTypeArray %_struct_7 %uint_1
  699. %_struct_9 = OpTypeStruct %_arr__struct_7_uint_1
  700. %_struct_10 = OpTypeStruct %uint
  701. %_ptr_Uniform_uint = OpTypePointer Uniform %uint
  702. %void = OpTypeVoid
  703. %13 = OpTypeFunction %void
  704. %uint_0 = OpConstant %uint 0
  705. %_struct_15 = OpTypeStruct %uint
  706. %_arr__struct_15_uint_1 = OpTypeArray %_struct_15 %uint_1
  707. %_ptr_Uniform__struct_9 = OpTypePointer Uniform %_struct_9
  708. %_ptr_Function__struct_15 = OpTypePointer Function %_struct_15
  709. %3 = OpVariable %_ptr_Uniform__struct_9 Uniform
  710. %_ptr_Function__arr__struct_15_uint_1 = OpTypePointer Function %_arr__struct_15_uint_1
  711. %2 = OpFunction %void None %13
  712. %20 = OpLabel
  713. %21 = OpVariable %_ptr_Function__arr__struct_15_uint_1 Function
  714. %22 = OpLoad %_struct_9 %3
  715. %23 = OpCompositeExtract %_arr__struct_7_uint_1 %22 0
  716. %24 = OpCompositeExtract %_struct_7 %23 0
  717. %25 = OpCompositeExtract %_struct_6 %24 0
  718. %26 = OpCompositeExtract %uint %25 0
  719. %27 = OpCompositeConstruct %_struct_15 %26
  720. %28 = OpCompositeConstruct %_arr__struct_15_uint_1 %27
  721. OpStore %21 %28
  722. %29 = OpAccessChain %_ptr_Function__struct_15 %21 %uint_0
  723. %30 = OpLoad %_struct_15 %29
  724. %31 = OpCompositeExtract %uint %30 0
  725. OpReturn
  726. OpFunctionEnd
  727. )";
  728. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  729. SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER |
  730. SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES);
  731. SinglePassRunAndMatch<CopyPropagateArrays>(before, false);
  732. }
  733. TEST_F(CopyPropArrayPassTest, IsomorphicTypes3) {
  734. const std::string before =
  735. R"(
  736. ; CHECK: [[int:%\w+]] = OpTypeInt 32 0
  737. ; CHECK: [[s1:%\w+]] = OpTypeStruct [[int]]
  738. ; CHECK: [[s2:%\w+]] = OpTypeStruct [[s1]]
  739. ; CHECK: [[a1:%\w+]] = OpTypeArray [[s2]]
  740. ; CHECK: [[s3:%\w+]] = OpTypeStruct [[a1]]
  741. ; CHECK: [[s1_1:%\w+]] = OpTypeStruct [[int]]
  742. ; CHECK: [[p_s3:%\w+]] = OpTypePointer Uniform [[s3]]
  743. ; CHECK: [[p_s1_1:%\w+]] = OpTypePointer Function [[s1_1]]
  744. ; CHECK: [[global_var:%\w+]] = OpVariable [[p_s3]] Uniform
  745. ; CHECK: [[p_s2:%\w+]] = OpTypePointer Uniform [[s2]]
  746. ; CHECK: [[p_s1:%\w+]] = OpTypePointer Uniform [[s1]]
  747. ; CHECK: [[var:%\w+]] = OpVariable [[p_s1_1]] Function
  748. ; CHECK: [[ac1:%\w+]] = OpAccessChain [[p_s2]] [[global_var]] %uint_0 %uint_0
  749. ; CHECK: [[ac2:%\w+]] = OpAccessChain [[p_s1]] [[ac1]] %uint_0
  750. ; CHECK: [[ld:%\w+]] = OpLoad [[s1]] [[ac2]]
  751. ; CHECK: [[ex:%\w+]] = OpCompositeExtract [[int]] [[ld]]
  752. ; CHECK: [[copy:%\w+]] = OpCompositeConstruct [[s1_1]] [[ex]]
  753. ; CHECK: OpStore [[var]] [[copy]]
  754. OpCapability Shader
  755. %1 = OpExtInstImport "GLSL.std.450"
  756. OpMemoryModel Logical GLSL450
  757. OpEntryPoint Fragment %2 "PS_main"
  758. OpExecutionMode %2 OriginUpperLeft
  759. OpSource HLSL 600
  760. OpDecorate %3 DescriptorSet 0
  761. OpDecorate %3 Binding 101
  762. %uint = OpTypeInt 32 0
  763. %uint_1 = OpConstant %uint 1
  764. %_struct_6 = OpTypeStruct %uint
  765. %_struct_7 = OpTypeStruct %_struct_6
  766. %_arr__struct_7_uint_1 = OpTypeArray %_struct_7 %uint_1
  767. %_struct_9 = OpTypeStruct %_arr__struct_7_uint_1
  768. %_ptr_Uniform_uint = OpTypePointer Uniform %uint
  769. %void = OpTypeVoid
  770. %13 = OpTypeFunction %void
  771. %uint_0 = OpConstant %uint 0
  772. %_struct_15 = OpTypeStruct %uint
  773. %_struct_10 = OpTypeStruct %uint
  774. %_arr__struct_15_uint_1 = OpTypeArray %_struct_15 %uint_1
  775. %_ptr_Uniform__struct_9 = OpTypePointer Uniform %_struct_9
  776. %_ptr_Function__struct_15 = OpTypePointer Function %_struct_15
  777. %3 = OpVariable %_ptr_Uniform__struct_9 Uniform
  778. %_ptr_Function__arr__struct_15_uint_1 = OpTypePointer Function %_arr__struct_15_uint_1
  779. %2 = OpFunction %void None %13
  780. %20 = OpLabel
  781. %21 = OpVariable %_ptr_Function__arr__struct_15_uint_1 Function
  782. %var = OpVariable %_ptr_Function__struct_15 Function
  783. %22 = OpLoad %_struct_9 %3
  784. %23 = OpCompositeExtract %_arr__struct_7_uint_1 %22 0
  785. %24 = OpCompositeExtract %_struct_7 %23 0
  786. %25 = OpCompositeExtract %_struct_6 %24 0
  787. %26 = OpCompositeExtract %uint %25 0
  788. %27 = OpCompositeConstruct %_struct_15 %26
  789. %28 = OpCompositeConstruct %_arr__struct_15_uint_1 %27
  790. OpStore %21 %28
  791. %29 = OpAccessChain %_ptr_Function__struct_15 %21 %uint_0
  792. %30 = OpLoad %_struct_15 %29
  793. OpStore %var %30
  794. OpReturn
  795. OpFunctionEnd
  796. )";
  797. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  798. SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER |
  799. SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES);
  800. SinglePassRunAndMatch<CopyPropagateArrays>(before, false);
  801. }
  802. TEST_F(CopyPropArrayPassTest, BadMergingTwoObjects) {
  803. // The second element in the |OpCompositeConstruct| is from a different
  804. // object.
  805. const std::string text =
  806. R"(OpCapability Shader
  807. OpMemoryModel Logical GLSL450
  808. OpEntryPoint Fragment %main "main"
  809. OpExecutionMode %main OriginUpperLeft
  810. OpName %type_ConstBuf "type.ConstBuf"
  811. OpMemberName %type_ConstBuf 0 "TexSizeU"
  812. OpMemberName %type_ConstBuf 1 "TexSizeV"
  813. OpName %ConstBuf "ConstBuf"
  814. OpName %main "main"
  815. OpMemberDecorate %type_ConstBuf 0 Offset 0
  816. OpMemberDecorate %type_ConstBuf 1 Offset 8
  817. OpDecorate %type_ConstBuf Block
  818. OpDecorate %ConstBuf DescriptorSet 0
  819. OpDecorate %ConstBuf Binding 2
  820. %float = OpTypeFloat 32
  821. %v2float = OpTypeVector %float 2
  822. %type_ConstBuf = OpTypeStruct %v2float %v2float
  823. %_ptr_Uniform_type_ConstBuf = OpTypePointer Uniform %type_ConstBuf
  824. %void = OpTypeVoid
  825. %9 = OpTypeFunction %void
  826. %uint = OpTypeInt 32 0
  827. %int_0 = OpConstant %uint 0
  828. %uint_2 = OpConstant %uint 2
  829. %_arr_v2float_uint_2 = OpTypeArray %v2float %uint_2
  830. %_ptr_Function__arr_v2float_uint_2 = OpTypePointer Function %_arr_v2float_uint_2
  831. %_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
  832. %ConstBuf = OpVariable %_ptr_Uniform_type_ConstBuf Uniform
  833. %main = OpFunction %void None %9
  834. %24 = OpLabel
  835. %25 = OpVariable %_ptr_Function__arr_v2float_uint_2 Function
  836. %27 = OpAccessChain %_ptr_Uniform_v2float %ConstBuf %int_0
  837. %28 = OpLoad %v2float %27
  838. %29 = OpAccessChain %_ptr_Uniform_v2float %ConstBuf %int_0
  839. %30 = OpLoad %v2float %29
  840. %31 = OpFNegate %v2float %30
  841. %37 = OpCompositeConstruct %_arr_v2float_uint_2 %28 %31
  842. OpStore %25 %37
  843. OpReturn
  844. OpFunctionEnd
  845. )";
  846. auto result = SinglePassRunAndDisassemble<CopyPropagateArrays>(
  847. text, /* skip_nop = */ true, /* do_validation = */ false);
  848. EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
  849. }
  850. TEST_F(CopyPropArrayPassTest, SecondElementNotContained) {
  851. // The second element in the |OpCompositeConstruct| is not a memory object.
  852. // Make sure no change happends.
  853. const std::string text =
  854. R"(OpCapability Shader
  855. OpMemoryModel Logical GLSL450
  856. OpEntryPoint Fragment %main "main"
  857. OpExecutionMode %main OriginUpperLeft
  858. OpName %type_ConstBuf "type.ConstBuf"
  859. OpMemberName %type_ConstBuf 0 "TexSizeU"
  860. OpMemberName %type_ConstBuf 1 "TexSizeV"
  861. OpName %ConstBuf "ConstBuf"
  862. OpName %main "main"
  863. OpMemberDecorate %type_ConstBuf 0 Offset 0
  864. OpMemberDecorate %type_ConstBuf 1 Offset 8
  865. OpDecorate %type_ConstBuf Block
  866. OpDecorate %ConstBuf DescriptorSet 0
  867. OpDecorate %ConstBuf Binding 2
  868. OpDecorate %ConstBuf2 DescriptorSet 1
  869. OpDecorate %ConstBuf2 Binding 2
  870. %float = OpTypeFloat 32
  871. %v2float = OpTypeVector %float 2
  872. %type_ConstBuf = OpTypeStruct %v2float %v2float
  873. %_ptr_Uniform_type_ConstBuf = OpTypePointer Uniform %type_ConstBuf
  874. %void = OpTypeVoid
  875. %9 = OpTypeFunction %void
  876. %uint = OpTypeInt 32 0
  877. %int_0 = OpConstant %uint 0
  878. %int_1 = OpConstant %uint 1
  879. %uint_2 = OpConstant %uint 2
  880. %_arr_v2float_uint_2 = OpTypeArray %v2float %uint_2
  881. %_ptr_Function__arr_v2float_uint_2 = OpTypePointer Function %_arr_v2float_uint_2
  882. %_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
  883. %ConstBuf = OpVariable %_ptr_Uniform_type_ConstBuf Uniform
  884. %ConstBuf2 = OpVariable %_ptr_Uniform_type_ConstBuf Uniform
  885. %main = OpFunction %void None %9
  886. %24 = OpLabel
  887. %25 = OpVariable %_ptr_Function__arr_v2float_uint_2 Function
  888. %27 = OpAccessChain %_ptr_Uniform_v2float %ConstBuf %int_0
  889. %28 = OpLoad %v2float %27
  890. %29 = OpAccessChain %_ptr_Uniform_v2float %ConstBuf2 %int_1
  891. %30 = OpLoad %v2float %29
  892. %37 = OpCompositeConstruct %_arr_v2float_uint_2 %28 %30
  893. OpStore %25 %37
  894. OpReturn
  895. OpFunctionEnd
  896. )";
  897. auto result = SinglePassRunAndDisassemble<CopyPropagateArrays>(
  898. text, /* skip_nop = */ true, /* do_validation = */ false);
  899. EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
  900. }
  901. // This test will place a load before the store. We cannot propagate in this
  902. // case.
  903. TEST_F(CopyPropArrayPassTest, LoadBeforeStore) {
  904. const std::string text =
  905. R"(
  906. OpCapability Shader
  907. OpMemoryModel Logical GLSL450
  908. OpEntryPoint Fragment %main "main" %in_var_INDEX %out_var_SV_Target
  909. OpExecutionMode %main OriginUpperLeft
  910. OpSource HLSL 600
  911. OpName %type_MyCBuffer "type.MyCBuffer"
  912. OpMemberName %type_MyCBuffer 0 "Data"
  913. OpName %MyCBuffer "MyCBuffer"
  914. OpName %main "main"
  915. OpName %in_var_INDEX "in.var.INDEX"
  916. OpName %out_var_SV_Target "out.var.SV_Target"
  917. OpDecorate %_arr_v4float_uint_8 ArrayStride 16
  918. OpMemberDecorate %type_MyCBuffer 0 Offset 0
  919. OpDecorate %type_MyCBuffer Block
  920. OpDecorate %in_var_INDEX Flat
  921. OpDecorate %in_var_INDEX Location 0
  922. OpDecorate %out_var_SV_Target Location 0
  923. OpDecorate %MyCBuffer DescriptorSet 0
  924. OpDecorate %MyCBuffer Binding 0
  925. %float = OpTypeFloat 32
  926. %v4float = OpTypeVector %float 4
  927. %uint = OpTypeInt 32 0
  928. %uint_8 = OpConstant %uint 8
  929. %_arr_v4float_uint_8 = OpTypeArray %v4float %uint_8
  930. %type_MyCBuffer = OpTypeStruct %_arr_v4float_uint_8
  931. %_ptr_Uniform_type_MyCBuffer = OpTypePointer Uniform %type_MyCBuffer
  932. %void = OpTypeVoid
  933. %13 = OpTypeFunction %void
  934. %int = OpTypeInt 32 1
  935. %_ptr_Input_int = OpTypePointer Input %int
  936. %_ptr_Output_v4float = OpTypePointer Output %v4float
  937. %_arr_v4float_uint_8_0 = OpTypeArray %v4float %uint_8
  938. %_ptr_Function__arr_v4float_uint_8_0 = OpTypePointer Function %_arr_v4float_uint_8_0
  939. %int_0 = OpConstant %int 0
  940. %_ptr_Uniform__arr_v4float_uint_8 = OpTypePointer Uniform %_arr_v4float_uint_8
  941. %_ptr_Function_v4float = OpTypePointer Function %v4float
  942. %MyCBuffer = OpVariable %_ptr_Uniform_type_MyCBuffer Uniform
  943. %in_var_INDEX = OpVariable %_ptr_Input_int Input
  944. %out_var_SV_Target = OpVariable %_ptr_Output_v4float Output
  945. %main = OpFunction %void None %13
  946. %22 = OpLabel
  947. %23 = OpVariable %_ptr_Function__arr_v4float_uint_8_0 Function
  948. %38 = OpAccessChain %_ptr_Function_v4float %23 %24
  949. %39 = OpLoad %v4float %36
  950. %24 = OpLoad %int %in_var_INDEX
  951. %25 = OpAccessChain %_ptr_Uniform__arr_v4float_uint_8 %MyCBuffer %int_0
  952. %26 = OpLoad %_arr_v4float_uint_8 %25
  953. %27 = OpCompositeExtract %v4float %26 0
  954. %28 = OpCompositeExtract %v4float %26 1
  955. %29 = OpCompositeExtract %v4float %26 2
  956. %30 = OpCompositeExtract %v4float %26 3
  957. %31 = OpCompositeExtract %v4float %26 4
  958. %32 = OpCompositeExtract %v4float %26 5
  959. %33 = OpCompositeExtract %v4float %26 6
  960. %34 = OpCompositeExtract %v4float %26 7
  961. %35 = OpCompositeConstruct %_arr_v4float_uint_8_0 %27 %28 %29 %30 %31 %32 %33 %34
  962. OpStore %23 %35
  963. %36 = OpAccessChain %_ptr_Function_v4float %23 %24
  964. %37 = OpLoad %v4float %36
  965. OpStore %out_var_SV_Target %37
  966. OpReturn
  967. OpFunctionEnd
  968. )";
  969. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  970. SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER |
  971. SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES);
  972. auto result = SinglePassRunAndDisassemble<CopyPropagateArrays>(
  973. text, /* skip_nop = */ true, /* do_validation = */ false);
  974. EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
  975. }
  976. // This test will place a load where it is not dominated by the store. We
  977. // cannot propagate in this case.
  978. TEST_F(CopyPropArrayPassTest, LoadNotDominated) {
  979. const std::string text =
  980. R"(
  981. OpCapability Shader
  982. OpMemoryModel Logical GLSL450
  983. OpEntryPoint Fragment %main "main" %in_var_INDEX %out_var_SV_Target
  984. OpExecutionMode %main OriginUpperLeft
  985. OpSource HLSL 600
  986. OpName %type_MyCBuffer "type.MyCBuffer"
  987. OpMemberName %type_MyCBuffer 0 "Data"
  988. OpName %MyCBuffer "MyCBuffer"
  989. OpName %main "main"
  990. OpName %in_var_INDEX "in.var.INDEX"
  991. OpName %out_var_SV_Target "out.var.SV_Target"
  992. OpDecorate %_arr_v4float_uint_8 ArrayStride 16
  993. OpMemberDecorate %type_MyCBuffer 0 Offset 0
  994. OpDecorate %type_MyCBuffer Block
  995. OpDecorate %in_var_INDEX Flat
  996. OpDecorate %in_var_INDEX Location 0
  997. OpDecorate %out_var_SV_Target Location 0
  998. OpDecorate %MyCBuffer DescriptorSet 0
  999. OpDecorate %MyCBuffer Binding 0
  1000. %bool = OpTypeBool
  1001. %true = OpConstantTrue %bool
  1002. %float = OpTypeFloat 32
  1003. %v4float = OpTypeVector %float 4
  1004. %uint = OpTypeInt 32 0
  1005. %uint_8 = OpConstant %uint 8
  1006. %_arr_v4float_uint_8 = OpTypeArray %v4float %uint_8
  1007. %type_MyCBuffer = OpTypeStruct %_arr_v4float_uint_8
  1008. %_ptr_Uniform_type_MyCBuffer = OpTypePointer Uniform %type_MyCBuffer
  1009. %void = OpTypeVoid
  1010. %13 = OpTypeFunction %void
  1011. %int = OpTypeInt 32 1
  1012. %_ptr_Input_int = OpTypePointer Input %int
  1013. %_ptr_Output_v4float = OpTypePointer Output %v4float
  1014. %_arr_v4float_uint_8_0 = OpTypeArray %v4float %uint_8
  1015. %_ptr_Function__arr_v4float_uint_8_0 = OpTypePointer Function %_arr_v4float_uint_8_0
  1016. %int_0 = OpConstant %int 0
  1017. %_ptr_Uniform__arr_v4float_uint_8 = OpTypePointer Uniform %_arr_v4float_uint_8
  1018. %_ptr_Function_v4float = OpTypePointer Function %v4float
  1019. %MyCBuffer = OpVariable %_ptr_Uniform_type_MyCBuffer Uniform
  1020. %in_var_INDEX = OpVariable %_ptr_Input_int Input
  1021. %out_var_SV_Target = OpVariable %_ptr_Output_v4float Output
  1022. %main = OpFunction %void None %13
  1023. %22 = OpLabel
  1024. %23 = OpVariable %_ptr_Function__arr_v4float_uint_8_0 Function
  1025. OpSelectionMerge %merge None
  1026. OpBranchConditional %true %if %else
  1027. %if = OpLabel
  1028. %24 = OpLoad %int %in_var_INDEX
  1029. %25 = OpAccessChain %_ptr_Uniform__arr_v4float_uint_8 %MyCBuffer %int_0
  1030. %26 = OpLoad %_arr_v4float_uint_8 %25
  1031. %27 = OpCompositeExtract %v4float %26 0
  1032. %28 = OpCompositeExtract %v4float %26 1
  1033. %29 = OpCompositeExtract %v4float %26 2
  1034. %30 = OpCompositeExtract %v4float %26 3
  1035. %31 = OpCompositeExtract %v4float %26 4
  1036. %32 = OpCompositeExtract %v4float %26 5
  1037. %33 = OpCompositeExtract %v4float %26 6
  1038. %34 = OpCompositeExtract %v4float %26 7
  1039. %35 = OpCompositeConstruct %_arr_v4float_uint_8_0 %27 %28 %29 %30 %31 %32 %33 %34
  1040. OpStore %23 %35
  1041. %38 = OpAccessChain %_ptr_Function_v4float %23 %24
  1042. %39 = OpLoad %v4float %36
  1043. OpBranch %merge
  1044. %else = OpLabel
  1045. %36 = OpAccessChain %_ptr_Function_v4float %23 %24
  1046. %37 = OpLoad %v4float %36
  1047. OpBranch %merge
  1048. %merge = OpLabel
  1049. %phi = OpPhi %out_var_SV_Target %39 %if %37 %else
  1050. OpStore %out_var_SV_Target %phi
  1051. OpReturn
  1052. OpFunctionEnd
  1053. )";
  1054. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  1055. SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER |
  1056. SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES);
  1057. auto result = SinglePassRunAndDisassemble<CopyPropagateArrays>(
  1058. text, /* skip_nop = */ true, /* do_validation = */ false);
  1059. EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
  1060. }
  1061. // This test has a partial store to the variable. We cannot propagate in this
  1062. // case.
  1063. TEST_F(CopyPropArrayPassTest, PartialStore) {
  1064. const std::string text =
  1065. R"(
  1066. OpCapability Shader
  1067. OpMemoryModel Logical GLSL450
  1068. OpEntryPoint Fragment %main "main" %in_var_INDEX %out_var_SV_Target
  1069. OpExecutionMode %main OriginUpperLeft
  1070. OpSource HLSL 600
  1071. OpName %type_MyCBuffer "type.MyCBuffer"
  1072. OpMemberName %type_MyCBuffer 0 "Data"
  1073. OpName %MyCBuffer "MyCBuffer"
  1074. OpName %main "main"
  1075. OpName %in_var_INDEX "in.var.INDEX"
  1076. OpName %out_var_SV_Target "out.var.SV_Target"
  1077. OpDecorate %_arr_v4float_uint_8 ArrayStride 16
  1078. OpMemberDecorate %type_MyCBuffer 0 Offset 0
  1079. OpDecorate %type_MyCBuffer Block
  1080. OpDecorate %in_var_INDEX Flat
  1081. OpDecorate %in_var_INDEX Location 0
  1082. OpDecorate %out_var_SV_Target Location 0
  1083. OpDecorate %MyCBuffer DescriptorSet 0
  1084. OpDecorate %MyCBuffer Binding 0
  1085. %float = OpTypeFloat 32
  1086. %v4float = OpTypeVector %float 4
  1087. %uint = OpTypeInt 32 0
  1088. %uint_8 = OpConstant %uint 8
  1089. %_arr_v4float_uint_8 = OpTypeArray %v4float %uint_8
  1090. %type_MyCBuffer = OpTypeStruct %_arr_v4float_uint_8
  1091. %_ptr_Uniform_type_MyCBuffer = OpTypePointer Uniform %type_MyCBuffer
  1092. %void = OpTypeVoid
  1093. %13 = OpTypeFunction %void
  1094. %int = OpTypeInt 32 1
  1095. %_ptr_Input_int = OpTypePointer Input %int
  1096. %_ptr_Output_v4float = OpTypePointer Output %v4float
  1097. %_arr_v4float_uint_8_0 = OpTypeArray %v4float %uint_8
  1098. %_ptr_Function__arr_v4float_uint_8_0 = OpTypePointer Function %_arr_v4float_uint_8_0
  1099. %int_0 = OpConstant %int 0
  1100. %f0 = OpConstant %float 0
  1101. %v4const = OpConstantComposite %v4float %f0 %f0 %f0 %f0
  1102. %_ptr_Uniform__arr_v4float_uint_8 = OpTypePointer Uniform %_arr_v4float_uint_8
  1103. %_ptr_Function_v4float = OpTypePointer Function %v4float
  1104. %MyCBuffer = OpVariable %_ptr_Uniform_type_MyCBuffer Uniform
  1105. %in_var_INDEX = OpVariable %_ptr_Input_int Input
  1106. %out_var_SV_Target = OpVariable %_ptr_Output_v4float Output
  1107. %main = OpFunction %void None %13
  1108. %22 = OpLabel
  1109. %23 = OpVariable %_ptr_Function__arr_v4float_uint_8_0 Function
  1110. %24 = OpLoad %int %in_var_INDEX
  1111. %25 = OpAccessChain %_ptr_Uniform__arr_v4float_uint_8 %MyCBuffer %int_0
  1112. %26 = OpLoad %_arr_v4float_uint_8 %25
  1113. %27 = OpCompositeExtract %v4float %26 0
  1114. %28 = OpCompositeExtract %v4float %26 1
  1115. %29 = OpCompositeExtract %v4float %26 2
  1116. %30 = OpCompositeExtract %v4float %26 3
  1117. %31 = OpCompositeExtract %v4float %26 4
  1118. %32 = OpCompositeExtract %v4float %26 5
  1119. %33 = OpCompositeExtract %v4float %26 6
  1120. %34 = OpCompositeExtract %v4float %26 7
  1121. %35 = OpCompositeConstruct %_arr_v4float_uint_8_0 %27 %28 %29 %30 %31 %32 %33 %34
  1122. OpStore %23 %35
  1123. %36 = OpAccessChain %_ptr_Function_v4float %23 %24
  1124. %37 = OpLoad %v4float %36
  1125. OpStore %36 %v4const
  1126. OpStore %out_var_SV_Target %37
  1127. OpReturn
  1128. OpFunctionEnd
  1129. )";
  1130. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  1131. SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER |
  1132. SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES);
  1133. auto result = SinglePassRunAndDisassemble<CopyPropagateArrays>(
  1134. text, /* skip_nop = */ true, /* do_validation = */ false);
  1135. EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
  1136. }
  1137. // This test does not have a proper copy of an object. We cannot propagate in
  1138. // this case.
  1139. TEST_F(CopyPropArrayPassTest, NotACopy) {
  1140. const std::string text =
  1141. R"(
  1142. OpCapability Shader
  1143. OpMemoryModel Logical GLSL450
  1144. OpEntryPoint Fragment %main "main" %in_var_INDEX %out_var_SV_Target
  1145. OpExecutionMode %main OriginUpperLeft
  1146. OpSource HLSL 600
  1147. OpName %type_MyCBuffer "type.MyCBuffer"
  1148. OpMemberName %type_MyCBuffer 0 "Data"
  1149. OpName %MyCBuffer "MyCBuffer"
  1150. OpName %main "main"
  1151. OpName %in_var_INDEX "in.var.INDEX"
  1152. OpName %out_var_SV_Target "out.var.SV_Target"
  1153. OpDecorate %_arr_v4float_uint_8 ArrayStride 16
  1154. OpMemberDecorate %type_MyCBuffer 0 Offset 0
  1155. OpDecorate %type_MyCBuffer Block
  1156. OpDecorate %in_var_INDEX Flat
  1157. OpDecorate %in_var_INDEX Location 0
  1158. OpDecorate %out_var_SV_Target Location 0
  1159. OpDecorate %MyCBuffer DescriptorSet 0
  1160. OpDecorate %MyCBuffer Binding 0
  1161. %float = OpTypeFloat 32
  1162. %v4float = OpTypeVector %float 4
  1163. %uint = OpTypeInt 32 0
  1164. %uint_8 = OpConstant %uint 8
  1165. %_arr_v4float_uint_8 = OpTypeArray %v4float %uint_8
  1166. %type_MyCBuffer = OpTypeStruct %_arr_v4float_uint_8
  1167. %_ptr_Uniform_type_MyCBuffer = OpTypePointer Uniform %type_MyCBuffer
  1168. %void = OpTypeVoid
  1169. %13 = OpTypeFunction %void
  1170. %int = OpTypeInt 32 1
  1171. %_ptr_Input_int = OpTypePointer Input %int
  1172. %_ptr_Output_v4float = OpTypePointer Output %v4float
  1173. %_arr_v4float_uint_8_0 = OpTypeArray %v4float %uint_8
  1174. %_ptr_Function__arr_v4float_uint_8_0 = OpTypePointer Function %_arr_v4float_uint_8_0
  1175. %int_0 = OpConstant %int 0
  1176. %f0 = OpConstant %float 0
  1177. %v4const = OpConstantComposite %v4float %f0 %f0 %f0 %f0
  1178. %_ptr_Uniform__arr_v4float_uint_8 = OpTypePointer Uniform %_arr_v4float_uint_8
  1179. %_ptr_Function_v4float = OpTypePointer Function %v4float
  1180. %MyCBuffer = OpVariable %_ptr_Uniform_type_MyCBuffer Uniform
  1181. %in_var_INDEX = OpVariable %_ptr_Input_int Input
  1182. %out_var_SV_Target = OpVariable %_ptr_Output_v4float Output
  1183. %main = OpFunction %void None %13
  1184. %22 = OpLabel
  1185. %23 = OpVariable %_ptr_Function__arr_v4float_uint_8_0 Function
  1186. %24 = OpLoad %int %in_var_INDEX
  1187. %25 = OpAccessChain %_ptr_Uniform__arr_v4float_uint_8 %MyCBuffer %int_0
  1188. %26 = OpLoad %_arr_v4float_uint_8 %25
  1189. %27 = OpCompositeExtract %v4float %26 0
  1190. %28 = OpCompositeExtract %v4float %26 0
  1191. %29 = OpCompositeExtract %v4float %26 2
  1192. %30 = OpCompositeExtract %v4float %26 3
  1193. %31 = OpCompositeExtract %v4float %26 4
  1194. %32 = OpCompositeExtract %v4float %26 5
  1195. %33 = OpCompositeExtract %v4float %26 6
  1196. %34 = OpCompositeExtract %v4float %26 7
  1197. %35 = OpCompositeConstruct %_arr_v4float_uint_8_0 %27 %28 %29 %30 %31 %32 %33 %34
  1198. OpStore %23 %35
  1199. %36 = OpAccessChain %_ptr_Function_v4float %23 %24
  1200. %37 = OpLoad %v4float %36
  1201. OpStore %out_var_SV_Target %37
  1202. OpReturn
  1203. OpFunctionEnd
  1204. )";
  1205. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  1206. SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER |
  1207. SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES);
  1208. auto result = SinglePassRunAndDisassemble<CopyPropagateArrays>(
  1209. text, /* skip_nop = */ true, /* do_validation = */ false);
  1210. EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
  1211. }
  1212. TEST_F(CopyPropArrayPassTest, BadCopyViaInserts1) {
  1213. const std::string text =
  1214. R"(
  1215. OpCapability Shader
  1216. OpMemoryModel Logical GLSL450
  1217. OpEntryPoint Fragment %main "main" %in_var_INDEX %out_var_SV_Target
  1218. OpExecutionMode %main OriginUpperLeft
  1219. OpSource HLSL 600
  1220. OpName %type_MyCBuffer "type.MyCBuffer"
  1221. OpMemberName %type_MyCBuffer 0 "Data"
  1222. OpName %MyCBuffer "MyCBuffer"
  1223. OpName %main "main"
  1224. OpName %in_var_INDEX "in.var.INDEX"
  1225. OpName %out_var_SV_Target "out.var.SV_Target"
  1226. OpDecorate %_arr_v4float_uint_8 ArrayStride 16
  1227. OpMemberDecorate %type_MyCBuffer 0 Offset 0
  1228. OpDecorate %type_MyCBuffer Block
  1229. OpDecorate %in_var_INDEX Flat
  1230. OpDecorate %in_var_INDEX Location 0
  1231. OpDecorate %out_var_SV_Target Location 0
  1232. OpDecorate %MyCBuffer DescriptorSet 0
  1233. OpDecorate %MyCBuffer Binding 0
  1234. %float = OpTypeFloat 32
  1235. %v4float = OpTypeVector %float 4
  1236. %uint = OpTypeInt 32 0
  1237. %uint_8 = OpConstant %uint 8
  1238. %_arr_v4float_uint_8 = OpTypeArray %v4float %uint_8
  1239. %type_MyCBuffer = OpTypeStruct %_arr_v4float_uint_8
  1240. %_ptr_Uniform_type_MyCBuffer = OpTypePointer Uniform %type_MyCBuffer
  1241. %void = OpTypeVoid
  1242. %13 = OpTypeFunction %void
  1243. %int = OpTypeInt 32 1
  1244. %_ptr_Input_int = OpTypePointer Input %int
  1245. %_ptr_Output_v4float = OpTypePointer Output %v4float
  1246. %_arr_v4float_uint_8_0 = OpTypeArray %v4float %uint_8
  1247. %_ptr_Function__arr_v4float_uint_8_0 = OpTypePointer Function %_arr_v4float_uint_8_0
  1248. %int_0 = OpConstant %int 0
  1249. %_ptr_Uniform__arr_v4float_uint_8 = OpTypePointer Uniform %_arr_v4float_uint_8
  1250. %_ptr_Function_v4float = OpTypePointer Function %v4float
  1251. %MyCBuffer = OpVariable %_ptr_Uniform_type_MyCBuffer Uniform
  1252. %in_var_INDEX = OpVariable %_ptr_Input_int Input
  1253. %out_var_SV_Target = OpVariable %_ptr_Output_v4float Output
  1254. %main = OpFunction %void None %13
  1255. %22 = OpLabel
  1256. %23 = OpVariable %_ptr_Function__arr_v4float_uint_8_0 Function
  1257. %undef = OpUndef %_arr_v4float_uint_8_0
  1258. %24 = OpLoad %int %in_var_INDEX
  1259. %25 = OpAccessChain %_ptr_Uniform__arr_v4float_uint_8 %MyCBuffer %int_0
  1260. %26 = OpLoad %_arr_v4float_uint_8 %25
  1261. %27 = OpCompositeExtract %v4float %26 0
  1262. %i0 = OpCompositeInsert %_arr_v4float_uint_8_0 %27 %undef 0
  1263. %28 = OpCompositeExtract %v4float %26 1
  1264. %i1 = OpCompositeInsert %_arr_v4float_uint_8_0 %28 %i0 1
  1265. %29 = OpCompositeExtract %v4float %26 2
  1266. %i2 = OpCompositeInsert %_arr_v4float_uint_8_0 %29 %i1 3
  1267. %30 = OpCompositeExtract %v4float %26 3
  1268. %i3 = OpCompositeInsert %_arr_v4float_uint_8_0 %30 %i2 3
  1269. %31 = OpCompositeExtract %v4float %26 4
  1270. %i4 = OpCompositeInsert %_arr_v4float_uint_8_0 %31 %i3 4
  1271. %32 = OpCompositeExtract %v4float %26 5
  1272. %i5 = OpCompositeInsert %_arr_v4float_uint_8_0 %32 %i4 5
  1273. %33 = OpCompositeExtract %v4float %26 6
  1274. %i6 = OpCompositeInsert %_arr_v4float_uint_8_0 %33 %i5 6
  1275. %34 = OpCompositeExtract %v4float %26 7
  1276. %i7 = OpCompositeInsert %_arr_v4float_uint_8_0 %34 %i6 7
  1277. OpStore %23 %i7
  1278. %36 = OpAccessChain %_ptr_Function_v4float %23 %24
  1279. %37 = OpLoad %v4float %36
  1280. OpStore %out_var_SV_Target %37
  1281. OpReturn
  1282. OpFunctionEnd
  1283. )";
  1284. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  1285. SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER |
  1286. SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES);
  1287. auto result = SinglePassRunAndDisassemble<CopyPropagateArrays>(
  1288. text, /* skip_nop = */ true, /* do_validation = */ false);
  1289. EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
  1290. }
  1291. TEST_F(CopyPropArrayPassTest, BadCopyViaInserts2) {
  1292. const std::string text =
  1293. R"(
  1294. OpCapability Shader
  1295. OpMemoryModel Logical GLSL450
  1296. OpEntryPoint Fragment %main "main" %in_var_INDEX %out_var_SV_Target
  1297. OpExecutionMode %main OriginUpperLeft
  1298. OpSource HLSL 600
  1299. OpName %type_MyCBuffer "type.MyCBuffer"
  1300. OpMemberName %type_MyCBuffer 0 "Data"
  1301. OpName %MyCBuffer "MyCBuffer"
  1302. OpName %main "main"
  1303. OpName %in_var_INDEX "in.var.INDEX"
  1304. OpName %out_var_SV_Target "out.var.SV_Target"
  1305. OpDecorate %_arr_v4float_uint_8 ArrayStride 16
  1306. OpMemberDecorate %type_MyCBuffer 0 Offset 0
  1307. OpDecorate %type_MyCBuffer Block
  1308. OpDecorate %in_var_INDEX Flat
  1309. OpDecorate %in_var_INDEX Location 0
  1310. OpDecorate %out_var_SV_Target Location 0
  1311. OpDecorate %MyCBuffer DescriptorSet 0
  1312. OpDecorate %MyCBuffer Binding 0
  1313. %float = OpTypeFloat 32
  1314. %v4float = OpTypeVector %float 4
  1315. %uint = OpTypeInt 32 0
  1316. %uint_8 = OpConstant %uint 8
  1317. %_arr_v4float_uint_8 = OpTypeArray %v4float %uint_8
  1318. %type_MyCBuffer = OpTypeStruct %_arr_v4float_uint_8
  1319. %_ptr_Uniform_type_MyCBuffer = OpTypePointer Uniform %type_MyCBuffer
  1320. %void = OpTypeVoid
  1321. %13 = OpTypeFunction %void
  1322. %int = OpTypeInt 32 1
  1323. %_ptr_Input_int = OpTypePointer Input %int
  1324. %_ptr_Output_v4float = OpTypePointer Output %v4float
  1325. %_arr_v4float_uint_8_0 = OpTypeArray %v4float %uint_8
  1326. %_ptr_Function__arr_v4float_uint_8_0 = OpTypePointer Function %_arr_v4float_uint_8_0
  1327. %int_0 = OpConstant %int 0
  1328. %_ptr_Uniform__arr_v4float_uint_8 = OpTypePointer Uniform %_arr_v4float_uint_8
  1329. %_ptr_Function_v4float = OpTypePointer Function %v4float
  1330. %MyCBuffer = OpVariable %_ptr_Uniform_type_MyCBuffer Uniform
  1331. %in_var_INDEX = OpVariable %_ptr_Input_int Input
  1332. %out_var_SV_Target = OpVariable %_ptr_Output_v4float Output
  1333. %main = OpFunction %void None %13
  1334. %22 = OpLabel
  1335. %23 = OpVariable %_ptr_Function__arr_v4float_uint_8_0 Function
  1336. %undef = OpUndef %_arr_v4float_uint_8_0
  1337. %24 = OpLoad %int %in_var_INDEX
  1338. %25 = OpAccessChain %_ptr_Uniform__arr_v4float_uint_8 %MyCBuffer %int_0
  1339. %26 = OpLoad %_arr_v4float_uint_8 %25
  1340. %27 = OpCompositeExtract %v4float %26 0
  1341. %i0 = OpCompositeInsert %_arr_v4float_uint_8_0 %27 %undef 0
  1342. %28 = OpCompositeExtract %v4float %26 1
  1343. %i1 = OpCompositeInsert %_arr_v4float_uint_8_0 %28 %i0 1
  1344. %29 = OpCompositeExtract %v4float %26 3
  1345. %i2 = OpCompositeInsert %_arr_v4float_uint_8_0 %29 %i1 2
  1346. %30 = OpCompositeExtract %v4float %26 3
  1347. %i3 = OpCompositeInsert %_arr_v4float_uint_8_0 %30 %i2 3
  1348. %31 = OpCompositeExtract %v4float %26 4
  1349. %i4 = OpCompositeInsert %_arr_v4float_uint_8_0 %31 %i3 4
  1350. %32 = OpCompositeExtract %v4float %26 5
  1351. %i5 = OpCompositeInsert %_arr_v4float_uint_8_0 %32 %i4 5
  1352. %33 = OpCompositeExtract %v4float %26 6
  1353. %i6 = OpCompositeInsert %_arr_v4float_uint_8_0 %33 %i5 6
  1354. %34 = OpCompositeExtract %v4float %26 7
  1355. %i7 = OpCompositeInsert %_arr_v4float_uint_8_0 %34 %i6 7
  1356. OpStore %23 %i7
  1357. %36 = OpAccessChain %_ptr_Function_v4float %23 %24
  1358. %37 = OpLoad %v4float %36
  1359. OpStore %out_var_SV_Target %37
  1360. OpReturn
  1361. OpFunctionEnd
  1362. )";
  1363. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  1364. SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER |
  1365. SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES);
  1366. auto result = SinglePassRunAndDisassemble<CopyPropagateArrays>(
  1367. text, /* skip_nop = */ true, /* do_validation = */ false);
  1368. EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
  1369. }
  1370. TEST_F(CopyPropArrayPassTest, BadCopyViaInserts3) {
  1371. const std::string text =
  1372. R"(
  1373. OpCapability Shader
  1374. OpMemoryModel Logical GLSL450
  1375. OpEntryPoint Fragment %main "main" %in_var_INDEX %out_var_SV_Target
  1376. OpExecutionMode %main OriginUpperLeft
  1377. OpSource HLSL 600
  1378. OpName %type_MyCBuffer "type.MyCBuffer"
  1379. OpMemberName %type_MyCBuffer 0 "Data"
  1380. OpName %MyCBuffer "MyCBuffer"
  1381. OpName %main "main"
  1382. OpName %in_var_INDEX "in.var.INDEX"
  1383. OpName %out_var_SV_Target "out.var.SV_Target"
  1384. OpDecorate %_arr_v4float_uint_8 ArrayStride 16
  1385. OpMemberDecorate %type_MyCBuffer 0 Offset 0
  1386. OpDecorate %type_MyCBuffer Block
  1387. OpDecorate %in_var_INDEX Flat
  1388. OpDecorate %in_var_INDEX Location 0
  1389. OpDecorate %out_var_SV_Target Location 0
  1390. OpDecorate %MyCBuffer DescriptorSet 0
  1391. OpDecorate %MyCBuffer Binding 0
  1392. %float = OpTypeFloat 32
  1393. %v4float = OpTypeVector %float 4
  1394. %uint = OpTypeInt 32 0
  1395. %uint_8 = OpConstant %uint 8
  1396. %_arr_v4float_uint_8 = OpTypeArray %v4float %uint_8
  1397. %type_MyCBuffer = OpTypeStruct %_arr_v4float_uint_8
  1398. %_ptr_Uniform_type_MyCBuffer = OpTypePointer Uniform %type_MyCBuffer
  1399. %void = OpTypeVoid
  1400. %13 = OpTypeFunction %void
  1401. %int = OpTypeInt 32 1
  1402. %_ptr_Input_int = OpTypePointer Input %int
  1403. %_ptr_Output_v4float = OpTypePointer Output %v4float
  1404. %_arr_v4float_uint_8_0 = OpTypeArray %v4float %uint_8
  1405. %_ptr_Function__arr_v4float_uint_8_0 = OpTypePointer Function %_arr_v4float_uint_8_0
  1406. %int_0 = OpConstant %int 0
  1407. %_ptr_Uniform__arr_v4float_uint_8 = OpTypePointer Uniform %_arr_v4float_uint_8
  1408. %_ptr_Function_v4float = OpTypePointer Function %v4float
  1409. %MyCBuffer = OpVariable %_ptr_Uniform_type_MyCBuffer Uniform
  1410. %in_var_INDEX = OpVariable %_ptr_Input_int Input
  1411. %out_var_SV_Target = OpVariable %_ptr_Output_v4float Output
  1412. %main = OpFunction %void None %13
  1413. %22 = OpLabel
  1414. %23 = OpVariable %_ptr_Function__arr_v4float_uint_8_0 Function
  1415. %undef = OpUndef %_arr_v4float_uint_8_0
  1416. %24 = OpLoad %int %in_var_INDEX
  1417. %25 = OpAccessChain %_ptr_Uniform__arr_v4float_uint_8 %MyCBuffer %int_0
  1418. %26 = OpLoad %_arr_v4float_uint_8 %25
  1419. %28 = OpCompositeExtract %v4float %26 1
  1420. %i1 = OpCompositeInsert %_arr_v4float_uint_8_0 %28 %undef 1
  1421. %29 = OpCompositeExtract %v4float %26 2
  1422. %i2 = OpCompositeInsert %_arr_v4float_uint_8_0 %29 %i1 2
  1423. %30 = OpCompositeExtract %v4float %26 3
  1424. %i3 = OpCompositeInsert %_arr_v4float_uint_8_0 %30 %i2 3
  1425. %31 = OpCompositeExtract %v4float %26 4
  1426. %i4 = OpCompositeInsert %_arr_v4float_uint_8_0 %31 %i3 4
  1427. %32 = OpCompositeExtract %v4float %26 5
  1428. %i5 = OpCompositeInsert %_arr_v4float_uint_8_0 %32 %i4 5
  1429. %33 = OpCompositeExtract %v4float %26 6
  1430. %i6 = OpCompositeInsert %_arr_v4float_uint_8_0 %33 %i5 6
  1431. %34 = OpCompositeExtract %v4float %26 7
  1432. %i7 = OpCompositeInsert %_arr_v4float_uint_8_0 %34 %i6 7
  1433. OpStore %23 %i7
  1434. %36 = OpAccessChain %_ptr_Function_v4float %23 %24
  1435. %37 = OpLoad %v4float %36
  1436. OpStore %out_var_SV_Target %37
  1437. OpReturn
  1438. OpFunctionEnd
  1439. )";
  1440. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  1441. SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER |
  1442. SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES);
  1443. auto result = SinglePassRunAndDisassemble<CopyPropagateArrays>(
  1444. text, /* skip_nop = */ true, /* do_validation = */ false);
  1445. EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
  1446. }
  1447. TEST_F(CopyPropArrayPassTest, AtomicAdd) {
  1448. const std::string before = R"(OpCapability SampledBuffer
  1449. OpCapability StorageImageExtendedFormats
  1450. OpCapability ImageBuffer
  1451. OpCapability Shader
  1452. %1 = OpExtInstImport "GLSL.std.450"
  1453. OpMemoryModel Logical GLSL450
  1454. OpEntryPoint GLCompute %2 "min" %gl_GlobalInvocationID
  1455. OpExecutionMode %2 LocalSize 64 1 1
  1456. OpSource HLSL 600
  1457. OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId
  1458. OpDecorate %4 DescriptorSet 4
  1459. OpDecorate %4 Binding 70
  1460. %uint = OpTypeInt 32 0
  1461. %6 = OpTypeImage %uint Buffer 0 0 0 2 R32ui
  1462. %_ptr_UniformConstant_6 = OpTypePointer UniformConstant %6
  1463. %_ptr_Function_6 = OpTypePointer Function %6
  1464. %void = OpTypeVoid
  1465. %10 = OpTypeFunction %void
  1466. %uint_0 = OpConstant %uint 0
  1467. %uint_1 = OpConstant %uint 1
  1468. %v3uint = OpTypeVector %uint 3
  1469. %_ptr_Input_v3uint = OpTypePointer Input %v3uint
  1470. %_ptr_Image_uint = OpTypePointer Image %uint
  1471. %4 = OpVariable %_ptr_UniformConstant_6 UniformConstant
  1472. %gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input
  1473. %2 = OpFunction %void None %10
  1474. %17 = OpLabel
  1475. %16 = OpVariable %_ptr_Function_6 Function
  1476. %18 = OpLoad %6 %4
  1477. OpStore %16 %18
  1478. %19 = OpImageTexelPointer %_ptr_Image_uint %16 %uint_0 %uint_0
  1479. %20 = OpAtomicIAdd %uint %19 %uint_1 %uint_0 %uint_1
  1480. OpReturn
  1481. OpFunctionEnd
  1482. )";
  1483. const std::string after = R"(OpCapability SampledBuffer
  1484. OpCapability StorageImageExtendedFormats
  1485. OpCapability ImageBuffer
  1486. OpCapability Shader
  1487. %1 = OpExtInstImport "GLSL.std.450"
  1488. OpMemoryModel Logical GLSL450
  1489. OpEntryPoint GLCompute %2 "min" %gl_GlobalInvocationID
  1490. OpExecutionMode %2 LocalSize 64 1 1
  1491. OpSource HLSL 600
  1492. OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId
  1493. OpDecorate %4 DescriptorSet 4
  1494. OpDecorate %4 Binding 70
  1495. %uint = OpTypeInt 32 0
  1496. %6 = OpTypeImage %uint Buffer 0 0 0 2 R32ui
  1497. %_ptr_UniformConstant_6 = OpTypePointer UniformConstant %6
  1498. %_ptr_Function_6 = OpTypePointer Function %6
  1499. %void = OpTypeVoid
  1500. %10 = OpTypeFunction %void
  1501. %uint_0 = OpConstant %uint 0
  1502. %uint_1 = OpConstant %uint 1
  1503. %v3uint = OpTypeVector %uint 3
  1504. %_ptr_Input_v3uint = OpTypePointer Input %v3uint
  1505. %_ptr_Image_uint = OpTypePointer Image %uint
  1506. %4 = OpVariable %_ptr_UniformConstant_6 UniformConstant
  1507. %gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input
  1508. %2 = OpFunction %void None %10
  1509. %17 = OpLabel
  1510. %16 = OpVariable %_ptr_Function_6 Function
  1511. %18 = OpLoad %6 %4
  1512. OpStore %16 %18
  1513. %19 = OpImageTexelPointer %_ptr_Image_uint %4 %uint_0 %uint_0
  1514. %20 = OpAtomicIAdd %uint %19 %uint_1 %uint_0 %uint_1
  1515. OpReturn
  1516. OpFunctionEnd
  1517. )";
  1518. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  1519. SinglePassRunAndCheck<CopyPropagateArrays>(before, after, true, true);
  1520. }
  1521. TEST_F(CopyPropArrayPassTest, IndexIsNullConstnat) {
  1522. const std::string text = R"(
  1523. ; CHECK: [[var:%\w+]] = OpVariable {{%\w+}} Uniform
  1524. ; CHECK: [[null:%\w+]] = OpConstantNull %uint
  1525. ; CHECK: [[ac1:%\w+]] = OpAccessChain %_ptr_Uniform__arr_uint_uint_1 [[var]] %uint_0 %uint_0
  1526. ; CHECK: OpAccessChain %_ptr_Uniform_uint [[ac1]] [[null]]
  1527. ; CHECK-NEXT: OpReturn
  1528. OpCapability Shader
  1529. OpMemoryModel Logical GLSL450
  1530. OpEntryPoint Fragment %main "main"
  1531. OpExecutionMode %main OriginUpperLeft
  1532. OpSource HLSL 600
  1533. OpDecorate %myCBuffer DescriptorSet 0
  1534. OpDecorate %myCBuffer Binding 0
  1535. OpDecorate %_arr_v4float_uint_1 ArrayStride 16
  1536. OpMemberDecorate %MyConstantBuffer 0 Offset 0
  1537. OpMemberDecorate %type_myCBuffer 0 Offset 0
  1538. OpDecorate %type_myCBuffer Block
  1539. %uint = OpTypeInt 32 0
  1540. %int_0 = OpConstant %uint 0
  1541. %uint_1 = OpConstant %uint 1
  1542. %_arr_v4float_uint_1 = OpTypeArray %uint %uint_1
  1543. %MyConstantBuffer = OpTypeStruct %_arr_v4float_uint_1
  1544. %type_myCBuffer = OpTypeStruct %MyConstantBuffer
  1545. %_ptr_Uniform_type_myCBuffer = OpTypePointer Uniform %type_myCBuffer
  1546. %_arr_v4float_uint_1_0 = OpTypeArray %uint %uint_1
  1547. %void = OpTypeVoid
  1548. %19 = OpTypeFunction %void
  1549. %_ptr_Function_v4float = OpTypePointer Function %uint
  1550. %_ptr_Uniform_MyConstantBuffer = OpTypePointer Uniform %MyConstantBuffer
  1551. %myCBuffer = OpVariable %_ptr_Uniform_type_myCBuffer Uniform
  1552. %_ptr_Function__arr_v4float_uint_1_0 = OpTypePointer Function %_arr_v4float_uint_1_0
  1553. %23 = OpConstantNull %uint
  1554. %main = OpFunction %void None %19
  1555. %24 = OpLabel
  1556. %25 = OpVariable %_ptr_Function__arr_v4float_uint_1_0 Function
  1557. %26 = OpAccessChain %_ptr_Uniform_MyConstantBuffer %myCBuffer %int_0
  1558. %27 = OpLoad %MyConstantBuffer %26
  1559. %28 = OpCompositeExtract %_arr_v4float_uint_1 %27 0
  1560. %29 = OpCompositeExtract %uint %28 0
  1561. %30 = OpCompositeConstruct %_arr_v4float_uint_1_0 %29
  1562. OpStore %25 %30
  1563. %31 = OpAccessChain %_ptr_Function_v4float %25 %23
  1564. OpReturn
  1565. OpFunctionEnd
  1566. )";
  1567. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  1568. SinglePassRunAndMatch<CopyPropagateArrays>(text, true);
  1569. }
  1570. TEST_F(CopyPropArrayPassTest, DebugDeclare) {
  1571. const std::string before =
  1572. R"(OpCapability Shader
  1573. %ext = OpExtInstImport "OpenCL.DebugInfo.100"
  1574. OpMemoryModel Logical GLSL450
  1575. OpEntryPoint Fragment %main "main" %in_var_INDEX %out_var_SV_Target
  1576. OpExecutionMode %main OriginUpperLeft
  1577. OpSource HLSL 600
  1578. %file_name = OpString "test"
  1579. %float_name = OpString "float"
  1580. %main_name = OpString "main"
  1581. %f_name = OpString "f"
  1582. OpName %type_MyCBuffer "type.MyCBuffer"
  1583. OpMemberName %type_MyCBuffer 0 "Data"
  1584. OpName %MyCBuffer "MyCBuffer"
  1585. OpName %main "main"
  1586. OpName %in_var_INDEX "in.var.INDEX"
  1587. OpName %out_var_SV_Target "out.var.SV_Target"
  1588. OpDecorate %_arr_v4float_uint_8 ArrayStride 16
  1589. OpMemberDecorate %type_MyCBuffer 0 Offset 0
  1590. OpDecorate %type_MyCBuffer Block
  1591. OpDecorate %in_var_INDEX Flat
  1592. OpDecorate %in_var_INDEX Location 0
  1593. OpDecorate %out_var_SV_Target Location 0
  1594. OpDecorate %MyCBuffer DescriptorSet 0
  1595. OpDecorate %MyCBuffer Binding 0
  1596. %float = OpTypeFloat 32
  1597. %v4float = OpTypeVector %float 4
  1598. %uint = OpTypeInt 32 0
  1599. %uint_8 = OpConstant %uint 8
  1600. %uint_32 = OpConstant %uint 32
  1601. %_arr_v4float_uint_8 = OpTypeArray %v4float %uint_8
  1602. %type_MyCBuffer = OpTypeStruct %_arr_v4float_uint_8
  1603. %_ptr_Uniform_type_MyCBuffer = OpTypePointer Uniform %type_MyCBuffer
  1604. %void = OpTypeVoid
  1605. %13 = OpTypeFunction %void
  1606. %int = OpTypeInt 32 1
  1607. %_ptr_Input_int = OpTypePointer Input %int
  1608. %_ptr_Output_v4float = OpTypePointer Output %v4float
  1609. %_arr_v4float_uint_8_0 = OpTypeArray %v4float %uint_8
  1610. %_ptr_Function__arr_v4float_uint_8_0 = OpTypePointer Function %_arr_v4float_uint_8_0
  1611. %int_0 = OpConstant %int 0
  1612. %_ptr_Uniform__arr_v4float_uint_8 = OpTypePointer Uniform %_arr_v4float_uint_8
  1613. %_ptr_Function_v4float = OpTypePointer Function %v4float
  1614. %MyCBuffer = OpVariable %_ptr_Uniform_type_MyCBuffer Uniform
  1615. %in_var_INDEX = OpVariable %_ptr_Input_int Input
  1616. %out_var_SV_Target = OpVariable %_ptr_Output_v4float Output
  1617. %null_expr = OpExtInst %void %ext DebugExpression
  1618. %src = OpExtInst %void %ext DebugSource %file_name
  1619. %cu = OpExtInst %void %ext DebugCompilationUnit 1 4 %src HLSL
  1620. %dbg_tf = OpExtInst %void %ext DebugTypeBasic %float_name %uint_32 Float
  1621. %main_ty = OpExtInst %void %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %dbg_tf
  1622. %dbg_main = OpExtInst %void %ext DebugFunction %main_name %main_ty %src 0 0 %cu %main_name FlagIsProtected|FlagIsPrivate 10 %main
  1623. ; CHECK: [[deref:%\w+]] = OpExtInst %void [[ext:%\w+]] DebugOperation Deref
  1624. ; CHECK: [[dbg_f:%\w+]] = OpExtInst %void [[ext]] DebugLocalVariable
  1625. %dbg_f = OpExtInst %void %ext DebugLocalVariable %f_name %dbg_tf %src 0 0 %dbg_main FlagIsLocal
  1626. ; CHECK: [[deref_expr:%\w+]] = OpExtInst %void [[ext]] DebugExpression [[deref]]
  1627. ; CHECK: OpAccessChain
  1628. ; CHECK: [[newptr:%\w+]] = OpAccessChain %_ptr_Uniform__arr_v4float_uint_8 %MyCBuffer %int_0
  1629. ; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_f]] [[newptr]] [[deref_expr]]
  1630. ; CHECK: [[element_ptr:%\w+]] = OpAccessChain %_ptr_Uniform_v4float [[newptr]] %24
  1631. ; CHECK: [[load:%\w+]] = OpLoad %v4float [[element_ptr]]
  1632. ; CHECK: OpStore %out_var_SV_Target [[load]]
  1633. %main = OpFunction %void None %13
  1634. %22 = OpLabel
  1635. %23 = OpVariable %_ptr_Function__arr_v4float_uint_8_0 Function
  1636. %24 = OpLoad %int %in_var_INDEX
  1637. %25 = OpAccessChain %_ptr_Uniform__arr_v4float_uint_8 %MyCBuffer %int_0
  1638. %26 = OpLoad %_arr_v4float_uint_8 %25
  1639. %27 = OpCompositeExtract %v4float %26 0
  1640. %28 = OpCompositeExtract %v4float %26 1
  1641. %29 = OpCompositeExtract %v4float %26 2
  1642. %30 = OpCompositeExtract %v4float %26 3
  1643. %31 = OpCompositeExtract %v4float %26 4
  1644. %32 = OpCompositeExtract %v4float %26 5
  1645. %33 = OpCompositeExtract %v4float %26 6
  1646. %34 = OpCompositeExtract %v4float %26 7
  1647. %35 = OpCompositeConstruct %_arr_v4float_uint_8_0 %27 %28 %29 %30 %31 %32 %33 %34
  1648. OpStore %23 %35
  1649. %decl = OpExtInst %void %ext DebugDeclare %dbg_f %23 %null_expr
  1650. %36 = OpAccessChain %_ptr_Function_v4float %23 %24
  1651. %37 = OpLoad %v4float %36
  1652. OpStore %out_var_SV_Target %37
  1653. OpReturn
  1654. OpFunctionEnd
  1655. )";
  1656. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  1657. SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER |
  1658. SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES);
  1659. SinglePassRunAndMatch<CopyPropagateArrays>(before, false);
  1660. }
  1661. TEST_F(CopyPropArrayPassTest, DebugValue) {
  1662. const std::string before =
  1663. R"(OpCapability Shader
  1664. %ext = OpExtInstImport "OpenCL.DebugInfo.100"
  1665. OpMemoryModel Logical GLSL450
  1666. OpEntryPoint Fragment %main "main" %in_var_INDEX %out_var_SV_Target
  1667. OpExecutionMode %main OriginUpperLeft
  1668. OpSource HLSL 600
  1669. %file_name = OpString "test"
  1670. %float_name = OpString "float"
  1671. %main_name = OpString "main"
  1672. %f_name = OpString "f"
  1673. OpName %type_MyCBuffer "type.MyCBuffer"
  1674. OpMemberName %type_MyCBuffer 0 "Data"
  1675. OpName %MyCBuffer "MyCBuffer"
  1676. OpName %main "main"
  1677. OpName %in_var_INDEX "in.var.INDEX"
  1678. OpName %out_var_SV_Target "out.var.SV_Target"
  1679. OpDecorate %_arr_v4float_uint_8 ArrayStride 16
  1680. OpMemberDecorate %type_MyCBuffer 0 Offset 0
  1681. OpDecorate %type_MyCBuffer Block
  1682. OpDecorate %in_var_INDEX Flat
  1683. OpDecorate %in_var_INDEX Location 0
  1684. OpDecorate %out_var_SV_Target Location 0
  1685. OpDecorate %MyCBuffer DescriptorSet 0
  1686. OpDecorate %MyCBuffer Binding 0
  1687. %float = OpTypeFloat 32
  1688. %v4float = OpTypeVector %float 4
  1689. %uint = OpTypeInt 32 0
  1690. %uint_8 = OpConstant %uint 8
  1691. %uint_32 = OpConstant %uint 32
  1692. %_arr_v4float_uint_8 = OpTypeArray %v4float %uint_8
  1693. %type_MyCBuffer = OpTypeStruct %_arr_v4float_uint_8
  1694. %_ptr_Uniform_type_MyCBuffer = OpTypePointer Uniform %type_MyCBuffer
  1695. %void = OpTypeVoid
  1696. %13 = OpTypeFunction %void
  1697. %int = OpTypeInt 32 1
  1698. %_ptr_Input_int = OpTypePointer Input %int
  1699. %_ptr_Output_v4float = OpTypePointer Output %v4float
  1700. %_arr_v4float_uint_8_0 = OpTypeArray %v4float %uint_8
  1701. %_ptr_Function__arr_v4float_uint_8_0 = OpTypePointer Function %_arr_v4float_uint_8_0
  1702. %int_0 = OpConstant %int 0
  1703. %_ptr_Uniform__arr_v4float_uint_8 = OpTypePointer Uniform %_arr_v4float_uint_8
  1704. %_ptr_Function_v4float = OpTypePointer Function %v4float
  1705. %MyCBuffer = OpVariable %_ptr_Uniform_type_MyCBuffer Uniform
  1706. %in_var_INDEX = OpVariable %_ptr_Input_int Input
  1707. %out_var_SV_Target = OpVariable %_ptr_Output_v4float Output
  1708. ; CHECK: [[deref:%\w+]] = OpExtInst %void [[ext:%\w+]] DebugOperation Deref
  1709. ; CHECK: [[deref_expr:%\w+]] = OpExtInst %void [[ext]] DebugExpression [[deref]]
  1710. %deref = OpExtInst %void %ext DebugOperation Deref
  1711. %expr = OpExtInst %void %ext DebugExpression %deref
  1712. %src = OpExtInst %void %ext DebugSource %file_name
  1713. %cu = OpExtInst %void %ext DebugCompilationUnit 1 4 %src HLSL
  1714. %dbg_tf = OpExtInst %void %ext DebugTypeBasic %float_name %uint_32 Float
  1715. %main_ty = OpExtInst %void %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %dbg_tf
  1716. %dbg_main = OpExtInst %void %ext DebugFunction %main_name %main_ty %src 0 0 %cu %main_name FlagIsProtected|FlagIsPrivate 10 %main
  1717. ; CHECK: [[dbg_f:%\w+]] = OpExtInst %void [[ext]] DebugLocalVariable
  1718. %dbg_f = OpExtInst %void %ext DebugLocalVariable %f_name %dbg_tf %src 0 0 %dbg_main FlagIsLocal
  1719. %main = OpFunction %void None %13
  1720. %22 = OpLabel
  1721. %23 = OpVariable %_ptr_Function__arr_v4float_uint_8_0 Function
  1722. %24 = OpLoad %int %in_var_INDEX
  1723. %25 = OpAccessChain %_ptr_Uniform__arr_v4float_uint_8 %MyCBuffer %int_0
  1724. %26 = OpLoad %_arr_v4float_uint_8 %25
  1725. %27 = OpCompositeExtract %v4float %26 0
  1726. %28 = OpCompositeExtract %v4float %26 1
  1727. %29 = OpCompositeExtract %v4float %26 2
  1728. %30 = OpCompositeExtract %v4float %26 3
  1729. %31 = OpCompositeExtract %v4float %26 4
  1730. %32 = OpCompositeExtract %v4float %26 5
  1731. %33 = OpCompositeExtract %v4float %26 6
  1732. %34 = OpCompositeExtract %v4float %26 7
  1733. %35 = OpCompositeConstruct %_arr_v4float_uint_8_0 %27 %28 %29 %30 %31 %32 %33 %34
  1734. OpStore %23 %35
  1735. ; CHECK: OpAccessChain
  1736. ; CHECK: [[newptr:%\w+]] = OpAccessChain %_ptr_Uniform__arr_v4float_uint_8 %MyCBuffer %int_0
  1737. ; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_f]] [[newptr]] [[deref_expr]]
  1738. ; CHECK: [[element_ptr:%\w+]] = OpAccessChain %_ptr_Uniform_v4float [[newptr]] %24
  1739. ; CHECK: [[load:%\w+]] = OpLoad %v4float [[element_ptr]]
  1740. ; CHECK: OpStore %out_var_SV_Target [[load]]
  1741. %decl = OpExtInst %void %ext DebugValue %dbg_f %23 %expr
  1742. %36 = OpAccessChain %_ptr_Function_v4float %23 %24
  1743. %37 = OpLoad %v4float %36
  1744. OpStore %out_var_SV_Target %37
  1745. OpReturn
  1746. OpFunctionEnd
  1747. )";
  1748. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  1749. SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER |
  1750. SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES);
  1751. SinglePassRunAndMatch<CopyPropagateArrays>(before, false);
  1752. }
  1753. TEST_F(CopyPropArrayPassTest, FunctionDeclaration) {
  1754. // Make sure the pass works with a function declaration that is called.
  1755. const std::string text = R"(OpCapability Addresses
  1756. OpCapability Linkage
  1757. OpCapability Kernel
  1758. OpCapability Int8
  1759. %1 = OpExtInstImport "OpenCL.std"
  1760. OpMemoryModel Physical64 OpenCL
  1761. OpEntryPoint Kernel %2 "_Z23julia__1166_kernel_77094Bool"
  1762. OpExecutionMode %2 ContractionOff
  1763. OpSource Unknown 0
  1764. OpDecorate %3 LinkageAttributes "julia_error_7712" Import
  1765. %void = OpTypeVoid
  1766. %5 = OpTypeFunction %void
  1767. %3 = OpFunction %void None %5
  1768. OpFunctionEnd
  1769. %2 = OpFunction %void None %5
  1770. %6 = OpLabel
  1771. %7 = OpFunctionCall %void %3
  1772. OpReturn
  1773. OpFunctionEnd
  1774. )";
  1775. SinglePassRunAndCheck<CopyPropagateArrays>(text, text, false);
  1776. }
  1777. // Since Spir-V 1.4, resources that are used by a shader must be on the
  1778. // OpEntryPoint instruction with the inputs and outputs. This test ensures that
  1779. // this does not stop the pass from working.
  1780. TEST_F(CopyPropArrayPassTest, EntryPointUser) {
  1781. const std::string before = R"(OpCapability Shader
  1782. OpMemoryModel Logical GLSL450
  1783. OpEntryPoint GLCompute %main "main" %g_rwTexture3d
  1784. OpExecutionMode %main LocalSize 256 1 1
  1785. OpSource HLSL 660
  1786. OpName %type_3d_image "type.3d.image"
  1787. OpName %g_rwTexture3d "g_rwTexture3d"
  1788. OpName %main "main"
  1789. OpDecorate %g_rwTexture3d DescriptorSet 0
  1790. OpDecorate %g_rwTexture3d Binding 0
  1791. %uint = OpTypeInt 32 0
  1792. %uint_0 = OpConstant %uint 0
  1793. %uint_1 = OpConstant %uint 1
  1794. %uint_2 = OpConstant %uint 2
  1795. %uint_3 = OpConstant %uint 3
  1796. %v3uint = OpTypeVector %uint 3
  1797. %10 = OpConstantComposite %v3uint %uint_1 %uint_2 %uint_3
  1798. %type_3d_image = OpTypeImage %uint 3D 2 0 0 2 R32ui
  1799. %_ptr_UniformConstant_type_3d_image = OpTypePointer UniformConstant %type_3d_image
  1800. %void = OpTypeVoid
  1801. %13 = OpTypeFunction %void
  1802. %_ptr_Function_type_3d_image = OpTypePointer Function %type_3d_image
  1803. %_ptr_Image_uint = OpTypePointer Image %uint
  1804. %g_rwTexture3d = OpVariable %_ptr_UniformConstant_type_3d_image UniformConstant
  1805. %main = OpFunction %void None %13
  1806. %16 = OpLabel
  1807. %17 = OpVariable %_ptr_Function_type_3d_image Function
  1808. %18 = OpLoad %type_3d_image %g_rwTexture3d
  1809. OpStore %17 %18
  1810. ; CHECK: %19 = OpImageTexelPointer %_ptr_Image_uint %g_rwTexture3d %10 %uint_0
  1811. %19 = OpImageTexelPointer %_ptr_Image_uint %17 %10 %uint_0
  1812. %20 = OpAtomicIAdd %uint %19 %uint_1 %uint_0 %uint_1
  1813. OpReturn
  1814. OpFunctionEnd
  1815. )";
  1816. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  1817. SetTargetEnv(SPV_ENV_UNIVERSAL_1_4);
  1818. SinglePassRunAndMatch<CopyPropagateArrays>(before, false);
  1819. }
  1820. // As per SPIRV spec, struct cannot be indexed with non-constant indices
  1821. // through OpAccessChain, only arrays.
  1822. // The copy-propagate-array pass tries to remove superfluous copies when the
  1823. // original array could be indexed instead of the copy.
  1824. //
  1825. // This test verifies we handle this case:
  1826. // struct SRC { int field1; ...; int fieldN }
  1827. // int tmp_arr[N] = { SRC.field1, ..., SRC.fieldN }
  1828. // return tmp_arr[index];
  1829. //
  1830. // In such case, we cannot optimize the access: this array was added to allow
  1831. // dynamic indexing in the struct.
  1832. TEST_F(CopyPropArrayPassTest, StructIndexCannotBecomeDynamic) {
  1833. const std::string text = R"(OpCapability Shader
  1834. OpMemoryModel Logical GLSL450
  1835. OpEntryPoint Vertex %1 "main"
  1836. OpDecorate %2 DescriptorSet 0
  1837. OpDecorate %2 Binding 0
  1838. OpMemberDecorate %_struct_3 0 Offset 0
  1839. OpDecorate %_struct_3 Block
  1840. %int = OpTypeInt 32 1
  1841. %int_0 = OpConstant %int 0
  1842. %float = OpTypeFloat 32
  1843. %v4float = OpTypeVector %float 4
  1844. %_struct_3 = OpTypeStruct %v4float
  1845. %_ptr_Uniform__struct_3 = OpTypePointer Uniform %_struct_3
  1846. %uint = OpTypeInt 32 0
  1847. %void = OpTypeVoid
  1848. %11 = OpTypeFunction %void
  1849. %_ptr_Function_uint = OpTypePointer Function %uint
  1850. %13 = OpTypeFunction %v4float %_ptr_Function_uint
  1851. %uint_1 = OpConstant %uint 1
  1852. %_arr_v4float_uint_1 = OpTypeArray %v4float %uint_1
  1853. %_ptr_Function__arr_v4float_uint_1 = OpTypePointer Function %_arr_v4float_uint_1
  1854. %_ptr_Function_v4float = OpTypePointer Function %v4float
  1855. %_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
  1856. %2 = OpVariable %_ptr_Uniform__struct_3 Uniform
  1857. %19 = OpUndef %v4float
  1858. %1 = OpFunction %void None %11
  1859. %20 = OpLabel
  1860. OpReturn
  1861. OpFunctionEnd
  1862. %21 = OpFunction %v4float None %13
  1863. %22 = OpFunctionParameter %_ptr_Function_uint
  1864. %23 = OpLabel
  1865. %24 = OpVariable %_ptr_Function__arr_v4float_uint_1 Function
  1866. %25 = OpAccessChain %_ptr_Uniform_v4float %2 %int_0
  1867. %26 = OpLoad %v4float %25
  1868. %27 = OpCompositeConstruct %_arr_v4float_uint_1 %26
  1869. OpStore %24 %27
  1870. %28 = OpLoad %uint %22
  1871. %29 = OpAccessChain %_ptr_Function_v4float %24 %28
  1872. OpReturnValue %19
  1873. OpFunctionEnd
  1874. )";
  1875. SinglePassRunAndCheck<CopyPropagateArrays>(text, text, false);
  1876. }
  1877. // If the size of an array used in an OpCompositeInsert is not known at compile
  1878. // time, then we should not propagate the array, because we do not have a single
  1879. // array that represents the final value.
  1880. TEST_F(CopyPropArrayPassTest, SpecConstSizedArray) {
  1881. const std::string text = R"(OpCapability Shader
  1882. %1 = OpExtInstImport "GLSL.std.450"
  1883. OpMemoryModel Logical GLSL450
  1884. OpEntryPoint Fragment %2 "main"
  1885. OpExecutionMode %2 OriginUpperLeft
  1886. %void = OpTypeVoid
  1887. %4 = OpTypeFunction %void
  1888. %int = OpTypeInt 32 1
  1889. %uint = OpTypeInt 32 0
  1890. %7 = OpSpecConstant %uint 32
  1891. %_arr_int_7 = OpTypeArray %int %7
  1892. %int_63 = OpConstant %int 63
  1893. %uint_0 = OpConstant %uint 0
  1894. %bool = OpTypeBool
  1895. %int_0 = OpConstant %int 0
  1896. %int_587202566 = OpConstant %int 587202566
  1897. %false = OpConstantFalse %bool
  1898. %_ptr_Function__arr_int_7 = OpTypePointer Function %_arr_int_7
  1899. %16 = OpUndef %_arr_int_7
  1900. %2 = OpFunction %void None %4
  1901. %17 = OpLabel
  1902. %18 = OpVariable %_ptr_Function__arr_int_7 Function
  1903. %19 = OpCompositeInsert %_arr_int_7 %int_0 %16 0
  1904. OpStore %18 %19
  1905. OpReturn
  1906. OpFunctionEnd
  1907. )";
  1908. SinglePassRunAndCheck<CopyPropagateArrays>(text, text, false);
  1909. }
  1910. TEST_F(CopyPropArrayPassTest, InterpolateFunctions) {
  1911. const std::string before = R"(OpCapability InterpolationFunction
  1912. OpCapability Shader
  1913. %1 = OpExtInstImport "GLSL.std.450"
  1914. OpMemoryModel Logical GLSL450
  1915. OpEntryPoint Fragment %main "main" %in_var_COLOR
  1916. OpExecutionMode %main OriginUpperLeft
  1917. OpSource HLSL 680
  1918. OpName %in_var_COLOR "in.var.COLOR"
  1919. OpName %main "main"
  1920. OpName %offset "offset"
  1921. OpDecorate %in_var_COLOR Location 0
  1922. %int = OpTypeInt 32 1
  1923. %int_0 = OpConstant %int 0
  1924. %float = OpTypeFloat 32
  1925. %float_0 = OpConstant %float 0
  1926. %v2float = OpTypeVector %float 2
  1927. %v4float = OpTypeVector %float 4
  1928. %_ptr_Input_v4float = OpTypePointer Input %v4float
  1929. %void = OpTypeVoid
  1930. %19 = OpTypeFunction %void
  1931. %_ptr_Function_v4float = OpTypePointer Function %v4float
  1932. %in_var_COLOR = OpVariable %_ptr_Input_v4float Input
  1933. %main = OpFunction %void None %19
  1934. %20 = OpLabel
  1935. %45 = OpVariable %_ptr_Function_v4float Function
  1936. %25 = OpLoad %v4float %in_var_COLOR
  1937. OpStore %45 %25
  1938. ; CHECK: OpExtInst %v4float %1 InterpolateAtCentroid %in_var_COLOR
  1939. %52 = OpExtInst %v4float %1 InterpolateAtCentroid %45
  1940. ; CHECK: OpExtInst %v4float %1 InterpolateAtSample %in_var_COLOR %int_0
  1941. %54 = OpExtInst %v4float %1 InterpolateAtSample %45 %int_0
  1942. %offset = OpCompositeConstruct %v2float %float_0 %float_0
  1943. ; CHECK: OpExtInst %v4float %1 InterpolateAtOffset %in_var_COLOR %offset
  1944. %56 = OpExtInst %v4float %1 InterpolateAtOffset %45 %offset
  1945. OpReturn
  1946. OpFunctionEnd
  1947. )";
  1948. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  1949. SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER |
  1950. SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES);
  1951. SinglePassRunAndMatch<CopyPropagateArrays>(before, false);
  1952. }
  1953. TEST_F(CopyPropArrayPassTest, InterpolateMultiPropagation) {
  1954. const std::string before = R"(OpCapability InterpolationFunction
  1955. OpCapability Shader
  1956. %1 = OpExtInstImport "GLSL.std.450"
  1957. OpMemoryModel Logical GLSL450
  1958. OpEntryPoint Fragment %main "main" %in_var_COLOR
  1959. OpExecutionMode %main OriginUpperLeft
  1960. OpSource HLSL 680
  1961. OpName %in_var_COLOR "in.var.COLOR"
  1962. OpName %main "main"
  1963. OpName %param_var_color "param.var.color"
  1964. OpDecorate %in_var_COLOR Location 0
  1965. %float = OpTypeFloat 32
  1966. %v4float = OpTypeVector %float 4
  1967. %_ptr_Input_v4float = OpTypePointer Input %v4float
  1968. %void = OpTypeVoid
  1969. %19 = OpTypeFunction %void
  1970. %_ptr_Function_v4float = OpTypePointer Function %v4float
  1971. %in_var_COLOR = OpVariable %_ptr_Input_v4float Input
  1972. %main = OpFunction %void None %19
  1973. %20 = OpLabel
  1974. %45 = OpVariable %_ptr_Function_v4float Function
  1975. %param_var_color = OpVariable %_ptr_Function_v4float Function
  1976. %25 = OpLoad %v4float %in_var_COLOR
  1977. OpStore %param_var_color %25
  1978. ; CHECK: OpExtInst %v4float %1 InterpolateAtCentroid %in_var_COLOR
  1979. %52 = OpExtInst %v4float %1 InterpolateAtCentroid %param_var_color
  1980. %49 = OpLoad %v4float %param_var_color
  1981. OpStore %45 %49
  1982. ; CHECK: OpExtInst %v4float %1 InterpolateAtCentroid %in_var_COLOR
  1983. %54 = OpExtInst %v4float %1 InterpolateAtCentroid %45
  1984. OpReturn
  1985. OpFunctionEnd
  1986. )";
  1987. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  1988. SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER |
  1989. SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES);
  1990. SinglePassRunAndMatch<CopyPropagateArrays>(before, false);
  1991. }
  1992. TEST_F(CopyPropArrayPassTest, PropagateScalar) {
  1993. const std::string before = R"(OpCapability InterpolationFunction
  1994. OpCapability Shader
  1995. %1 = OpExtInstImport "GLSL.std.450"
  1996. OpMemoryModel Logical GLSL450
  1997. OpEntryPoint Fragment %main "main" %in_var_SV_InstanceID
  1998. OpExecutionMode %main OriginUpperLeft
  1999. OpSource HLSL 680
  2000. OpName %in_var_SV_InstanceID "in.var.SV_InstanceID"
  2001. OpName %main "main"
  2002. OpDecorate %in_var_SV_InstanceID Location 0
  2003. %float = OpTypeFloat 32
  2004. %v4float = OpTypeVector %float 4
  2005. %_ptr_Input_float = OpTypePointer Input %float
  2006. %void = OpTypeVoid
  2007. %19 = OpTypeFunction %void
  2008. %_ptr_Function_float = OpTypePointer Function %float
  2009. %in_var_SV_InstanceID = OpVariable %_ptr_Input_float Input
  2010. %main = OpFunction %void None %19
  2011. %20 = OpLabel
  2012. %45 = OpVariable %_ptr_Function_float Function
  2013. %25 = OpLoad %v4float %in_var_SV_InstanceID
  2014. OpStore %45 %25
  2015. ; CHECK: OpExtInst %v4float %1 InterpolateAtCentroid %in_var_SV_InstanceID
  2016. %52 = OpExtInst %v4float %1 InterpolateAtCentroid %45
  2017. OpReturn
  2018. OpFunctionEnd
  2019. )";
  2020. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  2021. SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER |
  2022. SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES);
  2023. SinglePassRunAndMatch<CopyPropagateArrays>(before, false);
  2024. }
  2025. TEST_F(CopyPropArrayPassTest, StoreToAccessChain) {
  2026. const std::string before = R"(OpCapability InterpolationFunction
  2027. OpCapability MeshShadingEXT
  2028. OpExtension "SPV_EXT_mesh_shader"
  2029. OpMemoryModel Logical GLSL450
  2030. OpEntryPoint MeshEXT %1 "main" %2 %3
  2031. OpExecutionMode %1 LocalSize 128 1 1
  2032. OpExecutionMode %1 OutputTrianglesEXT
  2033. OpExecutionMode %1 OutputVertices 64
  2034. OpExecutionMode %1 OutputPrimitivesEXT 126
  2035. OpDecorate %3 Flat
  2036. OpDecorate %3 Location 2
  2037. %uint = OpTypeInt 32 0
  2038. %uint_4 = OpConstant %uint 4
  2039. %uint_32 = OpConstant %uint 32
  2040. %_arr_uint_uint_32 = OpTypeArray %uint %uint_32
  2041. %_struct_8 = OpTypeStruct %_arr_uint_uint_32
  2042. %_ptr_TaskPayloadWorkgroupEXT__struct_8 = OpTypePointer TaskPayloadWorkgroupEXT %_struct_8
  2043. %uint_64 = OpConstant %uint 64
  2044. %_arr_uint_uint_64 = OpTypeArray %uint %uint_64
  2045. %_ptr_Output__arr_uint_uint_64 = OpTypePointer Output %_arr_uint_uint_64
  2046. %void = OpTypeVoid
  2047. %14 = OpTypeFunction %void
  2048. %_ptr_Function_uint = OpTypePointer Function %uint
  2049. %_ptr_Function__arr_uint_uint_32 = OpTypePointer Function %_arr_uint_uint_32
  2050. %_ptr_Output_uint = OpTypePointer Output %uint
  2051. %2 = OpVariable %_ptr_TaskPayloadWorkgroupEXT__struct_8 TaskPayloadWorkgroupEXT
  2052. %3 = OpVariable %_ptr_Output__arr_uint_uint_64 Output
  2053. %1 = OpFunction %void None %14
  2054. %18 = OpLabel
  2055. %19 = OpVariable %_ptr_Function__arr_uint_uint_32 Function
  2056. %20 = OpLoad %_struct_8 %2
  2057. %21 = OpCompositeExtract %_arr_uint_uint_32 %20 0
  2058. ; CHECK: %28 = OpAccessChain %_ptr_TaskPayloadWorkgroupEXT__arr_uint_uint_32 %2 %uint_0
  2059. OpStore %19 %21
  2060. ; CHECK: %22 = OpAccessChain %_ptr_TaskPayloadWorkgroupEXT_uint %28 %uint_4
  2061. %22 = OpAccessChain %_ptr_Function_uint %19 %uint_4
  2062. %23 = OpLoad %uint %22
  2063. %24 = OpAccessChain %_ptr_Output_uint %3 %uint_4
  2064. OpStore %24 %23
  2065. OpReturn
  2066. OpFunctionEnd
  2067. )";
  2068. SetTargetEnv(SPV_ENV_UNIVERSAL_1_4);
  2069. SinglePassRunAndMatch<CopyPropagateArrays>(before, true);
  2070. }
  2071. TEST_F(CopyPropArrayPassTest, PropCopyLogical) {
  2072. const std::string before = R"(
  2073. ; CHECK: [[v4array_ptr:%\w+]] = OpTypePointer Uniform %14
  2074. ; CHECK: [[v4_ptr:%\w+]] = OpTypePointer Uniform %7
  2075. ; CHECK: [[ac:%\w+]] = OpAccessChain [[v4array_ptr]] %19 %21 %33
  2076. ; CHECK: %47 = OpAccessChain [[v4_ptr]] [[ac]] %37
  2077. OpCapability Shader
  2078. %1 = OpExtInstImport "GLSL.std.450"
  2079. OpMemoryModel Logical GLSL450
  2080. OpEntryPoint Vertex %4 "main" %19 %30 %32
  2081. OpSource GLSL 430
  2082. OpName %4 "main"
  2083. OpDecorate %14 ArrayStride 16
  2084. OpDecorate %15 ArrayStride 16
  2085. OpMemberDecorate %16 0 Offset 0
  2086. OpMemberDecorate %16 1 Offset 32
  2087. OpDecorate %17 Block
  2088. OpMemberDecorate %17 0 Offset 0
  2089. OpDecorate %19 Binding 0
  2090. OpDecorate %19 DescriptorSet 0
  2091. OpDecorate %28 Block
  2092. OpMemberDecorate %28 0 BuiltIn Position
  2093. OpMemberDecorate %28 1 BuiltIn PointSize
  2094. OpMemberDecorate %28 2 BuiltIn ClipDistance
  2095. OpDecorate %32 Location 0
  2096. %2 = OpTypeVoid
  2097. %3 = OpTypeFunction %2
  2098. %6 = OpTypeFloat 32
  2099. %7 = OpTypeVector %6 4
  2100. %8 = OpTypeInt 32 0
  2101. %9 = OpConstant %8 2
  2102. %10 = OpTypeArray %7 %9
  2103. %11 = OpTypeStruct %10 %10
  2104. %14 = OpTypeArray %7 %9
  2105. %15 = OpTypeArray %7 %9
  2106. %16 = OpTypeStruct %14 %15
  2107. %17 = OpTypeStruct %16
  2108. %18 = OpTypePointer Uniform %17
  2109. %19 = OpVariable %18 Uniform
  2110. %20 = OpTypeInt 32 1
  2111. %21 = OpConstant %20 0
  2112. %22 = OpTypePointer Uniform %16
  2113. %26 = OpConstant %8 1
  2114. %27 = OpTypeArray %6 %26
  2115. %28 = OpTypeStruct %7 %6 %27
  2116. %29 = OpTypePointer Output %28
  2117. %30 = OpVariable %29 Output
  2118. %31 = OpTypePointer Input %7
  2119. %32 = OpVariable %31 Input
  2120. %33 = OpConstant %8 0
  2121. %34 = OpTypePointer Input %6
  2122. %38 = OpTypePointer Function %7
  2123. %41 = OpTypePointer Output %7
  2124. %43 = OpTypePointer Function %10
  2125. %4 = OpFunction %2 None %3
  2126. %5 = OpLabel
  2127. %44 = OpVariable %43 Function
  2128. %23 = OpAccessChain %22 %19 %21
  2129. %24 = OpLoad %16 %23
  2130. %25 = OpCopyLogical %11 %24
  2131. %46 = OpCompositeExtract %10 %25 0
  2132. OpStore %44 %46
  2133. %35 = OpAccessChain %34 %32 %33
  2134. %36 = OpLoad %6 %35
  2135. %37 = OpConvertFToS %20 %36
  2136. %47 = OpAccessChain %38 %44 %37
  2137. %40 = OpLoad %7 %47
  2138. %42 = OpAccessChain %41 %30 %21
  2139. OpStore %42 %40
  2140. OpReturn
  2141. OpFunctionEnd
  2142. )";
  2143. SetTargetEnv(SPV_ENV_UNIVERSAL_1_6);
  2144. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  2145. SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
  2146. SinglePassRunAndMatch<CopyPropagateArrays>(before, true);
  2147. }
  2148. } // namespace
  2149. } // namespace opt
  2150. } // namespace spvtools