fold_test.cpp 245 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199
  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 <limits>
  14. #include <memory>
  15. #include <string>
  16. #include <unordered_set>
  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/fold.h"
  24. #include "source/opt/ir_context.h"
  25. #include "source/opt/module.h"
  26. #include "spirv-tools/libspirv.hpp"
  27. #include "test/opt/pass_utils.h"
  28. namespace spvtools {
  29. namespace opt {
  30. namespace {
  31. using ::testing::Contains;
  32. std::string Disassemble(const std::string& original, IRContext* context,
  33. uint32_t disassemble_options = 0) {
  34. std::vector<uint32_t> optimized_bin;
  35. context->module()->ToBinary(&optimized_bin, true);
  36. spv_target_env target_env = SPV_ENV_UNIVERSAL_1_2;
  37. SpirvTools tools(target_env);
  38. std::string optimized_asm;
  39. EXPECT_TRUE(
  40. tools.Disassemble(optimized_bin, &optimized_asm, disassemble_options))
  41. << "Disassembling failed for shader:\n"
  42. << original << std::endl;
  43. return optimized_asm;
  44. }
  45. void Match(const std::string& original, IRContext* context,
  46. uint32_t disassemble_options = 0) {
  47. std::string disassembly = Disassemble(original, context, disassemble_options);
  48. auto match_result = effcee::Match(disassembly, original);
  49. EXPECT_EQ(effcee::Result::Status::Ok, match_result.status())
  50. << match_result.message() << "\nChecking result:\n"
  51. << disassembly;
  52. }
  53. template <class ResultType>
  54. struct InstructionFoldingCase {
  55. InstructionFoldingCase(const std::string& tb, uint32_t id, ResultType result)
  56. : test_body(tb), id_to_fold(id), expected_result(result) {}
  57. std::string test_body;
  58. uint32_t id_to_fold;
  59. ResultType expected_result;
  60. };
  61. using IntegerInstructionFoldingTest =
  62. ::testing::TestWithParam<InstructionFoldingCase<uint32_t>>;
  63. TEST_P(IntegerInstructionFoldingTest, Case) {
  64. const auto& tc = GetParam();
  65. // Build module.
  66. std::unique_ptr<IRContext> context =
  67. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
  68. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  69. ASSERT_NE(nullptr, context);
  70. // Fold the instruction to test.
  71. analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
  72. Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
  73. bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
  74. // Make sure the instruction folded as expected.
  75. EXPECT_TRUE(succeeded);
  76. if (inst != nullptr) {
  77. EXPECT_EQ(inst->opcode(), SpvOpCopyObject);
  78. inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
  79. EXPECT_EQ(inst->opcode(), SpvOpConstant);
  80. analysis::ConstantManager* const_mrg = context->get_constant_mgr();
  81. const analysis::IntConstant* result =
  82. const_mrg->GetConstantFromInst(inst)->AsIntConstant();
  83. EXPECT_NE(result, nullptr);
  84. if (result != nullptr) {
  85. EXPECT_EQ(result->GetU32BitValue(), tc.expected_result);
  86. }
  87. }
  88. }
  89. // Returns a common SPIR-V header for all of the test that follow.
  90. #define INT_0_ID 100
  91. #define TRUE_ID 101
  92. #define VEC2_0_ID 102
  93. #define INT_7_ID 103
  94. #define FLOAT_0_ID 104
  95. #define DOUBLE_0_ID 105
  96. #define VEC4_0_ID 106
  97. #define DVEC4_0_ID 106
  98. #define HALF_0_ID 108
  99. const std::string& Header() {
  100. static const std::string header = R"(OpCapability Shader
  101. OpCapability Float16
  102. OpCapability Float64
  103. OpCapability Int16
  104. OpCapability Int64
  105. %1 = OpExtInstImport "GLSL.std.450"
  106. OpMemoryModel Logical GLSL450
  107. OpEntryPoint Fragment %main "main"
  108. OpExecutionMode %main OriginUpperLeft
  109. OpSource GLSL 140
  110. OpName %main "main"
  111. %void = OpTypeVoid
  112. %void_func = OpTypeFunction %void
  113. %bool = OpTypeBool
  114. %float = OpTypeFloat 32
  115. %double = OpTypeFloat 64
  116. %half = OpTypeFloat 16
  117. %101 = OpConstantTrue %bool ; Need a def with an numerical id to define id maps.
  118. %true = OpConstantTrue %bool
  119. %false = OpConstantFalse %bool
  120. %bool_null = OpConstantNull %bool
  121. %short = OpTypeInt 16 1
  122. %int = OpTypeInt 32 1
  123. %long = OpTypeInt 64 1
  124. %uint = OpTypeInt 32 0
  125. %v2int = OpTypeVector %int 2
  126. %v4int = OpTypeVector %int 4
  127. %v4float = OpTypeVector %float 4
  128. %v4double = OpTypeVector %double 4
  129. %v2float = OpTypeVector %float 2
  130. %v2double = OpTypeVector %double 2
  131. %v2bool = OpTypeVector %bool 2
  132. %struct_v2int_int_int = OpTypeStruct %v2int %int %int
  133. %_ptr_int = OpTypePointer Function %int
  134. %_ptr_uint = OpTypePointer Function %uint
  135. %_ptr_bool = OpTypePointer Function %bool
  136. %_ptr_float = OpTypePointer Function %float
  137. %_ptr_double = OpTypePointer Function %double
  138. %_ptr_half = OpTypePointer Function %half
  139. %_ptr_long = OpTypePointer Function %long
  140. %_ptr_v2int = OpTypePointer Function %v2int
  141. %_ptr_v4int = OpTypePointer Function %v4int
  142. %_ptr_v4float = OpTypePointer Function %v4float
  143. %_ptr_v4double = OpTypePointer Function %v4double
  144. %_ptr_struct_v2int_int_int = OpTypePointer Function %struct_v2int_int_int
  145. %_ptr_v2float = OpTypePointer Function %v2float
  146. %_ptr_v2double = OpTypePointer Function %v2double
  147. %short_0 = OpConstant %short 0
  148. %short_2 = OpConstant %short 2
  149. %short_3 = OpConstant %short 3
  150. %100 = OpConstant %int 0 ; Need a def with an numerical id to define id maps.
  151. %103 = OpConstant %int 7 ; Need a def with an numerical id to define id maps.
  152. %int_0 = OpConstant %int 0
  153. %int_1 = OpConstant %int 1
  154. %int_2 = OpConstant %int 2
  155. %int_3 = OpConstant %int 3
  156. %int_4 = OpConstant %int 4
  157. %int_n24 = OpConstant %int -24
  158. %int_min = OpConstant %int -2147483648
  159. %int_max = OpConstant %int 2147483647
  160. %long_0 = OpConstant %long 0
  161. %long_2 = OpConstant %long 2
  162. %long_3 = OpConstant %long 3
  163. %uint_0 = OpConstant %uint 0
  164. %uint_1 = OpConstant %uint 1
  165. %uint_2 = OpConstant %uint 2
  166. %uint_3 = OpConstant %uint 3
  167. %uint_4 = OpConstant %uint 4
  168. %uint_32 = OpConstant %uint 32
  169. %uint_42 = OpConstant %uint 42
  170. %uint_max = OpConstant %uint 4294967295
  171. %v2int_undef = OpUndef %v2int
  172. %v2int_0_0 = OpConstantComposite %v2int %int_0 %int_0
  173. %v2int_1_0 = OpConstantComposite %v2int %int_1 %int_0
  174. %v2int_2_2 = OpConstantComposite %v2int %int_2 %int_2
  175. %v2int_2_3 = OpConstantComposite %v2int %int_2 %int_3
  176. %v2int_3_2 = OpConstantComposite %v2int %int_3 %int_2
  177. %v2int_4_4 = OpConstantComposite %v2int %int_4 %int_4
  178. %v2bool_null = OpConstantNull %v2bool
  179. %v2bool_true_false = OpConstantComposite %v2bool %true %false
  180. %v2bool_false_true = OpConstantComposite %v2bool %false %true
  181. %struct_v2int_int_int_null = OpConstantNull %struct_v2int_int_int
  182. %v2int_null = OpConstantNull %v2int
  183. %102 = OpConstantComposite %v2int %103 %103
  184. %v4int_0_0_0_0 = OpConstantComposite %v4int %int_0 %int_0 %int_0 %int_0
  185. %struct_undef_0_0 = OpConstantComposite %struct_v2int_int_int %v2int_undef %int_0 %int_0
  186. %float_n1 = OpConstant %float -1
  187. %104 = OpConstant %float 0 ; Need a def with an numerical id to define id maps.
  188. %float_null = OpConstantNull %float
  189. %float_0 = OpConstant %float 0
  190. %float_1 = OpConstant %float 1
  191. %float_2 = OpConstant %float 2
  192. %float_3 = OpConstant %float 3
  193. %float_4 = OpConstant %float 4
  194. %float_0p5 = OpConstant %float 0.5
  195. %v2float_0_0 = OpConstantComposite %v2float %float_0 %float_0
  196. %v2float_2_2 = OpConstantComposite %v2float %float_2 %float_2
  197. %v2float_2_3 = OpConstantComposite %v2float %float_2 %float_3
  198. %v2float_3_2 = OpConstantComposite %v2float %float_3 %float_2
  199. %v2float_4_4 = OpConstantComposite %v2float %float_4 %float_4
  200. %v2float_2_0p5 = OpConstantComposite %v2float %float_2 %float_0p5
  201. %v2float_null = OpConstantNull %v2float
  202. %double_n1 = OpConstant %double -1
  203. %105 = OpConstant %double 0 ; Need a def with an numerical id to define id maps.
  204. %double_null = OpConstantNull %double
  205. %double_0 = OpConstant %double 0
  206. %double_1 = OpConstant %double 1
  207. %double_2 = OpConstant %double 2
  208. %double_3 = OpConstant %double 3
  209. %double_4 = OpConstant %double 4
  210. %double_0p5 = OpConstant %double 0.5
  211. %v2double_0_0 = OpConstantComposite %v2double %double_0 %double_0
  212. %v2double_2_2 = OpConstantComposite %v2double %double_2 %double_2
  213. %v2double_2_3 = OpConstantComposite %v2double %double_2 %double_3
  214. %v2double_3_2 = OpConstantComposite %v2double %double_3 %double_2
  215. %v2double_4_4 = OpConstantComposite %v2double %double_4 %double_4
  216. %v2double_2_0p5 = OpConstantComposite %v2double %double_2 %double_0p5
  217. %v2double_null = OpConstantNull %v2double
  218. %108 = OpConstant %half 0
  219. %half_1 = OpConstant %half 1
  220. %106 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
  221. %v4float_0_0_0_0 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
  222. %v4float_0_0_0_1 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_1
  223. %v4float_0_1_0_0 = OpConstantComposite %v4float %float_0 %float_1 %float_null %float_0
  224. %v4float_1_1_1_1 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
  225. %107 = OpConstantComposite %v4double %double_0 %double_0 %double_0 %double_0
  226. %v4double_0_0_0_0 = OpConstantComposite %v4double %double_0 %double_0 %double_0 %double_0
  227. %v4double_0_0_0_1 = OpConstantComposite %v4double %double_0 %double_0 %double_0 %double_1
  228. %v4double_0_1_0_0 = OpConstantComposite %v4double %double_0 %double_1 %double_null %double_0
  229. %v4double_1_1_1_1 = OpConstantComposite %v4double %double_1 %double_1 %double_1 %double_1
  230. %v4double_1_1_1_0p5 = OpConstantComposite %v4double %double_1 %double_1 %double_1 %double_0p5
  231. %v4double_null = OpConstantNull %v4double
  232. %v4float_n1_2_1_3 = OpConstantComposite %v4float %float_n1 %float_2 %float_1 %float_3
  233. )";
  234. return header;
  235. }
  236. // Returns the header with definitions of float NaN and double NaN. Since FC
  237. // "; CHECK: [[double_n0:%\\w+]] = OpConstant [[double]] -0\n" finds
  238. // %double_nan = OpConstant %double -0x1.8p+1024 instead of
  239. // %double_n0 = OpConstant %double -0,
  240. // we separates those definitions from Header().
  241. const std::string& HeaderWithNaN() {
  242. static const std::string headerWithNaN =
  243. Header() +
  244. R"(%float_nan = OpConstant %float -0x1.8p+128
  245. %double_nan = OpConstant %double -0x1.8p+1024
  246. )";
  247. return headerWithNaN;
  248. }
  249. // clang-format off
  250. INSTANTIATE_TEST_SUITE_P(TestCase, IntegerInstructionFoldingTest,
  251. ::testing::Values(
  252. // Test case 0: fold 0*n
  253. InstructionFoldingCase<uint32_t>(
  254. Header() + "%main = OpFunction %void None %void_func\n" +
  255. "%main_lab = OpLabel\n" +
  256. "%n = OpVariable %_ptr_int Function\n" +
  257. "%load = OpLoad %int %n\n" +
  258. "%2 = OpIMul %int %int_0 %load\n" +
  259. "OpReturn\n" +
  260. "OpFunctionEnd",
  261. 2, 0),
  262. // Test case 1: fold n*0
  263. InstructionFoldingCase<uint32_t>(
  264. Header() + "%main = OpFunction %void None %void_func\n" +
  265. "%main_lab = OpLabel\n" +
  266. "%n = OpVariable %_ptr_int Function\n" +
  267. "%load = OpLoad %int %n\n" +
  268. "%2 = OpIMul %int %load %int_0\n" +
  269. "OpReturn\n" +
  270. "OpFunctionEnd",
  271. 2, 0),
  272. // Test case 2: fold 0/n (signed)
  273. InstructionFoldingCase<uint32_t>(
  274. Header() + "%main = OpFunction %void None %void_func\n" +
  275. "%main_lab = OpLabel\n" +
  276. "%n = OpVariable %_ptr_int Function\n" +
  277. "%load = OpLoad %int %n\n" +
  278. "%2 = OpSDiv %int %int_0 %load\n" +
  279. "OpReturn\n" +
  280. "OpFunctionEnd",
  281. 2, 0),
  282. // Test case 3: fold n/0 (signed)
  283. InstructionFoldingCase<uint32_t>(
  284. Header() + "%main = OpFunction %void None %void_func\n" +
  285. "%main_lab = OpLabel\n" +
  286. "%n = OpVariable %_ptr_int Function\n" +
  287. "%load = OpLoad %int %n\n" +
  288. "%2 = OpSDiv %int %load %int_0\n" +
  289. "OpReturn\n" +
  290. "OpFunctionEnd",
  291. 2, 0),
  292. // Test case 4: fold 0/n (unsigned)
  293. InstructionFoldingCase<uint32_t>(
  294. Header() + "%main = OpFunction %void None %void_func\n" +
  295. "%main_lab = OpLabel\n" +
  296. "%n = OpVariable %_ptr_uint Function\n" +
  297. "%load = OpLoad %uint %n\n" +
  298. "%2 = OpUDiv %uint %uint_0 %load\n" +
  299. "OpReturn\n" +
  300. "OpFunctionEnd",
  301. 2, 0),
  302. // Test case 5: fold n/0 (unsigned)
  303. InstructionFoldingCase<uint32_t>(
  304. Header() + "%main = OpFunction %void None %void_func\n" +
  305. "%main_lab = OpLabel\n" +
  306. "%n = OpVariable %_ptr_int Function\n" +
  307. "%load = OpLoad %int %n\n" +
  308. "%2 = OpSDiv %int %load %int_0\n" +
  309. "OpReturn\n" +
  310. "OpFunctionEnd",
  311. 2, 0),
  312. // Test case 6: fold 0 remainder n
  313. InstructionFoldingCase<uint32_t>(
  314. Header() + "%main = OpFunction %void None %void_func\n" +
  315. "%main_lab = OpLabel\n" +
  316. "%n = OpVariable %_ptr_int Function\n" +
  317. "%load = OpLoad %int %n\n" +
  318. "%2 = OpSRem %int %int_0 %load\n" +
  319. "OpReturn\n" +
  320. "OpFunctionEnd",
  321. 2, 0),
  322. // Test case 7: fold n remainder 0
  323. InstructionFoldingCase<uint32_t>(
  324. Header() + "%main = OpFunction %void None %void_func\n" +
  325. "%main_lab = OpLabel\n" +
  326. "%n = OpVariable %_ptr_int Function\n" +
  327. "%load = OpLoad %int %n\n" +
  328. "%2 = OpSRem %int %load %int_0\n" +
  329. "OpReturn\n" +
  330. "OpFunctionEnd",
  331. 2, 0),
  332. // Test case 8: fold 0%n (signed)
  333. InstructionFoldingCase<uint32_t>(
  334. Header() + "%main = OpFunction %void None %void_func\n" +
  335. "%main_lab = OpLabel\n" +
  336. "%n = OpVariable %_ptr_int Function\n" +
  337. "%load = OpLoad %int %n\n" +
  338. "%2 = OpSMod %int %int_0 %load\n" +
  339. "OpReturn\n" +
  340. "OpFunctionEnd",
  341. 2, 0),
  342. // Test case 9: fold n%0 (signed)
  343. InstructionFoldingCase<uint32_t>(
  344. Header() + "%main = OpFunction %void None %void_func\n" +
  345. "%main_lab = OpLabel\n" +
  346. "%n = OpVariable %_ptr_int Function\n" +
  347. "%load = OpLoad %int %n\n" +
  348. "%2 = OpSMod %int %load %int_0\n" +
  349. "OpReturn\n" +
  350. "OpFunctionEnd",
  351. 2, 0),
  352. // Test case 10: fold 0%n (unsigned)
  353. InstructionFoldingCase<uint32_t>(
  354. Header() + "%main = OpFunction %void None %void_func\n" +
  355. "%main_lab = OpLabel\n" +
  356. "%n = OpVariable %_ptr_uint Function\n" +
  357. "%load = OpLoad %uint %n\n" +
  358. "%2 = OpUMod %uint %uint_0 %load\n" +
  359. "OpReturn\n" +
  360. "OpFunctionEnd",
  361. 2, 0),
  362. // Test case 11: fold n%0 (unsigned)
  363. InstructionFoldingCase<uint32_t>(
  364. Header() + "%main = OpFunction %void None %void_func\n" +
  365. "%main_lab = OpLabel\n" +
  366. "%n = OpVariable %_ptr_uint Function\n" +
  367. "%load = OpLoad %uint %n\n" +
  368. "%2 = OpUMod %uint %load %uint_0\n" +
  369. "OpReturn\n" +
  370. "OpFunctionEnd",
  371. 2, 0),
  372. // Test case 12: fold n << 32
  373. InstructionFoldingCase<uint32_t>(
  374. Header() + "%main = OpFunction %void None %void_func\n" +
  375. "%main_lab = OpLabel\n" +
  376. "%n = OpVariable %_ptr_uint Function\n" +
  377. "%load = OpLoad %uint %n\n" +
  378. "%2 = OpShiftLeftLogical %uint %load %uint_32\n" +
  379. "OpReturn\n" +
  380. "OpFunctionEnd",
  381. 2, 0),
  382. // Test case 13: fold n >> 32
  383. InstructionFoldingCase<uint32_t>(
  384. Header() + "%main = OpFunction %void None %void_func\n" +
  385. "%main_lab = OpLabel\n" +
  386. "%n = OpVariable %_ptr_uint Function\n" +
  387. "%load = OpLoad %uint %n\n" +
  388. "%2 = OpShiftRightLogical %uint %load %uint_32\n" +
  389. "OpReturn\n" +
  390. "OpFunctionEnd",
  391. 2, 0),
  392. // Test case 14: fold n | 0xFFFFFFFF
  393. InstructionFoldingCase<uint32_t>(
  394. Header() + "%main = OpFunction %void None %void_func\n" +
  395. "%main_lab = OpLabel\n" +
  396. "%n = OpVariable %_ptr_uint Function\n" +
  397. "%load = OpLoad %uint %n\n" +
  398. "%2 = OpBitwiseOr %uint %load %uint_max\n" +
  399. "OpReturn\n" +
  400. "OpFunctionEnd",
  401. 2, 0xFFFFFFFF),
  402. // Test case 15: fold 0xFFFFFFFF | n
  403. InstructionFoldingCase<uint32_t>(
  404. Header() + "%main = OpFunction %void None %void_func\n" +
  405. "%main_lab = OpLabel\n" +
  406. "%n = OpVariable %_ptr_uint Function\n" +
  407. "%load = OpLoad %uint %n\n" +
  408. "%2 = OpBitwiseOr %uint %uint_max %load\n" +
  409. "OpReturn\n" +
  410. "OpFunctionEnd",
  411. 2, 0xFFFFFFFF),
  412. // Test case 16: fold n & 0
  413. InstructionFoldingCase<uint32_t>(
  414. Header() + "%main = OpFunction %void None %void_func\n" +
  415. "%main_lab = OpLabel\n" +
  416. "%n = OpVariable %_ptr_uint Function\n" +
  417. "%load = OpLoad %uint %n\n" +
  418. "%2 = OpBitwiseAnd %uint %load %uint_0\n" +
  419. "OpReturn\n" +
  420. "OpFunctionEnd",
  421. 2, 0),
  422. // Test case 17: fold 1/0 (signed)
  423. InstructionFoldingCase<uint32_t>(
  424. Header() + "%main = OpFunction %void None %void_func\n" +
  425. "%main_lab = OpLabel\n" +
  426. "%2 = OpSDiv %int %int_1 %int_0\n" +
  427. "OpReturn\n" +
  428. "OpFunctionEnd",
  429. 2, 0),
  430. // Test case 18: fold 1/0 (unsigned)
  431. InstructionFoldingCase<uint32_t>(
  432. Header() + "%main = OpFunction %void None %void_func\n" +
  433. "%main_lab = OpLabel\n" +
  434. "%2 = OpUDiv %uint %uint_1 %uint_0\n" +
  435. "OpReturn\n" +
  436. "OpFunctionEnd",
  437. 2, 0),
  438. // Test case 19: fold OpSRem 1 0 (signed)
  439. InstructionFoldingCase<uint32_t>(
  440. Header() + "%main = OpFunction %void None %void_func\n" +
  441. "%main_lab = OpLabel\n" +
  442. "%2 = OpSRem %int %int_1 %int_0\n" +
  443. "OpReturn\n" +
  444. "OpFunctionEnd",
  445. 2, 0),
  446. // Test case 20: fold 1%0 (signed)
  447. InstructionFoldingCase<uint32_t>(
  448. Header() + "%main = OpFunction %void None %void_func\n" +
  449. "%main_lab = OpLabel\n" +
  450. "%2 = OpSMod %int %int_1 %int_0\n" +
  451. "OpReturn\n" +
  452. "OpFunctionEnd",
  453. 2, 0),
  454. // Test case 21: fold 1%0 (unsigned)
  455. InstructionFoldingCase<uint32_t>(
  456. Header() + "%main = OpFunction %void None %void_func\n" +
  457. "%main_lab = OpLabel\n" +
  458. "%2 = OpUMod %uint %uint_1 %uint_0\n" +
  459. "OpReturn\n" +
  460. "OpFunctionEnd",
  461. 2, 0),
  462. // Test case 22: fold unsigned n >> 42 (undefined, so set to zero).
  463. InstructionFoldingCase<uint32_t>(
  464. Header() + "%main = OpFunction %void None %void_func\n" +
  465. "%main_lab = OpLabel\n" +
  466. "%n = OpVariable %_ptr_uint Function\n" +
  467. "%load = OpLoad %uint %n\n" +
  468. "%2 = OpShiftRightLogical %uint %load %uint_42\n" +
  469. "OpReturn\n" +
  470. "OpFunctionEnd",
  471. 2, 0),
  472. // Test case 23: fold signed n >> 42 (undefined, so set to zero).
  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 = OpShiftRightLogical %int %load %uint_42\n" +
  479. "OpReturn\n" +
  480. "OpFunctionEnd",
  481. 2, 0),
  482. // Test case 24: fold n << 42 (undefined, so set to zero).
  483. InstructionFoldingCase<uint32_t>(
  484. Header() + "%main = OpFunction %void None %void_func\n" +
  485. "%main_lab = OpLabel\n" +
  486. "%n = OpVariable %_ptr_int Function\n" +
  487. "%load = OpLoad %int %n\n" +
  488. "%2 = OpShiftLeftLogical %int %load %uint_42\n" +
  489. "OpReturn\n" +
  490. "OpFunctionEnd",
  491. 2, 0),
  492. // Test case 25: fold -24 >> 32 (defined as -1)
  493. InstructionFoldingCase<uint32_t>(
  494. Header() + "%main = OpFunction %void None %void_func\n" +
  495. "%main_lab = OpLabel\n" +
  496. "%2 = OpShiftRightArithmetic %int %int_n24 %uint_32\n" +
  497. "OpReturn\n" +
  498. "OpFunctionEnd",
  499. 2, -1),
  500. // Test case 26: fold 2 >> 32 (signed)
  501. InstructionFoldingCase<uint32_t>(
  502. Header() + "%main = OpFunction %void None %void_func\n" +
  503. "%main_lab = OpLabel\n" +
  504. "%2 = OpShiftRightArithmetic %int %int_2 %uint_32\n" +
  505. "OpReturn\n" +
  506. "OpFunctionEnd",
  507. 2, 0),
  508. // Test case 27: fold 2 >> 32 (unsigned)
  509. InstructionFoldingCase<uint32_t>(
  510. Header() + "%main = OpFunction %void None %void_func\n" +
  511. "%main_lab = OpLabel\n" +
  512. "%2 = OpShiftRightLogical %int %int_2 %uint_32\n" +
  513. "OpReturn\n" +
  514. "OpFunctionEnd",
  515. 2, 0),
  516. // Test case 28: fold 2 << 32
  517. InstructionFoldingCase<uint32_t>(
  518. Header() + "%main = OpFunction %void None %void_func\n" +
  519. "%main_lab = OpLabel\n" +
  520. "%2 = OpShiftLeftLogical %int %int_2 %uint_32\n" +
  521. "OpReturn\n" +
  522. "OpFunctionEnd",
  523. 2, 0),
  524. // Test case 29: fold -INT_MIN
  525. InstructionFoldingCase<uint32_t>(
  526. Header() + "%main = OpFunction %void None %void_func\n" +
  527. "%main_lab = OpLabel\n" +
  528. "%2 = OpSNegate %int %int_min\n" +
  529. "OpReturn\n" +
  530. "OpFunctionEnd",
  531. 2, std::numeric_limits<int32_t>::min())
  532. ));
  533. // clang-format on
  534. using IntVectorInstructionFoldingTest =
  535. ::testing::TestWithParam<InstructionFoldingCase<std::vector<uint32_t>>>;
  536. TEST_P(IntVectorInstructionFoldingTest, Case) {
  537. const auto& tc = GetParam();
  538. // Build module.
  539. std::unique_ptr<IRContext> context =
  540. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
  541. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  542. ASSERT_NE(nullptr, context);
  543. // Fold the instruction to test.
  544. analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
  545. Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
  546. SpvOp original_opcode = inst->opcode();
  547. bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
  548. // Make sure the instruction folded as expected.
  549. EXPECT_EQ(succeeded, inst == nullptr || inst->opcode() != original_opcode);
  550. if (succeeded && inst != nullptr) {
  551. EXPECT_EQ(inst->opcode(), SpvOpCopyObject);
  552. inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
  553. std::vector<SpvOp> opcodes = {SpvOpConstantComposite};
  554. EXPECT_THAT(opcodes, Contains(inst->opcode()));
  555. analysis::ConstantManager* const_mrg = context->get_constant_mgr();
  556. const analysis::Constant* result = const_mrg->GetConstantFromInst(inst);
  557. EXPECT_NE(result, nullptr);
  558. if (result != nullptr) {
  559. const std::vector<const analysis::Constant*>& componenets =
  560. result->AsVectorConstant()->GetComponents();
  561. EXPECT_EQ(componenets.size(), tc.expected_result.size());
  562. for (size_t i = 0; i < componenets.size(); i++) {
  563. EXPECT_EQ(tc.expected_result[i], componenets[i]->GetU32());
  564. }
  565. }
  566. }
  567. }
  568. // clang-format off
  569. INSTANTIATE_TEST_SUITE_P(TestCase, IntVectorInstructionFoldingTest,
  570. ::testing::Values(
  571. // Test case 0: fold 0*n
  572. InstructionFoldingCase<std::vector<uint32_t>>(
  573. Header() + "%main = OpFunction %void None %void_func\n" +
  574. "%main_lab = OpLabel\n" +
  575. "%n = OpVariable %_ptr_int Function\n" +
  576. "%load = OpLoad %int %n\n" +
  577. "%2 = OpVectorShuffle %v2int %v2int_2_2 %v2int_2_3 0 3\n" +
  578. "OpReturn\n" +
  579. "OpFunctionEnd",
  580. 2, {2,3}),
  581. InstructionFoldingCase<std::vector<uint32_t>>(
  582. Header() + "%main = OpFunction %void None %void_func\n" +
  583. "%main_lab = OpLabel\n" +
  584. "%n = OpVariable %_ptr_int Function\n" +
  585. "%load = OpLoad %int %n\n" +
  586. "%2 = OpVectorShuffle %v2int %v2int_null %v2int_2_3 0 3\n" +
  587. "OpReturn\n" +
  588. "OpFunctionEnd",
  589. 2, {0,3}),
  590. InstructionFoldingCase<std::vector<uint32_t>>(
  591. Header() + "%main = OpFunction %void None %void_func\n" +
  592. "%main_lab = OpLabel\n" +
  593. "%n = OpVariable %_ptr_int Function\n" +
  594. "%load = OpLoad %int %n\n" +
  595. "%2 = OpVectorShuffle %v2int %v2int_null %v2int_2_3 4294967295 3\n" +
  596. "OpReturn\n" +
  597. "OpFunctionEnd",
  598. 2, {0,0}),
  599. InstructionFoldingCase<std::vector<uint32_t>>(
  600. Header() + "%main = OpFunction %void None %void_func\n" +
  601. "%main_lab = OpLabel\n" +
  602. "%n = OpVariable %_ptr_int Function\n" +
  603. "%load = OpLoad %int %n\n" +
  604. "%2 = OpVectorShuffle %v2int %v2int_null %v2int_2_3 0 4294967295 \n" +
  605. "OpReturn\n" +
  606. "OpFunctionEnd",
  607. 2, {0,0})
  608. ));
  609. // clang-format on
  610. using BooleanInstructionFoldingTest =
  611. ::testing::TestWithParam<InstructionFoldingCase<bool>>;
  612. TEST_P(BooleanInstructionFoldingTest, Case) {
  613. const auto& tc = GetParam();
  614. // Build module.
  615. std::unique_ptr<IRContext> context =
  616. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
  617. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  618. ASSERT_NE(nullptr, context);
  619. // Fold the instruction to test.
  620. analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
  621. Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
  622. bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
  623. // Make sure the instruction folded as expected.
  624. EXPECT_TRUE(succeeded);
  625. if (inst != nullptr) {
  626. EXPECT_EQ(inst->opcode(), SpvOpCopyObject);
  627. inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
  628. std::vector<SpvOp> bool_opcodes = {SpvOpConstantTrue, SpvOpConstantFalse};
  629. EXPECT_THAT(bool_opcodes, Contains(inst->opcode()));
  630. analysis::ConstantManager* const_mrg = context->get_constant_mgr();
  631. const analysis::BoolConstant* result =
  632. const_mrg->GetConstantFromInst(inst)->AsBoolConstant();
  633. EXPECT_NE(result, nullptr);
  634. if (result != nullptr) {
  635. EXPECT_EQ(result->value(), tc.expected_result);
  636. }
  637. }
  638. }
  639. // clang-format off
  640. INSTANTIATE_TEST_SUITE_P(TestCase, BooleanInstructionFoldingTest,
  641. ::testing::Values(
  642. // Test case 0: fold true || n
  643. InstructionFoldingCase<bool>(
  644. Header() + "%main = OpFunction %void None %void_func\n" +
  645. "%main_lab = OpLabel\n" +
  646. "%n = OpVariable %_ptr_bool Function\n" +
  647. "%load = OpLoad %bool %n\n" +
  648. "%2 = OpLogicalOr %bool %true %load\n" +
  649. "OpReturn\n" +
  650. "OpFunctionEnd",
  651. 2, true),
  652. // Test case 1: fold n || true
  653. InstructionFoldingCase<bool>(
  654. Header() + "%main = OpFunction %void None %void_func\n" +
  655. "%main_lab = OpLabel\n" +
  656. "%n = OpVariable %_ptr_bool Function\n" +
  657. "%load = OpLoad %bool %n\n" +
  658. "%2 = OpLogicalOr %bool %load %true\n" +
  659. "OpReturn\n" +
  660. "OpFunctionEnd",
  661. 2, true),
  662. // Test case 2: fold false && n
  663. InstructionFoldingCase<bool>(
  664. Header() + "%main = OpFunction %void None %void_func\n" +
  665. "%main_lab = OpLabel\n" +
  666. "%n = OpVariable %_ptr_bool Function\n" +
  667. "%load = OpLoad %bool %n\n" +
  668. "%2 = OpLogicalAnd %bool %false %load\n" +
  669. "OpReturn\n" +
  670. "OpFunctionEnd",
  671. 2, false),
  672. // Test case 3: fold n && false
  673. InstructionFoldingCase<bool>(
  674. Header() + "%main = OpFunction %void None %void_func\n" +
  675. "%main_lab = OpLabel\n" +
  676. "%n = OpVariable %_ptr_bool Function\n" +
  677. "%load = OpLoad %bool %n\n" +
  678. "%2 = OpLogicalAnd %bool %load %false\n" +
  679. "OpReturn\n" +
  680. "OpFunctionEnd",
  681. 2, false),
  682. // Test case 4: fold n < 0 (unsigned)
  683. InstructionFoldingCase<bool>(
  684. Header() + "%main = OpFunction %void None %void_func\n" +
  685. "%main_lab = OpLabel\n" +
  686. "%n = OpVariable %_ptr_uint Function\n" +
  687. "%load = OpLoad %uint %n\n" +
  688. "%2 = OpULessThan %bool %load %uint_0\n" +
  689. "OpReturn\n" +
  690. "OpFunctionEnd",
  691. 2, false),
  692. // Test case 5: fold UINT_MAX < n (unsigned)
  693. InstructionFoldingCase<bool>(
  694. Header() + "%main = OpFunction %void None %void_func\n" +
  695. "%main_lab = OpLabel\n" +
  696. "%n = OpVariable %_ptr_uint Function\n" +
  697. "%load = OpLoad %uint %n\n" +
  698. "%2 = OpULessThan %bool %uint_max %load\n" +
  699. "OpReturn\n" +
  700. "OpFunctionEnd",
  701. 2, false),
  702. // Test case 6: fold INT_MAX < n (signed)
  703. InstructionFoldingCase<bool>(
  704. Header() + "%main = OpFunction %void None %void_func\n" +
  705. "%main_lab = OpLabel\n" +
  706. "%n = OpVariable %_ptr_int Function\n" +
  707. "%load = OpLoad %int %n\n" +
  708. "%2 = OpSLessThan %bool %int_max %load\n" +
  709. "OpReturn\n" +
  710. "OpFunctionEnd",
  711. 2, false),
  712. // Test case 7: fold n < INT_MIN (signed)
  713. InstructionFoldingCase<bool>(
  714. Header() + "%main = OpFunction %void None %void_func\n" +
  715. "%main_lab = OpLabel\n" +
  716. "%n = OpVariable %_ptr_int Function\n" +
  717. "%load = OpLoad %int %n\n" +
  718. "%2 = OpSLessThan %bool %load %int_min\n" +
  719. "OpReturn\n" +
  720. "OpFunctionEnd",
  721. 2, false),
  722. // Test case 8: fold 0 > n (unsigned)
  723. InstructionFoldingCase<bool>(
  724. Header() + "%main = OpFunction %void None %void_func\n" +
  725. "%main_lab = OpLabel\n" +
  726. "%n = OpVariable %_ptr_uint Function\n" +
  727. "%load = OpLoad %uint %n\n" +
  728. "%2 = OpUGreaterThan %bool %uint_0 %load\n" +
  729. "OpReturn\n" +
  730. "OpFunctionEnd",
  731. 2, false),
  732. // Test case 9: fold n > UINT_MAX (unsigned)
  733. InstructionFoldingCase<bool>(
  734. Header() + "%main = OpFunction %void None %void_func\n" +
  735. "%main_lab = OpLabel\n" +
  736. "%n = OpVariable %_ptr_uint Function\n" +
  737. "%load = OpLoad %uint %n\n" +
  738. "%2 = OpUGreaterThan %bool %load %uint_max\n" +
  739. "OpReturn\n" +
  740. "OpFunctionEnd",
  741. 2, false),
  742. // Test case 10: fold n > INT_MAX (signed)
  743. InstructionFoldingCase<bool>(
  744. Header() + "%main = OpFunction %void None %void_func\n" +
  745. "%main_lab = OpLabel\n" +
  746. "%n = OpVariable %_ptr_int Function\n" +
  747. "%load = OpLoad %int %n\n" +
  748. "%2 = OpSGreaterThan %bool %load %int_max\n" +
  749. "OpReturn\n" +
  750. "OpFunctionEnd",
  751. 2, false),
  752. // Test case 11: fold INT_MIN > n (signed)
  753. InstructionFoldingCase<bool>(
  754. Header() + "%main = OpFunction %void None %void_func\n" +
  755. "%main_lab = OpLabel\n" +
  756. "%n = OpVariable %_ptr_uint Function\n" +
  757. "%load = OpLoad %uint %n\n" +
  758. "%2 = OpSGreaterThan %bool %int_min %load\n" +
  759. "OpReturn\n" +
  760. "OpFunctionEnd",
  761. 2, false),
  762. // Test case 12: fold 0 <= n (unsigned)
  763. InstructionFoldingCase<bool>(
  764. Header() + "%main = OpFunction %void None %void_func\n" +
  765. "%main_lab = OpLabel\n" +
  766. "%n = OpVariable %_ptr_uint Function\n" +
  767. "%load = OpLoad %uint %n\n" +
  768. "%2 = OpULessThanEqual %bool %uint_0 %load\n" +
  769. "OpReturn\n" +
  770. "OpFunctionEnd",
  771. 2, true),
  772. // Test case 13: fold n <= UINT_MAX (unsigned)
  773. InstructionFoldingCase<bool>(
  774. Header() + "%main = OpFunction %void None %void_func\n" +
  775. "%main_lab = OpLabel\n" +
  776. "%n = OpVariable %_ptr_uint Function\n" +
  777. "%load = OpLoad %uint %n\n" +
  778. "%2 = OpULessThanEqual %bool %load %uint_max\n" +
  779. "OpReturn\n" +
  780. "OpFunctionEnd",
  781. 2, true),
  782. // Test case 14: fold INT_MIN <= n (signed)
  783. InstructionFoldingCase<bool>(
  784. Header() + "%main = OpFunction %void None %void_func\n" +
  785. "%main_lab = OpLabel\n" +
  786. "%n = OpVariable %_ptr_int Function\n" +
  787. "%load = OpLoad %int %n\n" +
  788. "%2 = OpSLessThanEqual %bool %int_min %load\n" +
  789. "OpReturn\n" +
  790. "OpFunctionEnd",
  791. 2, true),
  792. // Test case 15: fold n <= INT_MAX (signed)
  793. InstructionFoldingCase<bool>(
  794. Header() + "%main = OpFunction %void None %void_func\n" +
  795. "%main_lab = OpLabel\n" +
  796. "%n = OpVariable %_ptr_int Function\n" +
  797. "%load = OpLoad %int %n\n" +
  798. "%2 = OpSLessThanEqual %bool %load %int_max\n" +
  799. "OpReturn\n" +
  800. "OpFunctionEnd",
  801. 2, true),
  802. // Test case 16: fold n >= 0 (unsigned)
  803. InstructionFoldingCase<bool>(
  804. Header() + "%main = OpFunction %void None %void_func\n" +
  805. "%main_lab = OpLabel\n" +
  806. "%n = OpVariable %_ptr_uint Function\n" +
  807. "%load = OpLoad %uint %n\n" +
  808. "%2 = OpUGreaterThanEqual %bool %load %uint_0\n" +
  809. "OpReturn\n" +
  810. "OpFunctionEnd",
  811. 2, true),
  812. // Test case 17: fold UINT_MAX >= n (unsigned)
  813. InstructionFoldingCase<bool>(
  814. Header() + "%main = OpFunction %void None %void_func\n" +
  815. "%main_lab = OpLabel\n" +
  816. "%n = OpVariable %_ptr_uint Function\n" +
  817. "%load = OpLoad %uint %n\n" +
  818. "%2 = OpUGreaterThanEqual %bool %uint_max %load\n" +
  819. "OpReturn\n" +
  820. "OpFunctionEnd",
  821. 2, true),
  822. // Test case 18: fold n >= INT_MIN (signed)
  823. InstructionFoldingCase<bool>(
  824. Header() + "%main = OpFunction %void None %void_func\n" +
  825. "%main_lab = OpLabel\n" +
  826. "%n = OpVariable %_ptr_int Function\n" +
  827. "%load = OpLoad %int %n\n" +
  828. "%2 = OpSGreaterThanEqual %bool %load %int_min\n" +
  829. "OpReturn\n" +
  830. "OpFunctionEnd",
  831. 2, true),
  832. // Test case 19: fold INT_MAX >= n (signed)
  833. InstructionFoldingCase<bool>(
  834. Header() + "%main = OpFunction %void None %void_func\n" +
  835. "%main_lab = OpLabel\n" +
  836. "%n = OpVariable %_ptr_int Function\n" +
  837. "%load = OpLoad %int %n\n" +
  838. "%2 = OpSGreaterThanEqual %bool %int_max %load\n" +
  839. "OpReturn\n" +
  840. "OpFunctionEnd",
  841. 2, true)
  842. ));
  843. INSTANTIATE_TEST_SUITE_P(FClampAndCmpLHS, BooleanInstructionFoldingTest,
  844. ::testing::Values(
  845. // Test case 0: fold 0.0 > clamp(n, 0.0, 1.0)
  846. InstructionFoldingCase<bool>(
  847. Header() + "%main = OpFunction %void None %void_func\n" +
  848. "%main_lab = OpLabel\n" +
  849. "%n = OpVariable %_ptr_float Function\n" +
  850. "%ld = OpLoad %float %n\n" +
  851. "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
  852. "%2 = OpFOrdGreaterThan %bool %float_0 %clamp\n" +
  853. "OpReturn\n" +
  854. "OpFunctionEnd",
  855. 2, false),
  856. // Test case 1: fold 0.0 > clamp(n, -1.0, -1.0)
  857. InstructionFoldingCase<bool>(
  858. Header() + "%main = OpFunction %void None %void_func\n" +
  859. "%main_lab = OpLabel\n" +
  860. "%n = OpVariable %_ptr_float Function\n" +
  861. "%ld = OpLoad %float %n\n" +
  862. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_n1\n" +
  863. "%2 = OpFOrdGreaterThan %bool %float_0 %clamp\n" +
  864. "OpReturn\n" +
  865. "OpFunctionEnd",
  866. 2, true),
  867. // Test case 2: fold 0.0 >= clamp(n, 1, 2)
  868. InstructionFoldingCase<bool>(
  869. Header() + "%main = OpFunction %void None %void_func\n" +
  870. "%main_lab = OpLabel\n" +
  871. "%n = OpVariable %_ptr_float Function\n" +
  872. "%ld = OpLoad %float %n\n" +
  873. "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
  874. "%2 = OpFOrdGreaterThanEqual %bool %float_0 %clamp\n" +
  875. "OpReturn\n" +
  876. "OpFunctionEnd",
  877. 2, false),
  878. // Test case 3: fold 0.0 >= clamp(n, -1.0, 0.0)
  879. InstructionFoldingCase<bool>(
  880. Header() + "%main = OpFunction %void None %void_func\n" +
  881. "%main_lab = OpLabel\n" +
  882. "%n = OpVariable %_ptr_float Function\n" +
  883. "%ld = OpLoad %float %n\n" +
  884. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
  885. "%2 = OpFOrdGreaterThanEqual %bool %float_0 %clamp\n" +
  886. "OpReturn\n" +
  887. "OpFunctionEnd",
  888. 2, true),
  889. // Test case 4: fold 0.0 <= clamp(n, 0.0, 1.0)
  890. InstructionFoldingCase<bool>(
  891. Header() + "%main = OpFunction %void None %void_func\n" +
  892. "%main_lab = OpLabel\n" +
  893. "%n = OpVariable %_ptr_float Function\n" +
  894. "%ld = OpLoad %float %n\n" +
  895. "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
  896. "%2 = OpFOrdLessThanEqual %bool %float_0 %clamp\n" +
  897. "OpReturn\n" +
  898. "OpFunctionEnd",
  899. 2, true),
  900. // Test case 5: fold 0.0 <= clamp(n, -1.0, -1.0)
  901. InstructionFoldingCase<bool>(
  902. Header() + "%main = OpFunction %void None %void_func\n" +
  903. "%main_lab = OpLabel\n" +
  904. "%n = OpVariable %_ptr_float Function\n" +
  905. "%ld = OpLoad %float %n\n" +
  906. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_n1\n" +
  907. "%2 = OpFOrdLessThanEqual %bool %float_0 %clamp\n" +
  908. "OpReturn\n" +
  909. "OpFunctionEnd",
  910. 2, false),
  911. // Test case 6: fold 0.0 < clamp(n, 1, 2)
  912. InstructionFoldingCase<bool>(
  913. Header() + "%main = OpFunction %void None %void_func\n" +
  914. "%main_lab = OpLabel\n" +
  915. "%n = OpVariable %_ptr_float Function\n" +
  916. "%ld = OpLoad %float %n\n" +
  917. "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
  918. "%2 = OpFOrdLessThan %bool %float_0 %clamp\n" +
  919. "OpReturn\n" +
  920. "OpFunctionEnd",
  921. 2, true),
  922. // Test case 7: fold 0.0 < clamp(n, -1.0, 0.0)
  923. InstructionFoldingCase<bool>(
  924. Header() + "%main = OpFunction %void None %void_func\n" +
  925. "%main_lab = OpLabel\n" +
  926. "%n = OpVariable %_ptr_float Function\n" +
  927. "%ld = OpLoad %float %n\n" +
  928. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
  929. "%2 = OpFOrdLessThan %bool %float_0 %clamp\n" +
  930. "OpReturn\n" +
  931. "OpFunctionEnd",
  932. 2, false),
  933. // Test case 8: fold 0.0 > clamp(n, 0.0, 1.0)
  934. InstructionFoldingCase<bool>(
  935. Header() + "%main = OpFunction %void None %void_func\n" +
  936. "%main_lab = OpLabel\n" +
  937. "%n = OpVariable %_ptr_float Function\n" +
  938. "%ld = OpLoad %float %n\n" +
  939. "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
  940. "%2 = OpFUnordGreaterThan %bool %float_0 %clamp\n" +
  941. "OpReturn\n" +
  942. "OpFunctionEnd",
  943. 2, false),
  944. // Test case 9: fold 0.0 > clamp(n, -1.0, -1.0)
  945. InstructionFoldingCase<bool>(
  946. Header() + "%main = OpFunction %void None %void_func\n" +
  947. "%main_lab = OpLabel\n" +
  948. "%n = OpVariable %_ptr_float Function\n" +
  949. "%ld = OpLoad %float %n\n" +
  950. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_n1\n" +
  951. "%2 = OpFUnordGreaterThan %bool %float_0 %clamp\n" +
  952. "OpReturn\n" +
  953. "OpFunctionEnd",
  954. 2, true),
  955. // Test case 10: fold 0.0 >= clamp(n, 1, 2)
  956. InstructionFoldingCase<bool>(
  957. Header() + "%main = OpFunction %void None %void_func\n" +
  958. "%main_lab = OpLabel\n" +
  959. "%n = OpVariable %_ptr_float Function\n" +
  960. "%ld = OpLoad %float %n\n" +
  961. "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
  962. "%2 = OpFUnordGreaterThanEqual %bool %float_0 %clamp\n" +
  963. "OpReturn\n" +
  964. "OpFunctionEnd",
  965. 2, false),
  966. // Test case 11: fold 0.0 >= clamp(n, -1.0, 0.0)
  967. InstructionFoldingCase<bool>(
  968. Header() + "%main = OpFunction %void None %void_func\n" +
  969. "%main_lab = OpLabel\n" +
  970. "%n = OpVariable %_ptr_float Function\n" +
  971. "%ld = OpLoad %float %n\n" +
  972. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
  973. "%2 = OpFUnordGreaterThanEqual %bool %float_0 %clamp\n" +
  974. "OpReturn\n" +
  975. "OpFunctionEnd",
  976. 2, true),
  977. // Test case 12: fold 0.0 <= clamp(n, 0.0, 1.0)
  978. InstructionFoldingCase<bool>(
  979. Header() + "%main = OpFunction %void None %void_func\n" +
  980. "%main_lab = OpLabel\n" +
  981. "%n = OpVariable %_ptr_float Function\n" +
  982. "%ld = OpLoad %float %n\n" +
  983. "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
  984. "%2 = OpFUnordLessThanEqual %bool %float_0 %clamp\n" +
  985. "OpReturn\n" +
  986. "OpFunctionEnd",
  987. 2, true),
  988. // Test case 13: fold 0.0 <= clamp(n, -1.0, -1.0)
  989. InstructionFoldingCase<bool>(
  990. Header() + "%main = OpFunction %void None %void_func\n" +
  991. "%main_lab = OpLabel\n" +
  992. "%n = OpVariable %_ptr_float Function\n" +
  993. "%ld = OpLoad %float %n\n" +
  994. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_n1\n" +
  995. "%2 = OpFUnordLessThanEqual %bool %float_0 %clamp\n" +
  996. "OpReturn\n" +
  997. "OpFunctionEnd",
  998. 2, false),
  999. // Test case 14: fold 0.0 < clamp(n, 1, 2)
  1000. InstructionFoldingCase<bool>(
  1001. Header() + "%main = OpFunction %void None %void_func\n" +
  1002. "%main_lab = OpLabel\n" +
  1003. "%n = OpVariable %_ptr_float Function\n" +
  1004. "%ld = OpLoad %float %n\n" +
  1005. "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
  1006. "%2 = OpFUnordLessThan %bool %float_0 %clamp\n" +
  1007. "OpReturn\n" +
  1008. "OpFunctionEnd",
  1009. 2, true),
  1010. // Test case 15: fold 0.0 < clamp(n, -1.0, 0.0)
  1011. InstructionFoldingCase<bool>(
  1012. Header() + "%main = OpFunction %void None %void_func\n" +
  1013. "%main_lab = OpLabel\n" +
  1014. "%n = OpVariable %_ptr_float Function\n" +
  1015. "%ld = OpLoad %float %n\n" +
  1016. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
  1017. "%2 = OpFUnordLessThan %bool %float_0 %clamp\n" +
  1018. "OpReturn\n" +
  1019. "OpFunctionEnd",
  1020. 2, false)
  1021. ));
  1022. INSTANTIATE_TEST_SUITE_P(FClampAndCmpRHS, BooleanInstructionFoldingTest,
  1023. ::testing::Values(
  1024. // Test case 0: fold clamp(n, 0.0, 1.0) > 1.0
  1025. InstructionFoldingCase<bool>(
  1026. Header() + "%main = OpFunction %void None %void_func\n" +
  1027. "%main_lab = OpLabel\n" +
  1028. "%n = OpVariable %_ptr_float Function\n" +
  1029. "%ld = OpLoad %float %n\n" +
  1030. "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
  1031. "%2 = OpFOrdGreaterThan %bool %clamp %float_1\n" +
  1032. "OpReturn\n" +
  1033. "OpFunctionEnd",
  1034. 2, false),
  1035. // Test case 1: fold clamp(n, 1.0, 1.0) > 0.0
  1036. InstructionFoldingCase<bool>(
  1037. Header() + "%main = OpFunction %void None %void_func\n" +
  1038. "%main_lab = OpLabel\n" +
  1039. "%n = OpVariable %_ptr_float Function\n" +
  1040. "%ld = OpLoad %float %n\n" +
  1041. "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_1\n" +
  1042. "%2 = OpFOrdGreaterThan %bool %clamp %float_0\n" +
  1043. "OpReturn\n" +
  1044. "OpFunctionEnd",
  1045. 2, true),
  1046. // Test case 2: fold clamp(n, 1, 2) >= 0.0
  1047. InstructionFoldingCase<bool>(
  1048. Header() + "%main = OpFunction %void None %void_func\n" +
  1049. "%main_lab = OpLabel\n" +
  1050. "%n = OpVariable %_ptr_float Function\n" +
  1051. "%ld = OpLoad %float %n\n" +
  1052. "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
  1053. "%2 = OpFOrdGreaterThanEqual %bool %clamp %float_0\n" +
  1054. "OpReturn\n" +
  1055. "OpFunctionEnd",
  1056. 2, true),
  1057. // Test case 3: fold clamp(n, 1.0, 2.0) >= 3.0
  1058. InstructionFoldingCase<bool>(
  1059. Header() + "%main = OpFunction %void None %void_func\n" +
  1060. "%main_lab = OpLabel\n" +
  1061. "%n = OpVariable %_ptr_float Function\n" +
  1062. "%ld = OpLoad %float %n\n" +
  1063. "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
  1064. "%2 = OpFOrdGreaterThanEqual %bool %clamp %float_3\n" +
  1065. "OpReturn\n" +
  1066. "OpFunctionEnd",
  1067. 2, false),
  1068. // Test case 4: fold clamp(n, 0.0, 1.0) <= 1.0
  1069. InstructionFoldingCase<bool>(
  1070. Header() + "%main = OpFunction %void None %void_func\n" +
  1071. "%main_lab = OpLabel\n" +
  1072. "%n = OpVariable %_ptr_float Function\n" +
  1073. "%ld = OpLoad %float %n\n" +
  1074. "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
  1075. "%2 = OpFOrdLessThanEqual %bool %clamp %float_1\n" +
  1076. "OpReturn\n" +
  1077. "OpFunctionEnd",
  1078. 2, true),
  1079. // Test case 5: fold clamp(n, 1.0, 2.0) <= 0.0
  1080. InstructionFoldingCase<bool>(
  1081. Header() + "%main = OpFunction %void None %void_func\n" +
  1082. "%main_lab = OpLabel\n" +
  1083. "%n = OpVariable %_ptr_float Function\n" +
  1084. "%ld = OpLoad %float %n\n" +
  1085. "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
  1086. "%2 = OpFOrdLessThanEqual %bool %clamp %float_0\n" +
  1087. "OpReturn\n" +
  1088. "OpFunctionEnd",
  1089. 2, false),
  1090. // Test case 6: fold clamp(n, 1, 2) < 3
  1091. InstructionFoldingCase<bool>(
  1092. Header() + "%main = OpFunction %void None %void_func\n" +
  1093. "%main_lab = OpLabel\n" +
  1094. "%n = OpVariable %_ptr_float Function\n" +
  1095. "%ld = OpLoad %float %n\n" +
  1096. "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
  1097. "%2 = OpFOrdLessThan %bool %clamp %float_3\n" +
  1098. "OpReturn\n" +
  1099. "OpFunctionEnd",
  1100. 2, true),
  1101. // Test case 7: fold clamp(n, -1.0, 0.0) < -1.0
  1102. InstructionFoldingCase<bool>(
  1103. Header() + "%main = OpFunction %void None %void_func\n" +
  1104. "%main_lab = OpLabel\n" +
  1105. "%n = OpVariable %_ptr_float Function\n" +
  1106. "%ld = OpLoad %float %n\n" +
  1107. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
  1108. "%2 = OpFOrdLessThan %bool %clamp %float_n1\n" +
  1109. "OpReturn\n" +
  1110. "OpFunctionEnd",
  1111. 2, false),
  1112. // Test case 8: fold clamp(n, 0.0, 1.0) > 1.0
  1113. InstructionFoldingCase<bool>(
  1114. Header() + "%main = OpFunction %void None %void_func\n" +
  1115. "%main_lab = OpLabel\n" +
  1116. "%n = OpVariable %_ptr_float Function\n" +
  1117. "%ld = OpLoad %float %n\n" +
  1118. "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
  1119. "%2 = OpFUnordGreaterThan %bool %clamp %float_1\n" +
  1120. "OpReturn\n" +
  1121. "OpFunctionEnd",
  1122. 2, false),
  1123. // Test case 9: fold clamp(n, 1.0, 2.0) > 0.0
  1124. InstructionFoldingCase<bool>(
  1125. Header() + "%main = OpFunction %void None %void_func\n" +
  1126. "%main_lab = OpLabel\n" +
  1127. "%n = OpVariable %_ptr_float Function\n" +
  1128. "%ld = OpLoad %float %n\n" +
  1129. "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
  1130. "%2 = OpFUnordGreaterThan %bool %clamp %float_0\n" +
  1131. "OpReturn\n" +
  1132. "OpFunctionEnd",
  1133. 2, true),
  1134. // Test case 10: fold clamp(n, 1, 2) >= 3.0
  1135. InstructionFoldingCase<bool>(
  1136. Header() + "%main = OpFunction %void None %void_func\n" +
  1137. "%main_lab = OpLabel\n" +
  1138. "%n = OpVariable %_ptr_float Function\n" +
  1139. "%ld = OpLoad %float %n\n" +
  1140. "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
  1141. "%2 = OpFUnordGreaterThanEqual %bool %clamp %float_3\n" +
  1142. "OpReturn\n" +
  1143. "OpFunctionEnd",
  1144. 2, false),
  1145. // Test case 11: fold clamp(n, -1.0, 0.0) >= -1.0
  1146. InstructionFoldingCase<bool>(
  1147. Header() + "%main = OpFunction %void None %void_func\n" +
  1148. "%main_lab = OpLabel\n" +
  1149. "%n = OpVariable %_ptr_float Function\n" +
  1150. "%ld = OpLoad %float %n\n" +
  1151. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
  1152. "%2 = OpFUnordGreaterThanEqual %bool %clamp %float_n1\n" +
  1153. "OpReturn\n" +
  1154. "OpFunctionEnd",
  1155. 2, true),
  1156. // Test case 12: fold clamp(n, 0.0, 1.0) <= 1.0
  1157. InstructionFoldingCase<bool>(
  1158. Header() + "%main = OpFunction %void None %void_func\n" +
  1159. "%main_lab = OpLabel\n" +
  1160. "%n = OpVariable %_ptr_float Function\n" +
  1161. "%ld = OpLoad %float %n\n" +
  1162. "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
  1163. "%2 = OpFUnordLessThanEqual %bool %clamp %float_1\n" +
  1164. "OpReturn\n" +
  1165. "OpFunctionEnd",
  1166. 2, true),
  1167. // Test case 13: fold clamp(n, 1.0, 1.0) <= 0.0
  1168. InstructionFoldingCase<bool>(
  1169. Header() + "%main = OpFunction %void None %void_func\n" +
  1170. "%main_lab = OpLabel\n" +
  1171. "%n = OpVariable %_ptr_float Function\n" +
  1172. "%ld = OpLoad %float %n\n" +
  1173. "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_1\n" +
  1174. "%2 = OpFUnordLessThanEqual %bool %clamp %float_0\n" +
  1175. "OpReturn\n" +
  1176. "OpFunctionEnd",
  1177. 2, false),
  1178. // Test case 14: fold clamp(n, 1, 2) < 3
  1179. InstructionFoldingCase<bool>(
  1180. Header() + "%main = OpFunction %void None %void_func\n" +
  1181. "%main_lab = OpLabel\n" +
  1182. "%n = OpVariable %_ptr_float Function\n" +
  1183. "%ld = OpLoad %float %n\n" +
  1184. "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
  1185. "%2 = OpFUnordLessThan %bool %clamp %float_3\n" +
  1186. "OpReturn\n" +
  1187. "OpFunctionEnd",
  1188. 2, true),
  1189. // Test case 15: fold clamp(n, -1.0, 0.0) < -1.0
  1190. InstructionFoldingCase<bool>(
  1191. Header() + "%main = OpFunction %void None %void_func\n" +
  1192. "%main_lab = OpLabel\n" +
  1193. "%n = OpVariable %_ptr_float Function\n" +
  1194. "%ld = OpLoad %float %n\n" +
  1195. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
  1196. "%2 = OpFUnordLessThan %bool %clamp %float_n1\n" +
  1197. "OpReturn\n" +
  1198. "OpFunctionEnd",
  1199. 2, false),
  1200. // Test case 16: fold clamp(n, -1.0, 0.0) < -1.0 (one test for double)
  1201. InstructionFoldingCase<bool>(
  1202. Header() + "%main = OpFunction %void None %void_func\n" +
  1203. "%main_lab = OpLabel\n" +
  1204. "%n = OpVariable %_ptr_double Function\n" +
  1205. "%ld = OpLoad %double %n\n" +
  1206. "%clamp = OpExtInst %double %1 FClamp %ld %double_n1 %double_0\n" +
  1207. "%2 = OpFUnordLessThan %bool %clamp %double_n1\n" +
  1208. "OpReturn\n" +
  1209. "OpFunctionEnd",
  1210. 2, false)
  1211. ));
  1212. // clang-format on
  1213. using FloatInstructionFoldingTest =
  1214. ::testing::TestWithParam<InstructionFoldingCase<float>>;
  1215. TEST_P(FloatInstructionFoldingTest, Case) {
  1216. const auto& tc = GetParam();
  1217. // Build module.
  1218. std::unique_ptr<IRContext> context =
  1219. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
  1220. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  1221. ASSERT_NE(nullptr, context);
  1222. // Fold the instruction to test.
  1223. analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
  1224. Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
  1225. bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
  1226. // Make sure the instruction folded as expected.
  1227. EXPECT_TRUE(succeeded);
  1228. if (inst != nullptr) {
  1229. EXPECT_EQ(inst->opcode(), SpvOpCopyObject);
  1230. inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
  1231. EXPECT_EQ(inst->opcode(), SpvOpConstant);
  1232. analysis::ConstantManager* const_mrg = context->get_constant_mgr();
  1233. const analysis::FloatConstant* result =
  1234. const_mrg->GetConstantFromInst(inst)->AsFloatConstant();
  1235. EXPECT_NE(result, nullptr);
  1236. if (result != nullptr) {
  1237. EXPECT_EQ(result->GetFloatValue(), tc.expected_result);
  1238. }
  1239. }
  1240. }
  1241. // Not testing NaNs because there are no expectations concerning NaNs according
  1242. // to the "Precision and Operation of SPIR-V Instructions" section of the Vulkan
  1243. // specification.
  1244. // clang-format off
  1245. INSTANTIATE_TEST_SUITE_P(FloatConstantFoldingTest, FloatInstructionFoldingTest,
  1246. ::testing::Values(
  1247. // Test case 0: Fold 2.0 - 1.0
  1248. InstructionFoldingCase<float>(
  1249. Header() + "%main = OpFunction %void None %void_func\n" +
  1250. "%main_lab = OpLabel\n" +
  1251. "%2 = OpFSub %float %float_2 %float_1\n" +
  1252. "OpReturn\n" +
  1253. "OpFunctionEnd",
  1254. 2, 1.0),
  1255. // Test case 1: Fold 2.0 + 1.0
  1256. InstructionFoldingCase<float>(
  1257. Header() + "%main = OpFunction %void None %void_func\n" +
  1258. "%main_lab = OpLabel\n" +
  1259. "%2 = OpFAdd %float %float_2 %float_1\n" +
  1260. "OpReturn\n" +
  1261. "OpFunctionEnd",
  1262. 2, 3.0),
  1263. // Test case 2: Fold 3.0 * 2.0
  1264. InstructionFoldingCase<float>(
  1265. Header() + "%main = OpFunction %void None %void_func\n" +
  1266. "%main_lab = OpLabel\n" +
  1267. "%2 = OpFMul %float %float_3 %float_2\n" +
  1268. "OpReturn\n" +
  1269. "OpFunctionEnd",
  1270. 2, 6.0),
  1271. // Test case 3: Fold 1.0 / 2.0
  1272. InstructionFoldingCase<float>(
  1273. Header() + "%main = OpFunction %void None %void_func\n" +
  1274. "%main_lab = OpLabel\n" +
  1275. "%2 = OpFDiv %float %float_1 %float_2\n" +
  1276. "OpReturn\n" +
  1277. "OpFunctionEnd",
  1278. 2, 0.5),
  1279. // Test case 4: Fold 1.0 / 0.0
  1280. InstructionFoldingCase<float>(
  1281. Header() + "%main = OpFunction %void None %void_func\n" +
  1282. "%main_lab = OpLabel\n" +
  1283. "%2 = OpFDiv %float %float_1 %float_0\n" +
  1284. "OpReturn\n" +
  1285. "OpFunctionEnd",
  1286. 2, std::numeric_limits<float>::infinity()),
  1287. // Test case 5: Fold -1.0 / 0.0
  1288. InstructionFoldingCase<float>(
  1289. Header() + "%main = OpFunction %void None %void_func\n" +
  1290. "%main_lab = OpLabel\n" +
  1291. "%2 = OpFDiv %float %float_n1 %float_0\n" +
  1292. "OpReturn\n" +
  1293. "OpFunctionEnd",
  1294. 2, -std::numeric_limits<float>::infinity()),
  1295. // Test case 6: Fold (2.0, 3.0) dot (2.0, 0.5)
  1296. InstructionFoldingCase<float>(
  1297. Header() + "%main = OpFunction %void None %void_func\n" +
  1298. "%main_lab = OpLabel\n" +
  1299. "%2 = OpDot %float %v2float_2_3 %v2float_2_0p5\n" +
  1300. "OpReturn\n" +
  1301. "OpFunctionEnd",
  1302. 2, 5.5f),
  1303. // Test case 7: Fold (0.0, 0.0) dot v
  1304. InstructionFoldingCase<float>(
  1305. Header() + "%main = OpFunction %void None %void_func\n" +
  1306. "%main_lab = OpLabel\n" +
  1307. "%v = OpVariable %_ptr_v2float Function\n" +
  1308. "%2 = OpLoad %v2float %v\n" +
  1309. "%3 = OpDot %float %v2float_0_0 %2\n" +
  1310. "OpReturn\n" +
  1311. "OpFunctionEnd",
  1312. 3, 0.0f),
  1313. // Test case 8: Fold v dot (0.0, 0.0)
  1314. InstructionFoldingCase<float>(
  1315. Header() + "%main = OpFunction %void None %void_func\n" +
  1316. "%main_lab = OpLabel\n" +
  1317. "%v = OpVariable %_ptr_v2float Function\n" +
  1318. "%2 = OpLoad %v2float %v\n" +
  1319. "%3 = OpDot %float %2 %v2float_0_0\n" +
  1320. "OpReturn\n" +
  1321. "OpFunctionEnd",
  1322. 3, 0.0f),
  1323. // Test case 9: Fold Null dot v
  1324. InstructionFoldingCase<float>(
  1325. Header() + "%main = OpFunction %void None %void_func\n" +
  1326. "%main_lab = OpLabel\n" +
  1327. "%v = OpVariable %_ptr_v2float Function\n" +
  1328. "%2 = OpLoad %v2float %v\n" +
  1329. "%3 = OpDot %float %v2float_null %2\n" +
  1330. "OpReturn\n" +
  1331. "OpFunctionEnd",
  1332. 3, 0.0f),
  1333. // Test case 10: Fold v dot Null
  1334. InstructionFoldingCase<float>(
  1335. Header() + "%main = OpFunction %void None %void_func\n" +
  1336. "%main_lab = OpLabel\n" +
  1337. "%v = OpVariable %_ptr_v2float Function\n" +
  1338. "%2 = OpLoad %v2float %v\n" +
  1339. "%3 = OpDot %float %2 %v2float_null\n" +
  1340. "OpReturn\n" +
  1341. "OpFunctionEnd",
  1342. 3, 0.0f),
  1343. // Test case 11: Fold -2.0
  1344. InstructionFoldingCase<float>(
  1345. Header() + "%main = OpFunction %void None %void_func\n" +
  1346. "%main_lab = OpLabel\n" +
  1347. "%2 = OpFNegate %float %float_2\n" +
  1348. "OpReturn\n" +
  1349. "OpFunctionEnd",
  1350. 2, -2)
  1351. ));
  1352. // clang-format on
  1353. using DoubleInstructionFoldingTest =
  1354. ::testing::TestWithParam<InstructionFoldingCase<double>>;
  1355. TEST_P(DoubleInstructionFoldingTest, Case) {
  1356. const auto& tc = GetParam();
  1357. // Build module.
  1358. std::unique_ptr<IRContext> context =
  1359. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
  1360. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  1361. ASSERT_NE(nullptr, context);
  1362. // Fold the instruction to test.
  1363. analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
  1364. Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
  1365. bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
  1366. // Make sure the instruction folded as expected.
  1367. EXPECT_TRUE(succeeded);
  1368. if (inst != nullptr) {
  1369. EXPECT_EQ(inst->opcode(), SpvOpCopyObject);
  1370. inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
  1371. EXPECT_EQ(inst->opcode(), SpvOpConstant);
  1372. analysis::ConstantManager* const_mrg = context->get_constant_mgr();
  1373. const analysis::FloatConstant* result =
  1374. const_mrg->GetConstantFromInst(inst)->AsFloatConstant();
  1375. EXPECT_NE(result, nullptr);
  1376. if (result != nullptr) {
  1377. EXPECT_EQ(result->GetDoubleValue(), tc.expected_result);
  1378. }
  1379. }
  1380. }
  1381. // clang-format off
  1382. INSTANTIATE_TEST_SUITE_P(DoubleConstantFoldingTest, DoubleInstructionFoldingTest,
  1383. ::testing::Values(
  1384. // Test case 0: Fold 2.0 - 1.0
  1385. InstructionFoldingCase<double>(
  1386. Header() + "%main = OpFunction %void None %void_func\n" +
  1387. "%main_lab = OpLabel\n" +
  1388. "%2 = OpFSub %double %double_2 %double_1\n" +
  1389. "OpReturn\n" +
  1390. "OpFunctionEnd",
  1391. 2, 1.0),
  1392. // Test case 1: Fold 2.0 + 1.0
  1393. InstructionFoldingCase<double>(
  1394. Header() + "%main = OpFunction %void None %void_func\n" +
  1395. "%main_lab = OpLabel\n" +
  1396. "%2 = OpFAdd %double %double_2 %double_1\n" +
  1397. "OpReturn\n" +
  1398. "OpFunctionEnd",
  1399. 2, 3.0),
  1400. // Test case 2: Fold 3.0 * 2.0
  1401. InstructionFoldingCase<double>(
  1402. Header() + "%main = OpFunction %void None %void_func\n" +
  1403. "%main_lab = OpLabel\n" +
  1404. "%2 = OpFMul %double %double_3 %double_2\n" +
  1405. "OpReturn\n" +
  1406. "OpFunctionEnd",
  1407. 2, 6.0),
  1408. // Test case 3: Fold 1.0 / 2.0
  1409. InstructionFoldingCase<double>(
  1410. Header() + "%main = OpFunction %void None %void_func\n" +
  1411. "%main_lab = OpLabel\n" +
  1412. "%2 = OpFDiv %double %double_1 %double_2\n" +
  1413. "OpReturn\n" +
  1414. "OpFunctionEnd",
  1415. 2, 0.5),
  1416. // Test case 4: Fold 1.0 / 0.0
  1417. InstructionFoldingCase<double>(
  1418. Header() + "%main = OpFunction %void None %void_func\n" +
  1419. "%main_lab = OpLabel\n" +
  1420. "%2 = OpFDiv %double %double_1 %double_0\n" +
  1421. "OpReturn\n" +
  1422. "OpFunctionEnd",
  1423. 2, std::numeric_limits<double>::infinity()),
  1424. // Test case 5: Fold -1.0 / 0.0
  1425. InstructionFoldingCase<double>(
  1426. Header() + "%main = OpFunction %void None %void_func\n" +
  1427. "%main_lab = OpLabel\n" +
  1428. "%2 = OpFDiv %double %double_n1 %double_0\n" +
  1429. "OpReturn\n" +
  1430. "OpFunctionEnd",
  1431. 2, -std::numeric_limits<double>::infinity()),
  1432. // Test case 6: Fold (2.0, 3.0) dot (2.0, 0.5)
  1433. InstructionFoldingCase<double>(
  1434. Header() + "%main = OpFunction %void None %void_func\n" +
  1435. "%main_lab = OpLabel\n" +
  1436. "%2 = OpDot %double %v2double_2_3 %v2double_2_0p5\n" +
  1437. "OpReturn\n" +
  1438. "OpFunctionEnd",
  1439. 2, 5.5f),
  1440. // Test case 7: Fold (0.0, 0.0) dot v
  1441. InstructionFoldingCase<double>(
  1442. Header() + "%main = OpFunction %void None %void_func\n" +
  1443. "%main_lab = OpLabel\n" +
  1444. "%v = OpVariable %_ptr_v2double Function\n" +
  1445. "%2 = OpLoad %v2double %v\n" +
  1446. "%3 = OpDot %double %v2double_0_0 %2\n" +
  1447. "OpReturn\n" +
  1448. "OpFunctionEnd",
  1449. 3, 0.0f),
  1450. // Test case 8: Fold v dot (0.0, 0.0)
  1451. InstructionFoldingCase<double>(
  1452. Header() + "%main = OpFunction %void None %void_func\n" +
  1453. "%main_lab = OpLabel\n" +
  1454. "%v = OpVariable %_ptr_v2double Function\n" +
  1455. "%2 = OpLoad %v2double %v\n" +
  1456. "%3 = OpDot %double %2 %v2double_0_0\n" +
  1457. "OpReturn\n" +
  1458. "OpFunctionEnd",
  1459. 3, 0.0f),
  1460. // Test case 9: Fold Null dot v
  1461. InstructionFoldingCase<double>(
  1462. Header() + "%main = OpFunction %void None %void_func\n" +
  1463. "%main_lab = OpLabel\n" +
  1464. "%v = OpVariable %_ptr_v2double Function\n" +
  1465. "%2 = OpLoad %v2double %v\n" +
  1466. "%3 = OpDot %double %v2double_null %2\n" +
  1467. "OpReturn\n" +
  1468. "OpFunctionEnd",
  1469. 3, 0.0f),
  1470. // Test case 10: Fold v dot Null
  1471. InstructionFoldingCase<double>(
  1472. Header() + "%main = OpFunction %void None %void_func\n" +
  1473. "%main_lab = OpLabel\n" +
  1474. "%v = OpVariable %_ptr_v2double Function\n" +
  1475. "%2 = OpLoad %v2double %v\n" +
  1476. "%3 = OpDot %double %2 %v2double_null\n" +
  1477. "OpReturn\n" +
  1478. "OpFunctionEnd",
  1479. 3, 0.0f),
  1480. // Test case 11: Fold -2.0
  1481. InstructionFoldingCase<double>(
  1482. Header() + "%main = OpFunction %void None %void_func\n" +
  1483. "%main_lab = OpLabel\n" +
  1484. "%2 = OpFNegate %double %double_2\n" +
  1485. "OpReturn\n" +
  1486. "OpFunctionEnd",
  1487. 2, -2)
  1488. ));
  1489. // clang-format on
  1490. // clang-format off
  1491. INSTANTIATE_TEST_SUITE_P(DoubleOrderedCompareConstantFoldingTest, BooleanInstructionFoldingTest,
  1492. ::testing::Values(
  1493. // Test case 0: fold 1.0 == 2.0
  1494. InstructionFoldingCase<bool>(
  1495. Header() + "%main = OpFunction %void None %void_func\n" +
  1496. "%main_lab = OpLabel\n" +
  1497. "%2 = OpFOrdEqual %bool %double_1 %double_2\n" +
  1498. "OpReturn\n" +
  1499. "OpFunctionEnd",
  1500. 2, false),
  1501. // Test case 1: fold 1.0 != 2.0
  1502. InstructionFoldingCase<bool>(
  1503. Header() + "%main = OpFunction %void None %void_func\n" +
  1504. "%main_lab = OpLabel\n" +
  1505. "%2 = OpFOrdNotEqual %bool %double_1 %double_2\n" +
  1506. "OpReturn\n" +
  1507. "OpFunctionEnd",
  1508. 2, true),
  1509. // Test case 2: fold 1.0 < 2.0
  1510. InstructionFoldingCase<bool>(
  1511. Header() + "%main = OpFunction %void None %void_func\n" +
  1512. "%main_lab = OpLabel\n" +
  1513. "%2 = OpFOrdLessThan %bool %double_1 %double_2\n" +
  1514. "OpReturn\n" +
  1515. "OpFunctionEnd",
  1516. 2, true),
  1517. // Test case 3: fold 1.0 > 2.0
  1518. InstructionFoldingCase<bool>(
  1519. Header() + "%main = OpFunction %void None %void_func\n" +
  1520. "%main_lab = OpLabel\n" +
  1521. "%2 = OpFOrdGreaterThan %bool %double_1 %double_2\n" +
  1522. "OpReturn\n" +
  1523. "OpFunctionEnd",
  1524. 2, false),
  1525. // Test case 4: fold 1.0 <= 2.0
  1526. InstructionFoldingCase<bool>(
  1527. Header() + "%main = OpFunction %void None %void_func\n" +
  1528. "%main_lab = OpLabel\n" +
  1529. "%2 = OpFOrdLessThanEqual %bool %double_1 %double_2\n" +
  1530. "OpReturn\n" +
  1531. "OpFunctionEnd",
  1532. 2, true),
  1533. // Test case 5: fold 1.0 >= 2.0
  1534. InstructionFoldingCase<bool>(
  1535. Header() + "%main = OpFunction %void None %void_func\n" +
  1536. "%main_lab = OpLabel\n" +
  1537. "%2 = OpFOrdGreaterThanEqual %bool %double_1 %double_2\n" +
  1538. "OpReturn\n" +
  1539. "OpFunctionEnd",
  1540. 2, false),
  1541. // Test case 6: fold 1.0 == 1.0
  1542. InstructionFoldingCase<bool>(
  1543. Header() + "%main = OpFunction %void None %void_func\n" +
  1544. "%main_lab = OpLabel\n" +
  1545. "%2 = OpFOrdEqual %bool %double_1 %double_1\n" +
  1546. "OpReturn\n" +
  1547. "OpFunctionEnd",
  1548. 2, true),
  1549. // Test case 7: fold 1.0 != 1.0
  1550. InstructionFoldingCase<bool>(
  1551. Header() + "%main = OpFunction %void None %void_func\n" +
  1552. "%main_lab = OpLabel\n" +
  1553. "%2 = OpFOrdNotEqual %bool %double_1 %double_1\n" +
  1554. "OpReturn\n" +
  1555. "OpFunctionEnd",
  1556. 2, false),
  1557. // Test case 8: fold 1.0 < 1.0
  1558. InstructionFoldingCase<bool>(
  1559. Header() + "%main = OpFunction %void None %void_func\n" +
  1560. "%main_lab = OpLabel\n" +
  1561. "%2 = OpFOrdLessThan %bool %double_1 %double_1\n" +
  1562. "OpReturn\n" +
  1563. "OpFunctionEnd",
  1564. 2, false),
  1565. // Test case 9: fold 1.0 > 1.0
  1566. InstructionFoldingCase<bool>(
  1567. Header() + "%main = OpFunction %void None %void_func\n" +
  1568. "%main_lab = OpLabel\n" +
  1569. "%2 = OpFOrdGreaterThan %bool %double_1 %double_1\n" +
  1570. "OpReturn\n" +
  1571. "OpFunctionEnd",
  1572. 2, false),
  1573. // Test case 10: fold 1.0 <= 1.0
  1574. InstructionFoldingCase<bool>(
  1575. Header() + "%main = OpFunction %void None %void_func\n" +
  1576. "%main_lab = OpLabel\n" +
  1577. "%2 = OpFOrdLessThanEqual %bool %double_1 %double_1\n" +
  1578. "OpReturn\n" +
  1579. "OpFunctionEnd",
  1580. 2, true),
  1581. // Test case 11: fold 1.0 >= 1.0
  1582. InstructionFoldingCase<bool>(
  1583. Header() + "%main = OpFunction %void None %void_func\n" +
  1584. "%main_lab = OpLabel\n" +
  1585. "%2 = OpFOrdGreaterThanEqual %bool %double_1 %double_1\n" +
  1586. "OpReturn\n" +
  1587. "OpFunctionEnd",
  1588. 2, true),
  1589. // Test case 12: fold 2.0 < 1.0
  1590. InstructionFoldingCase<bool>(
  1591. Header() + "%main = OpFunction %void None %void_func\n" +
  1592. "%main_lab = OpLabel\n" +
  1593. "%2 = OpFOrdLessThan %bool %double_2 %double_1\n" +
  1594. "OpReturn\n" +
  1595. "OpFunctionEnd",
  1596. 2, false),
  1597. // Test case 13: fold 2.0 > 1.0
  1598. InstructionFoldingCase<bool>(
  1599. Header() + "%main = OpFunction %void None %void_func\n" +
  1600. "%main_lab = OpLabel\n" +
  1601. "%2 = OpFOrdGreaterThan %bool %double_2 %double_1\n" +
  1602. "OpReturn\n" +
  1603. "OpFunctionEnd",
  1604. 2, true),
  1605. // Test case 14: fold 2.0 <= 1.0
  1606. InstructionFoldingCase<bool>(
  1607. Header() + "%main = OpFunction %void None %void_func\n" +
  1608. "%main_lab = OpLabel\n" +
  1609. "%2 = OpFOrdLessThanEqual %bool %double_2 %double_1\n" +
  1610. "OpReturn\n" +
  1611. "OpFunctionEnd",
  1612. 2, false),
  1613. // Test case 15: fold 2.0 >= 1.0
  1614. InstructionFoldingCase<bool>(
  1615. Header() + "%main = OpFunction %void None %void_func\n" +
  1616. "%main_lab = OpLabel\n" +
  1617. "%2 = OpFOrdGreaterThanEqual %bool %double_2 %double_1\n" +
  1618. "OpReturn\n" +
  1619. "OpFunctionEnd",
  1620. 2, true)
  1621. ));
  1622. INSTANTIATE_TEST_SUITE_P(DoubleUnorderedCompareConstantFoldingTest, BooleanInstructionFoldingTest,
  1623. ::testing::Values(
  1624. // Test case 0: fold 1.0 == 2.0
  1625. InstructionFoldingCase<bool>(
  1626. Header() + "%main = OpFunction %void None %void_func\n" +
  1627. "%main_lab = OpLabel\n" +
  1628. "%2 = OpFUnordEqual %bool %double_1 %double_2\n" +
  1629. "OpReturn\n" +
  1630. "OpFunctionEnd",
  1631. 2, false),
  1632. // Test case 1: fold 1.0 != 2.0
  1633. InstructionFoldingCase<bool>(
  1634. Header() + "%main = OpFunction %void None %void_func\n" +
  1635. "%main_lab = OpLabel\n" +
  1636. "%2 = OpFUnordNotEqual %bool %double_1 %double_2\n" +
  1637. "OpReturn\n" +
  1638. "OpFunctionEnd",
  1639. 2, true),
  1640. // Test case 2: fold 1.0 < 2.0
  1641. InstructionFoldingCase<bool>(
  1642. Header() + "%main = OpFunction %void None %void_func\n" +
  1643. "%main_lab = OpLabel\n" +
  1644. "%2 = OpFUnordLessThan %bool %double_1 %double_2\n" +
  1645. "OpReturn\n" +
  1646. "OpFunctionEnd",
  1647. 2, true),
  1648. // Test case 3: fold 1.0 > 2.0
  1649. InstructionFoldingCase<bool>(
  1650. Header() + "%main = OpFunction %void None %void_func\n" +
  1651. "%main_lab = OpLabel\n" +
  1652. "%2 = OpFUnordGreaterThan %bool %double_1 %double_2\n" +
  1653. "OpReturn\n" +
  1654. "OpFunctionEnd",
  1655. 2, false),
  1656. // Test case 4: fold 1.0 <= 2.0
  1657. InstructionFoldingCase<bool>(
  1658. Header() + "%main = OpFunction %void None %void_func\n" +
  1659. "%main_lab = OpLabel\n" +
  1660. "%2 = OpFUnordLessThanEqual %bool %double_1 %double_2\n" +
  1661. "OpReturn\n" +
  1662. "OpFunctionEnd",
  1663. 2, true),
  1664. // Test case 5: fold 1.0 >= 2.0
  1665. InstructionFoldingCase<bool>(
  1666. Header() + "%main = OpFunction %void None %void_func\n" +
  1667. "%main_lab = OpLabel\n" +
  1668. "%2 = OpFUnordGreaterThanEqual %bool %double_1 %double_2\n" +
  1669. "OpReturn\n" +
  1670. "OpFunctionEnd",
  1671. 2, false),
  1672. // Test case 6: fold 1.0 == 1.0
  1673. InstructionFoldingCase<bool>(
  1674. Header() + "%main = OpFunction %void None %void_func\n" +
  1675. "%main_lab = OpLabel\n" +
  1676. "%2 = OpFUnordEqual %bool %double_1 %double_1\n" +
  1677. "OpReturn\n" +
  1678. "OpFunctionEnd",
  1679. 2, true),
  1680. // Test case 7: fold 1.0 != 1.0
  1681. InstructionFoldingCase<bool>(
  1682. Header() + "%main = OpFunction %void None %void_func\n" +
  1683. "%main_lab = OpLabel\n" +
  1684. "%2 = OpFUnordNotEqual %bool %double_1 %double_1\n" +
  1685. "OpReturn\n" +
  1686. "OpFunctionEnd",
  1687. 2, false),
  1688. // Test case 8: fold 1.0 < 1.0
  1689. InstructionFoldingCase<bool>(
  1690. Header() + "%main = OpFunction %void None %void_func\n" +
  1691. "%main_lab = OpLabel\n" +
  1692. "%2 = OpFUnordLessThan %bool %double_1 %double_1\n" +
  1693. "OpReturn\n" +
  1694. "OpFunctionEnd",
  1695. 2, false),
  1696. // Test case 9: fold 1.0 > 1.0
  1697. InstructionFoldingCase<bool>(
  1698. Header() + "%main = OpFunction %void None %void_func\n" +
  1699. "%main_lab = OpLabel\n" +
  1700. "%2 = OpFUnordGreaterThan %bool %double_1 %double_1\n" +
  1701. "OpReturn\n" +
  1702. "OpFunctionEnd",
  1703. 2, false),
  1704. // Test case 10: fold 1.0 <= 1.0
  1705. InstructionFoldingCase<bool>(
  1706. Header() + "%main = OpFunction %void None %void_func\n" +
  1707. "%main_lab = OpLabel\n" +
  1708. "%2 = OpFUnordLessThanEqual %bool %double_1 %double_1\n" +
  1709. "OpReturn\n" +
  1710. "OpFunctionEnd",
  1711. 2, true),
  1712. // Test case 11: fold 1.0 >= 1.0
  1713. InstructionFoldingCase<bool>(
  1714. Header() + "%main = OpFunction %void None %void_func\n" +
  1715. "%main_lab = OpLabel\n" +
  1716. "%2 = OpFUnordGreaterThanEqual %bool %double_1 %double_1\n" +
  1717. "OpReturn\n" +
  1718. "OpFunctionEnd",
  1719. 2, true),
  1720. // Test case 12: fold 2.0 < 1.0
  1721. InstructionFoldingCase<bool>(
  1722. Header() + "%main = OpFunction %void None %void_func\n" +
  1723. "%main_lab = OpLabel\n" +
  1724. "%2 = OpFUnordLessThan %bool %double_2 %double_1\n" +
  1725. "OpReturn\n" +
  1726. "OpFunctionEnd",
  1727. 2, false),
  1728. // Test case 13: fold 2.0 > 1.0
  1729. InstructionFoldingCase<bool>(
  1730. Header() + "%main = OpFunction %void None %void_func\n" +
  1731. "%main_lab = OpLabel\n" +
  1732. "%2 = OpFUnordGreaterThan %bool %double_2 %double_1\n" +
  1733. "OpReturn\n" +
  1734. "OpFunctionEnd",
  1735. 2, true),
  1736. // Test case 14: fold 2.0 <= 1.0
  1737. InstructionFoldingCase<bool>(
  1738. Header() + "%main = OpFunction %void None %void_func\n" +
  1739. "%main_lab = OpLabel\n" +
  1740. "%2 = OpFUnordLessThanEqual %bool %double_2 %double_1\n" +
  1741. "OpReturn\n" +
  1742. "OpFunctionEnd",
  1743. 2, false),
  1744. // Test case 15: fold 2.0 >= 1.0
  1745. InstructionFoldingCase<bool>(
  1746. Header() + "%main = OpFunction %void None %void_func\n" +
  1747. "%main_lab = OpLabel\n" +
  1748. "%2 = OpFUnordGreaterThanEqual %bool %double_2 %double_1\n" +
  1749. "OpReturn\n" +
  1750. "OpFunctionEnd",
  1751. 2, true)
  1752. ));
  1753. INSTANTIATE_TEST_SUITE_P(FloatOrderedCompareConstantFoldingTest, BooleanInstructionFoldingTest,
  1754. ::testing::Values(
  1755. // Test case 0: fold 1.0 == 2.0
  1756. InstructionFoldingCase<bool>(
  1757. Header() + "%main = OpFunction %void None %void_func\n" +
  1758. "%main_lab = OpLabel\n" +
  1759. "%2 = OpFOrdEqual %bool %float_1 %float_2\n" +
  1760. "OpReturn\n" +
  1761. "OpFunctionEnd",
  1762. 2, false),
  1763. // Test case 1: fold 1.0 != 2.0
  1764. InstructionFoldingCase<bool>(
  1765. Header() + "%main = OpFunction %void None %void_func\n" +
  1766. "%main_lab = OpLabel\n" +
  1767. "%2 = OpFOrdNotEqual %bool %float_1 %float_2\n" +
  1768. "OpReturn\n" +
  1769. "OpFunctionEnd",
  1770. 2, true),
  1771. // Test case 2: fold 1.0 < 2.0
  1772. InstructionFoldingCase<bool>(
  1773. Header() + "%main = OpFunction %void None %void_func\n" +
  1774. "%main_lab = OpLabel\n" +
  1775. "%2 = OpFOrdLessThan %bool %float_1 %float_2\n" +
  1776. "OpReturn\n" +
  1777. "OpFunctionEnd",
  1778. 2, true),
  1779. // Test case 3: fold 1.0 > 2.0
  1780. InstructionFoldingCase<bool>(
  1781. Header() + "%main = OpFunction %void None %void_func\n" +
  1782. "%main_lab = OpLabel\n" +
  1783. "%2 = OpFOrdGreaterThan %bool %float_1 %float_2\n" +
  1784. "OpReturn\n" +
  1785. "OpFunctionEnd",
  1786. 2, false),
  1787. // Test case 4: fold 1.0 <= 2.0
  1788. InstructionFoldingCase<bool>(
  1789. Header() + "%main = OpFunction %void None %void_func\n" +
  1790. "%main_lab = OpLabel\n" +
  1791. "%2 = OpFOrdLessThanEqual %bool %float_1 %float_2\n" +
  1792. "OpReturn\n" +
  1793. "OpFunctionEnd",
  1794. 2, true),
  1795. // Test case 5: fold 1.0 >= 2.0
  1796. InstructionFoldingCase<bool>(
  1797. Header() + "%main = OpFunction %void None %void_func\n" +
  1798. "%main_lab = OpLabel\n" +
  1799. "%2 = OpFOrdGreaterThanEqual %bool %float_1 %float_2\n" +
  1800. "OpReturn\n" +
  1801. "OpFunctionEnd",
  1802. 2, false),
  1803. // Test case 6: fold 1.0 == 1.0
  1804. InstructionFoldingCase<bool>(
  1805. Header() + "%main = OpFunction %void None %void_func\n" +
  1806. "%main_lab = OpLabel\n" +
  1807. "%2 = OpFOrdEqual %bool %float_1 %float_1\n" +
  1808. "OpReturn\n" +
  1809. "OpFunctionEnd",
  1810. 2, true),
  1811. // Test case 7: fold 1.0 != 1.0
  1812. InstructionFoldingCase<bool>(
  1813. Header() + "%main = OpFunction %void None %void_func\n" +
  1814. "%main_lab = OpLabel\n" +
  1815. "%2 = OpFOrdNotEqual %bool %float_1 %float_1\n" +
  1816. "OpReturn\n" +
  1817. "OpFunctionEnd",
  1818. 2, false),
  1819. // Test case 8: fold 1.0 < 1.0
  1820. InstructionFoldingCase<bool>(
  1821. Header() + "%main = OpFunction %void None %void_func\n" +
  1822. "%main_lab = OpLabel\n" +
  1823. "%2 = OpFOrdLessThan %bool %float_1 %float_1\n" +
  1824. "OpReturn\n" +
  1825. "OpFunctionEnd",
  1826. 2, false),
  1827. // Test case 9: fold 1.0 > 1.0
  1828. InstructionFoldingCase<bool>(
  1829. Header() + "%main = OpFunction %void None %void_func\n" +
  1830. "%main_lab = OpLabel\n" +
  1831. "%2 = OpFOrdGreaterThan %bool %float_1 %float_1\n" +
  1832. "OpReturn\n" +
  1833. "OpFunctionEnd",
  1834. 2, false),
  1835. // Test case 10: fold 1.0 <= 1.0
  1836. InstructionFoldingCase<bool>(
  1837. Header() + "%main = OpFunction %void None %void_func\n" +
  1838. "%main_lab = OpLabel\n" +
  1839. "%2 = OpFOrdLessThanEqual %bool %float_1 %float_1\n" +
  1840. "OpReturn\n" +
  1841. "OpFunctionEnd",
  1842. 2, true),
  1843. // Test case 11: fold 1.0 >= 1.0
  1844. InstructionFoldingCase<bool>(
  1845. Header() + "%main = OpFunction %void None %void_func\n" +
  1846. "%main_lab = OpLabel\n" +
  1847. "%2 = OpFOrdGreaterThanEqual %bool %float_1 %float_1\n" +
  1848. "OpReturn\n" +
  1849. "OpFunctionEnd",
  1850. 2, true),
  1851. // Test case 12: fold 2.0 < 1.0
  1852. InstructionFoldingCase<bool>(
  1853. Header() + "%main = OpFunction %void None %void_func\n" +
  1854. "%main_lab = OpLabel\n" +
  1855. "%2 = OpFOrdLessThan %bool %float_2 %float_1\n" +
  1856. "OpReturn\n" +
  1857. "OpFunctionEnd",
  1858. 2, false),
  1859. // Test case 13: fold 2.0 > 1.0
  1860. InstructionFoldingCase<bool>(
  1861. Header() + "%main = OpFunction %void None %void_func\n" +
  1862. "%main_lab = OpLabel\n" +
  1863. "%2 = OpFOrdGreaterThan %bool %float_2 %float_1\n" +
  1864. "OpReturn\n" +
  1865. "OpFunctionEnd",
  1866. 2, true),
  1867. // Test case 14: fold 2.0 <= 1.0
  1868. InstructionFoldingCase<bool>(
  1869. Header() + "%main = OpFunction %void None %void_func\n" +
  1870. "%main_lab = OpLabel\n" +
  1871. "%2 = OpFOrdLessThanEqual %bool %float_2 %float_1\n" +
  1872. "OpReturn\n" +
  1873. "OpFunctionEnd",
  1874. 2, false),
  1875. // Test case 15: fold 2.0 >= 1.0
  1876. InstructionFoldingCase<bool>(
  1877. Header() + "%main = OpFunction %void None %void_func\n" +
  1878. "%main_lab = OpLabel\n" +
  1879. "%2 = OpFOrdGreaterThanEqual %bool %float_2 %float_1\n" +
  1880. "OpReturn\n" +
  1881. "OpFunctionEnd",
  1882. 2, true)
  1883. ));
  1884. INSTANTIATE_TEST_SUITE_P(FloatUnorderedCompareConstantFoldingTest, BooleanInstructionFoldingTest,
  1885. ::testing::Values(
  1886. // Test case 0: fold 1.0 == 2.0
  1887. InstructionFoldingCase<bool>(
  1888. Header() + "%main = OpFunction %void None %void_func\n" +
  1889. "%main_lab = OpLabel\n" +
  1890. "%2 = OpFUnordEqual %bool %float_1 %float_2\n" +
  1891. "OpReturn\n" +
  1892. "OpFunctionEnd",
  1893. 2, false),
  1894. // Test case 1: fold 1.0 != 2.0
  1895. InstructionFoldingCase<bool>(
  1896. Header() + "%main = OpFunction %void None %void_func\n" +
  1897. "%main_lab = OpLabel\n" +
  1898. "%2 = OpFUnordNotEqual %bool %float_1 %float_2\n" +
  1899. "OpReturn\n" +
  1900. "OpFunctionEnd",
  1901. 2, true),
  1902. // Test case 2: fold 1.0 < 2.0
  1903. InstructionFoldingCase<bool>(
  1904. Header() + "%main = OpFunction %void None %void_func\n" +
  1905. "%main_lab = OpLabel\n" +
  1906. "%2 = OpFUnordLessThan %bool %float_1 %float_2\n" +
  1907. "OpReturn\n" +
  1908. "OpFunctionEnd",
  1909. 2, true),
  1910. // Test case 3: fold 1.0 > 2.0
  1911. InstructionFoldingCase<bool>(
  1912. Header() + "%main = OpFunction %void None %void_func\n" +
  1913. "%main_lab = OpLabel\n" +
  1914. "%2 = OpFUnordGreaterThan %bool %float_1 %float_2\n" +
  1915. "OpReturn\n" +
  1916. "OpFunctionEnd",
  1917. 2, false),
  1918. // Test case 4: fold 1.0 <= 2.0
  1919. InstructionFoldingCase<bool>(
  1920. Header() + "%main = OpFunction %void None %void_func\n" +
  1921. "%main_lab = OpLabel\n" +
  1922. "%2 = OpFUnordLessThanEqual %bool %float_1 %float_2\n" +
  1923. "OpReturn\n" +
  1924. "OpFunctionEnd",
  1925. 2, true),
  1926. // Test case 5: fold 1.0 >= 2.0
  1927. InstructionFoldingCase<bool>(
  1928. Header() + "%main = OpFunction %void None %void_func\n" +
  1929. "%main_lab = OpLabel\n" +
  1930. "%2 = OpFUnordGreaterThanEqual %bool %float_1 %float_2\n" +
  1931. "OpReturn\n" +
  1932. "OpFunctionEnd",
  1933. 2, false),
  1934. // Test case 6: fold 1.0 == 1.0
  1935. InstructionFoldingCase<bool>(
  1936. Header() + "%main = OpFunction %void None %void_func\n" +
  1937. "%main_lab = OpLabel\n" +
  1938. "%2 = OpFUnordEqual %bool %float_1 %float_1\n" +
  1939. "OpReturn\n" +
  1940. "OpFunctionEnd",
  1941. 2, true),
  1942. // Test case 7: fold 1.0 != 1.0
  1943. InstructionFoldingCase<bool>(
  1944. Header() + "%main = OpFunction %void None %void_func\n" +
  1945. "%main_lab = OpLabel\n" +
  1946. "%2 = OpFUnordNotEqual %bool %float_1 %float_1\n" +
  1947. "OpReturn\n" +
  1948. "OpFunctionEnd",
  1949. 2, false),
  1950. // Test case 8: fold 1.0 < 1.0
  1951. InstructionFoldingCase<bool>(
  1952. Header() + "%main = OpFunction %void None %void_func\n" +
  1953. "%main_lab = OpLabel\n" +
  1954. "%2 = OpFUnordLessThan %bool %float_1 %float_1\n" +
  1955. "OpReturn\n" +
  1956. "OpFunctionEnd",
  1957. 2, false),
  1958. // Test case 9: fold 1.0 > 1.0
  1959. InstructionFoldingCase<bool>(
  1960. Header() + "%main = OpFunction %void None %void_func\n" +
  1961. "%main_lab = OpLabel\n" +
  1962. "%2 = OpFUnordGreaterThan %bool %float_1 %float_1\n" +
  1963. "OpReturn\n" +
  1964. "OpFunctionEnd",
  1965. 2, false),
  1966. // Test case 10: fold 1.0 <= 1.0
  1967. InstructionFoldingCase<bool>(
  1968. Header() + "%main = OpFunction %void None %void_func\n" +
  1969. "%main_lab = OpLabel\n" +
  1970. "%2 = OpFUnordLessThanEqual %bool %float_1 %float_1\n" +
  1971. "OpReturn\n" +
  1972. "OpFunctionEnd",
  1973. 2, true),
  1974. // Test case 11: fold 1.0 >= 1.0
  1975. InstructionFoldingCase<bool>(
  1976. Header() + "%main = OpFunction %void None %void_func\n" +
  1977. "%main_lab = OpLabel\n" +
  1978. "%2 = OpFUnordGreaterThanEqual %bool %float_1 %float_1\n" +
  1979. "OpReturn\n" +
  1980. "OpFunctionEnd",
  1981. 2, true),
  1982. // Test case 12: fold 2.0 < 1.0
  1983. InstructionFoldingCase<bool>(
  1984. Header() + "%main = OpFunction %void None %void_func\n" +
  1985. "%main_lab = OpLabel\n" +
  1986. "%2 = OpFUnordLessThan %bool %float_2 %float_1\n" +
  1987. "OpReturn\n" +
  1988. "OpFunctionEnd",
  1989. 2, false),
  1990. // Test case 13: fold 2.0 > 1.0
  1991. InstructionFoldingCase<bool>(
  1992. Header() + "%main = OpFunction %void None %void_func\n" +
  1993. "%main_lab = OpLabel\n" +
  1994. "%2 = OpFUnordGreaterThan %bool %float_2 %float_1\n" +
  1995. "OpReturn\n" +
  1996. "OpFunctionEnd",
  1997. 2, true),
  1998. // Test case 14: fold 2.0 <= 1.0
  1999. InstructionFoldingCase<bool>(
  2000. Header() + "%main = OpFunction %void None %void_func\n" +
  2001. "%main_lab = OpLabel\n" +
  2002. "%2 = OpFUnordLessThanEqual %bool %float_2 %float_1\n" +
  2003. "OpReturn\n" +
  2004. "OpFunctionEnd",
  2005. 2, false),
  2006. // Test case 15: fold 2.0 >= 1.0
  2007. InstructionFoldingCase<bool>(
  2008. Header() + "%main = OpFunction %void None %void_func\n" +
  2009. "%main_lab = OpLabel\n" +
  2010. "%2 = OpFUnordGreaterThanEqual %bool %float_2 %float_1\n" +
  2011. "OpReturn\n" +
  2012. "OpFunctionEnd",
  2013. 2, true)
  2014. ));
  2015. INSTANTIATE_TEST_SUITE_P(DoubleNaNCompareConstantFoldingTest, BooleanInstructionFoldingTest,
  2016. ::testing::Values(
  2017. // Test case 0: fold NaN == 0 (ord)
  2018. InstructionFoldingCase<bool>(
  2019. HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
  2020. "%main_lab = OpLabel\n" +
  2021. "%2 = OpFOrdEqual %bool %double_nan %double_0\n" +
  2022. "OpReturn\n" +
  2023. "OpFunctionEnd",
  2024. 2, false),
  2025. // Test case 1: fold NaN == NaN (unord)
  2026. InstructionFoldingCase<bool>(
  2027. HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
  2028. "%main_lab = OpLabel\n" +
  2029. "%2 = OpFUnordEqual %bool %double_nan %double_0\n" +
  2030. "OpReturn\n" +
  2031. "OpFunctionEnd",
  2032. 2, true),
  2033. // Test case 2: fold NaN != NaN (ord)
  2034. InstructionFoldingCase<bool>(
  2035. HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
  2036. "%main_lab = OpLabel\n" +
  2037. "%2 = OpFOrdNotEqual %bool %double_nan %double_0\n" +
  2038. "OpReturn\n" +
  2039. "OpFunctionEnd",
  2040. 2, false),
  2041. // Test case 3: fold NaN != NaN (unord)
  2042. InstructionFoldingCase<bool>(
  2043. HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
  2044. "%main_lab = OpLabel\n" +
  2045. "%2 = OpFUnordNotEqual %bool %double_nan %double_0\n" +
  2046. "OpReturn\n" +
  2047. "OpFunctionEnd",
  2048. 2, true)
  2049. ));
  2050. INSTANTIATE_TEST_SUITE_P(FloatNaNCompareConstantFoldingTest, BooleanInstructionFoldingTest,
  2051. ::testing::Values(
  2052. // Test case 0: fold NaN == 0 (ord)
  2053. InstructionFoldingCase<bool>(
  2054. HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
  2055. "%main_lab = OpLabel\n" +
  2056. "%2 = OpFOrdEqual %bool %float_nan %float_0\n" +
  2057. "OpReturn\n" +
  2058. "OpFunctionEnd",
  2059. 2, false),
  2060. // Test case 1: fold NaN == NaN (unord)
  2061. InstructionFoldingCase<bool>(
  2062. HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
  2063. "%main_lab = OpLabel\n" +
  2064. "%2 = OpFUnordEqual %bool %float_nan %float_0\n" +
  2065. "OpReturn\n" +
  2066. "OpFunctionEnd",
  2067. 2, true),
  2068. // Test case 2: fold NaN != NaN (ord)
  2069. InstructionFoldingCase<bool>(
  2070. HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
  2071. "%main_lab = OpLabel\n" +
  2072. "%2 = OpFOrdNotEqual %bool %float_nan %float_0\n" +
  2073. "OpReturn\n" +
  2074. "OpFunctionEnd",
  2075. 2, false),
  2076. // Test case 3: fold NaN != NaN (unord)
  2077. InstructionFoldingCase<bool>(
  2078. HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
  2079. "%main_lab = OpLabel\n" +
  2080. "%2 = OpFUnordNotEqual %bool %float_nan %float_0\n" +
  2081. "OpReturn\n" +
  2082. "OpFunctionEnd",
  2083. 2, true)
  2084. ));
  2085. // clang-format on
  2086. template <class ResultType>
  2087. struct InstructionFoldingCaseWithMap {
  2088. InstructionFoldingCaseWithMap(const std::string& tb, uint32_t id,
  2089. ResultType result,
  2090. std::function<uint32_t(uint32_t)> map)
  2091. : test_body(tb), id_to_fold(id), expected_result(result), id_map(map) {}
  2092. std::string test_body;
  2093. uint32_t id_to_fold;
  2094. ResultType expected_result;
  2095. std::function<uint32_t(uint32_t)> id_map;
  2096. };
  2097. using IntegerInstructionFoldingTestWithMap =
  2098. ::testing::TestWithParam<InstructionFoldingCaseWithMap<uint32_t>>;
  2099. TEST_P(IntegerInstructionFoldingTestWithMap, Case) {
  2100. const auto& tc = GetParam();
  2101. // Build module.
  2102. std::unique_ptr<IRContext> context =
  2103. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
  2104. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  2105. ASSERT_NE(nullptr, context);
  2106. // Fold the instruction to test.
  2107. analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
  2108. Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
  2109. inst = context->get_instruction_folder().FoldInstructionToConstant(inst,
  2110. tc.id_map);
  2111. // Make sure the instruction folded as expected.
  2112. EXPECT_NE(inst, nullptr);
  2113. if (inst != nullptr) {
  2114. EXPECT_EQ(inst->opcode(), SpvOpConstant);
  2115. analysis::ConstantManager* const_mrg = context->get_constant_mgr();
  2116. const analysis::IntConstant* result =
  2117. const_mrg->GetConstantFromInst(inst)->AsIntConstant();
  2118. EXPECT_NE(result, nullptr);
  2119. if (result != nullptr) {
  2120. EXPECT_EQ(result->GetU32BitValue(), tc.expected_result);
  2121. }
  2122. }
  2123. }
  2124. // clang-format off
  2125. INSTANTIATE_TEST_SUITE_P(TestCase, IntegerInstructionFoldingTestWithMap,
  2126. ::testing::Values(
  2127. // Test case 0: fold %3 = 0; %3 * n
  2128. InstructionFoldingCaseWithMap<uint32_t>(
  2129. Header() + "%main = OpFunction %void None %void_func\n" +
  2130. "%main_lab = OpLabel\n" +
  2131. "%n = OpVariable %_ptr_int Function\n" +
  2132. "%load = OpLoad %int %n\n" +
  2133. "%3 = OpCopyObject %int %int_0\n"
  2134. "%2 = OpIMul %int %3 %load\n" +
  2135. "OpReturn\n" +
  2136. "OpFunctionEnd",
  2137. 2, 0, [](uint32_t id) {return (id == 3 ? INT_0_ID : id);})
  2138. ));
  2139. // clang-format on
  2140. using BooleanInstructionFoldingTestWithMap =
  2141. ::testing::TestWithParam<InstructionFoldingCaseWithMap<bool>>;
  2142. TEST_P(BooleanInstructionFoldingTestWithMap, Case) {
  2143. const auto& tc = GetParam();
  2144. // Build module.
  2145. std::unique_ptr<IRContext> context =
  2146. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
  2147. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  2148. ASSERT_NE(nullptr, context);
  2149. // Fold the instruction to test.
  2150. analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
  2151. Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
  2152. inst = context->get_instruction_folder().FoldInstructionToConstant(inst,
  2153. tc.id_map);
  2154. // Make sure the instruction folded as expected.
  2155. EXPECT_NE(inst, nullptr);
  2156. if (inst != nullptr) {
  2157. std::vector<SpvOp> bool_opcodes = {SpvOpConstantTrue, SpvOpConstantFalse};
  2158. EXPECT_THAT(bool_opcodes, Contains(inst->opcode()));
  2159. analysis::ConstantManager* const_mrg = context->get_constant_mgr();
  2160. const analysis::BoolConstant* result =
  2161. const_mrg->GetConstantFromInst(inst)->AsBoolConstant();
  2162. EXPECT_NE(result, nullptr);
  2163. if (result != nullptr) {
  2164. EXPECT_EQ(result->value(), tc.expected_result);
  2165. }
  2166. }
  2167. }
  2168. // clang-format off
  2169. INSTANTIATE_TEST_SUITE_P(TestCase, BooleanInstructionFoldingTestWithMap,
  2170. ::testing::Values(
  2171. // Test case 0: fold %3 = true; %3 || n
  2172. InstructionFoldingCaseWithMap<bool>(
  2173. Header() + "%main = OpFunction %void None %void_func\n" +
  2174. "%main_lab = OpLabel\n" +
  2175. "%n = OpVariable %_ptr_bool Function\n" +
  2176. "%load = OpLoad %bool %n\n" +
  2177. "%3 = OpCopyObject %bool %true\n" +
  2178. "%2 = OpLogicalOr %bool %3 %load\n" +
  2179. "OpReturn\n" +
  2180. "OpFunctionEnd",
  2181. 2, true, [](uint32_t id) {return (id == 3 ? TRUE_ID : id);})
  2182. ));
  2183. // clang-format on
  2184. using GeneralInstructionFoldingTest =
  2185. ::testing::TestWithParam<InstructionFoldingCase<uint32_t>>;
  2186. TEST_P(GeneralInstructionFoldingTest, Case) {
  2187. const auto& tc = GetParam();
  2188. // Build module.
  2189. std::unique_ptr<IRContext> context =
  2190. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
  2191. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  2192. ASSERT_NE(nullptr, context);
  2193. // Fold the instruction to test.
  2194. analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
  2195. Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
  2196. std::unique_ptr<Instruction> original_inst(inst->Clone(context.get()));
  2197. bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
  2198. // Make sure the instruction folded as expected.
  2199. EXPECT_EQ(inst->result_id(), original_inst->result_id());
  2200. EXPECT_EQ(inst->type_id(), original_inst->type_id());
  2201. EXPECT_TRUE((!succeeded) == (tc.expected_result == 0));
  2202. if (succeeded) {
  2203. EXPECT_EQ(inst->opcode(), SpvOpCopyObject);
  2204. EXPECT_EQ(inst->GetSingleWordInOperand(0), tc.expected_result);
  2205. } else {
  2206. EXPECT_EQ(inst->NumInOperands(), original_inst->NumInOperands());
  2207. for (uint32_t i = 0; i < inst->NumInOperands(); ++i) {
  2208. EXPECT_EQ(inst->GetOperand(i), original_inst->GetOperand(i));
  2209. }
  2210. }
  2211. }
  2212. // clang-format off
  2213. INSTANTIATE_TEST_SUITE_P(IntegerArithmeticTestCases, GeneralInstructionFoldingTest,
  2214. ::testing::Values(
  2215. // Test case 0: Don't fold n * m
  2216. InstructionFoldingCase<uint32_t>(
  2217. Header() + "%main = OpFunction %void None %void_func\n" +
  2218. "%main_lab = OpLabel\n" +
  2219. "%n = OpVariable %_ptr_int Function\n" +
  2220. "%m = OpVariable %_ptr_int Function\n" +
  2221. "%load_n = OpLoad %int %n\n" +
  2222. "%load_m = OpLoad %int %m\n" +
  2223. "%2 = OpIMul %int %load_n %load_m\n" +
  2224. "OpReturn\n" +
  2225. "OpFunctionEnd",
  2226. 2, 0),
  2227. // Test case 1: Don't fold n / m (unsigned)
  2228. InstructionFoldingCase<uint32_t>(
  2229. Header() + "%main = OpFunction %void None %void_func\n" +
  2230. "%main_lab = OpLabel\n" +
  2231. "%n = OpVariable %_ptr_uint Function\n" +
  2232. "%m = OpVariable %_ptr_uint Function\n" +
  2233. "%load_n = OpLoad %uint %n\n" +
  2234. "%load_m = OpLoad %uint %m\n" +
  2235. "%2 = OpUDiv %uint %load_n %load_m\n" +
  2236. "OpReturn\n" +
  2237. "OpFunctionEnd",
  2238. 2, 0),
  2239. // Test case 2: Don't fold n / m (signed)
  2240. InstructionFoldingCase<uint32_t>(
  2241. Header() + "%main = OpFunction %void None %void_func\n" +
  2242. "%main_lab = OpLabel\n" +
  2243. "%n = OpVariable %_ptr_int Function\n" +
  2244. "%m = OpVariable %_ptr_int Function\n" +
  2245. "%load_n = OpLoad %int %n\n" +
  2246. "%load_m = OpLoad %int %m\n" +
  2247. "%2 = OpSDiv %int %load_n %load_m\n" +
  2248. "OpReturn\n" +
  2249. "OpFunctionEnd",
  2250. 2, 0),
  2251. // Test case 3: Don't fold n remainder m
  2252. InstructionFoldingCase<uint32_t>(
  2253. Header() + "%main = OpFunction %void None %void_func\n" +
  2254. "%main_lab = OpLabel\n" +
  2255. "%n = OpVariable %_ptr_int Function\n" +
  2256. "%m = OpVariable %_ptr_int Function\n" +
  2257. "%load_n = OpLoad %int %n\n" +
  2258. "%load_m = OpLoad %int %m\n" +
  2259. "%2 = OpSRem %int %load_n %load_m\n" +
  2260. "OpReturn\n" +
  2261. "OpFunctionEnd",
  2262. 2, 0),
  2263. // Test case 4: Don't fold n % m (signed)
  2264. InstructionFoldingCase<uint32_t>(
  2265. Header() + "%main = OpFunction %void None %void_func\n" +
  2266. "%main_lab = OpLabel\n" +
  2267. "%n = OpVariable %_ptr_int Function\n" +
  2268. "%m = OpVariable %_ptr_int Function\n" +
  2269. "%load_n = OpLoad %int %n\n" +
  2270. "%load_m = OpLoad %int %m\n" +
  2271. "%2 = OpSMod %int %load_n %load_m\n" +
  2272. "OpReturn\n" +
  2273. "OpFunctionEnd",
  2274. 2, 0),
  2275. // Test case 5: Don't fold n % m (unsigned)
  2276. InstructionFoldingCase<uint32_t>(
  2277. Header() + "%main = OpFunction %void None %void_func\n" +
  2278. "%main_lab = OpLabel\n" +
  2279. "%n = OpVariable %_ptr_uint Function\n" +
  2280. "%m = OpVariable %_ptr_uint Function\n" +
  2281. "%load_n = OpLoad %uint %n\n" +
  2282. "%load_m = OpLoad %uint %m\n" +
  2283. "%2 = OpUMod %int %load_n %load_m\n" +
  2284. "OpReturn\n" +
  2285. "OpFunctionEnd",
  2286. 2, 0),
  2287. // Test case 6: Don't fold n << m
  2288. InstructionFoldingCase<uint32_t>(
  2289. Header() + "%main = OpFunction %void None %void_func\n" +
  2290. "%main_lab = OpLabel\n" +
  2291. "%n = OpVariable %_ptr_uint Function\n" +
  2292. "%m = OpVariable %_ptr_uint Function\n" +
  2293. "%load_n = OpLoad %uint %n\n" +
  2294. "%load_m = OpLoad %uint %m\n" +
  2295. "%2 = OpShiftRightLogical %int %load_n %load_m\n" +
  2296. "OpReturn\n" +
  2297. "OpFunctionEnd",
  2298. 2, 0),
  2299. // Test case 7: Don't fold n >> m
  2300. InstructionFoldingCase<uint32_t>(
  2301. Header() + "%main = OpFunction %void None %void_func\n" +
  2302. "%main_lab = OpLabel\n" +
  2303. "%n = OpVariable %_ptr_uint Function\n" +
  2304. "%m = OpVariable %_ptr_uint Function\n" +
  2305. "%load_n = OpLoad %uint %n\n" +
  2306. "%load_m = OpLoad %uint %m\n" +
  2307. "%2 = OpShiftLeftLogical %int %load_n %load_m\n" +
  2308. "OpReturn\n" +
  2309. "OpFunctionEnd",
  2310. 2, 0),
  2311. // Test case 8: Don't fold n | m
  2312. InstructionFoldingCase<uint32_t>(
  2313. Header() + "%main = OpFunction %void None %void_func\n" +
  2314. "%main_lab = OpLabel\n" +
  2315. "%n = OpVariable %_ptr_uint Function\n" +
  2316. "%m = OpVariable %_ptr_uint Function\n" +
  2317. "%load_n = OpLoad %uint %n\n" +
  2318. "%load_m = OpLoad %uint %m\n" +
  2319. "%2 = OpBitwiseOr %int %load_n %load_m\n" +
  2320. "OpReturn\n" +
  2321. "OpFunctionEnd",
  2322. 2, 0),
  2323. // Test case 9: Don't fold n & m
  2324. InstructionFoldingCase<uint32_t>(
  2325. Header() + "%main = OpFunction %void None %void_func\n" +
  2326. "%main_lab = OpLabel\n" +
  2327. "%n = OpVariable %_ptr_uint Function\n" +
  2328. "%m = OpVariable %_ptr_uint Function\n" +
  2329. "%load_n = OpLoad %uint %n\n" +
  2330. "%load_m = OpLoad %uint %m\n" +
  2331. "%2 = OpBitwiseAnd %int %load_n %load_m\n" +
  2332. "OpReturn\n" +
  2333. "OpFunctionEnd",
  2334. 2, 0),
  2335. // Test case 10: Don't fold n < m (unsigned)
  2336. InstructionFoldingCase<uint32_t>(
  2337. Header() + "%main = OpFunction %void None %void_func\n" +
  2338. "%main_lab = OpLabel\n" +
  2339. "%n = OpVariable %_ptr_uint Function\n" +
  2340. "%m = OpVariable %_ptr_uint Function\n" +
  2341. "%load_n = OpLoad %uint %n\n" +
  2342. "%load_m = OpLoad %uint %m\n" +
  2343. "%2 = OpULessThan %bool %load_n %load_m\n" +
  2344. "OpReturn\n" +
  2345. "OpFunctionEnd",
  2346. 2, 0),
  2347. // Test case 11: Don't fold n > m (unsigned)
  2348. InstructionFoldingCase<uint32_t>(
  2349. Header() + "%main = OpFunction %void None %void_func\n" +
  2350. "%main_lab = OpLabel\n" +
  2351. "%n = OpVariable %_ptr_uint Function\n" +
  2352. "%m = OpVariable %_ptr_uint Function\n" +
  2353. "%load_n = OpLoad %uint %n\n" +
  2354. "%load_m = OpLoad %uint %m\n" +
  2355. "%2 = OpUGreaterThan %bool %load_n %load_m\n" +
  2356. "OpReturn\n" +
  2357. "OpFunctionEnd",
  2358. 2, 0),
  2359. // Test case 12: Don't fold n <= m (unsigned)
  2360. InstructionFoldingCase<uint32_t>(
  2361. Header() + "%main = OpFunction %void None %void_func\n" +
  2362. "%main_lab = OpLabel\n" +
  2363. "%n = OpVariable %_ptr_uint Function\n" +
  2364. "%m = OpVariable %_ptr_uint Function\n" +
  2365. "%load_n = OpLoad %uint %n\n" +
  2366. "%load_m = OpLoad %uint %m\n" +
  2367. "%2 = OpULessThanEqual %bool %load_n %load_m\n" +
  2368. "OpReturn\n" +
  2369. "OpFunctionEnd",
  2370. 2, 0),
  2371. // Test case 13: Don't fold n >= m (unsigned)
  2372. InstructionFoldingCase<uint32_t>(
  2373. Header() + "%main = OpFunction %void None %void_func\n" +
  2374. "%main_lab = OpLabel\n" +
  2375. "%n = OpVariable %_ptr_uint Function\n" +
  2376. "%m = OpVariable %_ptr_uint Function\n" +
  2377. "%load_n = OpLoad %uint %n\n" +
  2378. "%load_m = OpLoad %uint %m\n" +
  2379. "%2 = OpUGreaterThanEqual %bool %load_n %load_m\n" +
  2380. "OpReturn\n" +
  2381. "OpFunctionEnd",
  2382. 2, 0),
  2383. // Test case 14: Don't fold n < m (signed)
  2384. InstructionFoldingCase<uint32_t>(
  2385. Header() + "%main = OpFunction %void None %void_func\n" +
  2386. "%main_lab = OpLabel\n" +
  2387. "%n = OpVariable %_ptr_int Function\n" +
  2388. "%m = OpVariable %_ptr_int Function\n" +
  2389. "%load_n = OpLoad %int %n\n" +
  2390. "%load_m = OpLoad %int %m\n" +
  2391. "%2 = OpULessThan %bool %load_n %load_m\n" +
  2392. "OpReturn\n" +
  2393. "OpFunctionEnd",
  2394. 2, 0),
  2395. // Test case 15: Don't fold n > m (signed)
  2396. InstructionFoldingCase<uint32_t>(
  2397. Header() + "%main = OpFunction %void None %void_func\n" +
  2398. "%main_lab = OpLabel\n" +
  2399. "%n = OpVariable %_ptr_int Function\n" +
  2400. "%m = OpVariable %_ptr_int Function\n" +
  2401. "%load_n = OpLoad %int %n\n" +
  2402. "%load_m = OpLoad %int %m\n" +
  2403. "%2 = OpUGreaterThan %bool %load_n %load_m\n" +
  2404. "OpReturn\n" +
  2405. "OpFunctionEnd",
  2406. 2, 0),
  2407. // Test case 16: Don't fold n <= m (signed)
  2408. InstructionFoldingCase<uint32_t>(
  2409. Header() + "%main = OpFunction %void None %void_func\n" +
  2410. "%main_lab = OpLabel\n" +
  2411. "%n = OpVariable %_ptr_int Function\n" +
  2412. "%m = OpVariable %_ptr_int Function\n" +
  2413. "%load_n = OpLoad %int %n\n" +
  2414. "%load_m = OpLoad %int %m\n" +
  2415. "%2 = OpULessThanEqual %bool %load_n %load_m\n" +
  2416. "OpReturn\n" +
  2417. "OpFunctionEnd",
  2418. 2, 0),
  2419. // Test case 17: Don't fold n >= m (signed)
  2420. InstructionFoldingCase<uint32_t>(
  2421. Header() + "%main = OpFunction %void None %void_func\n" +
  2422. "%main_lab = OpLabel\n" +
  2423. "%n = OpVariable %_ptr_int Function\n" +
  2424. "%m = OpVariable %_ptr_int Function\n" +
  2425. "%load_n = OpLoad %int %n\n" +
  2426. "%load_m = OpLoad %int %m\n" +
  2427. "%2 = OpUGreaterThanEqual %bool %load_n %load_m\n" +
  2428. "OpReturn\n" +
  2429. "OpFunctionEnd",
  2430. 2, 0),
  2431. // Test case 18: Don't fold n || m
  2432. InstructionFoldingCase<uint32_t>(
  2433. Header() + "%main = OpFunction %void None %void_func\n" +
  2434. "%main_lab = OpLabel\n" +
  2435. "%n = OpVariable %_ptr_bool Function\n" +
  2436. "%m = OpVariable %_ptr_bool Function\n" +
  2437. "%load_n = OpLoad %bool %n\n" +
  2438. "%load_m = OpLoad %bool %m\n" +
  2439. "%2 = OpLogicalOr %bool %load_n %load_m\n" +
  2440. "OpReturn\n" +
  2441. "OpFunctionEnd",
  2442. 2, 0),
  2443. // Test case 19: Don't fold n && m
  2444. InstructionFoldingCase<uint32_t>(
  2445. Header() + "%main = OpFunction %void None %void_func\n" +
  2446. "%main_lab = OpLabel\n" +
  2447. "%n = OpVariable %_ptr_bool Function\n" +
  2448. "%m = OpVariable %_ptr_bool Function\n" +
  2449. "%load_n = OpLoad %bool %n\n" +
  2450. "%load_m = OpLoad %bool %m\n" +
  2451. "%2 = OpLogicalAnd %bool %load_n %load_m\n" +
  2452. "OpReturn\n" +
  2453. "OpFunctionEnd",
  2454. 2, 0),
  2455. // Test case 20: Don't fold n * 3
  2456. InstructionFoldingCase<uint32_t>(
  2457. Header() + "%main = OpFunction %void None %void_func\n" +
  2458. "%main_lab = OpLabel\n" +
  2459. "%n = OpVariable %_ptr_int Function\n" +
  2460. "%load_n = OpLoad %int %n\n" +
  2461. "%2 = OpIMul %int %load_n %int_3\n" +
  2462. "OpReturn\n" +
  2463. "OpFunctionEnd",
  2464. 2, 0),
  2465. // Test case 21: Don't fold n / 3 (unsigned)
  2466. InstructionFoldingCase<uint32_t>(
  2467. Header() + "%main = OpFunction %void None %void_func\n" +
  2468. "%main_lab = OpLabel\n" +
  2469. "%n = OpVariable %_ptr_uint Function\n" +
  2470. "%load_n = OpLoad %uint %n\n" +
  2471. "%2 = OpUDiv %uint %load_n %uint_3\n" +
  2472. "OpReturn\n" +
  2473. "OpFunctionEnd",
  2474. 2, 0),
  2475. // Test case 22: Don't fold n / 3 (signed)
  2476. InstructionFoldingCase<uint32_t>(
  2477. Header() + "%main = OpFunction %void None %void_func\n" +
  2478. "%main_lab = OpLabel\n" +
  2479. "%n = OpVariable %_ptr_int Function\n" +
  2480. "%load_n = OpLoad %int %n\n" +
  2481. "%2 = OpSDiv %int %load_n %int_3\n" +
  2482. "OpReturn\n" +
  2483. "OpFunctionEnd",
  2484. 2, 0),
  2485. // Test case 23: Don't fold n remainder 3
  2486. InstructionFoldingCase<uint32_t>(
  2487. Header() + "%main = OpFunction %void None %void_func\n" +
  2488. "%main_lab = OpLabel\n" +
  2489. "%n = OpVariable %_ptr_int Function\n" +
  2490. "%load_n = OpLoad %int %n\n" +
  2491. "%2 = OpSRem %int %load_n %int_3\n" +
  2492. "OpReturn\n" +
  2493. "OpFunctionEnd",
  2494. 2, 0),
  2495. // Test case 24: Don't fold n % 3 (signed)
  2496. InstructionFoldingCase<uint32_t>(
  2497. Header() + "%main = OpFunction %void None %void_func\n" +
  2498. "%main_lab = OpLabel\n" +
  2499. "%n = OpVariable %_ptr_int Function\n" +
  2500. "%load_n = OpLoad %int %n\n" +
  2501. "%2 = OpSMod %int %load_n %int_3\n" +
  2502. "OpReturn\n" +
  2503. "OpFunctionEnd",
  2504. 2, 0),
  2505. // Test case 25: Don't fold n % 3 (unsigned)
  2506. InstructionFoldingCase<uint32_t>(
  2507. Header() + "%main = OpFunction %void None %void_func\n" +
  2508. "%main_lab = OpLabel\n" +
  2509. "%n = OpVariable %_ptr_uint Function\n" +
  2510. "%load_n = OpLoad %uint %n\n" +
  2511. "%2 = OpUMod %int %load_n %int_3\n" +
  2512. "OpReturn\n" +
  2513. "OpFunctionEnd",
  2514. 2, 0),
  2515. // Test case 26: Don't fold n << 3
  2516. InstructionFoldingCase<uint32_t>(
  2517. Header() + "%main = OpFunction %void None %void_func\n" +
  2518. "%main_lab = OpLabel\n" +
  2519. "%n = OpVariable %_ptr_uint Function\n" +
  2520. "%load_n = OpLoad %uint %n\n" +
  2521. "%2 = OpShiftRightLogical %int %load_n %int_3\n" +
  2522. "OpReturn\n" +
  2523. "OpFunctionEnd",
  2524. 2, 0),
  2525. // Test case 27: Don't fold n >> 3
  2526. InstructionFoldingCase<uint32_t>(
  2527. Header() + "%main = OpFunction %void None %void_func\n" +
  2528. "%main_lab = OpLabel\n" +
  2529. "%n = OpVariable %_ptr_uint Function\n" +
  2530. "%load_n = OpLoad %uint %n\n" +
  2531. "%2 = OpShiftLeftLogical %int %load_n %int_3\n" +
  2532. "OpReturn\n" +
  2533. "OpFunctionEnd",
  2534. 2, 0),
  2535. // Test case 28: Don't fold n | 3
  2536. InstructionFoldingCase<uint32_t>(
  2537. Header() + "%main = OpFunction %void None %void_func\n" +
  2538. "%main_lab = OpLabel\n" +
  2539. "%n = OpVariable %_ptr_uint Function\n" +
  2540. "%load_n = OpLoad %uint %n\n" +
  2541. "%2 = OpBitwiseOr %int %load_n %int_3\n" +
  2542. "OpReturn\n" +
  2543. "OpFunctionEnd",
  2544. 2, 0),
  2545. // Test case 29: Don't fold n & 3
  2546. InstructionFoldingCase<uint32_t>(
  2547. Header() + "%main = OpFunction %void None %void_func\n" +
  2548. "%main_lab = OpLabel\n" +
  2549. "%n = OpVariable %_ptr_uint Function\n" +
  2550. "%load_n = OpLoad %uint %n\n" +
  2551. "%2 = OpBitwiseAnd %uint %load_n %uint_3\n" +
  2552. "OpReturn\n" +
  2553. "OpFunctionEnd",
  2554. 2, 0),
  2555. // Test case 30: Don't fold n < 3 (unsigned)
  2556. InstructionFoldingCase<uint32_t>(
  2557. Header() + "%main = OpFunction %void None %void_func\n" +
  2558. "%main_lab = OpLabel\n" +
  2559. "%n = OpVariable %_ptr_uint Function\n" +
  2560. "%load_n = OpLoad %uint %n\n" +
  2561. "%2 = OpULessThan %bool %load_n %uint_3\n" +
  2562. "OpReturn\n" +
  2563. "OpFunctionEnd",
  2564. 2, 0),
  2565. // Test case 31: Don't fold n > 3 (unsigned)
  2566. InstructionFoldingCase<uint32_t>(
  2567. Header() + "%main = OpFunction %void None %void_func\n" +
  2568. "%main_lab = OpLabel\n" +
  2569. "%n = OpVariable %_ptr_uint Function\n" +
  2570. "%load_n = OpLoad %uint %n\n" +
  2571. "%2 = OpUGreaterThan %bool %load_n %uint_3\n" +
  2572. "OpReturn\n" +
  2573. "OpFunctionEnd",
  2574. 2, 0),
  2575. // Test case 32: Don't fold n <= 3 (unsigned)
  2576. InstructionFoldingCase<uint32_t>(
  2577. Header() + "%main = OpFunction %void None %void_func\n" +
  2578. "%main_lab = OpLabel\n" +
  2579. "%n = OpVariable %_ptr_uint Function\n" +
  2580. "%load_n = OpLoad %uint %n\n" +
  2581. "%2 = OpULessThanEqual %bool %load_n %uint_3\n" +
  2582. "OpReturn\n" +
  2583. "OpFunctionEnd",
  2584. 2, 0),
  2585. // Test case 33: Don't fold n >= 3 (unsigned)
  2586. InstructionFoldingCase<uint32_t>(
  2587. Header() + "%main = OpFunction %void None %void_func\n" +
  2588. "%main_lab = OpLabel\n" +
  2589. "%n = OpVariable %_ptr_uint Function\n" +
  2590. "%load_n = OpLoad %uint %n\n" +
  2591. "%2 = OpUGreaterThanEqual %bool %load_n %uint_3\n" +
  2592. "OpReturn\n" +
  2593. "OpFunctionEnd",
  2594. 2, 0),
  2595. // Test case 34: Don't fold n < 3 (signed)
  2596. InstructionFoldingCase<uint32_t>(
  2597. Header() + "%main = OpFunction %void None %void_func\n" +
  2598. "%main_lab = OpLabel\n" +
  2599. "%n = OpVariable %_ptr_int Function\n" +
  2600. "%load_n = OpLoad %int %n\n" +
  2601. "%2 = OpULessThan %bool %load_n %int_3\n" +
  2602. "OpReturn\n" +
  2603. "OpFunctionEnd",
  2604. 2, 0),
  2605. // Test case 35: Don't fold n > 3 (signed)
  2606. InstructionFoldingCase<uint32_t>(
  2607. Header() + "%main = OpFunction %void None %void_func\n" +
  2608. "%main_lab = OpLabel\n" +
  2609. "%n = OpVariable %_ptr_int Function\n" +
  2610. "%load_n = OpLoad %int %n\n" +
  2611. "%2 = OpUGreaterThan %bool %load_n %int_3\n" +
  2612. "OpReturn\n" +
  2613. "OpFunctionEnd",
  2614. 2, 0),
  2615. // Test case 36: Don't fold n <= 3 (signed)
  2616. InstructionFoldingCase<uint32_t>(
  2617. Header() + "%main = OpFunction %void None %void_func\n" +
  2618. "%main_lab = OpLabel\n" +
  2619. "%n = OpVariable %_ptr_int Function\n" +
  2620. "%load_n = OpLoad %int %n\n" +
  2621. "%2 = OpULessThanEqual %bool %load_n %int_3\n" +
  2622. "OpReturn\n" +
  2623. "OpFunctionEnd",
  2624. 2, 0),
  2625. // Test case 37: Don't fold n >= 3 (signed)
  2626. InstructionFoldingCase<uint32_t>(
  2627. Header() + "%main = OpFunction %void None %void_func\n" +
  2628. "%main_lab = OpLabel\n" +
  2629. "%n = OpVariable %_ptr_int Function\n" +
  2630. "%load_n = OpLoad %int %n\n" +
  2631. "%2 = OpUGreaterThanEqual %bool %load_n %int_3\n" +
  2632. "OpReturn\n" +
  2633. "OpFunctionEnd",
  2634. 2, 0),
  2635. // Test case 38: Don't fold 2 + 3 (long), bad length
  2636. InstructionFoldingCase<uint32_t>(
  2637. Header() + "%main = OpFunction %void None %void_func\n" +
  2638. "%main_lab = OpLabel\n" +
  2639. "%2 = OpIAdd %long %long_2 %long_3\n" +
  2640. "OpReturn\n" +
  2641. "OpFunctionEnd",
  2642. 2, 0),
  2643. // Test case 39: Don't fold 2 + 3 (short), bad length
  2644. InstructionFoldingCase<uint32_t>(
  2645. Header() + "%main = OpFunction %void None %void_func\n" +
  2646. "%main_lab = OpLabel\n" +
  2647. "%2 = OpIAdd %short %short_2 %short_3\n" +
  2648. "OpReturn\n" +
  2649. "OpFunctionEnd",
  2650. 2, 0),
  2651. // Test case 40: fold 1*n
  2652. InstructionFoldingCase<uint32_t>(
  2653. Header() + "%main = OpFunction %void None %void_func\n" +
  2654. "%main_lab = OpLabel\n" +
  2655. "%n = OpVariable %_ptr_int Function\n" +
  2656. "%3 = OpLoad %int %n\n" +
  2657. "%2 = OpIMul %int %int_1 %3\n" +
  2658. "OpReturn\n" +
  2659. "OpFunctionEnd",
  2660. 2, 3),
  2661. // Test case 41: fold n*1
  2662. InstructionFoldingCase<uint32_t>(
  2663. Header() + "%main = OpFunction %void None %void_func\n" +
  2664. "%main_lab = OpLabel\n" +
  2665. "%n = OpVariable %_ptr_int Function\n" +
  2666. "%3 = OpLoad %int %n\n" +
  2667. "%2 = OpIMul %int %3 %int_1\n" +
  2668. "OpReturn\n" +
  2669. "OpFunctionEnd",
  2670. 2, 3)
  2671. ));
  2672. INSTANTIATE_TEST_SUITE_P(CompositeExtractFoldingTest, GeneralInstructionFoldingTest,
  2673. ::testing::Values(
  2674. // Test case 0: fold Insert feeding extract
  2675. InstructionFoldingCase<uint32_t>(
  2676. Header() + "%main = OpFunction %void None %void_func\n" +
  2677. "%main_lab = OpLabel\n" +
  2678. "%n = OpVariable %_ptr_int Function\n" +
  2679. "%2 = OpLoad %int %n\n" +
  2680. "%3 = OpCompositeInsert %v4int %2 %v4int_0_0_0_0 0\n" +
  2681. "%4 = OpCompositeInsert %v4int %int_1 %3 1\n" +
  2682. "%5 = OpCompositeInsert %v4int %int_1 %4 2\n" +
  2683. "%6 = OpCompositeInsert %v4int %int_1 %5 3\n" +
  2684. "%7 = OpCompositeExtract %int %6 0\n" +
  2685. "OpReturn\n" +
  2686. "OpFunctionEnd",
  2687. 7, 2),
  2688. // Test case 1: fold Composite construct feeding extract (position 0)
  2689. InstructionFoldingCase<uint32_t>(
  2690. Header() + "%main = OpFunction %void None %void_func\n" +
  2691. "%main_lab = OpLabel\n" +
  2692. "%n = OpVariable %_ptr_int Function\n" +
  2693. "%2 = OpLoad %int %n\n" +
  2694. "%3 = OpCompositeConstruct %v4int %2 %int_0 %int_0 %int_0\n" +
  2695. "%4 = OpCompositeExtract %int %3 0\n" +
  2696. "OpReturn\n" +
  2697. "OpFunctionEnd",
  2698. 4, 2),
  2699. // Test case 2: fold Composite construct feeding extract (position 3)
  2700. InstructionFoldingCase<uint32_t>(
  2701. Header() + "%main = OpFunction %void None %void_func\n" +
  2702. "%main_lab = OpLabel\n" +
  2703. "%n = OpVariable %_ptr_int Function\n" +
  2704. "%2 = OpLoad %int %n\n" +
  2705. "%3 = OpCompositeConstruct %v4int %2 %int_0 %int_0 %100\n" +
  2706. "%4 = OpCompositeExtract %int %3 3\n" +
  2707. "OpReturn\n" +
  2708. "OpFunctionEnd",
  2709. 4, INT_0_ID),
  2710. // Test case 3: fold Composite construct with vectors feeding extract (scalar element)
  2711. InstructionFoldingCase<uint32_t>(
  2712. Header() + "%main = OpFunction %void None %void_func\n" +
  2713. "%main_lab = OpLabel\n" +
  2714. "%n = OpVariable %_ptr_int Function\n" +
  2715. "%2 = OpLoad %int %n\n" +
  2716. "%3 = OpCompositeConstruct %v2int %2 %int_0\n" +
  2717. "%4 = OpCompositeConstruct %v4int %3 %int_0 %100\n" +
  2718. "%5 = OpCompositeExtract %int %4 3\n" +
  2719. "OpReturn\n" +
  2720. "OpFunctionEnd",
  2721. 5, INT_0_ID),
  2722. // Test case 4: fold Composite construct with vectors feeding extract (start of vector element)
  2723. InstructionFoldingCase<uint32_t>(
  2724. Header() + "%main = OpFunction %void None %void_func\n" +
  2725. "%main_lab = OpLabel\n" +
  2726. "%n = OpVariable %_ptr_int Function\n" +
  2727. "%2 = OpLoad %int %n\n" +
  2728. "%3 = OpCompositeConstruct %v2int %2 %int_0\n" +
  2729. "%4 = OpCompositeConstruct %v4int %3 %int_0 %100\n" +
  2730. "%5 = OpCompositeExtract %int %4 0\n" +
  2731. "OpReturn\n" +
  2732. "OpFunctionEnd",
  2733. 5, 2),
  2734. // Test case 5: fold Composite construct with vectors feeding extract (middle of vector element)
  2735. InstructionFoldingCase<uint32_t>(
  2736. Header() + "%main = OpFunction %void None %void_func\n" +
  2737. "%main_lab = OpLabel\n" +
  2738. "%n = OpVariable %_ptr_int Function\n" +
  2739. "%2 = OpLoad %int %n\n" +
  2740. "%3 = OpCompositeConstruct %v2int %int_0 %2\n" +
  2741. "%4 = OpCompositeConstruct %v4int %3 %int_0 %100\n" +
  2742. "%5 = OpCompositeExtract %int %4 1\n" +
  2743. "OpReturn\n" +
  2744. "OpFunctionEnd",
  2745. 5, 2),
  2746. // Test case 6: fold Composite construct with multiple indices.
  2747. InstructionFoldingCase<uint32_t>(
  2748. Header() + "%main = OpFunction %void None %void_func\n" +
  2749. "%main_lab = OpLabel\n" +
  2750. "%n = OpVariable %_ptr_int Function\n" +
  2751. "%2 = OpLoad %int %n\n" +
  2752. "%3 = OpCompositeConstruct %v2int %int_0 %2\n" +
  2753. "%4 = OpCompositeConstruct %struct_v2int_int_int %3 %int_0 %100\n" +
  2754. "%5 = OpCompositeExtract %int %4 0 1\n" +
  2755. "OpReturn\n" +
  2756. "OpFunctionEnd",
  2757. 5, 2),
  2758. // Test case 7: fold constant extract.
  2759. InstructionFoldingCase<uint32_t>(
  2760. Header() + "%main = OpFunction %void None %void_func\n" +
  2761. "%main_lab = OpLabel\n" +
  2762. "%2 = OpCompositeExtract %int %102 1\n" +
  2763. "OpReturn\n" +
  2764. "OpFunctionEnd",
  2765. 2, INT_7_ID),
  2766. // Test case 8: constant struct has OpUndef
  2767. InstructionFoldingCase<uint32_t>(
  2768. Header() + "%main = OpFunction %void None %void_func\n" +
  2769. "%main_lab = OpLabel\n" +
  2770. "%2 = OpCompositeExtract %int %struct_undef_0_0 0 1\n" +
  2771. "OpReturn\n" +
  2772. "OpFunctionEnd",
  2773. 2, 0),
  2774. // Test case 9: Extracting a member of element inserted via Insert
  2775. InstructionFoldingCase<uint32_t>(
  2776. Header() + "%main = OpFunction %void None %void_func\n" +
  2777. "%main_lab = OpLabel\n" +
  2778. "%n = OpVariable %_ptr_struct_v2int_int_int Function\n" +
  2779. "%2 = OpLoad %struct_v2int_int_int %n\n" +
  2780. "%3 = OpCompositeInsert %struct_v2int_int_int %102 %2 0\n" +
  2781. "%4 = OpCompositeExtract %int %3 0 1\n" +
  2782. "OpReturn\n" +
  2783. "OpFunctionEnd",
  2784. 4, 103),
  2785. // Test case 10: Extracting a element that is partially changed by Insert. (Don't fold)
  2786. InstructionFoldingCase<uint32_t>(
  2787. Header() + "%main = OpFunction %void None %void_func\n" +
  2788. "%main_lab = OpLabel\n" +
  2789. "%n = OpVariable %_ptr_struct_v2int_int_int Function\n" +
  2790. "%2 = OpLoad %struct_v2int_int_int %n\n" +
  2791. "%3 = OpCompositeInsert %struct_v2int_int_int %int_0 %2 0 1\n" +
  2792. "%4 = OpCompositeExtract %v2int %3 0\n" +
  2793. "OpReturn\n" +
  2794. "OpFunctionEnd",
  2795. 4, 0),
  2796. // Test case 11: Extracting from result of vector shuffle (first input)
  2797. InstructionFoldingCase<uint32_t>(
  2798. Header() + "%main = OpFunction %void None %void_func\n" +
  2799. "%main_lab = OpLabel\n" +
  2800. "%n = OpVariable %_ptr_v2int Function\n" +
  2801. "%2 = OpLoad %v2int %n\n" +
  2802. "%3 = OpVectorShuffle %v2int %102 %2 3 0\n" +
  2803. "%4 = OpCompositeExtract %int %3 1\n" +
  2804. "OpReturn\n" +
  2805. "OpFunctionEnd",
  2806. 4, INT_7_ID),
  2807. // Test case 12: Extracting from result of vector shuffle (second input)
  2808. InstructionFoldingCase<uint32_t>(
  2809. Header() + "%main = OpFunction %void None %void_func\n" +
  2810. "%main_lab = OpLabel\n" +
  2811. "%n = OpVariable %_ptr_v2int Function\n" +
  2812. "%2 = OpLoad %v2int %n\n" +
  2813. "%3 = OpVectorShuffle %v2int %2 %102 2 0\n" +
  2814. "%4 = OpCompositeExtract %int %3 0\n" +
  2815. "OpReturn\n" +
  2816. "OpFunctionEnd",
  2817. 4, INT_7_ID)
  2818. ));
  2819. INSTANTIATE_TEST_SUITE_P(CompositeConstructFoldingTest, GeneralInstructionFoldingTest,
  2820. ::testing::Values(
  2821. // Test case 0: fold Extracts feeding construct
  2822. InstructionFoldingCase<uint32_t>(
  2823. Header() + "%main = OpFunction %void None %void_func\n" +
  2824. "%main_lab = OpLabel\n" +
  2825. "%2 = OpCopyObject %v4int %v4int_0_0_0_0\n" +
  2826. "%3 = OpCompositeExtract %int %2 0\n" +
  2827. "%4 = OpCompositeExtract %int %2 1\n" +
  2828. "%5 = OpCompositeExtract %int %2 2\n" +
  2829. "%6 = OpCompositeExtract %int %2 3\n" +
  2830. "%7 = OpCompositeConstruct %v4int %3 %4 %5 %6\n" +
  2831. "OpReturn\n" +
  2832. "OpFunctionEnd",
  2833. 7, 2),
  2834. // Test case 1: Don't fold Extracts feeding construct (Different source)
  2835. InstructionFoldingCase<uint32_t>(
  2836. Header() + "%main = OpFunction %void None %void_func\n" +
  2837. "%main_lab = OpLabel\n" +
  2838. "%2 = OpCopyObject %v4int %v4int_0_0_0_0\n" +
  2839. "%3 = OpCompositeExtract %int %2 0\n" +
  2840. "%4 = OpCompositeExtract %int %2 1\n" +
  2841. "%5 = OpCompositeExtract %int %2 2\n" +
  2842. "%6 = OpCompositeExtract %int %v4int_0_0_0_0 3\n" +
  2843. "%7 = OpCompositeConstruct %v4int %3 %4 %5 %6\n" +
  2844. "OpReturn\n" +
  2845. "OpFunctionEnd",
  2846. 7, 0),
  2847. // Test case 2: Don't fold Extracts feeding construct (bad indices)
  2848. InstructionFoldingCase<uint32_t>(
  2849. Header() + "%main = OpFunction %void None %void_func\n" +
  2850. "%main_lab = OpLabel\n" +
  2851. "%2 = OpCopyObject %v4int %v4int_0_0_0_0\n" +
  2852. "%3 = OpCompositeExtract %int %2 0\n" +
  2853. "%4 = OpCompositeExtract %int %2 0\n" +
  2854. "%5 = OpCompositeExtract %int %2 2\n" +
  2855. "%6 = OpCompositeExtract %int %2 3\n" +
  2856. "%7 = OpCompositeConstruct %v4int %3 %4 %5 %6\n" +
  2857. "OpReturn\n" +
  2858. "OpFunctionEnd",
  2859. 7, 0),
  2860. // Test case 3: Don't fold Extracts feeding construct (different type)
  2861. InstructionFoldingCase<uint32_t>(
  2862. Header() + "%main = OpFunction %void None %void_func\n" +
  2863. "%main_lab = OpLabel\n" +
  2864. "%2 = OpCopyObject %struct_v2int_int_int %struct_v2int_int_int_null\n" +
  2865. "%3 = OpCompositeExtract %v2int %2 0\n" +
  2866. "%4 = OpCompositeExtract %int %2 1\n" +
  2867. "%5 = OpCompositeExtract %int %2 2\n" +
  2868. "%7 = OpCompositeConstruct %v4int %3 %4 %5\n" +
  2869. "OpReturn\n" +
  2870. "OpFunctionEnd",
  2871. 7, 0),
  2872. // Test case 4: Fold construct with constants to constant.
  2873. InstructionFoldingCase<uint32_t>(
  2874. Header() + "%main = OpFunction %void None %void_func\n" +
  2875. "%main_lab = OpLabel\n" +
  2876. "%2 = OpCompositeConstruct %v2int %103 %103\n" +
  2877. "OpReturn\n" +
  2878. "OpFunctionEnd",
  2879. 2, VEC2_0_ID)
  2880. ));
  2881. INSTANTIATE_TEST_SUITE_P(PhiFoldingTest, GeneralInstructionFoldingTest,
  2882. ::testing::Values(
  2883. // Test case 0: Fold phi with the same values for all edges.
  2884. InstructionFoldingCase<uint32_t>(
  2885. Header() + "%main = OpFunction %void None %void_func\n" +
  2886. "%main_lab = OpLabel\n" +
  2887. " OpBranchConditional %true %l1 %l2\n" +
  2888. "%l1 = OpLabel\n" +
  2889. " OpBranch %merge_lab\n" +
  2890. "%l2 = OpLabel\n" +
  2891. " OpBranch %merge_lab\n" +
  2892. "%merge_lab = OpLabel\n" +
  2893. "%2 = OpPhi %int %100 %l1 %100 %l2\n" +
  2894. "OpReturn\n" +
  2895. "OpFunctionEnd",
  2896. 2, INT_0_ID),
  2897. // Test case 1: Fold phi in pass through loop.
  2898. InstructionFoldingCase<uint32_t>(
  2899. Header() + "%main = OpFunction %void None %void_func\n" +
  2900. "%main_lab = OpLabel\n" +
  2901. " OpBranch %l1\n" +
  2902. "%l1 = OpLabel\n" +
  2903. "%2 = OpPhi %int %100 %main_lab %2 %l1\n" +
  2904. " OpBranchConditional %true %l1 %merge_lab\n" +
  2905. "%merge_lab = OpLabel\n" +
  2906. "OpReturn\n" +
  2907. "OpFunctionEnd",
  2908. 2, INT_0_ID),
  2909. // Test case 2: Don't Fold phi because of different values.
  2910. InstructionFoldingCase<uint32_t>(
  2911. Header() + "%main = OpFunction %void None %void_func\n" +
  2912. "%main_lab = OpLabel\n" +
  2913. " OpBranch %l1\n" +
  2914. "%l1 = OpLabel\n" +
  2915. "%2 = OpPhi %int %int_0 %main_lab %int_3 %l1\n" +
  2916. " OpBranchConditional %true %l1 %merge_lab\n" +
  2917. "%merge_lab = OpLabel\n" +
  2918. "OpReturn\n" +
  2919. "OpFunctionEnd",
  2920. 2, 0)
  2921. ));
  2922. INSTANTIATE_TEST_SUITE_P(FloatRedundantFoldingTest, GeneralInstructionFoldingTest,
  2923. ::testing::Values(
  2924. // Test case 0: Don't fold n + 1.0
  2925. InstructionFoldingCase<uint32_t>(
  2926. Header() + "%main = OpFunction %void None %void_func\n" +
  2927. "%main_lab = OpLabel\n" +
  2928. "%n = OpVariable %_ptr_float Function\n" +
  2929. "%3 = OpLoad %float %n\n" +
  2930. "%2 = OpFAdd %float %3 %float_2\n" +
  2931. "OpReturn\n" +
  2932. "OpFunctionEnd",
  2933. 2, 0),
  2934. // Test case 1: Don't fold n - 1.0
  2935. InstructionFoldingCase<uint32_t>(
  2936. Header() + "%main = OpFunction %void None %void_func\n" +
  2937. "%main_lab = OpLabel\n" +
  2938. "%n = OpVariable %_ptr_float Function\n" +
  2939. "%3 = OpLoad %float %n\n" +
  2940. "%2 = OpFSub %float %3 %float_2\n" +
  2941. "OpReturn\n" +
  2942. "OpFunctionEnd",
  2943. 2, 0),
  2944. // Test case 2: Don't fold n * 2.0
  2945. InstructionFoldingCase<uint32_t>(
  2946. Header() + "%main = OpFunction %void None %void_func\n" +
  2947. "%main_lab = OpLabel\n" +
  2948. "%n = OpVariable %_ptr_float Function\n" +
  2949. "%3 = OpLoad %float %n\n" +
  2950. "%2 = OpFMul %float %3 %float_2\n" +
  2951. "OpReturn\n" +
  2952. "OpFunctionEnd",
  2953. 2, 0),
  2954. // Test case 3: Fold n + 0.0
  2955. InstructionFoldingCase<uint32_t>(
  2956. Header() + "%main = OpFunction %void None %void_func\n" +
  2957. "%main_lab = OpLabel\n" +
  2958. "%n = OpVariable %_ptr_float Function\n" +
  2959. "%3 = OpLoad %float %n\n" +
  2960. "%2 = OpFAdd %float %3 %float_0\n" +
  2961. "OpReturn\n" +
  2962. "OpFunctionEnd",
  2963. 2, 3),
  2964. // Test case 4: Fold 0.0 + n
  2965. InstructionFoldingCase<uint32_t>(
  2966. Header() + "%main = OpFunction %void None %void_func\n" +
  2967. "%main_lab = OpLabel\n" +
  2968. "%n = OpVariable %_ptr_float Function\n" +
  2969. "%3 = OpLoad %float %n\n" +
  2970. "%2 = OpFAdd %float %float_0 %3\n" +
  2971. "OpReturn\n" +
  2972. "OpFunctionEnd",
  2973. 2, 3),
  2974. // Test case 5: Fold n - 0.0
  2975. InstructionFoldingCase<uint32_t>(
  2976. Header() + "%main = OpFunction %void None %void_func\n" +
  2977. "%main_lab = OpLabel\n" +
  2978. "%n = OpVariable %_ptr_float Function\n" +
  2979. "%3 = OpLoad %float %n\n" +
  2980. "%2 = OpFSub %float %3 %float_0\n" +
  2981. "OpReturn\n" +
  2982. "OpFunctionEnd",
  2983. 2, 3),
  2984. // Test case 6: Fold n * 1.0
  2985. InstructionFoldingCase<uint32_t>(
  2986. Header() + "%main = OpFunction %void None %void_func\n" +
  2987. "%main_lab = OpLabel\n" +
  2988. "%n = OpVariable %_ptr_float Function\n" +
  2989. "%3 = OpLoad %float %n\n" +
  2990. "%2 = OpFMul %float %3 %float_1\n" +
  2991. "OpReturn\n" +
  2992. "OpFunctionEnd",
  2993. 2, 3),
  2994. // Test case 7: Fold 1.0 * n
  2995. InstructionFoldingCase<uint32_t>(
  2996. Header() + "%main = OpFunction %void None %void_func\n" +
  2997. "%main_lab = OpLabel\n" +
  2998. "%n = OpVariable %_ptr_float Function\n" +
  2999. "%3 = OpLoad %float %n\n" +
  3000. "%2 = OpFMul %float %float_1 %3\n" +
  3001. "OpReturn\n" +
  3002. "OpFunctionEnd",
  3003. 2, 3),
  3004. // Test case 8: Fold n / 1.0
  3005. InstructionFoldingCase<uint32_t>(
  3006. Header() + "%main = OpFunction %void None %void_func\n" +
  3007. "%main_lab = OpLabel\n" +
  3008. "%n = OpVariable %_ptr_float Function\n" +
  3009. "%3 = OpLoad %float %n\n" +
  3010. "%2 = OpFDiv %float %3 %float_1\n" +
  3011. "OpReturn\n" +
  3012. "OpFunctionEnd",
  3013. 2, 3),
  3014. // Test case 9: Fold n * 0.0
  3015. InstructionFoldingCase<uint32_t>(
  3016. Header() + "%main = OpFunction %void None %void_func\n" +
  3017. "%main_lab = OpLabel\n" +
  3018. "%n = OpVariable %_ptr_float Function\n" +
  3019. "%3 = OpLoad %float %n\n" +
  3020. "%2 = OpFMul %float %3 %104\n" +
  3021. "OpReturn\n" +
  3022. "OpFunctionEnd",
  3023. 2, FLOAT_0_ID),
  3024. // Test case 10: Fold 0.0 * n
  3025. InstructionFoldingCase<uint32_t>(
  3026. Header() + "%main = OpFunction %void None %void_func\n" +
  3027. "%main_lab = OpLabel\n" +
  3028. "%n = OpVariable %_ptr_float Function\n" +
  3029. "%3 = OpLoad %float %n\n" +
  3030. "%2 = OpFMul %float %104 %3\n" +
  3031. "OpReturn\n" +
  3032. "OpFunctionEnd",
  3033. 2, FLOAT_0_ID),
  3034. // Test case 11: Fold 0.0 / n
  3035. InstructionFoldingCase<uint32_t>(
  3036. Header() + "%main = OpFunction %void None %void_func\n" +
  3037. "%main_lab = OpLabel\n" +
  3038. "%n = OpVariable %_ptr_float Function\n" +
  3039. "%3 = OpLoad %float %n\n" +
  3040. "%2 = OpFDiv %float %104 %3\n" +
  3041. "OpReturn\n" +
  3042. "OpFunctionEnd",
  3043. 2, FLOAT_0_ID),
  3044. // Test case 12: Don't fold mix(a, b, 2.0)
  3045. InstructionFoldingCase<uint32_t>(
  3046. Header() + "%main = OpFunction %void None %void_func\n" +
  3047. "%main_lab = OpLabel\n" +
  3048. "%a = OpVariable %_ptr_float Function\n" +
  3049. "%b = OpVariable %_ptr_float Function\n" +
  3050. "%3 = OpLoad %float %a\n" +
  3051. "%4 = OpLoad %float %b\n" +
  3052. "%2 = OpExtInst %float %1 FMix %3 %4 %float_2\n" +
  3053. "OpReturn\n" +
  3054. "OpFunctionEnd",
  3055. 2, 0),
  3056. // Test case 13: Fold mix(a, b, 0.0)
  3057. InstructionFoldingCase<uint32_t>(
  3058. Header() + "%main = OpFunction %void None %void_func\n" +
  3059. "%main_lab = OpLabel\n" +
  3060. "%a = OpVariable %_ptr_float Function\n" +
  3061. "%b = OpVariable %_ptr_float Function\n" +
  3062. "%3 = OpLoad %float %a\n" +
  3063. "%4 = OpLoad %float %b\n" +
  3064. "%2 = OpExtInst %float %1 FMix %3 %4 %float_0\n" +
  3065. "OpReturn\n" +
  3066. "OpFunctionEnd",
  3067. 2, 3),
  3068. // Test case 14: Fold mix(a, b, 1.0)
  3069. InstructionFoldingCase<uint32_t>(
  3070. Header() + "%main = OpFunction %void None %void_func\n" +
  3071. "%main_lab = OpLabel\n" +
  3072. "%a = OpVariable %_ptr_float Function\n" +
  3073. "%b = OpVariable %_ptr_float Function\n" +
  3074. "%3 = OpLoad %float %a\n" +
  3075. "%4 = OpLoad %float %b\n" +
  3076. "%2 = OpExtInst %float %1 FMix %3 %4 %float_1\n" +
  3077. "OpReturn\n" +
  3078. "OpFunctionEnd",
  3079. 2, 4),
  3080. // Test case 15: Fold vector fadd with null
  3081. InstructionFoldingCase<uint32_t>(
  3082. Header() + "%main = OpFunction %void None %void_func\n" +
  3083. "%main_lab = OpLabel\n" +
  3084. "%a = OpVariable %_ptr_v2float Function\n" +
  3085. "%2 = OpLoad %v2float %a\n" +
  3086. "%3 = OpFAdd %v2float %2 %v2float_null\n" +
  3087. "OpReturn\n" +
  3088. "OpFunctionEnd",
  3089. 3, 2),
  3090. // Test case 16: Fold vector fadd with null
  3091. InstructionFoldingCase<uint32_t>(
  3092. Header() + "%main = OpFunction %void None %void_func\n" +
  3093. "%main_lab = OpLabel\n" +
  3094. "%a = OpVariable %_ptr_v2float Function\n" +
  3095. "%2 = OpLoad %v2float %a\n" +
  3096. "%3 = OpFAdd %v2float %v2float_null %2\n" +
  3097. "OpReturn\n" +
  3098. "OpFunctionEnd",
  3099. 3, 2),
  3100. // Test case 15: Fold vector fsub with null
  3101. InstructionFoldingCase<uint32_t>(
  3102. Header() + "%main = OpFunction %void None %void_func\n" +
  3103. "%main_lab = OpLabel\n" +
  3104. "%a = OpVariable %_ptr_v2float Function\n" +
  3105. "%2 = OpLoad %v2float %a\n" +
  3106. "%3 = OpFSub %v2float %2 %v2float_null\n" +
  3107. "OpReturn\n" +
  3108. "OpFunctionEnd",
  3109. 3, 2),
  3110. // Test case 16: Fold 0.0(half) * n
  3111. InstructionFoldingCase<uint32_t>(
  3112. Header() + "%main = OpFunction %void None %void_func\n" +
  3113. "%main_lab = OpLabel\n" +
  3114. "%n = OpVariable %_ptr_half Function\n" +
  3115. "%3 = OpLoad %half %n\n" +
  3116. "%2 = OpFMul %half %108 %3\n" +
  3117. "OpReturn\n" +
  3118. "OpFunctionEnd",
  3119. 2, HALF_0_ID),
  3120. // Test case 17: Don't fold 1.0(half) * n
  3121. InstructionFoldingCase<uint32_t>(
  3122. Header() + "%main = OpFunction %void None %void_func\n" +
  3123. "%main_lab = OpLabel\n" +
  3124. "%n = OpVariable %_ptr_half Function\n" +
  3125. "%3 = OpLoad %half %n\n" +
  3126. "%2 = OpFMul %half %half_1 %3\n" +
  3127. "OpReturn\n" +
  3128. "OpFunctionEnd",
  3129. 2, 0),
  3130. // Test case 18: Don't fold 1.0 * 1.0 (half)
  3131. InstructionFoldingCase<uint32_t>(
  3132. Header() + "%main = OpFunction %void None %void_func\n" +
  3133. "%main_lab = OpLabel\n" +
  3134. "%2 = OpFMul %half %half_1 %half_1\n" +
  3135. "OpReturn\n" +
  3136. "OpFunctionEnd",
  3137. 2, 0)
  3138. ));
  3139. INSTANTIATE_TEST_SUITE_P(DoubleRedundantFoldingTest, GeneralInstructionFoldingTest,
  3140. ::testing::Values(
  3141. // Test case 0: Don't fold n + 1.0
  3142. InstructionFoldingCase<uint32_t>(
  3143. Header() + "%main = OpFunction %void None %void_func\n" +
  3144. "%main_lab = OpLabel\n" +
  3145. "%n = OpVariable %_ptr_double Function\n" +
  3146. "%3 = OpLoad %double %n\n" +
  3147. "%2 = OpFAdd %double %3 %double_2\n" +
  3148. "OpReturn\n" +
  3149. "OpFunctionEnd",
  3150. 2, 0),
  3151. // Test case 1: Don't fold n - 1.0
  3152. InstructionFoldingCase<uint32_t>(
  3153. Header() + "%main = OpFunction %void None %void_func\n" +
  3154. "%main_lab = OpLabel\n" +
  3155. "%n = OpVariable %_ptr_double Function\n" +
  3156. "%3 = OpLoad %double %n\n" +
  3157. "%2 = OpFSub %double %3 %double_2\n" +
  3158. "OpReturn\n" +
  3159. "OpFunctionEnd",
  3160. 2, 0),
  3161. // Test case 2: Don't fold n * 2.0
  3162. InstructionFoldingCase<uint32_t>(
  3163. Header() + "%main = OpFunction %void None %void_func\n" +
  3164. "%main_lab = OpLabel\n" +
  3165. "%n = OpVariable %_ptr_double Function\n" +
  3166. "%3 = OpLoad %double %n\n" +
  3167. "%2 = OpFMul %double %3 %double_2\n" +
  3168. "OpReturn\n" +
  3169. "OpFunctionEnd",
  3170. 2, 0),
  3171. // Test case 3: Fold n + 0.0
  3172. InstructionFoldingCase<uint32_t>(
  3173. Header() + "%main = OpFunction %void None %void_func\n" +
  3174. "%main_lab = OpLabel\n" +
  3175. "%n = OpVariable %_ptr_double Function\n" +
  3176. "%3 = OpLoad %double %n\n" +
  3177. "%2 = OpFAdd %double %3 %double_0\n" +
  3178. "OpReturn\n" +
  3179. "OpFunctionEnd",
  3180. 2, 3),
  3181. // Test case 4: Fold 0.0 + n
  3182. InstructionFoldingCase<uint32_t>(
  3183. Header() + "%main = OpFunction %void None %void_func\n" +
  3184. "%main_lab = OpLabel\n" +
  3185. "%n = OpVariable %_ptr_double Function\n" +
  3186. "%3 = OpLoad %double %n\n" +
  3187. "%2 = OpFAdd %double %double_0 %3\n" +
  3188. "OpReturn\n" +
  3189. "OpFunctionEnd",
  3190. 2, 3),
  3191. // Test case 5: Fold n - 0.0
  3192. InstructionFoldingCase<uint32_t>(
  3193. Header() + "%main = OpFunction %void None %void_func\n" +
  3194. "%main_lab = OpLabel\n" +
  3195. "%n = OpVariable %_ptr_double Function\n" +
  3196. "%3 = OpLoad %double %n\n" +
  3197. "%2 = OpFSub %double %3 %double_0\n" +
  3198. "OpReturn\n" +
  3199. "OpFunctionEnd",
  3200. 2, 3),
  3201. // Test case 6: Fold n * 1.0
  3202. InstructionFoldingCase<uint32_t>(
  3203. Header() + "%main = OpFunction %void None %void_func\n" +
  3204. "%main_lab = OpLabel\n" +
  3205. "%n = OpVariable %_ptr_double Function\n" +
  3206. "%3 = OpLoad %double %n\n" +
  3207. "%2 = OpFMul %double %3 %double_1\n" +
  3208. "OpReturn\n" +
  3209. "OpFunctionEnd",
  3210. 2, 3),
  3211. // Test case 7: Fold 1.0 * n
  3212. InstructionFoldingCase<uint32_t>(
  3213. Header() + "%main = OpFunction %void None %void_func\n" +
  3214. "%main_lab = OpLabel\n" +
  3215. "%n = OpVariable %_ptr_double Function\n" +
  3216. "%3 = OpLoad %double %n\n" +
  3217. "%2 = OpFMul %double %double_1 %3\n" +
  3218. "OpReturn\n" +
  3219. "OpFunctionEnd",
  3220. 2, 3),
  3221. // Test case 8: Fold n / 1.0
  3222. InstructionFoldingCase<uint32_t>(
  3223. Header() + "%main = OpFunction %void None %void_func\n" +
  3224. "%main_lab = OpLabel\n" +
  3225. "%n = OpVariable %_ptr_double Function\n" +
  3226. "%3 = OpLoad %double %n\n" +
  3227. "%2 = OpFDiv %double %3 %double_1\n" +
  3228. "OpReturn\n" +
  3229. "OpFunctionEnd",
  3230. 2, 3),
  3231. // Test case 9: Fold n * 0.0
  3232. InstructionFoldingCase<uint32_t>(
  3233. Header() + "%main = OpFunction %void None %void_func\n" +
  3234. "%main_lab = OpLabel\n" +
  3235. "%n = OpVariable %_ptr_double Function\n" +
  3236. "%3 = OpLoad %double %n\n" +
  3237. "%2 = OpFMul %double %3 %105\n" +
  3238. "OpReturn\n" +
  3239. "OpFunctionEnd",
  3240. 2, DOUBLE_0_ID),
  3241. // Test case 10: Fold 0.0 * n
  3242. InstructionFoldingCase<uint32_t>(
  3243. Header() + "%main = OpFunction %void None %void_func\n" +
  3244. "%main_lab = OpLabel\n" +
  3245. "%n = OpVariable %_ptr_double Function\n" +
  3246. "%3 = OpLoad %double %n\n" +
  3247. "%2 = OpFMul %double %105 %3\n" +
  3248. "OpReturn\n" +
  3249. "OpFunctionEnd",
  3250. 2, DOUBLE_0_ID),
  3251. // Test case 11: Fold 0.0 / n
  3252. InstructionFoldingCase<uint32_t>(
  3253. Header() + "%main = OpFunction %void None %void_func\n" +
  3254. "%main_lab = OpLabel\n" +
  3255. "%n = OpVariable %_ptr_double Function\n" +
  3256. "%3 = OpLoad %double %n\n" +
  3257. "%2 = OpFDiv %double %105 %3\n" +
  3258. "OpReturn\n" +
  3259. "OpFunctionEnd",
  3260. 2, DOUBLE_0_ID),
  3261. // Test case 12: Don't fold mix(a, b, 2.0)
  3262. InstructionFoldingCase<uint32_t>(
  3263. Header() + "%main = OpFunction %void None %void_func\n" +
  3264. "%main_lab = OpLabel\n" +
  3265. "%a = OpVariable %_ptr_double Function\n" +
  3266. "%b = OpVariable %_ptr_double Function\n" +
  3267. "%3 = OpLoad %double %a\n" +
  3268. "%4 = OpLoad %double %b\n" +
  3269. "%2 = OpExtInst %double %1 FMix %3 %4 %double_2\n" +
  3270. "OpReturn\n" +
  3271. "OpFunctionEnd",
  3272. 2, 0),
  3273. // Test case 13: Fold mix(a, b, 0.0)
  3274. InstructionFoldingCase<uint32_t>(
  3275. Header() + "%main = OpFunction %void None %void_func\n" +
  3276. "%main_lab = OpLabel\n" +
  3277. "%a = OpVariable %_ptr_double Function\n" +
  3278. "%b = OpVariable %_ptr_double Function\n" +
  3279. "%3 = OpLoad %double %a\n" +
  3280. "%4 = OpLoad %double %b\n" +
  3281. "%2 = OpExtInst %double %1 FMix %3 %4 %double_0\n" +
  3282. "OpReturn\n" +
  3283. "OpFunctionEnd",
  3284. 2, 3),
  3285. // Test case 14: Fold mix(a, b, 1.0)
  3286. InstructionFoldingCase<uint32_t>(
  3287. Header() + "%main = OpFunction %void None %void_func\n" +
  3288. "%main_lab = OpLabel\n" +
  3289. "%a = OpVariable %_ptr_double Function\n" +
  3290. "%b = OpVariable %_ptr_double Function\n" +
  3291. "%3 = OpLoad %double %a\n" +
  3292. "%4 = OpLoad %double %b\n" +
  3293. "%2 = OpExtInst %double %1 FMix %3 %4 %double_1\n" +
  3294. "OpReturn\n" +
  3295. "OpFunctionEnd",
  3296. 2, 4)
  3297. ));
  3298. INSTANTIATE_TEST_SUITE_P(FloatVectorRedundantFoldingTest, GeneralInstructionFoldingTest,
  3299. ::testing::Values(
  3300. // Test case 0: Don't fold a * vec4(0.0, 0.0, 0.0, 1.0)
  3301. InstructionFoldingCase<uint32_t>(
  3302. Header() + "%main = OpFunction %void None %void_func\n" +
  3303. "%main_lab = OpLabel\n" +
  3304. "%n = OpVariable %_ptr_v4float Function\n" +
  3305. "%3 = OpLoad %v4float %n\n" +
  3306. "%2 = OpFMul %v4float %3 %v4float_0_0_0_1\n" +
  3307. "OpReturn\n" +
  3308. "OpFunctionEnd",
  3309. 2, 0),
  3310. // Test case 1: Fold a * vec4(0.0, 0.0, 0.0, 0.0)
  3311. InstructionFoldingCase<uint32_t>(
  3312. Header() + "%main = OpFunction %void None %void_func\n" +
  3313. "%main_lab = OpLabel\n" +
  3314. "%n = OpVariable %_ptr_v4float Function\n" +
  3315. "%3 = OpLoad %v4float %n\n" +
  3316. "%2 = OpFMul %v4float %3 %106\n" +
  3317. "OpReturn\n" +
  3318. "OpFunctionEnd",
  3319. 2, VEC4_0_ID),
  3320. // Test case 2: Fold a * vec4(1.0, 1.0, 1.0, 1.0)
  3321. InstructionFoldingCase<uint32_t>(
  3322. Header() + "%main = OpFunction %void None %void_func\n" +
  3323. "%main_lab = OpLabel\n" +
  3324. "%n = OpVariable %_ptr_v4float Function\n" +
  3325. "%3 = OpLoad %v4float %n\n" +
  3326. "%2 = OpFMul %v4float %3 %v4float_1_1_1_1\n" +
  3327. "OpReturn\n" +
  3328. "OpFunctionEnd",
  3329. 2, 3)
  3330. ));
  3331. INSTANTIATE_TEST_SUITE_P(DoubleVectorRedundantFoldingTest, GeneralInstructionFoldingTest,
  3332. ::testing::Values(
  3333. // Test case 0: Don't fold a * vec4(0.0, 0.0, 0.0, 1.0)
  3334. InstructionFoldingCase<uint32_t>(
  3335. Header() + "%main = OpFunction %void None %void_func\n" +
  3336. "%main_lab = OpLabel\n" +
  3337. "%n = OpVariable %_ptr_v4double Function\n" +
  3338. "%3 = OpLoad %v4double %n\n" +
  3339. "%2 = OpFMul %v4double %3 %v4double_0_0_0_1\n" +
  3340. "OpReturn\n" +
  3341. "OpFunctionEnd",
  3342. 2, 0),
  3343. // Test case 1: Fold a * vec4(0.0, 0.0, 0.0, 0.0)
  3344. InstructionFoldingCase<uint32_t>(
  3345. Header() + "%main = OpFunction %void None %void_func\n" +
  3346. "%main_lab = OpLabel\n" +
  3347. "%n = OpVariable %_ptr_v4double Function\n" +
  3348. "%3 = OpLoad %v4double %n\n" +
  3349. "%2 = OpFMul %v4double %3 %106\n" +
  3350. "OpReturn\n" +
  3351. "OpFunctionEnd",
  3352. 2, DVEC4_0_ID),
  3353. // Test case 2: Fold a * vec4(1.0, 1.0, 1.0, 1.0)
  3354. InstructionFoldingCase<uint32_t>(
  3355. Header() + "%main = OpFunction %void None %void_func\n" +
  3356. "%main_lab = OpLabel\n" +
  3357. "%n = OpVariable %_ptr_v4double Function\n" +
  3358. "%3 = OpLoad %v4double %n\n" +
  3359. "%2 = OpFMul %v4double %3 %v4double_1_1_1_1\n" +
  3360. "OpReturn\n" +
  3361. "OpFunctionEnd",
  3362. 2, 3)
  3363. ));
  3364. INSTANTIATE_TEST_SUITE_P(IntegerRedundantFoldingTest, GeneralInstructionFoldingTest,
  3365. ::testing::Values(
  3366. // Test case 0: Don't fold n + 1
  3367. InstructionFoldingCase<uint32_t>(
  3368. Header() + "%main = OpFunction %void None %void_func\n" +
  3369. "%main_lab = OpLabel\n" +
  3370. "%n = OpVariable %_ptr_uint Function\n" +
  3371. "%3 = OpLoad %uint %n\n" +
  3372. "%2 = OpIAdd %uint %3 %uint_1\n" +
  3373. "OpReturn\n" +
  3374. "OpFunctionEnd",
  3375. 2, 0),
  3376. // Test case 1: Don't fold 1 + n
  3377. InstructionFoldingCase<uint32_t>(
  3378. Header() + "%main = OpFunction %void None %void_func\n" +
  3379. "%main_lab = OpLabel\n" +
  3380. "%n = OpVariable %_ptr_uint Function\n" +
  3381. "%3 = OpLoad %uint %n\n" +
  3382. "%2 = OpIAdd %uint %uint_1 %3\n" +
  3383. "OpReturn\n" +
  3384. "OpFunctionEnd",
  3385. 2, 0),
  3386. // Test case 2: Fold n + 0
  3387. InstructionFoldingCase<uint32_t>(
  3388. Header() + "%main = OpFunction %void None %void_func\n" +
  3389. "%main_lab = OpLabel\n" +
  3390. "%n = OpVariable %_ptr_uint Function\n" +
  3391. "%3 = OpLoad %uint %n\n" +
  3392. "%2 = OpIAdd %uint %3 %uint_0\n" +
  3393. "OpReturn\n" +
  3394. "OpFunctionEnd",
  3395. 2, 3),
  3396. // Test case 3: Fold 0 + n
  3397. InstructionFoldingCase<uint32_t>(
  3398. Header() + "%main = OpFunction %void None %void_func\n" +
  3399. "%main_lab = OpLabel\n" +
  3400. "%n = OpVariable %_ptr_uint Function\n" +
  3401. "%3 = OpLoad %uint %n\n" +
  3402. "%2 = OpIAdd %uint %uint_0 %3\n" +
  3403. "OpReturn\n" +
  3404. "OpFunctionEnd",
  3405. 2, 3),
  3406. // Test case 4: Don't fold n + (1,0)
  3407. InstructionFoldingCase<uint32_t>(
  3408. Header() + "%main = OpFunction %void None %void_func\n" +
  3409. "%main_lab = OpLabel\n" +
  3410. "%n = OpVariable %_ptr_v2int Function\n" +
  3411. "%3 = OpLoad %v2int %n\n" +
  3412. "%2 = OpIAdd %v2int %3 %v2int_1_0\n" +
  3413. "OpReturn\n" +
  3414. "OpFunctionEnd",
  3415. 2, 0),
  3416. // Test case 5: Don't fold (1,0) + n
  3417. InstructionFoldingCase<uint32_t>(
  3418. Header() + "%main = OpFunction %void None %void_func\n" +
  3419. "%main_lab = OpLabel\n" +
  3420. "%n = OpVariable %_ptr_v2int Function\n" +
  3421. "%3 = OpLoad %v2int %n\n" +
  3422. "%2 = OpIAdd %v2int %v2int_1_0 %3\n" +
  3423. "OpReturn\n" +
  3424. "OpFunctionEnd",
  3425. 2, 0),
  3426. // Test case 6: Fold n + (0,0)
  3427. InstructionFoldingCase<uint32_t>(
  3428. Header() + "%main = OpFunction %void None %void_func\n" +
  3429. "%main_lab = OpLabel\n" +
  3430. "%n = OpVariable %_ptr_v2int Function\n" +
  3431. "%3 = OpLoad %v2int %n\n" +
  3432. "%2 = OpIAdd %v2int %3 %v2int_0_0\n" +
  3433. "OpReturn\n" +
  3434. "OpFunctionEnd",
  3435. 2, 3),
  3436. // Test case 7: Fold (0,0) + n
  3437. InstructionFoldingCase<uint32_t>(
  3438. Header() + "%main = OpFunction %void None %void_func\n" +
  3439. "%main_lab = OpLabel\n" +
  3440. "%n = OpVariable %_ptr_v2int Function\n" +
  3441. "%3 = OpLoad %v2int %n\n" +
  3442. "%2 = OpIAdd %v2int %v2int_0_0 %3\n" +
  3443. "OpReturn\n" +
  3444. "OpFunctionEnd",
  3445. 2, 3)
  3446. ));
  3447. INSTANTIATE_TEST_SUITE_P(ClampAndCmpLHS, GeneralInstructionFoldingTest,
  3448. ::testing::Values(
  3449. // Test case 0: Don't Fold 0.0 < clamp(-1, 1)
  3450. InstructionFoldingCase<uint32_t>(
  3451. Header() + "%main = OpFunction %void None %void_func\n" +
  3452. "%main_lab = OpLabel\n" +
  3453. "%n = OpVariable %_ptr_float Function\n" +
  3454. "%ld = OpLoad %float %n\n" +
  3455. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
  3456. "%2 = OpFUnordLessThan %bool %float_0 %clamp\n" +
  3457. "OpReturn\n" +
  3458. "OpFunctionEnd",
  3459. 2, 0),
  3460. // Test case 1: Don't Fold 0.0 < clamp(-1, 1)
  3461. InstructionFoldingCase<uint32_t>(
  3462. Header() + "%main = OpFunction %void None %void_func\n" +
  3463. "%main_lab = OpLabel\n" +
  3464. "%n = OpVariable %_ptr_float Function\n" +
  3465. "%ld = OpLoad %float %n\n" +
  3466. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
  3467. "%2 = OpFOrdLessThan %bool %float_0 %clamp\n" +
  3468. "OpReturn\n" +
  3469. "OpFunctionEnd",
  3470. 2, 0),
  3471. // Test case 2: Don't Fold 0.0 <= clamp(-1, 1)
  3472. InstructionFoldingCase<uint32_t>(
  3473. Header() + "%main = OpFunction %void None %void_func\n" +
  3474. "%main_lab = OpLabel\n" +
  3475. "%n = OpVariable %_ptr_float Function\n" +
  3476. "%ld = OpLoad %float %n\n" +
  3477. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
  3478. "%2 = OpFUnordLessThanEqual %bool %float_0 %clamp\n" +
  3479. "OpReturn\n" +
  3480. "OpFunctionEnd",
  3481. 2, 0),
  3482. // Test case 3: Don't Fold 0.0 <= clamp(-1, 1)
  3483. InstructionFoldingCase<uint32_t>(
  3484. Header() + "%main = OpFunction %void None %void_func\n" +
  3485. "%main_lab = OpLabel\n" +
  3486. "%n = OpVariable %_ptr_float Function\n" +
  3487. "%ld = OpLoad %float %n\n" +
  3488. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
  3489. "%2 = OpFOrdLessThanEqual %bool %float_0 %clamp\n" +
  3490. "OpReturn\n" +
  3491. "OpFunctionEnd",
  3492. 2, 0),
  3493. // Test case 4: Don't Fold 0.0 > clamp(-1, 1)
  3494. InstructionFoldingCase<uint32_t>(
  3495. Header() + "%main = OpFunction %void None %void_func\n" +
  3496. "%main_lab = OpLabel\n" +
  3497. "%n = OpVariable %_ptr_float Function\n" +
  3498. "%ld = OpLoad %float %n\n" +
  3499. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
  3500. "%2 = OpFUnordGreaterThan %bool %float_0 %clamp\n" +
  3501. "OpReturn\n" +
  3502. "OpFunctionEnd",
  3503. 2, 0),
  3504. // Test case 5: Don't Fold 0.0 > clamp(-1, 1)
  3505. InstructionFoldingCase<uint32_t>(
  3506. Header() + "%main = OpFunction %void None %void_func\n" +
  3507. "%main_lab = OpLabel\n" +
  3508. "%n = OpVariable %_ptr_float Function\n" +
  3509. "%ld = OpLoad %float %n\n" +
  3510. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
  3511. "%2 = OpFOrdGreaterThan %bool %float_0 %clamp\n" +
  3512. "OpReturn\n" +
  3513. "OpFunctionEnd",
  3514. 2, 0),
  3515. // Test case 6: Don't Fold 0.0 >= clamp(-1, 1)
  3516. InstructionFoldingCase<uint32_t>(
  3517. Header() + "%main = OpFunction %void None %void_func\n" +
  3518. "%main_lab = OpLabel\n" +
  3519. "%n = OpVariable %_ptr_float Function\n" +
  3520. "%ld = OpLoad %float %n\n" +
  3521. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
  3522. "%2 = OpFUnordGreaterThanEqual %bool %float_0 %clamp\n" +
  3523. "OpReturn\n" +
  3524. "OpFunctionEnd",
  3525. 2, 0),
  3526. // Test case 7: Don't Fold 0.0 >= clamp(-1, 1)
  3527. InstructionFoldingCase<uint32_t>(
  3528. Header() + "%main = OpFunction %void None %void_func\n" +
  3529. "%main_lab = OpLabel\n" +
  3530. "%n = OpVariable %_ptr_float Function\n" +
  3531. "%ld = OpLoad %float %n\n" +
  3532. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
  3533. "%2 = OpFOrdGreaterThanEqual %bool %float_0 %clamp\n" +
  3534. "OpReturn\n" +
  3535. "OpFunctionEnd",
  3536. 2, 0),
  3537. // Test case 8: Don't Fold 0.0 < clamp(0, 1)
  3538. InstructionFoldingCase<uint32_t>(
  3539. Header() + "%main = OpFunction %void None %void_func\n" +
  3540. "%main_lab = OpLabel\n" +
  3541. "%n = OpVariable %_ptr_float Function\n" +
  3542. "%ld = OpLoad %float %n\n" +
  3543. "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
  3544. "%2 = OpFUnordLessThan %bool %float_0 %clamp\n" +
  3545. "OpReturn\n" +
  3546. "OpFunctionEnd",
  3547. 2, 0),
  3548. // Test case 9: Don't Fold 0.0 < clamp(0, 1)
  3549. InstructionFoldingCase<uint32_t>(
  3550. Header() + "%main = OpFunction %void None %void_func\n" +
  3551. "%main_lab = OpLabel\n" +
  3552. "%n = OpVariable %_ptr_float Function\n" +
  3553. "%ld = OpLoad %float %n\n" +
  3554. "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
  3555. "%2 = OpFOrdLessThan %bool %float_0 %clamp\n" +
  3556. "OpReturn\n" +
  3557. "OpFunctionEnd",
  3558. 2, 0),
  3559. // Test case 10: Don't Fold 0.0 > clamp(-1, 0)
  3560. InstructionFoldingCase<uint32_t>(
  3561. Header() + "%main = OpFunction %void None %void_func\n" +
  3562. "%main_lab = OpLabel\n" +
  3563. "%n = OpVariable %_ptr_float Function\n" +
  3564. "%ld = OpLoad %float %n\n" +
  3565. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
  3566. "%2 = OpFUnordGreaterThan %bool %float_0 %clamp\n" +
  3567. "OpReturn\n" +
  3568. "OpFunctionEnd",
  3569. 2, 0),
  3570. // Test case 11: Don't Fold 0.0 > clamp(-1, 0)
  3571. InstructionFoldingCase<uint32_t>(
  3572. Header() + "%main = OpFunction %void None %void_func\n" +
  3573. "%main_lab = OpLabel\n" +
  3574. "%n = OpVariable %_ptr_float Function\n" +
  3575. "%ld = OpLoad %float %n\n" +
  3576. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
  3577. "%2 = OpFOrdGreaterThan %bool %float_0 %clamp\n" +
  3578. "OpReturn\n" +
  3579. "OpFunctionEnd",
  3580. 2, 0)
  3581. ));
  3582. INSTANTIATE_TEST_SUITE_P(ClampAndCmpRHS, GeneralInstructionFoldingTest,
  3583. ::testing::Values(
  3584. // Test case 0: Don't Fold clamp(-1, 1) < 0.0
  3585. InstructionFoldingCase<uint32_t>(
  3586. Header() + "%main = OpFunction %void None %void_func\n" +
  3587. "%main_lab = OpLabel\n" +
  3588. "%n = OpVariable %_ptr_float Function\n" +
  3589. "%ld = OpLoad %float %n\n" +
  3590. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
  3591. "%2 = OpFUnordLessThan %bool %clamp %float_0\n" +
  3592. "OpReturn\n" +
  3593. "OpFunctionEnd",
  3594. 2, 0),
  3595. // Test case 1: Don't Fold clamp(-1, 1) < 0.0
  3596. InstructionFoldingCase<uint32_t>(
  3597. Header() + "%main = OpFunction %void None %void_func\n" +
  3598. "%main_lab = OpLabel\n" +
  3599. "%n = OpVariable %_ptr_float Function\n" +
  3600. "%ld = OpLoad %float %n\n" +
  3601. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
  3602. "%2 = OpFOrdLessThan %bool %clamp %float_0\n" +
  3603. "OpReturn\n" +
  3604. "OpFunctionEnd",
  3605. 2, 0),
  3606. // Test case 2: Don't Fold clamp(-1, 1) <= 0.0
  3607. InstructionFoldingCase<uint32_t>(
  3608. Header() + "%main = OpFunction %void None %void_func\n" +
  3609. "%main_lab = OpLabel\n" +
  3610. "%n = OpVariable %_ptr_float Function\n" +
  3611. "%ld = OpLoad %float %n\n" +
  3612. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
  3613. "%2 = OpFUnordLessThanEqual %bool %clamp %float_0\n" +
  3614. "OpReturn\n" +
  3615. "OpFunctionEnd",
  3616. 2, 0),
  3617. // Test case 3: Don't Fold clamp(-1, 1) <= 0.0
  3618. InstructionFoldingCase<uint32_t>(
  3619. Header() + "%main = OpFunction %void None %void_func\n" +
  3620. "%main_lab = OpLabel\n" +
  3621. "%n = OpVariable %_ptr_float Function\n" +
  3622. "%ld = OpLoad %float %n\n" +
  3623. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
  3624. "%2 = OpFOrdLessThanEqual %bool %clamp %float_0\n" +
  3625. "OpReturn\n" +
  3626. "OpFunctionEnd",
  3627. 2, 0),
  3628. // Test case 4: Don't Fold clamp(-1, 1) > 0.0
  3629. InstructionFoldingCase<uint32_t>(
  3630. Header() + "%main = OpFunction %void None %void_func\n" +
  3631. "%main_lab = OpLabel\n" +
  3632. "%n = OpVariable %_ptr_float Function\n" +
  3633. "%ld = OpLoad %float %n\n" +
  3634. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
  3635. "%2 = OpFUnordGreaterThan %bool %clamp %float_0\n" +
  3636. "OpReturn\n" +
  3637. "OpFunctionEnd",
  3638. 2, 0),
  3639. // Test case 5: Don't Fold clamp(-1, 1) > 0.0
  3640. InstructionFoldingCase<uint32_t>(
  3641. Header() + "%main = OpFunction %void None %void_func\n" +
  3642. "%main_lab = OpLabel\n" +
  3643. "%n = OpVariable %_ptr_float Function\n" +
  3644. "%ld = OpLoad %float %n\n" +
  3645. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
  3646. "%2 = OpFOrdGreaterThan %bool %clamp %float_0\n" +
  3647. "OpReturn\n" +
  3648. "OpFunctionEnd",
  3649. 2, 0),
  3650. // Test case 6: Don't Fold clamp(-1, 1) >= 0.0
  3651. InstructionFoldingCase<uint32_t>(
  3652. Header() + "%main = OpFunction %void None %void_func\n" +
  3653. "%main_lab = OpLabel\n" +
  3654. "%n = OpVariable %_ptr_float Function\n" +
  3655. "%ld = OpLoad %float %n\n" +
  3656. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
  3657. "%2 = OpFUnordGreaterThanEqual %bool %clamp %float_0\n" +
  3658. "OpReturn\n" +
  3659. "OpFunctionEnd",
  3660. 2, 0),
  3661. // Test case 7: Don't Fold clamp(-1, 1) >= 0.0
  3662. InstructionFoldingCase<uint32_t>(
  3663. Header() + "%main = OpFunction %void None %void_func\n" +
  3664. "%main_lab = OpLabel\n" +
  3665. "%n = OpVariable %_ptr_float Function\n" +
  3666. "%ld = OpLoad %float %n\n" +
  3667. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
  3668. "%2 = OpFOrdGreaterThanEqual %bool %clamp %float_0\n" +
  3669. "OpReturn\n" +
  3670. "OpFunctionEnd",
  3671. 2, 0),
  3672. // Test case 8: Don't Fold clamp(-1, 0) < 0.0
  3673. InstructionFoldingCase<uint32_t>(
  3674. Header() + "%main = OpFunction %void None %void_func\n" +
  3675. "%main_lab = OpLabel\n" +
  3676. "%n = OpVariable %_ptr_float Function\n" +
  3677. "%ld = OpLoad %float %n\n" +
  3678. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
  3679. "%2 = OpFUnordLessThan %bool %clamp %float_0\n" +
  3680. "OpReturn\n" +
  3681. "OpFunctionEnd",
  3682. 2, 0),
  3683. // Test case 9: Don't Fold clamp(0, 1) < 1
  3684. InstructionFoldingCase<uint32_t>(
  3685. Header() + "%main = OpFunction %void None %void_func\n" +
  3686. "%main_lab = OpLabel\n" +
  3687. "%n = OpVariable %_ptr_float Function\n" +
  3688. "%ld = OpLoad %float %n\n" +
  3689. "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
  3690. "%2 = OpFOrdLessThan %bool %clamp %float_1\n" +
  3691. "OpReturn\n" +
  3692. "OpFunctionEnd",
  3693. 2, 0),
  3694. // Test case 10: Don't Fold clamp(-1, 0) > -1
  3695. InstructionFoldingCase<uint32_t>(
  3696. Header() + "%main = OpFunction %void None %void_func\n" +
  3697. "%main_lab = OpLabel\n" +
  3698. "%n = OpVariable %_ptr_float Function\n" +
  3699. "%ld = OpLoad %float %n\n" +
  3700. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
  3701. "%2 = OpFUnordGreaterThan %bool %clamp %float_n1\n" +
  3702. "OpReturn\n" +
  3703. "OpFunctionEnd",
  3704. 2, 0),
  3705. // Test case 11: Don't Fold clamp(-1, 0) > -1
  3706. InstructionFoldingCase<uint32_t>(
  3707. Header() + "%main = OpFunction %void None %void_func\n" +
  3708. "%main_lab = OpLabel\n" +
  3709. "%n = OpVariable %_ptr_float Function\n" +
  3710. "%ld = OpLoad %float %n\n" +
  3711. "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
  3712. "%2 = OpFOrdGreaterThan %bool %clamp %float_n1\n" +
  3713. "OpReturn\n" +
  3714. "OpFunctionEnd",
  3715. 2, 0)
  3716. ));
  3717. INSTANTIATE_TEST_SUITE_P(FToIConstantFoldingTest, IntegerInstructionFoldingTest,
  3718. ::testing::Values(
  3719. // Test case 0: Fold int(3.0)
  3720. InstructionFoldingCase<uint32_t>(
  3721. Header() + "%main = OpFunction %void None %void_func\n" +
  3722. "%main_lab = OpLabel\n" +
  3723. "%2 = OpConvertFToS %int %float_3\n" +
  3724. "OpReturn\n" +
  3725. "OpFunctionEnd",
  3726. 2, 3),
  3727. // Test case 1: Fold uint(3.0)
  3728. InstructionFoldingCase<uint32_t>(
  3729. Header() + "%main = OpFunction %void None %void_func\n" +
  3730. "%main_lab = OpLabel\n" +
  3731. "%2 = OpConvertFToU %int %float_3\n" +
  3732. "OpReturn\n" +
  3733. "OpFunctionEnd",
  3734. 2, 3)
  3735. ));
  3736. INSTANTIATE_TEST_SUITE_P(IToFConstantFoldingTest, FloatInstructionFoldingTest,
  3737. ::testing::Values(
  3738. // Test case 0: Fold float(3)
  3739. InstructionFoldingCase<float>(
  3740. Header() + "%main = OpFunction %void None %void_func\n" +
  3741. "%main_lab = OpLabel\n" +
  3742. "%2 = OpConvertSToF %float %int_3\n" +
  3743. "OpReturn\n" +
  3744. "OpFunctionEnd",
  3745. 2, 3.0),
  3746. // Test case 1: Fold float(3u)
  3747. InstructionFoldingCase<float>(
  3748. Header() + "%main = OpFunction %void None %void_func\n" +
  3749. "%main_lab = OpLabel\n" +
  3750. "%2 = OpConvertUToF %float %uint_3\n" +
  3751. "OpReturn\n" +
  3752. "OpFunctionEnd",
  3753. 2, 3.0)
  3754. ));
  3755. // clang-format on
  3756. using ToNegateFoldingTest =
  3757. ::testing::TestWithParam<InstructionFoldingCase<uint32_t>>;
  3758. TEST_P(ToNegateFoldingTest, Case) {
  3759. const auto& tc = GetParam();
  3760. // Build module.
  3761. std::unique_ptr<IRContext> context =
  3762. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
  3763. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  3764. ASSERT_NE(nullptr, context);
  3765. // Fold the instruction to test.
  3766. analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
  3767. Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
  3768. std::unique_ptr<Instruction> original_inst(inst->Clone(context.get()));
  3769. bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
  3770. // Make sure the instruction folded as expected.
  3771. EXPECT_EQ(inst->result_id(), original_inst->result_id());
  3772. EXPECT_EQ(inst->type_id(), original_inst->type_id());
  3773. EXPECT_TRUE((!succeeded) == (tc.expected_result == 0));
  3774. if (succeeded) {
  3775. EXPECT_EQ(inst->opcode(), SpvOpFNegate);
  3776. EXPECT_EQ(inst->GetSingleWordInOperand(0), tc.expected_result);
  3777. } else {
  3778. EXPECT_EQ(inst->NumInOperands(), original_inst->NumInOperands());
  3779. for (uint32_t i = 0; i < inst->NumInOperands(); ++i) {
  3780. EXPECT_EQ(inst->GetOperand(i), original_inst->GetOperand(i));
  3781. }
  3782. }
  3783. }
  3784. // clang-format off
  3785. INSTANTIATE_TEST_SUITE_P(FloatRedundantSubFoldingTest, ToNegateFoldingTest,
  3786. ::testing::Values(
  3787. // Test case 0: Don't fold 1.0 - n
  3788. InstructionFoldingCase<uint32_t>(
  3789. Header() + "%main = OpFunction %void None %void_func\n" +
  3790. "%main_lab = OpLabel\n" +
  3791. "%n = OpVariable %_ptr_float Function\n" +
  3792. "%3 = OpLoad %float %n\n" +
  3793. "%2 = OpFSub %float %float_1 %3\n" +
  3794. "OpReturn\n" +
  3795. "OpFunctionEnd",
  3796. 2, 0),
  3797. // Test case 1: Fold 0.0 - n
  3798. InstructionFoldingCase<uint32_t>(
  3799. Header() + "%main = OpFunction %void None %void_func\n" +
  3800. "%main_lab = OpLabel\n" +
  3801. "%n = OpVariable %_ptr_float Function\n" +
  3802. "%3 = OpLoad %float %n\n" +
  3803. "%2 = OpFSub %float %float_0 %3\n" +
  3804. "OpReturn\n" +
  3805. "OpFunctionEnd",
  3806. 2, 3),
  3807. // Test case 2: Don't fold (0,0,0,1) - n
  3808. InstructionFoldingCase<uint32_t>(
  3809. Header() + "%main = OpFunction %void None %void_func\n" +
  3810. "%main_lab = OpLabel\n" +
  3811. "%n = OpVariable %_ptr_v4float Function\n" +
  3812. "%3 = OpLoad %v4float %n\n" +
  3813. "%2 = OpFSub %v4float %v4float_0_0_0_1 %3\n" +
  3814. "OpReturn\n" +
  3815. "OpFunctionEnd",
  3816. 2, 0),
  3817. // Test case 3: Fold (0,0,0,0) - n
  3818. InstructionFoldingCase<uint32_t>(
  3819. Header() + "%main = OpFunction %void None %void_func\n" +
  3820. "%main_lab = OpLabel\n" +
  3821. "%n = OpVariable %_ptr_v4float Function\n" +
  3822. "%3 = OpLoad %v4float %n\n" +
  3823. "%2 = OpFSub %v4float %v4float_0_0_0_0 %3\n" +
  3824. "OpReturn\n" +
  3825. "OpFunctionEnd",
  3826. 2, 3)
  3827. ));
  3828. INSTANTIATE_TEST_SUITE_P(DoubleRedundantSubFoldingTest, ToNegateFoldingTest,
  3829. ::testing::Values(
  3830. // Test case 0: Don't fold 1.0 - n
  3831. InstructionFoldingCase<uint32_t>(
  3832. Header() + "%main = OpFunction %void None %void_func\n" +
  3833. "%main_lab = OpLabel\n" +
  3834. "%n = OpVariable %_ptr_double Function\n" +
  3835. "%3 = OpLoad %double %n\n" +
  3836. "%2 = OpFSub %double %double_1 %3\n" +
  3837. "OpReturn\n" +
  3838. "OpFunctionEnd",
  3839. 2, 0),
  3840. // Test case 1: Fold 0.0 - n
  3841. InstructionFoldingCase<uint32_t>(
  3842. Header() + "%main = OpFunction %void None %void_func\n" +
  3843. "%main_lab = OpLabel\n" +
  3844. "%n = OpVariable %_ptr_double Function\n" +
  3845. "%3 = OpLoad %double %n\n" +
  3846. "%2 = OpFSub %double %double_0 %3\n" +
  3847. "OpReturn\n" +
  3848. "OpFunctionEnd",
  3849. 2, 3),
  3850. // Test case 2: Don't fold (0,0,0,1) - n
  3851. InstructionFoldingCase<uint32_t>(
  3852. Header() + "%main = OpFunction %void None %void_func\n" +
  3853. "%main_lab = OpLabel\n" +
  3854. "%n = OpVariable %_ptr_v4double Function\n" +
  3855. "%3 = OpLoad %v4double %n\n" +
  3856. "%2 = OpFSub %v4double %v4double_0_0_0_1 %3\n" +
  3857. "OpReturn\n" +
  3858. "OpFunctionEnd",
  3859. 2, 0),
  3860. // Test case 3: Fold (0,0,0,0) - n
  3861. InstructionFoldingCase<uint32_t>(
  3862. Header() + "%main = OpFunction %void None %void_func\n" +
  3863. "%main_lab = OpLabel\n" +
  3864. "%n = OpVariable %_ptr_v4double Function\n" +
  3865. "%3 = OpLoad %v4double %n\n" +
  3866. "%2 = OpFSub %v4double %v4double_0_0_0_0 %3\n" +
  3867. "OpReturn\n" +
  3868. "OpFunctionEnd",
  3869. 2, 3)
  3870. ));
  3871. using MatchingInstructionFoldingTest =
  3872. ::testing::TestWithParam<InstructionFoldingCase<bool>>;
  3873. TEST_P(MatchingInstructionFoldingTest, Case) {
  3874. const auto& tc = GetParam();
  3875. // Build module.
  3876. std::unique_ptr<IRContext> context =
  3877. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
  3878. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  3879. ASSERT_NE(nullptr, context);
  3880. // Fold the instruction to test.
  3881. analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
  3882. Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
  3883. std::unique_ptr<Instruction> original_inst(inst->Clone(context.get()));
  3884. bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
  3885. EXPECT_EQ(succeeded, tc.expected_result);
  3886. if (succeeded) {
  3887. Match(tc.test_body, context.get());
  3888. }
  3889. }
  3890. INSTANTIATE_TEST_SUITE_P(RedundantIntegerMatching, MatchingInstructionFoldingTest,
  3891. ::testing::Values(
  3892. // Test case 0: Fold 0 + n (change sign)
  3893. InstructionFoldingCase<bool>(
  3894. Header() +
  3895. "; CHECK: [[uint:%\\w+]] = OpTypeInt 32 0\n" +
  3896. "; CHECK: %2 = OpBitcast [[uint]] %3\n" +
  3897. "%main = OpFunction %void None %void_func\n" +
  3898. "%main_lab = OpLabel\n" +
  3899. "%n = OpVariable %_ptr_int Function\n" +
  3900. "%3 = OpLoad %uint %n\n" +
  3901. "%2 = OpIAdd %uint %int_0 %3\n" +
  3902. "OpReturn\n" +
  3903. "OpFunctionEnd\n",
  3904. 2, true),
  3905. // Test case 0: Fold 0 + n (change sign)
  3906. InstructionFoldingCase<bool>(
  3907. Header() +
  3908. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  3909. "; CHECK: %2 = OpBitcast [[int]] %3\n" +
  3910. "%main = OpFunction %void None %void_func\n" +
  3911. "%main_lab = OpLabel\n" +
  3912. "%n = OpVariable %_ptr_int Function\n" +
  3913. "%3 = OpLoad %int %n\n" +
  3914. "%2 = OpIAdd %int %uint_0 %3\n" +
  3915. "OpReturn\n" +
  3916. "OpFunctionEnd\n",
  3917. 2, true)
  3918. ));
  3919. INSTANTIATE_TEST_SUITE_P(MergeNegateTest, MatchingInstructionFoldingTest,
  3920. ::testing::Values(
  3921. // Test case 0: fold consecutive fnegate
  3922. // -(-x) = x
  3923. InstructionFoldingCase<bool>(
  3924. Header() +
  3925. "; CHECK: [[ld:%\\w+]] = OpLoad [[float:%\\w+]]\n" +
  3926. "; CHECK: %4 = OpCopyObject [[float]] [[ld]]\n" +
  3927. "%main = OpFunction %void None %void_func\n" +
  3928. "%main_lab = OpLabel\n" +
  3929. "%var = OpVariable %_ptr_float Function\n" +
  3930. "%2 = OpLoad %float %var\n" +
  3931. "%3 = OpFNegate %float %2\n" +
  3932. "%4 = OpFNegate %float %3\n" +
  3933. "OpReturn\n" +
  3934. "OpFunctionEnd",
  3935. 4, true),
  3936. // Test case 1: fold fnegate(fmul with const).
  3937. // -(x * 2.0) = x * -2.0
  3938. InstructionFoldingCase<bool>(
  3939. Header() +
  3940. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  3941. "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2\n" +
  3942. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  3943. "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_n2]]\n" +
  3944. "%main = OpFunction %void None %void_func\n" +
  3945. "%main_lab = OpLabel\n" +
  3946. "%var = OpVariable %_ptr_float Function\n" +
  3947. "%2 = OpLoad %float %var\n" +
  3948. "%3 = OpFMul %float %2 %float_2\n" +
  3949. "%4 = OpFNegate %float %3\n" +
  3950. "OpReturn\n" +
  3951. "OpFunctionEnd",
  3952. 4, true),
  3953. // Test case 2: fold fnegate(fmul with const).
  3954. // -(2.0 * x) = x * 2.0
  3955. InstructionFoldingCase<bool>(
  3956. Header() +
  3957. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  3958. "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2\n" +
  3959. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  3960. "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_n2]]\n" +
  3961. "%main = OpFunction %void None %void_func\n" +
  3962. "%main_lab = OpLabel\n" +
  3963. "%var = OpVariable %_ptr_float Function\n" +
  3964. "%2 = OpLoad %float %var\n" +
  3965. "%3 = OpFMul %float %float_2 %2\n" +
  3966. "%4 = OpFNegate %float %3\n" +
  3967. "OpReturn\n" +
  3968. "OpFunctionEnd",
  3969. 4, true),
  3970. // Test case 3: fold fnegate(fdiv with const).
  3971. // -(x / 2.0) = x * -0.5
  3972. InstructionFoldingCase<bool>(
  3973. Header() +
  3974. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  3975. "; CHECK: [[float_n0p5:%\\w+]] = OpConstant [[float]] -0.5\n" +
  3976. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  3977. "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_n0p5]]\n" +
  3978. "%main = OpFunction %void None %void_func\n" +
  3979. "%main_lab = OpLabel\n" +
  3980. "%var = OpVariable %_ptr_float Function\n" +
  3981. "%2 = OpLoad %float %var\n" +
  3982. "%3 = OpFDiv %float %2 %float_2\n" +
  3983. "%4 = OpFNegate %float %3\n" +
  3984. "OpReturn\n" +
  3985. "OpFunctionEnd",
  3986. 4, true),
  3987. // Test case 4: fold fnegate(fdiv with const).
  3988. // -(2.0 / x) = -2.0 / x
  3989. InstructionFoldingCase<bool>(
  3990. Header() +
  3991. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  3992. "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2\n" +
  3993. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  3994. "; CHECK: %4 = OpFDiv [[float]] [[float_n2]] [[ld]]\n" +
  3995. "%main = OpFunction %void None %void_func\n" +
  3996. "%main_lab = OpLabel\n" +
  3997. "%var = OpVariable %_ptr_float Function\n" +
  3998. "%2 = OpLoad %float %var\n" +
  3999. "%3 = OpFDiv %float %float_2 %2\n" +
  4000. "%4 = OpFNegate %float %3\n" +
  4001. "OpReturn\n" +
  4002. "OpFunctionEnd",
  4003. 4, true),
  4004. // Test case 5: fold fnegate(fadd with const).
  4005. // -(2.0 + x) = -2.0 - x
  4006. InstructionFoldingCase<bool>(
  4007. Header() +
  4008. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  4009. "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2\n" +
  4010. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  4011. "; CHECK: %4 = OpFSub [[float]] [[float_n2]] [[ld]]\n" +
  4012. "%main = OpFunction %void None %void_func\n" +
  4013. "%main_lab = OpLabel\n" +
  4014. "%var = OpVariable %_ptr_float Function\n" +
  4015. "%2 = OpLoad %float %var\n" +
  4016. "%3 = OpFAdd %float %float_2 %2\n" +
  4017. "%4 = OpFNegate %float %3\n" +
  4018. "OpReturn\n" +
  4019. "OpFunctionEnd",
  4020. 4, true),
  4021. // Test case 6: fold fnegate(fadd with const).
  4022. // -(x + 2.0) = -2.0 - x
  4023. InstructionFoldingCase<bool>(
  4024. Header() +
  4025. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  4026. "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2\n" +
  4027. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  4028. "; CHECK: %4 = OpFSub [[float]] [[float_n2]] [[ld]]\n" +
  4029. "%main = OpFunction %void None %void_func\n" +
  4030. "%main_lab = OpLabel\n" +
  4031. "%var = OpVariable %_ptr_float Function\n" +
  4032. "%2 = OpLoad %float %var\n" +
  4033. "%3 = OpFAdd %float %2 %float_2\n" +
  4034. "%4 = OpFNegate %float %3\n" +
  4035. "OpReturn\n" +
  4036. "OpFunctionEnd",
  4037. 4, true),
  4038. // Test case 7: fold fnegate(fsub with const).
  4039. // -(2.0 - x) = x - 2.0
  4040. InstructionFoldingCase<bool>(
  4041. Header() +
  4042. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  4043. "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
  4044. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  4045. "; CHECK: %4 = OpFSub [[float]] [[ld]] [[float_2]]\n" +
  4046. "%main = OpFunction %void None %void_func\n" +
  4047. "%main_lab = OpLabel\n" +
  4048. "%var = OpVariable %_ptr_float Function\n" +
  4049. "%2 = OpLoad %float %var\n" +
  4050. "%3 = OpFSub %float %float_2 %2\n" +
  4051. "%4 = OpFNegate %float %3\n" +
  4052. "OpReturn\n" +
  4053. "OpFunctionEnd",
  4054. 4, true),
  4055. // Test case 8: fold fnegate(fsub with const).
  4056. // -(x - 2.0) = 2.0 - x
  4057. InstructionFoldingCase<bool>(
  4058. Header() +
  4059. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  4060. "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
  4061. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  4062. "; CHECK: %4 = OpFSub [[float]] [[float_2]] [[ld]]\n" +
  4063. "%main = OpFunction %void None %void_func\n" +
  4064. "%main_lab = OpLabel\n" +
  4065. "%var = OpVariable %_ptr_float Function\n" +
  4066. "%2 = OpLoad %float %var\n" +
  4067. "%3 = OpFSub %float %2 %float_2\n" +
  4068. "%4 = OpFNegate %float %3\n" +
  4069. "OpReturn\n" +
  4070. "OpFunctionEnd",
  4071. 4, true),
  4072. // Test case 9: fold consecutive snegate
  4073. // -(-x) = x
  4074. InstructionFoldingCase<bool>(
  4075. Header() +
  4076. "; CHECK: [[ld:%\\w+]] = OpLoad [[int:%\\w+]]\n" +
  4077. "; CHECK: %4 = OpCopyObject [[int]] [[ld]]\n" +
  4078. "%main = OpFunction %void None %void_func\n" +
  4079. "%main_lab = OpLabel\n" +
  4080. "%var = OpVariable %_ptr_int Function\n" +
  4081. "%2 = OpLoad %int %var\n" +
  4082. "%3 = OpSNegate %int %2\n" +
  4083. "%4 = OpSNegate %int %3\n" +
  4084. "OpReturn\n" +
  4085. "OpFunctionEnd",
  4086. 4, true),
  4087. // Test case 10: fold consecutive vector negate
  4088. // -(-x) = x
  4089. InstructionFoldingCase<bool>(
  4090. Header() +
  4091. "; CHECK: [[ld:%\\w+]] = OpLoad [[v2float:%\\w+]]\n" +
  4092. "; CHECK: %4 = OpCopyObject [[v2float]] [[ld]]\n" +
  4093. "%main = OpFunction %void None %void_func\n" +
  4094. "%main_lab = OpLabel\n" +
  4095. "%var = OpVariable %_ptr_v2float Function\n" +
  4096. "%2 = OpLoad %v2float %var\n" +
  4097. "%3 = OpFNegate %v2float %2\n" +
  4098. "%4 = OpFNegate %v2float %3\n" +
  4099. "OpReturn\n" +
  4100. "OpFunctionEnd",
  4101. 4, true),
  4102. // Test case 11: fold snegate(iadd with const).
  4103. // -(2 + x) = -2 - x
  4104. InstructionFoldingCase<bool>(
  4105. Header() +
  4106. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  4107. "; CHECK: OpConstant [[int]] -2147483648\n" +
  4108. "; CHECK: [[int_n2:%\\w+]] = OpConstant [[int]] -2\n" +
  4109. "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
  4110. "; CHECK: %4 = OpISub [[int]] [[int_n2]] [[ld]]\n" +
  4111. "%main = OpFunction %void None %void_func\n" +
  4112. "%main_lab = OpLabel\n" +
  4113. "%var = OpVariable %_ptr_int Function\n" +
  4114. "%2 = OpLoad %int %var\n" +
  4115. "%3 = OpIAdd %int %int_2 %2\n" +
  4116. "%4 = OpSNegate %int %3\n" +
  4117. "OpReturn\n" +
  4118. "OpFunctionEnd",
  4119. 4, true),
  4120. // Test case 12: fold snegate(iadd with const).
  4121. // -(x + 2) = -2 - x
  4122. InstructionFoldingCase<bool>(
  4123. Header() +
  4124. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  4125. "; CHECK: OpConstant [[int]] -2147483648\n" +
  4126. "; CHECK: [[int_n2:%\\w+]] = OpConstant [[int]] -2\n" +
  4127. "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
  4128. "; CHECK: %4 = OpISub [[int]] [[int_n2]] [[ld]]\n" +
  4129. "%main = OpFunction %void None %void_func\n" +
  4130. "%main_lab = OpLabel\n" +
  4131. "%var = OpVariable %_ptr_int Function\n" +
  4132. "%2 = OpLoad %int %var\n" +
  4133. "%3 = OpIAdd %int %2 %int_2\n" +
  4134. "%4 = OpSNegate %int %3\n" +
  4135. "OpReturn\n" +
  4136. "OpFunctionEnd",
  4137. 4, true),
  4138. // Test case 13: fold snegate(isub with const).
  4139. // -(2 - x) = x - 2
  4140. InstructionFoldingCase<bool>(
  4141. Header() +
  4142. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  4143. "; CHECK: [[int_2:%\\w+]] = OpConstant [[int]] 2\n" +
  4144. "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
  4145. "; CHECK: %4 = OpISub [[int]] [[ld]] [[int_2]]\n" +
  4146. "%main = OpFunction %void None %void_func\n" +
  4147. "%main_lab = OpLabel\n" +
  4148. "%var = OpVariable %_ptr_int Function\n" +
  4149. "%2 = OpLoad %int %var\n" +
  4150. "%3 = OpISub %int %int_2 %2\n" +
  4151. "%4 = OpSNegate %int %3\n" +
  4152. "OpReturn\n" +
  4153. "OpFunctionEnd",
  4154. 4, true),
  4155. // Test case 14: fold snegate(isub with const).
  4156. // -(x - 2) = 2 - x
  4157. InstructionFoldingCase<bool>(
  4158. Header() +
  4159. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  4160. "; CHECK: [[int_2:%\\w+]] = OpConstant [[int]] 2\n" +
  4161. "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
  4162. "; CHECK: %4 = OpISub [[int]] [[int_2]] [[ld]]\n" +
  4163. "%main = OpFunction %void None %void_func\n" +
  4164. "%main_lab = OpLabel\n" +
  4165. "%var = OpVariable %_ptr_int Function\n" +
  4166. "%2 = OpLoad %int %var\n" +
  4167. "%3 = OpISub %int %2 %int_2\n" +
  4168. "%4 = OpSNegate %int %3\n" +
  4169. "OpReturn\n" +
  4170. "OpFunctionEnd",
  4171. 4, true),
  4172. // Test case 15: fold snegate(iadd with const).
  4173. // -(x + 2) = -2 - x
  4174. InstructionFoldingCase<bool>(
  4175. Header() +
  4176. "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
  4177. "; CHECK: [[long_n2:%\\w+]] = OpConstant [[long]] -2\n" +
  4178. "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
  4179. "; CHECK: %4 = OpISub [[long]] [[long_n2]] [[ld]]\n" +
  4180. "%main = OpFunction %void None %void_func\n" +
  4181. "%main_lab = OpLabel\n" +
  4182. "%var = OpVariable %_ptr_long Function\n" +
  4183. "%2 = OpLoad %long %var\n" +
  4184. "%3 = OpIAdd %long %2 %long_2\n" +
  4185. "%4 = OpSNegate %long %3\n" +
  4186. "OpReturn\n" +
  4187. "OpFunctionEnd",
  4188. 4, true),
  4189. // Test case 16: fold snegate(isub with const).
  4190. // -(2 - x) = x - 2
  4191. InstructionFoldingCase<bool>(
  4192. Header() +
  4193. "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
  4194. "; CHECK: [[long_2:%\\w+]] = OpConstant [[long]] 2\n" +
  4195. "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
  4196. "; CHECK: %4 = OpISub [[long]] [[ld]] [[long_2]]\n" +
  4197. "%main = OpFunction %void None %void_func\n" +
  4198. "%main_lab = OpLabel\n" +
  4199. "%var = OpVariable %_ptr_long Function\n" +
  4200. "%2 = OpLoad %long %var\n" +
  4201. "%3 = OpISub %long %long_2 %2\n" +
  4202. "%4 = OpSNegate %long %3\n" +
  4203. "OpReturn\n" +
  4204. "OpFunctionEnd",
  4205. 4, true),
  4206. // Test case 17: fold snegate(isub with const).
  4207. // -(x - 2) = 2 - x
  4208. InstructionFoldingCase<bool>(
  4209. Header() +
  4210. "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
  4211. "; CHECK: [[long_2:%\\w+]] = OpConstant [[long]] 2\n" +
  4212. "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
  4213. "; CHECK: %4 = OpISub [[long]] [[long_2]] [[ld]]\n" +
  4214. "%main = OpFunction %void None %void_func\n" +
  4215. "%main_lab = OpLabel\n" +
  4216. "%var = OpVariable %_ptr_long Function\n" +
  4217. "%2 = OpLoad %long %var\n" +
  4218. "%3 = OpISub %long %2 %long_2\n" +
  4219. "%4 = OpSNegate %long %3\n" +
  4220. "OpReturn\n" +
  4221. "OpFunctionEnd",
  4222. 4, true),
  4223. // Test case 18: fold -vec4(-1.0, 2.0, 1.0, 3.0)
  4224. InstructionFoldingCase<bool>(
  4225. Header() +
  4226. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  4227. "; CHECK: [[v4float:%\\w+]] = OpTypeVector [[float]] 4\n" +
  4228. "; CHECK: [[float_n1:%\\w+]] = OpConstant [[float]] -1\n" +
  4229. "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
  4230. "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2\n" +
  4231. "; CHECK: [[float_n3:%\\w+]] = OpConstant [[float]] -3\n" +
  4232. "; CHECK: [[v4float_1_n2_n1_n3:%\\w+]] = OpConstantComposite [[v4float]] [[float_1]] [[float_n2]] [[float_n1]] [[float_n3]]\n" +
  4233. "; CHECK: %2 = OpCopyObject [[v4float]] [[v4float_1_n2_n1_n3]]\n" +
  4234. "%main = OpFunction %void None %void_func\n" +
  4235. "%main_lab = OpLabel\n" +
  4236. "%2 = OpFNegate %v4float %v4float_n1_2_1_3\n" +
  4237. "OpReturn\n" +
  4238. "OpFunctionEnd",
  4239. 2, true),
  4240. // Test case 19: fold vector fnegate with null
  4241. InstructionFoldingCase<bool>(
  4242. Header() +
  4243. "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
  4244. "; CHECK: [[v2double:%\\w+]] = OpTypeVector [[double]] 2\n" +
  4245. "; CHECK: [[double_n0:%\\w+]] = OpConstant [[double]] -0\n" +
  4246. "; CHECK: [[v2double_0_0:%\\w+]] = OpConstantComposite [[v2double]] [[double_n0]] [[double_n0]]\n" +
  4247. "; CHECK: %2 = OpCopyObject [[v2double]] [[v2double_0_0]]\n" +
  4248. "%main = OpFunction %void None %void_func\n" +
  4249. "%main_lab = OpLabel\n" +
  4250. "%2 = OpFNegate %v2double %v2double_null\n" +
  4251. "OpReturn\n" +
  4252. "OpFunctionEnd",
  4253. 2, true)
  4254. ));
  4255. INSTANTIATE_TEST_SUITE_P(ReciprocalFDivTest, MatchingInstructionFoldingTest,
  4256. ::testing::Values(
  4257. // Test case 0: scalar reicprocal
  4258. // x / 0.5 = x * 2.0
  4259. InstructionFoldingCase<bool>(
  4260. Header() +
  4261. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  4262. "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
  4263. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  4264. "; CHECK: %3 = OpFMul [[float]] [[ld]] [[float_2]]\n" +
  4265. "%main = OpFunction %void None %void_func\n" +
  4266. "%main_lab = OpLabel\n" +
  4267. "%var = OpVariable %_ptr_float Function\n" +
  4268. "%2 = OpLoad %float %var\n" +
  4269. "%3 = OpFDiv %float %2 %float_0p5\n" +
  4270. "OpReturn\n" +
  4271. "OpFunctionEnd\n",
  4272. 3, true),
  4273. // Test case 1: Unfoldable
  4274. InstructionFoldingCase<bool>(
  4275. Header() +
  4276. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  4277. "; CHECK: [[float_0:%\\w+]] = OpConstant [[float]] 0\n" +
  4278. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  4279. "; CHECK: %3 = OpFDiv [[float]] [[ld]] [[float_0]]\n" +
  4280. "%main = OpFunction %void None %void_func\n" +
  4281. "%main_lab = OpLabel\n" +
  4282. "%var = OpVariable %_ptr_float Function\n" +
  4283. "%2 = OpLoad %float %var\n" +
  4284. "%3 = OpFDiv %float %2 %104\n" +
  4285. "OpReturn\n" +
  4286. "OpFunctionEnd\n",
  4287. 3, false),
  4288. // Test case 2: Vector reciprocal
  4289. // x / {2.0, 0.5} = x * {0.5, 2.0}
  4290. InstructionFoldingCase<bool>(
  4291. Header() +
  4292. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  4293. "; CHECK: [[v2float:%\\w+]] = OpTypeVector [[float]] 2\n" +
  4294. "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
  4295. "; CHECK: [[float_0p5:%\\w+]] = OpConstant [[float]] 0.5\n" +
  4296. "; CHECK: [[v2float_0p5_2:%\\w+]] = OpConstantComposite [[v2float]] [[float_0p5]] [[float_2]]\n" +
  4297. "; CHECK: [[ld:%\\w+]] = OpLoad [[v2float]]\n" +
  4298. "; CHECK: %3 = OpFMul [[v2float]] [[ld]] [[v2float_0p5_2]]\n" +
  4299. "%main = OpFunction %void None %void_func\n" +
  4300. "%main_lab = OpLabel\n" +
  4301. "%var = OpVariable %_ptr_v2float Function\n" +
  4302. "%2 = OpLoad %v2float %var\n" +
  4303. "%3 = OpFDiv %v2float %2 %v2float_2_0p5\n" +
  4304. "OpReturn\n" +
  4305. "OpFunctionEnd\n",
  4306. 3, true),
  4307. // Test case 3: double reciprocal
  4308. // x / 2.0 = x * 0.5
  4309. InstructionFoldingCase<bool>(
  4310. Header() +
  4311. "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
  4312. "; CHECK: [[double_0p5:%\\w+]] = OpConstant [[double]] 0.5\n" +
  4313. "; CHECK: [[ld:%\\w+]] = OpLoad [[double]]\n" +
  4314. "; CHECK: %3 = OpFMul [[double]] [[ld]] [[double_0p5]]\n" +
  4315. "%main = OpFunction %void None %void_func\n" +
  4316. "%main_lab = OpLabel\n" +
  4317. "%var = OpVariable %_ptr_double Function\n" +
  4318. "%2 = OpLoad %double %var\n" +
  4319. "%3 = OpFDiv %double %2 %double_2\n" +
  4320. "OpReturn\n" +
  4321. "OpFunctionEnd\n",
  4322. 3, true),
  4323. // Test case 4: don't fold x / 0.
  4324. InstructionFoldingCase<bool>(
  4325. Header() +
  4326. "%main = OpFunction %void None %void_func\n" +
  4327. "%main_lab = OpLabel\n" +
  4328. "%var = OpVariable %_ptr_v2float Function\n" +
  4329. "%2 = OpLoad %v2float %var\n" +
  4330. "%3 = OpFDiv %v2float %2 %v2float_null\n" +
  4331. "OpReturn\n" +
  4332. "OpFunctionEnd\n",
  4333. 3, false)
  4334. ));
  4335. INSTANTIATE_TEST_SUITE_P(MergeMulTest, MatchingInstructionFoldingTest,
  4336. ::testing::Values(
  4337. // Test case 0: fold consecutive fmuls
  4338. // (x * 3.0) * 2.0 = x * 6.0
  4339. InstructionFoldingCase<bool>(
  4340. Header() +
  4341. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  4342. "; CHECK: [[float_6:%\\w+]] = OpConstant [[float]] 6\n" +
  4343. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  4344. "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_6]]\n" +
  4345. "%main = OpFunction %void None %void_func\n" +
  4346. "%main_lab = OpLabel\n" +
  4347. "%var = OpVariable %_ptr_float Function\n" +
  4348. "%2 = OpLoad %float %var\n" +
  4349. "%3 = OpFMul %float %2 %float_3\n" +
  4350. "%4 = OpFMul %float %3 %float_2\n" +
  4351. "OpReturn\n" +
  4352. "OpFunctionEnd\n",
  4353. 4, true),
  4354. // Test case 1: fold consecutive fmuls
  4355. // 2.0 * (x * 3.0) = x * 6.0
  4356. InstructionFoldingCase<bool>(
  4357. Header() +
  4358. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  4359. "; CHECK: [[float_6:%\\w+]] = OpConstant [[float]] 6\n" +
  4360. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  4361. "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_6]]\n" +
  4362. "%main = OpFunction %void None %void_func\n" +
  4363. "%main_lab = OpLabel\n" +
  4364. "%var = OpVariable %_ptr_float Function\n" +
  4365. "%2 = OpLoad %float %var\n" +
  4366. "%3 = OpFMul %float %2 %float_3\n" +
  4367. "%4 = OpFMul %float %float_2 %3\n" +
  4368. "OpReturn\n" +
  4369. "OpFunctionEnd\n",
  4370. 4, true),
  4371. // Test case 2: fold consecutive fmuls
  4372. // (3.0 * x) * 2.0 = x * 6.0
  4373. InstructionFoldingCase<bool>(
  4374. Header() +
  4375. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  4376. "; CHECK: [[float_6:%\\w+]] = OpConstant [[float]] 6\n" +
  4377. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  4378. "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_6]]\n" +
  4379. "%main = OpFunction %void None %void_func\n" +
  4380. "%main_lab = OpLabel\n" +
  4381. "%var = OpVariable %_ptr_float Function\n" +
  4382. "%2 = OpLoad %float %var\n" +
  4383. "%3 = OpFMul %float %float_3 %2\n" +
  4384. "%4 = OpFMul %float %float_2 %3\n" +
  4385. "OpReturn\n" +
  4386. "OpFunctionEnd\n",
  4387. 4, true),
  4388. // Test case 3: fold vector fmul
  4389. InstructionFoldingCase<bool>(
  4390. Header() +
  4391. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  4392. "; CHECK: [[v2float:%\\w+]] = OpTypeVector [[float]] 2\n" +
  4393. "; CHECK: [[float_6:%\\w+]] = OpConstant [[float]] 6\n" +
  4394. "; CHECK: [[v2float_6_6:%\\w+]] = OpConstantComposite [[v2float]] [[float_6]] [[float_6]]\n" +
  4395. "; CHECK: [[ld:%\\w+]] = OpLoad [[v2float]]\n" +
  4396. "; CHECK: %4 = OpFMul [[v2float]] [[ld]] [[v2float_6_6]]\n" +
  4397. "%main = OpFunction %void None %void_func\n" +
  4398. "%main_lab = OpLabel\n" +
  4399. "%var = OpVariable %_ptr_v2float Function\n" +
  4400. "%2 = OpLoad %v2float %var\n" +
  4401. "%3 = OpFMul %v2float %2 %v2float_2_3\n" +
  4402. "%4 = OpFMul %v2float %3 %v2float_3_2\n" +
  4403. "OpReturn\n" +
  4404. "OpFunctionEnd\n",
  4405. 4, true),
  4406. // Test case 4: fold double fmuls
  4407. // (x * 3.0) * 2.0 = x * 6.0
  4408. InstructionFoldingCase<bool>(
  4409. Header() +
  4410. "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
  4411. "; CHECK: [[double_6:%\\w+]] = OpConstant [[double]] 6\n" +
  4412. "; CHECK: [[ld:%\\w+]] = OpLoad [[double]]\n" +
  4413. "; CHECK: %4 = OpFMul [[double]] [[ld]] [[double_6]]\n" +
  4414. "%main = OpFunction %void None %void_func\n" +
  4415. "%main_lab = OpLabel\n" +
  4416. "%var = OpVariable %_ptr_double Function\n" +
  4417. "%2 = OpLoad %double %var\n" +
  4418. "%3 = OpFMul %double %2 %double_3\n" +
  4419. "%4 = OpFMul %double %3 %double_2\n" +
  4420. "OpReturn\n" +
  4421. "OpFunctionEnd\n",
  4422. 4, true),
  4423. // Test case 5: fold 32 bit imuls
  4424. // (x * 3) * 2 = x * 6
  4425. InstructionFoldingCase<bool>(
  4426. Header() +
  4427. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  4428. "; CHECK: [[int_6:%\\w+]] = OpConstant [[int]] 6\n" +
  4429. "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
  4430. "; CHECK: %4 = OpIMul [[int]] [[ld]] [[int_6]]\n" +
  4431. "%main = OpFunction %void None %void_func\n" +
  4432. "%main_lab = OpLabel\n" +
  4433. "%var = OpVariable %_ptr_int Function\n" +
  4434. "%2 = OpLoad %int %var\n" +
  4435. "%3 = OpIMul %int %2 %int_3\n" +
  4436. "%4 = OpIMul %int %3 %int_2\n" +
  4437. "OpReturn\n" +
  4438. "OpFunctionEnd\n",
  4439. 4, true),
  4440. // Test case 6: fold 64 bit imuls
  4441. // (x * 3) * 2 = x * 6
  4442. InstructionFoldingCase<bool>(
  4443. Header() +
  4444. "; CHECK: [[long:%\\w+]] = OpTypeInt 64\n" +
  4445. "; CHECK: [[long_6:%\\w+]] = OpConstant [[long]] 6\n" +
  4446. "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
  4447. "; CHECK: %4 = OpIMul [[long]] [[ld]] [[long_6]]\n" +
  4448. "%main = OpFunction %void None %void_func\n" +
  4449. "%main_lab = OpLabel\n" +
  4450. "%var = OpVariable %_ptr_long Function\n" +
  4451. "%2 = OpLoad %long %var\n" +
  4452. "%3 = OpIMul %long %2 %long_3\n" +
  4453. "%4 = OpIMul %long %3 %long_2\n" +
  4454. "OpReturn\n" +
  4455. "OpFunctionEnd\n",
  4456. 4, true),
  4457. // Test case 7: merge vector integer mults
  4458. InstructionFoldingCase<bool>(
  4459. Header() +
  4460. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  4461. "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2\n" +
  4462. "; CHECK: [[int_6:%\\w+]] = OpConstant [[int]] 6\n" +
  4463. "; CHECK: [[v2int_6_6:%\\w+]] = OpConstantComposite [[v2int]] [[int_6]] [[int_6]]\n" +
  4464. "; CHECK: [[ld:%\\w+]] = OpLoad [[v2int]]\n" +
  4465. "; CHECK: %4 = OpIMul [[v2int]] [[ld]] [[v2int_6_6]]\n" +
  4466. "%main = OpFunction %void None %void_func\n" +
  4467. "%main_lab = OpLabel\n" +
  4468. "%var = OpVariable %_ptr_v2int Function\n" +
  4469. "%2 = OpLoad %v2int %var\n" +
  4470. "%3 = OpIMul %v2int %2 %v2int_2_3\n" +
  4471. "%4 = OpIMul %v2int %3 %v2int_3_2\n" +
  4472. "OpReturn\n" +
  4473. "OpFunctionEnd\n",
  4474. 4, true),
  4475. // Test case 8: merge fmul of fdiv
  4476. // 2.0 * (2.0 / x) = 4.0 / x
  4477. InstructionFoldingCase<bool>(
  4478. Header() +
  4479. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  4480. "; CHECK: [[float_4:%\\w+]] = OpConstant [[float]] 4\n" +
  4481. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  4482. "; CHECK: %4 = OpFDiv [[float]] [[float_4]] [[ld]]\n" +
  4483. "%main = OpFunction %void None %void_func\n" +
  4484. "%main_lab = OpLabel\n" +
  4485. "%var = OpVariable %_ptr_float Function\n" +
  4486. "%2 = OpLoad %float %var\n" +
  4487. "%3 = OpFDiv %float %float_2 %2\n" +
  4488. "%4 = OpFMul %float %float_2 %3\n" +
  4489. "OpReturn\n" +
  4490. "OpFunctionEnd\n",
  4491. 4, true),
  4492. // Test case 9: merge fmul of fdiv
  4493. // (2.0 / x) * 2.0 = 4.0 / x
  4494. InstructionFoldingCase<bool>(
  4495. Header() +
  4496. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  4497. "; CHECK: [[float_4:%\\w+]] = OpConstant [[float]] 4\n" +
  4498. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  4499. "; CHECK: %4 = OpFDiv [[float]] [[float_4]] [[ld]]\n" +
  4500. "%main = OpFunction %void None %void_func\n" +
  4501. "%main_lab = OpLabel\n" +
  4502. "%var = OpVariable %_ptr_float Function\n" +
  4503. "%2 = OpLoad %float %var\n" +
  4504. "%3 = OpFDiv %float %float_2 %2\n" +
  4505. "%4 = OpFMul %float %3 %float_2\n" +
  4506. "OpReturn\n" +
  4507. "OpFunctionEnd\n",
  4508. 4, true),
  4509. // Test case 10: Do not merge imul of sdiv
  4510. // 4 * (x / 2)
  4511. InstructionFoldingCase<bool>(
  4512. Header() +
  4513. "%main = OpFunction %void None %void_func\n" +
  4514. "%main_lab = OpLabel\n" +
  4515. "%var = OpVariable %_ptr_int Function\n" +
  4516. "%2 = OpLoad %int %var\n" +
  4517. "%3 = OpSDiv %int %2 %int_2\n" +
  4518. "%4 = OpIMul %int %int_4 %3\n" +
  4519. "OpReturn\n" +
  4520. "OpFunctionEnd\n",
  4521. 4, false),
  4522. // Test case 11: Do not merge imul of sdiv
  4523. // (x / 2) * 4
  4524. InstructionFoldingCase<bool>(
  4525. Header() +
  4526. "%main = OpFunction %void None %void_func\n" +
  4527. "%main_lab = OpLabel\n" +
  4528. "%var = OpVariable %_ptr_int Function\n" +
  4529. "%2 = OpLoad %int %var\n" +
  4530. "%3 = OpSDiv %int %2 %int_2\n" +
  4531. "%4 = OpIMul %int %3 %int_4\n" +
  4532. "OpReturn\n" +
  4533. "OpFunctionEnd\n",
  4534. 4, false),
  4535. // Test case 12: Do not merge imul of udiv
  4536. // 4 * (x / 2)
  4537. InstructionFoldingCase<bool>(
  4538. Header() +
  4539. "%main = OpFunction %void None %void_func\n" +
  4540. "%main_lab = OpLabel\n" +
  4541. "%var = OpVariable %_ptr_uint Function\n" +
  4542. "%2 = OpLoad %uint %var\n" +
  4543. "%3 = OpUDiv %uint %2 %uint_2\n" +
  4544. "%4 = OpIMul %uint %uint_4 %3\n" +
  4545. "OpReturn\n" +
  4546. "OpFunctionEnd\n",
  4547. 4, false),
  4548. // Test case 13: Do not merge imul of udiv
  4549. // (x / 2) * 4
  4550. InstructionFoldingCase<bool>(
  4551. Header() +
  4552. "%main = OpFunction %void None %void_func\n" +
  4553. "%main_lab = OpLabel\n" +
  4554. "%var = OpVariable %_ptr_uint Function\n" +
  4555. "%2 = OpLoad %uint %var\n" +
  4556. "%3 = OpUDiv %uint %2 %uint_2\n" +
  4557. "%4 = OpIMul %uint %3 %uint_4\n" +
  4558. "OpReturn\n" +
  4559. "OpFunctionEnd\n",
  4560. 4, false),
  4561. // Test case 14: Don't fold
  4562. // (x / 3) * 4
  4563. InstructionFoldingCase<bool>(
  4564. Header() +
  4565. "%main = OpFunction %void None %void_func\n" +
  4566. "%main_lab = OpLabel\n" +
  4567. "%var = OpVariable %_ptr_uint Function\n" +
  4568. "%2 = OpLoad %uint %var\n" +
  4569. "%3 = OpUDiv %uint %2 %uint_3\n" +
  4570. "%4 = OpIMul %uint %3 %uint_4\n" +
  4571. "OpReturn\n" +
  4572. "OpFunctionEnd\n",
  4573. 4, false),
  4574. // Test case 15: merge vector fmul of fdiv
  4575. // (x / {2,2}) * {4,4} = x * {2,2}
  4576. InstructionFoldingCase<bool>(
  4577. Header() +
  4578. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  4579. "; CHECK: [[v2float:%\\w+]] = OpTypeVector [[float]] 2\n" +
  4580. "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
  4581. "; CHECK: [[v2float_2_2:%\\w+]] = OpConstantComposite [[v2float]] [[float_2]] [[float_2]]\n" +
  4582. "; CHECK: [[ld:%\\w+]] = OpLoad [[v2float]]\n" +
  4583. "; CHECK: %4 = OpFMul [[v2float]] [[ld]] [[v2float_2_2]]\n" +
  4584. "%main = OpFunction %void None %void_func\n" +
  4585. "%main_lab = OpLabel\n" +
  4586. "%var = OpVariable %_ptr_v2float Function\n" +
  4587. "%2 = OpLoad %v2float %var\n" +
  4588. "%3 = OpFDiv %v2float %2 %v2float_2_2\n" +
  4589. "%4 = OpFMul %v2float %3 %v2float_4_4\n" +
  4590. "OpReturn\n" +
  4591. "OpFunctionEnd\n",
  4592. 4, true),
  4593. // Test case 16: merge vector imul of snegate
  4594. // (-x) * {2,2} = x * {-2,-2}
  4595. InstructionFoldingCase<bool>(
  4596. Header() +
  4597. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  4598. "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2\n" +
  4599. "; CHECK: OpConstant [[int]] -2147483648\n" +
  4600. "; CHECK: [[int_n2:%\\w+]] = OpConstant [[int]] -2\n" +
  4601. "; CHECK: [[v2int_n2_n2:%\\w+]] = OpConstantComposite [[v2int]] [[int_n2]] [[int_n2]]\n" +
  4602. "; CHECK: [[ld:%\\w+]] = OpLoad [[v2int]]\n" +
  4603. "; CHECK: %4 = OpIMul [[v2int]] [[ld]] [[v2int_n2_n2]]\n" +
  4604. "%main = OpFunction %void None %void_func\n" +
  4605. "%main_lab = OpLabel\n" +
  4606. "%var = OpVariable %_ptr_v2int Function\n" +
  4607. "%2 = OpLoad %v2int %var\n" +
  4608. "%3 = OpSNegate %v2int %2\n" +
  4609. "%4 = OpIMul %v2int %3 %v2int_2_2\n" +
  4610. "OpReturn\n" +
  4611. "OpFunctionEnd\n",
  4612. 4, true),
  4613. // Test case 17: merge vector imul of snegate
  4614. // {2,2} * (-x) = x * {-2,-2}
  4615. InstructionFoldingCase<bool>(
  4616. Header() +
  4617. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  4618. "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2\n" +
  4619. "; CHECK: OpConstant [[int]] -2147483648\n" +
  4620. "; CHECK: [[int_n2:%\\w+]] = OpConstant [[int]] -2\n" +
  4621. "; CHECK: [[v2int_n2_n2:%\\w+]] = OpConstantComposite [[v2int]] [[int_n2]] [[int_n2]]\n" +
  4622. "; CHECK: [[ld:%\\w+]] = OpLoad [[v2int]]\n" +
  4623. "; CHECK: %4 = OpIMul [[v2int]] [[ld]] [[v2int_n2_n2]]\n" +
  4624. "%main = OpFunction %void None %void_func\n" +
  4625. "%main_lab = OpLabel\n" +
  4626. "%var = OpVariable %_ptr_v2int Function\n" +
  4627. "%2 = OpLoad %v2int %var\n" +
  4628. "%3 = OpSNegate %v2int %2\n" +
  4629. "%4 = OpIMul %v2int %v2int_2_2 %3\n" +
  4630. "OpReturn\n" +
  4631. "OpFunctionEnd\n",
  4632. 4, true),
  4633. // Test case 18: Fold OpVectorTimesScalar
  4634. // {4,4} = OpVectorTimesScalar v2float {2,2} 2
  4635. InstructionFoldingCase<bool>(
  4636. Header() +
  4637. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  4638. "; CHECK: [[v2float:%\\w+]] = OpTypeVector [[float]] 2\n" +
  4639. "; CHECK: [[float_4:%\\w+]] = OpConstant [[float]] 4\n" +
  4640. "; CHECK: [[v2float_4_4:%\\w+]] = OpConstantComposite [[v2float]] [[float_4]] [[float_4]]\n" +
  4641. "; CHECK: %2 = OpCopyObject [[v2float]] [[v2float_4_4]]\n" +
  4642. "%main = OpFunction %void None %void_func\n" +
  4643. "%main_lab = OpLabel\n" +
  4644. "%2 = OpVectorTimesScalar %v2float %v2float_2_2 %float_2\n" +
  4645. "OpReturn\n" +
  4646. "OpFunctionEnd",
  4647. 2, true),
  4648. // Test case 19: Fold OpVectorTimesScalar
  4649. // {0,0} = OpVectorTimesScalar v2float v2float_null -1
  4650. InstructionFoldingCase<bool>(
  4651. Header() +
  4652. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  4653. "; CHECK: [[v2float:%\\w+]] = OpTypeVector [[float]] 2\n" +
  4654. "; CHECK: [[v2float_null:%\\w+]] = OpConstantNull [[v2float]]\n" +
  4655. "; CHECK: %2 = OpCopyObject [[v2float]] [[v2float_null]]\n" +
  4656. "%main = OpFunction %void None %void_func\n" +
  4657. "%main_lab = OpLabel\n" +
  4658. "%2 = OpVectorTimesScalar %v2float %v2float_null %float_n1\n" +
  4659. "OpReturn\n" +
  4660. "OpFunctionEnd",
  4661. 2, true),
  4662. // Test case 20: Fold OpVectorTimesScalar
  4663. // {4,4} = OpVectorTimesScalar v2double {2,2} 2
  4664. InstructionFoldingCase<bool>(
  4665. Header() +
  4666. "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
  4667. "; CHECK: [[v2double:%\\w+]] = OpTypeVector [[double]] 2\n" +
  4668. "; CHECK: [[double_4:%\\w+]] = OpConstant [[double]] 4\n" +
  4669. "; CHECK: [[v2double_4_4:%\\w+]] = OpConstantComposite [[v2double]] [[double_4]] [[double_4]]\n" +
  4670. "; CHECK: %2 = OpCopyObject [[v2double]] [[v2double_4_4]]\n" +
  4671. "%main = OpFunction %void None %void_func\n" +
  4672. "%main_lab = OpLabel\n" +
  4673. "%2 = OpVectorTimesScalar %v2double %v2double_2_2 %double_2\n" +
  4674. "OpReturn\n" +
  4675. "OpFunctionEnd",
  4676. 2, true),
  4677. // Test case 21: Fold OpVectorTimesScalar
  4678. // {0,0} = OpVectorTimesScalar v2double {0,0} n
  4679. InstructionFoldingCase<bool>(
  4680. Header() +
  4681. "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
  4682. "; CHECK: [[v2double:%\\w+]] = OpTypeVector [[double]] 2\n" +
  4683. "; CHECK: {{%\\w+}} = OpConstant [[double]] 0\n" +
  4684. "; CHECK: [[double_0:%\\w+]] = OpConstant [[double]] 0\n" +
  4685. "; CHECK: [[v2double_0_0:%\\w+]] = OpConstantComposite [[v2double]] [[double_0]] [[double_0]]\n" +
  4686. "; CHECK: %2 = OpCopyObject [[v2double]] [[v2double_0_0]]\n" +
  4687. "%main = OpFunction %void None %void_func\n" +
  4688. "%main_lab = OpLabel\n" +
  4689. "%n = OpVariable %_ptr_double Function\n" +
  4690. "%load = OpLoad %double %n\n" +
  4691. "%2 = OpVectorTimesScalar %v2double %v2double_0_0 %load\n" +
  4692. "OpReturn\n" +
  4693. "OpFunctionEnd",
  4694. 2, true),
  4695. // Test case 22: Fold OpVectorTimesScalar
  4696. // {0,0} = OpVectorTimesScalar v2double n 0
  4697. InstructionFoldingCase<bool>(
  4698. Header() +
  4699. "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
  4700. "; CHECK: [[v2double:%\\w+]] = OpTypeVector [[double]] 2\n" +
  4701. "; CHECK: [[v2double_null:%\\w+]] = OpConstantNull [[v2double]]\n" +
  4702. "; CHECK: %2 = OpCopyObject [[v2double]] [[v2double_null]]\n" +
  4703. "%main = OpFunction %void None %void_func\n" +
  4704. "%main_lab = OpLabel\n" +
  4705. "%n = OpVariable %_ptr_v2double Function\n" +
  4706. "%load = OpLoad %v2double %n\n" +
  4707. "%2 = OpVectorTimesScalar %v2double %load %double_0\n" +
  4708. "OpReturn\n" +
  4709. "OpFunctionEnd",
  4710. 2, true),
  4711. // Test case 23: merge fmul of fdiv
  4712. // x * (y / x) = y
  4713. InstructionFoldingCase<bool>(
  4714. Header() +
  4715. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  4716. "; CHECK: [[ldx:%\\w+]] = OpLoad [[float]]\n" +
  4717. "; CHECK: [[ldy:%\\w+]] = OpLoad [[float]] [[y:%\\w+]]\n" +
  4718. "; CHECK: %5 = OpCopyObject [[float]] [[ldy]]\n" +
  4719. "%main = OpFunction %void None %void_func\n" +
  4720. "%main_lab = OpLabel\n" +
  4721. "%x = OpVariable %_ptr_float Function\n" +
  4722. "%y = OpVariable %_ptr_float Function\n" +
  4723. "%2 = OpLoad %float %x\n" +
  4724. "%3 = OpLoad %float %y\n" +
  4725. "%4 = OpFDiv %float %3 %2\n" +
  4726. "%5 = OpFMul %float %2 %4\n" +
  4727. "OpReturn\n" +
  4728. "OpFunctionEnd\n",
  4729. 5, true),
  4730. // Test case 24: merge fmul of fdiv
  4731. // (y / x) * x = y
  4732. InstructionFoldingCase<bool>(
  4733. Header() +
  4734. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  4735. "; CHECK: [[ldx:%\\w+]] = OpLoad [[float]]\n" +
  4736. "; CHECK: [[ldy:%\\w+]] = OpLoad [[float]] [[y:%\\w+]]\n" +
  4737. "; CHECK: %5 = OpCopyObject [[float]] [[ldy]]\n" +
  4738. "%main = OpFunction %void None %void_func\n" +
  4739. "%main_lab = OpLabel\n" +
  4740. "%x = OpVariable %_ptr_float Function\n" +
  4741. "%y = OpVariable %_ptr_float Function\n" +
  4742. "%2 = OpLoad %float %x\n" +
  4743. "%3 = OpLoad %float %y\n" +
  4744. "%4 = OpFDiv %float %3 %2\n" +
  4745. "%5 = OpFMul %float %4 %2\n" +
  4746. "OpReturn\n" +
  4747. "OpFunctionEnd\n",
  4748. 5, true)
  4749. ));
  4750. INSTANTIATE_TEST_SUITE_P(MergeDivTest, MatchingInstructionFoldingTest,
  4751. ::testing::Values(
  4752. // Test case 0: merge consecutive fdiv
  4753. // 4.0 / (2.0 / x) = 2.0 * x
  4754. InstructionFoldingCase<bool>(
  4755. Header() +
  4756. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  4757. "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
  4758. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  4759. "; CHECK: %4 = OpFMul [[float]] [[float_2]] [[ld]]\n" +
  4760. "%main = OpFunction %void None %void_func\n" +
  4761. "%main_lab = OpLabel\n" +
  4762. "%var = OpVariable %_ptr_float Function\n" +
  4763. "%2 = OpLoad %float %var\n" +
  4764. "%3 = OpFDiv %float %float_2 %2\n" +
  4765. "%4 = OpFDiv %float %float_4 %3\n" +
  4766. "OpReturn\n" +
  4767. "OpFunctionEnd\n",
  4768. 4, true),
  4769. // Test case 1: merge consecutive fdiv
  4770. // 4.0 / (x / 2.0) = 8.0 / x
  4771. InstructionFoldingCase<bool>(
  4772. Header() +
  4773. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  4774. "; CHECK: [[float_8:%\\w+]] = OpConstant [[float]] 8\n" +
  4775. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  4776. "; CHECK: %4 = OpFDiv [[float]] [[float_8]] [[ld]]\n" +
  4777. "%main = OpFunction %void None %void_func\n" +
  4778. "%main_lab = OpLabel\n" +
  4779. "%var = OpVariable %_ptr_float Function\n" +
  4780. "%2 = OpLoad %float %var\n" +
  4781. "%3 = OpFDiv %float %2 %float_2\n" +
  4782. "%4 = OpFDiv %float %float_4 %3\n" +
  4783. "OpReturn\n" +
  4784. "OpFunctionEnd\n",
  4785. 4, true),
  4786. // Test case 2: merge consecutive fdiv
  4787. // (4.0 / x) / 2.0 = 2.0 / x
  4788. InstructionFoldingCase<bool>(
  4789. Header() +
  4790. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  4791. "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
  4792. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  4793. "; CHECK: %4 = OpFDiv [[float]] [[float_2]] [[ld]]\n" +
  4794. "%main = OpFunction %void None %void_func\n" +
  4795. "%main_lab = OpLabel\n" +
  4796. "%var = OpVariable %_ptr_float Function\n" +
  4797. "%2 = OpLoad %float %var\n" +
  4798. "%3 = OpFDiv %float %float_4 %2\n" +
  4799. "%4 = OpFDiv %float %3 %float_2\n" +
  4800. "OpReturn\n" +
  4801. "OpFunctionEnd\n",
  4802. 4, true),
  4803. // Test case 3: Do not merge consecutive sdiv
  4804. // 4 / (2 / x)
  4805. InstructionFoldingCase<bool>(
  4806. Header() +
  4807. "%main = OpFunction %void None %void_func\n" +
  4808. "%main_lab = OpLabel\n" +
  4809. "%var = OpVariable %_ptr_int Function\n" +
  4810. "%2 = OpLoad %int %var\n" +
  4811. "%3 = OpSDiv %int %int_2 %2\n" +
  4812. "%4 = OpSDiv %int %int_4 %3\n" +
  4813. "OpReturn\n" +
  4814. "OpFunctionEnd\n",
  4815. 4, false),
  4816. // Test case 4: Do not merge consecutive sdiv
  4817. // 4 / (x / 2)
  4818. InstructionFoldingCase<bool>(
  4819. Header() +
  4820. "%main = OpFunction %void None %void_func\n" +
  4821. "%main_lab = OpLabel\n" +
  4822. "%var = OpVariable %_ptr_int Function\n" +
  4823. "%2 = OpLoad %int %var\n" +
  4824. "%3 = OpSDiv %int %2 %int_2\n" +
  4825. "%4 = OpSDiv %int %int_4 %3\n" +
  4826. "OpReturn\n" +
  4827. "OpFunctionEnd\n",
  4828. 4, false),
  4829. // Test case 5: Do not merge consecutive sdiv
  4830. // (4 / x) / 2
  4831. InstructionFoldingCase<bool>(
  4832. Header() +
  4833. "%main = OpFunction %void None %void_func\n" +
  4834. "%main_lab = OpLabel\n" +
  4835. "%var = OpVariable %_ptr_int Function\n" +
  4836. "%2 = OpLoad %int %var\n" +
  4837. "%3 = OpSDiv %int %int_4 %2\n" +
  4838. "%4 = OpSDiv %int %3 %int_2\n" +
  4839. "OpReturn\n" +
  4840. "OpFunctionEnd\n",
  4841. 4, false),
  4842. // Test case 6: Do not merge consecutive sdiv
  4843. // (x / 4) / 2
  4844. InstructionFoldingCase<bool>(
  4845. Header() +
  4846. "%main = OpFunction %void None %void_func\n" +
  4847. "%main_lab = OpLabel\n" +
  4848. "%var = OpVariable %_ptr_int Function\n" +
  4849. "%2 = OpLoad %int %var\n" +
  4850. "%3 = OpSDiv %int %2 %int_4\n" +
  4851. "%4 = OpSDiv %int %3 %int_2\n" +
  4852. "OpReturn\n" +
  4853. "OpFunctionEnd\n",
  4854. 4, false),
  4855. // Test case 7: Do not merge sdiv of imul
  4856. // 4 / (2 * x)
  4857. InstructionFoldingCase<bool>(
  4858. Header() +
  4859. "%main = OpFunction %void None %void_func\n" +
  4860. "%main_lab = OpLabel\n" +
  4861. "%var = OpVariable %_ptr_int Function\n" +
  4862. "%2 = OpLoad %int %var\n" +
  4863. "%3 = OpIMul %int %int_2 %2\n" +
  4864. "%4 = OpSDiv %int %int_4 %3\n" +
  4865. "OpReturn\n" +
  4866. "OpFunctionEnd\n",
  4867. 4, false),
  4868. // Test case 8: Do not merge sdiv of imul
  4869. // 4 / (x * 2)
  4870. InstructionFoldingCase<bool>(
  4871. Header() +
  4872. "%main = OpFunction %void None %void_func\n" +
  4873. "%main_lab = OpLabel\n" +
  4874. "%var = OpVariable %_ptr_int Function\n" +
  4875. "%2 = OpLoad %int %var\n" +
  4876. "%3 = OpIMul %int %2 %int_2\n" +
  4877. "%4 = OpSDiv %int %int_4 %3\n" +
  4878. "OpReturn\n" +
  4879. "OpFunctionEnd\n",
  4880. 4, false),
  4881. // Test case 9: Do not merge sdiv of imul
  4882. // (4 * x) / 2
  4883. InstructionFoldingCase<bool>(
  4884. Header() +
  4885. "%main = OpFunction %void None %void_func\n" +
  4886. "%main_lab = OpLabel\n" +
  4887. "%var = OpVariable %_ptr_int Function\n" +
  4888. "%2 = OpLoad %int %var\n" +
  4889. "%3 = OpIMul %int %int_4 %2\n" +
  4890. "%4 = OpSDiv %int %3 %int_2\n" +
  4891. "OpReturn\n" +
  4892. "OpFunctionEnd\n",
  4893. 4, false),
  4894. // Test case 10: Do not merge sdiv of imul
  4895. // (x * 4) / 2
  4896. InstructionFoldingCase<bool>(
  4897. Header() +
  4898. "%main = OpFunction %void None %void_func\n" +
  4899. "%main_lab = OpLabel\n" +
  4900. "%var = OpVariable %_ptr_int Function\n" +
  4901. "%2 = OpLoad %int %var\n" +
  4902. "%3 = OpIMul %int %2 %int_4\n" +
  4903. "%4 = OpSDiv %int %3 %int_2\n" +
  4904. "OpReturn\n" +
  4905. "OpFunctionEnd\n",
  4906. 4, false),
  4907. // Test case 11: merge sdiv of snegate
  4908. // (-x) / 2 = x / -2
  4909. InstructionFoldingCase<bool>(
  4910. Header() +
  4911. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  4912. "; CHECK: OpConstant [[int]] -2147483648\n" +
  4913. "; CHECK: [[int_n2:%\\w+]] = OpConstant [[int]] -2\n" +
  4914. "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
  4915. "; CHECK: %4 = OpSDiv [[int]] [[ld]] [[int_n2]]\n" +
  4916. "%main = OpFunction %void None %void_func\n" +
  4917. "%main_lab = OpLabel\n" +
  4918. "%var = OpVariable %_ptr_int Function\n" +
  4919. "%2 = OpLoad %int %var\n" +
  4920. "%3 = OpSNegate %int %2\n" +
  4921. "%4 = OpSDiv %int %3 %int_2\n" +
  4922. "OpReturn\n" +
  4923. "OpFunctionEnd\n",
  4924. 4, true),
  4925. // Test case 12: merge sdiv of snegate
  4926. // 2 / (-x) = -2 / x
  4927. InstructionFoldingCase<bool>(
  4928. Header() +
  4929. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  4930. "; CHECK: OpConstant [[int]] -2147483648\n" +
  4931. "; CHECK: [[int_n2:%\\w+]] = OpConstant [[int]] -2\n" +
  4932. "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
  4933. "; CHECK: %4 = OpSDiv [[int]] [[int_n2]] [[ld]]\n" +
  4934. "%main = OpFunction %void None %void_func\n" +
  4935. "%main_lab = OpLabel\n" +
  4936. "%var = OpVariable %_ptr_int Function\n" +
  4937. "%2 = OpLoad %int %var\n" +
  4938. "%3 = OpSNegate %int %2\n" +
  4939. "%4 = OpSDiv %int %int_2 %3\n" +
  4940. "OpReturn\n" +
  4941. "OpFunctionEnd\n",
  4942. 4, true),
  4943. // Test case 13: Don't merge
  4944. // (x / {null}) / {null}
  4945. InstructionFoldingCase<bool>(
  4946. Header() +
  4947. "%main = OpFunction %void None %void_func\n" +
  4948. "%main_lab = OpLabel\n" +
  4949. "%var = OpVariable %_ptr_v2float Function\n" +
  4950. "%2 = OpLoad %float %var\n" +
  4951. "%3 = OpFDiv %float %2 %v2float_null\n" +
  4952. "%4 = OpFDiv %float %3 %v2float_null\n" +
  4953. "OpReturn\n" +
  4954. "OpFunctionEnd\n",
  4955. 4, false),
  4956. // Test case 14: merge fmul of fdiv
  4957. // (y * x) / x = y
  4958. InstructionFoldingCase<bool>(
  4959. Header() +
  4960. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  4961. "; CHECK: [[ldx:%\\w+]] = OpLoad [[float]]\n" +
  4962. "; CHECK: [[ldy:%\\w+]] = OpLoad [[float]] [[y:%\\w+]]\n" +
  4963. "; CHECK: %5 = OpCopyObject [[float]] [[ldy]]\n" +
  4964. "%main = OpFunction %void None %void_func\n" +
  4965. "%main_lab = OpLabel\n" +
  4966. "%x = OpVariable %_ptr_float Function\n" +
  4967. "%y = OpVariable %_ptr_float Function\n" +
  4968. "%2 = OpLoad %float %x\n" +
  4969. "%3 = OpLoad %float %y\n" +
  4970. "%4 = OpFMul %float %3 %2\n" +
  4971. "%5 = OpFDiv %float %4 %2\n" +
  4972. "OpReturn\n" +
  4973. "OpFunctionEnd\n",
  4974. 5, true),
  4975. // Test case 15: merge fmul of fdiv
  4976. // (x * y) / x = y
  4977. InstructionFoldingCase<bool>(
  4978. Header() +
  4979. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  4980. "; CHECK: [[ldx:%\\w+]] = OpLoad [[float]]\n" +
  4981. "; CHECK: [[ldy:%\\w+]] = OpLoad [[float]] [[y:%\\w+]]\n" +
  4982. "; CHECK: %5 = OpCopyObject [[float]] [[ldy]]\n" +
  4983. "%main = OpFunction %void None %void_func\n" +
  4984. "%main_lab = OpLabel\n" +
  4985. "%x = OpVariable %_ptr_float Function\n" +
  4986. "%y = OpVariable %_ptr_float Function\n" +
  4987. "%2 = OpLoad %float %x\n" +
  4988. "%3 = OpLoad %float %y\n" +
  4989. "%4 = OpFMul %float %2 %3\n" +
  4990. "%5 = OpFDiv %float %4 %2\n" +
  4991. "OpReturn\n" +
  4992. "OpFunctionEnd\n",
  4993. 5, true)
  4994. ));
  4995. INSTANTIATE_TEST_SUITE_P(MergeAddTest, MatchingInstructionFoldingTest,
  4996. ::testing::Values(
  4997. // Test case 0: merge add of negate
  4998. // (-x) + 2 = 2 - x
  4999. InstructionFoldingCase<bool>(
  5000. Header() +
  5001. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5002. "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
  5003. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  5004. "; CHECK: %4 = OpFSub [[float]] [[float_2]] [[ld]]\n" +
  5005. "%main = OpFunction %void None %void_func\n" +
  5006. "%main_lab = OpLabel\n" +
  5007. "%var = OpVariable %_ptr_float Function\n" +
  5008. "%2 = OpLoad %float %var\n" +
  5009. "%3 = OpFNegate %float %2\n" +
  5010. "%4 = OpFAdd %float %3 %float_2\n" +
  5011. "OpReturn\n" +
  5012. "OpFunctionEnd\n",
  5013. 4, true),
  5014. // Test case 1: merge add of negate
  5015. // 2 + (-x) = 2 - x
  5016. InstructionFoldingCase<bool>(
  5017. Header() +
  5018. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5019. "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
  5020. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  5021. "; CHECK: %4 = OpFSub [[float]] [[float_2]] [[ld]]\n" +
  5022. "%main = OpFunction %void None %void_func\n" +
  5023. "%main_lab = OpLabel\n" +
  5024. "%var = OpVariable %_ptr_float Function\n" +
  5025. "%2 = OpLoad %float %var\n" +
  5026. "%3 = OpSNegate %float %2\n" +
  5027. "%4 = OpIAdd %float %float_2 %3\n" +
  5028. "OpReturn\n" +
  5029. "OpFunctionEnd\n",
  5030. 4, true),
  5031. // Test case 2: merge add of negate
  5032. // (-x) + 2 = 2 - x
  5033. InstructionFoldingCase<bool>(
  5034. Header() +
  5035. "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
  5036. "; CHECK: [[long_2:%\\w+]] = OpConstant [[long]] 2\n" +
  5037. "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
  5038. "; CHECK: %4 = OpISub [[long]] [[long_2]] [[ld]]\n" +
  5039. "%main = OpFunction %void None %void_func\n" +
  5040. "%main_lab = OpLabel\n" +
  5041. "%var = OpVariable %_ptr_long Function\n" +
  5042. "%2 = OpLoad %long %var\n" +
  5043. "%3 = OpSNegate %long %2\n" +
  5044. "%4 = OpIAdd %long %3 %long_2\n" +
  5045. "OpReturn\n" +
  5046. "OpFunctionEnd\n",
  5047. 4, true),
  5048. // Test case 3: merge add of negate
  5049. // 2 + (-x) = 2 - x
  5050. InstructionFoldingCase<bool>(
  5051. Header() +
  5052. "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
  5053. "; CHECK: [[long_2:%\\w+]] = OpConstant [[long]] 2\n" +
  5054. "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
  5055. "; CHECK: %4 = OpISub [[long]] [[long_2]] [[ld]]\n" +
  5056. "%main = OpFunction %void None %void_func\n" +
  5057. "%main_lab = OpLabel\n" +
  5058. "%var = OpVariable %_ptr_long Function\n" +
  5059. "%2 = OpLoad %long %var\n" +
  5060. "%3 = OpSNegate %long %2\n" +
  5061. "%4 = OpIAdd %long %long_2 %3\n" +
  5062. "OpReturn\n" +
  5063. "OpFunctionEnd\n",
  5064. 4, true),
  5065. // Test case 4: merge add of subtract
  5066. // (x - 1) + 2 = x + 1
  5067. InstructionFoldingCase<bool>(
  5068. Header() +
  5069. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5070. "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
  5071. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  5072. "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_1]]\n" +
  5073. "%main = OpFunction %void None %void_func\n" +
  5074. "%main_lab = OpLabel\n" +
  5075. "%var = OpVariable %_ptr_float Function\n" +
  5076. "%2 = OpLoad %float %var\n" +
  5077. "%3 = OpFSub %float %2 %float_1\n" +
  5078. "%4 = OpFAdd %float %3 %float_2\n" +
  5079. "OpReturn\n" +
  5080. "OpFunctionEnd\n",
  5081. 4, true),
  5082. // Test case 5: merge add of subtract
  5083. // (1 - x) + 2 = 3 - x
  5084. InstructionFoldingCase<bool>(
  5085. Header() +
  5086. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5087. "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
  5088. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  5089. "; CHECK: %4 = OpFSub [[float]] [[float_3]] [[ld]]\n" +
  5090. "%main = OpFunction %void None %void_func\n" +
  5091. "%main_lab = OpLabel\n" +
  5092. "%var = OpVariable %_ptr_float Function\n" +
  5093. "%2 = OpLoad %float %var\n" +
  5094. "%3 = OpFSub %float %float_1 %2\n" +
  5095. "%4 = OpFAdd %float %3 %float_2\n" +
  5096. "OpReturn\n" +
  5097. "OpFunctionEnd\n",
  5098. 4, true),
  5099. // Test case 6: merge add of subtract
  5100. // 2 + (x - 1) = x + 1
  5101. InstructionFoldingCase<bool>(
  5102. Header() +
  5103. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5104. "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
  5105. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  5106. "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_1]]\n" +
  5107. "%main = OpFunction %void None %void_func\n" +
  5108. "%main_lab = OpLabel\n" +
  5109. "%var = OpVariable %_ptr_float Function\n" +
  5110. "%2 = OpLoad %float %var\n" +
  5111. "%3 = OpFSub %float %2 %float_1\n" +
  5112. "%4 = OpFAdd %float %float_2 %3\n" +
  5113. "OpReturn\n" +
  5114. "OpFunctionEnd\n",
  5115. 4, true),
  5116. // Test case 7: merge add of subtract
  5117. // 2 + (1 - x) = 3 - x
  5118. InstructionFoldingCase<bool>(
  5119. Header() +
  5120. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5121. "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
  5122. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  5123. "; CHECK: %4 = OpFSub [[float]] [[float_3]] [[ld]]\n" +
  5124. "%main = OpFunction %void None %void_func\n" +
  5125. "%main_lab = OpLabel\n" +
  5126. "%var = OpVariable %_ptr_float Function\n" +
  5127. "%2 = OpLoad %float %var\n" +
  5128. "%3 = OpFSub %float %float_1 %2\n" +
  5129. "%4 = OpFAdd %float %float_2 %3\n" +
  5130. "OpReturn\n" +
  5131. "OpFunctionEnd\n",
  5132. 4, true),
  5133. // Test case 8: merge add of add
  5134. // (x + 1) + 2 = x + 3
  5135. InstructionFoldingCase<bool>(
  5136. Header() +
  5137. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5138. "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
  5139. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  5140. "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_3]]\n" +
  5141. "%main = OpFunction %void None %void_func\n" +
  5142. "%main_lab = OpLabel\n" +
  5143. "%var = OpVariable %_ptr_float Function\n" +
  5144. "%2 = OpLoad %float %var\n" +
  5145. "%3 = OpFAdd %float %2 %float_1\n" +
  5146. "%4 = OpFAdd %float %3 %float_2\n" +
  5147. "OpReturn\n" +
  5148. "OpFunctionEnd\n",
  5149. 4, true),
  5150. // Test case 9: merge add of add
  5151. // (1 + x) + 2 = 3 + x
  5152. InstructionFoldingCase<bool>(
  5153. Header() +
  5154. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5155. "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
  5156. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  5157. "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_3]]\n" +
  5158. "%main = OpFunction %void None %void_func\n" +
  5159. "%main_lab = OpLabel\n" +
  5160. "%var = OpVariable %_ptr_float Function\n" +
  5161. "%2 = OpLoad %float %var\n" +
  5162. "%3 = OpFAdd %float %float_1 %2\n" +
  5163. "%4 = OpFAdd %float %3 %float_2\n" +
  5164. "OpReturn\n" +
  5165. "OpFunctionEnd\n",
  5166. 4, true),
  5167. // Test case 10: merge add of add
  5168. // 2 + (x + 1) = x + 1
  5169. InstructionFoldingCase<bool>(
  5170. Header() +
  5171. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5172. "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
  5173. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  5174. "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_3]]\n" +
  5175. "%main = OpFunction %void None %void_func\n" +
  5176. "%main_lab = OpLabel\n" +
  5177. "%var = OpVariable %_ptr_float Function\n" +
  5178. "%2 = OpLoad %float %var\n" +
  5179. "%3 = OpFAdd %float %2 %float_1\n" +
  5180. "%4 = OpFAdd %float %float_2 %3\n" +
  5181. "OpReturn\n" +
  5182. "OpFunctionEnd\n",
  5183. 4, true),
  5184. // Test case 11: merge add of add
  5185. // 2 + (1 + x) = 3 - x
  5186. InstructionFoldingCase<bool>(
  5187. Header() +
  5188. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5189. "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
  5190. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  5191. "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_3]]\n" +
  5192. "%main = OpFunction %void None %void_func\n" +
  5193. "%main_lab = OpLabel\n" +
  5194. "%var = OpVariable %_ptr_float Function\n" +
  5195. "%2 = OpLoad %float %var\n" +
  5196. "%3 = OpFAdd %float %float_1 %2\n" +
  5197. "%4 = OpFAdd %float %float_2 %3\n" +
  5198. "OpReturn\n" +
  5199. "OpFunctionEnd\n",
  5200. 4, true)
  5201. ));
  5202. INSTANTIATE_TEST_SUITE_P(MergeSubTest, MatchingInstructionFoldingTest,
  5203. ::testing::Values(
  5204. // Test case 0: merge sub of negate
  5205. // (-x) - 2 = -2 - x
  5206. InstructionFoldingCase<bool>(
  5207. Header() +
  5208. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5209. "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2\n" +
  5210. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  5211. "; CHECK: %4 = OpFSub [[float]] [[float_n2]] [[ld]]\n" +
  5212. "%main = OpFunction %void None %void_func\n" +
  5213. "%main_lab = OpLabel\n" +
  5214. "%var = OpVariable %_ptr_float Function\n" +
  5215. "%2 = OpLoad %float %var\n" +
  5216. "%3 = OpFNegate %float %2\n" +
  5217. "%4 = OpFSub %float %3 %float_2\n" +
  5218. "OpReturn\n" +
  5219. "OpFunctionEnd\n",
  5220. 4, true),
  5221. // Test case 1: merge sub of negate
  5222. // 2 - (-x) = x + 2
  5223. InstructionFoldingCase<bool>(
  5224. Header() +
  5225. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5226. "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
  5227. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  5228. "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_2]]\n" +
  5229. "%main = OpFunction %void None %void_func\n" +
  5230. "%main_lab = OpLabel\n" +
  5231. "%var = OpVariable %_ptr_float Function\n" +
  5232. "%2 = OpLoad %float %var\n" +
  5233. "%3 = OpFNegate %float %2\n" +
  5234. "%4 = OpFSub %float %float_2 %3\n" +
  5235. "OpReturn\n" +
  5236. "OpFunctionEnd\n",
  5237. 4, true),
  5238. // Test case 2: merge sub of negate
  5239. // (-x) - 2 = -2 - x
  5240. InstructionFoldingCase<bool>(
  5241. Header() +
  5242. "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
  5243. "; CHECK: [[long_n2:%\\w+]] = OpConstant [[long]] -2\n" +
  5244. "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
  5245. "; CHECK: %4 = OpISub [[long]] [[long_n2]] [[ld]]\n" +
  5246. "%main = OpFunction %void None %void_func\n" +
  5247. "%main_lab = OpLabel\n" +
  5248. "%var = OpVariable %_ptr_long Function\n" +
  5249. "%2 = OpLoad %long %var\n" +
  5250. "%3 = OpSNegate %long %2\n" +
  5251. "%4 = OpISub %long %3 %long_2\n" +
  5252. "OpReturn\n" +
  5253. "OpFunctionEnd\n",
  5254. 4, true),
  5255. // Test case 3: merge sub of negate
  5256. // 2 - (-x) = x + 2
  5257. InstructionFoldingCase<bool>(
  5258. Header() +
  5259. "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
  5260. "; CHECK: [[long_2:%\\w+]] = OpConstant [[long]] 2\n" +
  5261. "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
  5262. "; CHECK: %4 = OpIAdd [[long]] [[ld]] [[long_2]]\n" +
  5263. "%main = OpFunction %void None %void_func\n" +
  5264. "%main_lab = OpLabel\n" +
  5265. "%var = OpVariable %_ptr_long Function\n" +
  5266. "%2 = OpLoad %long %var\n" +
  5267. "%3 = OpSNegate %long %2\n" +
  5268. "%4 = OpISub %long %long_2 %3\n" +
  5269. "OpReturn\n" +
  5270. "OpFunctionEnd\n",
  5271. 4, true),
  5272. // Test case 4: merge add of subtract
  5273. // (x + 2) - 1 = x + 1
  5274. InstructionFoldingCase<bool>(
  5275. Header() +
  5276. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5277. "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
  5278. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  5279. "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_1]]\n" +
  5280. "%main = OpFunction %void None %void_func\n" +
  5281. "%main_lab = OpLabel\n" +
  5282. "%var = OpVariable %_ptr_float Function\n" +
  5283. "%2 = OpLoad %float %var\n" +
  5284. "%3 = OpFAdd %float %2 %float_2\n" +
  5285. "%4 = OpFSub %float %3 %float_1\n" +
  5286. "OpReturn\n" +
  5287. "OpFunctionEnd\n",
  5288. 4, true),
  5289. // Test case 5: merge add of subtract
  5290. // (2 + x) - 1 = x + 1
  5291. InstructionFoldingCase<bool>(
  5292. Header() +
  5293. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5294. "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
  5295. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  5296. "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_1]]\n" +
  5297. "%main = OpFunction %void None %void_func\n" +
  5298. "%main_lab = OpLabel\n" +
  5299. "%var = OpVariable %_ptr_float Function\n" +
  5300. "%2 = OpLoad %float %var\n" +
  5301. "%3 = OpFAdd %float %float_2 %2\n" +
  5302. "%4 = OpFSub %float %3 %float_1\n" +
  5303. "OpReturn\n" +
  5304. "OpFunctionEnd\n",
  5305. 4, true),
  5306. // Test case 6: merge add of subtract
  5307. // 2 - (x + 1) = 1 - x
  5308. InstructionFoldingCase<bool>(
  5309. Header() +
  5310. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5311. "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
  5312. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  5313. "; CHECK: %4 = OpFSub [[float]] [[float_1]] [[ld]]\n" +
  5314. "%main = OpFunction %void None %void_func\n" +
  5315. "%main_lab = OpLabel\n" +
  5316. "%var = OpVariable %_ptr_float Function\n" +
  5317. "%2 = OpLoad %float %var\n" +
  5318. "%3 = OpFAdd %float %2 %float_1\n" +
  5319. "%4 = OpFSub %float %float_2 %3\n" +
  5320. "OpReturn\n" +
  5321. "OpFunctionEnd\n",
  5322. 4, true),
  5323. // Test case 7: merge add of subtract
  5324. // 2 - (1 + x) = 1 - x
  5325. InstructionFoldingCase<bool>(
  5326. Header() +
  5327. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5328. "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
  5329. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  5330. "; CHECK: %4 = OpFSub [[float]] [[float_1]] [[ld]]\n" +
  5331. "%main = OpFunction %void None %void_func\n" +
  5332. "%main_lab = OpLabel\n" +
  5333. "%var = OpVariable %_ptr_float Function\n" +
  5334. "%2 = OpLoad %float %var\n" +
  5335. "%3 = OpFAdd %float %float_1 %2\n" +
  5336. "%4 = OpFSub %float %float_2 %3\n" +
  5337. "OpReturn\n" +
  5338. "OpFunctionEnd\n",
  5339. 4, true),
  5340. // Test case 8: merge subtract of subtract
  5341. // (x - 2) - 1 = x - 3
  5342. InstructionFoldingCase<bool>(
  5343. Header() +
  5344. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5345. "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
  5346. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  5347. "; CHECK: %4 = OpFSub [[float]] [[ld]] [[float_3]]\n" +
  5348. "%main = OpFunction %void None %void_func\n" +
  5349. "%main_lab = OpLabel\n" +
  5350. "%var = OpVariable %_ptr_float Function\n" +
  5351. "%2 = OpLoad %float %var\n" +
  5352. "%3 = OpFSub %float %2 %float_2\n" +
  5353. "%4 = OpFSub %float %3 %float_1\n" +
  5354. "OpReturn\n" +
  5355. "OpFunctionEnd\n",
  5356. 4, true),
  5357. // Test case 9: merge subtract of subtract
  5358. // (2 - x) - 1 = 1 - x
  5359. InstructionFoldingCase<bool>(
  5360. Header() +
  5361. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5362. "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
  5363. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  5364. "; CHECK: %4 = OpFSub [[float]] [[float_1]] [[ld]]\n" +
  5365. "%main = OpFunction %void None %void_func\n" +
  5366. "%main_lab = OpLabel\n" +
  5367. "%var = OpVariable %_ptr_float Function\n" +
  5368. "%2 = OpLoad %float %var\n" +
  5369. "%3 = OpFSub %float %float_2 %2\n" +
  5370. "%4 = OpFSub %float %3 %float_1\n" +
  5371. "OpReturn\n" +
  5372. "OpFunctionEnd\n",
  5373. 4, true),
  5374. // Test case 10: merge subtract of subtract
  5375. // 2 - (x - 1) = 3 - x
  5376. InstructionFoldingCase<bool>(
  5377. Header() +
  5378. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5379. "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
  5380. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  5381. "; CHECK: %4 = OpFSub [[float]] [[float_3]] [[ld]]\n" +
  5382. "%main = OpFunction %void None %void_func\n" +
  5383. "%main_lab = OpLabel\n" +
  5384. "%var = OpVariable %_ptr_float Function\n" +
  5385. "%2 = OpLoad %float %var\n" +
  5386. "%3 = OpFSub %float %2 %float_1\n" +
  5387. "%4 = OpFSub %float %float_2 %3\n" +
  5388. "OpReturn\n" +
  5389. "OpFunctionEnd\n",
  5390. 4, true),
  5391. // Test case 11: merge subtract of subtract
  5392. // 1 - (2 - x) = x + (-1)
  5393. InstructionFoldingCase<bool>(
  5394. Header() +
  5395. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5396. "; CHECK: [[float_n1:%\\w+]] = OpConstant [[float]] -1\n" +
  5397. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  5398. "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_n1]]\n" +
  5399. "%main = OpFunction %void None %void_func\n" +
  5400. "%main_lab = OpLabel\n" +
  5401. "%var = OpVariable %_ptr_float Function\n" +
  5402. "%2 = OpLoad %float %var\n" +
  5403. "%3 = OpFSub %float %float_2 %2\n" +
  5404. "%4 = OpFSub %float %float_1 %3\n" +
  5405. "OpReturn\n" +
  5406. "OpFunctionEnd\n",
  5407. 4, true),
  5408. // Test case 12: merge subtract of subtract
  5409. // 2 - (1 - x) = x + 1
  5410. InstructionFoldingCase<bool>(
  5411. Header() +
  5412. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5413. "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
  5414. "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
  5415. "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_1]]\n" +
  5416. "%main = OpFunction %void None %void_func\n" +
  5417. "%main_lab = OpLabel\n" +
  5418. "%var = OpVariable %_ptr_float Function\n" +
  5419. "%2 = OpLoad %float %var\n" +
  5420. "%3 = OpFSub %float %float_1 %2\n" +
  5421. "%4 = OpFSub %float %float_2 %3\n" +
  5422. "OpReturn\n" +
  5423. "OpFunctionEnd\n",
  5424. 4, true)
  5425. ));
  5426. INSTANTIATE_TEST_SUITE_P(SelectFoldingTest, MatchingInstructionFoldingTest,
  5427. ::testing::Values(
  5428. // Test case 0: Fold select with the same values for both sides
  5429. InstructionFoldingCase<bool>(
  5430. Header() +
  5431. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  5432. "; CHECK: [[int0:%\\w+]] = OpConstant [[int]] 0\n" +
  5433. "; CHECK: %2 = OpCopyObject [[int]] [[int0]]\n" +
  5434. "%main = OpFunction %void None %void_func\n" +
  5435. "%main_lab = OpLabel\n" +
  5436. "%n = OpVariable %_ptr_bool Function\n" +
  5437. "%load = OpLoad %bool %n\n" +
  5438. "%2 = OpSelect %int %load %100 %100\n" +
  5439. "OpReturn\n" +
  5440. "OpFunctionEnd",
  5441. 2, true),
  5442. // Test case 1: Fold select true to left side
  5443. InstructionFoldingCase<bool>(
  5444. Header() +
  5445. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  5446. "; CHECK: [[int0:%\\w+]] = OpConstant [[int]] 0\n" +
  5447. "; CHECK: %2 = OpCopyObject [[int]] [[int0]]\n" +
  5448. "%main = OpFunction %void None %void_func\n" +
  5449. "%main_lab = OpLabel\n" +
  5450. "%n = OpVariable %_ptr_int Function\n" +
  5451. "%load = OpLoad %bool %n\n" +
  5452. "%2 = OpSelect %int %true %100 %n\n" +
  5453. "OpReturn\n" +
  5454. "OpFunctionEnd",
  5455. 2, true),
  5456. // Test case 2: Fold select false to right side
  5457. InstructionFoldingCase<bool>(
  5458. Header() +
  5459. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  5460. "; CHECK: [[int0:%\\w+]] = OpConstant [[int]] 0\n" +
  5461. "; CHECK: %2 = OpCopyObject [[int]] [[int0]]\n" +
  5462. "%main = OpFunction %void None %void_func\n" +
  5463. "%main_lab = OpLabel\n" +
  5464. "%n = OpVariable %_ptr_int Function\n" +
  5465. "%load = OpLoad %bool %n\n" +
  5466. "%2 = OpSelect %int %false %n %100\n" +
  5467. "OpReturn\n" +
  5468. "OpFunctionEnd",
  5469. 2, true),
  5470. // Test case 3: Fold select null to right side
  5471. InstructionFoldingCase<bool>(
  5472. Header() +
  5473. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  5474. "; CHECK: [[int0:%\\w+]] = OpConstant [[int]] 0\n" +
  5475. "; CHECK: %2 = OpCopyObject [[int]] [[int0]]\n" +
  5476. "%main = OpFunction %void None %void_func\n" +
  5477. "%main_lab = OpLabel\n" +
  5478. "%n = OpVariable %_ptr_int Function\n" +
  5479. "%load = OpLoad %int %n\n" +
  5480. "%2 = OpSelect %int %bool_null %load %100\n" +
  5481. "OpReturn\n" +
  5482. "OpFunctionEnd",
  5483. 2, true),
  5484. // Test case 4: vector null
  5485. InstructionFoldingCase<bool>(
  5486. Header() +
  5487. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  5488. "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2\n" +
  5489. "; CHECK: [[int2:%\\w+]] = OpConstant [[int]] 2\n" +
  5490. "; CHECK: [[v2int2_2:%\\w+]] = OpConstantComposite [[v2int]] [[int2]] [[int2]]\n" +
  5491. "; CHECK: %2 = OpCopyObject [[v2int]] [[v2int2_2]]\n" +
  5492. "%main = OpFunction %void None %void_func\n" +
  5493. "%main_lab = OpLabel\n" +
  5494. "%n = OpVariable %_ptr_v2int Function\n" +
  5495. "%load = OpLoad %v2int %n\n" +
  5496. "%2 = OpSelect %v2int %v2bool_null %load %v2int_2_2\n" +
  5497. "OpReturn\n" +
  5498. "OpFunctionEnd",
  5499. 2, true),
  5500. // Test case 5: vector select
  5501. InstructionFoldingCase<bool>(
  5502. Header() +
  5503. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  5504. "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2\n" +
  5505. "; CHECK: %4 = OpVectorShuffle [[v2int]] %2 %3 0 3\n" +
  5506. "%main = OpFunction %void None %void_func\n" +
  5507. "%main_lab = OpLabel\n" +
  5508. "%m = OpVariable %_ptr_v2int Function\n" +
  5509. "%n = OpVariable %_ptr_v2int Function\n" +
  5510. "%2 = OpLoad %v2int %n\n" +
  5511. "%3 = OpLoad %v2int %n\n" +
  5512. "%4 = OpSelect %v2int %v2bool_true_false %2 %3\n" +
  5513. "OpReturn\n" +
  5514. "OpFunctionEnd",
  5515. 4, true),
  5516. // Test case 6: vector select
  5517. InstructionFoldingCase<bool>(
  5518. Header() +
  5519. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  5520. "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2\n" +
  5521. "; CHECK: %4 = OpVectorShuffle [[v2int]] %2 %3 2 1\n" +
  5522. "%main = OpFunction %void None %void_func\n" +
  5523. "%main_lab = OpLabel\n" +
  5524. "%m = OpVariable %_ptr_v2int Function\n" +
  5525. "%n = OpVariable %_ptr_v2int Function\n" +
  5526. "%2 = OpLoad %v2int %n\n" +
  5527. "%3 = OpLoad %v2int %n\n" +
  5528. "%4 = OpSelect %v2int %v2bool_false_true %2 %3\n" +
  5529. "OpReturn\n" +
  5530. "OpFunctionEnd",
  5531. 4, true)
  5532. ));
  5533. INSTANTIATE_TEST_SUITE_P(CompositeExtractMatchingTest, MatchingInstructionFoldingTest,
  5534. ::testing::Values(
  5535. // Test case 0: Extracting from result of consecutive shuffles of differing
  5536. // size.
  5537. InstructionFoldingCase<bool>(
  5538. Header() +
  5539. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  5540. "; CHECK: %5 = OpCompositeExtract [[int]] %2 2\n" +
  5541. "%main = OpFunction %void None %void_func\n" +
  5542. "%main_lab = OpLabel\n" +
  5543. "%n = OpVariable %_ptr_v4int Function\n" +
  5544. "%2 = OpLoad %v4int %n\n" +
  5545. "%3 = OpVectorShuffle %v2int %2 %2 2 3\n" +
  5546. "%4 = OpVectorShuffle %v4int %2 %3 0 4 2 5\n" +
  5547. "%5 = OpCompositeExtract %int %4 1\n" +
  5548. "OpReturn\n" +
  5549. "OpFunctionEnd",
  5550. 5, true),
  5551. // Test case 1: Extracting from result of vector shuffle of differing
  5552. // input and result sizes.
  5553. InstructionFoldingCase<bool>(
  5554. Header() +
  5555. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  5556. "; CHECK: %4 = OpCompositeExtract [[int]] %2 2\n" +
  5557. "%main = OpFunction %void None %void_func\n" +
  5558. "%main_lab = OpLabel\n" +
  5559. "%n = OpVariable %_ptr_v4int Function\n" +
  5560. "%2 = OpLoad %v4int %n\n" +
  5561. "%3 = OpVectorShuffle %v2int %2 %2 2 3\n" +
  5562. "%4 = OpCompositeExtract %int %3 0\n" +
  5563. "OpReturn\n" +
  5564. "OpFunctionEnd",
  5565. 4, true),
  5566. // Test case 2: Extracting from result of vector shuffle of differing
  5567. // input and result sizes.
  5568. InstructionFoldingCase<bool>(
  5569. Header() +
  5570. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  5571. "; CHECK: %4 = OpCompositeExtract [[int]] %2 3\n" +
  5572. "%main = OpFunction %void None %void_func\n" +
  5573. "%main_lab = OpLabel\n" +
  5574. "%n = OpVariable %_ptr_v4int Function\n" +
  5575. "%2 = OpLoad %v4int %n\n" +
  5576. "%3 = OpVectorShuffle %v2int %2 %2 2 3\n" +
  5577. "%4 = OpCompositeExtract %int %3 1\n" +
  5578. "OpReturn\n" +
  5579. "OpFunctionEnd",
  5580. 4, true),
  5581. // Test case 3: Using fmix feeding extract with a 1 in the a position.
  5582. InstructionFoldingCase<bool>(
  5583. Header() +
  5584. "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
  5585. "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 4\n" +
  5586. "; CHECK: [[ptr_v4double:%\\w+]] = OpTypePointer Function [[v4double]]\n" +
  5587. "; CHECK: [[m:%\\w+]] = OpVariable [[ptr_v4double]] Function\n" +
  5588. "; CHECK: [[n:%\\w+]] = OpVariable [[ptr_v4double]] Function\n" +
  5589. "; CHECK: [[ld:%\\w+]] = OpLoad [[v4double]] [[n]]\n" +
  5590. "; CHECK: %5 = OpCompositeExtract [[double]] [[ld]] 1\n" +
  5591. "%main = OpFunction %void None %void_func\n" +
  5592. "%main_lab = OpLabel\n" +
  5593. "%m = OpVariable %_ptr_v4double Function\n" +
  5594. "%n = OpVariable %_ptr_v4double Function\n" +
  5595. "%2 = OpLoad %v4double %m\n" +
  5596. "%3 = OpLoad %v4double %n\n" +
  5597. "%4 = OpExtInst %v4double %1 FMix %2 %3 %v4double_0_1_0_0\n" +
  5598. "%5 = OpCompositeExtract %double %4 1\n" +
  5599. "OpReturn\n" +
  5600. "OpFunctionEnd",
  5601. 5, true),
  5602. // Test case 4: Using fmix feeding extract with a 0 in the a position.
  5603. InstructionFoldingCase<bool>(
  5604. Header() +
  5605. "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
  5606. "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 4\n" +
  5607. "; CHECK: [[ptr_v4double:%\\w+]] = OpTypePointer Function [[v4double]]\n" +
  5608. "; CHECK: [[m:%\\w+]] = OpVariable [[ptr_v4double]] Function\n" +
  5609. "; CHECK: [[n:%\\w+]] = OpVariable [[ptr_v4double]] Function\n" +
  5610. "; CHECK: [[ld:%\\w+]] = OpLoad [[v4double]] [[m]]\n" +
  5611. "; CHECK: %5 = OpCompositeExtract [[double]] [[ld]] 2\n" +
  5612. "%main = OpFunction %void None %void_func\n" +
  5613. "%main_lab = OpLabel\n" +
  5614. "%m = OpVariable %_ptr_v4double Function\n" +
  5615. "%n = OpVariable %_ptr_v4double Function\n" +
  5616. "%2 = OpLoad %v4double %m\n" +
  5617. "%3 = OpLoad %v4double %n\n" +
  5618. "%4 = OpExtInst %v4double %1 FMix %2 %3 %v4double_0_1_0_0\n" +
  5619. "%5 = OpCompositeExtract %double %4 2\n" +
  5620. "OpReturn\n" +
  5621. "OpFunctionEnd",
  5622. 5, true),
  5623. // Test case 5: Using fmix feeding extract with a null for the alpha
  5624. InstructionFoldingCase<bool>(
  5625. Header() +
  5626. "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
  5627. "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 4\n" +
  5628. "; CHECK: [[ptr_v4double:%\\w+]] = OpTypePointer Function [[v4double]]\n" +
  5629. "; CHECK: [[m:%\\w+]] = OpVariable [[ptr_v4double]] Function\n" +
  5630. "; CHECK: [[n:%\\w+]] = OpVariable [[ptr_v4double]] Function\n" +
  5631. "; CHECK: [[ld:%\\w+]] = OpLoad [[v4double]] [[m]]\n" +
  5632. "; CHECK: %5 = OpCompositeExtract [[double]] [[ld]] 0\n" +
  5633. "%main = OpFunction %void None %void_func\n" +
  5634. "%main_lab = OpLabel\n" +
  5635. "%m = OpVariable %_ptr_v4double Function\n" +
  5636. "%n = OpVariable %_ptr_v4double Function\n" +
  5637. "%2 = OpLoad %v4double %m\n" +
  5638. "%3 = OpLoad %v4double %n\n" +
  5639. "%4 = OpExtInst %v4double %1 FMix %2 %3 %v4double_null\n" +
  5640. "%5 = OpCompositeExtract %double %4 0\n" +
  5641. "OpReturn\n" +
  5642. "OpFunctionEnd",
  5643. 5, true),
  5644. // Test case 6: Don't fold: Using fmix feeding extract with 0.5 in the a
  5645. // position.
  5646. InstructionFoldingCase<bool>(
  5647. Header() +
  5648. "%main = OpFunction %void None %void_func\n" +
  5649. "%main_lab = OpLabel\n" +
  5650. "%m = OpVariable %_ptr_v4double Function\n" +
  5651. "%n = OpVariable %_ptr_v4double Function\n" +
  5652. "%2 = OpLoad %v4double %m\n" +
  5653. "%3 = OpLoad %v4double %n\n" +
  5654. "%4 = OpExtInst %v4double %1 FMix %2 %3 %v4double_1_1_1_0p5\n" +
  5655. "%5 = OpCompositeExtract %double %4 3\n" +
  5656. "OpReturn\n" +
  5657. "OpFunctionEnd",
  5658. 5, false),
  5659. // Test case 7: Extracting the undefined literal value from a vector
  5660. // shuffle.
  5661. InstructionFoldingCase<bool>(
  5662. Header() +
  5663. "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
  5664. "; CHECK: %4 = OpUndef [[int]]\n" +
  5665. "%main = OpFunction %void None %void_func\n" +
  5666. "%main_lab = OpLabel\n" +
  5667. "%n = OpVariable %_ptr_v4int Function\n" +
  5668. "%2 = OpLoad %v4int %n\n" +
  5669. "%3 = OpVectorShuffle %v2int %2 %2 2 4294967295\n" +
  5670. "%4 = OpCompositeExtract %int %3 1\n" +
  5671. "OpReturn\n" +
  5672. "OpFunctionEnd",
  5673. 4, true)
  5674. ));
  5675. INSTANTIATE_TEST_SUITE_P(DotProductMatchingTest, MatchingInstructionFoldingTest,
  5676. ::testing::Values(
  5677. // Test case 0: Using OpDot to extract last element.
  5678. InstructionFoldingCase<bool>(
  5679. Header() +
  5680. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5681. "; CHECK: %3 = OpCompositeExtract [[float]] %2 3\n" +
  5682. "%main = OpFunction %void None %void_func\n" +
  5683. "%main_lab = OpLabel\n" +
  5684. "%n = OpVariable %_ptr_v4float Function\n" +
  5685. "%2 = OpLoad %v4float %n\n" +
  5686. "%3 = OpDot %float %2 %v4float_0_0_0_1\n" +
  5687. "OpReturn\n" +
  5688. "OpFunctionEnd",
  5689. 3, true),
  5690. // Test case 1: Using OpDot to extract last element.
  5691. InstructionFoldingCase<bool>(
  5692. Header() +
  5693. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5694. "; CHECK: %3 = OpCompositeExtract [[float]] %2 3\n" +
  5695. "%main = OpFunction %void None %void_func\n" +
  5696. "%main_lab = OpLabel\n" +
  5697. "%n = OpVariable %_ptr_v4float Function\n" +
  5698. "%2 = OpLoad %v4float %n\n" +
  5699. "%3 = OpDot %float %v4float_0_0_0_1 %2\n" +
  5700. "OpReturn\n" +
  5701. "OpFunctionEnd",
  5702. 3, true),
  5703. // Test case 2: Using OpDot to extract second element.
  5704. InstructionFoldingCase<bool>(
  5705. Header() +
  5706. "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
  5707. "; CHECK: %3 = OpCompositeExtract [[float]] %2 1\n" +
  5708. "%main = OpFunction %void None %void_func\n" +
  5709. "%main_lab = OpLabel\n" +
  5710. "%n = OpVariable %_ptr_v4float Function\n" +
  5711. "%2 = OpLoad %v4float %n\n" +
  5712. "%3 = OpDot %float %v4float_0_1_0_0 %2\n" +
  5713. "OpReturn\n" +
  5714. "OpFunctionEnd",
  5715. 3, true),
  5716. // Test case 3: Using OpDot to extract last element.
  5717. InstructionFoldingCase<bool>(
  5718. Header() +
  5719. "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
  5720. "; CHECK: %3 = OpCompositeExtract [[double]] %2 3\n" +
  5721. "%main = OpFunction %void None %void_func\n" +
  5722. "%main_lab = OpLabel\n" +
  5723. "%n = OpVariable %_ptr_v4double Function\n" +
  5724. "%2 = OpLoad %v4double %n\n" +
  5725. "%3 = OpDot %double %2 %v4double_0_0_0_1\n" +
  5726. "OpReturn\n" +
  5727. "OpFunctionEnd",
  5728. 3, true),
  5729. // Test case 4: Using OpDot to extract last element.
  5730. InstructionFoldingCase<bool>(
  5731. Header() +
  5732. "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
  5733. "; CHECK: %3 = OpCompositeExtract [[double]] %2 3\n" +
  5734. "%main = OpFunction %void None %void_func\n" +
  5735. "%main_lab = OpLabel\n" +
  5736. "%n = OpVariable %_ptr_v4double Function\n" +
  5737. "%2 = OpLoad %v4double %n\n" +
  5738. "%3 = OpDot %double %v4double_0_0_0_1 %2\n" +
  5739. "OpReturn\n" +
  5740. "OpFunctionEnd",
  5741. 3, true),
  5742. // Test case 5: Using OpDot to extract second element.
  5743. InstructionFoldingCase<bool>(
  5744. Header() +
  5745. "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
  5746. "; CHECK: %3 = OpCompositeExtract [[double]] %2 1\n" +
  5747. "%main = OpFunction %void None %void_func\n" +
  5748. "%main_lab = OpLabel\n" +
  5749. "%n = OpVariable %_ptr_v4double Function\n" +
  5750. "%2 = OpLoad %v4double %n\n" +
  5751. "%3 = OpDot %double %v4double_0_1_0_0 %2\n" +
  5752. "OpReturn\n" +
  5753. "OpFunctionEnd",
  5754. 3, true)
  5755. ));
  5756. using MatchingInstructionWithNoResultFoldingTest =
  5757. ::testing::TestWithParam<InstructionFoldingCase<bool>>;
  5758. // Test folding instructions that do not have a result. The instruction
  5759. // that will be folded is the last instruction before the return. If there
  5760. // are multiple returns, there is not guarentee which one is used.
  5761. TEST_P(MatchingInstructionWithNoResultFoldingTest, Case) {
  5762. const auto& tc = GetParam();
  5763. // Build module.
  5764. std::unique_ptr<IRContext> context =
  5765. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
  5766. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  5767. ASSERT_NE(nullptr, context);
  5768. // Fold the instruction to test.
  5769. Instruction* inst = nullptr;
  5770. Function* func = &*context->module()->begin();
  5771. for (auto& bb : *func) {
  5772. Instruction* terminator = bb.terminator();
  5773. if (terminator->IsReturnOrAbort()) {
  5774. inst = terminator->PreviousNode();
  5775. break;
  5776. }
  5777. }
  5778. assert(inst && "Invalid test. Could not find instruction to fold.");
  5779. std::unique_ptr<Instruction> original_inst(inst->Clone(context.get()));
  5780. bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
  5781. EXPECT_EQ(succeeded, tc.expected_result);
  5782. if (succeeded) {
  5783. Match(tc.test_body, context.get());
  5784. }
  5785. }
  5786. INSTANTIATE_TEST_SUITE_P(StoreMatchingTest, MatchingInstructionWithNoResultFoldingTest,
  5787. ::testing::Values(
  5788. // Test case 0: Remove store of undef.
  5789. InstructionFoldingCase<bool>(
  5790. Header() +
  5791. "; CHECK: OpLabel\n" +
  5792. "; CHECK-NOT: OpStore\n" +
  5793. "; CHECK: OpReturn\n" +
  5794. "%main = OpFunction %void None %void_func\n" +
  5795. "%main_lab = OpLabel\n" +
  5796. "%n = OpVariable %_ptr_v4double Function\n" +
  5797. "%undef = OpUndef %v4double\n" +
  5798. "OpStore %n %undef\n" +
  5799. "OpReturn\n" +
  5800. "OpFunctionEnd",
  5801. 0 /* OpStore */, true),
  5802. // Test case 1: Keep volatile store.
  5803. InstructionFoldingCase<bool>(
  5804. Header() +
  5805. "%main = OpFunction %void None %void_func\n" +
  5806. "%main_lab = OpLabel\n" +
  5807. "%n = OpVariable %_ptr_v4double Function\n" +
  5808. "%undef = OpUndef %v4double\n" +
  5809. "OpStore %n %undef Volatile\n" +
  5810. "OpReturn\n" +
  5811. "OpFunctionEnd",
  5812. 0 /* OpStore */, false)
  5813. ));
  5814. INSTANTIATE_TEST_SUITE_P(VectorShuffleMatchingTest, MatchingInstructionWithNoResultFoldingTest,
  5815. ::testing::Values(
  5816. // Test case 0: Basic test 1
  5817. InstructionFoldingCase<bool>(
  5818. Header() +
  5819. "; CHECK: OpVectorShuffle\n" +
  5820. "; CHECK: OpVectorShuffle {{%\\w+}} %7 %5 2 3 6 7\n" +
  5821. "; CHECK: OpReturn\n" +
  5822. "%main = OpFunction %void None %void_func\n" +
  5823. "%main_lab = OpLabel\n" +
  5824. "%2 = OpVariable %_ptr_v4double Function\n" +
  5825. "%3 = OpVariable %_ptr_v4double Function\n" +
  5826. "%4 = OpVariable %_ptr_v4double Function\n" +
  5827. "%5 = OpLoad %v4double %2\n" +
  5828. "%6 = OpLoad %v4double %3\n" +
  5829. "%7 = OpLoad %v4double %4\n" +
  5830. "%8 = OpVectorShuffle %v4double %5 %6 2 3 4 5\n" +
  5831. "%9 = OpVectorShuffle %v4double %7 %8 2 3 4 5\n" +
  5832. "OpReturn\n" +
  5833. "OpFunctionEnd",
  5834. 9, true),
  5835. // Test case 1: Basic test 2
  5836. InstructionFoldingCase<bool>(
  5837. Header() +
  5838. "; CHECK: OpVectorShuffle\n" +
  5839. "; CHECK: OpVectorShuffle {{%\\w+}} %6 %7 0 1 4 5\n" +
  5840. "; CHECK: OpReturn\n" +
  5841. "%main = OpFunction %void None %void_func\n" +
  5842. "%main_lab = OpLabel\n" +
  5843. "%2 = OpVariable %_ptr_v4double Function\n" +
  5844. "%3 = OpVariable %_ptr_v4double Function\n" +
  5845. "%4 = OpVariable %_ptr_v4double Function\n" +
  5846. "%5 = OpLoad %v4double %2\n" +
  5847. "%6 = OpLoad %v4double %3\n" +
  5848. "%7 = OpLoad %v4double %4\n" +
  5849. "%8 = OpVectorShuffle %v4double %5 %6 2 3 4 5\n" +
  5850. "%9 = OpVectorShuffle %v4double %8 %7 2 3 4 5\n" +
  5851. "OpReturn\n" +
  5852. "OpFunctionEnd",
  5853. 9, true),
  5854. // Test case 2: Basic test 3
  5855. InstructionFoldingCase<bool>(
  5856. Header() +
  5857. "; CHECK: OpVectorShuffle\n" +
  5858. "; CHECK: OpVectorShuffle {{%\\w+}} %5 %7 3 2 4 5\n" +
  5859. "; CHECK: OpReturn\n" +
  5860. "%main = OpFunction %void None %void_func\n" +
  5861. "%main_lab = OpLabel\n" +
  5862. "%2 = OpVariable %_ptr_v4double Function\n" +
  5863. "%3 = OpVariable %_ptr_v4double Function\n" +
  5864. "%4 = OpVariable %_ptr_v4double Function\n" +
  5865. "%5 = OpLoad %v4double %2\n" +
  5866. "%6 = OpLoad %v4double %3\n" +
  5867. "%7 = OpLoad %v4double %4\n" +
  5868. "%8 = OpVectorShuffle %v4double %5 %6 2 3 4 5\n" +
  5869. "%9 = OpVectorShuffle %v4double %8 %7 1 0 4 5\n" +
  5870. "OpReturn\n" +
  5871. "OpFunctionEnd",
  5872. 9, true),
  5873. // Test case 3: Basic test 4
  5874. InstructionFoldingCase<bool>(
  5875. Header() +
  5876. "; CHECK: OpVectorShuffle\n" +
  5877. "; CHECK: OpVectorShuffle {{%\\w+}} %7 %6 2 3 5 4\n" +
  5878. "; CHECK: OpReturn\n" +
  5879. "%main = OpFunction %void None %void_func\n" +
  5880. "%main_lab = OpLabel\n" +
  5881. "%2 = OpVariable %_ptr_v4double Function\n" +
  5882. "%3 = OpVariable %_ptr_v4double Function\n" +
  5883. "%4 = OpVariable %_ptr_v4double Function\n" +
  5884. "%5 = OpLoad %v4double %2\n" +
  5885. "%6 = OpLoad %v4double %3\n" +
  5886. "%7 = OpLoad %v4double %4\n" +
  5887. "%8 = OpVectorShuffle %v4double %5 %6 2 3 4 5\n" +
  5888. "%9 = OpVectorShuffle %v4double %7 %8 2 3 7 6\n" +
  5889. "OpReturn\n" +
  5890. "OpFunctionEnd",
  5891. 9, true),
  5892. // Test case 4: Don't fold, need both operands of the feeder.
  5893. InstructionFoldingCase<bool>(
  5894. Header() +
  5895. "%main = OpFunction %void None %void_func\n" +
  5896. "%main_lab = OpLabel\n" +
  5897. "%2 = OpVariable %_ptr_v4double Function\n" +
  5898. "%3 = OpVariable %_ptr_v4double Function\n" +
  5899. "%4 = OpVariable %_ptr_v4double Function\n" +
  5900. "%5 = OpLoad %v4double %2\n" +
  5901. "%6 = OpLoad %v4double %3\n" +
  5902. "%7 = OpLoad %v4double %4\n" +
  5903. "%8 = OpVectorShuffle %v4double %5 %6 2 3 4 5\n" +
  5904. "%9 = OpVectorShuffle %v4double %7 %8 2 3 7 5\n" +
  5905. "OpReturn\n" +
  5906. "OpFunctionEnd",
  5907. 9, false),
  5908. // Test case 5: Don't fold, need both operands of the feeder.
  5909. InstructionFoldingCase<bool>(
  5910. Header() +
  5911. "%main = OpFunction %void None %void_func\n" +
  5912. "%main_lab = OpLabel\n" +
  5913. "%2 = OpVariable %_ptr_v4double Function\n" +
  5914. "%3 = OpVariable %_ptr_v4double Function\n" +
  5915. "%4 = OpVariable %_ptr_v4double Function\n" +
  5916. "%5 = OpLoad %v4double %2\n" +
  5917. "%6 = OpLoad %v4double %3\n" +
  5918. "%7 = OpLoad %v4double %4\n" +
  5919. "%8 = OpVectorShuffle %v4double %5 %6 2 3 4 5\n" +
  5920. "%9 = OpVectorShuffle %v4double %8 %7 2 0 7 5\n" +
  5921. "OpReturn\n" +
  5922. "OpFunctionEnd",
  5923. 9, false),
  5924. // Test case 6: Fold, need both operands of the feeder, but they are the same.
  5925. InstructionFoldingCase<bool>(
  5926. Header() +
  5927. "; CHECK: OpVectorShuffle\n" +
  5928. "; CHECK: OpVectorShuffle {{%\\w+}} %5 %7 0 2 7 5\n" +
  5929. "; CHECK: OpReturn\n" +
  5930. "%main = OpFunction %void None %void_func\n" +
  5931. "%main_lab = OpLabel\n" +
  5932. "%2 = OpVariable %_ptr_v4double Function\n" +
  5933. "%3 = OpVariable %_ptr_v4double Function\n" +
  5934. "%4 = OpVariable %_ptr_v4double Function\n" +
  5935. "%5 = OpLoad %v4double %2\n" +
  5936. "%6 = OpLoad %v4double %3\n" +
  5937. "%7 = OpLoad %v4double %4\n" +
  5938. "%8 = OpVectorShuffle %v4double %5 %5 2 3 4 5\n" +
  5939. "%9 = OpVectorShuffle %v4double %8 %7 2 0 7 5\n" +
  5940. "OpReturn\n" +
  5941. "OpFunctionEnd",
  5942. 9, true),
  5943. // Test case 7: Fold, need both operands of the feeder, but they are the same.
  5944. InstructionFoldingCase<bool>(
  5945. Header() +
  5946. "; CHECK: OpVectorShuffle\n" +
  5947. "; CHECK: OpVectorShuffle {{%\\w+}} %7 %5 2 0 5 7\n" +
  5948. "; CHECK: OpReturn\n" +
  5949. "%main = OpFunction %void None %void_func\n" +
  5950. "%main_lab = OpLabel\n" +
  5951. "%2 = OpVariable %_ptr_v4double Function\n" +
  5952. "%3 = OpVariable %_ptr_v4double Function\n" +
  5953. "%4 = OpVariable %_ptr_v4double Function\n" +
  5954. "%5 = OpLoad %v4double %2\n" +
  5955. "%6 = OpLoad %v4double %3\n" +
  5956. "%7 = OpLoad %v4double %4\n" +
  5957. "%8 = OpVectorShuffle %v4double %5 %5 2 3 4 5\n" +
  5958. "%9 = OpVectorShuffle %v4double %7 %8 2 0 7 5\n" +
  5959. "OpReturn\n" +
  5960. "OpFunctionEnd",
  5961. 9, true),
  5962. // Test case 8: Replace first operand with a smaller vector.
  5963. InstructionFoldingCase<bool>(
  5964. Header() +
  5965. "; CHECK: OpVectorShuffle\n" +
  5966. "; CHECK: OpVectorShuffle {{%\\w+}} %5 %7 0 0 5 3\n" +
  5967. "; CHECK: OpReturn\n" +
  5968. "%main = OpFunction %void None %void_func\n" +
  5969. "%main_lab = OpLabel\n" +
  5970. "%2 = OpVariable %_ptr_v2double Function\n" +
  5971. "%3 = OpVariable %_ptr_v4double Function\n" +
  5972. "%4 = OpVariable %_ptr_v4double Function\n" +
  5973. "%5 = OpLoad %v2double %2\n" +
  5974. "%6 = OpLoad %v4double %3\n" +
  5975. "%7 = OpLoad %v4double %4\n" +
  5976. "%8 = OpVectorShuffle %v4double %5 %5 0 1 2 3\n" +
  5977. "%9 = OpVectorShuffle %v4double %8 %7 2 0 7 5\n" +
  5978. "OpReturn\n" +
  5979. "OpFunctionEnd",
  5980. 9, true),
  5981. // Test case 9: Replace first operand with a larger vector.
  5982. InstructionFoldingCase<bool>(
  5983. Header() +
  5984. "; CHECK: OpVectorShuffle\n" +
  5985. "; CHECK: OpVectorShuffle {{%\\w+}} %5 %7 3 0 7 5\n" +
  5986. "; CHECK: OpReturn\n" +
  5987. "%main = OpFunction %void None %void_func\n" +
  5988. "%main_lab = OpLabel\n" +
  5989. "%2 = OpVariable %_ptr_v4double Function\n" +
  5990. "%3 = OpVariable %_ptr_v4double Function\n" +
  5991. "%4 = OpVariable %_ptr_v4double Function\n" +
  5992. "%5 = OpLoad %v4double %2\n" +
  5993. "%6 = OpLoad %v4double %3\n" +
  5994. "%7 = OpLoad %v4double %4\n" +
  5995. "%8 = OpVectorShuffle %v2double %5 %5 0 3\n" +
  5996. "%9 = OpVectorShuffle %v4double %8 %7 1 0 5 3\n" +
  5997. "OpReturn\n" +
  5998. "OpFunctionEnd",
  5999. 9, true),
  6000. // Test case 10: Replace unused operand with null.
  6001. InstructionFoldingCase<bool>(
  6002. Header() +
  6003. "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
  6004. "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 2\n" +
  6005. "; CHECK: [[null:%\\w+]] = OpConstantNull [[v4double]]\n" +
  6006. "; CHECK: OpVectorShuffle\n" +
  6007. "; CHECK: OpVectorShuffle {{%\\w+}} [[null]] %7 4 2 5 3\n" +
  6008. "; CHECK: OpReturn\n" +
  6009. "%main = OpFunction %void None %void_func\n" +
  6010. "%main_lab = OpLabel\n" +
  6011. "%2 = OpVariable %_ptr_v4double Function\n" +
  6012. "%3 = OpVariable %_ptr_v4double Function\n" +
  6013. "%4 = OpVariable %_ptr_v4double Function\n" +
  6014. "%5 = OpLoad %v4double %2\n" +
  6015. "%6 = OpLoad %v4double %3\n" +
  6016. "%7 = OpLoad %v4double %4\n" +
  6017. "%8 = OpVectorShuffle %v2double %5 %5 0 3\n" +
  6018. "%9 = OpVectorShuffle %v4double %8 %7 4 2 5 3\n" +
  6019. "OpReturn\n" +
  6020. "OpFunctionEnd",
  6021. 9, true),
  6022. // Test case 11: Replace unused operand with null.
  6023. InstructionFoldingCase<bool>(
  6024. Header() +
  6025. "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
  6026. "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 2\n" +
  6027. "; CHECK: [[null:%\\w+]] = OpConstantNull [[v4double]]\n" +
  6028. "; CHECK: OpVectorShuffle\n" +
  6029. "; CHECK: OpVectorShuffle {{%\\w+}} [[null]] %5 2 2 5 5\n" +
  6030. "; CHECK: OpReturn\n" +
  6031. "%main = OpFunction %void None %void_func\n" +
  6032. "%main_lab = OpLabel\n" +
  6033. "%2 = OpVariable %_ptr_v4double Function\n" +
  6034. "%3 = OpVariable %_ptr_v4double Function\n" +
  6035. "%5 = OpLoad %v4double %2\n" +
  6036. "%6 = OpLoad %v4double %3\n" +
  6037. "%8 = OpVectorShuffle %v2double %5 %5 0 3\n" +
  6038. "%9 = OpVectorShuffle %v4double %8 %8 2 2 3 3\n" +
  6039. "OpReturn\n" +
  6040. "OpFunctionEnd",
  6041. 9, true),
  6042. // Test case 12: Replace unused operand with null.
  6043. InstructionFoldingCase<bool>(
  6044. Header() +
  6045. "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
  6046. "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 2\n" +
  6047. "; CHECK: [[null:%\\w+]] = OpConstantNull [[v4double]]\n" +
  6048. "; CHECK: OpVectorShuffle\n" +
  6049. "; CHECK: OpVectorShuffle {{%\\w+}} %7 [[null]] 2 0 1 3\n" +
  6050. "; CHECK: OpReturn\n" +
  6051. "%main = OpFunction %void None %void_func\n" +
  6052. "%main_lab = OpLabel\n" +
  6053. "%2 = OpVariable %_ptr_v4double Function\n" +
  6054. "%3 = OpVariable %_ptr_v4double Function\n" +
  6055. "%4 = OpVariable %_ptr_v4double Function\n" +
  6056. "%5 = OpLoad %v4double %2\n" +
  6057. "%6 = OpLoad %v4double %3\n" +
  6058. "%7 = OpLoad %v4double %4\n" +
  6059. "%8 = OpVectorShuffle %v2double %5 %5 0 3\n" +
  6060. "%9 = OpVectorShuffle %v4double %7 %8 2 0 1 3\n" +
  6061. "OpReturn\n" +
  6062. "OpFunctionEnd",
  6063. 9, true),
  6064. // Test case 13: Shuffle with undef literal.
  6065. InstructionFoldingCase<bool>(
  6066. Header() +
  6067. "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
  6068. "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 2\n" +
  6069. "; CHECK: OpVectorShuffle\n" +
  6070. "; CHECK: OpVectorShuffle {{%\\w+}} %7 {{%\\w+}} 2 0 1 4294967295\n" +
  6071. "; CHECK: OpReturn\n" +
  6072. "%main = OpFunction %void None %void_func\n" +
  6073. "%main_lab = OpLabel\n" +
  6074. "%2 = OpVariable %_ptr_v4double Function\n" +
  6075. "%3 = OpVariable %_ptr_v4double Function\n" +
  6076. "%4 = OpVariable %_ptr_v4double Function\n" +
  6077. "%5 = OpLoad %v4double %2\n" +
  6078. "%6 = OpLoad %v4double %3\n" +
  6079. "%7 = OpLoad %v4double %4\n" +
  6080. "%8 = OpVectorShuffle %v2double %5 %5 0 1\n" +
  6081. "%9 = OpVectorShuffle %v4double %7 %8 2 0 1 4294967295\n" +
  6082. "OpReturn\n" +
  6083. "OpFunctionEnd",
  6084. 9, true)
  6085. ));
  6086. } // namespace
  6087. } // namespace opt
  6088. } // namespace spvtools