block_merge_test.cpp 42 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472
  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. TEST_F(BlockMergeTest, MaximalReconvergenceNoMeldToMerge) {
  1255. const std::string text = R"(
  1256. OpCapability Shader
  1257. OpCapability GroupNonUniformBallot
  1258. OpCapability GroupNonUniformArithmetic
  1259. OpExtension "SPV_KHR_maximal_reconvergence"
  1260. OpMemoryModel Logical GLSL450
  1261. OpEntryPoint GLCompute %main "main" %gl_GlobalInvocationID %output
  1262. OpExecutionMode %main LocalSize 1 1 1
  1263. OpExecutionMode %main MaximallyReconvergesKHR
  1264. OpSource HLSL 660
  1265. OpName %type_RWStructuredBuffer_uint "type.RWStructuredBuffer.uint"
  1266. OpName %output "output"
  1267. OpName %main "main"
  1268. OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId
  1269. OpDecorate %output DescriptorSet 0
  1270. OpDecorate %output Binding 0
  1271. OpDecorate %_runtimearr_uint ArrayStride 4
  1272. OpMemberDecorate %type_RWStructuredBuffer_uint 0 Offset 0
  1273. OpDecorate %type_RWStructuredBuffer_uint Block
  1274. %uint = OpTypeInt 32 0
  1275. %bool = OpTypeBool
  1276. %int = OpTypeInt 32 1
  1277. %int_0 = OpConstant %int 0
  1278. %int_1 = OpConstant %int 1
  1279. %_runtimearr_uint = OpTypeRuntimeArray %uint
  1280. %type_RWStructuredBuffer_uint = OpTypeStruct %_runtimearr_uint
  1281. %_ptr_StorageBuffer_type_RWStructuredBuffer_uint = OpTypePointer StorageBuffer %type_RWStructuredBuffer_uint
  1282. %v3uint = OpTypeVector %uint 3
  1283. %_ptr_Input_v3uint = OpTypePointer Input %v3uint
  1284. %void = OpTypeVoid
  1285. %15 = OpTypeFunction %void
  1286. %uint_3 = OpConstant %uint 3
  1287. %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
  1288. %output = OpVariable %_ptr_StorageBuffer_type_RWStructuredBuffer_uint StorageBuffer
  1289. %gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input
  1290. %main = OpFunction %void None %15
  1291. %18 = OpLabel
  1292. %19 = OpLoad %v3uint %gl_GlobalInvocationID
  1293. OpBranch %20
  1294. %20 = OpLabel
  1295. OpLoopMerge %21 %22 None
  1296. ; CHECK: OpLoopMerge [[merge:%\w+]] [[continue:%\w+]]
  1297. OpBranch %23
  1298. %23 = OpLabel
  1299. %24 = OpCompositeExtract %uint %19 0
  1300. %25 = OpGroupNonUniformBroadcastFirst %uint %uint_3 %24
  1301. %26 = OpIEqual %bool %24 %25
  1302. OpSelectionMerge %27 None
  1303. OpBranchConditional %26 %28 %27
  1304. %28 = OpLabel
  1305. %29 = OpGroupNonUniformIAdd %int %uint_3 Reduce %int_1
  1306. %30 = OpBitcast %uint %29
  1307. OpBranch %21
  1308. ; CHECK: [[t1:%\w+]] = OpGroupNonUniformIAdd %int %uint_3 Reduce %int_1
  1309. ; CHECK-NEXT: [[t2:%\w+]] = OpBitcast %uint [[t1]]
  1310. ; CHECK-NEXT: OpBranch [[merge]]
  1311. %27 = OpLabel
  1312. OpBranch %22
  1313. %22 = OpLabel
  1314. OpBranch %20
  1315. %21 = OpLabel
  1316. %31 = OpAccessChain %_ptr_StorageBuffer_uint %output %int_0 %24
  1317. OpStore %31 %30
  1318. OpReturn
  1319. OpFunctionEnd
  1320. )";
  1321. SetTargetEnv(SPV_ENV_VULKAN_1_3);
  1322. SinglePassRunAndMatch<BlockMergePass>(text, true);
  1323. }
  1324. TEST_F(BlockMergeTest, NoMaximalReconvergenceMeldToMerge) {
  1325. const std::string text = R"(
  1326. OpCapability Shader
  1327. OpCapability GroupNonUniformBallot
  1328. OpCapability GroupNonUniformArithmetic
  1329. OpMemoryModel Logical GLSL450
  1330. OpEntryPoint GLCompute %main "main" %gl_GlobalInvocationID %output
  1331. OpExecutionMode %main LocalSize 1 1 1
  1332. OpSource HLSL 660
  1333. OpName %type_RWStructuredBuffer_uint "type.RWStructuredBuffer.uint"
  1334. OpName %output "output"
  1335. OpName %main "main"
  1336. OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId
  1337. OpDecorate %output DescriptorSet 0
  1338. OpDecorate %output Binding 0
  1339. OpDecorate %_runtimearr_uint ArrayStride 4
  1340. OpMemberDecorate %type_RWStructuredBuffer_uint 0 Offset 0
  1341. OpDecorate %type_RWStructuredBuffer_uint Block
  1342. %uint = OpTypeInt 32 0
  1343. %bool = OpTypeBool
  1344. %int = OpTypeInt 32 1
  1345. %int_0 = OpConstant %int 0
  1346. %int_1 = OpConstant %int 1
  1347. %_runtimearr_uint = OpTypeRuntimeArray %uint
  1348. %type_RWStructuredBuffer_uint = OpTypeStruct %_runtimearr_uint
  1349. %_ptr_StorageBuffer_type_RWStructuredBuffer_uint = OpTypePointer StorageBuffer %type_RWStructuredBuffer_uint
  1350. %v3uint = OpTypeVector %uint 3
  1351. %_ptr_Input_v3uint = OpTypePointer Input %v3uint
  1352. %void = OpTypeVoid
  1353. %15 = OpTypeFunction %void
  1354. %uint_3 = OpConstant %uint 3
  1355. %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
  1356. %output = OpVariable %_ptr_StorageBuffer_type_RWStructuredBuffer_uint StorageBuffer
  1357. %gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input
  1358. %main = OpFunction %void None %15
  1359. %18 = OpLabel
  1360. %19 = OpLoad %v3uint %gl_GlobalInvocationID
  1361. OpBranch %20
  1362. %20 = OpLabel
  1363. OpLoopMerge %21 %22 None
  1364. ; CHECK: OpLoopMerge [[merge:%\w+]] [[continue:%\w+]]
  1365. OpBranch %23
  1366. %23 = OpLabel
  1367. %24 = OpCompositeExtract %uint %19 0
  1368. %25 = OpGroupNonUniformBroadcastFirst %uint %uint_3 %24
  1369. %26 = OpIEqual %bool %24 %25
  1370. OpSelectionMerge %27 None
  1371. OpBranchConditional %26 %28 %27
  1372. %28 = OpLabel
  1373. %29 = OpGroupNonUniformIAdd %int %uint_3 Reduce %int_1
  1374. %30 = OpBitcast %uint %29
  1375. OpBranch %21
  1376. ; CHECK: [[merge]] = OpLabel
  1377. ; CHECK-NEXT: [[t1:%\w+]] = OpGroupNonUniformIAdd %int %uint_3 Reduce %int_1
  1378. ; CHECK-NEXT: [[t2:%\w+]] = OpBitcast %uint [[t1]]
  1379. %27 = OpLabel
  1380. OpBranch %22
  1381. %22 = OpLabel
  1382. OpBranch %20
  1383. %21 = OpLabel
  1384. %31 = OpAccessChain %_ptr_StorageBuffer_uint %output %int_0 %24
  1385. OpStore %31 %30
  1386. OpReturn
  1387. OpFunctionEnd
  1388. )";
  1389. SetTargetEnv(SPV_ENV_VULKAN_1_3);
  1390. SinglePassRunAndMatch<BlockMergePass>(text, true);
  1391. }
  1392. // TODO(greg-lunarg): Add tests to verify handling of these cases:
  1393. //
  1394. // More complex control flow
  1395. // Others?
  1396. } // namespace
  1397. } // namespace opt
  1398. } // namespace spvtools