fold_test.cpp 342 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469
  1. // Copyright (c) 2016 Google Inc.
  2. // Licensed under the Apache License, Version 2.0 (the "License");
  3. // you may not use this file except in compliance with the License.
  4. // You may obtain a copy of the License at
  5. //
  6. // http://www.apache.org/licenses/LICENSE-2.0
  7. //
  8. // Unless required by applicable law or agreed to in writing, software
  9. // distributed under the License is distributed on an "AS IS" BASIS,
  10. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. // See the License for the specific language governing permissions and
  12. // limitations under the License.
  13. #include "source/opt/fold.h"
  14. #include <limits>
  15. #include <memory>
  16. #include <string>
  17. #include <unordered_set>
  18. #include <vector>
  19. #include "effcee/effcee.h"
  20. #include "gmock/gmock.h"
  21. #include "gtest/gtest.h"
  22. #include "source/opt/build_module.h"
  23. #include "source/opt/def_use_manager.h"
  24. #include "source/opt/ir_context.h"
  25. #include "source/opt/module.h"
  26. #include "spirv-tools/libspirv.hpp"
  27. #include "test/opt/pass_utils.h"
  28. namespace spvtools {
  29. namespace opt {
  30. namespace {
  31. using ::testing::Contains;
  32. std::string Disassemble(const std::string& original, IRContext* context,
  33. uint32_t disassemble_options = 0) {
  34. std::vector<uint32_t> optimized_bin;
  35. context->module()->ToBinary(&optimized_bin, true);
  36. spv_target_env target_env = SPV_ENV_UNIVERSAL_1_2;
  37. SpirvTools tools(target_env);
  38. std::string optimized_asm;
  39. EXPECT_TRUE(
  40. tools.Disassemble(optimized_bin, &optimized_asm, disassemble_options))
  41. << "Disassembling failed for shader:\n"
  42. << original << std::endl;
  43. return optimized_asm;
  44. }
  45. void Match(const std::string& original, IRContext* context,
  46. uint32_t disassemble_options = 0) {
  47. std::string disassembly = Disassemble(original, context, disassemble_options);
  48. auto match_result = effcee::Match(disassembly, original);
  49. EXPECT_EQ(effcee::Result::Status::Ok, match_result.status())
  50. << match_result.message() << "\nChecking result:\n"
  51. << disassembly;
  52. }
  53. template <class ResultType>
  54. struct InstructionFoldingCase {
  55. InstructionFoldingCase(const std::string& tb, uint32_t id, ResultType result)
  56. : test_body(tb), id_to_fold(id), expected_result(result) {}
  57. std::string test_body;
  58. uint32_t id_to_fold;
  59. ResultType expected_result;
  60. };
  61. using IntegerInstructionFoldingTest =
  62. ::testing::TestWithParam<InstructionFoldingCase<uint32_t>>;
  63. TEST_P(IntegerInstructionFoldingTest, Case) {
  64. const auto& tc = GetParam();
  65. // Build module.
  66. std::unique_ptr<IRContext> context =
  67. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
  68. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  69. ASSERT_NE(nullptr, context);
  70. // Fold the instruction to test.
  71. analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
  72. Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
  73. bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
  74. // Make sure the instruction folded as expected.
  75. EXPECT_TRUE(succeeded);
  76. if (inst != nullptr) {
  77. EXPECT_EQ(inst->opcode(), spv::Op::OpCopyObject);
  78. inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
  79. EXPECT_EQ(inst->opcode(), spv::Op::OpConstant);
  80. analysis::ConstantManager* const_mrg = context->get_constant_mgr();
  81. const analysis::Constant* constant = const_mrg->GetConstantFromInst(inst);
  82. // We expect to see either integer types or 16-bit float types here.
  83. EXPECT_TRUE((constant->AsIntConstant() != nullptr) ||
  84. ((constant->AsFloatConstant() != nullptr) &&
  85. (constant->type()->AsFloat()->width() == 16)));
  86. const analysis::ScalarConstant* result =
  87. const_mrg->GetConstantFromInst(inst)->AsScalarConstant();
  88. EXPECT_NE(result, nullptr);
  89. if (result != nullptr) {
  90. EXPECT_EQ(result->GetU32BitValue(), tc.expected_result);
  91. }
  92. }
  93. }
  94. // Returns a common SPIR-V header for all of the test that follow.
  95. #define INT_0_ID 100
  96. #define TRUE_ID 101
  97. #define VEC2_0_ID 102
  98. #define INT_7_ID 103
  99. #define FLOAT_0_ID 104
  100. #define DOUBLE_0_ID 105
  101. #define VEC4_0_ID 106
  102. #define DVEC4_0_ID 106
  103. #define HALF_0_ID 108
  104. const std::string& Header() {
  105. static const std::string header = R"(OpCapability Shader
  106. OpCapability Float16
  107. OpCapability Float64
  108. OpCapability Int8
  109. OpCapability Int16
  110. OpCapability Int64
  111. %1 = OpExtInstImport "GLSL.std.450"
  112. OpMemoryModel Logical GLSL450
  113. OpEntryPoint Fragment %main "main"
  114. OpExecutionMode %main OriginUpperLeft
  115. OpSource GLSL 140
  116. OpName %main "main"
  117. %void = OpTypeVoid
  118. %void_func = OpTypeFunction %void
  119. %bool = OpTypeBool
  120. %float = OpTypeFloat 32
  121. %double = OpTypeFloat 64
  122. %half = OpTypeFloat 16
  123. %101 = OpConstantTrue %bool ; Need a def with an numerical id to define id maps.
  124. %true = OpConstantTrue %bool
  125. %false = OpConstantFalse %bool
  126. %bool_null = OpConstantNull %bool
  127. %short = OpTypeInt 16 1
  128. %ushort = OpTypeInt 16 0
  129. %byte = OpTypeInt 8 1
  130. %ubyte = OpTypeInt 8 0
  131. %int = OpTypeInt 32 1
  132. %long = OpTypeInt 64 1
  133. %uint = OpTypeInt 32 0
  134. %ulong = OpTypeInt 64 0
  135. %v2int = OpTypeVector %int 2
  136. %v4int = OpTypeVector %int 4
  137. %v4float = OpTypeVector %float 4
  138. %v4double = OpTypeVector %double 4
  139. %v2uint = OpTypeVector %uint 2
  140. %v2float = OpTypeVector %float 2
  141. %v2double = OpTypeVector %double 2
  142. %v2half = OpTypeVector %half 2
  143. %v2bool = OpTypeVector %bool 2
  144. %m2x2int = OpTypeMatrix %v2int 2
  145. %mat4v4float = OpTypeMatrix %v4float 4
  146. %mat4v4double = OpTypeMatrix %v4double 4
  147. %struct_v2int_int_int = OpTypeStruct %v2int %int %int
  148. %_ptr_int = OpTypePointer Function %int
  149. %_ptr_uint = OpTypePointer Function %uint
  150. %_ptr_bool = OpTypePointer Function %bool
  151. %_ptr_float = OpTypePointer Function %float
  152. %_ptr_double = OpTypePointer Function %double
  153. %_ptr_half = OpTypePointer Function %half
  154. %_ptr_long = OpTypePointer Function %long
  155. %_ptr_ulong = OpTypePointer Function %ulong
  156. %_ptr_v2int = OpTypePointer Function %v2int
  157. %_ptr_v4int = OpTypePointer Function %v4int
  158. %_ptr_v4float = OpTypePointer Function %v4float
  159. %_ptr_v4double = OpTypePointer Function %v4double
  160. %_ptr_struct_v2int_int_int = OpTypePointer Function %struct_v2int_int_int
  161. %_ptr_v2float = OpTypePointer Function %v2float
  162. %_ptr_v2double = OpTypePointer Function %v2double
  163. %short_0 = OpConstant %short 0
  164. %short_2 = OpConstant %short 2
  165. %short_3 = OpConstant %short 3
  166. %ubyte_1 = OpConstant %ubyte 1
  167. %byte_n1 = OpConstant %byte -1
  168. %100 = OpConstant %int 0 ; Need a def with an numerical id to define id maps.
  169. %103 = OpConstant %int 7 ; Need a def with an numerical id to define id maps.
  170. %int_0 = OpConstant %int 0
  171. %int_1 = OpConstant %int 1
  172. %int_2 = OpConstant %int 2
  173. %int_3 = OpConstant %int 3
  174. %int_4 = OpConstant %int 4
  175. %int_10 = OpConstant %int 10
  176. %int_1073741824 = OpConstant %int 1073741824
  177. %int_n1 = OpConstant %int -1
  178. %int_n24 = OpConstant %int -24
  179. %int_n858993459 = OpConstant %int -858993459
  180. %int_min = OpConstant %int -2147483648
  181. %int_max = OpConstant %int 2147483647
  182. %long_0 = OpConstant %long 0
  183. %long_1 = OpConstant %long 1
  184. %long_2 = OpConstant %long 2
  185. %long_3 = OpConstant %long 3
  186. %long_10 = OpConstant %long 10
  187. %long_4611686018427387904 = OpConstant %long 4611686018427387904
  188. %long_n1 = OpConstant %long -1
  189. %long_n3689348814741910323 = OpConstant %long -3689348814741910323
  190. %long_min = OpConstant %long -9223372036854775808
  191. %long_max = OpConstant %long 9223372036854775807
  192. %uint_0 = OpConstant %uint 0
  193. %uint_1 = OpConstant %uint 1
  194. %uint_2 = OpConstant %uint 2
  195. %uint_3 = OpConstant %uint 3
  196. %uint_4 = OpConstant %uint 4
  197. %uint_32 = OpConstant %uint 32
  198. %uint_42 = OpConstant %uint 42
  199. %uint_2147483649 = OpConstant %uint 2147483649
  200. %uint_max = OpConstant %uint 4294967295
  201. %ulong_0 = OpConstant %ulong 0
  202. %ulong_1 = OpConstant %ulong 1
  203. %ulong_2 = OpConstant %ulong 2
  204. %ulong_9223372036854775809 = OpConstant %ulong 9223372036854775809
  205. %ulong_max = OpConstant %ulong 18446744073709551615
  206. %v2int_undef = OpUndef %v2int
  207. %v2int_0_0 = OpConstantComposite %v2int %int_0 %int_0
  208. %v2int_1_0 = OpConstantComposite %v2int %int_1 %int_0
  209. %v2int_2_2 = OpConstantComposite %v2int %int_2 %int_2
  210. %v2int_2_3 = OpConstantComposite %v2int %int_2 %int_3
  211. %v2int_3_2 = OpConstantComposite %v2int %int_3 %int_2
  212. %v2int_4_4 = OpConstantComposite %v2int %int_4 %int_4
  213. %v2int_min_max = OpConstantComposite %v2int %int_min %int_max
  214. %v2bool_null = OpConstantNull %v2bool
  215. %v2bool_true_false = OpConstantComposite %v2bool %true %false
  216. %v2bool_false_true = OpConstantComposite %v2bool %false %true
  217. %struct_v2int_int_int_null = OpConstantNull %struct_v2int_int_int
  218. %v2int_null = OpConstantNull %v2int
  219. %102 = OpConstantComposite %v2int %103 %103
  220. %v4int_undef = OpUndef %v4int
  221. %v4int_0_0_0_0 = OpConstantComposite %v4int %int_0 %int_0 %int_0 %int_0
  222. %m2x2int_undef = OpUndef %m2x2int
  223. %struct_undef_0_0 = OpConstantComposite %struct_v2int_int_int %v2int_undef %int_0 %int_0
  224. %float_n1 = OpConstant %float -1
  225. %104 = OpConstant %float 0 ; Need a def with an numerical id to define id maps.
  226. %float_null = OpConstantNull %float
  227. %float_0 = OpConstant %float 0
  228. %float_n0 = OpConstant %float -0.0
  229. %float_1 = OpConstant %float 1
  230. %float_2 = OpConstant %float 2
  231. %float_3 = OpConstant %float 3
  232. %float_4 = OpConstant %float 4
  233. %float_2049 = OpConstant %float 2049
  234. %float_n2049 = OpConstant %float -2049
  235. %float_0p5 = OpConstant %float 0.5
  236. %float_0p2 = OpConstant %float 0.2
  237. %float_pi = OpConstant %float 1.5555
  238. %float_1e16 = OpConstant %float 1e16
  239. %float_n1e16 = OpConstant %float -1e16
  240. %float_1en16 = OpConstant %float 1e-16
  241. %float_n1en16 = OpConstant %float -1e-16
  242. %v2float_0_0 = OpConstantComposite %v2float %float_0 %float_0
  243. %v2float_2_2 = OpConstantComposite %v2float %float_2 %float_2
  244. %v2float_2_3 = OpConstantComposite %v2float %float_2 %float_3
  245. %v2float_3_2 = OpConstantComposite %v2float %float_3 %float_2
  246. %v2float_4_4 = OpConstantComposite %v2float %float_4 %float_4
  247. %v2float_2_0p5 = OpConstantComposite %v2float %float_2 %float_0p5
  248. %v2float_0p2_0p5 = OpConstantComposite %v2float %float_0p2 %float_0p5
  249. %v2float_null = OpConstantNull %v2float
  250. %double_n1 = OpConstant %double -1
  251. %105 = OpConstant %double 0 ; Need a def with an numerical id to define id maps.
  252. %double_null = OpConstantNull %double
  253. %double_0 = OpConstant %double 0
  254. %double_n0 = OpConstant %double -0.0
  255. %double_1 = OpConstant %double 1
  256. %double_2 = OpConstant %double 2
  257. %double_3 = OpConstant %double 3
  258. %double_4 = OpConstant %double 4
  259. %double_5 = OpConstant %double 5
  260. %double_0p5 = OpConstant %double 0.5
  261. %double_0p2 = OpConstant %double 0.2
  262. %v2double_0_0 = OpConstantComposite %v2double %double_0 %double_0
  263. %v2double_2_2 = OpConstantComposite %v2double %double_2 %double_2
  264. %v2double_2_3 = OpConstantComposite %v2double %double_2 %double_3
  265. %v2double_3_2 = OpConstantComposite %v2double %double_3 %double_2
  266. %v2double_4_4 = OpConstantComposite %v2double %double_4 %double_4
  267. %v2double_2_0p5 = OpConstantComposite %v2double %double_2 %double_0p5
  268. %v2double_null = OpConstantNull %v2double
  269. %108 = OpConstant %half 0
  270. %half_1 = OpConstant %half 1
  271. %half_0_1 = OpConstantComposite %v2half %108 %half_1
  272. %106 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
  273. %v4float_0_0_0_0 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
  274. %v4float_0_0_0_1 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_1
  275. %v4float_0_1_0_0 = OpConstantComposite %v4float %float_0 %float_1 %float_null %float_0
  276. %v4float_1_1_1_1 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
  277. %v4float_1_2_3_4 = OpConstantComposite %v4float %float_1 %float_2 %float_3 %float_4
  278. %v4float_null = OpConstantNull %v4float
  279. %mat4v4float_null = OpConstantComposite %mat4v4float %v4float_null %v4float_null %v4float_null %v4float_null
  280. %mat4v4float_1_2_3_4 = OpConstantComposite %mat4v4float %v4float_1_2_3_4 %v4float_1_2_3_4 %v4float_1_2_3_4 %v4float_1_2_3_4
  281. %107 = OpConstantComposite %v4double %double_0 %double_0 %double_0 %double_0
  282. %v4double_0_0_0_0 = OpConstantComposite %v4double %double_0 %double_0 %double_0 %double_0
  283. %v4double_0_0_0_1 = OpConstantComposite %v4double %double_0 %double_0 %double_0 %double_1
  284. %v4double_0_1_0_0 = OpConstantComposite %v4double %double_0 %double_1 %double_null %double_0
  285. %v4double_1_1_1_1 = OpConstantComposite %v4double %double_1 %double_1 %double_1 %double_1
  286. %v4double_1_2_3_4 = OpConstantComposite %v4double %double_1 %double_2 %double_3 %double_4
  287. %v4double_1_1_1_0p5 = OpConstantComposite %v4double %double_1 %double_1 %double_1 %double_0p5
  288. %v4double_null = OpConstantNull %v4double
  289. %mat4v4double_null = OpConstantComposite %mat4v4double %v4double_null %v4double_null %v4double_null %v4double_null
  290. %mat4v4double_1_2_3_4 = OpConstantComposite %mat4v4double %v4double_1_2_3_4 %v4double_1_2_3_4 %v4double_1_2_3_4 %v4double_1_2_3_4
  291. %v4float_n1_2_1_3 = OpConstantComposite %v4float %float_n1 %float_2 %float_1 %float_3
  292. %uint_0x3f800000 = OpConstant %uint 0x3f800000
  293. %uint_0xbf800000 = OpConstant %uint 0xbf800000
  294. %v2uint_0x3f800000_0xbf800000 = OpConstantComposite %v2uint %uint_0x3f800000 %uint_0xbf800000
  295. %long_0xbf8000003f800000 = OpConstant %long 0xbf8000003f800000
  296. %int_0x3FF00000 = OpConstant %int 0x3FF00000
  297. %int_0x00000000 = OpConstant %int 0x00000000
  298. %int_0xC05FD666 = OpConstant %int 0xC05FD666
  299. %int_0x66666666 = OpConstant %int 0x66666666
  300. %v4int_0x3FF00000_0x00000000_0xC05FD666_0x66666666 = OpConstantComposite %v4int %int_0x00000000 %int_0x3FF00000 %int_0x66666666 %int_0xC05FD666
  301. %ushort_0xBC00 = OpConstant %ushort 0xBC00
  302. %short_0xBC00 = OpConstant %short 0xBC00
  303. )";
  304. return header;
  305. }
  306. // Returns the header with definitions of float NaN and double NaN. Since FC
  307. // "; CHECK: [[double_n0:%\\w+]] = OpConstant [[double]] -0\n" finds
  308. // %double_nan = OpConstant %double -0x1.8p+1024 instead of
  309. // %double_n0 = OpConstant %double -0,
  310. // we separates those definitions from Header().
  311. const std::string& HeaderWithNaN() {
  312. static const std::string headerWithNaN =
  313. Header() +
  314. R"(%float_nan = OpConstant %float -0x1.8p+128
  315. %double_nan = OpConstant %double -0x1.8p+1024
  316. )";
  317. return headerWithNaN;
  318. }
  319. // clang-format off
  320. INSTANTIATE_TEST_SUITE_P(TestCase, IntegerInstructionFoldingTest,
  321. ::testing::Values(
  322. // Test case 0: fold 0*n
  323. InstructionFoldingCase<uint32_t>(
  324. Header() + "%main = OpFunction %void None %void_func\n" +
  325. "%main_lab = OpLabel\n" +
  326. "%n = OpVariable %_ptr_int Function\n" +
  327. "%load = OpLoad %int %n\n" +
  328. "%2 = OpIMul %int %int_0 %load\n" +
  329. "OpReturn\n" +
  330. "OpFunctionEnd",
  331. 2, 0),
  332. // Test case 1: fold n*0
  333. InstructionFoldingCase<uint32_t>(
  334. Header() + "%main = OpFunction %void None %void_func\n" +
  335. "%main_lab = OpLabel\n" +
  336. "%n = OpVariable %_ptr_int Function\n" +
  337. "%load = OpLoad %int %n\n" +
  338. "%2 = OpIMul %int %load %int_0\n" +
  339. "OpReturn\n" +
  340. "OpFunctionEnd",
  341. 2, 0),
  342. // Test case 2: fold 0/n (signed)
  343. InstructionFoldingCase<uint32_t>(
  344. Header() + "%main = OpFunction %void None %void_func\n" +
  345. "%main_lab = OpLabel\n" +
  346. "%n = OpVariable %_ptr_int Function\n" +
  347. "%load = OpLoad %int %n\n" +
  348. "%2 = OpSDiv %int %int_0 %load\n" +
  349. "OpReturn\n" +
  350. "OpFunctionEnd",
  351. 2, 0),
  352. // Test case 3: fold n/0 (signed)
  353. InstructionFoldingCase<uint32_t>(
  354. Header() + "%main = OpFunction %void None %void_func\n" +
  355. "%main_lab = OpLabel\n" +
  356. "%n = OpVariable %_ptr_int Function\n" +
  357. "%load = OpLoad %int %n\n" +
  358. "%2 = OpSDiv %int %load %int_0\n" +
  359. "OpReturn\n" +
  360. "OpFunctionEnd",
  361. 2, 0),
  362. // Test case 4: fold 0/n (unsigned)
  363. InstructionFoldingCase<uint32_t>(
  364. Header() + "%main = OpFunction %void None %void_func\n" +
  365. "%main_lab = OpLabel\n" +
  366. "%n = OpVariable %_ptr_uint Function\n" +
  367. "%load = OpLoad %uint %n\n" +
  368. "%2 = OpUDiv %uint %uint_0 %load\n" +
  369. "OpReturn\n" +
  370. "OpFunctionEnd",
  371. 2, 0),
  372. // Test case 5: fold n/0 (unsigned)
  373. InstructionFoldingCase<uint32_t>(
  374. Header() + "%main = OpFunction %void None %void_func\n" +
  375. "%main_lab = OpLabel\n" +
  376. "%n = OpVariable %_ptr_int Function\n" +
  377. "%load = OpLoad %int %n\n" +
  378. "%2 = OpSDiv %int %load %int_0\n" +
  379. "OpReturn\n" +
  380. "OpFunctionEnd",
  381. 2, 0),
  382. // Test case 6: fold 0 remainder n
  383. InstructionFoldingCase<uint32_t>(
  384. Header() + "%main = OpFunction %void None %void_func\n" +
  385. "%main_lab = OpLabel\n" +
  386. "%n = OpVariable %_ptr_int Function\n" +
  387. "%load = OpLoad %int %n\n" +
  388. "%2 = OpSRem %int %int_0 %load\n" +
  389. "OpReturn\n" +
  390. "OpFunctionEnd",
  391. 2, 0),
  392. // Test case 7: fold n remainder 0
  393. InstructionFoldingCase<uint32_t>(
  394. Header() + "%main = OpFunction %void None %void_func\n" +
  395. "%main_lab = OpLabel\n" +
  396. "%n = OpVariable %_ptr_int Function\n" +
  397. "%load = OpLoad %int %n\n" +
  398. "%2 = OpSRem %int %load %int_0\n" +
  399. "OpReturn\n" +
  400. "OpFunctionEnd",
  401. 2, 0),
  402. // Test case 8: fold 0%n (signed)
  403. InstructionFoldingCase<uint32_t>(
  404. Header() + "%main = OpFunction %void None %void_func\n" +
  405. "%main_lab = OpLabel\n" +
  406. "%n = OpVariable %_ptr_int Function\n" +
  407. "%load = OpLoad %int %n\n" +
  408. "%2 = OpSMod %int %int_0 %load\n" +
  409. "OpReturn\n" +
  410. "OpFunctionEnd",
  411. 2, 0),
  412. // Test case 9: fold n%0 (signed)
  413. InstructionFoldingCase<uint32_t>(
  414. Header() + "%main = OpFunction %void None %void_func\n" +
  415. "%main_lab = OpLabel\n" +
  416. "%n = OpVariable %_ptr_int Function\n" +
  417. "%load = OpLoad %int %n\n" +
  418. "%2 = OpSMod %int %load %int_0\n" +
  419. "OpReturn\n" +
  420. "OpFunctionEnd",
  421. 2, 0),
  422. // Test case 10: fold 0%n (unsigned)
  423. InstructionFoldingCase<uint32_t>(
  424. Header() + "%main = OpFunction %void None %void_func\n" +
  425. "%main_lab = OpLabel\n" +
  426. "%n = OpVariable %_ptr_uint Function\n" +
  427. "%load = OpLoad %uint %n\n" +
  428. "%2 = OpUMod %uint %uint_0 %load\n" +
  429. "OpReturn\n" +
  430. "OpFunctionEnd",
  431. 2, 0),
  432. // Test case 11: fold n%0 (unsigned)
  433. InstructionFoldingCase<uint32_t>(
  434. Header() + "%main = OpFunction %void None %void_func\n" +
  435. "%main_lab = OpLabel\n" +
  436. "%n = OpVariable %_ptr_uint Function\n" +
  437. "%load = OpLoad %uint %n\n" +
  438. "%2 = OpUMod %uint %load %uint_0\n" +
  439. "OpReturn\n" +
  440. "OpFunctionEnd",
  441. 2, 0),
  442. // Test case 12: fold n << 32
  443. InstructionFoldingCase<uint32_t>(
  444. Header() + "%main = OpFunction %void None %void_func\n" +
  445. "%main_lab = OpLabel\n" +
  446. "%n = OpVariable %_ptr_uint Function\n" +
  447. "%load = OpLoad %uint %n\n" +
  448. "%2 = OpShiftLeftLogical %uint %load %uint_32\n" +
  449. "OpReturn\n" +
  450. "OpFunctionEnd",
  451. 2, 0),
  452. // Test case 13: fold n >> 32
  453. InstructionFoldingCase<uint32_t>(
  454. Header() + "%main = OpFunction %void None %void_func\n" +
  455. "%main_lab = OpLabel\n" +
  456. "%n = OpVariable %_ptr_uint Function\n" +
  457. "%load = OpLoad %uint %n\n" +
  458. "%2 = OpShiftRightLogical %uint %load %uint_32\n" +
  459. "OpReturn\n" +
  460. "OpFunctionEnd",
  461. 2, 0),
  462. // Test case 14: fold n | 0xFFFFFFFF
  463. InstructionFoldingCase<uint32_t>(
  464. Header() + "%main = OpFunction %void None %void_func\n" +
  465. "%main_lab = OpLabel\n" +
  466. "%n = OpVariable %_ptr_uint Function\n" +
  467. "%load = OpLoad %uint %n\n" +
  468. "%2 = OpBitwiseOr %uint %load %uint_max\n" +
  469. "OpReturn\n" +
  470. "OpFunctionEnd",
  471. 2, 0xFFFFFFFF),
  472. // Test case 15: fold 0xFFFFFFFF | n
  473. InstructionFoldingCase<uint32_t>(
  474. Header() + "%main = OpFunction %void None %void_func\n" +
  475. "%main_lab = OpLabel\n" +
  476. "%n = OpVariable %_ptr_uint Function\n" +
  477. "%load = OpLoad %uint %n\n" +
  478. "%2 = OpBitwiseOr %uint %uint_max %load\n" +
  479. "OpReturn\n" +
  480. "OpFunctionEnd",
  481. 2, 0xFFFFFFFF),
  482. // Test case 16: fold n & 0
  483. InstructionFoldingCase<uint32_t>(
  484. Header() + "%main = OpFunction %void None %void_func\n" +
  485. "%main_lab = OpLabel\n" +
  486. "%n = OpVariable %_ptr_uint Function\n" +
  487. "%load = OpLoad %uint %n\n" +
  488. "%2 = OpBitwiseAnd %uint %load %uint_0\n" +
  489. "OpReturn\n" +
  490. "OpFunctionEnd",
  491. 2, 0),
  492. // Test case 17: fold 1/0 (signed)
  493. InstructionFoldingCase<uint32_t>(
  494. Header() + "%main = OpFunction %void None %void_func\n" +
  495. "%main_lab = OpLabel\n" +
  496. "%2 = OpSDiv %int %int_1 %int_0\n" +
  497. "OpReturn\n" +
  498. "OpFunctionEnd",
  499. 2, 0),
  500. // Test case 18: fold 1/0 (unsigned)
  501. InstructionFoldingCase<uint32_t>(
  502. Header() + "%main = OpFunction %void None %void_func\n" +
  503. "%main_lab = OpLabel\n" +
  504. "%2 = OpUDiv %uint %uint_1 %uint_0\n" +
  505. "OpReturn\n" +
  506. "OpFunctionEnd",
  507. 2, 0),
  508. // Test case 19: fold OpSRem 1 0 (signed)
  509. InstructionFoldingCase<uint32_t>(
  510. Header() + "%main = OpFunction %void None %void_func\n" +
  511. "%main_lab = OpLabel\n" +
  512. "%2 = OpSRem %int %int_1 %int_0\n" +
  513. "OpReturn\n" +
  514. "OpFunctionEnd",
  515. 2, 0),
  516. // Test case 20: fold 1%0 (signed)
  517. InstructionFoldingCase<uint32_t>(
  518. Header() + "%main = OpFunction %void None %void_func\n" +
  519. "%main_lab = OpLabel\n" +
  520. "%2 = OpSMod %int %int_1 %int_0\n" +
  521. "OpReturn\n" +
  522. "OpFunctionEnd",
  523. 2, 0),
  524. // Test case 21: fold 1%0 (unsigned)
  525. InstructionFoldingCase<uint32_t>(
  526. Header() + "%main = OpFunction %void None %void_func\n" +
  527. "%main_lab = OpLabel\n" +
  528. "%2 = OpUMod %uint %uint_1 %uint_0\n" +
  529. "OpReturn\n" +
  530. "OpFunctionEnd",
  531. 2, 0),
  532. // Test case 22: fold unsigned n >> 42 (undefined, so set to zero).
  533. InstructionFoldingCase<uint32_t>(
  534. Header() + "%main = OpFunction %void None %void_func\n" +
  535. "%main_lab = OpLabel\n" +
  536. "%n = OpVariable %_ptr_uint Function\n" +
  537. "%load = OpLoad %uint %n\n" +
  538. "%2 = OpShiftRightLogical %uint %load %uint_42\n" +
  539. "OpReturn\n" +
  540. "OpFunctionEnd",
  541. 2, 0),
  542. // Test case 23: fold signed n >> 42 (undefined, so set to zero).
  543. InstructionFoldingCase<uint32_t>(
  544. Header() + "%main = OpFunction %void None %void_func\n" +
  545. "%main_lab = OpLabel\n" +
  546. "%n = OpVariable %_ptr_int Function\n" +
  547. "%load = OpLoad %int %n\n" +
  548. "%2 = OpShiftRightLogical %int %load %uint_42\n" +
  549. "OpReturn\n" +
  550. "OpFunctionEnd",
  551. 2, 0),
  552. // Test case 24: fold n << 42 (undefined, so set to zero).
  553. InstructionFoldingCase<uint32_t>(
  554. Header() + "%main = OpFunction %void None %void_func\n" +
  555. "%main_lab = OpLabel\n" +
  556. "%n = OpVariable %_ptr_int Function\n" +
  557. "%load = OpLoad %int %n\n" +
  558. "%2 = OpShiftLeftLogical %int %load %uint_42\n" +
  559. "OpReturn\n" +
  560. "OpFunctionEnd",
  561. 2, 0),
  562. // Test case 25: fold -24 >> 32 (defined as -1)
  563. InstructionFoldingCase<uint32_t>(
  564. Header() + "%main = OpFunction %void None %void_func\n" +
  565. "%main_lab = OpLabel\n" +
  566. "%2 = OpShiftRightArithmetic %int %int_n24 %uint_32\n" +
  567. "OpReturn\n" +
  568. "OpFunctionEnd",
  569. 2, -1),
  570. // Test case 26: fold 2 >> 32 (signed)
  571. InstructionFoldingCase<uint32_t>(
  572. Header() + "%main = OpFunction %void None %void_func\n" +
  573. "%main_lab = OpLabel\n" +
  574. "%2 = OpShiftRightArithmetic %int %int_2 %uint_32\n" +
  575. "OpReturn\n" +
  576. "OpFunctionEnd",
  577. 2, 0),
  578. // Test case 27: fold 2 >> 32 (unsigned)
  579. InstructionFoldingCase<uint32_t>(
  580. Header() + "%main = OpFunction %void None %void_func\n" +
  581. "%main_lab = OpLabel\n" +
  582. "%2 = OpShiftRightLogical %int %int_2 %uint_32\n" +
  583. "OpReturn\n" +
  584. "OpFunctionEnd",
  585. 2, 0),
  586. // Test case 28: fold 2 << 32
  587. InstructionFoldingCase<uint32_t>(
  588. Header() + "%main = OpFunction %void None %void_func\n" +
  589. "%main_lab = OpLabel\n" +
  590. "%2 = OpShiftLeftLogical %int %int_2 %uint_32\n" +
  591. "OpReturn\n" +
  592. "OpFunctionEnd",
  593. 2, 0),
  594. // Test case 29: fold -INT_MIN
  595. InstructionFoldingCase<uint32_t>(
  596. Header() + "%main = OpFunction %void None %void_func\n" +
  597. "%main_lab = OpLabel\n" +
  598. "%2 = OpSNegate %int %int_min\n" +
  599. "OpReturn\n" +
  600. "OpFunctionEnd",
  601. 2, std::numeric_limits<int32_t>::min()),
  602. // Test case 30: fold UMin 3 4
  603. InstructionFoldingCase<uint32_t>(
  604. Header() + "%main = OpFunction %void None %void_func\n" +
  605. "%main_lab = OpLabel\n" +
  606. "%2 = OpExtInst %uint %1 UMin %uint_3 %uint_4\n" +
  607. "OpReturn\n" +
  608. "OpFunctionEnd",
  609. 2, 3),
  610. // Test case 31: fold UMin 4 2
  611. InstructionFoldingCase<uint32_t>(
  612. Header() + "%main = OpFunction %void None %void_func\n" +
  613. "%main_lab = OpLabel\n" +
  614. "%2 = OpExtInst %uint %1 UMin %uint_4 %uint_2\n" +
  615. "OpReturn\n" +
  616. "OpFunctionEnd",
  617. 2, 2),
  618. // Test case 32: fold SMin 3 4
  619. InstructionFoldingCase<uint32_t>(
  620. Header() + "%main = OpFunction %void None %void_func\n" +
  621. "%main_lab = OpLabel\n" +
  622. "%2 = OpExtInst %int %1 UMin %int_3 %int_4\n" +
  623. "OpReturn\n" +
  624. "OpFunctionEnd",
  625. 2, 3),
  626. // Test case 33: fold SMin 4 2
  627. InstructionFoldingCase<uint32_t>(
  628. Header() + "%main = OpFunction %void None %void_func\n" +
  629. "%main_lab = OpLabel\n" +
  630. "%2 = OpExtInst %int %1 SMin %int_4 %int_2\n" +
  631. "OpReturn\n" +
  632. "OpFunctionEnd",
  633. 2, 2),
  634. // Test case 34: fold UMax 3 4
  635. InstructionFoldingCase<uint32_t>(
  636. Header() + "%main = OpFunction %void None %void_func\n" +
  637. "%main_lab = OpLabel\n" +
  638. "%2 = OpExtInst %uint %1 UMax %uint_3 %uint_4\n" +
  639. "OpReturn\n" +
  640. "OpFunctionEnd",
  641. 2, 4),
  642. // Test case 35: fold UMax 3 2
  643. InstructionFoldingCase<uint32_t>(
  644. Header() + "%main = OpFunction %void None %void_func\n" +
  645. "%main_lab = OpLabel\n" +
  646. "%2 = OpExtInst %uint %1 UMax %uint_3 %uint_2\n" +
  647. "OpReturn\n" +
  648. "OpFunctionEnd",
  649. 2, 3),
  650. // Test case 36: fold SMax 3 4
  651. InstructionFoldingCase<uint32_t>(
  652. Header() + "%main = OpFunction %void None %void_func\n" +
  653. "%main_lab = OpLabel\n" +
  654. "%2 = OpExtInst %int %1 UMax %int_3 %int_4\n" +
  655. "OpReturn\n" +
  656. "OpFunctionEnd",
  657. 2, 4),
  658. // Test case 37: fold SMax 3 2
  659. InstructionFoldingCase<uint32_t>(
  660. Header() + "%main = OpFunction %void None %void_func\n" +
  661. "%main_lab = OpLabel\n" +
  662. "%2 = OpExtInst %int %1 SMax %int_3 %int_2\n" +
  663. "OpReturn\n" +
  664. "OpFunctionEnd",
  665. 2, 3),
  666. // Test case 38: fold UClamp 2 3 4
  667. InstructionFoldingCase<uint32_t>(
  668. Header() + "%main = OpFunction %void None %void_func\n" +
  669. "%main_lab = OpLabel\n" +
  670. "%2 = OpExtInst %uint %1 UClamp %uint_2 %uint_3 %uint_4\n" +
  671. "OpReturn\n" +
  672. "OpFunctionEnd",
  673. 2, 3),
  674. // Test case 39: fold UClamp 2 0 4
  675. InstructionFoldingCase<uint32_t>(
  676. Header() + "%main = OpFunction %void None %void_func\n" +
  677. "%main_lab = OpLabel\n" +
  678. "%2 = OpExtInst %uint %1 UClamp %uint_2 %uint_0 %uint_4\n" +
  679. "OpReturn\n" +
  680. "OpFunctionEnd",
  681. 2, 2),
  682. // Test case 40: fold UClamp 2 0 1
  683. InstructionFoldingCase<uint32_t>(
  684. Header() + "%main = OpFunction %void None %void_func\n" +
  685. "%main_lab = OpLabel\n" +
  686. "%2 = OpExtInst %uint %1 UClamp %uint_2 %uint_0 %uint_1\n" +
  687. "OpReturn\n" +
  688. "OpFunctionEnd",
  689. 2, 1),
  690. // Test case 41: fold SClamp 2 3 4
  691. InstructionFoldingCase<uint32_t>(
  692. Header() + "%main = OpFunction %void None %void_func\n" +
  693. "%main_lab = OpLabel\n" +
  694. "%2 = OpExtInst %int %1 SClamp %int_2 %int_3 %int_4\n" +
  695. "OpReturn\n" +
  696. "OpFunctionEnd",
  697. 2, 3),
  698. // Test case 42: fold SClamp 2 0 4
  699. InstructionFoldingCase<uint32_t>(
  700. Header() + "%main = OpFunction %void None %void_func\n" +
  701. "%main_lab = OpLabel\n" +
  702. "%2 = OpExtInst %int %1 SClamp %int_2 %int_0 %int_4\n" +
  703. "OpReturn\n" +
  704. "OpFunctionEnd",
  705. 2, 2),
  706. // Test case 43: fold SClamp 2 0 1
  707. InstructionFoldingCase<uint32_t>(
  708. Header() + "%main = OpFunction %void None %void_func\n" +
  709. "%main_lab = OpLabel\n" +
  710. "%2 = OpExtInst %int %1 SClamp %int_2 %int_0 %int_1\n" +
  711. "OpReturn\n" +
  712. "OpFunctionEnd",
  713. 2, 1),
  714. // Test case 44: SClamp 1 2 x
  715. InstructionFoldingCase<uint32_t>(
  716. Header() + "%main = OpFunction %void None %void_func\n" +
  717. "%main_lab = OpLabel\n" +
  718. "%undef = OpUndef %int\n" +
  719. "%2 = OpExtInst %int %1 SClamp %int_1 %int_2 %undef\n" +
  720. "OpReturn\n" +
  721. "OpFunctionEnd",
  722. 2, 2),
  723. // Test case 45: SClamp 2 x 1
  724. InstructionFoldingCase<uint32_t>(
  725. Header() + "%main = OpFunction %void None %void_func\n" +
  726. "%main_lab = OpLabel\n" +
  727. "%undef = OpUndef %int\n" +
  728. "%2 = OpExtInst %int %1 SClamp %int_2 %undef %int_1\n" +
  729. "OpReturn\n" +
  730. "OpFunctionEnd",
  731. 2, 1),
  732. // Test case 44: UClamp 1 2 x
  733. InstructionFoldingCase<uint32_t>(
  734. Header() + "%main = OpFunction %void None %void_func\n" +
  735. "%main_lab = OpLabel\n" +
  736. "%undef = OpUndef %uint\n" +
  737. "%2 = OpExtInst %uint %1 UClamp %uint_1 %uint_2 %undef\n" +
  738. "OpReturn\n" +
  739. "OpFunctionEnd",
  740. 2, 2),
  741. // Test case 45: UClamp 2 x 1
  742. InstructionFoldingCase<uint32_t>(
  743. Header() + "%main = OpFunction %void None %void_func\n" +
  744. "%main_lab = OpLabel\n" +
  745. "%undef = OpUndef %uint\n" +
  746. "%2 = OpExtInst %uint %1 UClamp %uint_2 %undef %uint_1\n" +
  747. "OpReturn\n" +
  748. "OpFunctionEnd",
  749. 2, 1),
  750. // Test case 46: Bit-cast int 0 to unsigned int
  751. InstructionFoldingCase<uint32_t>(
  752. Header() + "%main = OpFunction %void None %void_func\n" +
  753. "%main_lab = OpLabel\n" +
  754. "%2 = OpBitcast %uint %int_0\n" +
  755. "OpReturn\n" +
  756. "OpFunctionEnd",
  757. 2, 0),
  758. // Test case 47: Bit-cast int -24 to unsigned int
  759. InstructionFoldingCase<uint32_t>(
  760. Header() + "%main = OpFunction %void None %void_func\n" +
  761. "%main_lab = OpLabel\n" +
  762. "%2 = OpBitcast %uint %int_n24\n" +
  763. "OpReturn\n" +
  764. "OpFunctionEnd",
  765. 2, static_cast<uint32_t>(-24)),
  766. // Test case 48: Bit-cast float 1.0f to unsigned int
  767. InstructionFoldingCase<uint32_t>(
  768. Header() + "%main = OpFunction %void None %void_func\n" +
  769. "%main_lab = OpLabel\n" +
  770. "%2 = OpBitcast %uint %float_1\n" +
  771. "OpReturn\n" +
  772. "OpFunctionEnd",
  773. 2, static_cast<uint32_t>(0x3f800000)),
  774. // Test case 49: Bit-cast ushort 0xBC00 to ushort
  775. InstructionFoldingCase<uint32_t>(
  776. Header() + "%main = OpFunction %void None %void_func\n" +
  777. "%main_lab = OpLabel\n" +
  778. "%2 = OpBitcast %ushort %ushort_0xBC00\n" +
  779. "OpReturn\n" +
  780. "OpFunctionEnd",
  781. 2, 0xBC00),
  782. // Test case 50: Bit-cast short 0xBC00 to ushort
  783. InstructionFoldingCase<uint32_t>(
  784. Header() + "%main = OpFunction %void None %void_func\n" +
  785. "%main_lab = OpLabel\n" +
  786. "%2 = OpBitcast %ushort %short_0xBC00\n" +
  787. "OpReturn\n" +
  788. "OpFunctionEnd",
  789. 2, 0xFFFFBC00),
  790. // Test case 51: Bit-cast half 1 to ushort
  791. InstructionFoldingCase<uint32_t>(
  792. Header() + "%main = OpFunction %void None %void_func\n" +
  793. "%main_lab = OpLabel\n" +
  794. "%2 = OpBitcast %ushort %half_1\n" +
  795. "OpReturn\n" +
  796. "OpFunctionEnd",
  797. 2, 0x3C00),
  798. // Test case 52: Bit-cast ushort 0xBC00 to short
  799. InstructionFoldingCase<uint32_t>(
  800. Header() + "%main = OpFunction %void None %void_func\n" +
  801. "%main_lab = OpLabel\n" +
  802. "%2 = OpBitcast %short %ushort_0xBC00\n" +
  803. "OpReturn\n" +
  804. "OpFunctionEnd",
  805. 2, 0xBC00),
  806. // Test case 53: Bit-cast short 0xBC00 to short
  807. InstructionFoldingCase<uint32_t>(
  808. Header() + "%main = OpFunction %void None %void_func\n" +
  809. "%main_lab = OpLabel\n" +
  810. "%2 = OpBitcast %short %short_0xBC00\n" +
  811. "OpReturn\n" +
  812. "OpFunctionEnd",
  813. 2, 0xFFFFBC00),
  814. // Test case 54: Bit-cast half 1 to short
  815. InstructionFoldingCase<uint32_t>(
  816. Header() + "%main = OpFunction %void None %void_func\n" +
  817. "%main_lab = OpLabel\n" +
  818. "%2 = OpBitcast %short %half_1\n" +
  819. "OpReturn\n" +
  820. "OpFunctionEnd",
  821. 2, 0x3C00),
  822. // Test case 55: Bit-cast ushort 0xBC00 to half
  823. InstructionFoldingCase<uint32_t>(
  824. Header() + "%main = OpFunction %void None %void_func\n" +
  825. "%main_lab = OpLabel\n" +
  826. "%2 = OpBitcast %half %ushort_0xBC00\n" +
  827. "OpReturn\n" +
  828. "OpFunctionEnd",
  829. 2, 0xBC00),
  830. // Test case 56: Bit-cast short 0xBC00 to half
  831. InstructionFoldingCase<uint32_t>(
  832. Header() + "%main = OpFunction %void None %void_func\n" +
  833. "%main_lab = OpLabel\n" +
  834. "%2 = OpBitcast %half %short_0xBC00\n" +
  835. "OpReturn\n" +
  836. "OpFunctionEnd",
  837. 2, 0xFFFFBC00),
  838. // Test case 57: Bit-cast half 1 to half
  839. InstructionFoldingCase<uint32_t>(
  840. Header() + "%main = OpFunction %void None %void_func\n" +
  841. "%main_lab = OpLabel\n" +
  842. "%2 = OpBitcast %half %half_1\n" +
  843. "OpReturn\n" +
  844. "OpFunctionEnd",
  845. 2, 0x3C00),
  846. // Test case 58: Bit-cast ubyte 1 to byte
  847. InstructionFoldingCase<uint32_t>(
  848. Header() + "%main = OpFunction %void None %void_func\n" +
  849. "%main_lab = OpLabel\n" +
  850. "%2 = OpBitcast %byte %ubyte_1\n" +
  851. "OpReturn\n" +
  852. "OpFunctionEnd",
  853. 2, 1),
  854. // Test case 59: Bit-cast byte -1 to ubyte
  855. InstructionFoldingCase<uint32_t>(
  856. Header() + "%main = OpFunction %void None %void_func\n" +
  857. "%main_lab = OpLabel\n" +
  858. "%2 = OpBitcast %ubyte %byte_n1\n" +
  859. "OpReturn\n" +
  860. "OpFunctionEnd",
  861. 2, 0xFFFFFFFF)
  862. ));
  863. // clang-format on
  864. using IntVectorInstructionFoldingTest =
  865. ::testing::TestWithParam<InstructionFoldingCase<std::vector<uint32_t>>>;
  866. TEST_P(IntVectorInstructionFoldingTest, Case) {
  867. const auto& tc = GetParam();
  868. // Build module.
  869. std::unique_ptr<IRContext> context =
  870. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
  871. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  872. ASSERT_NE(nullptr, context);
  873. // Fold the instruction to test.
  874. analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
  875. Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
  876. spv::Op original_opcode = inst->opcode();
  877. bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
  878. // Make sure the instruction folded as expected.
  879. EXPECT_EQ(succeeded, inst == nullptr || inst->opcode() != original_opcode);
  880. if (succeeded && inst != nullptr) {
  881. EXPECT_EQ(inst->opcode(), spv::Op::OpCopyObject);
  882. inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
  883. std::vector<spv::Op> opcodes = {spv::Op::OpConstantComposite};
  884. EXPECT_THAT(opcodes, Contains(inst->opcode()));
  885. analysis::ConstantManager* const_mrg = context->get_constant_mgr();
  886. const analysis::Constant* result = const_mrg->GetConstantFromInst(inst);
  887. EXPECT_NE(result, nullptr);
  888. if (result != nullptr) {
  889. const std::vector<const analysis::Constant*>& componenets =
  890. result->AsVectorConstant()->GetComponents();
  891. EXPECT_EQ(componenets.size(), tc.expected_result.size());
  892. for (size_t i = 0; i < componenets.size(); i++) {
  893. EXPECT_EQ(tc.expected_result[i], componenets[i]->GetU32());
  894. }
  895. }
  896. }
  897. }
  898. // clang-format off
  899. INSTANTIATE_TEST_SUITE_P(TestCase, IntVectorInstructionFoldingTest,
  900. ::testing::Values(
  901. // Test case 0: fold 0*n
  902. InstructionFoldingCase<std::vector<uint32_t>>(
  903. Header() + "%main = OpFunction %void None %void_func\n" +
  904. "%main_lab = OpLabel\n" +
  905. "%n = OpVariable %_ptr_int Function\n" +
  906. "%load = OpLoad %int %n\n" +
  907. "%2 = OpVectorShuffle %v2int %v2int_2_2 %v2int_2_3 0 3\n" +
  908. "OpReturn\n" +
  909. "OpFunctionEnd",
  910. 2, {2,3}),
  911. InstructionFoldingCase<std::vector<uint32_t>>(
  912. Header() + "%main = OpFunction %void None %void_func\n" +
  913. "%main_lab = OpLabel\n" +
  914. "%n = OpVariable %_ptr_int Function\n" +
  915. "%load = OpLoad %int %n\n" +
  916. "%2 = OpVectorShuffle %v2int %v2int_null %v2int_2_3 0 3\n" +
  917. "OpReturn\n" +
  918. "OpFunctionEnd",
  919. 2, {0,3}),
  920. InstructionFoldingCase<std::vector<uint32_t>>(
  921. Header() + "%main = OpFunction %void None %void_func\n" +
  922. "%main_lab = OpLabel\n" +
  923. "%n = OpVariable %_ptr_int Function\n" +
  924. "%load = OpLoad %int %n\n" +
  925. "%2 = OpVectorShuffle %v2int %v2int_null %v2int_2_3 4294967295 3\n" +
  926. "OpReturn\n" +
  927. "OpFunctionEnd",
  928. 2, {0,0}),
  929. InstructionFoldingCase<std::vector<uint32_t>>(
  930. Header() + "%main = OpFunction %void None %void_func\n" +
  931. "%main_lab = OpLabel\n" +
  932. "%n = OpVariable %_ptr_int Function\n" +
  933. "%load = OpLoad %int %n\n" +
  934. "%2 = OpVectorShuffle %v2int %v2int_null %v2int_2_3 0 4294967295 \n" +
  935. "OpReturn\n" +
  936. "OpFunctionEnd",
  937. 2, {0,0}),
  938. // Test case 4: fold bit-cast int -24 to unsigned int
  939. InstructionFoldingCase<std::vector<uint32_t>>(
  940. Header() + "%main = OpFunction %void None %void_func\n" +
  941. "%main_lab = OpLabel\n" +
  942. "%n = OpVariable %_ptr_int Function\n" +
  943. "%load = OpLoad %int %n\n" +
  944. "%2 = OpBitcast %v2uint %v2int_min_max\n" +
  945. "OpReturn\n" +
  946. "OpFunctionEnd",
  947. 2, {2147483648, 2147483647})
  948. ));
  949. // clang-format on
  950. using DoubleVectorInstructionFoldingTest =
  951. ::testing::TestWithParam<InstructionFoldingCase<std::vector<double>>>;
  952. TEST_P(DoubleVectorInstructionFoldingTest, Case) {
  953. const auto& tc = GetParam();
  954. // Build module.
  955. std::unique_ptr<IRContext> context =
  956. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
  957. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  958. ASSERT_NE(nullptr, context);
  959. // Fold the instruction to test.
  960. analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
  961. Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
  962. bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
  963. // Make sure the instruction folded as expected.
  964. EXPECT_TRUE(succeeded);
  965. if (succeeded && inst != nullptr) {
  966. EXPECT_EQ(inst->opcode(), spv::Op::OpCopyObject);
  967. inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
  968. std::vector<spv::Op> opcodes = {spv::Op::OpConstantComposite};
  969. EXPECT_THAT(opcodes, Contains(inst->opcode()));
  970. analysis::ConstantManager* const_mrg = context->get_constant_mgr();
  971. const analysis::Constant* result = const_mrg->GetConstantFromInst(inst);
  972. EXPECT_NE(result, nullptr);
  973. if (result != nullptr) {
  974. const std::vector<const analysis::Constant*>& componenets =
  975. result->AsVectorConstant()->GetComponents();
  976. EXPECT_EQ(componenets.size(), tc.expected_result.size());
  977. for (size_t i = 0; i < componenets.size(); i++) {
  978. EXPECT_EQ(tc.expected_result[i], componenets[i]->GetDouble());
  979. }
  980. }
  981. }
  982. }
  983. // clang-format off
  984. INSTANTIATE_TEST_SUITE_P(TestCase, DoubleVectorInstructionFoldingTest,
  985. ::testing::Values(
  986. // Test case 0: bit-cast int {0x3FF00000,0x00000000,0xC05FD666,0x66666666}
  987. // to double vector
  988. InstructionFoldingCase<std::vector<double>>(
  989. Header() + "%main = OpFunction %void None %void_func\n" +
  990. "%main_lab = OpLabel\n" +
  991. "%2 = OpBitcast %v2double %v4int_0x3FF00000_0x00000000_0xC05FD666_0x66666666\n" +
  992. "OpReturn\n" +
  993. "OpFunctionEnd",
  994. 2, {1.0,-127.35}),
  995. // Test case 1: OpVectorTimesMatrix Non-Zero Zero {{0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0}} {1.0, 2.0, 3.0, 4.0} {0.0, 0.0, 0.0, 0.0}
  996. InstructionFoldingCase<std::vector<double>>(
  997. Header() +
  998. "%main = OpFunction %void None %void_func\n" +
  999. "%main_lab = OpLabel\n" +
  1000. "%2 = OpVectorTimesMatrix %v4double %v4double_1_2_3_4 %mat4v4double_null\n" +
  1001. "OpReturn\n" +
  1002. "OpFunctionEnd",
  1003. 2, {0.0,0.0,0.0,0.0}),
  1004. // Test case 2: OpVectorTimesMatrix Zero Non-Zero {{1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}} {0.0, 0.0, 0.0, 0.0} {0.0, 0.0, 0.0, 0.0}
  1005. InstructionFoldingCase<std::vector<double>>(
  1006. Header() +
  1007. "%main = OpFunction %void None %void_func\n" +
  1008. "%main_lab = OpLabel\n" +
  1009. "%2 = OpVectorTimesMatrix %v4double %v4double_null %mat4v4double_1_2_3_4\n" +
  1010. "OpReturn\n" +
  1011. "OpFunctionEnd",
  1012. 2, {0.0,0.0,0.0,0.0}),
  1013. // Test case 3: OpVectorTimesMatrix Non-Zero Non-Zero {{1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}} {1.0, 2.0, 3.0, 4.0} {30.0, 30.0, 30.0, 30.0}
  1014. InstructionFoldingCase<std::vector<double>>(
  1015. Header() +
  1016. "%main = OpFunction %void None %void_func\n" +
  1017. "%main_lab = OpLabel\n" +
  1018. "%2 = OpVectorTimesMatrix %v4double %v4double_1_2_3_4 %mat4v4double_1_2_3_4\n" +
  1019. "OpReturn\n" +
  1020. "OpFunctionEnd",
  1021. 2, {30.0,30.0,30.0,30.0}),
  1022. // Test case 4: OpMatrixTimesVector Zero Non-Zero {1.0, 2.0, 3.0, 4.0} {{0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0}} {0.0, 0.0, 0.0, 0.0}
  1023. InstructionFoldingCase<std::vector<double>>(
  1024. Header() +
  1025. "%main = OpFunction %void None %void_func\n" +
  1026. "%main_lab = OpLabel\n" +
  1027. "%2 = OpMatrixTimesVector %v4double %mat4v4double_null %v4double_1_2_3_4\n" +
  1028. "OpReturn\n" +
  1029. "OpFunctionEnd",
  1030. 2, {0.0,0.0,0.0,0.0}),
  1031. // Test case 5: OpMatrixTimesVector Non-Zero Zero {{1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}} {0.0, 0.0, 0.0, 0.0} {0.0, 0.0, 0.0, 0.0}
  1032. InstructionFoldingCase<std::vector<double>>(
  1033. Header() +
  1034. "%main = OpFunction %void None %void_func\n" +
  1035. "%main_lab = OpLabel\n" +
  1036. "%2 = OpMatrixTimesVector %v4double %mat4v4double_1_2_3_4 %v4double_null\n" +
  1037. "OpReturn\n" +
  1038. "OpFunctionEnd",
  1039. 2, {0.0,0.0,0.0,0.0}),
  1040. // Test case 6: OpMatrixTimesVector Non-Zero Non-Zero {1.0, 2.0, 3.0, 4.0} {{1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}} {10.0, 20.0, 30.0, 40.0}
  1041. InstructionFoldingCase<std::vector<double>>(
  1042. Header() +
  1043. "%main = OpFunction %void None %void_func\n" +
  1044. "%main_lab = OpLabel\n" +
  1045. "%2 = OpMatrixTimesVector %v4double %mat4v4double_1_2_3_4 %v4double_1_2_3_4\n" +
  1046. "OpReturn\n" +
  1047. "OpFunctionEnd",
  1048. 2, {10.0,20.0,30.0,40.0})
  1049. ));
  1050. using FloatVectorInstructionFoldingTest =
  1051. ::testing::TestWithParam<InstructionFoldingCase<std::vector<float>>>;
  1052. TEST_P(FloatVectorInstructionFoldingTest, Case) {
  1053. const auto& tc = GetParam();
  1054. // Build module.
  1055. std::unique_ptr<IRContext> context =
  1056. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
  1057. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  1058. ASSERT_NE(nullptr, context);
  1059. // Fold the instruction to test.
  1060. analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
  1061. Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
  1062. spv::Op original_opcode = inst->opcode();
  1063. bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
  1064. // Make sure the instruction folded as expected.
  1065. EXPECT_EQ(succeeded, inst == nullptr || inst->opcode() != original_opcode);
  1066. if (succeeded && inst != nullptr) {
  1067. EXPECT_EQ(inst->opcode(), spv::Op::OpCopyObject);
  1068. inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
  1069. std::vector<spv::Op> opcodes = {spv::Op::OpConstantComposite};
  1070. EXPECT_THAT(opcodes, Contains(inst->opcode()));
  1071. analysis::ConstantManager* const_mrg = context->get_constant_mgr();
  1072. const analysis::Constant* result = const_mrg->GetConstantFromInst(inst);
  1073. EXPECT_NE(result, nullptr);
  1074. if (result != nullptr) {
  1075. const std::vector<const analysis::Constant*>& componenets =
  1076. result->AsVectorConstant()->GetComponents();
  1077. EXPECT_EQ(componenets.size(), tc.expected_result.size());
  1078. for (size_t i = 0; i < componenets.size(); i++) {
  1079. EXPECT_EQ(tc.expected_result[i], componenets[i]->GetFloat());
  1080. }
  1081. }
  1082. }
  1083. }
  1084. // clang-format off
  1085. INSTANTIATE_TEST_SUITE_P(TestCase, FloatVectorInstructionFoldingTest,
  1086. ::testing::Values(
  1087. // Test case 0: FMix {2.0, 2.0}, {2.0, 3.0} {0.2,0.5}
  1088. InstructionFoldingCase<std::vector<float>>(
  1089. Header() + "%main = OpFunction %void None %void_func\n" +
  1090. "%main_lab = OpLabel\n" +
  1091. "%2 = OpExtInst %v2float %1 FMix %v2float_2_3 %v2float_0_0 %v2float_0p2_0p5\n" +
  1092. "OpReturn\n" +
  1093. "OpFunctionEnd",
  1094. 2, {1.6f,1.5f}),
  1095. // Test case 1: bit-cast unsigned int vector {0x3f800000, 0xbf800000} to
  1096. // float vector
  1097. InstructionFoldingCase<std::vector<float>>(
  1098. Header() + "%main = OpFunction %void None %void_func\n" +
  1099. "%main_lab = OpLabel\n" +
  1100. "%2 = OpBitcast %v2float %v2uint_0x3f800000_0xbf800000\n" +
  1101. "OpReturn\n" +
  1102. "OpFunctionEnd",
  1103. 2, {1.0f,-1.0f}),
  1104. // Test case 2: bit-cast long int 0xbf8000003f800000 to float vector
  1105. InstructionFoldingCase<std::vector<float>>(
  1106. Header() + "%main = OpFunction %void None %void_func\n" +
  1107. "%main_lab = OpLabel\n" +
  1108. "%2 = OpBitcast %v2float %long_0xbf8000003f800000\n" +
  1109. "OpReturn\n" +
  1110. "OpFunctionEnd",
  1111. 2, {1.0f,-1.0f}),
  1112. // Test case 3: OpVectorTimesMatrix Non-Zero Zero {{0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0}} {1.0, 2.0, 3.0, 4.0} {0.0, 0.0, 0.0, 0.0}
  1113. InstructionFoldingCase<std::vector<float>>(
  1114. Header() +
  1115. "%main = OpFunction %void None %void_func\n" +
  1116. "%main_lab = OpLabel\n" +
  1117. "%2 = OpVectorTimesMatrix %v4float %v4float_1_2_3_4 %mat4v4float_null\n" +
  1118. "OpReturn\n" +
  1119. "OpFunctionEnd",
  1120. 2, {0.0f,0.0f,0.0f,0.0f}),
  1121. // Test case 4: OpVectorTimesMatrix Zero Non-Zero {{1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}} {0.0, 0.0, 0.0, 0.0} {0.0, 0.0, 0.0, 0.0}
  1122. InstructionFoldingCase<std::vector<float>>(
  1123. Header() +
  1124. "%main = OpFunction %void None %void_func\n" +
  1125. "%main_lab = OpLabel\n" +
  1126. "%2 = OpVectorTimesMatrix %v4float %v4float_null %mat4v4float_1_2_3_4\n" +
  1127. "OpReturn\n" +
  1128. "OpFunctionEnd",
  1129. 2, {0.0f,0.0f,0.0f,0.0f}),
  1130. // Test case 5: OpVectorTimesMatrix Non-Zero Non-Zero {{1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}} {1.0, 2.0, 3.0, 4.0} {30.0, 30.0, 30.0, 30.0}
  1131. InstructionFoldingCase<std::vector<float>>(
  1132. Header() +
  1133. "%main = OpFunction %void None %void_func\n" +
  1134. "%main_lab = OpLabel\n" +
  1135. "%2 = OpVectorTimesMatrix %v4float %v4float_1_2_3_4 %mat4v4float_1_2_3_4\n" +
  1136. "OpReturn\n" +
  1137. "OpFunctionEnd",
  1138. 2, {30.0f,30.0f,30.0f,30.0f}),
  1139. // Test case 6: OpMatrixTimesVector Zero Non-Zero {1.0, 2.0, 3.0, 4.0} {{0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0}} {0.0, 0.0, 0.0, 0.0}
  1140. InstructionFoldingCase<std::vector<float>>(
  1141. Header() +
  1142. "%main = OpFunction %void None %void_func\n" +
  1143. "%main_lab = OpLabel\n" +
  1144. "%2 = OpMatrixTimesVector %v4float %mat4v4float_null %v4float_1_2_3_4\n" +
  1145. "OpReturn\n" +
  1146. "OpFunctionEnd",
  1147. 2, {0.0f,0.0f,0.0f,0.0f}),
  1148. // Test case 7: OpMatrixTimesVector Non-Zero Zero {{1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}} {0.0, 0.0, 0.0, 0.0} {0.0, 0.0, 0.0, 0.0}
  1149. InstructionFoldingCase<std::vector<float>>(
  1150. Header() +
  1151. "%main = OpFunction %void None %void_func\n" +
  1152. "%main_lab = OpLabel\n" +
  1153. "%2 = OpMatrixTimesVector %v4float %mat4v4float_1_2_3_4 %v4float_null\n" +
  1154. "OpReturn\n" +
  1155. "OpFunctionEnd",
  1156. 2, {0.0f,0.0f,0.0f,0.0f}),
  1157. // Test case 8: OpMatrixTimesVector Non-Zero Non-Zero {1.0, 2.0, 3.0, 4.0} {{1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}} {10.0, 20.0, 30.0, 40.0}
  1158. InstructionFoldingCase<std::vector<float>>(
  1159. Header() +
  1160. "%main = OpFunction %void None %void_func\n" +
  1161. "%main_lab = OpLabel\n" +
  1162. "%2 = OpMatrixTimesVector %v4float %mat4v4float_1_2_3_4 %v4float_1_2_3_4\n" +
  1163. "OpReturn\n" +
  1164. "OpFunctionEnd",
  1165. 2, {10.0f,20.0f,30.0f,40.0f})
  1166. ));
  1167. // clang-format on
  1168. using BooleanInstructionFoldingTest =
  1169. ::testing::TestWithParam<InstructionFoldingCase<bool>>;
  1170. TEST_P(BooleanInstructionFoldingTest, Case) {
  1171. const auto& tc = GetParam();
  1172. // Build module.
  1173. std::unique_ptr<IRContext> context =
  1174. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
  1175. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  1176. ASSERT_NE(nullptr, context);
  1177. // Fold the instruction to test.
  1178. analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
  1179. Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
  1180. bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
  1181. // Make sure the instruction folded as expected.
  1182. EXPECT_TRUE(succeeded);
  1183. if (inst != nullptr) {
  1184. EXPECT_EQ(inst->opcode(), spv::Op::OpCopyObject);
  1185. inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
  1186. std::vector<spv::Op> bool_opcodes = {spv::Op::OpConstantTrue,
  1187. spv::Op::OpConstantFalse};
  1188. EXPECT_THAT(bool_opcodes, Contains(inst->opcode()));
  1189. analysis::ConstantManager* const_mrg = context->get_constant_mgr();
  1190. const analysis::BoolConstant* result =
  1191. const_mrg->GetConstantFromInst(inst)->AsBoolConstant();
  1192. EXPECT_NE(result, nullptr);
  1193. if (result != nullptr) {
  1194. EXPECT_EQ(result->value(), tc.expected_result);
  1195. }
  1196. }
  1197. }
  1198. // clang-format off
  1199. INSTANTIATE_TEST_SUITE_P(TestCase, BooleanInstructionFoldingTest,
  1200. ::testing::Values(
  1201. // Test case 0: fold true || n
  1202. InstructionFoldingCase<bool>(
  1203. Header() + "%main = OpFunction %void None %void_func\n" +
  1204. "%main_lab = OpLabel\n" +
  1205. "%n = OpVariable %_ptr_bool Function\n" +
  1206. "%load = OpLoad %bool %n\n" +
  1207. "%2 = OpLogicalOr %bool %true %load\n" +
  1208. "OpReturn\n" +
  1209. "OpFunctionEnd",
  1210. 2, true),
  1211. // Test case 1: fold n || true
  1212. InstructionFoldingCase<bool>(
  1213. Header() + "%main = OpFunction %void None %void_func\n" +
  1214. "%main_lab = OpLabel\n" +
  1215. "%n = OpVariable %_ptr_bool Function\n" +
  1216. "%load = OpLoad %bool %n\n" +
  1217. "%2 = OpLogicalOr %bool %load %true\n" +
  1218. "OpReturn\n" +
  1219. "OpFunctionEnd",
  1220. 2, true),
  1221. // Test case 2: fold false && n
  1222. InstructionFoldingCase<bool>(
  1223. Header() + "%main = OpFunction %void None %void_func\n" +
  1224. "%main_lab = OpLabel\n" +
  1225. "%n = OpVariable %_ptr_bool Function\n" +
  1226. "%load = OpLoad %bool %n\n" +
  1227. "%2 = OpLogicalAnd %bool %false %load\n" +
  1228. "OpReturn\n" +
  1229. "OpFunctionEnd",
  1230. 2, false),
  1231. // Test case 3: fold n && false
  1232. InstructionFoldingCase<bool>(
  1233. Header() + "%main = OpFunction %void None %void_func\n" +
  1234. "%main_lab = OpLabel\n" +
  1235. "%n = OpVariable %_ptr_bool Function\n" +
  1236. "%load = OpLoad %bool %n\n" +
  1237. "%2 = OpLogicalAnd %bool %load %false\n" +
  1238. "OpReturn\n" +
  1239. "OpFunctionEnd",
  1240. 2, false),
  1241. // Test case 4: fold n < 0 (unsigned)
  1242. InstructionFoldingCase<bool>(
  1243. Header() + "%main = OpFunction %void None %void_func\n" +
  1244. "%main_lab = OpLabel\n" +
  1245. "%n = OpVariable %_ptr_uint Function\n" +
  1246. "%load = OpLoad %uint %n\n" +
  1247. "%2 = OpULessThan %bool %load %uint_0\n" +
  1248. "OpReturn\n" +
  1249. "OpFunctionEnd",
  1250. 2, false),
  1251. // Test case 5: fold UINT_MAX < n (unsigned)
  1252. InstructionFoldingCase<bool>(
  1253. Header() + "%main = OpFunction %void None %void_func\n" +
  1254. "%main_lab = OpLabel\n" +
  1255. "%n = OpVariable %_ptr_uint Function\n" +
  1256. "%load = OpLoad %uint %n\n" +
  1257. "%2 = OpULessThan %bool %uint_max %load\n" +
  1258. "OpReturn\n" +
  1259. "OpFunctionEnd",
  1260. 2, false),
  1261. // Test case 6: fold INT_MAX < n (signed)
  1262. InstructionFoldingCase<bool>(
  1263. Header() + "%main = OpFunction %void None %void_func\n" +
  1264. "%main_lab = OpLabel\n" +
  1265. "%n = OpVariable %_ptr_int Function\n" +
  1266. "%load = OpLoad %int %n\n" +
  1267. "%2 = OpSLessThan %bool %int_max %load\n" +
  1268. "OpReturn\n" +
  1269. "OpFunctionEnd",
  1270. 2, false),
  1271. // Test case 7: fold n < INT_MIN (signed)
  1272. InstructionFoldingCase<bool>(
  1273. Header() + "%main = OpFunction %void None %void_func\n" +
  1274. "%main_lab = OpLabel\n" +
  1275. "%n = OpVariable %_ptr_int Function\n" +
  1276. "%load = OpLoad %int %n\n" +
  1277. "%2 = OpSLessThan %bool %load %int_min\n" +
  1278. "OpReturn\n" +
  1279. "OpFunctionEnd",
  1280. 2, false),
  1281. // Test case 8: fold 0 > n (unsigned)
  1282. InstructionFoldingCase<bool>(
  1283. Header() + "%main = OpFunction %void None %void_func\n" +
  1284. "%main_lab = OpLabel\n" +
  1285. "%n = OpVariable %_ptr_uint Function\n" +
  1286. "%load = OpLoad %uint %n\n" +
  1287. "%2 = OpUGreaterThan %bool %uint_0 %load\n" +
  1288. "OpReturn\n" +
  1289. "OpFunctionEnd",
  1290. 2, false),
  1291. // Test case 9: fold n > UINT_MAX (unsigned)
  1292. InstructionFoldingCase<bool>(
  1293. Header() + "%main = OpFunction %void None %void_func\n" +
  1294. "%main_lab = OpLabel\n" +
  1295. "%n = OpVariable %_ptr_uint Function\n" +
  1296. "%load = OpLoad %uint %n\n" +
  1297. "%2 = OpUGreaterThan %bool %load %uint_max\n" +
  1298. "OpReturn\n" +
  1299. "OpFunctionEnd",
  1300. 2, false),
  1301. // Test case 10: fold n > INT_MAX (signed)
  1302. InstructionFoldingCase<bool>(
  1303. Header() + "%main = OpFunction %void None %void_func\n" +
  1304. "%main_lab = OpLabel\n" +
  1305. "%n = OpVariable %_ptr_int Function\n" +
  1306. "%load = OpLoad %int %n\n" +
  1307. "%2 = OpSGreaterThan %bool %load %int_max\n" +
  1308. "OpReturn\n" +
  1309. "OpFunctionEnd",
  1310. 2, false),
  1311. // Test case 11: fold INT_MIN > n (signed)
  1312. InstructionFoldingCase<bool>(
  1313. Header() + "%main = OpFunction %void None %void_func\n" +
  1314. "%main_lab = OpLabel\n" +
  1315. "%n = OpVariable %_ptr_uint Function\n" +
  1316. "%load = OpLoad %uint %n\n" +
  1317. "%2 = OpSGreaterThan %bool %int_min %load\n" +
  1318. "OpReturn\n" +
  1319. "OpFunctionEnd",
  1320. 2, false),
  1321. // Test case 12: fold 0 <= n (unsigned)
  1322. InstructionFoldingCase<bool>(
  1323. Header() + "%main = OpFunction %void None %void_func\n" +
  1324. "%main_lab = OpLabel\n" +
  1325. "%n = OpVariable %_ptr_uint Function\n" +
  1326. "%load = OpLoad %uint %n\n" +
  1327. "%2 = OpULessThanEqual %bool %uint_0 %load\n" +
  1328. "OpReturn\n" +
  1329. "OpFunctionEnd",
  1330. 2, true),
  1331. // Test case 13: fold n <= UINT_MAX (unsigned)
  1332. InstructionFoldingCase<bool>(
  1333. Header() + "%main = OpFunction %void None %void_func\n" +
  1334. "%main_lab = OpLabel\n" +
  1335. "%n = OpVariable %_ptr_uint Function\n" +
  1336. "%load = OpLoad %uint %n\n" +
  1337. "%2 = OpULessThanEqual %bool %load %uint_max\n" +
  1338. "OpReturn\n" +
  1339. "OpFunctionEnd",
  1340. 2, true),
  1341. // Test case 14: fold INT_MIN <= n (signed)
  1342. InstructionFoldingCase<bool>(
  1343. Header() + "%main = OpFunction %void None %void_func\n" +
  1344. "%main_lab = OpLabel\n" +
  1345. "%n = OpVariable %_ptr_int Function\n" +
  1346. "%load = OpLoad %int %n\n" +
  1347. "%2 = OpSLessThanEqual %bool %int_min %load\n" +
  1348. "OpReturn\n" +
  1349. "OpFunctionEnd",
  1350. 2, true),
  1351. // Test case 15: fold n <= INT_MAX (signed)
  1352. InstructionFoldingCase<bool>(
  1353. Header() + "%main = OpFunction %void None %void_func\n" +
  1354. "%main_lab = OpLabel\n" +
  1355. "%n = OpVariable %_ptr_int Function\n" +
  1356. "%load = OpLoad %int %n\n" +
  1357. "%2 = OpSLessThanEqual %bool %load %int_max\n" +
  1358. "OpReturn\n" +
  1359. "OpFunctionEnd",
  1360. 2, true),
  1361. // Test case 16: fold n >= 0 (unsigned)
  1362. InstructionFoldingCase<bool>(
  1363. Header() + "%main = OpFunction %void None %void_func\n" +
  1364. "%main_lab = OpLabel\n" +
  1365. "%n = OpVariable %_ptr_uint Function\n" +
  1366. "%load = OpLoad %uint %n\n" +
  1367. "%2 = OpUGreaterThanEqual %bool %load %uint_0\n" +
  1368. "OpReturn\n" +
  1369. "OpFunctionEnd",
  1370. 2, true),
  1371. // Test case 17: fold UINT_MAX >= n (unsigned)
  1372. InstructionFoldingCase<bool>(
  1373. Header() + "%main = OpFunction %void None %void_func\n" +
  1374. "%main_lab = OpLabel\n" +
  1375. "%n = OpVariable %_ptr_uint Function\n" +
  1376. "%load = OpLoad %uint %n\n" +
  1377. "%2 = OpUGreaterThanEqual %bool %uint_max %load\n" +
  1378. "OpReturn\n" +
  1379. "OpFunctionEnd",
  1380. 2, true),
  1381. // Test case 18: fold n >= INT_MIN (signed)
  1382. InstructionFoldingCase<bool>(
  1383. Header() + "%main = OpFunction %void None %void_func\n" +
  1384. "%main_lab = OpLabel\n" +
  1385. "%n = OpVariable %_ptr_int Function\n" +
  1386. "%load = OpLoad %int %n\n" +
  1387. "%2 = OpSGreaterThanEqual %bool %load %int_min\n" +
  1388. "OpReturn\n" +
  1389. "OpFunctionEnd",
  1390. 2, true),
  1391. // Test case 19: fold INT_MAX >= n (signed)
  1392. InstructionFoldingCase<bool>(
  1393. Header() + "%main = OpFunction %void None %void_func\n" +
  1394. "%main_lab = OpLabel\n" +
  1395. "%n = OpVariable %_ptr_int Function\n" +
  1396. "%load = OpLoad %int %n\n" +
  1397. "%2 = OpSGreaterThanEqual %bool %int_max %load\n" +
  1398. "OpReturn\n" +
  1399. "OpFunctionEnd",
  1400. 2, true)
  1401. ));
  1402. INSTANTIATE_TEST_SUITE_P(FClampAndCmpLHS, BooleanInstructionFoldingTest,
  1403. ::testing::Values(
  1404. // Test case 0: fold 0.0 > clamp(n, 0.0, 1.0)
  1405. InstructionFoldingCase<bool>(
  1406. Header() + "%main = OpFunction %void None %void_func\n" +
  1407. "%main_lab = OpLabel\n" +
  1408. "%n = OpVariable %_ptr_float Function\n" +
  1409. "%ld = OpLoad %float %n\n" +
  1410. "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
  1411. "%2 = OpFOrdGreaterThan %bool %float_0 %clamp\n" +
  1412. "OpReturn\n" +
  1413. "OpFunctionEnd",
  1414. 2, false),
  1415. // Test case 1: fold 0.0 > clamp(n, -1.0, -1.0)
  1416. InstructionFoldingCase<bool>(
  1417. Header() + "%main = OpFunction %void None %void_func\n" +
  1418. "%main_lab = OpLabel\n" +
  1419. "%n = OpVariable %_ptr_float Function\n" +
  1420. "%ld = OpLoad %float %n\n" +
  1421. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_n1\n" +
  1422. "%2 = OpFOrdGreaterThan %bool %float_0 %clamp\n" +
  1423. "OpReturn\n" +
  1424. "OpFunctionEnd",
  1425. 2, true),
  1426. // Test case 2: fold 0.0 >= clamp(n, 1, 2)
  1427. InstructionFoldingCase<bool>(
  1428. Header() + "%main = OpFunction %void None %void_func\n" +
  1429. "%main_lab = OpLabel\n" +
  1430. "%n = OpVariable %_ptr_float Function\n" +
  1431. "%ld = OpLoad %float %n\n" +
  1432. "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
  1433. "%2 = OpFOrdGreaterThanEqual %bool %float_0 %clamp\n" +
  1434. "OpReturn\n" +
  1435. "OpFunctionEnd",
  1436. 2, false),
  1437. // Test case 3: fold 0.0 >= clamp(n, -1.0, 0.0)
  1438. InstructionFoldingCase<bool>(
  1439. Header() + "%main = OpFunction %void None %void_func\n" +
  1440. "%main_lab = OpLabel\n" +
  1441. "%n = OpVariable %_ptr_float Function\n" +
  1442. "%ld = OpLoad %float %n\n" +
  1443. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
  1444. "%2 = OpFOrdGreaterThanEqual %bool %float_0 %clamp\n" +
  1445. "OpReturn\n" +
  1446. "OpFunctionEnd",
  1447. 2, true),
  1448. // Test case 4: fold 0.0 <= clamp(n, 0.0, 1.0)
  1449. InstructionFoldingCase<bool>(
  1450. Header() + "%main = OpFunction %void None %void_func\n" +
  1451. "%main_lab = OpLabel\n" +
  1452. "%n = OpVariable %_ptr_float Function\n" +
  1453. "%ld = OpLoad %float %n\n" +
  1454. "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
  1455. "%2 = OpFOrdLessThanEqual %bool %float_0 %clamp\n" +
  1456. "OpReturn\n" +
  1457. "OpFunctionEnd",
  1458. 2, true),
  1459. // Test case 5: fold 0.0 <= clamp(n, -1.0, -1.0)
  1460. InstructionFoldingCase<bool>(
  1461. Header() + "%main = OpFunction %void None %void_func\n" +
  1462. "%main_lab = OpLabel\n" +
  1463. "%n = OpVariable %_ptr_float Function\n" +
  1464. "%ld = OpLoad %float %n\n" +
  1465. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_n1\n" +
  1466. "%2 = OpFOrdLessThanEqual %bool %float_0 %clamp\n" +
  1467. "OpReturn\n" +
  1468. "OpFunctionEnd",
  1469. 2, false),
  1470. // Test case 6: fold 0.0 < clamp(n, 1, 2)
  1471. InstructionFoldingCase<bool>(
  1472. Header() + "%main = OpFunction %void None %void_func\n" +
  1473. "%main_lab = OpLabel\n" +
  1474. "%n = OpVariable %_ptr_float Function\n" +
  1475. "%ld = OpLoad %float %n\n" +
  1476. "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
  1477. "%2 = OpFOrdLessThan %bool %float_0 %clamp\n" +
  1478. "OpReturn\n" +
  1479. "OpFunctionEnd",
  1480. 2, true),
  1481. // Test case 7: fold 0.0 < clamp(n, -1.0, 0.0)
  1482. InstructionFoldingCase<bool>(
  1483. Header() + "%main = OpFunction %void None %void_func\n" +
  1484. "%main_lab = OpLabel\n" +
  1485. "%n = OpVariable %_ptr_float Function\n" +
  1486. "%ld = OpLoad %float %n\n" +
  1487. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
  1488. "%2 = OpFOrdLessThan %bool %float_0 %clamp\n" +
  1489. "OpReturn\n" +
  1490. "OpFunctionEnd",
  1491. 2, false),
  1492. // Test case 8: fold 0.0 > clamp(n, 0.0, 1.0)
  1493. InstructionFoldingCase<bool>(
  1494. Header() + "%main = OpFunction %void None %void_func\n" +
  1495. "%main_lab = OpLabel\n" +
  1496. "%n = OpVariable %_ptr_float Function\n" +
  1497. "%ld = OpLoad %float %n\n" +
  1498. "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
  1499. "%2 = OpFUnordGreaterThan %bool %float_0 %clamp\n" +
  1500. "OpReturn\n" +
  1501. "OpFunctionEnd",
  1502. 2, false),
  1503. // Test case 9: fold 0.0 > clamp(n, -1.0, -1.0)
  1504. InstructionFoldingCase<bool>(
  1505. Header() + "%main = OpFunction %void None %void_func\n" +
  1506. "%main_lab = OpLabel\n" +
  1507. "%n = OpVariable %_ptr_float Function\n" +
  1508. "%ld = OpLoad %float %n\n" +
  1509. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_n1\n" +
  1510. "%2 = OpFUnordGreaterThan %bool %float_0 %clamp\n" +
  1511. "OpReturn\n" +
  1512. "OpFunctionEnd",
  1513. 2, true),
  1514. // Test case 10: fold 0.0 >= clamp(n, 1, 2)
  1515. InstructionFoldingCase<bool>(
  1516. Header() + "%main = OpFunction %void None %void_func\n" +
  1517. "%main_lab = OpLabel\n" +
  1518. "%n = OpVariable %_ptr_float Function\n" +
  1519. "%ld = OpLoad %float %n\n" +
  1520. "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
  1521. "%2 = OpFUnordGreaterThanEqual %bool %float_0 %clamp\n" +
  1522. "OpReturn\n" +
  1523. "OpFunctionEnd",
  1524. 2, false),
  1525. // Test case 11: fold 0.0 >= clamp(n, -1.0, 0.0)
  1526. InstructionFoldingCase<bool>(
  1527. Header() + "%main = OpFunction %void None %void_func\n" +
  1528. "%main_lab = OpLabel\n" +
  1529. "%n = OpVariable %_ptr_float Function\n" +
  1530. "%ld = OpLoad %float %n\n" +
  1531. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
  1532. "%2 = OpFUnordGreaterThanEqual %bool %float_0 %clamp\n" +
  1533. "OpReturn\n" +
  1534. "OpFunctionEnd",
  1535. 2, true),
  1536. // Test case 12: fold 0.0 <= clamp(n, 0.0, 1.0)
  1537. InstructionFoldingCase<bool>(
  1538. Header() + "%main = OpFunction %void None %void_func\n" +
  1539. "%main_lab = OpLabel\n" +
  1540. "%n = OpVariable %_ptr_float Function\n" +
  1541. "%ld = OpLoad %float %n\n" +
  1542. "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
  1543. "%2 = OpFUnordLessThanEqual %bool %float_0 %clamp\n" +
  1544. "OpReturn\n" +
  1545. "OpFunctionEnd",
  1546. 2, true),
  1547. // Test case 13: fold 0.0 <= clamp(n, -1.0, -1.0)
  1548. InstructionFoldingCase<bool>(
  1549. Header() + "%main = OpFunction %void None %void_func\n" +
  1550. "%main_lab = OpLabel\n" +
  1551. "%n = OpVariable %_ptr_float Function\n" +
  1552. "%ld = OpLoad %float %n\n" +
  1553. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_n1\n" +
  1554. "%2 = OpFUnordLessThanEqual %bool %float_0 %clamp\n" +
  1555. "OpReturn\n" +
  1556. "OpFunctionEnd",
  1557. 2, false),
  1558. // Test case 14: fold 0.0 < clamp(n, 1, 2)
  1559. InstructionFoldingCase<bool>(
  1560. Header() + "%main = OpFunction %void None %void_func\n" +
  1561. "%main_lab = OpLabel\n" +
  1562. "%n = OpVariable %_ptr_float Function\n" +
  1563. "%ld = OpLoad %float %n\n" +
  1564. "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
  1565. "%2 = OpFUnordLessThan %bool %float_0 %clamp\n" +
  1566. "OpReturn\n" +
  1567. "OpFunctionEnd",
  1568. 2, true),
  1569. // Test case 15: fold 0.0 < clamp(n, -1.0, 0.0)
  1570. InstructionFoldingCase<bool>(
  1571. Header() + "%main = OpFunction %void None %void_func\n" +
  1572. "%main_lab = OpLabel\n" +
  1573. "%n = OpVariable %_ptr_float Function\n" +
  1574. "%ld = OpLoad %float %n\n" +
  1575. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
  1576. "%2 = OpFUnordLessThan %bool %float_0 %clamp\n" +
  1577. "OpReturn\n" +
  1578. "OpFunctionEnd",
  1579. 2, false)
  1580. ));
  1581. INSTANTIATE_TEST_SUITE_P(FClampAndCmpRHS, BooleanInstructionFoldingTest,
  1582. ::testing::Values(
  1583. // Test case 0: fold clamp(n, 0.0, 1.0) > 1.0
  1584. InstructionFoldingCase<bool>(
  1585. Header() + "%main = OpFunction %void None %void_func\n" +
  1586. "%main_lab = OpLabel\n" +
  1587. "%n = OpVariable %_ptr_float Function\n" +
  1588. "%ld = OpLoad %float %n\n" +
  1589. "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
  1590. "%2 = OpFOrdGreaterThan %bool %clamp %float_1\n" +
  1591. "OpReturn\n" +
  1592. "OpFunctionEnd",
  1593. 2, false),
  1594. // Test case 1: fold clamp(n, 1.0, 1.0) > 0.0
  1595. InstructionFoldingCase<bool>(
  1596. Header() + "%main = OpFunction %void None %void_func\n" +
  1597. "%main_lab = OpLabel\n" +
  1598. "%n = OpVariable %_ptr_float Function\n" +
  1599. "%ld = OpLoad %float %n\n" +
  1600. "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_1\n" +
  1601. "%2 = OpFOrdGreaterThan %bool %clamp %float_0\n" +
  1602. "OpReturn\n" +
  1603. "OpFunctionEnd",
  1604. 2, true),
  1605. // Test case 2: fold clamp(n, 1, 2) >= 0.0
  1606. InstructionFoldingCase<bool>(
  1607. Header() + "%main = OpFunction %void None %void_func\n" +
  1608. "%main_lab = OpLabel\n" +
  1609. "%n = OpVariable %_ptr_float Function\n" +
  1610. "%ld = OpLoad %float %n\n" +
  1611. "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
  1612. "%2 = OpFOrdGreaterThanEqual %bool %clamp %float_0\n" +
  1613. "OpReturn\n" +
  1614. "OpFunctionEnd",
  1615. 2, true),
  1616. // Test case 3: fold clamp(n, 1.0, 2.0) >= 3.0
  1617. InstructionFoldingCase<bool>(
  1618. Header() + "%main = OpFunction %void None %void_func\n" +
  1619. "%main_lab = OpLabel\n" +
  1620. "%n = OpVariable %_ptr_float Function\n" +
  1621. "%ld = OpLoad %float %n\n" +
  1622. "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
  1623. "%2 = OpFOrdGreaterThanEqual %bool %clamp %float_3\n" +
  1624. "OpReturn\n" +
  1625. "OpFunctionEnd",
  1626. 2, false),
  1627. // Test case 4: fold clamp(n, 0.0, 1.0) <= 1.0
  1628. InstructionFoldingCase<bool>(
  1629. Header() + "%main = OpFunction %void None %void_func\n" +
  1630. "%main_lab = OpLabel\n" +
  1631. "%n = OpVariable %_ptr_float Function\n" +
  1632. "%ld = OpLoad %float %n\n" +
  1633. "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
  1634. "%2 = OpFOrdLessThanEqual %bool %clamp %float_1\n" +
  1635. "OpReturn\n" +
  1636. "OpFunctionEnd",
  1637. 2, true),
  1638. // Test case 5: fold clamp(n, 1.0, 2.0) <= 0.0
  1639. InstructionFoldingCase<bool>(
  1640. Header() + "%main = OpFunction %void None %void_func\n" +
  1641. "%main_lab = OpLabel\n" +
  1642. "%n = OpVariable %_ptr_float Function\n" +
  1643. "%ld = OpLoad %float %n\n" +
  1644. "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
  1645. "%2 = OpFOrdLessThanEqual %bool %clamp %float_0\n" +
  1646. "OpReturn\n" +
  1647. "OpFunctionEnd",
  1648. 2, false),
  1649. // Test case 6: fold clamp(n, 1, 2) < 3
  1650. InstructionFoldingCase<bool>(
  1651. Header() + "%main = OpFunction %void None %void_func\n" +
  1652. "%main_lab = OpLabel\n" +
  1653. "%n = OpVariable %_ptr_float Function\n" +
  1654. "%ld = OpLoad %float %n\n" +
  1655. "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
  1656. "%2 = OpFOrdLessThan %bool %clamp %float_3\n" +
  1657. "OpReturn\n" +
  1658. "OpFunctionEnd",
  1659. 2, true),
  1660. // Test case 7: fold clamp(n, -1.0, 0.0) < -1.0
  1661. InstructionFoldingCase<bool>(
  1662. Header() + "%main = OpFunction %void None %void_func\n" +
  1663. "%main_lab = OpLabel\n" +
  1664. "%n = OpVariable %_ptr_float Function\n" +
  1665. "%ld = OpLoad %float %n\n" +
  1666. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
  1667. "%2 = OpFOrdLessThan %bool %clamp %float_n1\n" +
  1668. "OpReturn\n" +
  1669. "OpFunctionEnd",
  1670. 2, false),
  1671. // Test case 8: fold clamp(n, 0.0, 1.0) > 1.0
  1672. InstructionFoldingCase<bool>(
  1673. Header() + "%main = OpFunction %void None %void_func\n" +
  1674. "%main_lab = OpLabel\n" +
  1675. "%n = OpVariable %_ptr_float Function\n" +
  1676. "%ld = OpLoad %float %n\n" +
  1677. "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
  1678. "%2 = OpFUnordGreaterThan %bool %clamp %float_1\n" +
  1679. "OpReturn\n" +
  1680. "OpFunctionEnd",
  1681. 2, false),
  1682. // Test case 9: fold clamp(n, 1.0, 2.0) > 0.0
  1683. InstructionFoldingCase<bool>(
  1684. Header() + "%main = OpFunction %void None %void_func\n" +
  1685. "%main_lab = OpLabel\n" +
  1686. "%n = OpVariable %_ptr_float Function\n" +
  1687. "%ld = OpLoad %float %n\n" +
  1688. "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
  1689. "%2 = OpFUnordGreaterThan %bool %clamp %float_0\n" +
  1690. "OpReturn\n" +
  1691. "OpFunctionEnd",
  1692. 2, true),
  1693. // Test case 10: fold clamp(n, 1, 2) >= 3.0
  1694. InstructionFoldingCase<bool>(
  1695. Header() + "%main = OpFunction %void None %void_func\n" +
  1696. "%main_lab = OpLabel\n" +
  1697. "%n = OpVariable %_ptr_float Function\n" +
  1698. "%ld = OpLoad %float %n\n" +
  1699. "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
  1700. "%2 = OpFUnordGreaterThanEqual %bool %clamp %float_3\n" +
  1701. "OpReturn\n" +
  1702. "OpFunctionEnd",
  1703. 2, false),
  1704. // Test case 11: fold clamp(n, -1.0, 0.0) >= -1.0
  1705. InstructionFoldingCase<bool>(
  1706. Header() + "%main = OpFunction %void None %void_func\n" +
  1707. "%main_lab = OpLabel\n" +
  1708. "%n = OpVariable %_ptr_float Function\n" +
  1709. "%ld = OpLoad %float %n\n" +
  1710. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
  1711. "%2 = OpFUnordGreaterThanEqual %bool %clamp %float_n1\n" +
  1712. "OpReturn\n" +
  1713. "OpFunctionEnd",
  1714. 2, true),
  1715. // Test case 12: fold clamp(n, 0.0, 1.0) <= 1.0
  1716. InstructionFoldingCase<bool>(
  1717. Header() + "%main = OpFunction %void None %void_func\n" +
  1718. "%main_lab = OpLabel\n" +
  1719. "%n = OpVariable %_ptr_float Function\n" +
  1720. "%ld = OpLoad %float %n\n" +
  1721. "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
  1722. "%2 = OpFUnordLessThanEqual %bool %clamp %float_1\n" +
  1723. "OpReturn\n" +
  1724. "OpFunctionEnd",
  1725. 2, true),
  1726. // Test case 13: fold clamp(n, 1.0, 1.0) <= 0.0
  1727. InstructionFoldingCase<bool>(
  1728. Header() + "%main = OpFunction %void None %void_func\n" +
  1729. "%main_lab = OpLabel\n" +
  1730. "%n = OpVariable %_ptr_float Function\n" +
  1731. "%ld = OpLoad %float %n\n" +
  1732. "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_1\n" +
  1733. "%2 = OpFUnordLessThanEqual %bool %clamp %float_0\n" +
  1734. "OpReturn\n" +
  1735. "OpFunctionEnd",
  1736. 2, false),
  1737. // Test case 14: fold clamp(n, 1, 2) < 3
  1738. InstructionFoldingCase<bool>(
  1739. Header() + "%main = OpFunction %void None %void_func\n" +
  1740. "%main_lab = OpLabel\n" +
  1741. "%n = OpVariable %_ptr_float Function\n" +
  1742. "%ld = OpLoad %float %n\n" +
  1743. "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
  1744. "%2 = OpFUnordLessThan %bool %clamp %float_3\n" +
  1745. "OpReturn\n" +
  1746. "OpFunctionEnd",
  1747. 2, true),
  1748. // Test case 15: fold clamp(n, -1.0, 0.0) < -1.0
  1749. InstructionFoldingCase<bool>(
  1750. Header() + "%main = OpFunction %void None %void_func\n" +
  1751. "%main_lab = OpLabel\n" +
  1752. "%n = OpVariable %_ptr_float Function\n" +
  1753. "%ld = OpLoad %float %n\n" +
  1754. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
  1755. "%2 = OpFUnordLessThan %bool %clamp %float_n1\n" +
  1756. "OpReturn\n" +
  1757. "OpFunctionEnd",
  1758. 2, false),
  1759. // Test case 16: fold clamp(n, -1.0, 0.0) < -1.0 (one test for double)
  1760. InstructionFoldingCase<bool>(
  1761. Header() + "%main = OpFunction %void None %void_func\n" +
  1762. "%main_lab = OpLabel\n" +
  1763. "%n = OpVariable %_ptr_double Function\n" +
  1764. "%ld = OpLoad %double %n\n" +
  1765. "%clamp = OpExtInst %double %1 FClamp %ld %double_n1 %double_0\n" +
  1766. "%2 = OpFUnordLessThan %bool %clamp %double_n1\n" +
  1767. "OpReturn\n" +
  1768. "OpFunctionEnd",
  1769. 2, false)
  1770. ));
  1771. // clang-format on
  1772. using FloatInstructionFoldingTest =
  1773. ::testing::TestWithParam<InstructionFoldingCase<float>>;
  1774. TEST_P(FloatInstructionFoldingTest, Case) {
  1775. const auto& tc = GetParam();
  1776. // Build module.
  1777. std::unique_ptr<IRContext> context =
  1778. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
  1779. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  1780. ASSERT_NE(nullptr, context);
  1781. // Fold the instruction to test.
  1782. analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
  1783. Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
  1784. bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
  1785. // Make sure the instruction folded as expected.
  1786. EXPECT_TRUE(succeeded);
  1787. if (inst != nullptr) {
  1788. EXPECT_EQ(inst->opcode(), spv::Op::OpCopyObject);
  1789. inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
  1790. EXPECT_EQ(inst->opcode(), spv::Op::OpConstant);
  1791. analysis::ConstantManager* const_mrg = context->get_constant_mgr();
  1792. const analysis::FloatConstant* result =
  1793. const_mrg->GetConstantFromInst(inst)->AsFloatConstant();
  1794. EXPECT_NE(result, nullptr);
  1795. if (result != nullptr) {
  1796. if (!std::isnan(tc.expected_result)) {
  1797. EXPECT_EQ(result->GetFloatValue(), tc.expected_result);
  1798. } else {
  1799. EXPECT_TRUE(std::isnan(result->GetFloatValue()));
  1800. }
  1801. }
  1802. }
  1803. }
  1804. // Not testing NaNs because there are no expectations concerning NaNs according
  1805. // to the "Precision and Operation of SPIR-V Instructions" section of the Vulkan
  1806. // specification.
  1807. // clang-format off
  1808. INSTANTIATE_TEST_SUITE_P(FloatConstantFoldingTest, FloatInstructionFoldingTest,
  1809. ::testing::Values(
  1810. // Test case 0: Fold 2.0 - 1.0
  1811. InstructionFoldingCase<float>(
  1812. Header() + "%main = OpFunction %void None %void_func\n" +
  1813. "%main_lab = OpLabel\n" +
  1814. "%2 = OpFSub %float %float_2 %float_1\n" +
  1815. "OpReturn\n" +
  1816. "OpFunctionEnd",
  1817. 2, 1.0),
  1818. // Test case 1: Fold 2.0 + 1.0
  1819. InstructionFoldingCase<float>(
  1820. Header() + "%main = OpFunction %void None %void_func\n" +
  1821. "%main_lab = OpLabel\n" +
  1822. "%2 = OpFAdd %float %float_2 %float_1\n" +
  1823. "OpReturn\n" +
  1824. "OpFunctionEnd",
  1825. 2, 3.0),
  1826. // Test case 2: Fold 3.0 * 2.0
  1827. InstructionFoldingCase<float>(
  1828. Header() + "%main = OpFunction %void None %void_func\n" +
  1829. "%main_lab = OpLabel\n" +
  1830. "%2 = OpFMul %float %float_3 %float_2\n" +
  1831. "OpReturn\n" +
  1832. "OpFunctionEnd",
  1833. 2, 6.0),
  1834. // Test case 3: Fold 1.0 / 2.0
  1835. InstructionFoldingCase<float>(
  1836. Header() + "%main = OpFunction %void None %void_func\n" +
  1837. "%main_lab = OpLabel\n" +
  1838. "%2 = OpFDiv %float %float_1 %float_2\n" +
  1839. "OpReturn\n" +
  1840. "OpFunctionEnd",
  1841. 2, 0.5),
  1842. // Test case 4: Fold 1.0 / 0.0
  1843. InstructionFoldingCase<float>(
  1844. Header() + "%main = OpFunction %void None %void_func\n" +
  1845. "%main_lab = OpLabel\n" +
  1846. "%2 = OpFDiv %float %float_1 %float_0\n" +
  1847. "OpReturn\n" +
  1848. "OpFunctionEnd",
  1849. 2, std::numeric_limits<float>::infinity()),
  1850. // Test case 5: Fold -1.0 / 0.0
  1851. InstructionFoldingCase<float>(
  1852. Header() + "%main = OpFunction %void None %void_func\n" +
  1853. "%main_lab = OpLabel\n" +
  1854. "%2 = OpFDiv %float %float_n1 %float_0\n" +
  1855. "OpReturn\n" +
  1856. "OpFunctionEnd",
  1857. 2, -std::numeric_limits<float>::infinity()),
  1858. // Test case 6: Fold (2.0, 3.0) dot (2.0, 0.5)
  1859. InstructionFoldingCase<float>(
  1860. Header() + "%main = OpFunction %void None %void_func\n" +
  1861. "%main_lab = OpLabel\n" +
  1862. "%2 = OpDot %float %v2float_2_3 %v2float_2_0p5\n" +
  1863. "OpReturn\n" +
  1864. "OpFunctionEnd",
  1865. 2, 5.5f),
  1866. // Test case 7: Fold (0.0, 0.0) dot v
  1867. InstructionFoldingCase<float>(
  1868. Header() + "%main = OpFunction %void None %void_func\n" +
  1869. "%main_lab = OpLabel\n" +
  1870. "%v = OpVariable %_ptr_v2float Function\n" +
  1871. "%2 = OpLoad %v2float %v\n" +
  1872. "%3 = OpDot %float %v2float_0_0 %2\n" +
  1873. "OpReturn\n" +
  1874. "OpFunctionEnd",
  1875. 3, 0.0f),
  1876. // Test case 8: Fold v dot (0.0, 0.0)
  1877. InstructionFoldingCase<float>(
  1878. Header() + "%main = OpFunction %void None %void_func\n" +
  1879. "%main_lab = OpLabel\n" +
  1880. "%v = OpVariable %_ptr_v2float Function\n" +
  1881. "%2 = OpLoad %v2float %v\n" +
  1882. "%3 = OpDot %float %2 %v2float_0_0\n" +
  1883. "OpReturn\n" +
  1884. "OpFunctionEnd",
  1885. 3, 0.0f),
  1886. // Test case 9: Fold Null dot v
  1887. InstructionFoldingCase<float>(
  1888. Header() + "%main = OpFunction %void None %void_func\n" +
  1889. "%main_lab = OpLabel\n" +
  1890. "%v = OpVariable %_ptr_v2float Function\n" +
  1891. "%2 = OpLoad %v2float %v\n" +
  1892. "%3 = OpDot %float %v2float_null %2\n" +
  1893. "OpReturn\n" +
  1894. "OpFunctionEnd",
  1895. 3, 0.0f),
  1896. // Test case 10: Fold v dot Null
  1897. InstructionFoldingCase<float>(
  1898. Header() + "%main = OpFunction %void None %void_func\n" +
  1899. "%main_lab = OpLabel\n" +
  1900. "%v = OpVariable %_ptr_v2float Function\n" +
  1901. "%2 = OpLoad %v2float %v\n" +
  1902. "%3 = OpDot %float %2 %v2float_null\n" +
  1903. "OpReturn\n" +
  1904. "OpFunctionEnd",
  1905. 3, 0.0f),
  1906. // Test case 11: Fold -2.0
  1907. InstructionFoldingCase<float>(
  1908. Header() + "%main = OpFunction %void None %void_func\n" +
  1909. "%main_lab = OpLabel\n" +
  1910. "%2 = OpFNegate %float %float_2\n" +
  1911. "OpReturn\n" +
  1912. "OpFunctionEnd",
  1913. 2, -2),
  1914. // Test case 12: QuantizeToF16 1.0
  1915. InstructionFoldingCase<float>(
  1916. Header() + "%main = OpFunction %void None %void_func\n" +
  1917. "%main_lab = OpLabel\n" +
  1918. "%2 = OpQuantizeToF16 %float %float_1\n" +
  1919. "OpReturn\n" +
  1920. "OpFunctionEnd",
  1921. 2, 1.0),
  1922. // Test case 13: QuantizeToF16 positive non exact
  1923. InstructionFoldingCase<float>(
  1924. Header() + "%main = OpFunction %void None %void_func\n" +
  1925. "%main_lab = OpLabel\n" +
  1926. "%2 = OpQuantizeToF16 %float %float_2049\n" +
  1927. "OpReturn\n" +
  1928. "OpFunctionEnd",
  1929. 2, 2048),
  1930. // Test case 14: QuantizeToF16 negative non exact
  1931. InstructionFoldingCase<float>(
  1932. Header() + "%main = OpFunction %void None %void_func\n" +
  1933. "%main_lab = OpLabel\n" +
  1934. "%2 = OpQuantizeToF16 %float %float_n2049\n" +
  1935. "OpReturn\n" +
  1936. "OpFunctionEnd",
  1937. 2, -2048),
  1938. // Test case 15: QuantizeToF16 large positive
  1939. InstructionFoldingCase<float>(
  1940. Header() + "%main = OpFunction %void None %void_func\n" +
  1941. "%main_lab = OpLabel\n" +
  1942. "%2 = OpQuantizeToF16 %float %float_1e16\n" +
  1943. "OpReturn\n" +
  1944. "OpFunctionEnd",
  1945. 2, std::numeric_limits<float>::infinity()),
  1946. // Test case 16: QuantizeToF16 large negative
  1947. InstructionFoldingCase<float>(
  1948. Header() + "%main = OpFunction %void None %void_func\n" +
  1949. "%main_lab = OpLabel\n" +
  1950. "%2 = OpQuantizeToF16 %float %float_n1e16\n" +
  1951. "OpReturn\n" +
  1952. "OpFunctionEnd",
  1953. 2, -std::numeric_limits<float>::infinity()),
  1954. // Test case 17: QuantizeToF16 small positive
  1955. InstructionFoldingCase<float>(
  1956. Header() + "%main = OpFunction %void None %void_func\n" +
  1957. "%main_lab = OpLabel\n" +
  1958. "%2 = OpQuantizeToF16 %float %float_1en16\n" +
  1959. "OpReturn\n" +
  1960. "OpFunctionEnd",
  1961. 2, 0.0),
  1962. // Test case 18: QuantizeToF16 small negative
  1963. InstructionFoldingCase<float>(
  1964. Header() + "%main = OpFunction %void None %void_func\n" +
  1965. "%main_lab = OpLabel\n" +
  1966. "%2 = OpQuantizeToF16 %float %float_n1en16\n" +
  1967. "OpReturn\n" +
  1968. "OpFunctionEnd",
  1969. 2, 0.0),
  1970. // Test case 19: QuantizeToF16 nan
  1971. InstructionFoldingCase<float>(
  1972. HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
  1973. "%main_lab = OpLabel\n" +
  1974. "%2 = OpQuantizeToF16 %float %float_nan\n" +
  1975. "OpReturn\n" +
  1976. "OpFunctionEnd",
  1977. 2, std::numeric_limits<float>::quiet_NaN()),
  1978. // Test case 20: FMix 1.0 4.0 0.2
  1979. InstructionFoldingCase<float>(
  1980. Header() + "%main = OpFunction %void None %void_func\n" +
  1981. "%main_lab = OpLabel\n" +
  1982. "%2 = OpExtInst %float %1 FMix %float_1 %float_4 %float_0p2\n" +
  1983. "OpReturn\n" +
  1984. "OpFunctionEnd",
  1985. 2, 1.6f),
  1986. // Test case 21: FMin 1.0 4.0
  1987. InstructionFoldingCase<float>(
  1988. Header() + "%main = OpFunction %void None %void_func\n" +
  1989. "%main_lab = OpLabel\n" +
  1990. "%2 = OpExtInst %float %1 FMin %float_1 %float_4\n" +
  1991. "OpReturn\n" +
  1992. "OpFunctionEnd",
  1993. 2, 1.0f),
  1994. // Test case 22: FMin 4.0 0.2
  1995. InstructionFoldingCase<float>(
  1996. Header() + "%main = OpFunction %void None %void_func\n" +
  1997. "%main_lab = OpLabel\n" +
  1998. "%2 = OpExtInst %float %1 FMin %float_4 %float_0p2\n" +
  1999. "OpReturn\n" +
  2000. "OpFunctionEnd",
  2001. 2, 0.2f),
  2002. // Test case 23: FMax 1.0 4.0
  2003. InstructionFoldingCase<float>(
  2004. Header() + "%main = OpFunction %void None %void_func\n" +
  2005. "%main_lab = OpLabel\n" +
  2006. "%2 = OpExtInst %float %1 FMax %float_1 %float_4\n" +
  2007. "OpReturn\n" +
  2008. "OpFunctionEnd",
  2009. 2, 4.0f),
  2010. // Test case 24: FMax 1.0 0.2
  2011. InstructionFoldingCase<float>(
  2012. Header() + "%main = OpFunction %void None %void_func\n" +
  2013. "%main_lab = OpLabel\n" +
  2014. "%2 = OpExtInst %float %1 FMax %float_1 %float_0p2\n" +
  2015. "OpReturn\n" +
  2016. "OpFunctionEnd",
  2017. 2, 1.0f),
  2018. // Test case 25: FClamp 1.0 0.2 4.0
  2019. InstructionFoldingCase<float>(
  2020. Header() + "%main = OpFunction %void None %void_func\n" +
  2021. "%main_lab = OpLabel\n" +
  2022. "%2 = OpExtInst %float %1 FClamp %float_1 %float_0p2 %float_4\n" +
  2023. "OpReturn\n" +
  2024. "OpFunctionEnd",
  2025. 2, 1.0f),
  2026. // Test case 26: FClamp 0.2 2.0 4.0
  2027. InstructionFoldingCase<float>(
  2028. Header() + "%main = OpFunction %void None %void_func\n" +
  2029. "%main_lab = OpLabel\n" +
  2030. "%2 = OpExtInst %float %1 FClamp %float_0p2 %float_2 %float_4\n" +
  2031. "OpReturn\n" +
  2032. "OpFunctionEnd",
  2033. 2, 2.0f),
  2034. // Test case 27: FClamp 2049.0 2.0 4.0
  2035. InstructionFoldingCase<float>(
  2036. Header() + "%main = OpFunction %void None %void_func\n" +
  2037. "%main_lab = OpLabel\n" +
  2038. "%2 = OpExtInst %float %1 FClamp %float_2049 %float_2 %float_4\n" +
  2039. "OpReturn\n" +
  2040. "OpFunctionEnd",
  2041. 2, 4.0f),
  2042. // Test case 28: FClamp 1.0 2.0 x
  2043. InstructionFoldingCase<float>(
  2044. Header() + "%main = OpFunction %void None %void_func\n" +
  2045. "%main_lab = OpLabel\n" +
  2046. "%undef = OpUndef %float\n" +
  2047. "%2 = OpExtInst %float %1 FClamp %float_1 %float_2 %undef\n" +
  2048. "OpReturn\n" +
  2049. "OpFunctionEnd",
  2050. 2, 2.0),
  2051. // Test case 29: FClamp 1.0 x 0.5
  2052. InstructionFoldingCase<float>(
  2053. Header() + "%main = OpFunction %void None %void_func\n" +
  2054. "%main_lab = OpLabel\n" +
  2055. "%undef = OpUndef %float\n" +
  2056. "%2 = OpExtInst %float %1 FClamp %float_1 %undef %float_0p5\n" +
  2057. "OpReturn\n" +
  2058. "OpFunctionEnd",
  2059. 2, 0.5),
  2060. // Test case 30: Sin 0.0
  2061. InstructionFoldingCase<float>(
  2062. Header() + "%main = OpFunction %void None %void_func\n" +
  2063. "%main_lab = OpLabel\n" +
  2064. "%2 = OpExtInst %float %1 Sin %float_0\n" +
  2065. "OpReturn\n" +
  2066. "OpFunctionEnd",
  2067. 2, 0.0),
  2068. // Test case 31: Cos 0.0
  2069. InstructionFoldingCase<float>(
  2070. Header() + "%main = OpFunction %void None %void_func\n" +
  2071. "%main_lab = OpLabel\n" +
  2072. "%2 = OpExtInst %float %1 Cos %float_0\n" +
  2073. "OpReturn\n" +
  2074. "OpFunctionEnd",
  2075. 2, 1.0),
  2076. // Test case 32: Tan 0.0
  2077. InstructionFoldingCase<float>(
  2078. Header() + "%main = OpFunction %void None %void_func\n" +
  2079. "%main_lab = OpLabel\n" +
  2080. "%2 = OpExtInst %float %1 Tan %float_0\n" +
  2081. "OpReturn\n" +
  2082. "OpFunctionEnd",
  2083. 2, 0.0),
  2084. // Test case 33: Asin 0.0
  2085. InstructionFoldingCase<float>(
  2086. Header() + "%main = OpFunction %void None %void_func\n" +
  2087. "%main_lab = OpLabel\n" +
  2088. "%2 = OpExtInst %float %1 Asin %float_0\n" +
  2089. "OpReturn\n" +
  2090. "OpFunctionEnd",
  2091. 2, 0.0),
  2092. // Test case 34: Acos 1.0
  2093. InstructionFoldingCase<float>(
  2094. Header() + "%main = OpFunction %void None %void_func\n" +
  2095. "%main_lab = OpLabel\n" +
  2096. "%2 = OpExtInst %float %1 Acos %float_1\n" +
  2097. "OpReturn\n" +
  2098. "OpFunctionEnd",
  2099. 2, 0.0),
  2100. // Test case 35: Atan 0.0
  2101. InstructionFoldingCase<float>(
  2102. Header() + "%main = OpFunction %void None %void_func\n" +
  2103. "%main_lab = OpLabel\n" +
  2104. "%2 = OpExtInst %float %1 Atan %float_0\n" +
  2105. "OpReturn\n" +
  2106. "OpFunctionEnd",
  2107. 2, 0.0),
  2108. // Test case 36: Exp 0.0
  2109. InstructionFoldingCase<float>(
  2110. Header() + "%main = OpFunction %void None %void_func\n" +
  2111. "%main_lab = OpLabel\n" +
  2112. "%2 = OpExtInst %float %1 Exp %float_0\n" +
  2113. "OpReturn\n" +
  2114. "OpFunctionEnd",
  2115. 2, 1.0),
  2116. // Test case 37: Log 1.0
  2117. InstructionFoldingCase<float>(
  2118. Header() + "%main = OpFunction %void None %void_func\n" +
  2119. "%main_lab = OpLabel\n" +
  2120. "%2 = OpExtInst %float %1 Log %float_1\n" +
  2121. "OpReturn\n" +
  2122. "OpFunctionEnd",
  2123. 2, 0.0),
  2124. // Test case 38: Exp2 2.0
  2125. InstructionFoldingCase<float>(
  2126. Header() + "%main = OpFunction %void None %void_func\n" +
  2127. "%main_lab = OpLabel\n" +
  2128. "%2 = OpExtInst %float %1 Exp2 %float_2\n" +
  2129. "OpReturn\n" +
  2130. "OpFunctionEnd",
  2131. 2, 4.0),
  2132. // Test case 39: Log2 4.0
  2133. InstructionFoldingCase<float>(
  2134. Header() + "%main = OpFunction %void None %void_func\n" +
  2135. "%main_lab = OpLabel\n" +
  2136. "%2 = OpExtInst %float %1 Log2 %float_4\n" +
  2137. "OpReturn\n" +
  2138. "OpFunctionEnd",
  2139. 2, 2.0),
  2140. // Test case 40: Sqrt 4.0
  2141. InstructionFoldingCase<float>(
  2142. Header() + "%main = OpFunction %void None %void_func\n" +
  2143. "%main_lab = OpLabel\n" +
  2144. "%2 = OpExtInst %float %1 Sqrt %float_4\n" +
  2145. "OpReturn\n" +
  2146. "OpFunctionEnd",
  2147. 2, 2.0),
  2148. // Test case 41: Atan2 0.0 1.0
  2149. InstructionFoldingCase<float>(
  2150. Header() + "%main = OpFunction %void None %void_func\n" +
  2151. "%main_lab = OpLabel\n" +
  2152. "%2 = OpExtInst %float %1 Atan2 %float_0 %float_1\n" +
  2153. "OpReturn\n" +
  2154. "OpFunctionEnd",
  2155. 2, 0.0),
  2156. // Test case 42: Pow 2.0 3.0
  2157. InstructionFoldingCase<float>(
  2158. Header() + "%main = OpFunction %void None %void_func\n" +
  2159. "%main_lab = OpLabel\n" +
  2160. "%2 = OpExtInst %float %1 Pow %float_2 %float_3\n" +
  2161. "OpReturn\n" +
  2162. "OpFunctionEnd",
  2163. 2, 8.0),
  2164. // Test case 43: Fold 1.0 / -0.0.
  2165. InstructionFoldingCase<float>(
  2166. Header() + "%main = OpFunction %void None %void_func\n" +
  2167. "%main_lab = OpLabel\n" +
  2168. "%2 = OpFDiv %float %float_1 %float_n0\n" +
  2169. "OpReturn\n" +
  2170. "OpFunctionEnd",
  2171. 2, -std::numeric_limits<float>::infinity()),
  2172. // Test case 44: Fold -1.0 / -0.0
  2173. InstructionFoldingCase<float>(
  2174. Header() + "%main = OpFunction %void None %void_func\n" +
  2175. "%main_lab = OpLabel\n" +
  2176. "%2 = OpFDiv %float %float_n1 %float_n0\n" +
  2177. "OpReturn\n" +
  2178. "OpFunctionEnd",
  2179. 2, std::numeric_limits<float>::infinity()),
  2180. // Test case 45: Fold 0.0 / 0.0
  2181. InstructionFoldingCase<float>(
  2182. Header() + "%main = OpFunction %void None %void_func\n" +
  2183. "%main_lab = OpLabel\n" +
  2184. "%2 = OpFDiv %float %float_0 %float_0\n" +
  2185. "OpReturn\n" +
  2186. "OpFunctionEnd",
  2187. 2, std::numeric_limits<float>::quiet_NaN()),
  2188. // Test case 46: Fold 0.0 / -0.0
  2189. InstructionFoldingCase<float>(
  2190. Header() + "%main = OpFunction %void None %void_func\n" +
  2191. "%main_lab = OpLabel\n" +
  2192. "%2 = OpFDiv %float %float_0 %float_n0\n" +
  2193. "OpReturn\n" +
  2194. "OpFunctionEnd",
  2195. 2, std::numeric_limits<float>::quiet_NaN())
  2196. ));
  2197. // clang-format on
  2198. using DoubleInstructionFoldingTest =
  2199. ::testing::TestWithParam<InstructionFoldingCase<double>>;
  2200. TEST_P(DoubleInstructionFoldingTest, Case) {
  2201. const auto& tc = GetParam();
  2202. // Build module.
  2203. std::unique_ptr<IRContext> context =
  2204. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
  2205. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  2206. ASSERT_NE(nullptr, context);
  2207. // Fold the instruction to test.
  2208. analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
  2209. Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
  2210. bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
  2211. // Make sure the instruction folded as expected.
  2212. EXPECT_TRUE(succeeded);
  2213. if (inst != nullptr) {
  2214. EXPECT_EQ(inst->opcode(), spv::Op::OpCopyObject);
  2215. inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
  2216. EXPECT_EQ(inst->opcode(), spv::Op::OpConstant);
  2217. analysis::ConstantManager* const_mrg = context->get_constant_mgr();
  2218. const analysis::FloatConstant* result =
  2219. const_mrg->GetConstantFromInst(inst)->AsFloatConstant();
  2220. EXPECT_NE(result, nullptr);
  2221. if (result != nullptr) {
  2222. if (!std::isnan(tc.expected_result)) {
  2223. EXPECT_EQ(result->GetDoubleValue(), tc.expected_result);
  2224. } else {
  2225. EXPECT_TRUE(std::isnan(result->GetDoubleValue()));
  2226. }
  2227. }
  2228. }
  2229. }
  2230. // clang-format off
  2231. INSTANTIATE_TEST_SUITE_P(DoubleConstantFoldingTest, DoubleInstructionFoldingTest,
  2232. ::testing::Values(
  2233. // Test case 0: Fold 2.0 - 1.0
  2234. InstructionFoldingCase<double>(
  2235. Header() + "%main = OpFunction %void None %void_func\n" +
  2236. "%main_lab = OpLabel\n" +
  2237. "%2 = OpFSub %double %double_2 %double_1\n" +
  2238. "OpReturn\n" +
  2239. "OpFunctionEnd",
  2240. 2, 1.0),
  2241. // Test case 1: Fold 2.0 + 1.0
  2242. InstructionFoldingCase<double>(
  2243. Header() + "%main = OpFunction %void None %void_func\n" +
  2244. "%main_lab = OpLabel\n" +
  2245. "%2 = OpFAdd %double %double_2 %double_1\n" +
  2246. "OpReturn\n" +
  2247. "OpFunctionEnd",
  2248. 2, 3.0),
  2249. // Test case 2: Fold 3.0 * 2.0
  2250. InstructionFoldingCase<double>(
  2251. Header() + "%main = OpFunction %void None %void_func\n" +
  2252. "%main_lab = OpLabel\n" +
  2253. "%2 = OpFMul %double %double_3 %double_2\n" +
  2254. "OpReturn\n" +
  2255. "OpFunctionEnd",
  2256. 2, 6.0),
  2257. // Test case 3: Fold 1.0 / 2.0
  2258. InstructionFoldingCase<double>(
  2259. Header() + "%main = OpFunction %void None %void_func\n" +
  2260. "%main_lab = OpLabel\n" +
  2261. "%2 = OpFDiv %double %double_1 %double_2\n" +
  2262. "OpReturn\n" +
  2263. "OpFunctionEnd",
  2264. 2, 0.5),
  2265. // Test case 4: Fold 1.0 / 0.0
  2266. InstructionFoldingCase<double>(
  2267. Header() + "%main = OpFunction %void None %void_func\n" +
  2268. "%main_lab = OpLabel\n" +
  2269. "%2 = OpFDiv %double %double_1 %double_0\n" +
  2270. "OpReturn\n" +
  2271. "OpFunctionEnd",
  2272. 2, std::numeric_limits<double>::infinity()),
  2273. // Test case 5: Fold -1.0 / 0.0
  2274. InstructionFoldingCase<double>(
  2275. Header() + "%main = OpFunction %void None %void_func\n" +
  2276. "%main_lab = OpLabel\n" +
  2277. "%2 = OpFDiv %double %double_n1 %double_0\n" +
  2278. "OpReturn\n" +
  2279. "OpFunctionEnd",
  2280. 2, -std::numeric_limits<double>::infinity()),
  2281. // Test case 6: Fold (2.0, 3.0) dot (2.0, 0.5)
  2282. InstructionFoldingCase<double>(
  2283. Header() + "%main = OpFunction %void None %void_func\n" +
  2284. "%main_lab = OpLabel\n" +
  2285. "%2 = OpDot %double %v2double_2_3 %v2double_2_0p5\n" +
  2286. "OpReturn\n" +
  2287. "OpFunctionEnd",
  2288. 2, 5.5f),
  2289. // Test case 7: Fold (0.0, 0.0) dot v
  2290. InstructionFoldingCase<double>(
  2291. Header() + "%main = OpFunction %void None %void_func\n" +
  2292. "%main_lab = OpLabel\n" +
  2293. "%v = OpVariable %_ptr_v2double Function\n" +
  2294. "%2 = OpLoad %v2double %v\n" +
  2295. "%3 = OpDot %double %v2double_0_0 %2\n" +
  2296. "OpReturn\n" +
  2297. "OpFunctionEnd",
  2298. 3, 0.0f),
  2299. // Test case 8: Fold v dot (0.0, 0.0)
  2300. InstructionFoldingCase<double>(
  2301. Header() + "%main = OpFunction %void None %void_func\n" +
  2302. "%main_lab = OpLabel\n" +
  2303. "%v = OpVariable %_ptr_v2double Function\n" +
  2304. "%2 = OpLoad %v2double %v\n" +
  2305. "%3 = OpDot %double %2 %v2double_0_0\n" +
  2306. "OpReturn\n" +
  2307. "OpFunctionEnd",
  2308. 3, 0.0f),
  2309. // Test case 9: Fold Null dot v
  2310. InstructionFoldingCase<double>(
  2311. Header() + "%main = OpFunction %void None %void_func\n" +
  2312. "%main_lab = OpLabel\n" +
  2313. "%v = OpVariable %_ptr_v2double Function\n" +
  2314. "%2 = OpLoad %v2double %v\n" +
  2315. "%3 = OpDot %double %v2double_null %2\n" +
  2316. "OpReturn\n" +
  2317. "OpFunctionEnd",
  2318. 3, 0.0f),
  2319. // Test case 10: Fold v dot Null
  2320. InstructionFoldingCase<double>(
  2321. Header() + "%main = OpFunction %void None %void_func\n" +
  2322. "%main_lab = OpLabel\n" +
  2323. "%v = OpVariable %_ptr_v2double Function\n" +
  2324. "%2 = OpLoad %v2double %v\n" +
  2325. "%3 = OpDot %double %2 %v2double_null\n" +
  2326. "OpReturn\n" +
  2327. "OpFunctionEnd",
  2328. 3, 0.0f),
  2329. // Test case 11: Fold -2.0
  2330. InstructionFoldingCase<double>(
  2331. Header() + "%main = OpFunction %void None %void_func\n" +
  2332. "%main_lab = OpLabel\n" +
  2333. "%2 = OpFNegate %double %double_2\n" +
  2334. "OpReturn\n" +
  2335. "OpFunctionEnd",
  2336. 2, -2),
  2337. // Test case 12: FMin 1.0 4.0
  2338. InstructionFoldingCase<double>(
  2339. Header() + "%main = OpFunction %void None %void_func\n" +
  2340. "%main_lab = OpLabel\n" +
  2341. "%2 = OpExtInst %double %1 FMin %double_1 %double_4\n" +
  2342. "OpReturn\n" +
  2343. "OpFunctionEnd",
  2344. 2, 1.0),
  2345. // Test case 13: FMin 4.0 0.2
  2346. InstructionFoldingCase<double>(
  2347. Header() + "%main = OpFunction %void None %void_func\n" +
  2348. "%main_lab = OpLabel\n" +
  2349. "%2 = OpExtInst %double %1 FMin %double_4 %double_0p2\n" +
  2350. "OpReturn\n" +
  2351. "OpFunctionEnd",
  2352. 2, 0.2),
  2353. // Test case 14: FMax 1.0 4.0
  2354. InstructionFoldingCase<double>(
  2355. Header() + "%main = OpFunction %void None %void_func\n" +
  2356. "%main_lab = OpLabel\n" +
  2357. "%2 = OpExtInst %double %1 FMax %double_1 %double_4\n" +
  2358. "OpReturn\n" +
  2359. "OpFunctionEnd",
  2360. 2, 4.0),
  2361. // Test case 15: FMax 1.0 0.2
  2362. InstructionFoldingCase<double>(
  2363. Header() + "%main = OpFunction %void None %void_func\n" +
  2364. "%main_lab = OpLabel\n" +
  2365. "%2 = OpExtInst %double %1 FMax %double_1 %double_0p2\n" +
  2366. "OpReturn\n" +
  2367. "OpFunctionEnd",
  2368. 2, 1.0),
  2369. // Test case 16: FClamp 1.0 0.2 4.0
  2370. InstructionFoldingCase<double>(
  2371. Header() + "%main = OpFunction %void None %void_func\n" +
  2372. "%main_lab = OpLabel\n" +
  2373. "%2 = OpExtInst %double %1 FClamp %double_1 %double_0p2 %double_4\n" +
  2374. "OpReturn\n" +
  2375. "OpFunctionEnd",
  2376. 2, 1.0),
  2377. // Test case 17: FClamp 0.2 2.0 4.0
  2378. InstructionFoldingCase<double>(
  2379. Header() + "%main = OpFunction %void None %void_func\n" +
  2380. "%main_lab = OpLabel\n" +
  2381. "%2 = OpExtInst %double %1 FClamp %double_0p2 %double_2 %double_4\n" +
  2382. "OpReturn\n" +
  2383. "OpFunctionEnd",
  2384. 2, 2.0),
  2385. // Test case 18: FClamp 5.0 2.0 4.0
  2386. InstructionFoldingCase<double>(
  2387. Header() + "%main = OpFunction %void None %void_func\n" +
  2388. "%main_lab = OpLabel\n" +
  2389. "%2 = OpExtInst %double %1 FClamp %double_5 %double_2 %double_4\n" +
  2390. "OpReturn\n" +
  2391. "OpFunctionEnd",
  2392. 2, 4.0),
  2393. // Test case 19: FClamp 1.0 2.0 x
  2394. InstructionFoldingCase<double>(
  2395. Header() + "%main = OpFunction %void None %void_func\n" +
  2396. "%main_lab = OpLabel\n" +
  2397. "%undef = OpUndef %double\n" +
  2398. "%2 = OpExtInst %double %1 FClamp %double_1 %double_2 %undef\n" +
  2399. "OpReturn\n" +
  2400. "OpFunctionEnd",
  2401. 2, 2.0),
  2402. // Test case 20: FClamp 1.0 x 0.5
  2403. InstructionFoldingCase<double>(
  2404. Header() + "%main = OpFunction %void None %void_func\n" +
  2405. "%main_lab = OpLabel\n" +
  2406. "%undef = OpUndef %double\n" +
  2407. "%2 = OpExtInst %double %1 FClamp %double_1 %undef %double_0p5\n" +
  2408. "OpReturn\n" +
  2409. "OpFunctionEnd",
  2410. 2, 0.5),
  2411. // Test case 21: Sqrt 4.0
  2412. InstructionFoldingCase<double>(
  2413. Header() + "%main = OpFunction %void None %void_func\n" +
  2414. "%main_lab = OpLabel\n" +
  2415. "%undef = OpUndef %double\n" +
  2416. "%2 = OpExtInst %double %1 Sqrt %double_4\n" +
  2417. "OpReturn\n" +
  2418. "OpFunctionEnd",
  2419. 2, 2.0),
  2420. // Test case 22: Pow 2.0 3.0
  2421. InstructionFoldingCase<double>(
  2422. Header() + "%main = OpFunction %void None %void_func\n" +
  2423. "%main_lab = OpLabel\n" +
  2424. "%undef = OpUndef %double\n" +
  2425. "%2 = OpExtInst %double %1 Pow %double_2 %double_3\n" +
  2426. "OpReturn\n" +
  2427. "OpFunctionEnd",
  2428. 2, 8.0),
  2429. // Test case 23: Fold 1.0 / -0.0.
  2430. InstructionFoldingCase<double>(
  2431. Header() + "%main = OpFunction %void None %void_func\n" +
  2432. "%main_lab = OpLabel\n" +
  2433. "%2 = OpFDiv %double %double_1 %double_n0\n" +
  2434. "OpReturn\n" +
  2435. "OpFunctionEnd",
  2436. 2, -std::numeric_limits<double>::infinity()),
  2437. // Test case 24: Fold -1.0 / -0.0
  2438. InstructionFoldingCase<double>(
  2439. Header() + "%main = OpFunction %void None %void_func\n" +
  2440. "%main_lab = OpLabel\n" +
  2441. "%2 = OpFDiv %double %double_n1 %double_n0\n" +
  2442. "OpReturn\n" +
  2443. "OpFunctionEnd",
  2444. 2, std::numeric_limits<double>::infinity()),
  2445. // Test case 25: Fold 0.0 / 0.0
  2446. InstructionFoldingCase<double>(
  2447. Header() + "%main = OpFunction %void None %void_func\n" +
  2448. "%main_lab = OpLabel\n" +
  2449. "%2 = OpFDiv %double %double_0 %double_0\n" +
  2450. "OpReturn\n" +
  2451. "OpFunctionEnd",
  2452. 2, std::numeric_limits<double>::quiet_NaN()),
  2453. // Test case 26: Fold 0.0 / -0.0
  2454. InstructionFoldingCase<double>(
  2455. Header() + "%main = OpFunction %void None %void_func\n" +
  2456. "%main_lab = OpLabel\n" +
  2457. "%2 = OpFDiv %double %double_0 %double_n0\n" +
  2458. "OpReturn\n" +
  2459. "OpFunctionEnd",
  2460. 2, std::numeric_limits<double>::quiet_NaN())
  2461. ));
  2462. // clang-format on
  2463. // clang-format off
  2464. INSTANTIATE_TEST_SUITE_P(DoubleOrderedCompareConstantFoldingTest, BooleanInstructionFoldingTest,
  2465. ::testing::Values(
  2466. // Test case 0: fold 1.0 == 2.0
  2467. InstructionFoldingCase<bool>(
  2468. Header() + "%main = OpFunction %void None %void_func\n" +
  2469. "%main_lab = OpLabel\n" +
  2470. "%2 = OpFOrdEqual %bool %double_1 %double_2\n" +
  2471. "OpReturn\n" +
  2472. "OpFunctionEnd",
  2473. 2, false),
  2474. // Test case 1: fold 1.0 != 2.0
  2475. InstructionFoldingCase<bool>(
  2476. Header() + "%main = OpFunction %void None %void_func\n" +
  2477. "%main_lab = OpLabel\n" +
  2478. "%2 = OpFOrdNotEqual %bool %double_1 %double_2\n" +
  2479. "OpReturn\n" +
  2480. "OpFunctionEnd",
  2481. 2, true),
  2482. // Test case 2: fold 1.0 < 2.0
  2483. InstructionFoldingCase<bool>(
  2484. Header() + "%main = OpFunction %void None %void_func\n" +
  2485. "%main_lab = OpLabel\n" +
  2486. "%2 = OpFOrdLessThan %bool %double_1 %double_2\n" +
  2487. "OpReturn\n" +
  2488. "OpFunctionEnd",
  2489. 2, true),
  2490. // Test case 3: fold 1.0 > 2.0
  2491. InstructionFoldingCase<bool>(
  2492. Header() + "%main = OpFunction %void None %void_func\n" +
  2493. "%main_lab = OpLabel\n" +
  2494. "%2 = OpFOrdGreaterThan %bool %double_1 %double_2\n" +
  2495. "OpReturn\n" +
  2496. "OpFunctionEnd",
  2497. 2, false),
  2498. // Test case 4: fold 1.0 <= 2.0
  2499. InstructionFoldingCase<bool>(
  2500. Header() + "%main = OpFunction %void None %void_func\n" +
  2501. "%main_lab = OpLabel\n" +
  2502. "%2 = OpFOrdLessThanEqual %bool %double_1 %double_2\n" +
  2503. "OpReturn\n" +
  2504. "OpFunctionEnd",
  2505. 2, true),
  2506. // Test case 5: fold 1.0 >= 2.0
  2507. InstructionFoldingCase<bool>(
  2508. Header() + "%main = OpFunction %void None %void_func\n" +
  2509. "%main_lab = OpLabel\n" +
  2510. "%2 = OpFOrdGreaterThanEqual %bool %double_1 %double_2\n" +
  2511. "OpReturn\n" +
  2512. "OpFunctionEnd",
  2513. 2, false),
  2514. // Test case 6: fold 1.0 == 1.0
  2515. InstructionFoldingCase<bool>(
  2516. Header() + "%main = OpFunction %void None %void_func\n" +
  2517. "%main_lab = OpLabel\n" +
  2518. "%2 = OpFOrdEqual %bool %double_1 %double_1\n" +
  2519. "OpReturn\n" +
  2520. "OpFunctionEnd",
  2521. 2, true),
  2522. // Test case 7: fold 1.0 != 1.0
  2523. InstructionFoldingCase<bool>(
  2524. Header() + "%main = OpFunction %void None %void_func\n" +
  2525. "%main_lab = OpLabel\n" +
  2526. "%2 = OpFOrdNotEqual %bool %double_1 %double_1\n" +
  2527. "OpReturn\n" +
  2528. "OpFunctionEnd",
  2529. 2, false),
  2530. // Test case 8: fold 1.0 < 1.0
  2531. InstructionFoldingCase<bool>(
  2532. Header() + "%main = OpFunction %void None %void_func\n" +
  2533. "%main_lab = OpLabel\n" +
  2534. "%2 = OpFOrdLessThan %bool %double_1 %double_1\n" +
  2535. "OpReturn\n" +
  2536. "OpFunctionEnd",
  2537. 2, false),
  2538. // Test case 9: fold 1.0 > 1.0
  2539. InstructionFoldingCase<bool>(
  2540. Header() + "%main = OpFunction %void None %void_func\n" +
  2541. "%main_lab = OpLabel\n" +
  2542. "%2 = OpFOrdGreaterThan %bool %double_1 %double_1\n" +
  2543. "OpReturn\n" +
  2544. "OpFunctionEnd",
  2545. 2, false),
  2546. // Test case 10: fold 1.0 <= 1.0
  2547. InstructionFoldingCase<bool>(
  2548. Header() + "%main = OpFunction %void None %void_func\n" +
  2549. "%main_lab = OpLabel\n" +
  2550. "%2 = OpFOrdLessThanEqual %bool %double_1 %double_1\n" +
  2551. "OpReturn\n" +
  2552. "OpFunctionEnd",
  2553. 2, true),
  2554. // Test case 11: fold 1.0 >= 1.0
  2555. InstructionFoldingCase<bool>(
  2556. Header() + "%main = OpFunction %void None %void_func\n" +
  2557. "%main_lab = OpLabel\n" +
  2558. "%2 = OpFOrdGreaterThanEqual %bool %double_1 %double_1\n" +
  2559. "OpReturn\n" +
  2560. "OpFunctionEnd",
  2561. 2, true),
  2562. // Test case 12: fold 2.0 < 1.0
  2563. InstructionFoldingCase<bool>(
  2564. Header() + "%main = OpFunction %void None %void_func\n" +
  2565. "%main_lab = OpLabel\n" +
  2566. "%2 = OpFOrdLessThan %bool %double_2 %double_1\n" +
  2567. "OpReturn\n" +
  2568. "OpFunctionEnd",
  2569. 2, false),
  2570. // Test case 13: fold 2.0 > 1.0
  2571. InstructionFoldingCase<bool>(
  2572. Header() + "%main = OpFunction %void None %void_func\n" +
  2573. "%main_lab = OpLabel\n" +
  2574. "%2 = OpFOrdGreaterThan %bool %double_2 %double_1\n" +
  2575. "OpReturn\n" +
  2576. "OpFunctionEnd",
  2577. 2, true),
  2578. // Test case 14: fold 2.0 <= 1.0
  2579. InstructionFoldingCase<bool>(
  2580. Header() + "%main = OpFunction %void None %void_func\n" +
  2581. "%main_lab = OpLabel\n" +
  2582. "%2 = OpFOrdLessThanEqual %bool %double_2 %double_1\n" +
  2583. "OpReturn\n" +
  2584. "OpFunctionEnd",
  2585. 2, false),
  2586. // Test case 15: fold 2.0 >= 1.0
  2587. InstructionFoldingCase<bool>(
  2588. Header() + "%main = OpFunction %void None %void_func\n" +
  2589. "%main_lab = OpLabel\n" +
  2590. "%2 = OpFOrdGreaterThanEqual %bool %double_2 %double_1\n" +
  2591. "OpReturn\n" +
  2592. "OpFunctionEnd",
  2593. 2, true)
  2594. ));
  2595. INSTANTIATE_TEST_SUITE_P(DoubleUnorderedCompareConstantFoldingTest, BooleanInstructionFoldingTest,
  2596. ::testing::Values(
  2597. // Test case 0: fold 1.0 == 2.0
  2598. InstructionFoldingCase<bool>(
  2599. Header() + "%main = OpFunction %void None %void_func\n" +
  2600. "%main_lab = OpLabel\n" +
  2601. "%2 = OpFUnordEqual %bool %double_1 %double_2\n" +
  2602. "OpReturn\n" +
  2603. "OpFunctionEnd",
  2604. 2, false),
  2605. // Test case 1: fold 1.0 != 2.0
  2606. InstructionFoldingCase<bool>(
  2607. Header() + "%main = OpFunction %void None %void_func\n" +
  2608. "%main_lab = OpLabel\n" +
  2609. "%2 = OpFUnordNotEqual %bool %double_1 %double_2\n" +
  2610. "OpReturn\n" +
  2611. "OpFunctionEnd",
  2612. 2, true),
  2613. // Test case 2: fold 1.0 < 2.0
  2614. InstructionFoldingCase<bool>(
  2615. Header() + "%main = OpFunction %void None %void_func\n" +
  2616. "%main_lab = OpLabel\n" +
  2617. "%2 = OpFUnordLessThan %bool %double_1 %double_2\n" +
  2618. "OpReturn\n" +
  2619. "OpFunctionEnd",
  2620. 2, true),
  2621. // Test case 3: fold 1.0 > 2.0
  2622. InstructionFoldingCase<bool>(
  2623. Header() + "%main = OpFunction %void None %void_func\n" +
  2624. "%main_lab = OpLabel\n" +
  2625. "%2 = OpFUnordGreaterThan %bool %double_1 %double_2\n" +
  2626. "OpReturn\n" +
  2627. "OpFunctionEnd",
  2628. 2, false),
  2629. // Test case 4: fold 1.0 <= 2.0
  2630. InstructionFoldingCase<bool>(
  2631. Header() + "%main = OpFunction %void None %void_func\n" +
  2632. "%main_lab = OpLabel\n" +
  2633. "%2 = OpFUnordLessThanEqual %bool %double_1 %double_2\n" +
  2634. "OpReturn\n" +
  2635. "OpFunctionEnd",
  2636. 2, true),
  2637. // Test case 5: fold 1.0 >= 2.0
  2638. InstructionFoldingCase<bool>(
  2639. Header() + "%main = OpFunction %void None %void_func\n" +
  2640. "%main_lab = OpLabel\n" +
  2641. "%2 = OpFUnordGreaterThanEqual %bool %double_1 %double_2\n" +
  2642. "OpReturn\n" +
  2643. "OpFunctionEnd",
  2644. 2, false),
  2645. // Test case 6: fold 1.0 == 1.0
  2646. InstructionFoldingCase<bool>(
  2647. Header() + "%main = OpFunction %void None %void_func\n" +
  2648. "%main_lab = OpLabel\n" +
  2649. "%2 = OpFUnordEqual %bool %double_1 %double_1\n" +
  2650. "OpReturn\n" +
  2651. "OpFunctionEnd",
  2652. 2, true),
  2653. // Test case 7: fold 1.0 != 1.0
  2654. InstructionFoldingCase<bool>(
  2655. Header() + "%main = OpFunction %void None %void_func\n" +
  2656. "%main_lab = OpLabel\n" +
  2657. "%2 = OpFUnordNotEqual %bool %double_1 %double_1\n" +
  2658. "OpReturn\n" +
  2659. "OpFunctionEnd",
  2660. 2, false),
  2661. // Test case 8: fold 1.0 < 1.0
  2662. InstructionFoldingCase<bool>(
  2663. Header() + "%main = OpFunction %void None %void_func\n" +
  2664. "%main_lab = OpLabel\n" +
  2665. "%2 = OpFUnordLessThan %bool %double_1 %double_1\n" +
  2666. "OpReturn\n" +
  2667. "OpFunctionEnd",
  2668. 2, false),
  2669. // Test case 9: fold 1.0 > 1.0
  2670. InstructionFoldingCase<bool>(
  2671. Header() + "%main = OpFunction %void None %void_func\n" +
  2672. "%main_lab = OpLabel\n" +
  2673. "%2 = OpFUnordGreaterThan %bool %double_1 %double_1\n" +
  2674. "OpReturn\n" +
  2675. "OpFunctionEnd",
  2676. 2, false),
  2677. // Test case 10: fold 1.0 <= 1.0
  2678. InstructionFoldingCase<bool>(
  2679. Header() + "%main = OpFunction %void None %void_func\n" +
  2680. "%main_lab = OpLabel\n" +
  2681. "%2 = OpFUnordLessThanEqual %bool %double_1 %double_1\n" +
  2682. "OpReturn\n" +
  2683. "OpFunctionEnd",
  2684. 2, true),
  2685. // Test case 11: fold 1.0 >= 1.0
  2686. InstructionFoldingCase<bool>(
  2687. Header() + "%main = OpFunction %void None %void_func\n" +
  2688. "%main_lab = OpLabel\n" +
  2689. "%2 = OpFUnordGreaterThanEqual %bool %double_1 %double_1\n" +
  2690. "OpReturn\n" +
  2691. "OpFunctionEnd",
  2692. 2, true),
  2693. // Test case 12: fold 2.0 < 1.0
  2694. InstructionFoldingCase<bool>(
  2695. Header() + "%main = OpFunction %void None %void_func\n" +
  2696. "%main_lab = OpLabel\n" +
  2697. "%2 = OpFUnordLessThan %bool %double_2 %double_1\n" +
  2698. "OpReturn\n" +
  2699. "OpFunctionEnd",
  2700. 2, false),
  2701. // Test case 13: fold 2.0 > 1.0
  2702. InstructionFoldingCase<bool>(
  2703. Header() + "%main = OpFunction %void None %void_func\n" +
  2704. "%main_lab = OpLabel\n" +
  2705. "%2 = OpFUnordGreaterThan %bool %double_2 %double_1\n" +
  2706. "OpReturn\n" +
  2707. "OpFunctionEnd",
  2708. 2, true),
  2709. // Test case 14: fold 2.0 <= 1.0
  2710. InstructionFoldingCase<bool>(
  2711. Header() + "%main = OpFunction %void None %void_func\n" +
  2712. "%main_lab = OpLabel\n" +
  2713. "%2 = OpFUnordLessThanEqual %bool %double_2 %double_1\n" +
  2714. "OpReturn\n" +
  2715. "OpFunctionEnd",
  2716. 2, false),
  2717. // Test case 15: fold 2.0 >= 1.0
  2718. InstructionFoldingCase<bool>(
  2719. Header() + "%main = OpFunction %void None %void_func\n" +
  2720. "%main_lab = OpLabel\n" +
  2721. "%2 = OpFUnordGreaterThanEqual %bool %double_2 %double_1\n" +
  2722. "OpReturn\n" +
  2723. "OpFunctionEnd",
  2724. 2, true)
  2725. ));
  2726. INSTANTIATE_TEST_SUITE_P(FloatOrderedCompareConstantFoldingTest, BooleanInstructionFoldingTest,
  2727. ::testing::Values(
  2728. // Test case 0: fold 1.0 == 2.0
  2729. InstructionFoldingCase<bool>(
  2730. Header() + "%main = OpFunction %void None %void_func\n" +
  2731. "%main_lab = OpLabel\n" +
  2732. "%2 = OpFOrdEqual %bool %float_1 %float_2\n" +
  2733. "OpReturn\n" +
  2734. "OpFunctionEnd",
  2735. 2, false),
  2736. // Test case 1: fold 1.0 != 2.0
  2737. InstructionFoldingCase<bool>(
  2738. Header() + "%main = OpFunction %void None %void_func\n" +
  2739. "%main_lab = OpLabel\n" +
  2740. "%2 = OpFOrdNotEqual %bool %float_1 %float_2\n" +
  2741. "OpReturn\n" +
  2742. "OpFunctionEnd",
  2743. 2, true),
  2744. // Test case 2: fold 1.0 < 2.0
  2745. InstructionFoldingCase<bool>(
  2746. Header() + "%main = OpFunction %void None %void_func\n" +
  2747. "%main_lab = OpLabel\n" +
  2748. "%2 = OpFOrdLessThan %bool %float_1 %float_2\n" +
  2749. "OpReturn\n" +
  2750. "OpFunctionEnd",
  2751. 2, true),
  2752. // Test case 3: fold 1.0 > 2.0
  2753. InstructionFoldingCase<bool>(
  2754. Header() + "%main = OpFunction %void None %void_func\n" +
  2755. "%main_lab = OpLabel\n" +
  2756. "%2 = OpFOrdGreaterThan %bool %float_1 %float_2\n" +
  2757. "OpReturn\n" +
  2758. "OpFunctionEnd",
  2759. 2, false),
  2760. // Test case 4: fold 1.0 <= 2.0
  2761. InstructionFoldingCase<bool>(
  2762. Header() + "%main = OpFunction %void None %void_func\n" +
  2763. "%main_lab = OpLabel\n" +
  2764. "%2 = OpFOrdLessThanEqual %bool %float_1 %float_2\n" +
  2765. "OpReturn\n" +
  2766. "OpFunctionEnd",
  2767. 2, true),
  2768. // Test case 5: fold 1.0 >= 2.0
  2769. InstructionFoldingCase<bool>(
  2770. Header() + "%main = OpFunction %void None %void_func\n" +
  2771. "%main_lab = OpLabel\n" +
  2772. "%2 = OpFOrdGreaterThanEqual %bool %float_1 %float_2\n" +
  2773. "OpReturn\n" +
  2774. "OpFunctionEnd",
  2775. 2, false),
  2776. // Test case 6: fold 1.0 == 1.0
  2777. InstructionFoldingCase<bool>(
  2778. Header() + "%main = OpFunction %void None %void_func\n" +
  2779. "%main_lab = OpLabel\n" +
  2780. "%2 = OpFOrdEqual %bool %float_1 %float_1\n" +
  2781. "OpReturn\n" +
  2782. "OpFunctionEnd",
  2783. 2, true),
  2784. // Test case 7: fold 1.0 != 1.0
  2785. InstructionFoldingCase<bool>(
  2786. Header() + "%main = OpFunction %void None %void_func\n" +
  2787. "%main_lab = OpLabel\n" +
  2788. "%2 = OpFOrdNotEqual %bool %float_1 %float_1\n" +
  2789. "OpReturn\n" +
  2790. "OpFunctionEnd",
  2791. 2, false),
  2792. // Test case 8: fold 1.0 < 1.0
  2793. InstructionFoldingCase<bool>(
  2794. Header() + "%main = OpFunction %void None %void_func\n" +
  2795. "%main_lab = OpLabel\n" +
  2796. "%2 = OpFOrdLessThan %bool %float_1 %float_1\n" +
  2797. "OpReturn\n" +
  2798. "OpFunctionEnd",
  2799. 2, false),
  2800. // Test case 9: fold 1.0 > 1.0
  2801. InstructionFoldingCase<bool>(
  2802. Header() + "%main = OpFunction %void None %void_func\n" +
  2803. "%main_lab = OpLabel\n" +
  2804. "%2 = OpFOrdGreaterThan %bool %float_1 %float_1\n" +
  2805. "OpReturn\n" +
  2806. "OpFunctionEnd",
  2807. 2, false),
  2808. // Test case 10: fold 1.0 <= 1.0
  2809. InstructionFoldingCase<bool>(
  2810. Header() + "%main = OpFunction %void None %void_func\n" +
  2811. "%main_lab = OpLabel\n" +
  2812. "%2 = OpFOrdLessThanEqual %bool %float_1 %float_1\n" +
  2813. "OpReturn\n" +
  2814. "OpFunctionEnd",
  2815. 2, true),
  2816. // Test case 11: fold 1.0 >= 1.0
  2817. InstructionFoldingCase<bool>(
  2818. Header() + "%main = OpFunction %void None %void_func\n" +
  2819. "%main_lab = OpLabel\n" +
  2820. "%2 = OpFOrdGreaterThanEqual %bool %float_1 %float_1\n" +
  2821. "OpReturn\n" +
  2822. "OpFunctionEnd",
  2823. 2, true),
  2824. // Test case 12: fold 2.0 < 1.0
  2825. InstructionFoldingCase<bool>(
  2826. Header() + "%main = OpFunction %void None %void_func\n" +
  2827. "%main_lab = OpLabel\n" +
  2828. "%2 = OpFOrdLessThan %bool %float_2 %float_1\n" +
  2829. "OpReturn\n" +
  2830. "OpFunctionEnd",
  2831. 2, false),
  2832. // Test case 13: fold 2.0 > 1.0
  2833. InstructionFoldingCase<bool>(
  2834. Header() + "%main = OpFunction %void None %void_func\n" +
  2835. "%main_lab = OpLabel\n" +
  2836. "%2 = OpFOrdGreaterThan %bool %float_2 %float_1\n" +
  2837. "OpReturn\n" +
  2838. "OpFunctionEnd",
  2839. 2, true),
  2840. // Test case 14: fold 2.0 <= 1.0
  2841. InstructionFoldingCase<bool>(
  2842. Header() + "%main = OpFunction %void None %void_func\n" +
  2843. "%main_lab = OpLabel\n" +
  2844. "%2 = OpFOrdLessThanEqual %bool %float_2 %float_1\n" +
  2845. "OpReturn\n" +
  2846. "OpFunctionEnd",
  2847. 2, false),
  2848. // Test case 15: fold 2.0 >= 1.0
  2849. InstructionFoldingCase<bool>(
  2850. Header() + "%main = OpFunction %void None %void_func\n" +
  2851. "%main_lab = OpLabel\n" +
  2852. "%2 = OpFOrdGreaterThanEqual %bool %float_2 %float_1\n" +
  2853. "OpReturn\n" +
  2854. "OpFunctionEnd",
  2855. 2, true)
  2856. ));
  2857. INSTANTIATE_TEST_SUITE_P(FloatUnorderedCompareConstantFoldingTest, BooleanInstructionFoldingTest,
  2858. ::testing::Values(
  2859. // Test case 0: fold 1.0 == 2.0
  2860. InstructionFoldingCase<bool>(
  2861. Header() + "%main = OpFunction %void None %void_func\n" +
  2862. "%main_lab = OpLabel\n" +
  2863. "%2 = OpFUnordEqual %bool %float_1 %float_2\n" +
  2864. "OpReturn\n" +
  2865. "OpFunctionEnd",
  2866. 2, false),
  2867. // Test case 1: fold 1.0 != 2.0
  2868. InstructionFoldingCase<bool>(
  2869. Header() + "%main = OpFunction %void None %void_func\n" +
  2870. "%main_lab = OpLabel\n" +
  2871. "%2 = OpFUnordNotEqual %bool %float_1 %float_2\n" +
  2872. "OpReturn\n" +
  2873. "OpFunctionEnd",
  2874. 2, true),
  2875. // Test case 2: fold 1.0 < 2.0
  2876. InstructionFoldingCase<bool>(
  2877. Header() + "%main = OpFunction %void None %void_func\n" +
  2878. "%main_lab = OpLabel\n" +
  2879. "%2 = OpFUnordLessThan %bool %float_1 %float_2\n" +
  2880. "OpReturn\n" +
  2881. "OpFunctionEnd",
  2882. 2, true),
  2883. // Test case 3: fold 1.0 > 2.0
  2884. InstructionFoldingCase<bool>(
  2885. Header() + "%main = OpFunction %void None %void_func\n" +
  2886. "%main_lab = OpLabel\n" +
  2887. "%2 = OpFUnordGreaterThan %bool %float_1 %float_2\n" +
  2888. "OpReturn\n" +
  2889. "OpFunctionEnd",
  2890. 2, false),
  2891. // Test case 4: fold 1.0 <= 2.0
  2892. InstructionFoldingCase<bool>(
  2893. Header() + "%main = OpFunction %void None %void_func\n" +
  2894. "%main_lab = OpLabel\n" +
  2895. "%2 = OpFUnordLessThanEqual %bool %float_1 %float_2\n" +
  2896. "OpReturn\n" +
  2897. "OpFunctionEnd",
  2898. 2, true),
  2899. // Test case 5: fold 1.0 >= 2.0
  2900. InstructionFoldingCase<bool>(
  2901. Header() + "%main = OpFunction %void None %void_func\n" +
  2902. "%main_lab = OpLabel\n" +
  2903. "%2 = OpFUnordGreaterThanEqual %bool %float_1 %float_2\n" +
  2904. "OpReturn\n" +
  2905. "OpFunctionEnd",
  2906. 2, false),
  2907. // Test case 6: fold 1.0 == 1.0
  2908. InstructionFoldingCase<bool>(
  2909. Header() + "%main = OpFunction %void None %void_func\n" +
  2910. "%main_lab = OpLabel\n" +
  2911. "%2 = OpFUnordEqual %bool %float_1 %float_1\n" +
  2912. "OpReturn\n" +
  2913. "OpFunctionEnd",
  2914. 2, true),
  2915. // Test case 7: fold 1.0 != 1.0
  2916. InstructionFoldingCase<bool>(
  2917. Header() + "%main = OpFunction %void None %void_func\n" +
  2918. "%main_lab = OpLabel\n" +
  2919. "%2 = OpFUnordNotEqual %bool %float_1 %float_1\n" +
  2920. "OpReturn\n" +
  2921. "OpFunctionEnd",
  2922. 2, false),
  2923. // Test case 8: fold 1.0 < 1.0
  2924. InstructionFoldingCase<bool>(
  2925. Header() + "%main = OpFunction %void None %void_func\n" +
  2926. "%main_lab = OpLabel\n" +
  2927. "%2 = OpFUnordLessThan %bool %float_1 %float_1\n" +
  2928. "OpReturn\n" +
  2929. "OpFunctionEnd",
  2930. 2, false),
  2931. // Test case 9: fold 1.0 > 1.0
  2932. InstructionFoldingCase<bool>(
  2933. Header() + "%main = OpFunction %void None %void_func\n" +
  2934. "%main_lab = OpLabel\n" +
  2935. "%2 = OpFUnordGreaterThan %bool %float_1 %float_1\n" +
  2936. "OpReturn\n" +
  2937. "OpFunctionEnd",
  2938. 2, false),
  2939. // Test case 10: fold 1.0 <= 1.0
  2940. InstructionFoldingCase<bool>(
  2941. Header() + "%main = OpFunction %void None %void_func\n" +
  2942. "%main_lab = OpLabel\n" +
  2943. "%2 = OpFUnordLessThanEqual %bool %float_1 %float_1\n" +
  2944. "OpReturn\n" +
  2945. "OpFunctionEnd",
  2946. 2, true),
  2947. // Test case 11: fold 1.0 >= 1.0
  2948. InstructionFoldingCase<bool>(
  2949. Header() + "%main = OpFunction %void None %void_func\n" +
  2950. "%main_lab = OpLabel\n" +
  2951. "%2 = OpFUnordGreaterThanEqual %bool %float_1 %float_1\n" +
  2952. "OpReturn\n" +
  2953. "OpFunctionEnd",
  2954. 2, true),
  2955. // Test case 12: fold 2.0 < 1.0
  2956. InstructionFoldingCase<bool>(
  2957. Header() + "%main = OpFunction %void None %void_func\n" +
  2958. "%main_lab = OpLabel\n" +
  2959. "%2 = OpFUnordLessThan %bool %float_2 %float_1\n" +
  2960. "OpReturn\n" +
  2961. "OpFunctionEnd",
  2962. 2, false),
  2963. // Test case 13: fold 2.0 > 1.0
  2964. InstructionFoldingCase<bool>(
  2965. Header() + "%main = OpFunction %void None %void_func\n" +
  2966. "%main_lab = OpLabel\n" +
  2967. "%2 = OpFUnordGreaterThan %bool %float_2 %float_1\n" +
  2968. "OpReturn\n" +
  2969. "OpFunctionEnd",
  2970. 2, true),
  2971. // Test case 14: fold 2.0 <= 1.0
  2972. InstructionFoldingCase<bool>(
  2973. Header() + "%main = OpFunction %void None %void_func\n" +
  2974. "%main_lab = OpLabel\n" +
  2975. "%2 = OpFUnordLessThanEqual %bool %float_2 %float_1\n" +
  2976. "OpReturn\n" +
  2977. "OpFunctionEnd",
  2978. 2, false),
  2979. // Test case 15: fold 2.0 >= 1.0
  2980. InstructionFoldingCase<bool>(
  2981. Header() + "%main = OpFunction %void None %void_func\n" +
  2982. "%main_lab = OpLabel\n" +
  2983. "%2 = OpFUnordGreaterThanEqual %bool %float_2 %float_1\n" +
  2984. "OpReturn\n" +
  2985. "OpFunctionEnd",
  2986. 2, true)
  2987. ));
  2988. INSTANTIATE_TEST_SUITE_P(DoubleNaNCompareConstantFoldingTest, BooleanInstructionFoldingTest,
  2989. ::testing::Values(
  2990. // Test case 0: fold NaN == 0 (ord)
  2991. InstructionFoldingCase<bool>(
  2992. HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
  2993. "%main_lab = OpLabel\n" +
  2994. "%2 = OpFOrdEqual %bool %double_nan %double_0\n" +
  2995. "OpReturn\n" +
  2996. "OpFunctionEnd",
  2997. 2, false),
  2998. // Test case 1: fold NaN == NaN (unord)
  2999. InstructionFoldingCase<bool>(
  3000. HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
  3001. "%main_lab = OpLabel\n" +
  3002. "%2 = OpFUnordEqual %bool %double_nan %double_0\n" +
  3003. "OpReturn\n" +
  3004. "OpFunctionEnd",
  3005. 2, true),
  3006. // Test case 2: fold NaN != NaN (ord)
  3007. InstructionFoldingCase<bool>(
  3008. HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
  3009. "%main_lab = OpLabel\n" +
  3010. "%2 = OpFOrdNotEqual %bool %double_nan %double_0\n" +
  3011. "OpReturn\n" +
  3012. "OpFunctionEnd",
  3013. 2, false),
  3014. // Test case 3: fold NaN != NaN (unord)
  3015. InstructionFoldingCase<bool>(
  3016. HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
  3017. "%main_lab = OpLabel\n" +
  3018. "%2 = OpFUnordNotEqual %bool %double_nan %double_0\n" +
  3019. "OpReturn\n" +
  3020. "OpFunctionEnd",
  3021. 2, true)
  3022. ));
  3023. INSTANTIATE_TEST_SUITE_P(FloatNaNCompareConstantFoldingTest, BooleanInstructionFoldingTest,
  3024. ::testing::Values(
  3025. // Test case 0: fold NaN == 0 (ord)
  3026. InstructionFoldingCase<bool>(
  3027. HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
  3028. "%main_lab = OpLabel\n" +
  3029. "%2 = OpFOrdEqual %bool %float_nan %float_0\n" +
  3030. "OpReturn\n" +
  3031. "OpFunctionEnd",
  3032. 2, false),
  3033. // Test case 1: fold NaN == NaN (unord)
  3034. InstructionFoldingCase<bool>(
  3035. HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
  3036. "%main_lab = OpLabel\n" +
  3037. "%2 = OpFUnordEqual %bool %float_nan %float_0\n" +
  3038. "OpReturn\n" +
  3039. "OpFunctionEnd",
  3040. 2, true),
  3041. // Test case 2: fold NaN != NaN (ord)
  3042. InstructionFoldingCase<bool>(
  3043. HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
  3044. "%main_lab = OpLabel\n" +
  3045. "%2 = OpFOrdNotEqual %bool %float_nan %float_0\n" +
  3046. "OpReturn\n" +
  3047. "OpFunctionEnd",
  3048. 2, false),
  3049. // Test case 3: fold NaN != NaN (unord)
  3050. InstructionFoldingCase<bool>(
  3051. HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
  3052. "%main_lab = OpLabel\n" +
  3053. "%2 = OpFUnordNotEqual %bool %float_nan %float_0\n" +
  3054. "OpReturn\n" +
  3055. "OpFunctionEnd",
  3056. 2, true)
  3057. ));
  3058. // clang-format on
  3059. template <class ResultType>
  3060. struct InstructionFoldingCaseWithMap {
  3061. InstructionFoldingCaseWithMap(const std::string& tb, uint32_t id,
  3062. ResultType result,
  3063. std::function<uint32_t(uint32_t)> map)
  3064. : test_body(tb), id_to_fold(id), expected_result(result), id_map(map) {}
  3065. std::string test_body;
  3066. uint32_t id_to_fold;
  3067. ResultType expected_result;
  3068. std::function<uint32_t(uint32_t)> id_map;
  3069. };
  3070. using IntegerInstructionFoldingTestWithMap =
  3071. ::testing::TestWithParam<InstructionFoldingCaseWithMap<uint32_t>>;
  3072. TEST_P(IntegerInstructionFoldingTestWithMap, Case) {
  3073. const auto& tc = GetParam();
  3074. // Build module.
  3075. std::unique_ptr<IRContext> context =
  3076. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
  3077. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  3078. ASSERT_NE(nullptr, context);
  3079. // Fold the instruction to test.
  3080. analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
  3081. Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
  3082. inst = context->get_instruction_folder().FoldInstructionToConstant(inst,
  3083. tc.id_map);
  3084. // Make sure the instruction folded as expected.
  3085. EXPECT_NE(inst, nullptr);
  3086. if (inst != nullptr) {
  3087. EXPECT_EQ(inst->opcode(), spv::Op::OpConstant);
  3088. analysis::ConstantManager* const_mrg = context->get_constant_mgr();
  3089. const analysis::IntConstant* result =
  3090. const_mrg->GetConstantFromInst(inst)->AsIntConstant();
  3091. EXPECT_NE(result, nullptr);
  3092. if (result != nullptr) {
  3093. EXPECT_EQ(result->GetU32BitValue(), tc.expected_result);
  3094. }
  3095. }
  3096. }
  3097. // clang-format off
  3098. INSTANTIATE_TEST_SUITE_P(TestCase, IntegerInstructionFoldingTestWithMap,
  3099. ::testing::Values(
  3100. // Test case 0: fold %3 = 0; %3 * n
  3101. InstructionFoldingCaseWithMap<uint32_t>(
  3102. Header() + "%main = OpFunction %void None %void_func\n" +
  3103. "%main_lab = OpLabel\n" +
  3104. "%n = OpVariable %_ptr_int Function\n" +
  3105. "%load = OpLoad %int %n\n" +
  3106. "%3 = OpCopyObject %int %int_0\n"
  3107. "%2 = OpIMul %int %3 %load\n" +
  3108. "OpReturn\n" +
  3109. "OpFunctionEnd",
  3110. 2, 0, [](uint32_t id) {return (id == 3 ? INT_0_ID : id);})
  3111. ));
  3112. // clang-format on
  3113. using BooleanInstructionFoldingTestWithMap =
  3114. ::testing::TestWithParam<InstructionFoldingCaseWithMap<bool>>;
  3115. TEST_P(BooleanInstructionFoldingTestWithMap, Case) {
  3116. const auto& tc = GetParam();
  3117. // Build module.
  3118. std::unique_ptr<IRContext> context =
  3119. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
  3120. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  3121. ASSERT_NE(nullptr, context);
  3122. // Fold the instruction to test.
  3123. analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
  3124. Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
  3125. inst = context->get_instruction_folder().FoldInstructionToConstant(inst,
  3126. tc.id_map);
  3127. // Make sure the instruction folded as expected.
  3128. EXPECT_NE(inst, nullptr);
  3129. if (inst != nullptr) {
  3130. std::vector<spv::Op> bool_opcodes = {spv::Op::OpConstantTrue,
  3131. spv::Op::OpConstantFalse};
  3132. EXPECT_THAT(bool_opcodes, Contains(inst->opcode()));
  3133. analysis::ConstantManager* const_mrg = context->get_constant_mgr();
  3134. const analysis::BoolConstant* result =
  3135. const_mrg->GetConstantFromInst(inst)->AsBoolConstant();
  3136. EXPECT_NE(result, nullptr);
  3137. if (result != nullptr) {
  3138. EXPECT_EQ(result->value(), tc.expected_result);
  3139. }
  3140. }
  3141. }
  3142. // clang-format off
  3143. INSTANTIATE_TEST_SUITE_P(TestCase, BooleanInstructionFoldingTestWithMap,
  3144. ::testing::Values(
  3145. // Test case 0: fold %3 = true; %3 || n
  3146. InstructionFoldingCaseWithMap<bool>(
  3147. Header() + "%main = OpFunction %void None %void_func\n" +
  3148. "%main_lab = OpLabel\n" +
  3149. "%n = OpVariable %_ptr_bool Function\n" +
  3150. "%load = OpLoad %bool %n\n" +
  3151. "%3 = OpCopyObject %bool %true\n" +
  3152. "%2 = OpLogicalOr %bool %3 %load\n" +
  3153. "OpReturn\n" +
  3154. "OpFunctionEnd",
  3155. 2, true, [](uint32_t id) {return (id == 3 ? TRUE_ID : id);})
  3156. ));
  3157. // clang-format on
  3158. using GeneralInstructionFoldingTest =
  3159. ::testing::TestWithParam<InstructionFoldingCase<uint32_t>>;
  3160. TEST_P(GeneralInstructionFoldingTest, Case) {
  3161. const auto& tc = GetParam();
  3162. // Build module.
  3163. std::unique_ptr<IRContext> context =
  3164. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
  3165. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  3166. ASSERT_NE(nullptr, context);
  3167. // Fold the instruction to test.
  3168. analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
  3169. Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
  3170. std::unique_ptr<Instruction> original_inst(inst->Clone(context.get()));
  3171. bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
  3172. // Make sure the instruction folded as expected.
  3173. EXPECT_EQ(inst->result_id(), original_inst->result_id());
  3174. EXPECT_EQ(inst->type_id(), original_inst->type_id());
  3175. EXPECT_TRUE((!succeeded) == (tc.expected_result == 0));
  3176. if (succeeded) {
  3177. EXPECT_EQ(inst->opcode(), spv::Op::OpCopyObject);
  3178. EXPECT_EQ(inst->GetSingleWordInOperand(0), tc.expected_result);
  3179. } else {
  3180. EXPECT_EQ(inst->NumInOperands(), original_inst->NumInOperands());
  3181. for (uint32_t i = 0; i < inst->NumInOperands(); ++i) {
  3182. EXPECT_EQ(inst->GetOperand(i), original_inst->GetOperand(i));
  3183. }
  3184. }
  3185. }
  3186. // clang-format off
  3187. INSTANTIATE_TEST_SUITE_P(IntegerArithmeticTestCases, GeneralInstructionFoldingTest,
  3188. ::testing::Values(
  3189. // Test case 0: Don't fold n * m
  3190. InstructionFoldingCase<uint32_t>(
  3191. Header() + "%main = OpFunction %void None %void_func\n" +
  3192. "%main_lab = OpLabel\n" +
  3193. "%n = OpVariable %_ptr_int Function\n" +
  3194. "%m = OpVariable %_ptr_int Function\n" +
  3195. "%load_n = OpLoad %int %n\n" +
  3196. "%load_m = OpLoad %int %m\n" +
  3197. "%2 = OpIMul %int %load_n %load_m\n" +
  3198. "OpReturn\n" +
  3199. "OpFunctionEnd",
  3200. 2, 0),
  3201. // Test case 1: Don't fold n / m (unsigned)
  3202. InstructionFoldingCase<uint32_t>(
  3203. Header() + "%main = OpFunction %void None %void_func\n" +
  3204. "%main_lab = OpLabel\n" +
  3205. "%n = OpVariable %_ptr_uint Function\n" +
  3206. "%m = OpVariable %_ptr_uint Function\n" +
  3207. "%load_n = OpLoad %uint %n\n" +
  3208. "%load_m = OpLoad %uint %m\n" +
  3209. "%2 = OpUDiv %uint %load_n %load_m\n" +
  3210. "OpReturn\n" +
  3211. "OpFunctionEnd",
  3212. 2, 0),
  3213. // Test case 2: Don't fold n / m (signed)
  3214. InstructionFoldingCase<uint32_t>(
  3215. Header() + "%main = OpFunction %void None %void_func\n" +
  3216. "%main_lab = OpLabel\n" +
  3217. "%n = OpVariable %_ptr_int Function\n" +
  3218. "%m = OpVariable %_ptr_int Function\n" +
  3219. "%load_n = OpLoad %int %n\n" +
  3220. "%load_m = OpLoad %int %m\n" +
  3221. "%2 = OpSDiv %int %load_n %load_m\n" +
  3222. "OpReturn\n" +
  3223. "OpFunctionEnd",
  3224. 2, 0),
  3225. // Test case 3: Don't fold n remainder m
  3226. InstructionFoldingCase<uint32_t>(
  3227. Header() + "%main = OpFunction %void None %void_func\n" +
  3228. "%main_lab = OpLabel\n" +
  3229. "%n = OpVariable %_ptr_int Function\n" +
  3230. "%m = OpVariable %_ptr_int Function\n" +
  3231. "%load_n = OpLoad %int %n\n" +
  3232. "%load_m = OpLoad %int %m\n" +
  3233. "%2 = OpSRem %int %load_n %load_m\n" +
  3234. "OpReturn\n" +
  3235. "OpFunctionEnd",
  3236. 2, 0),
  3237. // Test case 4: Don't fold n % m (signed)
  3238. InstructionFoldingCase<uint32_t>(
  3239. Header() + "%main = OpFunction %void None %void_func\n" +
  3240. "%main_lab = OpLabel\n" +
  3241. "%n = OpVariable %_ptr_int Function\n" +
  3242. "%m = OpVariable %_ptr_int Function\n" +
  3243. "%load_n = OpLoad %int %n\n" +
  3244. "%load_m = OpLoad %int %m\n" +
  3245. "%2 = OpSMod %int %load_n %load_m\n" +
  3246. "OpReturn\n" +
  3247. "OpFunctionEnd",
  3248. 2, 0),
  3249. // Test case 5: Don't fold n % m (unsigned)
  3250. InstructionFoldingCase<uint32_t>(
  3251. Header() + "%main = OpFunction %void None %void_func\n" +
  3252. "%main_lab = OpLabel\n" +
  3253. "%n = OpVariable %_ptr_uint Function\n" +
  3254. "%m = OpVariable %_ptr_uint Function\n" +
  3255. "%load_n = OpLoad %uint %n\n" +
  3256. "%load_m = OpLoad %uint %m\n" +
  3257. "%2 = OpUMod %int %load_n %load_m\n" +
  3258. "OpReturn\n" +
  3259. "OpFunctionEnd",
  3260. 2, 0),
  3261. // Test case 6: Don't fold n << m
  3262. InstructionFoldingCase<uint32_t>(
  3263. Header() + "%main = OpFunction %void None %void_func\n" +
  3264. "%main_lab = OpLabel\n" +
  3265. "%n = OpVariable %_ptr_uint Function\n" +
  3266. "%m = OpVariable %_ptr_uint Function\n" +
  3267. "%load_n = OpLoad %uint %n\n" +
  3268. "%load_m = OpLoad %uint %m\n" +
  3269. "%2 = OpShiftRightLogical %int %load_n %load_m\n" +
  3270. "OpReturn\n" +
  3271. "OpFunctionEnd",
  3272. 2, 0),
  3273. // Test case 7: Don't fold n >> m
  3274. InstructionFoldingCase<uint32_t>(
  3275. Header() + "%main = OpFunction %void None %void_func\n" +
  3276. "%main_lab = OpLabel\n" +
  3277. "%n = OpVariable %_ptr_uint Function\n" +
  3278. "%m = OpVariable %_ptr_uint Function\n" +
  3279. "%load_n = OpLoad %uint %n\n" +
  3280. "%load_m = OpLoad %uint %m\n" +
  3281. "%2 = OpShiftLeftLogical %int %load_n %load_m\n" +
  3282. "OpReturn\n" +
  3283. "OpFunctionEnd",
  3284. 2, 0),
  3285. // Test case 8: Don't fold n | m
  3286. InstructionFoldingCase<uint32_t>(
  3287. Header() + "%main = OpFunction %void None %void_func\n" +
  3288. "%main_lab = OpLabel\n" +
  3289. "%n = OpVariable %_ptr_uint Function\n" +
  3290. "%m = OpVariable %_ptr_uint Function\n" +
  3291. "%load_n = OpLoad %uint %n\n" +
  3292. "%load_m = OpLoad %uint %m\n" +
  3293. "%2 = OpBitwiseOr %int %load_n %load_m\n" +
  3294. "OpReturn\n" +
  3295. "OpFunctionEnd",
  3296. 2, 0),
  3297. // Test case 9: Don't fold n & m
  3298. InstructionFoldingCase<uint32_t>(
  3299. Header() + "%main = OpFunction %void None %void_func\n" +
  3300. "%main_lab = OpLabel\n" +
  3301. "%n = OpVariable %_ptr_uint Function\n" +
  3302. "%m = OpVariable %_ptr_uint Function\n" +
  3303. "%load_n = OpLoad %uint %n\n" +
  3304. "%load_m = OpLoad %uint %m\n" +
  3305. "%2 = OpBitwiseAnd %int %load_n %load_m\n" +
  3306. "OpReturn\n" +
  3307. "OpFunctionEnd",
  3308. 2, 0),
  3309. // Test case 10: Don't fold n < m (unsigned)
  3310. InstructionFoldingCase<uint32_t>(
  3311. Header() + "%main = OpFunction %void None %void_func\n" +
  3312. "%main_lab = OpLabel\n" +
  3313. "%n = OpVariable %_ptr_uint Function\n" +
  3314. "%m = OpVariable %_ptr_uint Function\n" +
  3315. "%load_n = OpLoad %uint %n\n" +
  3316. "%load_m = OpLoad %uint %m\n" +
  3317. "%2 = OpULessThan %bool %load_n %load_m\n" +
  3318. "OpReturn\n" +
  3319. "OpFunctionEnd",
  3320. 2, 0),
  3321. // Test case 11: Don't fold n > m (unsigned)
  3322. InstructionFoldingCase<uint32_t>(
  3323. Header() + "%main = OpFunction %void None %void_func\n" +
  3324. "%main_lab = OpLabel\n" +
  3325. "%n = OpVariable %_ptr_uint Function\n" +
  3326. "%m = OpVariable %_ptr_uint Function\n" +
  3327. "%load_n = OpLoad %uint %n\n" +
  3328. "%load_m = OpLoad %uint %m\n" +
  3329. "%2 = OpUGreaterThan %bool %load_n %load_m\n" +
  3330. "OpReturn\n" +
  3331. "OpFunctionEnd",
  3332. 2, 0),
  3333. // Test case 12: Don't fold n <= m (unsigned)
  3334. InstructionFoldingCase<uint32_t>(
  3335. Header() + "%main = OpFunction %void None %void_func\n" +
  3336. "%main_lab = OpLabel\n" +
  3337. "%n = OpVariable %_ptr_uint Function\n" +
  3338. "%m = OpVariable %_ptr_uint Function\n" +
  3339. "%load_n = OpLoad %uint %n\n" +
  3340. "%load_m = OpLoad %uint %m\n" +
  3341. "%2 = OpULessThanEqual %bool %load_n %load_m\n" +
  3342. "OpReturn\n" +
  3343. "OpFunctionEnd",
  3344. 2, 0),
  3345. // Test case 13: Don't fold n >= m (unsigned)
  3346. InstructionFoldingCase<uint32_t>(
  3347. Header() + "%main = OpFunction %void None %void_func\n" +
  3348. "%main_lab = OpLabel\n" +
  3349. "%n = OpVariable %_ptr_uint Function\n" +
  3350. "%m = OpVariable %_ptr_uint Function\n" +
  3351. "%load_n = OpLoad %uint %n\n" +
  3352. "%load_m = OpLoad %uint %m\n" +
  3353. "%2 = OpUGreaterThanEqual %bool %load_n %load_m\n" +
  3354. "OpReturn\n" +
  3355. "OpFunctionEnd",
  3356. 2, 0),
  3357. // Test case 14: Don't fold n < m (signed)
  3358. InstructionFoldingCase<uint32_t>(
  3359. Header() + "%main = OpFunction %void None %void_func\n" +
  3360. "%main_lab = OpLabel\n" +
  3361. "%n = OpVariable %_ptr_int Function\n" +
  3362. "%m = OpVariable %_ptr_int Function\n" +
  3363. "%load_n = OpLoad %int %n\n" +
  3364. "%load_m = OpLoad %int %m\n" +
  3365. "%2 = OpULessThan %bool %load_n %load_m\n" +
  3366. "OpReturn\n" +
  3367. "OpFunctionEnd",
  3368. 2, 0),
  3369. // Test case 15: Don't fold n > m (signed)
  3370. InstructionFoldingCase<uint32_t>(
  3371. Header() + "%main = OpFunction %void None %void_func\n" +
  3372. "%main_lab = OpLabel\n" +
  3373. "%n = OpVariable %_ptr_int Function\n" +
  3374. "%m = OpVariable %_ptr_int Function\n" +
  3375. "%load_n = OpLoad %int %n\n" +
  3376. "%load_m = OpLoad %int %m\n" +
  3377. "%2 = OpUGreaterThan %bool %load_n %load_m\n" +
  3378. "OpReturn\n" +
  3379. "OpFunctionEnd",
  3380. 2, 0),
  3381. // Test case 16: Don't fold n <= m (signed)
  3382. InstructionFoldingCase<uint32_t>(
  3383. Header() + "%main = OpFunction %void None %void_func\n" +
  3384. "%main_lab = OpLabel\n" +
  3385. "%n = OpVariable %_ptr_int Function\n" +
  3386. "%m = OpVariable %_ptr_int Function\n" +
  3387. "%load_n = OpLoad %int %n\n" +
  3388. "%load_m = OpLoad %int %m\n" +
  3389. "%2 = OpULessThanEqual %bool %load_n %load_m\n" +
  3390. "OpReturn\n" +
  3391. "OpFunctionEnd",
  3392. 2, 0),
  3393. // Test case 17: Don't fold n >= m (signed)
  3394. InstructionFoldingCase<uint32_t>(
  3395. Header() + "%main = OpFunction %void None %void_func\n" +
  3396. "%main_lab = OpLabel\n" +
  3397. "%n = OpVariable %_ptr_int Function\n" +
  3398. "%m = OpVariable %_ptr_int Function\n" +
  3399. "%load_n = OpLoad %int %n\n" +
  3400. "%load_m = OpLoad %int %m\n" +
  3401. "%2 = OpUGreaterThanEqual %bool %load_n %load_m\n" +
  3402. "OpReturn\n" +
  3403. "OpFunctionEnd",
  3404. 2, 0),
  3405. // Test case 18: Don't fold n || m
  3406. InstructionFoldingCase<uint32_t>(
  3407. Header() + "%main = OpFunction %void None %void_func\n" +
  3408. "%main_lab = OpLabel\n" +
  3409. "%n = OpVariable %_ptr_bool Function\n" +
  3410. "%m = OpVariable %_ptr_bool Function\n" +
  3411. "%load_n = OpLoad %bool %n\n" +
  3412. "%load_m = OpLoad %bool %m\n" +
  3413. "%2 = OpLogicalOr %bool %load_n %load_m\n" +
  3414. "OpReturn\n" +
  3415. "OpFunctionEnd",
  3416. 2, 0),
  3417. // Test case 19: Don't fold n && m
  3418. InstructionFoldingCase<uint32_t>(
  3419. Header() + "%main = OpFunction %void None %void_func\n" +
  3420. "%main_lab = OpLabel\n" +
  3421. "%n = OpVariable %_ptr_bool Function\n" +
  3422. "%m = OpVariable %_ptr_bool Function\n" +
  3423. "%load_n = OpLoad %bool %n\n" +
  3424. "%load_m = OpLoad %bool %m\n" +
  3425. "%2 = OpLogicalAnd %bool %load_n %load_m\n" +
  3426. "OpReturn\n" +
  3427. "OpFunctionEnd",
  3428. 2, 0),
  3429. // Test case 20: Don't fold n * 3
  3430. InstructionFoldingCase<uint32_t>(
  3431. Header() + "%main = OpFunction %void None %void_func\n" +
  3432. "%main_lab = OpLabel\n" +
  3433. "%n = OpVariable %_ptr_int Function\n" +
  3434. "%load_n = OpLoad %int %n\n" +
  3435. "%2 = OpIMul %int %load_n %int_3\n" +
  3436. "OpReturn\n" +
  3437. "OpFunctionEnd",
  3438. 2, 0),
  3439. // Test case 21: Don't fold n / 3 (unsigned)
  3440. InstructionFoldingCase<uint32_t>(
  3441. Header() + "%main = OpFunction %void None %void_func\n" +
  3442. "%main_lab = OpLabel\n" +
  3443. "%n = OpVariable %_ptr_uint Function\n" +
  3444. "%load_n = OpLoad %uint %n\n" +
  3445. "%2 = OpUDiv %uint %load_n %uint_3\n" +
  3446. "OpReturn\n" +
  3447. "OpFunctionEnd",
  3448. 2, 0),
  3449. // Test case 22: Don't fold n / 3 (signed)
  3450. InstructionFoldingCase<uint32_t>(
  3451. Header() + "%main = OpFunction %void None %void_func\n" +
  3452. "%main_lab = OpLabel\n" +
  3453. "%n = OpVariable %_ptr_int Function\n" +
  3454. "%load_n = OpLoad %int %n\n" +
  3455. "%2 = OpSDiv %int %load_n %int_3\n" +
  3456. "OpReturn\n" +
  3457. "OpFunctionEnd",
  3458. 2, 0),
  3459. // Test case 23: Don't fold n remainder 3
  3460. InstructionFoldingCase<uint32_t>(
  3461. Header() + "%main = OpFunction %void None %void_func\n" +
  3462. "%main_lab = OpLabel\n" +
  3463. "%n = OpVariable %_ptr_int Function\n" +
  3464. "%load_n = OpLoad %int %n\n" +
  3465. "%2 = OpSRem %int %load_n %int_3\n" +
  3466. "OpReturn\n" +
  3467. "OpFunctionEnd",
  3468. 2, 0),
  3469. // Test case 24: Don't fold n % 3 (signed)
  3470. InstructionFoldingCase<uint32_t>(
  3471. Header() + "%main = OpFunction %void None %void_func\n" +
  3472. "%main_lab = OpLabel\n" +
  3473. "%n = OpVariable %_ptr_int Function\n" +
  3474. "%load_n = OpLoad %int %n\n" +
  3475. "%2 = OpSMod %int %load_n %int_3\n" +
  3476. "OpReturn\n" +
  3477. "OpFunctionEnd",
  3478. 2, 0),
  3479. // Test case 25: Don't fold n % 3 (unsigned)
  3480. InstructionFoldingCase<uint32_t>(
  3481. Header() + "%main = OpFunction %void None %void_func\n" +
  3482. "%main_lab = OpLabel\n" +
  3483. "%n = OpVariable %_ptr_uint Function\n" +
  3484. "%load_n = OpLoad %uint %n\n" +
  3485. "%2 = OpUMod %int %load_n %int_3\n" +
  3486. "OpReturn\n" +
  3487. "OpFunctionEnd",
  3488. 2, 0),
  3489. // Test case 26: Don't fold n << 3
  3490. InstructionFoldingCase<uint32_t>(
  3491. Header() + "%main = OpFunction %void None %void_func\n" +
  3492. "%main_lab = OpLabel\n" +
  3493. "%n = OpVariable %_ptr_uint Function\n" +
  3494. "%load_n = OpLoad %uint %n\n" +
  3495. "%2 = OpShiftRightLogical %int %load_n %int_3\n" +
  3496. "OpReturn\n" +
  3497. "OpFunctionEnd",
  3498. 2, 0),
  3499. // Test case 27: Don't fold n >> 3
  3500. InstructionFoldingCase<uint32_t>(
  3501. Header() + "%main = OpFunction %void None %void_func\n" +
  3502. "%main_lab = OpLabel\n" +
  3503. "%n = OpVariable %_ptr_uint Function\n" +
  3504. "%load_n = OpLoad %uint %n\n" +
  3505. "%2 = OpShiftLeftLogical %int %load_n %int_3\n" +
  3506. "OpReturn\n" +
  3507. "OpFunctionEnd",
  3508. 2, 0),
  3509. // Test case 28: Don't fold n | 3
  3510. InstructionFoldingCase<uint32_t>(
  3511. Header() + "%main = OpFunction %void None %void_func\n" +
  3512. "%main_lab = OpLabel\n" +
  3513. "%n = OpVariable %_ptr_uint Function\n" +
  3514. "%load_n = OpLoad %uint %n\n" +
  3515. "%2 = OpBitwiseOr %int %load_n %int_3\n" +
  3516. "OpReturn\n" +
  3517. "OpFunctionEnd",
  3518. 2, 0),
  3519. // Test case 29: Don't fold n & 3
  3520. InstructionFoldingCase<uint32_t>(
  3521. Header() + "%main = OpFunction %void None %void_func\n" +
  3522. "%main_lab = OpLabel\n" +
  3523. "%n = OpVariable %_ptr_uint Function\n" +
  3524. "%load_n = OpLoad %uint %n\n" +
  3525. "%2 = OpBitwiseAnd %uint %load_n %uint_3\n" +
  3526. "OpReturn\n" +
  3527. "OpFunctionEnd",
  3528. 2, 0),
  3529. // Test case 30: Don't fold n < 3 (unsigned)
  3530. InstructionFoldingCase<uint32_t>(
  3531. Header() + "%main = OpFunction %void None %void_func\n" +
  3532. "%main_lab = OpLabel\n" +
  3533. "%n = OpVariable %_ptr_uint Function\n" +
  3534. "%load_n = OpLoad %uint %n\n" +
  3535. "%2 = OpULessThan %bool %load_n %uint_3\n" +
  3536. "OpReturn\n" +
  3537. "OpFunctionEnd",
  3538. 2, 0),
  3539. // Test case 31: Don't fold n > 3 (unsigned)
  3540. InstructionFoldingCase<uint32_t>(
  3541. Header() + "%main = OpFunction %void None %void_func\n" +
  3542. "%main_lab = OpLabel\n" +
  3543. "%n = OpVariable %_ptr_uint Function\n" +
  3544. "%load_n = OpLoad %uint %n\n" +
  3545. "%2 = OpUGreaterThan %bool %load_n %uint_3\n" +
  3546. "OpReturn\n" +
  3547. "OpFunctionEnd",
  3548. 2, 0),
  3549. // Test case 32: Don't fold n <= 3 (unsigned)
  3550. InstructionFoldingCase<uint32_t>(
  3551. Header() + "%main = OpFunction %void None %void_func\n" +
  3552. "%main_lab = OpLabel\n" +
  3553. "%n = OpVariable %_ptr_uint Function\n" +
  3554. "%load_n = OpLoad %uint %n\n" +
  3555. "%2 = OpULessThanEqual %bool %load_n %uint_3\n" +
  3556. "OpReturn\n" +
  3557. "OpFunctionEnd",
  3558. 2, 0),
  3559. // Test case 33: Don't fold n >= 3 (unsigned)
  3560. InstructionFoldingCase<uint32_t>(
  3561. Header() + "%main = OpFunction %void None %void_func\n" +
  3562. "%main_lab = OpLabel\n" +
  3563. "%n = OpVariable %_ptr_uint Function\n" +
  3564. "%load_n = OpLoad %uint %n\n" +
  3565. "%2 = OpUGreaterThanEqual %bool %load_n %uint_3\n" +
  3566. "OpReturn\n" +
  3567. "OpFunctionEnd",
  3568. 2, 0),
  3569. // Test case 34: Don't fold n < 3 (signed)
  3570. InstructionFoldingCase<uint32_t>(
  3571. Header() + "%main = OpFunction %void None %void_func\n" +
  3572. "%main_lab = OpLabel\n" +
  3573. "%n = OpVariable %_ptr_int Function\n" +
  3574. "%load_n = OpLoad %int %n\n" +
  3575. "%2 = OpULessThan %bool %load_n %int_3\n" +
  3576. "OpReturn\n" +
  3577. "OpFunctionEnd",
  3578. 2, 0),
  3579. // Test case 35: Don't fold n > 3 (signed)
  3580. InstructionFoldingCase<uint32_t>(
  3581. Header() + "%main = OpFunction %void None %void_func\n" +
  3582. "%main_lab = OpLabel\n" +
  3583. "%n = OpVariable %_ptr_int Function\n" +
  3584. "%load_n = OpLoad %int %n\n" +
  3585. "%2 = OpUGreaterThan %bool %load_n %int_3\n" +
  3586. "OpReturn\n" +
  3587. "OpFunctionEnd",
  3588. 2, 0),
  3589. // Test case 36: Don't fold n <= 3 (signed)
  3590. InstructionFoldingCase<uint32_t>(
  3591. Header() + "%main = OpFunction %void None %void_func\n" +
  3592. "%main_lab = OpLabel\n" +
  3593. "%n = OpVariable %_ptr_int Function\n" +
  3594. "%load_n = OpLoad %int %n\n" +
  3595. "%2 = OpULessThanEqual %bool %load_n %int_3\n" +
  3596. "OpReturn\n" +
  3597. "OpFunctionEnd",
  3598. 2, 0),
  3599. // Test case 37: Don't fold n >= 3 (signed)
  3600. InstructionFoldingCase<uint32_t>(
  3601. Header() + "%main = OpFunction %void None %void_func\n" +
  3602. "%main_lab = OpLabel\n" +
  3603. "%n = OpVariable %_ptr_int Function\n" +
  3604. "%load_n = OpLoad %int %n\n" +
  3605. "%2 = OpUGreaterThanEqual %bool %load_n %int_3\n" +
  3606. "OpReturn\n" +
  3607. "OpFunctionEnd",
  3608. 2, 0),
  3609. // Test case 38: Don't fold 2 + 3 (long), bad length
  3610. InstructionFoldingCase<uint32_t>(
  3611. Header() + "%main = OpFunction %void None %void_func\n" +
  3612. "%main_lab = OpLabel\n" +
  3613. "%2 = OpIAdd %long %long_2 %long_3\n" +
  3614. "OpReturn\n" +
  3615. "OpFunctionEnd",
  3616. 2, 0),
  3617. // Test case 39: Don't fold 2 + 3 (short), bad length
  3618. InstructionFoldingCase<uint32_t>(
  3619. Header() + "%main = OpFunction %void None %void_func\n" +
  3620. "%main_lab = OpLabel\n" +
  3621. "%2 = OpIAdd %short %short_2 %short_3\n" +
  3622. "OpReturn\n" +
  3623. "OpFunctionEnd",
  3624. 2, 0),
  3625. // Test case 40: fold 1*n
  3626. InstructionFoldingCase<uint32_t>(
  3627. Header() + "%main = OpFunction %void None %void_func\n" +
  3628. "%main_lab = OpLabel\n" +
  3629. "%n = OpVariable %_ptr_int Function\n" +
  3630. "%3 = OpLoad %int %n\n" +
  3631. "%2 = OpIMul %int %int_1 %3\n" +
  3632. "OpReturn\n" +
  3633. "OpFunctionEnd",
  3634. 2, 3),
  3635. // Test case 41: fold n*1
  3636. InstructionFoldingCase<uint32_t>(
  3637. Header() + "%main = OpFunction %void None %void_func\n" +
  3638. "%main_lab = OpLabel\n" +
  3639. "%n = OpVariable %_ptr_int Function\n" +
  3640. "%3 = OpLoad %int %n\n" +
  3641. "%2 = OpIMul %int %3 %int_1\n" +
  3642. "OpReturn\n" +
  3643. "OpFunctionEnd",
  3644. 2, 3),
  3645. // Test case 42: Don't fold comparisons of 64-bit types
  3646. // (https://github.com/KhronosGroup/SPIRV-Tools/issues/3343).
  3647. InstructionFoldingCase<uint32_t>(
  3648. Header() + "%main = OpFunction %void None %void_func\n" +
  3649. "%main_lab = OpLabel\n" +
  3650. "%2 = OpSLessThan %bool %long_0 %long_2\n" +
  3651. "OpReturn\n" +
  3652. "OpFunctionEnd",
  3653. 2, 0)
  3654. ));
  3655. INSTANTIATE_TEST_SUITE_P(CompositeExtractFoldingTest, GeneralInstructionFoldingTest,
  3656. ::testing::Values(
  3657. // Test case 0: fold Insert feeding extract
  3658. InstructionFoldingCase<uint32_t>(
  3659. Header() + "%main = OpFunction %void None %void_func\n" +
  3660. "%main_lab = OpLabel\n" +
  3661. "%n = OpVariable %_ptr_int Function\n" +
  3662. "%2 = OpLoad %int %n\n" +
  3663. "%3 = OpCompositeInsert %v4int %2 %v4int_0_0_0_0 0\n" +
  3664. "%4 = OpCompositeInsert %v4int %int_1 %3 1\n" +
  3665. "%5 = OpCompositeInsert %v4int %int_1 %4 2\n" +
  3666. "%6 = OpCompositeInsert %v4int %int_1 %5 3\n" +
  3667. "%7 = OpCompositeExtract %int %6 0\n" +
  3668. "OpReturn\n" +
  3669. "OpFunctionEnd",
  3670. 7, 2),
  3671. // Test case 1: fold Composite construct feeding extract (position 0)
  3672. InstructionFoldingCase<uint32_t>(
  3673. Header() + "%main = OpFunction %void None %void_func\n" +
  3674. "%main_lab = OpLabel\n" +
  3675. "%n = OpVariable %_ptr_int Function\n" +
  3676. "%2 = OpLoad %int %n\n" +
  3677. "%3 = OpCompositeConstruct %v4int %2 %int_0 %int_0 %int_0\n" +
  3678. "%4 = OpCompositeExtract %int %3 0\n" +
  3679. "OpReturn\n" +
  3680. "OpFunctionEnd",
  3681. 4, 2),
  3682. // Test case 2: fold Composite construct feeding extract (position 3)
  3683. InstructionFoldingCase<uint32_t>(
  3684. Header() + "%main = OpFunction %void None %void_func\n" +
  3685. "%main_lab = OpLabel\n" +
  3686. "%n = OpVariable %_ptr_int Function\n" +
  3687. "%2 = OpLoad %int %n\n" +
  3688. "%3 = OpCompositeConstruct %v4int %2 %int_0 %int_0 %100\n" +
  3689. "%4 = OpCompositeExtract %int %3 3\n" +
  3690. "OpReturn\n" +
  3691. "OpFunctionEnd",
  3692. 4, INT_0_ID),
  3693. // Test case 3: fold Composite construct with vectors feeding extract (scalar element)
  3694. InstructionFoldingCase<uint32_t>(
  3695. Header() + "%main = OpFunction %void None %void_func\n" +
  3696. "%main_lab = OpLabel\n" +
  3697. "%n = OpVariable %_ptr_int Function\n" +
  3698. "%2 = OpLoad %int %n\n" +
  3699. "%3 = OpCompositeConstruct %v2int %2 %int_0\n" +
  3700. "%4 = OpCompositeConstruct %v4int %3 %int_0 %100\n" +
  3701. "%5 = OpCompositeExtract %int %4 3\n" +
  3702. "OpReturn\n" +
  3703. "OpFunctionEnd",
  3704. 5, INT_0_ID),
  3705. // Test case 4: fold Composite construct with vectors feeding extract (start of vector element)
  3706. InstructionFoldingCase<uint32_t>(
  3707. Header() + "%main = OpFunction %void None %void_func\n" +
  3708. "%main_lab = OpLabel\n" +
  3709. "%n = OpVariable %_ptr_int Function\n" +
  3710. "%2 = OpLoad %int %n\n" +
  3711. "%3 = OpCompositeConstruct %v2int %2 %int_0\n" +
  3712. "%4 = OpCompositeConstruct %v4int %3 %int_0 %100\n" +
  3713. "%5 = OpCompositeExtract %int %4 0\n" +
  3714. "OpReturn\n" +
  3715. "OpFunctionEnd",
  3716. 5, 2),
  3717. // Test case 5: fold Composite construct with vectors feeding extract (middle of vector element)
  3718. InstructionFoldingCase<uint32_t>(
  3719. Header() + "%main = OpFunction %void None %void_func\n" +
  3720. "%main_lab = OpLabel\n" +
  3721. "%n = OpVariable %_ptr_int Function\n" +
  3722. "%2 = OpLoad %int %n\n" +
  3723. "%3 = OpCompositeConstruct %v2int %int_0 %2\n" +
  3724. "%4 = OpCompositeConstruct %v4int %3 %int_0 %100\n" +
  3725. "%5 = OpCompositeExtract %int %4 1\n" +
  3726. "OpReturn\n" +
  3727. "OpFunctionEnd",
  3728. 5, 2),
  3729. // Test case 6: fold Composite construct with multiple indices.
  3730. InstructionFoldingCase<uint32_t>(
  3731. Header() + "%main = OpFunction %void None %void_func\n" +
  3732. "%main_lab = OpLabel\n" +
  3733. "%n = OpVariable %_ptr_int Function\n" +
  3734. "%2 = OpLoad %int %n\n" +
  3735. "%3 = OpCompositeConstruct %v2int %int_0 %2\n" +
  3736. "%4 = OpCompositeConstruct %struct_v2int_int_int %3 %int_0 %100\n" +
  3737. "%5 = OpCompositeExtract %int %4 0 1\n" +
  3738. "OpReturn\n" +
  3739. "OpFunctionEnd",
  3740. 5, 2),
  3741. // Test case 7: fold constant extract.
  3742. InstructionFoldingCase<uint32_t>(
  3743. Header() + "%main = OpFunction %void None %void_func\n" +
  3744. "%main_lab = OpLabel\n" +
  3745. "%2 = OpCompositeExtract %int %102 1\n" +
  3746. "OpReturn\n" +
  3747. "OpFunctionEnd",
  3748. 2, INT_7_ID),
  3749. // Test case 8: constant struct has OpUndef
  3750. InstructionFoldingCase<uint32_t>(
  3751. Header() + "%main = OpFunction %void None %void_func\n" +
  3752. "%main_lab = OpLabel\n" +
  3753. "%2 = OpCompositeExtract %int %struct_undef_0_0 0 1\n" +
  3754. "OpReturn\n" +
  3755. "OpFunctionEnd",
  3756. 2, 0),
  3757. // Test case 9: Extracting a member of element inserted via Insert
  3758. InstructionFoldingCase<uint32_t>(
  3759. Header() + "%main = OpFunction %void None %void_func\n" +
  3760. "%main_lab = OpLabel\n" +
  3761. "%n = OpVariable %_ptr_struct_v2int_int_int Function\n" +
  3762. "%2 = OpLoad %struct_v2int_int_int %n\n" +
  3763. "%3 = OpCompositeInsert %struct_v2int_int_int %102 %2 0\n" +
  3764. "%4 = OpCompositeExtract %int %3 0 1\n" +
  3765. "OpReturn\n" +
  3766. "OpFunctionEnd",
  3767. 4, 103),
  3768. // Test case 10: Extracting a element that is partially changed by Insert. (Don't fold)
  3769. InstructionFoldingCase<uint32_t>(
  3770. Header() + "%main = OpFunction %void None %void_func\n" +
  3771. "%main_lab = OpLabel\n" +
  3772. "%n = OpVariable %_ptr_struct_v2int_int_int Function\n" +
  3773. "%2 = OpLoad %struct_v2int_int_int %n\n" +
  3774. "%3 = OpCompositeInsert %struct_v2int_int_int %int_0 %2 0 1\n" +
  3775. "%4 = OpCompositeExtract %v2int %3 0\n" +
  3776. "OpReturn\n" +
  3777. "OpFunctionEnd",
  3778. 4, 0),
  3779. // Test case 11: Extracting from result of vector shuffle (first input)
  3780. InstructionFoldingCase<uint32_t>(
  3781. Header() + "%main = OpFunction %void None %void_func\n" +
  3782. "%main_lab = OpLabel\n" +
  3783. "%n = OpVariable %_ptr_v2int Function\n" +
  3784. "%2 = OpLoad %v2int %n\n" +
  3785. "%3 = OpVectorShuffle %v2int %102 %2 3 0\n" +
  3786. "%4 = OpCompositeExtract %int %3 1\n" +
  3787. "OpReturn\n" +
  3788. "OpFunctionEnd",
  3789. 4, INT_7_ID),
  3790. // Test case 12: Extracting from result of vector shuffle (second input)
  3791. InstructionFoldingCase<uint32_t>(
  3792. Header() + "%main = OpFunction %void None %void_func\n" +
  3793. "%main_lab = OpLabel\n" +
  3794. "%n = OpVariable %_ptr_v2int Function\n" +
  3795. "%2 = OpLoad %v2int %n\n" +
  3796. "%3 = OpVectorShuffle %v2int %2 %102 2 0\n" +
  3797. "%4 = OpCompositeExtract %int %3 0\n" +
  3798. "OpReturn\n" +
  3799. "OpFunctionEnd",
  3800. 4, INT_7_ID),
  3801. // Test case 13: https://github.com/KhronosGroup/SPIRV-Tools/issues/2608
  3802. // Out of bounds access. Do not fold.
  3803. InstructionFoldingCase<uint32_t>(
  3804. Header() + "%main = OpFunction %void None %void_func\n" +
  3805. "%main_lab = OpLabel\n" +
  3806. "%2 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1\n" +
  3807. "%3 = OpCompositeExtract %float %2 4\n" +
  3808. "OpReturn\n" +
  3809. "OpFunctionEnd",
  3810. 3, 0),
  3811. // Test case 14: https://github.com/KhronosGroup/SPIRV-Tools/issues/3631
  3812. // Extract the component right after the vector constituent.
  3813. InstructionFoldingCase<uint32_t>(
  3814. Header() + "%main = OpFunction %void None %void_func\n" +
  3815. "%main_lab = OpLabel\n" +
  3816. "%2 = OpCompositeConstruct %v2int %int_0 %int_0\n" +
  3817. "%3 = OpCompositeConstruct %v4int %2 %100 %int_0\n" +
  3818. "%4 = OpCompositeExtract %int %3 2\n" +
  3819. "OpReturn\n" +
  3820. "OpFunctionEnd",
  3821. 4, INT_0_ID),
  3822. // Test case 15:
  3823. // Don't fold extract fed by construct with vector result if the index is
  3824. // past the last element.
  3825. InstructionFoldingCase<uint32_t>(
  3826. Header() + "%main = OpFunction %void None %void_func\n" +
  3827. "%main_lab = OpLabel\n" +
  3828. "%2 = OpCompositeConstruct %v2int %int_0 %int_0\n" +
  3829. "%3 = OpCompositeConstruct %v4int %2 %100 %int_0\n" +
  3830. "%4 = OpCompositeExtract %int %3 4\n" +
  3831. "OpReturn\n" +
  3832. "OpFunctionEnd",
  3833. 4, 0)
  3834. ));
  3835. INSTANTIATE_TEST_SUITE_P(CompositeConstructFoldingTest, GeneralInstructionFoldingTest,
  3836. ::testing::Values(
  3837. // Test case 0: fold Extracts feeding construct
  3838. InstructionFoldingCase<uint32_t>(
  3839. Header() + "%main = OpFunction %void None %void_func\n" +
  3840. "%main_lab = OpLabel\n" +
  3841. "%2 = OpCopyObject %v4int %v4int_0_0_0_0\n" +
  3842. "%3 = OpCompositeExtract %int %2 0\n" +
  3843. "%4 = OpCompositeExtract %int %2 1\n" +
  3844. "%5 = OpCompositeExtract %int %2 2\n" +
  3845. "%6 = OpCompositeExtract %int %2 3\n" +
  3846. "%7 = OpCompositeConstruct %v4int %3 %4 %5 %6\n" +
  3847. "OpReturn\n" +
  3848. "OpFunctionEnd",
  3849. 7, 2),
  3850. // Test case 1: Don't fold Extracts feeding construct (Different source)
  3851. InstructionFoldingCase<uint32_t>(
  3852. Header() + "%main = OpFunction %void None %void_func\n" +
  3853. "%main_lab = OpLabel\n" +
  3854. "%2 = OpCopyObject %v4int %v4int_0_0_0_0\n" +
  3855. "%3 = OpCompositeExtract %int %2 0\n" +
  3856. "%4 = OpCompositeExtract %int %2 1\n" +
  3857. "%5 = OpCompositeExtract %int %2 2\n" +
  3858. "%6 = OpCompositeExtract %int %v4int_0_0_0_0 3\n" +
  3859. "%7 = OpCompositeConstruct %v4int %3 %4 %5 %6\n" +
  3860. "OpReturn\n" +
  3861. "OpFunctionEnd",
  3862. 7, 0),
  3863. // Test case 2: Don't fold Extracts feeding construct (bad indices)
  3864. InstructionFoldingCase<uint32_t>(
  3865. Header() + "%main = OpFunction %void None %void_func\n" +
  3866. "%main_lab = OpLabel\n" +
  3867. "%2 = OpCopyObject %v4int %v4int_0_0_0_0\n" +
  3868. "%3 = OpCompositeExtract %int %2 0\n" +
  3869. "%4 = OpCompositeExtract %int %2 0\n" +
  3870. "%5 = OpCompositeExtract %int %2 2\n" +
  3871. "%6 = OpCompositeExtract %int %2 3\n" +
  3872. "%7 = OpCompositeConstruct %v4int %3 %4 %5 %6\n" +
  3873. "OpReturn\n" +
  3874. "OpFunctionEnd",
  3875. 7, 0),
  3876. // Test case 3: Don't fold Extracts feeding construct (different type)
  3877. InstructionFoldingCase<uint32_t>(
  3878. Header() + "%main = OpFunction %void None %void_func\n" +
  3879. "%main_lab = OpLabel\n" +
  3880. "%2 = OpCopyObject %struct_v2int_int_int %struct_v2int_int_int_null\n" +
  3881. "%3 = OpCompositeExtract %v2int %2 0\n" +
  3882. "%4 = OpCompositeExtract %int %2 1\n" +
  3883. "%5 = OpCompositeExtract %int %2 2\n" +
  3884. "%7 = OpCompositeConstruct %v4int %3 %4 %5\n" +
  3885. "OpReturn\n" +
  3886. "OpFunctionEnd",
  3887. 7, 0),
  3888. // Test case 4: Fold construct with constants to constant.
  3889. InstructionFoldingCase<uint32_t>(
  3890. Header() + "%main = OpFunction %void None %void_func\n" +
  3891. "%main_lab = OpLabel\n" +
  3892. "%2 = OpCompositeConstruct %v2int %103 %103\n" +
  3893. "OpReturn\n" +
  3894. "OpFunctionEnd",
  3895. 2, VEC2_0_ID),
  3896. // Test case 5: Don't segfault when trying to fold an OpCompositeConstruct
  3897. // for an empty struct, and we reached the id limit.
  3898. InstructionFoldingCase<uint32_t>(
  3899. Header() + "%empty_struct = OpTypeStruct\n" +
  3900. "%main = OpFunction %void None %void_func\n" +
  3901. "%main_lab = OpLabel\n" +
  3902. "%4194303 = OpCompositeConstruct %empty_struct\n" +
  3903. "OpReturn\n" +
  3904. "OpFunctionEnd",
  3905. 4194303, 0)
  3906. ));
  3907. INSTANTIATE_TEST_SUITE_P(PhiFoldingTest, GeneralInstructionFoldingTest,
  3908. ::testing::Values(
  3909. // Test case 0: Fold phi with the same values for all edges.
  3910. InstructionFoldingCase<uint32_t>(
  3911. Header() + "%main = OpFunction %void None %void_func\n" +
  3912. "%main_lab = OpLabel\n" +
  3913. " OpBranchConditional %true %l1 %l2\n" +
  3914. "%l1 = OpLabel\n" +
  3915. " OpBranch %merge_lab\n" +
  3916. "%l2 = OpLabel\n" +
  3917. " OpBranch %merge_lab\n" +
  3918. "%merge_lab = OpLabel\n" +
  3919. "%2 = OpPhi %int %100 %l1 %100 %l2\n" +
  3920. "OpReturn\n" +
  3921. "OpFunctionEnd",
  3922. 2, INT_0_ID),
  3923. // Test case 1: Fold phi in pass through loop.
  3924. InstructionFoldingCase<uint32_t>(
  3925. Header() + "%main = OpFunction %void None %void_func\n" +
  3926. "%main_lab = OpLabel\n" +
  3927. " OpBranch %l1\n" +
  3928. "%l1 = OpLabel\n" +
  3929. "%2 = OpPhi %int %100 %main_lab %2 %l1\n" +
  3930. " OpBranchConditional %true %l1 %merge_lab\n" +
  3931. "%merge_lab = OpLabel\n" +
  3932. "OpReturn\n" +
  3933. "OpFunctionEnd",
  3934. 2, INT_0_ID),
  3935. // Test case 2: Don't Fold phi because of different values.
  3936. InstructionFoldingCase<uint32_t>(
  3937. Header() + "%main = OpFunction %void None %void_func\n" +
  3938. "%main_lab = OpLabel\n" +
  3939. " OpBranch %l1\n" +
  3940. "%l1 = OpLabel\n" +
  3941. "%2 = OpPhi %int %int_0 %main_lab %int_3 %l1\n" +
  3942. " OpBranchConditional %true %l1 %merge_lab\n" +
  3943. "%merge_lab = OpLabel\n" +
  3944. "OpReturn\n" +
  3945. "OpFunctionEnd",
  3946. 2, 0)
  3947. ));
  3948. INSTANTIATE_TEST_SUITE_P(FloatRedundantFoldingTest, GeneralInstructionFoldingTest,
  3949. ::testing::Values(
  3950. // Test case 0: Don't fold n + 1.0
  3951. InstructionFoldingCase<uint32_t>(
  3952. Header() + "%main = OpFunction %void None %void_func\n" +
  3953. "%main_lab = OpLabel\n" +
  3954. "%n = OpVariable %_ptr_float Function\n" +
  3955. "%3 = OpLoad %float %n\n" +
  3956. "%2 = OpFAdd %float %3 %float_2\n" +
  3957. "OpReturn\n" +
  3958. "OpFunctionEnd",
  3959. 2, 0),
  3960. // Test case 1: Don't fold n - 1.0
  3961. InstructionFoldingCase<uint32_t>(
  3962. Header() + "%main = OpFunction %void None %void_func\n" +
  3963. "%main_lab = OpLabel\n" +
  3964. "%n = OpVariable %_ptr_float Function\n" +
  3965. "%3 = OpLoad %float %n\n" +
  3966. "%2 = OpFSub %float %3 %float_2\n" +
  3967. "OpReturn\n" +
  3968. "OpFunctionEnd",
  3969. 2, 0),
  3970. // Test case 2: Don't fold n * 2.0
  3971. InstructionFoldingCase<uint32_t>(
  3972. Header() + "%main = OpFunction %void None %void_func\n" +
  3973. "%main_lab = OpLabel\n" +
  3974. "%n = OpVariable %_ptr_float Function\n" +
  3975. "%3 = OpLoad %float %n\n" +
  3976. "%2 = OpFMul %float %3 %float_2\n" +
  3977. "OpReturn\n" +
  3978. "OpFunctionEnd",
  3979. 2, 0),
  3980. // Test case 3: Fold n + 0.0
  3981. InstructionFoldingCase<uint32_t>(
  3982. Header() + "%main = OpFunction %void None %void_func\n" +
  3983. "%main_lab = OpLabel\n" +
  3984. "%n = OpVariable %_ptr_float Function\n" +
  3985. "%3 = OpLoad %float %n\n" +
  3986. "%2 = OpFAdd %float %3 %float_0\n" +
  3987. "OpReturn\n" +
  3988. "OpFunctionEnd",
  3989. 2, 3),
  3990. // Test case 4: Fold 0.0 + n
  3991. InstructionFoldingCase<uint32_t>(
  3992. Header() + "%main = OpFunction %void None %void_func\n" +
  3993. "%main_lab = OpLabel\n" +
  3994. "%n = OpVariable %_ptr_float Function\n" +
  3995. "%3 = OpLoad %float %n\n" +
  3996. "%2 = OpFAdd %float %float_0 %3\n" +
  3997. "OpReturn\n" +
  3998. "OpFunctionEnd",
  3999. 2, 3),
  4000. // Test case 5: Fold n - 0.0
  4001. InstructionFoldingCase<uint32_t>(
  4002. Header() + "%main = OpFunction %void None %void_func\n" +
  4003. "%main_lab = OpLabel\n" +
  4004. "%n = OpVariable %_ptr_float Function\n" +
  4005. "%3 = OpLoad %float %n\n" +
  4006. "%2 = OpFSub %float %3 %float_0\n" +
  4007. "OpReturn\n" +
  4008. "OpFunctionEnd",
  4009. 2, 3),
  4010. // Test case 6: Fold n * 1.0
  4011. InstructionFoldingCase<uint32_t>(
  4012. Header() + "%main = OpFunction %void None %void_func\n" +
  4013. "%main_lab = OpLabel\n" +
  4014. "%n = OpVariable %_ptr_float Function\n" +
  4015. "%3 = OpLoad %float %n\n" +
  4016. "%2 = OpFMul %float %3 %float_1\n" +
  4017. "OpReturn\n" +
  4018. "OpFunctionEnd",
  4019. 2, 3),
  4020. // Test case 7: Fold 1.0 * n
  4021. InstructionFoldingCase<uint32_t>(
  4022. Header() + "%main = OpFunction %void None %void_func\n" +
  4023. "%main_lab = OpLabel\n" +
  4024. "%n = OpVariable %_ptr_float Function\n" +
  4025. "%3 = OpLoad %float %n\n" +
  4026. "%2 = OpFMul %float %float_1 %3\n" +
  4027. "OpReturn\n" +
  4028. "OpFunctionEnd",
  4029. 2, 3),
  4030. // Test case 8: Fold n / 1.0
  4031. InstructionFoldingCase<uint32_t>(
  4032. Header() + "%main = OpFunction %void None %void_func\n" +
  4033. "%main_lab = OpLabel\n" +
  4034. "%n = OpVariable %_ptr_float Function\n" +
  4035. "%3 = OpLoad %float %n\n" +
  4036. "%2 = OpFDiv %float %3 %float_1\n" +
  4037. "OpReturn\n" +
  4038. "OpFunctionEnd",
  4039. 2, 3),
  4040. // Test case 9: Fold n * 0.0
  4041. InstructionFoldingCase<uint32_t>(
  4042. Header() + "%main = OpFunction %void None %void_func\n" +
  4043. "%main_lab = OpLabel\n" +
  4044. "%n = OpVariable %_ptr_float Function\n" +
  4045. "%3 = OpLoad %float %n\n" +
  4046. "%2 = OpFMul %float %3 %104\n" +
  4047. "OpReturn\n" +
  4048. "OpFunctionEnd",
  4049. 2, FLOAT_0_ID),
  4050. // Test case 10: Fold 0.0 * n
  4051. InstructionFoldingCase<uint32_t>(
  4052. Header() + "%main = OpFunction %void None %void_func\n" +
  4053. "%main_lab = OpLabel\n" +
  4054. "%n = OpVariable %_ptr_float Function\n" +
  4055. "%3 = OpLoad %float %n\n" +
  4056. "%2 = OpFMul %float %104 %3\n" +
  4057. "OpReturn\n" +
  4058. "OpFunctionEnd",
  4059. 2, FLOAT_0_ID),
  4060. // Test case 11: Fold 0.0 / n
  4061. InstructionFoldingCase<uint32_t>(
  4062. Header() + "%main = OpFunction %void None %void_func\n" +
  4063. "%main_lab = OpLabel\n" +
  4064. "%n = OpVariable %_ptr_float Function\n" +
  4065. "%3 = OpLoad %float %n\n" +
  4066. "%2 = OpFDiv %float %104 %3\n" +
  4067. "OpReturn\n" +
  4068. "OpFunctionEnd",
  4069. 2, FLOAT_0_ID),
  4070. // Test case 12: Don't fold mix(a, b, 2.0)
  4071. InstructionFoldingCase<uint32_t>(
  4072. Header() + "%main = OpFunction %void None %void_func\n" +
  4073. "%main_lab = OpLabel\n" +
  4074. "%a = OpVariable %_ptr_float Function\n" +
  4075. "%b = OpVariable %_ptr_float Function\n" +
  4076. "%3 = OpLoad %float %a\n" +
  4077. "%4 = OpLoad %float %b\n" +
  4078. "%2 = OpExtInst %float %1 FMix %3 %4 %float_2\n" +
  4079. "OpReturn\n" +
  4080. "OpFunctionEnd",
  4081. 2, 0),
  4082. // Test case 13: Fold mix(a, b, 0.0)
  4083. InstructionFoldingCase<uint32_t>(
  4084. Header() + "%main = OpFunction %void None %void_func\n" +
  4085. "%main_lab = OpLabel\n" +
  4086. "%a = OpVariable %_ptr_float Function\n" +
  4087. "%b = OpVariable %_ptr_float Function\n" +
  4088. "%3 = OpLoad %float %a\n" +
  4089. "%4 = OpLoad %float %b\n" +
  4090. "%2 = OpExtInst %float %1 FMix %3 %4 %float_0\n" +
  4091. "OpReturn\n" +
  4092. "OpFunctionEnd",
  4093. 2, 3),
  4094. // Test case 14: Fold mix(a, b, 1.0)
  4095. InstructionFoldingCase<uint32_t>(
  4096. Header() + "%main = OpFunction %void None %void_func\n" +
  4097. "%main_lab = OpLabel\n" +
  4098. "%a = OpVariable %_ptr_float Function\n" +
  4099. "%b = OpVariable %_ptr_float Function\n" +
  4100. "%3 = OpLoad %float %a\n" +
  4101. "%4 = OpLoad %float %b\n" +
  4102. "%2 = OpExtInst %float %1 FMix %3 %4 %float_1\n" +
  4103. "OpReturn\n" +
  4104. "OpFunctionEnd",
  4105. 2, 4),
  4106. // Test case 15: Fold vector fadd with null
  4107. InstructionFoldingCase<uint32_t>(
  4108. Header() + "%main = OpFunction %void None %void_func\n" +
  4109. "%main_lab = OpLabel\n" +
  4110. "%a = OpVariable %_ptr_v2float Function\n" +
  4111. "%2 = OpLoad %v2float %a\n" +
  4112. "%3 = OpFAdd %v2float %2 %v2float_null\n" +
  4113. "OpReturn\n" +
  4114. "OpFunctionEnd",
  4115. 3, 2),
  4116. // Test case 16: Fold vector fadd with null
  4117. InstructionFoldingCase<uint32_t>(
  4118. Header() + "%main = OpFunction %void None %void_func\n" +
  4119. "%main_lab = OpLabel\n" +
  4120. "%a = OpVariable %_ptr_v2float Function\n" +
  4121. "%2 = OpLoad %v2float %a\n" +
  4122. "%3 = OpFAdd %v2float %v2float_null %2\n" +
  4123. "OpReturn\n" +
  4124. "OpFunctionEnd",
  4125. 3, 2),
  4126. // Test case 17: Fold vector fsub with null
  4127. InstructionFoldingCase<uint32_t>(
  4128. Header() + "%main = OpFunction %void None %void_func\n" +
  4129. "%main_lab = OpLabel\n" +
  4130. "%a = OpVariable %_ptr_v2float Function\n" +
  4131. "%2 = OpLoad %v2float %a\n" +
  4132. "%3 = OpFSub %v2float %2 %v2float_null\n" +
  4133. "OpReturn\n" +
  4134. "OpFunctionEnd",
  4135. 3, 2),
  4136. // Test case 18: Fold 0.0(half) * n
  4137. InstructionFoldingCase<uint32_t>(
  4138. Header() + "%main = OpFunction %void None %void_func\n" +
  4139. "%main_lab = OpLabel\n" +
  4140. "%n = OpVariable %_ptr_half Function\n" +
  4141. "%3 = OpLoad %half %n\n" +
  4142. "%2 = OpFMul %half %108 %3\n" +
  4143. "OpReturn\n" +
  4144. "OpFunctionEnd",
  4145. 2, HALF_0_ID),
  4146. // Test case 19: Don't fold 1.0(half) * n
  4147. InstructionFoldingCase<uint32_t>(
  4148. Header() + "%main = OpFunction %void None %void_func\n" +
  4149. "%main_lab = OpLabel\n" +
  4150. "%n = OpVariable %_ptr_half Function\n" +
  4151. "%3 = OpLoad %half %n\n" +
  4152. "%2 = OpFMul %half %half_1 %3\n" +
  4153. "OpReturn\n" +
  4154. "OpFunctionEnd",
  4155. 2, 0),
  4156. // Test case 20: Don't fold 1.0 * 1.0 (half)
  4157. InstructionFoldingCase<uint32_t>(
  4158. Header() + "%main = OpFunction %void None %void_func\n" +
  4159. "%main_lab = OpLabel\n" +
  4160. "%2 = OpFMul %half %half_1 %half_1\n" +
  4161. "OpReturn\n" +
  4162. "OpFunctionEnd",
  4163. 2, 0),
  4164. // Test case 21: Don't fold (0.0, 1.0) * (0.0, 1.0) (half)
  4165. InstructionFoldingCase<uint32_t>(
  4166. Header() + "%main = OpFunction %void None %void_func\n" +
  4167. "%main_lab = OpLabel\n" +
  4168. "%2 = OpFMul %v2half %half_0_1 %half_0_1\n" +
  4169. "OpReturn\n" +
  4170. "OpFunctionEnd",
  4171. 2, 0),
  4172. // Test case 22: Don't fold (0.0, 1.0) dotp (0.0, 1.0) (half)
  4173. InstructionFoldingCase<uint32_t>(
  4174. Header() + "%main = OpFunction %void None %void_func\n" +
  4175. "%main_lab = OpLabel\n" +
  4176. "%2 = OpDot %half %half_0_1 %half_0_1\n" +
  4177. "OpReturn\n" +
  4178. "OpFunctionEnd",
  4179. 2, 0)
  4180. ));
  4181. INSTANTIATE_TEST_SUITE_P(DoubleRedundantFoldingTest, GeneralInstructionFoldingTest,
  4182. ::testing::Values(
  4183. // Test case 0: Don't fold n + 1.0
  4184. InstructionFoldingCase<uint32_t>(
  4185. Header() + "%main = OpFunction %void None %void_func\n" +
  4186. "%main_lab = OpLabel\n" +
  4187. "%n = OpVariable %_ptr_double Function\n" +
  4188. "%3 = OpLoad %double %n\n" +
  4189. "%2 = OpFAdd %double %3 %double_2\n" +
  4190. "OpReturn\n" +
  4191. "OpFunctionEnd",
  4192. 2, 0),
  4193. // Test case 1: Don't fold n - 1.0
  4194. InstructionFoldingCase<uint32_t>(
  4195. Header() + "%main = OpFunction %void None %void_func\n" +
  4196. "%main_lab = OpLabel\n" +
  4197. "%n = OpVariable %_ptr_double Function\n" +
  4198. "%3 = OpLoad %double %n\n" +
  4199. "%2 = OpFSub %double %3 %double_2\n" +
  4200. "OpReturn\n" +
  4201. "OpFunctionEnd",
  4202. 2, 0),
  4203. // Test case 2: Don't fold n * 2.0
  4204. InstructionFoldingCase<uint32_t>(
  4205. Header() + "%main = OpFunction %void None %void_func\n" +
  4206. "%main_lab = OpLabel\n" +
  4207. "%n = OpVariable %_ptr_double Function\n" +
  4208. "%3 = OpLoad %double %n\n" +
  4209. "%2 = OpFMul %double %3 %double_2\n" +
  4210. "OpReturn\n" +
  4211. "OpFunctionEnd",
  4212. 2, 0),
  4213. // Test case 3: Fold n + 0.0
  4214. InstructionFoldingCase<uint32_t>(
  4215. Header() + "%main = OpFunction %void None %void_func\n" +
  4216. "%main_lab = OpLabel\n" +
  4217. "%n = OpVariable %_ptr_double Function\n" +
  4218. "%3 = OpLoad %double %n\n" +
  4219. "%2 = OpFAdd %double %3 %double_0\n" +
  4220. "OpReturn\n" +
  4221. "OpFunctionEnd",
  4222. 2, 3),
  4223. // Test case 4: Fold 0.0 + n
  4224. InstructionFoldingCase<uint32_t>(
  4225. Header() + "%main = OpFunction %void None %void_func\n" +
  4226. "%main_lab = OpLabel\n" +
  4227. "%n = OpVariable %_ptr_double Function\n" +
  4228. "%3 = OpLoad %double %n\n" +
  4229. "%2 = OpFAdd %double %double_0 %3\n" +
  4230. "OpReturn\n" +
  4231. "OpFunctionEnd",
  4232. 2, 3),
  4233. // Test case 5: Fold n - 0.0
  4234. InstructionFoldingCase<uint32_t>(
  4235. Header() + "%main = OpFunction %void None %void_func\n" +
  4236. "%main_lab = OpLabel\n" +
  4237. "%n = OpVariable %_ptr_double Function\n" +
  4238. "%3 = OpLoad %double %n\n" +
  4239. "%2 = OpFSub %double %3 %double_0\n" +
  4240. "OpReturn\n" +
  4241. "OpFunctionEnd",
  4242. 2, 3),
  4243. // Test case 6: Fold n * 1.0
  4244. InstructionFoldingCase<uint32_t>(
  4245. Header() + "%main = OpFunction %void None %void_func\n" +
  4246. "%main_lab = OpLabel\n" +
  4247. "%n = OpVariable %_ptr_double Function\n" +
  4248. "%3 = OpLoad %double %n\n" +
  4249. "%2 = OpFMul %double %3 %double_1\n" +
  4250. "OpReturn\n" +
  4251. "OpFunctionEnd",
  4252. 2, 3),
  4253. // Test case 7: Fold 1.0 * n
  4254. InstructionFoldingCase<uint32_t>(
  4255. Header() + "%main = OpFunction %void None %void_func\n" +
  4256. "%main_lab = OpLabel\n" +
  4257. "%n = OpVariable %_ptr_double Function\n" +
  4258. "%3 = OpLoad %double %n\n" +
  4259. "%2 = OpFMul %double %double_1 %3\n" +
  4260. "OpReturn\n" +
  4261. "OpFunctionEnd",
  4262. 2, 3),
  4263. // Test case 8: Fold n / 1.0
  4264. InstructionFoldingCase<uint32_t>(
  4265. Header() + "%main = OpFunction %void None %void_func\n" +
  4266. "%main_lab = OpLabel\n" +
  4267. "%n = OpVariable %_ptr_double Function\n" +
  4268. "%3 = OpLoad %double %n\n" +
  4269. "%2 = OpFDiv %double %3 %double_1\n" +
  4270. "OpReturn\n" +
  4271. "OpFunctionEnd",
  4272. 2, 3),
  4273. // Test case 9: Fold n * 0.0
  4274. InstructionFoldingCase<uint32_t>(
  4275. Header() + "%main = OpFunction %void None %void_func\n" +
  4276. "%main_lab = OpLabel\n" +
  4277. "%n = OpVariable %_ptr_double Function\n" +
  4278. "%3 = OpLoad %double %n\n" +
  4279. "%2 = OpFMul %double %3 %105\n" +
  4280. "OpReturn\n" +
  4281. "OpFunctionEnd",
  4282. 2, DOUBLE_0_ID),
  4283. // Test case 10: Fold 0.0 * n
  4284. InstructionFoldingCase<uint32_t>(
  4285. Header() + "%main = OpFunction %void None %void_func\n" +
  4286. "%main_lab = OpLabel\n" +
  4287. "%n = OpVariable %_ptr_double Function\n" +
  4288. "%3 = OpLoad %double %n\n" +
  4289. "%2 = OpFMul %double %105 %3\n" +
  4290. "OpReturn\n" +
  4291. "OpFunctionEnd",
  4292. 2, DOUBLE_0_ID),
  4293. // Test case 11: Fold 0.0 / n
  4294. InstructionFoldingCase<uint32_t>(
  4295. Header() + "%main = OpFunction %void None %void_func\n" +
  4296. "%main_lab = OpLabel\n" +
  4297. "%n = OpVariable %_ptr_double Function\n" +
  4298. "%3 = OpLoad %double %n\n" +
  4299. "%2 = OpFDiv %double %105 %3\n" +
  4300. "OpReturn\n" +
  4301. "OpFunctionEnd",
  4302. 2, DOUBLE_0_ID),
  4303. // Test case 12: Don't fold mix(a, b, 2.0)
  4304. InstructionFoldingCase<uint32_t>(
  4305. Header() + "%main = OpFunction %void None %void_func\n" +
  4306. "%main_lab = OpLabel\n" +
  4307. "%a = OpVariable %_ptr_double Function\n" +
  4308. "%b = OpVariable %_ptr_double Function\n" +
  4309. "%3 = OpLoad %double %a\n" +
  4310. "%4 = OpLoad %double %b\n" +
  4311. "%2 = OpExtInst %double %1 FMix %3 %4 %double_2\n" +
  4312. "OpReturn\n" +
  4313. "OpFunctionEnd",
  4314. 2, 0),
  4315. // Test case 13: Fold mix(a, b, 0.0)
  4316. InstructionFoldingCase<uint32_t>(
  4317. Header() + "%main = OpFunction %void None %void_func\n" +
  4318. "%main_lab = OpLabel\n" +
  4319. "%a = OpVariable %_ptr_double Function\n" +
  4320. "%b = OpVariable %_ptr_double Function\n" +
  4321. "%3 = OpLoad %double %a\n" +
  4322. "%4 = OpLoad %double %b\n" +
  4323. "%2 = OpExtInst %double %1 FMix %3 %4 %double_0\n" +
  4324. "OpReturn\n" +
  4325. "OpFunctionEnd",
  4326. 2, 3),
  4327. // Test case 14: Fold mix(a, b, 1.0)
  4328. InstructionFoldingCase<uint32_t>(
  4329. Header() + "%main = OpFunction %void None %void_func\n" +
  4330. "%main_lab = OpLabel\n" +
  4331. "%a = OpVariable %_ptr_double Function\n" +
  4332. "%b = OpVariable %_ptr_double Function\n" +
  4333. "%3 = OpLoad %double %a\n" +
  4334. "%4 = OpLoad %double %b\n" +
  4335. "%2 = OpExtInst %double %1 FMix %3 %4 %double_1\n" +
  4336. "OpReturn\n" +
  4337. "OpFunctionEnd",
  4338. 2, 4)
  4339. ));
  4340. INSTANTIATE_TEST_SUITE_P(FloatVectorRedundantFoldingTest, GeneralInstructionFoldingTest,
  4341. ::testing::Values(
  4342. // Test case 0: Don't fold a * vec4(0.0, 0.0, 0.0, 1.0)
  4343. InstructionFoldingCase<uint32_t>(
  4344. Header() + "%main = OpFunction %void None %void_func\n" +
  4345. "%main_lab = OpLabel\n" +
  4346. "%n = OpVariable %_ptr_v4float Function\n" +
  4347. "%3 = OpLoad %v4float %n\n" +
  4348. "%2 = OpFMul %v4float %3 %v4float_0_0_0_1\n" +
  4349. "OpReturn\n" +
  4350. "OpFunctionEnd",
  4351. 2, 0),
  4352. // Test case 1: Fold a * vec4(0.0, 0.0, 0.0, 0.0)
  4353. InstructionFoldingCase<uint32_t>(
  4354. Header() + "%main = OpFunction %void None %void_func\n" +
  4355. "%main_lab = OpLabel\n" +
  4356. "%n = OpVariable %_ptr_v4float Function\n" +
  4357. "%3 = OpLoad %v4float %n\n" +
  4358. "%2 = OpFMul %v4float %3 %106\n" +
  4359. "OpReturn\n" +
  4360. "OpFunctionEnd",
  4361. 2, VEC4_0_ID),
  4362. // Test case 2: Fold a * vec4(1.0, 1.0, 1.0, 1.0)
  4363. InstructionFoldingCase<uint32_t>(
  4364. Header() + "%main = OpFunction %void None %void_func\n" +
  4365. "%main_lab = OpLabel\n" +
  4366. "%n = OpVariable %_ptr_v4float Function\n" +
  4367. "%3 = OpLoad %v4float %n\n" +
  4368. "%2 = OpFMul %v4float %3 %v4float_1_1_1_1\n" +
  4369. "OpReturn\n" +
  4370. "OpFunctionEnd",
  4371. 2, 3)
  4372. ));
  4373. INSTANTIATE_TEST_SUITE_P(DoubleVectorRedundantFoldingTest, GeneralInstructionFoldingTest,
  4374. ::testing::Values(
  4375. // Test case 0: Don't fold a * vec4(0.0, 0.0, 0.0, 1.0)
  4376. InstructionFoldingCase<uint32_t>(
  4377. Header() + "%main = OpFunction %void None %void_func\n" +
  4378. "%main_lab = OpLabel\n" +
  4379. "%n = OpVariable %_ptr_v4double Function\n" +
  4380. "%3 = OpLoad %v4double %n\n" +
  4381. "%2 = OpFMul %v4double %3 %v4double_0_0_0_1\n" +
  4382. "OpReturn\n" +
  4383. "OpFunctionEnd",
  4384. 2, 0),
  4385. // Test case 1: Fold a * vec4(0.0, 0.0, 0.0, 0.0)
  4386. InstructionFoldingCase<uint32_t>(
  4387. Header() + "%main = OpFunction %void None %void_func\n" +
  4388. "%main_lab = OpLabel\n" +
  4389. "%n = OpVariable %_ptr_v4double Function\n" +
  4390. "%3 = OpLoad %v4double %n\n" +
  4391. "%2 = OpFMul %v4double %3 %106\n" +
  4392. "OpReturn\n" +
  4393. "OpFunctionEnd",
  4394. 2, DVEC4_0_ID),
  4395. // Test case 2: Fold a * vec4(1.0, 1.0, 1.0, 1.0)
  4396. InstructionFoldingCase<uint32_t>(
  4397. Header() + "%main = OpFunction %void None %void_func\n" +
  4398. "%main_lab = OpLabel\n" +
  4399. "%n = OpVariable %_ptr_v4double Function\n" +
  4400. "%3 = OpLoad %v4double %n\n" +
  4401. "%2 = OpFMul %v4double %3 %v4double_1_1_1_1\n" +
  4402. "OpReturn\n" +
  4403. "OpFunctionEnd",
  4404. 2, 3)
  4405. ));
  4406. INSTANTIATE_TEST_SUITE_P(IntegerRedundantFoldingTest, GeneralInstructionFoldingTest,
  4407. ::testing::Values(
  4408. // Test case 0: Don't fold n + 1
  4409. InstructionFoldingCase<uint32_t>(
  4410. Header() + "%main = OpFunction %void None %void_func\n" +
  4411. "%main_lab = OpLabel\n" +
  4412. "%n = OpVariable %_ptr_uint Function\n" +
  4413. "%3 = OpLoad %uint %n\n" +
  4414. "%2 = OpIAdd %uint %3 %uint_1\n" +
  4415. "OpReturn\n" +
  4416. "OpFunctionEnd",
  4417. 2, 0),
  4418. // Test case 1: Don't fold 1 + n
  4419. InstructionFoldingCase<uint32_t>(
  4420. Header() + "%main = OpFunction %void None %void_func\n" +
  4421. "%main_lab = OpLabel\n" +
  4422. "%n = OpVariable %_ptr_uint Function\n" +
  4423. "%3 = OpLoad %uint %n\n" +
  4424. "%2 = OpIAdd %uint %uint_1 %3\n" +
  4425. "OpReturn\n" +
  4426. "OpFunctionEnd",
  4427. 2, 0),
  4428. // Test case 2: Fold n + 0
  4429. InstructionFoldingCase<uint32_t>(
  4430. Header() + "%main = OpFunction %void None %void_func\n" +
  4431. "%main_lab = OpLabel\n" +
  4432. "%n = OpVariable %_ptr_uint Function\n" +
  4433. "%3 = OpLoad %uint %n\n" +
  4434. "%2 = OpIAdd %uint %3 %uint_0\n" +
  4435. "OpReturn\n" +
  4436. "OpFunctionEnd",
  4437. 2, 3),
  4438. // Test case 3: Fold 0 + n
  4439. InstructionFoldingCase<uint32_t>(
  4440. Header() + "%main = OpFunction %void None %void_func\n" +
  4441. "%main_lab = OpLabel\n" +
  4442. "%n = OpVariable %_ptr_uint Function\n" +
  4443. "%3 = OpLoad %uint %n\n" +
  4444. "%2 = OpIAdd %uint %uint_0 %3\n" +
  4445. "OpReturn\n" +
  4446. "OpFunctionEnd",
  4447. 2, 3),
  4448. // Test case 4: Don't fold n + (1,0)
  4449. InstructionFoldingCase<uint32_t>(
  4450. Header() + "%main = OpFunction %void None %void_func\n" +
  4451. "%main_lab = OpLabel\n" +
  4452. "%n = OpVariable %_ptr_v2int Function\n" +
  4453. "%3 = OpLoad %v2int %n\n" +
  4454. "%2 = OpIAdd %v2int %3 %v2int_1_0\n" +
  4455. "OpReturn\n" +
  4456. "OpFunctionEnd",
  4457. 2, 0),
  4458. // Test case 5: Don't fold (1,0) + n
  4459. InstructionFoldingCase<uint32_t>(
  4460. Header() + "%main = OpFunction %void None %void_func\n" +
  4461. "%main_lab = OpLabel\n" +
  4462. "%n = OpVariable %_ptr_v2int Function\n" +
  4463. "%3 = OpLoad %v2int %n\n" +
  4464. "%2 = OpIAdd %v2int %v2int_1_0 %3\n" +
  4465. "OpReturn\n" +
  4466. "OpFunctionEnd",
  4467. 2, 0),
  4468. // Test case 6: Fold n + (0,0)
  4469. InstructionFoldingCase<uint32_t>(
  4470. Header() + "%main = OpFunction %void None %void_func\n" +
  4471. "%main_lab = OpLabel\n" +
  4472. "%n = OpVariable %_ptr_v2int Function\n" +
  4473. "%3 = OpLoad %v2int %n\n" +
  4474. "%2 = OpIAdd %v2int %3 %v2int_0_0\n" +
  4475. "OpReturn\n" +
  4476. "OpFunctionEnd",
  4477. 2, 3),
  4478. // Test case 7: Fold (0,0) + n
  4479. InstructionFoldingCase<uint32_t>(
  4480. Header() + "%main = OpFunction %void None %void_func\n" +
  4481. "%main_lab = OpLabel\n" +
  4482. "%n = OpVariable %_ptr_v2int Function\n" +
  4483. "%3 = OpLoad %v2int %n\n" +
  4484. "%2 = OpIAdd %v2int %v2int_0_0 %3\n" +
  4485. "OpReturn\n" +
  4486. "OpFunctionEnd",
  4487. 2, 3)
  4488. ));
  4489. INSTANTIATE_TEST_SUITE_P(ClampAndCmpLHS, GeneralInstructionFoldingTest,
  4490. ::testing::Values(
  4491. // Test case 0: Don't Fold 0.0 < clamp(-1, 1)
  4492. InstructionFoldingCase<uint32_t>(
  4493. Header() + "%main = OpFunction %void None %void_func\n" +
  4494. "%main_lab = OpLabel\n" +
  4495. "%n = OpVariable %_ptr_float Function\n" +
  4496. "%ld = OpLoad %float %n\n" +
  4497. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
  4498. "%2 = OpFUnordLessThan %bool %float_0 %clamp\n" +
  4499. "OpReturn\n" +
  4500. "OpFunctionEnd",
  4501. 2, 0),
  4502. // Test case 1: Don't Fold 0.0 < clamp(-1, 1)
  4503. InstructionFoldingCase<uint32_t>(
  4504. Header() + "%main = OpFunction %void None %void_func\n" +
  4505. "%main_lab = OpLabel\n" +
  4506. "%n = OpVariable %_ptr_float Function\n" +
  4507. "%ld = OpLoad %float %n\n" +
  4508. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
  4509. "%2 = OpFOrdLessThan %bool %float_0 %clamp\n" +
  4510. "OpReturn\n" +
  4511. "OpFunctionEnd",
  4512. 2, 0),
  4513. // Test case 2: Don't Fold 0.0 <= clamp(-1, 1)
  4514. InstructionFoldingCase<uint32_t>(
  4515. Header() + "%main = OpFunction %void None %void_func\n" +
  4516. "%main_lab = OpLabel\n" +
  4517. "%n = OpVariable %_ptr_float Function\n" +
  4518. "%ld = OpLoad %float %n\n" +
  4519. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
  4520. "%2 = OpFUnordLessThanEqual %bool %float_0 %clamp\n" +
  4521. "OpReturn\n" +
  4522. "OpFunctionEnd",
  4523. 2, 0),
  4524. // Test case 3: Don't Fold 0.0 <= clamp(-1, 1)
  4525. InstructionFoldingCase<uint32_t>(
  4526. Header() + "%main = OpFunction %void None %void_func\n" +
  4527. "%main_lab = OpLabel\n" +
  4528. "%n = OpVariable %_ptr_float Function\n" +
  4529. "%ld = OpLoad %float %n\n" +
  4530. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
  4531. "%2 = OpFOrdLessThanEqual %bool %float_0 %clamp\n" +
  4532. "OpReturn\n" +
  4533. "OpFunctionEnd",
  4534. 2, 0),
  4535. // Test case 4: Don't Fold 0.0 > clamp(-1, 1)
  4536. InstructionFoldingCase<uint32_t>(
  4537. Header() + "%main = OpFunction %void None %void_func\n" +
  4538. "%main_lab = OpLabel\n" +
  4539. "%n = OpVariable %_ptr_float Function\n" +
  4540. "%ld = OpLoad %float %n\n" +
  4541. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
  4542. "%2 = OpFUnordGreaterThan %bool %float_0 %clamp\n" +
  4543. "OpReturn\n" +
  4544. "OpFunctionEnd",
  4545. 2, 0),
  4546. // Test case 5: Don't Fold 0.0 > clamp(-1, 1)
  4547. InstructionFoldingCase<uint32_t>(
  4548. Header() + "%main = OpFunction %void None %void_func\n" +
  4549. "%main_lab = OpLabel\n" +
  4550. "%n = OpVariable %_ptr_float Function\n" +
  4551. "%ld = OpLoad %float %n\n" +
  4552. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
  4553. "%2 = OpFOrdGreaterThan %bool %float_0 %clamp\n" +
  4554. "OpReturn\n" +
  4555. "OpFunctionEnd",
  4556. 2, 0),
  4557. // Test case 6: Don't Fold 0.0 >= clamp(-1, 1)
  4558. InstructionFoldingCase<uint32_t>(
  4559. Header() + "%main = OpFunction %void None %void_func\n" +
  4560. "%main_lab = OpLabel\n" +
  4561. "%n = OpVariable %_ptr_float Function\n" +
  4562. "%ld = OpLoad %float %n\n" +
  4563. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
  4564. "%2 = OpFUnordGreaterThanEqual %bool %float_0 %clamp\n" +
  4565. "OpReturn\n" +
  4566. "OpFunctionEnd",
  4567. 2, 0),
  4568. // Test case 7: Don't Fold 0.0 >= clamp(-1, 1)
  4569. InstructionFoldingCase<uint32_t>(
  4570. Header() + "%main = OpFunction %void None %void_func\n" +
  4571. "%main_lab = OpLabel\n" +
  4572. "%n = OpVariable %_ptr_float Function\n" +
  4573. "%ld = OpLoad %float %n\n" +
  4574. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
  4575. "%2 = OpFOrdGreaterThanEqual %bool %float_0 %clamp\n" +
  4576. "OpReturn\n" +
  4577. "OpFunctionEnd",
  4578. 2, 0),
  4579. // Test case 8: Don't Fold 0.0 < clamp(0, 1)
  4580. InstructionFoldingCase<uint32_t>(
  4581. Header() + "%main = OpFunction %void None %void_func\n" +
  4582. "%main_lab = OpLabel\n" +
  4583. "%n = OpVariable %_ptr_float Function\n" +
  4584. "%ld = OpLoad %float %n\n" +
  4585. "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
  4586. "%2 = OpFUnordLessThan %bool %float_0 %clamp\n" +
  4587. "OpReturn\n" +
  4588. "OpFunctionEnd",
  4589. 2, 0),
  4590. // Test case 9: Don't Fold 0.0 < clamp(0, 1)
  4591. InstructionFoldingCase<uint32_t>(
  4592. Header() + "%main = OpFunction %void None %void_func\n" +
  4593. "%main_lab = OpLabel\n" +
  4594. "%n = OpVariable %_ptr_float Function\n" +
  4595. "%ld = OpLoad %float %n\n" +
  4596. "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
  4597. "%2 = OpFOrdLessThan %bool %float_0 %clamp\n" +
  4598. "OpReturn\n" +
  4599. "OpFunctionEnd",
  4600. 2, 0),
  4601. // Test case 10: Don't Fold 0.0 > clamp(-1, 0)
  4602. InstructionFoldingCase<uint32_t>(
  4603. Header() + "%main = OpFunction %void None %void_func\n" +
  4604. "%main_lab = OpLabel\n" +
  4605. "%n = OpVariable %_ptr_float Function\n" +
  4606. "%ld = OpLoad %float %n\n" +
  4607. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
  4608. "%2 = OpFUnordGreaterThan %bool %float_0 %clamp\n" +
  4609. "OpReturn\n" +
  4610. "OpFunctionEnd",
  4611. 2, 0),
  4612. // Test case 11: Don't Fold 0.0 > clamp(-1, 0)
  4613. InstructionFoldingCase<uint32_t>(
  4614. Header() + "%main = OpFunction %void None %void_func\n" +
  4615. "%main_lab = OpLabel\n" +
  4616. "%n = OpVariable %_ptr_float Function\n" +
  4617. "%ld = OpLoad %float %n\n" +
  4618. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
  4619. "%2 = OpFOrdGreaterThan %bool %float_0 %clamp\n" +
  4620. "OpReturn\n" +
  4621. "OpFunctionEnd",
  4622. 2, 0)
  4623. ));
  4624. INSTANTIATE_TEST_SUITE_P(ClampAndCmpRHS, GeneralInstructionFoldingTest,
  4625. ::testing::Values(
  4626. // Test case 0: Don't Fold clamp(-1, 1) < 0.0
  4627. InstructionFoldingCase<uint32_t>(
  4628. Header() + "%main = OpFunction %void None %void_func\n" +
  4629. "%main_lab = OpLabel\n" +
  4630. "%n = OpVariable %_ptr_float Function\n" +
  4631. "%ld = OpLoad %float %n\n" +
  4632. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
  4633. "%2 = OpFUnordLessThan %bool %clamp %float_0\n" +
  4634. "OpReturn\n" +
  4635. "OpFunctionEnd",
  4636. 2, 0),
  4637. // Test case 1: Don't Fold clamp(-1, 1) < 0.0
  4638. InstructionFoldingCase<uint32_t>(
  4639. Header() + "%main = OpFunction %void None %void_func\n" +
  4640. "%main_lab = OpLabel\n" +
  4641. "%n = OpVariable %_ptr_float Function\n" +
  4642. "%ld = OpLoad %float %n\n" +
  4643. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
  4644. "%2 = OpFOrdLessThan %bool %clamp %float_0\n" +
  4645. "OpReturn\n" +
  4646. "OpFunctionEnd",
  4647. 2, 0),
  4648. // Test case 2: Don't Fold clamp(-1, 1) <= 0.0
  4649. InstructionFoldingCase<uint32_t>(
  4650. Header() + "%main = OpFunction %void None %void_func\n" +
  4651. "%main_lab = OpLabel\n" +
  4652. "%n = OpVariable %_ptr_float Function\n" +
  4653. "%ld = OpLoad %float %n\n" +
  4654. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
  4655. "%2 = OpFUnordLessThanEqual %bool %clamp %float_0\n" +
  4656. "OpReturn\n" +
  4657. "OpFunctionEnd",
  4658. 2, 0),
  4659. // Test case 3: Don't Fold clamp(-1, 1) <= 0.0
  4660. InstructionFoldingCase<uint32_t>(
  4661. Header() + "%main = OpFunction %void None %void_func\n" +
  4662. "%main_lab = OpLabel\n" +
  4663. "%n = OpVariable %_ptr_float Function\n" +
  4664. "%ld = OpLoad %float %n\n" +
  4665. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
  4666. "%2 = OpFOrdLessThanEqual %bool %clamp %float_0\n" +
  4667. "OpReturn\n" +
  4668. "OpFunctionEnd",
  4669. 2, 0),
  4670. // Test case 4: Don't Fold clamp(-1, 1) > 0.0
  4671. InstructionFoldingCase<uint32_t>(
  4672. Header() + "%main = OpFunction %void None %void_func\n" +
  4673. "%main_lab = OpLabel\n" +
  4674. "%n = OpVariable %_ptr_float Function\n" +
  4675. "%ld = OpLoad %float %n\n" +
  4676. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
  4677. "%2 = OpFUnordGreaterThan %bool %clamp %float_0\n" +
  4678. "OpReturn\n" +
  4679. "OpFunctionEnd",
  4680. 2, 0),
  4681. // Test case 5: Don't Fold clamp(-1, 1) > 0.0
  4682. InstructionFoldingCase<uint32_t>(
  4683. Header() + "%main = OpFunction %void None %void_func\n" +
  4684. "%main_lab = OpLabel\n" +
  4685. "%n = OpVariable %_ptr_float Function\n" +
  4686. "%ld = OpLoad %float %n\n" +
  4687. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
  4688. "%2 = OpFOrdGreaterThan %bool %clamp %float_0\n" +
  4689. "OpReturn\n" +
  4690. "OpFunctionEnd",
  4691. 2, 0),
  4692. // Test case 6: Don't Fold clamp(-1, 1) >= 0.0
  4693. InstructionFoldingCase<uint32_t>(
  4694. Header() + "%main = OpFunction %void None %void_func\n" +
  4695. "%main_lab = OpLabel\n" +
  4696. "%n = OpVariable %_ptr_float Function\n" +
  4697. "%ld = OpLoad %float %n\n" +
  4698. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
  4699. "%2 = OpFUnordGreaterThanEqual %bool %clamp %float_0\n" +
  4700. "OpReturn\n" +
  4701. "OpFunctionEnd",
  4702. 2, 0),
  4703. // Test case 7: Don't Fold clamp(-1, 1) >= 0.0
  4704. InstructionFoldingCase<uint32_t>(
  4705. Header() + "%main = OpFunction %void None %void_func\n" +
  4706. "%main_lab = OpLabel\n" +
  4707. "%n = OpVariable %_ptr_float Function\n" +
  4708. "%ld = OpLoad %float %n\n" +
  4709. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
  4710. "%2 = OpFOrdGreaterThanEqual %bool %clamp %float_0\n" +
  4711. "OpReturn\n" +
  4712. "OpFunctionEnd",
  4713. 2, 0),
  4714. // Test case 8: Don't Fold clamp(-1, 0) < 0.0
  4715. InstructionFoldingCase<uint32_t>(
  4716. Header() + "%main = OpFunction %void None %void_func\n" +
  4717. "%main_lab = OpLabel\n" +
  4718. "%n = OpVariable %_ptr_float Function\n" +
  4719. "%ld = OpLoad %float %n\n" +
  4720. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
  4721. "%2 = OpFUnordLessThan %bool %clamp %float_0\n" +
  4722. "OpReturn\n" +
  4723. "OpFunctionEnd",
  4724. 2, 0),
  4725. // Test case 9: Don't Fold clamp(0, 1) < 1
  4726. InstructionFoldingCase<uint32_t>(
  4727. Header() + "%main = OpFunction %void None %void_func\n" +
  4728. "%main_lab = OpLabel\n" +
  4729. "%n = OpVariable %_ptr_float Function\n" +
  4730. "%ld = OpLoad %float %n\n" +
  4731. "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
  4732. "%2 = OpFOrdLessThan %bool %clamp %float_1\n" +
  4733. "OpReturn\n" +
  4734. "OpFunctionEnd",
  4735. 2, 0),
  4736. // Test case 10: Don't Fold clamp(-1, 0) > -1
  4737. InstructionFoldingCase<uint32_t>(
  4738. Header() + "%main = OpFunction %void None %void_func\n" +
  4739. "%main_lab = OpLabel\n" +
  4740. "%n = OpVariable %_ptr_float Function\n" +
  4741. "%ld = OpLoad %float %n\n" +
  4742. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
  4743. "%2 = OpFUnordGreaterThan %bool %clamp %float_n1\n" +
  4744. "OpReturn\n" +
  4745. "OpFunctionEnd",
  4746. 2, 0),
  4747. // Test case 11: Don't Fold clamp(-1, 0) > -1
  4748. InstructionFoldingCase<uint32_t>(
  4749. Header() + "%main = OpFunction %void None %void_func\n" +
  4750. "%main_lab = OpLabel\n" +
  4751. "%n = OpVariable %_ptr_float Function\n" +
  4752. "%ld = OpLoad %float %n\n" +
  4753. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
  4754. "%2 = OpFOrdGreaterThan %bool %clamp %float_n1\n" +
  4755. "OpReturn\n" +
  4756. "OpFunctionEnd",
  4757. 2, 0)
  4758. ));
  4759. INSTANTIATE_TEST_SUITE_P(FToIConstantFoldingTest, IntegerInstructionFoldingTest,
  4760. ::testing::Values(
  4761. // Test case 0: Fold int(3.0)
  4762. InstructionFoldingCase<uint32_t>(
  4763. Header() + "%main = OpFunction %void None %void_func\n" +
  4764. "%main_lab = OpLabel\n" +
  4765. "%2 = OpConvertFToS %int %float_3\n" +
  4766. "OpReturn\n" +
  4767. "OpFunctionEnd",
  4768. 2, 3),
  4769. // Test case 1: Fold uint(3.0)
  4770. InstructionFoldingCase<uint32_t>(
  4771. Header() + "%main = OpFunction %void None %void_func\n" +
  4772. "%main_lab = OpLabel\n" +
  4773. "%2 = OpConvertFToU %int %float_3\n" +
  4774. "OpReturn\n" +
  4775. "OpFunctionEnd",
  4776. 2, 3)
  4777. ));
  4778. INSTANTIATE_TEST_SUITE_P(IToFConstantFoldingTest, FloatInstructionFoldingTest,
  4779. ::testing::Values(
  4780. // Test case 0: Fold float(3)
  4781. InstructionFoldingCase<float>(
  4782. Header() + "%main = OpFunction %void None %void_func\n" +
  4783. "%main_lab = OpLabel\n" +
  4784. "%2 = OpConvertSToF %float %int_3\n" +
  4785. "OpReturn\n" +
  4786. "OpFunctionEnd",
  4787. 2, 3.0),
  4788. // Test case 1: Fold float(3u)
  4789. InstructionFoldingCase<float>(
  4790. Header() + "%main = OpFunction %void None %void_func\n" +
  4791. "%main_lab = OpLabel\n" +
  4792. "%2 = OpConvertUToF %float %uint_3\n" +
  4793. "OpReturn\n" +
  4794. "OpFunctionEnd",
  4795. 2, 3.0)
  4796. ));
  4797. // clang-format on
  4798. using ToNegateFoldingTest =
  4799. ::testing::TestWithParam<InstructionFoldingCase<uint32_t>>;
  4800. TEST_P(ToNegateFoldingTest, Case) {
  4801. const auto& tc = GetParam();
  4802. // Build module.
  4803. std::unique_ptr<IRContext> context =
  4804. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
  4805. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  4806. ASSERT_NE(nullptr, context);
  4807. // Fold the instruction to test.
  4808. analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
  4809. Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
  4810. std::unique_ptr<Instruction> original_inst(inst->Clone(context.get()));
  4811. bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
  4812. // Make sure the instruction folded as expected.
  4813. EXPECT_EQ(inst->result_id(), original_inst->result_id());
  4814. EXPECT_EQ(inst->type_id(), original_inst->type_id());
  4815. EXPECT_TRUE((!succeeded) == (tc.expected_result == 0));
  4816. if (succeeded) {
  4817. EXPECT_EQ(inst->opcode(), spv::Op::OpFNegate);
  4818. EXPECT_EQ(inst->GetSingleWordInOperand(0), tc.expected_result);
  4819. } else {
  4820. EXPECT_EQ(inst->NumInOperands(), original_inst->NumInOperands());
  4821. for (uint32_t i = 0; i < inst->NumInOperands(); ++i) {
  4822. EXPECT_EQ(inst->GetOperand(i), original_inst->GetOperand(i));
  4823. }
  4824. }
  4825. }
  4826. // clang-format off
  4827. INSTANTIATE_TEST_SUITE_P(FloatRedundantSubFoldingTest, ToNegateFoldingTest,
  4828. ::testing::Values(
  4829. // Test case 0: Don't fold 1.0 - n
  4830. InstructionFoldingCase<uint32_t>(
  4831. Header() + "%main = OpFunction %void None %void_func\n" +
  4832. "%main_lab = OpLabel\n" +
  4833. "%n = OpVariable %_ptr_float Function\n" +
  4834. "%3 = OpLoad %float %n\n" +
  4835. "%2 = OpFSub %float %float_1 %3\n" +
  4836. "OpReturn\n" +
  4837. "OpFunctionEnd",
  4838. 2, 0),
  4839. // Test case 1: Fold 0.0 - n
  4840. InstructionFoldingCase<uint32_t>(
  4841. Header() + "%main = OpFunction %void None %void_func\n" +
  4842. "%main_lab = OpLabel\n" +
  4843. "%n = OpVariable %_ptr_float Function\n" +
  4844. "%3 = OpLoad %float %n\n" +
  4845. "%2 = OpFSub %float %float_0 %3\n" +
  4846. "OpReturn\n" +
  4847. "OpFunctionEnd",
  4848. 2, 3),
  4849. // Test case 2: Don't fold (0,0,0,1) - n
  4850. InstructionFoldingCase<uint32_t>(
  4851. Header() + "%main = OpFunction %void None %void_func\n" +
  4852. "%main_lab = OpLabel\n" +
  4853. "%n = OpVariable %_ptr_v4float Function\n" +
  4854. "%3 = OpLoad %v4float %n\n" +
  4855. "%2 = OpFSub %v4float %v4float_0_0_0_1 %3\n" +
  4856. "OpReturn\n" +
  4857. "OpFunctionEnd",
  4858. 2, 0),
  4859. // Test case 3: Fold (0,0,0,0) - n
  4860. InstructionFoldingCase<uint32_t>(
  4861. Header() + "%main = OpFunction %void None %void_func\n" +
  4862. "%main_lab = OpLabel\n" +
  4863. "%n = OpVariable %_ptr_v4float Function\n" +
  4864. "%3 = OpLoad %v4float %n\n" +
  4865. "%2 = OpFSub %v4float %v4float_0_0_0_0 %3\n" +
  4866. "OpReturn\n" +
  4867. "OpFunctionEnd",
  4868. 2, 3)
  4869. ));
  4870. INSTANTIATE_TEST_SUITE_P(DoubleRedundantSubFoldingTest, ToNegateFoldingTest,
  4871. ::testing::Values(
  4872. // Test case 0: Don't fold 1.0 - n
  4873. InstructionFoldingCase<uint32_t>(
  4874. Header() + "%main = OpFunction %void None %void_func\n" +
  4875. "%main_lab = OpLabel\n" +
  4876. "%n = OpVariable %_ptr_double Function\n" +
  4877. "%3 = OpLoad %double %n\n" +
  4878. "%2 = OpFSub %double %double_1 %3\n" +
  4879. "OpReturn\n" +
  4880. "OpFunctionEnd",
  4881. 2, 0),
  4882. // Test case 1: Fold 0.0 - n
  4883. InstructionFoldingCase<uint32_t>(
  4884. Header() + "%main = OpFunction %void None %void_func\n" +
  4885. "%main_lab = OpLabel\n" +
  4886. "%n = OpVariable %_ptr_double Function\n" +
  4887. "%3 = OpLoad %double %n\n" +
  4888. "%2 = OpFSub %double %double_0 %3\n" +
  4889. "OpReturn\n" +
  4890. "OpFunctionEnd",
  4891. 2, 3),
  4892. // Test case 2: Don't fold (0,0,0,1) - n
  4893. InstructionFoldingCase<uint32_t>(
  4894. Header() + "%main = OpFunction %void None %void_func\n" +
  4895. "%main_lab = OpLabel\n" +
  4896. "%n = OpVariable %_ptr_v4double Function\n" +
  4897. "%3 = OpLoad %v4double %n\n" +
  4898. "%2 = OpFSub %v4double %v4double_0_0_0_1 %3\n" +
  4899. "OpReturn\n" +
  4900. "OpFunctionEnd",
  4901. 2, 0),
  4902. // Test case 3: Fold (0,0,0,0) - n
  4903. InstructionFoldingCase<uint32_t>(
  4904. Header() + "%main = OpFunction %void None %void_func\n" +
  4905. "%main_lab = OpLabel\n" +
  4906. "%n = OpVariable %_ptr_v4double Function\n" +
  4907. "%3 = OpLoad %v4double %n\n" +
  4908. "%2 = OpFSub %v4double %v4double_0_0_0_0 %3\n" +
  4909. "OpReturn\n" +
  4910. "OpFunctionEnd",
  4911. 2, 3)
  4912. ));
  4913. using MatchingInstructionFoldingTest =
  4914. ::testing::TestWithParam<InstructionFoldingCase<bool>>;
  4915. TEST_P(MatchingInstructionFoldingTest, Case) {
  4916. const auto& tc = GetParam();
  4917. // Build module.
  4918. std::unique_ptr<IRContext> context =
  4919. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
  4920. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  4921. ASSERT_NE(nullptr, context);
  4922. // Fold the instruction to test.
  4923. analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
  4924. Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
  4925. std::unique_ptr<Instruction> original_inst(inst->Clone(context.get()));
  4926. bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
  4927. EXPECT_EQ(succeeded, tc.expected_result);
  4928. if (succeeded) {
  4929. Match(tc.test_body, context.get());
  4930. }
  4931. }
  4932. INSTANTIATE_TEST_SUITE_P(RedundantIntegerMatching, MatchingInstructionFoldingTest,
  4933. ::testing::Values(
  4934. // Test case 0: Fold 0 + n (change sign)
  4935. InstructionFoldingCase<bool>(
  4936. Header() +
  4937. "; CHECK: [[uint:%\\w+]] = OpTypeInt 32 0\n" +
  4938. "; CHECK: %2 = OpBitcast [[uint]] %3\n" +
  4939. "%main = OpFunction %void None %void_func\n" +
  4940. "%main_lab = OpLabel\n" +
  4941. "%n = OpVariable %_ptr_int Function\n" +
  4942. "%3 = OpLoad %uint %n\n" +
  4943. "%2 = OpIAdd %uint %int_0 %3\n" +
  4944. "OpReturn\n" +
  4945. "OpFunctionEnd\n",
  4946. 2, true),
  4947. // Test case 0: Fold 0 + n (change sign)
  4948. InstructionFoldingCase<bool>(
  4949. Header() +
  4950. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  4951. "; CHECK: %2 = OpBitcast [[int]] %3\n" +
  4952. "%main = OpFunction %void None %void_func\n" +
  4953. "%main_lab = OpLabel\n" +
  4954. "%n = OpVariable %_ptr_int Function\n" +
  4955. "%3 = OpLoad %int %n\n" +
  4956. "%2 = OpIAdd %int %uint_0 %3\n" +
  4957. "OpReturn\n" +
  4958. "OpFunctionEnd\n",
  4959. 2, true)
  4960. ));
  4961. INSTANTIATE_TEST_SUITE_P(MergeNegateTest, MatchingInstructionFoldingTest,
  4962. ::testing::Values(
  4963. // Test case 0: fold consecutive fnegate
  4964. // -(-x) = x
  4965. InstructionFoldingCase<bool>(
  4966. Header() +
  4967. "; CHECK: [[ld:%\\w+]] = OpLoad [[float:%\\w+]]\n" +
  4968. "; CHECK: %4 = OpCopyObject [[float]] [[ld]]\n" +
  4969. "%main = OpFunction %void None %void_func\n" +
  4970. "%main_lab = OpLabel\n" +
  4971. "%var = OpVariable %_ptr_float Function\n" +
  4972. "%2 = OpLoad %float %var\n" +
  4973. "%3 = OpFNegate %float %2\n" +
  4974. "%4 = OpFNegate %float %3\n" +
  4975. "OpReturn\n" +
  4976. "OpFunctionEnd",
  4977. 4, true),
  4978. // Test case 1: fold fnegate(fmul with const).
  4979. // -(x * 2.0) = x * -2.0
  4980. InstructionFoldingCase<bool>(
  4981. Header() +
  4982. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  4983. "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2{{[[:space:]]}}\n" +
  4984. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  4985. "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_n2]]\n" +
  4986. "%main = OpFunction %void None %void_func\n" +
  4987. "%main_lab = OpLabel\n" +
  4988. "%var = OpVariable %_ptr_float Function\n" +
  4989. "%2 = OpLoad %float %var\n" +
  4990. "%3 = OpFMul %float %2 %float_2\n" +
  4991. "%4 = OpFNegate %float %3\n" +
  4992. "OpReturn\n" +
  4993. "OpFunctionEnd",
  4994. 4, true),
  4995. // Test case 2: fold fnegate(fmul with const).
  4996. // -(2.0 * x) = x * 2.0
  4997. InstructionFoldingCase<bool>(
  4998. Header() +
  4999. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5000. "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2{{[[:space:]]}}\n" +
  5001. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  5002. "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_n2]]\n" +
  5003. "%main = OpFunction %void None %void_func\n" +
  5004. "%main_lab = OpLabel\n" +
  5005. "%var = OpVariable %_ptr_float Function\n" +
  5006. "%2 = OpLoad %float %var\n" +
  5007. "%3 = OpFMul %float %float_2 %2\n" +
  5008. "%4 = OpFNegate %float %3\n" +
  5009. "OpReturn\n" +
  5010. "OpFunctionEnd",
  5011. 4, true),
  5012. // Test case 3: fold fnegate(fdiv with const).
  5013. // -(x / 2.0) = x * -0.5
  5014. InstructionFoldingCase<bool>(
  5015. Header() +
  5016. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5017. "; CHECK: [[float_n0p5:%\\w+]] = OpConstant [[float]] -0.5\n" +
  5018. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  5019. "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_n0p5]]\n" +
  5020. "%main = OpFunction %void None %void_func\n" +
  5021. "%main_lab = OpLabel\n" +
  5022. "%var = OpVariable %_ptr_float Function\n" +
  5023. "%2 = OpLoad %float %var\n" +
  5024. "%3 = OpFDiv %float %2 %float_2\n" +
  5025. "%4 = OpFNegate %float %3\n" +
  5026. "OpReturn\n" +
  5027. "OpFunctionEnd",
  5028. 4, true),
  5029. // Test case 4: fold fnegate(fdiv with const).
  5030. // -(2.0 / x) = -2.0 / x
  5031. InstructionFoldingCase<bool>(
  5032. Header() +
  5033. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5034. "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2{{[[:space:]]}}\n" +
  5035. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  5036. "; CHECK: %4 = OpFDiv [[float]] [[float_n2]] [[ld]]\n" +
  5037. "%main = OpFunction %void None %void_func\n" +
  5038. "%main_lab = OpLabel\n" +
  5039. "%var = OpVariable %_ptr_float Function\n" +
  5040. "%2 = OpLoad %float %var\n" +
  5041. "%3 = OpFDiv %float %float_2 %2\n" +
  5042. "%4 = OpFNegate %float %3\n" +
  5043. "OpReturn\n" +
  5044. "OpFunctionEnd",
  5045. 4, true),
  5046. // Test case 5: fold fnegate(fadd with const).
  5047. // -(2.0 + x) = -2.0 - x
  5048. InstructionFoldingCase<bool>(
  5049. Header() +
  5050. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5051. "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2{{[[:space:]]}}\n" +
  5052. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  5053. "; CHECK: %4 = OpFSub [[float]] [[float_n2]] [[ld]]\n" +
  5054. "%main = OpFunction %void None %void_func\n" +
  5055. "%main_lab = OpLabel\n" +
  5056. "%var = OpVariable %_ptr_float Function\n" +
  5057. "%2 = OpLoad %float %var\n" +
  5058. "%3 = OpFAdd %float %float_2 %2\n" +
  5059. "%4 = OpFNegate %float %3\n" +
  5060. "OpReturn\n" +
  5061. "OpFunctionEnd",
  5062. 4, true),
  5063. // Test case 6: fold fnegate(fadd with const).
  5064. // -(x + 2.0) = -2.0 - x
  5065. InstructionFoldingCase<bool>(
  5066. Header() +
  5067. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5068. "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2{{[[:space:]]}}\n" +
  5069. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  5070. "; CHECK: %4 = OpFSub [[float]] [[float_n2]] [[ld]]\n" +
  5071. "%main = OpFunction %void None %void_func\n" +
  5072. "%main_lab = OpLabel\n" +
  5073. "%var = OpVariable %_ptr_float Function\n" +
  5074. "%2 = OpLoad %float %var\n" +
  5075. "%3 = OpFAdd %float %2 %float_2\n" +
  5076. "%4 = OpFNegate %float %3\n" +
  5077. "OpReturn\n" +
  5078. "OpFunctionEnd",
  5079. 4, true),
  5080. // Test case 7: fold fnegate(fsub with const).
  5081. // -(2.0 - x) = x - 2.0
  5082. InstructionFoldingCase<bool>(
  5083. Header() +
  5084. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5085. "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
  5086. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  5087. "; CHECK: %4 = OpFSub [[float]] [[ld]] [[float_2]]\n" +
  5088. "%main = OpFunction %void None %void_func\n" +
  5089. "%main_lab = OpLabel\n" +
  5090. "%var = OpVariable %_ptr_float Function\n" +
  5091. "%2 = OpLoad %float %var\n" +
  5092. "%3 = OpFSub %float %float_2 %2\n" +
  5093. "%4 = OpFNegate %float %3\n" +
  5094. "OpReturn\n" +
  5095. "OpFunctionEnd",
  5096. 4, true),
  5097. // Test case 8: fold fnegate(fsub with const).
  5098. // -(x - 2.0) = 2.0 - x
  5099. InstructionFoldingCase<bool>(
  5100. Header() +
  5101. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5102. "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
  5103. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  5104. "; CHECK: %4 = OpFSub [[float]] [[float_2]] [[ld]]\n" +
  5105. "%main = OpFunction %void None %void_func\n" +
  5106. "%main_lab = OpLabel\n" +
  5107. "%var = OpVariable %_ptr_float Function\n" +
  5108. "%2 = OpLoad %float %var\n" +
  5109. "%3 = OpFSub %float %2 %float_2\n" +
  5110. "%4 = OpFNegate %float %3\n" +
  5111. "OpReturn\n" +
  5112. "OpFunctionEnd",
  5113. 4, true),
  5114. // Test case 9: fold consecutive snegate
  5115. // -(-x) = x
  5116. InstructionFoldingCase<bool>(
  5117. Header() +
  5118. "; CHECK: [[ld:%\\w+]] = OpLoad [[int:%\\w+]]\n" +
  5119. "; CHECK: %4 = OpCopyObject [[int]] [[ld]]\n" +
  5120. "%main = OpFunction %void None %void_func\n" +
  5121. "%main_lab = OpLabel\n" +
  5122. "%var = OpVariable %_ptr_int Function\n" +
  5123. "%2 = OpLoad %int %var\n" +
  5124. "%3 = OpSNegate %int %2\n" +
  5125. "%4 = OpSNegate %int %3\n" +
  5126. "OpReturn\n" +
  5127. "OpFunctionEnd",
  5128. 4, true),
  5129. // Test case 10: fold consecutive vector negate
  5130. // -(-x) = x
  5131. InstructionFoldingCase<bool>(
  5132. Header() +
  5133. "; CHECK: [[ld:%\\w+]] = OpLoad [[v2float:%\\w+]]\n" +
  5134. "; CHECK: %4 = OpCopyObject [[v2float]] [[ld]]\n" +
  5135. "%main = OpFunction %void None %void_func\n" +
  5136. "%main_lab = OpLabel\n" +
  5137. "%var = OpVariable %_ptr_v2float Function\n" +
  5138. "%2 = OpLoad %v2float %var\n" +
  5139. "%3 = OpFNegate %v2float %2\n" +
  5140. "%4 = OpFNegate %v2float %3\n" +
  5141. "OpReturn\n" +
  5142. "OpFunctionEnd",
  5143. 4, true),
  5144. // Test case 11: fold snegate(iadd with const).
  5145. // -(2 + x) = -2 - x
  5146. InstructionFoldingCase<bool>(
  5147. Header() +
  5148. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  5149. "; CHECK: OpConstant [[int]] -2147483648\n" +
  5150. "; CHECK: [[int_n2:%\\w+]] = OpConstant [[int]] -2{{[[:space:]]}}\n" +
  5151. "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
  5152. "; CHECK: %4 = OpISub [[int]] [[int_n2]] [[ld]]\n" +
  5153. "%main = OpFunction %void None %void_func\n" +
  5154. "%main_lab = OpLabel\n" +
  5155. "%var = OpVariable %_ptr_int Function\n" +
  5156. "%2 = OpLoad %int %var\n" +
  5157. "%3 = OpIAdd %int %int_2 %2\n" +
  5158. "%4 = OpSNegate %int %3\n" +
  5159. "OpReturn\n" +
  5160. "OpFunctionEnd",
  5161. 4, true),
  5162. // Test case 12: fold snegate(iadd with const).
  5163. // -(x + 2) = -2 - x
  5164. InstructionFoldingCase<bool>(
  5165. Header() +
  5166. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  5167. "; CHECK: OpConstant [[int]] -2147483648\n" +
  5168. "; CHECK: [[int_n2:%\\w+]] = OpConstant [[int]] -2{{[[:space:]]}}\n" +
  5169. "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
  5170. "; CHECK: %4 = OpISub [[int]] [[int_n2]] [[ld]]\n" +
  5171. "%main = OpFunction %void None %void_func\n" +
  5172. "%main_lab = OpLabel\n" +
  5173. "%var = OpVariable %_ptr_int Function\n" +
  5174. "%2 = OpLoad %int %var\n" +
  5175. "%3 = OpIAdd %int %2 %int_2\n" +
  5176. "%4 = OpSNegate %int %3\n" +
  5177. "OpReturn\n" +
  5178. "OpFunctionEnd",
  5179. 4, true),
  5180. // Test case 13: fold snegate(isub with const).
  5181. // -(2 - x) = x - 2
  5182. InstructionFoldingCase<bool>(
  5183. Header() +
  5184. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  5185. "; CHECK: [[int_2:%\\w+]] = OpConstant [[int]] 2\n" +
  5186. "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
  5187. "; CHECK: %4 = OpISub [[int]] [[ld]] [[int_2]]\n" +
  5188. "%main = OpFunction %void None %void_func\n" +
  5189. "%main_lab = OpLabel\n" +
  5190. "%var = OpVariable %_ptr_int Function\n" +
  5191. "%2 = OpLoad %int %var\n" +
  5192. "%3 = OpISub %int %int_2 %2\n" +
  5193. "%4 = OpSNegate %int %3\n" +
  5194. "OpReturn\n" +
  5195. "OpFunctionEnd",
  5196. 4, true),
  5197. // Test case 14: fold snegate(isub with const).
  5198. // -(x - 2) = 2 - x
  5199. InstructionFoldingCase<bool>(
  5200. Header() +
  5201. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  5202. "; CHECK: [[int_2:%\\w+]] = OpConstant [[int]] 2\n" +
  5203. "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
  5204. "; CHECK: %4 = OpISub [[int]] [[int_2]] [[ld]]\n" +
  5205. "%main = OpFunction %void None %void_func\n" +
  5206. "%main_lab = OpLabel\n" +
  5207. "%var = OpVariable %_ptr_int Function\n" +
  5208. "%2 = OpLoad %int %var\n" +
  5209. "%3 = OpISub %int %2 %int_2\n" +
  5210. "%4 = OpSNegate %int %3\n" +
  5211. "OpReturn\n" +
  5212. "OpFunctionEnd",
  5213. 4, true),
  5214. // Test case 15: fold snegate(iadd with const).
  5215. // -(x + 2) = -2 - x
  5216. InstructionFoldingCase<bool>(
  5217. Header() +
  5218. "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
  5219. "; CHECK: [[long_n2:%\\w+]] = OpConstant [[long]] -2{{[[:space:]]}}\n" +
  5220. "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
  5221. "; CHECK: %4 = OpISub [[long]] [[long_n2]] [[ld]]\n" +
  5222. "%main = OpFunction %void None %void_func\n" +
  5223. "%main_lab = OpLabel\n" +
  5224. "%var = OpVariable %_ptr_long Function\n" +
  5225. "%2 = OpLoad %long %var\n" +
  5226. "%3 = OpIAdd %long %2 %long_2\n" +
  5227. "%4 = OpSNegate %long %3\n" +
  5228. "OpReturn\n" +
  5229. "OpFunctionEnd",
  5230. 4, true),
  5231. // Test case 16: fold snegate(isub with const).
  5232. // -(2 - x) = x - 2
  5233. InstructionFoldingCase<bool>(
  5234. Header() +
  5235. "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
  5236. "; CHECK: [[long_2:%\\w+]] = OpConstant [[long]] 2\n" +
  5237. "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
  5238. "; CHECK: %4 = OpISub [[long]] [[ld]] [[long_2]]\n" +
  5239. "%main = OpFunction %void None %void_func\n" +
  5240. "%main_lab = OpLabel\n" +
  5241. "%var = OpVariable %_ptr_long Function\n" +
  5242. "%2 = OpLoad %long %var\n" +
  5243. "%3 = OpISub %long %long_2 %2\n" +
  5244. "%4 = OpSNegate %long %3\n" +
  5245. "OpReturn\n" +
  5246. "OpFunctionEnd",
  5247. 4, true),
  5248. // Test case 17: fold snegate(isub with const).
  5249. // -(x - 2) = 2 - x
  5250. InstructionFoldingCase<bool>(
  5251. Header() +
  5252. "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
  5253. "; CHECK: [[long_2:%\\w+]] = OpConstant [[long]] 2\n" +
  5254. "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
  5255. "; CHECK: %4 = OpISub [[long]] [[long_2]] [[ld]]\n" +
  5256. "%main = OpFunction %void None %void_func\n" +
  5257. "%main_lab = OpLabel\n" +
  5258. "%var = OpVariable %_ptr_long Function\n" +
  5259. "%2 = OpLoad %long %var\n" +
  5260. "%3 = OpISub %long %2 %long_2\n" +
  5261. "%4 = OpSNegate %long %3\n" +
  5262. "OpReturn\n" +
  5263. "OpFunctionEnd",
  5264. 4, true),
  5265. // Test case 18: fold -vec4(-1.0, 2.0, 1.0, 3.0)
  5266. InstructionFoldingCase<bool>(
  5267. Header() +
  5268. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5269. "; CHECK: [[v4float:%\\w+]] = OpTypeVector [[float]] 4{{[[:space:]]}}\n" +
  5270. "; CHECK: [[float_n1:%\\w+]] = OpConstant [[float]] -1{{[[:space:]]}}\n" +
  5271. "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1{{[[:space:]]}}\n" +
  5272. "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2{{[[:space:]]}}\n" +
  5273. "; CHECK: [[float_n3:%\\w+]] = OpConstant [[float]] -3{{[[:space:]]}}\n" +
  5274. "; CHECK: [[v4float_1_n2_n1_n3:%\\w+]] = OpConstantComposite [[v4float]] [[float_1]] [[float_n2]] [[float_n1]] [[float_n3]]\n" +
  5275. "; CHECK: %2 = OpCopyObject [[v4float]] [[v4float_1_n2_n1_n3]]\n" +
  5276. "%main = OpFunction %void None %void_func\n" +
  5277. "%main_lab = OpLabel\n" +
  5278. "%2 = OpFNegate %v4float %v4float_n1_2_1_3\n" +
  5279. "OpReturn\n" +
  5280. "OpFunctionEnd",
  5281. 2, true),
  5282. // Test case 19: fold vector fnegate with null
  5283. InstructionFoldingCase<bool>(
  5284. Header() +
  5285. "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
  5286. "; CHECK: [[v2double:%\\w+]] = OpTypeVector [[double]] 2\n" +
  5287. "; CHECK: [[double_n0:%\\w+]] = OpConstant [[double]] -0\n" +
  5288. "; CHECK: [[v2double_0_0:%\\w+]] = OpConstantComposite [[v2double]] [[double_n0]] [[double_n0]]\n" +
  5289. "; CHECK: %2 = OpCopyObject [[v2double]] [[v2double_0_0]]\n" +
  5290. "%main = OpFunction %void None %void_func\n" +
  5291. "%main_lab = OpLabel\n" +
  5292. "%2 = OpFNegate %v2double %v2double_null\n" +
  5293. "OpReturn\n" +
  5294. "OpFunctionEnd",
  5295. 2, true)
  5296. ));
  5297. INSTANTIATE_TEST_SUITE_P(ReciprocalFDivTest, MatchingInstructionFoldingTest,
  5298. ::testing::Values(
  5299. // Test case 0: scalar reicprocal
  5300. // x / 0.5 = x * 2.0
  5301. InstructionFoldingCase<bool>(
  5302. Header() +
  5303. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5304. "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
  5305. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  5306. "; CHECK: %3 = OpFMul [[float]] [[ld]] [[float_2]]\n" +
  5307. "%main = OpFunction %void None %void_func\n" +
  5308. "%main_lab = OpLabel\n" +
  5309. "%var = OpVariable %_ptr_float Function\n" +
  5310. "%2 = OpLoad %float %var\n" +
  5311. "%3 = OpFDiv %float %2 %float_0p5\n" +
  5312. "OpReturn\n" +
  5313. "OpFunctionEnd\n",
  5314. 3, true),
  5315. // Test case 1: Unfoldable
  5316. InstructionFoldingCase<bool>(
  5317. Header() +
  5318. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5319. "; CHECK: [[float_0:%\\w+]] = OpConstant [[float]] 0\n" +
  5320. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  5321. "; CHECK: %3 = OpFDiv [[float]] [[ld]] [[float_0]]\n" +
  5322. "%main = OpFunction %void None %void_func\n" +
  5323. "%main_lab = OpLabel\n" +
  5324. "%var = OpVariable %_ptr_float Function\n" +
  5325. "%2 = OpLoad %float %var\n" +
  5326. "%3 = OpFDiv %float %2 %104\n" +
  5327. "OpReturn\n" +
  5328. "OpFunctionEnd\n",
  5329. 3, false),
  5330. // Test case 2: Vector reciprocal
  5331. // x / {2.0, 0.5} = x * {0.5, 2.0}
  5332. InstructionFoldingCase<bool>(
  5333. Header() +
  5334. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5335. "; CHECK: [[v2float:%\\w+]] = OpTypeVector [[float]] 2\n" +
  5336. "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
  5337. "; CHECK: [[float_0p5:%\\w+]] = OpConstant [[float]] 0.5\n" +
  5338. "; CHECK: [[v2float_0p5_2:%\\w+]] = OpConstantComposite [[v2float]] [[float_0p5]] [[float_2]]\n" +
  5339. "; CHECK: [[ld:%\\w+]] = OpLoad [[v2float]]\n" +
  5340. "; CHECK: %3 = OpFMul [[v2float]] [[ld]] [[v2float_0p5_2]]\n" +
  5341. "%main = OpFunction %void None %void_func\n" +
  5342. "%main_lab = OpLabel\n" +
  5343. "%var = OpVariable %_ptr_v2float Function\n" +
  5344. "%2 = OpLoad %v2float %var\n" +
  5345. "%3 = OpFDiv %v2float %2 %v2float_2_0p5\n" +
  5346. "OpReturn\n" +
  5347. "OpFunctionEnd\n",
  5348. 3, true),
  5349. // Test case 3: double reciprocal
  5350. // x / 2.0 = x * 0.5
  5351. InstructionFoldingCase<bool>(
  5352. Header() +
  5353. "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
  5354. "; CHECK: [[double_0p5:%\\w+]] = OpConstant [[double]] 0.5\n" +
  5355. "; CHECK: [[ld:%\\w+]] = OpLoad [[double]]\n" +
  5356. "; CHECK: %3 = OpFMul [[double]] [[ld]] [[double_0p5]]\n" +
  5357. "%main = OpFunction %void None %void_func\n" +
  5358. "%main_lab = OpLabel\n" +
  5359. "%var = OpVariable %_ptr_double Function\n" +
  5360. "%2 = OpLoad %double %var\n" +
  5361. "%3 = OpFDiv %double %2 %double_2\n" +
  5362. "OpReturn\n" +
  5363. "OpFunctionEnd\n",
  5364. 3, true),
  5365. // Test case 4: don't fold x / 0.
  5366. InstructionFoldingCase<bool>(
  5367. Header() +
  5368. "%main = OpFunction %void None %void_func\n" +
  5369. "%main_lab = OpLabel\n" +
  5370. "%var = OpVariable %_ptr_v2float Function\n" +
  5371. "%2 = OpLoad %v2float %var\n" +
  5372. "%3 = OpFDiv %v2float %2 %v2float_null\n" +
  5373. "OpReturn\n" +
  5374. "OpFunctionEnd\n",
  5375. 3, false)
  5376. ));
  5377. INSTANTIATE_TEST_SUITE_P(MergeMulTest, MatchingInstructionFoldingTest,
  5378. ::testing::Values(
  5379. // Test case 0: fold consecutive fmuls
  5380. // (x * 3.0) * 2.0 = x * 6.0
  5381. InstructionFoldingCase<bool>(
  5382. Header() +
  5383. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5384. "; CHECK: [[float_6:%\\w+]] = OpConstant [[float]] 6\n" +
  5385. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  5386. "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_6]]\n" +
  5387. "%main = OpFunction %void None %void_func\n" +
  5388. "%main_lab = OpLabel\n" +
  5389. "%var = OpVariable %_ptr_float Function\n" +
  5390. "%2 = OpLoad %float %var\n" +
  5391. "%3 = OpFMul %float %2 %float_3\n" +
  5392. "%4 = OpFMul %float %3 %float_2\n" +
  5393. "OpReturn\n" +
  5394. "OpFunctionEnd\n",
  5395. 4, true),
  5396. // Test case 1: fold consecutive fmuls
  5397. // 2.0 * (x * 3.0) = x * 6.0
  5398. InstructionFoldingCase<bool>(
  5399. Header() +
  5400. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5401. "; CHECK: [[float_6:%\\w+]] = OpConstant [[float]] 6\n" +
  5402. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  5403. "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_6]]\n" +
  5404. "%main = OpFunction %void None %void_func\n" +
  5405. "%main_lab = OpLabel\n" +
  5406. "%var = OpVariable %_ptr_float Function\n" +
  5407. "%2 = OpLoad %float %var\n" +
  5408. "%3 = OpFMul %float %2 %float_3\n" +
  5409. "%4 = OpFMul %float %float_2 %3\n" +
  5410. "OpReturn\n" +
  5411. "OpFunctionEnd\n",
  5412. 4, true),
  5413. // Test case 2: fold consecutive fmuls
  5414. // (3.0 * x) * 2.0 = x * 6.0
  5415. InstructionFoldingCase<bool>(
  5416. Header() +
  5417. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5418. "; CHECK: [[float_6:%\\w+]] = OpConstant [[float]] 6\n" +
  5419. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  5420. "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_6]]\n" +
  5421. "%main = OpFunction %void None %void_func\n" +
  5422. "%main_lab = OpLabel\n" +
  5423. "%var = OpVariable %_ptr_float Function\n" +
  5424. "%2 = OpLoad %float %var\n" +
  5425. "%3 = OpFMul %float %float_3 %2\n" +
  5426. "%4 = OpFMul %float %float_2 %3\n" +
  5427. "OpReturn\n" +
  5428. "OpFunctionEnd\n",
  5429. 4, true),
  5430. // Test case 3: fold vector fmul
  5431. InstructionFoldingCase<bool>(
  5432. Header() +
  5433. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5434. "; CHECK: [[v2float:%\\w+]] = OpTypeVector [[float]] 2\n" +
  5435. "; CHECK: [[float_6:%\\w+]] = OpConstant [[float]] 6\n" +
  5436. "; CHECK: [[v2float_6_6:%\\w+]] = OpConstantComposite [[v2float]] [[float_6]] [[float_6]]\n" +
  5437. "; CHECK: [[ld:%\\w+]] = OpLoad [[v2float]]\n" +
  5438. "; CHECK: %4 = OpFMul [[v2float]] [[ld]] [[v2float_6_6]]\n" +
  5439. "%main = OpFunction %void None %void_func\n" +
  5440. "%main_lab = OpLabel\n" +
  5441. "%var = OpVariable %_ptr_v2float Function\n" +
  5442. "%2 = OpLoad %v2float %var\n" +
  5443. "%3 = OpFMul %v2float %2 %v2float_2_3\n" +
  5444. "%4 = OpFMul %v2float %3 %v2float_3_2\n" +
  5445. "OpReturn\n" +
  5446. "OpFunctionEnd\n",
  5447. 4, true),
  5448. // Test case 4: fold double fmuls
  5449. // (x * 3.0) * 2.0 = x * 6.0
  5450. InstructionFoldingCase<bool>(
  5451. Header() +
  5452. "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
  5453. "; CHECK: [[double_6:%\\w+]] = OpConstant [[double]] 6\n" +
  5454. "; CHECK: [[ld:%\\w+]] = OpLoad [[double]]\n" +
  5455. "; CHECK: %4 = OpFMul [[double]] [[ld]] [[double_6]]\n" +
  5456. "%main = OpFunction %void None %void_func\n" +
  5457. "%main_lab = OpLabel\n" +
  5458. "%var = OpVariable %_ptr_double Function\n" +
  5459. "%2 = OpLoad %double %var\n" +
  5460. "%3 = OpFMul %double %2 %double_3\n" +
  5461. "%4 = OpFMul %double %3 %double_2\n" +
  5462. "OpReturn\n" +
  5463. "OpFunctionEnd\n",
  5464. 4, true),
  5465. // Test case 5: fold 32 bit imuls
  5466. // (x * 3) * 2 = x * 6
  5467. InstructionFoldingCase<bool>(
  5468. Header() +
  5469. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  5470. "; CHECK: [[int_6:%\\w+]] = OpConstant [[int]] 6\n" +
  5471. "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
  5472. "; CHECK: %4 = OpIMul [[int]] [[ld]] [[int_6]]\n" +
  5473. "%main = OpFunction %void None %void_func\n" +
  5474. "%main_lab = OpLabel\n" +
  5475. "%var = OpVariable %_ptr_int Function\n" +
  5476. "%2 = OpLoad %int %var\n" +
  5477. "%3 = OpIMul %int %2 %int_3\n" +
  5478. "%4 = OpIMul %int %3 %int_2\n" +
  5479. "OpReturn\n" +
  5480. "OpFunctionEnd\n",
  5481. 4, true),
  5482. // Test case 6: fold 64 bit imuls
  5483. // (x * 3) * 2 = x * 6
  5484. InstructionFoldingCase<bool>(
  5485. Header() +
  5486. "; CHECK: [[long:%\\w+]] = OpTypeInt 64\n" +
  5487. "; CHECK: [[long_6:%\\w+]] = OpConstant [[long]] 6\n" +
  5488. "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
  5489. "; CHECK: %4 = OpIMul [[long]] [[ld]] [[long_6]]\n" +
  5490. "%main = OpFunction %void None %void_func\n" +
  5491. "%main_lab = OpLabel\n" +
  5492. "%var = OpVariable %_ptr_long Function\n" +
  5493. "%2 = OpLoad %long %var\n" +
  5494. "%3 = OpIMul %long %2 %long_3\n" +
  5495. "%4 = OpIMul %long %3 %long_2\n" +
  5496. "OpReturn\n" +
  5497. "OpFunctionEnd\n",
  5498. 4, true),
  5499. // Test case 7: merge vector integer mults
  5500. InstructionFoldingCase<bool>(
  5501. Header() +
  5502. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  5503. "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2\n" +
  5504. "; CHECK: [[int_6:%\\w+]] = OpConstant [[int]] 6\n" +
  5505. "; CHECK: [[v2int_6_6:%\\w+]] = OpConstantComposite [[v2int]] [[int_6]] [[int_6]]\n" +
  5506. "; CHECK: [[ld:%\\w+]] = OpLoad [[v2int]]\n" +
  5507. "; CHECK: %4 = OpIMul [[v2int]] [[ld]] [[v2int_6_6]]\n" +
  5508. "%main = OpFunction %void None %void_func\n" +
  5509. "%main_lab = OpLabel\n" +
  5510. "%var = OpVariable %_ptr_v2int Function\n" +
  5511. "%2 = OpLoad %v2int %var\n" +
  5512. "%3 = OpIMul %v2int %2 %v2int_2_3\n" +
  5513. "%4 = OpIMul %v2int %3 %v2int_3_2\n" +
  5514. "OpReturn\n" +
  5515. "OpFunctionEnd\n",
  5516. 4, true),
  5517. // Test case 8: merge fmul of fdiv
  5518. // 2.0 * (2.0 / x) = 4.0 / x
  5519. InstructionFoldingCase<bool>(
  5520. Header() +
  5521. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5522. "; CHECK: [[float_4:%\\w+]] = OpConstant [[float]] 4\n" +
  5523. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  5524. "; CHECK: %4 = OpFDiv [[float]] [[float_4]] [[ld]]\n" +
  5525. "%main = OpFunction %void None %void_func\n" +
  5526. "%main_lab = OpLabel\n" +
  5527. "%var = OpVariable %_ptr_float Function\n" +
  5528. "%2 = OpLoad %float %var\n" +
  5529. "%3 = OpFDiv %float %float_2 %2\n" +
  5530. "%4 = OpFMul %float %float_2 %3\n" +
  5531. "OpReturn\n" +
  5532. "OpFunctionEnd\n",
  5533. 4, true),
  5534. // Test case 9: merge fmul of fdiv
  5535. // (2.0 / x) * 2.0 = 4.0 / x
  5536. InstructionFoldingCase<bool>(
  5537. Header() +
  5538. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5539. "; CHECK: [[float_4:%\\w+]] = OpConstant [[float]] 4\n" +
  5540. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  5541. "; CHECK: %4 = OpFDiv [[float]] [[float_4]] [[ld]]\n" +
  5542. "%main = OpFunction %void None %void_func\n" +
  5543. "%main_lab = OpLabel\n" +
  5544. "%var = OpVariable %_ptr_float Function\n" +
  5545. "%2 = OpLoad %float %var\n" +
  5546. "%3 = OpFDiv %float %float_2 %2\n" +
  5547. "%4 = OpFMul %float %3 %float_2\n" +
  5548. "OpReturn\n" +
  5549. "OpFunctionEnd\n",
  5550. 4, true),
  5551. // Test case 10: Do not merge imul of sdiv
  5552. // 4 * (x / 2)
  5553. InstructionFoldingCase<bool>(
  5554. Header() +
  5555. "%main = OpFunction %void None %void_func\n" +
  5556. "%main_lab = OpLabel\n" +
  5557. "%var = OpVariable %_ptr_int Function\n" +
  5558. "%2 = OpLoad %int %var\n" +
  5559. "%3 = OpSDiv %int %2 %int_2\n" +
  5560. "%4 = OpIMul %int %int_4 %3\n" +
  5561. "OpReturn\n" +
  5562. "OpFunctionEnd\n",
  5563. 4, false),
  5564. // Test case 11: Do not merge imul of sdiv
  5565. // (x / 2) * 4
  5566. InstructionFoldingCase<bool>(
  5567. Header() +
  5568. "%main = OpFunction %void None %void_func\n" +
  5569. "%main_lab = OpLabel\n" +
  5570. "%var = OpVariable %_ptr_int Function\n" +
  5571. "%2 = OpLoad %int %var\n" +
  5572. "%3 = OpSDiv %int %2 %int_2\n" +
  5573. "%4 = OpIMul %int %3 %int_4\n" +
  5574. "OpReturn\n" +
  5575. "OpFunctionEnd\n",
  5576. 4, false),
  5577. // Test case 12: Do not merge imul of udiv
  5578. // 4 * (x / 2)
  5579. InstructionFoldingCase<bool>(
  5580. Header() +
  5581. "%main = OpFunction %void None %void_func\n" +
  5582. "%main_lab = OpLabel\n" +
  5583. "%var = OpVariable %_ptr_uint Function\n" +
  5584. "%2 = OpLoad %uint %var\n" +
  5585. "%3 = OpUDiv %uint %2 %uint_2\n" +
  5586. "%4 = OpIMul %uint %uint_4 %3\n" +
  5587. "OpReturn\n" +
  5588. "OpFunctionEnd\n",
  5589. 4, false),
  5590. // Test case 13: Do not merge imul of udiv
  5591. // (x / 2) * 4
  5592. InstructionFoldingCase<bool>(
  5593. Header() +
  5594. "%main = OpFunction %void None %void_func\n" +
  5595. "%main_lab = OpLabel\n" +
  5596. "%var = OpVariable %_ptr_uint Function\n" +
  5597. "%2 = OpLoad %uint %var\n" +
  5598. "%3 = OpUDiv %uint %2 %uint_2\n" +
  5599. "%4 = OpIMul %uint %3 %uint_4\n" +
  5600. "OpReturn\n" +
  5601. "OpFunctionEnd\n",
  5602. 4, false),
  5603. // Test case 14: Don't fold
  5604. // (x / 3) * 4
  5605. InstructionFoldingCase<bool>(
  5606. Header() +
  5607. "%main = OpFunction %void None %void_func\n" +
  5608. "%main_lab = OpLabel\n" +
  5609. "%var = OpVariable %_ptr_uint Function\n" +
  5610. "%2 = OpLoad %uint %var\n" +
  5611. "%3 = OpUDiv %uint %2 %uint_3\n" +
  5612. "%4 = OpIMul %uint %3 %uint_4\n" +
  5613. "OpReturn\n" +
  5614. "OpFunctionEnd\n",
  5615. 4, false),
  5616. // Test case 15: merge vector fmul of fdiv
  5617. // (x / {2,2}) * {4,4} = x * {2,2}
  5618. InstructionFoldingCase<bool>(
  5619. Header() +
  5620. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5621. "; CHECK: [[v2float:%\\w+]] = OpTypeVector [[float]] 2\n" +
  5622. "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
  5623. "; CHECK: [[v2float_2_2:%\\w+]] = OpConstantComposite [[v2float]] [[float_2]] [[float_2]]\n" +
  5624. "; CHECK: [[ld:%\\w+]] = OpLoad [[v2float]]\n" +
  5625. "; CHECK: %4 = OpFMul [[v2float]] [[ld]] [[v2float_2_2]]\n" +
  5626. "%main = OpFunction %void None %void_func\n" +
  5627. "%main_lab = OpLabel\n" +
  5628. "%var = OpVariable %_ptr_v2float Function\n" +
  5629. "%2 = OpLoad %v2float %var\n" +
  5630. "%3 = OpFDiv %v2float %2 %v2float_2_2\n" +
  5631. "%4 = OpFMul %v2float %3 %v2float_4_4\n" +
  5632. "OpReturn\n" +
  5633. "OpFunctionEnd\n",
  5634. 4, true),
  5635. // Test case 16: merge vector imul of snegate
  5636. // (-x) * {2,2} = x * {-2,-2}
  5637. InstructionFoldingCase<bool>(
  5638. Header() +
  5639. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  5640. "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2{{[[:space:]]}}\n" +
  5641. "; CHECK: OpConstant [[int]] -2147483648{{[[:space:]]}}\n" +
  5642. "; CHECK: [[int_n2:%\\w+]] = OpConstant [[int]] -2{{[[:space:]]}}\n" +
  5643. "; CHECK: [[v2int_n2_n2:%\\w+]] = OpConstantComposite [[v2int]] [[int_n2]] [[int_n2]]\n" +
  5644. "; CHECK: [[ld:%\\w+]] = OpLoad [[v2int]]\n" +
  5645. "; CHECK: %4 = OpIMul [[v2int]] [[ld]] [[v2int_n2_n2]]\n" +
  5646. "%main = OpFunction %void None %void_func\n" +
  5647. "%main_lab = OpLabel\n" +
  5648. "%var = OpVariable %_ptr_v2int Function\n" +
  5649. "%2 = OpLoad %v2int %var\n" +
  5650. "%3 = OpSNegate %v2int %2\n" +
  5651. "%4 = OpIMul %v2int %3 %v2int_2_2\n" +
  5652. "OpReturn\n" +
  5653. "OpFunctionEnd\n",
  5654. 4, true),
  5655. // Test case 17: merge vector imul of snegate
  5656. // {2,2} * (-x) = x * {-2,-2}
  5657. InstructionFoldingCase<bool>(
  5658. Header() +
  5659. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  5660. "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2{{[[:space:]]}}\n" +
  5661. "; CHECK: OpConstant [[int]] -2147483648{{[[:space:]]}}\n" +
  5662. "; CHECK: [[int_n2:%\\w+]] = OpConstant [[int]] -2{{[[:space:]]}}\n" +
  5663. "; CHECK: [[v2int_n2_n2:%\\w+]] = OpConstantComposite [[v2int]] [[int_n2]] [[int_n2]]\n" +
  5664. "; CHECK: [[ld:%\\w+]] = OpLoad [[v2int]]\n" +
  5665. "; CHECK: %4 = OpIMul [[v2int]] [[ld]] [[v2int_n2_n2]]\n" +
  5666. "%main = OpFunction %void None %void_func\n" +
  5667. "%main_lab = OpLabel\n" +
  5668. "%var = OpVariable %_ptr_v2int Function\n" +
  5669. "%2 = OpLoad %v2int %var\n" +
  5670. "%3 = OpSNegate %v2int %2\n" +
  5671. "%4 = OpIMul %v2int %v2int_2_2 %3\n" +
  5672. "OpReturn\n" +
  5673. "OpFunctionEnd\n",
  5674. 4, true),
  5675. // Test case 18: Fold OpVectorTimesScalar
  5676. // {4,4} = OpVectorTimesScalar v2float {2,2} 2
  5677. InstructionFoldingCase<bool>(
  5678. Header() +
  5679. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5680. "; CHECK: [[v2float:%\\w+]] = OpTypeVector [[float]] 2\n" +
  5681. "; CHECK: [[float_4:%\\w+]] = OpConstant [[float]] 4\n" +
  5682. "; CHECK: [[v2float_4_4:%\\w+]] = OpConstantComposite [[v2float]] [[float_4]] [[float_4]]\n" +
  5683. "; CHECK: %2 = OpCopyObject [[v2float]] [[v2float_4_4]]\n" +
  5684. "%main = OpFunction %void None %void_func\n" +
  5685. "%main_lab = OpLabel\n" +
  5686. "%2 = OpVectorTimesScalar %v2float %v2float_2_2 %float_2\n" +
  5687. "OpReturn\n" +
  5688. "OpFunctionEnd",
  5689. 2, true),
  5690. // Test case 19: Fold OpVectorTimesScalar
  5691. // {0,0} = OpVectorTimesScalar v2float v2float_null -1
  5692. InstructionFoldingCase<bool>(
  5693. Header() +
  5694. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5695. "; CHECK: [[v2float:%\\w+]] = OpTypeVector [[float]] 2\n" +
  5696. "; CHECK: [[v2float_null:%\\w+]] = OpConstantNull [[v2float]]\n" +
  5697. "; CHECK: %2 = OpCopyObject [[v2float]] [[v2float_null]]\n" +
  5698. "%main = OpFunction %void None %void_func\n" +
  5699. "%main_lab = OpLabel\n" +
  5700. "%2 = OpVectorTimesScalar %v2float %v2float_null %float_n1\n" +
  5701. "OpReturn\n" +
  5702. "OpFunctionEnd",
  5703. 2, true),
  5704. // Test case 20: Fold OpVectorTimesScalar
  5705. // {4,4} = OpVectorTimesScalar v2double {2,2} 2
  5706. InstructionFoldingCase<bool>(
  5707. Header() +
  5708. "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
  5709. "; CHECK: [[v2double:%\\w+]] = OpTypeVector [[double]] 2\n" +
  5710. "; CHECK: [[double_4:%\\w+]] = OpConstant [[double]] 4\n" +
  5711. "; CHECK: [[v2double_4_4:%\\w+]] = OpConstantComposite [[v2double]] [[double_4]] [[double_4]]\n" +
  5712. "; CHECK: %2 = OpCopyObject [[v2double]] [[v2double_4_4]]\n" +
  5713. "%main = OpFunction %void None %void_func\n" +
  5714. "%main_lab = OpLabel\n" +
  5715. "%2 = OpVectorTimesScalar %v2double %v2double_2_2 %double_2\n" +
  5716. "OpReturn\n" +
  5717. "OpFunctionEnd",
  5718. 2, true),
  5719. // Test case 21: Fold OpVectorTimesScalar
  5720. // {0,0} = OpVectorTimesScalar v2double {0,0} n
  5721. InstructionFoldingCase<bool>(
  5722. Header() +
  5723. "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
  5724. "; CHECK: [[v2double:%\\w+]] = OpTypeVector [[double]] 2\n" +
  5725. "; CHECK: {{%\\w+}} = OpConstant [[double]] 0\n" +
  5726. "; CHECK: [[double_0:%\\w+]] = OpConstant [[double]] 0\n" +
  5727. "; CHECK: [[v2double_0_0:%\\w+]] = OpConstantComposite [[v2double]] [[double_0]] [[double_0]]\n" +
  5728. "; CHECK: %2 = OpCopyObject [[v2double]] [[v2double_0_0]]\n" +
  5729. "%main = OpFunction %void None %void_func\n" +
  5730. "%main_lab = OpLabel\n" +
  5731. "%n = OpVariable %_ptr_double Function\n" +
  5732. "%load = OpLoad %double %n\n" +
  5733. "%2 = OpVectorTimesScalar %v2double %v2double_0_0 %load\n" +
  5734. "OpReturn\n" +
  5735. "OpFunctionEnd",
  5736. 2, true),
  5737. // Test case 22: Fold OpVectorTimesScalar
  5738. // {0,0} = OpVectorTimesScalar v2double n 0
  5739. InstructionFoldingCase<bool>(
  5740. Header() +
  5741. "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
  5742. "; CHECK: [[v2double:%\\w+]] = OpTypeVector [[double]] 2\n" +
  5743. "; CHECK: [[v2double_null:%\\w+]] = OpConstantNull [[v2double]]\n" +
  5744. "; CHECK: %2 = OpCopyObject [[v2double]] [[v2double_null]]\n" +
  5745. "%main = OpFunction %void None %void_func\n" +
  5746. "%main_lab = OpLabel\n" +
  5747. "%n = OpVariable %_ptr_v2double Function\n" +
  5748. "%load = OpLoad %v2double %n\n" +
  5749. "%2 = OpVectorTimesScalar %v2double %load %double_0\n" +
  5750. "OpReturn\n" +
  5751. "OpFunctionEnd",
  5752. 2, true),
  5753. // Test case 23: merge fmul of fdiv
  5754. // x * (y / x) = y
  5755. InstructionFoldingCase<bool>(
  5756. Header() +
  5757. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5758. "; CHECK: [[ldx:%\\w+]] = OpLoad [[float]]\n" +
  5759. "; CHECK: [[ldy:%\\w+]] = OpLoad [[float]] [[y:%\\w+]]\n" +
  5760. "; CHECK: %5 = OpCopyObject [[float]] [[ldy]]\n" +
  5761. "%main = OpFunction %void None %void_func\n" +
  5762. "%main_lab = OpLabel\n" +
  5763. "%x = OpVariable %_ptr_float Function\n" +
  5764. "%y = OpVariable %_ptr_float Function\n" +
  5765. "%2 = OpLoad %float %x\n" +
  5766. "%3 = OpLoad %float %y\n" +
  5767. "%4 = OpFDiv %float %3 %2\n" +
  5768. "%5 = OpFMul %float %2 %4\n" +
  5769. "OpReturn\n" +
  5770. "OpFunctionEnd\n",
  5771. 5, true),
  5772. // Test case 24: merge fmul of fdiv
  5773. // (y / x) * x = y
  5774. InstructionFoldingCase<bool>(
  5775. Header() +
  5776. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5777. "; CHECK: [[ldx:%\\w+]] = OpLoad [[float]]\n" +
  5778. "; CHECK: [[ldy:%\\w+]] = OpLoad [[float]] [[y:%\\w+]]\n" +
  5779. "; CHECK: %5 = OpCopyObject [[float]] [[ldy]]\n" +
  5780. "%main = OpFunction %void None %void_func\n" +
  5781. "%main_lab = OpLabel\n" +
  5782. "%x = OpVariable %_ptr_float Function\n" +
  5783. "%y = OpVariable %_ptr_float Function\n" +
  5784. "%2 = OpLoad %float %x\n" +
  5785. "%3 = OpLoad %float %y\n" +
  5786. "%4 = OpFDiv %float %3 %2\n" +
  5787. "%5 = OpFMul %float %4 %2\n" +
  5788. "OpReturn\n" +
  5789. "OpFunctionEnd\n",
  5790. 5, true),
  5791. // Test case 25: fold overflowing signed 32 bit imuls
  5792. // (x * 1073741824) * 2 = x * int_min
  5793. InstructionFoldingCase<bool>(
  5794. Header() +
  5795. "; CHECK: [[int:%\\w+]] = OpTypeInt 32\n" +
  5796. "; CHECK: [[int_min:%\\w+]] = OpConstant [[int]] -2147483648\n" +
  5797. "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
  5798. "; CHECK: %4 = OpIMul [[int]] [[ld]] [[int_min]]\n" +
  5799. "%main = OpFunction %void None %void_func\n" +
  5800. "%main_lab = OpLabel\n" +
  5801. "%var = OpVariable %_ptr_int Function\n" +
  5802. "%2 = OpLoad %int %var\n" +
  5803. "%3 = OpIMul %int %2 %int_1073741824\n" +
  5804. "%4 = OpIMul %int %3 %int_2\n" +
  5805. "OpReturn\n" +
  5806. "OpFunctionEnd\n",
  5807. 4, true),
  5808. // Test case 26: fold overflowing signed 64 bit imuls
  5809. // (x * 4611686018427387904) * 2 = x * long_min
  5810. InstructionFoldingCase<bool>(
  5811. Header() +
  5812. "; CHECK: [[long:%\\w+]] = OpTypeInt 64\n" +
  5813. "; CHECK: [[long_min:%\\w+]] = OpConstant [[long]] -9223372036854775808\n" +
  5814. "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
  5815. "; CHECK: %4 = OpIMul [[long]] [[ld]] [[long_min]]\n" +
  5816. "%main = OpFunction %void None %void_func\n" +
  5817. "%main_lab = OpLabel\n" +
  5818. "%var = OpVariable %_ptr_long Function\n" +
  5819. "%2 = OpLoad %long %var\n" +
  5820. "%3 = OpIMul %long %2 %long_4611686018427387904\n" +
  5821. "%4 = OpIMul %long %3 %long_2\n" +
  5822. "OpReturn\n" +
  5823. "OpFunctionEnd\n",
  5824. 4, true),
  5825. // Test case 27: fold overflowing 32 bit unsigned imuls
  5826. // (x * 2147483649) * 2 = x * 2
  5827. InstructionFoldingCase<bool>(
  5828. Header() +
  5829. "; CHECK: [[uint:%\\w+]] = OpTypeInt 32 0\n" +
  5830. "; CHECK: [[uint_2:%\\w+]] = OpConstant [[uint]] 2\n" +
  5831. "; CHECK: [[ld:%\\w+]] = OpLoad [[uint]]\n" +
  5832. "; CHECK: %4 = OpIMul [[uint]] [[ld]] [[uint_2]]\n" +
  5833. "%main = OpFunction %void None %void_func\n" +
  5834. "%main_lab = OpLabel\n" +
  5835. "%var = OpVariable %_ptr_uint Function\n" +
  5836. "%2 = OpLoad %uint %var\n" +
  5837. "%3 = OpIMul %uint %2 %uint_2147483649\n" +
  5838. "%4 = OpIMul %uint %3 %uint_2\n" +
  5839. "OpReturn\n" +
  5840. "OpFunctionEnd\n",
  5841. 4, true),
  5842. // Test case 28: fold overflowing 64 bit unsigned imuls
  5843. // (x * 9223372036854775809) * 2 = x * 2
  5844. InstructionFoldingCase<bool>(
  5845. Header() +
  5846. "; CHECK: [[ulong:%\\w+]] = OpTypeInt 64 0\n" +
  5847. "; CHECK: [[ulong_2:%\\w+]] = OpConstant [[ulong]] 2\n" +
  5848. "; CHECK: [[ld:%\\w+]] = OpLoad [[ulong]]\n" +
  5849. "; CHECK: %4 = OpIMul [[ulong]] [[ld]] [[ulong_2]]\n" +
  5850. "%main = OpFunction %void None %void_func\n" +
  5851. "%main_lab = OpLabel\n" +
  5852. "%var = OpVariable %_ptr_ulong Function\n" +
  5853. "%2 = OpLoad %ulong %var\n" +
  5854. "%3 = OpIMul %ulong %2 %ulong_9223372036854775809\n" +
  5855. "%4 = OpIMul %ulong %3 %ulong_2\n" +
  5856. "OpReturn\n" +
  5857. "OpFunctionEnd\n",
  5858. 4, true),
  5859. // Test case 29: fold underflowing signed 32 bit imuls
  5860. // (x * (-858993459)) * 10 = x * 2
  5861. InstructionFoldingCase<bool>(
  5862. Header() +
  5863. "; CHECK: [[int:%\\w+]] = OpTypeInt 32\n" +
  5864. "; CHECK: [[int_2:%\\w+]] = OpConstant [[int]] 2\n" +
  5865. "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
  5866. "; CHECK: %4 = OpIMul [[int]] [[ld]] [[int_2]]\n" +
  5867. "%main = OpFunction %void None %void_func\n" +
  5868. "%main_lab = OpLabel\n" +
  5869. "%var = OpVariable %_ptr_int Function\n" +
  5870. "%2 = OpLoad %int %var\n" +
  5871. "%3 = OpIMul %int %2 %int_n858993459\n" +
  5872. "%4 = OpIMul %int %3 %int_10\n" +
  5873. "OpReturn\n" +
  5874. "OpFunctionEnd\n",
  5875. 4, true),
  5876. // Test case 30: fold underflowing signed 64 bit imuls
  5877. // (x * (-3689348814741910323)) * 10 = x * 2
  5878. InstructionFoldingCase<bool>(
  5879. Header() +
  5880. "; CHECK: [[long:%\\w+]] = OpTypeInt 64\n" +
  5881. "; CHECK: [[long_2:%\\w+]] = OpConstant [[long]] 2\n" +
  5882. "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
  5883. "; CHECK: %4 = OpIMul [[long]] [[ld]] [[long_2]]\n" +
  5884. "%main = OpFunction %void None %void_func\n" +
  5885. "%main_lab = OpLabel\n" +
  5886. "%var = OpVariable %_ptr_long Function\n" +
  5887. "%2 = OpLoad %long %var\n" +
  5888. "%3 = OpIMul %long %2 %long_n3689348814741910323\n" +
  5889. "%4 = OpIMul %long %3 %long_10\n" +
  5890. "OpReturn\n" +
  5891. "OpFunctionEnd\n",
  5892. 4, true)
  5893. ));
  5894. INSTANTIATE_TEST_SUITE_P(MergeDivTest, MatchingInstructionFoldingTest,
  5895. ::testing::Values(
  5896. // Test case 0: merge consecutive fdiv
  5897. // 4.0 / (2.0 / x) = 2.0 * x
  5898. InstructionFoldingCase<bool>(
  5899. Header() +
  5900. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5901. "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
  5902. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  5903. "; CHECK: %4 = OpFMul [[float]] [[float_2]] [[ld]]\n" +
  5904. "%main = OpFunction %void None %void_func\n" +
  5905. "%main_lab = OpLabel\n" +
  5906. "%var = OpVariable %_ptr_float Function\n" +
  5907. "%2 = OpLoad %float %var\n" +
  5908. "%3 = OpFDiv %float %float_2 %2\n" +
  5909. "%4 = OpFDiv %float %float_4 %3\n" +
  5910. "OpReturn\n" +
  5911. "OpFunctionEnd\n",
  5912. 4, true),
  5913. // Test case 1: merge consecutive fdiv
  5914. // 4.0 / (x / 2.0) = 8.0 / x
  5915. InstructionFoldingCase<bool>(
  5916. Header() +
  5917. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5918. "; CHECK: [[float_8:%\\w+]] = OpConstant [[float]] 8\n" +
  5919. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  5920. "; CHECK: %4 = OpFDiv [[float]] [[float_8]] [[ld]]\n" +
  5921. "%main = OpFunction %void None %void_func\n" +
  5922. "%main_lab = OpLabel\n" +
  5923. "%var = OpVariable %_ptr_float Function\n" +
  5924. "%2 = OpLoad %float %var\n" +
  5925. "%3 = OpFDiv %float %2 %float_2\n" +
  5926. "%4 = OpFDiv %float %float_4 %3\n" +
  5927. "OpReturn\n" +
  5928. "OpFunctionEnd\n",
  5929. 4, true),
  5930. // Test case 2: merge consecutive fdiv
  5931. // (4.0 / x) / 2.0 = 2.0 / x
  5932. InstructionFoldingCase<bool>(
  5933. Header() +
  5934. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5935. "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
  5936. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  5937. "; CHECK: %4 = OpFDiv [[float]] [[float_2]] [[ld]]\n" +
  5938. "%main = OpFunction %void None %void_func\n" +
  5939. "%main_lab = OpLabel\n" +
  5940. "%var = OpVariable %_ptr_float Function\n" +
  5941. "%2 = OpLoad %float %var\n" +
  5942. "%3 = OpFDiv %float %float_4 %2\n" +
  5943. "%4 = OpFDiv %float %3 %float_2\n" +
  5944. "OpReturn\n" +
  5945. "OpFunctionEnd\n",
  5946. 4, true),
  5947. // Test case 3: Do not merge consecutive sdiv
  5948. // 4 / (2 / x)
  5949. InstructionFoldingCase<bool>(
  5950. Header() +
  5951. "%main = OpFunction %void None %void_func\n" +
  5952. "%main_lab = OpLabel\n" +
  5953. "%var = OpVariable %_ptr_int Function\n" +
  5954. "%2 = OpLoad %int %var\n" +
  5955. "%3 = OpSDiv %int %int_2 %2\n" +
  5956. "%4 = OpSDiv %int %int_4 %3\n" +
  5957. "OpReturn\n" +
  5958. "OpFunctionEnd\n",
  5959. 4, false),
  5960. // Test case 4: Do not merge consecutive sdiv
  5961. // 4 / (x / 2)
  5962. InstructionFoldingCase<bool>(
  5963. Header() +
  5964. "%main = OpFunction %void None %void_func\n" +
  5965. "%main_lab = OpLabel\n" +
  5966. "%var = OpVariable %_ptr_int Function\n" +
  5967. "%2 = OpLoad %int %var\n" +
  5968. "%3 = OpSDiv %int %2 %int_2\n" +
  5969. "%4 = OpSDiv %int %int_4 %3\n" +
  5970. "OpReturn\n" +
  5971. "OpFunctionEnd\n",
  5972. 4, false),
  5973. // Test case 5: Do not merge consecutive sdiv
  5974. // (4 / x) / 2
  5975. InstructionFoldingCase<bool>(
  5976. Header() +
  5977. "%main = OpFunction %void None %void_func\n" +
  5978. "%main_lab = OpLabel\n" +
  5979. "%var = OpVariable %_ptr_int Function\n" +
  5980. "%2 = OpLoad %int %var\n" +
  5981. "%3 = OpSDiv %int %int_4 %2\n" +
  5982. "%4 = OpSDiv %int %3 %int_2\n" +
  5983. "OpReturn\n" +
  5984. "OpFunctionEnd\n",
  5985. 4, false),
  5986. // Test case 6: Do not merge consecutive sdiv
  5987. // (x / 4) / 2
  5988. InstructionFoldingCase<bool>(
  5989. Header() +
  5990. "%main = OpFunction %void None %void_func\n" +
  5991. "%main_lab = OpLabel\n" +
  5992. "%var = OpVariable %_ptr_int Function\n" +
  5993. "%2 = OpLoad %int %var\n" +
  5994. "%3 = OpSDiv %int %2 %int_4\n" +
  5995. "%4 = OpSDiv %int %3 %int_2\n" +
  5996. "OpReturn\n" +
  5997. "OpFunctionEnd\n",
  5998. 4, false),
  5999. // Test case 7: Do not merge sdiv of imul
  6000. // 4 / (2 * x)
  6001. InstructionFoldingCase<bool>(
  6002. Header() +
  6003. "%main = OpFunction %void None %void_func\n" +
  6004. "%main_lab = OpLabel\n" +
  6005. "%var = OpVariable %_ptr_int Function\n" +
  6006. "%2 = OpLoad %int %var\n" +
  6007. "%3 = OpIMul %int %int_2 %2\n" +
  6008. "%4 = OpSDiv %int %int_4 %3\n" +
  6009. "OpReturn\n" +
  6010. "OpFunctionEnd\n",
  6011. 4, false),
  6012. // Test case 8: Do not merge sdiv of imul
  6013. // 4 / (x * 2)
  6014. InstructionFoldingCase<bool>(
  6015. Header() +
  6016. "%main = OpFunction %void None %void_func\n" +
  6017. "%main_lab = OpLabel\n" +
  6018. "%var = OpVariable %_ptr_int Function\n" +
  6019. "%2 = OpLoad %int %var\n" +
  6020. "%3 = OpIMul %int %2 %int_2\n" +
  6021. "%4 = OpSDiv %int %int_4 %3\n" +
  6022. "OpReturn\n" +
  6023. "OpFunctionEnd\n",
  6024. 4, false),
  6025. // Test case 9: Do not merge sdiv of imul
  6026. // (4 * x) / 2
  6027. InstructionFoldingCase<bool>(
  6028. Header() +
  6029. "%main = OpFunction %void None %void_func\n" +
  6030. "%main_lab = OpLabel\n" +
  6031. "%var = OpVariable %_ptr_int Function\n" +
  6032. "%2 = OpLoad %int %var\n" +
  6033. "%3 = OpIMul %int %int_4 %2\n" +
  6034. "%4 = OpSDiv %int %3 %int_2\n" +
  6035. "OpReturn\n" +
  6036. "OpFunctionEnd\n",
  6037. 4, false),
  6038. // Test case 10: Do not merge sdiv of imul
  6039. // (x * 4) / 2
  6040. InstructionFoldingCase<bool>(
  6041. Header() +
  6042. "%main = OpFunction %void None %void_func\n" +
  6043. "%main_lab = OpLabel\n" +
  6044. "%var = OpVariable %_ptr_int Function\n" +
  6045. "%2 = OpLoad %int %var\n" +
  6046. "%3 = OpIMul %int %2 %int_4\n" +
  6047. "%4 = OpSDiv %int %3 %int_2\n" +
  6048. "OpReturn\n" +
  6049. "OpFunctionEnd\n",
  6050. 4, false),
  6051. // Test case 11: Do not merge sdiv of snegate. If %2 is INT_MIN, then the
  6052. // sign of %3 will be the same as %2. This cannot be accounted for in OpSDiv.
  6053. // Specifically, (-INT_MIN) / 2 != INT_MIN / -2.
  6054. InstructionFoldingCase<bool>(
  6055. Header() +
  6056. "%main = OpFunction %void None %void_func\n" +
  6057. "%main_lab = OpLabel\n" +
  6058. "%var = OpVariable %_ptr_int Function\n" +
  6059. "%2 = OpLoad %int %var\n" +
  6060. "%3 = OpSNegate %int %2\n" +
  6061. "%4 = OpSDiv %int %3 %int_2\n" +
  6062. "OpReturn\n" +
  6063. "OpFunctionEnd\n",
  6064. 4, false),
  6065. // Test case 12: Do not merge sdiv of snegate. If %2 is INT_MIN, then the
  6066. // sign of %3 will be the same as %2. This cannot be accounted for in OpSDiv.
  6067. // Specifically, 2 / (-INT_MIN) != -2 / INT_MIN.
  6068. InstructionFoldingCase<bool>(
  6069. Header() +
  6070. "%main = OpFunction %void None %void_func\n" +
  6071. "%main_lab = OpLabel\n" +
  6072. "%var = OpVariable %_ptr_int Function\n" +
  6073. "%2 = OpLoad %int %var\n" +
  6074. "%3 = OpSNegate %int %2\n" +
  6075. "%4 = OpSDiv %int %int_2 %3\n" +
  6076. "OpReturn\n" +
  6077. "OpFunctionEnd\n",
  6078. 4, false),
  6079. // Test case 13: Don't merge
  6080. // (x / {null}) / {null}
  6081. InstructionFoldingCase<bool>(
  6082. Header() +
  6083. "%main = OpFunction %void None %void_func\n" +
  6084. "%main_lab = OpLabel\n" +
  6085. "%var = OpVariable %_ptr_v2float Function\n" +
  6086. "%2 = OpLoad %float %var\n" +
  6087. "%3 = OpFDiv %float %2 %v2float_null\n" +
  6088. "%4 = OpFDiv %float %3 %v2float_null\n" +
  6089. "OpReturn\n" +
  6090. "OpFunctionEnd\n",
  6091. 4, false),
  6092. // Test case 14: merge fmul of fdiv
  6093. // (y * x) / x = y
  6094. InstructionFoldingCase<bool>(
  6095. Header() +
  6096. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  6097. "; CHECK: [[ldx:%\\w+]] = OpLoad [[float]]\n" +
  6098. "; CHECK: [[ldy:%\\w+]] = OpLoad [[float]] [[y:%\\w+]]\n" +
  6099. "; CHECK: %5 = OpCopyObject [[float]] [[ldy]]\n" +
  6100. "%main = OpFunction %void None %void_func\n" +
  6101. "%main_lab = OpLabel\n" +
  6102. "%x = OpVariable %_ptr_float Function\n" +
  6103. "%y = OpVariable %_ptr_float Function\n" +
  6104. "%2 = OpLoad %float %x\n" +
  6105. "%3 = OpLoad %float %y\n" +
  6106. "%4 = OpFMul %float %3 %2\n" +
  6107. "%5 = OpFDiv %float %4 %2\n" +
  6108. "OpReturn\n" +
  6109. "OpFunctionEnd\n",
  6110. 5, true),
  6111. // Test case 15: merge fmul of fdiv
  6112. // (x * y) / x = y
  6113. InstructionFoldingCase<bool>(
  6114. Header() +
  6115. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  6116. "; CHECK: [[ldx:%\\w+]] = OpLoad [[float]]\n" +
  6117. "; CHECK: [[ldy:%\\w+]] = OpLoad [[float]] [[y:%\\w+]]\n" +
  6118. "; CHECK: %5 = OpCopyObject [[float]] [[ldy]]\n" +
  6119. "%main = OpFunction %void None %void_func\n" +
  6120. "%main_lab = OpLabel\n" +
  6121. "%x = OpVariable %_ptr_float Function\n" +
  6122. "%y = OpVariable %_ptr_float Function\n" +
  6123. "%2 = OpLoad %float %x\n" +
  6124. "%3 = OpLoad %float %y\n" +
  6125. "%4 = OpFMul %float %2 %3\n" +
  6126. "%5 = OpFDiv %float %4 %2\n" +
  6127. "OpReturn\n" +
  6128. "OpFunctionEnd\n",
  6129. 5, true),
  6130. // Test case 16: Do not merge udiv of snegate
  6131. // (-x) / 2u
  6132. InstructionFoldingCase<bool>(
  6133. Header() +
  6134. "%main = OpFunction %void None %void_func\n" +
  6135. "%main_lab = OpLabel\n" +
  6136. "%var = OpVariable %_ptr_uint Function\n" +
  6137. "%2 = OpLoad %uint %var\n" +
  6138. "%3 = OpSNegate %uint %2\n" +
  6139. "%4 = OpUDiv %uint %3 %uint_2\n" +
  6140. "OpReturn\n" +
  6141. "OpFunctionEnd\n",
  6142. 4, false),
  6143. // Test case 17: Do not merge udiv of snegate
  6144. // 2u / (-x)
  6145. InstructionFoldingCase<bool>(
  6146. Header() +
  6147. "%main = OpFunction %void None %void_func\n" +
  6148. "%main_lab = OpLabel\n" +
  6149. "%var = OpVariable %_ptr_uint Function\n" +
  6150. "%2 = OpLoad %uint %var\n" +
  6151. "%3 = OpSNegate %uint %2\n" +
  6152. "%4 = OpUDiv %uint %uint_2 %3\n" +
  6153. "OpReturn\n" +
  6154. "OpFunctionEnd\n",
  6155. 4, false)
  6156. ));
  6157. INSTANTIATE_TEST_SUITE_P(MergeAddTest, MatchingInstructionFoldingTest,
  6158. ::testing::Values(
  6159. // Test case 0: merge add of negate
  6160. // (-x) + 2 = 2 - x
  6161. InstructionFoldingCase<bool>(
  6162. Header() +
  6163. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  6164. "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
  6165. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  6166. "; CHECK: %4 = OpFSub [[float]] [[float_2]] [[ld]]\n" +
  6167. "%main = OpFunction %void None %void_func\n" +
  6168. "%main_lab = OpLabel\n" +
  6169. "%var = OpVariable %_ptr_float Function\n" +
  6170. "%2 = OpLoad %float %var\n" +
  6171. "%3 = OpFNegate %float %2\n" +
  6172. "%4 = OpFAdd %float %3 %float_2\n" +
  6173. "OpReturn\n" +
  6174. "OpFunctionEnd\n",
  6175. 4, true),
  6176. // Test case 1: merge add of negate
  6177. // 2 + (-x) = 2 - x
  6178. InstructionFoldingCase<bool>(
  6179. Header() +
  6180. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  6181. "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
  6182. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  6183. "; CHECK: %4 = OpFSub [[float]] [[float_2]] [[ld]]\n" +
  6184. "%main = OpFunction %void None %void_func\n" +
  6185. "%main_lab = OpLabel\n" +
  6186. "%var = OpVariable %_ptr_float Function\n" +
  6187. "%2 = OpLoad %float %var\n" +
  6188. "%3 = OpSNegate %float %2\n" +
  6189. "%4 = OpIAdd %float %float_2 %3\n" +
  6190. "OpReturn\n" +
  6191. "OpFunctionEnd\n",
  6192. 4, true),
  6193. // Test case 2: merge add of negate
  6194. // (-x) + 2 = 2 - x
  6195. InstructionFoldingCase<bool>(
  6196. Header() +
  6197. "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
  6198. "; CHECK: [[long_2:%\\w+]] = OpConstant [[long]] 2\n" +
  6199. "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
  6200. "; CHECK: %4 = OpISub [[long]] [[long_2]] [[ld]]\n" +
  6201. "%main = OpFunction %void None %void_func\n" +
  6202. "%main_lab = OpLabel\n" +
  6203. "%var = OpVariable %_ptr_long Function\n" +
  6204. "%2 = OpLoad %long %var\n" +
  6205. "%3 = OpSNegate %long %2\n" +
  6206. "%4 = OpIAdd %long %3 %long_2\n" +
  6207. "OpReturn\n" +
  6208. "OpFunctionEnd\n",
  6209. 4, true),
  6210. // Test case 3: merge add of negate
  6211. // 2 + (-x) = 2 - x
  6212. InstructionFoldingCase<bool>(
  6213. Header() +
  6214. "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
  6215. "; CHECK: [[long_2:%\\w+]] = OpConstant [[long]] 2\n" +
  6216. "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
  6217. "; CHECK: %4 = OpISub [[long]] [[long_2]] [[ld]]\n" +
  6218. "%main = OpFunction %void None %void_func\n" +
  6219. "%main_lab = OpLabel\n" +
  6220. "%var = OpVariable %_ptr_long Function\n" +
  6221. "%2 = OpLoad %long %var\n" +
  6222. "%3 = OpSNegate %long %2\n" +
  6223. "%4 = OpIAdd %long %long_2 %3\n" +
  6224. "OpReturn\n" +
  6225. "OpFunctionEnd\n",
  6226. 4, true),
  6227. // Test case 4: merge add of subtract
  6228. // (x - 1) + 2 = x + 1
  6229. InstructionFoldingCase<bool>(
  6230. Header() +
  6231. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  6232. "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
  6233. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  6234. "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_1]]\n" +
  6235. "%main = OpFunction %void None %void_func\n" +
  6236. "%main_lab = OpLabel\n" +
  6237. "%var = OpVariable %_ptr_float Function\n" +
  6238. "%2 = OpLoad %float %var\n" +
  6239. "%3 = OpFSub %float %2 %float_1\n" +
  6240. "%4 = OpFAdd %float %3 %float_2\n" +
  6241. "OpReturn\n" +
  6242. "OpFunctionEnd\n",
  6243. 4, true),
  6244. // Test case 5: merge add of subtract
  6245. // (1 - x) + 2 = 3 - x
  6246. InstructionFoldingCase<bool>(
  6247. Header() +
  6248. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  6249. "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
  6250. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  6251. "; CHECK: %4 = OpFSub [[float]] [[float_3]] [[ld]]\n" +
  6252. "%main = OpFunction %void None %void_func\n" +
  6253. "%main_lab = OpLabel\n" +
  6254. "%var = OpVariable %_ptr_float Function\n" +
  6255. "%2 = OpLoad %float %var\n" +
  6256. "%3 = OpFSub %float %float_1 %2\n" +
  6257. "%4 = OpFAdd %float %3 %float_2\n" +
  6258. "OpReturn\n" +
  6259. "OpFunctionEnd\n",
  6260. 4, true),
  6261. // Test case 6: merge add of subtract
  6262. // 2 + (x - 1) = x + 1
  6263. InstructionFoldingCase<bool>(
  6264. Header() +
  6265. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  6266. "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
  6267. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  6268. "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_1]]\n" +
  6269. "%main = OpFunction %void None %void_func\n" +
  6270. "%main_lab = OpLabel\n" +
  6271. "%var = OpVariable %_ptr_float Function\n" +
  6272. "%2 = OpLoad %float %var\n" +
  6273. "%3 = OpFSub %float %2 %float_1\n" +
  6274. "%4 = OpFAdd %float %float_2 %3\n" +
  6275. "OpReturn\n" +
  6276. "OpFunctionEnd\n",
  6277. 4, true),
  6278. // Test case 7: merge add of subtract
  6279. // 2 + (1 - x) = 3 - x
  6280. InstructionFoldingCase<bool>(
  6281. Header() +
  6282. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  6283. "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
  6284. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  6285. "; CHECK: %4 = OpFSub [[float]] [[float_3]] [[ld]]\n" +
  6286. "%main = OpFunction %void None %void_func\n" +
  6287. "%main_lab = OpLabel\n" +
  6288. "%var = OpVariable %_ptr_float Function\n" +
  6289. "%2 = OpLoad %float %var\n" +
  6290. "%3 = OpFSub %float %float_1 %2\n" +
  6291. "%4 = OpFAdd %float %float_2 %3\n" +
  6292. "OpReturn\n" +
  6293. "OpFunctionEnd\n",
  6294. 4, true),
  6295. // Test case 8: merge add of add
  6296. // (x + 1) + 2 = x + 3
  6297. InstructionFoldingCase<bool>(
  6298. Header() +
  6299. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  6300. "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
  6301. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  6302. "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_3]]\n" +
  6303. "%main = OpFunction %void None %void_func\n" +
  6304. "%main_lab = OpLabel\n" +
  6305. "%var = OpVariable %_ptr_float Function\n" +
  6306. "%2 = OpLoad %float %var\n" +
  6307. "%3 = OpFAdd %float %2 %float_1\n" +
  6308. "%4 = OpFAdd %float %3 %float_2\n" +
  6309. "OpReturn\n" +
  6310. "OpFunctionEnd\n",
  6311. 4, true),
  6312. // Test case 9: merge add of add
  6313. // (1 + x) + 2 = 3 + x
  6314. InstructionFoldingCase<bool>(
  6315. Header() +
  6316. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  6317. "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
  6318. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  6319. "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_3]]\n" +
  6320. "%main = OpFunction %void None %void_func\n" +
  6321. "%main_lab = OpLabel\n" +
  6322. "%var = OpVariable %_ptr_float Function\n" +
  6323. "%2 = OpLoad %float %var\n" +
  6324. "%3 = OpFAdd %float %float_1 %2\n" +
  6325. "%4 = OpFAdd %float %3 %float_2\n" +
  6326. "OpReturn\n" +
  6327. "OpFunctionEnd\n",
  6328. 4, true),
  6329. // Test case 10: merge add of add
  6330. // 2 + (x + 1) = x + 1
  6331. InstructionFoldingCase<bool>(
  6332. Header() +
  6333. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  6334. "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
  6335. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  6336. "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_3]]\n" +
  6337. "%main = OpFunction %void None %void_func\n" +
  6338. "%main_lab = OpLabel\n" +
  6339. "%var = OpVariable %_ptr_float Function\n" +
  6340. "%2 = OpLoad %float %var\n" +
  6341. "%3 = OpFAdd %float %2 %float_1\n" +
  6342. "%4 = OpFAdd %float %float_2 %3\n" +
  6343. "OpReturn\n" +
  6344. "OpFunctionEnd\n",
  6345. 4, true),
  6346. // Test case 11: merge add of add
  6347. // 2 + (1 + x) = 3 - x
  6348. InstructionFoldingCase<bool>(
  6349. Header() +
  6350. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  6351. "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
  6352. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  6353. "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_3]]\n" +
  6354. "%main = OpFunction %void None %void_func\n" +
  6355. "%main_lab = OpLabel\n" +
  6356. "%var = OpVariable %_ptr_float Function\n" +
  6357. "%2 = OpLoad %float %var\n" +
  6358. "%3 = OpFAdd %float %float_1 %2\n" +
  6359. "%4 = OpFAdd %float %float_2 %3\n" +
  6360. "OpReturn\n" +
  6361. "OpFunctionEnd\n",
  6362. 4, true),
  6363. // Test case 12: fold overflowing signed 32 bit iadds
  6364. // (x + int_max) + 1 = x + int_min
  6365. InstructionFoldingCase<bool>(
  6366. Header() +
  6367. "; CHECK: [[int:%\\w+]] = OpTypeInt 32\n" +
  6368. "; CHECK: [[int_min:%\\w+]] = OpConstant [[int]] -2147483648\n" +
  6369. "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
  6370. "; CHECK: %4 = OpIAdd [[int]] [[ld]] [[int_min]]\n" +
  6371. "%main = OpFunction %void None %void_func\n" +
  6372. "%main_lab = OpLabel\n" +
  6373. "%var = OpVariable %_ptr_int Function\n" +
  6374. "%2 = OpLoad %int %var\n" +
  6375. "%3 = OpIAdd %int %2 %int_max\n" +
  6376. "%4 = OpIAdd %int %3 %int_1\n" +
  6377. "OpReturn\n" +
  6378. "OpFunctionEnd\n",
  6379. 4, true),
  6380. // Test case 13: fold overflowing signed 64 bit iadds
  6381. // (x + long_max) + 1 = x + long_min
  6382. InstructionFoldingCase<bool>(
  6383. Header() +
  6384. "; CHECK: [[long:%\\w+]] = OpTypeInt 64\n" +
  6385. "; CHECK: [[long_min:%\\w+]] = OpConstant [[long]] -9223372036854775808\n" +
  6386. "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
  6387. "; CHECK: %4 = OpIAdd [[long]] [[ld]] [[long_min]]\n" +
  6388. "%main = OpFunction %void None %void_func\n" +
  6389. "%main_lab = OpLabel\n" +
  6390. "%var = OpVariable %_ptr_long Function\n" +
  6391. "%2 = OpLoad %long %var\n" +
  6392. "%3 = OpIAdd %long %2 %long_max\n" +
  6393. "%4 = OpIAdd %long %3 %long_1\n" +
  6394. "OpReturn\n" +
  6395. "OpFunctionEnd\n",
  6396. 4, true),
  6397. // Test case 14: fold overflowing 32 bit unsigned iadds
  6398. // (x + uint_max) + 2 = x + 1
  6399. InstructionFoldingCase<bool>(
  6400. Header() +
  6401. "; CHECK: [[uint:%\\w+]] = OpTypeInt 32 0\n" +
  6402. "; CHECK: [[uint_1:%\\w+]] = OpConstant [[uint]] 1\n" +
  6403. "; CHECK: [[ld:%\\w+]] = OpLoad [[uint]]\n" +
  6404. "; CHECK: %4 = OpIAdd [[uint]] [[ld]] [[uint_1]]\n" +
  6405. "%main = OpFunction %void None %void_func\n" +
  6406. "%main_lab = OpLabel\n" +
  6407. "%var = OpVariable %_ptr_uint Function\n" +
  6408. "%2 = OpLoad %uint %var\n" +
  6409. "%3 = OpIAdd %uint %2 %uint_max\n" +
  6410. "%4 = OpIAdd %uint %3 %uint_2\n" +
  6411. "OpReturn\n" +
  6412. "OpFunctionEnd\n",
  6413. 4, true),
  6414. // Test case 15: fold overflowing 64 bit unsigned iadds
  6415. // (x + ulong_max) + 2 = x + 1
  6416. InstructionFoldingCase<bool>(
  6417. Header() +
  6418. "; CHECK: [[ulong:%\\w+]] = OpTypeInt 64 0\n" +
  6419. "; CHECK: [[ulong_1:%\\w+]] = OpConstant [[ulong]] 1\n" +
  6420. "; CHECK: [[ld:%\\w+]] = OpLoad [[ulong]]\n" +
  6421. "; CHECK: %4 = OpIAdd [[ulong]] [[ld]] [[ulong_1]]\n" +
  6422. "%main = OpFunction %void None %void_func\n" +
  6423. "%main_lab = OpLabel\n" +
  6424. "%var = OpVariable %_ptr_ulong Function\n" +
  6425. "%2 = OpLoad %ulong %var\n" +
  6426. "%3 = OpIAdd %ulong %2 %ulong_max\n" +
  6427. "%4 = OpIAdd %ulong %3 %ulong_2\n" +
  6428. "OpReturn\n" +
  6429. "OpFunctionEnd\n",
  6430. 4, true),
  6431. // Test case 16: fold underflowing signed 32 bit iadds
  6432. // (x + int_min) + (-1) = x + int_max
  6433. InstructionFoldingCase<bool>(
  6434. Header() +
  6435. "; CHECK: [[int:%\\w+]] = OpTypeInt 32\n" +
  6436. "; CHECK: [[int_max:%\\w+]] = OpConstant [[int]] 2147483647\n" +
  6437. "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
  6438. "; CHECK: %4 = OpIAdd [[int]] [[ld]] [[int_max]]\n" +
  6439. "%main = OpFunction %void None %void_func\n" +
  6440. "%main_lab = OpLabel\n" +
  6441. "%var = OpVariable %_ptr_int Function\n" +
  6442. "%2 = OpLoad %int %var\n" +
  6443. "%3 = OpIAdd %int %2 %int_min\n" +
  6444. "%4 = OpIAdd %int %3 %int_n1\n" +
  6445. "OpReturn\n" +
  6446. "OpFunctionEnd\n",
  6447. 4, true),
  6448. // Test case 17: fold underflowing signed 64 bit iadds
  6449. // (x + long_min) + (-1) = x + long_max
  6450. InstructionFoldingCase<bool>(
  6451. Header() +
  6452. "; CHECK: [[long:%\\w+]] = OpTypeInt 64\n" +
  6453. "; CHECK: [[long_max:%\\w+]] = OpConstant [[long]] 9223372036854775807\n" +
  6454. "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
  6455. "; CHECK: %4 = OpIAdd [[long]] [[ld]] [[long_max]]\n" +
  6456. "%main = OpFunction %void None %void_func\n" +
  6457. "%main_lab = OpLabel\n" +
  6458. "%var = OpVariable %_ptr_long Function\n" +
  6459. "%2 = OpLoad %long %var\n" +
  6460. "%3 = OpIAdd %long %2 %long_min\n" +
  6461. "%4 = OpIAdd %long %3 %long_n1\n" +
  6462. "OpReturn\n" +
  6463. "OpFunctionEnd\n",
  6464. 4, true)
  6465. ));
  6466. INSTANTIATE_TEST_SUITE_P(MergeGenericAddSub, MatchingInstructionFoldingTest,
  6467. ::testing::Values(
  6468. // Test case 0: merge of add of sub
  6469. // (a - b) + b => a
  6470. InstructionFoldingCase<bool>(
  6471. Header() +
  6472. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  6473. "; CHECK: %6 = OpCopyObject [[float]] %3\n" +
  6474. "%main = OpFunction %void None %void_func\n" +
  6475. "%main_lab = OpLabel\n" +
  6476. "%var0 = OpVariable %_ptr_float Function\n" +
  6477. "%var1 = OpVariable %_ptr_float Function\n" +
  6478. "%3 = OpLoad %float %var0\n" +
  6479. "%4 = OpLoad %float %var1\n" +
  6480. "%5 = OpFSub %float %3 %4\n" +
  6481. "%6 = OpFAdd %float %5 %4\n" +
  6482. "OpReturn\n" +
  6483. "OpFunctionEnd\n",
  6484. 6, true),
  6485. // Test case 1: merge of add of sub
  6486. // b + (a - b) => a
  6487. InstructionFoldingCase<bool>(
  6488. Header() +
  6489. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  6490. "; CHECK: %6 = OpCopyObject [[float]] %3\n" +
  6491. "%main = OpFunction %void None %void_func\n" +
  6492. "%main_lab = OpLabel\n" +
  6493. "%var0 = OpVariable %_ptr_float Function\n" +
  6494. "%var1 = OpVariable %_ptr_float Function\n" +
  6495. "%3 = OpLoad %float %var0\n" +
  6496. "%4 = OpLoad %float %var1\n" +
  6497. "%5 = OpFSub %float %3 %4\n" +
  6498. "%6 = OpFAdd %float %4 %5\n" +
  6499. "OpReturn\n" +
  6500. "OpFunctionEnd\n",
  6501. 6, true)
  6502. ));
  6503. INSTANTIATE_TEST_SUITE_P(FactorAddMul, MatchingInstructionFoldingTest,
  6504. ::testing::Values(
  6505. // Test case 0: factor of add of muls
  6506. // (a * b) + (a * c) => a * (b + c)
  6507. InstructionFoldingCase<bool>(
  6508. Header() +
  6509. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  6510. "; CHECK: [[newadd:%\\w+]] = OpFAdd [[float]] %4 %5\n" +
  6511. "; CHECK: %9 = OpFMul [[float]] %6 [[newadd]]\n" +
  6512. "%main = OpFunction %void None %void_func\n" +
  6513. "%main_lab = OpLabel\n" +
  6514. "%var0 = OpVariable %_ptr_float Function\n" +
  6515. "%var1 = OpVariable %_ptr_float Function\n" +
  6516. "%var2 = OpVariable %_ptr_float Function\n" +
  6517. "%4 = OpLoad %float %var0\n" +
  6518. "%5 = OpLoad %float %var1\n" +
  6519. "%6 = OpLoad %float %var2\n" +
  6520. "%7 = OpFMul %float %6 %4\n" +
  6521. "%8 = OpFMul %float %6 %5\n" +
  6522. "%9 = OpFAdd %float %7 %8\n" +
  6523. "OpReturn\n" +
  6524. "OpFunctionEnd\n",
  6525. 9, true),
  6526. // Test case 1: factor of add of muls
  6527. // (b * a) + (a * c) => a * (b + c)
  6528. InstructionFoldingCase<bool>(
  6529. Header() +
  6530. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  6531. "; CHECK: [[newadd:%\\w+]] = OpFAdd [[float]] %4 %5\n" +
  6532. "; CHECK: %9 = OpFMul [[float]] %6 [[newadd]]\n" +
  6533. "%main = OpFunction %void None %void_func\n" +
  6534. "%main_lab = OpLabel\n" +
  6535. "%var0 = OpVariable %_ptr_float Function\n" +
  6536. "%var1 = OpVariable %_ptr_float Function\n" +
  6537. "%var2 = OpVariable %_ptr_float Function\n" +
  6538. "%4 = OpLoad %float %var0\n" +
  6539. "%5 = OpLoad %float %var1\n" +
  6540. "%6 = OpLoad %float %var2\n" +
  6541. "%7 = OpFMul %float %4 %6\n" +
  6542. "%8 = OpFMul %float %6 %5\n" +
  6543. "%9 = OpFAdd %float %7 %8\n" +
  6544. "OpReturn\n" +
  6545. "OpFunctionEnd\n",
  6546. 9, true),
  6547. // Test case 2: factor of add of muls
  6548. // (a * b) + (c * a) => a * (b + c)
  6549. InstructionFoldingCase<bool>(
  6550. Header() +
  6551. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  6552. "; CHECK: [[newadd:%\\w+]] = OpFAdd [[float]] %4 %5\n" +
  6553. "; CHECK: %9 = OpFMul [[float]] %6 [[newadd]]\n" +
  6554. "%main = OpFunction %void None %void_func\n" +
  6555. "%main_lab = OpLabel\n" +
  6556. "%var0 = OpVariable %_ptr_float Function\n" +
  6557. "%var1 = OpVariable %_ptr_float Function\n" +
  6558. "%var2 = OpVariable %_ptr_float Function\n" +
  6559. "%4 = OpLoad %float %var0\n" +
  6560. "%5 = OpLoad %float %var1\n" +
  6561. "%6 = OpLoad %float %var2\n" +
  6562. "%7 = OpFMul %float %6 %4\n" +
  6563. "%8 = OpFMul %float %5 %6\n" +
  6564. "%9 = OpFAdd %float %7 %8\n" +
  6565. "OpReturn\n" +
  6566. "OpFunctionEnd\n",
  6567. 9, true),
  6568. // Test case 3: factor of add of muls
  6569. // (b * a) + (c * a) => a * (b + c)
  6570. InstructionFoldingCase<bool>(
  6571. Header() +
  6572. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  6573. "; CHECK: [[newadd:%\\w+]] = OpFAdd [[float]] %4 %5\n" +
  6574. "; CHECK: %9 = OpFMul [[float]] %6 [[newadd]]\n" +
  6575. "%main = OpFunction %void None %void_func\n" +
  6576. "%main_lab = OpLabel\n" +
  6577. "%var0 = OpVariable %_ptr_float Function\n" +
  6578. "%var1 = OpVariable %_ptr_float Function\n" +
  6579. "%var2 = OpVariable %_ptr_float Function\n" +
  6580. "%4 = OpLoad %float %var0\n" +
  6581. "%5 = OpLoad %float %var1\n" +
  6582. "%6 = OpLoad %float %var2\n" +
  6583. "%7 = OpFMul %float %4 %6\n" +
  6584. "%8 = OpFMul %float %5 %6\n" +
  6585. "%9 = OpFAdd %float %7 %8\n" +
  6586. "OpReturn\n" +
  6587. "OpFunctionEnd\n",
  6588. 9, true)
  6589. ));
  6590. INSTANTIATE_TEST_SUITE_P(MergeSubTest, MatchingInstructionFoldingTest,
  6591. ::testing::Values(
  6592. // Test case 0: merge sub of negate
  6593. // (-x) - 2 = -2 - x
  6594. InstructionFoldingCase<bool>(
  6595. Header() +
  6596. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  6597. "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2{{[[:space:]]}}\n" +
  6598. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  6599. "; CHECK: %4 = OpFSub [[float]] [[float_n2]] [[ld]]\n" +
  6600. "%main = OpFunction %void None %void_func\n" +
  6601. "%main_lab = OpLabel\n" +
  6602. "%var = OpVariable %_ptr_float Function\n" +
  6603. "%2 = OpLoad %float %var\n" +
  6604. "%3 = OpFNegate %float %2\n" +
  6605. "%4 = OpFSub %float %3 %float_2\n" +
  6606. "OpReturn\n" +
  6607. "OpFunctionEnd\n",
  6608. 4, true),
  6609. // Test case 1: merge sub of negate
  6610. // 2 - (-x) = x + 2
  6611. InstructionFoldingCase<bool>(
  6612. Header() +
  6613. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  6614. "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
  6615. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  6616. "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_2]]\n" +
  6617. "%main = OpFunction %void None %void_func\n" +
  6618. "%main_lab = OpLabel\n" +
  6619. "%var = OpVariable %_ptr_float Function\n" +
  6620. "%2 = OpLoad %float %var\n" +
  6621. "%3 = OpFNegate %float %2\n" +
  6622. "%4 = OpFSub %float %float_2 %3\n" +
  6623. "OpReturn\n" +
  6624. "OpFunctionEnd\n",
  6625. 4, true),
  6626. // Test case 2: merge sub of negate
  6627. // (-x) - 2 = -2 - x
  6628. InstructionFoldingCase<bool>(
  6629. Header() +
  6630. "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
  6631. "; CHECK: [[long_n2:%\\w+]] = OpConstant [[long]] -2{{[[:space:]]}}\n" +
  6632. "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
  6633. "; CHECK: %4 = OpISub [[long]] [[long_n2]] [[ld]]\n" +
  6634. "%main = OpFunction %void None %void_func\n" +
  6635. "%main_lab = OpLabel\n" +
  6636. "%var = OpVariable %_ptr_long Function\n" +
  6637. "%2 = OpLoad %long %var\n" +
  6638. "%3 = OpSNegate %long %2\n" +
  6639. "%4 = OpISub %long %3 %long_2\n" +
  6640. "OpReturn\n" +
  6641. "OpFunctionEnd\n",
  6642. 4, true),
  6643. // Test case 3: merge sub of negate
  6644. // 2 - (-x) = x + 2
  6645. InstructionFoldingCase<bool>(
  6646. Header() +
  6647. "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
  6648. "; CHECK: [[long_2:%\\w+]] = OpConstant [[long]] 2\n" +
  6649. "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
  6650. "; CHECK: %4 = OpIAdd [[long]] [[ld]] [[long_2]]\n" +
  6651. "%main = OpFunction %void None %void_func\n" +
  6652. "%main_lab = OpLabel\n" +
  6653. "%var = OpVariable %_ptr_long Function\n" +
  6654. "%2 = OpLoad %long %var\n" +
  6655. "%3 = OpSNegate %long %2\n" +
  6656. "%4 = OpISub %long %long_2 %3\n" +
  6657. "OpReturn\n" +
  6658. "OpFunctionEnd\n",
  6659. 4, true),
  6660. // Test case 4: merge add of subtract
  6661. // (x + 2) - 1 = x + 1
  6662. InstructionFoldingCase<bool>(
  6663. Header() +
  6664. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  6665. "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
  6666. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  6667. "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_1]]\n" +
  6668. "%main = OpFunction %void None %void_func\n" +
  6669. "%main_lab = OpLabel\n" +
  6670. "%var = OpVariable %_ptr_float Function\n" +
  6671. "%2 = OpLoad %float %var\n" +
  6672. "%3 = OpFAdd %float %2 %float_2\n" +
  6673. "%4 = OpFSub %float %3 %float_1\n" +
  6674. "OpReturn\n" +
  6675. "OpFunctionEnd\n",
  6676. 4, true),
  6677. // Test case 5: merge add of subtract
  6678. // (2 + x) - 1 = x + 1
  6679. InstructionFoldingCase<bool>(
  6680. Header() +
  6681. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  6682. "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
  6683. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  6684. "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_1]]\n" +
  6685. "%main = OpFunction %void None %void_func\n" +
  6686. "%main_lab = OpLabel\n" +
  6687. "%var = OpVariable %_ptr_float Function\n" +
  6688. "%2 = OpLoad %float %var\n" +
  6689. "%3 = OpFAdd %float %float_2 %2\n" +
  6690. "%4 = OpFSub %float %3 %float_1\n" +
  6691. "OpReturn\n" +
  6692. "OpFunctionEnd\n",
  6693. 4, true),
  6694. // Test case 6: merge add of subtract
  6695. // 2 - (x + 1) = 1 - x
  6696. InstructionFoldingCase<bool>(
  6697. Header() +
  6698. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  6699. "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
  6700. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  6701. "; CHECK: %4 = OpFSub [[float]] [[float_1]] [[ld]]\n" +
  6702. "%main = OpFunction %void None %void_func\n" +
  6703. "%main_lab = OpLabel\n" +
  6704. "%var = OpVariable %_ptr_float Function\n" +
  6705. "%2 = OpLoad %float %var\n" +
  6706. "%3 = OpFAdd %float %2 %float_1\n" +
  6707. "%4 = OpFSub %float %float_2 %3\n" +
  6708. "OpReturn\n" +
  6709. "OpFunctionEnd\n",
  6710. 4, true),
  6711. // Test case 7: merge add of subtract
  6712. // 2 - (1 + x) = 1 - x
  6713. InstructionFoldingCase<bool>(
  6714. Header() +
  6715. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  6716. "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
  6717. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  6718. "; CHECK: %4 = OpFSub [[float]] [[float_1]] [[ld]]\n" +
  6719. "%main = OpFunction %void None %void_func\n" +
  6720. "%main_lab = OpLabel\n" +
  6721. "%var = OpVariable %_ptr_float Function\n" +
  6722. "%2 = OpLoad %float %var\n" +
  6723. "%3 = OpFAdd %float %float_1 %2\n" +
  6724. "%4 = OpFSub %float %float_2 %3\n" +
  6725. "OpReturn\n" +
  6726. "OpFunctionEnd\n",
  6727. 4, true),
  6728. // Test case 8: merge subtract of subtract
  6729. // (x - 2) - 1 = x - 3
  6730. InstructionFoldingCase<bool>(
  6731. Header() +
  6732. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  6733. "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
  6734. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  6735. "; CHECK: %4 = OpFSub [[float]] [[ld]] [[float_3]]\n" +
  6736. "%main = OpFunction %void None %void_func\n" +
  6737. "%main_lab = OpLabel\n" +
  6738. "%var = OpVariable %_ptr_float Function\n" +
  6739. "%2 = OpLoad %float %var\n" +
  6740. "%3 = OpFSub %float %2 %float_2\n" +
  6741. "%4 = OpFSub %float %3 %float_1\n" +
  6742. "OpReturn\n" +
  6743. "OpFunctionEnd\n",
  6744. 4, true),
  6745. // Test case 9: merge subtract of subtract
  6746. // (2 - x) - 1 = 1 - x
  6747. InstructionFoldingCase<bool>(
  6748. Header() +
  6749. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  6750. "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
  6751. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  6752. "; CHECK: %4 = OpFSub [[float]] [[float_1]] [[ld]]\n" +
  6753. "%main = OpFunction %void None %void_func\n" +
  6754. "%main_lab = OpLabel\n" +
  6755. "%var = OpVariable %_ptr_float Function\n" +
  6756. "%2 = OpLoad %float %var\n" +
  6757. "%3 = OpFSub %float %float_2 %2\n" +
  6758. "%4 = OpFSub %float %3 %float_1\n" +
  6759. "OpReturn\n" +
  6760. "OpFunctionEnd\n",
  6761. 4, true),
  6762. // Test case 10: merge subtract of subtract
  6763. // 2 - (x - 1) = 3 - x
  6764. InstructionFoldingCase<bool>(
  6765. Header() +
  6766. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  6767. "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
  6768. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  6769. "; CHECK: %4 = OpFSub [[float]] [[float_3]] [[ld]]\n" +
  6770. "%main = OpFunction %void None %void_func\n" +
  6771. "%main_lab = OpLabel\n" +
  6772. "%var = OpVariable %_ptr_float Function\n" +
  6773. "%2 = OpLoad %float %var\n" +
  6774. "%3 = OpFSub %float %2 %float_1\n" +
  6775. "%4 = OpFSub %float %float_2 %3\n" +
  6776. "OpReturn\n" +
  6777. "OpFunctionEnd\n",
  6778. 4, true),
  6779. // Test case 11: merge subtract of subtract
  6780. // 1 - (2 - x) = x + (-1)
  6781. InstructionFoldingCase<bool>(
  6782. Header() +
  6783. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  6784. "; CHECK: [[float_n1:%\\w+]] = OpConstant [[float]] -1\n" +
  6785. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  6786. "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_n1]]\n" +
  6787. "%main = OpFunction %void None %void_func\n" +
  6788. "%main_lab = OpLabel\n" +
  6789. "%var = OpVariable %_ptr_float Function\n" +
  6790. "%2 = OpLoad %float %var\n" +
  6791. "%3 = OpFSub %float %float_2 %2\n" +
  6792. "%4 = OpFSub %float %float_1 %3\n" +
  6793. "OpReturn\n" +
  6794. "OpFunctionEnd\n",
  6795. 4, true),
  6796. // Test case 12: merge subtract of subtract
  6797. // 2 - (1 - x) = x + 1
  6798. InstructionFoldingCase<bool>(
  6799. Header() +
  6800. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  6801. "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
  6802. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  6803. "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_1]]\n" +
  6804. "%main = OpFunction %void None %void_func\n" +
  6805. "%main_lab = OpLabel\n" +
  6806. "%var = OpVariable %_ptr_float Function\n" +
  6807. "%2 = OpLoad %float %var\n" +
  6808. "%3 = OpFSub %float %float_1 %2\n" +
  6809. "%4 = OpFSub %float %float_2 %3\n" +
  6810. "OpReturn\n" +
  6811. "OpFunctionEnd\n",
  6812. 4, true),
  6813. // Test case 13: merge subtract of subtract with mixed types.
  6814. // 2 - (1 - x) = x + 1
  6815. InstructionFoldingCase<bool>(
  6816. Header() +
  6817. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  6818. "; CHECK: [[int_1:%\\w+]] = OpConstant [[int]] 1\n" +
  6819. "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
  6820. "; CHECK: %4 = OpIAdd [[int]] [[ld]] [[int_1]]\n" +
  6821. "%main = OpFunction %void None %void_func\n" +
  6822. "%main_lab = OpLabel\n" +
  6823. "%var = OpVariable %_ptr_int Function\n" +
  6824. "%2 = OpLoad %int %var\n" +
  6825. "%3 = OpISub %int %uint_1 %2\n" +
  6826. "%4 = OpISub %int %int_2 %3\n" +
  6827. "OpReturn\n" +
  6828. "OpFunctionEnd\n",
  6829. 4, true),
  6830. // Test case 14: fold overflowing signed 32 bit isubs
  6831. // (x - int_max) - 1 = x - int_min
  6832. InstructionFoldingCase<bool>(
  6833. Header() +
  6834. "; CHECK: [[int:%\\w+]] = OpTypeInt 32\n" +
  6835. "; CHECK: [[int_min:%\\w+]] = OpConstant [[int]] -2147483648\n" +
  6836. "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
  6837. "; CHECK: %4 = OpISub [[int]] [[ld]] [[int_min]]\n" +
  6838. "%main = OpFunction %void None %void_func\n" +
  6839. "%main_lab = OpLabel\n" +
  6840. "%var = OpVariable %_ptr_int Function\n" +
  6841. "%2 = OpLoad %int %var\n" +
  6842. "%3 = OpISub %int %2 %int_max\n" +
  6843. "%4 = OpISub %int %3 %int_1\n" +
  6844. "OpReturn\n" +
  6845. "OpFunctionEnd\n",
  6846. 4, true),
  6847. // Test case 15: fold overflowing signed 64 bit isubs
  6848. // (x - long_max) - 1 = x - long_min
  6849. InstructionFoldingCase<bool>(
  6850. Header() +
  6851. "; CHECK: [[long:%\\w+]] = OpTypeInt 64\n" +
  6852. "; CHECK: [[long_min:%\\w+]] = OpConstant [[long]] -9223372036854775808\n" +
  6853. "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
  6854. "; CHECK: %4 = OpISub [[long]] [[ld]] [[long_min]]\n" +
  6855. "%main = OpFunction %void None %void_func\n" +
  6856. "%main_lab = OpLabel\n" +
  6857. "%var = OpVariable %_ptr_long Function\n" +
  6858. "%2 = OpLoad %long %var\n" +
  6859. "%3 = OpISub %long %2 %long_max\n" +
  6860. "%4 = OpISub %long %3 %long_1\n" +
  6861. "OpReturn\n" +
  6862. "OpFunctionEnd\n",
  6863. 4, true)
  6864. ));
  6865. INSTANTIATE_TEST_SUITE_P(SelectFoldingTest, MatchingInstructionFoldingTest,
  6866. ::testing::Values(
  6867. // Test case 0: Fold select with the same values for both sides
  6868. InstructionFoldingCase<bool>(
  6869. Header() +
  6870. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  6871. "; CHECK: [[int0:%\\w+]] = OpConstant [[int]] 0\n" +
  6872. "; CHECK: %2 = OpCopyObject [[int]] [[int0]]\n" +
  6873. "%main = OpFunction %void None %void_func\n" +
  6874. "%main_lab = OpLabel\n" +
  6875. "%n = OpVariable %_ptr_bool Function\n" +
  6876. "%load = OpLoad %bool %n\n" +
  6877. "%2 = OpSelect %int %load %100 %100\n" +
  6878. "OpReturn\n" +
  6879. "OpFunctionEnd",
  6880. 2, true),
  6881. // Test case 1: Fold select true to left side
  6882. InstructionFoldingCase<bool>(
  6883. Header() +
  6884. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  6885. "; CHECK: [[int0:%\\w+]] = OpConstant [[int]] 0\n" +
  6886. "; CHECK: %2 = OpCopyObject [[int]] [[int0]]\n" +
  6887. "%main = OpFunction %void None %void_func\n" +
  6888. "%main_lab = OpLabel\n" +
  6889. "%n = OpVariable %_ptr_int Function\n" +
  6890. "%load = OpLoad %bool %n\n" +
  6891. "%2 = OpSelect %int %true %100 %n\n" +
  6892. "OpReturn\n" +
  6893. "OpFunctionEnd",
  6894. 2, true),
  6895. // Test case 2: Fold select false to right side
  6896. InstructionFoldingCase<bool>(
  6897. Header() +
  6898. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  6899. "; CHECK: [[int0:%\\w+]] = OpConstant [[int]] 0\n" +
  6900. "; CHECK: %2 = OpCopyObject [[int]] [[int0]]\n" +
  6901. "%main = OpFunction %void None %void_func\n" +
  6902. "%main_lab = OpLabel\n" +
  6903. "%n = OpVariable %_ptr_int Function\n" +
  6904. "%load = OpLoad %bool %n\n" +
  6905. "%2 = OpSelect %int %false %n %100\n" +
  6906. "OpReturn\n" +
  6907. "OpFunctionEnd",
  6908. 2, true),
  6909. // Test case 3: Fold select null to right side
  6910. InstructionFoldingCase<bool>(
  6911. Header() +
  6912. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  6913. "; CHECK: [[int0:%\\w+]] = OpConstant [[int]] 0\n" +
  6914. "; CHECK: %2 = OpCopyObject [[int]] [[int0]]\n" +
  6915. "%main = OpFunction %void None %void_func\n" +
  6916. "%main_lab = OpLabel\n" +
  6917. "%n = OpVariable %_ptr_int Function\n" +
  6918. "%load = OpLoad %int %n\n" +
  6919. "%2 = OpSelect %int %bool_null %load %100\n" +
  6920. "OpReturn\n" +
  6921. "OpFunctionEnd",
  6922. 2, true),
  6923. // Test case 4: vector null
  6924. InstructionFoldingCase<bool>(
  6925. Header() +
  6926. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  6927. "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2\n" +
  6928. "; CHECK: [[int2:%\\w+]] = OpConstant [[int]] 2\n" +
  6929. "; CHECK: [[v2int2_2:%\\w+]] = OpConstantComposite [[v2int]] [[int2]] [[int2]]\n" +
  6930. "; CHECK: %2 = OpCopyObject [[v2int]] [[v2int2_2]]\n" +
  6931. "%main = OpFunction %void None %void_func\n" +
  6932. "%main_lab = OpLabel\n" +
  6933. "%n = OpVariable %_ptr_v2int Function\n" +
  6934. "%load = OpLoad %v2int %n\n" +
  6935. "%2 = OpSelect %v2int %v2bool_null %load %v2int_2_2\n" +
  6936. "OpReturn\n" +
  6937. "OpFunctionEnd",
  6938. 2, true),
  6939. // Test case 5: vector select
  6940. InstructionFoldingCase<bool>(
  6941. Header() +
  6942. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  6943. "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2\n" +
  6944. "; CHECK: %4 = OpVectorShuffle [[v2int]] %2 %3 0 3\n" +
  6945. "%main = OpFunction %void None %void_func\n" +
  6946. "%main_lab = OpLabel\n" +
  6947. "%m = OpVariable %_ptr_v2int Function\n" +
  6948. "%n = OpVariable %_ptr_v2int Function\n" +
  6949. "%2 = OpLoad %v2int %n\n" +
  6950. "%3 = OpLoad %v2int %n\n" +
  6951. "%4 = OpSelect %v2int %v2bool_true_false %2 %3\n" +
  6952. "OpReturn\n" +
  6953. "OpFunctionEnd",
  6954. 4, true),
  6955. // Test case 6: vector select
  6956. InstructionFoldingCase<bool>(
  6957. Header() +
  6958. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  6959. "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2\n" +
  6960. "; CHECK: %4 = OpVectorShuffle [[v2int]] %2 %3 2 1\n" +
  6961. "%main = OpFunction %void None %void_func\n" +
  6962. "%main_lab = OpLabel\n" +
  6963. "%m = OpVariable %_ptr_v2int Function\n" +
  6964. "%n = OpVariable %_ptr_v2int Function\n" +
  6965. "%2 = OpLoad %v2int %n\n" +
  6966. "%3 = OpLoad %v2int %n\n" +
  6967. "%4 = OpSelect %v2int %v2bool_false_true %2 %3\n" +
  6968. "OpReturn\n" +
  6969. "OpFunctionEnd",
  6970. 4, true)
  6971. ));
  6972. INSTANTIATE_TEST_SUITE_P(CompositeExtractOrInsertMatchingTest, MatchingInstructionFoldingTest,
  6973. ::testing::Values(
  6974. // Test case 0: Extracting from result of consecutive shuffles of differing
  6975. // size.
  6976. InstructionFoldingCase<bool>(
  6977. Header() +
  6978. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  6979. "; CHECK: %5 = OpCompositeExtract [[int]] %2 2\n" +
  6980. "%main = OpFunction %void None %void_func\n" +
  6981. "%main_lab = OpLabel\n" +
  6982. "%n = OpVariable %_ptr_v4int Function\n" +
  6983. "%2 = OpLoad %v4int %n\n" +
  6984. "%3 = OpVectorShuffle %v2int %2 %2 2 3\n" +
  6985. "%4 = OpVectorShuffle %v4int %2 %3 0 4 2 5\n" +
  6986. "%5 = OpCompositeExtract %int %4 1\n" +
  6987. "OpReturn\n" +
  6988. "OpFunctionEnd",
  6989. 5, true),
  6990. // Test case 1: Extracting from result of vector shuffle of differing
  6991. // input and result sizes.
  6992. InstructionFoldingCase<bool>(
  6993. Header() +
  6994. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  6995. "; CHECK: %4 = OpCompositeExtract [[int]] %2 2\n" +
  6996. "%main = OpFunction %void None %void_func\n" +
  6997. "%main_lab = OpLabel\n" +
  6998. "%n = OpVariable %_ptr_v4int Function\n" +
  6999. "%2 = OpLoad %v4int %n\n" +
  7000. "%3 = OpVectorShuffle %v2int %2 %2 2 3\n" +
  7001. "%4 = OpCompositeExtract %int %3 0\n" +
  7002. "OpReturn\n" +
  7003. "OpFunctionEnd",
  7004. 4, true),
  7005. // Test case 2: Extracting from result of vector shuffle of differing
  7006. // input and result sizes.
  7007. InstructionFoldingCase<bool>(
  7008. Header() +
  7009. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  7010. "; CHECK: %4 = OpCompositeExtract [[int]] %2 3\n" +
  7011. "%main = OpFunction %void None %void_func\n" +
  7012. "%main_lab = OpLabel\n" +
  7013. "%n = OpVariable %_ptr_v4int Function\n" +
  7014. "%2 = OpLoad %v4int %n\n" +
  7015. "%3 = OpVectorShuffle %v2int %2 %2 2 3\n" +
  7016. "%4 = OpCompositeExtract %int %3 1\n" +
  7017. "OpReturn\n" +
  7018. "OpFunctionEnd",
  7019. 4, true),
  7020. // Test case 3: Using fmix feeding extract with a 1 in the a position.
  7021. InstructionFoldingCase<bool>(
  7022. Header() +
  7023. "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
  7024. "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 4\n" +
  7025. "; CHECK: [[ptr_v4double:%\\w+]] = OpTypePointer Function [[v4double]]\n" +
  7026. "; CHECK: [[m:%\\w+]] = OpVariable [[ptr_v4double]] Function\n" +
  7027. "; CHECK: [[n:%\\w+]] = OpVariable [[ptr_v4double]] Function\n" +
  7028. "; CHECK: [[ld:%\\w+]] = OpLoad [[v4double]] [[n]]\n" +
  7029. "; CHECK: %5 = OpCompositeExtract [[double]] [[ld]] 1\n" +
  7030. "%main = OpFunction %void None %void_func\n" +
  7031. "%main_lab = OpLabel\n" +
  7032. "%m = OpVariable %_ptr_v4double Function\n" +
  7033. "%n = OpVariable %_ptr_v4double Function\n" +
  7034. "%2 = OpLoad %v4double %m\n" +
  7035. "%3 = OpLoad %v4double %n\n" +
  7036. "%4 = OpExtInst %v4double %1 FMix %2 %3 %v4double_0_1_0_0\n" +
  7037. "%5 = OpCompositeExtract %double %4 1\n" +
  7038. "OpReturn\n" +
  7039. "OpFunctionEnd",
  7040. 5, true),
  7041. // Test case 4: Using fmix feeding extract with a 0 in the a position.
  7042. InstructionFoldingCase<bool>(
  7043. Header() +
  7044. "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
  7045. "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 4\n" +
  7046. "; CHECK: [[ptr_v4double:%\\w+]] = OpTypePointer Function [[v4double]]\n" +
  7047. "; CHECK: [[m:%\\w+]] = OpVariable [[ptr_v4double]] Function\n" +
  7048. "; CHECK: [[n:%\\w+]] = OpVariable [[ptr_v4double]] Function\n" +
  7049. "; CHECK: [[ld:%\\w+]] = OpLoad [[v4double]] [[m]]\n" +
  7050. "; CHECK: %5 = OpCompositeExtract [[double]] [[ld]] 2\n" +
  7051. "%main = OpFunction %void None %void_func\n" +
  7052. "%main_lab = OpLabel\n" +
  7053. "%m = OpVariable %_ptr_v4double Function\n" +
  7054. "%n = OpVariable %_ptr_v4double Function\n" +
  7055. "%2 = OpLoad %v4double %m\n" +
  7056. "%3 = OpLoad %v4double %n\n" +
  7057. "%4 = OpExtInst %v4double %1 FMix %2 %3 %v4double_0_1_0_0\n" +
  7058. "%5 = OpCompositeExtract %double %4 2\n" +
  7059. "OpReturn\n" +
  7060. "OpFunctionEnd",
  7061. 5, true),
  7062. // Test case 5: Using fmix feeding extract with a null for the alpha
  7063. InstructionFoldingCase<bool>(
  7064. Header() +
  7065. "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
  7066. "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 4\n" +
  7067. "; CHECK: [[ptr_v4double:%\\w+]] = OpTypePointer Function [[v4double]]\n" +
  7068. "; CHECK: [[m:%\\w+]] = OpVariable [[ptr_v4double]] Function\n" +
  7069. "; CHECK: [[n:%\\w+]] = OpVariable [[ptr_v4double]] Function\n" +
  7070. "; CHECK: [[ld:%\\w+]] = OpLoad [[v4double]] [[m]]\n" +
  7071. "; CHECK: %5 = OpCompositeExtract [[double]] [[ld]] 0\n" +
  7072. "%main = OpFunction %void None %void_func\n" +
  7073. "%main_lab = OpLabel\n" +
  7074. "%m = OpVariable %_ptr_v4double Function\n" +
  7075. "%n = OpVariable %_ptr_v4double Function\n" +
  7076. "%2 = OpLoad %v4double %m\n" +
  7077. "%3 = OpLoad %v4double %n\n" +
  7078. "%4 = OpExtInst %v4double %1 FMix %2 %3 %v4double_null\n" +
  7079. "%5 = OpCompositeExtract %double %4 0\n" +
  7080. "OpReturn\n" +
  7081. "OpFunctionEnd",
  7082. 5, true),
  7083. // Test case 6: Don't fold: Using fmix feeding extract with 0.5 in the a
  7084. // position.
  7085. InstructionFoldingCase<bool>(
  7086. Header() +
  7087. "%main = OpFunction %void None %void_func\n" +
  7088. "%main_lab = OpLabel\n" +
  7089. "%m = OpVariable %_ptr_v4double Function\n" +
  7090. "%n = OpVariable %_ptr_v4double Function\n" +
  7091. "%2 = OpLoad %v4double %m\n" +
  7092. "%3 = OpLoad %v4double %n\n" +
  7093. "%4 = OpExtInst %v4double %1 FMix %2 %3 %v4double_1_1_1_0p5\n" +
  7094. "%5 = OpCompositeExtract %double %4 3\n" +
  7095. "OpReturn\n" +
  7096. "OpFunctionEnd",
  7097. 5, false),
  7098. // Test case 7: Extracting the undefined literal value from a vector
  7099. // shuffle.
  7100. InstructionFoldingCase<bool>(
  7101. Header() +
  7102. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  7103. "; CHECK: %4 = OpUndef [[int]]\n" +
  7104. "%main = OpFunction %void None %void_func\n" +
  7105. "%main_lab = OpLabel\n" +
  7106. "%n = OpVariable %_ptr_v4int Function\n" +
  7107. "%2 = OpLoad %v4int %n\n" +
  7108. "%3 = OpVectorShuffle %v2int %2 %2 2 4294967295\n" +
  7109. "%4 = OpCompositeExtract %int %3 1\n" +
  7110. "OpReturn\n" +
  7111. "OpFunctionEnd",
  7112. 4, true),
  7113. // Test case 8: Inserting every element of a vector turns into a composite construct.
  7114. InstructionFoldingCase<bool>(
  7115. Header() +
  7116. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  7117. "; CHECK-DAG: [[v4:%\\w+]] = OpTypeVector [[int]] 4\n" +
  7118. "; CHECK-DAG: [[int1:%\\w+]] = OpConstant [[int]] 1\n" +
  7119. "; CHECK-DAG: [[int2:%\\w+]] = OpConstant [[int]] 2\n" +
  7120. "; CHECK-DAG: [[int3:%\\w+]] = OpConstant [[int]] 3\n" +
  7121. "; CHECK: [[construct:%\\w+]] = OpCompositeConstruct [[v4]] %100 [[int1]] [[int2]] [[int3]]\n" +
  7122. "; CHECK: %5 = OpCopyObject [[v4]] [[construct]]\n" +
  7123. "%main = OpFunction %void None %void_func\n" +
  7124. "%main_lab = OpLabel\n" +
  7125. "%2 = OpCompositeInsert %v4int %100 %v4int_undef 0\n" +
  7126. "%3 = OpCompositeInsert %v4int %int_1 %2 1\n" +
  7127. "%4 = OpCompositeInsert %v4int %int_2 %3 2\n" +
  7128. "%5 = OpCompositeInsert %v4int %int_3 %4 3\n" +
  7129. "OpReturn\n" +
  7130. "OpFunctionEnd",
  7131. 5, true),
  7132. // Test case 9: Inserting every element of a vector turns into a composite construct in a different order.
  7133. InstructionFoldingCase<bool>(
  7134. Header() +
  7135. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  7136. "; CHECK-DAG: [[v4:%\\w+]] = OpTypeVector [[int]] 4\n" +
  7137. "; CHECK-DAG: [[int1:%\\w+]] = OpConstant [[int]] 1\n" +
  7138. "; CHECK-DAG: [[int2:%\\w+]] = OpConstant [[int]] 2\n" +
  7139. "; CHECK-DAG: [[int3:%\\w+]] = OpConstant [[int]] 3\n" +
  7140. "; CHECK: [[construct:%\\w+]] = OpCompositeConstruct [[v4]] %100 [[int1]] [[int2]] [[int3]]\n" +
  7141. "; CHECK: %5 = OpCopyObject [[v4]] [[construct]]\n" +
  7142. "%main = OpFunction %void None %void_func\n" +
  7143. "%main_lab = OpLabel\n" +
  7144. "%2 = OpCompositeInsert %v4int %100 %v4int_undef 0\n" +
  7145. "%4 = OpCompositeInsert %v4int %int_2 %2 2\n" +
  7146. "%3 = OpCompositeInsert %v4int %int_1 %4 1\n" +
  7147. "%5 = OpCompositeInsert %v4int %int_3 %3 3\n" +
  7148. "OpReturn\n" +
  7149. "OpFunctionEnd",
  7150. 5, true),
  7151. // Test case 10: Check multiple inserts to the same position are handled correctly.
  7152. InstructionFoldingCase<bool>(
  7153. Header() +
  7154. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  7155. "; CHECK-DAG: [[v4:%\\w+]] = OpTypeVector [[int]] 4\n" +
  7156. "; CHECK-DAG: [[int1:%\\w+]] = OpConstant [[int]] 1\n" +
  7157. "; CHECK-DAG: [[int2:%\\w+]] = OpConstant [[int]] 2\n" +
  7158. "; CHECK-DAG: [[int3:%\\w+]] = OpConstant [[int]] 3\n" +
  7159. "; CHECK: [[construct:%\\w+]] = OpCompositeConstruct [[v4]] %100 [[int1]] [[int2]] [[int3]]\n" +
  7160. "; CHECK: %6 = OpCopyObject [[v4]] [[construct]]\n" +
  7161. "%main = OpFunction %void None %void_func\n" +
  7162. "%main_lab = OpLabel\n" +
  7163. "%2 = OpCompositeInsert %v4int %100 %v4int_undef 0\n" +
  7164. "%3 = OpCompositeInsert %v4int %int_2 %2 2\n" +
  7165. "%4 = OpCompositeInsert %v4int %int_4 %3 1\n" +
  7166. "%5 = OpCompositeInsert %v4int %int_1 %4 1\n" +
  7167. "%6 = OpCompositeInsert %v4int %int_3 %5 3\n" +
  7168. "OpReturn\n" +
  7169. "OpFunctionEnd",
  7170. 6, true),
  7171. // Test case 11: The last indexes are 0 and 1, but they have different first indexes. This should not be folded.
  7172. InstructionFoldingCase<bool>(
  7173. Header() +
  7174. "%main = OpFunction %void None %void_func\n" +
  7175. "%main_lab = OpLabel\n" +
  7176. "%2 = OpCompositeInsert %m2x2int %100 %m2x2int_undef 0 0\n" +
  7177. "%3 = OpCompositeInsert %m2x2int %int_1 %2 1 1\n" +
  7178. "OpReturn\n" +
  7179. "OpFunctionEnd",
  7180. 3, false),
  7181. // Test case 12: Don't fold when there is a partial insertion.
  7182. InstructionFoldingCase<bool>(
  7183. Header() +
  7184. "%main = OpFunction %void None %void_func\n" +
  7185. "%main_lab = OpLabel\n" +
  7186. "%2 = OpCompositeInsert %m2x2int %v2int_1_0 %m2x2int_undef 0\n" +
  7187. "%3 = OpCompositeInsert %m2x2int %int_4 %2 0 0\n" +
  7188. "%4 = OpCompositeInsert %m2x2int %v2int_2_3 %3 1\n" +
  7189. "OpReturn\n" +
  7190. "OpFunctionEnd",
  7191. 4, false),
  7192. // Test case 13: Insert into a column of a matrix
  7193. InstructionFoldingCase<bool>(
  7194. Header() +
  7195. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  7196. "; CHECK-DAG: [[v2:%\\w+]] = OpTypeVector [[int]] 2\n" +
  7197. "; CHECK: [[m2x2:%\\w+]] = OpTypeMatrix [[v2]] 2\n" +
  7198. "; CHECK-DAG: [[m2x2_undef:%\\w+]] = OpUndef [[m2x2]]\n" +
  7199. "; CHECK-DAG: [[int1:%\\w+]] = OpConstant [[int]] 1\n" +
  7200. // We keep this insert in the chain. DeadInsertElimPass should remove it.
  7201. "; CHECK: [[insert:%\\w+]] = OpCompositeInsert [[m2x2]] %100 [[m2x2_undef]] 0 0\n" +
  7202. "; CHECK: [[construct:%\\w+]] = OpCompositeConstruct [[v2]] %100 [[int1]]\n" +
  7203. "; CHECK: %3 = OpCompositeInsert [[m2x2]] [[construct]] [[insert]] 0\n" +
  7204. "%main = OpFunction %void None %void_func\n" +
  7205. "%main_lab = OpLabel\n" +
  7206. "%2 = OpCompositeInsert %m2x2int %100 %m2x2int_undef 0 0\n" +
  7207. "%3 = OpCompositeInsert %m2x2int %int_1 %2 0 1\n" +
  7208. "OpReturn\n" +
  7209. "OpFunctionEnd",
  7210. 3, true),
  7211. // Test case 14: Insert all elements of the matrix.
  7212. InstructionFoldingCase<bool>(
  7213. Header() +
  7214. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  7215. "; CHECK-DAG: [[v2:%\\w+]] = OpTypeVector [[int]] 2\n" +
  7216. "; CHECK: [[m2x2:%\\w+]] = OpTypeMatrix [[v2]] 2\n" +
  7217. "; CHECK-DAG: [[m2x2_undef:%\\w+]] = OpUndef [[m2x2]]\n" +
  7218. "; CHECK-DAG: [[int1:%\\w+]] = OpConstant [[int]] 1\n" +
  7219. "; CHECK-DAG: [[int2:%\\w+]] = OpConstant [[int]] 2\n" +
  7220. "; CHECK-DAG: [[int3:%\\w+]] = OpConstant [[int]] 3\n" +
  7221. "; CHECK: [[c0:%\\w+]] = OpCompositeConstruct [[v2]] %100 [[int1]]\n" +
  7222. "; CHECK: [[c1:%\\w+]] = OpCompositeConstruct [[v2]] [[int2]] [[int3]]\n" +
  7223. "; CHECK: [[matrix:%\\w+]] = OpCompositeConstruct [[m2x2]] [[c0]] [[c1]]\n" +
  7224. "; CHECK: %5 = OpCopyObject [[m2x2]] [[matrix]]\n" +
  7225. "%main = OpFunction %void None %void_func\n" +
  7226. "%main_lab = OpLabel\n" +
  7227. "%2 = OpCompositeConstruct %v2int %100 %int_1\n" +
  7228. "%3 = OpCompositeInsert %m2x2int %2 %m2x2int_undef 0\n" +
  7229. "%4 = OpCompositeInsert %m2x2int %int_2 %3 1 0\n" +
  7230. "%5 = OpCompositeInsert %m2x2int %int_3 %4 1 1\n" +
  7231. "OpReturn\n" +
  7232. "OpFunctionEnd",
  7233. 5, true),
  7234. // Test case 15: Replace construct with extract when reconstructing a member
  7235. // of another object.
  7236. InstructionFoldingCase<bool>(
  7237. Header() +
  7238. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  7239. "; CHECK: [[v2:%\\w+]] = OpTypeVector [[int]] 2\n" +
  7240. "; CHECK: [[m2x2:%\\w+]] = OpTypeMatrix [[v2]] 2\n" +
  7241. "; CHECK: [[m2x2_undef:%\\w+]] = OpUndef [[m2x2]]\n" +
  7242. "; CHECK: %5 = OpCompositeExtract [[v2]] [[m2x2_undef]]\n" +
  7243. "%main = OpFunction %void None %void_func\n" +
  7244. "%main_lab = OpLabel\n" +
  7245. "%3 = OpCompositeExtract %int %m2x2int_undef 1 0\n" +
  7246. "%4 = OpCompositeExtract %int %m2x2int_undef 1 1\n" +
  7247. "%5 = OpCompositeConstruct %v2int %3 %4\n" +
  7248. "OpReturn\n" +
  7249. "OpFunctionEnd",
  7250. 5, true),
  7251. // Test case 16: Don't fold when type cannot be deduced to a constant.
  7252. InstructionFoldingCase<bool>(
  7253. Header() +
  7254. "%main = OpFunction %void None %void_func\n" +
  7255. "%main_lab = OpLabel\n" +
  7256. "%4 = OpCompositeInsert %struct_v2int_int_int %int_1 %struct_v2int_int_int_null 2\n" +
  7257. "OpReturn\n" +
  7258. "OpFunctionEnd",
  7259. 4, false)
  7260. ));
  7261. INSTANTIATE_TEST_SUITE_P(DotProductMatchingTest, MatchingInstructionFoldingTest,
  7262. ::testing::Values(
  7263. // Test case 0: Using OpDot to extract last element.
  7264. InstructionFoldingCase<bool>(
  7265. Header() +
  7266. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  7267. "; CHECK: %3 = OpCompositeExtract [[float]] %2 3\n" +
  7268. "%main = OpFunction %void None %void_func\n" +
  7269. "%main_lab = OpLabel\n" +
  7270. "%n = OpVariable %_ptr_v4float Function\n" +
  7271. "%2 = OpLoad %v4float %n\n" +
  7272. "%3 = OpDot %float %2 %v4float_0_0_0_1\n" +
  7273. "OpReturn\n" +
  7274. "OpFunctionEnd",
  7275. 3, true),
  7276. // Test case 1: Using OpDot to extract last element.
  7277. InstructionFoldingCase<bool>(
  7278. Header() +
  7279. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  7280. "; CHECK: %3 = OpCompositeExtract [[float]] %2 3\n" +
  7281. "%main = OpFunction %void None %void_func\n" +
  7282. "%main_lab = OpLabel\n" +
  7283. "%n = OpVariable %_ptr_v4float Function\n" +
  7284. "%2 = OpLoad %v4float %n\n" +
  7285. "%3 = OpDot %float %v4float_0_0_0_1 %2\n" +
  7286. "OpReturn\n" +
  7287. "OpFunctionEnd",
  7288. 3, true),
  7289. // Test case 2: Using OpDot to extract second element.
  7290. InstructionFoldingCase<bool>(
  7291. Header() +
  7292. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  7293. "; CHECK: %3 = OpCompositeExtract [[float]] %2 1\n" +
  7294. "%main = OpFunction %void None %void_func\n" +
  7295. "%main_lab = OpLabel\n" +
  7296. "%n = OpVariable %_ptr_v4float Function\n" +
  7297. "%2 = OpLoad %v4float %n\n" +
  7298. "%3 = OpDot %float %v4float_0_1_0_0 %2\n" +
  7299. "OpReturn\n" +
  7300. "OpFunctionEnd",
  7301. 3, true),
  7302. // Test case 3: Using OpDot to extract last element.
  7303. InstructionFoldingCase<bool>(
  7304. Header() +
  7305. "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
  7306. "; CHECK: %3 = OpCompositeExtract [[double]] %2 3\n" +
  7307. "%main = OpFunction %void None %void_func\n" +
  7308. "%main_lab = OpLabel\n" +
  7309. "%n = OpVariable %_ptr_v4double Function\n" +
  7310. "%2 = OpLoad %v4double %n\n" +
  7311. "%3 = OpDot %double %2 %v4double_0_0_0_1\n" +
  7312. "OpReturn\n" +
  7313. "OpFunctionEnd",
  7314. 3, true),
  7315. // Test case 4: Using OpDot to extract last element.
  7316. InstructionFoldingCase<bool>(
  7317. Header() +
  7318. "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
  7319. "; CHECK: %3 = OpCompositeExtract [[double]] %2 3\n" +
  7320. "%main = OpFunction %void None %void_func\n" +
  7321. "%main_lab = OpLabel\n" +
  7322. "%n = OpVariable %_ptr_v4double Function\n" +
  7323. "%2 = OpLoad %v4double %n\n" +
  7324. "%3 = OpDot %double %v4double_0_0_0_1 %2\n" +
  7325. "OpReturn\n" +
  7326. "OpFunctionEnd",
  7327. 3, true),
  7328. // Test case 5: Using OpDot to extract second element.
  7329. InstructionFoldingCase<bool>(
  7330. Header() +
  7331. "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
  7332. "; CHECK: %3 = OpCompositeExtract [[double]] %2 1\n" +
  7333. "%main = OpFunction %void None %void_func\n" +
  7334. "%main_lab = OpLabel\n" +
  7335. "%n = OpVariable %_ptr_v4double Function\n" +
  7336. "%2 = OpLoad %v4double %n\n" +
  7337. "%3 = OpDot %double %v4double_0_1_0_0 %2\n" +
  7338. "OpReturn\n" +
  7339. "OpFunctionEnd",
  7340. 3, true)
  7341. ));
  7342. INSTANTIATE_TEST_SUITE_P(VectorShuffleMatchingTest, MatchingInstructionFoldingTest,
  7343. ::testing::Values(
  7344. // Test case 0: Using OpDot to extract last element.
  7345. InstructionFoldingCase<bool>(
  7346. Header() +
  7347. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  7348. "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2{{[[:space:]]}}\n" +
  7349. "; CHECK: [[null:%\\w+]] = OpConstantNull [[v2int]]\n" +
  7350. "; CHECK: OpVectorShuffle\n" +
  7351. "; CHECK: %3 = OpVectorShuffle [[v2int]] [[null]] {{%\\w+}} 4294967295 2\n" +
  7352. "%main = OpFunction %void None %void_func\n" +
  7353. "%main_lab = OpLabel\n" +
  7354. "%n = OpVariable %_ptr_int Function\n" +
  7355. "%load = OpLoad %int %n\n" +
  7356. "%2 = OpVectorShuffle %v2int %v2int_null %v2int_2_3 3 0xFFFFFFFF \n" +
  7357. "%3 = OpVectorShuffle %v2int %2 %v2int_2_3 1 2 \n" +
  7358. "OpReturn\n" +
  7359. "OpFunctionEnd",
  7360. 3, true)
  7361. ));
  7362. INSTANTIATE_TEST_SUITE_P(FmaGenerationMatchingTest, MatchingInstructionFoldingTest,
  7363. ::testing::Values(
  7364. // Test case 0: (x * y) + a = Fma(x, y, a)
  7365. InstructionFoldingCase<bool>(
  7366. Header() +
  7367. "; CHECK: [[ext:%\\w+]] = OpExtInstImport \"GLSL.std.450\"\n" +
  7368. "; CHECK: OpFunction\n" +
  7369. "; CHECK: [[x:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
  7370. "; CHECK: [[y:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
  7371. "; CHECK: [[a:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
  7372. "; CHECK: [[lx:%\\w+]] = OpLoad {{%\\w+}} [[x]]\n" +
  7373. "; CHECK: [[ly:%\\w+]] = OpLoad {{%\\w+}} [[y]]\n" +
  7374. "; CHECK: [[la:%\\w+]] = OpLoad {{%\\w+}} [[a]]\n" +
  7375. "; CHECK: [[fma:%\\w+]] = OpExtInst {{%\\w+}} [[ext]] Fma [[lx]] [[ly]] [[la]]\n" +
  7376. "; CHECK: OpStore {{%\\w+}} [[fma]]\n" +
  7377. "%main = OpFunction %void None %void_func\n" +
  7378. "%main_lab = OpLabel\n" +
  7379. "%x = OpVariable %_ptr_float Function\n" +
  7380. "%y = OpVariable %_ptr_float Function\n" +
  7381. "%a = OpVariable %_ptr_float Function\n" +
  7382. "%lx = OpLoad %float %x\n" +
  7383. "%ly = OpLoad %float %y\n" +
  7384. "%mul = OpFMul %float %lx %ly\n" +
  7385. "%la = OpLoad %float %a\n" +
  7386. "%3 = OpFAdd %float %mul %la\n" +
  7387. "OpStore %a %3\n" +
  7388. "OpReturn\n" +
  7389. "OpFunctionEnd",
  7390. 3, true),
  7391. // Test case 1: a + (x * y) = Fma(x, y, a)
  7392. InstructionFoldingCase<bool>(
  7393. Header() +
  7394. "; CHECK: [[ext:%\\w+]] = OpExtInstImport \"GLSL.std.450\"\n" +
  7395. "; CHECK: OpFunction\n" +
  7396. "; CHECK: [[x:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
  7397. "; CHECK: [[y:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
  7398. "; CHECK: [[a:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
  7399. "; CHECK: [[lx:%\\w+]] = OpLoad {{%\\w+}} [[x]]\n" +
  7400. "; CHECK: [[ly:%\\w+]] = OpLoad {{%\\w+}} [[y]]\n" +
  7401. "; CHECK: [[la:%\\w+]] = OpLoad {{%\\w+}} [[a]]\n" +
  7402. "; CHECK: [[fma:%\\w+]] = OpExtInst {{%\\w+}} [[ext]] Fma [[lx]] [[ly]] [[la]]\n" +
  7403. "; CHECK: OpStore {{%\\w+}} [[fma]]\n" +
  7404. "%main = OpFunction %void None %void_func\n" +
  7405. "%main_lab = OpLabel\n" +
  7406. "%x = OpVariable %_ptr_float Function\n" +
  7407. "%y = OpVariable %_ptr_float Function\n" +
  7408. "%a = OpVariable %_ptr_float Function\n" +
  7409. "%lx = OpLoad %float %x\n" +
  7410. "%ly = OpLoad %float %y\n" +
  7411. "%mul = OpFMul %float %lx %ly\n" +
  7412. "%la = OpLoad %float %a\n" +
  7413. "%3 = OpFAdd %float %la %mul\n" +
  7414. "OpStore %a %3\n" +
  7415. "OpReturn\n" +
  7416. "OpFunctionEnd",
  7417. 3, true),
  7418. // Test case 2: (x * y) + a = Fma(x, y, a) with vectors
  7419. InstructionFoldingCase<bool>(
  7420. Header() +
  7421. "; CHECK: [[ext:%\\w+]] = OpExtInstImport \"GLSL.std.450\"\n" +
  7422. "; CHECK: OpFunction\n" +
  7423. "; CHECK: [[x:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
  7424. "; CHECK: [[y:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
  7425. "; CHECK: [[a:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
  7426. "; CHECK: [[lx:%\\w+]] = OpLoad {{%\\w+}} [[x]]\n" +
  7427. "; CHECK: [[ly:%\\w+]] = OpLoad {{%\\w+}} [[y]]\n" +
  7428. "; CHECK: [[la:%\\w+]] = OpLoad {{%\\w+}} [[a]]\n" +
  7429. "; CHECK: [[fma:%\\w+]] = OpExtInst {{%\\w+}} [[ext]] Fma [[lx]] [[ly]] [[la]]\n" +
  7430. "; CHECK: OpStore {{%\\w+}} [[fma]]\n" +
  7431. "%main = OpFunction %void None %void_func\n" +
  7432. "%main_lab = OpLabel\n" +
  7433. "%x = OpVariable %_ptr_v4float Function\n" +
  7434. "%y = OpVariable %_ptr_v4float Function\n" +
  7435. "%a = OpVariable %_ptr_v4float Function\n" +
  7436. "%lx = OpLoad %v4float %x\n" +
  7437. "%ly = OpLoad %v4float %y\n" +
  7438. "%mul = OpFMul %v4float %lx %ly\n" +
  7439. "%la = OpLoad %v4float %a\n" +
  7440. "%3 = OpFAdd %v4float %mul %la\n" +
  7441. "OpStore %a %3\n" +
  7442. "OpReturn\n" +
  7443. "OpFunctionEnd",
  7444. 3, true),
  7445. // Test case 3: a + (x * y) = Fma(x, y, a) with vectors
  7446. InstructionFoldingCase<bool>(
  7447. Header() +
  7448. "; CHECK: [[ext:%\\w+]] = OpExtInstImport \"GLSL.std.450\"\n" +
  7449. "; CHECK: OpFunction\n" +
  7450. "; CHECK: [[x:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
  7451. "; CHECK: [[y:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
  7452. "; CHECK: [[a:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
  7453. "; CHECK: [[lx:%\\w+]] = OpLoad {{%\\w+}} [[x]]\n" +
  7454. "; CHECK: [[ly:%\\w+]] = OpLoad {{%\\w+}} [[y]]\n" +
  7455. "; CHECK: [[la:%\\w+]] = OpLoad {{%\\w+}} [[a]]\n" +
  7456. "; CHECK: [[fma:%\\w+]] = OpExtInst {{%\\w+}} [[ext]] Fma [[lx]] [[ly]] [[la]]\n" +
  7457. "; CHECK: OpStore {{%\\w+}} [[fma]]\n" +
  7458. "%main = OpFunction %void None %void_func\n" +
  7459. "%main_lab = OpLabel\n" +
  7460. "%x = OpVariable %_ptr_float Function\n" +
  7461. "%y = OpVariable %_ptr_float Function\n" +
  7462. "%a = OpVariable %_ptr_float Function\n" +
  7463. "%lx = OpLoad %float %x\n" +
  7464. "%ly = OpLoad %float %y\n" +
  7465. "%mul = OpFMul %float %lx %ly\n" +
  7466. "%la = OpLoad %float %a\n" +
  7467. "%3 = OpFAdd %float %la %mul\n" +
  7468. "OpStore %a %3\n" +
  7469. "OpReturn\n" +
  7470. "OpFunctionEnd",
  7471. 3, true),
  7472. // Test 4: that the OpExtInstImport instruction is generated if it is missing.
  7473. InstructionFoldingCase<bool>(
  7474. std::string() +
  7475. "; CHECK: [[ext:%\\w+]] = OpExtInstImport \"GLSL.std.450\"\n" +
  7476. "; CHECK: OpFunction\n" +
  7477. "; CHECK: [[x:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
  7478. "; CHECK: [[y:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
  7479. "; CHECK: [[a:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
  7480. "; CHECK: [[lx:%\\w+]] = OpLoad {{%\\w+}} [[x]]\n" +
  7481. "; CHECK: [[ly:%\\w+]] = OpLoad {{%\\w+}} [[y]]\n" +
  7482. "; CHECK: [[la:%\\w+]] = OpLoad {{%\\w+}} [[a]]\n" +
  7483. "; CHECK: [[fma:%\\w+]] = OpExtInst {{%\\w+}} [[ext]] Fma [[lx]] [[ly]] [[la]]\n" +
  7484. "; CHECK: OpStore {{%\\w+}} [[fma]]\n" +
  7485. "OpCapability Shader\n" +
  7486. "OpMemoryModel Logical GLSL450\n" +
  7487. "OpEntryPoint Fragment %main \"main\"\n" +
  7488. "OpExecutionMode %main OriginUpperLeft\n" +
  7489. "OpSource GLSL 140\n" +
  7490. "OpName %main \"main\"\n" +
  7491. "%void = OpTypeVoid\n" +
  7492. "%void_func = OpTypeFunction %void\n" +
  7493. "%bool = OpTypeBool\n" +
  7494. "%float = OpTypeFloat 32\n" +
  7495. "%_ptr_float = OpTypePointer Function %float\n" +
  7496. "%main = OpFunction %void None %void_func\n" +
  7497. "%main_lab = OpLabel\n" +
  7498. "%x = OpVariable %_ptr_float Function\n" +
  7499. "%y = OpVariable %_ptr_float Function\n" +
  7500. "%a = OpVariable %_ptr_float Function\n" +
  7501. "%lx = OpLoad %float %x\n" +
  7502. "%ly = OpLoad %float %y\n" +
  7503. "%mul = OpFMul %float %lx %ly\n" +
  7504. "%la = OpLoad %float %a\n" +
  7505. "%3 = OpFAdd %float %mul %la\n" +
  7506. "OpStore %a %3\n" +
  7507. "OpReturn\n" +
  7508. "OpFunctionEnd",
  7509. 3, true),
  7510. // Test 5: Don't fold if the multiple is marked no contract.
  7511. InstructionFoldingCase<bool>(
  7512. std::string() +
  7513. "OpCapability Shader\n" +
  7514. "OpMemoryModel Logical GLSL450\n" +
  7515. "OpEntryPoint Fragment %main \"main\"\n" +
  7516. "OpExecutionMode %main OriginUpperLeft\n" +
  7517. "OpSource GLSL 140\n" +
  7518. "OpName %main \"main\"\n" +
  7519. "OpDecorate %mul NoContraction\n" +
  7520. "%void = OpTypeVoid\n" +
  7521. "%void_func = OpTypeFunction %void\n" +
  7522. "%bool = OpTypeBool\n" +
  7523. "%float = OpTypeFloat 32\n" +
  7524. "%_ptr_float = OpTypePointer Function %float\n" +
  7525. "%main = OpFunction %void None %void_func\n" +
  7526. "%main_lab = OpLabel\n" +
  7527. "%x = OpVariable %_ptr_float Function\n" +
  7528. "%y = OpVariable %_ptr_float Function\n" +
  7529. "%a = OpVariable %_ptr_float Function\n" +
  7530. "%lx = OpLoad %float %x\n" +
  7531. "%ly = OpLoad %float %y\n" +
  7532. "%mul = OpFMul %float %lx %ly\n" +
  7533. "%la = OpLoad %float %a\n" +
  7534. "%3 = OpFAdd %float %mul %la\n" +
  7535. "OpStore %a %3\n" +
  7536. "OpReturn\n" +
  7537. "OpFunctionEnd",
  7538. 3, false),
  7539. // Test 6: Don't fold if the add is marked no contract.
  7540. InstructionFoldingCase<bool>(
  7541. std::string() +
  7542. "OpCapability Shader\n" +
  7543. "OpMemoryModel Logical GLSL450\n" +
  7544. "OpEntryPoint Fragment %main \"main\"\n" +
  7545. "OpExecutionMode %main OriginUpperLeft\n" +
  7546. "OpSource GLSL 140\n" +
  7547. "OpName %main \"main\"\n" +
  7548. "OpDecorate %3 NoContraction\n" +
  7549. "%void = OpTypeVoid\n" +
  7550. "%void_func = OpTypeFunction %void\n" +
  7551. "%bool = OpTypeBool\n" +
  7552. "%float = OpTypeFloat 32\n" +
  7553. "%_ptr_float = OpTypePointer Function %float\n" +
  7554. "%main = OpFunction %void None %void_func\n" +
  7555. "%main_lab = OpLabel\n" +
  7556. "%x = OpVariable %_ptr_float Function\n" +
  7557. "%y = OpVariable %_ptr_float Function\n" +
  7558. "%a = OpVariable %_ptr_float Function\n" +
  7559. "%lx = OpLoad %float %x\n" +
  7560. "%ly = OpLoad %float %y\n" +
  7561. "%mul = OpFMul %float %lx %ly\n" +
  7562. "%la = OpLoad %float %a\n" +
  7563. "%3 = OpFAdd %float %mul %la\n" +
  7564. "OpStore %a %3\n" +
  7565. "OpReturn\n" +
  7566. "OpFunctionEnd",
  7567. 3, false),
  7568. // Test case 7: (x * y) - a = Fma(x, y, -a)
  7569. InstructionFoldingCase<bool>(
  7570. Header() +
  7571. "; CHECK: [[ext:%\\w+]] = OpExtInstImport \"GLSL.std.450\"\n" +
  7572. "; CHECK: OpFunction\n" +
  7573. "; CHECK: [[x:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
  7574. "; CHECK: [[y:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
  7575. "; CHECK: [[a:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
  7576. "; CHECK: [[lx:%\\w+]] = OpLoad {{%\\w+}} [[x]]\n" +
  7577. "; CHECK: [[ly:%\\w+]] = OpLoad {{%\\w+}} [[y]]\n" +
  7578. "; CHECK: [[la:%\\w+]] = OpLoad {{%\\w+}} [[a]]\n" +
  7579. "; CHECK: [[na:%\\w+]] = OpFNegate {{%\\w+}} [[la]]\n" +
  7580. "; CHECK: [[fma:%\\w+]] = OpExtInst {{%\\w+}} [[ext]] Fma [[lx]] [[ly]] [[na]]\n" +
  7581. "; CHECK: OpStore {{%\\w+}} [[fma]]\n" +
  7582. "%main = OpFunction %void None %void_func\n" +
  7583. "%main_lab = OpLabel\n" +
  7584. "%x = OpVariable %_ptr_float Function\n" +
  7585. "%y = OpVariable %_ptr_float Function\n" +
  7586. "%a = OpVariable %_ptr_float Function\n" +
  7587. "%lx = OpLoad %float %x\n" +
  7588. "%ly = OpLoad %float %y\n" +
  7589. "%mul = OpFMul %float %lx %ly\n" +
  7590. "%la = OpLoad %float %a\n" +
  7591. "%3 = OpFSub %float %mul %la\n" +
  7592. "OpStore %a %3\n" +
  7593. "OpReturn\n" +
  7594. "OpFunctionEnd",
  7595. 3, true),
  7596. // Test case 8: a - (x * y) = Fma(-x, y, a)
  7597. InstructionFoldingCase<bool>(
  7598. Header() +
  7599. "; CHECK: [[ext:%\\w+]] = OpExtInstImport \"GLSL.std.450\"\n" +
  7600. "; CHECK: OpFunction\n" +
  7601. "; CHECK: [[x:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
  7602. "; CHECK: [[y:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
  7603. "; CHECK: [[a:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
  7604. "; CHECK: [[lx:%\\w+]] = OpLoad {{%\\w+}} [[x]]\n" +
  7605. "; CHECK: [[ly:%\\w+]] = OpLoad {{%\\w+}} [[y]]\n" +
  7606. "; CHECK: [[la:%\\w+]] = OpLoad {{%\\w+}} [[a]]\n" +
  7607. "; CHECK: [[nx:%\\w+]] = OpFNegate {{%\\w+}} [[lx]]\n" +
  7608. "; CHECK: [[fma:%\\w+]] = OpExtInst {{%\\w+}} [[ext]] Fma [[nx]] [[ly]] [[la]]\n" +
  7609. "; CHECK: OpStore {{%\\w+}} [[fma]]\n" +
  7610. "%main = OpFunction %void None %void_func\n" +
  7611. "%main_lab = OpLabel\n" +
  7612. "%x = OpVariable %_ptr_float Function\n" +
  7613. "%y = OpVariable %_ptr_float Function\n" +
  7614. "%a = OpVariable %_ptr_float Function\n" +
  7615. "%lx = OpLoad %float %x\n" +
  7616. "%ly = OpLoad %float %y\n" +
  7617. "%mul = OpFMul %float %lx %ly\n" +
  7618. "%la = OpLoad %float %a\n" +
  7619. "%3 = OpFSub %float %la %mul\n" +
  7620. "OpStore %a %3\n" +
  7621. "OpReturn\n" +
  7622. "OpFunctionEnd",
  7623. 3, true)
  7624. ));
  7625. using MatchingInstructionWithNoResultFoldingTest =
  7626. ::testing::TestWithParam<InstructionFoldingCase<bool>>;
  7627. // Test folding instructions that do not have a result. The instruction
  7628. // that will be folded is the last instruction before the return. If there
  7629. // are multiple returns, there is not guarantee which one is used.
  7630. TEST_P(MatchingInstructionWithNoResultFoldingTest, Case) {
  7631. const auto& tc = GetParam();
  7632. // Build module.
  7633. std::unique_ptr<IRContext> context =
  7634. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
  7635. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  7636. ASSERT_NE(nullptr, context);
  7637. // Fold the instruction to test.
  7638. Instruction* inst = nullptr;
  7639. Function* func = &*context->module()->begin();
  7640. for (auto& bb : *func) {
  7641. Instruction* terminator = bb.terminator();
  7642. if (terminator->IsReturnOrAbort()) {
  7643. inst = terminator->PreviousNode();
  7644. break;
  7645. }
  7646. }
  7647. assert(inst && "Invalid test. Could not find instruction to fold.");
  7648. std::unique_ptr<Instruction> original_inst(inst->Clone(context.get()));
  7649. bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
  7650. EXPECT_EQ(succeeded, tc.expected_result);
  7651. if (succeeded) {
  7652. Match(tc.test_body, context.get());
  7653. }
  7654. }
  7655. INSTANTIATE_TEST_SUITE_P(StoreMatchingTest, MatchingInstructionWithNoResultFoldingTest,
  7656. ::testing::Values(
  7657. // Test case 0: Remove store of undef.
  7658. InstructionFoldingCase<bool>(
  7659. Header() +
  7660. "; CHECK: OpLabel\n" +
  7661. "; CHECK-NOT: OpStore\n" +
  7662. "; CHECK: OpReturn\n" +
  7663. "%main = OpFunction %void None %void_func\n" +
  7664. "%main_lab = OpLabel\n" +
  7665. "%n = OpVariable %_ptr_v4double Function\n" +
  7666. "%undef = OpUndef %v4double\n" +
  7667. "OpStore %n %undef\n" +
  7668. "OpReturn\n" +
  7669. "OpFunctionEnd",
  7670. 0 /* OpStore */, true),
  7671. // Test case 1: Keep volatile store.
  7672. InstructionFoldingCase<bool>(
  7673. Header() +
  7674. "%main = OpFunction %void None %void_func\n" +
  7675. "%main_lab = OpLabel\n" +
  7676. "%n = OpVariable %_ptr_v4double Function\n" +
  7677. "%undef = OpUndef %v4double\n" +
  7678. "OpStore %n %undef Volatile\n" +
  7679. "OpReturn\n" +
  7680. "OpFunctionEnd",
  7681. 0 /* OpStore */, false)
  7682. ));
  7683. INSTANTIATE_TEST_SUITE_P(VectorShuffleMatchingTest, MatchingInstructionWithNoResultFoldingTest,
  7684. ::testing::Values(
  7685. // Test case 0: Basic test 1
  7686. InstructionFoldingCase<bool>(
  7687. Header() +
  7688. "; CHECK: OpVectorShuffle\n" +
  7689. "; CHECK: OpVectorShuffle {{%\\w+}} %7 %5 2 3 6 7\n" +
  7690. "; CHECK: OpReturn\n" +
  7691. "%main = OpFunction %void None %void_func\n" +
  7692. "%main_lab = OpLabel\n" +
  7693. "%2 = OpVariable %_ptr_v4double Function\n" +
  7694. "%3 = OpVariable %_ptr_v4double Function\n" +
  7695. "%4 = OpVariable %_ptr_v4double Function\n" +
  7696. "%5 = OpLoad %v4double %2\n" +
  7697. "%6 = OpLoad %v4double %3\n" +
  7698. "%7 = OpLoad %v4double %4\n" +
  7699. "%8 = OpVectorShuffle %v4double %5 %6 2 3 4 5\n" +
  7700. "%9 = OpVectorShuffle %v4double %7 %8 2 3 4 5\n" +
  7701. "OpReturn\n" +
  7702. "OpFunctionEnd",
  7703. 9, true),
  7704. // Test case 1: Basic test 2
  7705. InstructionFoldingCase<bool>(
  7706. Header() +
  7707. "; CHECK: OpVectorShuffle\n" +
  7708. "; CHECK: OpVectorShuffle {{%\\w+}} %6 %7 0 1 4 5\n" +
  7709. "; CHECK: OpReturn\n" +
  7710. "%main = OpFunction %void None %void_func\n" +
  7711. "%main_lab = OpLabel\n" +
  7712. "%2 = OpVariable %_ptr_v4double Function\n" +
  7713. "%3 = OpVariable %_ptr_v4double Function\n" +
  7714. "%4 = OpVariable %_ptr_v4double Function\n" +
  7715. "%5 = OpLoad %v4double %2\n" +
  7716. "%6 = OpLoad %v4double %3\n" +
  7717. "%7 = OpLoad %v4double %4\n" +
  7718. "%8 = OpVectorShuffle %v4double %5 %6 2 3 4 5\n" +
  7719. "%9 = OpVectorShuffle %v4double %8 %7 2 3 4 5\n" +
  7720. "OpReturn\n" +
  7721. "OpFunctionEnd",
  7722. 9, true),
  7723. // Test case 2: Basic test 3
  7724. InstructionFoldingCase<bool>(
  7725. Header() +
  7726. "; CHECK: OpVectorShuffle\n" +
  7727. "; CHECK: OpVectorShuffle {{%\\w+}} %5 %7 3 2 4 5\n" +
  7728. "; CHECK: OpReturn\n" +
  7729. "%main = OpFunction %void None %void_func\n" +
  7730. "%main_lab = OpLabel\n" +
  7731. "%2 = OpVariable %_ptr_v4double Function\n" +
  7732. "%3 = OpVariable %_ptr_v4double Function\n" +
  7733. "%4 = OpVariable %_ptr_v4double Function\n" +
  7734. "%5 = OpLoad %v4double %2\n" +
  7735. "%6 = OpLoad %v4double %3\n" +
  7736. "%7 = OpLoad %v4double %4\n" +
  7737. "%8 = OpVectorShuffle %v4double %5 %6 2 3 4 5\n" +
  7738. "%9 = OpVectorShuffle %v4double %8 %7 1 0 4 5\n" +
  7739. "OpReturn\n" +
  7740. "OpFunctionEnd",
  7741. 9, true),
  7742. // Test case 3: Basic test 4
  7743. InstructionFoldingCase<bool>(
  7744. Header() +
  7745. "; CHECK: OpVectorShuffle\n" +
  7746. "; CHECK: OpVectorShuffle {{%\\w+}} %7 %6 2 3 5 4\n" +
  7747. "; CHECK: OpReturn\n" +
  7748. "%main = OpFunction %void None %void_func\n" +
  7749. "%main_lab = OpLabel\n" +
  7750. "%2 = OpVariable %_ptr_v4double Function\n" +
  7751. "%3 = OpVariable %_ptr_v4double Function\n" +
  7752. "%4 = OpVariable %_ptr_v4double Function\n" +
  7753. "%5 = OpLoad %v4double %2\n" +
  7754. "%6 = OpLoad %v4double %3\n" +
  7755. "%7 = OpLoad %v4double %4\n" +
  7756. "%8 = OpVectorShuffle %v4double %5 %6 2 3 4 5\n" +
  7757. "%9 = OpVectorShuffle %v4double %7 %8 2 3 7 6\n" +
  7758. "OpReturn\n" +
  7759. "OpFunctionEnd",
  7760. 9, true),
  7761. // Test case 4: Don't fold, need both operands of the feeder.
  7762. InstructionFoldingCase<bool>(
  7763. Header() +
  7764. "%main = OpFunction %void None %void_func\n" +
  7765. "%main_lab = OpLabel\n" +
  7766. "%2 = OpVariable %_ptr_v4double Function\n" +
  7767. "%3 = OpVariable %_ptr_v4double Function\n" +
  7768. "%4 = OpVariable %_ptr_v4double Function\n" +
  7769. "%5 = OpLoad %v4double %2\n" +
  7770. "%6 = OpLoad %v4double %3\n" +
  7771. "%7 = OpLoad %v4double %4\n" +
  7772. "%8 = OpVectorShuffle %v4double %5 %6 2 3 4 5\n" +
  7773. "%9 = OpVectorShuffle %v4double %7 %8 2 3 7 5\n" +
  7774. "OpReturn\n" +
  7775. "OpFunctionEnd",
  7776. 9, false),
  7777. // Test case 5: Don't fold, need both operands of the feeder.
  7778. InstructionFoldingCase<bool>(
  7779. Header() +
  7780. "%main = OpFunction %void None %void_func\n" +
  7781. "%main_lab = OpLabel\n" +
  7782. "%2 = OpVariable %_ptr_v4double Function\n" +
  7783. "%3 = OpVariable %_ptr_v4double Function\n" +
  7784. "%4 = OpVariable %_ptr_v4double Function\n" +
  7785. "%5 = OpLoad %v4double %2\n" +
  7786. "%6 = OpLoad %v4double %3\n" +
  7787. "%7 = OpLoad %v4double %4\n" +
  7788. "%8 = OpVectorShuffle %v4double %5 %6 2 3 4 5\n" +
  7789. "%9 = OpVectorShuffle %v4double %8 %7 2 0 7 5\n" +
  7790. "OpReturn\n" +
  7791. "OpFunctionEnd",
  7792. 9, false),
  7793. // Test case 6: Fold, need both operands of the feeder, but they are the same.
  7794. InstructionFoldingCase<bool>(
  7795. Header() +
  7796. "; CHECK: OpVectorShuffle\n" +
  7797. "; CHECK: OpVectorShuffle {{%\\w+}} %5 %7 0 2 7 5\n" +
  7798. "; CHECK: OpReturn\n" +
  7799. "%main = OpFunction %void None %void_func\n" +
  7800. "%main_lab = OpLabel\n" +
  7801. "%2 = OpVariable %_ptr_v4double Function\n" +
  7802. "%3 = OpVariable %_ptr_v4double Function\n" +
  7803. "%4 = OpVariable %_ptr_v4double Function\n" +
  7804. "%5 = OpLoad %v4double %2\n" +
  7805. "%6 = OpLoad %v4double %3\n" +
  7806. "%7 = OpLoad %v4double %4\n" +
  7807. "%8 = OpVectorShuffle %v4double %5 %5 2 3 4 5\n" +
  7808. "%9 = OpVectorShuffle %v4double %8 %7 2 0 7 5\n" +
  7809. "OpReturn\n" +
  7810. "OpFunctionEnd",
  7811. 9, true),
  7812. // Test case 7: Fold, need both operands of the feeder, but they are the same.
  7813. InstructionFoldingCase<bool>(
  7814. Header() +
  7815. "; CHECK: OpVectorShuffle\n" +
  7816. "; CHECK: OpVectorShuffle {{%\\w+}} %7 %5 2 0 5 7\n" +
  7817. "; CHECK: OpReturn\n" +
  7818. "%main = OpFunction %void None %void_func\n" +
  7819. "%main_lab = OpLabel\n" +
  7820. "%2 = OpVariable %_ptr_v4double Function\n" +
  7821. "%3 = OpVariable %_ptr_v4double Function\n" +
  7822. "%4 = OpVariable %_ptr_v4double Function\n" +
  7823. "%5 = OpLoad %v4double %2\n" +
  7824. "%6 = OpLoad %v4double %3\n" +
  7825. "%7 = OpLoad %v4double %4\n" +
  7826. "%8 = OpVectorShuffle %v4double %5 %5 2 3 4 5\n" +
  7827. "%9 = OpVectorShuffle %v4double %7 %8 2 0 7 5\n" +
  7828. "OpReturn\n" +
  7829. "OpFunctionEnd",
  7830. 9, true),
  7831. // Test case 8: Replace first operand with a smaller vector.
  7832. InstructionFoldingCase<bool>(
  7833. Header() +
  7834. "; CHECK: OpVectorShuffle\n" +
  7835. "; CHECK: OpVectorShuffle {{%\\w+}} %5 %7 0 0 5 3\n" +
  7836. "; CHECK: OpReturn\n" +
  7837. "%main = OpFunction %void None %void_func\n" +
  7838. "%main_lab = OpLabel\n" +
  7839. "%2 = OpVariable %_ptr_v2double Function\n" +
  7840. "%3 = OpVariable %_ptr_v4double Function\n" +
  7841. "%4 = OpVariable %_ptr_v4double Function\n" +
  7842. "%5 = OpLoad %v2double %2\n" +
  7843. "%6 = OpLoad %v4double %3\n" +
  7844. "%7 = OpLoad %v4double %4\n" +
  7845. "%8 = OpVectorShuffle %v4double %5 %5 0 1 2 3\n" +
  7846. "%9 = OpVectorShuffle %v4double %8 %7 2 0 7 5\n" +
  7847. "OpReturn\n" +
  7848. "OpFunctionEnd",
  7849. 9, true),
  7850. // Test case 9: Replace first operand with a larger vector.
  7851. InstructionFoldingCase<bool>(
  7852. Header() +
  7853. "; CHECK: OpVectorShuffle\n" +
  7854. "; CHECK: OpVectorShuffle {{%\\w+}} %5 %7 3 0 7 5\n" +
  7855. "; CHECK: OpReturn\n" +
  7856. "%main = OpFunction %void None %void_func\n" +
  7857. "%main_lab = OpLabel\n" +
  7858. "%2 = OpVariable %_ptr_v4double Function\n" +
  7859. "%3 = OpVariable %_ptr_v4double Function\n" +
  7860. "%4 = OpVariable %_ptr_v4double Function\n" +
  7861. "%5 = OpLoad %v4double %2\n" +
  7862. "%6 = OpLoad %v4double %3\n" +
  7863. "%7 = OpLoad %v4double %4\n" +
  7864. "%8 = OpVectorShuffle %v2double %5 %5 0 3\n" +
  7865. "%9 = OpVectorShuffle %v4double %8 %7 1 0 5 3\n" +
  7866. "OpReturn\n" +
  7867. "OpFunctionEnd",
  7868. 9, true),
  7869. // Test case 10: Replace unused operand with null.
  7870. InstructionFoldingCase<bool>(
  7871. Header() +
  7872. "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
  7873. "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 2\n" +
  7874. "; CHECK: [[null:%\\w+]] = OpConstantNull [[v4double]]\n" +
  7875. "; CHECK: OpVectorShuffle\n" +
  7876. "; CHECK: OpVectorShuffle {{%\\w+}} [[null]] %7 4 2 5 3\n" +
  7877. "; CHECK: OpReturn\n" +
  7878. "%main = OpFunction %void None %void_func\n" +
  7879. "%main_lab = OpLabel\n" +
  7880. "%2 = OpVariable %_ptr_v4double Function\n" +
  7881. "%3 = OpVariable %_ptr_v4double Function\n" +
  7882. "%4 = OpVariable %_ptr_v4double Function\n" +
  7883. "%5 = OpLoad %v4double %2\n" +
  7884. "%6 = OpLoad %v4double %3\n" +
  7885. "%7 = OpLoad %v4double %4\n" +
  7886. "%8 = OpVectorShuffle %v2double %5 %5 0 3\n" +
  7887. "%9 = OpVectorShuffle %v4double %8 %7 4 2 5 3\n" +
  7888. "OpReturn\n" +
  7889. "OpFunctionEnd",
  7890. 9, true),
  7891. // Test case 11: Replace unused operand with null.
  7892. InstructionFoldingCase<bool>(
  7893. Header() +
  7894. "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
  7895. "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 2\n" +
  7896. "; CHECK: [[null:%\\w+]] = OpConstantNull [[v4double]]\n" +
  7897. "; CHECK: OpVectorShuffle\n" +
  7898. "; CHECK: OpVectorShuffle {{%\\w+}} [[null]] %5 2 2 5 5\n" +
  7899. "; CHECK: OpReturn\n" +
  7900. "%main = OpFunction %void None %void_func\n" +
  7901. "%main_lab = OpLabel\n" +
  7902. "%2 = OpVariable %_ptr_v4double Function\n" +
  7903. "%3 = OpVariable %_ptr_v4double Function\n" +
  7904. "%5 = OpLoad %v4double %2\n" +
  7905. "%6 = OpLoad %v4double %3\n" +
  7906. "%8 = OpVectorShuffle %v2double %5 %5 0 3\n" +
  7907. "%9 = OpVectorShuffle %v4double %8 %8 2 2 3 3\n" +
  7908. "OpReturn\n" +
  7909. "OpFunctionEnd",
  7910. 9, true),
  7911. // Test case 12: Replace unused operand with null.
  7912. InstructionFoldingCase<bool>(
  7913. Header() +
  7914. "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
  7915. "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 2\n" +
  7916. "; CHECK: [[null:%\\w+]] = OpConstantNull [[v4double]]\n" +
  7917. "; CHECK: OpVectorShuffle\n" +
  7918. "; CHECK: OpVectorShuffle {{%\\w+}} %7 [[null]] 2 0 1 3\n" +
  7919. "; CHECK: OpReturn\n" +
  7920. "%main = OpFunction %void None %void_func\n" +
  7921. "%main_lab = OpLabel\n" +
  7922. "%2 = OpVariable %_ptr_v4double Function\n" +
  7923. "%3 = OpVariable %_ptr_v4double Function\n" +
  7924. "%4 = OpVariable %_ptr_v4double Function\n" +
  7925. "%5 = OpLoad %v4double %2\n" +
  7926. "%6 = OpLoad %v4double %3\n" +
  7927. "%7 = OpLoad %v4double %4\n" +
  7928. "%8 = OpVectorShuffle %v2double %5 %5 0 3\n" +
  7929. "%9 = OpVectorShuffle %v4double %7 %8 2 0 1 3\n" +
  7930. "OpReturn\n" +
  7931. "OpFunctionEnd",
  7932. 9, true),
  7933. // Test case 13: Shuffle with undef literal.
  7934. InstructionFoldingCase<bool>(
  7935. Header() +
  7936. "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
  7937. "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 2\n" +
  7938. "; CHECK: OpVectorShuffle\n" +
  7939. "; CHECK: OpVectorShuffle {{%\\w+}} %7 {{%\\w+}} 2 0 1 4294967295\n" +
  7940. "; CHECK: OpReturn\n" +
  7941. "%main = OpFunction %void None %void_func\n" +
  7942. "%main_lab = OpLabel\n" +
  7943. "%2 = OpVariable %_ptr_v4double Function\n" +
  7944. "%3 = OpVariable %_ptr_v4double Function\n" +
  7945. "%4 = OpVariable %_ptr_v4double Function\n" +
  7946. "%5 = OpLoad %v4double %2\n" +
  7947. "%6 = OpLoad %v4double %3\n" +
  7948. "%7 = OpLoad %v4double %4\n" +
  7949. "%8 = OpVectorShuffle %v2double %5 %5 0 1\n" +
  7950. "%9 = OpVectorShuffle %v4double %7 %8 2 0 1 4294967295\n" +
  7951. "OpReturn\n" +
  7952. "OpFunctionEnd",
  7953. 9, true),
  7954. // Test case 14: Shuffle with undef literal and change size of first input vector.
  7955. InstructionFoldingCase<bool>(
  7956. Header() +
  7957. "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
  7958. "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 2\n" +
  7959. "; CHECK: OpVectorShuffle\n" +
  7960. "; CHECK: OpVectorShuffle {{%\\w+}} %5 %7 0 1 4 4294967295\n" +
  7961. "; CHECK: OpReturn\n" +
  7962. "%main = OpFunction %void None %void_func\n" +
  7963. "%main_lab = OpLabel\n" +
  7964. "%2 = OpVariable %_ptr_v4double Function\n" +
  7965. "%3 = OpVariable %_ptr_v4double Function\n" +
  7966. "%4 = OpVariable %_ptr_v4double Function\n" +
  7967. "%5 = OpLoad %v4double %2\n" +
  7968. "%6 = OpLoad %v4double %3\n" +
  7969. "%7 = OpLoad %v4double %4\n" +
  7970. "%8 = OpVectorShuffle %v2double %5 %5 0 1\n" +
  7971. "%9 = OpVectorShuffle %v4double %8 %7 0 1 2 4294967295\n" +
  7972. "OpReturn\n" +
  7973. "OpFunctionEnd",
  7974. 9, true)
  7975. ));
  7976. using EntryPointFoldingTest =
  7977. ::testing::TestWithParam<InstructionFoldingCase<bool>>;
  7978. TEST_P(EntryPointFoldingTest, Case) {
  7979. const auto& tc = GetParam();
  7980. // Build module.
  7981. std::unique_ptr<IRContext> context =
  7982. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
  7983. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  7984. ASSERT_NE(nullptr, context);
  7985. // Fold the instruction to test.
  7986. Instruction* inst = nullptr;
  7987. inst = &*context->module()->entry_points().begin();
  7988. assert(inst && "Invalid test. Could not find entry point instruction to fold.");
  7989. std::unique_ptr<Instruction> original_inst(inst->Clone(context.get()));
  7990. bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
  7991. EXPECT_EQ(succeeded, tc.expected_result);
  7992. if (succeeded) {
  7993. Match(tc.test_body, context.get());
  7994. }
  7995. }
  7996. INSTANTIATE_TEST_SUITE_P(OpEntryPointFoldingTest, EntryPointFoldingTest,
  7997. ::testing::Values(
  7998. // Test case 0: Basic test 1
  7999. InstructionFoldingCase<bool>(std::string() +
  8000. "; CHECK: OpEntryPoint Fragment %2 \"main\" %3\n" +
  8001. "OpCapability Shader\n" +
  8002. "%1 = OpExtInstImport \"GLSL.std.450\"\n" +
  8003. "OpMemoryModel Logical GLSL450\n" +
  8004. "OpEntryPoint Fragment %2 \"main\" %3 %3 %3\n" +
  8005. "OpExecutionMode %2 OriginUpperLeft\n" +
  8006. "OpSource GLSL 430\n" +
  8007. "OpDecorate %3 Location 0\n" +
  8008. "%void = OpTypeVoid\n" +
  8009. "%5 = OpTypeFunction %void\n" +
  8010. "%float = OpTypeFloat 32\n" +
  8011. "%v4float = OpTypeVector %float 4\n" +
  8012. "%_ptr_Output_v4float = OpTypePointer Output %v4float\n" +
  8013. "%3 = OpVariable %_ptr_Output_v4float Output\n" +
  8014. "%int = OpTypeInt 32 1\n" +
  8015. "%int_0 = OpConstant %int 0\n" +
  8016. "%_ptr_PushConstant_v4float = OpTypePointer PushConstant %v4float\n" +
  8017. "%2 = OpFunction %void None %5\n" +
  8018. "%12 = OpLabel\n" +
  8019. "OpReturn\n" +
  8020. "OpFunctionEnd\n",
  8021. 9, true),
  8022. InstructionFoldingCase<bool>(std::string() +
  8023. "; CHECK: OpEntryPoint Fragment %2 \"main\" %3 %4\n" +
  8024. "OpCapability Shader\n" +
  8025. "%1 = OpExtInstImport \"GLSL.std.450\"\n" +
  8026. "OpMemoryModel Logical GLSL450\n" +
  8027. "OpEntryPoint Fragment %2 \"main\" %3 %4 %3\n" +
  8028. "OpExecutionMode %2 OriginUpperLeft\n" +
  8029. "OpSource GLSL 430\n" +
  8030. "OpDecorate %3 Location 0\n" +
  8031. "%void = OpTypeVoid\n" +
  8032. "%5 = OpTypeFunction %void\n" +
  8033. "%float = OpTypeFloat 32\n" +
  8034. "%v4float = OpTypeVector %float 4\n" +
  8035. "%_ptr_Output_v4float = OpTypePointer Output %v4float\n" +
  8036. "%3 = OpVariable %_ptr_Output_v4float Output\n" +
  8037. "%4 = OpVariable %_ptr_Output_v4float Output\n" +
  8038. "%int = OpTypeInt 32 1\n" +
  8039. "%int_0 = OpConstant %int 0\n" +
  8040. "%_ptr_PushConstant_v4float = OpTypePointer PushConstant %v4float\n" +
  8041. "%2 = OpFunction %void None %5\n" +
  8042. "%12 = OpLabel\n" +
  8043. "OpReturn\n" +
  8044. "OpFunctionEnd\n",
  8045. 9, true),
  8046. InstructionFoldingCase<bool>(std::string() +
  8047. "; CHECK: OpEntryPoint Fragment %2 \"main\" %4 %3\n" +
  8048. "OpCapability Shader\n" +
  8049. "%1 = OpExtInstImport \"GLSL.std.450\"\n" +
  8050. "OpMemoryModel Logical GLSL450\n" +
  8051. "OpEntryPoint Fragment %2 \"main\" %4 %4 %3\n" +
  8052. "OpExecutionMode %2 OriginUpperLeft\n" +
  8053. "OpSource GLSL 430\n" +
  8054. "OpDecorate %3 Location 0\n" +
  8055. "%void = OpTypeVoid\n" +
  8056. "%5 = OpTypeFunction %void\n" +
  8057. "%float = OpTypeFloat 32\n" +
  8058. "%v4float = OpTypeVector %float 4\n" +
  8059. "%_ptr_Output_v4float = OpTypePointer Output %v4float\n" +
  8060. "%3 = OpVariable %_ptr_Output_v4float Output\n" +
  8061. "%4 = OpVariable %_ptr_Output_v4float Output\n" +
  8062. "%int = OpTypeInt 32 1\n" +
  8063. "%int_0 = OpConstant %int 0\n" +
  8064. "%_ptr_PushConstant_v4float = OpTypePointer PushConstant %v4float\n" +
  8065. "%2 = OpFunction %void None %5\n" +
  8066. "%12 = OpLabel\n" +
  8067. "OpReturn\n" +
  8068. "OpFunctionEnd\n",
  8069. 9, true)
  8070. ));
  8071. using SPV14FoldingTest =
  8072. ::testing::TestWithParam<InstructionFoldingCase<bool>>;
  8073. TEST_P(SPV14FoldingTest, Case) {
  8074. const auto& tc = GetParam();
  8075. // Build module.
  8076. std::unique_ptr<IRContext> context =
  8077. BuildModule(SPV_ENV_UNIVERSAL_1_4, nullptr, tc.test_body,
  8078. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  8079. ASSERT_NE(nullptr, context);
  8080. // Fold the instruction to test.
  8081. analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
  8082. Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
  8083. std::unique_ptr<Instruction> original_inst(inst->Clone(context.get()));
  8084. bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
  8085. EXPECT_EQ(succeeded, tc.expected_result);
  8086. if (succeeded) {
  8087. Match(tc.test_body, context.get());
  8088. }
  8089. }
  8090. INSTANTIATE_TEST_SUITE_P(SPV14FoldingTest, SPV14FoldingTest,
  8091. ::testing::Values(
  8092. // Test case 0: select vectors with scalar condition.
  8093. InstructionFoldingCase<bool>(std::string() +
  8094. "; CHECK-NOT: OpSelect\n" +
  8095. "; CHECK: %3 = OpCopyObject {{%\\w+}} %1\n" +
  8096. "OpCapability Shader\n" +
  8097. "OpCapability Linkage\n" +
  8098. "%void = OpTypeVoid\n" +
  8099. "%bool = OpTypeBool\n" +
  8100. "%true = OpConstantTrue %bool\n" +
  8101. "%int = OpTypeInt 32 0\n" +
  8102. "%int4 = OpTypeVector %int 4\n" +
  8103. "%int_0 = OpConstant %int 0\n" +
  8104. "%int_1 = OpConstant %int 1\n" +
  8105. "%1 = OpUndef %int4\n" +
  8106. "%2 = OpUndef %int4\n" +
  8107. "%void_fn = OpTypeFunction %void\n" +
  8108. "%func = OpFunction %void None %void_fn\n" +
  8109. "%entry = OpLabel\n" +
  8110. "%3 = OpSelect %int4 %true %1 %2\n" +
  8111. "OpReturn\n" +
  8112. "OpFunctionEnd\n"
  8113. ,
  8114. 3, true),
  8115. // Test case 1: select struct with scalar condition.
  8116. InstructionFoldingCase<bool>(std::string() +
  8117. "; CHECK-NOT: OpSelect\n" +
  8118. "; CHECK: %3 = OpCopyObject {{%\\w+}} %2\n" +
  8119. "OpCapability Shader\n" +
  8120. "OpCapability Linkage\n" +
  8121. "%void = OpTypeVoid\n" +
  8122. "%bool = OpTypeBool\n" +
  8123. "%true = OpConstantFalse %bool\n" +
  8124. "%int = OpTypeInt 32 0\n" +
  8125. "%struct = OpTypeStruct %int %int %int %int\n" +
  8126. "%int_0 = OpConstant %int 0\n" +
  8127. "%int_1 = OpConstant %int 1\n" +
  8128. "%1 = OpUndef %struct\n" +
  8129. "%2 = OpUndef %struct\n" +
  8130. "%void_fn = OpTypeFunction %void\n" +
  8131. "%func = OpFunction %void None %void_fn\n" +
  8132. "%entry = OpLabel\n" +
  8133. "%3 = OpSelect %struct %true %1 %2\n" +
  8134. "OpReturn\n" +
  8135. "OpFunctionEnd\n"
  8136. ,
  8137. 3, true),
  8138. // Test case 1: select array with scalar condition.
  8139. InstructionFoldingCase<bool>(std::string() +
  8140. "; CHECK-NOT: OpSelect\n" +
  8141. "; CHECK: %3 = OpCopyObject {{%\\w+}} %2\n" +
  8142. "OpCapability Shader\n" +
  8143. "OpCapability Linkage\n" +
  8144. "%void = OpTypeVoid\n" +
  8145. "%bool = OpTypeBool\n" +
  8146. "%true = OpConstantFalse %bool\n" +
  8147. "%int = OpTypeInt 32 0\n" +
  8148. "%int_0 = OpConstant %int 0\n" +
  8149. "%int_1 = OpConstant %int 1\n" +
  8150. "%int_4 = OpConstant %int 4\n" +
  8151. "%array = OpTypeStruct %int %int %int %int\n" +
  8152. "%1 = OpUndef %array\n" +
  8153. "%2 = OpUndef %array\n" +
  8154. "%void_fn = OpTypeFunction %void\n" +
  8155. "%func = OpFunction %void None %void_fn\n" +
  8156. "%entry = OpLabel\n" +
  8157. "%3 = OpSelect %array %true %1 %2\n" +
  8158. "OpReturn\n" +
  8159. "OpFunctionEnd\n"
  8160. ,
  8161. 3, true)
  8162. ));
  8163. std::string FloatControlsHeader(const std::string& capabilities) {
  8164. std::string header = R"(
  8165. OpCapability Shader
  8166. )" + capabilities + R"(
  8167. %void = OpTypeVoid
  8168. %float = OpTypeFloat 32
  8169. %float_0 = OpConstant %float 0
  8170. %float_1 = OpConstant %float 1
  8171. %void_fn = OpTypeFunction %void
  8172. %func = OpFunction %void None %void_fn
  8173. %entry = OpLabel
  8174. )";
  8175. return header;
  8176. }
  8177. using FloatControlsFoldingTest =
  8178. ::testing::TestWithParam<InstructionFoldingCase<bool>>;
  8179. TEST_P(FloatControlsFoldingTest, Case) {
  8180. const auto& tc = GetParam();
  8181. // Build module.
  8182. std::unique_ptr<IRContext> context =
  8183. BuildModule(SPV_ENV_UNIVERSAL_1_4, nullptr, tc.test_body,
  8184. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  8185. ASSERT_NE(nullptr, context);
  8186. // Fold the instruction to test.
  8187. analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
  8188. Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
  8189. std::unique_ptr<Instruction> original_inst(inst->Clone(context.get()));
  8190. bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
  8191. EXPECT_EQ(succeeded, tc.expected_result);
  8192. if (succeeded) {
  8193. Match(tc.test_body, context.get());
  8194. }
  8195. }
  8196. INSTANTIATE_TEST_SUITE_P(FloatControlsFoldingTest, FloatControlsFoldingTest,
  8197. ::testing::Values(
  8198. // Test case 0: no folding with DenormPreserve
  8199. InstructionFoldingCase<bool>(FloatControlsHeader("OpCapability DenormPreserve") +
  8200. "%1 = OpFAdd %float %float_0 %float_1\n" +
  8201. "OpReturn\n" +
  8202. "OpFunctionEnd\n"
  8203. ,
  8204. 1, false),
  8205. // Test case 1: no folding with DenormFlushToZero
  8206. InstructionFoldingCase<bool>(FloatControlsHeader("OpCapability DenormFlushToZero") +
  8207. "%1 = OpFAdd %float %float_0 %float_1\n" +
  8208. "OpReturn\n" +
  8209. "OpFunctionEnd\n"
  8210. ,
  8211. 1, false),
  8212. // Test case 2: no folding with SignedZeroInfNanPreserve
  8213. InstructionFoldingCase<bool>(FloatControlsHeader("OpCapability SignedZeroInfNanPreserve") +
  8214. "%1 = OpFAdd %float %float_0 %float_1\n" +
  8215. "OpReturn\n" +
  8216. "OpFunctionEnd\n"
  8217. ,
  8218. 1, false),
  8219. // Test case 3: no folding with RoundingModeRTE
  8220. InstructionFoldingCase<bool>(FloatControlsHeader("OpCapability RoundingModeRTE") +
  8221. "%1 = OpFAdd %float %float_0 %float_1\n" +
  8222. "OpReturn\n" +
  8223. "OpFunctionEnd\n"
  8224. ,
  8225. 1, false),
  8226. // Test case 4: no folding with RoundingModeRTZ
  8227. InstructionFoldingCase<bool>(FloatControlsHeader("OpCapability RoundingModeRTZ") +
  8228. "%1 = OpFAdd %float %float_0 %float_1\n" +
  8229. "OpReturn\n" +
  8230. "OpFunctionEnd\n"
  8231. ,
  8232. 1, false)
  8233. ));
  8234. std::string ImageOperandsTestBody(const std::string& image_instruction) {
  8235. std::string body = R"(
  8236. OpCapability Shader
  8237. OpCapability ImageGatherExtended
  8238. OpMemoryModel Logical GLSL450
  8239. OpEntryPoint Fragment %main "main"
  8240. OpExecutionMode %main OriginUpperLeft
  8241. OpDecorate %Texture DescriptorSet 0
  8242. OpDecorate %Texture Binding 0
  8243. %int = OpTypeInt 32 1
  8244. %int_n1 = OpConstant %int -1
  8245. %5 = OpConstant %int 0
  8246. %float = OpTypeFloat 32
  8247. %float_0 = OpConstant %float 0
  8248. %type_2d_image = OpTypeImage %float 2D 2 0 0 1 Unknown
  8249. %type_sampled_image = OpTypeSampledImage %type_2d_image
  8250. %type_sampler = OpTypeSampler
  8251. %_ptr_UniformConstant_type_sampler = OpTypePointer UniformConstant %type_sampler
  8252. %_ptr_UniformConstant_type_2d_image = OpTypePointer UniformConstant %type_2d_image
  8253. %_ptr_int = OpTypePointer Function %int
  8254. %v2int = OpTypeVector %int 2
  8255. %10 = OpTypeVector %float 4
  8256. %void = OpTypeVoid
  8257. %22 = OpTypeFunction %void
  8258. %v2float = OpTypeVector %float 2
  8259. %v3int = OpTypeVector %int 3
  8260. %Texture = OpVariable %_ptr_UniformConstant_type_2d_image UniformConstant
  8261. %gSampler = OpVariable %_ptr_UniformConstant_type_sampler UniformConstant
  8262. %101 = OpConstantComposite %v2int %int_n1 %int_n1
  8263. %20 = OpConstantComposite %v2float %float_0 %float_0
  8264. %main = OpFunction %void None %22
  8265. %23 = OpLabel
  8266. %var = OpVariable %_ptr_int Function
  8267. %88 = OpLoad %type_2d_image %Texture
  8268. %val = OpLoad %int %var
  8269. %sampler = OpLoad %type_sampler %gSampler
  8270. %26 = OpSampledImage %type_sampled_image %88 %sampler
  8271. )" + image_instruction + R"(
  8272. OpReturn
  8273. OpFunctionEnd
  8274. )";
  8275. return body;
  8276. }
  8277. INSTANTIATE_TEST_SUITE_P(ImageOperandsBitmaskFoldingTest, MatchingInstructionWithNoResultFoldingTest,
  8278. ::testing::Values(
  8279. // Test case 0: OpImageFetch without Offset
  8280. InstructionFoldingCase<bool>(ImageOperandsTestBody(
  8281. "%89 = OpImageFetch %10 %88 %101 Lod %5 \n")
  8282. , 89, false),
  8283. // Test case 1: OpImageFetch with non-const offset
  8284. InstructionFoldingCase<bool>(ImageOperandsTestBody(
  8285. "%89 = OpImageFetch %10 %88 %101 Lod|Offset %5 %val \n")
  8286. , 89, false),
  8287. // Test case 2: OpImageFetch with Lod and Offset
  8288. InstructionFoldingCase<bool>(ImageOperandsTestBody(
  8289. " %89 = OpImageFetch %10 %88 %101 Lod|Offset %5 %101 \n"
  8290. "; CHECK: %89 = OpImageFetch %10 %88 %101 Lod|ConstOffset %5 %101 \n")
  8291. , 89, true),
  8292. // Test case 3: OpImageFetch with Bias and Offset
  8293. InstructionFoldingCase<bool>(ImageOperandsTestBody(
  8294. " %89 = OpImageFetch %10 %88 %101 Bias|Offset %5 %101 \n"
  8295. "; CHECK: %89 = OpImageFetch %10 %88 %101 Bias|ConstOffset %5 %101 \n")
  8296. , 89, true),
  8297. // Test case 4: OpImageFetch with Grad and Offset.
  8298. // Grad adds 2 operands to the instruction.
  8299. InstructionFoldingCase<bool>(ImageOperandsTestBody(
  8300. " %89 = OpImageFetch %10 %88 %101 Grad|Offset %5 %5 %101 \n"
  8301. "; CHECK: %89 = OpImageFetch %10 %88 %101 Grad|ConstOffset %5 %5 %101 \n")
  8302. , 89, true),
  8303. // Test case 5: OpImageFetch with Offset and MinLod.
  8304. // This is an example of a case where the bitmask bit-offset is larger than
  8305. // that of the Offset.
  8306. InstructionFoldingCase<bool>(ImageOperandsTestBody(
  8307. " %89 = OpImageFetch %10 %88 %101 Offset|MinLod %101 %5 \n"
  8308. "; CHECK: %89 = OpImageFetch %10 %88 %101 ConstOffset|MinLod %101 %5 \n")
  8309. , 89, true),
  8310. // Test case 6: OpImageGather with constant Offset
  8311. InstructionFoldingCase<bool>(ImageOperandsTestBody(
  8312. " %89 = OpImageGather %10 %26 %20 %5 Offset %101 \n"
  8313. "; CHECK: %89 = OpImageGather %10 %26 %20 %5 ConstOffset %101 \n")
  8314. , 89, true),
  8315. // Test case 7: OpImageWrite with constant Offset
  8316. InstructionFoldingCase<bool>(ImageOperandsTestBody(
  8317. " OpImageWrite %88 %5 %101 Offset %101 \n"
  8318. "; CHECK: OpImageWrite %88 %5 %101 ConstOffset %101 \n")
  8319. , 0 /* No result-id */, true)
  8320. ));
  8321. } // namespace
  8322. } // namespace opt
  8323. } // namespace spvtools