fold_test.cpp 289 KB

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