2
0

block_merge_test.cpp 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330
  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 BlockMergeTest = PassTest<::testing::Test>;
  22. TEST_F(BlockMergeTest, Simple) {
  23. // Note: SPIR-V hand edited to insert block boundary
  24. // between two statements in main.
  25. //
  26. // #version 140
  27. //
  28. // in vec4 BaseColor;
  29. //
  30. // void main()
  31. // {
  32. // vec4 v = BaseColor;
  33. // gl_FragColor = v;
  34. // }
  35. const std::string predefs =
  36. R"(OpCapability Shader
  37. %1 = OpExtInstImport "GLSL.std.450"
  38. OpMemoryModel Logical GLSL450
  39. OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
  40. OpExecutionMode %main OriginUpperLeft
  41. OpSource GLSL 140
  42. OpName %main "main"
  43. OpName %v "v"
  44. OpName %BaseColor "BaseColor"
  45. OpName %gl_FragColor "gl_FragColor"
  46. %void = OpTypeVoid
  47. %7 = OpTypeFunction %void
  48. %float = OpTypeFloat 32
  49. %v4float = OpTypeVector %float 4
  50. %_ptr_Function_v4float = OpTypePointer Function %v4float
  51. %_ptr_Input_v4float = OpTypePointer Input %v4float
  52. %BaseColor = OpVariable %_ptr_Input_v4float Input
  53. %_ptr_Output_v4float = OpTypePointer Output %v4float
  54. %gl_FragColor = OpVariable %_ptr_Output_v4float Output
  55. )";
  56. const std::string before =
  57. R"(%main = OpFunction %void None %7
  58. %13 = OpLabel
  59. %v = OpVariable %_ptr_Function_v4float Function
  60. %14 = OpLoad %v4float %BaseColor
  61. OpStore %v %14
  62. OpBranch %15
  63. %15 = OpLabel
  64. %16 = OpLoad %v4float %v
  65. OpStore %gl_FragColor %16
  66. OpReturn
  67. OpFunctionEnd
  68. )";
  69. const std::string after =
  70. R"(%main = OpFunction %void None %7
  71. %13 = OpLabel
  72. %v = OpVariable %_ptr_Function_v4float Function
  73. %14 = OpLoad %v4float %BaseColor
  74. OpStore %v %14
  75. %16 = OpLoad %v4float %v
  76. OpStore %gl_FragColor %16
  77. OpReturn
  78. OpFunctionEnd
  79. )";
  80. SinglePassRunAndCheck<BlockMergePass>(predefs + before, predefs + after, true,
  81. true);
  82. }
  83. TEST_F(BlockMergeTest, BlockMergeForLinkage) {
  84. const std::string before =
  85. R"(OpCapability Shader
  86. OpCapability Linkage
  87. OpMemoryModel Logical GLSL450
  88. OpSource HLSL 630
  89. OpName %main "main"
  90. OpName %BaseColor "BaseColor"
  91. OpName %bb_entry "bb.entry"
  92. OpName %v "v"
  93. OpDecorate %main LinkageAttributes "main" Export
  94. %float = OpTypeFloat 32
  95. %v4float = OpTypeVector %float 4
  96. %_ptr_Function_v4float = OpTypePointer Function %v4float
  97. %8 = OpTypeFunction %v4float %_ptr_Function_v4float
  98. %main = OpFunction %v4float None %8
  99. %BaseColor = OpFunctionParameter %_ptr_Function_v4float
  100. %bb_entry = OpLabel
  101. %v = OpVariable %_ptr_Function_v4float Function
  102. %9 = OpLoad %v4float %BaseColor
  103. OpStore %v %9
  104. OpBranch %10
  105. %10 = OpLabel
  106. %11 = OpLoad %v4float %v
  107. OpBranch %12
  108. %12 = OpLabel
  109. OpReturnValue %11
  110. OpFunctionEnd
  111. )";
  112. const std::string after =
  113. R"(OpCapability Shader
  114. OpCapability Linkage
  115. OpMemoryModel Logical GLSL450
  116. OpSource HLSL 630
  117. OpName %main "main"
  118. OpName %BaseColor "BaseColor"
  119. OpName %bb_entry "bb.entry"
  120. OpName %v "v"
  121. OpDecorate %main LinkageAttributes "main" Export
  122. %float = OpTypeFloat 32
  123. %v4float = OpTypeVector %float 4
  124. %_ptr_Function_v4float = OpTypePointer Function %v4float
  125. %8 = OpTypeFunction %v4float %_ptr_Function_v4float
  126. %main = OpFunction %v4float None %8
  127. %BaseColor = OpFunctionParameter %_ptr_Function_v4float
  128. %bb_entry = OpLabel
  129. %v = OpVariable %_ptr_Function_v4float Function
  130. %9 = OpLoad %v4float %BaseColor
  131. OpStore %v %9
  132. %11 = OpLoad %v4float %v
  133. OpReturnValue %11
  134. OpFunctionEnd
  135. )";
  136. SinglePassRunAndCheck<BlockMergePass>(before, after, true, true);
  137. }
  138. TEST_F(BlockMergeTest, EmptyBlock) {
  139. // Note: SPIR-V hand edited to insert empty block
  140. // after two statements in main.
  141. //
  142. // #version 140
  143. //
  144. // in vec4 BaseColor;
  145. //
  146. // void main()
  147. // {
  148. // vec4 v = BaseColor;
  149. // gl_FragColor = v;
  150. // }
  151. const std::string predefs =
  152. R"(OpCapability Shader
  153. %1 = OpExtInstImport "GLSL.std.450"
  154. OpMemoryModel Logical GLSL450
  155. OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
  156. OpExecutionMode %main OriginUpperLeft
  157. OpSource GLSL 140
  158. OpName %main "main"
  159. OpName %v "v"
  160. OpName %BaseColor "BaseColor"
  161. OpName %gl_FragColor "gl_FragColor"
  162. %void = OpTypeVoid
  163. %7 = OpTypeFunction %void
  164. %float = OpTypeFloat 32
  165. %v4float = OpTypeVector %float 4
  166. %_ptr_Function_v4float = OpTypePointer Function %v4float
  167. %_ptr_Input_v4float = OpTypePointer Input %v4float
  168. %BaseColor = OpVariable %_ptr_Input_v4float Input
  169. %_ptr_Output_v4float = OpTypePointer Output %v4float
  170. %gl_FragColor = OpVariable %_ptr_Output_v4float Output
  171. )";
  172. const std::string before =
  173. R"(%main = OpFunction %void None %7
  174. %13 = OpLabel
  175. %v = OpVariable %_ptr_Function_v4float Function
  176. %14 = OpLoad %v4float %BaseColor
  177. OpStore %v %14
  178. OpBranch %15
  179. %15 = OpLabel
  180. %16 = OpLoad %v4float %v
  181. OpStore %gl_FragColor %16
  182. OpBranch %17
  183. %17 = OpLabel
  184. OpBranch %18
  185. %18 = OpLabel
  186. OpReturn
  187. OpFunctionEnd
  188. )";
  189. const std::string after =
  190. R"(%main = OpFunction %void None %7
  191. %13 = OpLabel
  192. %v = OpVariable %_ptr_Function_v4float Function
  193. %14 = OpLoad %v4float %BaseColor
  194. OpStore %v %14
  195. %16 = OpLoad %v4float %v
  196. OpStore %gl_FragColor %16
  197. OpReturn
  198. OpFunctionEnd
  199. )";
  200. SinglePassRunAndCheck<BlockMergePass>(predefs + before, predefs + after, true,
  201. true);
  202. }
  203. TEST_F(BlockMergeTest, NestedInControlFlow) {
  204. // Note: SPIR-V hand edited to insert block boundary
  205. // between OpFMul and OpStore in then-part.
  206. //
  207. // #version 140
  208. // in vec4 BaseColor;
  209. //
  210. // layout(std140) uniform U_t
  211. // {
  212. // bool g_B ;
  213. // } ;
  214. //
  215. // void main()
  216. // {
  217. // vec4 v = BaseColor;
  218. // if (g_B)
  219. // vec4 v = v * 0.25;
  220. // gl_FragColor = v;
  221. // }
  222. const std::string predefs =
  223. R"(OpCapability Shader
  224. %1 = OpExtInstImport "GLSL.std.450"
  225. OpMemoryModel Logical GLSL450
  226. OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
  227. OpExecutionMode %main OriginUpperLeft
  228. OpSource GLSL 140
  229. OpName %main "main"
  230. OpName %v "v"
  231. OpName %BaseColor "BaseColor"
  232. OpName %U_t "U_t"
  233. OpMemberName %U_t 0 "g_B"
  234. OpName %_ ""
  235. OpName %v_0 "v"
  236. OpName %gl_FragColor "gl_FragColor"
  237. OpMemberDecorate %U_t 0 Offset 0
  238. OpDecorate %U_t Block
  239. OpDecorate %_ DescriptorSet 0
  240. %void = OpTypeVoid
  241. %10 = OpTypeFunction %void
  242. %float = OpTypeFloat 32
  243. %v4float = OpTypeVector %float 4
  244. %_ptr_Function_v4float = OpTypePointer Function %v4float
  245. %_ptr_Input_v4float = OpTypePointer Input %v4float
  246. %BaseColor = OpVariable %_ptr_Input_v4float Input
  247. %uint = OpTypeInt 32 0
  248. %U_t = OpTypeStruct %uint
  249. %_ptr_Uniform_U_t = OpTypePointer Uniform %U_t
  250. %_ = OpVariable %_ptr_Uniform_U_t Uniform
  251. %int = OpTypeInt 32 1
  252. %int_0 = OpConstant %int 0
  253. %_ptr_Uniform_uint = OpTypePointer Uniform %uint
  254. %bool = OpTypeBool
  255. %uint_0 = OpConstant %uint 0
  256. %float_0_25 = OpConstant %float 0.25
  257. %_ptr_Output_v4float = OpTypePointer Output %v4float
  258. %gl_FragColor = OpVariable %_ptr_Output_v4float Output
  259. )";
  260. const std::string before =
  261. R"(%main = OpFunction %void None %10
  262. %24 = OpLabel
  263. %v = OpVariable %_ptr_Function_v4float Function
  264. %v_0 = OpVariable %_ptr_Function_v4float Function
  265. %25 = OpLoad %v4float %BaseColor
  266. OpStore %v %25
  267. %26 = OpAccessChain %_ptr_Uniform_uint %_ %int_0
  268. %27 = OpLoad %uint %26
  269. %28 = OpINotEqual %bool %27 %uint_0
  270. OpSelectionMerge %29 None
  271. OpBranchConditional %28 %30 %29
  272. %30 = OpLabel
  273. %31 = OpLoad %v4float %v
  274. %32 = OpVectorTimesScalar %v4float %31 %float_0_25
  275. OpBranch %33
  276. %33 = OpLabel
  277. OpStore %v_0 %32
  278. OpBranch %29
  279. %29 = OpLabel
  280. %34 = OpLoad %v4float %v
  281. OpStore %gl_FragColor %34
  282. OpReturn
  283. OpFunctionEnd
  284. )";
  285. const std::string after =
  286. R"(%main = OpFunction %void None %10
  287. %24 = OpLabel
  288. %v = OpVariable %_ptr_Function_v4float Function
  289. %v_0 = OpVariable %_ptr_Function_v4float Function
  290. %25 = OpLoad %v4float %BaseColor
  291. OpStore %v %25
  292. %26 = OpAccessChain %_ptr_Uniform_uint %_ %int_0
  293. %27 = OpLoad %uint %26
  294. %28 = OpINotEqual %bool %27 %uint_0
  295. OpSelectionMerge %29 None
  296. OpBranchConditional %28 %30 %29
  297. %30 = OpLabel
  298. %31 = OpLoad %v4float %v
  299. %32 = OpVectorTimesScalar %v4float %31 %float_0_25
  300. OpStore %v_0 %32
  301. OpBranch %29
  302. %29 = OpLabel
  303. %34 = OpLoad %v4float %v
  304. OpStore %gl_FragColor %34
  305. OpReturn
  306. OpFunctionEnd
  307. )";
  308. SinglePassRunAndCheck<BlockMergePass>(predefs + before, predefs + after, true,
  309. true);
  310. }
  311. TEST_F(BlockMergeTest, PhiInSuccessorOfMergedBlock) {
  312. const std::string text = R"(
  313. ; CHECK: OpSelectionMerge [[merge:%\w+]] None
  314. ; CHECK-NEXT: OpBranchConditional {{%\w+}} [[then:%\w+]] [[else:%\w+]]
  315. ; CHECK: [[then]] = OpLabel
  316. ; CHECK-NEXT: OpBranch [[merge]]
  317. ; CHECK: [[else]] = OpLabel
  318. ; CHECK-NEXT: OpBranch [[merge]]
  319. ; CHECK: [[merge]] = OpLabel
  320. ; CHECK-NEXT: OpPhi {{%\w+}} %true [[then]] %false [[else]]
  321. OpCapability Shader
  322. OpMemoryModel Logical GLSL450
  323. OpEntryPoint Fragment %func "func"
  324. OpExecutionMode %func OriginUpperLeft
  325. %void = OpTypeVoid
  326. %bool = OpTypeBool
  327. %true = OpConstantTrue %bool
  328. %false = OpConstantFalse %bool
  329. %functy = OpTypeFunction %void
  330. %func = OpFunction %void None %functy
  331. %entry = OpLabel
  332. OpSelectionMerge %merge None
  333. OpBranchConditional %true %then %else
  334. %then = OpLabel
  335. OpBranch %then_next
  336. %then_next = OpLabel
  337. OpBranch %merge
  338. %else = OpLabel
  339. OpBranch %merge
  340. %merge = OpLabel
  341. %phi = OpPhi %bool %true %then_next %false %else
  342. OpReturn
  343. OpFunctionEnd
  344. )";
  345. SinglePassRunAndMatch<BlockMergePass>(text, true);
  346. }
  347. TEST_F(BlockMergeTest, UpdateMergeInstruction) {
  348. const std::string text = R"(
  349. ; CHECK: OpSelectionMerge [[merge:%\w+]] None
  350. ; CHECK-NEXT: OpBranchConditional {{%\w+}} [[then:%\w+]] [[else:%\w+]]
  351. ; CHECK: [[then]] = OpLabel
  352. ; CHECK-NEXT: OpBranch [[merge]]
  353. ; CHECK: [[else]] = OpLabel
  354. ; CHECK-NEXT: OpBranch [[merge]]
  355. ; CHECK: [[merge]] = OpLabel
  356. ; CHECK-NEXT: OpReturn
  357. OpCapability Shader
  358. OpMemoryModel Logical GLSL450
  359. OpEntryPoint Fragment %func "func"
  360. OpExecutionMode %func OriginUpperLeft
  361. %void = OpTypeVoid
  362. %bool = OpTypeBool
  363. %true = OpConstantTrue %bool
  364. %false = OpConstantFalse %bool
  365. %functy = OpTypeFunction %void
  366. %func = OpFunction %void None %functy
  367. %entry = OpLabel
  368. OpSelectionMerge %real_merge None
  369. OpBranchConditional %true %then %else
  370. %then = OpLabel
  371. OpBranch %merge
  372. %else = OpLabel
  373. OpBranch %merge
  374. %merge = OpLabel
  375. OpBranch %real_merge
  376. %real_merge = OpLabel
  377. OpReturn
  378. OpFunctionEnd
  379. )";
  380. SinglePassRunAndMatch<BlockMergePass>(text, true);
  381. }
  382. TEST_F(BlockMergeTest, TwoMergeBlocksCannotBeMerged) {
  383. const std::string text = R"(
  384. ; CHECK: OpSelectionMerge [[outer_merge:%\w+]] None
  385. ; CHECK: OpSelectionMerge [[inner_merge:%\w+]] None
  386. ; CHECK: [[inner_merge]] = OpLabel
  387. ; CHECK-NEXT: OpBranch [[outer_merge]]
  388. ; CHECK: [[outer_merge]] = OpLabel
  389. ; CHECK-NEXT: OpReturn
  390. OpCapability Shader
  391. OpMemoryModel Logical GLSL450
  392. OpEntryPoint Fragment %func "func"
  393. OpExecutionMode %func OriginUpperLeft
  394. %void = OpTypeVoid
  395. %bool = OpTypeBool
  396. %true = OpConstantTrue %bool
  397. %false = OpConstantFalse %bool
  398. %functy = OpTypeFunction %void
  399. %func = OpFunction %void None %functy
  400. %entry = OpLabel
  401. OpSelectionMerge %outer_merge None
  402. OpBranchConditional %true %then %else
  403. %then = OpLabel
  404. OpBranch %inner_header
  405. %else = OpLabel
  406. OpBranch %inner_header
  407. %inner_header = OpLabel
  408. OpSelectionMerge %inner_merge None
  409. OpBranchConditional %true %inner_then %inner_else
  410. %inner_then = OpLabel
  411. OpBranch %inner_merge
  412. %inner_else = OpLabel
  413. OpBranch %inner_merge
  414. %inner_merge = OpLabel
  415. OpBranch %outer_merge
  416. %outer_merge = OpLabel
  417. OpReturn
  418. OpFunctionEnd
  419. )";
  420. SinglePassRunAndMatch<BlockMergePass>(text, true);
  421. }
  422. TEST_F(BlockMergeTest, MergeContinue) {
  423. const std::string text = R"(
  424. ; CHECK: OpBranch [[header:%\w+]]
  425. ; CHECK: [[header]] = OpLabel
  426. ; CHECK-NEXT: OpLogicalAnd
  427. ; CHECK-NEXT: OpLoopMerge {{%\w+}} [[header]] None
  428. ; CHECK-NEXT: OpBranch [[header]]
  429. OpCapability Shader
  430. OpMemoryModel Logical GLSL450
  431. OpEntryPoint Fragment %func "func"
  432. OpExecutionMode %func OriginUpperLeft
  433. %void = OpTypeVoid
  434. %bool = OpTypeBool
  435. %true = OpConstantTrue %bool
  436. %false = OpConstantFalse %bool
  437. %functy = OpTypeFunction %void
  438. %func = OpFunction %void None %functy
  439. %entry = OpLabel
  440. OpBranch %header
  441. %header = OpLabel
  442. OpLoopMerge %merge %continue None
  443. OpBranch %continue
  444. %continue = OpLabel
  445. %op = OpLogicalAnd %bool %true %false
  446. OpBranch %header
  447. %merge = OpLabel
  448. OpUnreachable
  449. OpFunctionEnd
  450. )";
  451. SinglePassRunAndMatch<BlockMergePass>(text, true);
  452. }
  453. TEST_F(BlockMergeTest, MergeContinueWithOpLine) {
  454. const std::string text = R"(
  455. ; CHECK: OpBranch [[header:%\w+]]
  456. ; CHECK: [[header]] = OpLabel
  457. ; CHECK-NEXT: OpLogicalAnd
  458. ; CHECK-NEXT: OpLine {{%\w+}} 1 1
  459. ; CHECK-NEXT: OpLoopMerge {{%\w+}} [[header]] None
  460. ; CHECK-NEXT: OpBranch [[header]]
  461. OpCapability Shader
  462. OpMemoryModel Logical GLSL450
  463. OpEntryPoint Fragment %func "func"
  464. OpExecutionMode %func OriginUpperLeft
  465. %src = OpString "test.shader"
  466. %void = OpTypeVoid
  467. %bool = OpTypeBool
  468. %true = OpConstantTrue %bool
  469. %false = OpConstantFalse %bool
  470. %functy = OpTypeFunction %void
  471. %func = OpFunction %void None %functy
  472. %entry = OpLabel
  473. OpBranch %header
  474. %header = OpLabel
  475. OpLoopMerge %merge %continue None
  476. OpBranch %continue
  477. %continue = OpLabel
  478. %op = OpLogicalAnd %bool %true %false
  479. OpLine %src 1 1
  480. OpBranch %header
  481. %merge = OpLabel
  482. OpUnreachable
  483. OpFunctionEnd
  484. )";
  485. SinglePassRunAndMatch<BlockMergePass>(text, true);
  486. }
  487. TEST_F(BlockMergeTest, TwoHeadersCannotBeMerged) {
  488. const std::string text = R"(
  489. ; CHECK: OpBranch [[loop_header:%\w+]]
  490. ; CHECK: [[loop_header]] = OpLabel
  491. ; CHECK-NEXT: OpLoopMerge
  492. ; CHECK-NEXT: OpBranch [[if_header:%\w+]]
  493. ; CHECK: [[if_header]] = OpLabel
  494. ; CHECK-NEXT: OpSelectionMerge
  495. OpCapability Shader
  496. OpMemoryModel Logical GLSL450
  497. OpEntryPoint Fragment %func "func"
  498. OpExecutionMode %func OriginUpperLeft
  499. %void = OpTypeVoid
  500. %bool = OpTypeBool
  501. %true = OpConstantTrue %bool
  502. %false = OpConstantFalse %bool
  503. %functy = OpTypeFunction %void
  504. %func = OpFunction %void None %functy
  505. %entry = OpLabel
  506. OpBranch %header
  507. %header = OpLabel
  508. OpLoopMerge %merge %continue None
  509. OpBranch %inner_header
  510. %inner_header = OpLabel
  511. OpSelectionMerge %if_merge None
  512. OpBranchConditional %true %then %if_merge
  513. %then = OpLabel
  514. OpBranch %continue
  515. %if_merge = OpLabel
  516. OpBranch %continue
  517. %continue = OpLabel
  518. OpBranchConditional %false %merge %header
  519. %merge = OpLabel
  520. OpReturn
  521. OpFunctionEnd
  522. )";
  523. SinglePassRunAndMatch<BlockMergePass>(text, true);
  524. }
  525. TEST_F(BlockMergeTest, CannotMergeContinue) {
  526. const std::string text = R"(
  527. ; CHECK: OpBranch [[loop_header:%\w+]]
  528. ; CHECK: [[loop_header]] = OpLabel
  529. ; CHECK-NEXT: OpLoopMerge {{%\w+}} [[continue:%\w+]]
  530. ; CHECK-NEXT: OpBranchConditional {{%\w+}} [[if_header:%\w+]]
  531. ; CHECK: [[if_header]] = OpLabel
  532. ; CHECK-NEXT: OpSelectionMerge
  533. ; CHECK: [[continue]] = OpLabel
  534. OpCapability Shader
  535. OpMemoryModel Logical GLSL450
  536. OpEntryPoint Fragment %func "func"
  537. OpExecutionMode %func OriginUpperLeft
  538. %void = OpTypeVoid
  539. %bool = OpTypeBool
  540. %true = OpConstantTrue %bool
  541. %false = OpConstantFalse %bool
  542. %functy = OpTypeFunction %void
  543. %func = OpFunction %void None %functy
  544. %entry = OpLabel
  545. OpBranch %header
  546. %header = OpLabel
  547. OpLoopMerge %merge %continue None
  548. OpBranchConditional %true %inner_header %merge
  549. %inner_header = OpLabel
  550. OpSelectionMerge %if_merge None
  551. OpBranchConditional %true %then %if_merge
  552. %then = OpLabel
  553. OpBranch %continue
  554. %if_merge = OpLabel
  555. OpBranch %continue
  556. %continue = OpLabel
  557. OpBranchConditional %false %merge %header
  558. %merge = OpLabel
  559. OpReturn
  560. OpFunctionEnd
  561. )";
  562. SinglePassRunAndMatch<BlockMergePass>(text, true);
  563. }
  564. TEST_F(BlockMergeTest, RemoveStructuredDeclaration) {
  565. // Note: SPIR-V hand edited remove dead branch and add block
  566. // before continue block
  567. //
  568. // #version 140
  569. // in vec4 BaseColor;
  570. //
  571. // void main()
  572. // {
  573. // while (true) {
  574. // break;
  575. // }
  576. // gl_FragColor = BaseColor;
  577. // }
  578. const std::string assembly =
  579. R"(
  580. ; CHECK: OpLabel
  581. ; CHECK: [[header:%\w+]] = OpLabel
  582. ; CHECK-NOT: OpLoopMerge
  583. ; CHECK: OpReturn
  584. ; CHECK: [[continue:%\w+]] = OpLabel
  585. ; CHECK-NEXT: OpBranch [[block:%\w+]]
  586. ; CHECK: [[block]] = OpLabel
  587. ; CHECK-NEXT: OpBranch [[header]]
  588. OpCapability Shader
  589. %1 = OpExtInstImport "GLSL.std.450"
  590. OpMemoryModel Logical GLSL450
  591. OpEntryPoint Fragment %main "main" %gl_FragColor %BaseColor
  592. OpExecutionMode %main OriginUpperLeft
  593. OpSource GLSL 140
  594. OpName %main "main"
  595. OpName %gl_FragColor "gl_FragColor"
  596. OpName %BaseColor "BaseColor"
  597. %void = OpTypeVoid
  598. %6 = OpTypeFunction %void
  599. %bool = OpTypeBool
  600. %true = OpConstantTrue %bool
  601. %float = OpTypeFloat 32
  602. %v4float = OpTypeVector %float 4
  603. %_ptr_Output_v4float = OpTypePointer Output %v4float
  604. %gl_FragColor = OpVariable %_ptr_Output_v4float Output
  605. %_ptr_Input_v4float = OpTypePointer Input %v4float
  606. %BaseColor = OpVariable %_ptr_Input_v4float Input
  607. %main = OpFunction %void None %6
  608. %13 = OpLabel
  609. OpBranch %14
  610. %14 = OpLabel
  611. OpLoopMerge %15 %16 None
  612. OpBranch %17
  613. %17 = OpLabel
  614. OpBranch %15
  615. %18 = OpLabel
  616. OpBranch %16
  617. %16 = OpLabel
  618. OpBranch %14
  619. %15 = OpLabel
  620. %19 = OpLoad %v4float %BaseColor
  621. OpStore %gl_FragColor %19
  622. OpReturn
  623. OpFunctionEnd
  624. )";
  625. SinglePassRunAndMatch<BlockMergePass>(assembly, true);
  626. }
  627. TEST_F(BlockMergeTest, DontMergeKill) {
  628. const std::string text = R"(
  629. ; CHECK: OpLoopMerge [[merge:%\w+]] [[cont:%\w+]] None
  630. ; CHECK-NEXT: OpBranch [[ret:%\w+]]
  631. ; CHECK: [[ret:%\w+]] = OpLabel
  632. ; CHECK-NEXT: OpKill
  633. ; CHECK-DAG: [[cont]] = OpLabel
  634. ; CHECK-DAG: [[merge]] = OpLabel
  635. OpCapability Shader
  636. OpMemoryModel Logical GLSL450
  637. OpEntryPoint Fragment %func "func"
  638. OpExecutionMode %func OriginUpperLeft
  639. %void = OpTypeVoid
  640. %bool = OpTypeBool
  641. %functy = OpTypeFunction %void
  642. %func = OpFunction %void None %functy
  643. %1 = OpLabel
  644. OpBranch %2
  645. %2 = OpLabel
  646. OpLoopMerge %3 %4 None
  647. OpBranch %5
  648. %5 = OpLabel
  649. OpKill
  650. %4 = OpLabel
  651. OpBranch %2
  652. %3 = OpLabel
  653. OpUnreachable
  654. OpFunctionEnd
  655. )";
  656. SinglePassRunAndMatch<BlockMergePass>(text, true);
  657. }
  658. TEST_F(BlockMergeTest, DontMergeTerminateInvocation) {
  659. const std::string text = R"(
  660. ; CHECK: OpLoopMerge [[merge:%\w+]] [[cont:%\w+]] None
  661. ; CHECK-NEXT: OpBranch [[ret:%\w+]]
  662. ; CHECK: [[ret:%\w+]] = OpLabel
  663. ; CHECK-NEXT: OpTerminateInvocation
  664. ; CHECK-DAG: [[cont]] = OpLabel
  665. ; CHECK-DAG: [[merge]] = OpLabel
  666. OpCapability Shader
  667. OpExtension "SPV_KHR_terminate_invocation"
  668. OpMemoryModel Logical GLSL450
  669. OpEntryPoint Fragment %func "func"
  670. OpExecutionMode %func OriginUpperLeft
  671. %void = OpTypeVoid
  672. %bool = OpTypeBool
  673. %functy = OpTypeFunction %void
  674. %func = OpFunction %void None %functy
  675. %1 = OpLabel
  676. OpBranch %2
  677. %2 = OpLabel
  678. OpLoopMerge %3 %4 None
  679. OpBranch %5
  680. %5 = OpLabel
  681. OpTerminateInvocation
  682. %4 = OpLabel
  683. OpBranch %2
  684. %3 = OpLabel
  685. OpUnreachable
  686. OpFunctionEnd
  687. )";
  688. SinglePassRunAndMatch<BlockMergePass>(text, true);
  689. }
  690. TEST_F(BlockMergeTest, DontMergeUnreachable) {
  691. const std::string text = R"(
  692. ; CHECK: OpLoopMerge [[merge:%\w+]] [[cont:%\w+]] None
  693. ; CHECK-NEXT: OpBranch [[ret:%\w+]]
  694. ; CHECK: [[ret:%\w+]] = OpLabel
  695. ; CHECK-NEXT: OpUnreachable
  696. ; CHECK-DAG: [[cont]] = OpLabel
  697. ; CHECK-DAG: [[merge]] = OpLabel
  698. OpCapability Shader
  699. OpMemoryModel Logical GLSL450
  700. OpEntryPoint Fragment %func "func"
  701. OpExecutionMode %func OriginUpperLeft
  702. %void = OpTypeVoid
  703. %bool = OpTypeBool
  704. %functy = OpTypeFunction %void
  705. %func = OpFunction %void None %functy
  706. %1 = OpLabel
  707. OpBranch %2
  708. %2 = OpLabel
  709. OpLoopMerge %3 %4 None
  710. OpBranch %5
  711. %5 = OpLabel
  712. OpUnreachable
  713. %4 = OpLabel
  714. OpBranch %2
  715. %3 = OpLabel
  716. OpUnreachable
  717. OpFunctionEnd
  718. )";
  719. SinglePassRunAndMatch<BlockMergePass>(text, false);
  720. }
  721. TEST_F(BlockMergeTest, DontMergeReturn) {
  722. const std::string text = R"(
  723. ; CHECK: OpLoopMerge [[merge:%\w+]] [[cont:%\w+]] None
  724. ; CHECK-NEXT: OpBranch [[ret:%\w+]]
  725. ; CHECK: [[ret:%\w+]] = OpLabel
  726. ; CHECK-NEXT: OpReturn
  727. ; CHECK-DAG: [[cont]] = OpLabel
  728. ; CHECK-DAG: [[merge]] = OpLabel
  729. OpCapability Shader
  730. OpMemoryModel Logical GLSL450
  731. OpEntryPoint Fragment %func "func"
  732. OpExecutionMode %func OriginUpperLeft
  733. %void = OpTypeVoid
  734. %bool = OpTypeBool
  735. %functy = OpTypeFunction %void
  736. %func = OpFunction %void None %functy
  737. %1 = OpLabel
  738. OpBranch %2
  739. %2 = OpLabel
  740. OpLoopMerge %3 %4 None
  741. OpBranch %5
  742. %5 = OpLabel
  743. OpReturn
  744. %4 = OpLabel
  745. OpBranch %2
  746. %3 = OpLabel
  747. OpUnreachable
  748. OpFunctionEnd
  749. )";
  750. SinglePassRunAndMatch<BlockMergePass>(text, true);
  751. }
  752. TEST_F(BlockMergeTest, DontMergeSwitch) {
  753. const std::string text = R"(
  754. ; CHECK: OpLoopMerge [[merge:%\w+]] [[cont:%\w+]] None
  755. ; CHECK-NEXT: OpBranch [[ret:%\w+]]
  756. ; CHECK: [[ret:%\w+]] = OpLabel
  757. ; CHECK-NEXT: OpSelectionMerge
  758. ; CHECK-NEXT: OpSwitch
  759. ; CHECK-DAG: [[cont]] = OpLabel
  760. ; CHECK-DAG: [[merge]] = OpLabel
  761. OpCapability Shader
  762. OpMemoryModel Logical GLSL450
  763. OpEntryPoint Fragment %func "func"
  764. OpExecutionMode %func OriginUpperLeft
  765. %void = OpTypeVoid
  766. %bool = OpTypeBool
  767. %int = OpTypeInt 32 1
  768. %int_0 = OpConstant %int 0
  769. %functy = OpTypeFunction %void
  770. %func = OpFunction %void None %functy
  771. %1 = OpLabel
  772. OpBranch %2
  773. %2 = OpLabel
  774. OpLoopMerge %3 %4 None
  775. OpBranch %5
  776. %5 = OpLabel
  777. OpSelectionMerge %6 None
  778. OpSwitch %int_0 %6
  779. %6 = OpLabel
  780. OpReturn
  781. %4 = OpLabel
  782. OpBranch %2
  783. %3 = OpLabel
  784. OpUnreachable
  785. OpFunctionEnd
  786. )";
  787. SinglePassRunAndMatch<BlockMergePass>(text, true);
  788. }
  789. TEST_F(BlockMergeTest, DontMergeReturnValue) {
  790. const std::string text = R"(
  791. ; CHECK: OpLoopMerge [[merge:%\w+]] [[cont:%\w+]] None
  792. ; CHECK-NEXT: OpBranch [[ret:%\w+]]
  793. ; CHECK: [[ret:%\w+]] = OpLabel
  794. ; CHECK-NEXT: OpReturn
  795. ; CHECK-DAG: [[cont]] = OpLabel
  796. ; CHECK-DAG: [[merge]] = OpLabel
  797. OpCapability Shader
  798. OpMemoryModel Logical GLSL450
  799. OpEntryPoint Fragment %func "func"
  800. OpExecutionMode %func OriginUpperLeft
  801. %void = OpTypeVoid
  802. %bool = OpTypeBool
  803. %functy = OpTypeFunction %void
  804. %otherfuncty = OpTypeFunction %bool
  805. %true = OpConstantTrue %bool
  806. %func = OpFunction %void None %functy
  807. %1 = OpLabel
  808. %2 = OpFunctionCall %bool %3
  809. OpReturn
  810. OpFunctionEnd
  811. %3 = OpFunction %bool None %otherfuncty
  812. %4 = OpLabel
  813. OpBranch %5
  814. %5 = OpLabel
  815. OpLoopMerge %6 %7 None
  816. OpBranch %8
  817. %8 = OpLabel
  818. OpReturnValue %true
  819. %7 = OpLabel
  820. OpBranch %5
  821. %6 = OpLabel
  822. OpUnreachable
  823. OpFunctionEnd
  824. )";
  825. SinglePassRunAndMatch<BlockMergePass>(text, true);
  826. }
  827. TEST_F(BlockMergeTest, MergeHeaders) {
  828. // Merge two headers when the second is the merge block of the first.
  829. const std::string text = R"(
  830. ; CHECK: OpFunction
  831. ; CHECK-NEXT: OpLabel
  832. ; CHECK-NEXT: OpBranch [[header:%\w+]]
  833. ; CHECK-NEXT: [[header]] = OpLabel
  834. ; CHECK-NEXT: OpSelectionMerge [[merge:%\w+]]
  835. ; CHECK: [[merge]] = OpLabel
  836. ; CHECK: OpReturn
  837. OpCapability Shader
  838. OpMemoryModel Logical GLSL450
  839. OpEntryPoint Fragment %func "func"
  840. OpExecutionMode %func OriginUpperLeft
  841. %void = OpTypeVoid
  842. %bool = OpTypeBool
  843. %functy = OpTypeFunction %void
  844. %otherfuncty = OpTypeFunction %bool
  845. %true = OpConstantTrue %bool
  846. %func = OpFunction %void None %functy
  847. %1 = OpLabel
  848. OpBranch %5
  849. %5 = OpLabel
  850. OpLoopMerge %8 %7 None
  851. OpBranch %8
  852. %7 = OpLabel
  853. OpBranch %5
  854. %8 = OpLabel
  855. OpSelectionMerge %m None
  856. OpBranchConditional %true %a %m
  857. %a = OpLabel
  858. OpBranch %m
  859. %m = OpLabel
  860. OpReturn
  861. OpFunctionEnd
  862. )";
  863. SinglePassRunAndMatch<BlockMergePass>(text, true);
  864. }
  865. TEST_F(BlockMergeTest, OpPhiInSuccessor) {
  866. // Checks that when merging blocks A and B, the OpPhi at the start of B is
  867. // removed and uses of its definition are replaced appropriately.
  868. const std::string prefix =
  869. R"(OpCapability Shader
  870. %1 = OpExtInstImport "GLSL.std.450"
  871. OpMemoryModel Logical GLSL450
  872. OpEntryPoint Fragment %main "main"
  873. OpExecutionMode %main OriginUpperLeft
  874. OpSource ESSL 310
  875. OpName %main "main"
  876. OpName %x "x"
  877. OpName %y "y"
  878. %void = OpTypeVoid
  879. %6 = OpTypeFunction %void
  880. %int = OpTypeInt 32 1
  881. %_ptr_Function_int = OpTypePointer Function %int
  882. %int_1 = OpConstant %int 1
  883. %main = OpFunction %void None %6
  884. %10 = OpLabel
  885. %x = OpVariable %_ptr_Function_int Function
  886. %y = OpVariable %_ptr_Function_int Function
  887. OpStore %x %int_1
  888. %11 = OpLoad %int %x
  889. )";
  890. const std::string suffix_before =
  891. R"(OpBranch %12
  892. %12 = OpLabel
  893. %13 = OpPhi %int %11 %10
  894. OpStore %y %13
  895. OpReturn
  896. OpFunctionEnd
  897. )";
  898. const std::string suffix_after =
  899. R"(OpStore %y %11
  900. OpReturn
  901. OpFunctionEnd
  902. )";
  903. SinglePassRunAndCheck<BlockMergePass>(prefix + suffix_before,
  904. prefix + suffix_after, true, true);
  905. }
  906. TEST_F(BlockMergeTest, MultipleOpPhisInSuccessor) {
  907. // Checks that when merging blocks A and B, the OpPhis at the start of B are
  908. // removed and uses of their definitions are replaced appropriately.
  909. const std::string prefix =
  910. R"(OpCapability Shader
  911. %1 = OpExtInstImport "GLSL.std.450"
  912. OpMemoryModel Logical GLSL450
  913. OpEntryPoint Fragment %main "main"
  914. OpExecutionMode %main OriginUpperLeft
  915. OpSource ESSL 310
  916. OpName %main "main"
  917. OpName %S "S"
  918. OpMemberName %S 0 "x"
  919. OpMemberName %S 1 "f"
  920. OpName %s "s"
  921. OpName %g "g"
  922. OpName %y "y"
  923. OpName %t "t"
  924. OpName %z "z"
  925. %void = OpTypeVoid
  926. %10 = OpTypeFunction %void
  927. %int = OpTypeInt 32 1
  928. %float = OpTypeFloat 32
  929. %S = OpTypeStruct %int %float
  930. %_ptr_Function_S = OpTypePointer Function %S
  931. %int_1 = OpConstant %int 1
  932. %float_2 = OpConstant %float 2
  933. %16 = OpConstantComposite %S %int_1 %float_2
  934. %_ptr_Function_float = OpTypePointer Function %float
  935. %_ptr_Function_int = OpTypePointer Function %int
  936. %int_3 = OpConstant %int 3
  937. %int_0 = OpConstant %int 0
  938. %main = OpFunction %void None %10
  939. %21 = OpLabel
  940. %s = OpVariable %_ptr_Function_S Function
  941. %g = OpVariable %_ptr_Function_float Function
  942. %y = OpVariable %_ptr_Function_int Function
  943. %t = OpVariable %_ptr_Function_S Function
  944. %z = OpVariable %_ptr_Function_float Function
  945. OpStore %s %16
  946. OpStore %g %float_2
  947. OpStore %y %int_3
  948. %22 = OpLoad %S %s
  949. OpStore %t %22
  950. %23 = OpAccessChain %_ptr_Function_float %s %int_1
  951. %24 = OpLoad %float %23
  952. %25 = OpLoad %float %g
  953. )";
  954. const std::string suffix_before =
  955. R"(OpBranch %26
  956. %26 = OpLabel
  957. %27 = OpPhi %float %24 %21
  958. %28 = OpPhi %float %25 %21
  959. %29 = OpFAdd %float %27 %28
  960. %30 = OpAccessChain %_ptr_Function_int %s %int_0
  961. %31 = OpLoad %int %30
  962. OpBranch %32
  963. %32 = OpLabel
  964. %33 = OpPhi %float %29 %26
  965. %34 = OpPhi %int %31 %26
  966. %35 = OpConvertSToF %float %34
  967. OpBranch %36
  968. %36 = OpLabel
  969. %37 = OpPhi %float %35 %32
  970. %38 = OpFSub %float %33 %37
  971. %39 = OpLoad %int %y
  972. OpBranch %40
  973. %40 = OpLabel
  974. %41 = OpPhi %float %38 %36
  975. %42 = OpPhi %int %39 %36
  976. %43 = OpConvertSToF %float %42
  977. %44 = OpFAdd %float %41 %43
  978. OpStore %z %44
  979. OpReturn
  980. OpFunctionEnd
  981. )";
  982. const std::string suffix_after =
  983. R"(%29 = OpFAdd %float %24 %25
  984. %30 = OpAccessChain %_ptr_Function_int %s %int_0
  985. %31 = OpLoad %int %30
  986. %35 = OpConvertSToF %float %31
  987. %38 = OpFSub %float %29 %35
  988. %39 = OpLoad %int %y
  989. %43 = OpConvertSToF %float %39
  990. %44 = OpFAdd %float %38 %43
  991. OpStore %z %44
  992. OpReturn
  993. OpFunctionEnd
  994. )";
  995. SinglePassRunAndCheck<BlockMergePass>(prefix + suffix_before,
  996. prefix + suffix_after, true, true);
  997. }
  998. TEST_F(BlockMergeTest, UnreachableLoop) {
  999. const std::string spirv = R"(OpCapability Shader
  1000. %1 = OpExtInstImport "GLSL.std.450"
  1001. OpMemoryModel Logical GLSL450
  1002. OpEntryPoint Fragment %main "main"
  1003. OpExecutionMode %main OriginUpperLeft
  1004. OpSource ESSL 310
  1005. OpName %main "main"
  1006. %void = OpTypeVoid
  1007. %4 = OpTypeFunction %void
  1008. %int = OpTypeInt 32 1
  1009. %_ptr_Function_int = OpTypePointer Function %int
  1010. %bool = OpTypeBool
  1011. %false = OpConstantFalse %bool
  1012. %main = OpFunction %void None %4
  1013. %9 = OpLabel
  1014. OpBranch %10
  1015. %11 = OpLabel
  1016. OpLoopMerge %12 %13 None
  1017. OpBranchConditional %false %13 %14
  1018. %13 = OpLabel
  1019. OpSelectionMerge %15 None
  1020. OpBranchConditional %false %16 %17
  1021. %16 = OpLabel
  1022. OpBranch %15
  1023. %17 = OpLabel
  1024. OpBranch %15
  1025. %15 = OpLabel
  1026. OpBranch %11
  1027. %14 = OpLabel
  1028. OpReturn
  1029. %12 = OpLabel
  1030. OpBranch %10
  1031. %10 = OpLabel
  1032. OpReturn
  1033. OpFunctionEnd
  1034. )";
  1035. SinglePassRunAndCheck<BlockMergePass>(spirv, spirv, true, true);
  1036. }
  1037. TEST_F(BlockMergeTest, DebugMerge) {
  1038. // Verify merge can be done completely, cleanly and validly in presence of
  1039. // NonSemantic.Shader.DebugInfo.100 instructions
  1040. const std::string text = R"(
  1041. ; CHECK: OpLoopMerge
  1042. ; CHECK-NEXT: OpBranch
  1043. ; CHECK-NOT: OpBranch
  1044. OpCapability Shader
  1045. OpExtension "SPV_KHR_non_semantic_info"
  1046. %1 = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
  1047. OpMemoryModel Logical GLSL450
  1048. OpEntryPoint Fragment %main "main" %in_var_COLOR %out_var_SV_TARGET
  1049. OpExecutionMode %main OriginUpperLeft
  1050. %5 = OpString "lexblock.hlsl"
  1051. %20 = OpString "float"
  1052. %32 = OpString "main"
  1053. %33 = OpString ""
  1054. %46 = OpString "b"
  1055. %49 = OpString "a"
  1056. %58 = OpString "c"
  1057. %63 = OpString "color"
  1058. OpName %in_var_COLOR "in.var.COLOR"
  1059. OpName %out_var_SV_TARGET "out.var.SV_TARGET"
  1060. OpName %main "main"
  1061. OpDecorate %in_var_COLOR Location 0
  1062. OpDecorate %out_var_SV_TARGET Location 0
  1063. %float = OpTypeFloat 32
  1064. %float_0 = OpConstant %float 0
  1065. %v4float = OpTypeVector %float 4
  1066. %9 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
  1067. %float_1 = OpConstant %float 1
  1068. %13 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
  1069. %uint = OpTypeInt 32 0
  1070. %uint_32 = OpConstant %uint 32
  1071. %_ptr_Input_v4float = OpTypePointer Input %v4float
  1072. %_ptr_Output_v4float = OpTypePointer Output %v4float
  1073. %void = OpTypeVoid
  1074. %uint_3 = OpConstant %uint 3
  1075. %uint_0 = OpConstant %uint 0
  1076. %uint_4 = OpConstant %uint 4
  1077. %uint_1 = OpConstant %uint 1
  1078. %uint_5 = OpConstant %uint 5
  1079. %uint_12 = OpConstant %uint 12
  1080. %uint_13 = OpConstant %uint 13
  1081. %uint_20 = OpConstant %uint 20
  1082. %uint_15 = OpConstant %uint 15
  1083. %uint_17 = OpConstant %uint 17
  1084. %uint_16 = OpConstant %uint 16
  1085. %uint_14 = OpConstant %uint 14
  1086. %uint_10 = OpConstant %uint 10
  1087. %65 = OpTypeFunction %void
  1088. %in_var_COLOR = OpVariable %_ptr_Input_v4float Input
  1089. %out_var_SV_TARGET = OpVariable %_ptr_Output_v4float Output
  1090. %62 = OpExtInst %void %1 DebugExpression
  1091. %22 = OpExtInst %void %1 DebugTypeBasic %20 %uint_32 %uint_3 %uint_0
  1092. %25 = OpExtInst %void %1 DebugTypeVector %22 %uint_4
  1093. %27 = OpExtInst %void %1 DebugTypeFunction %uint_3 %25 %25
  1094. %28 = OpExtInst %void %1 DebugSource %5
  1095. %29 = OpExtInst %void %1 DebugCompilationUnit %uint_1 %uint_4 %28 %uint_5
  1096. %34 = OpExtInst %void %1 DebugFunction %32 %27 %28 %uint_12 %uint_1 %29 %33 %uint_3 %uint_13
  1097. %37 = OpExtInst %void %1 DebugLexicalBlock %28 %uint_13 %uint_1 %34
  1098. %52 = OpExtInst %void %1 DebugLexicalBlock %28 %uint_15 %uint_12 %37
  1099. %54 = OpExtInst %void %1 DebugLocalVariable %46 %25 %28 %uint_17 %uint_12 %52 %uint_4
  1100. %56 = OpExtInst %void %1 DebugLocalVariable %49 %25 %28 %uint_16 %uint_12 %52 %uint_4
  1101. %59 = OpExtInst %void %1 DebugLocalVariable %58 %25 %28 %uint_14 %uint_10 %37 %uint_4
  1102. %64 = OpExtInst %void %1 DebugLocalVariable %63 %25 %28 %uint_12 %uint_20 %34 %uint_4 %uint_1
  1103. %main = OpFunction %void None %65
  1104. %66 = OpLabel
  1105. %69 = OpLoad %v4float %in_var_COLOR
  1106. %168 = OpExtInst %void %1 DebugValue %64 %69 %62
  1107. %169 = OpExtInst %void %1 DebugScope %37
  1108. OpLine %5 14 10
  1109. %164 = OpExtInst %void %1 DebugValue %59 %9 %62
  1110. OpLine %5 15 3
  1111. OpBranch %150
  1112. %150 = OpLabel
  1113. %165 = OpPhi %v4float %9 %66 %158 %159
  1114. %167 = OpExtInst %void %1 DebugValue %59 %165 %62
  1115. %170 = OpExtInst %void %1 DebugScope %37
  1116. OpLine %5 15 12
  1117. %171 = OpExtInst %void %1 DebugNoScope
  1118. OpLoopMerge %160 %159 None
  1119. OpBranch %151
  1120. %151 = OpLabel
  1121. OpLine %5 16 12
  1122. %162 = OpExtInst %void %1 DebugValue %56 %9 %62
  1123. OpLine %5 17 12
  1124. %163 = OpExtInst %void %1 DebugValue %54 %13 %62
  1125. OpLine %5 18 15
  1126. %158 = OpFAdd %v4float %165 %13
  1127. OpLine %5 18 5
  1128. %166 = OpExtInst %void %1 DebugValue %59 %158 %62
  1129. %172 = OpExtInst %void %1 DebugScope %37
  1130. OpLine %5 19 3
  1131. OpBranch %159
  1132. %159 = OpLabel
  1133. OpLine %5 19 3
  1134. OpBranch %150
  1135. %160 = OpLabel
  1136. OpUnreachable
  1137. OpFunctionEnd
  1138. )";
  1139. SinglePassRunAndMatch<BlockMergePass>(text, true);
  1140. }
  1141. TEST_F(BlockMergeTest, DontLoseCaseConstruct) {
  1142. const std::string text = R"(
  1143. OpCapability Shader
  1144. OpMemoryModel Logical GLSL450
  1145. OpEntryPoint GLCompute %func "func"
  1146. OpExecutionMode %func LocalSize 1 1 1
  1147. OpName %entry "entry";
  1148. OpName %loop "loop"
  1149. OpName %loop_merge "loop_merge"
  1150. OpName %loop_cont "loop_cont"
  1151. OpName %switch "switch"
  1152. OpName %switch_merge "switch_merge"
  1153. %void = OpTypeVoid
  1154. %bool = OpTypeBool
  1155. %int = OpTypeInt 32 0
  1156. %void_fn = OpTypeFunction %void
  1157. %bool_undef = OpUndef %bool
  1158. %int_undef = OpUndef %int
  1159. %func = OpFunction %void None %void_fn
  1160. %entry = OpLabel
  1161. OpBranch %loop
  1162. %loop = OpLabel
  1163. OpLoopMerge %loop_merge %loop_cont None
  1164. OpBranch %switch
  1165. %switch = OpLabel
  1166. OpSelectionMerge %switch_merge None
  1167. OpSwitch %int_undef %switch_merge 0 %break 1 %break
  1168. %break = OpLabel
  1169. OpBranch %loop_merge
  1170. %switch_merge = OpLabel
  1171. OpBranch %loop_cont
  1172. %loop_cont = OpLabel
  1173. OpBranch %loop
  1174. %loop_merge = OpLabel
  1175. OpReturn
  1176. OpFunctionEnd
  1177. )";
  1178. auto result = SinglePassRunAndDisassemble<opt::BlockMergePass>(
  1179. text, /* skip_nop = */ true, /* do_validation = */ true);
  1180. EXPECT_EQ(opt::Pass::Status::SuccessWithoutChange, std::get<1>(result));
  1181. }
  1182. TEST_F(BlockMergeTest, DontLoseDefaultCaseConstruct) {
  1183. const std::string text = R"(
  1184. OpCapability Shader
  1185. OpMemoryModel Logical GLSL450
  1186. OpEntryPoint GLCompute %func "func"
  1187. OpExecutionMode %func LocalSize 1 1 1
  1188. OpName %entry "entry";
  1189. OpName %loop "loop"
  1190. OpName %loop_merge "loop_merge"
  1191. OpName %loop_cont "loop_cont"
  1192. OpName %switch "switch"
  1193. OpName %switch_merge "switch_merge"
  1194. %void = OpTypeVoid
  1195. %bool = OpTypeBool
  1196. %int = OpTypeInt 32 0
  1197. %void_fn = OpTypeFunction %void
  1198. %bool_undef = OpUndef %bool
  1199. %int_undef = OpUndef %int
  1200. %func = OpFunction %void None %void_fn
  1201. %entry = OpLabel
  1202. OpBranch %loop
  1203. %loop = OpLabel
  1204. OpLoopMerge %loop_merge %loop_cont None
  1205. OpBranch %switch
  1206. %switch = OpLabel
  1207. OpSelectionMerge %switch_merge None
  1208. OpSwitch %int_undef %cont 0 %switch_merge 1 %switch_merge
  1209. %cont = OpLabel
  1210. OpBranch %loop_cont
  1211. %switch_merge = OpLabel
  1212. OpBranch %loop_merge
  1213. %loop_cont = OpLabel
  1214. OpBranch %loop
  1215. %loop_merge = OpLabel
  1216. OpReturn
  1217. OpFunctionEnd
  1218. )";
  1219. auto result = SinglePassRunAndDisassemble<opt::BlockMergePass>(
  1220. text, /* skip_nop = */ true, /* do_validation = */ true);
  1221. EXPECT_EQ(opt::Pass::Status::SuccessWithoutChange, std::get<1>(result));
  1222. }
  1223. TEST_F(BlockMergeTest, RebuildStructuredCFG) {
  1224. const std::string text = R"(
  1225. ; CHECK: = OpFunction
  1226. ; CHECK-NEXT: [[entry:%\w+]] = OpLabel
  1227. ; CHECK-NEXT: OpSelectionMerge [[merge:%\w+]] None
  1228. ; CHECK-NEXT: OpSwitch {{%\w+}} [[merge]] 0 [[other:%\w+]]
  1229. ; CHECK [[other]] = OpLabel
  1230. ; CHECK: OpBranch [[merge]]
  1231. ; CHECK [[merge]] = OpLabel
  1232. OpCapability Shader
  1233. OpMemoryModel Logical GLSL450
  1234. OpEntryPoint GLCompute %main "main"
  1235. OpExecutionMode %main LocalSize 1 1 1
  1236. %void = OpTypeVoid
  1237. %int = OpTypeInt 32 0
  1238. %int_1 = OpConstant %int 1
  1239. %void_fn = OpTypeFunction %void
  1240. %main = OpFunction %void None %void_fn
  1241. %entry = OpLabel
  1242. OpBranch %switch
  1243. %switch = OpLabel
  1244. OpSelectionMerge %merge None
  1245. OpSwitch %int_1 %merge 0 %other
  1246. %other = OpLabel
  1247. OpBranch %merge
  1248. %merge = OpLabel
  1249. OpReturn
  1250. OpFunctionEnd
  1251. )";
  1252. SinglePassRunAndMatch<BlockMergePass>(text, true);
  1253. }
  1254. // TODO(greg-lunarg): Add tests to verify handling of these cases:
  1255. //
  1256. // More complex control flow
  1257. // Others?
  1258. } // namespace
  1259. } // namespace opt
  1260. } // namespace spvtools