eliminate_dead_functions_test.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555
  1. // Copyright (c) 2017 Google Inc.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include <string>
  15. #include <vector>
  16. #include "gmock/gmock.h"
  17. #include "test/opt/assembly_builder.h"
  18. #include "test/opt/pass_fixture.h"
  19. #include "test/opt/pass_utils.h"
  20. namespace spvtools {
  21. namespace opt {
  22. namespace {
  23. using ::testing::HasSubstr;
  24. using EliminateDeadFunctionsBasicTest = PassTest<::testing::Test>;
  25. TEST_F(EliminateDeadFunctionsBasicTest, BasicDeleteDeadFunction) {
  26. // The function Dead should be removed because it is never called.
  27. const std::vector<const char*> common_code = {
  28. // clang-format off
  29. "OpCapability Shader",
  30. "OpMemoryModel Logical GLSL450",
  31. "OpEntryPoint Fragment %main \"main\"",
  32. "OpName %main \"main\"",
  33. "OpName %Live \"Live\"",
  34. "%void = OpTypeVoid",
  35. "%7 = OpTypeFunction %void",
  36. "%main = OpFunction %void None %7",
  37. "%15 = OpLabel",
  38. "%16 = OpFunctionCall %void %Live",
  39. "%17 = OpFunctionCall %void %Live",
  40. "OpReturn",
  41. "OpFunctionEnd",
  42. "%Live = OpFunction %void None %7",
  43. "%20 = OpLabel",
  44. "OpReturn",
  45. "OpFunctionEnd"
  46. // clang-format on
  47. };
  48. const std::vector<const char*> dead_function = {
  49. // clang-format off
  50. "%Dead = OpFunction %void None %7",
  51. "%19 = OpLabel",
  52. "OpReturn",
  53. "OpFunctionEnd",
  54. // clang-format on
  55. };
  56. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  57. SinglePassRunAndCheck<EliminateDeadFunctionsPass>(
  58. JoinAllInsts(Concat(common_code, dead_function)),
  59. JoinAllInsts(common_code), /* skip_nop = */ true);
  60. }
  61. TEST_F(EliminateDeadFunctionsBasicTest, BasicKeepLiveFunction) {
  62. // Everything is reachable from an entry point, so no functions should be
  63. // deleted.
  64. const std::vector<const char*> text = {
  65. // clang-format off
  66. "OpCapability Shader",
  67. "OpMemoryModel Logical GLSL450",
  68. "OpEntryPoint Fragment %main \"main\"",
  69. "OpName %main \"main\"",
  70. "OpName %Live1 \"Live1\"",
  71. "OpName %Live2 \"Live2\"",
  72. "%void = OpTypeVoid",
  73. "%7 = OpTypeFunction %void",
  74. "%main = OpFunction %void None %7",
  75. "%15 = OpLabel",
  76. "%16 = OpFunctionCall %void %Live2",
  77. "%17 = OpFunctionCall %void %Live1",
  78. "OpReturn",
  79. "OpFunctionEnd",
  80. "%Live1 = OpFunction %void None %7",
  81. "%19 = OpLabel",
  82. "OpReturn",
  83. "OpFunctionEnd",
  84. "%Live2 = OpFunction %void None %7",
  85. "%20 = OpLabel",
  86. "OpReturn",
  87. "OpFunctionEnd"
  88. // clang-format on
  89. };
  90. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  91. std::string assembly = JoinAllInsts(text);
  92. auto result = SinglePassRunAndDisassemble<EliminateDeadFunctionsPass>(
  93. assembly, /* skip_nop = */ true, /* do_validation = */ false);
  94. EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
  95. EXPECT_EQ(assembly, std::get<0>(result));
  96. }
  97. TEST_F(EliminateDeadFunctionsBasicTest, BasicKeepExportFunctions) {
  98. // All functions are reachable. In particular, ExportedFunc and Constant are
  99. // reachable because ExportedFunc is exported. Nothing should be removed.
  100. const std::vector<const char*> text = {
  101. // clang-format off
  102. "OpCapability Shader",
  103. "OpCapability Linkage",
  104. "OpMemoryModel Logical GLSL450",
  105. "OpEntryPoint Fragment %main \"main\"",
  106. "OpName %main \"main\"",
  107. "OpName %ExportedFunc \"ExportedFunc\"",
  108. "OpName %Live \"Live\"",
  109. "OpDecorate %ExportedFunc LinkageAttributes \"ExportedFunc\" Export",
  110. "%void = OpTypeVoid",
  111. "%7 = OpTypeFunction %void",
  112. "%main = OpFunction %void None %7",
  113. "%15 = OpLabel",
  114. "OpReturn",
  115. "OpFunctionEnd",
  116. "%ExportedFunc = OpFunction %void None %7",
  117. "%19 = OpLabel",
  118. "%16 = OpFunctionCall %void %Live",
  119. "OpReturn",
  120. "OpFunctionEnd",
  121. "%Live = OpFunction %void None %7",
  122. "%20 = OpLabel",
  123. "OpReturn",
  124. "OpFunctionEnd"
  125. // clang-format on
  126. };
  127. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  128. std::string assembly = JoinAllInsts(text);
  129. auto result = SinglePassRunAndDisassemble<EliminateDeadFunctionsPass>(
  130. assembly, /* skip_nop = */ true, /* do_validation = */ false);
  131. EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
  132. EXPECT_EQ(assembly, std::get<0>(result));
  133. }
  134. TEST_F(EliminateDeadFunctionsBasicTest, BasicRemoveDecorationsAndNames) {
  135. // We want to remove the names and decorations associated with results that
  136. // are removed. This test will check for that.
  137. const std::string text = R"(
  138. OpCapability Shader
  139. OpMemoryModel Logical GLSL450
  140. OpEntryPoint Vertex %main "main"
  141. OpName %main "main"
  142. OpName %Dead "Dead"
  143. OpName %x "x"
  144. OpName %y "y"
  145. OpName %z "z"
  146. OpDecorate %x RelaxedPrecision
  147. OpDecorate %y RelaxedPrecision
  148. OpDecorate %z RelaxedPrecision
  149. OpDecorate %6 RelaxedPrecision
  150. OpDecorate %7 RelaxedPrecision
  151. OpDecorate %8 RelaxedPrecision
  152. %void = OpTypeVoid
  153. %10 = OpTypeFunction %void
  154. %float = OpTypeFloat 32
  155. %_ptr_Function_float = OpTypePointer Function %float
  156. %float_1 = OpConstant %float 1
  157. %main = OpFunction %void None %10
  158. %14 = OpLabel
  159. OpReturn
  160. OpFunctionEnd
  161. %Dead = OpFunction %void None %10
  162. %15 = OpLabel
  163. %x = OpVariable %_ptr_Function_float Function
  164. %y = OpVariable %_ptr_Function_float Function
  165. %z = OpVariable %_ptr_Function_float Function
  166. OpStore %x %float_1
  167. OpStore %y %float_1
  168. %6 = OpLoad %float %x
  169. %7 = OpLoad %float %y
  170. %8 = OpFAdd %float %6 %7
  171. OpStore %z %8
  172. OpReturn
  173. OpFunctionEnd)";
  174. const std::string expected_output = R"(OpCapability Shader
  175. OpMemoryModel Logical GLSL450
  176. OpEntryPoint Vertex %main "main"
  177. OpName %main "main"
  178. %void = OpTypeVoid
  179. %10 = OpTypeFunction %void
  180. %float = OpTypeFloat 32
  181. %_ptr_Function_float = OpTypePointer Function %float
  182. %float_1 = OpConstant %float 1
  183. %main = OpFunction %void None %10
  184. %14 = OpLabel
  185. OpReturn
  186. OpFunctionEnd
  187. )";
  188. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  189. SinglePassRunAndCheck<EliminateDeadFunctionsPass>(text, expected_output,
  190. /* skip_nop = */ true);
  191. }
  192. TEST_F(EliminateDeadFunctionsBasicTest, DebugRemoveFunctionFromDebugFunction) {
  193. // We want to remove id of OpFunction from DebugFunction.
  194. const std::string text = R"(OpCapability Shader
  195. %1 = OpExtInstImport "OpenCL.DebugInfo.100"
  196. OpMemoryModel Logical GLSL450
  197. OpEntryPoint Fragment %2 "main" %3 %4
  198. OpExecutionMode %2 OriginUpperLeft
  199. %5 = OpString "ps.hlsl"
  200. OpSource HLSL 600 %5 "float4 foo() {
  201. return 1;
  202. }
  203. float4 main(float4 color : COLOR) : SV_TARGET {
  204. return foo() + color;
  205. }
  206. "
  207. %6 = OpString "float"
  208. %7 = OpString "main"
  209. %8 = OpString "foo"
  210. ; CHECK: [[foo:%\d+]] = OpString "foo"
  211. OpDecorate %3 Location 0
  212. OpDecorate %4 Location 0
  213. %uint = OpTypeInt 32 0
  214. %uint_32 = OpConstant %uint 32
  215. %float = OpTypeFloat 32
  216. %float_1 = OpConstant %float 1
  217. %v4float = OpTypeVector %float 4
  218. %14 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
  219. %_ptr_Input_v4float = OpTypePointer Input %v4float
  220. %_ptr_Output_v4float = OpTypePointer Output %v4float
  221. %void = OpTypeVoid
  222. %18 = OpTypeFunction %void
  223. %19 = OpTypeFunction %v4float
  224. %3 = OpVariable %_ptr_Input_v4float Input
  225. %4 = OpVariable %_ptr_Output_v4float Output
  226. %_ptr_Function_v4float = OpTypePointer Function %v4float
  227. ; CHECK: [[info_none:%\d+]] = OpExtInst %void %1 DebugInfoNone
  228. %20 = OpExtInst %void %1 DebugSource %5
  229. %21 = OpExtInst %void %1 DebugCompilationUnit 1 4 %20 HLSL
  230. %22 = OpExtInst %void %1 DebugTypeBasic %6 %uint_32 Float
  231. %23 = OpExtInst %void %1 DebugTypeVector %22 4
  232. %24 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %23 %23
  233. %25 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %23
  234. %26 = OpExtInst %void %1 DebugFunction %7 %24 %20 4 1 %21 %7 FlagIsProtected|FlagIsPrivate 4 %2
  235. %27 = OpExtInst %void %1 DebugFunction %8 %25 %20 1 1 %21 %8 FlagIsProtected|FlagIsPrivate 1 %28
  236. ; CHECK: {{%\d+}} = OpExtInst %void %1 DebugFunction [[foo]] {{%\d+}} {{%\d+}} 1 1 {{%\d+}} {{%\d+}} FlagIsProtected|FlagIsPrivate 1 [[info_none]]
  237. %29 = OpExtInst %void %1 DebugLexicalBlock %20 1 14 %27
  238. %40 = OpExtInst %void %1 DebugInlinedAt 4 %26
  239. %2 = OpFunction %void None %18
  240. %30 = OpLabel
  241. %39 = OpVariable %_ptr_Function_v4float Function
  242. %41 = OpExtInst %void %1 DebugScope %27 %40
  243. OpStore %39 %14
  244. %32 = OpLoad %v4float %39
  245. %42 = OpExtInst %void %1 DebugScope %26
  246. %33 = OpLoad %v4float %3
  247. %34 = OpFAdd %v4float %32 %33
  248. OpStore %4 %34
  249. %43 = OpExtInst %void %1 DebugNoScope
  250. OpReturn
  251. OpFunctionEnd
  252. %28 = OpFunction %v4float None %19
  253. %36 = OpLabel
  254. OpReturnValue %14
  255. OpFunctionEnd
  256. )";
  257. SinglePassRunAndMatch<EliminateDeadFunctionsPass>(text, false);
  258. }
  259. TEST_F(EliminateDeadFunctionsBasicTest,
  260. DebugRemoveFunctionUsingExistingDebugInfoNone) {
  261. // We want to remove id of OpFunction from DebugFunction.
  262. const std::string text = R"(OpCapability Shader
  263. %1 = OpExtInstImport "OpenCL.DebugInfo.100"
  264. OpMemoryModel Logical GLSL450
  265. OpEntryPoint Fragment %2 "main" %3 %4
  266. OpExecutionMode %2 OriginUpperLeft
  267. %5 = OpString "ps.hlsl"
  268. OpSource HLSL 600 %5 "float4 foo() {
  269. return 1;
  270. }
  271. float4 main(float4 color : COLOR) : SV_TARGET {
  272. return foo() + color;
  273. }
  274. "
  275. %6 = OpString "float"
  276. %7 = OpString "main"
  277. %8 = OpString "foo"
  278. ; CHECK: [[foo:%\d+]] = OpString "foo"
  279. OpDecorate %3 Location 0
  280. OpDecorate %4 Location 0
  281. %uint = OpTypeInt 32 0
  282. %uint_32 = OpConstant %uint 32
  283. %float = OpTypeFloat 32
  284. %float_1 = OpConstant %float 1
  285. %v4float = OpTypeVector %float 4
  286. %14 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
  287. %_ptr_Input_v4float = OpTypePointer Input %v4float
  288. %_ptr_Output_v4float = OpTypePointer Output %v4float
  289. %void = OpTypeVoid
  290. %18 = OpTypeFunction %void
  291. %19 = OpTypeFunction %v4float
  292. %3 = OpVariable %_ptr_Input_v4float Input
  293. %4 = OpVariable %_ptr_Output_v4float Output
  294. %_ptr_Function_v4float = OpTypePointer Function %v4float
  295. ; CHECK: [[info_none:%\d+]] = OpExtInst %void %1 DebugInfoNone
  296. %20 = OpExtInst %void %1 DebugSource %5
  297. %21 = OpExtInst %void %1 DebugCompilationUnit 1 4 %20 HLSL
  298. %22 = OpExtInst %void %1 DebugTypeBasic %6 %uint_32 Float
  299. %23 = OpExtInst %void %1 DebugTypeVector %22 4
  300. %24 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %23 %23
  301. %25 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %23
  302. %26 = OpExtInst %void %1 DebugFunction %7 %24 %20 4 1 %21 %7 FlagIsProtected|FlagIsPrivate 4 %2
  303. %27 = OpExtInst %void %1 DebugFunction %8 %25 %20 1 1 %21 %8 FlagIsProtected|FlagIsPrivate 1 %28
  304. ; CHECK: {{%\d+}} = OpExtInst %void %1 DebugFunction [[foo]] {{%\d+}} {{%\d+}} 1 1 {{%\d+}} {{%\d+}} FlagIsProtected|FlagIsPrivate 1 [[info_none]]
  305. %29 = OpExtInst %void %1 DebugLexicalBlock %20 1 14 %27
  306. %35 = OpExtInst %void %1 DebugInfoNone
  307. %40 = OpExtInst %void %1 DebugInlinedAt 4 %26
  308. %2 = OpFunction %void None %18
  309. %30 = OpLabel
  310. %39 = OpVariable %_ptr_Function_v4float Function
  311. %41 = OpExtInst %void %1 DebugScope %27 %40
  312. OpStore %39 %14
  313. %32 = OpLoad %v4float %39
  314. %42 = OpExtInst %void %1 DebugScope %26
  315. %33 = OpLoad %v4float %3
  316. %34 = OpFAdd %v4float %32 %33
  317. OpStore %4 %34
  318. %43 = OpExtInst %void %1 DebugNoScope
  319. OpReturn
  320. OpFunctionEnd
  321. %28 = OpFunction %v4float None %19
  322. %36 = OpLabel
  323. OpReturnValue %14
  324. OpFunctionEnd
  325. )";
  326. SinglePassRunAndMatch<EliminateDeadFunctionsPass>(text, false);
  327. }
  328. TEST_F(EliminateDeadFunctionsBasicTest, NonSemanticInfoPersists) {
  329. const std::string text = R"(
  330. ; CHECK: [[import:%\w+]] = OpExtInstImport
  331. ; CHECK: [[void:%\w+]] = OpTypeVoid
  332. ; CHECK-NOT: OpExtInst [[void]] [[import]] 1
  333. ; CHECK: OpExtInst [[void]] [[import]] 2
  334. OpCapability Shader
  335. OpExtension "SPV_KHR_non_semantic_info"
  336. %ext = OpExtInstImport "NonSemantic.Test"
  337. OpMemoryModel Logical GLSL450
  338. OpEntryPoint GLCompute %main "main"
  339. OpExecutionMode %main LocalSize 1 1 1
  340. %void = OpTypeVoid
  341. %void_fn = OpTypeFunction %void
  342. %main = OpFunction %void None %void_fn
  343. %entry = OpLabel
  344. OpReturn
  345. OpFunctionEnd
  346. %foo = OpFunction %void None %void_fn
  347. %foo_entry = OpLabel
  348. %non_semantic1 = OpExtInst %void %ext 1
  349. OpReturn
  350. OpFunctionEnd
  351. %non_semantic2 = OpExtInst %void %ext 2
  352. )";
  353. SinglePassRunAndMatch<EliminateDeadFunctionsPass>(text, true);
  354. }
  355. TEST_F(EliminateDeadFunctionsBasicTest, NonSemanticInfoRemoveDependent) {
  356. const std::string text = R"(
  357. ; CHECK: [[import:%\w+]] = OpExtInstImport
  358. ; CHECK: [[void:%\w+]] = OpTypeVoid
  359. ; CHECK-NOT: OpExtInst [[void]] [[import]] 1
  360. ; CHECK-NOT: OpExtInst [[void]] [[import]] 2
  361. ; CHECK: OpExtInst [[void]] [[import]] 3
  362. OpCapability Shader
  363. OpExtension "SPV_KHR_non_semantic_info"
  364. %ext = OpExtInstImport "NonSemantic.Test"
  365. OpMemoryModel Logical GLSL450
  366. OpEntryPoint GLCompute %main "main"
  367. OpExecutionMode %main LocalSize 1 1 1
  368. %void = OpTypeVoid
  369. %void_fn = OpTypeFunction %void
  370. %main = OpFunction %void None %void_fn
  371. %entry = OpLabel
  372. OpReturn
  373. OpFunctionEnd
  374. %foo = OpFunction %void None %void_fn
  375. %foo_entry = OpLabel
  376. %non_semantic1 = OpExtInst %void %ext 1
  377. OpReturn
  378. OpFunctionEnd
  379. %non_semantic2 = OpExtInst %void %ext 2 %foo
  380. %non_semantic3 = OpExtInst %void %ext 3
  381. )";
  382. SinglePassRunAndMatch<EliminateDeadFunctionsPass>(text, true);
  383. }
  384. TEST_F(EliminateDeadFunctionsBasicTest, NonSemanticInfoRemoveDependentTree) {
  385. const std::string text = R"(
  386. ; CHECK: [[import:%\w+]] = OpExtInstImport
  387. ; CHECK: [[void:%\w+]] = OpTypeVoid
  388. ; CHECK-NOT: OpExtInst [[void]] [[import]] 1
  389. ; CHECK-NOT: OpExtInst [[void]] [[import]] 2
  390. ; CHECK: OpExtInst [[void]] [[import]] 3
  391. ; CHECK-NOT: OpExtInst [[void]] [[import]] 4
  392. ; CHECK-NOT: OpExtInst [[void]] [[import]] 5
  393. OpCapability Shader
  394. OpExtension "SPV_KHR_non_semantic_info"
  395. %ext = OpExtInstImport "NonSemantic.Test"
  396. OpMemoryModel Logical GLSL450
  397. OpEntryPoint GLCompute %main "main"
  398. OpExecutionMode %main LocalSize 1 1 1
  399. %void = OpTypeVoid
  400. %void_fn = OpTypeFunction %void
  401. %main = OpFunction %void None %void_fn
  402. %entry = OpLabel
  403. OpReturn
  404. OpFunctionEnd
  405. %foo = OpFunction %void None %void_fn
  406. %foo_entry = OpLabel
  407. %non_semantic1 = OpExtInst %void %ext 1
  408. OpReturn
  409. OpFunctionEnd
  410. %non_semantic2 = OpExtInst %void %ext 2 %foo
  411. %non_semantic3 = OpExtInst %void %ext 3
  412. %non_semantic4 = OpExtInst %void %ext 4 %non_semantic2
  413. %non_semantic5 = OpExtInst %void %ext 5 %non_semantic4
  414. )";
  415. SinglePassRunAndMatch<EliminateDeadFunctionsPass>(text, true);
  416. }
  417. TEST_F(EliminateDeadFunctionsBasicTest, NonSemanticInfoRemoveDebugPrintf) {
  418. const std::string text = R"(
  419. ; CHECK-NOT: %foo_ = OpFunction %void None % 3
  420. ; CHECK-NOT: % 7 = OpLabel
  421. ; CHECK-NOT: %c = OpVariable %_ptr_Function_v4float Function
  422. ; CHECK-NOT: % 22 = OpAccessChain %_ptr_UniformConstant_13 %samplers %int_0
  423. ; CHECK-NOT: % 23 = OpLoad % 13 % 22
  424. ; CHECK-NOT: % 27 = OpImageSampleExplicitLod %v4float % 23 % 26 Lod %float_0
  425. ; CHECK-NOT: OpStore %c % 27
  426. ; CHECK-NOT: % 31 = OpAccessChain %_ptr_Function_float %c %uint_0
  427. ; CHECK-NOT: % 32 = OpLoad %float %31
  428. ; CHECK-NOT: % 34 = OpExtInst %void %33 1 % 28 % 32
  429. OpCapability RayTracingKHR
  430. OpExtension "SPV_KHR_non_semantic_info"
  431. OpExtension "SPV_KHR_ray_tracing"
  432. %1 = OpExtInstImport "GLSL.std.450"
  433. %33 = OpExtInstImport "NonSemantic.DebugPrintf"
  434. OpMemoryModel Logical GLSL450
  435. OpEntryPoint ClosestHitNV %main "main" %samplers
  436. %28 = OpString "%f"
  437. OpSource GLSL 460
  438. OpSourceExtension "GL_EXT_debug_printf"
  439. OpName %main "main"
  440. OpName %foo_ "foo("
  441. OpName %c "c"
  442. OpName %samplers "samplers"
  443. OpDecorate %samplers DescriptorSet 0
  444. OpDecorate %samplers Binding 0
  445. %void = OpTypeVoid
  446. %3 = OpTypeFunction %void
  447. %float = OpTypeFloat 32
  448. %v4float = OpTypeVector %float 4
  449. %_ptr_Function_v4float = OpTypePointer Function %v4float
  450. %12 = OpTypeImage %float 3D 0 0 0 1 Unknown
  451. %13 = OpTypeSampledImage %12
  452. %uint = OpTypeInt 32 0
  453. %uint_1 = OpConstant %uint 1
  454. %_arr_13_uint_1 = OpTypeArray %13 %uint_1
  455. %_ptr_UniformConstant__arr_13_uint_1 = OpTypePointer UniformConstant %_arr_13_uint_1
  456. %samplers = OpVariable %_ptr_UniformConstant__arr_13_uint_1 UniformConstant
  457. %int = OpTypeInt 32 1
  458. %int_0 = OpConstant %int 0
  459. %_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
  460. %v3float = OpTypeVector %float 3
  461. %float_0 = OpConstant %float 0
  462. %26 = OpConstantComposite %v3float %float_0 %float_0 %float_0
  463. %uint_0 = OpConstant %uint 0
  464. %_ptr_Function_float = OpTypePointer Function %float
  465. %main = OpFunction %void None %3
  466. %5 = OpLabel
  467. %36 = OpVariable %_ptr_Function_v4float Function
  468. %38 = OpAccessChain %_ptr_UniformConstant_13 %samplers %int_0
  469. %39 = OpLoad %13 %38
  470. %40 = OpImageSampleExplicitLod %v4float %39 %26 Lod %float_0
  471. OpStore %36 %40
  472. %41 = OpAccessChain %_ptr_Function_float %36 %uint_0
  473. %42 = OpLoad %float %41
  474. %43 = OpExtInst %void %33 1 %28 %42
  475. OpReturn
  476. OpFunctionEnd
  477. %foo_ = OpFunction %void None %3
  478. %7 = OpLabel
  479. %c = OpVariable %_ptr_Function_v4float Function
  480. %22 = OpAccessChain %_ptr_UniformConstant_13 %samplers %int_0
  481. %23 = OpLoad %13 %22
  482. %27 = OpImageSampleExplicitLod %v4float %23 %26 Lod %float_0
  483. OpStore %c %27
  484. %31 = OpAccessChain %_ptr_Function_float %c %uint_0
  485. %32 = OpLoad %float %31
  486. %34 = OpExtInst %void %33 1 %28 %32
  487. OpReturn
  488. OpFunctionEnd
  489. )";
  490. SetTargetEnv(SPV_ENV_VULKAN_1_2);
  491. SinglePassRunAndMatch<EliminateDeadFunctionsPass>(text, true);
  492. }
  493. TEST_F(EliminateDeadFunctionsBasicTest, DependentNonSemanticChain) {
  494. const std::string text = R"(
  495. ; CHECK: OpEntryPoint GLCompute [[main:%\w+]]
  496. ; CHECK: [[main]] = OpFunction
  497. ; CHECK-NOT: = OpFunction
  498. ; CHECK: [[ext1:%\w+]] = OpExtInst %void {{%\w+}} 1 [[main]]
  499. ; CHECK: [[ext2:%\w+]] = OpExtInst %void {{%\w+}} 2 [[ext1]]
  500. ; CHECK: [[ext3:%\w+]] = OpExtInst %void {{%\w+}} 3 [[ext1]] [[ext2]]
  501. OpCapability Shader
  502. OpExtension "SPV_KHR_non_semantic_info"
  503. %1 = OpExtInstImport "NonSemantic.Test"
  504. OpMemoryModel Logical GLSL450
  505. OpEntryPoint GLCompute %main "main"
  506. OpExecutionMode %main LocalSize 1 1 1
  507. %void = OpTypeVoid
  508. %void_fn = OpTypeFunction %void
  509. %main = OpFunction %void None %void_fn
  510. %main_entry = OpLabel
  511. OpReturn
  512. OpFunctionEnd
  513. %dead = OpFunction %void None %void_fn
  514. %dead_entry = OpLabel
  515. OpReturn
  516. OpFunctionEnd
  517. %2 = OpExtInst %void %1 1 %main
  518. %3 = OpExtInst %void %1 2 %2
  519. %4 = OpExtInst %void %1 3 %2 %3
  520. )";
  521. SetTargetEnv(SPV_ENV_VULKAN_1_0);
  522. SinglePassRunAndMatch<EliminateDeadFunctionsPass>(text, true);
  523. }
  524. } // namespace
  525. } // namespace opt
  526. } // namespace spvtools