dead_insert_elim_test.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851
  1. // Copyright (c) 2017 Valve Corporation
  2. // Copyright (c) 2017 LunarG Inc.
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software
  11. // distributed under the License is distributed on an "AS IS" BASIS,
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. // See the License for the specific language governing permissions and
  14. // limitations under the License.
  15. #include <string>
  16. #include "test/opt/pass_fixture.h"
  17. #include "test/opt/pass_utils.h"
  18. namespace spvtools {
  19. namespace opt {
  20. namespace {
  21. using DeadInsertElimTest = PassTest<::testing::Test>;
  22. TEST_F(DeadInsertElimTest, InsertAfterInsertElim) {
  23. // With two insertions to the same offset, the first is dead.
  24. //
  25. // Note: The SPIR-V assembly has had store/load elimination
  26. // performed to allow the inserts and extracts to directly
  27. // reference each other.
  28. //
  29. // #version 450
  30. //
  31. // layout (location=0) in float In0;
  32. // layout (location=1) in float In1;
  33. // layout (location=2) in vec2 In2;
  34. // layout (location=0) out vec4 OutColor;
  35. //
  36. // void main()
  37. // {
  38. // vec2 v = In2;
  39. // v.x = In0 + In1; // dead
  40. // v.x = 0.0;
  41. // OutColor = v.xyxy;
  42. // }
  43. const std::string before_predefs =
  44. R"(OpCapability Shader
  45. %1 = OpExtInstImport "GLSL.std.450"
  46. OpMemoryModel Logical GLSL450
  47. OpEntryPoint Fragment %main "main" %In2 %In0 %In1 %OutColor
  48. OpExecutionMode %main OriginUpperLeft
  49. OpSource GLSL 450
  50. OpName %main "main"
  51. OpName %In2 "In2"
  52. OpName %In0 "In0"
  53. OpName %In1 "In1"
  54. OpName %OutColor "OutColor"
  55. OpName %_Globals_ "_Globals_"
  56. OpMemberName %_Globals_ 0 "g_b"
  57. OpMemberName %_Globals_ 1 "g_n"
  58. OpName %_ ""
  59. OpDecorate %In2 Location 2
  60. OpDecorate %In0 Location 0
  61. OpDecorate %In1 Location 1
  62. OpDecorate %OutColor Location 0
  63. OpMemberDecorate %_Globals_ 0 Offset 0
  64. OpMemberDecorate %_Globals_ 1 Offset 4
  65. OpDecorate %_Globals_ Block
  66. OpDecorate %_ DescriptorSet 0
  67. OpDecorate %_ Binding 0
  68. %void = OpTypeVoid
  69. %11 = OpTypeFunction %void
  70. %float = OpTypeFloat 32
  71. %v2float = OpTypeVector %float 2
  72. %_ptr_Function_v2float = OpTypePointer Function %v2float
  73. %_ptr_Input_v2float = OpTypePointer Input %v2float
  74. %In2 = OpVariable %_ptr_Input_v2float Input
  75. %_ptr_Input_float = OpTypePointer Input %float
  76. %In0 = OpVariable %_ptr_Input_float Input
  77. %In1 = OpVariable %_ptr_Input_float Input
  78. %uint = OpTypeInt 32 0
  79. %_ptr_Function_float = OpTypePointer Function %float
  80. %float_0 = OpConstant %float 0
  81. %v4float = OpTypeVector %float 4
  82. %_ptr_Output_v4float = OpTypePointer Output %v4float
  83. %OutColor = OpVariable %_ptr_Output_v4float Output
  84. %int = OpTypeInt 32 1
  85. %_Globals_ = OpTypeStruct %uint %int
  86. %_ptr_Uniform__Globals_ = OpTypePointer Uniform %_Globals_
  87. %_ = OpVariable %_ptr_Uniform__Globals_ Uniform
  88. )";
  89. const std::string after_predefs =
  90. R"(OpCapability Shader
  91. %1 = OpExtInstImport "GLSL.std.450"
  92. OpMemoryModel Logical GLSL450
  93. OpEntryPoint Fragment %main "main" %In2 %In0 %In1 %OutColor
  94. OpExecutionMode %main OriginUpperLeft
  95. OpSource GLSL 450
  96. OpName %main "main"
  97. OpName %In2 "In2"
  98. OpName %In0 "In0"
  99. OpName %In1 "In1"
  100. OpName %OutColor "OutColor"
  101. OpName %_Globals_ "_Globals_"
  102. OpMemberName %_Globals_ 0 "g_b"
  103. OpMemberName %_Globals_ 1 "g_n"
  104. OpName %_ ""
  105. OpDecorate %In2 Location 2
  106. OpDecorate %In0 Location 0
  107. OpDecorate %In1 Location 1
  108. OpDecorate %OutColor Location 0
  109. OpMemberDecorate %_Globals_ 0 Offset 0
  110. OpMemberDecorate %_Globals_ 1 Offset 4
  111. OpDecorate %_Globals_ Block
  112. OpDecorate %_ DescriptorSet 0
  113. OpDecorate %_ Binding 0
  114. %void = OpTypeVoid
  115. %10 = OpTypeFunction %void
  116. %float = OpTypeFloat 32
  117. %v2float = OpTypeVector %float 2
  118. %_ptr_Function_v2float = OpTypePointer Function %v2float
  119. %_ptr_Input_v2float = OpTypePointer Input %v2float
  120. %In2 = OpVariable %_ptr_Input_v2float Input
  121. %_ptr_Input_float = OpTypePointer Input %float
  122. %In0 = OpVariable %_ptr_Input_float Input
  123. %In1 = OpVariable %_ptr_Input_float Input
  124. %uint = OpTypeInt 32 0
  125. %_ptr_Function_float = OpTypePointer Function %float
  126. %float_0 = OpConstant %float 0
  127. %v4float = OpTypeVector %float 4
  128. %_ptr_Output_v4float = OpTypePointer Output %v4float
  129. %OutColor = OpVariable %_ptr_Output_v4float Output
  130. %int = OpTypeInt 32 1
  131. %_Globals_ = OpTypeStruct %uint %int
  132. %_ptr_Uniform__Globals_ = OpTypePointer Uniform %_Globals_
  133. %_ = OpVariable %_ptr_Uniform__Globals_ Uniform
  134. )";
  135. const std::string before =
  136. R"(%main = OpFunction %void None %11
  137. %25 = OpLabel
  138. %26 = OpLoad %v2float %In2
  139. %27 = OpLoad %float %In0
  140. %28 = OpLoad %float %In1
  141. %29 = OpFAdd %float %27 %28
  142. %35 = OpCompositeInsert %v2float %29 %26 0
  143. %37 = OpCompositeInsert %v2float %float_0 %35 0
  144. %33 = OpVectorShuffle %v4float %37 %37 0 1 0 1
  145. OpStore %OutColor %33
  146. OpReturn
  147. OpFunctionEnd
  148. )";
  149. const std::string after =
  150. R"(%main = OpFunction %void None %10
  151. %23 = OpLabel
  152. %24 = OpLoad %v2float %In2
  153. %29 = OpCompositeInsert %v2float %float_0 %24 0
  154. %30 = OpVectorShuffle %v4float %29 %29 0 1 0 1
  155. OpStore %OutColor %30
  156. OpReturn
  157. OpFunctionEnd
  158. )";
  159. SinglePassRunAndCheck<DeadInsertElimPass>(before_predefs + before,
  160. after_predefs + after, true, true);
  161. }
  162. TEST_F(DeadInsertElimTest, DeadInsertForLinkage) {
  163. const std::string before =
  164. R"(OpCapability Shader
  165. OpCapability Linkage
  166. OpMemoryModel Logical GLSL450
  167. OpSource HLSL 630
  168. OpName %main "main"
  169. OpName %BaseColor "BaseColor"
  170. OpName %bb_entry "bb.entry"
  171. OpName %v "v"
  172. OpDecorate %main LinkageAttributes "main" Export
  173. %int = OpTypeInt 32 1
  174. %int_1 = OpConstant %int 1
  175. %uint = OpTypeInt 32 0
  176. %uint_0 = OpConstant %uint 0
  177. %int_0 = OpConstant %int 0
  178. %float = OpTypeFloat 32
  179. %float_0 = OpConstant %float 0
  180. %v2float = OpTypeVector %float 2
  181. %_ptr_Function_v2float = OpTypePointer Function %v2float
  182. %14 = OpTypeFunction %v2float %_ptr_Function_v2float
  183. %_ptr_Function_float = OpTypePointer Function %float
  184. %main = OpFunction %v2float None %14
  185. %BaseColor = OpFunctionParameter %_ptr_Function_v2float
  186. %bb_entry = OpLabel
  187. %v = OpVariable %_ptr_Function_v2float Function
  188. %16 = OpLoad %v2float %v
  189. %17 = OpAccessChain %_ptr_Function_float %BaseColor %int_1
  190. %18 = OpLoad %float %17
  191. %19 = OpCompositeInsert %v2float %18 %16 0
  192. %20 = OpCompositeInsert %v2float %float_0 %19 0
  193. OpReturnValue %20
  194. OpFunctionEnd
  195. )";
  196. const std::string after =
  197. R"(OpCapability Shader
  198. OpCapability Linkage
  199. OpMemoryModel Logical GLSL450
  200. OpSource HLSL 630
  201. OpName %main "main"
  202. OpName %BaseColor "BaseColor"
  203. OpName %bb_entry "bb.entry"
  204. OpName %v "v"
  205. OpDecorate %main LinkageAttributes "main" Export
  206. %int = OpTypeInt 32 1
  207. %uint = OpTypeInt 32 0
  208. %uint_0 = OpConstant %uint 0
  209. %int_0 = OpConstant %int 0
  210. %float = OpTypeFloat 32
  211. %float_0 = OpConstant %float 0
  212. %v2float = OpTypeVector %float 2
  213. %_ptr_Function_v2float = OpTypePointer Function %v2float
  214. %14 = OpTypeFunction %v2float %_ptr_Function_v2float
  215. %_ptr_Function_float = OpTypePointer Function %float
  216. %main = OpFunction %v2float None %14
  217. %BaseColor = OpFunctionParameter %_ptr_Function_v2float
  218. %bb_entry = OpLabel
  219. %v = OpVariable %_ptr_Function_v2float Function
  220. %16 = OpLoad %v2float %v
  221. %20 = OpCompositeInsert %v2float %float_0 %16 0
  222. OpReturnValue %20
  223. OpFunctionEnd
  224. )";
  225. SinglePassRunAndCheck<DeadInsertElimPass>(before, after, true, true);
  226. }
  227. TEST_F(DeadInsertElimTest, DeadInsertInChainWithPhi) {
  228. // Dead insert eliminated with phi in insertion chain.
  229. //
  230. // Note: The SPIR-V assembly has had store/load elimination
  231. // performed to allow the inserts and extracts to directly
  232. // reference each other.
  233. //
  234. // #version 450
  235. //
  236. // layout (location=0) in vec4 In0;
  237. // layout (location=1) in float In1;
  238. // layout (location=2) in float In2;
  239. // layout (location=0) out vec4 OutColor;
  240. //
  241. // layout(std140, binding = 0 ) uniform _Globals_
  242. // {
  243. // bool g_b;
  244. // };
  245. //
  246. // void main()
  247. // {
  248. // vec4 v = In0;
  249. // v.z = In1 + In2;
  250. // if (g_b) v.w = 1.0;
  251. // OutColor = vec4(v.x,v.y,0.0,v.w);
  252. // }
  253. const std::string before_predefs =
  254. R"(OpCapability Shader
  255. %1 = OpExtInstImport "GLSL.std.450"
  256. OpMemoryModel Logical GLSL450
  257. OpEntryPoint Fragment %main "main" %In0 %In1 %In2 %OutColor
  258. OpExecutionMode %main OriginUpperLeft
  259. OpSource GLSL 450
  260. OpName %main "main"
  261. OpName %In0 "In0"
  262. OpName %In1 "In1"
  263. OpName %In2 "In2"
  264. OpName %_Globals_ "_Globals_"
  265. OpMemberName %_Globals_ 0 "g_b"
  266. OpName %_ ""
  267. OpName %OutColor "OutColor"
  268. OpDecorate %In0 Location 0
  269. OpDecorate %In1 Location 1
  270. OpDecorate %In2 Location 2
  271. OpMemberDecorate %_Globals_ 0 Offset 0
  272. OpDecorate %_Globals_ Block
  273. OpDecorate %_ DescriptorSet 0
  274. OpDecorate %_ Binding 0
  275. OpDecorate %OutColor Location 0
  276. %void = OpTypeVoid
  277. %11 = OpTypeFunction %void
  278. %float = OpTypeFloat 32
  279. %v4float = OpTypeVector %float 4
  280. %_ptr_Function_v4float = OpTypePointer Function %v4float
  281. %_ptr_Input_v4float = OpTypePointer Input %v4float
  282. %In0 = OpVariable %_ptr_Input_v4float Input
  283. %_ptr_Input_float = OpTypePointer Input %float
  284. %In1 = OpVariable %_ptr_Input_float Input
  285. %In2 = OpVariable %_ptr_Input_float Input
  286. %uint = OpTypeInt 32 0
  287. %_ptr_Function_float = OpTypePointer Function %float
  288. %_Globals_ = OpTypeStruct %uint
  289. %_ptr_Uniform__Globals_ = OpTypePointer Uniform %_Globals_
  290. %_ = OpVariable %_ptr_Uniform__Globals_ Uniform
  291. %int = OpTypeInt 32 1
  292. %int_0 = OpConstant %int 0
  293. %_ptr_Uniform_uint = OpTypePointer Uniform %uint
  294. %bool = OpTypeBool
  295. %uint_0 = OpConstant %uint 0
  296. %float_1 = OpConstant %float 1
  297. %_ptr_Output_v4float = OpTypePointer Output %v4float
  298. %OutColor = OpVariable %_ptr_Output_v4float Output
  299. %float_0 = OpConstant %float 0
  300. )";
  301. const std::string after_predefs =
  302. R"(OpCapability Shader
  303. %1 = OpExtInstImport "GLSL.std.450"
  304. OpMemoryModel Logical GLSL450
  305. OpEntryPoint Fragment %main "main" %In0 %In1 %In2 %OutColor
  306. OpExecutionMode %main OriginUpperLeft
  307. OpSource GLSL 450
  308. OpName %main "main"
  309. OpName %In0 "In0"
  310. OpName %In1 "In1"
  311. OpName %In2 "In2"
  312. OpName %_Globals_ "_Globals_"
  313. OpMemberName %_Globals_ 0 "g_b"
  314. OpName %_ ""
  315. OpName %OutColor "OutColor"
  316. OpDecorate %In0 Location 0
  317. OpDecorate %In1 Location 1
  318. OpDecorate %In2 Location 2
  319. OpMemberDecorate %_Globals_ 0 Offset 0
  320. OpDecorate %_Globals_ Block
  321. OpDecorate %_ DescriptorSet 0
  322. OpDecorate %_ Binding 0
  323. OpDecorate %OutColor Location 0
  324. %void = OpTypeVoid
  325. %10 = OpTypeFunction %void
  326. %float = OpTypeFloat 32
  327. %v4float = OpTypeVector %float 4
  328. %_ptr_Function_v4float = OpTypePointer Function %v4float
  329. %_ptr_Input_v4float = OpTypePointer Input %v4float
  330. %In0 = OpVariable %_ptr_Input_v4float Input
  331. %_ptr_Input_float = OpTypePointer Input %float
  332. %In1 = OpVariable %_ptr_Input_float Input
  333. %In2 = OpVariable %_ptr_Input_float Input
  334. %uint = OpTypeInt 32 0
  335. %_ptr_Function_float = OpTypePointer Function %float
  336. %_Globals_ = OpTypeStruct %uint
  337. %_ptr_Uniform__Globals_ = OpTypePointer Uniform %_Globals_
  338. %_ = OpVariable %_ptr_Uniform__Globals_ Uniform
  339. %int = OpTypeInt 32 1
  340. %int_0 = OpConstant %int 0
  341. %_ptr_Uniform_uint = OpTypePointer Uniform %uint
  342. %bool = OpTypeBool
  343. %uint_0 = OpConstant %uint 0
  344. %float_1 = OpConstant %float 1
  345. %_ptr_Output_v4float = OpTypePointer Output %v4float
  346. %OutColor = OpVariable %_ptr_Output_v4float Output
  347. %float_0 = OpConstant %float 0
  348. )";
  349. const std::string before =
  350. R"(%main = OpFunction %void None %11
  351. %31 = OpLabel
  352. %32 = OpLoad %v4float %In0
  353. %33 = OpLoad %float %In1
  354. %34 = OpLoad %float %In2
  355. %35 = OpFAdd %float %33 %34
  356. %51 = OpCompositeInsert %v4float %35 %32 2
  357. %37 = OpAccessChain %_ptr_Uniform_uint %_ %int_0
  358. %38 = OpLoad %uint %37
  359. %39 = OpINotEqual %bool %38 %uint_0
  360. OpSelectionMerge %40 None
  361. OpBranchConditional %39 %41 %40
  362. %41 = OpLabel
  363. %53 = OpCompositeInsert %v4float %float_1 %51 3
  364. OpBranch %40
  365. %40 = OpLabel
  366. %60 = OpPhi %v4float %51 %31 %53 %41
  367. %55 = OpCompositeExtract %float %60 0
  368. %57 = OpCompositeExtract %float %60 1
  369. %59 = OpCompositeExtract %float %60 3
  370. %49 = OpCompositeConstruct %v4float %55 %57 %float_0 %59
  371. OpStore %OutColor %49
  372. OpReturn
  373. OpFunctionEnd
  374. )";
  375. const std::string after =
  376. R"(%main = OpFunction %void None %10
  377. %27 = OpLabel
  378. %28 = OpLoad %v4float %In0
  379. %33 = OpAccessChain %_ptr_Uniform_uint %_ %int_0
  380. %34 = OpLoad %uint %33
  381. %35 = OpINotEqual %bool %34 %uint_0
  382. OpSelectionMerge %36 None
  383. OpBranchConditional %35 %37 %36
  384. %37 = OpLabel
  385. %38 = OpCompositeInsert %v4float %float_1 %28 3
  386. OpBranch %36
  387. %36 = OpLabel
  388. %39 = OpPhi %v4float %28 %27 %38 %37
  389. %40 = OpCompositeExtract %float %39 0
  390. %41 = OpCompositeExtract %float %39 1
  391. %42 = OpCompositeExtract %float %39 3
  392. %43 = OpCompositeConstruct %v4float %40 %41 %float_0 %42
  393. OpStore %OutColor %43
  394. OpReturn
  395. OpFunctionEnd
  396. )";
  397. SinglePassRunAndCheck<DeadInsertElimPass>(before_predefs + before,
  398. after_predefs + after, true, true);
  399. }
  400. TEST_F(DeadInsertElimTest, DeadInsertTwoPasses) {
  401. // Dead insert which requires two passes to eliminate
  402. //
  403. // Note: The SPIR-V assembly has had store/load elimination
  404. // performed to allow the inserts and extracts to directly
  405. // reference each other.
  406. //
  407. // #version 450
  408. //
  409. // layout (location=0) in vec4 In0;
  410. // layout (location=1) in float In1;
  411. // layout (location=2) in float In2;
  412. // layout (location=0) out vec4 OutColor;
  413. //
  414. // layout(std140, binding = 0 ) uniform _Globals_
  415. // {
  416. // bool g_b;
  417. // bool g_b2;
  418. // };
  419. //
  420. // void main()
  421. // {
  422. // vec4 v1, v2;
  423. // v1 = In0;
  424. // v1.y = In1 + In2; // dead, second pass
  425. // if (g_b) v1.x = 1.0;
  426. // v2.x = v1.x;
  427. // v2.y = v1.y; // dead, first pass
  428. // if (g_b2) v2.x = 0.0;
  429. // OutColor = vec4(v2.x,v2.x,0.0,1.0);
  430. // }
  431. const std::string before_predefs =
  432. R"(OpCapability Shader
  433. %1 = OpExtInstImport "GLSL.std.450"
  434. OpMemoryModel Logical GLSL450
  435. OpEntryPoint Fragment %main "main" %In0 %In1 %In2 %OutColor
  436. OpExecutionMode %main OriginUpperLeft
  437. OpSource GLSL 450
  438. OpName %main "main"
  439. OpName %In0 "In0"
  440. OpName %In1 "In1"
  441. OpName %In2 "In2"
  442. OpName %_Globals_ "_Globals_"
  443. OpMemberName %_Globals_ 0 "g_b"
  444. OpMemberName %_Globals_ 1 "g_b2"
  445. OpName %_ ""
  446. OpName %OutColor "OutColor"
  447. OpDecorate %In0 Location 0
  448. OpDecorate %In1 Location 1
  449. OpDecorate %In2 Location 2
  450. OpMemberDecorate %_Globals_ 0 Offset 0
  451. OpMemberDecorate %_Globals_ 1 Offset 4
  452. OpDecorate %_Globals_ Block
  453. OpDecorate %_ DescriptorSet 0
  454. OpDecorate %_ Binding 0
  455. OpDecorate %OutColor Location 0
  456. %void = OpTypeVoid
  457. %10 = OpTypeFunction %void
  458. %float = OpTypeFloat 32
  459. %v4float = OpTypeVector %float 4
  460. %_ptr_Function_v4float = OpTypePointer Function %v4float
  461. %_ptr_Input_v4float = OpTypePointer Input %v4float
  462. %In0 = OpVariable %_ptr_Input_v4float Input
  463. %_ptr_Input_float = OpTypePointer Input %float
  464. %In1 = OpVariable %_ptr_Input_float Input
  465. %In2 = OpVariable %_ptr_Input_float Input
  466. %uint = OpTypeInt 32 0
  467. %_Globals_ = OpTypeStruct %uint %uint
  468. %_ptr_Uniform__Globals_ = OpTypePointer Uniform %_Globals_
  469. %_ = OpVariable %_ptr_Uniform__Globals_ Uniform
  470. %int = OpTypeInt 32 1
  471. %int_0 = OpConstant %int 0
  472. %_ptr_Uniform_uint = OpTypePointer Uniform %uint
  473. %bool = OpTypeBool
  474. %uint_0 = OpConstant %uint 0
  475. %float_1 = OpConstant %float 1
  476. %int_1 = OpConstant %int 1
  477. %float_0 = OpConstant %float 0
  478. %_ptr_Output_v4float = OpTypePointer Output %v4float
  479. %OutColor = OpVariable %_ptr_Output_v4float Output
  480. %27 = OpUndef %v4float
  481. )";
  482. const std::string after_predefs =
  483. R"(OpCapability Shader
  484. %1 = OpExtInstImport "GLSL.std.450"
  485. OpMemoryModel Logical GLSL450
  486. OpEntryPoint Fragment %main "main" %In0 %In1 %In2 %OutColor
  487. OpExecutionMode %main OriginUpperLeft
  488. OpSource GLSL 450
  489. OpName %main "main"
  490. OpName %In0 "In0"
  491. OpName %In1 "In1"
  492. OpName %In2 "In2"
  493. OpName %_Globals_ "_Globals_"
  494. OpMemberName %_Globals_ 0 "g_b"
  495. OpMemberName %_Globals_ 1 "g_b2"
  496. OpName %_ ""
  497. OpName %OutColor "OutColor"
  498. OpDecorate %In0 Location 0
  499. OpDecorate %In1 Location 1
  500. OpDecorate %In2 Location 2
  501. OpMemberDecorate %_Globals_ 0 Offset 0
  502. OpMemberDecorate %_Globals_ 1 Offset 4
  503. OpDecorate %_Globals_ Block
  504. OpDecorate %_ DescriptorSet 0
  505. OpDecorate %_ Binding 0
  506. OpDecorate %OutColor Location 0
  507. %void = OpTypeVoid
  508. %10 = OpTypeFunction %void
  509. %float = OpTypeFloat 32
  510. %v4float = OpTypeVector %float 4
  511. %_ptr_Function_v4float = OpTypePointer Function %v4float
  512. %_ptr_Input_v4float = OpTypePointer Input %v4float
  513. %In0 = OpVariable %_ptr_Input_v4float Input
  514. %_ptr_Input_float = OpTypePointer Input %float
  515. %In1 = OpVariable %_ptr_Input_float Input
  516. %In2 = OpVariable %_ptr_Input_float Input
  517. %uint = OpTypeInt 32 0
  518. %_Globals_ = OpTypeStruct %uint %uint
  519. %_ptr_Uniform__Globals_ = OpTypePointer Uniform %_Globals_
  520. %_ = OpVariable %_ptr_Uniform__Globals_ Uniform
  521. %int = OpTypeInt 32 1
  522. %int_0 = OpConstant %int 0
  523. %_ptr_Uniform_uint = OpTypePointer Uniform %uint
  524. %bool = OpTypeBool
  525. %uint_0 = OpConstant %uint 0
  526. %float_1 = OpConstant %float 1
  527. %int_1 = OpConstant %int 1
  528. %float_0 = OpConstant %float 0
  529. %_ptr_Output_v4float = OpTypePointer Output %v4float
  530. %OutColor = OpVariable %_ptr_Output_v4float Output
  531. %27 = OpUndef %v4float
  532. )";
  533. const std::string before =
  534. R"(%main = OpFunction %void None %10
  535. %28 = OpLabel
  536. %29 = OpLoad %v4float %In0
  537. %30 = OpLoad %float %In1
  538. %31 = OpLoad %float %In2
  539. %32 = OpFAdd %float %30 %31
  540. %33 = OpCompositeInsert %v4float %32 %29 1
  541. %34 = OpAccessChain %_ptr_Uniform_uint %_ %int_0
  542. %35 = OpLoad %uint %34
  543. %36 = OpINotEqual %bool %35 %uint_0
  544. OpSelectionMerge %37 None
  545. OpBranchConditional %36 %38 %37
  546. %38 = OpLabel
  547. %39 = OpCompositeInsert %v4float %float_1 %33 0
  548. OpBranch %37
  549. %37 = OpLabel
  550. %40 = OpPhi %v4float %33 %28 %39 %38
  551. %41 = OpCompositeExtract %float %40 0
  552. %42 = OpCompositeInsert %v4float %41 %27 0
  553. %43 = OpCompositeExtract %float %40 1
  554. %44 = OpCompositeInsert %v4float %43 %42 1
  555. %45 = OpAccessChain %_ptr_Uniform_uint %_ %int_1
  556. %46 = OpLoad %uint %45
  557. %47 = OpINotEqual %bool %46 %uint_0
  558. OpSelectionMerge %48 None
  559. OpBranchConditional %47 %49 %48
  560. %49 = OpLabel
  561. %50 = OpCompositeInsert %v4float %float_0 %44 0
  562. OpBranch %48
  563. %48 = OpLabel
  564. %51 = OpPhi %v4float %44 %37 %50 %49
  565. %52 = OpCompositeExtract %float %51 0
  566. %53 = OpCompositeExtract %float %51 0
  567. %54 = OpCompositeConstruct %v4float %52 %53 %float_0 %float_1
  568. OpStore %OutColor %54
  569. OpReturn
  570. OpFunctionEnd
  571. )";
  572. const std::string after =
  573. R"(%main = OpFunction %void None %10
  574. %28 = OpLabel
  575. %29 = OpLoad %v4float %In0
  576. %34 = OpAccessChain %_ptr_Uniform_uint %_ %int_0
  577. %35 = OpLoad %uint %34
  578. %36 = OpINotEqual %bool %35 %uint_0
  579. OpSelectionMerge %37 None
  580. OpBranchConditional %36 %38 %37
  581. %38 = OpLabel
  582. %39 = OpCompositeInsert %v4float %float_1 %29 0
  583. OpBranch %37
  584. %37 = OpLabel
  585. %40 = OpPhi %v4float %29 %28 %39 %38
  586. %41 = OpCompositeExtract %float %40 0
  587. %42 = OpCompositeInsert %v4float %41 %27 0
  588. %45 = OpAccessChain %_ptr_Uniform_uint %_ %int_1
  589. %46 = OpLoad %uint %45
  590. %47 = OpINotEqual %bool %46 %uint_0
  591. OpSelectionMerge %48 None
  592. OpBranchConditional %47 %49 %48
  593. %49 = OpLabel
  594. %50 = OpCompositeInsert %v4float %float_0 %42 0
  595. OpBranch %48
  596. %48 = OpLabel
  597. %51 = OpPhi %v4float %42 %37 %50 %49
  598. %52 = OpCompositeExtract %float %51 0
  599. %53 = OpCompositeExtract %float %51 0
  600. %54 = OpCompositeConstruct %v4float %52 %53 %float_0 %float_1
  601. OpStore %OutColor %54
  602. OpReturn
  603. OpFunctionEnd
  604. )";
  605. SinglePassRunAndCheck<DeadInsertElimPass>(before_predefs + before,
  606. after_predefs + after, true, true);
  607. }
  608. TEST_F(DeadInsertElimTest, DebugInsertAfterInsertElim) {
  609. // With two insertions to the same offset, the first is dead.
  610. //
  611. // Note: The SPIR-V assembly has had store/load elimination
  612. // performed to allow the inserts and extracts to directly
  613. // reference each other.
  614. //
  615. // #version 450
  616. //
  617. // layout (location=0) in float In0;
  618. // layout (location=1) in float In1;
  619. // layout (location=2) in vec2 In2;
  620. // layout (location=0) out vec4 OutColor;
  621. //
  622. // void main()
  623. // {
  624. // vec2 v = In2;
  625. // v.x = In0 + In1; // dead
  626. // v.x = 0.0;
  627. // OutColor = v.xyxy;
  628. // }
  629. const std::string text =
  630. R"(OpCapability Shader
  631. %1 = OpExtInstImport "GLSL.std.450"
  632. %ext = OpExtInstImport "OpenCL.DebugInfo.100"
  633. OpMemoryModel Logical GLSL450
  634. OpEntryPoint Fragment %main "main" %In2 %In0 %In1 %OutColor
  635. OpExecutionMode %main OriginUpperLeft
  636. OpSource GLSL 450
  637. %file_name = OpString "test"
  638. %float_name = OpString "float"
  639. %main_name = OpString "main"
  640. %f_name = OpString "f"
  641. OpName %main "main"
  642. OpName %In2 "In2"
  643. OpName %In0 "In0"
  644. OpName %In1 "In1"
  645. OpName %OutColor "OutColor"
  646. OpName %_Globals_ "_Globals_"
  647. OpMemberName %_Globals_ 0 "g_b"
  648. OpMemberName %_Globals_ 1 "g_n"
  649. OpName %_ ""
  650. OpDecorate %In2 Location 2
  651. OpDecorate %In0 Location 0
  652. OpDecorate %In1 Location 1
  653. OpDecorate %OutColor Location 0
  654. OpMemberDecorate %_Globals_ 0 Offset 0
  655. OpMemberDecorate %_Globals_ 1 Offset 4
  656. OpDecorate %_Globals_ Block
  657. OpDecorate %_ DescriptorSet 0
  658. OpDecorate %_ Binding 0
  659. %void = OpTypeVoid
  660. %11 = OpTypeFunction %void
  661. %float = OpTypeFloat 32
  662. %v2float = OpTypeVector %float 2
  663. %_ptr_Function_v2float = OpTypePointer Function %v2float
  664. %_ptr_Input_v2float = OpTypePointer Input %v2float
  665. %In2 = OpVariable %_ptr_Input_v2float Input
  666. %_ptr_Input_float = OpTypePointer Input %float
  667. %In0 = OpVariable %_ptr_Input_float Input
  668. %In1 = OpVariable %_ptr_Input_float Input
  669. %uint = OpTypeInt 32 0
  670. %uint_32 = OpConstant %uint 32
  671. %_ptr_Function_float = OpTypePointer Function %float
  672. %float_0 = OpConstant %float 0
  673. %v4float = OpTypeVector %float 4
  674. %_ptr_Output_v4float = OpTypePointer Output %v4float
  675. %OutColor = OpVariable %_ptr_Output_v4float Output
  676. %int = OpTypeInt 32 1
  677. %_Globals_ = OpTypeStruct %uint %int
  678. %_ptr_Uniform__Globals_ = OpTypePointer Uniform %_Globals_
  679. %_ = OpVariable %_ptr_Uniform__Globals_ Uniform
  680. %nullexpr = OpExtInst %void %ext DebugExpression
  681. %src = OpExtInst %void %ext DebugSource %file_name
  682. %cu = OpExtInst %void %ext DebugCompilationUnit 1 4 %src HLSL
  683. %dbg_tf = OpExtInst %void %ext DebugTypeBasic %float_name %uint_32 Float
  684. %dbg_v2f = OpExtInst %void %ext DebugTypeVector %dbg_tf 2
  685. %main_ty = OpExtInst %void %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %void
  686. %dbg_main = OpExtInst %void %ext DebugFunction %main_name %main_ty %src 0 0 %cu %main_name FlagIsProtected|FlagIsPrivate 0 %main
  687. %dbg_foo = OpExtInst %void %ext DebugLocalVariable %f_name %dbg_v2f %src 0 0 %dbg_main FlagIsLocal
  688. %main = OpFunction %void None %11
  689. %25 = OpLabel
  690. %26 = OpLoad %v2float %In2
  691. %27 = OpLoad %float %In0
  692. %28 = OpLoad %float %In1
  693. %29 = OpFAdd %float %27 %28
  694. ; CHECK: [[repl:%\w+]] = OpLoad %v2float %In2
  695. ; CHECK-NOT: OpCompositeInsert
  696. ; CHECK: DebugValue {{%\w+}} [[repl:%\w+]]
  697. ; CHECK-NEXT: OpCompositeInsert %v2float %float_0 [[repl]] 0
  698. %35 = OpCompositeInsert %v2float %29 %26 0
  699. %value = OpExtInst %void %ext DebugValue %dbg_foo %35 %nullexpr
  700. %37 = OpCompositeInsert %v2float %float_0 %35 0
  701. %33 = OpVectorShuffle %v4float %37 %37 0 1 0 1
  702. OpStore %OutColor %33
  703. OpReturn
  704. OpFunctionEnd
  705. )";
  706. SinglePassRunAndMatch<DeadInsertElimPass>(text, true);
  707. }
  708. TEST_F(DeadInsertElimTest, PhiOverEmptyStruct) {
  709. // Reproducer for nullptr access error in MarkInsertChain
  710. // that occurs when processing a phi operation with an
  711. // empty struct result type.
  712. //
  713. // Note: Disassembly created from HLSL source with
  714. // dxc -T cs_6_6 -spirv -Oconfig=
  715. // --eliminate-dead-branches,--merge-return,--ssa-rewrite
  716. //
  717. // RWBuffer<float> buf;
  718. //
  719. // struct S { };
  720. //
  721. // S fn() {
  722. // S s = (S)0;
  723. // if (buf[0] > 0) {
  724. // return s;
  725. // }
  726. // return s;
  727. // }
  728. //
  729. // [numthreads(1,1,1)]
  730. // void main() {
  731. // fn();
  732. // }
  733. const std::string disassembly =
  734. R"(OpCapability Shader
  735. OpCapability SampledBuffer
  736. OpCapability ImageBuffer
  737. OpMemoryModel Logical GLSL450
  738. OpEntryPoint GLCompute %main "main"
  739. OpExecutionMode %main LocalSize 1 1 1
  740. OpSource HLSL 660
  741. OpName %S "S"
  742. OpName %type_buffer_image "type.buffer.image"
  743. OpName %buf "buf"
  744. OpName %main "main"
  745. OpName %src_main "src.main"
  746. OpName %bb_entry "bb.entry"
  747. OpName %fn "fn"
  748. OpName %bb_entry_0 "bb.entry"
  749. OpName %s "s"
  750. OpName %if_true "if.true"
  751. OpName %if_merge "if.merge"
  752. OpDecorate %buf DescriptorSet 0
  753. OpDecorate %buf Binding 0
  754. %S = OpTypeStruct
  755. %4 = OpConstantNull %S
  756. %uint = OpTypeInt 32 0
  757. %uint_0 = OpConstant %uint 0
  758. %float = OpTypeFloat 32
  759. %float_0 = OpConstant %float 0
  760. %type_buffer_image = OpTypeImage %float Buffer 2 0 0 2 R32f
  761. %_ptr_UniformConstant_type_buffer_image = OpTypePointer UniformConstant %type_buffer_image
  762. %void = OpTypeVoid
  763. %12 = OpTypeFunction %void
  764. %19 = OpTypeFunction %S
  765. %_ptr_Function_S = OpTypePointer Function %S
  766. %v4float = OpTypeVector %float 4
  767. %bool = OpTypeBool
  768. %buf = OpVariable %_ptr_UniformConstant_type_buffer_image UniformConstant
  769. %false = OpConstantFalse %bool
  770. %_ptr_Function_bool = OpTypePointer Function %bool
  771. %true = OpConstantTrue %bool
  772. %main = OpFunction %void None %12
  773. %13 = OpLabel
  774. %14 = OpFunctionCall %void %src_main
  775. OpReturn
  776. OpFunctionEnd
  777. %src_main = OpFunction %void None %12
  778. %bb_entry = OpLabel
  779. %17 = OpFunctionCall %S %fn
  780. OpReturn
  781. OpFunctionEnd
  782. %fn = OpFunction %S None %19
  783. %bb_entry_0 = OpLabel
  784. %39 = OpVariable %_ptr_Function_bool Function %false
  785. %34 = OpVariable %_ptr_Function_S Function
  786. %s = OpVariable %_ptr_Function_S Function
  787. OpSelectionMerge %33 None
  788. OpSwitch %uint_0 %36
  789. %36 = OpLabel
  790. OpStore %s %4
  791. %23 = OpLoad %type_buffer_image %buf
  792. %25 = OpImageRead %v4float %23 %uint_0 None
  793. %26 = OpCompositeExtract %float %25 0
  794. %28 = OpFOrdGreaterThan %bool %26 %float_0
  795. OpSelectionMerge %if_merge None
  796. OpBranchConditional %28 %if_true %if_merge
  797. %if_true = OpLabel
  798. OpStore %39 %true
  799. OpStore %34 %4
  800. OpBranch %33
  801. %if_merge = OpLabel
  802. OpStore %39 %true
  803. OpStore %34 %4
  804. OpBranch %33
  805. %33 = OpLabel
  806. %41 = OpPhi %S %4 %if_true %4 %if_merge
  807. OpReturnValue %41
  808. OpFunctionEnd
  809. )";
  810. // Used to crash with a nullptr access violation when processing %41
  811. SinglePassRunToBinary<DeadInsertElimPass>(disassembly, true);
  812. }
  813. // TODO(greg-lunarg): Add tests to verify handling of these cases:
  814. //
  815. } // namespace
  816. } // namespace opt
  817. } // namespace spvtools