fold_test.cpp 377 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357
  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 <vector>
  18. #include "effcee/effcee.h"
  19. #include "gmock/gmock.h"
  20. #include "gtest/gtest.h"
  21. #include "source/opt/build_module.h"
  22. #include "source/opt/def_use_manager.h"
  23. #include "source/opt/ir_context.h"
  24. #include "source/opt/module.h"
  25. #include "spirv-tools/libspirv.hpp"
  26. namespace spvtools {
  27. namespace opt {
  28. namespace {
  29. using ::testing::Contains;
  30. std::string Disassemble(const std::string& original, IRContext* context,
  31. uint32_t disassemble_options = 0) {
  32. std::vector<uint32_t> optimized_bin;
  33. context->module()->ToBinary(&optimized_bin, true);
  34. spv_target_env target_env = SPV_ENV_UNIVERSAL_1_2;
  35. SpirvTools tools(target_env);
  36. std::string optimized_asm;
  37. EXPECT_TRUE(
  38. tools.Disassemble(optimized_bin, &optimized_asm, disassemble_options))
  39. << "Disassembling failed for shader:\n"
  40. << original << std::endl;
  41. return optimized_asm;
  42. }
  43. void Match(const std::string& original, IRContext* context,
  44. uint32_t disassemble_options = 0) {
  45. std::string disassembly = Disassemble(original, context, disassemble_options);
  46. auto match_result = effcee::Match(disassembly, original);
  47. EXPECT_EQ(effcee::Result::Status::Ok, match_result.status())
  48. << match_result.message() << "\nChecking result:\n"
  49. << disassembly;
  50. }
  51. template <class ResultType>
  52. struct InstructionFoldingCase {
  53. InstructionFoldingCase(const std::string& tb, uint32_t id, ResultType result)
  54. : test_body(tb), id_to_fold(id), expected_result(result) {}
  55. std::string test_body;
  56. uint32_t id_to_fold;
  57. ResultType expected_result;
  58. };
  59. std::tuple<std::unique_ptr<IRContext>, Instruction*> GetInstructionToFold(
  60. const std::string test_body, const uint32_t id_to_fold,
  61. spv_target_env spv_env) {
  62. // Build module.
  63. std::unique_ptr<IRContext> context =
  64. BuildModule(spv_env, nullptr, test_body,
  65. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  66. EXPECT_NE(nullptr, context);
  67. if (context == nullptr) {
  68. return {nullptr, nullptr};
  69. }
  70. // Fold the instruction to test.
  71. if (id_to_fold != 0) {
  72. analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
  73. Instruction* inst = def_use_mgr->GetDef(id_to_fold);
  74. return {std::move(context), inst};
  75. }
  76. // If there is not ID, we get the instruction just before a terminator
  77. // instruction. That could be a return or abort. This is used for cases where
  78. // the instruction we want to fold does not have a result id.
  79. Function* func = &*context->module()->begin();
  80. for (auto& bb : *func) {
  81. Instruction* terminator = bb.terminator();
  82. if (terminator->IsReturnOrAbort()) {
  83. return {std::move(context), terminator->PreviousNode()};
  84. }
  85. }
  86. return {nullptr, nullptr};
  87. }
  88. std::tuple<std::unique_ptr<IRContext>, Instruction*> FoldInstruction(
  89. const std::string test_body, const uint32_t id_to_fold,
  90. spv_target_env spv_env) {
  91. // Build module.
  92. std::unique_ptr<IRContext> context;
  93. Instruction* inst = nullptr;
  94. std::tie(context, inst) =
  95. GetInstructionToFold(test_body, id_to_fold, spv_env);
  96. if (context == nullptr) {
  97. return {nullptr, nullptr};
  98. }
  99. std::unique_ptr<Instruction> original_inst(inst->Clone(context.get()));
  100. bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
  101. EXPECT_EQ(inst->result_id(), original_inst->result_id());
  102. EXPECT_EQ(inst->type_id(), original_inst->type_id());
  103. if (!succeeded && inst != nullptr) {
  104. EXPECT_EQ(inst->NumInOperands(), original_inst->NumInOperands());
  105. for (uint32_t i = 0; i < inst->NumInOperands(); ++i) {
  106. EXPECT_EQ(inst->GetOperand(i), original_inst->GetOperand(i));
  107. }
  108. }
  109. return {std::move(context), succeeded ? inst : nullptr};
  110. }
  111. template <class ElementType, class Function>
  112. void CheckForExpectedScalarConstant(Instruction* inst,
  113. ElementType expected_result,
  114. Function GetValue) {
  115. ASSERT_TRUE(inst);
  116. IRContext* context = inst->context();
  117. analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
  118. while (inst->opcode() == spv::Op::OpCopyObject) {
  119. inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
  120. }
  121. // Make sure we have a constant.
  122. analysis::ConstantManager* const_mrg = context->get_constant_mgr();
  123. const analysis::Constant* constant = const_mrg->GetConstantFromInst(inst);
  124. ASSERT_TRUE(constant);
  125. // Make sure the constant is a scalar.
  126. const analysis::ScalarConstant* result = constant->AsScalarConstant();
  127. ASSERT_TRUE(result);
  128. // Check if the result matches the expected value.
  129. // If ExpectedType is not a float type, it should cast the value to a double
  130. // and never get a nan.
  131. if (!std::isnan(static_cast<double>(expected_result))) {
  132. EXPECT_EQ(expected_result, GetValue(result));
  133. } else {
  134. EXPECT_TRUE(std::isnan(static_cast<double>(GetValue(result))));
  135. }
  136. }
  137. template <class ElementType, class Function>
  138. void CheckForExpectedVectorConstant(Instruction* inst,
  139. std::vector<ElementType> expected_result,
  140. Function GetValue) {
  141. ASSERT_TRUE(inst);
  142. IRContext* context = inst->context();
  143. EXPECT_EQ(inst->opcode(), spv::Op::OpCopyObject);
  144. analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
  145. inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
  146. std::vector<spv::Op> opcodes = {spv::Op::OpConstantComposite};
  147. EXPECT_THAT(opcodes, Contains(inst->opcode()));
  148. analysis::ConstantManager* const_mrg = context->get_constant_mgr();
  149. const analysis::Constant* result = const_mrg->GetConstantFromInst(inst);
  150. EXPECT_NE(result, nullptr);
  151. if (result != nullptr) {
  152. const std::vector<const analysis::Constant*>& componenets =
  153. result->AsVectorConstant()->GetComponents();
  154. EXPECT_EQ(componenets.size(), expected_result.size());
  155. for (size_t i = 0; i < componenets.size(); i++) {
  156. EXPECT_EQ(expected_result[i], GetValue(componenets[i]));
  157. }
  158. }
  159. }
  160. using IntegerInstructionFoldingTest =
  161. ::testing::TestWithParam<InstructionFoldingCase<uint32_t>>;
  162. TEST_P(IntegerInstructionFoldingTest, Case) {
  163. const auto& tc = GetParam();
  164. std::unique_ptr<IRContext> context;
  165. Instruction* inst;
  166. std::tie(context, inst) =
  167. FoldInstruction(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_1);
  168. CheckForExpectedScalarConstant(
  169. inst, tc.expected_result, [](const analysis::Constant* c) {
  170. return c->AsScalarConstant()->GetU32BitValue();
  171. });
  172. }
  173. // Returns a common SPIR-V header for all of the test that follow.
  174. #define INT_0_ID 100
  175. #define TRUE_ID 101
  176. #define VEC2_0_ID 102
  177. #define INT_7_ID 103
  178. #define FLOAT_0_ID 104
  179. #define DOUBLE_0_ID 105
  180. #define VEC4_0_ID 106
  181. #define DVEC4_0_ID 106
  182. #define HALF_0_ID 108
  183. #define UINT_0_ID 109
  184. #define INT_NULL_ID 110
  185. #define UINT_NULL_ID 111
  186. const std::string& Header() {
  187. static const std::string header = R"(OpCapability Shader
  188. OpCapability Float16
  189. OpCapability Float64
  190. OpCapability Int8
  191. OpCapability Int16
  192. OpCapability Int64
  193. OpCapability CooperativeMatrixKHR
  194. OpExtension "SPV_KHR_cooperative_matrix"
  195. %1 = OpExtInstImport "GLSL.std.450"
  196. OpMemoryModel Logical GLSL450
  197. OpEntryPoint Fragment %main "main"
  198. OpExecutionMode %main OriginUpperLeft
  199. OpSource GLSL 140
  200. OpName %main "main"
  201. %void = OpTypeVoid
  202. %void_func = OpTypeFunction %void
  203. %bool = OpTypeBool
  204. %float = OpTypeFloat 32
  205. %double = OpTypeFloat 64
  206. %half = OpTypeFloat 16
  207. %101 = OpConstantTrue %bool ; Need a def with an numerical id to define id maps.
  208. %true = OpConstantTrue %bool
  209. %false = OpConstantFalse %bool
  210. %bool_null = OpConstantNull %bool
  211. %short = OpTypeInt 16 1
  212. %ushort = OpTypeInt 16 0
  213. %byte = OpTypeInt 8 1
  214. %ubyte = OpTypeInt 8 0
  215. %int = OpTypeInt 32 1
  216. %long = OpTypeInt 64 1
  217. %uint = OpTypeInt 32 0
  218. %ulong = OpTypeInt 64 0
  219. %v2int = OpTypeVector %int 2
  220. %v4int = OpTypeVector %int 4
  221. %v2short = OpTypeVector %short 2
  222. %v2long = OpTypeVector %long 2
  223. %v4long = OpTypeVector %long 4
  224. %v4float = OpTypeVector %float 4
  225. %v4double = OpTypeVector %double 4
  226. %v2uint = OpTypeVector %uint 2
  227. %v2ulong = OpTypeVector %ulong 2
  228. %v2float = OpTypeVector %float 2
  229. %v2double = OpTypeVector %double 2
  230. %v2half = OpTypeVector %half 2
  231. %v2bool = OpTypeVector %bool 2
  232. %m2x2int = OpTypeMatrix %v2int 2
  233. %mat4v2float = OpTypeMatrix %v2float 4
  234. %mat2v4float = OpTypeMatrix %v4float 2
  235. %mat4v4float = OpTypeMatrix %v4float 4
  236. %mat4v4double = OpTypeMatrix %v4double 4
  237. %struct_v2int_int_int = OpTypeStruct %v2int %int %int
  238. %_ptr_int = OpTypePointer Function %int
  239. %_ptr_uint = OpTypePointer Function %uint
  240. %_ptr_bool = OpTypePointer Function %bool
  241. %_ptr_float = OpTypePointer Function %float
  242. %_ptr_double = OpTypePointer Function %double
  243. %_ptr_half = OpTypePointer Function %half
  244. %_ptr_long = OpTypePointer Function %long
  245. %_ptr_ulong = OpTypePointer Function %ulong
  246. %_ptr_v2int = OpTypePointer Function %v2int
  247. %_ptr_v4int = OpTypePointer Function %v4int
  248. %_ptr_v4float = OpTypePointer Function %v4float
  249. %_ptr_v4double = OpTypePointer Function %v4double
  250. %_ptr_struct_v2int_int_int = OpTypePointer Function %struct_v2int_int_int
  251. %_ptr_v2float = OpTypePointer Function %v2float
  252. %_ptr_v2double = OpTypePointer Function %v2double
  253. %int_2 = OpConstant %int 2
  254. %int_arr_2 = OpTypeArray %int %int_2
  255. %short_0 = OpConstant %short 0
  256. %short_2 = OpConstant %short 2
  257. %short_3 = OpConstant %short 3
  258. %short_n5 = OpConstant %short -5
  259. %ubyte_1 = OpConstant %ubyte 1
  260. %byte_n1 = OpConstant %byte -1
  261. %100 = OpConstant %int 0 ; Need a def with an numerical id to define id maps.
  262. %110 = OpConstantNull %int ; Need a def with an numerical id to define id maps.
  263. %103 = OpConstant %int 7 ; Need a def with an numerical id to define id maps.
  264. %int_0 = OpConstant %int 0
  265. %int_1 = OpConstant %int 1
  266. %int_3 = OpConstant %int 3
  267. %int_4 = OpConstant %int 4
  268. %int_10 = OpConstant %int 10
  269. %int_1073741824 = OpConstant %int 1073741824
  270. %int_n1 = OpConstant %int -1
  271. %int_n24 = OpConstant %int -24
  272. %int_n858993459 = OpConstant %int -858993459
  273. %int_min = OpConstant %int -2147483648
  274. %int_max = OpConstant %int 2147483647
  275. %long_0 = OpConstant %long 0
  276. %long_1 = OpConstant %long 1
  277. %long_2 = OpConstant %long 2
  278. %long_3 = OpConstant %long 3
  279. %long_n3 = OpConstant %long -3
  280. %long_7 = OpConstant %long 7
  281. %long_n7 = OpConstant %long -7
  282. %long_10 = OpConstant %long 10
  283. %long_32768 = OpConstant %long 32768
  284. %long_n57344 = OpConstant %long -57344
  285. %long_n4611686018427387904 = OpConstant %long -4611686018427387904
  286. %long_4611686018427387904 = OpConstant %long 4611686018427387904
  287. %long_n1 = OpConstant %long -1
  288. %long_n3689348814741910323 = OpConstant %long -3689348814741910323
  289. %long_min = OpConstant %long -9223372036854775808
  290. %long_max = OpConstant %long 9223372036854775807
  291. %ulong_7 = OpConstant %ulong 7
  292. %ulong_4611686018427387904 = OpConstant %ulong 4611686018427387904
  293. %109 = OpConstant %uint 0 ; Need a def with an numerical id to define id maps.
  294. %111 = OpConstantNull %uint ; Need a def with an numerical id to define id maps.
  295. %uint_0 = OpConstant %uint 0
  296. %uint_1 = OpConstant %uint 1
  297. %uint_2 = OpConstant %uint 2
  298. %uint_3 = OpConstant %uint 3
  299. %uint_4 = OpConstant %uint 4
  300. %uint_32 = OpConstant %uint 32
  301. %uint_42 = OpConstant %uint 42
  302. %uint_2147483649 = OpConstant %uint 2147483649
  303. %uint_max = OpConstant %uint 4294967295
  304. %ulong_0 = OpConstant %ulong 0
  305. %ulong_1 = OpConstant %ulong 1
  306. %ulong_2 = OpConstant %ulong 2
  307. %ulong_9223372036854775809 = OpConstant %ulong 9223372036854775809
  308. %ulong_max = OpConstant %ulong 18446744073709551615
  309. %v2int_undef = OpUndef %v2int
  310. %v2int_0_0 = OpConstantComposite %v2int %int_0 %int_0
  311. %v2int_1_0 = OpConstantComposite %v2int %int_1 %int_0
  312. %v2int_2_2 = OpConstantComposite %v2int %int_2 %int_2
  313. %v2int_2_3 = OpConstantComposite %v2int %int_2 %int_3
  314. %v2int_3_2 = OpConstantComposite %v2int %int_3 %int_2
  315. %v2int_n1_n24 = OpConstantComposite %v2int %int_n1 %int_n24
  316. %v2int_4_4 = OpConstantComposite %v2int %int_4 %int_4
  317. %v2int_min_max = OpConstantComposite %v2int %int_min %int_max
  318. %v2short_2_n5 = OpConstantComposite %v2short %short_2 %short_n5
  319. %v2long_2_2 = OpConstantComposite %v2long %long_2 %long_2
  320. %v2long_2_3 = OpConstantComposite %v2long %long_2 %long_3
  321. %v2bool_null = OpConstantNull %v2bool
  322. %v2bool_true_false = OpConstantComposite %v2bool %true %false
  323. %v2bool_false_true = OpConstantComposite %v2bool %false %true
  324. %struct_v2int_int_int_null = OpConstantNull %struct_v2int_int_int
  325. %v2int_null = OpConstantNull %v2int
  326. %102 = OpConstantComposite %v2int %103 %103
  327. %v4int_undef = OpUndef %v4int
  328. %v4int_0_0_0_0 = OpConstantComposite %v4int %int_0 %int_0 %int_0 %int_0
  329. %m2x2int_undef = OpUndef %m2x2int
  330. %struct_undef_0_0 = OpConstantComposite %struct_v2int_int_int %v2int_undef %int_0 %int_0
  331. %float_n1 = OpConstant %float -1
  332. %104 = OpConstant %float 0 ; Need a def with an numerical id to define id maps.
  333. %float_null = OpConstantNull %float
  334. %float_0 = OpConstant %float 0
  335. %float_n0 = OpConstant %float -0.0
  336. %float_1 = OpConstant %float 1
  337. %float_2 = OpConstant %float 2
  338. %float_3 = OpConstant %float 3
  339. %float_4 = OpConstant %float 4
  340. %float_2049 = OpConstant %float 2049
  341. %float_n2049 = OpConstant %float -2049
  342. %float_0p5 = OpConstant %float 0.5
  343. %float_0p2 = OpConstant %float 0.2
  344. %float_pi = OpConstant %float 1.5555
  345. %float_1e16 = OpConstant %float 1e16
  346. %float_n1e16 = OpConstant %float -1e16
  347. %float_1en16 = OpConstant %float 1e-16
  348. %float_n1en16 = OpConstant %float -1e-16
  349. %v2float_0_0 = OpConstantComposite %v2float %float_0 %float_0
  350. %v2float_2_2 = OpConstantComposite %v2float %float_2 %float_2
  351. %v2float_2_3 = OpConstantComposite %v2float %float_2 %float_3
  352. %v2float_3_2 = OpConstantComposite %v2float %float_3 %float_2
  353. %v2float_4_4 = OpConstantComposite %v2float %float_4 %float_4
  354. %v2float_2_0p5 = OpConstantComposite %v2float %float_2 %float_0p5
  355. %v2float_0p2_0p5 = OpConstantComposite %v2float %float_0p2 %float_0p5
  356. %v2float_null = OpConstantNull %v2float
  357. %double_n1 = OpConstant %double -1
  358. %105 = OpConstant %double 0 ; Need a def with an numerical id to define id maps.
  359. %double_null = OpConstantNull %double
  360. %double_0 = OpConstant %double 0
  361. %double_n0 = OpConstant %double -0.0
  362. %double_1 = OpConstant %double 1
  363. %double_2 = OpConstant %double 2
  364. %double_3 = OpConstant %double 3
  365. %double_4 = OpConstant %double 4
  366. %double_5 = OpConstant %double 5
  367. %double_0p5 = OpConstant %double 0.5
  368. %double_0p2 = OpConstant %double 0.2
  369. %v2double_0_0 = OpConstantComposite %v2double %double_0 %double_0
  370. %v2double_2_2 = OpConstantComposite %v2double %double_2 %double_2
  371. %v2double_2_3 = OpConstantComposite %v2double %double_2 %double_3
  372. %v2double_3_2 = OpConstantComposite %v2double %double_3 %double_2
  373. %v2double_4_4 = OpConstantComposite %v2double %double_4 %double_4
  374. %v2double_2_0p5 = OpConstantComposite %v2double %double_2 %double_0p5
  375. %v2double_null = OpConstantNull %v2double
  376. %108 = OpConstant %half 0
  377. %half_1 = OpConstant %half 1
  378. %half_2 = OpConstant %half 2
  379. %half_0_1 = OpConstantComposite %v2half %108 %half_1
  380. %106 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
  381. %v4float_0_0_0_0 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
  382. %v4float_0_0_0_1 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_1
  383. %v4float_0_1_0_0 = OpConstantComposite %v4float %float_0 %float_1 %float_null %float_0
  384. %v4float_1_1_1_1 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
  385. %v4float_1_2_3_4 = OpConstantComposite %v4float %float_1 %float_2 %float_3 %float_4
  386. %v4float_null = OpConstantNull %v4float
  387. %mat2v4float_null = OpConstantNull %mat2v4float
  388. %mat4v4float_null = OpConstantNull %mat4v4float
  389. %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
  390. %mat4v4float_1_2_3_4_null = OpConstantComposite %mat4v4float %v4float_1_2_3_4 %v4float_null %v4float_1_2_3_4 %v4float_null
  391. %107 = OpConstantComposite %v4double %double_0 %double_0 %double_0 %double_0
  392. %v4double_0_0_0_0 = OpConstantComposite %v4double %double_0 %double_0 %double_0 %double_0
  393. %v4double_0_0_0_1 = OpConstantComposite %v4double %double_0 %double_0 %double_0 %double_1
  394. %v4double_0_1_0_0 = OpConstantComposite %v4double %double_0 %double_1 %double_null %double_0
  395. %v4double_1_1_1_1 = OpConstantComposite %v4double %double_1 %double_1 %double_1 %double_1
  396. %v4double_1_2_3_4 = OpConstantComposite %v4double %double_1 %double_2 %double_3 %double_4
  397. %v4double_1_1_1_0p5 = OpConstantComposite %v4double %double_1 %double_1 %double_1 %double_0p5
  398. %v4double_null = OpConstantNull %v4double
  399. %mat4v4double_null = OpConstantNull %mat4v4double
  400. %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
  401. %mat4v4double_1_2_3_4_null = OpConstantComposite %mat4v4double %v4double_1_2_3_4 %v4double_null %v4double_1_2_3_4 %v4double_null
  402. %v4float_n1_2_1_3 = OpConstantComposite %v4float %float_n1 %float_2 %float_1 %float_3
  403. %uint_0x3f800000 = OpConstant %uint 0x3f800000
  404. %uint_0xbf800000 = OpConstant %uint 0xbf800000
  405. %v2uint_0x3f800000_0xbf800000 = OpConstantComposite %v2uint %uint_0x3f800000 %uint_0xbf800000
  406. %long_0xbf8000003f800000 = OpConstant %long 0xbf8000003f800000
  407. %int_0x3FF00000 = OpConstant %int 0x3FF00000
  408. %int_0x00000000 = OpConstant %int 0x00000000
  409. %int_0xC05FD666 = OpConstant %int 0xC05FD666
  410. %int_0x66666666 = OpConstant %int 0x66666666
  411. %v4int_0x3FF00000_0x00000000_0xC05FD666_0x66666666 = OpConstantComposite %v4int %int_0x00000000 %int_0x3FF00000 %int_0x66666666 %int_0xC05FD666
  412. %ushort_0x4400 = OpConstant %ushort 0x4400
  413. %short_0x4400 = OpConstant %short 0x4400
  414. %ushort_0xBC00 = OpConstant %ushort 0xBC00
  415. %short_0xBC00 = OpConstant %short 0xBC00
  416. %int_arr_2_undef = OpUndef %int_arr_2
  417. %int_coop_matrix = OpTypeCooperativeMatrixKHR %int %uint_3 %uint_3 %uint_32 %uint_0
  418. %undef_int_coop_matrix = OpUndef %int_coop_matrix
  419. %uint_coop_matrix = OpTypeCooperativeMatrixKHR %uint %uint_3 %uint_3 %uint_32 %uint_0
  420. %undef_uint_coop_matrix = OpUndef %uint_coop_matrix
  421. %float_coop_matrix = OpTypeCooperativeMatrixKHR %float %uint_3 %uint_3 %uint_32 %uint_0
  422. %undef_float_coop_matrix = OpUndef %float_coop_matrix
  423. )";
  424. return header;
  425. }
  426. // Returns the header with definitions of float NaN and double NaN. Since FC
  427. // "; CHECK: [[double_n0:%\\w+]] = OpConstant [[double]] -0\n" finds
  428. // %double_nan = OpConstant %double -0x1.8p+1024 instead of
  429. // %double_n0 = OpConstant %double -0,
  430. // we separates those definitions from Header().
  431. const std::string& HeaderWithNaN() {
  432. static const std::string headerWithNaN =
  433. Header() +
  434. R"(%float_nan = OpConstant %float -0x1.8p+128
  435. %double_nan = OpConstant %double -0x1.8p+1024
  436. )";
  437. return headerWithNaN;
  438. }
  439. // clang-format off
  440. INSTANTIATE_TEST_SUITE_P(TestCase, IntegerInstructionFoldingTest,
  441. ::testing::Values(
  442. // Test case 0: fold 0*n
  443. InstructionFoldingCase<uint32_t>(
  444. Header() + "%main = OpFunction %void None %void_func\n" +
  445. "%main_lab = OpLabel\n" +
  446. "%n = OpVariable %_ptr_int Function\n" +
  447. "%load = OpLoad %int %n\n" +
  448. "%2 = OpIMul %int %int_0 %load\n" +
  449. "OpReturn\n" +
  450. "OpFunctionEnd",
  451. 2, 0),
  452. // Test case 1: fold n*0
  453. InstructionFoldingCase<uint32_t>(
  454. Header() + "%main = OpFunction %void None %void_func\n" +
  455. "%main_lab = OpLabel\n" +
  456. "%n = OpVariable %_ptr_int Function\n" +
  457. "%load = OpLoad %int %n\n" +
  458. "%2 = OpIMul %int %load %int_0\n" +
  459. "OpReturn\n" +
  460. "OpFunctionEnd",
  461. 2, 0),
  462. // Test case 2: fold 0/n (signed)
  463. InstructionFoldingCase<uint32_t>(
  464. Header() + "%main = OpFunction %void None %void_func\n" +
  465. "%main_lab = OpLabel\n" +
  466. "%n = OpVariable %_ptr_int Function\n" +
  467. "%load = OpLoad %int %n\n" +
  468. "%2 = OpSDiv %int %int_0 %load\n" +
  469. "OpReturn\n" +
  470. "OpFunctionEnd",
  471. 2, 0),
  472. // Test case 3: fold n/0 (signed)
  473. InstructionFoldingCase<uint32_t>(
  474. Header() + "%main = OpFunction %void None %void_func\n" +
  475. "%main_lab = OpLabel\n" +
  476. "%n = OpVariable %_ptr_int Function\n" +
  477. "%load = OpLoad %int %n\n" +
  478. "%2 = OpSDiv %int %load %int_0\n" +
  479. "OpReturn\n" +
  480. "OpFunctionEnd",
  481. 2, 0),
  482. // Test case 4: fold 0/n (unsigned)
  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 = OpUDiv %uint %uint_0 %load\n" +
  489. "OpReturn\n" +
  490. "OpFunctionEnd",
  491. 2, 0),
  492. // Test case 5: fold n/0 (unsigned)
  493. InstructionFoldingCase<uint32_t>(
  494. Header() + "%main = OpFunction %void None %void_func\n" +
  495. "%main_lab = OpLabel\n" +
  496. "%n = OpVariable %_ptr_int Function\n" +
  497. "%load = OpLoad %int %n\n" +
  498. "%2 = OpSDiv %int %load %int_0\n" +
  499. "OpReturn\n" +
  500. "OpFunctionEnd",
  501. 2, 0),
  502. // Test case 6: fold 0 remainder n
  503. InstructionFoldingCase<uint32_t>(
  504. Header() + "%main = OpFunction %void None %void_func\n" +
  505. "%main_lab = OpLabel\n" +
  506. "%n = OpVariable %_ptr_int Function\n" +
  507. "%load = OpLoad %int %n\n" +
  508. "%2 = OpSRem %int %int_0 %load\n" +
  509. "OpReturn\n" +
  510. "OpFunctionEnd",
  511. 2, 0),
  512. // Test case 7: fold n remainder 0
  513. InstructionFoldingCase<uint32_t>(
  514. Header() + "%main = OpFunction %void None %void_func\n" +
  515. "%main_lab = OpLabel\n" +
  516. "%n = OpVariable %_ptr_int Function\n" +
  517. "%load = OpLoad %int %n\n" +
  518. "%2 = OpSRem %int %load %int_0\n" +
  519. "OpReturn\n" +
  520. "OpFunctionEnd",
  521. 2, 0),
  522. // Test case 8: fold 0%n (signed)
  523. InstructionFoldingCase<uint32_t>(
  524. Header() + "%main = OpFunction %void None %void_func\n" +
  525. "%main_lab = OpLabel\n" +
  526. "%n = OpVariable %_ptr_int Function\n" +
  527. "%load = OpLoad %int %n\n" +
  528. "%2 = OpSMod %int %int_0 %load\n" +
  529. "OpReturn\n" +
  530. "OpFunctionEnd",
  531. 2, 0),
  532. // Test case 9: fold n%0 (signed)
  533. InstructionFoldingCase<uint32_t>(
  534. Header() + "%main = OpFunction %void None %void_func\n" +
  535. "%main_lab = OpLabel\n" +
  536. "%n = OpVariable %_ptr_int Function\n" +
  537. "%load = OpLoad %int %n\n" +
  538. "%2 = OpSMod %int %load %int_0\n" +
  539. "OpReturn\n" +
  540. "OpFunctionEnd",
  541. 2, 0),
  542. // Test case 10: fold 0%n (unsigned)
  543. InstructionFoldingCase<uint32_t>(
  544. Header() + "%main = OpFunction %void None %void_func\n" +
  545. "%main_lab = OpLabel\n" +
  546. "%n = OpVariable %_ptr_uint Function\n" +
  547. "%load = OpLoad %uint %n\n" +
  548. "%2 = OpUMod %uint %uint_0 %load\n" +
  549. "OpReturn\n" +
  550. "OpFunctionEnd",
  551. 2, 0),
  552. // Test case 11: fold n%0 (unsigned)
  553. InstructionFoldingCase<uint32_t>(
  554. Header() + "%main = OpFunction %void None %void_func\n" +
  555. "%main_lab = OpLabel\n" +
  556. "%n = OpVariable %_ptr_uint Function\n" +
  557. "%load = OpLoad %uint %n\n" +
  558. "%2 = OpUMod %uint %load %uint_0\n" +
  559. "OpReturn\n" +
  560. "OpFunctionEnd",
  561. 2, 0),
  562. // Test case 12: fold n << 32
  563. InstructionFoldingCase<uint32_t>(
  564. Header() + "%main = OpFunction %void None %void_func\n" +
  565. "%main_lab = OpLabel\n" +
  566. "%n = OpVariable %_ptr_uint Function\n" +
  567. "%load = OpLoad %uint %n\n" +
  568. "%2 = OpShiftLeftLogical %uint %load %uint_32\n" +
  569. "OpReturn\n" +
  570. "OpFunctionEnd",
  571. 2, 0),
  572. // Test case 13: fold n >> 32
  573. InstructionFoldingCase<uint32_t>(
  574. Header() + "%main = OpFunction %void None %void_func\n" +
  575. "%main_lab = OpLabel\n" +
  576. "%n = OpVariable %_ptr_uint Function\n" +
  577. "%load = OpLoad %uint %n\n" +
  578. "%2 = OpShiftRightLogical %uint %load %uint_32\n" +
  579. "OpReturn\n" +
  580. "OpFunctionEnd",
  581. 2, 0),
  582. // Test case 14: fold n | 0xFFFFFFFF
  583. InstructionFoldingCase<uint32_t>(
  584. Header() + "%main = OpFunction %void None %void_func\n" +
  585. "%main_lab = OpLabel\n" +
  586. "%n = OpVariable %_ptr_uint Function\n" +
  587. "%load = OpLoad %uint %n\n" +
  588. "%2 = OpBitwiseOr %uint %load %uint_max\n" +
  589. "OpReturn\n" +
  590. "OpFunctionEnd",
  591. 2, 0xFFFFFFFF),
  592. // Test case 15: fold 0xFFFFFFFF | n
  593. InstructionFoldingCase<uint32_t>(
  594. Header() + "%main = OpFunction %void None %void_func\n" +
  595. "%main_lab = OpLabel\n" +
  596. "%n = OpVariable %_ptr_uint Function\n" +
  597. "%load = OpLoad %uint %n\n" +
  598. "%2 = OpBitwiseOr %uint %uint_max %load\n" +
  599. "OpReturn\n" +
  600. "OpFunctionEnd",
  601. 2, 0xFFFFFFFF),
  602. // Test case 16: fold n & 0
  603. InstructionFoldingCase<uint32_t>(
  604. Header() + "%main = OpFunction %void None %void_func\n" +
  605. "%main_lab = OpLabel\n" +
  606. "%n = OpVariable %_ptr_uint Function\n" +
  607. "%load = OpLoad %uint %n\n" +
  608. "%2 = OpBitwiseAnd %uint %load %uint_0\n" +
  609. "OpReturn\n" +
  610. "OpFunctionEnd",
  611. 2, 0),
  612. // Test case 17: fold 1/0 (signed)
  613. InstructionFoldingCase<uint32_t>(
  614. Header() + "%main = OpFunction %void None %void_func\n" +
  615. "%main_lab = OpLabel\n" +
  616. "%2 = OpSDiv %int %int_1 %int_0\n" +
  617. "OpReturn\n" +
  618. "OpFunctionEnd",
  619. 2, 0),
  620. // Test case 18: fold 1/0 (unsigned)
  621. InstructionFoldingCase<uint32_t>(
  622. Header() + "%main = OpFunction %void None %void_func\n" +
  623. "%main_lab = OpLabel\n" +
  624. "%2 = OpUDiv %uint %uint_1 %uint_0\n" +
  625. "OpReturn\n" +
  626. "OpFunctionEnd",
  627. 2, 0),
  628. // Test case 19: fold OpSRem 1 0 (signed)
  629. InstructionFoldingCase<uint32_t>(
  630. Header() + "%main = OpFunction %void None %void_func\n" +
  631. "%main_lab = OpLabel\n" +
  632. "%2 = OpSRem %int %int_1 %int_0\n" +
  633. "OpReturn\n" +
  634. "OpFunctionEnd",
  635. 2, 0),
  636. // Test case 20: fold 1%0 (signed)
  637. InstructionFoldingCase<uint32_t>(
  638. Header() + "%main = OpFunction %void None %void_func\n" +
  639. "%main_lab = OpLabel\n" +
  640. "%2 = OpSMod %int %int_1 %int_0\n" +
  641. "OpReturn\n" +
  642. "OpFunctionEnd",
  643. 2, 0),
  644. // Test case 21: fold 1%0 (unsigned)
  645. InstructionFoldingCase<uint32_t>(
  646. Header() + "%main = OpFunction %void None %void_func\n" +
  647. "%main_lab = OpLabel\n" +
  648. "%2 = OpUMod %uint %uint_1 %uint_0\n" +
  649. "OpReturn\n" +
  650. "OpFunctionEnd",
  651. 2, 0),
  652. // Test case 22: fold unsigned n >> 42 (undefined, so set to zero).
  653. InstructionFoldingCase<uint32_t>(
  654. Header() + "%main = OpFunction %void None %void_func\n" +
  655. "%main_lab = OpLabel\n" +
  656. "%n = OpVariable %_ptr_uint Function\n" +
  657. "%load = OpLoad %uint %n\n" +
  658. "%2 = OpShiftRightLogical %uint %load %uint_42\n" +
  659. "OpReturn\n" +
  660. "OpFunctionEnd",
  661. 2, 0),
  662. // Test case 23: fold signed n >> 42 (undefined, so set to zero).
  663. InstructionFoldingCase<uint32_t>(
  664. Header() + "%main = OpFunction %void None %void_func\n" +
  665. "%main_lab = OpLabel\n" +
  666. "%n = OpVariable %_ptr_int Function\n" +
  667. "%load = OpLoad %int %n\n" +
  668. "%2 = OpShiftRightLogical %int %load %uint_42\n" +
  669. "OpReturn\n" +
  670. "OpFunctionEnd",
  671. 2, 0),
  672. // Test case 24: fold n << 42 (undefined, so set to zero).
  673. InstructionFoldingCase<uint32_t>(
  674. Header() + "%main = OpFunction %void None %void_func\n" +
  675. "%main_lab = OpLabel\n" +
  676. "%n = OpVariable %_ptr_int Function\n" +
  677. "%load = OpLoad %int %n\n" +
  678. "%2 = OpShiftLeftLogical %int %load %uint_42\n" +
  679. "OpReturn\n" +
  680. "OpFunctionEnd",
  681. 2, 0),
  682. // Test case 25: fold -24 >> 32 (defined as -1)
  683. InstructionFoldingCase<uint32_t>(
  684. Header() + "%main = OpFunction %void None %void_func\n" +
  685. "%main_lab = OpLabel\n" +
  686. "%2 = OpShiftRightArithmetic %int %int_n24 %uint_32\n" +
  687. "OpReturn\n" +
  688. "OpFunctionEnd",
  689. 2, -1),
  690. // Test case 26: fold 2 >> 32 (signed)
  691. InstructionFoldingCase<uint32_t>(
  692. Header() + "%main = OpFunction %void None %void_func\n" +
  693. "%main_lab = OpLabel\n" +
  694. "%2 = OpShiftRightArithmetic %int %int_2 %uint_32\n" +
  695. "OpReturn\n" +
  696. "OpFunctionEnd",
  697. 2, 0),
  698. // Test case 27: fold 2 >> 32 (unsigned)
  699. InstructionFoldingCase<uint32_t>(
  700. Header() + "%main = OpFunction %void None %void_func\n" +
  701. "%main_lab = OpLabel\n" +
  702. "%2 = OpShiftRightLogical %int %int_2 %uint_32\n" +
  703. "OpReturn\n" +
  704. "OpFunctionEnd",
  705. 2, 0),
  706. // Test case 28: fold 2 << 32
  707. InstructionFoldingCase<uint32_t>(
  708. Header() + "%main = OpFunction %void None %void_func\n" +
  709. "%main_lab = OpLabel\n" +
  710. "%2 = OpShiftLeftLogical %int %int_2 %uint_32\n" +
  711. "OpReturn\n" +
  712. "OpFunctionEnd",
  713. 2, 0),
  714. // Test case 29: fold -INT_MIN
  715. InstructionFoldingCase<uint32_t>(
  716. Header() + "%main = OpFunction %void None %void_func\n" +
  717. "%main_lab = OpLabel\n" +
  718. "%2 = OpSNegate %int %int_min\n" +
  719. "OpReturn\n" +
  720. "OpFunctionEnd",
  721. 2, std::numeric_limits<int32_t>::min()),
  722. // Test case 30: fold UMin 3 4
  723. InstructionFoldingCase<uint32_t>(
  724. Header() + "%main = OpFunction %void None %void_func\n" +
  725. "%main_lab = OpLabel\n" +
  726. "%2 = OpExtInst %uint %1 UMin %uint_3 %uint_4\n" +
  727. "OpReturn\n" +
  728. "OpFunctionEnd",
  729. 2, 3),
  730. // Test case 31: fold UMin 4 2
  731. InstructionFoldingCase<uint32_t>(
  732. Header() + "%main = OpFunction %void None %void_func\n" +
  733. "%main_lab = OpLabel\n" +
  734. "%2 = OpExtInst %uint %1 UMin %uint_4 %uint_2\n" +
  735. "OpReturn\n" +
  736. "OpFunctionEnd",
  737. 2, 2),
  738. // Test case 32: fold SMin 3 4
  739. InstructionFoldingCase<uint32_t>(
  740. Header() + "%main = OpFunction %void None %void_func\n" +
  741. "%main_lab = OpLabel\n" +
  742. "%2 = OpExtInst %int %1 UMin %int_3 %int_4\n" +
  743. "OpReturn\n" +
  744. "OpFunctionEnd",
  745. 2, 3),
  746. // Test case 33: fold SMin 4 2
  747. InstructionFoldingCase<uint32_t>(
  748. Header() + "%main = OpFunction %void None %void_func\n" +
  749. "%main_lab = OpLabel\n" +
  750. "%2 = OpExtInst %int %1 SMin %int_4 %int_2\n" +
  751. "OpReturn\n" +
  752. "OpFunctionEnd",
  753. 2, 2),
  754. // Test case 34: fold UMax 3 4
  755. InstructionFoldingCase<uint32_t>(
  756. Header() + "%main = OpFunction %void None %void_func\n" +
  757. "%main_lab = OpLabel\n" +
  758. "%2 = OpExtInst %uint %1 UMax %uint_3 %uint_4\n" +
  759. "OpReturn\n" +
  760. "OpFunctionEnd",
  761. 2, 4),
  762. // Test case 35: fold UMax 3 2
  763. InstructionFoldingCase<uint32_t>(
  764. Header() + "%main = OpFunction %void None %void_func\n" +
  765. "%main_lab = OpLabel\n" +
  766. "%2 = OpExtInst %uint %1 UMax %uint_3 %uint_2\n" +
  767. "OpReturn\n" +
  768. "OpFunctionEnd",
  769. 2, 3),
  770. // Test case 36: fold SMax 3 4
  771. InstructionFoldingCase<uint32_t>(
  772. Header() + "%main = OpFunction %void None %void_func\n" +
  773. "%main_lab = OpLabel\n" +
  774. "%2 = OpExtInst %int %1 UMax %int_3 %int_4\n" +
  775. "OpReturn\n" +
  776. "OpFunctionEnd",
  777. 2, 4),
  778. // Test case 37: fold SMax 3 2
  779. InstructionFoldingCase<uint32_t>(
  780. Header() + "%main = OpFunction %void None %void_func\n" +
  781. "%main_lab = OpLabel\n" +
  782. "%2 = OpExtInst %int %1 SMax %int_3 %int_2\n" +
  783. "OpReturn\n" +
  784. "OpFunctionEnd",
  785. 2, 3),
  786. // Test case 38: fold UClamp 2 3 4
  787. InstructionFoldingCase<uint32_t>(
  788. Header() + "%main = OpFunction %void None %void_func\n" +
  789. "%main_lab = OpLabel\n" +
  790. "%2 = OpExtInst %uint %1 UClamp %uint_2 %uint_3 %uint_4\n" +
  791. "OpReturn\n" +
  792. "OpFunctionEnd",
  793. 2, 3),
  794. // Test case 39: fold UClamp 2 0 4
  795. InstructionFoldingCase<uint32_t>(
  796. Header() + "%main = OpFunction %void None %void_func\n" +
  797. "%main_lab = OpLabel\n" +
  798. "%2 = OpExtInst %uint %1 UClamp %uint_2 %uint_0 %uint_4\n" +
  799. "OpReturn\n" +
  800. "OpFunctionEnd",
  801. 2, 2),
  802. // Test case 40: fold UClamp 2 0 1
  803. InstructionFoldingCase<uint32_t>(
  804. Header() + "%main = OpFunction %void None %void_func\n" +
  805. "%main_lab = OpLabel\n" +
  806. "%2 = OpExtInst %uint %1 UClamp %uint_2 %uint_0 %uint_1\n" +
  807. "OpReturn\n" +
  808. "OpFunctionEnd",
  809. 2, 1),
  810. // Test case 41: fold SClamp 2 3 4
  811. InstructionFoldingCase<uint32_t>(
  812. Header() + "%main = OpFunction %void None %void_func\n" +
  813. "%main_lab = OpLabel\n" +
  814. "%2 = OpExtInst %int %1 SClamp %int_2 %int_3 %int_4\n" +
  815. "OpReturn\n" +
  816. "OpFunctionEnd",
  817. 2, 3),
  818. // Test case 42: fold SClamp 2 0 4
  819. InstructionFoldingCase<uint32_t>(
  820. Header() + "%main = OpFunction %void None %void_func\n" +
  821. "%main_lab = OpLabel\n" +
  822. "%2 = OpExtInst %int %1 SClamp %int_2 %int_0 %int_4\n" +
  823. "OpReturn\n" +
  824. "OpFunctionEnd",
  825. 2, 2),
  826. // Test case 43: fold SClamp 2 0 1
  827. InstructionFoldingCase<uint32_t>(
  828. Header() + "%main = OpFunction %void None %void_func\n" +
  829. "%main_lab = OpLabel\n" +
  830. "%2 = OpExtInst %int %1 SClamp %int_2 %int_0 %int_1\n" +
  831. "OpReturn\n" +
  832. "OpFunctionEnd",
  833. 2, 1),
  834. // Test case 44: SClamp 1 2 x
  835. InstructionFoldingCase<uint32_t>(
  836. Header() + "%main = OpFunction %void None %void_func\n" +
  837. "%main_lab = OpLabel\n" +
  838. "%undef = OpUndef %int\n" +
  839. "%2 = OpExtInst %int %1 SClamp %int_1 %int_2 %undef\n" +
  840. "OpReturn\n" +
  841. "OpFunctionEnd",
  842. 2, 2),
  843. // Test case 45: SClamp 2 x 1
  844. InstructionFoldingCase<uint32_t>(
  845. Header() + "%main = OpFunction %void None %void_func\n" +
  846. "%main_lab = OpLabel\n" +
  847. "%undef = OpUndef %int\n" +
  848. "%2 = OpExtInst %int %1 SClamp %int_2 %undef %int_1\n" +
  849. "OpReturn\n" +
  850. "OpFunctionEnd",
  851. 2, 1),
  852. // Test case 46: UClamp 1 2 x
  853. InstructionFoldingCase<uint32_t>(
  854. Header() + "%main = OpFunction %void None %void_func\n" +
  855. "%main_lab = OpLabel\n" +
  856. "%undef = OpUndef %uint\n" +
  857. "%2 = OpExtInst %uint %1 UClamp %uint_1 %uint_2 %undef\n" +
  858. "OpReturn\n" +
  859. "OpFunctionEnd",
  860. 2, 2),
  861. // Test case 47: UClamp 2 x 1
  862. InstructionFoldingCase<uint32_t>(
  863. Header() + "%main = OpFunction %void None %void_func\n" +
  864. "%main_lab = OpLabel\n" +
  865. "%undef = OpUndef %uint\n" +
  866. "%2 = OpExtInst %uint %1 UClamp %uint_2 %undef %uint_1\n" +
  867. "OpReturn\n" +
  868. "OpFunctionEnd",
  869. 2, 1),
  870. // Test case 48: Bit-cast int 0 to unsigned int
  871. InstructionFoldingCase<uint32_t>(
  872. Header() + "%main = OpFunction %void None %void_func\n" +
  873. "%main_lab = OpLabel\n" +
  874. "%2 = OpBitcast %uint %int_0\n" +
  875. "OpReturn\n" +
  876. "OpFunctionEnd",
  877. 2, 0),
  878. // Test case 49: Bit-cast int -24 to unsigned int
  879. InstructionFoldingCase<uint32_t>(
  880. Header() + "%main = OpFunction %void None %void_func\n" +
  881. "%main_lab = OpLabel\n" +
  882. "%2 = OpBitcast %uint %int_n24\n" +
  883. "OpReturn\n" +
  884. "OpFunctionEnd",
  885. 2, static_cast<uint32_t>(-24)),
  886. // Test case 50: Bit-cast float 1.0f to unsigned int
  887. InstructionFoldingCase<uint32_t>(
  888. Header() + "%main = OpFunction %void None %void_func\n" +
  889. "%main_lab = OpLabel\n" +
  890. "%2 = OpBitcast %uint %float_1\n" +
  891. "OpReturn\n" +
  892. "OpFunctionEnd",
  893. 2, static_cast<uint32_t>(0x3f800000)),
  894. // Test case 51: Bit-cast ushort 0xBC00 to ushort
  895. InstructionFoldingCase<uint32_t>(
  896. Header() + "%main = OpFunction %void None %void_func\n" +
  897. "%main_lab = OpLabel\n" +
  898. "%2 = OpBitcast %ushort %ushort_0xBC00\n" +
  899. "OpReturn\n" +
  900. "OpFunctionEnd",
  901. 2, 0xBC00),
  902. // Test case 52: Bit-cast short 0xBC00 to ushort
  903. InstructionFoldingCase<uint32_t>(
  904. Header() + "%main = OpFunction %void None %void_func\n" +
  905. "%main_lab = OpLabel\n" +
  906. "%2 = OpBitcast %ushort %short_0xBC00\n" +
  907. "OpReturn\n" +
  908. "OpFunctionEnd",
  909. 2, 0xBC00),
  910. // Test case 53: Bit-cast half 1 to ushort
  911. InstructionFoldingCase<uint32_t>(
  912. Header() + "%main = OpFunction %void None %void_func\n" +
  913. "%main_lab = OpLabel\n" +
  914. "%2 = OpBitcast %ushort %half_1\n" +
  915. "OpReturn\n" +
  916. "OpFunctionEnd",
  917. 2, 0x3C00),
  918. // Test case 54: Bit-cast ushort 0xBC00 to short
  919. InstructionFoldingCase<uint32_t>(
  920. Header() + "%main = OpFunction %void None %void_func\n" +
  921. "%main_lab = OpLabel\n" +
  922. "%2 = OpBitcast %short %ushort_0xBC00\n" +
  923. "OpReturn\n" +
  924. "OpFunctionEnd",
  925. 2, 0xFFFFBC00),
  926. // Test case 55: Bit-cast short 0xBC00 to short
  927. InstructionFoldingCase<uint32_t>(
  928. Header() + "%main = OpFunction %void None %void_func\n" +
  929. "%main_lab = OpLabel\n" +
  930. "%2 = OpBitcast %short %short_0xBC00\n" +
  931. "OpReturn\n" +
  932. "OpFunctionEnd",
  933. 2, 0xFFFFBC00),
  934. // Test case 56: Bit-cast half 1 to short
  935. InstructionFoldingCase<uint32_t>(
  936. Header() + "%main = OpFunction %void None %void_func\n" +
  937. "%main_lab = OpLabel\n" +
  938. "%2 = OpBitcast %short %half_1\n" +
  939. "OpReturn\n" +
  940. "OpFunctionEnd",
  941. 2, 0x3C00),
  942. // Test case 57: Bit-cast ushort 0xBC00 to half
  943. InstructionFoldingCase<uint32_t>(
  944. Header() + "%main = OpFunction %void None %void_func\n" +
  945. "%main_lab = OpLabel\n" +
  946. "%2 = OpBitcast %half %ushort_0xBC00\n" +
  947. "OpReturn\n" +
  948. "OpFunctionEnd",
  949. 2, 0xBC00),
  950. // Test case 58: Bit-cast short 0xBC00 to half
  951. InstructionFoldingCase<uint32_t>(
  952. Header() + "%main = OpFunction %void None %void_func\n" +
  953. "%main_lab = OpLabel\n" +
  954. "%2 = OpBitcast %half %short_0xBC00\n" +
  955. "OpReturn\n" +
  956. "OpFunctionEnd",
  957. 2, 0xFFFFBC00),
  958. // Test case 59: Bit-cast half 1 to half
  959. InstructionFoldingCase<uint32_t>(
  960. Header() + "%main = OpFunction %void None %void_func\n" +
  961. "%main_lab = OpLabel\n" +
  962. "%2 = OpBitcast %half %half_1\n" +
  963. "OpReturn\n" +
  964. "OpFunctionEnd",
  965. 2, 0x3C00),
  966. // Test case 60: Bit-cast ubyte 1 to byte
  967. InstructionFoldingCase<uint32_t>(
  968. Header() + "%main = OpFunction %void None %void_func\n" +
  969. "%main_lab = OpLabel\n" +
  970. "%2 = OpBitcast %byte %ubyte_1\n" +
  971. "OpReturn\n" +
  972. "OpFunctionEnd",
  973. 2, 1),
  974. // Test case 61: Bit-cast byte -1 to ubyte
  975. InstructionFoldingCase<uint32_t>(
  976. Header() + "%main = OpFunction %void None %void_func\n" +
  977. "%main_lab = OpLabel\n" +
  978. "%2 = OpBitcast %ubyte %byte_n1\n" +
  979. "OpReturn\n" +
  980. "OpFunctionEnd",
  981. 2, 0xFF),
  982. // Test case 62: Negate 2.
  983. InstructionFoldingCase<uint32_t>(
  984. Header() + "%main = OpFunction %void None %void_func\n" +
  985. "%main_lab = OpLabel\n" +
  986. "%2 = OpSNegate %int %int_2\n" +
  987. "OpReturn\n" +
  988. "OpFunctionEnd",
  989. 2, -2),
  990. // Test case 63: Negate negative short.
  991. InstructionFoldingCase<uint32_t>(
  992. Header() + "%main = OpFunction %void None %void_func\n" +
  993. "%main_lab = OpLabel\n" +
  994. "%2 = OpSNegate %short %short_0xBC00\n" +
  995. "OpReturn\n" +
  996. "OpFunctionEnd",
  997. 2, 0x4400 /* expected to be sign extended. */),
  998. // Test case 64: Negate positive short.
  999. InstructionFoldingCase<uint32_t>(
  1000. Header() + "%main = OpFunction %void None %void_func\n" +
  1001. "%main_lab = OpLabel\n" +
  1002. "%2 = OpSNegate %short %short_0x4400\n" +
  1003. "OpReturn\n" +
  1004. "OpFunctionEnd",
  1005. 2, 0xFFFFBC00 /* expected to be sign extended. */),
  1006. // Test case 65: Negate a negative short.
  1007. InstructionFoldingCase<uint32_t>(
  1008. Header() + "%main = OpFunction %void None %void_func\n" +
  1009. "%main_lab = OpLabel\n" +
  1010. "%2 = OpSNegate %ushort %ushort_0xBC00\n" +
  1011. "OpReturn\n" +
  1012. "OpFunctionEnd",
  1013. 2, 0x4400 /* expected to be zero extended. */),
  1014. // Test case 66: Negate positive short.
  1015. InstructionFoldingCase<uint32_t>(
  1016. Header() + "%main = OpFunction %void None %void_func\n" +
  1017. "%main_lab = OpLabel\n" +
  1018. "%2 = OpSNegate %ushort %ushort_0x4400\n" +
  1019. "OpReturn\n" +
  1020. "OpFunctionEnd",
  1021. 2, 0xBC00 /* expected to be zero extended. */),
  1022. // Test case 67: Fold 2 + 3 (short)
  1023. InstructionFoldingCase<uint32_t>(
  1024. Header() + "%main = OpFunction %void None %void_func\n" +
  1025. "%main_lab = OpLabel\n" +
  1026. "%2 = OpIAdd %short %short_2 %short_3\n" +
  1027. "OpReturn\n" +
  1028. "OpFunctionEnd",
  1029. 2, 5),
  1030. // Test case 68: Fold 2 + -5 (short)
  1031. InstructionFoldingCase<uint32_t>(
  1032. Header() + "%main = OpFunction %void None %void_func\n" +
  1033. "%main_lab = OpLabel\n" +
  1034. "%2 = OpIAdd %short %short_2 %short_n5\n" +
  1035. "OpReturn\n" +
  1036. "OpFunctionEnd",
  1037. 2, -3),
  1038. // Test case 69: Fold int(3ll)
  1039. InstructionFoldingCase<uint32_t>(
  1040. Header() + "%main = OpFunction %void None %void_func\n" +
  1041. "%main_lab = OpLabel\n" +
  1042. "%2 = OpSConvert %int %long_3\n" +
  1043. "OpReturn\n" +
  1044. "OpFunctionEnd",
  1045. 2, 3),
  1046. // Test case 70: Fold short(-3ll)
  1047. InstructionFoldingCase<uint32_t>(
  1048. Header() + "%main = OpFunction %void None %void_func\n" +
  1049. "%main_lab = OpLabel\n" +
  1050. "%2 = OpSConvert %short %long_n3\n" +
  1051. "OpReturn\n" +
  1052. "OpFunctionEnd",
  1053. 2, -3),
  1054. // Test case 71: Fold short(32768ll) - This should do a sign extend when
  1055. // converting to short.
  1056. InstructionFoldingCase<uint32_t>(
  1057. Header() + "%main = OpFunction %void None %void_func\n" +
  1058. "%main_lab = OpLabel\n" +
  1059. "%2 = OpSConvert %short %long_32768\n" +
  1060. "OpReturn\n" +
  1061. "OpFunctionEnd",
  1062. 2, -32768),
  1063. // Test case 72: Fold short(-57344) - This should do a sign extend when
  1064. // converting to short making the upper bits 0.
  1065. InstructionFoldingCase<uint32_t>(
  1066. Header() + "%main = OpFunction %void None %void_func\n" +
  1067. "%main_lab = OpLabel\n" +
  1068. "%2 = OpSConvert %short %long_n57344\n" +
  1069. "OpReturn\n" +
  1070. "OpFunctionEnd",
  1071. 2, 8192),
  1072. // Test case 73: Fold int(-5(short)). The -5 should be interpreted as an unsigned value, and be zero extended to 32-bits.
  1073. InstructionFoldingCase<uint32_t>(
  1074. Header() + "%main = OpFunction %void None %void_func\n" +
  1075. "%main_lab = OpLabel\n" +
  1076. "%2 = OpUConvert %uint %short_n5\n" +
  1077. "OpReturn\n" +
  1078. "OpFunctionEnd",
  1079. 2, 65531),
  1080. // Test case 74: Fold short(-24(int)). The upper bits should be cleared. So 0xFFFFFFE8 should become 0x0000FFE8.
  1081. InstructionFoldingCase<uint32_t>(
  1082. Header() + "%main = OpFunction %void None %void_func\n" +
  1083. "%main_lab = OpLabel\n" +
  1084. "%2 = OpUConvert %ushort %int_n24\n" +
  1085. "OpReturn\n" +
  1086. "OpFunctionEnd",
  1087. 2, 65512)
  1088. ));
  1089. // clang-format on
  1090. using LongIntegerInstructionFoldingTest =
  1091. ::testing::TestWithParam<InstructionFoldingCase<uint64_t>>;
  1092. TEST_P(LongIntegerInstructionFoldingTest, Case) {
  1093. const auto& tc = GetParam();
  1094. std::unique_ptr<IRContext> context;
  1095. Instruction* inst;
  1096. std::tie(context, inst) =
  1097. FoldInstruction(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_1);
  1098. CheckForExpectedScalarConstant(
  1099. inst, tc.expected_result, [](const analysis::Constant* c) {
  1100. return c->AsScalarConstant()->GetU64BitValue();
  1101. });
  1102. }
  1103. INSTANTIATE_TEST_SUITE_P(
  1104. TestCase, LongIntegerInstructionFoldingTest,
  1105. ::testing::Values(
  1106. // Test case 0: fold 1+4611686018427387904
  1107. InstructionFoldingCase<uint64_t>(
  1108. Header() + "%main = OpFunction %void None %void_func\n" +
  1109. "%main_lab = OpLabel\n" +
  1110. "%n = OpVariable %_ptr_int Function\n" +
  1111. "%load = OpLoad %int %n\n" +
  1112. "%2 = OpIAdd %long %long_1 %long_4611686018427387904\n" +
  1113. "OpReturn\n" + "OpFunctionEnd",
  1114. 2, 1 + 4611686018427387904),
  1115. // Test case 1: fold 1-4611686018427387904
  1116. InstructionFoldingCase<uint64_t>(
  1117. Header() + "%main = OpFunction %void None %void_func\n" +
  1118. "%main_lab = OpLabel\n" +
  1119. "%n = OpVariable %_ptr_int Function\n" +
  1120. "%load = OpLoad %int %n\n" +
  1121. "%2 = OpISub %long %long_1 %long_4611686018427387904\n" +
  1122. "OpReturn\n" + "OpFunctionEnd",
  1123. 2, 1 - 4611686018427387904),
  1124. // Test case 2: fold 2*4611686018427387904
  1125. InstructionFoldingCase<uint64_t>(
  1126. Header() + "%main = OpFunction %void None %void_func\n" +
  1127. "%main_lab = OpLabel\n" +
  1128. "%n = OpVariable %_ptr_int Function\n" +
  1129. "%load = OpLoad %int %n\n" +
  1130. "%2 = OpIMul %long %long_2 %long_4611686018427387904\n" +
  1131. "OpReturn\n" + "OpFunctionEnd",
  1132. 2, 9223372036854775808ull),
  1133. // Test case 3: fold 4611686018427387904/2 (unsigned)
  1134. InstructionFoldingCase<uint64_t>(
  1135. Header() + "%main = OpFunction %void None %void_func\n" +
  1136. "%main_lab = OpLabel\n" +
  1137. "%n = OpVariable %_ptr_int Function\n" +
  1138. "%load = OpLoad %int %n\n" +
  1139. "%2 = OpUDiv %ulong %ulong_4611686018427387904 %ulong_2\n" +
  1140. "OpReturn\n" + "OpFunctionEnd",
  1141. 2, 4611686018427387904 / 2),
  1142. // Test case 4: fold 4611686018427387904/2 (signed)
  1143. InstructionFoldingCase<uint64_t>(
  1144. Header() + "%main = OpFunction %void None %void_func\n" +
  1145. "%main_lab = OpLabel\n" +
  1146. "%n = OpVariable %_ptr_int Function\n" +
  1147. "%load = OpLoad %int %n\n" +
  1148. "%2 = OpSDiv %long %long_4611686018427387904 %long_2\n" +
  1149. "OpReturn\n" + "OpFunctionEnd",
  1150. 2, 4611686018427387904 / 2),
  1151. // Test case 5: fold -4611686018427387904/2 (signed)
  1152. InstructionFoldingCase<uint64_t>(
  1153. Header() + "%main = OpFunction %void None %void_func\n" +
  1154. "%main_lab = OpLabel\n" +
  1155. "%n = OpVariable %_ptr_int Function\n" +
  1156. "%load = OpLoad %int %n\n" +
  1157. "%2 = OpSDiv %long %long_n4611686018427387904 %long_2\n" +
  1158. "OpReturn\n" + "OpFunctionEnd",
  1159. 2, -4611686018427387904 / 2),
  1160. // Test case 6: fold 4611686018427387904 mod 7 (unsigned)
  1161. InstructionFoldingCase<uint64_t>(
  1162. Header() + "%main = OpFunction %void None %void_func\n" +
  1163. "%main_lab = OpLabel\n" +
  1164. "%n = OpVariable %_ptr_int Function\n" +
  1165. "%load = OpLoad %int %n\n" +
  1166. "%2 = OpUMod %ulong %ulong_4611686018427387904 %ulong_7\n" +
  1167. "OpReturn\n" + "OpFunctionEnd",
  1168. 2, 4611686018427387904ull % 7ull),
  1169. // Test case 7: fold 7 mod 3 (signed)
  1170. InstructionFoldingCase<uint64_t>(
  1171. Header() + "%main = OpFunction %void None %void_func\n" +
  1172. "%main_lab = OpLabel\n" +
  1173. "%n = OpVariable %_ptr_int Function\n" +
  1174. "%load = OpLoad %int %n\n" +
  1175. "%2 = OpSMod %long %long_7 %long_3\n" + "OpReturn\n" +
  1176. "OpFunctionEnd",
  1177. 2, 1ull),
  1178. // Test case 8: fold 7 rem 3 (signed)
  1179. InstructionFoldingCase<uint64_t>(
  1180. Header() + "%main = OpFunction %void None %void_func\n" +
  1181. "%main_lab = OpLabel\n" +
  1182. "%n = OpVariable %_ptr_int Function\n" +
  1183. "%load = OpLoad %int %n\n" +
  1184. "%2 = OpSRem %long %long_7 %long_3\n" + "OpReturn\n" +
  1185. "OpFunctionEnd",
  1186. 2, 1ull),
  1187. // Test case 9: fold 7 mod -3 (signed)
  1188. InstructionFoldingCase<uint64_t>(
  1189. Header() + "%main = OpFunction %void None %void_func\n" +
  1190. "%main_lab = OpLabel\n" +
  1191. "%n = OpVariable %_ptr_int Function\n" +
  1192. "%load = OpLoad %int %n\n" +
  1193. "%2 = OpSMod %long %long_7 %long_n3\n" + "OpReturn\n" +
  1194. "OpFunctionEnd",
  1195. 2, -2ll),
  1196. // Test case 10: fold 7 rem 3 (signed)
  1197. InstructionFoldingCase<uint64_t>(
  1198. Header() + "%main = OpFunction %void None %void_func\n" +
  1199. "%main_lab = OpLabel\n" +
  1200. "%n = OpVariable %_ptr_int Function\n" +
  1201. "%load = OpLoad %int %n\n" +
  1202. "%2 = OpSRem %long %long_7 %long_n3\n" + "OpReturn\n" +
  1203. "OpFunctionEnd",
  1204. 2, 1ll),
  1205. // Test case 11: fold -7 mod 3 (signed)
  1206. InstructionFoldingCase<uint64_t>(
  1207. Header() + "%main = OpFunction %void None %void_func\n" +
  1208. "%main_lab = OpLabel\n" +
  1209. "%n = OpVariable %_ptr_int Function\n" +
  1210. "%load = OpLoad %int %n\n" +
  1211. "%2 = OpSMod %long %long_n7 %long_3\n" + "OpReturn\n" +
  1212. "OpFunctionEnd",
  1213. 2, 2ll),
  1214. // Test case 12: fold -7 rem 3 (signed)
  1215. InstructionFoldingCase<uint64_t>(
  1216. Header() + "%main = OpFunction %void None %void_func\n" +
  1217. "%main_lab = OpLabel\n" +
  1218. "%n = OpVariable %_ptr_int Function\n" +
  1219. "%load = OpLoad %int %n\n" +
  1220. "%2 = OpSRem %long %long_n7 %long_3\n" + "OpReturn\n" +
  1221. "OpFunctionEnd",
  1222. 2, -1ll),
  1223. // Test case 13: fold long(-24)
  1224. InstructionFoldingCase<uint64_t>(
  1225. Header() + "%main = OpFunction %void None %void_func\n" +
  1226. "%main_lab = OpLabel\n" +
  1227. "%n = OpVariable %_ptr_int Function\n" +
  1228. "%load = OpLoad %int %n\n" +
  1229. "%2 = OpSConvert %long %int_n24\n" + "OpReturn\n" +
  1230. "OpFunctionEnd",
  1231. 2, -24ll),
  1232. // Test case 14: fold long(-24)
  1233. InstructionFoldingCase<uint64_t>(
  1234. Header() + "%main = OpFunction %void None %void_func\n" +
  1235. "%main_lab = OpLabel\n" +
  1236. "%n = OpVariable %_ptr_int Function\n" +
  1237. "%load = OpLoad %int %n\n" + "%2 = OpSConvert %long %int_10\n" +
  1238. "OpReturn\n" + "OpFunctionEnd",
  1239. 2, 10ll),
  1240. // Test case 15: fold long(-24(short)).
  1241. // The upper bits should be cleared. So 0xFFFFFFE8 should become
  1242. // 0x000000000000FFE8.
  1243. InstructionFoldingCase<uint64_t>(
  1244. Header() + "%main = OpFunction %void None %void_func\n" +
  1245. "%main_lab = OpLabel\n" + "%2 = OpUConvert %ulong %short_n5\n" +
  1246. "OpReturn\n" + "OpFunctionEnd",
  1247. 2, 65531ull)));
  1248. using UIntVectorInstructionFoldingTest =
  1249. ::testing::TestWithParam<InstructionFoldingCase<std::vector<uint32_t>>>;
  1250. TEST_P(UIntVectorInstructionFoldingTest, Case) {
  1251. const auto& tc = GetParam();
  1252. std::unique_ptr<IRContext> context;
  1253. Instruction* inst;
  1254. std::tie(context, inst) =
  1255. FoldInstruction(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_1);
  1256. CheckForExpectedVectorConstant(
  1257. inst, tc.expected_result,
  1258. [](const analysis::Constant* c) { return c->GetU32(); });
  1259. }
  1260. // clang-format off
  1261. INSTANTIATE_TEST_SUITE_P(TestCase, UIntVectorInstructionFoldingTest,
  1262. ::testing::Values(
  1263. // Test case 0: fold 0*n
  1264. InstructionFoldingCase<std::vector<uint32_t>>(
  1265. Header() + "%main = OpFunction %void None %void_func\n" +
  1266. "%main_lab = OpLabel\n" +
  1267. "%n = OpVariable %_ptr_int Function\n" +
  1268. "%load = OpLoad %int %n\n" +
  1269. "%2 = OpVectorShuffle %v2int %v2int_2_2 %v2int_2_3 0 3\n" +
  1270. "OpReturn\n" +
  1271. "OpFunctionEnd",
  1272. 2, {2,3}),
  1273. InstructionFoldingCase<std::vector<uint32_t>>(
  1274. Header() + "%main = OpFunction %void None %void_func\n" +
  1275. "%main_lab = OpLabel\n" +
  1276. "%n = OpVariable %_ptr_int Function\n" +
  1277. "%load = OpLoad %int %n\n" +
  1278. "%2 = OpVectorShuffle %v2int %v2int_null %v2int_2_3 0 3\n" +
  1279. "OpReturn\n" +
  1280. "OpFunctionEnd",
  1281. 2, {0,3}),
  1282. // Test case 4: fold bit-cast int -24 to unsigned int
  1283. InstructionFoldingCase<std::vector<uint32_t>>(
  1284. Header() + "%main = OpFunction %void None %void_func\n" +
  1285. "%main_lab = OpLabel\n" +
  1286. "%n = OpVariable %_ptr_int Function\n" +
  1287. "%load = OpLoad %int %n\n" +
  1288. "%2 = OpBitcast %v2uint %v2int_min_max\n" +
  1289. "OpReturn\n" +
  1290. "OpFunctionEnd",
  1291. 2, {2147483648, 2147483647}),
  1292. // Test case 5: fold SNegate vector of uint
  1293. InstructionFoldingCase<std::vector<uint32_t>>(
  1294. Header() + "%main = OpFunction %void None %void_func\n" +
  1295. "%main_lab = OpLabel\n" +
  1296. "%n = OpVariable %_ptr_int Function\n" +
  1297. "%load = OpLoad %int %n\n" +
  1298. "%2 = OpSNegate %v2uint %v2uint_0x3f800000_0xbf800000\n" +
  1299. "OpReturn\n" +
  1300. "OpFunctionEnd",
  1301. 2, {static_cast<uint32_t>(-0x3f800000), static_cast<uint32_t>(-0xbf800000)}),
  1302. // Test case 6: fold vector components of uint (including integer overflow)
  1303. InstructionFoldingCase<std::vector<uint32_t>>(
  1304. Header() + "%main = OpFunction %void None %void_func\n" +
  1305. "%main_lab = OpLabel\n" +
  1306. "%2 = OpIAdd %v2uint %v2uint_0x3f800000_0xbf800000 %v2uint_0x3f800000_0xbf800000\n" +
  1307. "OpReturn\n" +
  1308. "OpFunctionEnd",
  1309. 2, {0x7f000000u, 0x7f000000u}),
  1310. // Test case 6: fold vector components of uint
  1311. InstructionFoldingCase<std::vector<uint32_t>>(
  1312. Header() + "%main = OpFunction %void None %void_func\n" +
  1313. "%main_lab = OpLabel\n" +
  1314. "%2 = OpSConvert %v2int %v2short_2_n5\n" +
  1315. "OpReturn\n" +
  1316. "OpFunctionEnd",
  1317. 2, {2,static_cast<uint32_t>(-5)}),
  1318. // Test case 6: fold vector components of uint (incuding integer overflow)
  1319. InstructionFoldingCase<std::vector<uint32_t>>(
  1320. Header() + "%main = OpFunction %void None %void_func\n" +
  1321. "%main_lab = OpLabel\n" +
  1322. "%2 = OpUConvert %v2uint %v2short_2_n5\n" +
  1323. "OpReturn\n" +
  1324. "OpFunctionEnd",
  1325. 2, {2,65531})
  1326. ));
  1327. // clang-format on
  1328. using IntVectorInstructionFoldingTest =
  1329. ::testing::TestWithParam<InstructionFoldingCase<std::vector<int32_t>>>;
  1330. TEST_P(IntVectorInstructionFoldingTest, Case) {
  1331. const auto& tc = GetParam();
  1332. std::unique_ptr<IRContext> context;
  1333. Instruction* inst;
  1334. std::tie(context, inst) =
  1335. FoldInstruction(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_1);
  1336. CheckForExpectedVectorConstant(
  1337. inst, tc.expected_result,
  1338. [](const analysis::Constant* c) { return c->GetS32(); });
  1339. }
  1340. // clang-format off
  1341. INSTANTIATE_TEST_SUITE_P(TestCase, IntVectorInstructionFoldingTest,
  1342. ::testing::Values(
  1343. // Test case 0: fold negate of a vector
  1344. InstructionFoldingCase<std::vector<int32_t>>(
  1345. Header() + "%main = OpFunction %void None %void_func\n" +
  1346. "%main_lab = OpLabel\n" +
  1347. "%2 = OpSNegate %v2int %v2int_2_3\n" +
  1348. "OpReturn\n" +
  1349. "OpFunctionEnd",
  1350. 2, {-2, -3}),
  1351. // Test case 1: fold negate of a vector containing negative values.
  1352. InstructionFoldingCase<std::vector<int32_t>>(
  1353. Header() + "%main = OpFunction %void None %void_func\n" +
  1354. "%main_lab = OpLabel\n" +
  1355. "%2 = OpSNegate %v2int %v2int_n1_n24\n" +
  1356. "OpReturn\n" +
  1357. "OpFunctionEnd",
  1358. 2, {1, 24}),
  1359. // Test case 2: fold negate of a vector at the limits
  1360. InstructionFoldingCase<std::vector<int32_t>>(
  1361. Header() + "%main = OpFunction %void None %void_func\n" +
  1362. "%main_lab = OpLabel\n" +
  1363. "%2 = OpSNegate %v2int %v2int_min_max\n" +
  1364. "OpReturn\n" +
  1365. "OpFunctionEnd",
  1366. 2, {INT_MIN, -INT_MAX}),
  1367. // Test case 3: fold vector components of int
  1368. InstructionFoldingCase<std::vector<int32_t>>(
  1369. Header() + "%main = OpFunction %void None %void_func\n" +
  1370. "%main_lab = OpLabel\n" +
  1371. "%2 = OpIMul %v2int %v2int_2_3 %v2int_2_3\n" +
  1372. "OpReturn\n" +
  1373. "OpFunctionEnd",
  1374. 2, {4,9})
  1375. ));
  1376. // clang-format on
  1377. using LongIntVectorInstructionFoldingTest =
  1378. ::testing::TestWithParam<InstructionFoldingCase<std::vector<uint64_t>>>;
  1379. TEST_P(LongIntVectorInstructionFoldingTest, Case) {
  1380. const auto& tc = GetParam();
  1381. std::unique_ptr<IRContext> context;
  1382. Instruction* inst;
  1383. std::tie(context, inst) =
  1384. FoldInstruction(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_1);
  1385. CheckForExpectedVectorConstant(
  1386. inst, tc.expected_result,
  1387. [](const analysis::Constant* c) { return c->GetU64(); });
  1388. }
  1389. // clang-format off
  1390. INSTANTIATE_TEST_SUITE_P(TestCase, LongIntVectorInstructionFoldingTest,
  1391. ::testing::Values(
  1392. // Test case 0: fold {2,2} + {2,3} (Testing that the vector logic works
  1393. // correctly. Scalar tests will check that the 64-bit values are correctly
  1394. // folded.)
  1395. InstructionFoldingCase<std::vector<uint64_t>>(
  1396. Header() + "%main = OpFunction %void None %void_func\n" +
  1397. "%main_lab = OpLabel\n" +
  1398. "%n = OpVariable %_ptr_int Function\n" +
  1399. "%load = OpLoad %int %n\n" +
  1400. "%2 = OpIAdd %v2long %v2long_2_2 %v2long_2_3\n" +
  1401. "OpReturn\n" +
  1402. "OpFunctionEnd",
  1403. 2, {4,5}),
  1404. // Test case 0: fold {2,2} / {2,3} (Testing that the vector logic works
  1405. // correctly. Scalar tests will check that the 64-bit values are correctly
  1406. // folded.)
  1407. InstructionFoldingCase<std::vector<uint64_t>>(
  1408. Header() + "%main = OpFunction %void None %void_func\n" +
  1409. "%main_lab = OpLabel\n" +
  1410. "%n = OpVariable %_ptr_int Function\n" +
  1411. "%load = OpLoad %int %n\n" +
  1412. "%2 = OpSDiv %v2long %v2long_2_2 %v2long_2_3\n" +
  1413. "OpReturn\n" +
  1414. "OpFunctionEnd",
  1415. 2, {1,0})
  1416. ));
  1417. // clang-format on
  1418. using DoubleVectorInstructionFoldingTest =
  1419. ::testing::TestWithParam<InstructionFoldingCase<std::vector<double>>>;
  1420. TEST_P(DoubleVectorInstructionFoldingTest, Case) {
  1421. const auto& tc = GetParam();
  1422. std::unique_ptr<IRContext> context;
  1423. Instruction* inst;
  1424. std::tie(context, inst) =
  1425. FoldInstruction(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_1);
  1426. CheckForExpectedVectorConstant(
  1427. inst, tc.expected_result,
  1428. [](const analysis::Constant* c) { return c->GetDouble(); });
  1429. }
  1430. // clang-format off
  1431. INSTANTIATE_TEST_SUITE_P(TestCase, DoubleVectorInstructionFoldingTest,
  1432. ::testing::Values(
  1433. // Test case 0: bit-cast int {0x3FF00000,0x00000000,0xC05FD666,0x66666666}
  1434. // to double vector
  1435. InstructionFoldingCase<std::vector<double>>(
  1436. Header() + "%main = OpFunction %void None %void_func\n" +
  1437. "%main_lab = OpLabel\n" +
  1438. "%2 = OpBitcast %v2double %v4int_0x3FF00000_0x00000000_0xC05FD666_0x66666666\n" +
  1439. "OpReturn\n" +
  1440. "OpFunctionEnd",
  1441. 2, {1.0,-127.35}),
  1442. // 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}
  1443. InstructionFoldingCase<std::vector<double>>(
  1444. Header() +
  1445. "%main = OpFunction %void None %void_func\n" +
  1446. "%main_lab = OpLabel\n" +
  1447. "%2 = OpVectorTimesMatrix %v4double %v4double_1_2_3_4 %mat4v4double_null\n" +
  1448. "OpReturn\n" +
  1449. "OpFunctionEnd",
  1450. 2, {0.0,0.0,0.0,0.0}),
  1451. // 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}
  1452. InstructionFoldingCase<std::vector<double>>(
  1453. Header() +
  1454. "%main = OpFunction %void None %void_func\n" +
  1455. "%main_lab = OpLabel\n" +
  1456. "%2 = OpVectorTimesMatrix %v4double %v4double_null %mat4v4double_1_2_3_4\n" +
  1457. "OpReturn\n" +
  1458. "OpFunctionEnd",
  1459. 2, {0.0,0.0,0.0,0.0}),
  1460. // 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}
  1461. InstructionFoldingCase<std::vector<double>>(
  1462. Header() +
  1463. "%main = OpFunction %void None %void_func\n" +
  1464. "%main_lab = OpLabel\n" +
  1465. "%2 = OpVectorTimesMatrix %v4double %v4double_1_2_3_4 %mat4v4double_1_2_3_4\n" +
  1466. "OpReturn\n" +
  1467. "OpFunctionEnd",
  1468. 2, {30.0,30.0,30.0,30.0}),
  1469. // Test case 4: OpVectorTimesMatrix Non-Zero Non-Zero {{1.0, 2.0, 3.0, 4.0}, Null, {1.0, 2.0, 3.0, 4.0}, Null} {1.0, 2.0, 3.0, 4.0} {30.0, 0.0, 30.0, 0.0}
  1470. InstructionFoldingCase<std::vector<double>>(
  1471. Header() +
  1472. "%main = OpFunction %void None %void_func\n" +
  1473. "%main_lab = OpLabel\n" +
  1474. "%2 = OpVectorTimesMatrix %v4double %v4double_1_2_3_4 %mat4v4double_1_2_3_4_null\n" +
  1475. "OpReturn\n" +
  1476. "OpFunctionEnd",
  1477. 2, {30.0,0.0,30.0,0.0}),
  1478. // Test case 5: 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}
  1479. InstructionFoldingCase<std::vector<double>>(
  1480. Header() +
  1481. "%main = OpFunction %void None %void_func\n" +
  1482. "%main_lab = OpLabel\n" +
  1483. "%2 = OpMatrixTimesVector %v4double %mat4v4double_null %v4double_1_2_3_4\n" +
  1484. "OpReturn\n" +
  1485. "OpFunctionEnd",
  1486. 2, {0.0,0.0,0.0,0.0}),
  1487. // Test case 6: 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}
  1488. InstructionFoldingCase<std::vector<double>>(
  1489. Header() +
  1490. "%main = OpFunction %void None %void_func\n" +
  1491. "%main_lab = OpLabel\n" +
  1492. "%2 = OpMatrixTimesVector %v4double %mat4v4double_1_2_3_4 %v4double_null\n" +
  1493. "OpReturn\n" +
  1494. "OpFunctionEnd",
  1495. 2, {0.0,0.0,0.0,0.0}),
  1496. // Test case 7: 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}
  1497. InstructionFoldingCase<std::vector<double>>(
  1498. Header() +
  1499. "%main = OpFunction %void None %void_func\n" +
  1500. "%main_lab = OpLabel\n" +
  1501. "%2 = OpMatrixTimesVector %v4double %mat4v4double_1_2_3_4 %v4double_1_2_3_4\n" +
  1502. "OpReturn\n" +
  1503. "OpFunctionEnd",
  1504. 2, {10.0,20.0,30.0,40.0}),
  1505. // Test case 8: OpMatrixTimesVector Non-Zero Non-Zero {1.0, 2.0, 3.0, 4.0} {{1.0, 2.0, 3.0, 4.0}, Null, {1.0, 2.0, 3.0, 4.0}, Null} {10.0, 20.0, 30.0, 40.0}
  1506. InstructionFoldingCase<std::vector<double>>(
  1507. Header() +
  1508. "%main = OpFunction %void None %void_func\n" +
  1509. "%main_lab = OpLabel\n" +
  1510. "%2 = OpMatrixTimesVector %v4double %mat4v4double_1_2_3_4_null %v4double_1_2_3_4\n" +
  1511. "OpReturn\n" +
  1512. "OpFunctionEnd",
  1513. 2, {4.0,8.0,12.0,16.0})
  1514. ));
  1515. using FloatVectorInstructionFoldingTest =
  1516. ::testing::TestWithParam<InstructionFoldingCase<std::vector<float>>>;
  1517. TEST_P(FloatVectorInstructionFoldingTest, Case) {
  1518. const auto& tc = GetParam();
  1519. std::unique_ptr<IRContext> context;
  1520. Instruction* inst;
  1521. std::tie(context, inst) = FoldInstruction(tc.test_body, tc.id_to_fold,SPV_ENV_UNIVERSAL_1_1);
  1522. CheckForExpectedVectorConstant(inst, tc.expected_result, [](const analysis::Constant* c){ return c->GetFloat();});
  1523. }
  1524. // clang-format off
  1525. INSTANTIATE_TEST_SUITE_P(TestCase, FloatVectorInstructionFoldingTest,
  1526. ::testing::Values(
  1527. // Test case 0: FMix {2.0, 2.0}, {2.0, 3.0} {0.2,0.5}
  1528. InstructionFoldingCase<std::vector<float>>(
  1529. Header() + "%main = OpFunction %void None %void_func\n" +
  1530. "%main_lab = OpLabel\n" +
  1531. "%2 = OpExtInst %v2float %1 FMix %v2float_2_3 %v2float_0_0 %v2float_0p2_0p5\n" +
  1532. "OpReturn\n" +
  1533. "OpFunctionEnd",
  1534. 2, {1.6f,1.5f}),
  1535. // Test case 1: bit-cast unsigned int vector {0x3f800000, 0xbf800000} to
  1536. // float vector
  1537. InstructionFoldingCase<std::vector<float>>(
  1538. Header() + "%main = OpFunction %void None %void_func\n" +
  1539. "%main_lab = OpLabel\n" +
  1540. "%2 = OpBitcast %v2float %v2uint_0x3f800000_0xbf800000\n" +
  1541. "OpReturn\n" +
  1542. "OpFunctionEnd",
  1543. 2, {1.0f,-1.0f}),
  1544. // Test case 2: bit-cast long int 0xbf8000003f800000 to float vector
  1545. InstructionFoldingCase<std::vector<float>>(
  1546. Header() + "%main = OpFunction %void None %void_func\n" +
  1547. "%main_lab = OpLabel\n" +
  1548. "%2 = OpBitcast %v2float %long_0xbf8000003f800000\n" +
  1549. "OpReturn\n" +
  1550. "OpFunctionEnd",
  1551. 2, {1.0f,-1.0f}),
  1552. // 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}
  1553. InstructionFoldingCase<std::vector<float>>(
  1554. Header() +
  1555. "%main = OpFunction %void None %void_func\n" +
  1556. "%main_lab = OpLabel\n" +
  1557. "%2 = OpVectorTimesMatrix %v4float %v4float_1_2_3_4 %mat4v4float_null\n" +
  1558. "OpReturn\n" +
  1559. "OpFunctionEnd",
  1560. 2, {0.0f,0.0f,0.0f,0.0f}),
  1561. // Test case 4: OpVectorTimesMatrix Non-Zero Non-Zero {{1.0, 2.0, 3.0, 4.0}, Null, {1.0, 2.0, 3.0, 4.0}, Null} {1.0, 2.0, 3.0, 4.0} {30.0, 0.0, 30.0, 0.0}
  1562. InstructionFoldingCase<std::vector<float>>(
  1563. Header() +
  1564. "%main = OpFunction %void None %void_func\n" +
  1565. "%main_lab = OpLabel\n" +
  1566. "%2 = OpVectorTimesMatrix %v4float %v4float_1_2_3_4 %mat4v4float_1_2_3_4_null\n" +
  1567. "OpReturn\n" +
  1568. "OpFunctionEnd",
  1569. 2, {30.0,0.0,30.0,0.0}),
  1570. // Test case 5: 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}
  1571. InstructionFoldingCase<std::vector<float>>(
  1572. Header() +
  1573. "%main = OpFunction %void None %void_func\n" +
  1574. "%main_lab = OpLabel\n" +
  1575. "%2 = OpVectorTimesMatrix %v4float %v4float_null %mat4v4float_1_2_3_4\n" +
  1576. "OpReturn\n" +
  1577. "OpFunctionEnd",
  1578. 2, {0.0f,0.0f,0.0f,0.0f}),
  1579. // Test case 6: 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}
  1580. InstructionFoldingCase<std::vector<float>>(
  1581. Header() +
  1582. "%main = OpFunction %void None %void_func\n" +
  1583. "%main_lab = OpLabel\n" +
  1584. "%2 = OpVectorTimesMatrix %v4float %v4float_1_2_3_4 %mat4v4float_1_2_3_4\n" +
  1585. "OpReturn\n" +
  1586. "OpFunctionEnd",
  1587. 2, {30.0f,30.0f,30.0f,30.0f}),
  1588. // Test case 7: 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}
  1589. InstructionFoldingCase<std::vector<float>>(
  1590. Header() +
  1591. "%main = OpFunction %void None %void_func\n" +
  1592. "%main_lab = OpLabel\n" +
  1593. "%2 = OpMatrixTimesVector %v4float %mat4v4float_null %v4float_1_2_3_4\n" +
  1594. "OpReturn\n" +
  1595. "OpFunctionEnd",
  1596. 2, {0.0f,0.0f,0.0f,0.0f}),
  1597. // Test case 8: 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}
  1598. InstructionFoldingCase<std::vector<float>>(
  1599. Header() +
  1600. "%main = OpFunction %void None %void_func\n" +
  1601. "%main_lab = OpLabel\n" +
  1602. "%2 = OpMatrixTimesVector %v4float %mat4v4float_1_2_3_4 %v4float_null\n" +
  1603. "OpReturn\n" +
  1604. "OpFunctionEnd",
  1605. 2, {0.0f,0.0f,0.0f,0.0f}),
  1606. // Test case 9: 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}
  1607. InstructionFoldingCase<std::vector<float>>(
  1608. Header() +
  1609. "%main = OpFunction %void None %void_func\n" +
  1610. "%main_lab = OpLabel\n" +
  1611. "%2 = OpMatrixTimesVector %v4float %mat4v4float_1_2_3_4 %v4float_1_2_3_4\n" +
  1612. "OpReturn\n" +
  1613. "OpFunctionEnd",
  1614. 2, {10.0f,20.0f,30.0f,40.0f}),
  1615. // Test case 10: OpMatrixTimesVector Non-Zero Non-Zero {1.0, 2.0, 3.0, 4.0} {{1.0, 2.0, 3.0, 4.0}, Null, {1.0, 2.0, 3.0, 4.0}, Null} {10.0, 20.0, 30.0, 40.0}
  1616. InstructionFoldingCase<std::vector<float>>(
  1617. Header() +
  1618. "%main = OpFunction %void None %void_func\n" +
  1619. "%main_lab = OpLabel\n" +
  1620. "%2 = OpMatrixTimesVector %v4float %mat4v4float_1_2_3_4_null %v4float_1_2_3_4\n" +
  1621. "OpReturn\n" +
  1622. "OpFunctionEnd",
  1623. 2, {4.0,8.0,12.0,16.0})
  1624. ));
  1625. // clang-format on
  1626. using FloatMatrixInstructionFoldingTest = ::testing::TestWithParam<
  1627. InstructionFoldingCase<std::vector<std::vector<float>>>>;
  1628. TEST_P(FloatMatrixInstructionFoldingTest, Case) {
  1629. const auto& tc = GetParam();
  1630. std::unique_ptr<IRContext> context;
  1631. Instruction* inst;
  1632. std::tie(context, inst) =
  1633. FoldInstruction(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_1);
  1634. EXPECT_EQ(inst->opcode(), spv::Op::OpCopyObject);
  1635. if (inst->opcode() == spv::Op::OpCopyObject) {
  1636. analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
  1637. inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
  1638. analysis::ConstantManager* const_mgr = context->get_constant_mgr();
  1639. const analysis::Constant* result = const_mgr->GetConstantFromInst(inst);
  1640. EXPECT_NE(result, nullptr);
  1641. if (result != nullptr) {
  1642. std::vector<const analysis::Constant*> matrix =
  1643. result->AsMatrixConstant()->GetComponents();
  1644. EXPECT_EQ(matrix.size(), tc.expected_result.size());
  1645. for (size_t c = 0; c < matrix.size(); c++) {
  1646. if (matrix[c]->AsNullConstant() != nullptr) {
  1647. matrix[c] = const_mgr->GetNullCompositeConstant(matrix[c]->type());
  1648. }
  1649. const analysis::VectorConstant* column_const =
  1650. matrix[c]->AsVectorConstant();
  1651. ASSERT_NE(column_const, nullptr);
  1652. const std::vector<const analysis::Constant*>& column =
  1653. column_const->GetComponents();
  1654. EXPECT_EQ(column.size(), tc.expected_result[c].size());
  1655. for (size_t r = 0; r < column.size(); r++) {
  1656. EXPECT_EQ(tc.expected_result[c][r], column[r]->GetFloat());
  1657. }
  1658. }
  1659. }
  1660. }
  1661. }
  1662. // clang-format off
  1663. INSTANTIATE_TEST_SUITE_P(TestCase, FloatMatrixInstructionFoldingTest,
  1664. ::testing::Values(
  1665. // Test case 0: OpTranspose square null matrix
  1666. InstructionFoldingCase<std::vector<std::vector<float>>>(
  1667. Header() + "%main = OpFunction %void None %void_func\n" +
  1668. "%main_lab = OpLabel\n" +
  1669. "%2 = OpTranspose %mat4v4float %mat4v4float_null\n" +
  1670. "OpReturn\n" +
  1671. "OpFunctionEnd",
  1672. 2, {{0.0f, 0.0f, 0.0f, 0.0f},{0.0f, 0.0f, 0.0f, 0.0f},{0.0f, 0.0f, 0.0f, 0.0f},{0.0f, 0.0f, 0.0f, 0.0f}}),
  1673. // Test case 1: OpTranspose rectangular null matrix
  1674. InstructionFoldingCase<std::vector<std::vector<float>>>(
  1675. Header() + "%main = OpFunction %void None %void_func\n" +
  1676. "%main_lab = OpLabel\n" +
  1677. "%2 = OpTranspose %mat4v2float %mat2v4float_null\n" +
  1678. "OpReturn\n" +
  1679. "OpFunctionEnd",
  1680. 2, {{0.0f, 0.0f},{0.0f, 0.0f},{0.0f, 0.0f},{0.0f, 0.0f}}),
  1681. InstructionFoldingCase<std::vector<std::vector<float>>>(
  1682. Header() + "%main = OpFunction %void None %void_func\n" +
  1683. "%main_lab = OpLabel\n" +
  1684. "%2 = OpTranspose %mat4v4float %mat4v4float_1_2_3_4\n" +
  1685. "OpReturn\n" +
  1686. "OpFunctionEnd",
  1687. 2, {{1.0f, 1.0f, 1.0f, 1.0f},{2.0f, 2.0f, 2.0f, 2.0f},{3.0f, 3.0f, 3.0f, 3.0f},{4.0f, 4.0f, 4.0f, 4.0f}})
  1688. ));
  1689. // clang-format on
  1690. using BooleanInstructionFoldingTest =
  1691. ::testing::TestWithParam<InstructionFoldingCase<bool>>;
  1692. TEST_P(BooleanInstructionFoldingTest, Case) {
  1693. const auto& tc = GetParam();
  1694. std::unique_ptr<IRContext> context;
  1695. Instruction* inst;
  1696. std::tie(context, inst) =
  1697. FoldInstruction(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_1);
  1698. CheckForExpectedScalarConstant(
  1699. inst, tc.expected_result,
  1700. [](const analysis::Constant* c) { return c->AsBoolConstant()->value(); });
  1701. }
  1702. // clang-format off
  1703. INSTANTIATE_TEST_SUITE_P(TestCase, BooleanInstructionFoldingTest,
  1704. ::testing::Values(
  1705. // Test case 0: fold true || n
  1706. InstructionFoldingCase<bool>(
  1707. Header() + "%main = OpFunction %void None %void_func\n" +
  1708. "%main_lab = OpLabel\n" +
  1709. "%n = OpVariable %_ptr_bool Function\n" +
  1710. "%load = OpLoad %bool %n\n" +
  1711. "%2 = OpLogicalOr %bool %true %load\n" +
  1712. "OpReturn\n" +
  1713. "OpFunctionEnd",
  1714. 2, true),
  1715. // Test case 1: fold n || true
  1716. InstructionFoldingCase<bool>(
  1717. Header() + "%main = OpFunction %void None %void_func\n" +
  1718. "%main_lab = OpLabel\n" +
  1719. "%n = OpVariable %_ptr_bool Function\n" +
  1720. "%load = OpLoad %bool %n\n" +
  1721. "%2 = OpLogicalOr %bool %load %true\n" +
  1722. "OpReturn\n" +
  1723. "OpFunctionEnd",
  1724. 2, true),
  1725. // Test case 2: fold false && n
  1726. InstructionFoldingCase<bool>(
  1727. Header() + "%main = OpFunction %void None %void_func\n" +
  1728. "%main_lab = OpLabel\n" +
  1729. "%n = OpVariable %_ptr_bool Function\n" +
  1730. "%load = OpLoad %bool %n\n" +
  1731. "%2 = OpLogicalAnd %bool %false %load\n" +
  1732. "OpReturn\n" +
  1733. "OpFunctionEnd",
  1734. 2, false),
  1735. // Test case 3: fold n && false
  1736. InstructionFoldingCase<bool>(
  1737. Header() + "%main = OpFunction %void None %void_func\n" +
  1738. "%main_lab = OpLabel\n" +
  1739. "%n = OpVariable %_ptr_bool Function\n" +
  1740. "%load = OpLoad %bool %n\n" +
  1741. "%2 = OpLogicalAnd %bool %load %false\n" +
  1742. "OpReturn\n" +
  1743. "OpFunctionEnd",
  1744. 2, false),
  1745. // Test case 4: fold n < 0 (unsigned)
  1746. InstructionFoldingCase<bool>(
  1747. Header() + "%main = OpFunction %void None %void_func\n" +
  1748. "%main_lab = OpLabel\n" +
  1749. "%n = OpVariable %_ptr_uint Function\n" +
  1750. "%load = OpLoad %uint %n\n" +
  1751. "%2 = OpULessThan %bool %load %uint_0\n" +
  1752. "OpReturn\n" +
  1753. "OpFunctionEnd",
  1754. 2, false),
  1755. // Test case 5: fold UINT_MAX < n (unsigned)
  1756. InstructionFoldingCase<bool>(
  1757. Header() + "%main = OpFunction %void None %void_func\n" +
  1758. "%main_lab = OpLabel\n" +
  1759. "%n = OpVariable %_ptr_uint Function\n" +
  1760. "%load = OpLoad %uint %n\n" +
  1761. "%2 = OpULessThan %bool %uint_max %load\n" +
  1762. "OpReturn\n" +
  1763. "OpFunctionEnd",
  1764. 2, false),
  1765. // Test case 6: fold INT_MAX < n (signed)
  1766. InstructionFoldingCase<bool>(
  1767. Header() + "%main = OpFunction %void None %void_func\n" +
  1768. "%main_lab = OpLabel\n" +
  1769. "%n = OpVariable %_ptr_int Function\n" +
  1770. "%load = OpLoad %int %n\n" +
  1771. "%2 = OpSLessThan %bool %int_max %load\n" +
  1772. "OpReturn\n" +
  1773. "OpFunctionEnd",
  1774. 2, false),
  1775. // Test case 7: fold n < INT_MIN (signed)
  1776. InstructionFoldingCase<bool>(
  1777. Header() + "%main = OpFunction %void None %void_func\n" +
  1778. "%main_lab = OpLabel\n" +
  1779. "%n = OpVariable %_ptr_int Function\n" +
  1780. "%load = OpLoad %int %n\n" +
  1781. "%2 = OpSLessThan %bool %load %int_min\n" +
  1782. "OpReturn\n" +
  1783. "OpFunctionEnd",
  1784. 2, false),
  1785. // Test case 8: fold 0 > n (unsigned)
  1786. InstructionFoldingCase<bool>(
  1787. Header() + "%main = OpFunction %void None %void_func\n" +
  1788. "%main_lab = OpLabel\n" +
  1789. "%n = OpVariable %_ptr_uint Function\n" +
  1790. "%load = OpLoad %uint %n\n" +
  1791. "%2 = OpUGreaterThan %bool %uint_0 %load\n" +
  1792. "OpReturn\n" +
  1793. "OpFunctionEnd",
  1794. 2, false),
  1795. // Test case 9: fold n > UINT_MAX (unsigned)
  1796. InstructionFoldingCase<bool>(
  1797. Header() + "%main = OpFunction %void None %void_func\n" +
  1798. "%main_lab = OpLabel\n" +
  1799. "%n = OpVariable %_ptr_uint Function\n" +
  1800. "%load = OpLoad %uint %n\n" +
  1801. "%2 = OpUGreaterThan %bool %load %uint_max\n" +
  1802. "OpReturn\n" +
  1803. "OpFunctionEnd",
  1804. 2, false),
  1805. // Test case 10: fold n > INT_MAX (signed)
  1806. InstructionFoldingCase<bool>(
  1807. Header() + "%main = OpFunction %void None %void_func\n" +
  1808. "%main_lab = OpLabel\n" +
  1809. "%n = OpVariable %_ptr_int Function\n" +
  1810. "%load = OpLoad %int %n\n" +
  1811. "%2 = OpSGreaterThan %bool %load %int_max\n" +
  1812. "OpReturn\n" +
  1813. "OpFunctionEnd",
  1814. 2, false),
  1815. // Test case 11: fold INT_MIN > n (signed)
  1816. InstructionFoldingCase<bool>(
  1817. Header() + "%main = OpFunction %void None %void_func\n" +
  1818. "%main_lab = OpLabel\n" +
  1819. "%n = OpVariable %_ptr_uint Function\n" +
  1820. "%load = OpLoad %uint %n\n" +
  1821. "%2 = OpSGreaterThan %bool %int_min %load\n" +
  1822. "OpReturn\n" +
  1823. "OpFunctionEnd",
  1824. 2, false),
  1825. // Test case 12: fold 0 <= n (unsigned)
  1826. InstructionFoldingCase<bool>(
  1827. Header() + "%main = OpFunction %void None %void_func\n" +
  1828. "%main_lab = OpLabel\n" +
  1829. "%n = OpVariable %_ptr_uint Function\n" +
  1830. "%load = OpLoad %uint %n\n" +
  1831. "%2 = OpULessThanEqual %bool %uint_0 %load\n" +
  1832. "OpReturn\n" +
  1833. "OpFunctionEnd",
  1834. 2, true),
  1835. // Test case 13: fold n <= UINT_MAX (unsigned)
  1836. InstructionFoldingCase<bool>(
  1837. Header() + "%main = OpFunction %void None %void_func\n" +
  1838. "%main_lab = OpLabel\n" +
  1839. "%n = OpVariable %_ptr_uint Function\n" +
  1840. "%load = OpLoad %uint %n\n" +
  1841. "%2 = OpULessThanEqual %bool %load %uint_max\n" +
  1842. "OpReturn\n" +
  1843. "OpFunctionEnd",
  1844. 2, true),
  1845. // Test case 14: fold INT_MIN <= n (signed)
  1846. InstructionFoldingCase<bool>(
  1847. Header() + "%main = OpFunction %void None %void_func\n" +
  1848. "%main_lab = OpLabel\n" +
  1849. "%n = OpVariable %_ptr_int Function\n" +
  1850. "%load = OpLoad %int %n\n" +
  1851. "%2 = OpSLessThanEqual %bool %int_min %load\n" +
  1852. "OpReturn\n" +
  1853. "OpFunctionEnd",
  1854. 2, true),
  1855. // Test case 15: fold n <= INT_MAX (signed)
  1856. InstructionFoldingCase<bool>(
  1857. Header() + "%main = OpFunction %void None %void_func\n" +
  1858. "%main_lab = OpLabel\n" +
  1859. "%n = OpVariable %_ptr_int Function\n" +
  1860. "%load = OpLoad %int %n\n" +
  1861. "%2 = OpSLessThanEqual %bool %load %int_max\n" +
  1862. "OpReturn\n" +
  1863. "OpFunctionEnd",
  1864. 2, true),
  1865. // Test case 16: fold n >= 0 (unsigned)
  1866. InstructionFoldingCase<bool>(
  1867. Header() + "%main = OpFunction %void None %void_func\n" +
  1868. "%main_lab = OpLabel\n" +
  1869. "%n = OpVariable %_ptr_uint Function\n" +
  1870. "%load = OpLoad %uint %n\n" +
  1871. "%2 = OpUGreaterThanEqual %bool %load %uint_0\n" +
  1872. "OpReturn\n" +
  1873. "OpFunctionEnd",
  1874. 2, true),
  1875. // Test case 17: fold UINT_MAX >= n (unsigned)
  1876. InstructionFoldingCase<bool>(
  1877. Header() + "%main = OpFunction %void None %void_func\n" +
  1878. "%main_lab = OpLabel\n" +
  1879. "%n = OpVariable %_ptr_uint Function\n" +
  1880. "%load = OpLoad %uint %n\n" +
  1881. "%2 = OpUGreaterThanEqual %bool %uint_max %load\n" +
  1882. "OpReturn\n" +
  1883. "OpFunctionEnd",
  1884. 2, true),
  1885. // Test case 18: fold n >= INT_MIN (signed)
  1886. InstructionFoldingCase<bool>(
  1887. Header() + "%main = OpFunction %void None %void_func\n" +
  1888. "%main_lab = OpLabel\n" +
  1889. "%n = OpVariable %_ptr_int Function\n" +
  1890. "%load = OpLoad %int %n\n" +
  1891. "%2 = OpSGreaterThanEqual %bool %load %int_min\n" +
  1892. "OpReturn\n" +
  1893. "OpFunctionEnd",
  1894. 2, true),
  1895. // Test case 19: fold INT_MAX >= n (signed)
  1896. InstructionFoldingCase<bool>(
  1897. Header() + "%main = OpFunction %void None %void_func\n" +
  1898. "%main_lab = OpLabel\n" +
  1899. "%n = OpVariable %_ptr_int Function\n" +
  1900. "%load = OpLoad %int %n\n" +
  1901. "%2 = OpSGreaterThanEqual %bool %int_max %load\n" +
  1902. "OpReturn\n" +
  1903. "OpFunctionEnd",
  1904. 2, true)
  1905. ));
  1906. INSTANTIATE_TEST_SUITE_P(FClampAndCmpLHS, BooleanInstructionFoldingTest,
  1907. ::testing::Values(
  1908. // Test case 0: fold 0.0 > clamp(n, 0.0, 1.0)
  1909. InstructionFoldingCase<bool>(
  1910. Header() + "%main = OpFunction %void None %void_func\n" +
  1911. "%main_lab = OpLabel\n" +
  1912. "%n = OpVariable %_ptr_float Function\n" +
  1913. "%ld = OpLoad %float %n\n" +
  1914. "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
  1915. "%2 = OpFOrdGreaterThan %bool %float_0 %clamp\n" +
  1916. "OpReturn\n" +
  1917. "OpFunctionEnd",
  1918. 2, false),
  1919. // Test case 1: fold 0.0 > clamp(n, -1.0, -1.0)
  1920. InstructionFoldingCase<bool>(
  1921. Header() + "%main = OpFunction %void None %void_func\n" +
  1922. "%main_lab = OpLabel\n" +
  1923. "%n = OpVariable %_ptr_float Function\n" +
  1924. "%ld = OpLoad %float %n\n" +
  1925. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_n1\n" +
  1926. "%2 = OpFOrdGreaterThan %bool %float_0 %clamp\n" +
  1927. "OpReturn\n" +
  1928. "OpFunctionEnd",
  1929. 2, true),
  1930. // Test case 2: fold 0.0 >= clamp(n, 1, 2)
  1931. InstructionFoldingCase<bool>(
  1932. Header() + "%main = OpFunction %void None %void_func\n" +
  1933. "%main_lab = OpLabel\n" +
  1934. "%n = OpVariable %_ptr_float Function\n" +
  1935. "%ld = OpLoad %float %n\n" +
  1936. "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
  1937. "%2 = OpFOrdGreaterThanEqual %bool %float_0 %clamp\n" +
  1938. "OpReturn\n" +
  1939. "OpFunctionEnd",
  1940. 2, false),
  1941. // Test case 3: fold 0.0 >= clamp(n, -1.0, 0.0)
  1942. InstructionFoldingCase<bool>(
  1943. Header() + "%main = OpFunction %void None %void_func\n" +
  1944. "%main_lab = OpLabel\n" +
  1945. "%n = OpVariable %_ptr_float Function\n" +
  1946. "%ld = OpLoad %float %n\n" +
  1947. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
  1948. "%2 = OpFOrdGreaterThanEqual %bool %float_0 %clamp\n" +
  1949. "OpReturn\n" +
  1950. "OpFunctionEnd",
  1951. 2, true),
  1952. // Test case 4: fold 0.0 <= clamp(n, 0.0, 1.0)
  1953. InstructionFoldingCase<bool>(
  1954. Header() + "%main = OpFunction %void None %void_func\n" +
  1955. "%main_lab = OpLabel\n" +
  1956. "%n = OpVariable %_ptr_float Function\n" +
  1957. "%ld = OpLoad %float %n\n" +
  1958. "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
  1959. "%2 = OpFOrdLessThanEqual %bool %float_0 %clamp\n" +
  1960. "OpReturn\n" +
  1961. "OpFunctionEnd",
  1962. 2, true),
  1963. // Test case 5: fold 0.0 <= clamp(n, -1.0, -1.0)
  1964. InstructionFoldingCase<bool>(
  1965. Header() + "%main = OpFunction %void None %void_func\n" +
  1966. "%main_lab = OpLabel\n" +
  1967. "%n = OpVariable %_ptr_float Function\n" +
  1968. "%ld = OpLoad %float %n\n" +
  1969. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_n1\n" +
  1970. "%2 = OpFOrdLessThanEqual %bool %float_0 %clamp\n" +
  1971. "OpReturn\n" +
  1972. "OpFunctionEnd",
  1973. 2, false),
  1974. // Test case 6: fold 0.0 < clamp(n, 1, 2)
  1975. InstructionFoldingCase<bool>(
  1976. Header() + "%main = OpFunction %void None %void_func\n" +
  1977. "%main_lab = OpLabel\n" +
  1978. "%n = OpVariable %_ptr_float Function\n" +
  1979. "%ld = OpLoad %float %n\n" +
  1980. "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
  1981. "%2 = OpFOrdLessThan %bool %float_0 %clamp\n" +
  1982. "OpReturn\n" +
  1983. "OpFunctionEnd",
  1984. 2, true),
  1985. // Test case 7: fold 0.0 < clamp(n, -1.0, 0.0)
  1986. InstructionFoldingCase<bool>(
  1987. Header() + "%main = OpFunction %void None %void_func\n" +
  1988. "%main_lab = OpLabel\n" +
  1989. "%n = OpVariable %_ptr_float Function\n" +
  1990. "%ld = OpLoad %float %n\n" +
  1991. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
  1992. "%2 = OpFOrdLessThan %bool %float_0 %clamp\n" +
  1993. "OpReturn\n" +
  1994. "OpFunctionEnd",
  1995. 2, false),
  1996. // Test case 8: fold 0.0 > clamp(n, 0.0, 1.0)
  1997. InstructionFoldingCase<bool>(
  1998. Header() + "%main = OpFunction %void None %void_func\n" +
  1999. "%main_lab = OpLabel\n" +
  2000. "%n = OpVariable %_ptr_float Function\n" +
  2001. "%ld = OpLoad %float %n\n" +
  2002. "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
  2003. "%2 = OpFUnordGreaterThan %bool %float_0 %clamp\n" +
  2004. "OpReturn\n" +
  2005. "OpFunctionEnd",
  2006. 2, false),
  2007. // Test case 9: fold 0.0 > clamp(n, -1.0, -1.0)
  2008. InstructionFoldingCase<bool>(
  2009. Header() + "%main = OpFunction %void None %void_func\n" +
  2010. "%main_lab = OpLabel\n" +
  2011. "%n = OpVariable %_ptr_float Function\n" +
  2012. "%ld = OpLoad %float %n\n" +
  2013. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_n1\n" +
  2014. "%2 = OpFUnordGreaterThan %bool %float_0 %clamp\n" +
  2015. "OpReturn\n" +
  2016. "OpFunctionEnd",
  2017. 2, true),
  2018. // Test case 10: fold 0.0 >= clamp(n, 1, 2)
  2019. InstructionFoldingCase<bool>(
  2020. Header() + "%main = OpFunction %void None %void_func\n" +
  2021. "%main_lab = OpLabel\n" +
  2022. "%n = OpVariable %_ptr_float Function\n" +
  2023. "%ld = OpLoad %float %n\n" +
  2024. "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
  2025. "%2 = OpFUnordGreaterThanEqual %bool %float_0 %clamp\n" +
  2026. "OpReturn\n" +
  2027. "OpFunctionEnd",
  2028. 2, false),
  2029. // Test case 11: fold 0.0 >= clamp(n, -1.0, 0.0)
  2030. InstructionFoldingCase<bool>(
  2031. Header() + "%main = OpFunction %void None %void_func\n" +
  2032. "%main_lab = OpLabel\n" +
  2033. "%n = OpVariable %_ptr_float Function\n" +
  2034. "%ld = OpLoad %float %n\n" +
  2035. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
  2036. "%2 = OpFUnordGreaterThanEqual %bool %float_0 %clamp\n" +
  2037. "OpReturn\n" +
  2038. "OpFunctionEnd",
  2039. 2, true),
  2040. // Test case 12: fold 0.0 <= clamp(n, 0.0, 1.0)
  2041. InstructionFoldingCase<bool>(
  2042. Header() + "%main = OpFunction %void None %void_func\n" +
  2043. "%main_lab = OpLabel\n" +
  2044. "%n = OpVariable %_ptr_float Function\n" +
  2045. "%ld = OpLoad %float %n\n" +
  2046. "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
  2047. "%2 = OpFUnordLessThanEqual %bool %float_0 %clamp\n" +
  2048. "OpReturn\n" +
  2049. "OpFunctionEnd",
  2050. 2, true),
  2051. // Test case 13: fold 0.0 <= clamp(n, -1.0, -1.0)
  2052. InstructionFoldingCase<bool>(
  2053. Header() + "%main = OpFunction %void None %void_func\n" +
  2054. "%main_lab = OpLabel\n" +
  2055. "%n = OpVariable %_ptr_float Function\n" +
  2056. "%ld = OpLoad %float %n\n" +
  2057. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_n1\n" +
  2058. "%2 = OpFUnordLessThanEqual %bool %float_0 %clamp\n" +
  2059. "OpReturn\n" +
  2060. "OpFunctionEnd",
  2061. 2, false),
  2062. // Test case 14: fold 0.0 < clamp(n, 1, 2)
  2063. InstructionFoldingCase<bool>(
  2064. Header() + "%main = OpFunction %void None %void_func\n" +
  2065. "%main_lab = OpLabel\n" +
  2066. "%n = OpVariable %_ptr_float Function\n" +
  2067. "%ld = OpLoad %float %n\n" +
  2068. "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
  2069. "%2 = OpFUnordLessThan %bool %float_0 %clamp\n" +
  2070. "OpReturn\n" +
  2071. "OpFunctionEnd",
  2072. 2, true),
  2073. // Test case 15: fold 0.0 < clamp(n, -1.0, 0.0)
  2074. InstructionFoldingCase<bool>(
  2075. Header() + "%main = OpFunction %void None %void_func\n" +
  2076. "%main_lab = OpLabel\n" +
  2077. "%n = OpVariable %_ptr_float Function\n" +
  2078. "%ld = OpLoad %float %n\n" +
  2079. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
  2080. "%2 = OpFUnordLessThan %bool %float_0 %clamp\n" +
  2081. "OpReturn\n" +
  2082. "OpFunctionEnd",
  2083. 2, false)
  2084. ));
  2085. INSTANTIATE_TEST_SUITE_P(FClampAndCmpRHS, BooleanInstructionFoldingTest,
  2086. ::testing::Values(
  2087. // Test case 0: fold clamp(n, 0.0, 1.0) > 1.0
  2088. InstructionFoldingCase<bool>(
  2089. Header() + "%main = OpFunction %void None %void_func\n" +
  2090. "%main_lab = OpLabel\n" +
  2091. "%n = OpVariable %_ptr_float Function\n" +
  2092. "%ld = OpLoad %float %n\n" +
  2093. "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
  2094. "%2 = OpFOrdGreaterThan %bool %clamp %float_1\n" +
  2095. "OpReturn\n" +
  2096. "OpFunctionEnd",
  2097. 2, false),
  2098. // Test case 1: fold clamp(n, 1.0, 1.0) > 0.0
  2099. InstructionFoldingCase<bool>(
  2100. Header() + "%main = OpFunction %void None %void_func\n" +
  2101. "%main_lab = OpLabel\n" +
  2102. "%n = OpVariable %_ptr_float Function\n" +
  2103. "%ld = OpLoad %float %n\n" +
  2104. "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_1\n" +
  2105. "%2 = OpFOrdGreaterThan %bool %clamp %float_0\n" +
  2106. "OpReturn\n" +
  2107. "OpFunctionEnd",
  2108. 2, true),
  2109. // Test case 2: fold clamp(n, 1, 2) >= 0.0
  2110. InstructionFoldingCase<bool>(
  2111. Header() + "%main = OpFunction %void None %void_func\n" +
  2112. "%main_lab = OpLabel\n" +
  2113. "%n = OpVariable %_ptr_float Function\n" +
  2114. "%ld = OpLoad %float %n\n" +
  2115. "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
  2116. "%2 = OpFOrdGreaterThanEqual %bool %clamp %float_0\n" +
  2117. "OpReturn\n" +
  2118. "OpFunctionEnd",
  2119. 2, true),
  2120. // Test case 3: fold clamp(n, 1.0, 2.0) >= 3.0
  2121. InstructionFoldingCase<bool>(
  2122. Header() + "%main = OpFunction %void None %void_func\n" +
  2123. "%main_lab = OpLabel\n" +
  2124. "%n = OpVariable %_ptr_float Function\n" +
  2125. "%ld = OpLoad %float %n\n" +
  2126. "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
  2127. "%2 = OpFOrdGreaterThanEqual %bool %clamp %float_3\n" +
  2128. "OpReturn\n" +
  2129. "OpFunctionEnd",
  2130. 2, false),
  2131. // Test case 4: fold clamp(n, 0.0, 1.0) <= 1.0
  2132. InstructionFoldingCase<bool>(
  2133. Header() + "%main = OpFunction %void None %void_func\n" +
  2134. "%main_lab = OpLabel\n" +
  2135. "%n = OpVariable %_ptr_float Function\n" +
  2136. "%ld = OpLoad %float %n\n" +
  2137. "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
  2138. "%2 = OpFOrdLessThanEqual %bool %clamp %float_1\n" +
  2139. "OpReturn\n" +
  2140. "OpFunctionEnd",
  2141. 2, true),
  2142. // Test case 5: fold clamp(n, 1.0, 2.0) <= 0.0
  2143. InstructionFoldingCase<bool>(
  2144. Header() + "%main = OpFunction %void None %void_func\n" +
  2145. "%main_lab = OpLabel\n" +
  2146. "%n = OpVariable %_ptr_float Function\n" +
  2147. "%ld = OpLoad %float %n\n" +
  2148. "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
  2149. "%2 = OpFOrdLessThanEqual %bool %clamp %float_0\n" +
  2150. "OpReturn\n" +
  2151. "OpFunctionEnd",
  2152. 2, false),
  2153. // Test case 6: fold clamp(n, 1, 2) < 3
  2154. InstructionFoldingCase<bool>(
  2155. Header() + "%main = OpFunction %void None %void_func\n" +
  2156. "%main_lab = OpLabel\n" +
  2157. "%n = OpVariable %_ptr_float Function\n" +
  2158. "%ld = OpLoad %float %n\n" +
  2159. "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
  2160. "%2 = OpFOrdLessThan %bool %clamp %float_3\n" +
  2161. "OpReturn\n" +
  2162. "OpFunctionEnd",
  2163. 2, true),
  2164. // Test case 7: fold clamp(n, -1.0, 0.0) < -1.0
  2165. InstructionFoldingCase<bool>(
  2166. Header() + "%main = OpFunction %void None %void_func\n" +
  2167. "%main_lab = OpLabel\n" +
  2168. "%n = OpVariable %_ptr_float Function\n" +
  2169. "%ld = OpLoad %float %n\n" +
  2170. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
  2171. "%2 = OpFOrdLessThan %bool %clamp %float_n1\n" +
  2172. "OpReturn\n" +
  2173. "OpFunctionEnd",
  2174. 2, false),
  2175. // Test case 8: fold clamp(n, 0.0, 1.0) > 1.0
  2176. InstructionFoldingCase<bool>(
  2177. Header() + "%main = OpFunction %void None %void_func\n" +
  2178. "%main_lab = OpLabel\n" +
  2179. "%n = OpVariable %_ptr_float Function\n" +
  2180. "%ld = OpLoad %float %n\n" +
  2181. "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
  2182. "%2 = OpFUnordGreaterThan %bool %clamp %float_1\n" +
  2183. "OpReturn\n" +
  2184. "OpFunctionEnd",
  2185. 2, false),
  2186. // Test case 9: fold clamp(n, 1.0, 2.0) > 0.0
  2187. InstructionFoldingCase<bool>(
  2188. Header() + "%main = OpFunction %void None %void_func\n" +
  2189. "%main_lab = OpLabel\n" +
  2190. "%n = OpVariable %_ptr_float Function\n" +
  2191. "%ld = OpLoad %float %n\n" +
  2192. "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
  2193. "%2 = OpFUnordGreaterThan %bool %clamp %float_0\n" +
  2194. "OpReturn\n" +
  2195. "OpFunctionEnd",
  2196. 2, true),
  2197. // Test case 10: fold clamp(n, 1, 2) >= 3.0
  2198. InstructionFoldingCase<bool>(
  2199. Header() + "%main = OpFunction %void None %void_func\n" +
  2200. "%main_lab = OpLabel\n" +
  2201. "%n = OpVariable %_ptr_float Function\n" +
  2202. "%ld = OpLoad %float %n\n" +
  2203. "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
  2204. "%2 = OpFUnordGreaterThanEqual %bool %clamp %float_3\n" +
  2205. "OpReturn\n" +
  2206. "OpFunctionEnd",
  2207. 2, false),
  2208. // Test case 11: fold clamp(n, -1.0, 0.0) >= -1.0
  2209. InstructionFoldingCase<bool>(
  2210. Header() + "%main = OpFunction %void None %void_func\n" +
  2211. "%main_lab = OpLabel\n" +
  2212. "%n = OpVariable %_ptr_float Function\n" +
  2213. "%ld = OpLoad %float %n\n" +
  2214. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
  2215. "%2 = OpFUnordGreaterThanEqual %bool %clamp %float_n1\n" +
  2216. "OpReturn\n" +
  2217. "OpFunctionEnd",
  2218. 2, true),
  2219. // Test case 12: fold clamp(n, 0.0, 1.0) <= 1.0
  2220. InstructionFoldingCase<bool>(
  2221. Header() + "%main = OpFunction %void None %void_func\n" +
  2222. "%main_lab = OpLabel\n" +
  2223. "%n = OpVariable %_ptr_float Function\n" +
  2224. "%ld = OpLoad %float %n\n" +
  2225. "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
  2226. "%2 = OpFUnordLessThanEqual %bool %clamp %float_1\n" +
  2227. "OpReturn\n" +
  2228. "OpFunctionEnd",
  2229. 2, true),
  2230. // Test case 13: fold clamp(n, 1.0, 1.0) <= 0.0
  2231. InstructionFoldingCase<bool>(
  2232. Header() + "%main = OpFunction %void None %void_func\n" +
  2233. "%main_lab = OpLabel\n" +
  2234. "%n = OpVariable %_ptr_float Function\n" +
  2235. "%ld = OpLoad %float %n\n" +
  2236. "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_1\n" +
  2237. "%2 = OpFUnordLessThanEqual %bool %clamp %float_0\n" +
  2238. "OpReturn\n" +
  2239. "OpFunctionEnd",
  2240. 2, false),
  2241. // Test case 14: fold clamp(n, 1, 2) < 3
  2242. InstructionFoldingCase<bool>(
  2243. Header() + "%main = OpFunction %void None %void_func\n" +
  2244. "%main_lab = OpLabel\n" +
  2245. "%n = OpVariable %_ptr_float Function\n" +
  2246. "%ld = OpLoad %float %n\n" +
  2247. "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
  2248. "%2 = OpFUnordLessThan %bool %clamp %float_3\n" +
  2249. "OpReturn\n" +
  2250. "OpFunctionEnd",
  2251. 2, true),
  2252. // Test case 15: fold clamp(n, -1.0, 0.0) < -1.0
  2253. InstructionFoldingCase<bool>(
  2254. Header() + "%main = OpFunction %void None %void_func\n" +
  2255. "%main_lab = OpLabel\n" +
  2256. "%n = OpVariable %_ptr_float Function\n" +
  2257. "%ld = OpLoad %float %n\n" +
  2258. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
  2259. "%2 = OpFUnordLessThan %bool %clamp %float_n1\n" +
  2260. "OpReturn\n" +
  2261. "OpFunctionEnd",
  2262. 2, false),
  2263. // Test case 16: fold clamp(n, -1.0, 0.0) < -1.0 (one test for double)
  2264. InstructionFoldingCase<bool>(
  2265. Header() + "%main = OpFunction %void None %void_func\n" +
  2266. "%main_lab = OpLabel\n" +
  2267. "%n = OpVariable %_ptr_double Function\n" +
  2268. "%ld = OpLoad %double %n\n" +
  2269. "%clamp = OpExtInst %double %1 FClamp %ld %double_n1 %double_0\n" +
  2270. "%2 = OpFUnordLessThan %bool %clamp %double_n1\n" +
  2271. "OpReturn\n" +
  2272. "OpFunctionEnd",
  2273. 2, false)
  2274. ));
  2275. // clang-format on
  2276. using FloatInstructionFoldingTest =
  2277. ::testing::TestWithParam<InstructionFoldingCase<float>>;
  2278. TEST_P(FloatInstructionFoldingTest, Case) {
  2279. const auto& tc = GetParam();
  2280. std::unique_ptr<IRContext> context;
  2281. Instruction* inst;
  2282. std::tie(context, inst) =
  2283. FoldInstruction(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_1);
  2284. CheckForExpectedScalarConstant(inst, tc.expected_result,
  2285. [](const analysis::Constant* c) {
  2286. return c->AsFloatConstant()->GetFloatValue();
  2287. });
  2288. }
  2289. // Not testing NaNs because there are no expectations concerning NaNs according
  2290. // to the "Precision and Operation of SPIR-V Instructions" section of the Vulkan
  2291. // specification.
  2292. // clang-format off
  2293. INSTANTIATE_TEST_SUITE_P(FloatConstantFoldingTest, FloatInstructionFoldingTest,
  2294. ::testing::Values(
  2295. // Test case 0: Fold 2.0 - 1.0
  2296. InstructionFoldingCase<float>(
  2297. Header() + "%main = OpFunction %void None %void_func\n" +
  2298. "%main_lab = OpLabel\n" +
  2299. "%2 = OpFSub %float %float_2 %float_1\n" +
  2300. "OpReturn\n" +
  2301. "OpFunctionEnd",
  2302. 2, 1.0),
  2303. // Test case 1: Fold 2.0 + 1.0
  2304. InstructionFoldingCase<float>(
  2305. Header() + "%main = OpFunction %void None %void_func\n" +
  2306. "%main_lab = OpLabel\n" +
  2307. "%2 = OpFAdd %float %float_2 %float_1\n" +
  2308. "OpReturn\n" +
  2309. "OpFunctionEnd",
  2310. 2, 3.0),
  2311. // Test case 2: Fold 3.0 * 2.0
  2312. InstructionFoldingCase<float>(
  2313. Header() + "%main = OpFunction %void None %void_func\n" +
  2314. "%main_lab = OpLabel\n" +
  2315. "%2 = OpFMul %float %float_3 %float_2\n" +
  2316. "OpReturn\n" +
  2317. "OpFunctionEnd",
  2318. 2, 6.0),
  2319. // Test case 3: Fold 1.0 / 2.0
  2320. InstructionFoldingCase<float>(
  2321. Header() + "%main = OpFunction %void None %void_func\n" +
  2322. "%main_lab = OpLabel\n" +
  2323. "%2 = OpFDiv %float %float_1 %float_2\n" +
  2324. "OpReturn\n" +
  2325. "OpFunctionEnd",
  2326. 2, 0.5),
  2327. // Test case 4: Fold 1.0 / 0.0
  2328. InstructionFoldingCase<float>(
  2329. Header() + "%main = OpFunction %void None %void_func\n" +
  2330. "%main_lab = OpLabel\n" +
  2331. "%2 = OpFDiv %float %float_1 %float_0\n" +
  2332. "OpReturn\n" +
  2333. "OpFunctionEnd",
  2334. 2, std::numeric_limits<float>::infinity()),
  2335. // Test case 5: Fold -1.0 / 0.0
  2336. InstructionFoldingCase<float>(
  2337. Header() + "%main = OpFunction %void None %void_func\n" +
  2338. "%main_lab = OpLabel\n" +
  2339. "%2 = OpFDiv %float %float_n1 %float_0\n" +
  2340. "OpReturn\n" +
  2341. "OpFunctionEnd",
  2342. 2, -std::numeric_limits<float>::infinity()),
  2343. // Test case 6: Fold (2.0, 3.0) dot (2.0, 0.5)
  2344. InstructionFoldingCase<float>(
  2345. Header() + "%main = OpFunction %void None %void_func\n" +
  2346. "%main_lab = OpLabel\n" +
  2347. "%2 = OpDot %float %v2float_2_3 %v2float_2_0p5\n" +
  2348. "OpReturn\n" +
  2349. "OpFunctionEnd",
  2350. 2, 5.5f),
  2351. // Test case 7: Fold (0.0, 0.0) dot v
  2352. InstructionFoldingCase<float>(
  2353. Header() + "%main = OpFunction %void None %void_func\n" +
  2354. "%main_lab = OpLabel\n" +
  2355. "%v = OpVariable %_ptr_v2float Function\n" +
  2356. "%2 = OpLoad %v2float %v\n" +
  2357. "%3 = OpDot %float %v2float_0_0 %2\n" +
  2358. "OpReturn\n" +
  2359. "OpFunctionEnd",
  2360. 3, 0.0f),
  2361. // Test case 8: Fold v dot (0.0, 0.0)
  2362. InstructionFoldingCase<float>(
  2363. Header() + "%main = OpFunction %void None %void_func\n" +
  2364. "%main_lab = OpLabel\n" +
  2365. "%v = OpVariable %_ptr_v2float Function\n" +
  2366. "%2 = OpLoad %v2float %v\n" +
  2367. "%3 = OpDot %float %2 %v2float_0_0\n" +
  2368. "OpReturn\n" +
  2369. "OpFunctionEnd",
  2370. 3, 0.0f),
  2371. // Test case 9: Fold Null dot v
  2372. InstructionFoldingCase<float>(
  2373. Header() + "%main = OpFunction %void None %void_func\n" +
  2374. "%main_lab = OpLabel\n" +
  2375. "%v = OpVariable %_ptr_v2float Function\n" +
  2376. "%2 = OpLoad %v2float %v\n" +
  2377. "%3 = OpDot %float %v2float_null %2\n" +
  2378. "OpReturn\n" +
  2379. "OpFunctionEnd",
  2380. 3, 0.0f),
  2381. // Test case 10: Fold v dot Null
  2382. InstructionFoldingCase<float>(
  2383. Header() + "%main = OpFunction %void None %void_func\n" +
  2384. "%main_lab = OpLabel\n" +
  2385. "%v = OpVariable %_ptr_v2float Function\n" +
  2386. "%2 = OpLoad %v2float %v\n" +
  2387. "%3 = OpDot %float %2 %v2float_null\n" +
  2388. "OpReturn\n" +
  2389. "OpFunctionEnd",
  2390. 3, 0.0f),
  2391. // Test case 11: Fold -2.0
  2392. InstructionFoldingCase<float>(
  2393. Header() + "%main = OpFunction %void None %void_func\n" +
  2394. "%main_lab = OpLabel\n" +
  2395. "%2 = OpFNegate %float %float_2\n" +
  2396. "OpReturn\n" +
  2397. "OpFunctionEnd",
  2398. 2, -2),
  2399. // Test case 12: QuantizeToF16 1.0
  2400. InstructionFoldingCase<float>(
  2401. Header() + "%main = OpFunction %void None %void_func\n" +
  2402. "%main_lab = OpLabel\n" +
  2403. "%2 = OpQuantizeToF16 %float %float_1\n" +
  2404. "OpReturn\n" +
  2405. "OpFunctionEnd",
  2406. 2, 1.0),
  2407. // Test case 13: QuantizeToF16 positive non exact
  2408. InstructionFoldingCase<float>(
  2409. Header() + "%main = OpFunction %void None %void_func\n" +
  2410. "%main_lab = OpLabel\n" +
  2411. "%2 = OpQuantizeToF16 %float %float_2049\n" +
  2412. "OpReturn\n" +
  2413. "OpFunctionEnd",
  2414. 2, 2048),
  2415. // Test case 14: QuantizeToF16 negative non exact
  2416. InstructionFoldingCase<float>(
  2417. Header() + "%main = OpFunction %void None %void_func\n" +
  2418. "%main_lab = OpLabel\n" +
  2419. "%2 = OpQuantizeToF16 %float %float_n2049\n" +
  2420. "OpReturn\n" +
  2421. "OpFunctionEnd",
  2422. 2, -2048),
  2423. // Test case 15: QuantizeToF16 large positive
  2424. InstructionFoldingCase<float>(
  2425. Header() + "%main = OpFunction %void None %void_func\n" +
  2426. "%main_lab = OpLabel\n" +
  2427. "%2 = OpQuantizeToF16 %float %float_1e16\n" +
  2428. "OpReturn\n" +
  2429. "OpFunctionEnd",
  2430. 2, std::numeric_limits<float>::infinity()),
  2431. // Test case 16: QuantizeToF16 large negative
  2432. InstructionFoldingCase<float>(
  2433. Header() + "%main = OpFunction %void None %void_func\n" +
  2434. "%main_lab = OpLabel\n" +
  2435. "%2 = OpQuantizeToF16 %float %float_n1e16\n" +
  2436. "OpReturn\n" +
  2437. "OpFunctionEnd",
  2438. 2, -std::numeric_limits<float>::infinity()),
  2439. // Test case 17: QuantizeToF16 small positive
  2440. InstructionFoldingCase<float>(
  2441. Header() + "%main = OpFunction %void None %void_func\n" +
  2442. "%main_lab = OpLabel\n" +
  2443. "%2 = OpQuantizeToF16 %float %float_1en16\n" +
  2444. "OpReturn\n" +
  2445. "OpFunctionEnd",
  2446. 2, 0.0),
  2447. // Test case 18: QuantizeToF16 small negative
  2448. InstructionFoldingCase<float>(
  2449. Header() + "%main = OpFunction %void None %void_func\n" +
  2450. "%main_lab = OpLabel\n" +
  2451. "%2 = OpQuantizeToF16 %float %float_n1en16\n" +
  2452. "OpReturn\n" +
  2453. "OpFunctionEnd",
  2454. 2, 0.0),
  2455. // Test case 19: QuantizeToF16 nan
  2456. InstructionFoldingCase<float>(
  2457. HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
  2458. "%main_lab = OpLabel\n" +
  2459. "%2 = OpQuantizeToF16 %float %float_nan\n" +
  2460. "OpReturn\n" +
  2461. "OpFunctionEnd",
  2462. 2, std::numeric_limits<float>::quiet_NaN()),
  2463. // Test case 20: FMix 1.0 4.0 0.2
  2464. InstructionFoldingCase<float>(
  2465. Header() + "%main = OpFunction %void None %void_func\n" +
  2466. "%main_lab = OpLabel\n" +
  2467. "%2 = OpExtInst %float %1 FMix %float_1 %float_4 %float_0p2\n" +
  2468. "OpReturn\n" +
  2469. "OpFunctionEnd",
  2470. 2, 1.6f),
  2471. // Test case 21: FMin 1.0 4.0
  2472. InstructionFoldingCase<float>(
  2473. Header() + "%main = OpFunction %void None %void_func\n" +
  2474. "%main_lab = OpLabel\n" +
  2475. "%2 = OpExtInst %float %1 FMin %float_1 %float_4\n" +
  2476. "OpReturn\n" +
  2477. "OpFunctionEnd",
  2478. 2, 1.0f),
  2479. // Test case 22: FMin 4.0 0.2
  2480. InstructionFoldingCase<float>(
  2481. Header() + "%main = OpFunction %void None %void_func\n" +
  2482. "%main_lab = OpLabel\n" +
  2483. "%2 = OpExtInst %float %1 FMin %float_4 %float_0p2\n" +
  2484. "OpReturn\n" +
  2485. "OpFunctionEnd",
  2486. 2, 0.2f),
  2487. // Test case 23: FMax 1.0 4.0
  2488. InstructionFoldingCase<float>(
  2489. Header() + "%main = OpFunction %void None %void_func\n" +
  2490. "%main_lab = OpLabel\n" +
  2491. "%2 = OpExtInst %float %1 FMax %float_1 %float_4\n" +
  2492. "OpReturn\n" +
  2493. "OpFunctionEnd",
  2494. 2, 4.0f),
  2495. // Test case 24: FMax 1.0 0.2
  2496. InstructionFoldingCase<float>(
  2497. Header() + "%main = OpFunction %void None %void_func\n" +
  2498. "%main_lab = OpLabel\n" +
  2499. "%2 = OpExtInst %float %1 FMax %float_1 %float_0p2\n" +
  2500. "OpReturn\n" +
  2501. "OpFunctionEnd",
  2502. 2, 1.0f),
  2503. // Test case 25: FClamp 1.0 0.2 4.0
  2504. InstructionFoldingCase<float>(
  2505. Header() + "%main = OpFunction %void None %void_func\n" +
  2506. "%main_lab = OpLabel\n" +
  2507. "%2 = OpExtInst %float %1 FClamp %float_1 %float_0p2 %float_4\n" +
  2508. "OpReturn\n" +
  2509. "OpFunctionEnd",
  2510. 2, 1.0f),
  2511. // Test case 26: FClamp 0.2 2.0 4.0
  2512. InstructionFoldingCase<float>(
  2513. Header() + "%main = OpFunction %void None %void_func\n" +
  2514. "%main_lab = OpLabel\n" +
  2515. "%2 = OpExtInst %float %1 FClamp %float_0p2 %float_2 %float_4\n" +
  2516. "OpReturn\n" +
  2517. "OpFunctionEnd",
  2518. 2, 2.0f),
  2519. // Test case 27: FClamp 2049.0 2.0 4.0
  2520. InstructionFoldingCase<float>(
  2521. Header() + "%main = OpFunction %void None %void_func\n" +
  2522. "%main_lab = OpLabel\n" +
  2523. "%2 = OpExtInst %float %1 FClamp %float_2049 %float_2 %float_4\n" +
  2524. "OpReturn\n" +
  2525. "OpFunctionEnd",
  2526. 2, 4.0f),
  2527. // Test case 28: FClamp 1.0 2.0 x
  2528. InstructionFoldingCase<float>(
  2529. Header() + "%main = OpFunction %void None %void_func\n" +
  2530. "%main_lab = OpLabel\n" +
  2531. "%undef = OpUndef %float\n" +
  2532. "%2 = OpExtInst %float %1 FClamp %float_1 %float_2 %undef\n" +
  2533. "OpReturn\n" +
  2534. "OpFunctionEnd",
  2535. 2, 2.0),
  2536. // Test case 29: FClamp 1.0 x 0.5
  2537. InstructionFoldingCase<float>(
  2538. Header() + "%main = OpFunction %void None %void_func\n" +
  2539. "%main_lab = OpLabel\n" +
  2540. "%undef = OpUndef %float\n" +
  2541. "%2 = OpExtInst %float %1 FClamp %float_1 %undef %float_0p5\n" +
  2542. "OpReturn\n" +
  2543. "OpFunctionEnd",
  2544. 2, 0.5),
  2545. // Test case 30: Sin 0.0
  2546. InstructionFoldingCase<float>(
  2547. Header() + "%main = OpFunction %void None %void_func\n" +
  2548. "%main_lab = OpLabel\n" +
  2549. "%2 = OpExtInst %float %1 Sin %float_0\n" +
  2550. "OpReturn\n" +
  2551. "OpFunctionEnd",
  2552. 2, 0.0),
  2553. // Test case 31: Cos 0.0
  2554. InstructionFoldingCase<float>(
  2555. Header() + "%main = OpFunction %void None %void_func\n" +
  2556. "%main_lab = OpLabel\n" +
  2557. "%2 = OpExtInst %float %1 Cos %float_0\n" +
  2558. "OpReturn\n" +
  2559. "OpFunctionEnd",
  2560. 2, 1.0),
  2561. // Test case 32: Tan 0.0
  2562. InstructionFoldingCase<float>(
  2563. Header() + "%main = OpFunction %void None %void_func\n" +
  2564. "%main_lab = OpLabel\n" +
  2565. "%2 = OpExtInst %float %1 Tan %float_0\n" +
  2566. "OpReturn\n" +
  2567. "OpFunctionEnd",
  2568. 2, 0.0),
  2569. // Test case 33: Asin 0.0
  2570. InstructionFoldingCase<float>(
  2571. Header() + "%main = OpFunction %void None %void_func\n" +
  2572. "%main_lab = OpLabel\n" +
  2573. "%2 = OpExtInst %float %1 Asin %float_0\n" +
  2574. "OpReturn\n" +
  2575. "OpFunctionEnd",
  2576. 2, 0.0),
  2577. // Test case 34: Acos 1.0
  2578. InstructionFoldingCase<float>(
  2579. Header() + "%main = OpFunction %void None %void_func\n" +
  2580. "%main_lab = OpLabel\n" +
  2581. "%2 = OpExtInst %float %1 Acos %float_1\n" +
  2582. "OpReturn\n" +
  2583. "OpFunctionEnd",
  2584. 2, 0.0),
  2585. // Test case 35: Atan 0.0
  2586. InstructionFoldingCase<float>(
  2587. Header() + "%main = OpFunction %void None %void_func\n" +
  2588. "%main_lab = OpLabel\n" +
  2589. "%2 = OpExtInst %float %1 Atan %float_0\n" +
  2590. "OpReturn\n" +
  2591. "OpFunctionEnd",
  2592. 2, 0.0),
  2593. // Test case 36: Exp 0.0
  2594. InstructionFoldingCase<float>(
  2595. Header() + "%main = OpFunction %void None %void_func\n" +
  2596. "%main_lab = OpLabel\n" +
  2597. "%2 = OpExtInst %float %1 Exp %float_0\n" +
  2598. "OpReturn\n" +
  2599. "OpFunctionEnd",
  2600. 2, 1.0),
  2601. // Test case 37: Log 1.0
  2602. InstructionFoldingCase<float>(
  2603. Header() + "%main = OpFunction %void None %void_func\n" +
  2604. "%main_lab = OpLabel\n" +
  2605. "%2 = OpExtInst %float %1 Log %float_1\n" +
  2606. "OpReturn\n" +
  2607. "OpFunctionEnd",
  2608. 2, 0.0),
  2609. // Test case 38: Exp2 2.0
  2610. InstructionFoldingCase<float>(
  2611. Header() + "%main = OpFunction %void None %void_func\n" +
  2612. "%main_lab = OpLabel\n" +
  2613. "%2 = OpExtInst %float %1 Exp2 %float_2\n" +
  2614. "OpReturn\n" +
  2615. "OpFunctionEnd",
  2616. 2, 4.0),
  2617. // Test case 39: Log2 4.0
  2618. InstructionFoldingCase<float>(
  2619. Header() + "%main = OpFunction %void None %void_func\n" +
  2620. "%main_lab = OpLabel\n" +
  2621. "%2 = OpExtInst %float %1 Log2 %float_4\n" +
  2622. "OpReturn\n" +
  2623. "OpFunctionEnd",
  2624. 2, 2.0),
  2625. // Test case 40: Sqrt 4.0
  2626. InstructionFoldingCase<float>(
  2627. Header() + "%main = OpFunction %void None %void_func\n" +
  2628. "%main_lab = OpLabel\n" +
  2629. "%2 = OpExtInst %float %1 Sqrt %float_4\n" +
  2630. "OpReturn\n" +
  2631. "OpFunctionEnd",
  2632. 2, 2.0),
  2633. // Test case 41: Atan2 0.0 1.0
  2634. InstructionFoldingCase<float>(
  2635. Header() + "%main = OpFunction %void None %void_func\n" +
  2636. "%main_lab = OpLabel\n" +
  2637. "%2 = OpExtInst %float %1 Atan2 %float_0 %float_1\n" +
  2638. "OpReturn\n" +
  2639. "OpFunctionEnd",
  2640. 2, 0.0),
  2641. // Test case 42: Pow 2.0 3.0
  2642. InstructionFoldingCase<float>(
  2643. Header() + "%main = OpFunction %void None %void_func\n" +
  2644. "%main_lab = OpLabel\n" +
  2645. "%2 = OpExtInst %float %1 Pow %float_2 %float_3\n" +
  2646. "OpReturn\n" +
  2647. "OpFunctionEnd",
  2648. 2, 8.0),
  2649. // Test case 43: Fold 1.0 / -0.0.
  2650. InstructionFoldingCase<float>(
  2651. Header() + "%main = OpFunction %void None %void_func\n" +
  2652. "%main_lab = OpLabel\n" +
  2653. "%2 = OpFDiv %float %float_1 %float_n0\n" +
  2654. "OpReturn\n" +
  2655. "OpFunctionEnd",
  2656. 2, -std::numeric_limits<float>::infinity()),
  2657. // Test case 44: Fold -1.0 / -0.0
  2658. InstructionFoldingCase<float>(
  2659. Header() + "%main = OpFunction %void None %void_func\n" +
  2660. "%main_lab = OpLabel\n" +
  2661. "%2 = OpFDiv %float %float_n1 %float_n0\n" +
  2662. "OpReturn\n" +
  2663. "OpFunctionEnd",
  2664. 2, std::numeric_limits<float>::infinity()),
  2665. // Test case 45: Fold 0.0 / 0.0
  2666. InstructionFoldingCase<float>(
  2667. Header() + "%main = OpFunction %void None %void_func\n" +
  2668. "%main_lab = OpLabel\n" +
  2669. "%2 = OpFDiv %float %float_0 %float_0\n" +
  2670. "OpReturn\n" +
  2671. "OpFunctionEnd",
  2672. 2, std::numeric_limits<float>::quiet_NaN()),
  2673. // Test case 46: Fold 0.0 / -0.0
  2674. InstructionFoldingCase<float>(
  2675. Header() + "%main = OpFunction %void None %void_func\n" +
  2676. "%main_lab = OpLabel\n" +
  2677. "%2 = OpFDiv %float %float_0 %float_n0\n" +
  2678. "OpReturn\n" +
  2679. "OpFunctionEnd",
  2680. 2, std::numeric_limits<float>::quiet_NaN())
  2681. ));
  2682. // clang-format on
  2683. using DoubleInstructionFoldingTest =
  2684. ::testing::TestWithParam<InstructionFoldingCase<double>>;
  2685. TEST_P(DoubleInstructionFoldingTest, Case) {
  2686. const auto& tc = GetParam();
  2687. std::unique_ptr<IRContext> context;
  2688. Instruction* inst;
  2689. std::tie(context, inst) =
  2690. FoldInstruction(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_1);
  2691. CheckForExpectedScalarConstant(
  2692. inst, tc.expected_result, [](const analysis::Constant* c) {
  2693. return c->AsFloatConstant()->GetDoubleValue();
  2694. });
  2695. }
  2696. // clang-format off
  2697. INSTANTIATE_TEST_SUITE_P(DoubleConstantFoldingTest, DoubleInstructionFoldingTest,
  2698. ::testing::Values(
  2699. // Test case 0: Fold 2.0 - 1.0
  2700. InstructionFoldingCase<double>(
  2701. Header() + "%main = OpFunction %void None %void_func\n" +
  2702. "%main_lab = OpLabel\n" +
  2703. "%2 = OpFSub %double %double_2 %double_1\n" +
  2704. "OpReturn\n" +
  2705. "OpFunctionEnd",
  2706. 2, 1.0),
  2707. // Test case 1: Fold 2.0 + 1.0
  2708. InstructionFoldingCase<double>(
  2709. Header() + "%main = OpFunction %void None %void_func\n" +
  2710. "%main_lab = OpLabel\n" +
  2711. "%2 = OpFAdd %double %double_2 %double_1\n" +
  2712. "OpReturn\n" +
  2713. "OpFunctionEnd",
  2714. 2, 3.0),
  2715. // Test case 2: Fold 3.0 * 2.0
  2716. InstructionFoldingCase<double>(
  2717. Header() + "%main = OpFunction %void None %void_func\n" +
  2718. "%main_lab = OpLabel\n" +
  2719. "%2 = OpFMul %double %double_3 %double_2\n" +
  2720. "OpReturn\n" +
  2721. "OpFunctionEnd",
  2722. 2, 6.0),
  2723. // Test case 3: Fold 1.0 / 2.0
  2724. InstructionFoldingCase<double>(
  2725. Header() + "%main = OpFunction %void None %void_func\n" +
  2726. "%main_lab = OpLabel\n" +
  2727. "%2 = OpFDiv %double %double_1 %double_2\n" +
  2728. "OpReturn\n" +
  2729. "OpFunctionEnd",
  2730. 2, 0.5),
  2731. // Test case 4: Fold 1.0 / 0.0
  2732. InstructionFoldingCase<double>(
  2733. Header() + "%main = OpFunction %void None %void_func\n" +
  2734. "%main_lab = OpLabel\n" +
  2735. "%2 = OpFDiv %double %double_1 %double_0\n" +
  2736. "OpReturn\n" +
  2737. "OpFunctionEnd",
  2738. 2, std::numeric_limits<double>::infinity()),
  2739. // Test case 5: Fold -1.0 / 0.0
  2740. InstructionFoldingCase<double>(
  2741. Header() + "%main = OpFunction %void None %void_func\n" +
  2742. "%main_lab = OpLabel\n" +
  2743. "%2 = OpFDiv %double %double_n1 %double_0\n" +
  2744. "OpReturn\n" +
  2745. "OpFunctionEnd",
  2746. 2, -std::numeric_limits<double>::infinity()),
  2747. // Test case 6: Fold (2.0, 3.0) dot (2.0, 0.5)
  2748. InstructionFoldingCase<double>(
  2749. Header() + "%main = OpFunction %void None %void_func\n" +
  2750. "%main_lab = OpLabel\n" +
  2751. "%2 = OpDot %double %v2double_2_3 %v2double_2_0p5\n" +
  2752. "OpReturn\n" +
  2753. "OpFunctionEnd",
  2754. 2, 5.5f),
  2755. // Test case 7: Fold (0.0, 0.0) dot v
  2756. InstructionFoldingCase<double>(
  2757. Header() + "%main = OpFunction %void None %void_func\n" +
  2758. "%main_lab = OpLabel\n" +
  2759. "%v = OpVariable %_ptr_v2double Function\n" +
  2760. "%2 = OpLoad %v2double %v\n" +
  2761. "%3 = OpDot %double %v2double_0_0 %2\n" +
  2762. "OpReturn\n" +
  2763. "OpFunctionEnd",
  2764. 3, 0.0f),
  2765. // Test case 8: Fold v dot (0.0, 0.0)
  2766. InstructionFoldingCase<double>(
  2767. Header() + "%main = OpFunction %void None %void_func\n" +
  2768. "%main_lab = OpLabel\n" +
  2769. "%v = OpVariable %_ptr_v2double Function\n" +
  2770. "%2 = OpLoad %v2double %v\n" +
  2771. "%3 = OpDot %double %2 %v2double_0_0\n" +
  2772. "OpReturn\n" +
  2773. "OpFunctionEnd",
  2774. 3, 0.0f),
  2775. // Test case 9: Fold Null dot v
  2776. InstructionFoldingCase<double>(
  2777. Header() + "%main = OpFunction %void None %void_func\n" +
  2778. "%main_lab = OpLabel\n" +
  2779. "%v = OpVariable %_ptr_v2double Function\n" +
  2780. "%2 = OpLoad %v2double %v\n" +
  2781. "%3 = OpDot %double %v2double_null %2\n" +
  2782. "OpReturn\n" +
  2783. "OpFunctionEnd",
  2784. 3, 0.0f),
  2785. // Test case 10: Fold v dot Null
  2786. InstructionFoldingCase<double>(
  2787. Header() + "%main = OpFunction %void None %void_func\n" +
  2788. "%main_lab = OpLabel\n" +
  2789. "%v = OpVariable %_ptr_v2double Function\n" +
  2790. "%2 = OpLoad %v2double %v\n" +
  2791. "%3 = OpDot %double %2 %v2double_null\n" +
  2792. "OpReturn\n" +
  2793. "OpFunctionEnd",
  2794. 3, 0.0f),
  2795. // Test case 11: Fold -2.0
  2796. InstructionFoldingCase<double>(
  2797. Header() + "%main = OpFunction %void None %void_func\n" +
  2798. "%main_lab = OpLabel\n" +
  2799. "%2 = OpFNegate %double %double_2\n" +
  2800. "OpReturn\n" +
  2801. "OpFunctionEnd",
  2802. 2, -2),
  2803. // Test case 12: FMin 1.0 4.0
  2804. InstructionFoldingCase<double>(
  2805. Header() + "%main = OpFunction %void None %void_func\n" +
  2806. "%main_lab = OpLabel\n" +
  2807. "%2 = OpExtInst %double %1 FMin %double_1 %double_4\n" +
  2808. "OpReturn\n" +
  2809. "OpFunctionEnd",
  2810. 2, 1.0),
  2811. // Test case 13: FMin 4.0 0.2
  2812. InstructionFoldingCase<double>(
  2813. Header() + "%main = OpFunction %void None %void_func\n" +
  2814. "%main_lab = OpLabel\n" +
  2815. "%2 = OpExtInst %double %1 FMin %double_4 %double_0p2\n" +
  2816. "OpReturn\n" +
  2817. "OpFunctionEnd",
  2818. 2, 0.2),
  2819. // Test case 14: FMax 1.0 4.0
  2820. InstructionFoldingCase<double>(
  2821. Header() + "%main = OpFunction %void None %void_func\n" +
  2822. "%main_lab = OpLabel\n" +
  2823. "%2 = OpExtInst %double %1 FMax %double_1 %double_4\n" +
  2824. "OpReturn\n" +
  2825. "OpFunctionEnd",
  2826. 2, 4.0),
  2827. // Test case 15: FMax 1.0 0.2
  2828. InstructionFoldingCase<double>(
  2829. Header() + "%main = OpFunction %void None %void_func\n" +
  2830. "%main_lab = OpLabel\n" +
  2831. "%2 = OpExtInst %double %1 FMax %double_1 %double_0p2\n" +
  2832. "OpReturn\n" +
  2833. "OpFunctionEnd",
  2834. 2, 1.0),
  2835. // Test case 16: FClamp 1.0 0.2 4.0
  2836. InstructionFoldingCase<double>(
  2837. Header() + "%main = OpFunction %void None %void_func\n" +
  2838. "%main_lab = OpLabel\n" +
  2839. "%2 = OpExtInst %double %1 FClamp %double_1 %double_0p2 %double_4\n" +
  2840. "OpReturn\n" +
  2841. "OpFunctionEnd",
  2842. 2, 1.0),
  2843. // Test case 17: FClamp 0.2 2.0 4.0
  2844. InstructionFoldingCase<double>(
  2845. Header() + "%main = OpFunction %void None %void_func\n" +
  2846. "%main_lab = OpLabel\n" +
  2847. "%2 = OpExtInst %double %1 FClamp %double_0p2 %double_2 %double_4\n" +
  2848. "OpReturn\n" +
  2849. "OpFunctionEnd",
  2850. 2, 2.0),
  2851. // Test case 18: FClamp 5.0 2.0 4.0
  2852. InstructionFoldingCase<double>(
  2853. Header() + "%main = OpFunction %void None %void_func\n" +
  2854. "%main_lab = OpLabel\n" +
  2855. "%2 = OpExtInst %double %1 FClamp %double_5 %double_2 %double_4\n" +
  2856. "OpReturn\n" +
  2857. "OpFunctionEnd",
  2858. 2, 4.0),
  2859. // Test case 19: FClamp 1.0 2.0 x
  2860. InstructionFoldingCase<double>(
  2861. Header() + "%main = OpFunction %void None %void_func\n" +
  2862. "%main_lab = OpLabel\n" +
  2863. "%undef = OpUndef %double\n" +
  2864. "%2 = OpExtInst %double %1 FClamp %double_1 %double_2 %undef\n" +
  2865. "OpReturn\n" +
  2866. "OpFunctionEnd",
  2867. 2, 2.0),
  2868. // Test case 20: FClamp 1.0 x 0.5
  2869. InstructionFoldingCase<double>(
  2870. Header() + "%main = OpFunction %void None %void_func\n" +
  2871. "%main_lab = OpLabel\n" +
  2872. "%undef = OpUndef %double\n" +
  2873. "%2 = OpExtInst %double %1 FClamp %double_1 %undef %double_0p5\n" +
  2874. "OpReturn\n" +
  2875. "OpFunctionEnd",
  2876. 2, 0.5),
  2877. // Test case 21: Sqrt 4.0
  2878. InstructionFoldingCase<double>(
  2879. Header() + "%main = OpFunction %void None %void_func\n" +
  2880. "%main_lab = OpLabel\n" +
  2881. "%undef = OpUndef %double\n" +
  2882. "%2 = OpExtInst %double %1 Sqrt %double_4\n" +
  2883. "OpReturn\n" +
  2884. "OpFunctionEnd",
  2885. 2, 2.0),
  2886. // Test case 22: Pow 2.0 3.0
  2887. InstructionFoldingCase<double>(
  2888. Header() + "%main = OpFunction %void None %void_func\n" +
  2889. "%main_lab = OpLabel\n" +
  2890. "%undef = OpUndef %double\n" +
  2891. "%2 = OpExtInst %double %1 Pow %double_2 %double_3\n" +
  2892. "OpReturn\n" +
  2893. "OpFunctionEnd",
  2894. 2, 8.0),
  2895. // Test case 23: Fold 1.0 / -0.0.
  2896. InstructionFoldingCase<double>(
  2897. Header() + "%main = OpFunction %void None %void_func\n" +
  2898. "%main_lab = OpLabel\n" +
  2899. "%2 = OpFDiv %double %double_1 %double_n0\n" +
  2900. "OpReturn\n" +
  2901. "OpFunctionEnd",
  2902. 2, -std::numeric_limits<double>::infinity()),
  2903. // Test case 24: Fold -1.0 / -0.0
  2904. InstructionFoldingCase<double>(
  2905. Header() + "%main = OpFunction %void None %void_func\n" +
  2906. "%main_lab = OpLabel\n" +
  2907. "%2 = OpFDiv %double %double_n1 %double_n0\n" +
  2908. "OpReturn\n" +
  2909. "OpFunctionEnd",
  2910. 2, std::numeric_limits<double>::infinity()),
  2911. // Test case 25: Fold 0.0 / 0.0
  2912. InstructionFoldingCase<double>(
  2913. Header() + "%main = OpFunction %void None %void_func\n" +
  2914. "%main_lab = OpLabel\n" +
  2915. "%2 = OpFDiv %double %double_0 %double_0\n" +
  2916. "OpReturn\n" +
  2917. "OpFunctionEnd",
  2918. 2, std::numeric_limits<double>::quiet_NaN()),
  2919. // Test case 26: Fold 0.0 / -0.0
  2920. InstructionFoldingCase<double>(
  2921. Header() + "%main = OpFunction %void None %void_func\n" +
  2922. "%main_lab = OpLabel\n" +
  2923. "%2 = OpFDiv %double %double_0 %double_n0\n" +
  2924. "OpReturn\n" +
  2925. "OpFunctionEnd",
  2926. 2, std::numeric_limits<double>::quiet_NaN())
  2927. ));
  2928. // clang-format on
  2929. // clang-format off
  2930. INSTANTIATE_TEST_SUITE_P(DoubleOrderedCompareConstantFoldingTest, BooleanInstructionFoldingTest,
  2931. ::testing::Values(
  2932. // Test case 0: fold 1.0 == 2.0
  2933. InstructionFoldingCase<bool>(
  2934. Header() + "%main = OpFunction %void None %void_func\n" +
  2935. "%main_lab = OpLabel\n" +
  2936. "%2 = OpFOrdEqual %bool %double_1 %double_2\n" +
  2937. "OpReturn\n" +
  2938. "OpFunctionEnd",
  2939. 2, false),
  2940. // Test case 1: fold 1.0 != 2.0
  2941. InstructionFoldingCase<bool>(
  2942. Header() + "%main = OpFunction %void None %void_func\n" +
  2943. "%main_lab = OpLabel\n" +
  2944. "%2 = OpFOrdNotEqual %bool %double_1 %double_2\n" +
  2945. "OpReturn\n" +
  2946. "OpFunctionEnd",
  2947. 2, true),
  2948. // Test case 2: fold 1.0 < 2.0
  2949. InstructionFoldingCase<bool>(
  2950. Header() + "%main = OpFunction %void None %void_func\n" +
  2951. "%main_lab = OpLabel\n" +
  2952. "%2 = OpFOrdLessThan %bool %double_1 %double_2\n" +
  2953. "OpReturn\n" +
  2954. "OpFunctionEnd",
  2955. 2, true),
  2956. // Test case 3: fold 1.0 > 2.0
  2957. InstructionFoldingCase<bool>(
  2958. Header() + "%main = OpFunction %void None %void_func\n" +
  2959. "%main_lab = OpLabel\n" +
  2960. "%2 = OpFOrdGreaterThan %bool %double_1 %double_2\n" +
  2961. "OpReturn\n" +
  2962. "OpFunctionEnd",
  2963. 2, false),
  2964. // Test case 4: fold 1.0 <= 2.0
  2965. InstructionFoldingCase<bool>(
  2966. Header() + "%main = OpFunction %void None %void_func\n" +
  2967. "%main_lab = OpLabel\n" +
  2968. "%2 = OpFOrdLessThanEqual %bool %double_1 %double_2\n" +
  2969. "OpReturn\n" +
  2970. "OpFunctionEnd",
  2971. 2, true),
  2972. // Test case 5: fold 1.0 >= 2.0
  2973. InstructionFoldingCase<bool>(
  2974. Header() + "%main = OpFunction %void None %void_func\n" +
  2975. "%main_lab = OpLabel\n" +
  2976. "%2 = OpFOrdGreaterThanEqual %bool %double_1 %double_2\n" +
  2977. "OpReturn\n" +
  2978. "OpFunctionEnd",
  2979. 2, false),
  2980. // Test case 6: fold 1.0 == 1.0
  2981. InstructionFoldingCase<bool>(
  2982. Header() + "%main = OpFunction %void None %void_func\n" +
  2983. "%main_lab = OpLabel\n" +
  2984. "%2 = OpFOrdEqual %bool %double_1 %double_1\n" +
  2985. "OpReturn\n" +
  2986. "OpFunctionEnd",
  2987. 2, true),
  2988. // Test case 7: fold 1.0 != 1.0
  2989. InstructionFoldingCase<bool>(
  2990. Header() + "%main = OpFunction %void None %void_func\n" +
  2991. "%main_lab = OpLabel\n" +
  2992. "%2 = OpFOrdNotEqual %bool %double_1 %double_1\n" +
  2993. "OpReturn\n" +
  2994. "OpFunctionEnd",
  2995. 2, false),
  2996. // Test case 8: fold 1.0 < 1.0
  2997. InstructionFoldingCase<bool>(
  2998. Header() + "%main = OpFunction %void None %void_func\n" +
  2999. "%main_lab = OpLabel\n" +
  3000. "%2 = OpFOrdLessThan %bool %double_1 %double_1\n" +
  3001. "OpReturn\n" +
  3002. "OpFunctionEnd",
  3003. 2, false),
  3004. // Test case 9: fold 1.0 > 1.0
  3005. InstructionFoldingCase<bool>(
  3006. Header() + "%main = OpFunction %void None %void_func\n" +
  3007. "%main_lab = OpLabel\n" +
  3008. "%2 = OpFOrdGreaterThan %bool %double_1 %double_1\n" +
  3009. "OpReturn\n" +
  3010. "OpFunctionEnd",
  3011. 2, false),
  3012. // Test case 10: fold 1.0 <= 1.0
  3013. InstructionFoldingCase<bool>(
  3014. Header() + "%main = OpFunction %void None %void_func\n" +
  3015. "%main_lab = OpLabel\n" +
  3016. "%2 = OpFOrdLessThanEqual %bool %double_1 %double_1\n" +
  3017. "OpReturn\n" +
  3018. "OpFunctionEnd",
  3019. 2, true),
  3020. // Test case 11: fold 1.0 >= 1.0
  3021. InstructionFoldingCase<bool>(
  3022. Header() + "%main = OpFunction %void None %void_func\n" +
  3023. "%main_lab = OpLabel\n" +
  3024. "%2 = OpFOrdGreaterThanEqual %bool %double_1 %double_1\n" +
  3025. "OpReturn\n" +
  3026. "OpFunctionEnd",
  3027. 2, true),
  3028. // Test case 12: fold 2.0 < 1.0
  3029. InstructionFoldingCase<bool>(
  3030. Header() + "%main = OpFunction %void None %void_func\n" +
  3031. "%main_lab = OpLabel\n" +
  3032. "%2 = OpFOrdLessThan %bool %double_2 %double_1\n" +
  3033. "OpReturn\n" +
  3034. "OpFunctionEnd",
  3035. 2, false),
  3036. // Test case 13: fold 2.0 > 1.0
  3037. InstructionFoldingCase<bool>(
  3038. Header() + "%main = OpFunction %void None %void_func\n" +
  3039. "%main_lab = OpLabel\n" +
  3040. "%2 = OpFOrdGreaterThan %bool %double_2 %double_1\n" +
  3041. "OpReturn\n" +
  3042. "OpFunctionEnd",
  3043. 2, true),
  3044. // Test case 14: fold 2.0 <= 1.0
  3045. InstructionFoldingCase<bool>(
  3046. Header() + "%main = OpFunction %void None %void_func\n" +
  3047. "%main_lab = OpLabel\n" +
  3048. "%2 = OpFOrdLessThanEqual %bool %double_2 %double_1\n" +
  3049. "OpReturn\n" +
  3050. "OpFunctionEnd",
  3051. 2, false),
  3052. // Test case 15: fold 2.0 >= 1.0
  3053. InstructionFoldingCase<bool>(
  3054. Header() + "%main = OpFunction %void None %void_func\n" +
  3055. "%main_lab = OpLabel\n" +
  3056. "%2 = OpFOrdGreaterThanEqual %bool %double_2 %double_1\n" +
  3057. "OpReturn\n" +
  3058. "OpFunctionEnd",
  3059. 2, true)
  3060. ));
  3061. INSTANTIATE_TEST_SUITE_P(DoubleUnorderedCompareConstantFoldingTest, BooleanInstructionFoldingTest,
  3062. ::testing::Values(
  3063. // Test case 0: fold 1.0 == 2.0
  3064. InstructionFoldingCase<bool>(
  3065. Header() + "%main = OpFunction %void None %void_func\n" +
  3066. "%main_lab = OpLabel\n" +
  3067. "%2 = OpFUnordEqual %bool %double_1 %double_2\n" +
  3068. "OpReturn\n" +
  3069. "OpFunctionEnd",
  3070. 2, false),
  3071. // Test case 1: fold 1.0 != 2.0
  3072. InstructionFoldingCase<bool>(
  3073. Header() + "%main = OpFunction %void None %void_func\n" +
  3074. "%main_lab = OpLabel\n" +
  3075. "%2 = OpFUnordNotEqual %bool %double_1 %double_2\n" +
  3076. "OpReturn\n" +
  3077. "OpFunctionEnd",
  3078. 2, true),
  3079. // Test case 2: fold 1.0 < 2.0
  3080. InstructionFoldingCase<bool>(
  3081. Header() + "%main = OpFunction %void None %void_func\n" +
  3082. "%main_lab = OpLabel\n" +
  3083. "%2 = OpFUnordLessThan %bool %double_1 %double_2\n" +
  3084. "OpReturn\n" +
  3085. "OpFunctionEnd",
  3086. 2, true),
  3087. // Test case 3: fold 1.0 > 2.0
  3088. InstructionFoldingCase<bool>(
  3089. Header() + "%main = OpFunction %void None %void_func\n" +
  3090. "%main_lab = OpLabel\n" +
  3091. "%2 = OpFUnordGreaterThan %bool %double_1 %double_2\n" +
  3092. "OpReturn\n" +
  3093. "OpFunctionEnd",
  3094. 2, false),
  3095. // Test case 4: fold 1.0 <= 2.0
  3096. InstructionFoldingCase<bool>(
  3097. Header() + "%main = OpFunction %void None %void_func\n" +
  3098. "%main_lab = OpLabel\n" +
  3099. "%2 = OpFUnordLessThanEqual %bool %double_1 %double_2\n" +
  3100. "OpReturn\n" +
  3101. "OpFunctionEnd",
  3102. 2, true),
  3103. // Test case 5: fold 1.0 >= 2.0
  3104. InstructionFoldingCase<bool>(
  3105. Header() + "%main = OpFunction %void None %void_func\n" +
  3106. "%main_lab = OpLabel\n" +
  3107. "%2 = OpFUnordGreaterThanEqual %bool %double_1 %double_2\n" +
  3108. "OpReturn\n" +
  3109. "OpFunctionEnd",
  3110. 2, false),
  3111. // Test case 6: fold 1.0 == 1.0
  3112. InstructionFoldingCase<bool>(
  3113. Header() + "%main = OpFunction %void None %void_func\n" +
  3114. "%main_lab = OpLabel\n" +
  3115. "%2 = OpFUnordEqual %bool %double_1 %double_1\n" +
  3116. "OpReturn\n" +
  3117. "OpFunctionEnd",
  3118. 2, true),
  3119. // Test case 7: fold 1.0 != 1.0
  3120. InstructionFoldingCase<bool>(
  3121. Header() + "%main = OpFunction %void None %void_func\n" +
  3122. "%main_lab = OpLabel\n" +
  3123. "%2 = OpFUnordNotEqual %bool %double_1 %double_1\n" +
  3124. "OpReturn\n" +
  3125. "OpFunctionEnd",
  3126. 2, false),
  3127. // Test case 8: fold 1.0 < 1.0
  3128. InstructionFoldingCase<bool>(
  3129. Header() + "%main = OpFunction %void None %void_func\n" +
  3130. "%main_lab = OpLabel\n" +
  3131. "%2 = OpFUnordLessThan %bool %double_1 %double_1\n" +
  3132. "OpReturn\n" +
  3133. "OpFunctionEnd",
  3134. 2, false),
  3135. // Test case 9: fold 1.0 > 1.0
  3136. InstructionFoldingCase<bool>(
  3137. Header() + "%main = OpFunction %void None %void_func\n" +
  3138. "%main_lab = OpLabel\n" +
  3139. "%2 = OpFUnordGreaterThan %bool %double_1 %double_1\n" +
  3140. "OpReturn\n" +
  3141. "OpFunctionEnd",
  3142. 2, false),
  3143. // Test case 10: fold 1.0 <= 1.0
  3144. InstructionFoldingCase<bool>(
  3145. Header() + "%main = OpFunction %void None %void_func\n" +
  3146. "%main_lab = OpLabel\n" +
  3147. "%2 = OpFUnordLessThanEqual %bool %double_1 %double_1\n" +
  3148. "OpReturn\n" +
  3149. "OpFunctionEnd",
  3150. 2, true),
  3151. // Test case 11: fold 1.0 >= 1.0
  3152. InstructionFoldingCase<bool>(
  3153. Header() + "%main = OpFunction %void None %void_func\n" +
  3154. "%main_lab = OpLabel\n" +
  3155. "%2 = OpFUnordGreaterThanEqual %bool %double_1 %double_1\n" +
  3156. "OpReturn\n" +
  3157. "OpFunctionEnd",
  3158. 2, true),
  3159. // Test case 12: fold 2.0 < 1.0
  3160. InstructionFoldingCase<bool>(
  3161. Header() + "%main = OpFunction %void None %void_func\n" +
  3162. "%main_lab = OpLabel\n" +
  3163. "%2 = OpFUnordLessThan %bool %double_2 %double_1\n" +
  3164. "OpReturn\n" +
  3165. "OpFunctionEnd",
  3166. 2, false),
  3167. // Test case 13: fold 2.0 > 1.0
  3168. InstructionFoldingCase<bool>(
  3169. Header() + "%main = OpFunction %void None %void_func\n" +
  3170. "%main_lab = OpLabel\n" +
  3171. "%2 = OpFUnordGreaterThan %bool %double_2 %double_1\n" +
  3172. "OpReturn\n" +
  3173. "OpFunctionEnd",
  3174. 2, true),
  3175. // Test case 14: fold 2.0 <= 1.0
  3176. InstructionFoldingCase<bool>(
  3177. Header() + "%main = OpFunction %void None %void_func\n" +
  3178. "%main_lab = OpLabel\n" +
  3179. "%2 = OpFUnordLessThanEqual %bool %double_2 %double_1\n" +
  3180. "OpReturn\n" +
  3181. "OpFunctionEnd",
  3182. 2, false),
  3183. // Test case 15: fold 2.0 >= 1.0
  3184. InstructionFoldingCase<bool>(
  3185. Header() + "%main = OpFunction %void None %void_func\n" +
  3186. "%main_lab = OpLabel\n" +
  3187. "%2 = OpFUnordGreaterThanEqual %bool %double_2 %double_1\n" +
  3188. "OpReturn\n" +
  3189. "OpFunctionEnd",
  3190. 2, true)
  3191. ));
  3192. INSTANTIATE_TEST_SUITE_P(FloatOrderedCompareConstantFoldingTest, BooleanInstructionFoldingTest,
  3193. ::testing::Values(
  3194. // Test case 0: fold 1.0 == 2.0
  3195. InstructionFoldingCase<bool>(
  3196. Header() + "%main = OpFunction %void None %void_func\n" +
  3197. "%main_lab = OpLabel\n" +
  3198. "%2 = OpFOrdEqual %bool %float_1 %float_2\n" +
  3199. "OpReturn\n" +
  3200. "OpFunctionEnd",
  3201. 2, false),
  3202. // Test case 1: fold 1.0 != 2.0
  3203. InstructionFoldingCase<bool>(
  3204. Header() + "%main = OpFunction %void None %void_func\n" +
  3205. "%main_lab = OpLabel\n" +
  3206. "%2 = OpFOrdNotEqual %bool %float_1 %float_2\n" +
  3207. "OpReturn\n" +
  3208. "OpFunctionEnd",
  3209. 2, true),
  3210. // Test case 2: fold 1.0 < 2.0
  3211. InstructionFoldingCase<bool>(
  3212. Header() + "%main = OpFunction %void None %void_func\n" +
  3213. "%main_lab = OpLabel\n" +
  3214. "%2 = OpFOrdLessThan %bool %float_1 %float_2\n" +
  3215. "OpReturn\n" +
  3216. "OpFunctionEnd",
  3217. 2, true),
  3218. // Test case 3: fold 1.0 > 2.0
  3219. InstructionFoldingCase<bool>(
  3220. Header() + "%main = OpFunction %void None %void_func\n" +
  3221. "%main_lab = OpLabel\n" +
  3222. "%2 = OpFOrdGreaterThan %bool %float_1 %float_2\n" +
  3223. "OpReturn\n" +
  3224. "OpFunctionEnd",
  3225. 2, false),
  3226. // Test case 4: fold 1.0 <= 2.0
  3227. InstructionFoldingCase<bool>(
  3228. Header() + "%main = OpFunction %void None %void_func\n" +
  3229. "%main_lab = OpLabel\n" +
  3230. "%2 = OpFOrdLessThanEqual %bool %float_1 %float_2\n" +
  3231. "OpReturn\n" +
  3232. "OpFunctionEnd",
  3233. 2, true),
  3234. // Test case 5: fold 1.0 >= 2.0
  3235. InstructionFoldingCase<bool>(
  3236. Header() + "%main = OpFunction %void None %void_func\n" +
  3237. "%main_lab = OpLabel\n" +
  3238. "%2 = OpFOrdGreaterThanEqual %bool %float_1 %float_2\n" +
  3239. "OpReturn\n" +
  3240. "OpFunctionEnd",
  3241. 2, false),
  3242. // Test case 6: fold 1.0 == 1.0
  3243. InstructionFoldingCase<bool>(
  3244. Header() + "%main = OpFunction %void None %void_func\n" +
  3245. "%main_lab = OpLabel\n" +
  3246. "%2 = OpFOrdEqual %bool %float_1 %float_1\n" +
  3247. "OpReturn\n" +
  3248. "OpFunctionEnd",
  3249. 2, true),
  3250. // Test case 7: fold 1.0 != 1.0
  3251. InstructionFoldingCase<bool>(
  3252. Header() + "%main = OpFunction %void None %void_func\n" +
  3253. "%main_lab = OpLabel\n" +
  3254. "%2 = OpFOrdNotEqual %bool %float_1 %float_1\n" +
  3255. "OpReturn\n" +
  3256. "OpFunctionEnd",
  3257. 2, false),
  3258. // Test case 8: fold 1.0 < 1.0
  3259. InstructionFoldingCase<bool>(
  3260. Header() + "%main = OpFunction %void None %void_func\n" +
  3261. "%main_lab = OpLabel\n" +
  3262. "%2 = OpFOrdLessThan %bool %float_1 %float_1\n" +
  3263. "OpReturn\n" +
  3264. "OpFunctionEnd",
  3265. 2, false),
  3266. // Test case 9: fold 1.0 > 1.0
  3267. InstructionFoldingCase<bool>(
  3268. Header() + "%main = OpFunction %void None %void_func\n" +
  3269. "%main_lab = OpLabel\n" +
  3270. "%2 = OpFOrdGreaterThan %bool %float_1 %float_1\n" +
  3271. "OpReturn\n" +
  3272. "OpFunctionEnd",
  3273. 2, false),
  3274. // Test case 10: fold 1.0 <= 1.0
  3275. InstructionFoldingCase<bool>(
  3276. Header() + "%main = OpFunction %void None %void_func\n" +
  3277. "%main_lab = OpLabel\n" +
  3278. "%2 = OpFOrdLessThanEqual %bool %float_1 %float_1\n" +
  3279. "OpReturn\n" +
  3280. "OpFunctionEnd",
  3281. 2, true),
  3282. // Test case 11: fold 1.0 >= 1.0
  3283. InstructionFoldingCase<bool>(
  3284. Header() + "%main = OpFunction %void None %void_func\n" +
  3285. "%main_lab = OpLabel\n" +
  3286. "%2 = OpFOrdGreaterThanEqual %bool %float_1 %float_1\n" +
  3287. "OpReturn\n" +
  3288. "OpFunctionEnd",
  3289. 2, true),
  3290. // Test case 12: fold 2.0 < 1.0
  3291. InstructionFoldingCase<bool>(
  3292. Header() + "%main = OpFunction %void None %void_func\n" +
  3293. "%main_lab = OpLabel\n" +
  3294. "%2 = OpFOrdLessThan %bool %float_2 %float_1\n" +
  3295. "OpReturn\n" +
  3296. "OpFunctionEnd",
  3297. 2, false),
  3298. // Test case 13: fold 2.0 > 1.0
  3299. InstructionFoldingCase<bool>(
  3300. Header() + "%main = OpFunction %void None %void_func\n" +
  3301. "%main_lab = OpLabel\n" +
  3302. "%2 = OpFOrdGreaterThan %bool %float_2 %float_1\n" +
  3303. "OpReturn\n" +
  3304. "OpFunctionEnd",
  3305. 2, true),
  3306. // Test case 14: fold 2.0 <= 1.0
  3307. InstructionFoldingCase<bool>(
  3308. Header() + "%main = OpFunction %void None %void_func\n" +
  3309. "%main_lab = OpLabel\n" +
  3310. "%2 = OpFOrdLessThanEqual %bool %float_2 %float_1\n" +
  3311. "OpReturn\n" +
  3312. "OpFunctionEnd",
  3313. 2, false),
  3314. // Test case 15: fold 2.0 >= 1.0
  3315. InstructionFoldingCase<bool>(
  3316. Header() + "%main = OpFunction %void None %void_func\n" +
  3317. "%main_lab = OpLabel\n" +
  3318. "%2 = OpFOrdGreaterThanEqual %bool %float_2 %float_1\n" +
  3319. "OpReturn\n" +
  3320. "OpFunctionEnd",
  3321. 2, true)
  3322. ));
  3323. INSTANTIATE_TEST_SUITE_P(FloatUnorderedCompareConstantFoldingTest, BooleanInstructionFoldingTest,
  3324. ::testing::Values(
  3325. // Test case 0: fold 1.0 == 2.0
  3326. InstructionFoldingCase<bool>(
  3327. Header() + "%main = OpFunction %void None %void_func\n" +
  3328. "%main_lab = OpLabel\n" +
  3329. "%2 = OpFUnordEqual %bool %float_1 %float_2\n" +
  3330. "OpReturn\n" +
  3331. "OpFunctionEnd",
  3332. 2, false),
  3333. // Test case 1: fold 1.0 != 2.0
  3334. InstructionFoldingCase<bool>(
  3335. Header() + "%main = OpFunction %void None %void_func\n" +
  3336. "%main_lab = OpLabel\n" +
  3337. "%2 = OpFUnordNotEqual %bool %float_1 %float_2\n" +
  3338. "OpReturn\n" +
  3339. "OpFunctionEnd",
  3340. 2, true),
  3341. // Test case 2: fold 1.0 < 2.0
  3342. InstructionFoldingCase<bool>(
  3343. Header() + "%main = OpFunction %void None %void_func\n" +
  3344. "%main_lab = OpLabel\n" +
  3345. "%2 = OpFUnordLessThan %bool %float_1 %float_2\n" +
  3346. "OpReturn\n" +
  3347. "OpFunctionEnd",
  3348. 2, true),
  3349. // Test case 3: fold 1.0 > 2.0
  3350. InstructionFoldingCase<bool>(
  3351. Header() + "%main = OpFunction %void None %void_func\n" +
  3352. "%main_lab = OpLabel\n" +
  3353. "%2 = OpFUnordGreaterThan %bool %float_1 %float_2\n" +
  3354. "OpReturn\n" +
  3355. "OpFunctionEnd",
  3356. 2, false),
  3357. // Test case 4: fold 1.0 <= 2.0
  3358. InstructionFoldingCase<bool>(
  3359. Header() + "%main = OpFunction %void None %void_func\n" +
  3360. "%main_lab = OpLabel\n" +
  3361. "%2 = OpFUnordLessThanEqual %bool %float_1 %float_2\n" +
  3362. "OpReturn\n" +
  3363. "OpFunctionEnd",
  3364. 2, true),
  3365. // Test case 5: fold 1.0 >= 2.0
  3366. InstructionFoldingCase<bool>(
  3367. Header() + "%main = OpFunction %void None %void_func\n" +
  3368. "%main_lab = OpLabel\n" +
  3369. "%2 = OpFUnordGreaterThanEqual %bool %float_1 %float_2\n" +
  3370. "OpReturn\n" +
  3371. "OpFunctionEnd",
  3372. 2, false),
  3373. // Test case 6: fold 1.0 == 1.0
  3374. InstructionFoldingCase<bool>(
  3375. Header() + "%main = OpFunction %void None %void_func\n" +
  3376. "%main_lab = OpLabel\n" +
  3377. "%2 = OpFUnordEqual %bool %float_1 %float_1\n" +
  3378. "OpReturn\n" +
  3379. "OpFunctionEnd",
  3380. 2, true),
  3381. // Test case 7: fold 1.0 != 1.0
  3382. InstructionFoldingCase<bool>(
  3383. Header() + "%main = OpFunction %void None %void_func\n" +
  3384. "%main_lab = OpLabel\n" +
  3385. "%2 = OpFUnordNotEqual %bool %float_1 %float_1\n" +
  3386. "OpReturn\n" +
  3387. "OpFunctionEnd",
  3388. 2, false),
  3389. // Test case 8: fold 1.0 < 1.0
  3390. InstructionFoldingCase<bool>(
  3391. Header() + "%main = OpFunction %void None %void_func\n" +
  3392. "%main_lab = OpLabel\n" +
  3393. "%2 = OpFUnordLessThan %bool %float_1 %float_1\n" +
  3394. "OpReturn\n" +
  3395. "OpFunctionEnd",
  3396. 2, false),
  3397. // Test case 9: fold 1.0 > 1.0
  3398. InstructionFoldingCase<bool>(
  3399. Header() + "%main = OpFunction %void None %void_func\n" +
  3400. "%main_lab = OpLabel\n" +
  3401. "%2 = OpFUnordGreaterThan %bool %float_1 %float_1\n" +
  3402. "OpReturn\n" +
  3403. "OpFunctionEnd",
  3404. 2, false),
  3405. // Test case 10: fold 1.0 <= 1.0
  3406. InstructionFoldingCase<bool>(
  3407. Header() + "%main = OpFunction %void None %void_func\n" +
  3408. "%main_lab = OpLabel\n" +
  3409. "%2 = OpFUnordLessThanEqual %bool %float_1 %float_1\n" +
  3410. "OpReturn\n" +
  3411. "OpFunctionEnd",
  3412. 2, true),
  3413. // Test case 11: fold 1.0 >= 1.0
  3414. InstructionFoldingCase<bool>(
  3415. Header() + "%main = OpFunction %void None %void_func\n" +
  3416. "%main_lab = OpLabel\n" +
  3417. "%2 = OpFUnordGreaterThanEqual %bool %float_1 %float_1\n" +
  3418. "OpReturn\n" +
  3419. "OpFunctionEnd",
  3420. 2, true),
  3421. // Test case 12: fold 2.0 < 1.0
  3422. InstructionFoldingCase<bool>(
  3423. Header() + "%main = OpFunction %void None %void_func\n" +
  3424. "%main_lab = OpLabel\n" +
  3425. "%2 = OpFUnordLessThan %bool %float_2 %float_1\n" +
  3426. "OpReturn\n" +
  3427. "OpFunctionEnd",
  3428. 2, false),
  3429. // Test case 13: fold 2.0 > 1.0
  3430. InstructionFoldingCase<bool>(
  3431. Header() + "%main = OpFunction %void None %void_func\n" +
  3432. "%main_lab = OpLabel\n" +
  3433. "%2 = OpFUnordGreaterThan %bool %float_2 %float_1\n" +
  3434. "OpReturn\n" +
  3435. "OpFunctionEnd",
  3436. 2, true),
  3437. // Test case 14: fold 2.0 <= 1.0
  3438. InstructionFoldingCase<bool>(
  3439. Header() + "%main = OpFunction %void None %void_func\n" +
  3440. "%main_lab = OpLabel\n" +
  3441. "%2 = OpFUnordLessThanEqual %bool %float_2 %float_1\n" +
  3442. "OpReturn\n" +
  3443. "OpFunctionEnd",
  3444. 2, false),
  3445. // Test case 15: fold 2.0 >= 1.0
  3446. InstructionFoldingCase<bool>(
  3447. Header() + "%main = OpFunction %void None %void_func\n" +
  3448. "%main_lab = OpLabel\n" +
  3449. "%2 = OpFUnordGreaterThanEqual %bool %float_2 %float_1\n" +
  3450. "OpReturn\n" +
  3451. "OpFunctionEnd",
  3452. 2, true)
  3453. ));
  3454. INSTANTIATE_TEST_SUITE_P(DoubleNaNCompareConstantFoldingTest, BooleanInstructionFoldingTest,
  3455. ::testing::Values(
  3456. // Test case 0: fold NaN == 0 (ord)
  3457. InstructionFoldingCase<bool>(
  3458. HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
  3459. "%main_lab = OpLabel\n" +
  3460. "%2 = OpFOrdEqual %bool %double_nan %double_0\n" +
  3461. "OpReturn\n" +
  3462. "OpFunctionEnd",
  3463. 2, false),
  3464. // Test case 1: fold NaN == NaN (unord)
  3465. InstructionFoldingCase<bool>(
  3466. HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
  3467. "%main_lab = OpLabel\n" +
  3468. "%2 = OpFUnordEqual %bool %double_nan %double_0\n" +
  3469. "OpReturn\n" +
  3470. "OpFunctionEnd",
  3471. 2, true),
  3472. // Test case 2: fold NaN != NaN (ord)
  3473. InstructionFoldingCase<bool>(
  3474. HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
  3475. "%main_lab = OpLabel\n" +
  3476. "%2 = OpFOrdNotEqual %bool %double_nan %double_0\n" +
  3477. "OpReturn\n" +
  3478. "OpFunctionEnd",
  3479. 2, false),
  3480. // Test case 3: fold NaN != NaN (unord)
  3481. InstructionFoldingCase<bool>(
  3482. HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
  3483. "%main_lab = OpLabel\n" +
  3484. "%2 = OpFUnordNotEqual %bool %double_nan %double_0\n" +
  3485. "OpReturn\n" +
  3486. "OpFunctionEnd",
  3487. 2, true)
  3488. ));
  3489. INSTANTIATE_TEST_SUITE_P(FloatNaNCompareConstantFoldingTest, BooleanInstructionFoldingTest,
  3490. ::testing::Values(
  3491. // Test case 0: fold NaN == 0 (ord)
  3492. InstructionFoldingCase<bool>(
  3493. HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
  3494. "%main_lab = OpLabel\n" +
  3495. "%2 = OpFOrdEqual %bool %float_nan %float_0\n" +
  3496. "OpReturn\n" +
  3497. "OpFunctionEnd",
  3498. 2, false),
  3499. // Test case 1: fold NaN == NaN (unord)
  3500. InstructionFoldingCase<bool>(
  3501. HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
  3502. "%main_lab = OpLabel\n" +
  3503. "%2 = OpFUnordEqual %bool %float_nan %float_0\n" +
  3504. "OpReturn\n" +
  3505. "OpFunctionEnd",
  3506. 2, true),
  3507. // Test case 2: fold NaN != NaN (ord)
  3508. InstructionFoldingCase<bool>(
  3509. HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
  3510. "%main_lab = OpLabel\n" +
  3511. "%2 = OpFOrdNotEqual %bool %float_nan %float_0\n" +
  3512. "OpReturn\n" +
  3513. "OpFunctionEnd",
  3514. 2, false),
  3515. // Test case 3: fold NaN != NaN (unord)
  3516. InstructionFoldingCase<bool>(
  3517. HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
  3518. "%main_lab = OpLabel\n" +
  3519. "%2 = OpFUnordNotEqual %bool %float_nan %float_0\n" +
  3520. "OpReturn\n" +
  3521. "OpFunctionEnd",
  3522. 2, true)
  3523. ));
  3524. // clang-format on
  3525. template <class ResultType>
  3526. struct InstructionFoldingCaseWithMap {
  3527. InstructionFoldingCaseWithMap(const std::string& tb, uint32_t id,
  3528. ResultType result,
  3529. std::function<uint32_t(uint32_t)> map)
  3530. : test_body(tb), id_to_fold(id), expected_result(result), id_map(map) {}
  3531. std::string test_body;
  3532. uint32_t id_to_fold;
  3533. ResultType expected_result;
  3534. std::function<uint32_t(uint32_t)> id_map;
  3535. };
  3536. using IntegerInstructionFoldingTestWithMap =
  3537. ::testing::TestWithParam<InstructionFoldingCaseWithMap<uint32_t>>;
  3538. TEST_P(IntegerInstructionFoldingTestWithMap, Case) {
  3539. const auto& tc = GetParam();
  3540. std::unique_ptr<IRContext> context;
  3541. Instruction* inst;
  3542. std::tie(context, inst) =
  3543. GetInstructionToFold(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_5);
  3544. inst = context->get_instruction_folder().FoldInstructionToConstant(inst,
  3545. tc.id_map);
  3546. EXPECT_NE(inst, nullptr);
  3547. CheckForExpectedScalarConstant(inst, tc.expected_result,
  3548. [](const analysis::Constant* c) {
  3549. return c->AsIntConstant()->GetU32BitValue();
  3550. });
  3551. }
  3552. // clang-format off
  3553. INSTANTIATE_TEST_SUITE_P(TestCase, IntegerInstructionFoldingTestWithMap,
  3554. ::testing::Values(
  3555. // Test case 0: fold %3 = 0; %3 * n
  3556. InstructionFoldingCaseWithMap<uint32_t>(
  3557. Header() + "%main = OpFunction %void None %void_func\n" +
  3558. "%main_lab = OpLabel\n" +
  3559. "%n = OpVariable %_ptr_int Function\n" +
  3560. "%load = OpLoad %int %n\n" +
  3561. "%3 = OpCopyObject %int %int_0\n"
  3562. "%2 = OpIMul %int %3 %load\n" +
  3563. "OpReturn\n" +
  3564. "OpFunctionEnd",
  3565. 2, 0, [](uint32_t id) {return (id == 3 ? INT_0_ID : id);})
  3566. ));
  3567. // clang-format on
  3568. using BooleanInstructionFoldingTestWithMap =
  3569. ::testing::TestWithParam<InstructionFoldingCaseWithMap<bool>>;
  3570. TEST_P(BooleanInstructionFoldingTestWithMap, Case) {
  3571. const auto& tc = GetParam();
  3572. std::unique_ptr<IRContext> context;
  3573. Instruction* inst;
  3574. std::tie(context, inst) =
  3575. GetInstructionToFold(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_5);
  3576. inst = context->get_instruction_folder().FoldInstructionToConstant(inst,
  3577. tc.id_map);
  3578. ASSERT_NE(inst, nullptr);
  3579. CheckForExpectedScalarConstant(
  3580. inst, tc.expected_result,
  3581. [](const analysis::Constant* c) { return c->AsBoolConstant()->value(); });
  3582. }
  3583. // clang-format off
  3584. INSTANTIATE_TEST_SUITE_P(TestCase, BooleanInstructionFoldingTestWithMap,
  3585. ::testing::Values(
  3586. // Test case 0: fold %3 = true; %3 || n
  3587. InstructionFoldingCaseWithMap<bool>(
  3588. Header() + "%main = OpFunction %void None %void_func\n" +
  3589. "%main_lab = OpLabel\n" +
  3590. "%n = OpVariable %_ptr_bool Function\n" +
  3591. "%load = OpLoad %bool %n\n" +
  3592. "%3 = OpCopyObject %bool %true\n" +
  3593. "%2 = OpLogicalOr %bool %3 %load\n" +
  3594. "OpReturn\n" +
  3595. "OpFunctionEnd",
  3596. 2, true, [](uint32_t id) {return (id == 3 ? TRUE_ID : id);})
  3597. ));
  3598. // clang-format on
  3599. using GeneralInstructionFoldingTest =
  3600. ::testing::TestWithParam<InstructionFoldingCase<uint32_t>>;
  3601. TEST_P(GeneralInstructionFoldingTest, Case) {
  3602. const auto& tc = GetParam();
  3603. std::unique_ptr<IRContext> context;
  3604. Instruction* inst;
  3605. std::tie(context, inst) =
  3606. FoldInstruction(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_1);
  3607. EXPECT_TRUE((inst == nullptr) == (tc.expected_result == 0));
  3608. if (inst != nullptr) {
  3609. EXPECT_EQ(inst->opcode(), spv::Op::OpCopyObject);
  3610. EXPECT_EQ(inst->GetSingleWordInOperand(0), tc.expected_result);
  3611. }
  3612. }
  3613. // clang-format off
  3614. INSTANTIATE_TEST_SUITE_P(IntegerArithmeticTestCases, GeneralInstructionFoldingTest,
  3615. ::testing::Values(
  3616. // Test case 0: Don't fold n * m
  3617. InstructionFoldingCase<uint32_t>(
  3618. Header() + "%main = OpFunction %void None %void_func\n" +
  3619. "%main_lab = OpLabel\n" +
  3620. "%n = OpVariable %_ptr_int Function\n" +
  3621. "%m = OpVariable %_ptr_int Function\n" +
  3622. "%load_n = OpLoad %int %n\n" +
  3623. "%load_m = OpLoad %int %m\n" +
  3624. "%2 = OpIMul %int %load_n %load_m\n" +
  3625. "OpReturn\n" +
  3626. "OpFunctionEnd",
  3627. 2, 0),
  3628. // Test case 1: Don't fold n / m (unsigned)
  3629. InstructionFoldingCase<uint32_t>(
  3630. Header() + "%main = OpFunction %void None %void_func\n" +
  3631. "%main_lab = OpLabel\n" +
  3632. "%n = OpVariable %_ptr_uint Function\n" +
  3633. "%m = OpVariable %_ptr_uint Function\n" +
  3634. "%load_n = OpLoad %uint %n\n" +
  3635. "%load_m = OpLoad %uint %m\n" +
  3636. "%2 = OpUDiv %uint %load_n %load_m\n" +
  3637. "OpReturn\n" +
  3638. "OpFunctionEnd",
  3639. 2, 0),
  3640. // Test case 2: Don't fold n / m (signed)
  3641. InstructionFoldingCase<uint32_t>(
  3642. Header() + "%main = OpFunction %void None %void_func\n" +
  3643. "%main_lab = OpLabel\n" +
  3644. "%n = OpVariable %_ptr_int Function\n" +
  3645. "%m = OpVariable %_ptr_int Function\n" +
  3646. "%load_n = OpLoad %int %n\n" +
  3647. "%load_m = OpLoad %int %m\n" +
  3648. "%2 = OpSDiv %int %load_n %load_m\n" +
  3649. "OpReturn\n" +
  3650. "OpFunctionEnd",
  3651. 2, 0),
  3652. // Test case 3: Don't fold n remainder m
  3653. InstructionFoldingCase<uint32_t>(
  3654. Header() + "%main = OpFunction %void None %void_func\n" +
  3655. "%main_lab = OpLabel\n" +
  3656. "%n = OpVariable %_ptr_int Function\n" +
  3657. "%m = OpVariable %_ptr_int Function\n" +
  3658. "%load_n = OpLoad %int %n\n" +
  3659. "%load_m = OpLoad %int %m\n" +
  3660. "%2 = OpSRem %int %load_n %load_m\n" +
  3661. "OpReturn\n" +
  3662. "OpFunctionEnd",
  3663. 2, 0),
  3664. // Test case 4: Don't fold n % m (signed)
  3665. InstructionFoldingCase<uint32_t>(
  3666. Header() + "%main = OpFunction %void None %void_func\n" +
  3667. "%main_lab = OpLabel\n" +
  3668. "%n = OpVariable %_ptr_int Function\n" +
  3669. "%m = OpVariable %_ptr_int Function\n" +
  3670. "%load_n = OpLoad %int %n\n" +
  3671. "%load_m = OpLoad %int %m\n" +
  3672. "%2 = OpSMod %int %load_n %load_m\n" +
  3673. "OpReturn\n" +
  3674. "OpFunctionEnd",
  3675. 2, 0),
  3676. // Test case 5: Don't fold n % m (unsigned)
  3677. InstructionFoldingCase<uint32_t>(
  3678. Header() + "%main = OpFunction %void None %void_func\n" +
  3679. "%main_lab = OpLabel\n" +
  3680. "%n = OpVariable %_ptr_uint Function\n" +
  3681. "%m = OpVariable %_ptr_uint Function\n" +
  3682. "%load_n = OpLoad %uint %n\n" +
  3683. "%load_m = OpLoad %uint %m\n" +
  3684. "%2 = OpUMod %int %load_n %load_m\n" +
  3685. "OpReturn\n" +
  3686. "OpFunctionEnd",
  3687. 2, 0),
  3688. // Test case 6: Don't fold n << m
  3689. InstructionFoldingCase<uint32_t>(
  3690. Header() + "%main = OpFunction %void None %void_func\n" +
  3691. "%main_lab = OpLabel\n" +
  3692. "%n = OpVariable %_ptr_uint Function\n" +
  3693. "%m = OpVariable %_ptr_uint Function\n" +
  3694. "%load_n = OpLoad %uint %n\n" +
  3695. "%load_m = OpLoad %uint %m\n" +
  3696. "%2 = OpShiftRightLogical %int %load_n %load_m\n" +
  3697. "OpReturn\n" +
  3698. "OpFunctionEnd",
  3699. 2, 0),
  3700. // Test case 7: Don't fold n >> m
  3701. InstructionFoldingCase<uint32_t>(
  3702. Header() + "%main = OpFunction %void None %void_func\n" +
  3703. "%main_lab = OpLabel\n" +
  3704. "%n = OpVariable %_ptr_uint Function\n" +
  3705. "%m = OpVariable %_ptr_uint Function\n" +
  3706. "%load_n = OpLoad %uint %n\n" +
  3707. "%load_m = OpLoad %uint %m\n" +
  3708. "%2 = OpShiftLeftLogical %int %load_n %load_m\n" +
  3709. "OpReturn\n" +
  3710. "OpFunctionEnd",
  3711. 2, 0),
  3712. // Test case 8: Don't fold n | m
  3713. InstructionFoldingCase<uint32_t>(
  3714. Header() + "%main = OpFunction %void None %void_func\n" +
  3715. "%main_lab = OpLabel\n" +
  3716. "%n = OpVariable %_ptr_uint Function\n" +
  3717. "%m = OpVariable %_ptr_uint Function\n" +
  3718. "%load_n = OpLoad %uint %n\n" +
  3719. "%load_m = OpLoad %uint %m\n" +
  3720. "%2 = OpBitwiseOr %int %load_n %load_m\n" +
  3721. "OpReturn\n" +
  3722. "OpFunctionEnd",
  3723. 2, 0),
  3724. // Test case 9: Don't fold n & m
  3725. InstructionFoldingCase<uint32_t>(
  3726. Header() + "%main = OpFunction %void None %void_func\n" +
  3727. "%main_lab = OpLabel\n" +
  3728. "%n = OpVariable %_ptr_uint Function\n" +
  3729. "%m = OpVariable %_ptr_uint Function\n" +
  3730. "%load_n = OpLoad %uint %n\n" +
  3731. "%load_m = OpLoad %uint %m\n" +
  3732. "%2 = OpBitwiseAnd %int %load_n %load_m\n" +
  3733. "OpReturn\n" +
  3734. "OpFunctionEnd",
  3735. 2, 0),
  3736. // Test case 10: Don't fold n < m (unsigned)
  3737. InstructionFoldingCase<uint32_t>(
  3738. Header() + "%main = OpFunction %void None %void_func\n" +
  3739. "%main_lab = OpLabel\n" +
  3740. "%n = OpVariable %_ptr_uint Function\n" +
  3741. "%m = OpVariable %_ptr_uint Function\n" +
  3742. "%load_n = OpLoad %uint %n\n" +
  3743. "%load_m = OpLoad %uint %m\n" +
  3744. "%2 = OpULessThan %bool %load_n %load_m\n" +
  3745. "OpReturn\n" +
  3746. "OpFunctionEnd",
  3747. 2, 0),
  3748. // Test case 11: Don't fold n > m (unsigned)
  3749. InstructionFoldingCase<uint32_t>(
  3750. Header() + "%main = OpFunction %void None %void_func\n" +
  3751. "%main_lab = OpLabel\n" +
  3752. "%n = OpVariable %_ptr_uint Function\n" +
  3753. "%m = OpVariable %_ptr_uint Function\n" +
  3754. "%load_n = OpLoad %uint %n\n" +
  3755. "%load_m = OpLoad %uint %m\n" +
  3756. "%2 = OpUGreaterThan %bool %load_n %load_m\n" +
  3757. "OpReturn\n" +
  3758. "OpFunctionEnd",
  3759. 2, 0),
  3760. // Test case 12: Don't fold n <= m (unsigned)
  3761. InstructionFoldingCase<uint32_t>(
  3762. Header() + "%main = OpFunction %void None %void_func\n" +
  3763. "%main_lab = OpLabel\n" +
  3764. "%n = OpVariable %_ptr_uint Function\n" +
  3765. "%m = OpVariable %_ptr_uint Function\n" +
  3766. "%load_n = OpLoad %uint %n\n" +
  3767. "%load_m = OpLoad %uint %m\n" +
  3768. "%2 = OpULessThanEqual %bool %load_n %load_m\n" +
  3769. "OpReturn\n" +
  3770. "OpFunctionEnd",
  3771. 2, 0),
  3772. // Test case 13: Don't fold n >= m (unsigned)
  3773. InstructionFoldingCase<uint32_t>(
  3774. Header() + "%main = OpFunction %void None %void_func\n" +
  3775. "%main_lab = OpLabel\n" +
  3776. "%n = OpVariable %_ptr_uint Function\n" +
  3777. "%m = OpVariable %_ptr_uint Function\n" +
  3778. "%load_n = OpLoad %uint %n\n" +
  3779. "%load_m = OpLoad %uint %m\n" +
  3780. "%2 = OpUGreaterThanEqual %bool %load_n %load_m\n" +
  3781. "OpReturn\n" +
  3782. "OpFunctionEnd",
  3783. 2, 0),
  3784. // Test case 14: Don't fold n < m (signed)
  3785. InstructionFoldingCase<uint32_t>(
  3786. Header() + "%main = OpFunction %void None %void_func\n" +
  3787. "%main_lab = OpLabel\n" +
  3788. "%n = OpVariable %_ptr_int Function\n" +
  3789. "%m = OpVariable %_ptr_int Function\n" +
  3790. "%load_n = OpLoad %int %n\n" +
  3791. "%load_m = OpLoad %int %m\n" +
  3792. "%2 = OpULessThan %bool %load_n %load_m\n" +
  3793. "OpReturn\n" +
  3794. "OpFunctionEnd",
  3795. 2, 0),
  3796. // Test case 15: Don't fold n > m (signed)
  3797. InstructionFoldingCase<uint32_t>(
  3798. Header() + "%main = OpFunction %void None %void_func\n" +
  3799. "%main_lab = OpLabel\n" +
  3800. "%n = OpVariable %_ptr_int Function\n" +
  3801. "%m = OpVariable %_ptr_int Function\n" +
  3802. "%load_n = OpLoad %int %n\n" +
  3803. "%load_m = OpLoad %int %m\n" +
  3804. "%2 = OpUGreaterThan %bool %load_n %load_m\n" +
  3805. "OpReturn\n" +
  3806. "OpFunctionEnd",
  3807. 2, 0),
  3808. // Test case 16: Don't fold n <= m (signed)
  3809. InstructionFoldingCase<uint32_t>(
  3810. Header() + "%main = OpFunction %void None %void_func\n" +
  3811. "%main_lab = OpLabel\n" +
  3812. "%n = OpVariable %_ptr_int Function\n" +
  3813. "%m = OpVariable %_ptr_int Function\n" +
  3814. "%load_n = OpLoad %int %n\n" +
  3815. "%load_m = OpLoad %int %m\n" +
  3816. "%2 = OpULessThanEqual %bool %load_n %load_m\n" +
  3817. "OpReturn\n" +
  3818. "OpFunctionEnd",
  3819. 2, 0),
  3820. // Test case 17: Don't fold n >= m (signed)
  3821. InstructionFoldingCase<uint32_t>(
  3822. Header() + "%main = OpFunction %void None %void_func\n" +
  3823. "%main_lab = OpLabel\n" +
  3824. "%n = OpVariable %_ptr_int Function\n" +
  3825. "%m = OpVariable %_ptr_int Function\n" +
  3826. "%load_n = OpLoad %int %n\n" +
  3827. "%load_m = OpLoad %int %m\n" +
  3828. "%2 = OpUGreaterThanEqual %bool %load_n %load_m\n" +
  3829. "OpReturn\n" +
  3830. "OpFunctionEnd",
  3831. 2, 0),
  3832. // Test case 18: Don't fold n || m
  3833. InstructionFoldingCase<uint32_t>(
  3834. Header() + "%main = OpFunction %void None %void_func\n" +
  3835. "%main_lab = OpLabel\n" +
  3836. "%n = OpVariable %_ptr_bool Function\n" +
  3837. "%m = OpVariable %_ptr_bool Function\n" +
  3838. "%load_n = OpLoad %bool %n\n" +
  3839. "%load_m = OpLoad %bool %m\n" +
  3840. "%2 = OpLogicalOr %bool %load_n %load_m\n" +
  3841. "OpReturn\n" +
  3842. "OpFunctionEnd",
  3843. 2, 0),
  3844. // Test case 19: Don't fold n && m
  3845. InstructionFoldingCase<uint32_t>(
  3846. Header() + "%main = OpFunction %void None %void_func\n" +
  3847. "%main_lab = OpLabel\n" +
  3848. "%n = OpVariable %_ptr_bool Function\n" +
  3849. "%m = OpVariable %_ptr_bool Function\n" +
  3850. "%load_n = OpLoad %bool %n\n" +
  3851. "%load_m = OpLoad %bool %m\n" +
  3852. "%2 = OpLogicalAnd %bool %load_n %load_m\n" +
  3853. "OpReturn\n" +
  3854. "OpFunctionEnd",
  3855. 2, 0),
  3856. // Test case 20: Don't fold n * 3
  3857. InstructionFoldingCase<uint32_t>(
  3858. Header() + "%main = OpFunction %void None %void_func\n" +
  3859. "%main_lab = OpLabel\n" +
  3860. "%n = OpVariable %_ptr_int Function\n" +
  3861. "%load_n = OpLoad %int %n\n" +
  3862. "%2 = OpIMul %int %load_n %int_3\n" +
  3863. "OpReturn\n" +
  3864. "OpFunctionEnd",
  3865. 2, 0),
  3866. // Test case 21: Don't fold n / 3 (unsigned)
  3867. InstructionFoldingCase<uint32_t>(
  3868. Header() + "%main = OpFunction %void None %void_func\n" +
  3869. "%main_lab = OpLabel\n" +
  3870. "%n = OpVariable %_ptr_uint Function\n" +
  3871. "%load_n = OpLoad %uint %n\n" +
  3872. "%2 = OpUDiv %uint %load_n %uint_3\n" +
  3873. "OpReturn\n" +
  3874. "OpFunctionEnd",
  3875. 2, 0),
  3876. // Test case 22: Don't fold n / 3 (signed)
  3877. InstructionFoldingCase<uint32_t>(
  3878. Header() + "%main = OpFunction %void None %void_func\n" +
  3879. "%main_lab = OpLabel\n" +
  3880. "%n = OpVariable %_ptr_int Function\n" +
  3881. "%load_n = OpLoad %int %n\n" +
  3882. "%2 = OpSDiv %int %load_n %int_3\n" +
  3883. "OpReturn\n" +
  3884. "OpFunctionEnd",
  3885. 2, 0),
  3886. // Test case 23: Don't fold n remainder 3
  3887. InstructionFoldingCase<uint32_t>(
  3888. Header() + "%main = OpFunction %void None %void_func\n" +
  3889. "%main_lab = OpLabel\n" +
  3890. "%n = OpVariable %_ptr_int Function\n" +
  3891. "%load_n = OpLoad %int %n\n" +
  3892. "%2 = OpSRem %int %load_n %int_3\n" +
  3893. "OpReturn\n" +
  3894. "OpFunctionEnd",
  3895. 2, 0),
  3896. // Test case 24: Don't fold n % 3 (signed)
  3897. InstructionFoldingCase<uint32_t>(
  3898. Header() + "%main = OpFunction %void None %void_func\n" +
  3899. "%main_lab = OpLabel\n" +
  3900. "%n = OpVariable %_ptr_int Function\n" +
  3901. "%load_n = OpLoad %int %n\n" +
  3902. "%2 = OpSMod %int %load_n %int_3\n" +
  3903. "OpReturn\n" +
  3904. "OpFunctionEnd",
  3905. 2, 0),
  3906. // Test case 25: Don't fold n % 3 (unsigned)
  3907. InstructionFoldingCase<uint32_t>(
  3908. Header() + "%main = OpFunction %void None %void_func\n" +
  3909. "%main_lab = OpLabel\n" +
  3910. "%n = OpVariable %_ptr_uint Function\n" +
  3911. "%load_n = OpLoad %uint %n\n" +
  3912. "%2 = OpUMod %int %load_n %int_3\n" +
  3913. "OpReturn\n" +
  3914. "OpFunctionEnd",
  3915. 2, 0),
  3916. // Test case 26: Don't fold n << 3
  3917. InstructionFoldingCase<uint32_t>(
  3918. Header() + "%main = OpFunction %void None %void_func\n" +
  3919. "%main_lab = OpLabel\n" +
  3920. "%n = OpVariable %_ptr_uint Function\n" +
  3921. "%load_n = OpLoad %uint %n\n" +
  3922. "%2 = OpShiftRightLogical %int %load_n %int_3\n" +
  3923. "OpReturn\n" +
  3924. "OpFunctionEnd",
  3925. 2, 0),
  3926. // Test case 27: Don't fold n >> 3
  3927. InstructionFoldingCase<uint32_t>(
  3928. Header() + "%main = OpFunction %void None %void_func\n" +
  3929. "%main_lab = OpLabel\n" +
  3930. "%n = OpVariable %_ptr_uint Function\n" +
  3931. "%load_n = OpLoad %uint %n\n" +
  3932. "%2 = OpShiftLeftLogical %int %load_n %int_3\n" +
  3933. "OpReturn\n" +
  3934. "OpFunctionEnd",
  3935. 2, 0),
  3936. // Test case 28: Don't fold n | 3
  3937. InstructionFoldingCase<uint32_t>(
  3938. Header() + "%main = OpFunction %void None %void_func\n" +
  3939. "%main_lab = OpLabel\n" +
  3940. "%n = OpVariable %_ptr_uint Function\n" +
  3941. "%load_n = OpLoad %uint %n\n" +
  3942. "%2 = OpBitwiseOr %int %load_n %int_3\n" +
  3943. "OpReturn\n" +
  3944. "OpFunctionEnd",
  3945. 2, 0),
  3946. // Test case 29: Don't fold n & 3
  3947. InstructionFoldingCase<uint32_t>(
  3948. Header() + "%main = OpFunction %void None %void_func\n" +
  3949. "%main_lab = OpLabel\n" +
  3950. "%n = OpVariable %_ptr_uint Function\n" +
  3951. "%load_n = OpLoad %uint %n\n" +
  3952. "%2 = OpBitwiseAnd %uint %load_n %uint_3\n" +
  3953. "OpReturn\n" +
  3954. "OpFunctionEnd",
  3955. 2, 0),
  3956. // Test case 30: Don't fold n < 3 (unsigned)
  3957. InstructionFoldingCase<uint32_t>(
  3958. Header() + "%main = OpFunction %void None %void_func\n" +
  3959. "%main_lab = OpLabel\n" +
  3960. "%n = OpVariable %_ptr_uint Function\n" +
  3961. "%load_n = OpLoad %uint %n\n" +
  3962. "%2 = OpULessThan %bool %load_n %uint_3\n" +
  3963. "OpReturn\n" +
  3964. "OpFunctionEnd",
  3965. 2, 0),
  3966. // Test case 31: Don't fold n > 3 (unsigned)
  3967. InstructionFoldingCase<uint32_t>(
  3968. Header() + "%main = OpFunction %void None %void_func\n" +
  3969. "%main_lab = OpLabel\n" +
  3970. "%n = OpVariable %_ptr_uint Function\n" +
  3971. "%load_n = OpLoad %uint %n\n" +
  3972. "%2 = OpUGreaterThan %bool %load_n %uint_3\n" +
  3973. "OpReturn\n" +
  3974. "OpFunctionEnd",
  3975. 2, 0),
  3976. // Test case 32: Don't fold n <= 3 (unsigned)
  3977. InstructionFoldingCase<uint32_t>(
  3978. Header() + "%main = OpFunction %void None %void_func\n" +
  3979. "%main_lab = OpLabel\n" +
  3980. "%n = OpVariable %_ptr_uint Function\n" +
  3981. "%load_n = OpLoad %uint %n\n" +
  3982. "%2 = OpULessThanEqual %bool %load_n %uint_3\n" +
  3983. "OpReturn\n" +
  3984. "OpFunctionEnd",
  3985. 2, 0),
  3986. // Test case 33: Don't fold n >= 3 (unsigned)
  3987. InstructionFoldingCase<uint32_t>(
  3988. Header() + "%main = OpFunction %void None %void_func\n" +
  3989. "%main_lab = OpLabel\n" +
  3990. "%n = OpVariable %_ptr_uint Function\n" +
  3991. "%load_n = OpLoad %uint %n\n" +
  3992. "%2 = OpUGreaterThanEqual %bool %load_n %uint_3\n" +
  3993. "OpReturn\n" +
  3994. "OpFunctionEnd",
  3995. 2, 0),
  3996. // Test case 34: Don't fold n < 3 (signed)
  3997. InstructionFoldingCase<uint32_t>(
  3998. Header() + "%main = OpFunction %void None %void_func\n" +
  3999. "%main_lab = OpLabel\n" +
  4000. "%n = OpVariable %_ptr_int Function\n" +
  4001. "%load_n = OpLoad %int %n\n" +
  4002. "%2 = OpULessThan %bool %load_n %int_3\n" +
  4003. "OpReturn\n" +
  4004. "OpFunctionEnd",
  4005. 2, 0),
  4006. // Test case 35: Don't fold n > 3 (signed)
  4007. InstructionFoldingCase<uint32_t>(
  4008. Header() + "%main = OpFunction %void None %void_func\n" +
  4009. "%main_lab = OpLabel\n" +
  4010. "%n = OpVariable %_ptr_int Function\n" +
  4011. "%load_n = OpLoad %int %n\n" +
  4012. "%2 = OpUGreaterThan %bool %load_n %int_3\n" +
  4013. "OpReturn\n" +
  4014. "OpFunctionEnd",
  4015. 2, 0),
  4016. // Test case 36: Don't fold n <= 3 (signed)
  4017. InstructionFoldingCase<uint32_t>(
  4018. Header() + "%main = OpFunction %void None %void_func\n" +
  4019. "%main_lab = OpLabel\n" +
  4020. "%n = OpVariable %_ptr_int Function\n" +
  4021. "%load_n = OpLoad %int %n\n" +
  4022. "%2 = OpULessThanEqual %bool %load_n %int_3\n" +
  4023. "OpReturn\n" +
  4024. "OpFunctionEnd",
  4025. 2, 0),
  4026. // Test case 37: Don't fold n >= 3 (signed)
  4027. InstructionFoldingCase<uint32_t>(
  4028. Header() + "%main = OpFunction %void None %void_func\n" +
  4029. "%main_lab = OpLabel\n" +
  4030. "%n = OpVariable %_ptr_int Function\n" +
  4031. "%load_n = OpLoad %int %n\n" +
  4032. "%2 = OpUGreaterThanEqual %bool %load_n %int_3\n" +
  4033. "OpReturn\n" +
  4034. "OpFunctionEnd",
  4035. 2, 0),
  4036. // Test case 38: fold 1*n
  4037. InstructionFoldingCase<uint32_t>(
  4038. Header() + "%main = OpFunction %void None %void_func\n" +
  4039. "%main_lab = OpLabel\n" +
  4040. "%n = OpVariable %_ptr_int Function\n" +
  4041. "%3 = OpLoad %int %n\n" +
  4042. "%2 = OpIMul %int %int_1 %3\n" +
  4043. "OpReturn\n" +
  4044. "OpFunctionEnd",
  4045. 2, 3),
  4046. // Test case 39: fold n*1
  4047. InstructionFoldingCase<uint32_t>(
  4048. Header() + "%main = OpFunction %void None %void_func\n" +
  4049. "%main_lab = OpLabel\n" +
  4050. "%n = OpVariable %_ptr_int Function\n" +
  4051. "%3 = OpLoad %int %n\n" +
  4052. "%2 = OpIMul %int %3 %int_1\n" +
  4053. "OpReturn\n" +
  4054. "OpFunctionEnd",
  4055. 2, 3),
  4056. // Test case 40: Don't fold comparisons of 64-bit types
  4057. // (https://github.com/KhronosGroup/SPIRV-Tools/issues/3343).
  4058. InstructionFoldingCase<uint32_t>(
  4059. Header() + "%main = OpFunction %void None %void_func\n" +
  4060. "%main_lab = OpLabel\n" +
  4061. "%2 = OpSLessThan %bool %long_0 %long_2\n" +
  4062. "OpReturn\n" +
  4063. "OpFunctionEnd",
  4064. 2, 0),
  4065. // Test case 41: Don't fold OpSNegate for cooperative matrices.
  4066. InstructionFoldingCase<uint32_t>(
  4067. Header() + "%main = OpFunction %void None %void_func\n" +
  4068. "%main_lab = OpLabel\n" +
  4069. "%2 = OpSNegate %int_coop_matrix %undef_int_coop_matrix\n" +
  4070. "OpReturn\n" +
  4071. "OpFunctionEnd",
  4072. 2, 0),
  4073. // Test case 42: Don't fold OpIAdd for cooperative matrices.
  4074. InstructionFoldingCase<uint32_t>(
  4075. Header() + "%main = OpFunction %void None %void_func\n" +
  4076. "%main_lab = OpLabel\n" +
  4077. "%2 = OpIAdd %int_coop_matrix %undef_int_coop_matrix %undef_int_coop_matrix\n" +
  4078. "OpReturn\n" +
  4079. "OpFunctionEnd",
  4080. 2, 0),
  4081. // Test case 43: Don't fold OpISub for cooperative matrices.
  4082. InstructionFoldingCase<uint32_t>(
  4083. Header() + "%main = OpFunction %void None %void_func\n" +
  4084. "%main_lab = OpLabel\n" +
  4085. "%2 = OpISub %int_coop_matrix %undef_int_coop_matrix %undef_int_coop_matrix\n" +
  4086. "OpReturn\n" +
  4087. "OpFunctionEnd",
  4088. 2, 0),
  4089. // Test case 44: Don't fold OpIMul for cooperative matrices.
  4090. InstructionFoldingCase<uint32_t>(
  4091. Header() + "%main = OpFunction %void None %void_func\n" +
  4092. "%main_lab = OpLabel\n" +
  4093. "%2 = OpIMul %int_coop_matrix %undef_int_coop_matrix %undef_int_coop_matrix\n" +
  4094. "OpReturn\n" +
  4095. "OpFunctionEnd",
  4096. 2, 0),
  4097. // Test case 45: Don't fold OpSDiv for cooperative matrices.
  4098. InstructionFoldingCase<uint32_t>(
  4099. Header() + "%main = OpFunction %void None %void_func\n" +
  4100. "%main_lab = OpLabel\n" +
  4101. "%2 = OpSDiv %int_coop_matrix %undef_int_coop_matrix %undef_int_coop_matrix\n" +
  4102. "OpReturn\n" +
  4103. "OpFunctionEnd",
  4104. 2, 0),
  4105. // Test case 46: Don't fold OpUDiv for cooperative matrices.
  4106. InstructionFoldingCase<uint32_t>(
  4107. Header() + "%main = OpFunction %void None %void_func\n" +
  4108. "%main_lab = OpLabel\n" +
  4109. "%2 = OpUDiv %uint_coop_matrix %undef_uint_coop_matrix %undef_uint_coop_matrix\n" +
  4110. "OpReturn\n" +
  4111. "OpFunctionEnd",
  4112. 2, 0),
  4113. // Test case 47: Don't fold OpMatrixTimesScalar for cooperative matrices.
  4114. InstructionFoldingCase<uint32_t>(
  4115. Header() + "%main = OpFunction %void None %void_func\n" +
  4116. "%main_lab = OpLabel\n" +
  4117. "%2 = OpMatrixTimesScalar %uint_coop_matrix %undef_uint_coop_matrix %uint_3\n" +
  4118. "OpReturn\n" +
  4119. "OpFunctionEnd",
  4120. 2, 0)
  4121. ));
  4122. INSTANTIATE_TEST_SUITE_P(CompositeExtractFoldingTest, GeneralInstructionFoldingTest,
  4123. ::testing::Values(
  4124. // Test case 0: fold Insert feeding extract
  4125. InstructionFoldingCase<uint32_t>(
  4126. Header() + "%main = OpFunction %void None %void_func\n" +
  4127. "%main_lab = OpLabel\n" +
  4128. "%n = OpVariable %_ptr_int Function\n" +
  4129. "%2 = OpLoad %int %n\n" +
  4130. "%3 = OpCompositeInsert %v4int %2 %v4int_0_0_0_0 0\n" +
  4131. "%4 = OpCompositeInsert %v4int %int_1 %3 1\n" +
  4132. "%5 = OpCompositeInsert %v4int %int_1 %4 2\n" +
  4133. "%6 = OpCompositeInsert %v4int %int_1 %5 3\n" +
  4134. "%7 = OpCompositeExtract %int %6 0\n" +
  4135. "OpReturn\n" +
  4136. "OpFunctionEnd",
  4137. 7, 2),
  4138. // Test case 1: fold Composite construct feeding extract (position 0)
  4139. InstructionFoldingCase<uint32_t>(
  4140. Header() + "%main = OpFunction %void None %void_func\n" +
  4141. "%main_lab = OpLabel\n" +
  4142. "%n = OpVariable %_ptr_int Function\n" +
  4143. "%2 = OpLoad %int %n\n" +
  4144. "%3 = OpCompositeConstruct %v4int %2 %int_0 %int_0 %int_0\n" +
  4145. "%4 = OpCompositeExtract %int %3 0\n" +
  4146. "OpReturn\n" +
  4147. "OpFunctionEnd",
  4148. 4, 2),
  4149. // Test case 2: fold Composite construct feeding extract (position 3)
  4150. InstructionFoldingCase<uint32_t>(
  4151. Header() + "%main = OpFunction %void None %void_func\n" +
  4152. "%main_lab = OpLabel\n" +
  4153. "%n = OpVariable %_ptr_int Function\n" +
  4154. "%2 = OpLoad %int %n\n" +
  4155. "%3 = OpCompositeConstruct %v4int %2 %int_0 %int_0 %100\n" +
  4156. "%4 = OpCompositeExtract %int %3 3\n" +
  4157. "OpReturn\n" +
  4158. "OpFunctionEnd",
  4159. 4, INT_0_ID),
  4160. // Test case 3: fold Composite construct with vectors feeding extract (scalar element)
  4161. InstructionFoldingCase<uint32_t>(
  4162. Header() + "%main = OpFunction %void None %void_func\n" +
  4163. "%main_lab = OpLabel\n" +
  4164. "%n = OpVariable %_ptr_int Function\n" +
  4165. "%2 = OpLoad %int %n\n" +
  4166. "%3 = OpCompositeConstruct %v2int %2 %int_0\n" +
  4167. "%4 = OpCompositeConstruct %v4int %3 %int_0 %100\n" +
  4168. "%5 = OpCompositeExtract %int %4 3\n" +
  4169. "OpReturn\n" +
  4170. "OpFunctionEnd",
  4171. 5, INT_0_ID),
  4172. // Test case 4: fold Composite construct with vectors feeding extract (start of vector element)
  4173. InstructionFoldingCase<uint32_t>(
  4174. Header() + "%main = OpFunction %void None %void_func\n" +
  4175. "%main_lab = OpLabel\n" +
  4176. "%n = OpVariable %_ptr_int Function\n" +
  4177. "%2 = OpLoad %int %n\n" +
  4178. "%3 = OpCompositeConstruct %v2int %2 %int_0\n" +
  4179. "%4 = OpCompositeConstruct %v4int %3 %int_0 %100\n" +
  4180. "%5 = OpCompositeExtract %int %4 0\n" +
  4181. "OpReturn\n" +
  4182. "OpFunctionEnd",
  4183. 5, 2),
  4184. // Test case 5: fold Composite construct with vectors feeding extract (middle of vector element)
  4185. InstructionFoldingCase<uint32_t>(
  4186. Header() + "%main = OpFunction %void None %void_func\n" +
  4187. "%main_lab = OpLabel\n" +
  4188. "%n = OpVariable %_ptr_int Function\n" +
  4189. "%2 = OpLoad %int %n\n" +
  4190. "%3 = OpCompositeConstruct %v2int %int_0 %2\n" +
  4191. "%4 = OpCompositeConstruct %v4int %3 %int_0 %100\n" +
  4192. "%5 = OpCompositeExtract %int %4 1\n" +
  4193. "OpReturn\n" +
  4194. "OpFunctionEnd",
  4195. 5, 2),
  4196. // Test case 6: fold Composite construct with multiple indices.
  4197. InstructionFoldingCase<uint32_t>(
  4198. Header() + "%main = OpFunction %void None %void_func\n" +
  4199. "%main_lab = OpLabel\n" +
  4200. "%n = OpVariable %_ptr_int Function\n" +
  4201. "%2 = OpLoad %int %n\n" +
  4202. "%3 = OpCompositeConstruct %v2int %int_0 %2\n" +
  4203. "%4 = OpCompositeConstruct %struct_v2int_int_int %3 %int_0 %100\n" +
  4204. "%5 = OpCompositeExtract %int %4 0 1\n" +
  4205. "OpReturn\n" +
  4206. "OpFunctionEnd",
  4207. 5, 2),
  4208. // Test case 7: fold constant extract.
  4209. InstructionFoldingCase<uint32_t>(
  4210. Header() + "%main = OpFunction %void None %void_func\n" +
  4211. "%main_lab = OpLabel\n" +
  4212. "%2 = OpCompositeExtract %int %102 1\n" +
  4213. "OpReturn\n" +
  4214. "OpFunctionEnd",
  4215. 2, INT_7_ID),
  4216. // Test case 8: constant struct has OpUndef
  4217. InstructionFoldingCase<uint32_t>(
  4218. Header() + "%main = OpFunction %void None %void_func\n" +
  4219. "%main_lab = OpLabel\n" +
  4220. "%2 = OpCompositeExtract %int %struct_undef_0_0 0 1\n" +
  4221. "OpReturn\n" +
  4222. "OpFunctionEnd",
  4223. 2, 0),
  4224. // Test case 9: Extracting a member of element inserted via Insert
  4225. InstructionFoldingCase<uint32_t>(
  4226. Header() + "%main = OpFunction %void None %void_func\n" +
  4227. "%main_lab = OpLabel\n" +
  4228. "%n = OpVariable %_ptr_struct_v2int_int_int Function\n" +
  4229. "%2 = OpLoad %struct_v2int_int_int %n\n" +
  4230. "%3 = OpCompositeInsert %struct_v2int_int_int %102 %2 0\n" +
  4231. "%4 = OpCompositeExtract %int %3 0 1\n" +
  4232. "OpReturn\n" +
  4233. "OpFunctionEnd",
  4234. 4, 103),
  4235. // Test case 10: Extracting a element that is partially changed by Insert. (Don't fold)
  4236. InstructionFoldingCase<uint32_t>(
  4237. Header() + "%main = OpFunction %void None %void_func\n" +
  4238. "%main_lab = OpLabel\n" +
  4239. "%n = OpVariable %_ptr_struct_v2int_int_int Function\n" +
  4240. "%2 = OpLoad %struct_v2int_int_int %n\n" +
  4241. "%3 = OpCompositeInsert %struct_v2int_int_int %int_0 %2 0 1\n" +
  4242. "%4 = OpCompositeExtract %v2int %3 0\n" +
  4243. "OpReturn\n" +
  4244. "OpFunctionEnd",
  4245. 4, 0),
  4246. // Test case 11: Extracting from result of vector shuffle (first input)
  4247. InstructionFoldingCase<uint32_t>(
  4248. Header() + "%main = OpFunction %void None %void_func\n" +
  4249. "%main_lab = OpLabel\n" +
  4250. "%n = OpVariable %_ptr_v2int Function\n" +
  4251. "%2 = OpLoad %v2int %n\n" +
  4252. "%3 = OpVectorShuffle %v2int %102 %2 3 0\n" +
  4253. "%4 = OpCompositeExtract %int %3 1\n" +
  4254. "OpReturn\n" +
  4255. "OpFunctionEnd",
  4256. 4, INT_7_ID),
  4257. // Test case 12: Extracting from result of vector shuffle (second input)
  4258. InstructionFoldingCase<uint32_t>(
  4259. Header() + "%main = OpFunction %void None %void_func\n" +
  4260. "%main_lab = OpLabel\n" +
  4261. "%n = OpVariable %_ptr_v2int Function\n" +
  4262. "%2 = OpLoad %v2int %n\n" +
  4263. "%3 = OpVectorShuffle %v2int %2 %102 2 0\n" +
  4264. "%4 = OpCompositeExtract %int %3 0\n" +
  4265. "OpReturn\n" +
  4266. "OpFunctionEnd",
  4267. 4, INT_7_ID),
  4268. // Test case 13: https://github.com/KhronosGroup/SPIRV-Tools/issues/2608
  4269. // Out of bounds access. Do not fold.
  4270. InstructionFoldingCase<uint32_t>(
  4271. Header() + "%main = OpFunction %void None %void_func\n" +
  4272. "%main_lab = OpLabel\n" +
  4273. "%2 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1\n" +
  4274. "%3 = OpCompositeExtract %float %2 4\n" +
  4275. "OpReturn\n" +
  4276. "OpFunctionEnd",
  4277. 3, 0),
  4278. // Test case 14: https://github.com/KhronosGroup/SPIRV-Tools/issues/3631
  4279. // Extract the component right after the vector constituent.
  4280. InstructionFoldingCase<uint32_t>(
  4281. Header() + "%main = OpFunction %void None %void_func\n" +
  4282. "%main_lab = OpLabel\n" +
  4283. "%2 = OpCompositeConstruct %v2int %int_0 %int_0\n" +
  4284. "%3 = OpCompositeConstruct %v4int %2 %100 %int_0\n" +
  4285. "%4 = OpCompositeExtract %int %3 2\n" +
  4286. "OpReturn\n" +
  4287. "OpFunctionEnd",
  4288. 4, INT_0_ID),
  4289. // Test case 15:
  4290. // Don't fold extract fed by construct with vector result if the index is
  4291. // past the last element.
  4292. InstructionFoldingCase<uint32_t>(
  4293. Header() + "%main = OpFunction %void None %void_func\n" +
  4294. "%main_lab = OpLabel\n" +
  4295. "%2 = OpCompositeConstruct %v2int %int_0 %int_0\n" +
  4296. "%3 = OpCompositeConstruct %v4int %2 %100 %int_0\n" +
  4297. "%4 = OpCompositeExtract %int %3 4\n" +
  4298. "OpReturn\n" +
  4299. "OpFunctionEnd",
  4300. 4, 0)
  4301. ));
  4302. INSTANTIATE_TEST_SUITE_P(CompositeConstructFoldingTest, GeneralInstructionFoldingTest,
  4303. ::testing::Values(
  4304. // Test case 0: fold Extracts feeding construct
  4305. InstructionFoldingCase<uint32_t>(
  4306. Header() + "%main = OpFunction %void None %void_func\n" +
  4307. "%main_lab = OpLabel\n" +
  4308. "%2 = OpCopyObject %v4int %v4int_0_0_0_0\n" +
  4309. "%3 = OpCompositeExtract %int %2 0\n" +
  4310. "%4 = OpCompositeExtract %int %2 1\n" +
  4311. "%5 = OpCompositeExtract %int %2 2\n" +
  4312. "%6 = OpCompositeExtract %int %2 3\n" +
  4313. "%7 = OpCompositeConstruct %v4int %3 %4 %5 %6\n" +
  4314. "OpReturn\n" +
  4315. "OpFunctionEnd",
  4316. 7, 2),
  4317. // Test case 1: Don't fold Extracts feeding construct (Different source)
  4318. InstructionFoldingCase<uint32_t>(
  4319. Header() + "%main = OpFunction %void None %void_func\n" +
  4320. "%main_lab = OpLabel\n" +
  4321. "%2 = OpCopyObject %v4int %v4int_0_0_0_0\n" +
  4322. "%3 = OpCompositeExtract %int %2 0\n" +
  4323. "%4 = OpCompositeExtract %int %2 1\n" +
  4324. "%5 = OpCompositeExtract %int %2 2\n" +
  4325. "%6 = OpCompositeExtract %int %v4int_0_0_0_0 3\n" +
  4326. "%7 = OpCompositeConstruct %v4int %3 %4 %5 %6\n" +
  4327. "OpReturn\n" +
  4328. "OpFunctionEnd",
  4329. 7, 0),
  4330. // Test case 2: Don't fold Extracts feeding construct (bad indices)
  4331. InstructionFoldingCase<uint32_t>(
  4332. Header() + "%main = OpFunction %void None %void_func\n" +
  4333. "%main_lab = OpLabel\n" +
  4334. "%2 = OpCopyObject %v4int %v4int_0_0_0_0\n" +
  4335. "%3 = OpCompositeExtract %int %2 0\n" +
  4336. "%4 = OpCompositeExtract %int %2 0\n" +
  4337. "%5 = OpCompositeExtract %int %2 2\n" +
  4338. "%6 = OpCompositeExtract %int %2 3\n" +
  4339. "%7 = OpCompositeConstruct %v4int %3 %4 %5 %6\n" +
  4340. "OpReturn\n" +
  4341. "OpFunctionEnd",
  4342. 7, 0),
  4343. // Test case 3: Don't fold Extracts feeding construct (different type)
  4344. InstructionFoldingCase<uint32_t>(
  4345. Header() + "%main = OpFunction %void None %void_func\n" +
  4346. "%main_lab = OpLabel\n" +
  4347. "%2 = OpCopyObject %struct_v2int_int_int %struct_v2int_int_int_null\n" +
  4348. "%3 = OpCompositeExtract %v2int %2 0\n" +
  4349. "%4 = OpCompositeExtract %int %2 1\n" +
  4350. "%5 = OpCompositeExtract %int %2 2\n" +
  4351. "%7 = OpCompositeConstruct %v4int %3 %4 %5\n" +
  4352. "OpReturn\n" +
  4353. "OpFunctionEnd",
  4354. 7, 0),
  4355. // Test case 4: Fold construct with constants to constant.
  4356. InstructionFoldingCase<uint32_t>(
  4357. Header() + "%main = OpFunction %void None %void_func\n" +
  4358. "%main_lab = OpLabel\n" +
  4359. "%2 = OpCompositeConstruct %v2int %103 %103\n" +
  4360. "OpReturn\n" +
  4361. "OpFunctionEnd",
  4362. 2, VEC2_0_ID),
  4363. // Test case 5: Don't segfault when trying to fold an OpCompositeConstruct
  4364. // for an empty struct, and we reached the id limit.
  4365. InstructionFoldingCase<uint32_t>(
  4366. Header() + "%empty_struct = OpTypeStruct\n" +
  4367. "%main = OpFunction %void None %void_func\n" +
  4368. "%main_lab = OpLabel\n" +
  4369. "%4194303 = OpCompositeConstruct %empty_struct\n" +
  4370. "OpReturn\n" +
  4371. "OpFunctionEnd",
  4372. 4194303, 0)
  4373. ));
  4374. INSTANTIATE_TEST_SUITE_P(PhiFoldingTest, GeneralInstructionFoldingTest,
  4375. ::testing::Values(
  4376. // Test case 0: Fold phi with the same values for all edges.
  4377. InstructionFoldingCase<uint32_t>(
  4378. Header() + "%main = OpFunction %void None %void_func\n" +
  4379. "%main_lab = OpLabel\n" +
  4380. " OpBranchConditional %true %l1 %l2\n" +
  4381. "%l1 = OpLabel\n" +
  4382. " OpBranch %merge_lab\n" +
  4383. "%l2 = OpLabel\n" +
  4384. " OpBranch %merge_lab\n" +
  4385. "%merge_lab = OpLabel\n" +
  4386. "%2 = OpPhi %int %100 %l1 %100 %l2\n" +
  4387. "OpReturn\n" +
  4388. "OpFunctionEnd",
  4389. 2, INT_0_ID),
  4390. // Test case 1: Fold phi in pass through loop.
  4391. InstructionFoldingCase<uint32_t>(
  4392. Header() + "%main = OpFunction %void None %void_func\n" +
  4393. "%main_lab = OpLabel\n" +
  4394. " OpBranch %l1\n" +
  4395. "%l1 = OpLabel\n" +
  4396. "%2 = OpPhi %int %100 %main_lab %2 %l1\n" +
  4397. " OpBranchConditional %true %l1 %merge_lab\n" +
  4398. "%merge_lab = OpLabel\n" +
  4399. "OpReturn\n" +
  4400. "OpFunctionEnd",
  4401. 2, INT_0_ID),
  4402. // Test case 2: Don't Fold phi because of different values.
  4403. InstructionFoldingCase<uint32_t>(
  4404. Header() + "%main = OpFunction %void None %void_func\n" +
  4405. "%main_lab = OpLabel\n" +
  4406. " OpBranch %l1\n" +
  4407. "%l1 = OpLabel\n" +
  4408. "%2 = OpPhi %int %int_0 %main_lab %int_3 %l1\n" +
  4409. " OpBranchConditional %true %l1 %merge_lab\n" +
  4410. "%merge_lab = OpLabel\n" +
  4411. "OpReturn\n" +
  4412. "OpFunctionEnd",
  4413. 2, 0)
  4414. ));
  4415. INSTANTIATE_TEST_SUITE_P(FloatRedundantFoldingTest, GeneralInstructionFoldingTest,
  4416. ::testing::Values(
  4417. // Test case 0: Don't fold n + 1.0
  4418. InstructionFoldingCase<uint32_t>(
  4419. Header() + "%main = OpFunction %void None %void_func\n" +
  4420. "%main_lab = OpLabel\n" +
  4421. "%n = OpVariable %_ptr_float Function\n" +
  4422. "%3 = OpLoad %float %n\n" +
  4423. "%2 = OpFAdd %float %3 %float_2\n" +
  4424. "OpReturn\n" +
  4425. "OpFunctionEnd",
  4426. 2, 0),
  4427. // Test case 1: Don't fold n - 1.0
  4428. InstructionFoldingCase<uint32_t>(
  4429. Header() + "%main = OpFunction %void None %void_func\n" +
  4430. "%main_lab = OpLabel\n" +
  4431. "%n = OpVariable %_ptr_float Function\n" +
  4432. "%3 = OpLoad %float %n\n" +
  4433. "%2 = OpFSub %float %3 %float_2\n" +
  4434. "OpReturn\n" +
  4435. "OpFunctionEnd",
  4436. 2, 0),
  4437. // Test case 2: Don't fold n * 2.0
  4438. InstructionFoldingCase<uint32_t>(
  4439. Header() + "%main = OpFunction %void None %void_func\n" +
  4440. "%main_lab = OpLabel\n" +
  4441. "%n = OpVariable %_ptr_float Function\n" +
  4442. "%3 = OpLoad %float %n\n" +
  4443. "%2 = OpFMul %float %3 %float_2\n" +
  4444. "OpReturn\n" +
  4445. "OpFunctionEnd",
  4446. 2, 0),
  4447. // Test case 3: Fold n + 0.0
  4448. InstructionFoldingCase<uint32_t>(
  4449. Header() + "%main = OpFunction %void None %void_func\n" +
  4450. "%main_lab = OpLabel\n" +
  4451. "%n = OpVariable %_ptr_float Function\n" +
  4452. "%3 = OpLoad %float %n\n" +
  4453. "%2 = OpFAdd %float %3 %float_0\n" +
  4454. "OpReturn\n" +
  4455. "OpFunctionEnd",
  4456. 2, 3),
  4457. // Test case 4: Fold 0.0 + n
  4458. InstructionFoldingCase<uint32_t>(
  4459. Header() + "%main = OpFunction %void None %void_func\n" +
  4460. "%main_lab = OpLabel\n" +
  4461. "%n = OpVariable %_ptr_float Function\n" +
  4462. "%3 = OpLoad %float %n\n" +
  4463. "%2 = OpFAdd %float %float_0 %3\n" +
  4464. "OpReturn\n" +
  4465. "OpFunctionEnd",
  4466. 2, 3),
  4467. // Test case 5: Fold n - 0.0
  4468. InstructionFoldingCase<uint32_t>(
  4469. Header() + "%main = OpFunction %void None %void_func\n" +
  4470. "%main_lab = OpLabel\n" +
  4471. "%n = OpVariable %_ptr_float Function\n" +
  4472. "%3 = OpLoad %float %n\n" +
  4473. "%2 = OpFSub %float %3 %float_0\n" +
  4474. "OpReturn\n" +
  4475. "OpFunctionEnd",
  4476. 2, 3),
  4477. // Test case 6: Fold n * 1.0
  4478. InstructionFoldingCase<uint32_t>(
  4479. Header() + "%main = OpFunction %void None %void_func\n" +
  4480. "%main_lab = OpLabel\n" +
  4481. "%n = OpVariable %_ptr_float Function\n" +
  4482. "%3 = OpLoad %float %n\n" +
  4483. "%2 = OpFMul %float %3 %float_1\n" +
  4484. "OpReturn\n" +
  4485. "OpFunctionEnd",
  4486. 2, 3),
  4487. // Test case 7: Fold 1.0 * n
  4488. InstructionFoldingCase<uint32_t>(
  4489. Header() + "%main = OpFunction %void None %void_func\n" +
  4490. "%main_lab = OpLabel\n" +
  4491. "%n = OpVariable %_ptr_float Function\n" +
  4492. "%3 = OpLoad %float %n\n" +
  4493. "%2 = OpFMul %float %float_1 %3\n" +
  4494. "OpReturn\n" +
  4495. "OpFunctionEnd",
  4496. 2, 3),
  4497. // Test case 8: Fold n / 1.0
  4498. InstructionFoldingCase<uint32_t>(
  4499. Header() + "%main = OpFunction %void None %void_func\n" +
  4500. "%main_lab = OpLabel\n" +
  4501. "%n = OpVariable %_ptr_float Function\n" +
  4502. "%3 = OpLoad %float %n\n" +
  4503. "%2 = OpFDiv %float %3 %float_1\n" +
  4504. "OpReturn\n" +
  4505. "OpFunctionEnd",
  4506. 2, 3),
  4507. // Test case 9: Fold n % 1.0
  4508. InstructionFoldingCase<uint32_t>(
  4509. Header() + "%main = OpFunction %void None %void_func\n" +
  4510. "%main_lab = OpLabel\n" +
  4511. "%n = OpVariable %_ptr_float Function\n" +
  4512. "%3 = OpLoad %float %n\n" +
  4513. "%2 = OpFMod %float %3 %float_1\n" +
  4514. "OpReturn\n" +
  4515. "OpFunctionEnd",
  4516. 2, FLOAT_0_ID),
  4517. // Test case 10: Fold n * 0.0
  4518. InstructionFoldingCase<uint32_t>(
  4519. Header() + "%main = OpFunction %void None %void_func\n" +
  4520. "%main_lab = OpLabel\n" +
  4521. "%n = OpVariable %_ptr_float Function\n" +
  4522. "%3 = OpLoad %float %n\n" +
  4523. "%2 = OpFMul %float %3 %104\n" +
  4524. "OpReturn\n" +
  4525. "OpFunctionEnd",
  4526. 2, FLOAT_0_ID),
  4527. // Test case 11: Fold 0.0 * n
  4528. InstructionFoldingCase<uint32_t>(
  4529. Header() + "%main = OpFunction %void None %void_func\n" +
  4530. "%main_lab = OpLabel\n" +
  4531. "%n = OpVariable %_ptr_float Function\n" +
  4532. "%3 = OpLoad %float %n\n" +
  4533. "%2 = OpFMul %float %104 %3\n" +
  4534. "OpReturn\n" +
  4535. "OpFunctionEnd",
  4536. 2, FLOAT_0_ID),
  4537. // Test case 12: Fold 0.0 / n
  4538. InstructionFoldingCase<uint32_t>(
  4539. Header() + "%main = OpFunction %void None %void_func\n" +
  4540. "%main_lab = OpLabel\n" +
  4541. "%n = OpVariable %_ptr_float Function\n" +
  4542. "%3 = OpLoad %float %n\n" +
  4543. "%2 = OpFDiv %float %104 %3\n" +
  4544. "OpReturn\n" +
  4545. "OpFunctionEnd",
  4546. 2, FLOAT_0_ID),
  4547. // Test case 13: Fold 0.0 % n
  4548. InstructionFoldingCase<uint32_t>(
  4549. Header() + "%main = OpFunction %void None %void_func\n" +
  4550. "%main_lab = OpLabel\n" +
  4551. "%n = OpVariable %_ptr_float Function\n" +
  4552. "%3 = OpLoad %float %n\n" +
  4553. "%2 = OpFMod %float %104 %3\n" +
  4554. "OpReturn\n" +
  4555. "OpFunctionEnd",
  4556. 2, FLOAT_0_ID),
  4557. // Test case 14: Don't fold mix(a, b, 2.0)
  4558. InstructionFoldingCase<uint32_t>(
  4559. Header() + "%main = OpFunction %void None %void_func\n" +
  4560. "%main_lab = OpLabel\n" +
  4561. "%a = OpVariable %_ptr_float Function\n" +
  4562. "%b = OpVariable %_ptr_float Function\n" +
  4563. "%3 = OpLoad %float %a\n" +
  4564. "%4 = OpLoad %float %b\n" +
  4565. "%2 = OpExtInst %float %1 FMix %3 %4 %float_2\n" +
  4566. "OpReturn\n" +
  4567. "OpFunctionEnd",
  4568. 2, 0),
  4569. // Test case 15: Fold mix(a, b, 0.0)
  4570. InstructionFoldingCase<uint32_t>(
  4571. Header() + "%main = OpFunction %void None %void_func\n" +
  4572. "%main_lab = OpLabel\n" +
  4573. "%a = OpVariable %_ptr_float Function\n" +
  4574. "%b = OpVariable %_ptr_float Function\n" +
  4575. "%3 = OpLoad %float %a\n" +
  4576. "%4 = OpLoad %float %b\n" +
  4577. "%2 = OpExtInst %float %1 FMix %3 %4 %float_0\n" +
  4578. "OpReturn\n" +
  4579. "OpFunctionEnd",
  4580. 2, 3),
  4581. // Test case 16: Fold mix(a, b, 1.0)
  4582. InstructionFoldingCase<uint32_t>(
  4583. Header() + "%main = OpFunction %void None %void_func\n" +
  4584. "%main_lab = OpLabel\n" +
  4585. "%a = OpVariable %_ptr_float Function\n" +
  4586. "%b = OpVariable %_ptr_float Function\n" +
  4587. "%3 = OpLoad %float %a\n" +
  4588. "%4 = OpLoad %float %b\n" +
  4589. "%2 = OpExtInst %float %1 FMix %3 %4 %float_1\n" +
  4590. "OpReturn\n" +
  4591. "OpFunctionEnd",
  4592. 2, 4),
  4593. // Test case 17: Fold vector fadd with null
  4594. InstructionFoldingCase<uint32_t>(
  4595. Header() + "%main = OpFunction %void None %void_func\n" +
  4596. "%main_lab = OpLabel\n" +
  4597. "%a = OpVariable %_ptr_v2float Function\n" +
  4598. "%2 = OpLoad %v2float %a\n" +
  4599. "%3 = OpFAdd %v2float %2 %v2float_null\n" +
  4600. "OpReturn\n" +
  4601. "OpFunctionEnd",
  4602. 3, 2),
  4603. // Test case 18: Fold vector fadd with null
  4604. InstructionFoldingCase<uint32_t>(
  4605. Header() + "%main = OpFunction %void None %void_func\n" +
  4606. "%main_lab = OpLabel\n" +
  4607. "%a = OpVariable %_ptr_v2float Function\n" +
  4608. "%2 = OpLoad %v2float %a\n" +
  4609. "%3 = OpFAdd %v2float %v2float_null %2\n" +
  4610. "OpReturn\n" +
  4611. "OpFunctionEnd",
  4612. 3, 2),
  4613. // Test case 19: Fold vector fsub with null
  4614. InstructionFoldingCase<uint32_t>(
  4615. Header() + "%main = OpFunction %void None %void_func\n" +
  4616. "%main_lab = OpLabel\n" +
  4617. "%a = OpVariable %_ptr_v2float Function\n" +
  4618. "%2 = OpLoad %v2float %a\n" +
  4619. "%3 = OpFSub %v2float %2 %v2float_null\n" +
  4620. "OpReturn\n" +
  4621. "OpFunctionEnd",
  4622. 3, 2),
  4623. // Test case 20: Fold 0.0(half) * n
  4624. InstructionFoldingCase<uint32_t>(
  4625. Header() + "%main = OpFunction %void None %void_func\n" +
  4626. "%main_lab = OpLabel\n" +
  4627. "%n = OpVariable %_ptr_half Function\n" +
  4628. "%3 = OpLoad %half %n\n" +
  4629. "%2 = OpFMul %half %108 %3\n" +
  4630. "OpReturn\n" +
  4631. "OpFunctionEnd",
  4632. 2, HALF_0_ID),
  4633. // Test case 21: Don't fold 1.0(half) * n
  4634. InstructionFoldingCase<uint32_t>(
  4635. Header() + "%main = OpFunction %void None %void_func\n" +
  4636. "%main_lab = OpLabel\n" +
  4637. "%n = OpVariable %_ptr_half Function\n" +
  4638. "%3 = OpLoad %half %n\n" +
  4639. "%2 = OpFMul %half %half_1 %3\n" +
  4640. "OpReturn\n" +
  4641. "OpFunctionEnd",
  4642. 2, 0),
  4643. // Test case 22: Don't fold 1.0 * 1.0 (half)
  4644. InstructionFoldingCase<uint32_t>(
  4645. Header() + "%main = OpFunction %void None %void_func\n" +
  4646. "%main_lab = OpLabel\n" +
  4647. "%2 = OpFMul %half %half_1 %half_1\n" +
  4648. "OpReturn\n" +
  4649. "OpFunctionEnd",
  4650. 2, 0),
  4651. // Test case 23: Don't fold (0.0, 1.0) * (0.0, 1.0) (half)
  4652. InstructionFoldingCase<uint32_t>(
  4653. Header() + "%main = OpFunction %void None %void_func\n" +
  4654. "%main_lab = OpLabel\n" +
  4655. "%2 = OpFMul %v2half %half_0_1 %half_0_1\n" +
  4656. "OpReturn\n" +
  4657. "OpFunctionEnd",
  4658. 2, 0),
  4659. // Test case 24: Don't fold (0.0, 1.0) dotp (0.0, 1.0) (half)
  4660. InstructionFoldingCase<uint32_t>(
  4661. Header() + "%main = OpFunction %void None %void_func\n" +
  4662. "%main_lab = OpLabel\n" +
  4663. "%2 = OpDot %half %half_0_1 %half_0_1\n" +
  4664. "OpReturn\n" +
  4665. "OpFunctionEnd",
  4666. 2, 0),
  4667. // Test case 25: Don't fold 1.0(half) / 2.0(half)
  4668. // We do not have to code to emulate 16-bit float operations. Just make sure we do not crash.
  4669. InstructionFoldingCase<uint32_t>(
  4670. Header() + "%main = OpFunction %void None %void_func\n" +
  4671. "%main_lab = OpLabel\n" +
  4672. "%n = OpVariable %_ptr_half Function\n" +
  4673. "%3 = OpLoad %half %n\n" +
  4674. "%2 = OpFDiv %half %half_1 %half_2\n" +
  4675. "OpReturn\n" +
  4676. "OpFunctionEnd",
  4677. 2, 0),
  4678. // Test case 26: Don't fold OpFNegate for cooperative matrices.
  4679. InstructionFoldingCase<uint32_t>(
  4680. Header() + "%main = OpFunction %void None %void_func\n" +
  4681. "%main_lab = OpLabel\n" +
  4682. "%2 = OpFNegate %float_coop_matrix %undef_float_coop_matrix\n" +
  4683. "OpReturn\n" +
  4684. "OpFunctionEnd",
  4685. 2, 0),
  4686. // Test case 27: Don't fold OpIAdd for cooperative matrices.
  4687. InstructionFoldingCase<uint32_t>(
  4688. Header() + "%main = OpFunction %void None %void_func\n" +
  4689. "%main_lab = OpLabel\n" +
  4690. "%2 = OpFAdd %float_coop_matrix %undef_float_coop_matrix %undef_float_coop_matrix\n" +
  4691. "OpReturn\n" +
  4692. "OpFunctionEnd",
  4693. 2, 0),
  4694. // Test case 28: Don't fold OpISub for cooperative matrices.
  4695. InstructionFoldingCase<uint32_t>(
  4696. Header() + "%main = OpFunction %void None %void_func\n" +
  4697. "%main_lab = OpLabel\n" +
  4698. "%2 = OpFSub %float_coop_matrix %undef_float_coop_matrix %undef_float_coop_matrix\n" +
  4699. "OpReturn\n" +
  4700. "OpFunctionEnd",
  4701. 2, 0),
  4702. // Test case 29: Don't fold OpIMul for cooperative matrices.
  4703. InstructionFoldingCase<uint32_t>(
  4704. Header() + "%main = OpFunction %void None %void_func\n" +
  4705. "%main_lab = OpLabel\n" +
  4706. "%2 = OpFMul %float_coop_matrix %undef_float_coop_matrix %undef_float_coop_matrix\n" +
  4707. "OpReturn\n" +
  4708. "OpFunctionEnd",
  4709. 2, 0),
  4710. // Test case 30: Don't fold OpSDiv for cooperative matrices.
  4711. InstructionFoldingCase<uint32_t>(
  4712. Header() + "%main = OpFunction %void None %void_func\n" +
  4713. "%main_lab = OpLabel\n" +
  4714. "%2 = OpFDiv %float_coop_matrix %undef_float_coop_matrix %undef_float_coop_matrix\n" +
  4715. "OpReturn\n" +
  4716. "OpFunctionEnd",
  4717. 2, 0),
  4718. // Test case 31: Don't fold OpMatrixTimesScalar for cooperative matrices.
  4719. InstructionFoldingCase<uint32_t>(
  4720. Header() + "%main = OpFunction %void None %void_func\n" +
  4721. "%main_lab = OpLabel\n" +
  4722. "%2 = OpMatrixTimesScalar %float_coop_matrix %undef_float_coop_matrix %float_3\n" +
  4723. "OpReturn\n" +
  4724. "OpFunctionEnd",
  4725. 2, 0)
  4726. ));
  4727. INSTANTIATE_TEST_SUITE_P(DoubleRedundantFoldingTest, GeneralInstructionFoldingTest,
  4728. ::testing::Values(
  4729. // Test case 0: Don't fold n + 1.0
  4730. InstructionFoldingCase<uint32_t>(
  4731. Header() + "%main = OpFunction %void None %void_func\n" +
  4732. "%main_lab = OpLabel\n" +
  4733. "%n = OpVariable %_ptr_double Function\n" +
  4734. "%3 = OpLoad %double %n\n" +
  4735. "%2 = OpFAdd %double %3 %double_2\n" +
  4736. "OpReturn\n" +
  4737. "OpFunctionEnd",
  4738. 2, 0),
  4739. // Test case 1: Don't fold n - 1.0
  4740. InstructionFoldingCase<uint32_t>(
  4741. Header() + "%main = OpFunction %void None %void_func\n" +
  4742. "%main_lab = OpLabel\n" +
  4743. "%n = OpVariable %_ptr_double Function\n" +
  4744. "%3 = OpLoad %double %n\n" +
  4745. "%2 = OpFSub %double %3 %double_2\n" +
  4746. "OpReturn\n" +
  4747. "OpFunctionEnd",
  4748. 2, 0),
  4749. // Test case 2: Don't fold n * 2.0
  4750. InstructionFoldingCase<uint32_t>(
  4751. Header() + "%main = OpFunction %void None %void_func\n" +
  4752. "%main_lab = OpLabel\n" +
  4753. "%n = OpVariable %_ptr_double Function\n" +
  4754. "%3 = OpLoad %double %n\n" +
  4755. "%2 = OpFMul %double %3 %double_2\n" +
  4756. "OpReturn\n" +
  4757. "OpFunctionEnd",
  4758. 2, 0),
  4759. // Test case 3: Fold n + 0.0
  4760. InstructionFoldingCase<uint32_t>(
  4761. Header() + "%main = OpFunction %void None %void_func\n" +
  4762. "%main_lab = OpLabel\n" +
  4763. "%n = OpVariable %_ptr_double Function\n" +
  4764. "%3 = OpLoad %double %n\n" +
  4765. "%2 = OpFAdd %double %3 %double_0\n" +
  4766. "OpReturn\n" +
  4767. "OpFunctionEnd",
  4768. 2, 3),
  4769. // Test case 4: Fold 0.0 + n
  4770. InstructionFoldingCase<uint32_t>(
  4771. Header() + "%main = OpFunction %void None %void_func\n" +
  4772. "%main_lab = OpLabel\n" +
  4773. "%n = OpVariable %_ptr_double Function\n" +
  4774. "%3 = OpLoad %double %n\n" +
  4775. "%2 = OpFAdd %double %double_0 %3\n" +
  4776. "OpReturn\n" +
  4777. "OpFunctionEnd",
  4778. 2, 3),
  4779. // Test case 5: Fold n - 0.0
  4780. InstructionFoldingCase<uint32_t>(
  4781. Header() + "%main = OpFunction %void None %void_func\n" +
  4782. "%main_lab = OpLabel\n" +
  4783. "%n = OpVariable %_ptr_double Function\n" +
  4784. "%3 = OpLoad %double %n\n" +
  4785. "%2 = OpFSub %double %3 %double_0\n" +
  4786. "OpReturn\n" +
  4787. "OpFunctionEnd",
  4788. 2, 3),
  4789. // Test case 6: Fold n * 1.0
  4790. InstructionFoldingCase<uint32_t>(
  4791. Header() + "%main = OpFunction %void None %void_func\n" +
  4792. "%main_lab = OpLabel\n" +
  4793. "%n = OpVariable %_ptr_double Function\n" +
  4794. "%3 = OpLoad %double %n\n" +
  4795. "%2 = OpFMul %double %3 %double_1\n" +
  4796. "OpReturn\n" +
  4797. "OpFunctionEnd",
  4798. 2, 3),
  4799. // Test case 7: Fold 1.0 * n
  4800. InstructionFoldingCase<uint32_t>(
  4801. Header() + "%main = OpFunction %void None %void_func\n" +
  4802. "%main_lab = OpLabel\n" +
  4803. "%n = OpVariable %_ptr_double Function\n" +
  4804. "%3 = OpLoad %double %n\n" +
  4805. "%2 = OpFMul %double %double_1 %3\n" +
  4806. "OpReturn\n" +
  4807. "OpFunctionEnd",
  4808. 2, 3),
  4809. // Test case 8: Fold n / 1.0
  4810. InstructionFoldingCase<uint32_t>(
  4811. Header() + "%main = OpFunction %void None %void_func\n" +
  4812. "%main_lab = OpLabel\n" +
  4813. "%n = OpVariable %_ptr_double Function\n" +
  4814. "%3 = OpLoad %double %n\n" +
  4815. "%2 = OpFDiv %double %3 %double_1\n" +
  4816. "OpReturn\n" +
  4817. "OpFunctionEnd",
  4818. 2, 3),
  4819. // Test case 9: Fold n * 0.0
  4820. InstructionFoldingCase<uint32_t>(
  4821. Header() + "%main = OpFunction %void None %void_func\n" +
  4822. "%main_lab = OpLabel\n" +
  4823. "%n = OpVariable %_ptr_double Function\n" +
  4824. "%3 = OpLoad %double %n\n" +
  4825. "%2 = OpFMul %double %3 %105\n" +
  4826. "OpReturn\n" +
  4827. "OpFunctionEnd",
  4828. 2, DOUBLE_0_ID),
  4829. // Test case 10: Fold 0.0 * n
  4830. InstructionFoldingCase<uint32_t>(
  4831. Header() + "%main = OpFunction %void None %void_func\n" +
  4832. "%main_lab = OpLabel\n" +
  4833. "%n = OpVariable %_ptr_double Function\n" +
  4834. "%3 = OpLoad %double %n\n" +
  4835. "%2 = OpFMul %double %105 %3\n" +
  4836. "OpReturn\n" +
  4837. "OpFunctionEnd",
  4838. 2, DOUBLE_0_ID),
  4839. // Test case 11: 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_double Function\n" +
  4844. "%3 = OpLoad %double %n\n" +
  4845. "%2 = OpFDiv %double %105 %3\n" +
  4846. "OpReturn\n" +
  4847. "OpFunctionEnd",
  4848. 2, DOUBLE_0_ID),
  4849. // Test case 12: Don't fold mix(a, b, 2.0)
  4850. InstructionFoldingCase<uint32_t>(
  4851. Header() + "%main = OpFunction %void None %void_func\n" +
  4852. "%main_lab = OpLabel\n" +
  4853. "%a = OpVariable %_ptr_double Function\n" +
  4854. "%b = OpVariable %_ptr_double Function\n" +
  4855. "%3 = OpLoad %double %a\n" +
  4856. "%4 = OpLoad %double %b\n" +
  4857. "%2 = OpExtInst %double %1 FMix %3 %4 %double_2\n" +
  4858. "OpReturn\n" +
  4859. "OpFunctionEnd",
  4860. 2, 0),
  4861. // Test case 13: Fold mix(a, b, 0.0)
  4862. InstructionFoldingCase<uint32_t>(
  4863. Header() + "%main = OpFunction %void None %void_func\n" +
  4864. "%main_lab = OpLabel\n" +
  4865. "%a = OpVariable %_ptr_double Function\n" +
  4866. "%b = OpVariable %_ptr_double Function\n" +
  4867. "%3 = OpLoad %double %a\n" +
  4868. "%4 = OpLoad %double %b\n" +
  4869. "%2 = OpExtInst %double %1 FMix %3 %4 %double_0\n" +
  4870. "OpReturn\n" +
  4871. "OpFunctionEnd",
  4872. 2, 3),
  4873. // Test case 14: Fold mix(a, b, 1.0)
  4874. InstructionFoldingCase<uint32_t>(
  4875. Header() + "%main = OpFunction %void None %void_func\n" +
  4876. "%main_lab = OpLabel\n" +
  4877. "%a = OpVariable %_ptr_double Function\n" +
  4878. "%b = OpVariable %_ptr_double Function\n" +
  4879. "%3 = OpLoad %double %a\n" +
  4880. "%4 = OpLoad %double %b\n" +
  4881. "%2 = OpExtInst %double %1 FMix %3 %4 %double_1\n" +
  4882. "OpReturn\n" +
  4883. "OpFunctionEnd",
  4884. 2, 4)
  4885. ));
  4886. INSTANTIATE_TEST_SUITE_P(FloatVectorRedundantFoldingTest, GeneralInstructionFoldingTest,
  4887. ::testing::Values(
  4888. // Test case 0: Don't fold a * vec4(0.0, 0.0, 0.0, 1.0)
  4889. InstructionFoldingCase<uint32_t>(
  4890. Header() + "%main = OpFunction %void None %void_func\n" +
  4891. "%main_lab = OpLabel\n" +
  4892. "%n = OpVariable %_ptr_v4float Function\n" +
  4893. "%3 = OpLoad %v4float %n\n" +
  4894. "%2 = OpFMul %v4float %3 %v4float_0_0_0_1\n" +
  4895. "OpReturn\n" +
  4896. "OpFunctionEnd",
  4897. 2, 0),
  4898. // Test case 1: Fold a * vec4(0.0, 0.0, 0.0, 0.0)
  4899. InstructionFoldingCase<uint32_t>(
  4900. Header() + "%main = OpFunction %void None %void_func\n" +
  4901. "%main_lab = OpLabel\n" +
  4902. "%n = OpVariable %_ptr_v4float Function\n" +
  4903. "%3 = OpLoad %v4float %n\n" +
  4904. "%2 = OpFMul %v4float %3 %106\n" +
  4905. "OpReturn\n" +
  4906. "OpFunctionEnd",
  4907. 2, VEC4_0_ID),
  4908. // Test case 2: Fold a * vec4(1.0, 1.0, 1.0, 1.0)
  4909. InstructionFoldingCase<uint32_t>(
  4910. Header() + "%main = OpFunction %void None %void_func\n" +
  4911. "%main_lab = OpLabel\n" +
  4912. "%n = OpVariable %_ptr_v4float Function\n" +
  4913. "%3 = OpLoad %v4float %n\n" +
  4914. "%2 = OpFMul %v4float %3 %v4float_1_1_1_1\n" +
  4915. "OpReturn\n" +
  4916. "OpFunctionEnd",
  4917. 2, 3)
  4918. ));
  4919. INSTANTIATE_TEST_SUITE_P(DoubleVectorRedundantFoldingTest, GeneralInstructionFoldingTest,
  4920. ::testing::Values(
  4921. // Test case 0: Don't fold a * vec4(0.0, 0.0, 0.0, 1.0)
  4922. InstructionFoldingCase<uint32_t>(
  4923. Header() + "%main = OpFunction %void None %void_func\n" +
  4924. "%main_lab = OpLabel\n" +
  4925. "%n = OpVariable %_ptr_v4double Function\n" +
  4926. "%3 = OpLoad %v4double %n\n" +
  4927. "%2 = OpFMul %v4double %3 %v4double_0_0_0_1\n" +
  4928. "OpReturn\n" +
  4929. "OpFunctionEnd",
  4930. 2, 0),
  4931. // Test case 1: Fold a * vec4(0.0, 0.0, 0.0, 0.0)
  4932. InstructionFoldingCase<uint32_t>(
  4933. Header() + "%main = OpFunction %void None %void_func\n" +
  4934. "%main_lab = OpLabel\n" +
  4935. "%n = OpVariable %_ptr_v4double Function\n" +
  4936. "%3 = OpLoad %v4double %n\n" +
  4937. "%2 = OpFMul %v4double %3 %106\n" +
  4938. "OpReturn\n" +
  4939. "OpFunctionEnd",
  4940. 2, DVEC4_0_ID),
  4941. // Test case 2: Fold a + vec4(0.0, 0.0, 0.0, 0.0)
  4942. InstructionFoldingCase<uint32_t>(
  4943. Header() + "%main = OpFunction %void None %void_func\n" +
  4944. "%main_lab = OpLabel\n" +
  4945. "%n = OpVariable %_ptr_v4double Function\n" +
  4946. "%3 = OpLoad %v4double %n\n" +
  4947. "%2 = OpFAdd %v4double %3 %106\n" +
  4948. "OpReturn\n" +
  4949. "OpFunctionEnd",
  4950. 2, 3),
  4951. // Test case 3: Fold a - vec4(0.0, 0.0, 0.0, 0.0)
  4952. InstructionFoldingCase<uint32_t>(
  4953. Header() + "%main = OpFunction %void None %void_func\n" +
  4954. "%main_lab = OpLabel\n" +
  4955. "%n = OpVariable %_ptr_v4double Function\n" +
  4956. "%3 = OpLoad %v4double %n\n" +
  4957. "%2 = OpFSub %v4double %3 %106\n" +
  4958. "OpReturn\n" +
  4959. "OpFunctionEnd",
  4960. 2, 3),
  4961. // Test case 4: Fold a * vec4(1.0, 1.0, 1.0, 1.0)
  4962. InstructionFoldingCase<uint32_t>(
  4963. Header() + "%main = OpFunction %void None %void_func\n" +
  4964. "%main_lab = OpLabel\n" +
  4965. "%n = OpVariable %_ptr_v4double Function\n" +
  4966. "%3 = OpLoad %v4double %n\n" +
  4967. "%2 = OpFMul %v4double %3 %v4double_1_1_1_1\n" +
  4968. "OpReturn\n" +
  4969. "OpFunctionEnd",
  4970. 2, 3)
  4971. ));
  4972. INSTANTIATE_TEST_SUITE_P(IntegerRedundantFoldingTest, GeneralInstructionFoldingTest,
  4973. ::testing::Values(
  4974. // Test case 0: Don't fold n + 1
  4975. InstructionFoldingCase<uint32_t>(
  4976. Header() + "%main = OpFunction %void None %void_func\n" +
  4977. "%main_lab = OpLabel\n" +
  4978. "%n = OpVariable %_ptr_uint Function\n" +
  4979. "%3 = OpLoad %uint %n\n" +
  4980. "%2 = OpIAdd %uint %3 %uint_1\n" +
  4981. "OpReturn\n" +
  4982. "OpFunctionEnd",
  4983. 2, 0),
  4984. // Test case 1: Don't fold 1 + n
  4985. InstructionFoldingCase<uint32_t>(
  4986. Header() + "%main = OpFunction %void None %void_func\n" +
  4987. "%main_lab = OpLabel\n" +
  4988. "%n = OpVariable %_ptr_uint Function\n" +
  4989. "%3 = OpLoad %uint %n\n" +
  4990. "%2 = OpIAdd %uint %uint_1 %3\n" +
  4991. "OpReturn\n" +
  4992. "OpFunctionEnd",
  4993. 2, 0),
  4994. // Test case 2: Fold n | 0
  4995. InstructionFoldingCase<uint32_t>(
  4996. Header() + "%main = OpFunction %void None %void_func\n" +
  4997. "%main_lab = OpLabel\n" +
  4998. "%n = OpVariable %_ptr_uint Function\n" +
  4999. "%3 = OpLoad %uint %n\n" +
  5000. "%2 = OpBitwiseOr %uint %3 %uint_0\n" +
  5001. "OpReturn\n" +
  5002. "OpFunctionEnd",
  5003. 2, 3),
  5004. // Test case 3: Fold n ^ 0
  5005. InstructionFoldingCase<uint32_t>(
  5006. Header() + "%main = OpFunction %void None %void_func\n" +
  5007. "%main_lab = OpLabel\n" +
  5008. "%n = OpVariable %_ptr_uint Function\n" +
  5009. "%3 = OpLoad %uint %n\n" +
  5010. "%2 = OpBitwiseXor %uint %3 %uint_0\n" +
  5011. "OpReturn\n" +
  5012. "OpFunctionEnd",
  5013. 2, 3),
  5014. // Test case 4: Fold n >> 0
  5015. InstructionFoldingCase<uint32_t>(
  5016. Header() + "%main = OpFunction %void None %void_func\n" +
  5017. "%main_lab = OpLabel\n" +
  5018. "%n = OpVariable %_ptr_uint Function\n" +
  5019. "%3 = OpLoad %uint %n\n" +
  5020. "%2 = OpShiftRightLogical %uint %3 %uint_0\n" +
  5021. "OpReturn\n" +
  5022. "OpFunctionEnd",
  5023. 2, 3),
  5024. // Test case 5: Fold n >> 0
  5025. InstructionFoldingCase<uint32_t>(
  5026. Header() + "%main = OpFunction %void None %void_func\n" +
  5027. "%main_lab = OpLabel\n" +
  5028. "%n = OpVariable %_ptr_uint Function\n" +
  5029. "%3 = OpLoad %uint %n\n" +
  5030. "%2 = OpShiftRightArithmetic %uint %3 %uint_0\n" +
  5031. "OpReturn\n" +
  5032. "OpFunctionEnd",
  5033. 2, 3),
  5034. // Test case 6: Fold n << 0
  5035. InstructionFoldingCase<uint32_t>(
  5036. Header() + "%main = OpFunction %void None %void_func\n" +
  5037. "%main_lab = OpLabel\n" +
  5038. "%n = OpVariable %_ptr_uint Function\n" +
  5039. "%3 = OpLoad %uint %n\n" +
  5040. "%2 = OpShiftLeftLogical %uint %3 %uint_0\n" +
  5041. "OpReturn\n" +
  5042. "OpFunctionEnd",
  5043. 2, 3),
  5044. // Test case 7: Fold n + 0
  5045. InstructionFoldingCase<uint32_t>(
  5046. Header() + "%main = OpFunction %void None %void_func\n" +
  5047. "%main_lab = OpLabel\n" +
  5048. "%n = OpVariable %_ptr_uint Function\n" +
  5049. "%3 = OpLoad %uint %n\n" +
  5050. "%2 = OpIAdd %uint %3 %uint_0\n" +
  5051. "OpReturn\n" +
  5052. "OpFunctionEnd",
  5053. 2, 3),
  5054. // Test case 8: Fold n - 0
  5055. InstructionFoldingCase<uint32_t>(
  5056. Header() + "%main = OpFunction %void None %void_func\n" +
  5057. "%main_lab = OpLabel\n" +
  5058. "%n = OpVariable %_ptr_uint Function\n" +
  5059. "%3 = OpLoad %uint %n\n" +
  5060. "%2 = OpISub %uint %3 %uint_0\n" +
  5061. "OpReturn\n" +
  5062. "OpFunctionEnd",
  5063. 2, 3),
  5064. // Test case 9: Fold 0 | n
  5065. InstructionFoldingCase<uint32_t>(
  5066. Header() + "%main = OpFunction %void None %void_func\n" +
  5067. "%main_lab = OpLabel\n" +
  5068. "%n = OpVariable %_ptr_uint Function\n" +
  5069. "%3 = OpLoad %uint %n\n" +
  5070. "%2 = OpBitwiseOr %uint %uint_0 %3\n" +
  5071. "OpReturn\n" +
  5072. "OpFunctionEnd",
  5073. 2, 3),
  5074. // Test case 10: Fold 0 ^ n
  5075. InstructionFoldingCase<uint32_t>(
  5076. Header() + "%main = OpFunction %void None %void_func\n" +
  5077. "%main_lab = OpLabel\n" +
  5078. "%n = OpVariable %_ptr_uint Function\n" +
  5079. "%3 = OpLoad %uint %n\n" +
  5080. "%2 = OpBitwiseXor %uint %uint_0 %3\n" +
  5081. "OpReturn\n" +
  5082. "OpFunctionEnd",
  5083. 2, 3),
  5084. // Test case 11: Fold 0 + n
  5085. InstructionFoldingCase<uint32_t>(
  5086. Header() + "%main = OpFunction %void None %void_func\n" +
  5087. "%main_lab = OpLabel\n" +
  5088. "%n = OpVariable %_ptr_uint Function\n" +
  5089. "%3 = OpLoad %uint %n\n" +
  5090. "%2 = OpIAdd %uint %uint_0 %3\n" +
  5091. "OpReturn\n" +
  5092. "OpFunctionEnd",
  5093. 2, 3),
  5094. // Test case 12: Don't fold n + (1,0)
  5095. InstructionFoldingCase<uint32_t>(
  5096. Header() + "%main = OpFunction %void None %void_func\n" +
  5097. "%main_lab = OpLabel\n" +
  5098. "%n = OpVariable %_ptr_v2int Function\n" +
  5099. "%3 = OpLoad %v2int %n\n" +
  5100. "%2 = OpIAdd %v2int %3 %v2int_1_0\n" +
  5101. "OpReturn\n" +
  5102. "OpFunctionEnd",
  5103. 2, 0),
  5104. // Test case 13: Don't fold (1,0) + n
  5105. InstructionFoldingCase<uint32_t>(
  5106. Header() + "%main = OpFunction %void None %void_func\n" +
  5107. "%main_lab = OpLabel\n" +
  5108. "%n = OpVariable %_ptr_v2int Function\n" +
  5109. "%3 = OpLoad %v2int %n\n" +
  5110. "%2 = OpIAdd %v2int %v2int_1_0 %3\n" +
  5111. "OpReturn\n" +
  5112. "OpFunctionEnd",
  5113. 2, 0),
  5114. // Test case 14: Fold n + (0,0)
  5115. InstructionFoldingCase<uint32_t>(
  5116. Header() + "%main = OpFunction %void None %void_func\n" +
  5117. "%main_lab = OpLabel\n" +
  5118. "%n = OpVariable %_ptr_v2int Function\n" +
  5119. "%3 = OpLoad %v2int %n\n" +
  5120. "%2 = OpIAdd %v2int %3 %v2int_0_0\n" +
  5121. "OpReturn\n" +
  5122. "OpFunctionEnd",
  5123. 2, 3),
  5124. // Test case 15: Fold (0,0) + n
  5125. InstructionFoldingCase<uint32_t>(
  5126. Header() + "%main = OpFunction %void None %void_func\n" +
  5127. "%main_lab = OpLabel\n" +
  5128. "%n = OpVariable %_ptr_v2int Function\n" +
  5129. "%3 = OpLoad %v2int %n\n" +
  5130. "%2 = OpIAdd %v2int %v2int_0_0 %3\n" +
  5131. "OpReturn\n" +
  5132. "OpFunctionEnd",
  5133. 2, 3),
  5134. // Test case 16: Fold n | (0,0)
  5135. InstructionFoldingCase<uint32_t>(
  5136. Header() + "%main = OpFunction %void None %void_func\n" +
  5137. "%main_lab = OpLabel\n" +
  5138. "%n = OpVariable %_ptr_v2int Function\n" +
  5139. "%3 = OpLoad %v2int %n\n" +
  5140. "%2 = OpBitwiseOr %v2int %3 %v2int_0_0\n" +
  5141. "OpReturn\n" +
  5142. "OpFunctionEnd",
  5143. 2, 3),
  5144. // Test case 17: Fold (0,0) | n
  5145. InstructionFoldingCase<uint32_t>(
  5146. Header() + "%main = OpFunction %void None %void_func\n" +
  5147. "%main_lab = OpLabel\n" +
  5148. "%n = OpVariable %_ptr_v2int Function\n" +
  5149. "%3 = OpLoad %v2int %n\n" +
  5150. "%2 = OpBitwiseOr %v2int %v2int_0_0 %3\n" +
  5151. "OpReturn\n" +
  5152. "OpFunctionEnd",
  5153. 2, 3),
  5154. // Test case 18: Fold 0 >> n
  5155. InstructionFoldingCase<uint32_t>(
  5156. Header() + "%main = OpFunction %void None %void_func\n" +
  5157. "%main_lab = OpLabel\n" +
  5158. "%n = OpVariable %_ptr_uint Function\n" +
  5159. "%3 = OpLoad %uint %n\n" +
  5160. "%2 = OpShiftRightLogical %uint %109 %3\n" +
  5161. "OpReturn\n" +
  5162. "OpFunctionEnd",
  5163. 2, UINT_0_ID),
  5164. // Test case 19: Fold 0 >> n
  5165. InstructionFoldingCase<uint32_t>(
  5166. Header() + "%main = OpFunction %void None %void_func\n" +
  5167. "%main_lab = OpLabel\n" +
  5168. "%n = OpVariable %_ptr_uint Function\n" +
  5169. "%3 = OpLoad %uint %n\n" +
  5170. "%2 = OpShiftRightArithmetic %uint %109 %3\n" +
  5171. "OpReturn\n" +
  5172. "OpFunctionEnd",
  5173. 2, UINT_0_ID),
  5174. // Test case 20: Fold 0 << n
  5175. InstructionFoldingCase<uint32_t>(
  5176. Header() + "%main = OpFunction %void None %void_func\n" +
  5177. "%main_lab = OpLabel\n" +
  5178. "%n = OpVariable %_ptr_uint Function\n" +
  5179. "%3 = OpLoad %uint %n\n" +
  5180. "%2 = OpShiftLeftLogical %uint %109 %3\n" +
  5181. "OpReturn\n" +
  5182. "OpFunctionEnd",
  5183. 2, UINT_0_ID),
  5184. // Test case 21: Fold 0 / n
  5185. InstructionFoldingCase<uint32_t>(
  5186. Header() + "%main = OpFunction %void None %void_func\n" +
  5187. "%main_lab = OpLabel\n" +
  5188. "%n = OpVariable %_ptr_uint Function\n" +
  5189. "%3 = OpLoad %int %n\n" +
  5190. "%2 = OpSDiv %int %100 %3\n" +
  5191. "OpReturn\n" +
  5192. "OpFunctionEnd",
  5193. 2, INT_0_ID),
  5194. // Test case 22: Fold 0 / n
  5195. InstructionFoldingCase<uint32_t>(
  5196. Header() + "%main = OpFunction %void None %void_func\n" +
  5197. "%main_lab = OpLabel\n" +
  5198. "%n = OpVariable %_ptr_uint Function\n" +
  5199. "%3 = OpLoad %uint %n\n" +
  5200. "%2 = OpUDiv %uint %109 %3\n" +
  5201. "OpReturn\n" +
  5202. "OpFunctionEnd",
  5203. 2, UINT_0_ID),
  5204. // Test case 23: Fold 0 % n
  5205. InstructionFoldingCase<uint32_t>(
  5206. Header() + "%main = OpFunction %void None %void_func\n" +
  5207. "%main_lab = OpLabel\n" +
  5208. "%n = OpVariable %_ptr_uint Function\n" +
  5209. "%3 = OpLoad %uint %n\n" +
  5210. "%2 = OpSMod %int %int_0 %3\n" +
  5211. "OpReturn\n" +
  5212. "OpFunctionEnd",
  5213. 2, INT_0_ID),
  5214. // Test case 24: Fold 0 % n
  5215. InstructionFoldingCase<uint32_t>(
  5216. Header() + "%main = OpFunction %void None %void_func\n" +
  5217. "%main_lab = OpLabel\n" +
  5218. "%n = OpVariable %_ptr_uint Function\n" +
  5219. "%3 = OpLoad %uint %n\n" +
  5220. "%2 = OpUMod %uint %109 %3\n" +
  5221. "OpReturn\n" +
  5222. "OpFunctionEnd",
  5223. 2, UINT_0_ID),
  5224. // Test case 25: Fold n % 1
  5225. InstructionFoldingCase<uint32_t>(
  5226. Header() + "%main = OpFunction %void None %void_func\n" +
  5227. "%main_lab = OpLabel\n" +
  5228. "%n = OpVariable %_ptr_uint Function\n" +
  5229. "%3 = OpLoad %int %n\n" +
  5230. "%2 = OpSMod %int %3 %int_1\n" +
  5231. "OpReturn\n" +
  5232. "OpFunctionEnd",
  5233. 2, INT_NULL_ID),
  5234. // Test case 26: Fold n % 1
  5235. InstructionFoldingCase<uint32_t>(
  5236. Header() + "%main = OpFunction %void None %void_func\n" +
  5237. "%main_lab = OpLabel\n" +
  5238. "%n = OpVariable %_ptr_uint Function\n" +
  5239. "%3 = OpLoad %uint %n\n" +
  5240. "%2 = OpUMod %uint %3 %uint_1\n" +
  5241. "OpReturn\n" +
  5242. "OpFunctionEnd",
  5243. 2, UINT_NULL_ID),
  5244. // Test case 27: Don't fold because of undefined value. Using 4294967295
  5245. // means that entry is undefined. We do not expect it to ever happen, so
  5246. // not worth folding.
  5247. InstructionFoldingCase<uint32_t>(
  5248. Header() + "%main = OpFunction %void None %void_func\n" +
  5249. "%main_lab = OpLabel\n" +
  5250. "%n = OpVariable %_ptr_int Function\n" +
  5251. "%load = OpLoad %int %n\n" +
  5252. "%2 = OpVectorShuffle %v2int %v2int_null %v2int_2_3 4294967295 3\n" +
  5253. "OpReturn\n" +
  5254. "OpFunctionEnd",
  5255. 2, 0),
  5256. // Test case 28: Don't fold because of undefined value. Using 4294967295
  5257. // means that entry is undefined. We do not expect it to ever happen, so
  5258. // not worth folding.
  5259. InstructionFoldingCase<uint32_t>(
  5260. Header() + "%main = OpFunction %void None %void_func\n" +
  5261. "%main_lab = OpLabel\n" +
  5262. "%n = OpVariable %_ptr_int Function\n" +
  5263. "%load = OpLoad %int %n\n" +
  5264. "%2 = OpVectorShuffle %v2int %v2int_null %v2int_2_3 0 4294967295 \n" +
  5265. "OpReturn\n" +
  5266. "OpFunctionEnd",
  5267. 2, 0)
  5268. ));
  5269. INSTANTIATE_TEST_SUITE_P(ClampAndCmpLHS, GeneralInstructionFoldingTest,
  5270. ::testing::Values(
  5271. // Test case 0: Don't Fold 0.0 < clamp(-1, 1)
  5272. InstructionFoldingCase<uint32_t>(
  5273. Header() + "%main = OpFunction %void None %void_func\n" +
  5274. "%main_lab = OpLabel\n" +
  5275. "%n = OpVariable %_ptr_float Function\n" +
  5276. "%ld = OpLoad %float %n\n" +
  5277. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
  5278. "%2 = OpFUnordLessThan %bool %float_0 %clamp\n" +
  5279. "OpReturn\n" +
  5280. "OpFunctionEnd",
  5281. 2, 0),
  5282. // Test case 1: Don't Fold 0.0 < clamp(-1, 1)
  5283. InstructionFoldingCase<uint32_t>(
  5284. Header() + "%main = OpFunction %void None %void_func\n" +
  5285. "%main_lab = OpLabel\n" +
  5286. "%n = OpVariable %_ptr_float Function\n" +
  5287. "%ld = OpLoad %float %n\n" +
  5288. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
  5289. "%2 = OpFOrdLessThan %bool %float_0 %clamp\n" +
  5290. "OpReturn\n" +
  5291. "OpFunctionEnd",
  5292. 2, 0),
  5293. // Test case 2: Don't Fold 0.0 <= clamp(-1, 1)
  5294. InstructionFoldingCase<uint32_t>(
  5295. Header() + "%main = OpFunction %void None %void_func\n" +
  5296. "%main_lab = OpLabel\n" +
  5297. "%n = OpVariable %_ptr_float Function\n" +
  5298. "%ld = OpLoad %float %n\n" +
  5299. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
  5300. "%2 = OpFUnordLessThanEqual %bool %float_0 %clamp\n" +
  5301. "OpReturn\n" +
  5302. "OpFunctionEnd",
  5303. 2, 0),
  5304. // Test case 3: Don't Fold 0.0 <= clamp(-1, 1)
  5305. InstructionFoldingCase<uint32_t>(
  5306. Header() + "%main = OpFunction %void None %void_func\n" +
  5307. "%main_lab = OpLabel\n" +
  5308. "%n = OpVariable %_ptr_float Function\n" +
  5309. "%ld = OpLoad %float %n\n" +
  5310. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
  5311. "%2 = OpFOrdLessThanEqual %bool %float_0 %clamp\n" +
  5312. "OpReturn\n" +
  5313. "OpFunctionEnd",
  5314. 2, 0),
  5315. // Test case 4: Don't Fold 0.0 > clamp(-1, 1)
  5316. InstructionFoldingCase<uint32_t>(
  5317. Header() + "%main = OpFunction %void None %void_func\n" +
  5318. "%main_lab = OpLabel\n" +
  5319. "%n = OpVariable %_ptr_float Function\n" +
  5320. "%ld = OpLoad %float %n\n" +
  5321. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
  5322. "%2 = OpFUnordGreaterThan %bool %float_0 %clamp\n" +
  5323. "OpReturn\n" +
  5324. "OpFunctionEnd",
  5325. 2, 0),
  5326. // Test case 5: Don't Fold 0.0 > clamp(-1, 1)
  5327. InstructionFoldingCase<uint32_t>(
  5328. Header() + "%main = OpFunction %void None %void_func\n" +
  5329. "%main_lab = OpLabel\n" +
  5330. "%n = OpVariable %_ptr_float Function\n" +
  5331. "%ld = OpLoad %float %n\n" +
  5332. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
  5333. "%2 = OpFOrdGreaterThan %bool %float_0 %clamp\n" +
  5334. "OpReturn\n" +
  5335. "OpFunctionEnd",
  5336. 2, 0),
  5337. // Test case 6: Don't Fold 0.0 >= clamp(-1, 1)
  5338. InstructionFoldingCase<uint32_t>(
  5339. Header() + "%main = OpFunction %void None %void_func\n" +
  5340. "%main_lab = OpLabel\n" +
  5341. "%n = OpVariable %_ptr_float Function\n" +
  5342. "%ld = OpLoad %float %n\n" +
  5343. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
  5344. "%2 = OpFUnordGreaterThanEqual %bool %float_0 %clamp\n" +
  5345. "OpReturn\n" +
  5346. "OpFunctionEnd",
  5347. 2, 0),
  5348. // Test case 7: Don't Fold 0.0 >= clamp(-1, 1)
  5349. InstructionFoldingCase<uint32_t>(
  5350. Header() + "%main = OpFunction %void None %void_func\n" +
  5351. "%main_lab = OpLabel\n" +
  5352. "%n = OpVariable %_ptr_float Function\n" +
  5353. "%ld = OpLoad %float %n\n" +
  5354. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
  5355. "%2 = OpFOrdGreaterThanEqual %bool %float_0 %clamp\n" +
  5356. "OpReturn\n" +
  5357. "OpFunctionEnd",
  5358. 2, 0),
  5359. // Test case 8: Don't Fold 0.0 < clamp(0, 1)
  5360. InstructionFoldingCase<uint32_t>(
  5361. Header() + "%main = OpFunction %void None %void_func\n" +
  5362. "%main_lab = OpLabel\n" +
  5363. "%n = OpVariable %_ptr_float Function\n" +
  5364. "%ld = OpLoad %float %n\n" +
  5365. "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
  5366. "%2 = OpFUnordLessThan %bool %float_0 %clamp\n" +
  5367. "OpReturn\n" +
  5368. "OpFunctionEnd",
  5369. 2, 0),
  5370. // Test case 9: Don't Fold 0.0 < clamp(0, 1)
  5371. InstructionFoldingCase<uint32_t>(
  5372. Header() + "%main = OpFunction %void None %void_func\n" +
  5373. "%main_lab = OpLabel\n" +
  5374. "%n = OpVariable %_ptr_float Function\n" +
  5375. "%ld = OpLoad %float %n\n" +
  5376. "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
  5377. "%2 = OpFOrdLessThan %bool %float_0 %clamp\n" +
  5378. "OpReturn\n" +
  5379. "OpFunctionEnd",
  5380. 2, 0),
  5381. // Test case 10: Don't Fold 0.0 > clamp(-1, 0)
  5382. InstructionFoldingCase<uint32_t>(
  5383. Header() + "%main = OpFunction %void None %void_func\n" +
  5384. "%main_lab = OpLabel\n" +
  5385. "%n = OpVariable %_ptr_float Function\n" +
  5386. "%ld = OpLoad %float %n\n" +
  5387. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
  5388. "%2 = OpFUnordGreaterThan %bool %float_0 %clamp\n" +
  5389. "OpReturn\n" +
  5390. "OpFunctionEnd",
  5391. 2, 0),
  5392. // Test case 11: Don't Fold 0.0 > clamp(-1, 0)
  5393. InstructionFoldingCase<uint32_t>(
  5394. Header() + "%main = OpFunction %void None %void_func\n" +
  5395. "%main_lab = OpLabel\n" +
  5396. "%n = OpVariable %_ptr_float Function\n" +
  5397. "%ld = OpLoad %float %n\n" +
  5398. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
  5399. "%2 = OpFOrdGreaterThan %bool %float_0 %clamp\n" +
  5400. "OpReturn\n" +
  5401. "OpFunctionEnd",
  5402. 2, 0)
  5403. ));
  5404. INSTANTIATE_TEST_SUITE_P(ClampAndCmpRHS, GeneralInstructionFoldingTest,
  5405. ::testing::Values(
  5406. // Test case 0: Don't Fold clamp(-1, 1) < 0.0
  5407. InstructionFoldingCase<uint32_t>(
  5408. Header() + "%main = OpFunction %void None %void_func\n" +
  5409. "%main_lab = OpLabel\n" +
  5410. "%n = OpVariable %_ptr_float Function\n" +
  5411. "%ld = OpLoad %float %n\n" +
  5412. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
  5413. "%2 = OpFUnordLessThan %bool %clamp %float_0\n" +
  5414. "OpReturn\n" +
  5415. "OpFunctionEnd",
  5416. 2, 0),
  5417. // Test case 1: Don't Fold clamp(-1, 1) < 0.0
  5418. InstructionFoldingCase<uint32_t>(
  5419. Header() + "%main = OpFunction %void None %void_func\n" +
  5420. "%main_lab = OpLabel\n" +
  5421. "%n = OpVariable %_ptr_float Function\n" +
  5422. "%ld = OpLoad %float %n\n" +
  5423. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
  5424. "%2 = OpFOrdLessThan %bool %clamp %float_0\n" +
  5425. "OpReturn\n" +
  5426. "OpFunctionEnd",
  5427. 2, 0),
  5428. // Test case 2: Don't Fold clamp(-1, 1) <= 0.0
  5429. InstructionFoldingCase<uint32_t>(
  5430. Header() + "%main = OpFunction %void None %void_func\n" +
  5431. "%main_lab = OpLabel\n" +
  5432. "%n = OpVariable %_ptr_float Function\n" +
  5433. "%ld = OpLoad %float %n\n" +
  5434. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
  5435. "%2 = OpFUnordLessThanEqual %bool %clamp %float_0\n" +
  5436. "OpReturn\n" +
  5437. "OpFunctionEnd",
  5438. 2, 0),
  5439. // Test case 3: Don't Fold clamp(-1, 1) <= 0.0
  5440. InstructionFoldingCase<uint32_t>(
  5441. Header() + "%main = OpFunction %void None %void_func\n" +
  5442. "%main_lab = OpLabel\n" +
  5443. "%n = OpVariable %_ptr_float Function\n" +
  5444. "%ld = OpLoad %float %n\n" +
  5445. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
  5446. "%2 = OpFOrdLessThanEqual %bool %clamp %float_0\n" +
  5447. "OpReturn\n" +
  5448. "OpFunctionEnd",
  5449. 2, 0),
  5450. // Test case 4: Don't Fold clamp(-1, 1) > 0.0
  5451. InstructionFoldingCase<uint32_t>(
  5452. Header() + "%main = OpFunction %void None %void_func\n" +
  5453. "%main_lab = OpLabel\n" +
  5454. "%n = OpVariable %_ptr_float Function\n" +
  5455. "%ld = OpLoad %float %n\n" +
  5456. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
  5457. "%2 = OpFUnordGreaterThan %bool %clamp %float_0\n" +
  5458. "OpReturn\n" +
  5459. "OpFunctionEnd",
  5460. 2, 0),
  5461. // Test case 5: Don't Fold clamp(-1, 1) > 0.0
  5462. InstructionFoldingCase<uint32_t>(
  5463. Header() + "%main = OpFunction %void None %void_func\n" +
  5464. "%main_lab = OpLabel\n" +
  5465. "%n = OpVariable %_ptr_float Function\n" +
  5466. "%ld = OpLoad %float %n\n" +
  5467. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
  5468. "%2 = OpFOrdGreaterThan %bool %clamp %float_0\n" +
  5469. "OpReturn\n" +
  5470. "OpFunctionEnd",
  5471. 2, 0),
  5472. // Test case 6: Don't Fold clamp(-1, 1) >= 0.0
  5473. InstructionFoldingCase<uint32_t>(
  5474. Header() + "%main = OpFunction %void None %void_func\n" +
  5475. "%main_lab = OpLabel\n" +
  5476. "%n = OpVariable %_ptr_float Function\n" +
  5477. "%ld = OpLoad %float %n\n" +
  5478. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
  5479. "%2 = OpFUnordGreaterThanEqual %bool %clamp %float_0\n" +
  5480. "OpReturn\n" +
  5481. "OpFunctionEnd",
  5482. 2, 0),
  5483. // Test case 7: Don't Fold clamp(-1, 1) >= 0.0
  5484. InstructionFoldingCase<uint32_t>(
  5485. Header() + "%main = OpFunction %void None %void_func\n" +
  5486. "%main_lab = OpLabel\n" +
  5487. "%n = OpVariable %_ptr_float Function\n" +
  5488. "%ld = OpLoad %float %n\n" +
  5489. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
  5490. "%2 = OpFOrdGreaterThanEqual %bool %clamp %float_0\n" +
  5491. "OpReturn\n" +
  5492. "OpFunctionEnd",
  5493. 2, 0),
  5494. // Test case 8: Don't Fold clamp(-1, 0) < 0.0
  5495. InstructionFoldingCase<uint32_t>(
  5496. Header() + "%main = OpFunction %void None %void_func\n" +
  5497. "%main_lab = OpLabel\n" +
  5498. "%n = OpVariable %_ptr_float Function\n" +
  5499. "%ld = OpLoad %float %n\n" +
  5500. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
  5501. "%2 = OpFUnordLessThan %bool %clamp %float_0\n" +
  5502. "OpReturn\n" +
  5503. "OpFunctionEnd",
  5504. 2, 0),
  5505. // Test case 9: Don't Fold clamp(0, 1) < 1
  5506. InstructionFoldingCase<uint32_t>(
  5507. Header() + "%main = OpFunction %void None %void_func\n" +
  5508. "%main_lab = OpLabel\n" +
  5509. "%n = OpVariable %_ptr_float Function\n" +
  5510. "%ld = OpLoad %float %n\n" +
  5511. "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
  5512. "%2 = OpFOrdLessThan %bool %clamp %float_1\n" +
  5513. "OpReturn\n" +
  5514. "OpFunctionEnd",
  5515. 2, 0),
  5516. // Test case 10: Don't Fold clamp(-1, 0) > -1
  5517. InstructionFoldingCase<uint32_t>(
  5518. Header() + "%main = OpFunction %void None %void_func\n" +
  5519. "%main_lab = OpLabel\n" +
  5520. "%n = OpVariable %_ptr_float Function\n" +
  5521. "%ld = OpLoad %float %n\n" +
  5522. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
  5523. "%2 = OpFUnordGreaterThan %bool %clamp %float_n1\n" +
  5524. "OpReturn\n" +
  5525. "OpFunctionEnd",
  5526. 2, 0),
  5527. // Test case 11: Don't Fold clamp(-1, 0) > -1
  5528. InstructionFoldingCase<uint32_t>(
  5529. Header() + "%main = OpFunction %void None %void_func\n" +
  5530. "%main_lab = OpLabel\n" +
  5531. "%n = OpVariable %_ptr_float Function\n" +
  5532. "%ld = OpLoad %float %n\n" +
  5533. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
  5534. "%2 = OpFOrdGreaterThan %bool %clamp %float_n1\n" +
  5535. "OpReturn\n" +
  5536. "OpFunctionEnd",
  5537. 2, 0)
  5538. ));
  5539. INSTANTIATE_TEST_SUITE_P(FToIConstantFoldingTest, IntegerInstructionFoldingTest,
  5540. ::testing::Values(
  5541. // Test case 0: Fold int(3.0)
  5542. InstructionFoldingCase<uint32_t>(
  5543. Header() + "%main = OpFunction %void None %void_func\n" +
  5544. "%main_lab = OpLabel\n" +
  5545. "%2 = OpConvertFToS %int %float_3\n" +
  5546. "OpReturn\n" +
  5547. "OpFunctionEnd",
  5548. 2, 3),
  5549. // Test case 1: Fold uint(3.0)
  5550. InstructionFoldingCase<uint32_t>(
  5551. Header() + "%main = OpFunction %void None %void_func\n" +
  5552. "%main_lab = OpLabel\n" +
  5553. "%2 = OpConvertFToU %int %float_3\n" +
  5554. "OpReturn\n" +
  5555. "OpFunctionEnd",
  5556. 2, 3)
  5557. ));
  5558. INSTANTIATE_TEST_SUITE_P(IToFConstantFoldingTest, FloatInstructionFoldingTest,
  5559. ::testing::Values(
  5560. // Test case 0: Fold float(3)
  5561. InstructionFoldingCase<float>(
  5562. Header() + "%main = OpFunction %void None %void_func\n" +
  5563. "%main_lab = OpLabel\n" +
  5564. "%2 = OpConvertSToF %float %int_3\n" +
  5565. "OpReturn\n" +
  5566. "OpFunctionEnd",
  5567. 2, 3.0),
  5568. // Test case 1: Fold float(3u)
  5569. InstructionFoldingCase<float>(
  5570. Header() + "%main = OpFunction %void None %void_func\n" +
  5571. "%main_lab = OpLabel\n" +
  5572. "%2 = OpConvertUToF %float %uint_3\n" +
  5573. "OpReturn\n" +
  5574. "OpFunctionEnd",
  5575. 2, 3.0)
  5576. ));
  5577. // clang-format on
  5578. using ToNegateFoldingTest =
  5579. ::testing::TestWithParam<InstructionFoldingCase<uint32_t>>;
  5580. TEST_P(ToNegateFoldingTest, Case) {
  5581. const auto& tc = GetParam();
  5582. std::unique_ptr<IRContext> context;
  5583. Instruction* inst;
  5584. std::tie(context, inst) =
  5585. FoldInstruction(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_1);
  5586. EXPECT_TRUE((inst == nullptr) == (tc.expected_result == 0));
  5587. if (inst != nullptr) {
  5588. EXPECT_EQ(inst->opcode(), spv::Op::OpFNegate);
  5589. EXPECT_EQ(inst->GetSingleWordInOperand(0), tc.expected_result);
  5590. }
  5591. }
  5592. // clang-format off
  5593. INSTANTIATE_TEST_SUITE_P(FloatRedundantSubFoldingTest, ToNegateFoldingTest,
  5594. ::testing::Values(
  5595. // Test case 0: Don't fold 1.0 - n
  5596. InstructionFoldingCase<uint32_t>(
  5597. Header() + "%main = OpFunction %void None %void_func\n" +
  5598. "%main_lab = OpLabel\n" +
  5599. "%n = OpVariable %_ptr_float Function\n" +
  5600. "%3 = OpLoad %float %n\n" +
  5601. "%2 = OpFSub %float %float_1 %3\n" +
  5602. "OpReturn\n" +
  5603. "OpFunctionEnd",
  5604. 2, 0),
  5605. // Test case 1: Fold 0.0 - n
  5606. InstructionFoldingCase<uint32_t>(
  5607. Header() + "%main = OpFunction %void None %void_func\n" +
  5608. "%main_lab = OpLabel\n" +
  5609. "%n = OpVariable %_ptr_float Function\n" +
  5610. "%3 = OpLoad %float %n\n" +
  5611. "%2 = OpFSub %float %float_0 %3\n" +
  5612. "OpReturn\n" +
  5613. "OpFunctionEnd",
  5614. 2, 3),
  5615. // Test case 2: Don't fold (0,0,0,1) - n
  5616. InstructionFoldingCase<uint32_t>(
  5617. Header() + "%main = OpFunction %void None %void_func\n" +
  5618. "%main_lab = OpLabel\n" +
  5619. "%n = OpVariable %_ptr_v4float Function\n" +
  5620. "%3 = OpLoad %v4float %n\n" +
  5621. "%2 = OpFSub %v4float %v4float_0_0_0_1 %3\n" +
  5622. "OpReturn\n" +
  5623. "OpFunctionEnd",
  5624. 2, 0),
  5625. // Test case 3: Fold (0,0,0,0) - n
  5626. InstructionFoldingCase<uint32_t>(
  5627. Header() + "%main = OpFunction %void None %void_func\n" +
  5628. "%main_lab = OpLabel\n" +
  5629. "%n = OpVariable %_ptr_v4float Function\n" +
  5630. "%3 = OpLoad %v4float %n\n" +
  5631. "%2 = OpFSub %v4float %v4float_0_0_0_0 %3\n" +
  5632. "OpReturn\n" +
  5633. "OpFunctionEnd",
  5634. 2, 3)
  5635. ));
  5636. INSTANTIATE_TEST_SUITE_P(DoubleRedundantSubFoldingTest, ToNegateFoldingTest,
  5637. ::testing::Values(
  5638. // Test case 0: Don't fold 1.0 - n
  5639. InstructionFoldingCase<uint32_t>(
  5640. Header() + "%main = OpFunction %void None %void_func\n" +
  5641. "%main_lab = OpLabel\n" +
  5642. "%n = OpVariable %_ptr_double Function\n" +
  5643. "%3 = OpLoad %double %n\n" +
  5644. "%2 = OpFSub %double %double_1 %3\n" +
  5645. "OpReturn\n" +
  5646. "OpFunctionEnd",
  5647. 2, 0),
  5648. // Test case 1: Fold 0.0 - n
  5649. InstructionFoldingCase<uint32_t>(
  5650. Header() + "%main = OpFunction %void None %void_func\n" +
  5651. "%main_lab = OpLabel\n" +
  5652. "%n = OpVariable %_ptr_double Function\n" +
  5653. "%3 = OpLoad %double %n\n" +
  5654. "%2 = OpFSub %double %double_0 %3\n" +
  5655. "OpReturn\n" +
  5656. "OpFunctionEnd",
  5657. 2, 3),
  5658. // Test case 2: Don't fold (0,0,0,1) - n
  5659. InstructionFoldingCase<uint32_t>(
  5660. Header() + "%main = OpFunction %void None %void_func\n" +
  5661. "%main_lab = OpLabel\n" +
  5662. "%n = OpVariable %_ptr_v4double Function\n" +
  5663. "%3 = OpLoad %v4double %n\n" +
  5664. "%2 = OpFSub %v4double %v4double_0_0_0_1 %3\n" +
  5665. "OpReturn\n" +
  5666. "OpFunctionEnd",
  5667. 2, 0),
  5668. // Test case 3: Fold (0,0,0,0) - n
  5669. InstructionFoldingCase<uint32_t>(
  5670. Header() + "%main = OpFunction %void None %void_func\n" +
  5671. "%main_lab = OpLabel\n" +
  5672. "%n = OpVariable %_ptr_v4double Function\n" +
  5673. "%3 = OpLoad %v4double %n\n" +
  5674. "%2 = OpFSub %v4double %v4double_0_0_0_0 %3\n" +
  5675. "OpReturn\n" +
  5676. "OpFunctionEnd",
  5677. 2, 3)
  5678. ));
  5679. using MatchingInstructionFoldingTest =
  5680. ::testing::TestWithParam<InstructionFoldingCase<bool>>;
  5681. TEST_P(MatchingInstructionFoldingTest, Case) {
  5682. const auto& tc = GetParam();
  5683. std::unique_ptr<IRContext> context;
  5684. Instruction* inst;
  5685. std::tie(context, inst) = FoldInstruction(tc.test_body, tc.id_to_fold,SPV_ENV_UNIVERSAL_1_1);
  5686. EXPECT_EQ(inst != nullptr, tc.expected_result);
  5687. if (inst != nullptr) {
  5688. Match(tc.test_body, context.get());
  5689. }
  5690. }
  5691. INSTANTIATE_TEST_SUITE_P(RedundantIntegerMatching, MatchingInstructionFoldingTest,
  5692. ::testing::Values(
  5693. // Test case 0: Fold 0 + n (change sign)
  5694. InstructionFoldingCase<bool>(
  5695. Header() +
  5696. "; CHECK: [[uint:%\\w+]] = OpTypeInt 32 0\n" +
  5697. "; CHECK: %2 = OpBitcast [[uint]] %3\n" +
  5698. "%main = OpFunction %void None %void_func\n" +
  5699. "%main_lab = OpLabel\n" +
  5700. "%n = OpVariable %_ptr_int Function\n" +
  5701. "%3 = OpLoad %uint %n\n" +
  5702. "%2 = OpIAdd %uint %int_0 %3\n" +
  5703. "OpReturn\n" +
  5704. "OpFunctionEnd\n",
  5705. 2, true),
  5706. // Test case 0: Fold 0 + n (change sign)
  5707. InstructionFoldingCase<bool>(
  5708. Header() +
  5709. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  5710. "; CHECK: %2 = OpBitcast [[int]] %3\n" +
  5711. "%main = OpFunction %void None %void_func\n" +
  5712. "%main_lab = OpLabel\n" +
  5713. "%n = OpVariable %_ptr_int Function\n" +
  5714. "%3 = OpLoad %int %n\n" +
  5715. "%2 = OpIAdd %int %uint_0 %3\n" +
  5716. "OpReturn\n" +
  5717. "OpFunctionEnd\n",
  5718. 2, true)
  5719. ));
  5720. INSTANTIATE_TEST_SUITE_P(MergeNegateTest, MatchingInstructionFoldingTest,
  5721. ::testing::Values(
  5722. // Test case 0: fold consecutive fnegate
  5723. // -(-x) = x
  5724. InstructionFoldingCase<bool>(
  5725. Header() +
  5726. "; CHECK: [[ld:%\\w+]] = OpLoad [[float:%\\w+]]\n" +
  5727. "; CHECK: %4 = OpCopyObject [[float]] [[ld]]\n" +
  5728. "%main = OpFunction %void None %void_func\n" +
  5729. "%main_lab = OpLabel\n" +
  5730. "%var = OpVariable %_ptr_float Function\n" +
  5731. "%2 = OpLoad %float %var\n" +
  5732. "%3 = OpFNegate %float %2\n" +
  5733. "%4 = OpFNegate %float %3\n" +
  5734. "OpReturn\n" +
  5735. "OpFunctionEnd",
  5736. 4, true),
  5737. // Test case 1: fold fnegate(fmul with const).
  5738. // -(x * 2.0) = x * -2.0
  5739. InstructionFoldingCase<bool>(
  5740. Header() +
  5741. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5742. "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2{{[[:space:]]}}\n" +
  5743. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  5744. "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_n2]]\n" +
  5745. "%main = OpFunction %void None %void_func\n" +
  5746. "%main_lab = OpLabel\n" +
  5747. "%var = OpVariable %_ptr_float Function\n" +
  5748. "%2 = OpLoad %float %var\n" +
  5749. "%3 = OpFMul %float %2 %float_2\n" +
  5750. "%4 = OpFNegate %float %3\n" +
  5751. "OpReturn\n" +
  5752. "OpFunctionEnd",
  5753. 4, true),
  5754. // Test case 2: fold fnegate(fmul with const).
  5755. // -(2.0 * x) = x * 2.0
  5756. InstructionFoldingCase<bool>(
  5757. Header() +
  5758. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5759. "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2{{[[:space:]]}}\n" +
  5760. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  5761. "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_n2]]\n" +
  5762. "%main = OpFunction %void None %void_func\n" +
  5763. "%main_lab = OpLabel\n" +
  5764. "%var = OpVariable %_ptr_float Function\n" +
  5765. "%2 = OpLoad %float %var\n" +
  5766. "%3 = OpFMul %float %float_2 %2\n" +
  5767. "%4 = OpFNegate %float %3\n" +
  5768. "OpReturn\n" +
  5769. "OpFunctionEnd",
  5770. 4, true),
  5771. // Test case 3: fold fnegate(fdiv with const).
  5772. // -(x / 2.0) = x * -0.5
  5773. InstructionFoldingCase<bool>(
  5774. Header() +
  5775. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5776. "; CHECK: [[float_n0p5:%\\w+]] = OpConstant [[float]] -0.5\n" +
  5777. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  5778. "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_n0p5]]\n" +
  5779. "%main = OpFunction %void None %void_func\n" +
  5780. "%main_lab = OpLabel\n" +
  5781. "%var = OpVariable %_ptr_float Function\n" +
  5782. "%2 = OpLoad %float %var\n" +
  5783. "%3 = OpFDiv %float %2 %float_2\n" +
  5784. "%4 = OpFNegate %float %3\n" +
  5785. "OpReturn\n" +
  5786. "OpFunctionEnd",
  5787. 4, true),
  5788. // Test case 4: fold fnegate(fdiv with const).
  5789. // -(2.0 / x) = -2.0 / x
  5790. InstructionFoldingCase<bool>(
  5791. Header() +
  5792. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5793. "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2{{[[:space:]]}}\n" +
  5794. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  5795. "; CHECK: %4 = OpFDiv [[float]] [[float_n2]] [[ld]]\n" +
  5796. "%main = OpFunction %void None %void_func\n" +
  5797. "%main_lab = OpLabel\n" +
  5798. "%var = OpVariable %_ptr_float Function\n" +
  5799. "%2 = OpLoad %float %var\n" +
  5800. "%3 = OpFDiv %float %float_2 %2\n" +
  5801. "%4 = OpFNegate %float %3\n" +
  5802. "OpReturn\n" +
  5803. "OpFunctionEnd",
  5804. 4, true),
  5805. // Test case 5: fold fnegate(fadd with const).
  5806. // -(2.0 + x) = -2.0 - x
  5807. InstructionFoldingCase<bool>(
  5808. Header() +
  5809. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5810. "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2{{[[:space:]]}}\n" +
  5811. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  5812. "; CHECK: %4 = OpFSub [[float]] [[float_n2]] [[ld]]\n" +
  5813. "%main = OpFunction %void None %void_func\n" +
  5814. "%main_lab = OpLabel\n" +
  5815. "%var = OpVariable %_ptr_float Function\n" +
  5816. "%2 = OpLoad %float %var\n" +
  5817. "%3 = OpFAdd %float %float_2 %2\n" +
  5818. "%4 = OpFNegate %float %3\n" +
  5819. "OpReturn\n" +
  5820. "OpFunctionEnd",
  5821. 4, true),
  5822. // Test case 6: fold fnegate(fadd with const).
  5823. // -(x + 2.0) = -2.0 - x
  5824. InstructionFoldingCase<bool>(
  5825. Header() +
  5826. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5827. "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2{{[[:space:]]}}\n" +
  5828. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  5829. "; CHECK: %4 = OpFSub [[float]] [[float_n2]] [[ld]]\n" +
  5830. "%main = OpFunction %void None %void_func\n" +
  5831. "%main_lab = OpLabel\n" +
  5832. "%var = OpVariable %_ptr_float Function\n" +
  5833. "%2 = OpLoad %float %var\n" +
  5834. "%3 = OpFAdd %float %2 %float_2\n" +
  5835. "%4 = OpFNegate %float %3\n" +
  5836. "OpReturn\n" +
  5837. "OpFunctionEnd",
  5838. 4, true),
  5839. // Test case 7: fold fnegate(fsub with const).
  5840. // -(2.0 - x) = x - 2.0
  5841. InstructionFoldingCase<bool>(
  5842. Header() +
  5843. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5844. "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
  5845. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  5846. "; CHECK: %4 = OpFSub [[float]] [[ld]] [[float_2]]\n" +
  5847. "%main = OpFunction %void None %void_func\n" +
  5848. "%main_lab = OpLabel\n" +
  5849. "%var = OpVariable %_ptr_float Function\n" +
  5850. "%2 = OpLoad %float %var\n" +
  5851. "%3 = OpFSub %float %float_2 %2\n" +
  5852. "%4 = OpFNegate %float %3\n" +
  5853. "OpReturn\n" +
  5854. "OpFunctionEnd",
  5855. 4, true),
  5856. // Test case 8: fold fnegate(fsub with const).
  5857. // -(x - 2.0) = 2.0 - x
  5858. InstructionFoldingCase<bool>(
  5859. Header() +
  5860. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5861. "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
  5862. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  5863. "; CHECK: %4 = OpFSub [[float]] [[float_2]] [[ld]]\n" +
  5864. "%main = OpFunction %void None %void_func\n" +
  5865. "%main_lab = OpLabel\n" +
  5866. "%var = OpVariable %_ptr_float Function\n" +
  5867. "%2 = OpLoad %float %var\n" +
  5868. "%3 = OpFSub %float %2 %float_2\n" +
  5869. "%4 = OpFNegate %float %3\n" +
  5870. "OpReturn\n" +
  5871. "OpFunctionEnd",
  5872. 4, true),
  5873. // Test case 9: fold consecutive snegate
  5874. // -(-x) = x
  5875. InstructionFoldingCase<bool>(
  5876. Header() +
  5877. "; CHECK: [[ld:%\\w+]] = OpLoad [[int:%\\w+]]\n" +
  5878. "; CHECK: %4 = OpCopyObject [[int]] [[ld]]\n" +
  5879. "%main = OpFunction %void None %void_func\n" +
  5880. "%main_lab = OpLabel\n" +
  5881. "%var = OpVariable %_ptr_int Function\n" +
  5882. "%2 = OpLoad %int %var\n" +
  5883. "%3 = OpSNegate %int %2\n" +
  5884. "%4 = OpSNegate %int %3\n" +
  5885. "OpReturn\n" +
  5886. "OpFunctionEnd",
  5887. 4, true),
  5888. // Test case 10: fold consecutive vector negate
  5889. // -(-x) = x
  5890. InstructionFoldingCase<bool>(
  5891. Header() +
  5892. "; CHECK: [[ld:%\\w+]] = OpLoad [[v2float:%\\w+]]\n" +
  5893. "; CHECK: %4 = OpCopyObject [[v2float]] [[ld]]\n" +
  5894. "%main = OpFunction %void None %void_func\n" +
  5895. "%main_lab = OpLabel\n" +
  5896. "%var = OpVariable %_ptr_v2float Function\n" +
  5897. "%2 = OpLoad %v2float %var\n" +
  5898. "%3 = OpFNegate %v2float %2\n" +
  5899. "%4 = OpFNegate %v2float %3\n" +
  5900. "OpReturn\n" +
  5901. "OpFunctionEnd",
  5902. 4, true),
  5903. // Test case 11: fold snegate(iadd with const).
  5904. // -(2 + x) = -2 - x
  5905. InstructionFoldingCase<bool>(
  5906. Header() +
  5907. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  5908. "; CHECK: OpConstant [[int]] -2147483648\n" +
  5909. "; CHECK: [[int_n2:%\\w+]] = OpConstant [[int]] -2{{[[:space:]]}}\n" +
  5910. "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
  5911. "; CHECK: %4 = OpISub [[int]] [[int_n2]] [[ld]]\n" +
  5912. "%main = OpFunction %void None %void_func\n" +
  5913. "%main_lab = OpLabel\n" +
  5914. "%var = OpVariable %_ptr_int Function\n" +
  5915. "%2 = OpLoad %int %var\n" +
  5916. "%3 = OpIAdd %int %int_2 %2\n" +
  5917. "%4 = OpSNegate %int %3\n" +
  5918. "OpReturn\n" +
  5919. "OpFunctionEnd",
  5920. 4, true),
  5921. // Test case 12: fold snegate(iadd with const).
  5922. // -(x + 2) = -2 - x
  5923. InstructionFoldingCase<bool>(
  5924. Header() +
  5925. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  5926. "; CHECK: OpConstant [[int]] -2147483648\n" +
  5927. "; CHECK: [[int_n2:%\\w+]] = OpConstant [[int]] -2{{[[:space:]]}}\n" +
  5928. "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
  5929. "; CHECK: %4 = OpISub [[int]] [[int_n2]] [[ld]]\n" +
  5930. "%main = OpFunction %void None %void_func\n" +
  5931. "%main_lab = OpLabel\n" +
  5932. "%var = OpVariable %_ptr_int Function\n" +
  5933. "%2 = OpLoad %int %var\n" +
  5934. "%3 = OpIAdd %int %2 %int_2\n" +
  5935. "%4 = OpSNegate %int %3\n" +
  5936. "OpReturn\n" +
  5937. "OpFunctionEnd",
  5938. 4, true),
  5939. // Test case 13: fold snegate(isub with const).
  5940. // -(2 - x) = x - 2
  5941. InstructionFoldingCase<bool>(
  5942. Header() +
  5943. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  5944. "; CHECK: [[int_2:%\\w+]] = OpConstant [[int]] 2\n" +
  5945. "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
  5946. "; CHECK: %4 = OpISub [[int]] [[ld]] [[int_2]]\n" +
  5947. "%main = OpFunction %void None %void_func\n" +
  5948. "%main_lab = OpLabel\n" +
  5949. "%var = OpVariable %_ptr_int Function\n" +
  5950. "%2 = OpLoad %int %var\n" +
  5951. "%3 = OpISub %int %int_2 %2\n" +
  5952. "%4 = OpSNegate %int %3\n" +
  5953. "OpReturn\n" +
  5954. "OpFunctionEnd",
  5955. 4, true),
  5956. // Test case 14: fold snegate(isub with const).
  5957. // -(x - 2) = 2 - x
  5958. InstructionFoldingCase<bool>(
  5959. Header() +
  5960. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  5961. "; CHECK: [[int_2:%\\w+]] = OpConstant [[int]] 2\n" +
  5962. "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
  5963. "; CHECK: %4 = OpISub [[int]] [[int_2]] [[ld]]\n" +
  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 = OpISub %int %2 %int_2\n" +
  5969. "%4 = OpSNegate %int %3\n" +
  5970. "OpReturn\n" +
  5971. "OpFunctionEnd",
  5972. 4, true),
  5973. // Test case 15: fold snegate(iadd with const).
  5974. // -(x + 2) = -2 - x
  5975. InstructionFoldingCase<bool>(
  5976. Header() +
  5977. "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
  5978. "; CHECK: [[long_n2:%\\w+]] = OpConstant [[long]] -2{{[[:space:]]}}\n" +
  5979. "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
  5980. "; CHECK: %4 = OpISub [[long]] [[long_n2]] [[ld]]\n" +
  5981. "%main = OpFunction %void None %void_func\n" +
  5982. "%main_lab = OpLabel\n" +
  5983. "%var = OpVariable %_ptr_long Function\n" +
  5984. "%2 = OpLoad %long %var\n" +
  5985. "%3 = OpIAdd %long %2 %long_2\n" +
  5986. "%4 = OpSNegate %long %3\n" +
  5987. "OpReturn\n" +
  5988. "OpFunctionEnd",
  5989. 4, true),
  5990. // Test case 16: fold snegate(isub with const).
  5991. // -(2 - x) = x - 2
  5992. InstructionFoldingCase<bool>(
  5993. Header() +
  5994. "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
  5995. "; CHECK: [[long_2:%\\w+]] = OpConstant [[long]] 2\n" +
  5996. "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
  5997. "; CHECK: %4 = OpISub [[long]] [[ld]] [[long_2]]\n" +
  5998. "%main = OpFunction %void None %void_func\n" +
  5999. "%main_lab = OpLabel\n" +
  6000. "%var = OpVariable %_ptr_long Function\n" +
  6001. "%2 = OpLoad %long %var\n" +
  6002. "%3 = OpISub %long %long_2 %2\n" +
  6003. "%4 = OpSNegate %long %3\n" +
  6004. "OpReturn\n" +
  6005. "OpFunctionEnd",
  6006. 4, true),
  6007. // Test case 17: fold snegate(isub with const).
  6008. // -(x - 2) = 2 - x
  6009. InstructionFoldingCase<bool>(
  6010. Header() +
  6011. "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
  6012. "; CHECK: [[long_2:%\\w+]] = OpConstant [[long]] 2\n" +
  6013. "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
  6014. "; CHECK: %4 = OpISub [[long]] [[long_2]] [[ld]]\n" +
  6015. "%main = OpFunction %void None %void_func\n" +
  6016. "%main_lab = OpLabel\n" +
  6017. "%var = OpVariable %_ptr_long Function\n" +
  6018. "%2 = OpLoad %long %var\n" +
  6019. "%3 = OpISub %long %2 %long_2\n" +
  6020. "%4 = OpSNegate %long %3\n" +
  6021. "OpReturn\n" +
  6022. "OpFunctionEnd",
  6023. 4, true),
  6024. // Test case 18: fold -vec4(-1.0, 2.0, 1.0, 3.0)
  6025. InstructionFoldingCase<bool>(
  6026. Header() +
  6027. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  6028. "; CHECK: [[v4float:%\\w+]] = OpTypeVector [[float]] 4{{[[:space:]]}}\n" +
  6029. "; CHECK: [[float_n1:%\\w+]] = OpConstant [[float]] -1{{[[:space:]]}}\n" +
  6030. "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1{{[[:space:]]}}\n" +
  6031. "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2{{[[:space:]]}}\n" +
  6032. "; CHECK: [[float_n3:%\\w+]] = OpConstant [[float]] -3{{[[:space:]]}}\n" +
  6033. "; CHECK: [[v4float_1_n2_n1_n3:%\\w+]] = OpConstantComposite [[v4float]] [[float_1]] [[float_n2]] [[float_n1]] [[float_n3]]\n" +
  6034. "; CHECK: %2 = OpCopyObject [[v4float]] [[v4float_1_n2_n1_n3]]\n" +
  6035. "%main = OpFunction %void None %void_func\n" +
  6036. "%main_lab = OpLabel\n" +
  6037. "%2 = OpFNegate %v4float %v4float_n1_2_1_3\n" +
  6038. "OpReturn\n" +
  6039. "OpFunctionEnd",
  6040. 2, true),
  6041. // Test case 19: fold vector fnegate with null
  6042. InstructionFoldingCase<bool>(
  6043. Header() +
  6044. "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
  6045. "; CHECK: [[v2double:%\\w+]] = OpTypeVector [[double]] 2\n" +
  6046. "; CHECK: [[double_n0:%\\w+]] = OpConstant [[double]] -0\n" +
  6047. "; CHECK: [[v2double_0_0:%\\w+]] = OpConstantComposite [[v2double]] [[double_n0]] [[double_n0]]\n" +
  6048. "; CHECK: %2 = OpCopyObject [[v2double]] [[v2double_0_0]]\n" +
  6049. "%main = OpFunction %void None %void_func\n" +
  6050. "%main_lab = OpLabel\n" +
  6051. "%2 = OpFNegate %v2double %v2double_null\n" +
  6052. "OpReturn\n" +
  6053. "OpFunctionEnd",
  6054. 2, true),
  6055. // Test case 20: fold snegate with OpIMul.
  6056. // -(x * 2) = x * -2
  6057. InstructionFoldingCase<bool>(
  6058. Header() +
  6059. "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
  6060. "; CHECK: [[long_n2:%\\w+]] = OpConstant [[long]] -2\n" +
  6061. "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
  6062. "; CHECK: %4 = OpIMul [[long]] [[ld]] [[long_n2]]\n" +
  6063. "%main = OpFunction %void None %void_func\n" +
  6064. "%main_lab = OpLabel\n" +
  6065. "%var = OpVariable %_ptr_long Function\n" +
  6066. "%2 = OpLoad %long %var\n" +
  6067. "%3 = OpIMul %long %2 %long_2\n" +
  6068. "%4 = OpSNegate %long %3\n" +
  6069. "OpReturn\n" +
  6070. "OpFunctionEnd",
  6071. 4, true),
  6072. // Test case 21: fold snegate with OpIMul.
  6073. // -(x * 2) = x * -2
  6074. InstructionFoldingCase<bool>(
  6075. Header() +
  6076. "; CHECK-DAG: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  6077. "; CHECK-DAG: [[uint:%\\w+]] = OpTypeInt 32 0\n" +
  6078. "; CHECK: [[uint_n2:%\\w+]] = OpConstant [[uint]] 4294967294\n" +
  6079. "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
  6080. "; CHECK: %4 = OpIMul [[int]] [[ld]] [[uint_n2]]\n" +
  6081. "%main = OpFunction %void None %void_func\n" +
  6082. "%main_lab = OpLabel\n" +
  6083. "%var = OpVariable %_ptr_int Function\n" +
  6084. "%2 = OpLoad %int %var\n" +
  6085. "%3 = OpIMul %int %2 %uint_2\n" +
  6086. "%4 = OpSNegate %int %3\n" +
  6087. "OpReturn\n" +
  6088. "OpFunctionEnd",
  6089. 4, true),
  6090. // Test case 22: fold snegate with OpIMul.
  6091. // -(-24 * x) = x * 24
  6092. InstructionFoldingCase<bool>(
  6093. Header() +
  6094. "; CHECK-DAG: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  6095. "; CHECK: [[int_24:%\\w+]] = OpConstant [[int]] 24\n" +
  6096. "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
  6097. "; CHECK: %4 = OpIMul [[int]] [[ld]] [[int_24]]\n" +
  6098. "%main = OpFunction %void None %void_func\n" +
  6099. "%main_lab = OpLabel\n" +
  6100. "%var = OpVariable %_ptr_int Function\n" +
  6101. "%2 = OpLoad %int %var\n" +
  6102. "%3 = OpIMul %int %int_n24 %2\n" +
  6103. "%4 = OpSNegate %int %3\n" +
  6104. "OpReturn\n" +
  6105. "OpFunctionEnd",
  6106. 4, true),
  6107. // Test case 23: fold snegate with OpIMul with UINT_MAX
  6108. // -(UINT_MAX * x) = x
  6109. InstructionFoldingCase<bool>(
  6110. Header() +
  6111. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  6112. "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
  6113. "; CHECK: %4 = OpCopyObject [[int]] [[ld]]\n" +
  6114. "%main = OpFunction %void None %void_func\n" +
  6115. "%main_lab = OpLabel\n" +
  6116. "%var = OpVariable %_ptr_int Function\n" +
  6117. "%2 = OpLoad %int %var\n" +
  6118. "%3 = OpIMul %int %uint_max %2\n" +
  6119. "%4 = OpSNegate %int %3\n" +
  6120. "OpReturn\n" +
  6121. "OpFunctionEnd",
  6122. 4, true),
  6123. // Test case 24: fold snegate with OpIMul using -INT_MAX
  6124. // -(x * 2147483649u) = x * 2147483647u
  6125. InstructionFoldingCase<bool>(
  6126. Header() +
  6127. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  6128. "; CHECK: [[uint:%\\w+]] = OpTypeInt 32 0\n" +
  6129. "; CHECK: [[uint_2147483647:%\\w+]] = OpConstant [[uint]] 2147483647\n" +
  6130. "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
  6131. "; CHECK: %4 = OpIMul [[int]] [[ld]] [[uint_2147483647]]\n" +
  6132. "%main = OpFunction %void None %void_func\n" +
  6133. "%main_lab = OpLabel\n" +
  6134. "%var = OpVariable %_ptr_int Function\n" +
  6135. "%2 = OpLoad %int %var\n" +
  6136. "%3 = OpIMul %int %2 %uint_2147483649\n" +
  6137. "%4 = OpSNegate %int %3\n" +
  6138. "OpReturn\n" +
  6139. "OpFunctionEnd",
  6140. 4, true),
  6141. // Test case 25: fold snegate with OpSDiv (long).
  6142. // -(x / 2) = x / -2
  6143. InstructionFoldingCase<bool>(
  6144. Header() +
  6145. "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
  6146. "; CHECK: [[long_n2:%\\w+]] = OpConstant [[long]] -2\n" +
  6147. "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
  6148. "; CHECK: %4 = OpSDiv [[long]] [[ld]] [[long_n2]]\n" +
  6149. "%main = OpFunction %void None %void_func\n" +
  6150. "%main_lab = OpLabel\n" +
  6151. "%var = OpVariable %_ptr_long Function\n" +
  6152. "%2 = OpLoad %long %var\n" +
  6153. "%3 = OpSDiv %long %2 %long_2\n" +
  6154. "%4 = OpSNegate %long %3\n" +
  6155. "OpReturn\n" +
  6156. "OpFunctionEnd",
  6157. 4, true),
  6158. // Test case 26: fold snegate with OpSDiv (int).
  6159. // -(x / 2) = x / -2
  6160. InstructionFoldingCase<bool>(
  6161. Header() +
  6162. "; CHECK-DAG: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  6163. "; CHECK-DAG: [[uint:%\\w+]] = OpTypeInt 32 0\n" +
  6164. "; CHECK: [[uint_n2:%\\w+]] = OpConstant [[uint]] 4294967294\n" +
  6165. "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
  6166. "; CHECK: %4 = OpSDiv [[int]] [[ld]] [[uint_n2]]\n" +
  6167. "%main = OpFunction %void None %void_func\n" +
  6168. "%main_lab = OpLabel\n" +
  6169. "%var = OpVariable %_ptr_int Function\n" +
  6170. "%2 = OpLoad %int %var\n" +
  6171. "%3 = OpSDiv %int %2 %uint_2\n" +
  6172. "%4 = OpSNegate %int %3\n" +
  6173. "OpReturn\n" +
  6174. "OpFunctionEnd",
  6175. 4, true),
  6176. // Test case 27: fold snegate with OpSDiv.
  6177. // -(-24 / x) = 24 / x
  6178. InstructionFoldingCase<bool>(
  6179. Header() +
  6180. "; CHECK-DAG: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  6181. "; CHECK: [[int_24:%\\w+]] = OpConstant [[int]] 24\n" +
  6182. "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
  6183. "; CHECK: %4 = OpSDiv [[int]] [[int_24]] [[ld]]\n" +
  6184. "%main = OpFunction %void None %void_func\n" +
  6185. "%main_lab = OpLabel\n" +
  6186. "%var = OpVariable %_ptr_int Function\n" +
  6187. "%2 = OpLoad %int %var\n" +
  6188. "%3 = OpSDiv %int %int_n24 %2\n" +
  6189. "%4 = OpSNegate %int %3\n" +
  6190. "OpReturn\n" +
  6191. "OpFunctionEnd",
  6192. 4, true),
  6193. // Test case 28: fold snegate with OpSDiv with UINT_MAX
  6194. // -(UINT_MAX / x) = (1 / x)
  6195. InstructionFoldingCase<bool>(
  6196. Header() +
  6197. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  6198. "; CHECK: [[uint:%\\w+]] = OpTypeInt 32 0\n" +
  6199. "; CHECK: [[uint_1:%\\w+]] = OpConstant [[uint]] 1\n" +
  6200. "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
  6201. "; CHECK: %4 = OpSDiv [[int]] [[uint_1]] [[ld]]\n" +
  6202. "%main = OpFunction %void None %void_func\n" +
  6203. "%main_lab = OpLabel\n" +
  6204. "%var = OpVariable %_ptr_int Function\n" +
  6205. "%2 = OpLoad %int %var\n" +
  6206. "%3 = OpSDiv %int %uint_max %2\n" +
  6207. "%4 = OpSNegate %int %3\n" +
  6208. "OpReturn\n" +
  6209. "OpFunctionEnd",
  6210. 4, true),
  6211. // Test case 29: fold snegate with OpSDiv using -INT_MAX
  6212. // -(x / 2147483647u) = x / 2147483647
  6213. InstructionFoldingCase<bool>(
  6214. Header() +
  6215. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  6216. "; CHECK: [[uint:%\\w+]] = OpTypeInt 32 0\n" +
  6217. "; CHECK: [[uint_2147483647:%\\w+]] = OpConstant [[uint]] 2147483647\n" +
  6218. "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
  6219. "; CHECK: %4 = OpSDiv [[int]] [[ld]] [[uint_2147483647]]\n" +
  6220. "%main = OpFunction %void None %void_func\n" +
  6221. "%main_lab = OpLabel\n" +
  6222. "%var = OpVariable %_ptr_int Function\n" +
  6223. "%2 = OpLoad %int %var\n" +
  6224. "%3 = OpSDiv %int %2 %uint_2147483649\n" +
  6225. "%4 = OpSNegate %int %3\n" +
  6226. "OpReturn\n" +
  6227. "OpFunctionEnd",
  6228. 4, true),
  6229. // Test case 30: Don't fold snegate int OpUDiv. The operands are interpreted
  6230. // as unsigned, so negating an operand is not the same a negating the
  6231. // result.
  6232. InstructionFoldingCase<bool>(
  6233. Header() +
  6234. "%main = OpFunction %void None %void_func\n" +
  6235. "%main_lab = OpLabel\n" +
  6236. "%var = OpVariable %_ptr_int Function\n" +
  6237. "%2 = OpLoad %int %var\n" +
  6238. "%3 = OpUDiv %int %2 %uint_1\n" +
  6239. "%4 = OpSNegate %int %3\n" +
  6240. "OpReturn\n" +
  6241. "OpFunctionEnd",
  6242. 4, false)
  6243. ));
  6244. INSTANTIATE_TEST_SUITE_P(ReciprocalFDivTest, MatchingInstructionFoldingTest,
  6245. ::testing::Values(
  6246. // Test case 0: scalar reicprocal
  6247. // x / 0.5 = x * 2.0
  6248. InstructionFoldingCase<bool>(
  6249. Header() +
  6250. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  6251. "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
  6252. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  6253. "; CHECK: %3 = OpFMul [[float]] [[ld]] [[float_2]]\n" +
  6254. "%main = OpFunction %void None %void_func\n" +
  6255. "%main_lab = OpLabel\n" +
  6256. "%var = OpVariable %_ptr_float Function\n" +
  6257. "%2 = OpLoad %float %var\n" +
  6258. "%3 = OpFDiv %float %2 %float_0p5\n" +
  6259. "OpReturn\n" +
  6260. "OpFunctionEnd\n",
  6261. 3, true),
  6262. // Test case 1: Unfoldable
  6263. InstructionFoldingCase<bool>(
  6264. Header() +
  6265. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  6266. "; CHECK: [[float_0:%\\w+]] = OpConstant [[float]] 0\n" +
  6267. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  6268. "; CHECK: %3 = OpFDiv [[float]] [[ld]] [[float_0]]\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 = OpFDiv %float %2 %104\n" +
  6274. "OpReturn\n" +
  6275. "OpFunctionEnd\n",
  6276. 3, false),
  6277. // Test case 2: Vector reciprocal
  6278. // x / {2.0, 0.5} = x * {0.5, 2.0}
  6279. InstructionFoldingCase<bool>(
  6280. Header() +
  6281. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  6282. "; CHECK: [[v2float:%\\w+]] = OpTypeVector [[float]] 2\n" +
  6283. "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
  6284. "; CHECK: [[float_0p5:%\\w+]] = OpConstant [[float]] 0.5\n" +
  6285. "; CHECK: [[v2float_0p5_2:%\\w+]] = OpConstantComposite [[v2float]] [[float_0p5]] [[float_2]]\n" +
  6286. "; CHECK: [[ld:%\\w+]] = OpLoad [[v2float]]\n" +
  6287. "; CHECK: %3 = OpFMul [[v2float]] [[ld]] [[v2float_0p5_2]]\n" +
  6288. "%main = OpFunction %void None %void_func\n" +
  6289. "%main_lab = OpLabel\n" +
  6290. "%var = OpVariable %_ptr_v2float Function\n" +
  6291. "%2 = OpLoad %v2float %var\n" +
  6292. "%3 = OpFDiv %v2float %2 %v2float_2_0p5\n" +
  6293. "OpReturn\n" +
  6294. "OpFunctionEnd\n",
  6295. 3, true),
  6296. // Test case 3: double reciprocal
  6297. // x / 2.0 = x * 0.5
  6298. InstructionFoldingCase<bool>(
  6299. Header() +
  6300. "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
  6301. "; CHECK: [[double_0p5:%\\w+]] = OpConstant [[double]] 0.5\n" +
  6302. "; CHECK: [[ld:%\\w+]] = OpLoad [[double]]\n" +
  6303. "; CHECK: %3 = OpFMul [[double]] [[ld]] [[double_0p5]]\n" +
  6304. "%main = OpFunction %void None %void_func\n" +
  6305. "%main_lab = OpLabel\n" +
  6306. "%var = OpVariable %_ptr_double Function\n" +
  6307. "%2 = OpLoad %double %var\n" +
  6308. "%3 = OpFDiv %double %2 %double_2\n" +
  6309. "OpReturn\n" +
  6310. "OpFunctionEnd\n",
  6311. 3, true),
  6312. // Test case 4: don't fold x / 0.
  6313. InstructionFoldingCase<bool>(
  6314. Header() +
  6315. "%main = OpFunction %void None %void_func\n" +
  6316. "%main_lab = OpLabel\n" +
  6317. "%var = OpVariable %_ptr_v2float Function\n" +
  6318. "%2 = OpLoad %v2float %var\n" +
  6319. "%3 = OpFDiv %v2float %2 %v2float_null\n" +
  6320. "OpReturn\n" +
  6321. "OpFunctionEnd\n",
  6322. 3, false)
  6323. ));
  6324. INSTANTIATE_TEST_SUITE_P(MergeMulTest, MatchingInstructionFoldingTest,
  6325. ::testing::Values(
  6326. // Test case 0: fold consecutive fmuls
  6327. // (x * 3.0) * 2.0 = x * 6.0
  6328. InstructionFoldingCase<bool>(
  6329. Header() +
  6330. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  6331. "; CHECK: [[float_6:%\\w+]] = OpConstant [[float]] 6\n" +
  6332. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  6333. "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_6]]\n" +
  6334. "%main = OpFunction %void None %void_func\n" +
  6335. "%main_lab = OpLabel\n" +
  6336. "%var = OpVariable %_ptr_float Function\n" +
  6337. "%2 = OpLoad %float %var\n" +
  6338. "%3 = OpFMul %float %2 %float_3\n" +
  6339. "%4 = OpFMul %float %3 %float_2\n" +
  6340. "OpReturn\n" +
  6341. "OpFunctionEnd\n",
  6342. 4, true),
  6343. // Test case 1: fold consecutive fmuls
  6344. // 2.0 * (x * 3.0) = x * 6.0
  6345. InstructionFoldingCase<bool>(
  6346. Header() +
  6347. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  6348. "; CHECK: [[float_6:%\\w+]] = OpConstant [[float]] 6\n" +
  6349. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  6350. "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_6]]\n" +
  6351. "%main = OpFunction %void None %void_func\n" +
  6352. "%main_lab = OpLabel\n" +
  6353. "%var = OpVariable %_ptr_float Function\n" +
  6354. "%2 = OpLoad %float %var\n" +
  6355. "%3 = OpFMul %float %2 %float_3\n" +
  6356. "%4 = OpFMul %float %float_2 %3\n" +
  6357. "OpReturn\n" +
  6358. "OpFunctionEnd\n",
  6359. 4, true),
  6360. // Test case 2: fold consecutive fmuls
  6361. // (3.0 * x) * 2.0 = x * 6.0
  6362. InstructionFoldingCase<bool>(
  6363. Header() +
  6364. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  6365. "; CHECK: [[float_6:%\\w+]] = OpConstant [[float]] 6\n" +
  6366. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  6367. "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_6]]\n" +
  6368. "%main = OpFunction %void None %void_func\n" +
  6369. "%main_lab = OpLabel\n" +
  6370. "%var = OpVariable %_ptr_float Function\n" +
  6371. "%2 = OpLoad %float %var\n" +
  6372. "%3 = OpFMul %float %float_3 %2\n" +
  6373. "%4 = OpFMul %float %float_2 %3\n" +
  6374. "OpReturn\n" +
  6375. "OpFunctionEnd\n",
  6376. 4, true),
  6377. // Test case 3: fold vector fmul
  6378. InstructionFoldingCase<bool>(
  6379. Header() +
  6380. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  6381. "; CHECK: [[v2float:%\\w+]] = OpTypeVector [[float]] 2\n" +
  6382. "; CHECK: [[float_6:%\\w+]] = OpConstant [[float]] 6\n" +
  6383. "; CHECK: [[v2float_6_6:%\\w+]] = OpConstantComposite [[v2float]] [[float_6]] [[float_6]]\n" +
  6384. "; CHECK: [[ld:%\\w+]] = OpLoad [[v2float]]\n" +
  6385. "; CHECK: %4 = OpFMul [[v2float]] [[ld]] [[v2float_6_6]]\n" +
  6386. "%main = OpFunction %void None %void_func\n" +
  6387. "%main_lab = OpLabel\n" +
  6388. "%var = OpVariable %_ptr_v2float Function\n" +
  6389. "%2 = OpLoad %v2float %var\n" +
  6390. "%3 = OpFMul %v2float %2 %v2float_2_3\n" +
  6391. "%4 = OpFMul %v2float %3 %v2float_3_2\n" +
  6392. "OpReturn\n" +
  6393. "OpFunctionEnd\n",
  6394. 4, true),
  6395. // Test case 4: fold double fmuls
  6396. // (x * 3.0) * 2.0 = x * 6.0
  6397. InstructionFoldingCase<bool>(
  6398. Header() +
  6399. "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
  6400. "; CHECK: [[double_6:%\\w+]] = OpConstant [[double]] 6\n" +
  6401. "; CHECK: [[ld:%\\w+]] = OpLoad [[double]]\n" +
  6402. "; CHECK: %4 = OpFMul [[double]] [[ld]] [[double_6]]\n" +
  6403. "%main = OpFunction %void None %void_func\n" +
  6404. "%main_lab = OpLabel\n" +
  6405. "%var = OpVariable %_ptr_double Function\n" +
  6406. "%2 = OpLoad %double %var\n" +
  6407. "%3 = OpFMul %double %2 %double_3\n" +
  6408. "%4 = OpFMul %double %3 %double_2\n" +
  6409. "OpReturn\n" +
  6410. "OpFunctionEnd\n",
  6411. 4, true),
  6412. // Test case 5: fold 32 bit imuls
  6413. // (x * 3) * 2 = x * 6
  6414. InstructionFoldingCase<bool>(
  6415. Header() +
  6416. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  6417. "; CHECK: [[int_6:%\\w+]] = OpConstant [[int]] 6\n" +
  6418. "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
  6419. "; CHECK: %4 = OpIMul [[int]] [[ld]] [[int_6]]\n" +
  6420. "%main = OpFunction %void None %void_func\n" +
  6421. "%main_lab = OpLabel\n" +
  6422. "%var = OpVariable %_ptr_int Function\n" +
  6423. "%2 = OpLoad %int %var\n" +
  6424. "%3 = OpIMul %int %2 %int_3\n" +
  6425. "%4 = OpIMul %int %3 %int_2\n" +
  6426. "OpReturn\n" +
  6427. "OpFunctionEnd\n",
  6428. 4, true),
  6429. // Test case 6: fold 64 bit imuls
  6430. // (x * 3) * 2 = x * 6
  6431. InstructionFoldingCase<bool>(
  6432. Header() +
  6433. "; CHECK: [[long:%\\w+]] = OpTypeInt 64\n" +
  6434. "; CHECK: [[long_6:%\\w+]] = OpConstant [[long]] 6\n" +
  6435. "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
  6436. "; CHECK: %4 = OpIMul [[long]] [[ld]] [[long_6]]\n" +
  6437. "%main = OpFunction %void None %void_func\n" +
  6438. "%main_lab = OpLabel\n" +
  6439. "%var = OpVariable %_ptr_long Function\n" +
  6440. "%2 = OpLoad %long %var\n" +
  6441. "%3 = OpIMul %long %2 %long_3\n" +
  6442. "%4 = OpIMul %long %3 %long_2\n" +
  6443. "OpReturn\n" +
  6444. "OpFunctionEnd\n",
  6445. 4, true),
  6446. // Test case 7: merge vector integer mults
  6447. InstructionFoldingCase<bool>(
  6448. Header() +
  6449. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  6450. "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2\n" +
  6451. "; CHECK: [[int_6:%\\w+]] = OpConstant [[int]] 6\n" +
  6452. "; CHECK: [[v2int_6_6:%\\w+]] = OpConstantComposite [[v2int]] [[int_6]] [[int_6]]\n" +
  6453. "; CHECK: [[ld:%\\w+]] = OpLoad [[v2int]]\n" +
  6454. "; CHECK: %4 = OpIMul [[v2int]] [[ld]] [[v2int_6_6]]\n" +
  6455. "%main = OpFunction %void None %void_func\n" +
  6456. "%main_lab = OpLabel\n" +
  6457. "%var = OpVariable %_ptr_v2int Function\n" +
  6458. "%2 = OpLoad %v2int %var\n" +
  6459. "%3 = OpIMul %v2int %2 %v2int_2_3\n" +
  6460. "%4 = OpIMul %v2int %3 %v2int_3_2\n" +
  6461. "OpReturn\n" +
  6462. "OpFunctionEnd\n",
  6463. 4, true),
  6464. // Test case 8: merge fmul of fdiv
  6465. // 2.0 * (2.0 / x) = 4.0 / x
  6466. InstructionFoldingCase<bool>(
  6467. Header() +
  6468. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  6469. "; CHECK: [[float_4:%\\w+]] = OpConstant [[float]] 4\n" +
  6470. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  6471. "; CHECK: %4 = OpFDiv [[float]] [[float_4]] [[ld]]\n" +
  6472. "%main = OpFunction %void None %void_func\n" +
  6473. "%main_lab = OpLabel\n" +
  6474. "%var = OpVariable %_ptr_float Function\n" +
  6475. "%2 = OpLoad %float %var\n" +
  6476. "%3 = OpFDiv %float %float_2 %2\n" +
  6477. "%4 = OpFMul %float %float_2 %3\n" +
  6478. "OpReturn\n" +
  6479. "OpFunctionEnd\n",
  6480. 4, true),
  6481. // Test case 9: merge fmul of fdiv
  6482. // (2.0 / x) * 2.0 = 4.0 / x
  6483. InstructionFoldingCase<bool>(
  6484. Header() +
  6485. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  6486. "; CHECK: [[float_4:%\\w+]] = OpConstant [[float]] 4\n" +
  6487. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  6488. "; CHECK: %4 = OpFDiv [[float]] [[float_4]] [[ld]]\n" +
  6489. "%main = OpFunction %void None %void_func\n" +
  6490. "%main_lab = OpLabel\n" +
  6491. "%var = OpVariable %_ptr_float Function\n" +
  6492. "%2 = OpLoad %float %var\n" +
  6493. "%3 = OpFDiv %float %float_2 %2\n" +
  6494. "%4 = OpFMul %float %3 %float_2\n" +
  6495. "OpReturn\n" +
  6496. "OpFunctionEnd\n",
  6497. 4, true),
  6498. // Test case 10: Do not merge imul of sdiv
  6499. // 4 * (x / 2)
  6500. InstructionFoldingCase<bool>(
  6501. Header() +
  6502. "%main = OpFunction %void None %void_func\n" +
  6503. "%main_lab = OpLabel\n" +
  6504. "%var = OpVariable %_ptr_int Function\n" +
  6505. "%2 = OpLoad %int %var\n" +
  6506. "%3 = OpSDiv %int %2 %int_2\n" +
  6507. "%4 = OpIMul %int %int_4 %3\n" +
  6508. "OpReturn\n" +
  6509. "OpFunctionEnd\n",
  6510. 4, false),
  6511. // Test case 11: Do not merge imul of sdiv
  6512. // (x / 2) * 4
  6513. InstructionFoldingCase<bool>(
  6514. Header() +
  6515. "%main = OpFunction %void None %void_func\n" +
  6516. "%main_lab = OpLabel\n" +
  6517. "%var = OpVariable %_ptr_int Function\n" +
  6518. "%2 = OpLoad %int %var\n" +
  6519. "%3 = OpSDiv %int %2 %int_2\n" +
  6520. "%4 = OpIMul %int %3 %int_4\n" +
  6521. "OpReturn\n" +
  6522. "OpFunctionEnd\n",
  6523. 4, false),
  6524. // Test case 12: Do not merge imul of udiv
  6525. // 4 * (x / 2)
  6526. InstructionFoldingCase<bool>(
  6527. Header() +
  6528. "%main = OpFunction %void None %void_func\n" +
  6529. "%main_lab = OpLabel\n" +
  6530. "%var = OpVariable %_ptr_uint Function\n" +
  6531. "%2 = OpLoad %uint %var\n" +
  6532. "%3 = OpUDiv %uint %2 %uint_2\n" +
  6533. "%4 = OpIMul %uint %uint_4 %3\n" +
  6534. "OpReturn\n" +
  6535. "OpFunctionEnd\n",
  6536. 4, false),
  6537. // Test case 13: Do not merge imul of udiv
  6538. // (x / 2) * 4
  6539. InstructionFoldingCase<bool>(
  6540. Header() +
  6541. "%main = OpFunction %void None %void_func\n" +
  6542. "%main_lab = OpLabel\n" +
  6543. "%var = OpVariable %_ptr_uint Function\n" +
  6544. "%2 = OpLoad %uint %var\n" +
  6545. "%3 = OpUDiv %uint %2 %uint_2\n" +
  6546. "%4 = OpIMul %uint %3 %uint_4\n" +
  6547. "OpReturn\n" +
  6548. "OpFunctionEnd\n",
  6549. 4, false),
  6550. // Test case 14: Don't fold
  6551. // (x / 3) * 4
  6552. InstructionFoldingCase<bool>(
  6553. Header() +
  6554. "%main = OpFunction %void None %void_func\n" +
  6555. "%main_lab = OpLabel\n" +
  6556. "%var = OpVariable %_ptr_uint Function\n" +
  6557. "%2 = OpLoad %uint %var\n" +
  6558. "%3 = OpUDiv %uint %2 %uint_3\n" +
  6559. "%4 = OpIMul %uint %3 %uint_4\n" +
  6560. "OpReturn\n" +
  6561. "OpFunctionEnd\n",
  6562. 4, false),
  6563. // Test case 15: merge vector fmul of fdiv
  6564. // (x / {2,2}) * {4,4} = x * {2,2}
  6565. InstructionFoldingCase<bool>(
  6566. Header() +
  6567. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  6568. "; CHECK: [[v2float:%\\w+]] = OpTypeVector [[float]] 2\n" +
  6569. "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
  6570. "; CHECK: [[v2float_2_2:%\\w+]] = OpConstantComposite [[v2float]] [[float_2]] [[float_2]]\n" +
  6571. "; CHECK: [[ld:%\\w+]] = OpLoad [[v2float]]\n" +
  6572. "; CHECK: %4 = OpFMul [[v2float]] [[ld]] [[v2float_2_2]]\n" +
  6573. "%main = OpFunction %void None %void_func\n" +
  6574. "%main_lab = OpLabel\n" +
  6575. "%var = OpVariable %_ptr_v2float Function\n" +
  6576. "%2 = OpLoad %v2float %var\n" +
  6577. "%3 = OpFDiv %v2float %2 %v2float_2_2\n" +
  6578. "%4 = OpFMul %v2float %3 %v2float_4_4\n" +
  6579. "OpReturn\n" +
  6580. "OpFunctionEnd\n",
  6581. 4, true),
  6582. // Test case 16: merge vector imul of snegate
  6583. // (-x) * {2,2} = x * {-2,-2}
  6584. InstructionFoldingCase<bool>(
  6585. Header() +
  6586. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  6587. "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2{{[[:space:]]}}\n" +
  6588. "; CHECK: OpConstant [[int]] -2147483648{{[[:space:]]}}\n" +
  6589. "; CHECK: [[int_n2:%\\w+]] = OpConstant [[int]] -2{{[[:space:]]}}\n" +
  6590. "; CHECK: [[v2int_n2_n2:%\\w+]] = OpConstantComposite [[v2int]] [[int_n2]] [[int_n2]]\n" +
  6591. "; CHECK: [[ld:%\\w+]] = OpLoad [[v2int]]\n" +
  6592. "; CHECK: %4 = OpIMul [[v2int]] [[ld]] [[v2int_n2_n2]]\n" +
  6593. "%main = OpFunction %void None %void_func\n" +
  6594. "%main_lab = OpLabel\n" +
  6595. "%var = OpVariable %_ptr_v2int Function\n" +
  6596. "%2 = OpLoad %v2int %var\n" +
  6597. "%3 = OpSNegate %v2int %2\n" +
  6598. "%4 = OpIMul %v2int %3 %v2int_2_2\n" +
  6599. "OpReturn\n" +
  6600. "OpFunctionEnd\n",
  6601. 4, true),
  6602. // Test case 17: merge vector imul of snegate
  6603. // {2,2} * (-x) = x * {-2,-2}
  6604. InstructionFoldingCase<bool>(
  6605. Header() +
  6606. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  6607. "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2{{[[:space:]]}}\n" +
  6608. "; CHECK: OpConstant [[int]] -2147483648{{[[:space:]]}}\n" +
  6609. "; CHECK: [[int_n2:%\\w+]] = OpConstant [[int]] -2{{[[:space:]]}}\n" +
  6610. "; CHECK: [[v2int_n2_n2:%\\w+]] = OpConstantComposite [[v2int]] [[int_n2]] [[int_n2]]\n" +
  6611. "; CHECK: [[ld:%\\w+]] = OpLoad [[v2int]]\n" +
  6612. "; CHECK: %4 = OpIMul [[v2int]] [[ld]] [[v2int_n2_n2]]\n" +
  6613. "%main = OpFunction %void None %void_func\n" +
  6614. "%main_lab = OpLabel\n" +
  6615. "%var = OpVariable %_ptr_v2int Function\n" +
  6616. "%2 = OpLoad %v2int %var\n" +
  6617. "%3 = OpSNegate %v2int %2\n" +
  6618. "%4 = OpIMul %v2int %v2int_2_2 %3\n" +
  6619. "OpReturn\n" +
  6620. "OpFunctionEnd\n",
  6621. 4, true),
  6622. // Test case 18: Fold OpVectorTimesScalar
  6623. // {4,4} = OpVectorTimesScalar v2float {2,2} 2
  6624. InstructionFoldingCase<bool>(
  6625. Header() +
  6626. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  6627. "; CHECK: [[v2float:%\\w+]] = OpTypeVector [[float]] 2\n" +
  6628. "; CHECK: [[float_4:%\\w+]] = OpConstant [[float]] 4\n" +
  6629. "; CHECK: [[v2float_4_4:%\\w+]] = OpConstantComposite [[v2float]] [[float_4]] [[float_4]]\n" +
  6630. "; CHECK: %2 = OpCopyObject [[v2float]] [[v2float_4_4]]\n" +
  6631. "%main = OpFunction %void None %void_func\n" +
  6632. "%main_lab = OpLabel\n" +
  6633. "%2 = OpVectorTimesScalar %v2float %v2float_2_2 %float_2\n" +
  6634. "OpReturn\n" +
  6635. "OpFunctionEnd",
  6636. 2, true),
  6637. // Test case 19: Fold OpVectorTimesScalar
  6638. // {0,0} = OpVectorTimesScalar v2float v2float_null -1
  6639. InstructionFoldingCase<bool>(
  6640. Header() +
  6641. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  6642. "; CHECK: [[v2float:%\\w+]] = OpTypeVector [[float]] 2\n" +
  6643. "; CHECK: [[v2float_null:%\\w+]] = OpConstantNull [[v2float]]\n" +
  6644. "; CHECK: %2 = OpCopyObject [[v2float]] [[v2float_null]]\n" +
  6645. "%main = OpFunction %void None %void_func\n" +
  6646. "%main_lab = OpLabel\n" +
  6647. "%2 = OpVectorTimesScalar %v2float %v2float_null %float_n1\n" +
  6648. "OpReturn\n" +
  6649. "OpFunctionEnd",
  6650. 2, true),
  6651. // Test case 20: Fold OpVectorTimesScalar
  6652. // {4,4} = OpVectorTimesScalar v2double {2,2} 2
  6653. InstructionFoldingCase<bool>(
  6654. Header() +
  6655. "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
  6656. "; CHECK: [[v2double:%\\w+]] = OpTypeVector [[double]] 2\n" +
  6657. "; CHECK: [[double_4:%\\w+]] = OpConstant [[double]] 4\n" +
  6658. "; CHECK: [[v2double_4_4:%\\w+]] = OpConstantComposite [[v2double]] [[double_4]] [[double_4]]\n" +
  6659. "; CHECK: %2 = OpCopyObject [[v2double]] [[v2double_4_4]]\n" +
  6660. "%main = OpFunction %void None %void_func\n" +
  6661. "%main_lab = OpLabel\n" +
  6662. "%2 = OpVectorTimesScalar %v2double %v2double_2_2 %double_2\n" +
  6663. "OpReturn\n" +
  6664. "OpFunctionEnd",
  6665. 2, true),
  6666. // Test case 21: Fold OpVectorTimesScalar
  6667. // {0,0} = OpVectorTimesScalar v2double {0,0} n
  6668. InstructionFoldingCase<bool>(
  6669. Header() +
  6670. "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
  6671. "; CHECK: [[v2double:%\\w+]] = OpTypeVector [[double]] 2\n" +
  6672. "; CHECK: {{%\\w+}} = OpConstant [[double]] 0\n" +
  6673. "; CHECK: [[double_0:%\\w+]] = OpConstant [[double]] 0\n" +
  6674. "; CHECK: [[v2double_0_0:%\\w+]] = OpConstantComposite [[v2double]] [[double_0]] [[double_0]]\n" +
  6675. "; CHECK: %2 = OpCopyObject [[v2double]] [[v2double_0_0]]\n" +
  6676. "%main = OpFunction %void None %void_func\n" +
  6677. "%main_lab = OpLabel\n" +
  6678. "%n = OpVariable %_ptr_double Function\n" +
  6679. "%load = OpLoad %double %n\n" +
  6680. "%2 = OpVectorTimesScalar %v2double %v2double_0_0 %load\n" +
  6681. "OpReturn\n" +
  6682. "OpFunctionEnd",
  6683. 2, true),
  6684. // Test case 22: Fold OpVectorTimesScalar
  6685. // {0,0} = OpVectorTimesScalar v2double n 0
  6686. InstructionFoldingCase<bool>(
  6687. Header() +
  6688. "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
  6689. "; CHECK: [[v2double:%\\w+]] = OpTypeVector [[double]] 2\n" +
  6690. "; CHECK: [[v2double_null:%\\w+]] = OpConstantNull [[v2double]]\n" +
  6691. "; CHECK: %2 = OpCopyObject [[v2double]] [[v2double_null]]\n" +
  6692. "%main = OpFunction %void None %void_func\n" +
  6693. "%main_lab = OpLabel\n" +
  6694. "%n = OpVariable %_ptr_v2double Function\n" +
  6695. "%load = OpLoad %v2double %n\n" +
  6696. "%2 = OpVectorTimesScalar %v2double %load %double_0\n" +
  6697. "OpReturn\n" +
  6698. "OpFunctionEnd",
  6699. 2, true),
  6700. // Test case 23: merge fmul of fdiv
  6701. // x * (y / x) = y
  6702. InstructionFoldingCase<bool>(
  6703. Header() +
  6704. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  6705. "; CHECK: [[ldx:%\\w+]] = OpLoad [[float]]\n" +
  6706. "; CHECK: [[ldy:%\\w+]] = OpLoad [[float]] [[y:%\\w+]]\n" +
  6707. "; CHECK: %5 = OpCopyObject [[float]] [[ldy]]\n" +
  6708. "%main = OpFunction %void None %void_func\n" +
  6709. "%main_lab = OpLabel\n" +
  6710. "%x = OpVariable %_ptr_float Function\n" +
  6711. "%y = OpVariable %_ptr_float Function\n" +
  6712. "%2 = OpLoad %float %x\n" +
  6713. "%3 = OpLoad %float %y\n" +
  6714. "%4 = OpFDiv %float %3 %2\n" +
  6715. "%5 = OpFMul %float %2 %4\n" +
  6716. "OpReturn\n" +
  6717. "OpFunctionEnd\n",
  6718. 5, true),
  6719. // Test case 24: merge fmul of fdiv
  6720. // (y / x) * x = y
  6721. InstructionFoldingCase<bool>(
  6722. Header() +
  6723. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  6724. "; CHECK: [[ldx:%\\w+]] = OpLoad [[float]]\n" +
  6725. "; CHECK: [[ldy:%\\w+]] = OpLoad [[float]] [[y:%\\w+]]\n" +
  6726. "; CHECK: %5 = OpCopyObject [[float]] [[ldy]]\n" +
  6727. "%main = OpFunction %void None %void_func\n" +
  6728. "%main_lab = OpLabel\n" +
  6729. "%x = OpVariable %_ptr_float Function\n" +
  6730. "%y = OpVariable %_ptr_float Function\n" +
  6731. "%2 = OpLoad %float %x\n" +
  6732. "%3 = OpLoad %float %y\n" +
  6733. "%4 = OpFDiv %float %3 %2\n" +
  6734. "%5 = OpFMul %float %4 %2\n" +
  6735. "OpReturn\n" +
  6736. "OpFunctionEnd\n",
  6737. 5, true),
  6738. // Test case 25: fold overflowing signed 32 bit imuls
  6739. // (x * 1073741824) * 2 = x * int_min
  6740. InstructionFoldingCase<bool>(
  6741. Header() +
  6742. "; CHECK: [[int:%\\w+]] = OpTypeInt 32\n" +
  6743. "; CHECK: [[int_min:%\\w+]] = OpConstant [[int]] -2147483648\n" +
  6744. "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
  6745. "; CHECK: %4 = OpIMul [[int]] [[ld]] [[int_min]]\n" +
  6746. "%main = OpFunction %void None %void_func\n" +
  6747. "%main_lab = OpLabel\n" +
  6748. "%var = OpVariable %_ptr_int Function\n" +
  6749. "%2 = OpLoad %int %var\n" +
  6750. "%3 = OpIMul %int %2 %int_1073741824\n" +
  6751. "%4 = OpIMul %int %3 %int_2\n" +
  6752. "OpReturn\n" +
  6753. "OpFunctionEnd\n",
  6754. 4, true),
  6755. // Test case 26: fold overflowing signed 64 bit imuls
  6756. // (x * 4611686018427387904) * 2 = x * long_min
  6757. InstructionFoldingCase<bool>(
  6758. Header() +
  6759. "; CHECK: [[long:%\\w+]] = OpTypeInt 64\n" +
  6760. "; CHECK: [[long_min:%\\w+]] = OpConstant [[long]] -9223372036854775808\n" +
  6761. "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
  6762. "; CHECK: %4 = OpIMul [[long]] [[ld]] [[long_min]]\n" +
  6763. "%main = OpFunction %void None %void_func\n" +
  6764. "%main_lab = OpLabel\n" +
  6765. "%var = OpVariable %_ptr_long Function\n" +
  6766. "%2 = OpLoad %long %var\n" +
  6767. "%3 = OpIMul %long %2 %long_4611686018427387904\n" +
  6768. "%4 = OpIMul %long %3 %long_2\n" +
  6769. "OpReturn\n" +
  6770. "OpFunctionEnd\n",
  6771. 4, true),
  6772. // Test case 27: fold overflowing 32 bit unsigned imuls
  6773. // (x * 2147483649) * 2 = x * 2
  6774. InstructionFoldingCase<bool>(
  6775. Header() +
  6776. "; CHECK: [[uint:%\\w+]] = OpTypeInt 32 0\n" +
  6777. "; CHECK: [[uint_2:%\\w+]] = OpConstant [[uint]] 2\n" +
  6778. "; CHECK: [[ld:%\\w+]] = OpLoad [[uint]]\n" +
  6779. "; CHECK: %4 = OpIMul [[uint]] [[ld]] [[uint_2]]\n" +
  6780. "%main = OpFunction %void None %void_func\n" +
  6781. "%main_lab = OpLabel\n" +
  6782. "%var = OpVariable %_ptr_uint Function\n" +
  6783. "%2 = OpLoad %uint %var\n" +
  6784. "%3 = OpIMul %uint %2 %uint_2147483649\n" +
  6785. "%4 = OpIMul %uint %3 %uint_2\n" +
  6786. "OpReturn\n" +
  6787. "OpFunctionEnd\n",
  6788. 4, true),
  6789. // Test case 28: fold overflowing 64 bit unsigned imuls
  6790. // (x * 9223372036854775809) * 2 = x * 2
  6791. InstructionFoldingCase<bool>(
  6792. Header() +
  6793. "; CHECK: [[ulong:%\\w+]] = OpTypeInt 64 0\n" +
  6794. "; CHECK: [[ulong_2:%\\w+]] = OpConstant [[ulong]] 2\n" +
  6795. "; CHECK: [[ld:%\\w+]] = OpLoad [[ulong]]\n" +
  6796. "; CHECK: %4 = OpIMul [[ulong]] [[ld]] [[ulong_2]]\n" +
  6797. "%main = OpFunction %void None %void_func\n" +
  6798. "%main_lab = OpLabel\n" +
  6799. "%var = OpVariable %_ptr_ulong Function\n" +
  6800. "%2 = OpLoad %ulong %var\n" +
  6801. "%3 = OpIMul %ulong %2 %ulong_9223372036854775809\n" +
  6802. "%4 = OpIMul %ulong %3 %ulong_2\n" +
  6803. "OpReturn\n" +
  6804. "OpFunctionEnd\n",
  6805. 4, true),
  6806. // Test case 29: fold underflowing signed 32 bit imuls
  6807. // (x * (-858993459)) * 10 = x * 2
  6808. InstructionFoldingCase<bool>(
  6809. Header() +
  6810. "; CHECK: [[int:%\\w+]] = OpTypeInt 32\n" +
  6811. "; CHECK: [[int_2:%\\w+]] = OpConstant [[int]] 2\n" +
  6812. "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
  6813. "; CHECK: %4 = OpIMul [[int]] [[ld]] [[int_2]]\n" +
  6814. "%main = OpFunction %void None %void_func\n" +
  6815. "%main_lab = OpLabel\n" +
  6816. "%var = OpVariable %_ptr_int Function\n" +
  6817. "%2 = OpLoad %int %var\n" +
  6818. "%3 = OpIMul %int %2 %int_n858993459\n" +
  6819. "%4 = OpIMul %int %3 %int_10\n" +
  6820. "OpReturn\n" +
  6821. "OpFunctionEnd\n",
  6822. 4, true),
  6823. // Test case 30: fold underflowing signed 64 bit imuls
  6824. // (x * (-3689348814741910323)) * 10 = x * 2
  6825. InstructionFoldingCase<bool>(
  6826. Header() +
  6827. "; CHECK: [[long:%\\w+]] = OpTypeInt 64\n" +
  6828. "; CHECK: [[long_2:%\\w+]] = OpConstant [[long]] 2\n" +
  6829. "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
  6830. "; CHECK: %4 = OpIMul [[long]] [[ld]] [[long_2]]\n" +
  6831. "%main = OpFunction %void None %void_func\n" +
  6832. "%main_lab = OpLabel\n" +
  6833. "%var = OpVariable %_ptr_long Function\n" +
  6834. "%2 = OpLoad %long %var\n" +
  6835. "%3 = OpIMul %long %2 %long_n3689348814741910323\n" +
  6836. "%4 = OpIMul %long %3 %long_10\n" +
  6837. "OpReturn\n" +
  6838. "OpFunctionEnd\n",
  6839. 4, true)
  6840. ));
  6841. INSTANTIATE_TEST_SUITE_P(MergeDivTest, MatchingInstructionFoldingTest,
  6842. ::testing::Values(
  6843. // Test case 0: merge consecutive fdiv
  6844. // 4.0 / (2.0 / x) = 2.0 * x
  6845. InstructionFoldingCase<bool>(
  6846. Header() +
  6847. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  6848. "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
  6849. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  6850. "; CHECK: %4 = OpFMul [[float]] [[float_2]] [[ld]]\n" +
  6851. "%main = OpFunction %void None %void_func\n" +
  6852. "%main_lab = OpLabel\n" +
  6853. "%var = OpVariable %_ptr_float Function\n" +
  6854. "%2 = OpLoad %float %var\n" +
  6855. "%3 = OpFDiv %float %float_2 %2\n" +
  6856. "%4 = OpFDiv %float %float_4 %3\n" +
  6857. "OpReturn\n" +
  6858. "OpFunctionEnd\n",
  6859. 4, true),
  6860. // Test case 1: merge consecutive fdiv
  6861. // 4.0 / (x / 2.0) = 8.0 / x
  6862. InstructionFoldingCase<bool>(
  6863. Header() +
  6864. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  6865. "; CHECK: [[float_8:%\\w+]] = OpConstant [[float]] 8\n" +
  6866. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  6867. "; CHECK: %4 = OpFDiv [[float]] [[float_8]] [[ld]]\n" +
  6868. "%main = OpFunction %void None %void_func\n" +
  6869. "%main_lab = OpLabel\n" +
  6870. "%var = OpVariable %_ptr_float Function\n" +
  6871. "%2 = OpLoad %float %var\n" +
  6872. "%3 = OpFDiv %float %2 %float_2\n" +
  6873. "%4 = OpFDiv %float %float_4 %3\n" +
  6874. "OpReturn\n" +
  6875. "OpFunctionEnd\n",
  6876. 4, true),
  6877. // Test case 2: merge consecutive fdiv
  6878. // (4.0 / x) / 2.0 = 2.0 / x
  6879. InstructionFoldingCase<bool>(
  6880. Header() +
  6881. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  6882. "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
  6883. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  6884. "; CHECK: %4 = OpFDiv [[float]] [[float_2]] [[ld]]\n" +
  6885. "%main = OpFunction %void None %void_func\n" +
  6886. "%main_lab = OpLabel\n" +
  6887. "%var = OpVariable %_ptr_float Function\n" +
  6888. "%2 = OpLoad %float %var\n" +
  6889. "%3 = OpFDiv %float %float_4 %2\n" +
  6890. "%4 = OpFDiv %float %3 %float_2\n" +
  6891. "OpReturn\n" +
  6892. "OpFunctionEnd\n",
  6893. 4, true),
  6894. // Test case 3: Do not merge consecutive sdiv
  6895. // 4 / (2 / x)
  6896. InstructionFoldingCase<bool>(
  6897. Header() +
  6898. "%main = OpFunction %void None %void_func\n" +
  6899. "%main_lab = OpLabel\n" +
  6900. "%var = OpVariable %_ptr_int Function\n" +
  6901. "%2 = OpLoad %int %var\n" +
  6902. "%3 = OpSDiv %int %int_2 %2\n" +
  6903. "%4 = OpSDiv %int %int_4 %3\n" +
  6904. "OpReturn\n" +
  6905. "OpFunctionEnd\n",
  6906. 4, false),
  6907. // Test case 4: Do not merge consecutive sdiv
  6908. // 4 / (x / 2)
  6909. InstructionFoldingCase<bool>(
  6910. Header() +
  6911. "%main = OpFunction %void None %void_func\n" +
  6912. "%main_lab = OpLabel\n" +
  6913. "%var = OpVariable %_ptr_int Function\n" +
  6914. "%2 = OpLoad %int %var\n" +
  6915. "%3 = OpSDiv %int %2 %int_2\n" +
  6916. "%4 = OpSDiv %int %int_4 %3\n" +
  6917. "OpReturn\n" +
  6918. "OpFunctionEnd\n",
  6919. 4, false),
  6920. // Test case 5: Do not merge consecutive sdiv
  6921. // (4 / x) / 2
  6922. InstructionFoldingCase<bool>(
  6923. Header() +
  6924. "%main = OpFunction %void None %void_func\n" +
  6925. "%main_lab = OpLabel\n" +
  6926. "%var = OpVariable %_ptr_int Function\n" +
  6927. "%2 = OpLoad %int %var\n" +
  6928. "%3 = OpSDiv %int %int_4 %2\n" +
  6929. "%4 = OpSDiv %int %3 %int_2\n" +
  6930. "OpReturn\n" +
  6931. "OpFunctionEnd\n",
  6932. 4, false),
  6933. // Test case 6: Do not merge consecutive sdiv
  6934. // (x / 4) / 2
  6935. InstructionFoldingCase<bool>(
  6936. Header() +
  6937. "%main = OpFunction %void None %void_func\n" +
  6938. "%main_lab = OpLabel\n" +
  6939. "%var = OpVariable %_ptr_int Function\n" +
  6940. "%2 = OpLoad %int %var\n" +
  6941. "%3 = OpSDiv %int %2 %int_4\n" +
  6942. "%4 = OpSDiv %int %3 %int_2\n" +
  6943. "OpReturn\n" +
  6944. "OpFunctionEnd\n",
  6945. 4, false),
  6946. // Test case 7: Do not merge sdiv of imul
  6947. // 4 / (2 * x)
  6948. InstructionFoldingCase<bool>(
  6949. Header() +
  6950. "%main = OpFunction %void None %void_func\n" +
  6951. "%main_lab = OpLabel\n" +
  6952. "%var = OpVariable %_ptr_int Function\n" +
  6953. "%2 = OpLoad %int %var\n" +
  6954. "%3 = OpIMul %int %int_2 %2\n" +
  6955. "%4 = OpSDiv %int %int_4 %3\n" +
  6956. "OpReturn\n" +
  6957. "OpFunctionEnd\n",
  6958. 4, false),
  6959. // Test case 8: Do not merge sdiv of imul
  6960. // 4 / (x * 2)
  6961. InstructionFoldingCase<bool>(
  6962. Header() +
  6963. "%main = OpFunction %void None %void_func\n" +
  6964. "%main_lab = OpLabel\n" +
  6965. "%var = OpVariable %_ptr_int Function\n" +
  6966. "%2 = OpLoad %int %var\n" +
  6967. "%3 = OpIMul %int %2 %int_2\n" +
  6968. "%4 = OpSDiv %int %int_4 %3\n" +
  6969. "OpReturn\n" +
  6970. "OpFunctionEnd\n",
  6971. 4, false),
  6972. // Test case 9: Do not merge sdiv of imul
  6973. // (4 * x) / 2
  6974. InstructionFoldingCase<bool>(
  6975. Header() +
  6976. "%main = OpFunction %void None %void_func\n" +
  6977. "%main_lab = OpLabel\n" +
  6978. "%var = OpVariable %_ptr_int Function\n" +
  6979. "%2 = OpLoad %int %var\n" +
  6980. "%3 = OpIMul %int %int_4 %2\n" +
  6981. "%4 = OpSDiv %int %3 %int_2\n" +
  6982. "OpReturn\n" +
  6983. "OpFunctionEnd\n",
  6984. 4, false),
  6985. // Test case 10: Do not merge sdiv of imul
  6986. // (x * 4) / 2
  6987. InstructionFoldingCase<bool>(
  6988. Header() +
  6989. "%main = OpFunction %void None %void_func\n" +
  6990. "%main_lab = OpLabel\n" +
  6991. "%var = OpVariable %_ptr_int Function\n" +
  6992. "%2 = OpLoad %int %var\n" +
  6993. "%3 = OpIMul %int %2 %int_4\n" +
  6994. "%4 = OpSDiv %int %3 %int_2\n" +
  6995. "OpReturn\n" +
  6996. "OpFunctionEnd\n",
  6997. 4, false),
  6998. // Test case 11: Do not merge sdiv of snegate. If %2 is INT_MIN, then the
  6999. // sign of %3 will be the same as %2. This cannot be accounted for in OpSDiv.
  7000. // Specifically, (-INT_MIN) / 2 != INT_MIN / -2.
  7001. InstructionFoldingCase<bool>(
  7002. Header() +
  7003. "%main = OpFunction %void None %void_func\n" +
  7004. "%main_lab = OpLabel\n" +
  7005. "%var = OpVariable %_ptr_int Function\n" +
  7006. "%2 = OpLoad %int %var\n" +
  7007. "%3 = OpSNegate %int %2\n" +
  7008. "%4 = OpSDiv %int %3 %int_2\n" +
  7009. "OpReturn\n" +
  7010. "OpFunctionEnd\n",
  7011. 4, false),
  7012. // Test case 12: Do not merge sdiv of snegate. If %2 is INT_MIN, then the
  7013. // sign of %3 will be the same as %2. This cannot be accounted for in OpSDiv.
  7014. // Specifically, 2 / (-INT_MIN) != -2 / INT_MIN.
  7015. InstructionFoldingCase<bool>(
  7016. Header() +
  7017. "%main = OpFunction %void None %void_func\n" +
  7018. "%main_lab = OpLabel\n" +
  7019. "%var = OpVariable %_ptr_int Function\n" +
  7020. "%2 = OpLoad %int %var\n" +
  7021. "%3 = OpSNegate %int %2\n" +
  7022. "%4 = OpSDiv %int %int_2 %3\n" +
  7023. "OpReturn\n" +
  7024. "OpFunctionEnd\n",
  7025. 4, false),
  7026. // Test case 13: Don't merge
  7027. // (x / {null}) / {null}
  7028. InstructionFoldingCase<bool>(
  7029. Header() +
  7030. "%main = OpFunction %void None %void_func\n" +
  7031. "%main_lab = OpLabel\n" +
  7032. "%var = OpVariable %_ptr_v2float Function\n" +
  7033. "%2 = OpLoad %float %var\n" +
  7034. "%3 = OpFDiv %float %2 %v2float_null\n" +
  7035. "%4 = OpFDiv %float %3 %v2float_null\n" +
  7036. "OpReturn\n" +
  7037. "OpFunctionEnd\n",
  7038. 4, false),
  7039. // Test case 14: merge fmul of fdiv
  7040. // (y * x) / x = y
  7041. InstructionFoldingCase<bool>(
  7042. Header() +
  7043. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  7044. "; CHECK: [[ldx:%\\w+]] = OpLoad [[float]]\n" +
  7045. "; CHECK: [[ldy:%\\w+]] = OpLoad [[float]] [[y:%\\w+]]\n" +
  7046. "; CHECK: %5 = OpCopyObject [[float]] [[ldy]]\n" +
  7047. "%main = OpFunction %void None %void_func\n" +
  7048. "%main_lab = OpLabel\n" +
  7049. "%x = OpVariable %_ptr_float Function\n" +
  7050. "%y = OpVariable %_ptr_float Function\n" +
  7051. "%2 = OpLoad %float %x\n" +
  7052. "%3 = OpLoad %float %y\n" +
  7053. "%4 = OpFMul %float %3 %2\n" +
  7054. "%5 = OpFDiv %float %4 %2\n" +
  7055. "OpReturn\n" +
  7056. "OpFunctionEnd\n",
  7057. 5, true),
  7058. // Test case 15: merge fmul of fdiv
  7059. // (x * y) / x = y
  7060. InstructionFoldingCase<bool>(
  7061. Header() +
  7062. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  7063. "; CHECK: [[ldx:%\\w+]] = OpLoad [[float]]\n" +
  7064. "; CHECK: [[ldy:%\\w+]] = OpLoad [[float]] [[y:%\\w+]]\n" +
  7065. "; CHECK: %5 = OpCopyObject [[float]] [[ldy]]\n" +
  7066. "%main = OpFunction %void None %void_func\n" +
  7067. "%main_lab = OpLabel\n" +
  7068. "%x = OpVariable %_ptr_float Function\n" +
  7069. "%y = OpVariable %_ptr_float Function\n" +
  7070. "%2 = OpLoad %float %x\n" +
  7071. "%3 = OpLoad %float %y\n" +
  7072. "%4 = OpFMul %float %2 %3\n" +
  7073. "%5 = OpFDiv %float %4 %2\n" +
  7074. "OpReturn\n" +
  7075. "OpFunctionEnd\n",
  7076. 5, true),
  7077. // Test case 16: Do not merge udiv of snegate
  7078. // (-x) / 2u
  7079. InstructionFoldingCase<bool>(
  7080. Header() +
  7081. "%main = OpFunction %void None %void_func\n" +
  7082. "%main_lab = OpLabel\n" +
  7083. "%var = OpVariable %_ptr_uint Function\n" +
  7084. "%2 = OpLoad %uint %var\n" +
  7085. "%3 = OpSNegate %uint %2\n" +
  7086. "%4 = OpUDiv %uint %3 %uint_2\n" +
  7087. "OpReturn\n" +
  7088. "OpFunctionEnd\n",
  7089. 4, false),
  7090. // Test case 17: Do not merge udiv of snegate
  7091. // 2u / (-x)
  7092. InstructionFoldingCase<bool>(
  7093. Header() +
  7094. "%main = OpFunction %void None %void_func\n" +
  7095. "%main_lab = OpLabel\n" +
  7096. "%var = OpVariable %_ptr_uint Function\n" +
  7097. "%2 = OpLoad %uint %var\n" +
  7098. "%3 = OpSNegate %uint %2\n" +
  7099. "%4 = OpUDiv %uint %uint_2 %3\n" +
  7100. "OpReturn\n" +
  7101. "OpFunctionEnd\n",
  7102. 4, false)
  7103. ));
  7104. INSTANTIATE_TEST_SUITE_P(MergeAddTest, MatchingInstructionFoldingTest,
  7105. ::testing::Values(
  7106. // Test case 0: merge add of negate
  7107. // (-x) + 2 = 2 - x
  7108. InstructionFoldingCase<bool>(
  7109. Header() +
  7110. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  7111. "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
  7112. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  7113. "; CHECK: %4 = OpFSub [[float]] [[float_2]] [[ld]]\n" +
  7114. "%main = OpFunction %void None %void_func\n" +
  7115. "%main_lab = OpLabel\n" +
  7116. "%var = OpVariable %_ptr_float Function\n" +
  7117. "%2 = OpLoad %float %var\n" +
  7118. "%3 = OpFNegate %float %2\n" +
  7119. "%4 = OpFAdd %float %3 %float_2\n" +
  7120. "OpReturn\n" +
  7121. "OpFunctionEnd\n",
  7122. 4, true),
  7123. // Test case 1: merge add of negate
  7124. // 2 + (-x) = 2 - x
  7125. InstructionFoldingCase<bool>(
  7126. Header() +
  7127. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  7128. "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
  7129. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  7130. "; CHECK: %4 = OpFSub [[float]] [[float_2]] [[ld]]\n" +
  7131. "%main = OpFunction %void None %void_func\n" +
  7132. "%main_lab = OpLabel\n" +
  7133. "%var = OpVariable %_ptr_float Function\n" +
  7134. "%2 = OpLoad %float %var\n" +
  7135. "%3 = OpSNegate %float %2\n" +
  7136. "%4 = OpIAdd %float %float_2 %3\n" +
  7137. "OpReturn\n" +
  7138. "OpFunctionEnd\n",
  7139. 4, true),
  7140. // Test case 2: merge add of negate
  7141. // (-x) + 2 = 2 - x
  7142. InstructionFoldingCase<bool>(
  7143. Header() +
  7144. "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
  7145. "; CHECK: [[long_2:%\\w+]] = OpConstant [[long]] 2\n" +
  7146. "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
  7147. "; CHECK: %4 = OpISub [[long]] [[long_2]] [[ld]]\n" +
  7148. "%main = OpFunction %void None %void_func\n" +
  7149. "%main_lab = OpLabel\n" +
  7150. "%var = OpVariable %_ptr_long Function\n" +
  7151. "%2 = OpLoad %long %var\n" +
  7152. "%3 = OpSNegate %long %2\n" +
  7153. "%4 = OpIAdd %long %3 %long_2\n" +
  7154. "OpReturn\n" +
  7155. "OpFunctionEnd\n",
  7156. 4, true),
  7157. // Test case 3: merge add of negate
  7158. // 2 + (-x) = 2 - x
  7159. InstructionFoldingCase<bool>(
  7160. Header() +
  7161. "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
  7162. "; CHECK: [[long_2:%\\w+]] = OpConstant [[long]] 2\n" +
  7163. "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
  7164. "; CHECK: %4 = OpISub [[long]] [[long_2]] [[ld]]\n" +
  7165. "%main = OpFunction %void None %void_func\n" +
  7166. "%main_lab = OpLabel\n" +
  7167. "%var = OpVariable %_ptr_long Function\n" +
  7168. "%2 = OpLoad %long %var\n" +
  7169. "%3 = OpSNegate %long %2\n" +
  7170. "%4 = OpIAdd %long %long_2 %3\n" +
  7171. "OpReturn\n" +
  7172. "OpFunctionEnd\n",
  7173. 4, true),
  7174. // Test case 4: merge add of subtract
  7175. // (x - 1) + 2 = x + 1
  7176. InstructionFoldingCase<bool>(
  7177. Header() +
  7178. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  7179. "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
  7180. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  7181. "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_1]]\n" +
  7182. "%main = OpFunction %void None %void_func\n" +
  7183. "%main_lab = OpLabel\n" +
  7184. "%var = OpVariable %_ptr_float Function\n" +
  7185. "%2 = OpLoad %float %var\n" +
  7186. "%3 = OpFSub %float %2 %float_1\n" +
  7187. "%4 = OpFAdd %float %3 %float_2\n" +
  7188. "OpReturn\n" +
  7189. "OpFunctionEnd\n",
  7190. 4, true),
  7191. // Test case 5: merge add of subtract
  7192. // (1 - x) + 2 = 3 - x
  7193. InstructionFoldingCase<bool>(
  7194. Header() +
  7195. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  7196. "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
  7197. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  7198. "; CHECK: %4 = OpFSub [[float]] [[float_3]] [[ld]]\n" +
  7199. "%main = OpFunction %void None %void_func\n" +
  7200. "%main_lab = OpLabel\n" +
  7201. "%var = OpVariable %_ptr_float Function\n" +
  7202. "%2 = OpLoad %float %var\n" +
  7203. "%3 = OpFSub %float %float_1 %2\n" +
  7204. "%4 = OpFAdd %float %3 %float_2\n" +
  7205. "OpReturn\n" +
  7206. "OpFunctionEnd\n",
  7207. 4, true),
  7208. // Test case 6: merge add of subtract
  7209. // 2 + (x - 1) = x + 1
  7210. InstructionFoldingCase<bool>(
  7211. Header() +
  7212. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  7213. "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
  7214. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  7215. "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_1]]\n" +
  7216. "%main = OpFunction %void None %void_func\n" +
  7217. "%main_lab = OpLabel\n" +
  7218. "%var = OpVariable %_ptr_float Function\n" +
  7219. "%2 = OpLoad %float %var\n" +
  7220. "%3 = OpFSub %float %2 %float_1\n" +
  7221. "%4 = OpFAdd %float %float_2 %3\n" +
  7222. "OpReturn\n" +
  7223. "OpFunctionEnd\n",
  7224. 4, true),
  7225. // Test case 7: merge add of subtract
  7226. // 2 + (1 - x) = 3 - x
  7227. InstructionFoldingCase<bool>(
  7228. Header() +
  7229. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  7230. "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
  7231. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  7232. "; CHECK: %4 = OpFSub [[float]] [[float_3]] [[ld]]\n" +
  7233. "%main = OpFunction %void None %void_func\n" +
  7234. "%main_lab = OpLabel\n" +
  7235. "%var = OpVariable %_ptr_float Function\n" +
  7236. "%2 = OpLoad %float %var\n" +
  7237. "%3 = OpFSub %float %float_1 %2\n" +
  7238. "%4 = OpFAdd %float %float_2 %3\n" +
  7239. "OpReturn\n" +
  7240. "OpFunctionEnd\n",
  7241. 4, true),
  7242. // Test case 8: merge add of add
  7243. // (x + 1) + 2 = x + 3
  7244. InstructionFoldingCase<bool>(
  7245. Header() +
  7246. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  7247. "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
  7248. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  7249. "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_3]]\n" +
  7250. "%main = OpFunction %void None %void_func\n" +
  7251. "%main_lab = OpLabel\n" +
  7252. "%var = OpVariable %_ptr_float Function\n" +
  7253. "%2 = OpLoad %float %var\n" +
  7254. "%3 = OpFAdd %float %2 %float_1\n" +
  7255. "%4 = OpFAdd %float %3 %float_2\n" +
  7256. "OpReturn\n" +
  7257. "OpFunctionEnd\n",
  7258. 4, true),
  7259. // Test case 9: merge add of add
  7260. // (1 + x) + 2 = 3 + x
  7261. InstructionFoldingCase<bool>(
  7262. Header() +
  7263. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  7264. "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
  7265. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  7266. "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_3]]\n" +
  7267. "%main = OpFunction %void None %void_func\n" +
  7268. "%main_lab = OpLabel\n" +
  7269. "%var = OpVariable %_ptr_float Function\n" +
  7270. "%2 = OpLoad %float %var\n" +
  7271. "%3 = OpFAdd %float %float_1 %2\n" +
  7272. "%4 = OpFAdd %float %3 %float_2\n" +
  7273. "OpReturn\n" +
  7274. "OpFunctionEnd\n",
  7275. 4, true),
  7276. // Test case 10: merge add of add
  7277. // 2 + (x + 1) = x + 1
  7278. InstructionFoldingCase<bool>(
  7279. Header() +
  7280. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  7281. "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
  7282. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  7283. "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_3]]\n" +
  7284. "%main = OpFunction %void None %void_func\n" +
  7285. "%main_lab = OpLabel\n" +
  7286. "%var = OpVariable %_ptr_float Function\n" +
  7287. "%2 = OpLoad %float %var\n" +
  7288. "%3 = OpFAdd %float %2 %float_1\n" +
  7289. "%4 = OpFAdd %float %float_2 %3\n" +
  7290. "OpReturn\n" +
  7291. "OpFunctionEnd\n",
  7292. 4, true),
  7293. // Test case 11: merge add of add
  7294. // 2 + (1 + x) = 3 - x
  7295. InstructionFoldingCase<bool>(
  7296. Header() +
  7297. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  7298. "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
  7299. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  7300. "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_3]]\n" +
  7301. "%main = OpFunction %void None %void_func\n" +
  7302. "%main_lab = OpLabel\n" +
  7303. "%var = OpVariable %_ptr_float Function\n" +
  7304. "%2 = OpLoad %float %var\n" +
  7305. "%3 = OpFAdd %float %float_1 %2\n" +
  7306. "%4 = OpFAdd %float %float_2 %3\n" +
  7307. "OpReturn\n" +
  7308. "OpFunctionEnd\n",
  7309. 4, true),
  7310. // Test case 12: fold overflowing signed 32 bit iadds
  7311. // (x + int_max) + 1 = x + int_min
  7312. InstructionFoldingCase<bool>(
  7313. Header() +
  7314. "; CHECK: [[int:%\\w+]] = OpTypeInt 32\n" +
  7315. "; CHECK: [[int_min:%\\w+]] = OpConstant [[int]] -2147483648\n" +
  7316. "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
  7317. "; CHECK: %4 = OpIAdd [[int]] [[ld]] [[int_min]]\n" +
  7318. "%main = OpFunction %void None %void_func\n" +
  7319. "%main_lab = OpLabel\n" +
  7320. "%var = OpVariable %_ptr_int Function\n" +
  7321. "%2 = OpLoad %int %var\n" +
  7322. "%3 = OpIAdd %int %2 %int_max\n" +
  7323. "%4 = OpIAdd %int %3 %int_1\n" +
  7324. "OpReturn\n" +
  7325. "OpFunctionEnd\n",
  7326. 4, true),
  7327. // Test case 13: fold overflowing signed 64 bit iadds
  7328. // (x + long_max) + 1 = x + long_min
  7329. InstructionFoldingCase<bool>(
  7330. Header() +
  7331. "; CHECK: [[long:%\\w+]] = OpTypeInt 64\n" +
  7332. "; CHECK: [[long_min:%\\w+]] = OpConstant [[long]] -9223372036854775808\n" +
  7333. "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
  7334. "; CHECK: %4 = OpIAdd [[long]] [[ld]] [[long_min]]\n" +
  7335. "%main = OpFunction %void None %void_func\n" +
  7336. "%main_lab = OpLabel\n" +
  7337. "%var = OpVariable %_ptr_long Function\n" +
  7338. "%2 = OpLoad %long %var\n" +
  7339. "%3 = OpIAdd %long %2 %long_max\n" +
  7340. "%4 = OpIAdd %long %3 %long_1\n" +
  7341. "OpReturn\n" +
  7342. "OpFunctionEnd\n",
  7343. 4, true),
  7344. // Test case 14: fold overflowing 32 bit unsigned iadds
  7345. // (x + uint_max) + 2 = x + 1
  7346. InstructionFoldingCase<bool>(
  7347. Header() +
  7348. "; CHECK: [[uint:%\\w+]] = OpTypeInt 32 0\n" +
  7349. "; CHECK: [[uint_1:%\\w+]] = OpConstant [[uint]] 1\n" +
  7350. "; CHECK: [[ld:%\\w+]] = OpLoad [[uint]]\n" +
  7351. "; CHECK: %4 = OpIAdd [[uint]] [[ld]] [[uint_1]]\n" +
  7352. "%main = OpFunction %void None %void_func\n" +
  7353. "%main_lab = OpLabel\n" +
  7354. "%var = OpVariable %_ptr_uint Function\n" +
  7355. "%2 = OpLoad %uint %var\n" +
  7356. "%3 = OpIAdd %uint %2 %uint_max\n" +
  7357. "%4 = OpIAdd %uint %3 %uint_2\n" +
  7358. "OpReturn\n" +
  7359. "OpFunctionEnd\n",
  7360. 4, true),
  7361. // Test case 15: fold overflowing 64 bit unsigned iadds
  7362. // (x + ulong_max) + 2 = x + 1
  7363. InstructionFoldingCase<bool>(
  7364. Header() +
  7365. "; CHECK: [[ulong:%\\w+]] = OpTypeInt 64 0\n" +
  7366. "; CHECK: [[ulong_1:%\\w+]] = OpConstant [[ulong]] 1\n" +
  7367. "; CHECK: [[ld:%\\w+]] = OpLoad [[ulong]]\n" +
  7368. "; CHECK: %4 = OpIAdd [[ulong]] [[ld]] [[ulong_1]]\n" +
  7369. "%main = OpFunction %void None %void_func\n" +
  7370. "%main_lab = OpLabel\n" +
  7371. "%var = OpVariable %_ptr_ulong Function\n" +
  7372. "%2 = OpLoad %ulong %var\n" +
  7373. "%3 = OpIAdd %ulong %2 %ulong_max\n" +
  7374. "%4 = OpIAdd %ulong %3 %ulong_2\n" +
  7375. "OpReturn\n" +
  7376. "OpFunctionEnd\n",
  7377. 4, true),
  7378. // Test case 16: fold underflowing signed 32 bit iadds
  7379. // (x + int_min) + (-1) = x + int_max
  7380. InstructionFoldingCase<bool>(
  7381. Header() +
  7382. "; CHECK: [[int:%\\w+]] = OpTypeInt 32\n" +
  7383. "; CHECK: [[int_max:%\\w+]] = OpConstant [[int]] 2147483647\n" +
  7384. "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
  7385. "; CHECK: %4 = OpIAdd [[int]] [[ld]] [[int_max]]\n" +
  7386. "%main = OpFunction %void None %void_func\n" +
  7387. "%main_lab = OpLabel\n" +
  7388. "%var = OpVariable %_ptr_int Function\n" +
  7389. "%2 = OpLoad %int %var\n" +
  7390. "%3 = OpIAdd %int %2 %int_min\n" +
  7391. "%4 = OpIAdd %int %3 %int_n1\n" +
  7392. "OpReturn\n" +
  7393. "OpFunctionEnd\n",
  7394. 4, true),
  7395. // Test case 17: fold underflowing signed 64 bit iadds
  7396. // (x + long_min) + (-1) = x + long_max
  7397. InstructionFoldingCase<bool>(
  7398. Header() +
  7399. "; CHECK: [[long:%\\w+]] = OpTypeInt 64\n" +
  7400. "; CHECK: [[long_max:%\\w+]] = OpConstant [[long]] 9223372036854775807\n" +
  7401. "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
  7402. "; CHECK: %4 = OpIAdd [[long]] [[ld]] [[long_max]]\n" +
  7403. "%main = OpFunction %void None %void_func\n" +
  7404. "%main_lab = OpLabel\n" +
  7405. "%var = OpVariable %_ptr_long Function\n" +
  7406. "%2 = OpLoad %long %var\n" +
  7407. "%3 = OpIAdd %long %2 %long_min\n" +
  7408. "%4 = OpIAdd %long %3 %long_n1\n" +
  7409. "OpReturn\n" +
  7410. "OpFunctionEnd\n",
  7411. 4, true)
  7412. ));
  7413. INSTANTIATE_TEST_SUITE_P(MergeGenericAddSub, MatchingInstructionFoldingTest,
  7414. ::testing::Values(
  7415. // Test case 0: merge of add of sub
  7416. // (a - b) + b => a
  7417. InstructionFoldingCase<bool>(
  7418. Header() +
  7419. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  7420. "; CHECK: %6 = OpCopyObject [[float]] %3\n" +
  7421. "%main = OpFunction %void None %void_func\n" +
  7422. "%main_lab = OpLabel\n" +
  7423. "%var0 = OpVariable %_ptr_float Function\n" +
  7424. "%var1 = OpVariable %_ptr_float Function\n" +
  7425. "%3 = OpLoad %float %var0\n" +
  7426. "%4 = OpLoad %float %var1\n" +
  7427. "%5 = OpFSub %float %3 %4\n" +
  7428. "%6 = OpFAdd %float %5 %4\n" +
  7429. "OpReturn\n" +
  7430. "OpFunctionEnd\n",
  7431. 6, true),
  7432. // Test case 1: merge of add of sub
  7433. // b + (a - b) => a
  7434. InstructionFoldingCase<bool>(
  7435. Header() +
  7436. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  7437. "; CHECK: %6 = OpCopyObject [[float]] %3\n" +
  7438. "%main = OpFunction %void None %void_func\n" +
  7439. "%main_lab = OpLabel\n" +
  7440. "%var0 = OpVariable %_ptr_float Function\n" +
  7441. "%var1 = OpVariable %_ptr_float Function\n" +
  7442. "%3 = OpLoad %float %var0\n" +
  7443. "%4 = OpLoad %float %var1\n" +
  7444. "%5 = OpFSub %float %3 %4\n" +
  7445. "%6 = OpFAdd %float %4 %5\n" +
  7446. "OpReturn\n" +
  7447. "OpFunctionEnd\n",
  7448. 6, true)
  7449. ));
  7450. INSTANTIATE_TEST_SUITE_P(FactorAddMul, MatchingInstructionFoldingTest,
  7451. ::testing::Values(
  7452. // Test case 0: factor of add of muls
  7453. // (a * b) + (a * c) => a * (b + c)
  7454. InstructionFoldingCase<bool>(
  7455. Header() +
  7456. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  7457. "; CHECK: [[newadd:%\\w+]] = OpFAdd [[float]] %4 %5\n" +
  7458. "; CHECK: %9 = OpFMul [[float]] %6 [[newadd]]\n" +
  7459. "%main = OpFunction %void None %void_func\n" +
  7460. "%main_lab = OpLabel\n" +
  7461. "%var0 = OpVariable %_ptr_float Function\n" +
  7462. "%var1 = OpVariable %_ptr_float Function\n" +
  7463. "%var2 = OpVariable %_ptr_float Function\n" +
  7464. "%4 = OpLoad %float %var0\n" +
  7465. "%5 = OpLoad %float %var1\n" +
  7466. "%6 = OpLoad %float %var2\n" +
  7467. "%7 = OpFMul %float %6 %4\n" +
  7468. "%8 = OpFMul %float %6 %5\n" +
  7469. "%9 = OpFAdd %float %7 %8\n" +
  7470. "OpReturn\n" +
  7471. "OpFunctionEnd\n",
  7472. 9, true),
  7473. // Test case 1: factor of add of muls
  7474. // (b * a) + (a * c) => a * (b + c)
  7475. InstructionFoldingCase<bool>(
  7476. Header() +
  7477. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  7478. "; CHECK: [[newadd:%\\w+]] = OpFAdd [[float]] %4 %5\n" +
  7479. "; CHECK: %9 = OpFMul [[float]] %6 [[newadd]]\n" +
  7480. "%main = OpFunction %void None %void_func\n" +
  7481. "%main_lab = OpLabel\n" +
  7482. "%var0 = OpVariable %_ptr_float Function\n" +
  7483. "%var1 = OpVariable %_ptr_float Function\n" +
  7484. "%var2 = OpVariable %_ptr_float Function\n" +
  7485. "%4 = OpLoad %float %var0\n" +
  7486. "%5 = OpLoad %float %var1\n" +
  7487. "%6 = OpLoad %float %var2\n" +
  7488. "%7 = OpFMul %float %4 %6\n" +
  7489. "%8 = OpFMul %float %6 %5\n" +
  7490. "%9 = OpFAdd %float %7 %8\n" +
  7491. "OpReturn\n" +
  7492. "OpFunctionEnd\n",
  7493. 9, true),
  7494. // Test case 2: factor of add of muls
  7495. // (a * b) + (c * a) => a * (b + c)
  7496. InstructionFoldingCase<bool>(
  7497. Header() +
  7498. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  7499. "; CHECK: [[newadd:%\\w+]] = OpFAdd [[float]] %4 %5\n" +
  7500. "; CHECK: %9 = OpFMul [[float]] %6 [[newadd]]\n" +
  7501. "%main = OpFunction %void None %void_func\n" +
  7502. "%main_lab = OpLabel\n" +
  7503. "%var0 = OpVariable %_ptr_float Function\n" +
  7504. "%var1 = OpVariable %_ptr_float Function\n" +
  7505. "%var2 = OpVariable %_ptr_float Function\n" +
  7506. "%4 = OpLoad %float %var0\n" +
  7507. "%5 = OpLoad %float %var1\n" +
  7508. "%6 = OpLoad %float %var2\n" +
  7509. "%7 = OpFMul %float %6 %4\n" +
  7510. "%8 = OpFMul %float %5 %6\n" +
  7511. "%9 = OpFAdd %float %7 %8\n" +
  7512. "OpReturn\n" +
  7513. "OpFunctionEnd\n",
  7514. 9, true),
  7515. // Test case 3: factor of add of muls
  7516. // (b * a) + (c * a) => a * (b + c)
  7517. InstructionFoldingCase<bool>(
  7518. Header() +
  7519. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  7520. "; CHECK: [[newadd:%\\w+]] = OpFAdd [[float]] %4 %5\n" +
  7521. "; CHECK: %9 = OpFMul [[float]] %6 [[newadd]]\n" +
  7522. "%main = OpFunction %void None %void_func\n" +
  7523. "%main_lab = OpLabel\n" +
  7524. "%var0 = OpVariable %_ptr_float Function\n" +
  7525. "%var1 = OpVariable %_ptr_float Function\n" +
  7526. "%var2 = OpVariable %_ptr_float Function\n" +
  7527. "%4 = OpLoad %float %var0\n" +
  7528. "%5 = OpLoad %float %var1\n" +
  7529. "%6 = OpLoad %float %var2\n" +
  7530. "%7 = OpFMul %float %4 %6\n" +
  7531. "%8 = OpFMul %float %5 %6\n" +
  7532. "%9 = OpFAdd %float %7 %8\n" +
  7533. "OpReturn\n" +
  7534. "OpFunctionEnd\n",
  7535. 9, true)
  7536. ));
  7537. INSTANTIATE_TEST_SUITE_P(MergeSubTest, MatchingInstructionFoldingTest,
  7538. ::testing::Values(
  7539. // Test case 0: merge sub of negate
  7540. // (-x) - 2 = -2 - x
  7541. InstructionFoldingCase<bool>(
  7542. Header() +
  7543. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  7544. "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2{{[[:space:]]}}\n" +
  7545. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  7546. "; CHECK: %4 = OpFSub [[float]] [[float_n2]] [[ld]]\n" +
  7547. "%main = OpFunction %void None %void_func\n" +
  7548. "%main_lab = OpLabel\n" +
  7549. "%var = OpVariable %_ptr_float Function\n" +
  7550. "%2 = OpLoad %float %var\n" +
  7551. "%3 = OpFNegate %float %2\n" +
  7552. "%4 = OpFSub %float %3 %float_2\n" +
  7553. "OpReturn\n" +
  7554. "OpFunctionEnd\n",
  7555. 4, true),
  7556. // Test case 1: merge sub of negate
  7557. // 2 - (-x) = x + 2
  7558. InstructionFoldingCase<bool>(
  7559. Header() +
  7560. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  7561. "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
  7562. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  7563. "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_2]]\n" +
  7564. "%main = OpFunction %void None %void_func\n" +
  7565. "%main_lab = OpLabel\n" +
  7566. "%var = OpVariable %_ptr_float Function\n" +
  7567. "%2 = OpLoad %float %var\n" +
  7568. "%3 = OpFNegate %float %2\n" +
  7569. "%4 = OpFSub %float %float_2 %3\n" +
  7570. "OpReturn\n" +
  7571. "OpFunctionEnd\n",
  7572. 4, true),
  7573. // Test case 2: merge sub of negate
  7574. // (-x) - 2 = -2 - x
  7575. InstructionFoldingCase<bool>(
  7576. Header() +
  7577. "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
  7578. "; CHECK: [[long_n2:%\\w+]] = OpConstant [[long]] -2{{[[:space:]]}}\n" +
  7579. "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
  7580. "; CHECK: %4 = OpISub [[long]] [[long_n2]] [[ld]]\n" +
  7581. "%main = OpFunction %void None %void_func\n" +
  7582. "%main_lab = OpLabel\n" +
  7583. "%var = OpVariable %_ptr_long Function\n" +
  7584. "%2 = OpLoad %long %var\n" +
  7585. "%3 = OpSNegate %long %2\n" +
  7586. "%4 = OpISub %long %3 %long_2\n" +
  7587. "OpReturn\n" +
  7588. "OpFunctionEnd\n",
  7589. 4, true),
  7590. // Test case 3: merge sub of negate
  7591. // 2 - (-x) = x + 2
  7592. InstructionFoldingCase<bool>(
  7593. Header() +
  7594. "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
  7595. "; CHECK: [[long_2:%\\w+]] = OpConstant [[long]] 2\n" +
  7596. "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
  7597. "; CHECK: %4 = OpIAdd [[long]] [[ld]] [[long_2]]\n" +
  7598. "%main = OpFunction %void None %void_func\n" +
  7599. "%main_lab = OpLabel\n" +
  7600. "%var = OpVariable %_ptr_long Function\n" +
  7601. "%2 = OpLoad %long %var\n" +
  7602. "%3 = OpSNegate %long %2\n" +
  7603. "%4 = OpISub %long %long_2 %3\n" +
  7604. "OpReturn\n" +
  7605. "OpFunctionEnd\n",
  7606. 4, true),
  7607. // Test case 4: merge add of subtract
  7608. // (x + 2) - 1 = x + 1
  7609. InstructionFoldingCase<bool>(
  7610. Header() +
  7611. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  7612. "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
  7613. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  7614. "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_1]]\n" +
  7615. "%main = OpFunction %void None %void_func\n" +
  7616. "%main_lab = OpLabel\n" +
  7617. "%var = OpVariable %_ptr_float Function\n" +
  7618. "%2 = OpLoad %float %var\n" +
  7619. "%3 = OpFAdd %float %2 %float_2\n" +
  7620. "%4 = OpFSub %float %3 %float_1\n" +
  7621. "OpReturn\n" +
  7622. "OpFunctionEnd\n",
  7623. 4, true),
  7624. // Test case 5: merge add of subtract
  7625. // (2 + x) - 1 = x + 1
  7626. InstructionFoldingCase<bool>(
  7627. Header() +
  7628. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  7629. "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
  7630. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  7631. "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_1]]\n" +
  7632. "%main = OpFunction %void None %void_func\n" +
  7633. "%main_lab = OpLabel\n" +
  7634. "%var = OpVariable %_ptr_float Function\n" +
  7635. "%2 = OpLoad %float %var\n" +
  7636. "%3 = OpFAdd %float %float_2 %2\n" +
  7637. "%4 = OpFSub %float %3 %float_1\n" +
  7638. "OpReturn\n" +
  7639. "OpFunctionEnd\n",
  7640. 4, true),
  7641. // Test case 6: merge add of subtract
  7642. // 2 - (x + 1) = 1 - x
  7643. InstructionFoldingCase<bool>(
  7644. Header() +
  7645. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  7646. "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
  7647. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  7648. "; CHECK: %4 = OpFSub [[float]] [[float_1]] [[ld]]\n" +
  7649. "%main = OpFunction %void None %void_func\n" +
  7650. "%main_lab = OpLabel\n" +
  7651. "%var = OpVariable %_ptr_float Function\n" +
  7652. "%2 = OpLoad %float %var\n" +
  7653. "%3 = OpFAdd %float %2 %float_1\n" +
  7654. "%4 = OpFSub %float %float_2 %3\n" +
  7655. "OpReturn\n" +
  7656. "OpFunctionEnd\n",
  7657. 4, true),
  7658. // Test case 7: merge add of subtract
  7659. // 2 - (1 + x) = 1 - x
  7660. InstructionFoldingCase<bool>(
  7661. Header() +
  7662. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  7663. "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
  7664. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  7665. "; CHECK: %4 = OpFSub [[float]] [[float_1]] [[ld]]\n" +
  7666. "%main = OpFunction %void None %void_func\n" +
  7667. "%main_lab = OpLabel\n" +
  7668. "%var = OpVariable %_ptr_float Function\n" +
  7669. "%2 = OpLoad %float %var\n" +
  7670. "%3 = OpFAdd %float %float_1 %2\n" +
  7671. "%4 = OpFSub %float %float_2 %3\n" +
  7672. "OpReturn\n" +
  7673. "OpFunctionEnd\n",
  7674. 4, true),
  7675. // Test case 8: merge subtract of subtract
  7676. // (x - 2) - 1 = x - 3
  7677. InstructionFoldingCase<bool>(
  7678. Header() +
  7679. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  7680. "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
  7681. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  7682. "; CHECK: %4 = OpFSub [[float]] [[ld]] [[float_3]]\n" +
  7683. "%main = OpFunction %void None %void_func\n" +
  7684. "%main_lab = OpLabel\n" +
  7685. "%var = OpVariable %_ptr_float Function\n" +
  7686. "%2 = OpLoad %float %var\n" +
  7687. "%3 = OpFSub %float %2 %float_2\n" +
  7688. "%4 = OpFSub %float %3 %float_1\n" +
  7689. "OpReturn\n" +
  7690. "OpFunctionEnd\n",
  7691. 4, true),
  7692. // Test case 9: merge subtract of subtract
  7693. // (2 - x) - 1 = 1 - x
  7694. InstructionFoldingCase<bool>(
  7695. Header() +
  7696. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  7697. "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
  7698. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  7699. "; CHECK: %4 = OpFSub [[float]] [[float_1]] [[ld]]\n" +
  7700. "%main = OpFunction %void None %void_func\n" +
  7701. "%main_lab = OpLabel\n" +
  7702. "%var = OpVariable %_ptr_float Function\n" +
  7703. "%2 = OpLoad %float %var\n" +
  7704. "%3 = OpFSub %float %float_2 %2\n" +
  7705. "%4 = OpFSub %float %3 %float_1\n" +
  7706. "OpReturn\n" +
  7707. "OpFunctionEnd\n",
  7708. 4, true),
  7709. // Test case 10: merge subtract of subtract
  7710. // 2 - (x - 1) = 3 - x
  7711. InstructionFoldingCase<bool>(
  7712. Header() +
  7713. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  7714. "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
  7715. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  7716. "; CHECK: %4 = OpFSub [[float]] [[float_3]] [[ld]]\n" +
  7717. "%main = OpFunction %void None %void_func\n" +
  7718. "%main_lab = OpLabel\n" +
  7719. "%var = OpVariable %_ptr_float Function\n" +
  7720. "%2 = OpLoad %float %var\n" +
  7721. "%3 = OpFSub %float %2 %float_1\n" +
  7722. "%4 = OpFSub %float %float_2 %3\n" +
  7723. "OpReturn\n" +
  7724. "OpFunctionEnd\n",
  7725. 4, true),
  7726. // Test case 11: merge subtract of subtract
  7727. // 1 - (2 - x) = x + (-1)
  7728. InstructionFoldingCase<bool>(
  7729. Header() +
  7730. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  7731. "; CHECK: [[float_n1:%\\w+]] = OpConstant [[float]] -1\n" +
  7732. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  7733. "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_n1]]\n" +
  7734. "%main = OpFunction %void None %void_func\n" +
  7735. "%main_lab = OpLabel\n" +
  7736. "%var = OpVariable %_ptr_float Function\n" +
  7737. "%2 = OpLoad %float %var\n" +
  7738. "%3 = OpFSub %float %float_2 %2\n" +
  7739. "%4 = OpFSub %float %float_1 %3\n" +
  7740. "OpReturn\n" +
  7741. "OpFunctionEnd\n",
  7742. 4, true),
  7743. // Test case 12: merge subtract of subtract
  7744. // 2 - (1 - x) = x + 1
  7745. InstructionFoldingCase<bool>(
  7746. Header() +
  7747. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  7748. "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
  7749. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  7750. "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_1]]\n" +
  7751. "%main = OpFunction %void None %void_func\n" +
  7752. "%main_lab = OpLabel\n" +
  7753. "%var = OpVariable %_ptr_float Function\n" +
  7754. "%2 = OpLoad %float %var\n" +
  7755. "%3 = OpFSub %float %float_1 %2\n" +
  7756. "%4 = OpFSub %float %float_2 %3\n" +
  7757. "OpReturn\n" +
  7758. "OpFunctionEnd\n",
  7759. 4, true),
  7760. // Test case 13: merge subtract of subtract with mixed types.
  7761. // 2 - (1 - x) = x + 1
  7762. InstructionFoldingCase<bool>(
  7763. Header() +
  7764. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  7765. "; CHECK: [[int_1:%\\w+]] = OpConstant [[int]] 1\n" +
  7766. "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
  7767. "; CHECK: %4 = OpIAdd [[int]] [[ld]] [[int_1]]\n" +
  7768. "%main = OpFunction %void None %void_func\n" +
  7769. "%main_lab = OpLabel\n" +
  7770. "%var = OpVariable %_ptr_int Function\n" +
  7771. "%2 = OpLoad %int %var\n" +
  7772. "%3 = OpISub %int %uint_1 %2\n" +
  7773. "%4 = OpISub %int %int_2 %3\n" +
  7774. "OpReturn\n" +
  7775. "OpFunctionEnd\n",
  7776. 4, true),
  7777. // Test case 14: fold overflowing signed 32 bit isubs
  7778. // (x - int_max) - 1 = x - int_min
  7779. InstructionFoldingCase<bool>(
  7780. Header() +
  7781. "; CHECK: [[int:%\\w+]] = OpTypeInt 32\n" +
  7782. "; CHECK: [[int_min:%\\w+]] = OpConstant [[int]] -2147483648\n" +
  7783. "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
  7784. "; CHECK: %4 = OpISub [[int]] [[ld]] [[int_min]]\n" +
  7785. "%main = OpFunction %void None %void_func\n" +
  7786. "%main_lab = OpLabel\n" +
  7787. "%var = OpVariable %_ptr_int Function\n" +
  7788. "%2 = OpLoad %int %var\n" +
  7789. "%3 = OpISub %int %2 %int_max\n" +
  7790. "%4 = OpISub %int %3 %int_1\n" +
  7791. "OpReturn\n" +
  7792. "OpFunctionEnd\n",
  7793. 4, true),
  7794. // Test case 15: fold overflowing signed 64 bit isubs
  7795. // (x - long_max) - 1 = x - long_min
  7796. InstructionFoldingCase<bool>(
  7797. Header() +
  7798. "; CHECK: [[long:%\\w+]] = OpTypeInt 64\n" +
  7799. "; CHECK: [[long_min:%\\w+]] = OpConstant [[long]] -9223372036854775808\n" +
  7800. "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
  7801. "; CHECK: %4 = OpISub [[long]] [[ld]] [[long_min]]\n" +
  7802. "%main = OpFunction %void None %void_func\n" +
  7803. "%main_lab = OpLabel\n" +
  7804. "%var = OpVariable %_ptr_long Function\n" +
  7805. "%2 = OpLoad %long %var\n" +
  7806. "%3 = OpISub %long %2 %long_max\n" +
  7807. "%4 = OpISub %long %3 %long_1\n" +
  7808. "OpReturn\n" +
  7809. "OpFunctionEnd\n",
  7810. 4, true)
  7811. ));
  7812. INSTANTIATE_TEST_SUITE_P(SelectFoldingTest, MatchingInstructionFoldingTest,
  7813. ::testing::Values(
  7814. // Test case 0: Fold select with the same values for both sides
  7815. InstructionFoldingCase<bool>(
  7816. Header() +
  7817. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  7818. "; CHECK: [[int0:%\\w+]] = OpConstant [[int]] 0\n" +
  7819. "; CHECK: %2 = OpCopyObject [[int]] [[int0]]\n" +
  7820. "%main = OpFunction %void None %void_func\n" +
  7821. "%main_lab = OpLabel\n" +
  7822. "%n = OpVariable %_ptr_bool Function\n" +
  7823. "%load = OpLoad %bool %n\n" +
  7824. "%2 = OpSelect %int %load %100 %100\n" +
  7825. "OpReturn\n" +
  7826. "OpFunctionEnd",
  7827. 2, true),
  7828. // Test case 1: Fold select true to left side
  7829. InstructionFoldingCase<bool>(
  7830. Header() +
  7831. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  7832. "; CHECK: [[int0:%\\w+]] = OpConstant [[int]] 0\n" +
  7833. "; CHECK: %2 = OpCopyObject [[int]] [[int0]]\n" +
  7834. "%main = OpFunction %void None %void_func\n" +
  7835. "%main_lab = OpLabel\n" +
  7836. "%n = OpVariable %_ptr_int Function\n" +
  7837. "%load = OpLoad %bool %n\n" +
  7838. "%2 = OpSelect %int %true %100 %n\n" +
  7839. "OpReturn\n" +
  7840. "OpFunctionEnd",
  7841. 2, true),
  7842. // Test case 2: Fold select false to right side
  7843. InstructionFoldingCase<bool>(
  7844. Header() +
  7845. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  7846. "; CHECK: [[int0:%\\w+]] = OpConstant [[int]] 0\n" +
  7847. "; CHECK: %2 = OpCopyObject [[int]] [[int0]]\n" +
  7848. "%main = OpFunction %void None %void_func\n" +
  7849. "%main_lab = OpLabel\n" +
  7850. "%n = OpVariable %_ptr_int Function\n" +
  7851. "%load = OpLoad %bool %n\n" +
  7852. "%2 = OpSelect %int %false %n %100\n" +
  7853. "OpReturn\n" +
  7854. "OpFunctionEnd",
  7855. 2, true),
  7856. // Test case 3: Fold select null to right side
  7857. InstructionFoldingCase<bool>(
  7858. Header() +
  7859. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  7860. "; CHECK: [[int0:%\\w+]] = OpConstant [[int]] 0\n" +
  7861. "; CHECK: %2 = OpCopyObject [[int]] [[int0]]\n" +
  7862. "%main = OpFunction %void None %void_func\n" +
  7863. "%main_lab = OpLabel\n" +
  7864. "%n = OpVariable %_ptr_int Function\n" +
  7865. "%load = OpLoad %int %n\n" +
  7866. "%2 = OpSelect %int %bool_null %load %100\n" +
  7867. "OpReturn\n" +
  7868. "OpFunctionEnd",
  7869. 2, true),
  7870. // Test case 4: vector null
  7871. InstructionFoldingCase<bool>(
  7872. Header() +
  7873. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  7874. "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2\n" +
  7875. "; CHECK: [[int2:%\\w+]] = OpConstant [[int]] 2\n" +
  7876. "; CHECK: [[v2int2_2:%\\w+]] = OpConstantComposite [[v2int]] [[int2]] [[int2]]\n" +
  7877. "; CHECK: %2 = OpCopyObject [[v2int]] [[v2int2_2]]\n" +
  7878. "%main = OpFunction %void None %void_func\n" +
  7879. "%main_lab = OpLabel\n" +
  7880. "%n = OpVariable %_ptr_v2int Function\n" +
  7881. "%load = OpLoad %v2int %n\n" +
  7882. "%2 = OpSelect %v2int %v2bool_null %load %v2int_2_2\n" +
  7883. "OpReturn\n" +
  7884. "OpFunctionEnd",
  7885. 2, true),
  7886. // Test case 5: vector select
  7887. InstructionFoldingCase<bool>(
  7888. Header() +
  7889. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  7890. "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2\n" +
  7891. "; CHECK: %4 = OpVectorShuffle [[v2int]] %2 %3 0 3\n" +
  7892. "%main = OpFunction %void None %void_func\n" +
  7893. "%main_lab = OpLabel\n" +
  7894. "%m = OpVariable %_ptr_v2int Function\n" +
  7895. "%n = OpVariable %_ptr_v2int Function\n" +
  7896. "%2 = OpLoad %v2int %n\n" +
  7897. "%3 = OpLoad %v2int %n\n" +
  7898. "%4 = OpSelect %v2int %v2bool_true_false %2 %3\n" +
  7899. "OpReturn\n" +
  7900. "OpFunctionEnd",
  7901. 4, true),
  7902. // Test case 6: vector select
  7903. InstructionFoldingCase<bool>(
  7904. Header() +
  7905. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  7906. "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2\n" +
  7907. "; CHECK: %4 = OpVectorShuffle [[v2int]] %2 %3 2 1\n" +
  7908. "%main = OpFunction %void None %void_func\n" +
  7909. "%main_lab = OpLabel\n" +
  7910. "%m = OpVariable %_ptr_v2int Function\n" +
  7911. "%n = OpVariable %_ptr_v2int Function\n" +
  7912. "%2 = OpLoad %v2int %n\n" +
  7913. "%3 = OpLoad %v2int %n\n" +
  7914. "%4 = OpSelect %v2int %v2bool_false_true %2 %3\n" +
  7915. "OpReturn\n" +
  7916. "OpFunctionEnd",
  7917. 4, true)
  7918. ));
  7919. INSTANTIATE_TEST_SUITE_P(CompositeExtractOrInsertMatchingTest, MatchingInstructionFoldingTest,
  7920. ::testing::Values(
  7921. // Test case 0: Extracting from result of consecutive shuffles of differing
  7922. // size.
  7923. InstructionFoldingCase<bool>(
  7924. Header() +
  7925. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  7926. "; CHECK: %5 = OpCompositeExtract [[int]] %2 2\n" +
  7927. "%main = OpFunction %void None %void_func\n" +
  7928. "%main_lab = OpLabel\n" +
  7929. "%n = OpVariable %_ptr_v4int Function\n" +
  7930. "%2 = OpLoad %v4int %n\n" +
  7931. "%3 = OpVectorShuffle %v2int %2 %2 2 3\n" +
  7932. "%4 = OpVectorShuffle %v4int %2 %3 0 4 2 5\n" +
  7933. "%5 = OpCompositeExtract %int %4 1\n" +
  7934. "OpReturn\n" +
  7935. "OpFunctionEnd",
  7936. 5, true),
  7937. // Test case 1: Extracting from result of vector shuffle of differing
  7938. // input and result sizes.
  7939. InstructionFoldingCase<bool>(
  7940. Header() +
  7941. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  7942. "; CHECK: %4 = OpCompositeExtract [[int]] %2 2\n" +
  7943. "%main = OpFunction %void None %void_func\n" +
  7944. "%main_lab = OpLabel\n" +
  7945. "%n = OpVariable %_ptr_v4int Function\n" +
  7946. "%2 = OpLoad %v4int %n\n" +
  7947. "%3 = OpVectorShuffle %v2int %2 %2 2 3\n" +
  7948. "%4 = OpCompositeExtract %int %3 0\n" +
  7949. "OpReturn\n" +
  7950. "OpFunctionEnd",
  7951. 4, true),
  7952. // Test case 2: Extracting from result of vector shuffle of differing
  7953. // input and result sizes.
  7954. InstructionFoldingCase<bool>(
  7955. Header() +
  7956. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  7957. "; CHECK: %4 = OpCompositeExtract [[int]] %2 3\n" +
  7958. "%main = OpFunction %void None %void_func\n" +
  7959. "%main_lab = OpLabel\n" +
  7960. "%n = OpVariable %_ptr_v4int Function\n" +
  7961. "%2 = OpLoad %v4int %n\n" +
  7962. "%3 = OpVectorShuffle %v2int %2 %2 2 3\n" +
  7963. "%4 = OpCompositeExtract %int %3 1\n" +
  7964. "OpReturn\n" +
  7965. "OpFunctionEnd",
  7966. 4, true),
  7967. // Test case 3: Using fmix feeding extract with a 1 in the a position.
  7968. InstructionFoldingCase<bool>(
  7969. Header() +
  7970. "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
  7971. "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 4\n" +
  7972. "; CHECK: [[ptr_v4double:%\\w+]] = OpTypePointer Function [[v4double]]\n" +
  7973. "; CHECK: [[m:%\\w+]] = OpVariable [[ptr_v4double]] Function\n" +
  7974. "; CHECK: [[n:%\\w+]] = OpVariable [[ptr_v4double]] Function\n" +
  7975. "; CHECK: [[ld:%\\w+]] = OpLoad [[v4double]] [[n]]\n" +
  7976. "; CHECK: %5 = OpCompositeExtract [[double]] [[ld]] 1\n" +
  7977. "%main = OpFunction %void None %void_func\n" +
  7978. "%main_lab = OpLabel\n" +
  7979. "%m = OpVariable %_ptr_v4double Function\n" +
  7980. "%n = OpVariable %_ptr_v4double Function\n" +
  7981. "%2 = OpLoad %v4double %m\n" +
  7982. "%3 = OpLoad %v4double %n\n" +
  7983. "%4 = OpExtInst %v4double %1 FMix %2 %3 %v4double_0_1_0_0\n" +
  7984. "%5 = OpCompositeExtract %double %4 1\n" +
  7985. "OpReturn\n" +
  7986. "OpFunctionEnd",
  7987. 5, true),
  7988. // Test case 4: Using fmix feeding extract with a 0 in the a position.
  7989. InstructionFoldingCase<bool>(
  7990. Header() +
  7991. "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
  7992. "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 4\n" +
  7993. "; CHECK: [[ptr_v4double:%\\w+]] = OpTypePointer Function [[v4double]]\n" +
  7994. "; CHECK: [[m:%\\w+]] = OpVariable [[ptr_v4double]] Function\n" +
  7995. "; CHECK: [[n:%\\w+]] = OpVariable [[ptr_v4double]] Function\n" +
  7996. "; CHECK: [[ld:%\\w+]] = OpLoad [[v4double]] [[m]]\n" +
  7997. "; CHECK: %5 = OpCompositeExtract [[double]] [[ld]] 2\n" +
  7998. "%main = OpFunction %void None %void_func\n" +
  7999. "%main_lab = OpLabel\n" +
  8000. "%m = OpVariable %_ptr_v4double Function\n" +
  8001. "%n = OpVariable %_ptr_v4double Function\n" +
  8002. "%2 = OpLoad %v4double %m\n" +
  8003. "%3 = OpLoad %v4double %n\n" +
  8004. "%4 = OpExtInst %v4double %1 FMix %2 %3 %v4double_0_1_0_0\n" +
  8005. "%5 = OpCompositeExtract %double %4 2\n" +
  8006. "OpReturn\n" +
  8007. "OpFunctionEnd",
  8008. 5, true),
  8009. // Test case 5: Using fmix feeding extract with a null for the alpha
  8010. InstructionFoldingCase<bool>(
  8011. Header() +
  8012. "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
  8013. "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 4\n" +
  8014. "; CHECK: [[ptr_v4double:%\\w+]] = OpTypePointer Function [[v4double]]\n" +
  8015. "; CHECK: [[m:%\\w+]] = OpVariable [[ptr_v4double]] Function\n" +
  8016. "; CHECK: [[n:%\\w+]] = OpVariable [[ptr_v4double]] Function\n" +
  8017. "; CHECK: [[ld:%\\w+]] = OpLoad [[v4double]] [[m]]\n" +
  8018. "; CHECK: %5 = OpCompositeExtract [[double]] [[ld]] 0\n" +
  8019. "%main = OpFunction %void None %void_func\n" +
  8020. "%main_lab = OpLabel\n" +
  8021. "%m = OpVariable %_ptr_v4double Function\n" +
  8022. "%n = OpVariable %_ptr_v4double Function\n" +
  8023. "%2 = OpLoad %v4double %m\n" +
  8024. "%3 = OpLoad %v4double %n\n" +
  8025. "%4 = OpExtInst %v4double %1 FMix %2 %3 %v4double_null\n" +
  8026. "%5 = OpCompositeExtract %double %4 0\n" +
  8027. "OpReturn\n" +
  8028. "OpFunctionEnd",
  8029. 5, true),
  8030. // Test case 6: Don't fold: Using fmix feeding extract with 0.5 in the a
  8031. // position.
  8032. InstructionFoldingCase<bool>(
  8033. Header() +
  8034. "%main = OpFunction %void None %void_func\n" +
  8035. "%main_lab = OpLabel\n" +
  8036. "%m = OpVariable %_ptr_v4double Function\n" +
  8037. "%n = OpVariable %_ptr_v4double Function\n" +
  8038. "%2 = OpLoad %v4double %m\n" +
  8039. "%3 = OpLoad %v4double %n\n" +
  8040. "%4 = OpExtInst %v4double %1 FMix %2 %3 %v4double_1_1_1_0p5\n" +
  8041. "%5 = OpCompositeExtract %double %4 3\n" +
  8042. "OpReturn\n" +
  8043. "OpFunctionEnd",
  8044. 5, false),
  8045. // Test case 7: Extracting the undefined literal value from a vector
  8046. // shuffle.
  8047. InstructionFoldingCase<bool>(
  8048. Header() +
  8049. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  8050. "; CHECK: %4 = OpUndef [[int]]\n" +
  8051. "%main = OpFunction %void None %void_func\n" +
  8052. "%main_lab = OpLabel\n" +
  8053. "%n = OpVariable %_ptr_v4int Function\n" +
  8054. "%2 = OpLoad %v4int %n\n" +
  8055. "%3 = OpVectorShuffle %v2int %2 %2 2 4294967295\n" +
  8056. "%4 = OpCompositeExtract %int %3 1\n" +
  8057. "OpReturn\n" +
  8058. "OpFunctionEnd",
  8059. 4, true),
  8060. // Test case 8: Inserting every element of a vector turns into a composite construct.
  8061. InstructionFoldingCase<bool>(
  8062. Header() +
  8063. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  8064. "; CHECK-DAG: [[v4:%\\w+]] = OpTypeVector [[int]] 4\n" +
  8065. "; CHECK-DAG: [[int1:%\\w+]] = OpConstant [[int]] 1\n" +
  8066. "; CHECK-DAG: [[int2:%\\w+]] = OpConstant [[int]] 2\n" +
  8067. "; CHECK-DAG: [[int3:%\\w+]] = OpConstant [[int]] 3\n" +
  8068. "; CHECK: [[construct:%\\w+]] = OpCompositeConstruct [[v4]] %100 [[int1]] [[int2]] [[int3]]\n" +
  8069. "; CHECK: %5 = OpCopyObject [[v4]] [[construct]]\n" +
  8070. "%main = OpFunction %void None %void_func\n" +
  8071. "%main_lab = OpLabel\n" +
  8072. "%2 = OpCompositeInsert %v4int %100 %v4int_undef 0\n" +
  8073. "%3 = OpCompositeInsert %v4int %int_1 %2 1\n" +
  8074. "%4 = OpCompositeInsert %v4int %int_2 %3 2\n" +
  8075. "%5 = OpCompositeInsert %v4int %int_3 %4 3\n" +
  8076. "OpReturn\n" +
  8077. "OpFunctionEnd",
  8078. 5, true),
  8079. // Test case 9: Inserting every element of a vector turns into a composite construct in a different order.
  8080. InstructionFoldingCase<bool>(
  8081. Header() +
  8082. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  8083. "; CHECK-DAG: [[v4:%\\w+]] = OpTypeVector [[int]] 4\n" +
  8084. "; CHECK-DAG: [[int1:%\\w+]] = OpConstant [[int]] 1\n" +
  8085. "; CHECK-DAG: [[int2:%\\w+]] = OpConstant [[int]] 2\n" +
  8086. "; CHECK-DAG: [[int3:%\\w+]] = OpConstant [[int]] 3\n" +
  8087. "; CHECK: [[construct:%\\w+]] = OpCompositeConstruct [[v4]] %100 [[int1]] [[int2]] [[int3]]\n" +
  8088. "; CHECK: %5 = OpCopyObject [[v4]] [[construct]]\n" +
  8089. "%main = OpFunction %void None %void_func\n" +
  8090. "%main_lab = OpLabel\n" +
  8091. "%2 = OpCompositeInsert %v4int %100 %v4int_undef 0\n" +
  8092. "%4 = OpCompositeInsert %v4int %int_2 %2 2\n" +
  8093. "%3 = OpCompositeInsert %v4int %int_1 %4 1\n" +
  8094. "%5 = OpCompositeInsert %v4int %int_3 %3 3\n" +
  8095. "OpReturn\n" +
  8096. "OpFunctionEnd",
  8097. 5, true),
  8098. // Test case 10: Check multiple inserts to the same position are handled correctly.
  8099. InstructionFoldingCase<bool>(
  8100. Header() +
  8101. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  8102. "; CHECK-DAG: [[v4:%\\w+]] = OpTypeVector [[int]] 4\n" +
  8103. "; CHECK-DAG: [[int1:%\\w+]] = OpConstant [[int]] 1\n" +
  8104. "; CHECK-DAG: [[int2:%\\w+]] = OpConstant [[int]] 2\n" +
  8105. "; CHECK-DAG: [[int3:%\\w+]] = OpConstant [[int]] 3\n" +
  8106. "; CHECK: [[construct:%\\w+]] = OpCompositeConstruct [[v4]] %100 [[int1]] [[int2]] [[int3]]\n" +
  8107. "; CHECK: %6 = OpCopyObject [[v4]] [[construct]]\n" +
  8108. "%main = OpFunction %void None %void_func\n" +
  8109. "%main_lab = OpLabel\n" +
  8110. "%2 = OpCompositeInsert %v4int %100 %v4int_undef 0\n" +
  8111. "%3 = OpCompositeInsert %v4int %int_2 %2 2\n" +
  8112. "%4 = OpCompositeInsert %v4int %int_4 %3 1\n" +
  8113. "%5 = OpCompositeInsert %v4int %int_1 %4 1\n" +
  8114. "%6 = OpCompositeInsert %v4int %int_3 %5 3\n" +
  8115. "OpReturn\n" +
  8116. "OpFunctionEnd",
  8117. 6, true),
  8118. // Test case 11: The last indexes are 0 and 1, but they have different first indexes. This should not be folded.
  8119. InstructionFoldingCase<bool>(
  8120. Header() +
  8121. "%main = OpFunction %void None %void_func\n" +
  8122. "%main_lab = OpLabel\n" +
  8123. "%2 = OpCompositeInsert %m2x2int %100 %m2x2int_undef 0 0\n" +
  8124. "%3 = OpCompositeInsert %m2x2int %int_1 %2 1 1\n" +
  8125. "OpReturn\n" +
  8126. "OpFunctionEnd",
  8127. 3, false),
  8128. // Test case 12: Don't fold when there is a partial insertion.
  8129. InstructionFoldingCase<bool>(
  8130. Header() +
  8131. "%main = OpFunction %void None %void_func\n" +
  8132. "%main_lab = OpLabel\n" +
  8133. "%2 = OpCompositeInsert %m2x2int %v2int_1_0 %m2x2int_undef 0\n" +
  8134. "%3 = OpCompositeInsert %m2x2int %int_4 %2 0 0\n" +
  8135. "%4 = OpCompositeInsert %m2x2int %v2int_2_3 %3 1\n" +
  8136. "OpReturn\n" +
  8137. "OpFunctionEnd",
  8138. 4, false),
  8139. // Test case 13: Insert into a column of a matrix
  8140. InstructionFoldingCase<bool>(
  8141. Header() +
  8142. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  8143. "; CHECK-DAG: [[v2:%\\w+]] = OpTypeVector [[int]] 2\n" +
  8144. "; CHECK: [[m2x2:%\\w+]] = OpTypeMatrix [[v2]] 2\n" +
  8145. "; CHECK-DAG: [[m2x2_undef:%\\w+]] = OpUndef [[m2x2]]\n" +
  8146. "; CHECK-DAG: [[int1:%\\w+]] = OpConstant [[int]] 1\n" +
  8147. // We keep this insert in the chain. DeadInsertElimPass should remove it.
  8148. "; CHECK: [[insert:%\\w+]] = OpCompositeInsert [[m2x2]] %100 [[m2x2_undef]] 0 0\n" +
  8149. "; CHECK: [[construct:%\\w+]] = OpCompositeConstruct [[v2]] %100 [[int1]]\n" +
  8150. "; CHECK: %3 = OpCompositeInsert [[m2x2]] [[construct]] [[insert]] 0\n" +
  8151. "%main = OpFunction %void None %void_func\n" +
  8152. "%main_lab = OpLabel\n" +
  8153. "%2 = OpCompositeInsert %m2x2int %100 %m2x2int_undef 0 0\n" +
  8154. "%3 = OpCompositeInsert %m2x2int %int_1 %2 0 1\n" +
  8155. "OpReturn\n" +
  8156. "OpFunctionEnd",
  8157. 3, true),
  8158. // Test case 14: Insert all elements of the matrix.
  8159. InstructionFoldingCase<bool>(
  8160. Header() +
  8161. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  8162. "; CHECK-DAG: [[v2:%\\w+]] = OpTypeVector [[int]] 2\n" +
  8163. "; CHECK: [[m2x2:%\\w+]] = OpTypeMatrix [[v2]] 2\n" +
  8164. "; CHECK-DAG: [[m2x2_undef:%\\w+]] = OpUndef [[m2x2]]\n" +
  8165. "; CHECK-DAG: [[int1:%\\w+]] = OpConstant [[int]] 1\n" +
  8166. "; CHECK-DAG: [[int2:%\\w+]] = OpConstant [[int]] 2\n" +
  8167. "; CHECK-DAG: [[int3:%\\w+]] = OpConstant [[int]] 3\n" +
  8168. "; CHECK: [[c0:%\\w+]] = OpCompositeConstruct [[v2]] %100 [[int1]]\n" +
  8169. "; CHECK: [[c1:%\\w+]] = OpCompositeConstruct [[v2]] [[int2]] [[int3]]\n" +
  8170. "; CHECK: [[matrix:%\\w+]] = OpCompositeConstruct [[m2x2]] [[c0]] [[c1]]\n" +
  8171. "; CHECK: %5 = OpCopyObject [[m2x2]] [[matrix]]\n" +
  8172. "%main = OpFunction %void None %void_func\n" +
  8173. "%main_lab = OpLabel\n" +
  8174. "%2 = OpCompositeConstruct %v2int %100 %int_1\n" +
  8175. "%3 = OpCompositeInsert %m2x2int %2 %m2x2int_undef 0\n" +
  8176. "%4 = OpCompositeInsert %m2x2int %int_2 %3 1 0\n" +
  8177. "%5 = OpCompositeInsert %m2x2int %int_3 %4 1 1\n" +
  8178. "OpReturn\n" +
  8179. "OpFunctionEnd",
  8180. 5, true),
  8181. // Test case 15: Replace construct with extract when reconstructing a member
  8182. // of another object.
  8183. InstructionFoldingCase<bool>(
  8184. Header() +
  8185. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  8186. "; CHECK: [[v2:%\\w+]] = OpTypeVector [[int]] 2\n" +
  8187. "; CHECK: [[m2x2:%\\w+]] = OpTypeMatrix [[v2]] 2\n" +
  8188. "; CHECK: [[m2x2_undef:%\\w+]] = OpUndef [[m2x2]]\n" +
  8189. "; CHECK: %5 = OpCompositeExtract [[v2]] [[m2x2_undef]]\n" +
  8190. "%main = OpFunction %void None %void_func\n" +
  8191. "%main_lab = OpLabel\n" +
  8192. "%3 = OpCompositeExtract %int %m2x2int_undef 1 0\n" +
  8193. "%4 = OpCompositeExtract %int %m2x2int_undef 1 1\n" +
  8194. "%5 = OpCompositeConstruct %v2int %3 %4\n" +
  8195. "OpReturn\n" +
  8196. "OpFunctionEnd",
  8197. 5, true),
  8198. // Test case 16: Don't fold when type cannot be deduced to a constant.
  8199. InstructionFoldingCase<bool>(
  8200. Header() +
  8201. "%main = OpFunction %void None %void_func\n" +
  8202. "%main_lab = OpLabel\n" +
  8203. "%4 = OpCompositeInsert %struct_v2int_int_int %int_1 %struct_v2int_int_int_null 2\n" +
  8204. "OpReturn\n" +
  8205. "OpFunctionEnd",
  8206. 4, false),
  8207. // Test case 17: Don't fold when index into composite is out of bounds.
  8208. InstructionFoldingCase<bool>(
  8209. Header() +
  8210. "%main = OpFunction %void None %void_func\n" +
  8211. "%main_lab = OpLabel\n" +
  8212. "%4 = OpCompositeExtract %int %struct_v2int_int_int 3\n" +
  8213. "OpReturn\n" +
  8214. "OpFunctionEnd",
  8215. 4, false),
  8216. // Test case 18: Fold when every element of an array is inserted.
  8217. InstructionFoldingCase<bool>(
  8218. Header() +
  8219. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  8220. "; CHECK: [[int2:%\\w+]] = OpConstant [[int]] 2\n" +
  8221. "; CHECK-DAG: [[arr_type:%\\w+]] = OpTypeArray [[int]] [[int2]]\n" +
  8222. "; CHECK-DAG: [[int10:%\\w+]] = OpConstant [[int]] 10\n" +
  8223. "; CHECK-DAG: [[int1:%\\w+]] = OpConstant [[int]] 1\n" +
  8224. "; CHECK: [[construct:%\\w+]] = OpCompositeConstruct [[arr_type]] [[int10]] [[int1]]\n" +
  8225. "; CHECK: %5 = OpCopyObject [[arr_type]] [[construct]]\n" +
  8226. "%main = OpFunction %void None %void_func\n" +
  8227. "%main_lab = OpLabel\n" +
  8228. "%4 = OpCompositeInsert %int_arr_2 %int_10 %int_arr_2_undef 0\n" +
  8229. "%5 = OpCompositeInsert %int_arr_2 %int_1 %4 1\n" +
  8230. "OpReturn\n" +
  8231. "OpFunctionEnd",
  8232. 5, true),
  8233. // Test case 19: Don't fold for isomorphic structs
  8234. InstructionFoldingCase<bool>(
  8235. Header() +
  8236. "%structA = OpTypeStruct %ulong\n" +
  8237. "%structB = OpTypeStruct %ulong\n" +
  8238. "%structC = OpTypeStruct %structB\n" +
  8239. "%struct_a_undef = OpUndef %structA\n" +
  8240. "%main = OpFunction %void None %void_func\n" +
  8241. "%main_lab = OpLabel\n" +
  8242. "%3 = OpCompositeExtract %ulong %struct_a_undef 0\n" +
  8243. "%4 = OpCompositeConstruct %structB %3\n" +
  8244. "OpReturn\n" +
  8245. "OpFunctionEnd",
  8246. 4, false)
  8247. ));
  8248. INSTANTIATE_TEST_SUITE_P(DotProductMatchingTest, MatchingInstructionFoldingTest,
  8249. ::testing::Values(
  8250. // Test case 0: Using OpDot to extract last element.
  8251. InstructionFoldingCase<bool>(
  8252. Header() +
  8253. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  8254. "; CHECK: %3 = OpCompositeExtract [[float]] %2 3\n" +
  8255. "%main = OpFunction %void None %void_func\n" +
  8256. "%main_lab = OpLabel\n" +
  8257. "%n = OpVariable %_ptr_v4float Function\n" +
  8258. "%2 = OpLoad %v4float %n\n" +
  8259. "%3 = OpDot %float %2 %v4float_0_0_0_1\n" +
  8260. "OpReturn\n" +
  8261. "OpFunctionEnd",
  8262. 3, true),
  8263. // Test case 1: Using OpDot to extract last element.
  8264. InstructionFoldingCase<bool>(
  8265. Header() +
  8266. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  8267. "; CHECK: %3 = OpCompositeExtract [[float]] %2 3\n" +
  8268. "%main = OpFunction %void None %void_func\n" +
  8269. "%main_lab = OpLabel\n" +
  8270. "%n = OpVariable %_ptr_v4float Function\n" +
  8271. "%2 = OpLoad %v4float %n\n" +
  8272. "%3 = OpDot %float %v4float_0_0_0_1 %2\n" +
  8273. "OpReturn\n" +
  8274. "OpFunctionEnd",
  8275. 3, true),
  8276. // Test case 2: Using OpDot to extract second element.
  8277. InstructionFoldingCase<bool>(
  8278. Header() +
  8279. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  8280. "; CHECK: %3 = OpCompositeExtract [[float]] %2 1\n" +
  8281. "%main = OpFunction %void None %void_func\n" +
  8282. "%main_lab = OpLabel\n" +
  8283. "%n = OpVariable %_ptr_v4float Function\n" +
  8284. "%2 = OpLoad %v4float %n\n" +
  8285. "%3 = OpDot %float %v4float_0_1_0_0 %2\n" +
  8286. "OpReturn\n" +
  8287. "OpFunctionEnd",
  8288. 3, true),
  8289. // Test case 3: Using OpDot to extract last element.
  8290. InstructionFoldingCase<bool>(
  8291. Header() +
  8292. "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
  8293. "; CHECK: %3 = OpCompositeExtract [[double]] %2 3\n" +
  8294. "%main = OpFunction %void None %void_func\n" +
  8295. "%main_lab = OpLabel\n" +
  8296. "%n = OpVariable %_ptr_v4double Function\n" +
  8297. "%2 = OpLoad %v4double %n\n" +
  8298. "%3 = OpDot %double %2 %v4double_0_0_0_1\n" +
  8299. "OpReturn\n" +
  8300. "OpFunctionEnd",
  8301. 3, true),
  8302. // Test case 4: Using OpDot to extract last element.
  8303. InstructionFoldingCase<bool>(
  8304. Header() +
  8305. "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
  8306. "; CHECK: %3 = OpCompositeExtract [[double]] %2 3\n" +
  8307. "%main = OpFunction %void None %void_func\n" +
  8308. "%main_lab = OpLabel\n" +
  8309. "%n = OpVariable %_ptr_v4double Function\n" +
  8310. "%2 = OpLoad %v4double %n\n" +
  8311. "%3 = OpDot %double %v4double_0_0_0_1 %2\n" +
  8312. "OpReturn\n" +
  8313. "OpFunctionEnd",
  8314. 3, true),
  8315. // Test case 5: Using OpDot to extract second element.
  8316. InstructionFoldingCase<bool>(
  8317. Header() +
  8318. "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
  8319. "; CHECK: %3 = OpCompositeExtract [[double]] %2 1\n" +
  8320. "%main = OpFunction %void None %void_func\n" +
  8321. "%main_lab = OpLabel\n" +
  8322. "%n = OpVariable %_ptr_v4double Function\n" +
  8323. "%2 = OpLoad %v4double %n\n" +
  8324. "%3 = OpDot %double %v4double_0_1_0_0 %2\n" +
  8325. "OpReturn\n" +
  8326. "OpFunctionEnd",
  8327. 3, true)
  8328. ));
  8329. INSTANTIATE_TEST_SUITE_P(VectorShuffleMatchingTest, MatchingInstructionFoldingTest,
  8330. ::testing::Values(
  8331. // Test case 0: Using OpDot to extract last element.
  8332. InstructionFoldingCase<bool>(
  8333. Header() +
  8334. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  8335. "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2{{[[:space:]]}}\n" +
  8336. "; CHECK: [[null:%\\w+]] = OpConstantNull [[v2int]]\n" +
  8337. "; CHECK: OpVectorShuffle\n" +
  8338. "; CHECK: %3 = OpVectorShuffle [[v2int]] [[null]] {{%\\w+}} 4294967295 2\n" +
  8339. "%main = OpFunction %void None %void_func\n" +
  8340. "%main_lab = OpLabel\n" +
  8341. "%n = OpVariable %_ptr_int Function\n" +
  8342. "%load = OpLoad %int %n\n" +
  8343. "%2 = OpVectorShuffle %v2int %v2int_null %v2int_2_3 3 0xFFFFFFFF \n" +
  8344. "%3 = OpVectorShuffle %v2int %2 %v2int_2_3 1 2 \n" +
  8345. "OpReturn\n" +
  8346. "OpFunctionEnd",
  8347. 3, true)
  8348. ));
  8349. // Issue #5658: The Adreno compiler does not handle 16-bit FMA instructions well.
  8350. // We want to avoid this by not generating FMA. We decided to never generate
  8351. // FMAs because, from a SPIR-V perspective, it is neutral. The ICD can generate
  8352. // the FMA if it wants. The simplest code is no code.
  8353. INSTANTIATE_TEST_SUITE_P(FmaGenerationMatchingTest, MatchingInstructionFoldingTest,
  8354. ::testing::Values(
  8355. // Test case 0: Don't fold (x * y) + a
  8356. InstructionFoldingCase<bool>(
  8357. Header() +
  8358. "%main = OpFunction %void None %void_func\n" +
  8359. "%main_lab = OpLabel\n" +
  8360. "%x = OpVariable %_ptr_float Function\n" +
  8361. "%y = OpVariable %_ptr_float Function\n" +
  8362. "%a = OpVariable %_ptr_float Function\n" +
  8363. "%lx = OpLoad %float %x\n" +
  8364. "%ly = OpLoad %float %y\n" +
  8365. "%mul = OpFMul %float %lx %ly\n" +
  8366. "%la = OpLoad %float %a\n" +
  8367. "%3 = OpFAdd %float %mul %la\n" +
  8368. "OpStore %a %3\n" +
  8369. "OpReturn\n" +
  8370. "OpFunctionEnd",
  8371. 3, false),
  8372. // Test case 1: Don't fold a + (x * y)
  8373. InstructionFoldingCase<bool>(
  8374. Header() +
  8375. "%main = OpFunction %void None %void_func\n" +
  8376. "%main_lab = OpLabel\n" +
  8377. "%x = OpVariable %_ptr_float Function\n" +
  8378. "%y = OpVariable %_ptr_float Function\n" +
  8379. "%a = OpVariable %_ptr_float Function\n" +
  8380. "%lx = OpLoad %float %x\n" +
  8381. "%ly = OpLoad %float %y\n" +
  8382. "%mul = OpFMul %float %lx %ly\n" +
  8383. "%la = OpLoad %float %a\n" +
  8384. "%3 = OpFAdd %float %la %mul\n" +
  8385. "OpStore %a %3\n" +
  8386. "OpReturn\n" +
  8387. "OpFunctionEnd",
  8388. 3, false),
  8389. // Test case 2: Don't fold (x * y) + a with vectors
  8390. InstructionFoldingCase<bool>(
  8391. Header() +
  8392. "%main = OpFunction %void None %void_func\n" +
  8393. "%main_lab = OpLabel\n" +
  8394. "%x = OpVariable %_ptr_v4float Function\n" +
  8395. "%y = OpVariable %_ptr_v4float Function\n" +
  8396. "%a = OpVariable %_ptr_v4float Function\n" +
  8397. "%lx = OpLoad %v4float %x\n" +
  8398. "%ly = OpLoad %v4float %y\n" +
  8399. "%mul = OpFMul %v4float %lx %ly\n" +
  8400. "%la = OpLoad %v4float %a\n" +
  8401. "%3 = OpFAdd %v4float %mul %la\n" +
  8402. "OpStore %a %3\n" +
  8403. "OpReturn\n" +
  8404. "OpFunctionEnd",
  8405. 3,false),
  8406. // Test case 3: Don't fold a + (x * y) with vectors
  8407. InstructionFoldingCase<bool>(
  8408. Header() +
  8409. "%main = OpFunction %void None %void_func\n" +
  8410. "%main_lab = OpLabel\n" +
  8411. "%x = OpVariable %_ptr_float Function\n" +
  8412. "%y = OpVariable %_ptr_float Function\n" +
  8413. "%a = OpVariable %_ptr_float Function\n" +
  8414. "%lx = OpLoad %float %x\n" +
  8415. "%ly = OpLoad %float %y\n" +
  8416. "%mul = OpFMul %float %lx %ly\n" +
  8417. "%la = OpLoad %float %a\n" +
  8418. "%3 = OpFAdd %float %la %mul\n" +
  8419. "OpStore %a %3\n" +
  8420. "OpReturn\n" +
  8421. "OpFunctionEnd",
  8422. 3, false),
  8423. // Test 4: Don't fold if the multiple is marked no contract.
  8424. InstructionFoldingCase<bool>(
  8425. std::string() +
  8426. "OpCapability Shader\n" +
  8427. "OpMemoryModel Logical GLSL450\n" +
  8428. "OpEntryPoint Fragment %main \"main\"\n" +
  8429. "OpExecutionMode %main OriginUpperLeft\n" +
  8430. "OpSource GLSL 140\n" +
  8431. "OpName %main \"main\"\n" +
  8432. "OpDecorate %mul NoContraction\n" +
  8433. "%void = OpTypeVoid\n" +
  8434. "%void_func = OpTypeFunction %void\n" +
  8435. "%bool = OpTypeBool\n" +
  8436. "%float = OpTypeFloat 32\n" +
  8437. "%_ptr_float = OpTypePointer Function %float\n" +
  8438. "%main = OpFunction %void None %void_func\n" +
  8439. "%main_lab = OpLabel\n" +
  8440. "%x = OpVariable %_ptr_float Function\n" +
  8441. "%y = OpVariable %_ptr_float Function\n" +
  8442. "%a = OpVariable %_ptr_float Function\n" +
  8443. "%lx = OpLoad %float %x\n" +
  8444. "%ly = OpLoad %float %y\n" +
  8445. "%mul = OpFMul %float %lx %ly\n" +
  8446. "%la = OpLoad %float %a\n" +
  8447. "%3 = OpFAdd %float %mul %la\n" +
  8448. "OpStore %a %3\n" +
  8449. "OpReturn\n" +
  8450. "OpFunctionEnd",
  8451. 3, false),
  8452. // Test 5: Don't fold if the add is marked no contract.
  8453. InstructionFoldingCase<bool>(
  8454. std::string() +
  8455. "OpCapability Shader\n" +
  8456. "OpMemoryModel Logical GLSL450\n" +
  8457. "OpEntryPoint Fragment %main \"main\"\n" +
  8458. "OpExecutionMode %main OriginUpperLeft\n" +
  8459. "OpSource GLSL 140\n" +
  8460. "OpName %main \"main\"\n" +
  8461. "OpDecorate %3 NoContraction\n" +
  8462. "%void = OpTypeVoid\n" +
  8463. "%void_func = OpTypeFunction %void\n" +
  8464. "%bool = OpTypeBool\n" +
  8465. "%float = OpTypeFloat 32\n" +
  8466. "%_ptr_float = OpTypePointer Function %float\n" +
  8467. "%main = OpFunction %void None %void_func\n" +
  8468. "%main_lab = OpLabel\n" +
  8469. "%x = OpVariable %_ptr_float Function\n" +
  8470. "%y = OpVariable %_ptr_float Function\n" +
  8471. "%a = OpVariable %_ptr_float Function\n" +
  8472. "%lx = OpLoad %float %x\n" +
  8473. "%ly = OpLoad %float %y\n" +
  8474. "%mul = OpFMul %float %lx %ly\n" +
  8475. "%la = OpLoad %float %a\n" +
  8476. "%3 = OpFAdd %float %mul %la\n" +
  8477. "OpStore %a %3\n" +
  8478. "OpReturn\n" +
  8479. "OpFunctionEnd",
  8480. 3, false),
  8481. // Test case 6: Don't fold (x * y) - a
  8482. InstructionFoldingCase<bool>(
  8483. Header() +
  8484. "%main = OpFunction %void None %void_func\n" +
  8485. "%main_lab = OpLabel\n" +
  8486. "%x = OpVariable %_ptr_float Function\n" +
  8487. "%y = OpVariable %_ptr_float Function\n" +
  8488. "%a = OpVariable %_ptr_float Function\n" +
  8489. "%lx = OpLoad %float %x\n" +
  8490. "%ly = OpLoad %float %y\n" +
  8491. "%mul = OpFMul %float %lx %ly\n" +
  8492. "%la = OpLoad %float %a\n" +
  8493. "%3 = OpFSub %float %mul %la\n" +
  8494. "OpStore %a %3\n" +
  8495. "OpReturn\n" +
  8496. "OpFunctionEnd",
  8497. 3, false),
  8498. // Test case 7: Don't fold a - (x * y)
  8499. InstructionFoldingCase<bool>(
  8500. Header() +
  8501. "%main = OpFunction %void None %void_func\n" +
  8502. "%main_lab = OpLabel\n" +
  8503. "%x = OpVariable %_ptr_float Function\n" +
  8504. "%y = OpVariable %_ptr_float Function\n" +
  8505. "%a = OpVariable %_ptr_float Function\n" +
  8506. "%lx = OpLoad %float %x\n" +
  8507. "%ly = OpLoad %float %y\n" +
  8508. "%mul = OpFMul %float %lx %ly\n" +
  8509. "%la = OpLoad %float %a\n" +
  8510. "%3 = OpFSub %float %la %mul\n" +
  8511. "OpStore %a %3\n" +
  8512. "OpReturn\n" +
  8513. "OpFunctionEnd",
  8514. 3, false)
  8515. ));
  8516. using MatchingInstructionWithNoResultFoldingTest =
  8517. ::testing::TestWithParam<InstructionFoldingCase<bool>>;
  8518. // Test folding instructions that do not have a result. The instruction
  8519. // that will be folded is the last instruction before the return. If there
  8520. // are multiple returns, there is not guarantee which one is used.
  8521. TEST_P(MatchingInstructionWithNoResultFoldingTest, Case) {
  8522. const auto& tc = GetParam();
  8523. std::unique_ptr<IRContext> context;
  8524. Instruction* inst;
  8525. std::tie(context, inst) = FoldInstruction(tc.test_body, tc.id_to_fold,SPV_ENV_UNIVERSAL_1_1);
  8526. // Find the instruction to test.
  8527. EXPECT_EQ(inst != nullptr, tc.expected_result);
  8528. if (inst != nullptr) {
  8529. Match(tc.test_body, context.get());
  8530. }
  8531. }
  8532. INSTANTIATE_TEST_SUITE_P(StoreMatchingTest, MatchingInstructionWithNoResultFoldingTest,
  8533. ::testing::Values(
  8534. // Test case 0: Remove store of undef.
  8535. InstructionFoldingCase<bool>(
  8536. Header() +
  8537. "; CHECK: OpLabel\n" +
  8538. "; CHECK-NOT: OpStore\n" +
  8539. "; CHECK: OpReturn\n" +
  8540. "%main = OpFunction %void None %void_func\n" +
  8541. "%main_lab = OpLabel\n" +
  8542. "%n = OpVariable %_ptr_v4double Function\n" +
  8543. "%undef = OpUndef %v4double\n" +
  8544. "OpStore %n %undef\n" +
  8545. "OpReturn\n" +
  8546. "OpFunctionEnd",
  8547. 0 /* OpStore */, true),
  8548. // Test case 1: Keep volatile store.
  8549. InstructionFoldingCase<bool>(
  8550. Header() +
  8551. "%main = OpFunction %void None %void_func\n" +
  8552. "%main_lab = OpLabel\n" +
  8553. "%n = OpVariable %_ptr_v4double Function\n" +
  8554. "%undef = OpUndef %v4double\n" +
  8555. "OpStore %n %undef Volatile\n" +
  8556. "OpReturn\n" +
  8557. "OpFunctionEnd",
  8558. 0 /* OpStore */, false)
  8559. ));
  8560. INSTANTIATE_TEST_SUITE_P(VectorShuffleMatchingTest, MatchingInstructionWithNoResultFoldingTest,
  8561. ::testing::Values(
  8562. // Test case 0: Basic test 1
  8563. InstructionFoldingCase<bool>(
  8564. Header() +
  8565. "; CHECK: OpVectorShuffle\n" +
  8566. "; CHECK: OpVectorShuffle {{%\\w+}} %7 %5 2 3 6 7\n" +
  8567. "; CHECK: OpReturn\n" +
  8568. "%main = OpFunction %void None %void_func\n" +
  8569. "%main_lab = OpLabel\n" +
  8570. "%2 = OpVariable %_ptr_v4double Function\n" +
  8571. "%3 = OpVariable %_ptr_v4double Function\n" +
  8572. "%4 = OpVariable %_ptr_v4double Function\n" +
  8573. "%5 = OpLoad %v4double %2\n" +
  8574. "%6 = OpLoad %v4double %3\n" +
  8575. "%7 = OpLoad %v4double %4\n" +
  8576. "%8 = OpVectorShuffle %v4double %5 %6 2 3 4 5\n" +
  8577. "%9 = OpVectorShuffle %v4double %7 %8 2 3 4 5\n" +
  8578. "OpReturn\n" +
  8579. "OpFunctionEnd",
  8580. 9, true),
  8581. // Test case 1: Basic test 2
  8582. InstructionFoldingCase<bool>(
  8583. Header() +
  8584. "; CHECK: OpVectorShuffle\n" +
  8585. "; CHECK: OpVectorShuffle {{%\\w+}} %6 %7 0 1 4 5\n" +
  8586. "; CHECK: OpReturn\n" +
  8587. "%main = OpFunction %void None %void_func\n" +
  8588. "%main_lab = OpLabel\n" +
  8589. "%2 = OpVariable %_ptr_v4double Function\n" +
  8590. "%3 = OpVariable %_ptr_v4double Function\n" +
  8591. "%4 = OpVariable %_ptr_v4double Function\n" +
  8592. "%5 = OpLoad %v4double %2\n" +
  8593. "%6 = OpLoad %v4double %3\n" +
  8594. "%7 = OpLoad %v4double %4\n" +
  8595. "%8 = OpVectorShuffle %v4double %5 %6 2 3 4 5\n" +
  8596. "%9 = OpVectorShuffle %v4double %8 %7 2 3 4 5\n" +
  8597. "OpReturn\n" +
  8598. "OpFunctionEnd",
  8599. 9, true),
  8600. // Test case 2: Basic test 3
  8601. InstructionFoldingCase<bool>(
  8602. Header() +
  8603. "; CHECK: OpVectorShuffle\n" +
  8604. "; CHECK: OpVectorShuffle {{%\\w+}} %5 %7 3 2 4 5\n" +
  8605. "; CHECK: OpReturn\n" +
  8606. "%main = OpFunction %void None %void_func\n" +
  8607. "%main_lab = OpLabel\n" +
  8608. "%2 = OpVariable %_ptr_v4double Function\n" +
  8609. "%3 = OpVariable %_ptr_v4double Function\n" +
  8610. "%4 = OpVariable %_ptr_v4double Function\n" +
  8611. "%5 = OpLoad %v4double %2\n" +
  8612. "%6 = OpLoad %v4double %3\n" +
  8613. "%7 = OpLoad %v4double %4\n" +
  8614. "%8 = OpVectorShuffle %v4double %5 %6 2 3 4 5\n" +
  8615. "%9 = OpVectorShuffle %v4double %8 %7 1 0 4 5\n" +
  8616. "OpReturn\n" +
  8617. "OpFunctionEnd",
  8618. 9, true),
  8619. // Test case 3: Basic test 4
  8620. InstructionFoldingCase<bool>(
  8621. Header() +
  8622. "; CHECK: OpVectorShuffle\n" +
  8623. "; CHECK: OpVectorShuffle {{%\\w+}} %7 %6 2 3 5 4\n" +
  8624. "; CHECK: OpReturn\n" +
  8625. "%main = OpFunction %void None %void_func\n" +
  8626. "%main_lab = OpLabel\n" +
  8627. "%2 = OpVariable %_ptr_v4double Function\n" +
  8628. "%3 = OpVariable %_ptr_v4double Function\n" +
  8629. "%4 = OpVariable %_ptr_v4double Function\n" +
  8630. "%5 = OpLoad %v4double %2\n" +
  8631. "%6 = OpLoad %v4double %3\n" +
  8632. "%7 = OpLoad %v4double %4\n" +
  8633. "%8 = OpVectorShuffle %v4double %5 %6 2 3 4 5\n" +
  8634. "%9 = OpVectorShuffle %v4double %7 %8 2 3 7 6\n" +
  8635. "OpReturn\n" +
  8636. "OpFunctionEnd",
  8637. 9, true),
  8638. // Test case 4: Don't fold, need both operands of the feeder.
  8639. InstructionFoldingCase<bool>(
  8640. Header() +
  8641. "%main = OpFunction %void None %void_func\n" +
  8642. "%main_lab = OpLabel\n" +
  8643. "%2 = OpVariable %_ptr_v4double Function\n" +
  8644. "%3 = OpVariable %_ptr_v4double Function\n" +
  8645. "%4 = OpVariable %_ptr_v4double Function\n" +
  8646. "%5 = OpLoad %v4double %2\n" +
  8647. "%6 = OpLoad %v4double %3\n" +
  8648. "%7 = OpLoad %v4double %4\n" +
  8649. "%8 = OpVectorShuffle %v4double %5 %6 2 3 4 5\n" +
  8650. "%9 = OpVectorShuffle %v4double %7 %8 2 3 7 5\n" +
  8651. "OpReturn\n" +
  8652. "OpFunctionEnd",
  8653. 9, false),
  8654. // Test case 5: Don't fold, need both operands of the feeder.
  8655. InstructionFoldingCase<bool>(
  8656. Header() +
  8657. "%main = OpFunction %void None %void_func\n" +
  8658. "%main_lab = OpLabel\n" +
  8659. "%2 = OpVariable %_ptr_v4double Function\n" +
  8660. "%3 = OpVariable %_ptr_v4double Function\n" +
  8661. "%4 = OpVariable %_ptr_v4double Function\n" +
  8662. "%5 = OpLoad %v4double %2\n" +
  8663. "%6 = OpLoad %v4double %3\n" +
  8664. "%7 = OpLoad %v4double %4\n" +
  8665. "%8 = OpVectorShuffle %v4double %5 %6 2 3 4 5\n" +
  8666. "%9 = OpVectorShuffle %v4double %8 %7 2 0 7 5\n" +
  8667. "OpReturn\n" +
  8668. "OpFunctionEnd",
  8669. 9, false),
  8670. // Test case 6: Fold, need both operands of the feeder, but they are the same.
  8671. InstructionFoldingCase<bool>(
  8672. Header() +
  8673. "; CHECK: OpVectorShuffle\n" +
  8674. "; CHECK: OpVectorShuffle {{%\\w+}} %5 %7 0 2 7 5\n" +
  8675. "; CHECK: OpReturn\n" +
  8676. "%main = OpFunction %void None %void_func\n" +
  8677. "%main_lab = OpLabel\n" +
  8678. "%2 = OpVariable %_ptr_v4double Function\n" +
  8679. "%3 = OpVariable %_ptr_v4double Function\n" +
  8680. "%4 = OpVariable %_ptr_v4double Function\n" +
  8681. "%5 = OpLoad %v4double %2\n" +
  8682. "%6 = OpLoad %v4double %3\n" +
  8683. "%7 = OpLoad %v4double %4\n" +
  8684. "%8 = OpVectorShuffle %v4double %5 %5 2 3 4 5\n" +
  8685. "%9 = OpVectorShuffle %v4double %8 %7 2 0 7 5\n" +
  8686. "OpReturn\n" +
  8687. "OpFunctionEnd",
  8688. 9, true),
  8689. // Test case 7: Fold, need both operands of the feeder, but they are the same.
  8690. InstructionFoldingCase<bool>(
  8691. Header() +
  8692. "; CHECK: OpVectorShuffle\n" +
  8693. "; CHECK: OpVectorShuffle {{%\\w+}} %7 %5 2 0 5 7\n" +
  8694. "; CHECK: OpReturn\n" +
  8695. "%main = OpFunction %void None %void_func\n" +
  8696. "%main_lab = OpLabel\n" +
  8697. "%2 = OpVariable %_ptr_v4double Function\n" +
  8698. "%3 = OpVariable %_ptr_v4double Function\n" +
  8699. "%4 = OpVariable %_ptr_v4double Function\n" +
  8700. "%5 = OpLoad %v4double %2\n" +
  8701. "%6 = OpLoad %v4double %3\n" +
  8702. "%7 = OpLoad %v4double %4\n" +
  8703. "%8 = OpVectorShuffle %v4double %5 %5 2 3 4 5\n" +
  8704. "%9 = OpVectorShuffle %v4double %7 %8 2 0 7 5\n" +
  8705. "OpReturn\n" +
  8706. "OpFunctionEnd",
  8707. 9, true),
  8708. // Test case 8: Replace first operand with a smaller vector.
  8709. InstructionFoldingCase<bool>(
  8710. Header() +
  8711. "; CHECK: OpVectorShuffle\n" +
  8712. "; CHECK: OpVectorShuffle {{%\\w+}} %5 %7 0 0 5 3\n" +
  8713. "; CHECK: OpReturn\n" +
  8714. "%main = OpFunction %void None %void_func\n" +
  8715. "%main_lab = OpLabel\n" +
  8716. "%2 = OpVariable %_ptr_v2double Function\n" +
  8717. "%3 = OpVariable %_ptr_v4double Function\n" +
  8718. "%4 = OpVariable %_ptr_v4double Function\n" +
  8719. "%5 = OpLoad %v2double %2\n" +
  8720. "%6 = OpLoad %v4double %3\n" +
  8721. "%7 = OpLoad %v4double %4\n" +
  8722. "%8 = OpVectorShuffle %v4double %5 %5 0 1 2 3\n" +
  8723. "%9 = OpVectorShuffle %v4double %8 %7 2 0 7 5\n" +
  8724. "OpReturn\n" +
  8725. "OpFunctionEnd",
  8726. 9, true),
  8727. // Test case 9: Replace first operand with a larger vector.
  8728. InstructionFoldingCase<bool>(
  8729. Header() +
  8730. "; CHECK: OpVectorShuffle\n" +
  8731. "; CHECK: OpVectorShuffle {{%\\w+}} %5 %7 3 0 7 5\n" +
  8732. "; CHECK: OpReturn\n" +
  8733. "%main = OpFunction %void None %void_func\n" +
  8734. "%main_lab = OpLabel\n" +
  8735. "%2 = OpVariable %_ptr_v4double Function\n" +
  8736. "%3 = OpVariable %_ptr_v4double Function\n" +
  8737. "%4 = OpVariable %_ptr_v4double Function\n" +
  8738. "%5 = OpLoad %v4double %2\n" +
  8739. "%6 = OpLoad %v4double %3\n" +
  8740. "%7 = OpLoad %v4double %4\n" +
  8741. "%8 = OpVectorShuffle %v2double %5 %5 0 3\n" +
  8742. "%9 = OpVectorShuffle %v4double %8 %7 1 0 5 3\n" +
  8743. "OpReturn\n" +
  8744. "OpFunctionEnd",
  8745. 9, true),
  8746. // Test case 10: Replace unused operand with null.
  8747. InstructionFoldingCase<bool>(
  8748. Header() +
  8749. "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
  8750. "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 2\n" +
  8751. "; CHECK: [[null:%\\w+]] = OpConstantNull [[v4double]]\n" +
  8752. "; CHECK: OpVectorShuffle\n" +
  8753. "; CHECK: OpVectorShuffle {{%\\w+}} [[null]] %7 4 2 5 3\n" +
  8754. "; CHECK: OpReturn\n" +
  8755. "%main = OpFunction %void None %void_func\n" +
  8756. "%main_lab = OpLabel\n" +
  8757. "%2 = OpVariable %_ptr_v4double Function\n" +
  8758. "%3 = OpVariable %_ptr_v4double Function\n" +
  8759. "%4 = OpVariable %_ptr_v4double Function\n" +
  8760. "%5 = OpLoad %v4double %2\n" +
  8761. "%6 = OpLoad %v4double %3\n" +
  8762. "%7 = OpLoad %v4double %4\n" +
  8763. "%8 = OpVectorShuffle %v2double %5 %5 0 3\n" +
  8764. "%9 = OpVectorShuffle %v4double %8 %7 4 2 5 3\n" +
  8765. "OpReturn\n" +
  8766. "OpFunctionEnd",
  8767. 9, true),
  8768. // Test case 11: Replace unused operand with null.
  8769. InstructionFoldingCase<bool>(
  8770. Header() +
  8771. "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
  8772. "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 2\n" +
  8773. "; CHECK: [[null:%\\w+]] = OpConstantNull [[v4double]]\n" +
  8774. "; CHECK: OpVectorShuffle\n" +
  8775. "; CHECK: OpVectorShuffle {{%\\w+}} [[null]] %5 2 2 5 5\n" +
  8776. "; CHECK: OpReturn\n" +
  8777. "%main = OpFunction %void None %void_func\n" +
  8778. "%main_lab = OpLabel\n" +
  8779. "%2 = OpVariable %_ptr_v4double Function\n" +
  8780. "%3 = OpVariable %_ptr_v4double Function\n" +
  8781. "%5 = OpLoad %v4double %2\n" +
  8782. "%6 = OpLoad %v4double %3\n" +
  8783. "%8 = OpVectorShuffle %v2double %5 %5 0 3\n" +
  8784. "%9 = OpVectorShuffle %v4double %8 %8 2 2 3 3\n" +
  8785. "OpReturn\n" +
  8786. "OpFunctionEnd",
  8787. 9, true),
  8788. // Test case 12: Replace unused operand with null.
  8789. InstructionFoldingCase<bool>(
  8790. Header() +
  8791. "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
  8792. "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 2\n" +
  8793. "; CHECK: [[null:%\\w+]] = OpConstantNull [[v4double]]\n" +
  8794. "; CHECK: OpVectorShuffle\n" +
  8795. "; CHECK: OpVectorShuffle {{%\\w+}} %7 [[null]] 2 0 1 3\n" +
  8796. "; CHECK: OpReturn\n" +
  8797. "%main = OpFunction %void None %void_func\n" +
  8798. "%main_lab = OpLabel\n" +
  8799. "%2 = OpVariable %_ptr_v4double Function\n" +
  8800. "%3 = OpVariable %_ptr_v4double Function\n" +
  8801. "%4 = OpVariable %_ptr_v4double Function\n" +
  8802. "%5 = OpLoad %v4double %2\n" +
  8803. "%6 = OpLoad %v4double %3\n" +
  8804. "%7 = OpLoad %v4double %4\n" +
  8805. "%8 = OpVectorShuffle %v2double %5 %5 0 3\n" +
  8806. "%9 = OpVectorShuffle %v4double %7 %8 2 0 1 3\n" +
  8807. "OpReturn\n" +
  8808. "OpFunctionEnd",
  8809. 9, true),
  8810. // Test case 13: Shuffle with undef literal.
  8811. InstructionFoldingCase<bool>(
  8812. Header() +
  8813. "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
  8814. "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 2\n" +
  8815. "; CHECK: OpVectorShuffle\n" +
  8816. "; CHECK: OpVectorShuffle {{%\\w+}} %7 {{%\\w+}} 2 0 1 4294967295\n" +
  8817. "; CHECK: OpReturn\n" +
  8818. "%main = OpFunction %void None %void_func\n" +
  8819. "%main_lab = OpLabel\n" +
  8820. "%2 = OpVariable %_ptr_v4double Function\n" +
  8821. "%3 = OpVariable %_ptr_v4double Function\n" +
  8822. "%4 = OpVariable %_ptr_v4double Function\n" +
  8823. "%5 = OpLoad %v4double %2\n" +
  8824. "%6 = OpLoad %v4double %3\n" +
  8825. "%7 = OpLoad %v4double %4\n" +
  8826. "%8 = OpVectorShuffle %v2double %5 %5 0 1\n" +
  8827. "%9 = OpVectorShuffle %v4double %7 %8 2 0 1 4294967295\n" +
  8828. "OpReturn\n" +
  8829. "OpFunctionEnd",
  8830. 9, true),
  8831. // Test case 14: Shuffle with undef literal and change size of first input vector.
  8832. InstructionFoldingCase<bool>(
  8833. Header() +
  8834. "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
  8835. "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 2\n" +
  8836. "; CHECK: OpVectorShuffle\n" +
  8837. "; CHECK: OpVectorShuffle {{%\\w+}} %5 %7 0 1 4 4294967295\n" +
  8838. "; CHECK: OpReturn\n" +
  8839. "%main = OpFunction %void None %void_func\n" +
  8840. "%main_lab = OpLabel\n" +
  8841. "%2 = OpVariable %_ptr_v4double Function\n" +
  8842. "%3 = OpVariable %_ptr_v4double Function\n" +
  8843. "%4 = OpVariable %_ptr_v4double Function\n" +
  8844. "%5 = OpLoad %v4double %2\n" +
  8845. "%6 = OpLoad %v4double %3\n" +
  8846. "%7 = OpLoad %v4double %4\n" +
  8847. "%8 = OpVectorShuffle %v2double %5 %5 0 1\n" +
  8848. "%9 = OpVectorShuffle %v4double %8 %7 0 1 2 4294967295\n" +
  8849. "OpReturn\n" +
  8850. "OpFunctionEnd",
  8851. 9, true)
  8852. ));
  8853. using EntryPointFoldingTest =
  8854. ::testing::TestWithParam<InstructionFoldingCase<bool>>;
  8855. TEST_P(EntryPointFoldingTest, Case) {
  8856. const auto& tc = GetParam();
  8857. // Build module.
  8858. std::unique_ptr<IRContext> context =
  8859. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
  8860. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  8861. ASSERT_NE(nullptr, context);
  8862. // Find the first entry point. That is the instruction we want to fold.
  8863. Instruction* inst = nullptr;
  8864. ASSERT_FALSE(context->module()->entry_points().empty());
  8865. inst = &*context->module()->entry_points().begin();
  8866. assert(inst && "Invalid test. Could not find entry point instruction to fold.");
  8867. std::unique_ptr<Instruction> original_inst(inst->Clone(context.get()));
  8868. bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
  8869. EXPECT_EQ(succeeded, tc.expected_result);
  8870. if (succeeded) {
  8871. Match(tc.test_body, context.get());
  8872. }
  8873. }
  8874. INSTANTIATE_TEST_SUITE_P(OpEntryPointFoldingTest, EntryPointFoldingTest,
  8875. ::testing::Values(
  8876. // Test case 0: Basic test 1
  8877. InstructionFoldingCase<bool>(std::string() +
  8878. "; CHECK: OpEntryPoint Fragment %2 \"main\" %3\n" +
  8879. "OpCapability Shader\n" +
  8880. "%1 = OpExtInstImport \"GLSL.std.450\"\n" +
  8881. "OpMemoryModel Logical GLSL450\n" +
  8882. "OpEntryPoint Fragment %2 \"main\" %3 %3 %3\n" +
  8883. "OpExecutionMode %2 OriginUpperLeft\n" +
  8884. "OpSource GLSL 430\n" +
  8885. "OpDecorate %3 Location 0\n" +
  8886. "%void = OpTypeVoid\n" +
  8887. "%5 = OpTypeFunction %void\n" +
  8888. "%float = OpTypeFloat 32\n" +
  8889. "%v4float = OpTypeVector %float 4\n" +
  8890. "%_ptr_Output_v4float = OpTypePointer Output %v4float\n" +
  8891. "%3 = OpVariable %_ptr_Output_v4float Output\n" +
  8892. "%int = OpTypeInt 32 1\n" +
  8893. "%int_0 = OpConstant %int 0\n" +
  8894. "%_ptr_PushConstant_v4float = OpTypePointer PushConstant %v4float\n" +
  8895. "%2 = OpFunction %void None %5\n" +
  8896. "%12 = OpLabel\n" +
  8897. "OpReturn\n" +
  8898. "OpFunctionEnd\n",
  8899. 9, true),
  8900. InstructionFoldingCase<bool>(std::string() +
  8901. "; CHECK: OpEntryPoint Fragment %2 \"main\" %3 %4\n" +
  8902. "OpCapability Shader\n" +
  8903. "%1 = OpExtInstImport \"GLSL.std.450\"\n" +
  8904. "OpMemoryModel Logical GLSL450\n" +
  8905. "OpEntryPoint Fragment %2 \"main\" %3 %4 %3\n" +
  8906. "OpExecutionMode %2 OriginUpperLeft\n" +
  8907. "OpSource GLSL 430\n" +
  8908. "OpDecorate %3 Location 0\n" +
  8909. "%void = OpTypeVoid\n" +
  8910. "%5 = OpTypeFunction %void\n" +
  8911. "%float = OpTypeFloat 32\n" +
  8912. "%v4float = OpTypeVector %float 4\n" +
  8913. "%_ptr_Output_v4float = OpTypePointer Output %v4float\n" +
  8914. "%3 = OpVariable %_ptr_Output_v4float Output\n" +
  8915. "%4 = OpVariable %_ptr_Output_v4float Output\n" +
  8916. "%int = OpTypeInt 32 1\n" +
  8917. "%int_0 = OpConstant %int 0\n" +
  8918. "%_ptr_PushConstant_v4float = OpTypePointer PushConstant %v4float\n" +
  8919. "%2 = OpFunction %void None %5\n" +
  8920. "%12 = OpLabel\n" +
  8921. "OpReturn\n" +
  8922. "OpFunctionEnd\n",
  8923. 9, true),
  8924. InstructionFoldingCase<bool>(std::string() +
  8925. "; CHECK: OpEntryPoint Fragment %2 \"main\" %4 %3\n" +
  8926. "OpCapability Shader\n" +
  8927. "%1 = OpExtInstImport \"GLSL.std.450\"\n" +
  8928. "OpMemoryModel Logical GLSL450\n" +
  8929. "OpEntryPoint Fragment %2 \"main\" %4 %4 %3\n" +
  8930. "OpExecutionMode %2 OriginUpperLeft\n" +
  8931. "OpSource GLSL 430\n" +
  8932. "OpDecorate %3 Location 0\n" +
  8933. "%void = OpTypeVoid\n" +
  8934. "%5 = OpTypeFunction %void\n" +
  8935. "%float = OpTypeFloat 32\n" +
  8936. "%v4float = OpTypeVector %float 4\n" +
  8937. "%_ptr_Output_v4float = OpTypePointer Output %v4float\n" +
  8938. "%3 = OpVariable %_ptr_Output_v4float Output\n" +
  8939. "%4 = OpVariable %_ptr_Output_v4float Output\n" +
  8940. "%int = OpTypeInt 32 1\n" +
  8941. "%int_0 = OpConstant %int 0\n" +
  8942. "%_ptr_PushConstant_v4float = OpTypePointer PushConstant %v4float\n" +
  8943. "%2 = OpFunction %void None %5\n" +
  8944. "%12 = OpLabel\n" +
  8945. "OpReturn\n" +
  8946. "OpFunctionEnd\n",
  8947. 9, true)
  8948. ));
  8949. using SPV14FoldingTest =
  8950. ::testing::TestWithParam<InstructionFoldingCase<bool>>;
  8951. TEST_P(SPV14FoldingTest, Case) {
  8952. const auto& tc = GetParam();
  8953. std::unique_ptr<IRContext> context;
  8954. Instruction* inst;
  8955. std::tie(context, inst) = FoldInstruction(tc.test_body, tc.id_to_fold,SPV_ENV_UNIVERSAL_1_4);
  8956. EXPECT_EQ(inst != nullptr, tc.expected_result);
  8957. if (inst != nullptr) {
  8958. Match(tc.test_body, context.get());
  8959. }
  8960. }
  8961. INSTANTIATE_TEST_SUITE_P(SPV14FoldingTest, SPV14FoldingTest,
  8962. ::testing::Values(
  8963. // Test case 0: select vectors with scalar condition.
  8964. InstructionFoldingCase<bool>(std::string() +
  8965. "; CHECK-NOT: OpSelect\n" +
  8966. "; CHECK: %3 = OpCopyObject {{%\\w+}} %1\n" +
  8967. "OpCapability Shader\n" +
  8968. "OpCapability Linkage\n" +
  8969. "%void = OpTypeVoid\n" +
  8970. "%bool = OpTypeBool\n" +
  8971. "%true = OpConstantTrue %bool\n" +
  8972. "%int = OpTypeInt 32 0\n" +
  8973. "%int4 = OpTypeVector %int 4\n" +
  8974. "%int_0 = OpConstant %int 0\n" +
  8975. "%int_1 = OpConstant %int 1\n" +
  8976. "%1 = OpUndef %int4\n" +
  8977. "%2 = OpUndef %int4\n" +
  8978. "%void_fn = OpTypeFunction %void\n" +
  8979. "%func = OpFunction %void None %void_fn\n" +
  8980. "%entry = OpLabel\n" +
  8981. "%3 = OpSelect %int4 %true %1 %2\n" +
  8982. "OpReturn\n" +
  8983. "OpFunctionEnd\n"
  8984. ,
  8985. 3, true),
  8986. // Test case 1: select struct with scalar condition.
  8987. InstructionFoldingCase<bool>(std::string() +
  8988. "; CHECK-NOT: OpSelect\n" +
  8989. "; CHECK: %3 = OpCopyObject {{%\\w+}} %2\n" +
  8990. "OpCapability Shader\n" +
  8991. "OpCapability Linkage\n" +
  8992. "%void = OpTypeVoid\n" +
  8993. "%bool = OpTypeBool\n" +
  8994. "%true = OpConstantFalse %bool\n" +
  8995. "%int = OpTypeInt 32 0\n" +
  8996. "%struct = OpTypeStruct %int %int %int %int\n" +
  8997. "%int_0 = OpConstant %int 0\n" +
  8998. "%int_1 = OpConstant %int 1\n" +
  8999. "%1 = OpUndef %struct\n" +
  9000. "%2 = OpUndef %struct\n" +
  9001. "%void_fn = OpTypeFunction %void\n" +
  9002. "%func = OpFunction %void None %void_fn\n" +
  9003. "%entry = OpLabel\n" +
  9004. "%3 = OpSelect %struct %true %1 %2\n" +
  9005. "OpReturn\n" +
  9006. "OpFunctionEnd\n"
  9007. ,
  9008. 3, true),
  9009. // Test case 1: select array with scalar condition.
  9010. InstructionFoldingCase<bool>(std::string() +
  9011. "; CHECK-NOT: OpSelect\n" +
  9012. "; CHECK: %3 = OpCopyObject {{%\\w+}} %2\n" +
  9013. "OpCapability Shader\n" +
  9014. "OpCapability Linkage\n" +
  9015. "%void = OpTypeVoid\n" +
  9016. "%bool = OpTypeBool\n" +
  9017. "%true = OpConstantFalse %bool\n" +
  9018. "%int = OpTypeInt 32 0\n" +
  9019. "%int_0 = OpConstant %int 0\n" +
  9020. "%int_1 = OpConstant %int 1\n" +
  9021. "%int_4 = OpConstant %int 4\n" +
  9022. "%array = OpTypeStruct %int %int %int %int\n" +
  9023. "%1 = OpUndef %array\n" +
  9024. "%2 = OpUndef %array\n" +
  9025. "%void_fn = OpTypeFunction %void\n" +
  9026. "%func = OpFunction %void None %void_fn\n" +
  9027. "%entry = OpLabel\n" +
  9028. "%3 = OpSelect %array %true %1 %2\n" +
  9029. "OpReturn\n" +
  9030. "OpFunctionEnd\n"
  9031. ,
  9032. 3, true)
  9033. ));
  9034. std::string FloatControlsHeader(const std::string& capabilities) {
  9035. std::string header = R"(
  9036. OpCapability Shader
  9037. )" + capabilities + R"(
  9038. %void = OpTypeVoid
  9039. %float = OpTypeFloat 32
  9040. %float_0 = OpConstant %float 0
  9041. %float_1 = OpConstant %float 1
  9042. %void_fn = OpTypeFunction %void
  9043. %func = OpFunction %void None %void_fn
  9044. %entry = OpLabel
  9045. )";
  9046. return header;
  9047. }
  9048. using FloatControlsFoldingTest =
  9049. ::testing::TestWithParam<InstructionFoldingCase<bool>>;
  9050. TEST_P(FloatControlsFoldingTest, Case) {
  9051. const auto& tc = GetParam();
  9052. std::unique_ptr<IRContext> context;
  9053. Instruction* inst;
  9054. std::tie(context, inst) = FoldInstruction(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_4);
  9055. EXPECT_EQ(inst != nullptr, tc.expected_result);
  9056. if (inst != nullptr) {
  9057. Match(tc.test_body, context.get());
  9058. }
  9059. }
  9060. INSTANTIATE_TEST_SUITE_P(FloatControlsFoldingTest, FloatControlsFoldingTest,
  9061. ::testing::Values(
  9062. // Test case 0: no folding with DenormPreserve
  9063. InstructionFoldingCase<bool>(FloatControlsHeader("OpCapability DenormPreserve") +
  9064. "%1 = OpFAdd %float %float_0 %float_1\n" +
  9065. "OpReturn\n" +
  9066. "OpFunctionEnd\n"
  9067. ,
  9068. 1, false),
  9069. // Test case 1: no folding with DenormFlushToZero
  9070. InstructionFoldingCase<bool>(FloatControlsHeader("OpCapability DenormFlushToZero") +
  9071. "%1 = OpFAdd %float %float_0 %float_1\n" +
  9072. "OpReturn\n" +
  9073. "OpFunctionEnd\n"
  9074. ,
  9075. 1, false),
  9076. // Test case 2: no folding with SignedZeroInfNanPreserve
  9077. InstructionFoldingCase<bool>(FloatControlsHeader("OpCapability SignedZeroInfNanPreserve") +
  9078. "%1 = OpFAdd %float %float_0 %float_1\n" +
  9079. "OpReturn\n" +
  9080. "OpFunctionEnd\n"
  9081. ,
  9082. 1, false),
  9083. // Test case 3: no folding with RoundingModeRTE
  9084. InstructionFoldingCase<bool>(FloatControlsHeader("OpCapability RoundingModeRTE") +
  9085. "%1 = OpFAdd %float %float_0 %float_1\n" +
  9086. "OpReturn\n" +
  9087. "OpFunctionEnd\n"
  9088. ,
  9089. 1, false),
  9090. // Test case 4: no folding with RoundingModeRTZ
  9091. InstructionFoldingCase<bool>(FloatControlsHeader("OpCapability RoundingModeRTZ") +
  9092. "%1 = OpFAdd %float %float_0 %float_1\n" +
  9093. "OpReturn\n" +
  9094. "OpFunctionEnd\n"
  9095. ,
  9096. 1, false)
  9097. ));
  9098. std::string ImageOperandsTestBody(const std::string& image_instruction) {
  9099. std::string body = R"(
  9100. OpCapability Shader
  9101. OpCapability ImageGatherExtended
  9102. OpMemoryModel Logical GLSL450
  9103. OpEntryPoint Fragment %main "main"
  9104. OpExecutionMode %main OriginUpperLeft
  9105. OpDecorate %Texture DescriptorSet 0
  9106. OpDecorate %Texture Binding 0
  9107. %int = OpTypeInt 32 1
  9108. %int_n1 = OpConstant %int -1
  9109. %5 = OpConstant %int 0
  9110. %float = OpTypeFloat 32
  9111. %float_0 = OpConstant %float 0
  9112. %type_2d_image = OpTypeImage %float 2D 2 0 0 1 Unknown
  9113. %type_sampled_image = OpTypeSampledImage %type_2d_image
  9114. %type_sampler = OpTypeSampler
  9115. %_ptr_UniformConstant_type_sampler = OpTypePointer UniformConstant %type_sampler
  9116. %_ptr_UniformConstant_type_2d_image = OpTypePointer UniformConstant %type_2d_image
  9117. %_ptr_int = OpTypePointer Function %int
  9118. %v2int = OpTypeVector %int 2
  9119. %10 = OpTypeVector %float 4
  9120. %void = OpTypeVoid
  9121. %22 = OpTypeFunction %void
  9122. %v2float = OpTypeVector %float 2
  9123. %v3int = OpTypeVector %int 3
  9124. %Texture = OpVariable %_ptr_UniformConstant_type_2d_image UniformConstant
  9125. %gSampler = OpVariable %_ptr_UniformConstant_type_sampler UniformConstant
  9126. %110 = OpConstantComposite %v2int %5 %5
  9127. %101 = OpConstantComposite %v2int %int_n1 %int_n1
  9128. %20 = OpConstantComposite %v2float %float_0 %float_0
  9129. %main = OpFunction %void None %22
  9130. %23 = OpLabel
  9131. %var = OpVariable %_ptr_int Function
  9132. %88 = OpLoad %type_2d_image %Texture
  9133. %val = OpLoad %int %var
  9134. %sampler = OpLoad %type_sampler %gSampler
  9135. %26 = OpSampledImage %type_sampled_image %88 %sampler
  9136. )" + image_instruction + R"(
  9137. OpReturn
  9138. OpFunctionEnd
  9139. )";
  9140. return body;
  9141. }
  9142. INSTANTIATE_TEST_SUITE_P(ImageOperandsBitmaskFoldingTest, MatchingInstructionWithNoResultFoldingTest,
  9143. ::testing::Values(
  9144. // Test case 0: OpImageFetch without Offset
  9145. InstructionFoldingCase<bool>(ImageOperandsTestBody(
  9146. "%89 = OpImageFetch %10 %88 %101 Lod %5 \n")
  9147. , 89, false),
  9148. // Test case 1: OpImageFetch with non-const offset
  9149. InstructionFoldingCase<bool>(ImageOperandsTestBody(
  9150. "%89 = OpImageFetch %10 %88 %101 Lod|Offset %5 %val \n")
  9151. , 89, false),
  9152. // Test case 2: OpImageFetch with Lod and Offset
  9153. InstructionFoldingCase<bool>(ImageOperandsTestBody(
  9154. " %89 = OpImageFetch %10 %88 %101 Lod|Offset %5 %101 \n"
  9155. "; CHECK: %89 = OpImageFetch %10 %88 %101 Lod|ConstOffset %5 %101 \n")
  9156. , 89, true),
  9157. // Test case 3: OpImageFetch with Bias and Offset
  9158. InstructionFoldingCase<bool>(ImageOperandsTestBody(
  9159. " %89 = OpImageFetch %10 %88 %101 Bias|Offset %5 %101 \n"
  9160. "; CHECK: %89 = OpImageFetch %10 %88 %101 Bias|ConstOffset %5 %101 \n")
  9161. , 89, true),
  9162. // Test case 4: OpImageFetch with Grad and Offset.
  9163. // Grad adds 2 operands to the instruction.
  9164. InstructionFoldingCase<bool>(ImageOperandsTestBody(
  9165. " %89 = OpImageFetch %10 %88 %101 Grad|Offset %5 %5 %101 \n"
  9166. "; CHECK: %89 = OpImageFetch %10 %88 %101 Grad|ConstOffset %5 %5 %101 \n")
  9167. , 89, true),
  9168. // Test case 5: OpImageFetch with Offset and MinLod.
  9169. // This is an example of a case where the bitmask bit-offset is larger than
  9170. // that of the Offset.
  9171. InstructionFoldingCase<bool>(ImageOperandsTestBody(
  9172. " %89 = OpImageFetch %10 %88 %101 Offset|MinLod %101 %5 \n"
  9173. "; CHECK: %89 = OpImageFetch %10 %88 %101 ConstOffset|MinLod %101 %5 \n")
  9174. , 89, true),
  9175. // Test case 6: OpImageGather with constant Offset
  9176. InstructionFoldingCase<bool>(ImageOperandsTestBody(
  9177. " %89 = OpImageGather %10 %26 %20 %5 Offset %101 \n"
  9178. "; CHECK: %89 = OpImageGather %10 %26 %20 %5 ConstOffset %101 \n")
  9179. , 89, true),
  9180. // Test case 7: OpImageWrite with constant Offset
  9181. InstructionFoldingCase<bool>(ImageOperandsTestBody(
  9182. " OpImageWrite %88 %5 %101 Offset %101 \n"
  9183. "; CHECK: OpImageWrite %88 %5 %101 ConstOffset %101 \n")
  9184. , 0 /* No result-id */, true),
  9185. // Test case 8: OpImageFetch with zero constant Offset
  9186. InstructionFoldingCase<bool>(ImageOperandsTestBody(
  9187. " %89 = OpImageFetch %10 %88 %101 Lod|Offset %5 %110 \n"
  9188. "; CHECK: %89 = OpImageFetch %10 %88 %101 Lod %5 \n")
  9189. , 89, true)
  9190. ));
  9191. } // namespace
  9192. } // namespace opt
  9193. } // namespace spvtools