eliminate_dead_member_test.cpp 56 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329
  1. // Copyright (c) 2019 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 "assembly_builder.h"
  15. #include "pass_fixture.h"
  16. #include "pass_utils.h"
  17. namespace {
  18. using namespace spvtools;
  19. using EliminateDeadMemberTest = opt::PassTest<::testing::Test>;
  20. TEST_F(EliminateDeadMemberTest, RemoveMember1) {
  21. // Test that the member "y" is removed.
  22. // Update OpMemberName for |y| and |z|.
  23. // Update OpMemberDecorate for |y| and |z|.
  24. // Update OpAccessChain for access to |z|.
  25. const std::string text = R"(
  26. ; CHECK: OpName
  27. ; CHECK-NEXT: OpMemberName %type__Globals 0 "x"
  28. ; CHECK-NEXT: OpMemberName %type__Globals 1 "z"
  29. ; CHECK-NOT: OpMemberName
  30. ; CHECK: OpMemberDecorate %type__Globals 0 Offset 0
  31. ; CHECK: OpMemberDecorate %type__Globals 1 Offset 8
  32. ; CHECK: %type__Globals = OpTypeStruct %float %float
  33. ; CHECK: OpAccessChain %_ptr_Uniform_float %_Globals %int_0
  34. ; CHECK: OpAccessChain %_ptr_Uniform_float %_Globals %uint_1
  35. OpCapability Shader
  36. OpMemoryModel Logical GLSL450
  37. OpEntryPoint Vertex %main "main" %in_var_Position %gl_Position
  38. OpSource HLSL 600
  39. OpName %type__Globals "type.$Globals"
  40. OpMemberName %type__Globals 0 "x"
  41. OpMemberName %type__Globals 1 "y"
  42. OpMemberName %type__Globals 2 "z"
  43. OpName %_Globals "$Globals"
  44. OpName %in_var_Position "in.var.Position"
  45. OpName %main "main"
  46. OpDecorate %gl_Position BuiltIn Position
  47. OpDecorate %in_var_Position Location 0
  48. OpDecorate %_Globals DescriptorSet 0
  49. OpDecorate %_Globals Binding 0
  50. OpMemberDecorate %type__Globals 0 Offset 0
  51. OpMemberDecorate %type__Globals 1 Offset 4
  52. OpMemberDecorate %type__Globals 2 Offset 8
  53. OpDecorate %type__Globals Block
  54. %int = OpTypeInt 32 1
  55. %int_0 = OpConstant %int 0
  56. %float = OpTypeFloat 32
  57. %int_2 = OpConstant %int 2
  58. %type__Globals = OpTypeStruct %float %float %float
  59. %_ptr_Uniform_type__Globals = OpTypePointer Uniform %type__Globals
  60. %v4float = OpTypeVector %float 4
  61. %_ptr_Input_v4float = OpTypePointer Input %v4float
  62. %_ptr_Output_v4float = OpTypePointer Output %v4float
  63. %void = OpTypeVoid
  64. %15 = OpTypeFunction %void
  65. %_ptr_Uniform_float = OpTypePointer Uniform %float
  66. %_Globals = OpVariable %_ptr_Uniform_type__Globals Uniform
  67. %in_var_Position = OpVariable %_ptr_Input_v4float Input
  68. %gl_Position = OpVariable %_ptr_Output_v4float Output
  69. %main = OpFunction %void None %15
  70. %17 = OpLabel
  71. %18 = OpLoad %v4float %in_var_Position
  72. %19 = OpAccessChain %_ptr_Uniform_float %_Globals %int_0
  73. %20 = OpLoad %float %19
  74. %21 = OpCompositeExtract %float %18 0
  75. %22 = OpFAdd %float %21 %20
  76. %23 = OpCompositeInsert %v4float %22 %18 0
  77. %24 = OpCompositeExtract %float %18 1
  78. %25 = OpCompositeInsert %v4float %24 %23 1
  79. %26 = OpAccessChain %_ptr_Uniform_float %_Globals %int_2
  80. %27 = OpLoad %float %26
  81. %28 = OpCompositeExtract %float %18 2
  82. %29 = OpFAdd %float %28 %27
  83. %30 = OpCompositeInsert %v4float %29 %25 2
  84. OpStore %gl_Position %30
  85. OpReturn
  86. OpFunctionEnd
  87. )";
  88. SinglePassRunAndMatch<opt::EliminateDeadMembersPass>(text, true);
  89. }
  90. TEST_F(EliminateDeadMemberTest, RemoveMemberWithGroupDecorations) {
  91. // Test that the member "y" is removed.
  92. // Update OpGroupMemberDecorate for %type__Globals member 1 and 2.
  93. // Update OpAccessChain for access to %type__Globals member 2.
  94. const std::string text = R"(
  95. ; CHECK: OpDecorate [[gr1:%\w+]] Offset 0
  96. ; CHECK: OpDecorate [[gr2:%\w+]] Offset 4
  97. ; CHECK: OpDecorate [[gr3:%\w+]] Offset 8
  98. ; CHECK: [[gr1]] = OpDecorationGroup
  99. ; CHECK: [[gr2]] = OpDecorationGroup
  100. ; CHECK: [[gr3]] = OpDecorationGroup
  101. ; CHECK: OpGroupMemberDecorate [[gr1]] %type__Globals 0
  102. ; CHECK-NOT: OpGroupMemberDecorate [[gr2]]
  103. ; CHECK: OpGroupMemberDecorate [[gr3]] %type__Globals 1
  104. ; CHECK: %type__Globals = OpTypeStruct %float %float
  105. ; CHECK: OpAccessChain %_ptr_Uniform_float %_Globals %int_0
  106. ; CHECK: OpAccessChain %_ptr_Uniform_float %_Globals %uint_1
  107. OpCapability Shader
  108. OpMemoryModel Logical GLSL450
  109. OpEntryPoint Vertex %main "main" %in_var_Position %gl_Position
  110. OpSource HLSL 600
  111. OpName %type__Globals "type.$Globals"
  112. OpName %_Globals "$Globals"
  113. OpDecorate %gl_Position BuiltIn Position
  114. OpDecorate %in_var_Position Location 0
  115. OpDecorate %_Globals DescriptorSet 0
  116. OpDecorate %_Globals Binding 0
  117. OpDecorate %gr1 Offset 0
  118. OpDecorate %gr2 Offset 4
  119. OpDecorate %gr3 Offset 8
  120. OpDecorate %type__Globals Block
  121. %gr1 = OpDecorationGroup
  122. %gr2 = OpDecorationGroup
  123. %gr3 = OpDecorationGroup
  124. OpGroupMemberDecorate %gr1 %type__Globals 0
  125. OpGroupMemberDecorate %gr2 %type__Globals 1
  126. OpGroupMemberDecorate %gr3 %type__Globals 2
  127. %int = OpTypeInt 32 1
  128. %int_0 = OpConstant %int 0
  129. %float = OpTypeFloat 32
  130. %int_2 = OpConstant %int 2
  131. %type__Globals = OpTypeStruct %float %float %float
  132. %_ptr_Uniform_type__Globals = OpTypePointer Uniform %type__Globals
  133. %v4float = OpTypeVector %float 4
  134. %_ptr_Input_v4float = OpTypePointer Input %v4float
  135. %_ptr_Output_v4float = OpTypePointer Output %v4float
  136. %void = OpTypeVoid
  137. %15 = OpTypeFunction %void
  138. %_ptr_Uniform_float = OpTypePointer Uniform %float
  139. %_Globals = OpVariable %_ptr_Uniform_type__Globals Uniform
  140. %in_var_Position = OpVariable %_ptr_Input_v4float Input
  141. %gl_Position = OpVariable %_ptr_Output_v4float Output
  142. %main = OpFunction %void None %15
  143. %17 = OpLabel
  144. %18 = OpLoad %v4float %in_var_Position
  145. %19 = OpAccessChain %_ptr_Uniform_float %_Globals %int_0
  146. %20 = OpLoad %float %19
  147. %21 = OpCompositeExtract %float %18 0
  148. %22 = OpFAdd %float %21 %20
  149. %23 = OpCompositeInsert %v4float %22 %18 0
  150. %24 = OpCompositeExtract %float %18 1
  151. %25 = OpCompositeInsert %v4float %24 %23 1
  152. %26 = OpAccessChain %_ptr_Uniform_float %_Globals %int_2
  153. %27 = OpLoad %float %26
  154. %28 = OpCompositeExtract %float %18 2
  155. %29 = OpFAdd %float %28 %27
  156. %30 = OpCompositeInsert %v4float %29 %25 2
  157. OpStore %gl_Position %30
  158. OpReturn
  159. OpFunctionEnd
  160. )";
  161. // Skipping validation because of a bug in the validator. See issue #2376.
  162. SinglePassRunAndMatch<opt::EliminateDeadMembersPass>(text, false);
  163. }
  164. TEST_F(EliminateDeadMemberTest, RemoveMemberUpdateConstant) {
  165. // Test that the member "x" is removed.
  166. // Update the OpConstantComposite instruction.
  167. const std::string text = R"(
  168. ; CHECK: OpName
  169. ; CHECK-NEXT: OpMemberName %type__Globals 0 "y"
  170. ; CHECK-NEXT: OpMemberName %type__Globals 1 "z"
  171. ; CHECK-NOT: OpMemberName
  172. ; CHECK: OpMemberDecorate %type__Globals 0 Offset 4
  173. ; CHECK: OpMemberDecorate %type__Globals 1 Offset 8
  174. ; CHECK: %type__Globals = OpTypeStruct %float %float
  175. ; CHECK: OpConstantComposite %type__Globals %float_1 %float_2
  176. ; CHECK: OpAccessChain %_ptr_Uniform_float %_Globals %uint_0
  177. ; CHECK: OpAccessChain %_ptr_Uniform_float %_Globals %uint_1
  178. OpCapability Shader
  179. OpMemoryModel Logical GLSL450
  180. OpEntryPoint Vertex %main "main" %in_var_Position %gl_Position
  181. OpSource HLSL 600
  182. OpName %type__Globals "type.$Globals"
  183. OpMemberName %type__Globals 0 "x"
  184. OpMemberName %type__Globals 1 "y"
  185. OpMemberName %type__Globals 2 "z"
  186. OpName %_Globals "$Globals"
  187. OpName %in_var_Position "in.var.Position"
  188. OpName %main "main"
  189. OpDecorate %gl_Position BuiltIn Position
  190. OpDecorate %in_var_Position Location 0
  191. OpDecorate %_Globals DescriptorSet 0
  192. OpDecorate %_Globals Binding 0
  193. OpMemberDecorate %type__Globals 0 Offset 0
  194. OpMemberDecorate %type__Globals 1 Offset 4
  195. OpMemberDecorate %type__Globals 2 Offset 8
  196. OpDecorate %type__Globals Block
  197. %int = OpTypeInt 32 1
  198. %int_1 = OpConstant %int 1
  199. %float = OpTypeFloat 32
  200. %float_0 = OpConstant %float 0
  201. %float_1 = OpConstant %float 1
  202. %float_2 = OpConstant %float 2
  203. %int_2 = OpConstant %int 2
  204. %type__Globals = OpTypeStruct %float %float %float
  205. %13 = OpConstantComposite %type__Globals %float_0 %float_1 %float_2
  206. %_ptr_Uniform_type__Globals = OpTypePointer Uniform %type__Globals
  207. %v4float = OpTypeVector %float 4
  208. %_ptr_Input_v4float = OpTypePointer Input %v4float
  209. %_ptr_Output_v4float = OpTypePointer Output %v4float
  210. %void = OpTypeVoid
  211. %19 = OpTypeFunction %void
  212. %_ptr_Uniform_float = OpTypePointer Uniform %float
  213. %_Globals = OpVariable %_ptr_Uniform_type__Globals Uniform
  214. %in_var_Position = OpVariable %_ptr_Input_v4float Input
  215. %gl_Position = OpVariable %_ptr_Output_v4float Output
  216. %main = OpFunction %void None %19
  217. %21 = OpLabel
  218. %22 = OpLoad %v4float %in_var_Position
  219. %23 = OpAccessChain %_ptr_Uniform_float %_Globals %int_1
  220. %24 = OpLoad %float %23
  221. %25 = OpCompositeExtract %float %22 0
  222. %26 = OpFAdd %float %25 %24
  223. %27 = OpCompositeInsert %v4float %26 %22 0
  224. %28 = OpCompositeExtract %float %22 1
  225. %29 = OpCompositeInsert %v4float %28 %27 1
  226. %30 = OpAccessChain %_ptr_Uniform_float %_Globals %int_2
  227. %31 = OpLoad %float %30
  228. %32 = OpCompositeExtract %float %22 2
  229. %33 = OpFAdd %float %32 %31
  230. %34 = OpCompositeInsert %v4float %33 %29 2
  231. OpStore %gl_Position %34
  232. OpReturn
  233. OpFunctionEnd
  234. )";
  235. SinglePassRunAndMatch<opt::EliminateDeadMembersPass>(text, true);
  236. }
  237. TEST_F(EliminateDeadMemberTest, RemoveMemberUpdateCompositeConstruct) {
  238. // Test that the member "x" is removed.
  239. // Update the OpConstantComposite instruction.
  240. const std::string text = R"(
  241. ; CHECK: OpName
  242. ; CHECK-NEXT: OpMemberName %type__Globals 0 "y"
  243. ; CHECK-NEXT: OpMemberName %type__Globals 1 "z"
  244. ; CHECK-NOT: OpMemberName
  245. ; CHECK: OpMemberDecorate %type__Globals 0 Offset 4
  246. ; CHECK: OpMemberDecorate %type__Globals 1 Offset 8
  247. ; CHECK: %type__Globals = OpTypeStruct %float %float
  248. ; CHECK: OpCompositeConstruct %type__Globals %float_1 %float_2
  249. ; CHECK: OpAccessChain %_ptr_Uniform_float %_Globals %uint_0
  250. ; CHECK: OpAccessChain %_ptr_Uniform_float %_Globals %uint_1
  251. OpCapability Shader
  252. OpMemoryModel Logical GLSL450
  253. OpEntryPoint Vertex %main "main" %in_var_Position %gl_Position
  254. OpSource HLSL 600
  255. OpName %type__Globals "type.$Globals"
  256. OpMemberName %type__Globals 0 "x"
  257. OpMemberName %type__Globals 1 "y"
  258. OpMemberName %type__Globals 2 "z"
  259. OpName %_Globals "$Globals"
  260. OpName %in_var_Position "in.var.Position"
  261. OpName %main "main"
  262. OpDecorate %gl_Position BuiltIn Position
  263. OpDecorate %in_var_Position Location 0
  264. OpDecorate %_Globals DescriptorSet 0
  265. OpDecorate %_Globals Binding 0
  266. OpMemberDecorate %type__Globals 0 Offset 0
  267. OpMemberDecorate %type__Globals 1 Offset 4
  268. OpMemberDecorate %type__Globals 2 Offset 8
  269. OpDecorate %type__Globals Block
  270. %int = OpTypeInt 32 1
  271. %int_1 = OpConstant %int 1
  272. %float = OpTypeFloat 32
  273. %float_0 = OpConstant %float 0
  274. %float_1 = OpConstant %float 1
  275. %float_2 = OpConstant %float 2
  276. %int_2 = OpConstant %int 2
  277. %type__Globals = OpTypeStruct %float %float %float
  278. %_ptr_Uniform_type__Globals = OpTypePointer Uniform %type__Globals
  279. %v4float = OpTypeVector %float 4
  280. %_ptr_Input_v4float = OpTypePointer Input %v4float
  281. %_ptr_Output_v4float = OpTypePointer Output %v4float
  282. %void = OpTypeVoid
  283. %19 = OpTypeFunction %void
  284. %_ptr_Uniform_float = OpTypePointer Uniform %float
  285. %_Globals = OpVariable %_ptr_Uniform_type__Globals Uniform
  286. %in_var_Position = OpVariable %_ptr_Input_v4float Input
  287. %gl_Position = OpVariable %_ptr_Output_v4float Output
  288. %main = OpFunction %void None %19
  289. %21 = OpLabel
  290. %13 = OpCompositeConstruct %type__Globals %float_0 %float_1 %float_2
  291. %22 = OpLoad %v4float %in_var_Position
  292. %23 = OpAccessChain %_ptr_Uniform_float %_Globals %int_1
  293. %24 = OpLoad %float %23
  294. %25 = OpCompositeExtract %float %22 0
  295. %26 = OpFAdd %float %25 %24
  296. %27 = OpCompositeInsert %v4float %26 %22 0
  297. %28 = OpCompositeExtract %float %22 1
  298. %29 = OpCompositeInsert %v4float %28 %27 1
  299. %30 = OpAccessChain %_ptr_Uniform_float %_Globals %int_2
  300. %31 = OpLoad %float %30
  301. %32 = OpCompositeExtract %float %22 2
  302. %33 = OpFAdd %float %32 %31
  303. %34 = OpCompositeInsert %v4float %33 %29 2
  304. OpStore %gl_Position %34
  305. OpReturn
  306. OpFunctionEnd
  307. )";
  308. SinglePassRunAndMatch<opt::EliminateDeadMembersPass>(text, true);
  309. }
  310. TEST_F(EliminateDeadMemberTest, RemoveMembersUpdateInserExtract1) {
  311. // Test that the members "x" and "z" are removed.
  312. // Update the OpCompositeExtract instruction.
  313. // Remove the OpCompositeInsert instruction since the member being inserted is
  314. // dead.
  315. const std::string text = R"(
  316. ; CHECK: OpName
  317. ; CHECK-NEXT: OpMemberName %type__Globals 0 "y"
  318. ; CHECK-NOT: OpMemberName
  319. ; CHECK: OpMemberDecorate %type__Globals 0 Offset 4
  320. ; CHECK-NOT: OpMemberDecorate %type__Globals 1 Offset
  321. ; CHECK: %type__Globals = OpTypeStruct %float
  322. ; CHECK: [[ld:%\w+]] = OpLoad %type__Globals %_Globals
  323. ; CHECK: OpCompositeExtract %float [[ld]] 0
  324. ; CHECK-NOT: OpCompositeInsert
  325. ; CHECK: OpReturn
  326. OpCapability Shader
  327. OpMemoryModel Logical GLSL450
  328. OpEntryPoint Vertex %main "main"
  329. OpSource HLSL 600
  330. OpName %type__Globals "type.$Globals"
  331. OpMemberName %type__Globals 0 "x"
  332. OpMemberName %type__Globals 1 "y"
  333. OpMemberName %type__Globals 2 "z"
  334. OpName %_Globals "$Globals"
  335. OpName %main "main"
  336. OpDecorate %_Globals DescriptorSet 0
  337. OpDecorate %_Globals Binding 0
  338. OpMemberDecorate %type__Globals 0 Offset 0
  339. OpMemberDecorate %type__Globals 1 Offset 4
  340. OpMemberDecorate %type__Globals 2 Offset 8
  341. OpDecorate %type__Globals Block
  342. %float = OpTypeFloat 32
  343. %type__Globals = OpTypeStruct %float %float %float
  344. %_ptr_Uniform_type__Globals = OpTypePointer Uniform %type__Globals
  345. %void = OpTypeVoid
  346. %7 = OpTypeFunction %void
  347. %_Globals = OpVariable %_ptr_Uniform_type__Globals Uniform
  348. %main = OpFunction %void None %7
  349. %8 = OpLabel
  350. %9 = OpLoad %type__Globals %_Globals
  351. %10 = OpCompositeExtract %float %9 1
  352. %11 = OpCompositeInsert %type__Globals %10 %9 2
  353. OpReturn
  354. OpFunctionEnd
  355. )";
  356. SinglePassRunAndMatch<opt::EliminateDeadMembersPass>(text, true);
  357. }
  358. TEST_F(EliminateDeadMemberTest, RemoveMembersUpdateInserExtract2) {
  359. // Test that the members "x" and "z" are removed.
  360. // Update the OpCompositeExtract instruction.
  361. // Update the OpCompositeInsert instruction.
  362. const std::string text = R"(
  363. ; CHECK: OpName
  364. ; CHECK-NEXT: OpMemberName %type__Globals 0 "y"
  365. ; CHECK-NOT: OpMemberName
  366. ; CHECK: OpMemberDecorate %type__Globals 0 Offset 4
  367. ; CHECK-NOT: OpMemberDecorate %type__Globals 1 Offset
  368. ; CHECK: %type__Globals = OpTypeStruct %float
  369. ; CHECK: [[ld:%\w+]] = OpLoad %type__Globals %_Globals
  370. ; CHECK: [[ex:%\w+]] = OpCompositeExtract %float [[ld]] 0
  371. ; CHECK: OpCompositeInsert %type__Globals [[ex]] [[ld]] 0
  372. ; CHECK: OpReturn
  373. OpCapability Shader
  374. OpMemoryModel Logical GLSL450
  375. OpEntryPoint Vertex %main "main"
  376. OpSource HLSL 600
  377. OpName %type__Globals "type.$Globals"
  378. OpMemberName %type__Globals 0 "x"
  379. OpMemberName %type__Globals 1 "y"
  380. OpMemberName %type__Globals 2 "z"
  381. OpName %_Globals "$Globals"
  382. OpName %main "main"
  383. OpDecorate %_Globals DescriptorSet 0
  384. OpDecorate %_Globals Binding 0
  385. OpMemberDecorate %type__Globals 0 Offset 0
  386. OpMemberDecorate %type__Globals 1 Offset 4
  387. OpMemberDecorate %type__Globals 2 Offset 8
  388. OpDecorate %type__Globals Block
  389. %float = OpTypeFloat 32
  390. %type__Globals = OpTypeStruct %float %float %float
  391. %_ptr_Uniform_type__Globals = OpTypePointer Uniform %type__Globals
  392. %void = OpTypeVoid
  393. %7 = OpTypeFunction %void
  394. %_Globals = OpVariable %_ptr_Uniform_type__Globals Uniform
  395. %main = OpFunction %void None %7
  396. %8 = OpLabel
  397. %9 = OpLoad %type__Globals %_Globals
  398. %10 = OpCompositeExtract %float %9 1
  399. %11 = OpCompositeInsert %type__Globals %10 %9 1
  400. OpReturn
  401. OpFunctionEnd
  402. )";
  403. SinglePassRunAndMatch<opt::EliminateDeadMembersPass>(text, true);
  404. }
  405. TEST_F(EliminateDeadMemberTest, RemoveMembersUpdateInserExtract3) {
  406. // Test that the members "x" and "z" are removed, and one member from the
  407. // substruct. Update the OpCompositeExtract instruction. Update the
  408. // OpCompositeInsert instruction.
  409. const std::string text = R"(
  410. ; CHECK: OpName
  411. ; CHECK-NEXT: OpMemberName %type__Globals 0 "y"
  412. ; CHECK-NOT: OpMemberName
  413. ; CHECK: OpMemberDecorate %type__Globals 0 Offset 16
  414. ; CHECK-NOT: OpMemberDecorate %type__Globals 1 Offset
  415. ; CHECK: OpMemberDecorate [[struct:%\w+]] 0 Offset 4
  416. ; CHECK: [[struct:%\w+]] = OpTypeStruct %float
  417. ; CHECK: %type__Globals = OpTypeStruct [[struct]]
  418. ; CHECK: [[ld:%\w+]] = OpLoad %type__Globals %_Globals
  419. ; CHECK: [[ex:%\w+]] = OpCompositeExtract %float [[ld]] 0 0
  420. ; CHECK: OpCompositeInsert %type__Globals [[ex]] [[ld]] 0 0
  421. ; CHECK: OpReturn
  422. OpCapability Shader
  423. OpMemoryModel Logical GLSL450
  424. OpEntryPoint Vertex %main "main"
  425. OpSource HLSL 600
  426. OpName %type__Globals "type.$Globals"
  427. OpMemberName %type__Globals 0 "x"
  428. OpMemberName %type__Globals 1 "y"
  429. OpMemberName %type__Globals 2 "z"
  430. OpName %_Globals "$Globals"
  431. OpName %main "main"
  432. OpDecorate %_Globals DescriptorSet 0
  433. OpDecorate %_Globals Binding 0
  434. OpMemberDecorate %type__Globals 0 Offset 0
  435. OpMemberDecorate %type__Globals 1 Offset 16
  436. OpMemberDecorate %type__Globals 2 Offset 24
  437. OpMemberDecorate %_struct_6 0 Offset 0
  438. OpMemberDecorate %_struct_6 1 Offset 4
  439. OpDecorate %type__Globals Block
  440. %float = OpTypeFloat 32
  441. %_struct_6 = OpTypeStruct %float %float
  442. %type__Globals = OpTypeStruct %float %_struct_6 %float
  443. %_ptr_Uniform_type__Globals = OpTypePointer Uniform %type__Globals
  444. %void = OpTypeVoid
  445. %7 = OpTypeFunction %void
  446. %_Globals = OpVariable %_ptr_Uniform_type__Globals Uniform
  447. %main = OpFunction %void None %7
  448. %8 = OpLabel
  449. %9 = OpLoad %type__Globals %_Globals
  450. %10 = OpCompositeExtract %float %9 1 1
  451. %11 = OpCompositeInsert %type__Globals %10 %9 1 1
  452. OpReturn
  453. OpFunctionEnd
  454. )";
  455. SinglePassRunAndMatch<opt::EliminateDeadMembersPass>(text, true);
  456. }
  457. TEST_F(EliminateDeadMemberTest, RemoveMembersUpdateInserExtract4) {
  458. // Test that the members "x" and "z" are removed, and one member from the
  459. // substruct. Update the OpCompositeExtract instruction. Update the
  460. // OpCompositeInsert instruction.
  461. const std::string text = R"(
  462. ; CHECK: OpName
  463. ; CHECK-NEXT: OpMemberName %type__Globals 0 "y"
  464. ; CHECK-NOT: OpMemberName
  465. ; CHECK: OpMemberDecorate %type__Globals 0 Offset 16
  466. ; CHECK-NOT: OpMemberDecorate %type__Globals 1 Offset
  467. ; CHECK: OpMemberDecorate [[struct:%\w+]] 0 Offset 4
  468. ; CHECK: [[struct:%\w+]] = OpTypeStruct %float
  469. ; CHECK: [[array:%\w+]] = OpTypeArray [[struct]]
  470. ; CHECK: %type__Globals = OpTypeStruct [[array]]
  471. ; CHECK: [[ld:%\w+]] = OpLoad %type__Globals %_Globals
  472. ; CHECK: [[ex:%\w+]] = OpCompositeExtract %float [[ld]] 0 1 0
  473. ; CHECK: OpCompositeInsert %type__Globals [[ex]] [[ld]] 0 1 0
  474. ; CHECK: OpReturn
  475. OpCapability Shader
  476. OpMemoryModel Logical GLSL450
  477. OpEntryPoint Vertex %main "main"
  478. OpSource HLSL 600
  479. OpName %type__Globals "type.$Globals"
  480. OpMemberName %type__Globals 0 "x"
  481. OpMemberName %type__Globals 1 "y"
  482. OpMemberName %type__Globals 2 "z"
  483. OpName %_Globals "$Globals"
  484. OpName %main "main"
  485. OpDecorate %_Globals DescriptorSet 0
  486. OpDecorate %_Globals Binding 0
  487. OpMemberDecorate %type__Globals 0 Offset 0
  488. OpMemberDecorate %type__Globals 1 Offset 16
  489. OpMemberDecorate %type__Globals 2 Offset 80
  490. OpMemberDecorate %_struct_6 0 Offset 0
  491. OpMemberDecorate %_struct_6 1 Offset 4
  492. OpDecorate %array ArrayStride 16
  493. OpDecorate %type__Globals Block
  494. %uint = OpTypeInt 32 0 ; 32-bit int, sign-less
  495. %uint_4 = OpConstant %uint 4
  496. %float = OpTypeFloat 32
  497. %_struct_6 = OpTypeStruct %float %float
  498. %array = OpTypeArray %_struct_6 %uint_4
  499. %type__Globals = OpTypeStruct %float %array %float
  500. %_ptr_Uniform_type__Globals = OpTypePointer Uniform %type__Globals
  501. %void = OpTypeVoid
  502. %7 = OpTypeFunction %void
  503. %_Globals = OpVariable %_ptr_Uniform_type__Globals Uniform
  504. %main = OpFunction %void None %7
  505. %8 = OpLabel
  506. %9 = OpLoad %type__Globals %_Globals
  507. %10 = OpCompositeExtract %float %9 1 1 1
  508. %11 = OpCompositeInsert %type__Globals %10 %9 1 1 1
  509. OpReturn
  510. OpFunctionEnd
  511. )";
  512. SinglePassRunAndMatch<opt::EliminateDeadMembersPass>(text, true);
  513. }
  514. TEST_F(EliminateDeadMemberTest, RemoveMembersUpdateArrayLength) {
  515. // Test that the members "x" and "y" are removed.
  516. // Member "z" is live because of the OpArrayLength instruction.
  517. // Update the OpArrayLength instruction.
  518. const std::string text = R"(
  519. ; CHECK: OpName
  520. ; CHECK-NEXT: OpMemberName %type__Globals 0 "z"
  521. ; CHECK-NOT: OpMemberName
  522. ; CHECK: OpMemberDecorate %type__Globals 0 Offset 16
  523. ; CHECK-NOT: OpMemberDecorate %type__Globals 1 Offset
  524. ; CHECK: %type__Globals = OpTypeStruct %_runtimearr_float
  525. ; CHECK: OpArrayLength %uint %_Globals 0
  526. OpCapability Shader
  527. OpMemoryModel Logical GLSL450
  528. OpEntryPoint Vertex %main "main"
  529. OpSource HLSL 600
  530. OpName %type__Globals "type.$Globals"
  531. OpMemberName %type__Globals 0 "x"
  532. OpMemberName %type__Globals 1 "y"
  533. OpMemberName %type__Globals 2 "z"
  534. OpName %_Globals "$Globals"
  535. OpName %main "main"
  536. OpDecorate %_Globals DescriptorSet 0
  537. OpDecorate %_Globals Binding 0
  538. OpDecorate %_runtimearr_float ArrayStride 16
  539. OpMemberDecorate %type__Globals 0 Offset 0
  540. OpMemberDecorate %type__Globals 1 Offset 4
  541. OpMemberDecorate %type__Globals 2 Offset 16
  542. OpDecorate %type__Globals Block
  543. %uint = OpTypeInt 32 0
  544. %float = OpTypeFloat 32
  545. %_runtimearr_float = OpTypeRuntimeArray %float
  546. %type__Globals = OpTypeStruct %float %float %_runtimearr_float
  547. %_ptr_Uniform_type__Globals = OpTypePointer Uniform %type__Globals
  548. %void = OpTypeVoid
  549. %9 = OpTypeFunction %void
  550. %_Globals = OpVariable %_ptr_Uniform_type__Globals Uniform
  551. %main = OpFunction %void None %9
  552. %10 = OpLabel
  553. %12 = OpArrayLength %uint %_Globals 2
  554. OpReturn
  555. OpFunctionEnd
  556. )";
  557. SinglePassRunAndMatch<opt::EliminateDeadMembersPass>(text, true);
  558. }
  559. TEST_F(EliminateDeadMemberTest, KeepMembersOpStore) {
  560. // Test that all members are kept because of an OpStore.
  561. // No change expected.
  562. const std::string text = R"(
  563. OpCapability Shader
  564. OpMemoryModel Logical GLSL450
  565. OpEntryPoint Vertex %main "main"
  566. OpSource HLSL 600
  567. OpName %type__Globals "type.$Globals"
  568. OpMemberName %type__Globals 0 "x"
  569. OpMemberName %type__Globals 1 "y"
  570. OpMemberName %type__Globals 2 "z"
  571. OpName %_Globals "$Globals"
  572. OpName %_Globals "$Globals2"
  573. OpName %main "main"
  574. OpDecorate %_Globals DescriptorSet 0
  575. OpDecorate %_Globals Binding 0
  576. OpMemberDecorate %type__Globals 0 Offset 0
  577. OpMemberDecorate %type__Globals 1 Offset 4
  578. OpMemberDecorate %type__Globals 2 Offset 16
  579. OpDecorate %type__Globals Block
  580. %uint = OpTypeInt 32 0
  581. %float = OpTypeFloat 32
  582. %type__Globals = OpTypeStruct %float %float %float
  583. %_ptr_Uniform_type__Globals = OpTypePointer Uniform %type__Globals
  584. %void = OpTypeVoid
  585. %9 = OpTypeFunction %void
  586. %_Globals = OpVariable %_ptr_Uniform_type__Globals Uniform
  587. %_Globals2 = OpVariable %_ptr_Uniform_type__Globals Uniform
  588. %main = OpFunction %void None %9
  589. %10 = OpLabel
  590. %11 = OpLoad %type__Globals %_Globals
  591. OpStore %_Globals2 %11
  592. OpReturn
  593. OpFunctionEnd
  594. )";
  595. auto result = SinglePassRunAndDisassemble<opt::EliminateDeadMembersPass>(
  596. text, /* skip_nop = */ true, /* do_validation = */ true);
  597. EXPECT_EQ(opt::Pass::Status::SuccessWithoutChange, std::get<1>(result));
  598. }
  599. TEST_F(EliminateDeadMemberTest, KeepStorageBufferMembers) {
  600. // Test that all members of the storage buffer struct %S are kept.
  601. // No change expected.
  602. const std::string text = R"(
  603. OpCapability Shader
  604. OpExtension "SPV_GOOGLE_hlsl_functionality1"
  605. OpExtension "SPV_GOOGLE_user_type"
  606. %1 = OpExtInstImport "GLSL.std.450"
  607. OpMemoryModel Logical GLSL450
  608. OpEntryPoint Fragment %PSMain "PSMain" %out_var_SV_TARGET
  609. OpExecutionMode %PSMain OriginUpperLeft
  610. OpSource HLSL 600
  611. OpName %type_StructuredBuffer_S "type.StructuredBuffer.S"
  612. OpName %S "S"
  613. OpMemberName %S 0 "A"
  614. OpMemberName %S 1 "B"
  615. OpName %Buf "Buf"
  616. OpName %out_var_SV_TARGET "out.var.SV_TARGET"
  617. OpName %PSMain "PSMain"
  618. OpDecorateString %out_var_SV_TARGET UserSemantic "SV_TARGET"
  619. OpDecorate %out_var_SV_TARGET Location 0
  620. OpDecorate %Buf DescriptorSet 0
  621. OpDecorate %Buf Binding 0
  622. OpMemberDecorate %S 0 Offset 0
  623. OpMemberDecorate %S 1 Offset 16
  624. OpDecorate %_runtimearr_S ArrayStride 32
  625. OpMemberDecorate %type_StructuredBuffer_S 0 Offset 0
  626. OpMemberDecorate %type_StructuredBuffer_S 0 NonWritable
  627. OpDecorate %type_StructuredBuffer_S BufferBlock
  628. OpDecorateString %Buf UserTypeGOOGLE "structuredbuffer"
  629. %int = OpTypeInt 32 1
  630. %int_0 = OpConstant %int 0
  631. %uint = OpTypeInt 32 0
  632. %uint_0 = OpConstant %uint 0
  633. %int_1 = OpConstant %int 1
  634. %float = OpTypeFloat 32
  635. %v4float = OpTypeVector %float 4
  636. %S = OpTypeStruct %v4float %v4float
  637. %_runtimearr_S = OpTypeRuntimeArray %S
  638. %type_StructuredBuffer_S = OpTypeStruct %_runtimearr_S
  639. %_ptr_Uniform_type_StructuredBuffer_S = OpTypePointer Uniform %type_StructuredBuffer_S
  640. %_ptr_Output_v4float = OpTypePointer Output %v4float
  641. %void = OpTypeVoid
  642. %18 = OpTypeFunction %void
  643. %_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
  644. %Buf = OpVariable %_ptr_Uniform_type_StructuredBuffer_S Uniform
  645. %out_var_SV_TARGET = OpVariable %_ptr_Output_v4float Output
  646. %PSMain = OpFunction %void None %18
  647. %20 = OpLabel
  648. %21 = OpAccessChain %_ptr_Uniform_v4float %Buf %int_0 %uint_0 %int_1
  649. %22 = OpLoad %v4float %21
  650. OpStore %out_var_SV_TARGET %22
  651. OpReturn
  652. OpFunctionEnd
  653. )";
  654. auto result = SinglePassRunAndDisassemble<opt::EliminateDeadMembersPass>(
  655. text, /* skip_nop = */ true, /* do_validation = */ true);
  656. EXPECT_EQ(opt::Pass::Status::SuccessWithoutChange, std::get<1>(result));
  657. }
  658. TEST_F(EliminateDeadMemberTest, KeepMembersOpCopyMemory) {
  659. // Test that all members are kept because of an OpCopyMemory.
  660. // No change expected.
  661. const std::string text = R"(
  662. OpCapability Shader
  663. OpMemoryModel Logical GLSL450
  664. OpEntryPoint Vertex %main "main"
  665. OpSource HLSL 600
  666. OpName %type__Globals "type.$Globals"
  667. OpMemberName %type__Globals 0 "x"
  668. OpMemberName %type__Globals 1 "y"
  669. OpMemberName %type__Globals 2 "z"
  670. OpName %_Globals "$Globals"
  671. OpName %_Globals "$Globals2"
  672. OpName %main "main"
  673. OpDecorate %_Globals DescriptorSet 0
  674. OpDecorate %_Globals Binding 0
  675. OpMemberDecorate %type__Globals 0 Offset 0
  676. OpMemberDecorate %type__Globals 1 Offset 4
  677. OpMemberDecorate %type__Globals 2 Offset 16
  678. OpDecorate %type__Globals Block
  679. %uint = OpTypeInt 32 0
  680. %float = OpTypeFloat 32
  681. %type__Globals = OpTypeStruct %float %float %float
  682. %_ptr_Uniform_type__Globals = OpTypePointer Uniform %type__Globals
  683. %void = OpTypeVoid
  684. %9 = OpTypeFunction %void
  685. %_Globals = OpVariable %_ptr_Uniform_type__Globals Uniform
  686. %_Globals2 = OpVariable %_ptr_Uniform_type__Globals Uniform
  687. %main = OpFunction %void None %9
  688. %10 = OpLabel
  689. OpCopyMemory %_Globals2 %_Globals
  690. OpReturn
  691. OpFunctionEnd
  692. )";
  693. auto result = SinglePassRunAndDisassemble<opt::EliminateDeadMembersPass>(
  694. text, /* skip_nop = */ true, /* do_validation = */ true);
  695. EXPECT_EQ(opt::Pass::Status::SuccessWithoutChange, std::get<1>(result));
  696. }
  697. TEST_F(EliminateDeadMemberTest, KeepMembersOpCopyMemorySized) {
  698. // Test that all members are kept because of an OpCopyMemorySized.
  699. // No change expected.
  700. const std::string text = R"(
  701. OpCapability Shader
  702. OpCapability Addresses
  703. OpMemoryModel Logical GLSL450
  704. OpEntryPoint Vertex %main "main"
  705. OpSource HLSL 600
  706. OpName %type__Globals "type.$Globals"
  707. OpMemberName %type__Globals 0 "x"
  708. OpMemberName %type__Globals 1 "y"
  709. OpMemberName %type__Globals 2 "z"
  710. OpName %_Globals "$Globals"
  711. OpName %_Globals "$Globals2"
  712. OpName %main "main"
  713. OpDecorate %_Globals DescriptorSet 0
  714. OpDecorate %_Globals Binding 0
  715. OpMemberDecorate %type__Globals 0 Offset 0
  716. OpMemberDecorate %type__Globals 1 Offset 4
  717. OpMemberDecorate %type__Globals 2 Offset 16
  718. OpDecorate %type__Globals Block
  719. %uint = OpTypeInt 32 0
  720. %uint_20 = OpConstant %uint 20
  721. %float = OpTypeFloat 32
  722. %type__Globals = OpTypeStruct %float %float %float
  723. %_ptr_Uniform_type__Globals = OpTypePointer Uniform %type__Globals
  724. %void = OpTypeVoid
  725. %9 = OpTypeFunction %void
  726. %_Globals = OpVariable %_ptr_Uniform_type__Globals Uniform
  727. %_Globals2 = OpVariable %_ptr_Uniform_type__Globals Uniform
  728. %main = OpFunction %void None %9
  729. %10 = OpLabel
  730. OpCopyMemorySized %_Globals2 %_Globals %uint_20
  731. OpReturn
  732. OpFunctionEnd
  733. )";
  734. auto result = SinglePassRunAndDisassemble<opt::EliminateDeadMembersPass>(
  735. text, /* skip_nop = */ true, /* do_validation = */ true);
  736. EXPECT_EQ(opt::Pass::Status::SuccessWithoutChange, std::get<1>(result));
  737. }
  738. TEST_F(EliminateDeadMemberTest, KeepMembersOpReturnValue) {
  739. // Test that all members are kept because of an OpCopyMemorySized.
  740. // No change expected.
  741. const std::string text = R"(
  742. OpCapability Shader
  743. OpCapability Linkage
  744. OpMemoryModel Logical GLSL450
  745. OpSource HLSL 600
  746. OpName %type__Globals "type.$Globals"
  747. OpMemberName %type__Globals 0 "x"
  748. OpMemberName %type__Globals 1 "y"
  749. OpMemberName %type__Globals 2 "z"
  750. OpName %_Globals "$Globals"
  751. OpName %_Globals "$Globals2"
  752. OpName %main "main"
  753. OpDecorate %_Globals DescriptorSet 0
  754. OpDecorate %_Globals Binding 0
  755. OpMemberDecorate %type__Globals 0 Offset 0
  756. OpMemberDecorate %type__Globals 1 Offset 4
  757. OpMemberDecorate %type__Globals 2 Offset 16
  758. OpDecorate %type__Globals Block
  759. %uint = OpTypeInt 32 0
  760. %uint_20 = OpConstant %uint 20
  761. %float = OpTypeFloat 32
  762. %type__Globals = OpTypeStruct %float %float %float
  763. %_ptr_Uniform_type__Globals = OpTypePointer Uniform %type__Globals
  764. %void = OpTypeVoid
  765. %9 = OpTypeFunction %type__Globals
  766. %_Globals = OpVariable %_ptr_Uniform_type__Globals Uniform
  767. %_Globals2 = OpVariable %_ptr_Uniform_type__Globals Uniform
  768. %main = OpFunction %type__Globals None %9
  769. %10 = OpLabel
  770. %11 = OpLoad %type__Globals %_Globals
  771. OpReturnValue %11
  772. OpFunctionEnd
  773. )";
  774. auto result = SinglePassRunAndDisassemble<opt::EliminateDeadMembersPass>(
  775. text, /* skip_nop = */ true, /* do_validation = */ true);
  776. EXPECT_EQ(opt::Pass::Status::SuccessWithoutChange, std::get<1>(result));
  777. }
  778. TEST_F(EliminateDeadMemberTest, RemoveMemberAccessChainWithArrays) {
  779. // Leave only 1 member in each of the structs.
  780. // Update OpMemberName, OpMemberDecorate, and OpAccessChain.
  781. const std::string text = R"(
  782. ; CHECK: OpName
  783. ; CHECK-NEXT: OpMemberName %type__Globals 0 "y"
  784. ; CHECK-NOT: OpMemberName
  785. ; CHECK: OpMemberDecorate %type__Globals 0 Offset 16
  786. ; CHECK: OpMemberDecorate [[struct:%\w+]] 0 Offset 4
  787. ; CHECK: [[struct]] = OpTypeStruct %float
  788. ; CHECK: [[array:%\w+]] = OpTypeArray [[struct]]
  789. ; CHECK: %type__Globals = OpTypeStruct [[array]]
  790. ; CHECK: [[undef:%\w+]] = OpUndef %uint
  791. ; CHECK: OpAccessChain %_ptr_Uniform_float %_Globals [[undef]] %uint_0 [[undef]] %uint_0
  792. OpCapability Shader
  793. OpCapability VariablePointersStorageBuffer
  794. OpMemoryModel Logical GLSL450
  795. OpEntryPoint Vertex %main "main"
  796. OpSource HLSL 600
  797. OpName %type__Globals "type.$Globals"
  798. OpMemberName %type__Globals 0 "x"
  799. OpMemberName %type__Globals 1 "y"
  800. OpMemberName %type__Globals 2 "z"
  801. OpName %_Globals "$Globals"
  802. OpName %main "main"
  803. OpDecorate %_Globals DescriptorSet 0
  804. OpDecorate %_Globals Binding 0
  805. OpMemberDecorate %type__Globals 0 Offset 0
  806. OpMemberDecorate %type__Globals 1 Offset 16
  807. OpMemberDecorate %type__Globals 2 Offset 48
  808. OpMemberDecorate %_struct_4 0 Offset 0
  809. OpMemberDecorate %_struct_4 1 Offset 4
  810. OpDecorate %_arr__struct_4_uint_2 ArrayStride 16
  811. OpDecorate %type__Globals Block
  812. %uint = OpTypeInt 32 0
  813. %uint_0 = OpConstant %uint 0
  814. %uint_1 = OpConstant %uint 1
  815. %uint_2 = OpConstant %uint 2
  816. %uint_3 = OpConstant %uint 3
  817. %float = OpTypeFloat 32
  818. %_struct_4 = OpTypeStruct %float %float
  819. %_arr__struct_4_uint_2 = OpTypeArray %_struct_4 %uint_2
  820. %type__Globals = OpTypeStruct %float %_arr__struct_4_uint_2 %float
  821. %_arr_type__Globals_uint_3 = OpTypeArray %type__Globals %uint_3
  822. %_ptr_Uniform__arr_type__Globals_uint_3 = OpTypePointer Uniform %_arr_type__Globals_uint_3
  823. %void = OpTypeVoid
  824. %15 = OpTypeFunction %void
  825. %_ptr_Uniform_float = OpTypePointer Uniform %float
  826. %_Globals = OpVariable %_ptr_Uniform__arr_type__Globals_uint_3 Uniform
  827. %main = OpFunction %void None %15
  828. %17 = OpLabel
  829. %18 = OpUndef %uint
  830. %19 = OpAccessChain %_ptr_Uniform_float %_Globals %18 %uint_1 %18 %uint_1
  831. OpReturn
  832. OpFunctionEnd
  833. )";
  834. SinglePassRunAndMatch<opt::EliminateDeadMembersPass>(text, true);
  835. }
  836. TEST_F(EliminateDeadMemberTest, RemoveMemberInboundsAccessChain) {
  837. // Test that the member "y" is removed.
  838. // Update OpMemberName for |y| and |z|.
  839. // Update OpMemberDecorate for |y| and |z|.
  840. // Update OpInboundsAccessChain for access to |z|.
  841. const std::string text = R"(
  842. ; CHECK: OpName
  843. ; CHECK-NEXT: OpMemberName %type__Globals 0 "x"
  844. ; CHECK-NEXT: OpMemberName %type__Globals 1 "z"
  845. ; CHECK-NOT: OpMemberName
  846. ; CHECK: OpMemberDecorate %type__Globals 0 Offset 0
  847. ; CHECK: OpMemberDecorate %type__Globals 1 Offset 8
  848. ; CHECK: %type__Globals = OpTypeStruct %float %float
  849. ; CHECK: OpInBoundsAccessChain %_ptr_Uniform_float %_Globals %int_0
  850. ; CHECK: OpInBoundsAccessChain %_ptr_Uniform_float %_Globals %uint_1
  851. OpCapability Shader
  852. OpMemoryModel Logical GLSL450
  853. OpEntryPoint Vertex %main "main" %in_var_Position %gl_Position
  854. OpSource HLSL 600
  855. OpName %type__Globals "type.$Globals"
  856. OpMemberName %type__Globals 0 "x"
  857. OpMemberName %type__Globals 1 "y"
  858. OpMemberName %type__Globals 2 "z"
  859. OpName %_Globals "$Globals"
  860. OpName %in_var_Position "in.var.Position"
  861. OpName %main "main"
  862. OpDecorate %gl_Position BuiltIn Position
  863. OpDecorate %in_var_Position Location 0
  864. OpDecorate %_Globals DescriptorSet 0
  865. OpDecorate %_Globals Binding 0
  866. OpMemberDecorate %type__Globals 0 Offset 0
  867. OpMemberDecorate %type__Globals 1 Offset 4
  868. OpMemberDecorate %type__Globals 2 Offset 8
  869. OpDecorate %type__Globals Block
  870. %int = OpTypeInt 32 1
  871. %int_0 = OpConstant %int 0
  872. %float = OpTypeFloat 32
  873. %int_2 = OpConstant %int 2
  874. %type__Globals = OpTypeStruct %float %float %float
  875. %_ptr_Uniform_type__Globals = OpTypePointer Uniform %type__Globals
  876. %v4float = OpTypeVector %float 4
  877. %_ptr_Input_v4float = OpTypePointer Input %v4float
  878. %_ptr_Output_v4float = OpTypePointer Output %v4float
  879. %void = OpTypeVoid
  880. %15 = OpTypeFunction %void
  881. %_ptr_Uniform_float = OpTypePointer Uniform %float
  882. %_Globals = OpVariable %_ptr_Uniform_type__Globals Uniform
  883. %in_var_Position = OpVariable %_ptr_Input_v4float Input
  884. %gl_Position = OpVariable %_ptr_Output_v4float Output
  885. %main = OpFunction %void None %15
  886. %17 = OpLabel
  887. %18 = OpLoad %v4float %in_var_Position
  888. %19 = OpInBoundsAccessChain %_ptr_Uniform_float %_Globals %int_0
  889. %20 = OpLoad %float %19
  890. %21 = OpCompositeExtract %float %18 0
  891. %22 = OpFAdd %float %21 %20
  892. %23 = OpCompositeInsert %v4float %22 %18 0
  893. %24 = OpCompositeExtract %float %18 1
  894. %25 = OpCompositeInsert %v4float %24 %23 1
  895. %26 = OpInBoundsAccessChain %_ptr_Uniform_float %_Globals %int_2
  896. %27 = OpLoad %float %26
  897. %28 = OpCompositeExtract %float %18 2
  898. %29 = OpFAdd %float %28 %27
  899. %30 = OpCompositeInsert %v4float %29 %25 2
  900. OpStore %gl_Position %30
  901. OpReturn
  902. OpFunctionEnd
  903. )";
  904. SinglePassRunAndMatch<opt::EliminateDeadMembersPass>(text, true);
  905. }
  906. TEST_F(EliminateDeadMemberTest, RemoveMemberPtrAccessChain) {
  907. // Test that the member "y" is removed.
  908. // Update OpMemberName for |y| and |z|.
  909. // Update OpMemberDecorate for |y| and |z|.
  910. // Update OpInboundsAccessChain for access to |z|.
  911. const std::string text = R"(
  912. ; CHECK: OpName
  913. ; CHECK-NEXT: OpMemberName %type__Globals 0 "x"
  914. ; CHECK-NEXT: OpMemberName %type__Globals 1 "z"
  915. ; CHECK-NOT: OpMemberName
  916. ; CHECK: OpMemberDecorate %type__Globals 0 Offset 0
  917. ; CHECK: OpMemberDecorate %type__Globals 1 Offset 16
  918. ; CHECK: %type__Globals = OpTypeStruct %float %float
  919. ; CHECK: [[ac:%\w+]] = OpAccessChain %_ptr_Uniform_type__Globals %_Globals %uint_0
  920. ; CHECK: OpPtrAccessChain %_ptr_Uniform_float [[ac]] %uint_1 %uint_0
  921. ; CHECK: OpPtrAccessChain %_ptr_Uniform_float [[ac]] %uint_0 %uint_1
  922. OpCapability Shader
  923. OpCapability VariablePointersStorageBuffer
  924. OpMemoryModel Logical GLSL450
  925. OpEntryPoint Vertex %main "main"
  926. OpSource HLSL 600
  927. OpName %type__Globals "type.$Globals"
  928. OpMemberName %type__Globals 0 "x"
  929. OpMemberName %type__Globals 1 "y"
  930. OpMemberName %type__Globals 2 "z"
  931. OpName %_Globals "$Globals"
  932. OpName %main "main"
  933. OpDecorate %_Globals DescriptorSet 0
  934. OpDecorate %_Globals Binding 0
  935. OpMemberDecorate %type__Globals 0 Offset 0
  936. OpMemberDecorate %type__Globals 1 Offset 4
  937. OpMemberDecorate %type__Globals 2 Offset 16
  938. OpDecorate %type__Globals Block
  939. OpDecorate %_ptr_Uniform_type__Globals ArrayStride 8
  940. %uint = OpTypeInt 32 0
  941. %uint_0 = OpConstant %uint 0
  942. %uint_1 = OpConstant %uint 1
  943. %uint_2 = OpConstant %uint 2
  944. %uint_3 = OpConstant %uint 3
  945. %float = OpTypeFloat 32
  946. %type__Globals = OpTypeStruct %float %float %float
  947. %_arr_type__Globals_uint_3 = OpTypeArray %type__Globals %uint_3
  948. %_ptr_Uniform_type__Globals = OpTypePointer Uniform %type__Globals
  949. %_ptr_Uniform__arr_type__Globals_uint_3 = OpTypePointer Uniform %_arr_type__Globals_uint_3
  950. %void = OpTypeVoid
  951. %14 = OpTypeFunction %void
  952. %_ptr_Uniform_float = OpTypePointer Uniform %float
  953. %_Globals = OpVariable %_ptr_Uniform__arr_type__Globals_uint_3 Uniform
  954. %main = OpFunction %void None %14
  955. %16 = OpLabel
  956. %17 = OpAccessChain %_ptr_Uniform_type__Globals %_Globals %uint_0
  957. %18 = OpPtrAccessChain %_ptr_Uniform_float %17 %uint_1 %uint_0
  958. %19 = OpPtrAccessChain %_ptr_Uniform_float %17 %uint_0 %uint_2
  959. OpReturn
  960. OpFunctionEnd
  961. )";
  962. SinglePassRunAndMatch<opt::EliminateDeadMembersPass>(text, true);
  963. }
  964. TEST_F(EliminateDeadMemberTest, RemoveMemberInBoundsPtrAccessChain) {
  965. // Test that the member "y" is removed.
  966. // Update OpMemberName for |y| and |z|.
  967. // Update OpMemberDecorate for |y| and |z|.
  968. // Update OpInboundsAccessChain for access to |z|.
  969. const std::string text = R"(
  970. ; CHECK: OpName
  971. ; CHECK-NEXT: OpMemberName %type__Globals 0 "x"
  972. ; CHECK-NEXT: OpMemberName %type__Globals 1 "z"
  973. ; CHECK-NOT: OpMemberName
  974. ; CHECK: OpMemberDecorate %type__Globals 0 Offset 0
  975. ; CHECK: OpMemberDecorate %type__Globals 1 Offset 16
  976. ; CHECK: %type__Globals = OpTypeStruct %float %float
  977. ; CHECK: [[ac:%\w+]] = OpAccessChain %_ptr_Uniform_type__Globals %_Globals %uint_0
  978. ; CHECK: OpInBoundsPtrAccessChain %_ptr_Uniform_float [[ac]] %uint_1 %uint_0
  979. ; CHECK: OpInBoundsPtrAccessChain %_ptr_Uniform_float [[ac]] %uint_0 %uint_1
  980. OpCapability Shader
  981. OpCapability Addresses
  982. OpMemoryModel Logical GLSL450
  983. OpEntryPoint Vertex %main "main"
  984. OpSource HLSL 600
  985. OpName %type__Globals "type.$Globals"
  986. OpMemberName %type__Globals 0 "x"
  987. OpMemberName %type__Globals 1 "y"
  988. OpMemberName %type__Globals 2 "z"
  989. OpName %_Globals "$Globals"
  990. OpName %main "main"
  991. OpDecorate %_Globals DescriptorSet 0
  992. OpDecorate %_Globals Binding 0
  993. OpMemberDecorate %type__Globals 0 Offset 0
  994. OpMemberDecorate %type__Globals 1 Offset 4
  995. OpMemberDecorate %type__Globals 2 Offset 16
  996. OpDecorate %type__Globals Block
  997. %uint = OpTypeInt 32 0
  998. %uint_0 = OpConstant %uint 0
  999. %uint_1 = OpConstant %uint 1
  1000. %uint_2 = OpConstant %uint 2
  1001. %uint_3 = OpConstant %uint 3
  1002. %float = OpTypeFloat 32
  1003. %type__Globals = OpTypeStruct %float %float %float
  1004. %_arr_type__Globals_uint_3 = OpTypeArray %type__Globals %uint_3
  1005. %_ptr_Uniform_type__Globals = OpTypePointer Uniform %type__Globals
  1006. %_ptr_Uniform__arr_type__Globals_uint_3 = OpTypePointer Uniform %_arr_type__Globals_uint_3
  1007. %void = OpTypeVoid
  1008. %14 = OpTypeFunction %void
  1009. %_ptr_Uniform_float = OpTypePointer Uniform %float
  1010. %_Globals = OpVariable %_ptr_Uniform__arr_type__Globals_uint_3 Uniform
  1011. %main = OpFunction %void None %14
  1012. %16 = OpLabel
  1013. %17 = OpAccessChain %_ptr_Uniform_type__Globals %_Globals %uint_0
  1014. %18 = OpInBoundsPtrAccessChain %_ptr_Uniform_float %17 %uint_1 %uint_0
  1015. %19 = OpInBoundsPtrAccessChain %_ptr_Uniform_float %17 %uint_0 %uint_2
  1016. OpReturn
  1017. OpFunctionEnd
  1018. )";
  1019. SinglePassRunAndMatch<opt::EliminateDeadMembersPass>(text, true);
  1020. }
  1021. TEST_F(EliminateDeadMemberTest, DontRemoveModfStructResultTypeMembers) {
  1022. const std::string text = R"(
  1023. OpCapability Shader
  1024. %1 = OpExtInstImport "GLSL.std.450"
  1025. OpMemoryModel Logical GLSL450
  1026. OpEntryPoint Fragment %main "main"
  1027. OpExecutionMode %main OriginUpperLeft
  1028. OpSource HLSL 600
  1029. %float = OpTypeFloat 32
  1030. %void = OpTypeVoid
  1031. %21 = OpTypeFunction %void
  1032. %ModfStructType = OpTypeStruct %float %float
  1033. %main = OpFunction %void None %21
  1034. %22 = OpLabel
  1035. %23 = OpUndef %float
  1036. %24 = OpExtInst %ModfStructType %1 ModfStruct %23
  1037. %25 = OpCompositeExtract %float %24 1
  1038. OpReturn
  1039. OpFunctionEnd
  1040. )";
  1041. auto result = SinglePassRunAndDisassemble<opt::EliminateDeadMembersPass>(
  1042. text, /* skip_nop = */ true, /* do_validation = */ true);
  1043. EXPECT_EQ(opt::Pass::Status::SuccessWithoutChange, std::get<1>(result));
  1044. }
  1045. TEST_F(EliminateDeadMemberTest, DontChangeInputStructs) {
  1046. // The input for a shader has to match the type of the output from the
  1047. // previous shader in the pipeline. Because of that, we cannot change the
  1048. // types of input variables.
  1049. const std::string text = R"(
  1050. OpCapability Shader
  1051. %1 = OpExtInstImport "GLSL.std.450"
  1052. OpMemoryModel Logical GLSL450
  1053. OpEntryPoint Fragment %main "main" %input_var
  1054. OpExecutionMode %main OriginUpperLeft
  1055. OpSource HLSL 600
  1056. %float = OpTypeFloat 32
  1057. %void = OpTypeVoid
  1058. %21 = OpTypeFunction %void
  1059. %in_var_type = OpTypeStruct %float %float
  1060. %in_ptr_type = OpTypePointer Input %in_var_type
  1061. %input_var = OpVariable %in_ptr_type Input
  1062. %main = OpFunction %void None %21
  1063. %22 = OpLabel
  1064. OpReturn
  1065. OpFunctionEnd
  1066. )";
  1067. auto result = SinglePassRunAndDisassemble<opt::EliminateDeadMembersPass>(
  1068. text, /* skip_nop = */ true, /* do_validation = */ true);
  1069. EXPECT_EQ(opt::Pass::Status::SuccessWithoutChange, std::get<1>(result));
  1070. }
  1071. TEST_F(EliminateDeadMemberTest, DontChangeOutputStructs) {
  1072. // The output for a shader has to match the type of the output from the
  1073. // previous shader in the pipeline. Because of that, we cannot change the
  1074. // types of output variables.
  1075. const std::string text = R"(
  1076. OpCapability Shader
  1077. %1 = OpExtInstImport "GLSL.std.450"
  1078. OpMemoryModel Logical GLSL450
  1079. OpEntryPoint Fragment %main "main" %output_var
  1080. OpExecutionMode %main OriginUpperLeft
  1081. OpSource HLSL 600
  1082. %float = OpTypeFloat 32
  1083. %void = OpTypeVoid
  1084. %21 = OpTypeFunction %void
  1085. %out_var_type = OpTypeStruct %float %float
  1086. %out_ptr_type = OpTypePointer Output %out_var_type
  1087. %output_var = OpVariable %out_ptr_type Output
  1088. %main = OpFunction %void None %21
  1089. %22 = OpLabel
  1090. OpReturn
  1091. OpFunctionEnd
  1092. )";
  1093. auto result = SinglePassRunAndDisassemble<opt::EliminateDeadMembersPass>(
  1094. text, /* skip_nop = */ true, /* do_validation = */ true);
  1095. EXPECT_EQ(opt::Pass::Status::SuccessWithoutChange, std::get<1>(result));
  1096. }
  1097. TEST_F(EliminateDeadMemberTest, UpdateSpecConstOpExtract) {
  1098. // Test that an extract in an OpSpecConstantOp is correctly updated.
  1099. const std::string text = R"(
  1100. ; CHECK: OpName
  1101. ; CHECK-NEXT: OpMemberName %type__Globals 0 "y"
  1102. ; CHECK-NOT: OpMemberName
  1103. ; CHECK: OpDecorate [[spec_const:%\w+]] SpecId 1
  1104. ; CHECK: OpMemberDecorate %type__Globals 0 Offset 4
  1105. ; CHECK: %type__Globals = OpTypeStruct %uint
  1106. ; CHECK: [[struct:%\w+]] = OpSpecConstantComposite %type__Globals [[spec_const]]
  1107. ; CHECK: OpSpecConstantOp %uint CompositeExtract [[struct]] 0
  1108. OpCapability Shader
  1109. OpCapability Addresses
  1110. OpMemoryModel Logical GLSL450
  1111. OpEntryPoint Vertex %main "main"
  1112. OpSource HLSL 600
  1113. OpName %type__Globals "type.$Globals"
  1114. OpMemberName %type__Globals 0 "x"
  1115. OpMemberName %type__Globals 1 "y"
  1116. OpMemberName %type__Globals 2 "z"
  1117. OpName %main "main"
  1118. OpDecorate %c_0 SpecId 0
  1119. OpDecorate %c_1 SpecId 1
  1120. OpDecorate %c_2 SpecId 2
  1121. OpMemberDecorate %type__Globals 0 Offset 0
  1122. OpMemberDecorate %type__Globals 1 Offset 4
  1123. OpMemberDecorate %type__Globals 2 Offset 16
  1124. %uint = OpTypeInt 32 0
  1125. %c_0 = OpSpecConstant %uint 0
  1126. %c_1 = OpSpecConstant %uint 1
  1127. %c_2 = OpSpecConstant %uint 2
  1128. %uint_0 = OpConstant %uint 0
  1129. %uint_1 = OpConstant %uint 1
  1130. %uint_2 = OpConstant %uint 2
  1131. %uint_3 = OpConstant %uint 3
  1132. %type__Globals = OpTypeStruct %uint %uint %uint
  1133. %spec_const_global = OpSpecConstantComposite %type__Globals %c_0 %c_1 %c_2
  1134. %extract = OpSpecConstantOp %uint CompositeExtract %spec_const_global 1
  1135. %void = OpTypeVoid
  1136. %14 = OpTypeFunction %void
  1137. %main = OpFunction %void None %14
  1138. %16 = OpLabel
  1139. OpReturn
  1140. OpFunctionEnd
  1141. )";
  1142. SinglePassRunAndMatch<opt::EliminateDeadMembersPass>(text, true);
  1143. }
  1144. TEST_F(EliminateDeadMemberTest, UpdateSpecConstOpInsert) {
  1145. // Test that an insert in an OpSpecConstantOp is correctly updated.
  1146. const std::string text = R"(
  1147. ; CHECK: OpName
  1148. ; CHECK-NEXT: OpMemberName %type__Globals 0 "y"
  1149. ; CHECK-NOT: OpMemberName
  1150. ; CHECK: OpDecorate [[spec_const:%\w+]] SpecId 1
  1151. ; CHECK: OpMemberDecorate %type__Globals 0 Offset 4
  1152. ; CHECK: %type__Globals = OpTypeStruct %uint
  1153. ; CHECK: [[struct:%\w+]] = OpSpecConstantComposite %type__Globals [[spec_const]]
  1154. ; CHECK: OpSpecConstantOp %type__Globals CompositeInsert %uint_3 [[struct]] 0
  1155. OpCapability Shader
  1156. OpCapability Addresses
  1157. OpMemoryModel Logical GLSL450
  1158. OpEntryPoint Vertex %main "main"
  1159. OpSource HLSL 600
  1160. OpName %type__Globals "type.$Globals"
  1161. OpMemberName %type__Globals 0 "x"
  1162. OpMemberName %type__Globals 1 "y"
  1163. OpMemberName %type__Globals 2 "z"
  1164. OpName %main "main"
  1165. OpDecorate %c_0 SpecId 0
  1166. OpDecorate %c_1 SpecId 1
  1167. OpDecorate %c_2 SpecId 2
  1168. OpMemberDecorate %type__Globals 0 Offset 0
  1169. OpMemberDecorate %type__Globals 1 Offset 4
  1170. OpMemberDecorate %type__Globals 2 Offset 16
  1171. %uint = OpTypeInt 32 0
  1172. %c_0 = OpSpecConstant %uint 0
  1173. %c_1 = OpSpecConstant %uint 1
  1174. %c_2 = OpSpecConstant %uint 2
  1175. %uint_0 = OpConstant %uint 0
  1176. %uint_1 = OpConstant %uint 1
  1177. %uint_2 = OpConstant %uint 2
  1178. %uint_3 = OpConstant %uint 3
  1179. %type__Globals = OpTypeStruct %uint %uint %uint
  1180. %spec_const_global = OpSpecConstantComposite %type__Globals %c_0 %c_1 %c_2
  1181. %insert = OpSpecConstantOp %type__Globals CompositeInsert %uint_3 %spec_const_global 1
  1182. %extract = OpSpecConstantOp %uint CompositeExtract %insert 1
  1183. %void = OpTypeVoid
  1184. %14 = OpTypeFunction %void
  1185. %main = OpFunction %void None %14
  1186. %16 = OpLabel
  1187. OpReturn
  1188. OpFunctionEnd
  1189. )";
  1190. SinglePassRunAndMatch<opt::EliminateDeadMembersPass>(text, true);
  1191. }
  1192. TEST_F(EliminateDeadMemberTest, 8BitIndexNoChange) {
  1193. // Test that the pass does not crash when an 8 bit index is used in an
  1194. // OpAccessChain. No change is expected.
  1195. const std::string text = R"(
  1196. OpCapability ImageQuery
  1197. OpCapability Int8
  1198. OpMemoryModel Logical GLSL450
  1199. OpEntryPoint Fragment %1 "OpnSeman/" %2
  1200. OpExecutionMode %1 OriginUpperLeft
  1201. %void = OpTypeVoid
  1202. %4 = OpTypeFunction %void
  1203. %float = OpTypeFloat 32
  1204. %v4float = OpTypeVector %float 4
  1205. %_struct_7 = OpTypeStruct %v4float
  1206. %_ptr_Function__struct_7 = OpTypePointer Function %_struct_7
  1207. %_ptr_Output_v4float = OpTypePointer Output %v4float
  1208. %10 = OpTypeFunction %v4float %_ptr_Function__struct_7
  1209. %char = OpTypeInt 8 1
  1210. %char_0 = OpConstant %char 0
  1211. %_ptr_Function_v4float = OpTypePointer Function %v4float
  1212. %2 = OpVariable %_ptr_Output_v4float Output
  1213. %1 = OpFunction %void None %4
  1214. %14 = OpLabel
  1215. %15 = OpVariable %_ptr_Function__struct_7 Function
  1216. %16 = OpFunctionCall %v4float %17 %15
  1217. OpReturn
  1218. OpFunctionEnd
  1219. %17 = OpFunction %v4float DontInline %10
  1220. %18 = OpFunctionParameter %_ptr_Function__struct_7
  1221. %19 = OpLabel
  1222. %20 = OpAccessChain %_ptr_Function_v4float %18 %char_0
  1223. %21 = OpLoad %v4float %20
  1224. OpReturnValue %21
  1225. OpFunctionEnd
  1226. )";
  1227. auto result = SinglePassRunAndDisassemble<opt::EliminateDeadMembersPass>(
  1228. text, /* skip_nop = */ true, /* do_validation = */ true);
  1229. EXPECT_EQ(opt::Pass::Status::SuccessWithoutChange, std::get<1>(result));
  1230. }
  1231. TEST_F(EliminateDeadMemberTest, 8BitIndexWithChange) {
  1232. // Test that the pass does not crash when an 8 bit index is used in an
  1233. // OpAccessChain. The index in the access change should be changed to 0.
  1234. const std::string text = R"(
  1235. OpCapability ImageQuery
  1236. OpCapability Int8
  1237. OpMemoryModel Logical GLSL450
  1238. OpEntryPoint Fragment %1 "OpnSeman/" %2
  1239. OpExecutionMode %1 OriginUpperLeft
  1240. %void = OpTypeVoid
  1241. %4 = OpTypeFunction %void
  1242. %float = OpTypeFloat 32
  1243. %v4float = OpTypeVector %float 4
  1244. %_struct_7 = OpTypeStruct %v4float %v4float
  1245. %_ptr_Function__struct_7 = OpTypePointer Function %_struct_7
  1246. %_ptr_Output_v4float = OpTypePointer Output %v4float
  1247. %10 = OpTypeFunction %v4float %_ptr_Function__struct_7
  1248. %char = OpTypeInt 8 1
  1249. %char_1 = OpConstant %char 1
  1250. %_ptr_Function_v4float = OpTypePointer Function %v4float
  1251. %2 = OpVariable %_ptr_Output_v4float Output
  1252. %1 = OpFunction %void None %4
  1253. %14 = OpLabel
  1254. %15 = OpVariable %_ptr_Function__struct_7 Function
  1255. %16 = OpFunctionCall %v4float %17 %15
  1256. OpReturn
  1257. OpFunctionEnd
  1258. %17 = OpFunction %v4float DontInline %10
  1259. ; CHECK: [[param:%\w+]] = OpFunctionParameter
  1260. %18 = OpFunctionParameter %_ptr_Function__struct_7
  1261. %19 = OpLabel
  1262. ; CHECK: OpAccessChain %_ptr_Function_v4float [[param]] %uint_0
  1263. %20 = OpAccessChain %_ptr_Function_v4float %18 %char_1
  1264. %21 = OpLoad %v4float %20
  1265. OpReturnValue %21
  1266. OpFunctionEnd
  1267. )";
  1268. SinglePassRunAndMatch<opt::EliminateDeadMembersPass>(text, true);
  1269. }
  1270. } // namespace