dead_branch_elim_test.cpp 89 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359
  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 DeadBranchElimTest = PassTest<::testing::Test>;
  22. TEST_F(DeadBranchElimTest, IfThenElseTrue) {
  23. // #version 140
  24. //
  25. // in vec4 BaseColor;
  26. //
  27. // void main()
  28. // {
  29. // vec4 v;
  30. // if (true)
  31. // v = vec4(0.0,0.0,0.0,0.0);
  32. // else
  33. // v = vec4(1.0,1.0,1.0,1.0);
  34. // gl_FragColor = v;
  35. // }
  36. const std::string predefs =
  37. R"(OpCapability Shader
  38. %1 = OpExtInstImport "GLSL.std.450"
  39. OpMemoryModel Logical GLSL450
  40. OpEntryPoint Fragment %main "main" %gl_FragColor %BaseColor
  41. OpExecutionMode %main OriginUpperLeft
  42. OpSource GLSL 140
  43. OpName %main "main"
  44. OpName %v "v"
  45. OpName %gl_FragColor "gl_FragColor"
  46. OpName %BaseColor "BaseColor"
  47. %void = OpTypeVoid
  48. %7 = OpTypeFunction %void
  49. %bool = OpTypeBool
  50. %true = OpConstantTrue %bool
  51. %float = OpTypeFloat 32
  52. %v4float = OpTypeVector %float 4
  53. %_ptr_Function_v4float = OpTypePointer Function %v4float
  54. %float_0 = OpConstant %float 0
  55. %14 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
  56. %float_1 = OpConstant %float 1
  57. %16 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
  58. %_ptr_Output_v4float = OpTypePointer Output %v4float
  59. %gl_FragColor = OpVariable %_ptr_Output_v4float Output
  60. %_ptr_Input_v4float = OpTypePointer Input %v4float
  61. %BaseColor = OpVariable %_ptr_Input_v4float Input
  62. )";
  63. const std::string before =
  64. R"(%main = OpFunction %void None %7
  65. %19 = OpLabel
  66. %v = OpVariable %_ptr_Function_v4float Function
  67. OpSelectionMerge %20 None
  68. OpBranchConditional %true %21 %22
  69. %21 = OpLabel
  70. OpStore %v %14
  71. OpBranch %20
  72. %22 = OpLabel
  73. OpStore %v %16
  74. OpBranch %20
  75. %20 = OpLabel
  76. %23 = OpLoad %v4float %v
  77. OpStore %gl_FragColor %23
  78. OpReturn
  79. OpFunctionEnd
  80. )";
  81. const std::string after =
  82. R"(%main = OpFunction %void None %7
  83. %19 = OpLabel
  84. %v = OpVariable %_ptr_Function_v4float Function
  85. OpBranch %21
  86. %21 = OpLabel
  87. OpStore %v %14
  88. OpBranch %20
  89. %20 = OpLabel
  90. %23 = OpLoad %v4float %v
  91. OpStore %gl_FragColor %23
  92. OpReturn
  93. OpFunctionEnd
  94. )";
  95. SinglePassRunAndCheck<DeadBranchElimPass>(predefs + before, predefs + after,
  96. true, true);
  97. }
  98. TEST_F(DeadBranchElimTest, IfThenElseFalse) {
  99. // #version 140
  100. //
  101. // in vec4 BaseColor;
  102. //
  103. // void main()
  104. // {
  105. // vec4 v;
  106. // if (false)
  107. // v = vec4(0.0,0.0,0.0,0.0);
  108. // else
  109. // v = vec4(1.0,1.0,1.0,1.0);
  110. // gl_FragColor = v;
  111. // }
  112. const std::string predefs =
  113. R"(OpCapability Shader
  114. %1 = OpExtInstImport "GLSL.std.450"
  115. OpMemoryModel Logical GLSL450
  116. OpEntryPoint Fragment %main "main" %gl_FragColor %BaseColor
  117. OpExecutionMode %main OriginUpperLeft
  118. OpSource GLSL 140
  119. OpName %main "main"
  120. OpName %v "v"
  121. OpName %gl_FragColor "gl_FragColor"
  122. OpName %BaseColor "BaseColor"
  123. %void = OpTypeVoid
  124. %7 = OpTypeFunction %void
  125. %bool = OpTypeBool
  126. %false = OpConstantFalse %bool
  127. %float = OpTypeFloat 32
  128. %v4float = OpTypeVector %float 4
  129. %_ptr_Function_v4float = OpTypePointer Function %v4float
  130. %float_0 = OpConstant %float 0
  131. %14 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
  132. %float_1 = OpConstant %float 1
  133. %16 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
  134. %_ptr_Output_v4float = OpTypePointer Output %v4float
  135. %gl_FragColor = OpVariable %_ptr_Output_v4float Output
  136. %_ptr_Input_v4float = OpTypePointer Input %v4float
  137. %BaseColor = OpVariable %_ptr_Input_v4float Input
  138. )";
  139. const std::string before =
  140. R"(%main = OpFunction %void None %7
  141. %19 = OpLabel
  142. %v = OpVariable %_ptr_Function_v4float Function
  143. OpSelectionMerge %20 None
  144. OpBranchConditional %false %21 %22
  145. %21 = OpLabel
  146. OpStore %v %14
  147. OpBranch %20
  148. %22 = OpLabel
  149. OpStore %v %16
  150. OpBranch %20
  151. %20 = OpLabel
  152. %23 = OpLoad %v4float %v
  153. OpStore %gl_FragColor %23
  154. OpReturn
  155. OpFunctionEnd
  156. )";
  157. const std::string after =
  158. R"(%main = OpFunction %void None %7
  159. %19 = OpLabel
  160. %v = OpVariable %_ptr_Function_v4float Function
  161. OpBranch %22
  162. %22 = OpLabel
  163. OpStore %v %16
  164. OpBranch %20
  165. %20 = OpLabel
  166. %23 = OpLoad %v4float %v
  167. OpStore %gl_FragColor %23
  168. OpReturn
  169. OpFunctionEnd
  170. )";
  171. SinglePassRunAndCheck<DeadBranchElimPass>(predefs + before, predefs + after,
  172. true, true);
  173. }
  174. TEST_F(DeadBranchElimTest, IfThenElseNull) {
  175. // For booleans OpConstantNull should be treated similar to OpConstantFalse.
  176. //
  177. // From the SPIR-V spec:
  178. // OpConstantNull: Declares a new null constant value.
  179. // The null value is type dependent, defined as follows:
  180. // - Scalar Boolean: false
  181. // ...
  182. const std::string predefs =
  183. R"(OpCapability Shader
  184. %1 = OpExtInstImport "GLSL.std.450"
  185. OpMemoryModel Logical GLSL450
  186. OpEntryPoint Fragment %main "main" %gl_FragColor %BaseColor
  187. OpExecutionMode %main OriginUpperLeft
  188. OpSource GLSL 140
  189. OpName %main "main"
  190. OpName %v "v"
  191. OpName %gl_FragColor "gl_FragColor"
  192. OpName %BaseColor "BaseColor"
  193. %void = OpTypeVoid
  194. %7 = OpTypeFunction %void
  195. %bool = OpTypeBool
  196. %9 = OpConstantNull %bool
  197. %float = OpTypeFloat 32
  198. %v4float = OpTypeVector %float 4
  199. %_ptr_Function_v4float = OpTypePointer Function %v4float
  200. %float_0 = OpConstant %float 0
  201. %14 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
  202. %float_1 = OpConstant %float 1
  203. %16 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
  204. %_ptr_Output_v4float = OpTypePointer Output %v4float
  205. %gl_FragColor = OpVariable %_ptr_Output_v4float Output
  206. %_ptr_Input_v4float = OpTypePointer Input %v4float
  207. %BaseColor = OpVariable %_ptr_Input_v4float Input
  208. )";
  209. const std::string before =
  210. R"(%main = OpFunction %void None %7
  211. %19 = OpLabel
  212. %v = OpVariable %_ptr_Function_v4float Function
  213. OpSelectionMerge %20 None
  214. OpBranchConditional %9 %21 %22
  215. %21 = OpLabel
  216. OpStore %v %14
  217. OpBranch %20
  218. %22 = OpLabel
  219. OpStore %v %16
  220. OpBranch %20
  221. %20 = OpLabel
  222. %23 = OpLoad %v4float %v
  223. OpStore %gl_FragColor %23
  224. OpReturn
  225. OpFunctionEnd
  226. )";
  227. const std::string after =
  228. R"(%main = OpFunction %void None %7
  229. %19 = OpLabel
  230. %v = OpVariable %_ptr_Function_v4float Function
  231. OpBranch %22
  232. %22 = OpLabel
  233. OpStore %v %16
  234. OpBranch %20
  235. %20 = OpLabel
  236. %23 = OpLoad %v4float %v
  237. OpStore %gl_FragColor %23
  238. OpReturn
  239. OpFunctionEnd
  240. )";
  241. SinglePassRunAndCheck<DeadBranchElimPass>(predefs + before, predefs + after,
  242. true, true);
  243. }
  244. TEST_F(DeadBranchElimTest, IfThenTrue) {
  245. // #version 140
  246. //
  247. // in vec4 BaseColor;
  248. //
  249. // void main()
  250. // {
  251. // vec4 v = BaseColor;
  252. // if (true)
  253. // v = v * vec4(0.5,0.5,0.5,0.5);
  254. // gl_FragColor = v;
  255. // }
  256. const std::string predefs =
  257. R"(OpCapability Shader
  258. %1 = OpExtInstImport "GLSL.std.450"
  259. OpMemoryModel Logical GLSL450
  260. OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
  261. OpExecutionMode %main OriginUpperLeft
  262. OpSource GLSL 140
  263. OpName %main "main"
  264. OpName %v "v"
  265. OpName %BaseColor "BaseColor"
  266. OpName %gl_FragColor "gl_FragColor"
  267. %void = OpTypeVoid
  268. %7 = OpTypeFunction %void
  269. %float = OpTypeFloat 32
  270. %v4float = OpTypeVector %float 4
  271. %_ptr_Function_v4float = OpTypePointer Function %v4float
  272. %_ptr_Input_v4float = OpTypePointer Input %v4float
  273. %BaseColor = OpVariable %_ptr_Input_v4float Input
  274. %bool = OpTypeBool
  275. %true = OpConstantTrue %bool
  276. %float_0_5 = OpConstant %float 0.5
  277. %15 = OpConstantComposite %v4float %float_0_5 %float_0_5 %float_0_5 %float_0_5
  278. %_ptr_Output_v4float = OpTypePointer Output %v4float
  279. %gl_FragColor = OpVariable %_ptr_Output_v4float Output
  280. )";
  281. const std::string before =
  282. R"(%main = OpFunction %void None %7
  283. %17 = OpLabel
  284. %v = OpVariable %_ptr_Function_v4float Function
  285. %18 = OpLoad %v4float %BaseColor
  286. OpStore %v %18
  287. OpSelectionMerge %19 None
  288. OpBranchConditional %true %20 %19
  289. %20 = OpLabel
  290. %21 = OpLoad %v4float %v
  291. %22 = OpFMul %v4float %21 %15
  292. OpStore %v %22
  293. OpBranch %19
  294. %19 = OpLabel
  295. %23 = OpLoad %v4float %v
  296. OpStore %gl_FragColor %23
  297. OpReturn
  298. OpFunctionEnd
  299. )";
  300. const std::string after =
  301. R"(%main = OpFunction %void None %7
  302. %17 = OpLabel
  303. %v = OpVariable %_ptr_Function_v4float Function
  304. %18 = OpLoad %v4float %BaseColor
  305. OpStore %v %18
  306. OpBranch %20
  307. %20 = OpLabel
  308. %21 = OpLoad %v4float %v
  309. %22 = OpFMul %v4float %21 %15
  310. OpStore %v %22
  311. OpBranch %19
  312. %19 = OpLabel
  313. %23 = OpLoad %v4float %v
  314. OpStore %gl_FragColor %23
  315. OpReturn
  316. OpFunctionEnd
  317. )";
  318. SinglePassRunAndCheck<DeadBranchElimPass>(predefs + before, predefs + after,
  319. true, true);
  320. }
  321. TEST_F(DeadBranchElimTest, IfThenFalse) {
  322. // #version 140
  323. //
  324. // in vec4 BaseColor;
  325. //
  326. // void main()
  327. // {
  328. // vec4 v = BaseColor;
  329. // if (false)
  330. // v = v * vec4(0.5,0.5,0.5,0.5);
  331. // gl_FragColor = v;
  332. // }
  333. const std::string predefs =
  334. R"(OpCapability Shader
  335. %1 = OpExtInstImport "GLSL.std.450"
  336. OpMemoryModel Logical GLSL450
  337. OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
  338. OpExecutionMode %main OriginUpperLeft
  339. OpSource GLSL 140
  340. OpName %main "main"
  341. OpName %v "v"
  342. OpName %BaseColor "BaseColor"
  343. OpName %gl_FragColor "gl_FragColor"
  344. %void = OpTypeVoid
  345. %7 = OpTypeFunction %void
  346. %float = OpTypeFloat 32
  347. %v4float = OpTypeVector %float 4
  348. %_ptr_Function_v4float = OpTypePointer Function %v4float
  349. %_ptr_Input_v4float = OpTypePointer Input %v4float
  350. %BaseColor = OpVariable %_ptr_Input_v4float Input
  351. %bool = OpTypeBool
  352. %false = OpConstantFalse %bool
  353. %float_0_5 = OpConstant %float 0.5
  354. %15 = OpConstantComposite %v4float %float_0_5 %float_0_5 %float_0_5 %float_0_5
  355. %_ptr_Output_v4float = OpTypePointer Output %v4float
  356. %gl_FragColor = OpVariable %_ptr_Output_v4float Output
  357. )";
  358. const std::string before =
  359. R"(%main = OpFunction %void None %7
  360. %17 = OpLabel
  361. %v = OpVariable %_ptr_Function_v4float Function
  362. %18 = OpLoad %v4float %BaseColor
  363. OpStore %v %18
  364. OpSelectionMerge %19 None
  365. OpBranchConditional %false %20 %19
  366. %20 = OpLabel
  367. %21 = OpLoad %v4float %v
  368. %22 = OpFMul %v4float %21 %15
  369. OpStore %v %22
  370. OpBranch %19
  371. %19 = OpLabel
  372. %23 = OpLoad %v4float %v
  373. OpStore %gl_FragColor %23
  374. OpReturn
  375. OpFunctionEnd
  376. )";
  377. const std::string after =
  378. R"(%main = OpFunction %void None %7
  379. %17 = OpLabel
  380. %v = OpVariable %_ptr_Function_v4float Function
  381. %18 = OpLoad %v4float %BaseColor
  382. OpStore %v %18
  383. OpBranch %19
  384. %19 = OpLabel
  385. %23 = OpLoad %v4float %v
  386. OpStore %gl_FragColor %23
  387. OpReturn
  388. OpFunctionEnd
  389. )";
  390. SinglePassRunAndCheck<DeadBranchElimPass>(predefs + before, predefs + after,
  391. true, true);
  392. }
  393. TEST_F(DeadBranchElimTest, IfThenElsePhiTrue) {
  394. // Test handling of phi in merge block after dead branch elimination.
  395. // Note: The SPIR-V has had store/load elimination and phi insertion
  396. //
  397. // #version 140
  398. //
  399. // void main()
  400. // {
  401. // vec4 v;
  402. // if (true)
  403. // v = vec4(0.0,0.0,0.0,0.0);
  404. // else
  405. // v = vec4(1.0,1.0,1.0,1.0);
  406. // gl_FragColor = v;
  407. // }
  408. const std::string predefs =
  409. R"(OpCapability Shader
  410. %1 = OpExtInstImport "GLSL.std.450"
  411. OpMemoryModel Logical GLSL450
  412. OpEntryPoint Fragment %main "main" %gl_FragColor
  413. OpExecutionMode %main OriginUpperLeft
  414. OpSource GLSL 140
  415. OpName %main "main"
  416. OpName %gl_FragColor "gl_FragColor"
  417. %void = OpTypeVoid
  418. %5 = OpTypeFunction %void
  419. %bool = OpTypeBool
  420. %true = OpConstantTrue %bool
  421. %float = OpTypeFloat 32
  422. %v4float = OpTypeVector %float 4
  423. %_ptr_Function_v4float = OpTypePointer Function %v4float
  424. %float_0 = OpConstant %float 0
  425. %12 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
  426. %float_1 = OpConstant %float 1
  427. %14 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
  428. %_ptr_Output_v4float = OpTypePointer Output %v4float
  429. %gl_FragColor = OpVariable %_ptr_Output_v4float Output
  430. %_ptr_Input_v4float = OpTypePointer Input %v4float
  431. )";
  432. const std::string before =
  433. R"(%main = OpFunction %void None %5
  434. %17 = OpLabel
  435. OpSelectionMerge %18 None
  436. OpBranchConditional %true %19 %20
  437. %19 = OpLabel
  438. OpBranch %18
  439. %20 = OpLabel
  440. OpBranch %18
  441. %18 = OpLabel
  442. %21 = OpPhi %v4float %12 %19 %14 %20
  443. OpStore %gl_FragColor %21
  444. OpReturn
  445. OpFunctionEnd
  446. )";
  447. const std::string after =
  448. R"(%main = OpFunction %void None %5
  449. %17 = OpLabel
  450. OpBranch %19
  451. %19 = OpLabel
  452. OpBranch %18
  453. %18 = OpLabel
  454. OpStore %gl_FragColor %12
  455. OpReturn
  456. OpFunctionEnd
  457. )";
  458. SinglePassRunAndCheck<DeadBranchElimPass>(predefs + before, predefs + after,
  459. true, true);
  460. }
  461. TEST_F(DeadBranchElimTest, IfThenElsePhiFalse) {
  462. // Test handling of phi in merge block after dead branch elimination.
  463. // Note: The SPIR-V has had store/load elimination and phi insertion
  464. //
  465. // #version 140
  466. //
  467. // void main()
  468. // {
  469. // vec4 v;
  470. // if (true)
  471. // v = vec4(0.0,0.0,0.0,0.0);
  472. // else
  473. // v = vec4(1.0,1.0,1.0,1.0);
  474. // gl_FragColor = v;
  475. // }
  476. const std::string predefs =
  477. R"(OpCapability Shader
  478. %1 = OpExtInstImport "GLSL.std.450"
  479. OpMemoryModel Logical GLSL450
  480. OpEntryPoint Fragment %main "main" %gl_FragColor
  481. OpExecutionMode %main OriginUpperLeft
  482. OpSource GLSL 140
  483. OpName %main "main"
  484. OpName %gl_FragColor "gl_FragColor"
  485. %void = OpTypeVoid
  486. %5 = OpTypeFunction %void
  487. %bool = OpTypeBool
  488. %false = OpConstantFalse %bool
  489. %float = OpTypeFloat 32
  490. %v4float = OpTypeVector %float 4
  491. %_ptr_Function_v4float = OpTypePointer Function %v4float
  492. %float_0 = OpConstant %float 0
  493. %12 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
  494. %float_1 = OpConstant %float 1
  495. %14 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
  496. %_ptr_Output_v4float = OpTypePointer Output %v4float
  497. %gl_FragColor = OpVariable %_ptr_Output_v4float Output
  498. %_ptr_Input_v4float = OpTypePointer Input %v4float
  499. )";
  500. const std::string before =
  501. R"(%main = OpFunction %void None %5
  502. %17 = OpLabel
  503. OpSelectionMerge %18 None
  504. OpBranchConditional %false %19 %20
  505. %19 = OpLabel
  506. OpBranch %18
  507. %20 = OpLabel
  508. OpBranch %18
  509. %18 = OpLabel
  510. %21 = OpPhi %v4float %12 %19 %14 %20
  511. OpStore %gl_FragColor %21
  512. OpReturn
  513. OpFunctionEnd
  514. )";
  515. const std::string after =
  516. R"(%main = OpFunction %void None %5
  517. %17 = OpLabel
  518. OpBranch %20
  519. %20 = OpLabel
  520. OpBranch %18
  521. %18 = OpLabel
  522. OpStore %gl_FragColor %14
  523. OpReturn
  524. OpFunctionEnd
  525. )";
  526. SinglePassRunAndCheck<DeadBranchElimPass>(predefs + before, predefs + after,
  527. true, true);
  528. }
  529. TEST_F(DeadBranchElimTest, CompoundIfThenElseFalse) {
  530. // #version 140
  531. //
  532. // layout(std140) uniform U_t
  533. // {
  534. // bool g_B ;
  535. // } ;
  536. //
  537. // void main()
  538. // {
  539. // vec4 v;
  540. // if (false) {
  541. // if (g_B)
  542. // v = vec4(0.0,0.0,0.0,0.0);
  543. // else
  544. // v = vec4(1.0,1.0,1.0,1.0);
  545. // } else {
  546. // if (g_B)
  547. // v = vec4(1.0,1.0,1.0,1.0);
  548. // else
  549. // v = vec4(0.0,0.0,0.0,0.0);
  550. // }
  551. // gl_FragColor = v;
  552. // }
  553. const std::string predefs =
  554. R"(OpCapability Shader
  555. %1 = OpExtInstImport "GLSL.std.450"
  556. OpMemoryModel Logical GLSL450
  557. OpEntryPoint Fragment %main "main" %gl_FragColor
  558. OpExecutionMode %main OriginUpperLeft
  559. OpSource GLSL 140
  560. OpName %main "main"
  561. OpName %U_t "U_t"
  562. OpMemberName %U_t 0 "g_B"
  563. OpName %_ ""
  564. OpName %v "v"
  565. OpName %gl_FragColor "gl_FragColor"
  566. OpMemberDecorate %U_t 0 Offset 0
  567. OpDecorate %U_t Block
  568. OpDecorate %_ DescriptorSet 0
  569. %void = OpTypeVoid
  570. %8 = OpTypeFunction %void
  571. %bool = OpTypeBool
  572. %false = OpConstantFalse %bool
  573. %uint = OpTypeInt 32 0
  574. %U_t = OpTypeStruct %uint
  575. %_ptr_Uniform_U_t = OpTypePointer Uniform %U_t
  576. %_ = OpVariable %_ptr_Uniform_U_t Uniform
  577. %int = OpTypeInt 32 1
  578. %int_0 = OpConstant %int 0
  579. %_ptr_Uniform_uint = OpTypePointer Uniform %uint
  580. %uint_0 = OpConstant %uint 0
  581. %float = OpTypeFloat 32
  582. %v4float = OpTypeVector %float 4
  583. %_ptr_Function_v4float = OpTypePointer Function %v4float
  584. %float_0 = OpConstant %float 0
  585. %21 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
  586. %float_1 = OpConstant %float 1
  587. %23 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
  588. %_ptr_Output_v4float = OpTypePointer Output %v4float
  589. %gl_FragColor = OpVariable %_ptr_Output_v4float Output
  590. )";
  591. const std::string before =
  592. R"(%main = OpFunction %void None %8
  593. %25 = OpLabel
  594. %v = OpVariable %_ptr_Function_v4float Function
  595. OpSelectionMerge %26 None
  596. OpBranchConditional %false %27 %28
  597. %27 = OpLabel
  598. %29 = OpAccessChain %_ptr_Uniform_uint %_ %int_0
  599. %30 = OpLoad %uint %29
  600. %31 = OpINotEqual %bool %30 %uint_0
  601. OpSelectionMerge %32 None
  602. OpBranchConditional %31 %33 %34
  603. %33 = OpLabel
  604. OpStore %v %21
  605. OpBranch %32
  606. %34 = OpLabel
  607. OpStore %v %23
  608. OpBranch %32
  609. %32 = OpLabel
  610. OpBranch %26
  611. %28 = OpLabel
  612. %35 = OpAccessChain %_ptr_Uniform_uint %_ %int_0
  613. %36 = OpLoad %uint %35
  614. %37 = OpINotEqual %bool %36 %uint_0
  615. OpSelectionMerge %38 None
  616. OpBranchConditional %37 %39 %40
  617. %39 = OpLabel
  618. OpStore %v %23
  619. OpBranch %38
  620. %40 = OpLabel
  621. OpStore %v %21
  622. OpBranch %38
  623. %38 = OpLabel
  624. OpBranch %26
  625. %26 = OpLabel
  626. %41 = OpLoad %v4float %v
  627. OpStore %gl_FragColor %41
  628. OpReturn
  629. OpFunctionEnd
  630. )";
  631. const std::string after =
  632. R"(%main = OpFunction %void None %8
  633. %25 = OpLabel
  634. %v = OpVariable %_ptr_Function_v4float Function
  635. OpBranch %28
  636. %28 = OpLabel
  637. %35 = OpAccessChain %_ptr_Uniform_uint %_ %int_0
  638. %36 = OpLoad %uint %35
  639. %37 = OpINotEqual %bool %36 %uint_0
  640. OpSelectionMerge %38 None
  641. OpBranchConditional %37 %39 %40
  642. %40 = OpLabel
  643. OpStore %v %21
  644. OpBranch %38
  645. %39 = OpLabel
  646. OpStore %v %23
  647. OpBranch %38
  648. %38 = OpLabel
  649. OpBranch %26
  650. %26 = OpLabel
  651. %41 = OpLoad %v4float %v
  652. OpStore %gl_FragColor %41
  653. OpReturn
  654. OpFunctionEnd
  655. )";
  656. SinglePassRunAndCheck<DeadBranchElimPass>(predefs + before, predefs + after,
  657. true, true);
  658. }
  659. TEST_F(DeadBranchElimTest, PreventOrphanMerge) {
  660. const std::string predefs =
  661. R"(OpCapability Shader
  662. %1 = OpExtInstImport "GLSL.std.450"
  663. OpMemoryModel Logical GLSL450
  664. OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
  665. OpExecutionMode %main OriginUpperLeft
  666. OpSource GLSL 140
  667. OpName %main "main"
  668. OpName %v "v"
  669. OpName %BaseColor "BaseColor"
  670. OpName %gl_FragColor "gl_FragColor"
  671. %void = OpTypeVoid
  672. %7 = OpTypeFunction %void
  673. %float = OpTypeFloat 32
  674. %v4float = OpTypeVector %float 4
  675. %_ptr_Function_v4float = OpTypePointer Function %v4float
  676. %_ptr_Input_v4float = OpTypePointer Input %v4float
  677. %BaseColor = OpVariable %_ptr_Input_v4float Input
  678. %bool = OpTypeBool
  679. %true = OpConstantTrue %bool
  680. %float_0_5 = OpConstant %float 0.5
  681. %_ptr_Output_v4float = OpTypePointer Output %v4float
  682. %gl_FragColor = OpVariable %_ptr_Output_v4float Output
  683. )";
  684. const std::string before =
  685. R"(%main = OpFunction %void None %7
  686. %16 = OpLabel
  687. %v = OpVariable %_ptr_Function_v4float Function
  688. %17 = OpLoad %v4float %BaseColor
  689. OpStore %v %17
  690. OpSelectionMerge %18 None
  691. OpBranchConditional %true %19 %20
  692. %19 = OpLabel
  693. OpKill
  694. %20 = OpLabel
  695. %21 = OpLoad %v4float %v
  696. %22 = OpVectorTimesScalar %v4float %21 %float_0_5
  697. OpStore %v %22
  698. OpBranch %18
  699. %18 = OpLabel
  700. %23 = OpLoad %v4float %v
  701. OpStore %gl_FragColor %23
  702. OpReturn
  703. OpFunctionEnd
  704. )";
  705. const std::string after =
  706. R"(%main = OpFunction %void None %7
  707. %16 = OpLabel
  708. %v = OpVariable %_ptr_Function_v4float Function
  709. %17 = OpLoad %v4float %BaseColor
  710. OpStore %v %17
  711. OpBranch %19
  712. %19 = OpLabel
  713. OpKill
  714. OpFunctionEnd
  715. )";
  716. SinglePassRunAndCheck<DeadBranchElimPass>(predefs + before, predefs + after,
  717. true, true);
  718. }
  719. TEST_F(DeadBranchElimTest, HandleOrphanMerge) {
  720. const std::string predefs =
  721. R"(OpCapability Shader
  722. %1 = OpExtInstImport "GLSL.std.450"
  723. OpMemoryModel Logical GLSL450
  724. OpEntryPoint Fragment %main "main" %gl_FragColor
  725. OpExecutionMode %main OriginUpperLeft
  726. OpSource GLSL 140
  727. OpName %main "main"
  728. OpName %foo_ "foo("
  729. OpName %gl_FragColor "gl_FragColor"
  730. OpDecorate %gl_FragColor Location 0
  731. %void = OpTypeVoid
  732. %6 = OpTypeFunction %void
  733. %float = OpTypeFloat 32
  734. %v4float = OpTypeVector %float 4
  735. %9 = OpTypeFunction %v4float
  736. %bool = OpTypeBool
  737. %true = OpConstantTrue %bool
  738. %float_0 = OpConstant %float 0
  739. %13 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
  740. %float_1 = OpConstant %float 1
  741. %15 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
  742. %_ptr_Output_v4float = OpTypePointer Output %v4float
  743. %gl_FragColor = OpVariable %_ptr_Output_v4float Output
  744. %main = OpFunction %void None %6
  745. %17 = OpLabel
  746. %18 = OpFunctionCall %v4float %foo_
  747. OpStore %gl_FragColor %18
  748. OpReturn
  749. OpFunctionEnd
  750. )";
  751. const std::string before =
  752. R"(%foo_ = OpFunction %v4float None %9
  753. %19 = OpLabel
  754. OpSelectionMerge %20 None
  755. OpBranchConditional %true %21 %22
  756. %21 = OpLabel
  757. OpReturnValue %13
  758. %22 = OpLabel
  759. OpReturnValue %15
  760. %20 = OpLabel
  761. %23 = OpUndef %v4float
  762. OpReturnValue %23
  763. OpFunctionEnd
  764. )";
  765. const std::string after =
  766. R"(%foo_ = OpFunction %v4float None %9
  767. %19 = OpLabel
  768. OpBranch %21
  769. %21 = OpLabel
  770. OpReturnValue %13
  771. OpFunctionEnd
  772. )";
  773. SinglePassRunAndCheck<DeadBranchElimPass>(predefs + before, predefs + after,
  774. true, true);
  775. }
  776. TEST_F(DeadBranchElimTest, KeepContinueTargetWhenKillAfterMerge) {
  777. // #version 450
  778. // void main() {
  779. // bool c;
  780. // bool d;
  781. // while(c) {
  782. // if(d) {
  783. // continue;
  784. // }
  785. // if(false) {
  786. // continue;
  787. // }
  788. // discard;
  789. // }
  790. // }
  791. const std::string predefs =
  792. R"(OpCapability Shader
  793. %1 = OpExtInstImport "GLSL.std.450"
  794. OpMemoryModel Logical GLSL450
  795. OpEntryPoint Fragment %main "main"
  796. OpExecutionMode %main OriginUpperLeft
  797. OpSource GLSL 450
  798. OpName %main "main"
  799. OpName %c "c"
  800. OpName %d "d"
  801. %void = OpTypeVoid
  802. %6 = OpTypeFunction %void
  803. %bool = OpTypeBool
  804. %_ptr_Function_bool = OpTypePointer Function %bool
  805. %false = OpConstantFalse %bool
  806. )";
  807. const std::string before =
  808. R"(%main = OpFunction %void None %6
  809. %10 = OpLabel
  810. %c = OpVariable %_ptr_Function_bool Function
  811. %d = OpVariable %_ptr_Function_bool Function
  812. OpBranch %11
  813. %11 = OpLabel
  814. OpLoopMerge %12 %13 None
  815. OpBranch %14
  816. %14 = OpLabel
  817. %15 = OpLoad %bool %c
  818. OpBranchConditional %15 %16 %12
  819. %16 = OpLabel
  820. %17 = OpLoad %bool %d
  821. OpSelectionMerge %18 None
  822. OpBranchConditional %17 %19 %18
  823. %19 = OpLabel
  824. OpBranch %13
  825. %18 = OpLabel
  826. OpSelectionMerge %20 None
  827. OpBranchConditional %false %21 %20
  828. %21 = OpLabel
  829. OpBranch %13
  830. %20 = OpLabel
  831. OpKill
  832. %13 = OpLabel
  833. OpBranch %11
  834. %12 = OpLabel
  835. OpReturn
  836. OpFunctionEnd
  837. )";
  838. const std::string after =
  839. R"(%main = OpFunction %void None %6
  840. %10 = OpLabel
  841. %c = OpVariable %_ptr_Function_bool Function
  842. %d = OpVariable %_ptr_Function_bool Function
  843. OpBranch %11
  844. %11 = OpLabel
  845. OpLoopMerge %12 %13 None
  846. OpBranch %14
  847. %14 = OpLabel
  848. %15 = OpLoad %bool %c
  849. OpBranchConditional %15 %16 %12
  850. %16 = OpLabel
  851. %17 = OpLoad %bool %d
  852. OpSelectionMerge %18 None
  853. OpBranchConditional %17 %19 %18
  854. %19 = OpLabel
  855. OpBranch %13
  856. %18 = OpLabel
  857. OpBranch %20
  858. %20 = OpLabel
  859. OpKill
  860. %13 = OpLabel
  861. OpBranch %11
  862. %12 = OpLabel
  863. OpReturn
  864. OpFunctionEnd
  865. )";
  866. SinglePassRunAndCheck<DeadBranchElimPass>(predefs + before, predefs + after,
  867. true, true);
  868. }
  869. TEST_F(DeadBranchElimTest, DecorateDeleted) {
  870. // Note: SPIR-V hand-edited to add decoration
  871. // #version 140
  872. //
  873. // in vec4 BaseColor;
  874. //
  875. // void main()
  876. // {
  877. // vec4 v = BaseColor;
  878. // if (false)
  879. // v = v * vec4(0.5,0.5,0.5,0.5);
  880. // gl_FragColor = v;
  881. // }
  882. const std::string predefs_before =
  883. R"(OpCapability Shader
  884. %1 = OpExtInstImport "GLSL.std.450"
  885. OpMemoryModel Logical GLSL450
  886. OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
  887. OpExecutionMode %main OriginUpperLeft
  888. OpSource GLSL 140
  889. OpName %main "main"
  890. OpName %v "v"
  891. OpName %BaseColor "BaseColor"
  892. OpName %gl_FragColor "gl_FragColor"
  893. OpDecorate %22 RelaxedPrecision
  894. %void = OpTypeVoid
  895. %7 = OpTypeFunction %void
  896. %float = OpTypeFloat 32
  897. %v4float = OpTypeVector %float 4
  898. %_ptr_Function_v4float = OpTypePointer Function %v4float
  899. %_ptr_Input_v4float = OpTypePointer Input %v4float
  900. %BaseColor = OpVariable %_ptr_Input_v4float Input
  901. %bool = OpTypeBool
  902. %false = OpConstantFalse %bool
  903. %float_0_5 = OpConstant %float 0.5
  904. %15 = OpConstantComposite %v4float %float_0_5 %float_0_5 %float_0_5 %float_0_5
  905. %_ptr_Output_v4float = OpTypePointer Output %v4float
  906. %gl_FragColor = OpVariable %_ptr_Output_v4float Output
  907. )";
  908. const std::string predefs_after =
  909. R"(OpCapability Shader
  910. %1 = OpExtInstImport "GLSL.std.450"
  911. OpMemoryModel Logical GLSL450
  912. OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
  913. OpExecutionMode %main OriginUpperLeft
  914. OpSource GLSL 140
  915. OpName %main "main"
  916. OpName %v "v"
  917. OpName %BaseColor "BaseColor"
  918. OpName %gl_FragColor "gl_FragColor"
  919. %void = OpTypeVoid
  920. %8 = OpTypeFunction %void
  921. %float = OpTypeFloat 32
  922. %v4float = OpTypeVector %float 4
  923. %_ptr_Function_v4float = OpTypePointer Function %v4float
  924. %_ptr_Input_v4float = OpTypePointer Input %v4float
  925. %BaseColor = OpVariable %_ptr_Input_v4float Input
  926. %bool = OpTypeBool
  927. %false = OpConstantFalse %bool
  928. %float_0_5 = OpConstant %float 0.5
  929. %16 = OpConstantComposite %v4float %float_0_5 %float_0_5 %float_0_5 %float_0_5
  930. %_ptr_Output_v4float = OpTypePointer Output %v4float
  931. %gl_FragColor = OpVariable %_ptr_Output_v4float Output
  932. )";
  933. const std::string before =
  934. R"(%main = OpFunction %void None %7
  935. %17 = OpLabel
  936. %v = OpVariable %_ptr_Function_v4float Function
  937. %18 = OpLoad %v4float %BaseColor
  938. OpStore %v %18
  939. OpSelectionMerge %19 None
  940. OpBranchConditional %false %20 %19
  941. %20 = OpLabel
  942. %21 = OpLoad %v4float %v
  943. %22 = OpFMul %v4float %21 %15
  944. OpStore %v %22
  945. OpBranch %19
  946. %19 = OpLabel
  947. %23 = OpLoad %v4float %v
  948. OpStore %gl_FragColor %23
  949. OpReturn
  950. OpFunctionEnd
  951. )";
  952. const std::string after =
  953. R"(%main = OpFunction %void None %8
  954. %18 = OpLabel
  955. %v = OpVariable %_ptr_Function_v4float Function
  956. %19 = OpLoad %v4float %BaseColor
  957. OpStore %v %19
  958. OpBranch %20
  959. %20 = OpLabel
  960. %23 = OpLoad %v4float %v
  961. OpStore %gl_FragColor %23
  962. OpReturn
  963. OpFunctionEnd
  964. )";
  965. SinglePassRunAndCheck<DeadBranchElimPass>(predefs_before + before,
  966. predefs_after + after, true, true);
  967. }
  968. TEST_F(DeadBranchElimTest, LoopInDeadBranch) {
  969. // #version 450
  970. //
  971. // layout(location = 0) in vec4 BaseColor;
  972. // layout(location = 0) out vec4 OutColor;
  973. //
  974. // void main()
  975. // {
  976. // vec4 v = BaseColor;
  977. // if (false)
  978. // for (int i=0; i<3; i++)
  979. // v = v * 0.5;
  980. // OutColor = v;
  981. // }
  982. const std::string predefs =
  983. R"(OpCapability Shader
  984. %1 = OpExtInstImport "GLSL.std.450"
  985. OpMemoryModel Logical GLSL450
  986. OpEntryPoint Fragment %main "main" %BaseColor %OutColor
  987. OpExecutionMode %main OriginUpperLeft
  988. OpSource GLSL 450
  989. OpName %main "main"
  990. OpName %v "v"
  991. OpName %BaseColor "BaseColor"
  992. OpName %i "i"
  993. OpName %OutColor "OutColor"
  994. OpDecorate %BaseColor Location 0
  995. OpDecorate %OutColor Location 0
  996. %void = OpTypeVoid
  997. %8 = OpTypeFunction %void
  998. %float = OpTypeFloat 32
  999. %v4float = OpTypeVector %float 4
  1000. %_ptr_Function_v4float = OpTypePointer Function %v4float
  1001. %_ptr_Input_v4float = OpTypePointer Input %v4float
  1002. %BaseColor = OpVariable %_ptr_Input_v4float Input
  1003. %bool = OpTypeBool
  1004. %false = OpConstantFalse %bool
  1005. %int = OpTypeInt 32 1
  1006. %_ptr_Function_int = OpTypePointer Function %int
  1007. %int_0 = OpConstant %int 0
  1008. %int_3 = OpConstant %int 3
  1009. %float_0_5 = OpConstant %float 0.5
  1010. %int_1 = OpConstant %int 1
  1011. %_ptr_Output_v4float = OpTypePointer Output %v4float
  1012. %OutColor = OpVariable %_ptr_Output_v4float Output
  1013. )";
  1014. const std::string before =
  1015. R"(%main = OpFunction %void None %8
  1016. %22 = OpLabel
  1017. %v = OpVariable %_ptr_Function_v4float Function
  1018. %i = OpVariable %_ptr_Function_int Function
  1019. %23 = OpLoad %v4float %BaseColor
  1020. OpStore %v %23
  1021. OpSelectionMerge %24 None
  1022. OpBranchConditional %false %25 %24
  1023. %25 = OpLabel
  1024. OpStore %i %int_0
  1025. OpBranch %26
  1026. %26 = OpLabel
  1027. OpLoopMerge %27 %28 None
  1028. OpBranch %29
  1029. %29 = OpLabel
  1030. %30 = OpLoad %int %i
  1031. %31 = OpSLessThan %bool %30 %int_3
  1032. OpBranchConditional %31 %32 %27
  1033. %32 = OpLabel
  1034. %33 = OpLoad %v4float %v
  1035. %34 = OpVectorTimesScalar %v4float %33 %float_0_5
  1036. OpStore %v %34
  1037. OpBranch %28
  1038. %28 = OpLabel
  1039. %35 = OpLoad %int %i
  1040. %36 = OpIAdd %int %35 %int_1
  1041. OpStore %i %36
  1042. OpBranch %26
  1043. %27 = OpLabel
  1044. OpBranch %24
  1045. %24 = OpLabel
  1046. %37 = OpLoad %v4float %v
  1047. OpStore %OutColor %37
  1048. OpReturn
  1049. OpFunctionEnd
  1050. )";
  1051. const std::string after =
  1052. R"(%main = OpFunction %void None %8
  1053. %22 = OpLabel
  1054. %v = OpVariable %_ptr_Function_v4float Function
  1055. %i = OpVariable %_ptr_Function_int Function
  1056. %23 = OpLoad %v4float %BaseColor
  1057. OpStore %v %23
  1058. OpBranch %24
  1059. %24 = OpLabel
  1060. %37 = OpLoad %v4float %v
  1061. OpStore %OutColor %37
  1062. OpReturn
  1063. OpFunctionEnd
  1064. )";
  1065. SinglePassRunAndCheck<DeadBranchElimPass>(predefs + before, predefs + after,
  1066. true, true);
  1067. }
  1068. TEST_F(DeadBranchElimTest, SwitchLiveCase) {
  1069. // #version 450
  1070. //
  1071. // layout (location=0) in vec4 BaseColor;
  1072. // layout (location=0) out vec4 OutColor;
  1073. //
  1074. // void main()
  1075. // {
  1076. // switch (1) {
  1077. // case 0:
  1078. // OutColor = vec4(0.0,0.0,0.0,0.0);
  1079. // break;
  1080. // case 1:
  1081. // OutColor = vec4(0.125,0.125,0.125,0.125);
  1082. // break;
  1083. // case 2:
  1084. // OutColor = vec4(0.25,0.25,0.25,0.25);
  1085. // break;
  1086. // default:
  1087. // OutColor = vec4(1.0,1.0,1.0,1.0);
  1088. // }
  1089. // }
  1090. const std::string predefs =
  1091. R"(OpCapability Shader
  1092. %1 = OpExtInstImport "GLSL.std.450"
  1093. OpMemoryModel Logical GLSL450
  1094. OpEntryPoint Fragment %main "main" %OutColor %BaseColor
  1095. OpExecutionMode %main OriginUpperLeft
  1096. OpSource GLSL 450
  1097. OpName %main "main"
  1098. OpName %OutColor "OutColor"
  1099. OpName %BaseColor "BaseColor"
  1100. OpDecorate %OutColor Location 0
  1101. OpDecorate %BaseColor Location 0
  1102. %void = OpTypeVoid
  1103. %6 = OpTypeFunction %void
  1104. %int = OpTypeInt 32 1
  1105. %int_1 = OpConstant %int 1
  1106. %float = OpTypeFloat 32
  1107. %v4float = OpTypeVector %float 4
  1108. %_ptr_Output_v4float = OpTypePointer Output %v4float
  1109. %OutColor = OpVariable %_ptr_Output_v4float Output
  1110. %float_0 = OpConstant %float 0
  1111. %13 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
  1112. %float_0_125 = OpConstant %float 0.125
  1113. %15 = OpConstantComposite %v4float %float_0_125 %float_0_125 %float_0_125 %float_0_125
  1114. %float_0_25 = OpConstant %float 0.25
  1115. %17 = OpConstantComposite %v4float %float_0_25 %float_0_25 %float_0_25 %float_0_25
  1116. %float_1 = OpConstant %float 1
  1117. %19 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
  1118. %_ptr_Input_v4float = OpTypePointer Input %v4float
  1119. %BaseColor = OpVariable %_ptr_Input_v4float Input
  1120. )";
  1121. const std::string before =
  1122. R"(%main = OpFunction %void None %6
  1123. %21 = OpLabel
  1124. OpSelectionMerge %22 None
  1125. OpSwitch %int_1 %23 0 %24 1 %25 2 %26
  1126. %23 = OpLabel
  1127. OpStore %OutColor %19
  1128. OpBranch %22
  1129. %24 = OpLabel
  1130. OpStore %OutColor %13
  1131. OpBranch %22
  1132. %25 = OpLabel
  1133. OpStore %OutColor %15
  1134. OpBranch %22
  1135. %26 = OpLabel
  1136. OpStore %OutColor %17
  1137. OpBranch %22
  1138. %22 = OpLabel
  1139. OpReturn
  1140. OpFunctionEnd
  1141. )";
  1142. const std::string after =
  1143. R"(%main = OpFunction %void None %6
  1144. %21 = OpLabel
  1145. OpBranch %25
  1146. %25 = OpLabel
  1147. OpStore %OutColor %15
  1148. OpBranch %22
  1149. %22 = OpLabel
  1150. OpReturn
  1151. OpFunctionEnd
  1152. )";
  1153. SinglePassRunAndCheck<DeadBranchElimPass>(predefs + before, predefs + after,
  1154. true, true);
  1155. }
  1156. TEST_F(DeadBranchElimTest, SwitchLiveDefault) {
  1157. // #version 450
  1158. //
  1159. // layout (location=0) in vec4 BaseColor;
  1160. // layout (location=0) out vec4 OutColor;
  1161. //
  1162. // void main()
  1163. // {
  1164. // switch (7) {
  1165. // case 0:
  1166. // OutColor = vec4(0.0,0.0,0.0,0.0);
  1167. // break;
  1168. // case 1:
  1169. // OutColor = vec4(0.125,0.125,0.125,0.125);
  1170. // break;
  1171. // case 2:
  1172. // OutColor = vec4(0.25,0.25,0.25,0.25);
  1173. // break;
  1174. // default:
  1175. // OutColor = vec4(1.0,1.0,1.0,1.0);
  1176. // }
  1177. // }
  1178. const std::string predefs =
  1179. R"(OpCapability Shader
  1180. %1 = OpExtInstImport "GLSL.std.450"
  1181. OpMemoryModel Logical GLSL450
  1182. OpEntryPoint Fragment %main "main" %OutColor %BaseColor
  1183. OpExecutionMode %main OriginUpperLeft
  1184. OpSource GLSL 450
  1185. OpName %main "main"
  1186. OpName %OutColor "OutColor"
  1187. OpName %BaseColor "BaseColor"
  1188. OpDecorate %OutColor Location 0
  1189. OpDecorate %BaseColor Location 0
  1190. %void = OpTypeVoid
  1191. %6 = OpTypeFunction %void
  1192. %int = OpTypeInt 32 1
  1193. %int_7 = OpConstant %int 7
  1194. %float = OpTypeFloat 32
  1195. %v4float = OpTypeVector %float 4
  1196. %_ptr_Output_v4float = OpTypePointer Output %v4float
  1197. %OutColor = OpVariable %_ptr_Output_v4float Output
  1198. %float_0 = OpConstant %float 0
  1199. %13 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
  1200. %float_0_125 = OpConstant %float 0.125
  1201. %15 = OpConstantComposite %v4float %float_0_125 %float_0_125 %float_0_125 %float_0_125
  1202. %float_0_25 = OpConstant %float 0.25
  1203. %17 = OpConstantComposite %v4float %float_0_25 %float_0_25 %float_0_25 %float_0_25
  1204. %float_1 = OpConstant %float 1
  1205. %19 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
  1206. %_ptr_Input_v4float = OpTypePointer Input %v4float
  1207. %BaseColor = OpVariable %_ptr_Input_v4float Input
  1208. )";
  1209. const std::string before =
  1210. R"(%main = OpFunction %void None %6
  1211. %21 = OpLabel
  1212. OpSelectionMerge %22 None
  1213. OpSwitch %int_7 %23 0 %24 1 %25 2 %26
  1214. %23 = OpLabel
  1215. OpStore %OutColor %19
  1216. OpBranch %22
  1217. %24 = OpLabel
  1218. OpStore %OutColor %13
  1219. OpBranch %22
  1220. %25 = OpLabel
  1221. OpStore %OutColor %15
  1222. OpBranch %22
  1223. %26 = OpLabel
  1224. OpStore %OutColor %17
  1225. OpBranch %22
  1226. %22 = OpLabel
  1227. OpReturn
  1228. OpFunctionEnd
  1229. )";
  1230. const std::string after =
  1231. R"(%main = OpFunction %void None %6
  1232. %21 = OpLabel
  1233. OpBranch %23
  1234. %23 = OpLabel
  1235. OpStore %OutColor %19
  1236. OpBranch %22
  1237. %22 = OpLabel
  1238. OpReturn
  1239. OpFunctionEnd
  1240. )";
  1241. SinglePassRunAndCheck<DeadBranchElimPass>(predefs + before, predefs + after,
  1242. true, true);
  1243. }
  1244. TEST_F(DeadBranchElimTest, SwitchLiveCaseBreakFromLoop) {
  1245. // This sample does not directly translate to GLSL/HLSL as
  1246. // direct breaks from a loop cannot be made from a switch.
  1247. // This construct is currently formed by inlining a function
  1248. // containing early returns from the cases of a switch. The
  1249. // function is wrapped in a one-trip loop and returns are
  1250. // translated to branches to the loop's merge block.
  1251. const std::string predefs =
  1252. R"(OpCapability Shader
  1253. %1 = OpExtInstImport "GLSL.std.450"
  1254. OpMemoryModel Logical GLSL450
  1255. OpEntryPoint Fragment %main "main" %OutColor %BaseColor
  1256. OpExecutionMode %main OriginUpperLeft
  1257. OpSource GLSL 450
  1258. OpName %main "main"
  1259. OpName %oc "oc"
  1260. OpName %OutColor "OutColor"
  1261. OpName %BaseColor "BaseColor"
  1262. OpDecorate %OutColor Location 0
  1263. OpDecorate %BaseColor Location 0
  1264. %void = OpTypeVoid
  1265. %7 = OpTypeFunction %void
  1266. %bool = OpTypeBool
  1267. %true = OpConstantTrue %bool
  1268. %false = OpConstantFalse %bool
  1269. %int = OpTypeInt 32 1
  1270. %int_1 = OpConstant %int 1
  1271. %float = OpTypeFloat 32
  1272. %v4float = OpTypeVector %float 4
  1273. %_ptr_Function_v4float = OpTypePointer Function %v4float
  1274. %float_0 = OpConstant %float 0
  1275. %17 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
  1276. %float_0_125 = OpConstant %float 0.125
  1277. %19 = OpConstantComposite %v4float %float_0_125 %float_0_125 %float_0_125 %float_0_125
  1278. %float_0_25 = OpConstant %float 0.25
  1279. %21 = OpConstantComposite %v4float %float_0_25 %float_0_25 %float_0_25 %float_0_25
  1280. %float_1 = OpConstant %float 1
  1281. %23 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
  1282. %_ptr_Output_v4float = OpTypePointer Output %v4float
  1283. %OutColor = OpVariable %_ptr_Output_v4float Output
  1284. %_ptr_Input_v4float = OpTypePointer Input %v4float
  1285. %BaseColor = OpVariable %_ptr_Input_v4float Input
  1286. )";
  1287. const std::string before =
  1288. R"(%main = OpFunction %void None %7
  1289. %26 = OpLabel
  1290. %oc = OpVariable %_ptr_Function_v4float Function
  1291. OpBranch %27
  1292. %27 = OpLabel
  1293. OpLoopMerge %28 %29 None
  1294. OpBranch %30
  1295. %30 = OpLabel
  1296. OpSelectionMerge %31 None
  1297. OpSwitch %int_1 %31 0 %32 1 %33 2 %34
  1298. %32 = OpLabel
  1299. OpStore %oc %17
  1300. OpBranch %28
  1301. %33 = OpLabel
  1302. OpStore %oc %19
  1303. OpBranch %28
  1304. %34 = OpLabel
  1305. OpStore %oc %21
  1306. OpBranch %28
  1307. %31 = OpLabel
  1308. OpStore %oc %23
  1309. OpBranch %28
  1310. %29 = OpLabel
  1311. OpBranchConditional %false %27 %28
  1312. %28 = OpLabel
  1313. %35 = OpLoad %v4float %oc
  1314. OpStore %OutColor %35
  1315. OpReturn
  1316. OpFunctionEnd
  1317. )";
  1318. const std::string after =
  1319. R"(%main = OpFunction %void None %7
  1320. %26 = OpLabel
  1321. %oc = OpVariable %_ptr_Function_v4float Function
  1322. OpBranch %27
  1323. %27 = OpLabel
  1324. OpLoopMerge %28 %29 None
  1325. OpBranch %30
  1326. %30 = OpLabel
  1327. OpBranch %33
  1328. %33 = OpLabel
  1329. OpStore %oc %19
  1330. OpBranch %28
  1331. %29 = OpLabel
  1332. OpBranch %27
  1333. %28 = OpLabel
  1334. %35 = OpLoad %v4float %oc
  1335. OpStore %OutColor %35
  1336. OpReturn
  1337. OpFunctionEnd
  1338. )";
  1339. SinglePassRunAndCheck<DeadBranchElimPass>(predefs + before, predefs + after,
  1340. true, true);
  1341. }
  1342. TEST_F(DeadBranchElimTest, LeaveContinueBackedge) {
  1343. const std::string text = R"(
  1344. ; CHECK: OpLoopMerge [[merge:%\w+]] [[continue:%\w+]] None
  1345. ; CHECK: [[continue]] = OpLabel
  1346. ; CHECK-NEXT: OpBranchConditional {{%\w+}} {{%\w+}} [[merge]]
  1347. ; CHECK-NEXT: [[merge]] = OpLabel
  1348. ; CHECK-NEXT: OpReturn
  1349. OpCapability Kernel
  1350. OpCapability Linkage
  1351. OpMemoryModel Logical OpenCL
  1352. %bool = OpTypeBool
  1353. %false = OpConstantFalse %bool
  1354. %void = OpTypeVoid
  1355. %funcTy = OpTypeFunction %void
  1356. %func = OpFunction %void None %funcTy
  1357. %1 = OpLabel
  1358. OpBranch %2
  1359. %2 = OpLabel
  1360. OpLoopMerge %3 %4 None
  1361. OpBranch %4
  1362. %4 = OpLabel
  1363. ; Be careful we don't remove the backedge to %2 despite never taking it.
  1364. OpBranchConditional %false %2 %3
  1365. %3 = OpLabel
  1366. OpReturn
  1367. OpFunctionEnd
  1368. )";
  1369. SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
  1370. }
  1371. TEST_F(DeadBranchElimTest, LeaveContinueBackedgeExtraBlock) {
  1372. const std::string text = R"(
  1373. ; CHECK: OpBranch [[header:%\w+]]
  1374. ; CHECK: OpLoopMerge [[merge:%\w+]] [[continue:%\w+]] None
  1375. ; CHECK-NEXT: OpBranch [[continue]]
  1376. ; CHECK-NEXT: [[continue]] = OpLabel
  1377. ; CHECK-NEXT: OpBranchConditional {{%\w+}} [[extra:%\w+]] [[merge]]
  1378. ; CHECK-NEXT: [[extra]] = OpLabel
  1379. ; CHECK-NEXT: OpBranch [[header]]
  1380. ; CHECK-NEXT: [[merge]] = OpLabel
  1381. ; CHECK-NEXT: OpReturn
  1382. OpCapability Kernel
  1383. OpCapability Linkage
  1384. OpMemoryModel Logical OpenCL
  1385. %bool = OpTypeBool
  1386. %false = OpConstantFalse %bool
  1387. %void = OpTypeVoid
  1388. %funcTy = OpTypeFunction %void
  1389. %func = OpFunction %void None %funcTy
  1390. %1 = OpLabel
  1391. OpBranch %2
  1392. %2 = OpLabel
  1393. OpLoopMerge %3 %4 None
  1394. OpBranch %4
  1395. %4 = OpLabel
  1396. ; Be careful we don't remove the backedge to %2 despite never taking it.
  1397. OpBranchConditional %false %5 %3
  1398. ; This block remains live despite being unreachable.
  1399. %5 = OpLabel
  1400. OpBranch %2
  1401. %3 = OpLabel
  1402. OpReturn
  1403. OpFunctionEnd
  1404. )";
  1405. SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
  1406. }
  1407. TEST_F(DeadBranchElimTest, RemovePhiWithUnreachableContinue) {
  1408. const std::string text = R"(
  1409. ; CHECK: [[entry:%\w+]] = OpLabel
  1410. ; CHECK-NEXT: OpBranch [[header:%\w+]]
  1411. ; CHECK: OpLoopMerge [[merge:%\w+]] [[continue:%\w+]] None
  1412. ; CHECK-NEXT: OpBranch [[ret:%\w+]]
  1413. ; CHECK-NEXT: [[ret]] = OpLabel
  1414. ; CHECK-NEXT: OpReturn
  1415. ; CHECK: [[continue]] = OpLabel
  1416. ; CHECK-NEXT: OpBranch [[header]]
  1417. ; CHECK: [[merge]] = OpLabel
  1418. ; CHECK-NEXT: OpUnreachable
  1419. OpCapability Kernel
  1420. OpCapability Linkage
  1421. OpMemoryModel Logical OpenCL
  1422. OpName %func "func"
  1423. OpDecorate %func LinkageAttributes "func" Export
  1424. %bool = OpTypeBool
  1425. %false = OpConstantFalse %bool
  1426. %true = OpConstantTrue %bool
  1427. %void = OpTypeVoid
  1428. %funcTy = OpTypeFunction %void
  1429. %func = OpFunction %void None %funcTy
  1430. %1 = OpLabel
  1431. OpBranch %2
  1432. %2 = OpLabel
  1433. %phi = OpPhi %bool %false %1 %true %continue
  1434. OpLoopMerge %merge %continue None
  1435. OpBranch %3
  1436. %3 = OpLabel
  1437. OpReturn
  1438. %continue = OpLabel
  1439. OpBranch %2
  1440. %merge = OpLabel
  1441. OpReturn
  1442. OpFunctionEnd
  1443. )";
  1444. SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
  1445. }
  1446. TEST_F(DeadBranchElimTest, UnreachableLoopMergeAndContinueTargets) {
  1447. const std::string text = R"(
  1448. ; CHECK: [[undef:%\w+]] = OpUndef %bool
  1449. ; CHECK: OpSelectionMerge [[header:%\w+]]
  1450. ; CHECK-NEXT: OpBranchConditional {{%\w+}} [[if_lab:%\w+]] [[else_lab:%\w+]]
  1451. ; CHECK: OpPhi %bool %false [[if_lab]] %false [[else_lab]] [[undef]] [[continue:%\w+]]
  1452. ; CHECK-NEXT: OpLoopMerge [[merge:%\w+]] [[continue]] None
  1453. ; CHECK-NEXT: OpBranch [[ret:%\w+]]
  1454. ; CHECK-NEXT: [[ret]] = OpLabel
  1455. ; CHECK-NEXT: OpReturn
  1456. ; CHECK: [[continue]] = OpLabel
  1457. ; CHECK-NEXT: OpBranch [[header]]
  1458. ; CHECK: [[merge]] = OpLabel
  1459. ; CHECK-NEXT: OpUnreachable
  1460. OpCapability Kernel
  1461. OpCapability Linkage
  1462. OpMemoryModel Logical OpenCL
  1463. OpName %func "func"
  1464. OpDecorate %func LinkageAttributes "func" Export
  1465. %bool = OpTypeBool
  1466. %false = OpConstantFalse %bool
  1467. %true = OpConstantTrue %bool
  1468. %void = OpTypeVoid
  1469. %funcTy = OpTypeFunction %void
  1470. %func = OpFunction %void None %funcTy
  1471. %1 = OpLabel
  1472. %c = OpUndef %bool
  1473. OpSelectionMerge %2 None
  1474. OpBranchConditional %c %if %else
  1475. %if = OpLabel
  1476. OpBranch %2
  1477. %else = OpLabel
  1478. OpBranch %2
  1479. %2 = OpLabel
  1480. %phi = OpPhi %bool %false %if %false %else %true %continue
  1481. OpLoopMerge %merge %continue None
  1482. OpBranch %3
  1483. %3 = OpLabel
  1484. OpReturn
  1485. %continue = OpLabel
  1486. OpBranch %2
  1487. %merge = OpLabel
  1488. OpReturn
  1489. OpFunctionEnd
  1490. )";
  1491. SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
  1492. }
  1493. TEST_F(DeadBranchElimTest, EarlyReconvergence) {
  1494. const std::string text = R"(
  1495. ; CHECK-NOT: OpBranchConditional
  1496. ; CHECK: [[logical:%\w+]] = OpLogicalOr
  1497. ; CHECK-NOT: OpPhi
  1498. ; CHECK: OpLogicalAnd {{%\w+}} {{%\w+}} [[logical]]
  1499. OpCapability Shader
  1500. OpMemoryModel Logical GLSL450
  1501. OpEntryPoint Fragment %func "func"
  1502. OpExecutionMode %func OriginUpperLeft
  1503. %void = OpTypeVoid
  1504. %bool = OpTypeBool
  1505. %false = OpConstantFalse %bool
  1506. %true = OpConstantTrue %bool
  1507. %func_ty = OpTypeFunction %void
  1508. %func = OpFunction %void None %func_ty
  1509. %1 = OpLabel
  1510. OpSelectionMerge %2 None
  1511. OpBranchConditional %false %3 %4
  1512. %3 = OpLabel
  1513. %12 = OpLogicalNot %bool %true
  1514. OpBranch %2
  1515. %4 = OpLabel
  1516. OpSelectionMerge %14 None
  1517. OpBranchConditional %false %5 %6
  1518. %5 = OpLabel
  1519. %10 = OpLogicalAnd %bool %true %false
  1520. OpBranch %7
  1521. %6 = OpLabel
  1522. %11 = OpLogicalOr %bool %true %false
  1523. OpBranch %7
  1524. %7 = OpLabel
  1525. ; This phi is in a block preceding the merge %14!
  1526. %8 = OpPhi %bool %10 %5 %11 %6
  1527. OpBranch %14
  1528. %14 = OpLabel
  1529. OpBranch %2
  1530. %2 = OpLabel
  1531. %9 = OpPhi %bool %12 %3 %8 %14
  1532. %13 = OpLogicalAnd %bool %true %9
  1533. OpReturn
  1534. OpFunctionEnd
  1535. )";
  1536. SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
  1537. }
  1538. TEST_F(DeadBranchElimTest, RemoveUnreachableBlocksFloating) {
  1539. const std::string text = R"(
  1540. ; CHECK: OpFunction
  1541. ; CHECK-NEXT: OpLabel
  1542. ; CHECK-NEXT: OpReturn
  1543. ; CHECK-NEXT: OpFunctionEnd
  1544. OpCapability Kernel
  1545. OpCapability Linkage
  1546. OpMemoryModel Logical OpenCL
  1547. OpName %func "func"
  1548. OpDecorate %func LinkageAttributes "func" Export
  1549. %void = OpTypeVoid
  1550. %1 = OpTypeFunction %void
  1551. %func = OpFunction %void None %1
  1552. %2 = OpLabel
  1553. OpReturn
  1554. %3 = OpLabel
  1555. OpReturn
  1556. OpFunctionEnd
  1557. )";
  1558. SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
  1559. }
  1560. TEST_F(DeadBranchElimTest, RemoveUnreachableBlocksFloatingJoin) {
  1561. const std::string text = R"(
  1562. ; CHECK: OpFunction
  1563. ; CHECK-NEXT: OpFunctionParameter
  1564. ; CHECK-NEXT: OpLabel
  1565. ; CHECK-NEXT: OpReturn
  1566. ; CHECK-NEXT: OpFunctionEnd
  1567. OpCapability Kernel
  1568. OpCapability Linkage
  1569. OpMemoryModel Logical OpenCL
  1570. OpName %func "func"
  1571. OpDecorate %func LinkageAttributes "func" Export
  1572. %void = OpTypeVoid
  1573. %bool = OpTypeBool
  1574. %false = OpConstantFalse %bool
  1575. %true = OpConstantTrue %bool
  1576. %1 = OpTypeFunction %void %bool
  1577. %func = OpFunction %void None %1
  1578. %bool_param = OpFunctionParameter %bool
  1579. %2 = OpLabel
  1580. OpReturn
  1581. %3 = OpLabel
  1582. OpSelectionMerge %6 None
  1583. OpBranchConditional %bool_param %4 %5
  1584. %4 = OpLabel
  1585. OpBranch %6
  1586. %5 = OpLabel
  1587. OpBranch %6
  1588. %6 = OpLabel
  1589. %7 = OpPhi %bool %true %4 %false %6
  1590. OpReturn
  1591. OpFunctionEnd
  1592. )";
  1593. SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
  1594. }
  1595. TEST_F(DeadBranchElimTest, RemoveUnreachableBlocksDeadPhi) {
  1596. const std::string text = R"(
  1597. ; CHECK: OpFunction
  1598. ; CHECK-NEXT: OpFunctionParameter
  1599. ; CHECK-NEXT: OpLabel
  1600. ; CHECK-NEXT: OpBranch [[label:%\w+]]
  1601. ; CHECK-NEXT: [[label]] = OpLabel
  1602. ; CHECK-NEXT: OpLogicalNot %bool %true
  1603. ; CHECK-NEXT: OpReturn
  1604. ; CHECK-NEXT: OpFunctionEnd
  1605. OpCapability Kernel
  1606. OpCapability Linkage
  1607. OpMemoryModel Logical OpenCL
  1608. OpName %func "func"
  1609. OpDecorate %func LinkageAttributes "func" Export
  1610. %void = OpTypeVoid
  1611. %bool = OpTypeBool
  1612. %false = OpConstantFalse %bool
  1613. %true = OpConstantTrue %bool
  1614. %1 = OpTypeFunction %void %bool
  1615. %func = OpFunction %void None %1
  1616. %bool_param = OpFunctionParameter %bool
  1617. %2 = OpLabel
  1618. OpBranch %3
  1619. %4 = OpLabel
  1620. OpBranch %3
  1621. %3 = OpLabel
  1622. %5 = OpPhi %bool %true %2 %false %4
  1623. %6 = OpLogicalNot %bool %5
  1624. OpReturn
  1625. OpFunctionEnd
  1626. )";
  1627. SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
  1628. }
  1629. TEST_F(DeadBranchElimTest, RemoveUnreachableBlocksPartiallyDeadPhi) {
  1630. const std::string text = R"(
  1631. ; CHECK: OpFunction
  1632. ; CHECK-NEXT: [[param:%\w+]] = OpFunctionParameter
  1633. ; CHECK-NEXT: OpLabel
  1634. ; CHECK-NEXT: OpBranchConditional [[param]] [[merge:%\w+]] [[br:%\w+]]
  1635. ; CHECK-NEXT: [[merge]] = OpLabel
  1636. ; CHECK-NEXT: [[phi:%\w+]] = OpPhi %bool %true %2 %false [[br]]
  1637. ; CHECK-NEXT: OpLogicalNot %bool [[phi]]
  1638. ; CHECK-NEXT: OpReturn
  1639. ; CHECK-NEXT: [[br]] = OpLabel
  1640. ; CHECK-NEXT: OpBranch [[merge]]
  1641. ; CHECK-NEXT: OpFunctionEnd
  1642. OpCapability Kernel
  1643. OpCapability Linkage
  1644. OpMemoryModel Logical OpenCL
  1645. OpName %func "func"
  1646. OpDecorate %func LinkageAttributes "func" Export
  1647. %void = OpTypeVoid
  1648. %bool = OpTypeBool
  1649. %false = OpConstantFalse %bool
  1650. %true = OpConstantTrue %bool
  1651. %1 = OpTypeFunction %void %bool
  1652. %func = OpFunction %void None %1
  1653. %bool_param = OpFunctionParameter %bool
  1654. %2 = OpLabel
  1655. OpBranchConditional %bool_param %3 %7
  1656. %7 = OpLabel
  1657. OpBranch %3
  1658. %4 = OpLabel
  1659. OpBranch %3
  1660. %3 = OpLabel
  1661. %5 = OpPhi %bool %true %2 %false %7 %false %4
  1662. %6 = OpLogicalNot %bool %5
  1663. OpReturn
  1664. OpFunctionEnd
  1665. )";
  1666. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  1667. SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
  1668. }
  1669. TEST_F(DeadBranchElimTest, LiveHeaderDeadPhi) {
  1670. const std::string text = R"(
  1671. ; CHECK: OpLabel
  1672. ; CHECK-NOT: OpBranchConditional
  1673. ; CHECK-NOT: OpPhi
  1674. ; CHECK: OpLogicalNot %bool %false
  1675. OpCapability Kernel
  1676. OpCapability Linkage
  1677. OpMemoryModel Logical OpenCL
  1678. OpName %func "func"
  1679. OpDecorate %func LinkageAttributes "func" Export
  1680. %void = OpTypeVoid
  1681. %bool = OpTypeBool
  1682. %true = OpConstantTrue %bool
  1683. %false = OpConstantFalse %bool
  1684. %func_ty = OpTypeFunction %void
  1685. %func = OpFunction %void None %func_ty
  1686. %1 = OpLabel
  1687. OpSelectionMerge %3 None
  1688. OpBranchConditional %true %2 %3
  1689. %2 = OpLabel
  1690. OpBranch %3
  1691. %3 = OpLabel
  1692. %5 = OpPhi %bool %true %3 %false %2
  1693. %6 = OpLogicalNot %bool %5
  1694. OpReturn
  1695. OpFunctionEnd
  1696. )";
  1697. SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
  1698. }
  1699. TEST_F(DeadBranchElimTest, ExtraBackedgeBlocksLive) {
  1700. const std::string text = R"(
  1701. ; CHECK: [[entry:%\w+]] = OpLabel
  1702. ; CHECK-NOT: OpSelectionMerge
  1703. ; CHECK: OpBranch [[header:%\w+]]
  1704. ; CHECK-NEXT: [[header]] = OpLabel
  1705. ; CHECK-NEXT: OpPhi %bool %true [[entry]] %false [[backedge:%\w+]]
  1706. ; CHECK-NEXT: OpLoopMerge
  1707. OpCapability Kernel
  1708. OpCapability Linkage
  1709. OpMemoryModel Logical OpenCL
  1710. OpName %func "func"
  1711. OpDecorate %func LinkageAttributes "func" Export
  1712. %void = OpTypeVoid
  1713. %bool = OpTypeBool
  1714. %true = OpConstantTrue %bool
  1715. %false = OpConstantFalse %bool
  1716. %func_ty = OpTypeFunction %void %bool
  1717. %func = OpFunction %void None %func_ty
  1718. %param = OpFunctionParameter %bool
  1719. %entry = OpLabel
  1720. OpSelectionMerge %if_merge None
  1721. ; This dead branch is included to ensure the pass does work.
  1722. OpBranchConditional %false %if_merge %loop_header
  1723. %loop_header = OpLabel
  1724. ; Both incoming edges are live, so the phi should be untouched.
  1725. %phi = OpPhi %bool %true %entry %false %backedge
  1726. OpLoopMerge %loop_merge %continue None
  1727. OpBranchConditional %param %loop_merge %continue
  1728. %continue = OpLabel
  1729. OpBranch %backedge
  1730. %backedge = OpLabel
  1731. OpBranch %loop_header
  1732. %loop_merge = OpLabel
  1733. OpBranch %if_merge
  1734. %if_merge = OpLabel
  1735. OpReturn
  1736. OpFunctionEnd
  1737. )";
  1738. SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
  1739. }
  1740. TEST_F(DeadBranchElimTest, ExtraBackedgeBlocksUnreachable) {
  1741. const std::string text = R"(
  1742. ; CHECK: [[entry:%\w+]] = OpLabel
  1743. ; CHECK-NEXT: OpBranch [[header:%\w+]]
  1744. ; CHECK-NEXT: [[header]] = OpLabel
  1745. ; CHECK-NEXT: OpLoopMerge [[merge:%\w+]] [[continue:%\w+]] None
  1746. ; CHECK-NEXT: OpBranch [[merge]]
  1747. ; CHECK-NEXT: [[merge]] = OpLabel
  1748. ; CHECK-NEXT: OpReturn
  1749. ; CHECK-NEXT: [[continue]] = OpLabel
  1750. ; CHECK-NEXT: OpBranch [[header]]
  1751. OpCapability Kernel
  1752. OpCapability Linkage
  1753. OpMemoryModel Logical OpenCL
  1754. OpName %func "func"
  1755. OpDecorate %func LinkageAttributes "func" Export
  1756. %void = OpTypeVoid
  1757. %bool = OpTypeBool
  1758. %true = OpConstantTrue %bool
  1759. %false = OpConstantFalse %bool
  1760. %func_ty = OpTypeFunction %void %bool
  1761. %func = OpFunction %void None %func_ty
  1762. %param = OpFunctionParameter %bool
  1763. %entry = OpLabel
  1764. OpBranch %loop_header
  1765. %loop_header = OpLabel
  1766. ; Since the continue is unreachable, %backedge will be removed. The phi will
  1767. ; instead require an edge from %continue.
  1768. %phi = OpPhi %bool %true %entry %false %backedge
  1769. OpLoopMerge %merge %continue None
  1770. OpBranch %merge
  1771. %continue = OpLabel
  1772. OpBranch %backedge
  1773. %backedge = OpLabel
  1774. OpBranch %loop_header
  1775. %merge = OpLabel
  1776. OpReturn
  1777. OpFunctionEnd
  1778. )";
  1779. SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
  1780. }
  1781. TEST_F(DeadBranchElimTest, NoUnnecessaryChanges) {
  1782. const std::string text = R"(
  1783. OpCapability Shader
  1784. OpMemoryModel Logical GLSL450
  1785. OpEntryPoint Fragment %func "func"
  1786. %void = OpTypeVoid
  1787. %bool = OpTypeBool
  1788. %true = OpConstantTrue %bool
  1789. %undef = OpUndef %bool
  1790. %functy = OpTypeFunction %void
  1791. %func = OpFunction %void None %functy
  1792. %1 = OpLabel
  1793. OpBranch %2
  1794. %2 = OpLabel
  1795. OpLoopMerge %4 %5 None
  1796. OpBranch %6
  1797. %6 = OpLabel
  1798. OpReturn
  1799. %5 = OpLabel
  1800. OpBranch %2
  1801. %4 = OpLabel
  1802. OpUnreachable
  1803. OpFunctionEnd
  1804. )";
  1805. auto result = SinglePassRunToBinary<DeadBranchElimPass>(text, true);
  1806. EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithoutChange);
  1807. }
  1808. TEST_F(DeadBranchElimTest, ExtraBackedgePartiallyDead) {
  1809. const std::string text = R"(
  1810. ; CHECK: OpLabel
  1811. ; CHECK: [[header:%\w+]] = OpLabel
  1812. ; CHECK: OpLoopMerge [[merge:%\w+]] [[continue:%\w+]] None
  1813. ; CHECK: [[merge]] = OpLabel
  1814. ; CHECK: [[continue]] = OpLabel
  1815. ; CHECK: OpBranch [[extra:%\w+]]
  1816. ; CHECK: [[extra]] = OpLabel
  1817. ; CHECK-NOT: OpSelectionMerge
  1818. ; CHECK-NEXT: OpBranch [[else:%\w+]]
  1819. ; CHECK-NEXT: [[else]] = OpLabel
  1820. ; CHECK-NEXT: OpLogicalOr
  1821. ; CHECK-NEXT: OpBranch [[backedge:%\w+]]
  1822. ; CHECK-NEXT: [[backedge:%\w+]] = OpLabel
  1823. ; CHECK-NEXT: OpBranch [[header]]
  1824. OpCapability Kernel
  1825. OpCapability Linkage
  1826. OpMemoryModel Logical OpenCL
  1827. OpName %func "func"
  1828. OpDecorate %func LinkageAttributes "func" Export
  1829. %void = OpTypeVoid
  1830. %bool = OpTypeBool
  1831. %true = OpConstantTrue %bool
  1832. %false = OpConstantFalse %bool
  1833. %func_ty = OpTypeFunction %void %bool
  1834. %func = OpFunction %void None %func_ty
  1835. %param = OpFunctionParameter %bool
  1836. %entry = OpLabel
  1837. OpBranch %loop_header
  1838. %loop_header = OpLabel
  1839. OpLoopMerge %loop_merge %continue None
  1840. OpBranchConditional %param %loop_merge %continue
  1841. %continue = OpLabel
  1842. OpBranch %extra
  1843. %extra = OpLabel
  1844. OpSelectionMerge %backedge None
  1845. OpBranchConditional %false %then %else
  1846. %then = OpLabel
  1847. %and = OpLogicalAnd %bool %true %false
  1848. OpBranch %backedge
  1849. %else = OpLabel
  1850. %or = OpLogicalOr %bool %true %false
  1851. OpBranch %backedge
  1852. %backedge = OpLabel
  1853. OpBranch %loop_header
  1854. %loop_merge = OpLabel
  1855. OpReturn
  1856. OpFunctionEnd
  1857. )";
  1858. SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
  1859. }
  1860. TEST_F(DeadBranchElimTest, UnreachableContinuePhiInMerge) {
  1861. const std::string text = R"(
  1862. ; CHECK: [[entry:%\w+]] = OpLabel
  1863. ; CHECK-NEXT: OpBranch [[header:%\w+]]
  1864. ; CHECK-NEXT: [[header]] = OpLabel
  1865. ; CHECK-NEXT: OpLoopMerge [[merge:%\w+]] [[continue:%\w+]] None
  1866. ; CHECK-NEXT: OpBranch [[label:%\w+]]
  1867. ; CHECK-NEXT: [[label]] = OpLabel
  1868. ; CHECK-NEXT: [[fadd:%\w+]] = OpFAdd
  1869. ; CHECK-NEXT: OpBranch [[label:%\w+]]
  1870. ; CHECK-NEXT: [[label]] = OpLabel
  1871. ; CHECK-NEXT: OpBranch [[merge]]
  1872. ; CHECK-NEXT: [[continue]] = OpLabel
  1873. ; CHECK-NEXT: OpBranch [[header]]
  1874. ; CHECK-NEXT: [[merge]] = OpLabel
  1875. ; CHECK-NEXT: OpStore {{%\w+}} [[fadd]]
  1876. OpCapability Shader
  1877. %1 = OpExtInstImport "GLSL.std.450"
  1878. OpMemoryModel Logical GLSL450
  1879. OpEntryPoint Fragment %main "main" %o
  1880. OpExecutionMode %main OriginUpperLeft
  1881. OpSource GLSL 430
  1882. OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
  1883. OpSourceExtension "GL_GOOGLE_include_directive"
  1884. OpName %main "main"
  1885. OpName %o "o"
  1886. OpName %S "S"
  1887. OpMemberName %S 0 "a"
  1888. OpName %U_t "U_t"
  1889. OpMemberName %U_t 0 "g_F"
  1890. OpMemberName %U_t 1 "g_F2"
  1891. OpDecorate %o Location 0
  1892. OpMemberDecorate %S 0 Offset 0
  1893. OpMemberDecorate %U_t 0 Volatile
  1894. OpMemberDecorate %U_t 0 Offset 0
  1895. OpMemberDecorate %U_t 1 Offset 4
  1896. OpDecorate %U_t BufferBlock
  1897. %void = OpTypeVoid
  1898. %7 = OpTypeFunction %void
  1899. %float = OpTypeFloat 32
  1900. %_ptr_Function_float = OpTypePointer Function %float
  1901. %float_0 = OpConstant %float 0
  1902. %int = OpTypeInt 32 1
  1903. %_ptr_Function_int = OpTypePointer Function %int
  1904. %int_0 = OpConstant %int 0
  1905. %int_10 = OpConstant %int 10
  1906. %bool = OpTypeBool
  1907. %true = OpConstantTrue %bool
  1908. %float_1 = OpConstant %float 1
  1909. %float_5 = OpConstant %float 5
  1910. %int_1 = OpConstant %int 1
  1911. %_ptr_Output_float = OpTypePointer Output %float
  1912. %o = OpVariable %_ptr_Output_float Output
  1913. %S = OpTypeStruct %float
  1914. %U_t = OpTypeStruct %S %S
  1915. %_ptr_Uniform_U_t = OpTypePointer Uniform %U_t
  1916. %main = OpFunction %void None %7
  1917. %22 = OpLabel
  1918. OpBranch %23
  1919. %23 = OpLabel
  1920. %24 = OpPhi %float %float_0 %22 %25 %26
  1921. %27 = OpPhi %int %int_0 %22 %28 %26
  1922. OpLoopMerge %29 %26 None
  1923. OpBranch %40
  1924. %40 = OpLabel
  1925. %25 = OpFAdd %float %24 %float_1
  1926. OpSelectionMerge %30 None
  1927. OpBranchConditional %true %31 %30
  1928. %31 = OpLabel
  1929. OpBranch %29
  1930. %30 = OpLabel
  1931. OpBranch %26
  1932. %26 = OpLabel
  1933. %28 = OpIAdd %int %27 %int_1
  1934. %32 = OpSLessThan %bool %27 %int_10
  1935. ; continue block branches to the header or another none dead block.
  1936. OpBranchConditional %32 %23 %29
  1937. %29 = OpLabel
  1938. %33 = OpPhi %float %24 %26 %25 %31
  1939. OpStore %o %33
  1940. OpReturn
  1941. OpFunctionEnd
  1942. )";
  1943. SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
  1944. }
  1945. TEST_F(DeadBranchElimTest, NonStructuredIf) {
  1946. const std::string text = R"(
  1947. ; CHECK-NOT: OpBranchConditional
  1948. OpCapability Kernel
  1949. OpCapability Linkage
  1950. OpMemoryModel Logical OpenCL
  1951. OpDecorate %func LinkageAttributes "func" Export
  1952. %void = OpTypeVoid
  1953. %bool = OpTypeBool
  1954. %true = OpConstantTrue %bool
  1955. %functy = OpTypeFunction %void
  1956. %func = OpFunction %void None %functy
  1957. %entry = OpLabel
  1958. OpBranchConditional %true %then %else
  1959. %then = OpLabel
  1960. OpBranch %final
  1961. %else = OpLabel
  1962. OpBranch %final
  1963. %final = OpLabel
  1964. OpReturn
  1965. OpFunctionEnd
  1966. )";
  1967. SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
  1968. }
  1969. TEST_F(DeadBranchElimTest, ReorderBlocks) {
  1970. const std::string text = R"(
  1971. ; CHECK: OpLabel
  1972. ; CHECK: OpBranch [[label:%\w+]]
  1973. ; CHECK: [[label:%\w+]] = OpLabel
  1974. ; CHECK-NEXT: OpLogicalNot
  1975. ; CHECK-NEXT: OpBranch [[label:%\w+]]
  1976. ; CHECK: [[label]] = OpLabel
  1977. ; CHECK-NEXT: OpReturn
  1978. OpCapability Shader
  1979. OpMemoryModel Logical GLSL450
  1980. OpEntryPoint Fragment %func "func"
  1981. OpExecutionMode %func OriginUpperLeft
  1982. %void = OpTypeVoid
  1983. %bool = OpTypeBool
  1984. %true = OpConstantTrue %bool
  1985. %func_ty = OpTypeFunction %void
  1986. %func = OpFunction %void None %func_ty
  1987. %1 = OpLabel
  1988. OpSelectionMerge %3 None
  1989. OpBranchConditional %true %2 %3
  1990. %3 = OpLabel
  1991. OpReturn
  1992. %2 = OpLabel
  1993. %not = OpLogicalNot %bool %true
  1994. OpBranch %3
  1995. OpFunctionEnd
  1996. )";
  1997. SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
  1998. }
  1999. TEST_F(DeadBranchElimTest, ReorderBlocksMultiple) {
  2000. // Checks are not important. The validation post optimization is the
  2001. // important part.
  2002. const std::string text = R"(
  2003. ; CHECK: OpLabel
  2004. OpCapability Shader
  2005. OpMemoryModel Logical GLSL450
  2006. OpEntryPoint Fragment %func "func"
  2007. OpExecutionMode %func OriginUpperLeft
  2008. %void = OpTypeVoid
  2009. %bool = OpTypeBool
  2010. %true = OpConstantTrue %bool
  2011. %func_ty = OpTypeFunction %void
  2012. %func = OpFunction %void None %func_ty
  2013. %1 = OpLabel
  2014. OpSelectionMerge %3 None
  2015. OpBranchConditional %true %2 %3
  2016. %3 = OpLabel
  2017. OpReturn
  2018. %2 = OpLabel
  2019. OpBranch %4
  2020. %4 = OpLabel
  2021. OpBranch %3
  2022. OpFunctionEnd
  2023. )";
  2024. SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
  2025. }
  2026. TEST_F(DeadBranchElimTest, ReorderBlocksMultiple2) {
  2027. // Checks are not important. The validation post optimization is the
  2028. // important part.
  2029. const std::string text = R"(
  2030. ; CHECK: OpLabel
  2031. OpCapability Shader
  2032. OpMemoryModel Logical GLSL450
  2033. OpEntryPoint Fragment %func "func"
  2034. OpExecutionMode %func OriginUpperLeft
  2035. %void = OpTypeVoid
  2036. %bool = OpTypeBool
  2037. %true = OpConstantTrue %bool
  2038. %func_ty = OpTypeFunction %void
  2039. %func = OpFunction %void None %func_ty
  2040. %1 = OpLabel
  2041. OpSelectionMerge %3 None
  2042. OpBranchConditional %true %2 %3
  2043. %3 = OpLabel
  2044. OpBranch %5
  2045. %5 = OpLabel
  2046. OpReturn
  2047. %2 = OpLabel
  2048. OpBranch %4
  2049. %4 = OpLabel
  2050. OpBranch %3
  2051. OpFunctionEnd
  2052. )";
  2053. SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
  2054. }
  2055. TEST_F(DeadBranchElimTest, SelectionMergeWithEarlyExit1) {
  2056. // Checks that if a selection merge construct contains a conditional branch
  2057. // to the merge node, then the OpSelectionMerge instruction is positioned
  2058. // correctly.
  2059. const std::string predefs = R"(
  2060. OpCapability Shader
  2061. %1 = OpExtInstImport "GLSL.std.450"
  2062. OpMemoryModel Logical GLSL450
  2063. OpEntryPoint Fragment %main "main"
  2064. OpExecutionMode %main OriginUpperLeft
  2065. OpSource GLSL 140
  2066. %void = OpTypeVoid
  2067. %func_type = OpTypeFunction %void
  2068. %bool = OpTypeBool
  2069. %true = OpConstantTrue %bool
  2070. %undef_bool = OpUndef %bool
  2071. )";
  2072. const std::string body =
  2073. R"(
  2074. ; CHECK: OpFunction
  2075. ; CHECK-NEXT: OpLabel
  2076. ; CHECK-NEXT: OpBranch [[taken_branch:%\w+]]
  2077. ; CHECK-NEXT: [[taken_branch]] = OpLabel
  2078. ; CHECK-NEXT: OpSelectionMerge [[merge:%\w+]]
  2079. ; CHECK-NEXT: OpBranchConditional {{%\w+}} [[merge]] {{%\w+}}
  2080. %main = OpFunction %void None %func_type
  2081. %entry_bb = OpLabel
  2082. OpSelectionMerge %outer_merge None
  2083. OpBranchConditional %true %bb1 %bb3
  2084. %bb1 = OpLabel
  2085. OpBranchConditional %undef_bool %outer_merge %bb2
  2086. %bb2 = OpLabel
  2087. OpBranch %outer_merge
  2088. %bb3 = OpLabel
  2089. OpBranch %outer_merge
  2090. %outer_merge = OpLabel
  2091. OpReturn
  2092. OpFunctionEnd
  2093. )";
  2094. SinglePassRunAndMatch<DeadBranchElimPass>(predefs + body, true);
  2095. }
  2096. TEST_F(DeadBranchElimTest, SelectionMergeWithEarlyExit2) {
  2097. // Checks that if a selection merge construct contains a conditional branch
  2098. // to the merge node, then the OpSelectionMerge instruction is positioned
  2099. // correctly.
  2100. const std::string predefs = R"(
  2101. OpCapability Shader
  2102. %1 = OpExtInstImport "GLSL.std.450"
  2103. OpMemoryModel Logical GLSL450
  2104. OpEntryPoint Fragment %main "main"
  2105. OpExecutionMode %main OriginUpperLeft
  2106. OpSource GLSL 140
  2107. %void = OpTypeVoid
  2108. %func_type = OpTypeFunction %void
  2109. %bool = OpTypeBool
  2110. %true = OpConstantTrue %bool
  2111. %undef_bool = OpUndef %bool
  2112. )";
  2113. const std::string body =
  2114. R"(
  2115. ; CHECK: OpFunction
  2116. ; CHECK-NEXT: OpLabel
  2117. ; CHECK-NEXT: OpBranch [[bb1:%\w+]]
  2118. ; CHECK-NEXT: [[bb1]] = OpLabel
  2119. ; CHECK-NEXT: OpSelectionMerge [[inner_merge:%\w+]]
  2120. ; CHECK: [[inner_merge]] = OpLabel
  2121. ; CHECK-NEXT: OpSelectionMerge [[outer_merge:%\w+]]
  2122. ; CHECK-NEXT: OpBranchConditional {{%\w+}} [[outer_merge]:%\w+]] {{%\w+}}
  2123. ; CHECK: [[outer_merge]] = OpLabel
  2124. ; CHECK-NEXT: OpReturn
  2125. %main = OpFunction %void None %func_type
  2126. %entry_bb = OpLabel
  2127. OpSelectionMerge %outer_merge None
  2128. OpBranchConditional %true %bb1 %bb5
  2129. %bb1 = OpLabel
  2130. OpSelectionMerge %inner_merge None
  2131. OpBranchConditional %undef_bool %bb2 %bb3
  2132. %bb2 = OpLabel
  2133. OpBranch %inner_merge
  2134. %bb3 = OpLabel
  2135. OpBranch %inner_merge
  2136. %inner_merge = OpLabel
  2137. OpBranchConditional %undef_bool %outer_merge %bb4
  2138. %bb4 = OpLabel
  2139. OpBranch %outer_merge
  2140. %bb5 = OpLabel
  2141. OpBranch %outer_merge
  2142. %outer_merge = OpLabel
  2143. OpReturn
  2144. OpFunctionEnd
  2145. )";
  2146. SinglePassRunAndMatch<DeadBranchElimPass>(predefs + body, true);
  2147. }
  2148. TEST_F(DeadBranchElimTest, SelectionMergeWithConditionalExit) {
  2149. // Checks that if a selection merge construct contains a conditional branch
  2150. // to the merge node, then we keep the OpSelectionMerge on that branch.
  2151. const std::string predefs = R"(
  2152. OpCapability Shader
  2153. %1 = OpExtInstImport "GLSL.std.450"
  2154. OpMemoryModel Logical GLSL450
  2155. OpEntryPoint Fragment %main "main"
  2156. OpExecutionMode %main OriginUpperLeft
  2157. OpSource GLSL 140
  2158. %void = OpTypeVoid
  2159. %func_type = OpTypeFunction %void
  2160. %bool = OpTypeBool
  2161. %true = OpConstantTrue %bool
  2162. %uint = OpTypeInt 32 0
  2163. %undef_int = OpUndef %uint
  2164. )";
  2165. const std::string body =
  2166. R"(
  2167. ; CHECK: OpLoopMerge [[loop_merge:%\w+]]
  2168. ; CHECK-NEXT: OpBranch [[bb1:%\w+]]
  2169. ; CHECK: [[bb1]] = OpLabel
  2170. ; CHECK-NEXT: OpBranch [[bb2:%\w+]]
  2171. ; CHECK: [[bb2]] = OpLabel
  2172. ; CHECK-NEXT: OpSelectionMerge [[sel_merge:%\w+]] None
  2173. ; CHECK-NEXT: OpSwitch {{%\w+}} [[sel_merge]] 1 [[bb3:%\w+]]
  2174. ; CHECK: [[bb3]] = OpLabel
  2175. ; CHECK-NEXT: OpBranch [[sel_merge]]
  2176. ; CHECK: [[sel_merge]] = OpLabel
  2177. ; CHECK-NEXT: OpBranch [[loop_merge]]
  2178. ; CHECK: [[loop_merge]] = OpLabel
  2179. ; CHECK-NEXT: OpReturn
  2180. %main = OpFunction %void None %func_type
  2181. %entry_bb = OpLabel
  2182. OpBranch %loop_header
  2183. %loop_header = OpLabel
  2184. OpLoopMerge %loop_merge %cont None
  2185. OpBranch %bb1
  2186. %bb1 = OpLabel
  2187. OpSelectionMerge %sel_merge None
  2188. OpBranchConditional %true %bb2 %bb4
  2189. %bb2 = OpLabel
  2190. OpSwitch %undef_int %sel_merge 1 %bb3
  2191. %bb3 = OpLabel
  2192. OpBranch %sel_merge
  2193. %bb4 = OpLabel
  2194. OpBranch %sel_merge
  2195. %sel_merge = OpLabel
  2196. OpBranch %loop_merge
  2197. %cont = OpLabel
  2198. OpBranch %loop_header
  2199. %loop_merge = OpLabel
  2200. OpReturn
  2201. OpFunctionEnd
  2202. )";
  2203. SinglePassRunAndMatch<DeadBranchElimPass>(predefs + body, true);
  2204. }
  2205. TEST_F(DeadBranchElimTest, SelectionMergeWithExitToLoop) {
  2206. // Checks that if a selection merge construct contains a conditional branch
  2207. // to a loop surrounding the selection merge, then we do not keep the
  2208. // OpSelectionMerge instruction.
  2209. const std::string predefs = R"(
  2210. OpCapability Shader
  2211. %1 = OpExtInstImport "GLSL.std.450"
  2212. OpMemoryModel Logical GLSL450
  2213. OpEntryPoint Fragment %main "main"
  2214. OpExecutionMode %main OriginUpperLeft
  2215. OpSource GLSL 140
  2216. %void = OpTypeVoid
  2217. %func_type = OpTypeFunction %void
  2218. %bool = OpTypeBool
  2219. %true = OpConstantTrue %bool
  2220. %undef_bool = OpUndef %bool
  2221. )";
  2222. const std::string body =
  2223. R"(
  2224. ; CHECK: OpLoopMerge [[loop_merge:%\w+]]
  2225. ; CHECK-NEXT: OpBranch [[bb1:%\w+]]
  2226. ; CHECK: [[bb1]] = OpLabel
  2227. ; CHECK-NEXT: OpBranch [[bb2:%\w+]]
  2228. ; CHECK: [[bb2]] = OpLabel
  2229. ; CHECK-NEXT: OpBranchConditional {{%\w+}} [[bb3:%\w+]] [[loop_merge]]
  2230. ; CHECK: [[bb3]] = OpLabel
  2231. ; CHECK-NEXT: OpBranch [[sel_merge:%\w+]]
  2232. ; CHECK: [[sel_merge]] = OpLabel
  2233. ; CHECK-NEXT: OpBranch [[loop_merge]]
  2234. ; CHECK: [[loop_merge]] = OpLabel
  2235. ; CHECK-NEXT: OpReturn
  2236. %main = OpFunction %void None %func_type
  2237. %entry_bb = OpLabel
  2238. OpBranch %loop_header
  2239. %loop_header = OpLabel
  2240. OpLoopMerge %loop_merge %cont None
  2241. OpBranch %bb1
  2242. %bb1 = OpLabel
  2243. OpSelectionMerge %sel_merge None
  2244. OpBranchConditional %true %bb2 %bb4
  2245. %bb2 = OpLabel
  2246. OpBranchConditional %undef_bool %bb3 %loop_merge
  2247. %bb3 = OpLabel
  2248. OpBranch %sel_merge
  2249. %bb4 = OpLabel
  2250. OpBranch %sel_merge
  2251. %sel_merge = OpLabel
  2252. OpBranch %loop_merge
  2253. %cont = OpLabel
  2254. OpBranch %loop_header
  2255. %loop_merge = OpLabel
  2256. OpReturn
  2257. OpFunctionEnd
  2258. )";
  2259. SinglePassRunAndMatch<DeadBranchElimPass>(predefs + body, true);
  2260. }
  2261. TEST_F(DeadBranchElimTest, SelectionMergeWithExitToLoopContinue) {
  2262. // Checks that if a selection merge construct contains a conditional branch
  2263. // to continue of a loop surrounding the selection merge, then we do not keep
  2264. // the OpSelectionMerge instruction.
  2265. const std::string predefs = R"(
  2266. OpCapability Shader
  2267. %1 = OpExtInstImport "GLSL.std.450"
  2268. OpMemoryModel Logical GLSL450
  2269. OpEntryPoint Fragment %main "main"
  2270. OpExecutionMode %main OriginUpperLeft
  2271. OpSource GLSL 140
  2272. %void = OpTypeVoid
  2273. %func_type = OpTypeFunction %void
  2274. %bool = OpTypeBool
  2275. %true = OpConstantTrue %bool
  2276. %undef_bool = OpUndef %bool
  2277. )";
  2278. const std::string body =
  2279. R"(;
  2280. ; CHECK: OpLabel
  2281. ; CHECK: [[loop_header:%\w+]] = OpLabel
  2282. ; CHECK: OpLoopMerge [[loop_merge:%\w+]] [[loop_cont:%\w+]]
  2283. ; CHECK-NEXT: OpBranch [[bb1:%\w+]]
  2284. ; CHECK: [[bb1]] = OpLabel
  2285. ; CHECK-NEXT: OpBranch [[bb2:%\w+]]
  2286. ; CHECK: [[bb2]] = OpLabel
  2287. ; CHECK-NEXT: OpBranchConditional {{%\w+}} [[bb3:%\w+]] [[loop_cont]]
  2288. ; CHECK: [[bb3]] = OpLabel
  2289. ; CHECK-NEXT: OpBranch [[sel_merge:%\w+]]
  2290. ; CHECK: [[sel_merge]] = OpLabel
  2291. ; CHECK-NEXT: OpBranch [[loop_merge]]
  2292. ; CHECK: [[loop_cont]] = OpLabel
  2293. ; CHECK-NEXT: OpBranch [[loop_header]]
  2294. ; CHECK: [[loop_merge]] = OpLabel
  2295. ; CHECK-NEXT: OpReturn
  2296. %main = OpFunction %void None %func_type
  2297. %entry_bb = OpLabel
  2298. OpBranch %loop_header
  2299. %loop_header = OpLabel
  2300. OpLoopMerge %loop_merge %cont None
  2301. OpBranch %bb1
  2302. %bb1 = OpLabel
  2303. OpSelectionMerge %sel_merge None
  2304. OpBranchConditional %true %bb2 %bb4
  2305. %bb2 = OpLabel
  2306. OpBranchConditional %undef_bool %bb3 %cont
  2307. %bb3 = OpLabel
  2308. OpBranch %sel_merge
  2309. %bb4 = OpLabel
  2310. OpBranch %sel_merge
  2311. %sel_merge = OpLabel
  2312. OpBranch %loop_merge
  2313. %cont = OpLabel
  2314. OpBranch %loop_header
  2315. %loop_merge = OpLabel
  2316. OpReturn
  2317. OpFunctionEnd
  2318. )";
  2319. SinglePassRunAndMatch<DeadBranchElimPass>(predefs + body, true);
  2320. }
  2321. TEST_F(DeadBranchElimTest, SelectionMergeWithExitToLoop2) {
  2322. // Same as |SelectionMergeWithExitToLoop|, except the switch goes to the loop
  2323. // merge or the selection merge. In this case, we do not need an
  2324. // OpSelectionMerge either.
  2325. const std::string predefs = R"(
  2326. OpCapability Shader
  2327. %1 = OpExtInstImport "GLSL.std.450"
  2328. OpMemoryModel Logical GLSL450
  2329. OpEntryPoint Fragment %main "main"
  2330. OpExecutionMode %main OriginUpperLeft
  2331. OpSource GLSL 140
  2332. %void = OpTypeVoid
  2333. %func_type = OpTypeFunction %void
  2334. %bool = OpTypeBool
  2335. %true = OpConstantTrue %bool
  2336. %undef_bool = OpUndef %bool
  2337. )";
  2338. const std::string body =
  2339. R"(
  2340. ; CHECK: OpLoopMerge [[loop_merge:%\w+]]
  2341. ; CHECK-NEXT: OpBranch [[bb1:%\w+]]
  2342. ; CHECK: [[bb1]] = OpLabel
  2343. ; CHECK-NEXT: OpBranch [[bb2:%\w+]]
  2344. ; CHECK: [[bb2]] = OpLabel
  2345. ; CHECK-NEXT: OpBranchConditional {{%\w+}} [[sel_merge:%\w+]] [[loop_merge]]
  2346. ; CHECK: [[sel_merge]] = OpLabel
  2347. ; CHECK-NEXT: OpBranch [[loop_merge]]
  2348. ; CHECK: [[loop_merge]] = OpLabel
  2349. ; CHECK-NEXT: OpReturn
  2350. %main = OpFunction %void None %func_type
  2351. %entry_bb = OpLabel
  2352. OpBranch %loop_header
  2353. %loop_header = OpLabel
  2354. OpLoopMerge %loop_merge %cont None
  2355. OpBranch %bb1
  2356. %bb1 = OpLabel
  2357. OpSelectionMerge %sel_merge None
  2358. OpBranchConditional %true %bb2 %bb4
  2359. %bb2 = OpLabel
  2360. OpBranchConditional %undef_bool %sel_merge %loop_merge
  2361. %bb4 = OpLabel
  2362. OpBranch %sel_merge
  2363. %sel_merge = OpLabel
  2364. OpBranch %loop_merge
  2365. %cont = OpLabel
  2366. OpBranch %loop_header
  2367. %loop_merge = OpLabel
  2368. OpReturn
  2369. OpFunctionEnd
  2370. )";
  2371. SinglePassRunAndMatch<DeadBranchElimPass>(predefs + body, true);
  2372. }
  2373. TEST_F(DeadBranchElimTest, SelectionMergeWithExitToLoopContinue2) {
  2374. // Same as |SelectionMergeWithExitToLoopContinue|, except the branch goes to
  2375. // the loop continue or the selection merge. In this case, we do not need an
  2376. // OpSelectionMerge either.
  2377. const std::string predefs = R"(
  2378. OpCapability Shader
  2379. %1 = OpExtInstImport "GLSL.std.450"
  2380. OpMemoryModel Logical GLSL450
  2381. OpEntryPoint Fragment %main "main"
  2382. OpExecutionMode %main OriginUpperLeft
  2383. OpSource GLSL 140
  2384. %void = OpTypeVoid
  2385. %func_type = OpTypeFunction %void
  2386. %bool = OpTypeBool
  2387. %true = OpConstantTrue %bool
  2388. %undef_bool = OpUndef %bool
  2389. )";
  2390. const std::string body =
  2391. R"(
  2392. ; CHECK: OpLabel
  2393. ; CHECK: [[loop_header:%\w+]] = OpLabel
  2394. ; CHECK: OpLoopMerge [[loop_merge:%\w+]] [[loop_cont:%\w+]]
  2395. ; CHECK-NEXT: OpBranch [[bb1:%\w+]]
  2396. ; CHECK: [[bb1]] = OpLabel
  2397. ; CHECK-NEXT: OpBranch [[bb2:%\w+]]
  2398. ; CHECK: [[bb2]] = OpLabel
  2399. ; CHECK-NEXT: OpBranchConditional {{%\w+}} [[sel_merge:%\w+]] [[loop_cont]]
  2400. ; CHECK: [[sel_merge]] = OpLabel
  2401. ; CHECK-NEXT: OpBranch [[loop_merge]]
  2402. ; CHECK: [[loop_cont]] = OpLabel
  2403. ; CHECK: OpBranch [[loop_header]]
  2404. ; CHECK: [[loop_merge]] = OpLabel
  2405. ; CHECK-NEXT: OpReturn
  2406. %main = OpFunction %void None %func_type
  2407. %entry_bb = OpLabel
  2408. OpBranch %loop_header
  2409. %loop_header = OpLabel
  2410. OpLoopMerge %loop_merge %cont None
  2411. OpBranch %bb1
  2412. %bb1 = OpLabel
  2413. OpSelectionMerge %sel_merge None
  2414. OpBranchConditional %true %bb2 %bb4
  2415. %bb2 = OpLabel
  2416. OpBranchConditional %undef_bool %sel_merge %cont
  2417. %bb4 = OpLabel
  2418. OpBranch %sel_merge
  2419. %sel_merge = OpLabel
  2420. OpBranch %loop_merge
  2421. %cont = OpLabel
  2422. OpBranch %loop_header
  2423. %loop_merge = OpLabel
  2424. OpReturn
  2425. OpFunctionEnd
  2426. )";
  2427. SinglePassRunAndMatch<DeadBranchElimPass>(predefs + body, true);
  2428. }
  2429. TEST_F(DeadBranchElimTest, SelectionMergeWithExitToLoop3) {
  2430. // Checks that if a selection merge construct contains a conditional branch
  2431. // to the selection merge, and another block inside the selection merge,
  2432. // then we must keep the OpSelectionMerge instruction on that branch.
  2433. const std::string predefs = R"(
  2434. OpCapability Shader
  2435. %1 = OpExtInstImport "GLSL.std.450"
  2436. OpMemoryModel Logical GLSL450
  2437. OpEntryPoint Fragment %main "main"
  2438. OpExecutionMode %main OriginUpperLeft
  2439. OpSource GLSL 140
  2440. %void = OpTypeVoid
  2441. %func_type = OpTypeFunction %void
  2442. %bool = OpTypeBool
  2443. %true = OpConstantTrue %bool
  2444. %uint = OpTypeInt 32 0
  2445. %undef_int = OpUndef %uint
  2446. %undef_bool = OpUndef %bool
  2447. )";
  2448. const std::string body =
  2449. R"(
  2450. ; CHECK: OpLoopMerge [[loop_merge:%\w+]]
  2451. ; CHECK-NEXT: OpBranch [[bb1:%\w+]]
  2452. ; CHECK: [[bb1]] = OpLabel
  2453. ; CHECK-NEXT: OpBranch [[bb2:%\w+]]
  2454. ; CHECK: [[bb2]] = OpLabel
  2455. ; CHECK-NEXT: OpSelectionMerge [[sel_merge:%\w+]] None
  2456. ; CHECK-NEXT: OpBranchConditional {{%\w+}} [[sel_merge]] [[bb3:%\w+]]
  2457. ; CHECK: [[bb3]] = OpLabel
  2458. ; CHECK-NEXT: OpBranch [[sel_merge]]
  2459. ; CHECK: [[sel_merge]] = OpLabel
  2460. ; CHECK-NEXT: OpBranch [[loop_merge]]
  2461. ; CHECK: [[loop_merge]] = OpLabel
  2462. ; CHECK-NEXT: OpReturn
  2463. %main = OpFunction %void None %func_type
  2464. %entry_bb = OpLabel
  2465. OpBranch %loop_header
  2466. %loop_header = OpLabel
  2467. OpLoopMerge %loop_merge %cont None
  2468. OpBranch %bb1
  2469. %bb1 = OpLabel
  2470. OpSelectionMerge %sel_merge None
  2471. OpBranchConditional %true %bb2 %bb4
  2472. %bb2 = OpLabel
  2473. ;OpSwitch %undef_int %sel_merge 0 %loop_merge 1 %bb3
  2474. OpBranchConditional %undef_bool %sel_merge %bb3
  2475. %bb3 = OpLabel
  2476. OpBranch %sel_merge
  2477. %bb4 = OpLabel
  2478. OpBranch %sel_merge
  2479. %sel_merge = OpLabel
  2480. OpBranch %loop_merge
  2481. %cont = OpLabel
  2482. OpBranch %loop_header
  2483. %loop_merge = OpLabel
  2484. OpReturn
  2485. OpFunctionEnd
  2486. )";
  2487. SinglePassRunAndMatch<DeadBranchElimPass>(predefs + body, true);
  2488. }
  2489. TEST_F(DeadBranchElimTest, SelectionMergeWithExitToLoopContinue3) {
  2490. // Checks that if a selection merge construct contains a conditional branch
  2491. // the selection merge, and another block inside the selection merge, then we
  2492. // must keep the OpSelectionMerge instruction on that branch.
  2493. const std::string predefs = R"(
  2494. OpCapability Shader
  2495. %1 = OpExtInstImport "GLSL.std.450"
  2496. OpMemoryModel Logical GLSL450
  2497. OpEntryPoint Fragment %main "main"
  2498. OpExecutionMode %main OriginUpperLeft
  2499. OpSource GLSL 140
  2500. %void = OpTypeVoid
  2501. %func_type = OpTypeFunction %void
  2502. %bool = OpTypeBool
  2503. %true = OpConstantTrue %bool
  2504. %uint = OpTypeInt 32 0
  2505. %undef_int = OpUndef %uint
  2506. %undef_bool = OpUndef %bool
  2507. )";
  2508. const std::string body =
  2509. R"(
  2510. ; CHECK: OpLabel
  2511. ; CHECK: [[loop_header:%\w+]] = OpLabel
  2512. ; CHECK: OpLoopMerge [[loop_merge:%\w+]] [[loop_continue:%\w+]]
  2513. ; CHECK-NEXT: OpBranch [[bb1:%\w+]]
  2514. ; CHECK: [[bb1]] = OpLabel
  2515. ; CHECK-NEXT: OpBranch [[bb2:%\w+]]
  2516. ; CHECK: [[bb2]] = OpLabel
  2517. ; CHECK-NEXT: OpSelectionMerge [[sel_merge:%\w+]] None
  2518. ; CHECK-NEXT: OpBranchConditional {{%\w+}} [[sel_merge]] [[bb3:%\w+]]
  2519. ; CHECK: [[bb3]] = OpLabel
  2520. ; CHECK-NEXT: OpBranch [[sel_merge]]
  2521. ; CHECK: [[sel_merge]] = OpLabel
  2522. ; CHECK-NEXT: OpBranch [[loop_merge]]
  2523. ; CHECK: [[loop_continue]] = OpLabel
  2524. ; CHECK-NEXT: OpBranch [[loop_header]]
  2525. ; CHECK: [[loop_merge]] = OpLabel
  2526. ; CHECK-NEXT: OpReturn
  2527. %main = OpFunction %void None %func_type
  2528. %entry_bb = OpLabel
  2529. OpBranch %loop_header
  2530. %loop_header = OpLabel
  2531. OpLoopMerge %loop_merge %cont None
  2532. OpBranch %bb1
  2533. %bb1 = OpLabel
  2534. OpSelectionMerge %sel_merge None
  2535. OpBranchConditional %true %bb2 %bb4
  2536. %bb2 = OpLabel
  2537. OpBranchConditional %undef_bool %sel_merge %bb3
  2538. %bb3 = OpLabel
  2539. OpBranch %sel_merge
  2540. %bb4 = OpLabel
  2541. OpBranch %sel_merge
  2542. %sel_merge = OpLabel
  2543. OpBranch %loop_merge
  2544. %cont = OpLabel
  2545. OpBranch %loop_header
  2546. %loop_merge = OpLabel
  2547. OpReturn
  2548. OpFunctionEnd
  2549. )";
  2550. SinglePassRunAndMatch<DeadBranchElimPass>(predefs + body, true);
  2551. }
  2552. TEST_F(DeadBranchElimTest, SelectionMergeSameAsLoopContinue) {
  2553. // Same as |SelectionMergeWithExitToLoopContinue|, except the branch in the
  2554. // selection construct is an |OpSwitch| instead of an |OpConditionalBranch|.
  2555. // The OpSelectionMerge instruction is not needed in this case either.
  2556. const std::string predefs = R"(
  2557. OpCapability Shader
  2558. %1 = OpExtInstImport "GLSL.std.450"
  2559. OpMemoryModel Logical GLSL450
  2560. OpEntryPoint Fragment %main "main"
  2561. OpExecutionMode %main OriginUpperLeft
  2562. OpSource GLSL 140
  2563. %void = OpTypeVoid
  2564. %func_type = OpTypeFunction %void
  2565. %bool = OpTypeBool
  2566. %true = OpConstantTrue %bool
  2567. %uint = OpTypeInt 32 0
  2568. %undef_bool = OpUndef %bool
  2569. )";
  2570. const std::string body =
  2571. R"(
  2572. ; CHECK: OpLabel
  2573. ; CHECK: [[loop_header:%\w+]] = OpLabel
  2574. ; CHECK: OpLoopMerge [[loop_merge:%\w+]] [[loop_cont:%\w+]]
  2575. ; CHECK-NEXT: OpBranch [[bb1:%\w+]]
  2576. ; CHECK: [[bb1]] = OpLabel
  2577. ; CHECK-NEXT: OpBranch [[bb2:%\w+]]
  2578. ; CHECK: [[bb2]] = OpLabel
  2579. ; CHECK-NEXT: OpSelectionMerge [[loop_cont]]
  2580. ; CHECK-NEXT: OpBranchConditional {{%\w+}} [[bb3:%\w+]] [[loop_cont]]
  2581. ; CHECK: [[bb3]] = OpLabel
  2582. ; CHECK-NEXT: OpBranch [[loop_cont]]
  2583. ; CHECK: [[loop_cont]] = OpLabel
  2584. ; CHECK-NEXT: OpBranchConditional {{%\w+}} [[loop_header]] [[loop_merge]]
  2585. ; CHECK: [[loop_merge]] = OpLabel
  2586. ; CHECK-NEXT: OpReturn
  2587. %main = OpFunction %void None %func_type
  2588. %entry_bb = OpLabel
  2589. OpBranch %loop_header
  2590. %loop_header = OpLabel
  2591. OpLoopMerge %loop_merge %cont None
  2592. OpBranch %bb1
  2593. %bb1 = OpLabel
  2594. OpSelectionMerge %cont None
  2595. OpBranchConditional %true %bb2 %bb4
  2596. %bb2 = OpLabel
  2597. OpBranchConditional %undef_bool %bb3 %cont
  2598. %bb3 = OpLabel
  2599. OpBranch %cont
  2600. %bb4 = OpLabel
  2601. OpBranch %cont
  2602. %cont = OpLabel
  2603. OpBranchConditional %undef_bool %loop_header %loop_merge
  2604. %loop_merge = OpLabel
  2605. OpReturn
  2606. OpFunctionEnd
  2607. )";
  2608. // The selection merge in the loop naming the continue target as merge is
  2609. // invalid, but handled by this pass so validation is disabled.
  2610. SinglePassRunAndMatch<DeadBranchElimPass>(predefs + body, false);
  2611. }
  2612. TEST_F(DeadBranchElimTest, SelectionMergeWithNestedLoop) {
  2613. const std::string body =
  2614. R"(
  2615. ; CHECK: OpSelectionMerge [[merge1:%\w+]]
  2616. ; CHECK: [[merge1]] = OpLabel
  2617. ; CHECK-NEXT: OpBranch [[preheader:%\w+]]
  2618. ; CHECK: [[preheader]] = OpLabel
  2619. ; CHECK-NOT: OpLabel
  2620. ; CHECK: OpBranch [[header:%\w+]]
  2621. ; CHECK: [[header]] = OpLabel
  2622. ; CHECK-NOT: OpLabel
  2623. ; CHECK: OpLoopMerge [[merge2:%\w+]]
  2624. ; CHECK: [[merge2]] = OpLabel
  2625. ; CHECK-NEXT: OpUnreachable
  2626. OpCapability Shader
  2627. %1 = OpExtInstImport "GLSL.std.450"
  2628. OpMemoryModel Logical GLSL450
  2629. OpEntryPoint Fragment %main "main"
  2630. OpExecutionMode %main OriginUpperLeft
  2631. OpSource ESSL 310
  2632. OpName %main "main"
  2633. OpName %h "h"
  2634. OpName %i "i"
  2635. %void = OpTypeVoid
  2636. %3 = OpTypeFunction %void
  2637. %bool = OpTypeBool
  2638. %_ptr_Function_bool = OpTypePointer Function %bool
  2639. %true = OpConstantTrue %bool
  2640. %int = OpTypeInt 32 1
  2641. %_ptr_Function_int = OpTypePointer Function %int
  2642. %int_1 = OpConstant %int 1
  2643. %int_0 = OpConstant %int 0
  2644. %27 = OpUndef %bool
  2645. %main = OpFunction %void None %3
  2646. %5 = OpLabel
  2647. %h = OpVariable %_ptr_Function_bool Function
  2648. %i = OpVariable %_ptr_Function_int Function
  2649. OpSelectionMerge %11 None
  2650. OpBranchConditional %27 %10 %11
  2651. %10 = OpLabel
  2652. OpBranch %11
  2653. %11 = OpLabel
  2654. OpSelectionMerge %14 None
  2655. OpBranchConditional %true %13 %14
  2656. %13 = OpLabel
  2657. OpStore %i %int_1
  2658. OpBranch %19
  2659. %19 = OpLabel
  2660. OpLoopMerge %21 %22 None
  2661. OpBranch %23
  2662. %23 = OpLabel
  2663. %26 = OpSGreaterThan %bool %int_1 %int_0
  2664. OpBranchConditional %true %20 %21
  2665. %20 = OpLabel
  2666. OpBranch %22
  2667. %22 = OpLabel
  2668. OpBranch %19
  2669. %21 = OpLabel
  2670. OpBranch %14
  2671. %14 = OpLabel
  2672. OpReturn
  2673. OpFunctionEnd
  2674. )";
  2675. SinglePassRunAndMatch<DeadBranchElimPass>(body, true);
  2676. }
  2677. TEST_F(DeadBranchElimTest, DontFoldBackedge) {
  2678. const std::string body =
  2679. R"(OpCapability Shader
  2680. %1 = OpExtInstImport "GLSL.std.450"
  2681. OpMemoryModel Logical GLSL450
  2682. OpEntryPoint Fragment %2 "main"
  2683. OpExecutionMode %2 OriginUpperLeft
  2684. %void = OpTypeVoid
  2685. %4 = OpTypeFunction %void
  2686. %bool = OpTypeBool
  2687. %false = OpConstantFalse %bool
  2688. %2 = OpFunction %void None %4
  2689. %7 = OpLabel
  2690. OpBranch %8
  2691. %8 = OpLabel
  2692. OpLoopMerge %9 %10 None
  2693. OpBranch %11
  2694. %11 = OpLabel
  2695. %12 = OpUndef %bool
  2696. OpSelectionMerge %10 None
  2697. OpBranchConditional %12 %13 %10
  2698. %13 = OpLabel
  2699. OpBranch %9
  2700. %10 = OpLabel
  2701. OpBranch %14
  2702. %14 = OpLabel
  2703. OpBranchConditional %false %8 %9
  2704. %9 = OpLabel
  2705. OpReturn
  2706. OpFunctionEnd
  2707. )";
  2708. SinglePassRunAndCheck<DeadBranchElimPass>(body, body, true);
  2709. }
  2710. TEST_F(DeadBranchElimTest, FoldBackedgeToHeader) {
  2711. const std::string body =
  2712. R"(
  2713. ; CHECK: OpLabel
  2714. ; CHECK: [[header:%\w+]] = OpLabel
  2715. ; CHECK-NEXT: OpLoopMerge {{%\w+}} [[cont:%\w+]]
  2716. ; CHECK: [[cont]] = OpLabel
  2717. ; This branch may not be in the continue block, but must come after it.
  2718. ; CHECK: OpBranch [[header]]
  2719. OpCapability Shader
  2720. %1 = OpExtInstImport "GLSL.std.450"
  2721. OpMemoryModel Logical GLSL450
  2722. OpEntryPoint Fragment %2 "main"
  2723. OpExecutionMode %2 OriginUpperLeft
  2724. %void = OpTypeVoid
  2725. %4 = OpTypeFunction %void
  2726. %bool = OpTypeBool
  2727. %true = OpConstantTrue %bool
  2728. %2 = OpFunction %void None %4
  2729. %7 = OpLabel
  2730. OpBranch %8
  2731. %8 = OpLabel
  2732. OpLoopMerge %9 %10 None
  2733. OpBranch %11
  2734. %11 = OpLabel
  2735. %12 = OpUndef %bool
  2736. OpSelectionMerge %10 None
  2737. OpBranchConditional %12 %13 %10
  2738. %13 = OpLabel
  2739. OpBranch %9
  2740. %10 = OpLabel
  2741. OpBranch %14
  2742. %14 = OpLabel
  2743. OpBranchConditional %true %8 %9
  2744. %9 = OpLabel
  2745. OpReturn
  2746. OpFunctionEnd
  2747. )";
  2748. // The selection merge in the loop naming the continue target as merge is
  2749. // invalid, but handled by this pass so validation is disabled.
  2750. SinglePassRunAndMatch<DeadBranchElimPass>(body, false);
  2751. }
  2752. TEST_F(DeadBranchElimTest, UnreachableMergeAndContinueSameBlock) {
  2753. const std::string spirv = R"(
  2754. ; CHECK: OpLabel
  2755. ; CHECK: [[outer:%\w+]] = OpLabel
  2756. ; CHECK-NEXT: OpLoopMerge [[outer_merge:%\w+]] [[outer_cont:%\w+]] None
  2757. ; CHECK-NEXT: OpBranch [[inner:%\w+]]
  2758. ; CHECK: [[inner]] = OpLabel
  2759. ; CHECK: OpLoopMerge [[inner_merge:%\w+]] [[inner_cont:%\w+]] None
  2760. ; CHECK: [[inner_cont]] = OpLabel
  2761. ; CHECK-NEXT: OpBranch [[inner]]
  2762. ; CHECK: [[inner_merge]] = OpLabel
  2763. ; CHECK-NEXT: OpUnreachable
  2764. ; CHECK: [[outer_cont]] = OpLabel
  2765. ; CHECK-NEXT: OpBranch [[outer]]
  2766. ; CHECK: [[outer_merge]] = OpLabel
  2767. ; CHECK-NEXT: OpUnreachable
  2768. OpCapability Shader
  2769. OpMemoryModel Logical GLSL450
  2770. OpEntryPoint GLCompute %main "main"
  2771. OpExecutionMode %main LocalSize 1 1 1
  2772. %void = OpTypeVoid
  2773. %bool = OpTypeBool
  2774. %true = OpConstantTrue %bool
  2775. %void_fn = OpTypeFunction %void
  2776. %main = OpFunction %void None %void_fn
  2777. %entry = OpLabel
  2778. OpBranch %outer_loop
  2779. %outer_loop = OpLabel
  2780. OpLoopMerge %outer_merge %outer_continue None
  2781. OpBranch %inner_loop
  2782. %inner_loop = OpLabel
  2783. OpLoopMerge %inner_merge %inner_continue None
  2784. OpBranch %inner_body
  2785. %inner_body = OpLabel
  2786. OpSelectionMerge %inner_continue None
  2787. OpBranchConditional %true %ret %inner_continue
  2788. %ret = OpLabel
  2789. OpReturn
  2790. %inner_continue = OpLabel
  2791. OpBranchConditional %true %inner_merge %inner_loop
  2792. %inner_merge = OpLabel
  2793. OpBranch %outer_continue
  2794. %outer_continue = OpLabel
  2795. OpBranchConditional %true %outer_merge %outer_loop
  2796. %outer_merge = OpLabel
  2797. OpReturn
  2798. OpFunctionEnd
  2799. )";
  2800. SinglePassRunAndMatch<DeadBranchElimPass>(spirv, true);
  2801. }
  2802. // Fold a switch with a nested break. The only case should be the default.
  2803. TEST_F(DeadBranchElimTest, FoldSwitchWithNestedBreak) {
  2804. const std::string spirv = R"(
  2805. ; CHECK: OpSwitch %int_3 [[case_bb:%\w+]]{{[[:space:]]}}
  2806. ; CHECK: [[case_bb]] = OpLabel
  2807. ; CHECK-NEXT: OpUndef
  2808. ; CHECK-NEXT: OpSelectionMerge
  2809. OpCapability Shader
  2810. %1 = OpExtInstImport "GLSL.std.450"
  2811. OpMemoryModel Logical GLSL450
  2812. OpEntryPoint Vertex %2 "main"
  2813. OpSource GLSL 450
  2814. %void = OpTypeVoid
  2815. %4 = OpTypeFunction %void
  2816. %int = OpTypeInt 32 1
  2817. %_ptr_Function_int = OpTypePointer Function %int
  2818. %int_3 = OpConstant %int 3
  2819. %int_1 = OpConstant %int 1
  2820. %bool = OpTypeBool
  2821. %2 = OpFunction %void None %4
  2822. %10 = OpLabel
  2823. OpSelectionMerge %11 None
  2824. OpSwitch %int_3 %12 3 %13
  2825. %12 = OpLabel
  2826. OpBranch %11
  2827. %13 = OpLabel
  2828. %14 = OpUndef %bool
  2829. OpSelectionMerge %15 None
  2830. OpBranchConditional %14 %16 %15
  2831. %16 = OpLabel
  2832. OpBranch %11
  2833. %15 = OpLabel
  2834. OpBranch %11
  2835. %11 = OpLabel
  2836. OpReturn
  2837. OpFunctionEnd
  2838. )";
  2839. SinglePassRunAndMatch<DeadBranchElimPass>(spirv, true);
  2840. }
  2841. TEST_F(DeadBranchElimTest, FoldBranchWithBreakToSwitch) {
  2842. const std::string spirv = R"(
  2843. ; CHECK: OpSelectionMerge [[sel_merge:%\w+]]
  2844. ; CHECK-NEXT: OpSwitch {{%\w+}} {{%\w+}} 3 [[bb:%\w+]]
  2845. ; CHECK: [[bb]] = OpLabel
  2846. ; CHECK-NEXT: OpBranch [[bb2:%\w+]]
  2847. ; CHECK: [[bb2]] = OpLabel
  2848. ; CHECK-NOT: OpSelectionMerge
  2849. ; CHECK: OpFunctionEnd
  2850. OpCapability Shader
  2851. %1 = OpExtInstImport "GLSL.std.450"
  2852. OpMemoryModel Logical GLSL450
  2853. OpEntryPoint Vertex %2 "main"
  2854. OpSource GLSL 450
  2855. %void = OpTypeVoid
  2856. %4 = OpTypeFunction %void
  2857. %int = OpTypeInt 32 1
  2858. %_ptr_Function_int = OpTypePointer Function %int
  2859. %int_3 = OpConstant %int 3
  2860. %int_1 = OpConstant %int 1
  2861. %bool = OpTypeBool
  2862. %true = OpConstantTrue %bool
  2863. %2 = OpFunction %void None %4
  2864. %10 = OpLabel
  2865. %undef_int = OpUndef %int
  2866. OpSelectionMerge %11 None
  2867. OpSwitch %undef_int %12 3 %13
  2868. %12 = OpLabel
  2869. OpBranch %11
  2870. %13 = OpLabel
  2871. OpSelectionMerge %15 None
  2872. OpBranchConditional %true %16 %15
  2873. %16 = OpLabel
  2874. %14 = OpUndef %bool
  2875. OpBranchConditional %14 %11 %17
  2876. %17 = OpLabel
  2877. OpBranch %15
  2878. %15 = OpLabel
  2879. OpBranch %11
  2880. %11 = OpLabel
  2881. OpReturn
  2882. OpFunctionEnd
  2883. )";
  2884. SinglePassRunAndMatch<DeadBranchElimPass>(spirv, true);
  2885. }
  2886. TEST_F(DeadBranchElimTest, IfInSwitch) {
  2887. // #version 310 es
  2888. //
  2889. // void main()
  2890. // {
  2891. // switch(0)
  2892. // {
  2893. // case 0:
  2894. // if(false)
  2895. // {
  2896. // }
  2897. // else
  2898. // {
  2899. // }
  2900. // }
  2901. // }
  2902. const std::string before =
  2903. R"(OpCapability Shader
  2904. %1 = OpExtInstImport "GLSL.std.450"
  2905. OpMemoryModel Logical GLSL450
  2906. OpEntryPoint Fragment %main "main"
  2907. OpExecutionMode %main OriginUpperLeft
  2908. OpSource ESSL 310
  2909. OpName %main "main"
  2910. %void = OpTypeVoid
  2911. %3 = OpTypeFunction %void
  2912. %int = OpTypeInt 32 1
  2913. %int_0 = OpConstant %int 0
  2914. %bool = OpTypeBool
  2915. %false = OpConstantFalse %bool
  2916. %main = OpFunction %void None %3
  2917. %5 = OpLabel
  2918. OpSelectionMerge %9 None
  2919. OpSwitch %int_0 %9 0 %8
  2920. %8 = OpLabel
  2921. OpSelectionMerge %13 None
  2922. OpBranchConditional %false %12 %13
  2923. %12 = OpLabel
  2924. OpBranch %13
  2925. %13 = OpLabel
  2926. OpBranch %9
  2927. %9 = OpLabel
  2928. OpReturn
  2929. OpFunctionEnd
  2930. )";
  2931. const std::string after =
  2932. R"(OpCapability Shader
  2933. %1 = OpExtInstImport "GLSL.std.450"
  2934. OpMemoryModel Logical GLSL450
  2935. OpEntryPoint Fragment %main "main"
  2936. OpExecutionMode %main OriginUpperLeft
  2937. OpSource ESSL 310
  2938. OpName %main "main"
  2939. %void = OpTypeVoid
  2940. %4 = OpTypeFunction %void
  2941. %int = OpTypeInt 32 1
  2942. %int_0 = OpConstant %int 0
  2943. %bool = OpTypeBool
  2944. %false = OpConstantFalse %bool
  2945. %main = OpFunction %void None %4
  2946. %9 = OpLabel
  2947. OpBranch %11
  2948. %11 = OpLabel
  2949. OpBranch %12
  2950. %12 = OpLabel
  2951. OpBranch %10
  2952. %10 = OpLabel
  2953. OpReturn
  2954. OpFunctionEnd
  2955. )";
  2956. SinglePassRunAndCheck<DeadBranchElimPass>(before, after, true, true);
  2957. }
  2958. TEST_F(DeadBranchElimTest, BreakInNestedHeaderWithSingleCase) {
  2959. const std::string text = R"(OpCapability Shader
  2960. %1 = OpExtInstImport "GLSL.std.450"
  2961. OpMemoryModel Logical GLSL450
  2962. OpEntryPoint Fragment %main "main"
  2963. OpExecutionMode %main OriginUpperLeft
  2964. OpSource GLSL 450
  2965. OpName %main "main"
  2966. %void = OpTypeVoid
  2967. %4 = OpTypeFunction %void
  2968. %bool = OpTypeBool
  2969. %uint = OpTypeInt 32 0
  2970. %uint_0 = OpConstant %uint 0
  2971. %8 = OpUndef %bool
  2972. %main = OpFunction %void None %4
  2973. %9 = OpLabel
  2974. OpSelectionMerge %10 None
  2975. OpSwitch %uint_0 %11
  2976. %11 = OpLabel
  2977. OpSelectionMerge %12 None
  2978. OpBranchConditional %8 %10 %12
  2979. %12 = OpLabel
  2980. OpBranch %10
  2981. %10 = OpLabel
  2982. OpReturn
  2983. OpFunctionEnd
  2984. )";
  2985. SinglePassRunAndCheck<DeadBranchElimPass>(text, text, true, true);
  2986. }
  2987. TEST_F(DeadBranchElimTest, BreakInNestedHeaderWithTwoCases) {
  2988. const std::string text = R"(
  2989. ; CHECK: OpSelectionMerge [[merge:%\w+]] None
  2990. ; CHECK-NEXT: OpSwitch %uint_0 [[bb:%\w+\n]]
  2991. OpCapability Shader
  2992. %1 = OpExtInstImport "GLSL.std.450"
  2993. OpMemoryModel Logical GLSL450
  2994. OpEntryPoint Fragment %main "main"
  2995. OpExecutionMode %main OriginUpperLeft
  2996. OpSource GLSL 450
  2997. OpName %main "main"
  2998. %void = OpTypeVoid
  2999. %4 = OpTypeFunction %void
  3000. %bool = OpTypeBool
  3001. %uint = OpTypeInt 32 0
  3002. %uint_0 = OpConstant %uint 0
  3003. %8 = OpUndef %bool
  3004. %main = OpFunction %void None %4
  3005. %9 = OpLabel
  3006. OpSelectionMerge %10 None
  3007. OpSwitch %uint_0 %11 1 %12
  3008. %11 = OpLabel
  3009. OpSelectionMerge %13 None
  3010. OpBranchConditional %8 %10 %13
  3011. %13 = OpLabel
  3012. OpBranch %10
  3013. %12 = OpLabel
  3014. OpBranch %10
  3015. %10 = OpLabel
  3016. OpReturn
  3017. OpFunctionEnd
  3018. )";
  3019. SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
  3020. }
  3021. TEST_F(DeadBranchElimTest, DebugInformation) {
  3022. const std::string text = R"(
  3023. OpCapability Shader
  3024. %1 = OpExtInstImport "GLSL.std.450"
  3025. %ext = OpExtInstImport "OpenCL.DebugInfo.100"
  3026. OpMemoryModel Logical GLSL450
  3027. OpEntryPoint Fragment %main "main" %gl_FragColor
  3028. OpExecutionMode %main OriginUpperLeft
  3029. OpSource GLSL 140
  3030. %name = OpString "test"
  3031. OpName %main "main"
  3032. OpName %gl_FragColor "gl_FragColor"
  3033. %void = OpTypeVoid
  3034. %5 = OpTypeFunction %void
  3035. %bool = OpTypeBool
  3036. %true = OpConstantTrue %bool
  3037. %float = OpTypeFloat 32
  3038. %v4float = OpTypeVector %float 4
  3039. %_ptr_Function_v4float = OpTypePointer Function %v4float
  3040. %float_0 = OpConstant %float 0
  3041. ; CHECK: [[value:%\w+]] = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
  3042. %12 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
  3043. %float_1 = OpConstant %float 1
  3044. %14 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
  3045. %_ptr_Output_v4float = OpTypePointer Output %v4float
  3046. %gl_FragColor = OpVariable %_ptr_Output_v4float Output
  3047. %_ptr_Input_v4float = OpTypePointer Input %v4float
  3048. %uint = OpTypeInt 32 0
  3049. %uint_32 = OpConstant %uint 32
  3050. %null_expr = OpExtInst %void %ext DebugExpression
  3051. %src = OpExtInst %void %ext DebugSource %name
  3052. %cu = OpExtInst %void %ext DebugCompilationUnit 1 4 %src HLSL
  3053. %ty = OpExtInst %void %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %void
  3054. %dbg_main = OpExtInst %void %ext DebugFunction %name %ty %src 0 0 %cu %name FlagIsProtected|FlagIsPrivate 0 %main
  3055. ; CHECK: [[bb1:%\w+]] = OpExtInst %void [[ext:%\w+]] DebugLexicalBlock [[src:%\w+]] 1 0 [[dbg_main:%\w+]]
  3056. ; CHECK: [[bb2:%\w+]] = OpExtInst %void [[ext]] DebugLexicalBlock [[src]] 2 0 [[dbg_main]]
  3057. ; CHECK: [[bb3:%\w+]] = OpExtInst %void [[ext]] DebugLexicalBlock [[src]] 3 0 [[dbg_main]]
  3058. %bb1 = OpExtInst %void %ext DebugLexicalBlock %src 1 0 %dbg_main
  3059. %bb2 = OpExtInst %void %ext DebugLexicalBlock %src 2 0 %dbg_main
  3060. %bb3 = OpExtInst %void %ext DebugLexicalBlock %src 3 0 %dbg_main
  3061. %dbg_f = OpExtInst %void %ext DebugTypeBasic %name %uint_32 Float
  3062. ; CHECK: [[dbg_foo:%\w+]] = OpExtInst %void [[ext]] DebugLocalVariable {{%\w+}} [[ty:%\w+]] [[src]] 0 0 [[dbg_main]]
  3063. %dbg_foo = OpExtInst %void %ext DebugLocalVariable %name %dbg_f %src 0 0 %dbg_main FlagIsLocal
  3064. ; CHECK: [[dbg_bar:%\w+]] = OpExtInst %void [[ext]] DebugLocalVariable {{%\w+}} [[ty]] [[src]] 1 0 [[bb3]]
  3065. %dbg_bar = OpExtInst %void %ext DebugLocalVariable %name %dbg_f %src 1 0 %bb3 FlagIsLocal
  3066. %main = OpFunction %void None %5
  3067. %17 = OpLabel
  3068. ; CHECK-NOT: DebugScope [[dbg_main]]
  3069. ; CHECK-NOT: OpLine {{%\w+}} 0 0
  3070. %scope0 = OpExtInst %void %ext DebugScope %dbg_main
  3071. OpLine %name 0 0
  3072. OpSelectionMerge %18 None
  3073. OpBranchConditional %true %19 %20
  3074. %19 = OpLabel
  3075. ; CHECK: DebugScope [[bb1]]
  3076. ; CHECK: OpLine {{%\w+}} 1 0
  3077. %scope1 = OpExtInst %void %ext DebugScope %bb1
  3078. OpLine %name 1 0
  3079. OpBranch %18
  3080. %20 = OpLabel
  3081. ; CHECK-NOT: DebugScope [[bb2]]
  3082. ; CHECK-NOT: OpLine {{%\w+}} 2 0
  3083. %scope2 = OpExtInst %void %ext DebugScope %bb2
  3084. OpLine %name 2 0
  3085. OpBranch %18
  3086. %18 = OpLabel
  3087. ; CHECK: DebugScope [[bb3]]
  3088. ; CHECK: OpLine {{%\w+}} 3 0
  3089. ; CHECK: DebugValue [[dbg_foo]] [[value]]
  3090. ; CHECK: OpLine {{%\w+}} 4 0
  3091. ; CHECK: OpStore %gl_FragColor [[value]]
  3092. ; CHECK: DebugDeclare [[dbg_bar]] %gl_FragColor
  3093. ; CHECK: DebugValue [[dbg_bar]] [[value]]
  3094. %scope3 = OpExtInst %void %ext DebugScope %bb3
  3095. OpLine %name 3 0
  3096. %21 = OpPhi %v4float %12 %19 %14 %20
  3097. %decl0 = OpExtInst %void %ext DebugValue %dbg_foo %21 %null_expr
  3098. OpLine %name 4 0
  3099. OpStore %gl_FragColor %21
  3100. %decl1 = OpExtInst %void %ext DebugDeclare %dbg_bar %gl_FragColor %null_expr
  3101. %decl2 = OpExtInst %void %ext DebugValue %dbg_bar %21 %null_expr
  3102. OpLine %name 5 0
  3103. OpReturn
  3104. OpFunctionEnd
  3105. )";
  3106. SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
  3107. }
  3108. TEST_F(DeadBranchElimTest, DontTransferDecorations) {
  3109. // When replacing %4 with %14, we don't want %14 to inherit %4's decorations.
  3110. const std::string text = R"(
  3111. ; CHECK-NOT: OpDecorate {{%\w+}} RelaxedPrecision
  3112. ; CHECK: [[div:%\w+]] = OpFDiv
  3113. ; CHECK: {{%\w+}} = OpCopyObject %float [[div]]
  3114. OpCapability Shader
  3115. %1 = OpExtInstImport "GLSL.std.450"
  3116. OpMemoryModel Logical GLSL450
  3117. OpEntryPoint Fragment %2 "main"
  3118. OpExecutionMode %2 OriginUpperLeft
  3119. %3 = OpString "STEVEN"
  3120. OpDecorate %4 RelaxedPrecision
  3121. %float = OpTypeFloat 32
  3122. %uint = OpTypeInt 32 0
  3123. %void = OpTypeVoid
  3124. %float_1 = OpConstant %float 1
  3125. %uint_0 = OpConstant %uint 0
  3126. %10 = OpTypeFunction %void
  3127. %2 = OpFunction %void None %10
  3128. %11 = OpLabel
  3129. OpSelectionMerge %12 None
  3130. OpSwitch %uint_0 %13
  3131. %13 = OpLabel
  3132. %14 = OpFDiv %float %float_1 %float_1
  3133. OpLine %3 0 0
  3134. OpBranch %12
  3135. %15 = OpLabel
  3136. OpBranch %12
  3137. %12 = OpLabel
  3138. %4 = OpPhi %float %float_1 %15 %14 %13
  3139. %16 = OpCopyObject %float %4
  3140. OpReturn
  3141. OpFunctionEnd
  3142. )";
  3143. SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
  3144. }
  3145. TEST_F(DeadBranchElimTest, FunctionDeclaration) {
  3146. // Make sure the pass works with a function declaration that is called.
  3147. const std::string text = R"(OpCapability Addresses
  3148. OpCapability Linkage
  3149. OpCapability Kernel
  3150. OpCapability Int8
  3151. %1 = OpExtInstImport "OpenCL.std"
  3152. OpMemoryModel Physical64 OpenCL
  3153. OpEntryPoint Kernel %2 "_Z23julia__1166_kernel_77094Bool"
  3154. OpExecutionMode %2 ContractionOff
  3155. OpSource Unknown 0
  3156. OpDecorate %3 LinkageAttributes "julia_error_7712" Import
  3157. %void = OpTypeVoid
  3158. %5 = OpTypeFunction %void
  3159. %3 = OpFunction %void None %5
  3160. OpFunctionEnd
  3161. %2 = OpFunction %void None %5
  3162. %6 = OpLabel
  3163. %7 = OpFunctionCall %void %3
  3164. OpReturn
  3165. OpFunctionEnd
  3166. )";
  3167. SinglePassRunAndCheck<DeadBranchElimPass>(text, text, false);
  3168. }
  3169. // TODO(greg-lunarg): Add tests to verify handling of these cases:
  3170. //
  3171. // More complex control flow
  3172. // Others?
  3173. } // namespace
  3174. } // namespace opt
  3175. } // namespace spvtools