12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320932193229323932493259326932793289329933093319332933393349335933693379338933993409341934293439344934593469347934893499350935193529353935493559356935793589359936093619362936393649365936693679368936993709371937293739374937593769377937893799380938193829383938493859386938793889389939093919392939393949395939693979398939994009401940294039404940594069407940894099410941194129413941494159416941794189419942094219422942394249425942694279428942994309431943294339434943594369437943894399440944194429443944494459446944794489449945094519452945394549455945694579458945994609461946294639464946594669467946894699470947194729473947494759476947794789479948094819482948394849485948694879488948994909491949294939494949594969497949894999500950195029503950495059506950795089509951095119512951395149515951695179518951995209521952295239524952595269527952895299530953195329533953495359536953795389539954095419542954395449545954695479548954995509551955295539554955595569557955895599560956195629563956495659566956795689569957095719572957395749575957695779578957995809581958295839584958595869587958895899590959195929593959495959596959795989599960096019602960396049605960696079608960996109611961296139614961596169617961896199620962196229623962496259626962796289629963096319632963396349635963696379638963996409641964296439644964596469647964896499650965196529653965496559656965796589659966096619662966396649665966696679668966996709671967296739674967596769677967896799680968196829683968496859686968796889689969096919692969396949695969696979698969997009701970297039704970597069707970897099710971197129713971497159716971797189719972097219722 |
- /* Pipeline hazard description translator.
- Copyright (C) 2000-2015 Free Software Foundation, Inc.
- Written by Vladimir Makarov <vmakarov@redhat.com>
- This file is part of GCC.
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 3, or (at your option) any
- later version.
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- for more details.
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3. If not see
- <http://www.gnu.org/licenses/>. */
- /* References:
- 1. The finite state automaton based pipeline hazard recognizer and
- instruction scheduler in GCC. V. Makarov. Proceedings of GCC
- summit, 2003.
- 2. Detecting pipeline structural hazards quickly. T. Proebsting,
- C. Fraser. Proceedings of ACM SIGPLAN-SIGACT Symposium on
- Principles of Programming Languages, pages 280--286, 1994.
- This article is a good start point to understand usage of finite
- state automata for pipeline hazard recognizers. But I'd
- recommend the 1st and 3rd article for more deep understanding.
- 3. Efficient Instruction Scheduling Using Finite State Automata:
- V. Bala and N. Rubin, Proceedings of MICRO-28. This is the best
- article about usage of finite state automata for pipeline hazard
- recognizers.
- The current implementation is described in the 1st article and it
- is different from the 3rd article in the following:
- 1. New operator `|' (alternative) is permitted in functional unit
- reservation which can be treated deterministically and
- non-deterministically.
- 2. Possibility of usage of nondeterministic automata too.
- 3. Possibility to query functional unit reservations for given
- automaton state.
- 4. Several constructions to describe impossible reservations
- (`exclusion_set', `presence_set', `final_presence_set',
- `absence_set', and `final_absence_set').
- 5. No reverse automata are generated. Trace instruction scheduling
- requires this. It can be easily added in the future if we
- really need this.
- 6. Union of automaton states are not generated yet. It is planned
- to be implemented. Such feature is needed to make more accurate
- interlock insn scheduling to get state describing functional
- unit reservation in a joint CFG point. */
- /* This file code processes constructions of machine description file
- which describes automaton used for recognition of processor pipeline
- hazards by insn scheduler and can be used for other tasks (such as
- VLIW insn packing.
- The translator functions `gen_cpu_unit', `gen_query_cpu_unit',
- `gen_bypass', `gen_excl_set', `gen_presence_set',
- `gen_final_presence_set', `gen_absence_set',
- `gen_final_absence_set', `gen_automaton', `gen_automata_option',
- `gen_reserv', `gen_insn_reserv' are called from file
- `genattrtab.c'. They transform RTL constructions describing
- automata in .md file into internal representation convenient for
- further processing.
- The translator major function `expand_automata' processes the
- description internal representation into finite state automaton.
- It can be divided on:
- o checking correctness of the automaton pipeline description
- (major function is `check_all_description').
- o generating automaton (automata) from the description (major
- function is `make_automaton').
- o optional transformation of nondeterministic finite state
- automata into deterministic ones if the alternative operator
- `|' is treated nondeterministically in the description (major
- function is NDFA_to_DFA).
- o optional minimization of the finite state automata by merging
- equivalent automaton states (major function is `minimize_DFA').
- o forming tables (some as comb vectors) and attributes
- representing the automata (functions output_..._table).
- Function `write_automata' outputs the created finite state
- automaton as different tables and functions which works with the
- automata to inquire automaton state and to change its state. These
- function are used by gcc instruction scheduler and may be some
- other gcc code. */
- #include "bconfig.h"
- #include "system.h"
- #include "coretypes.h"
- #include "tm.h"
- #include "rtl.h"
- #include "obstack.h"
- #include "errors.h"
- #include "gensupport.h"
- #include <math.h>
- #include "hashtab.h"
- #include "vec.h"
- #include "fnmatch.h"
- #ifndef CHAR_BIT
- #define CHAR_BIT 8
- #endif
- /* Positions in machine description file. Now they are not used. But
- they could be used in the future for better diagnostic messages. */
- typedef int pos_t;
- /* The following is element of vector of current (and planned in the
- future) functional unit reservations. */
- typedef unsigned HOST_WIDE_INT set_el_t;
- /* Reservations of function units are represented by value of the following
- type. */
- typedef set_el_t *reserv_sets_t;
- typedef const set_el_t *const_reserv_sets_t;
- /* The following structure describes a ticker. */
- struct ticker
- {
- /* The following member value is time of the ticker creation with
- taking into account time when the ticker is off. Active time of
- the ticker is current time minus the value. */
- int modified_creation_time;
- /* The following member value is time (incremented by one) when the
- ticker was off. Zero value means that now the ticker is on. */
- int incremented_off_time;
- };
- /* The ticker is represented by the following type. */
- typedef struct ticker ticker_t;
- /* The following type describes elements of output vectors. */
- typedef HOST_WIDE_INT vect_el_t;
- /* Forward declaration of structures of internal representation of
- pipeline description based on NDFA. */
- struct unit_decl;
- struct bypass_decl;
- struct result_decl;
- struct automaton_decl;
- struct unit_pattern_rel_decl;
- struct reserv_decl;
- struct insn_reserv_decl;
- struct decl;
- struct unit_regexp;
- struct result_regexp;
- struct reserv_regexp;
- struct nothing_regexp;
- struct sequence_regexp;
- struct repeat_regexp;
- struct allof_regexp;
- struct oneof_regexp;
- struct regexp;
- struct description;
- struct unit_set_el;
- struct pattern_set_el;
- struct pattern_reserv;
- struct state;
- struct alt_state;
- struct arc;
- struct ainsn;
- struct automaton;
- struct state_ainsn_table;
- /* The following typedefs are for brevity. */
- typedef struct unit_decl *unit_decl_t;
- typedef const struct unit_decl *const_unit_decl_t;
- typedef struct decl *decl_t;
- typedef const struct decl *const_decl_t;
- typedef struct regexp *regexp_t;
- typedef struct unit_set_el *unit_set_el_t;
- typedef struct pattern_set_el *pattern_set_el_t;
- typedef struct pattern_reserv *pattern_reserv_t;
- typedef struct alt_state *alt_state_t;
- typedef struct state *state_t;
- typedef const struct state *const_state_t;
- typedef struct arc *arc_t;
- typedef struct ainsn *ainsn_t;
- typedef struct automaton *automaton_t;
- typedef struct automata_list_el *automata_list_el_t;
- typedef const struct automata_list_el *const_automata_list_el_t;
- typedef struct state_ainsn_table *state_ainsn_table_t;
- /* Undefined position. */
- static pos_t no_pos = 0;
- /* All IR is stored in the following obstack. */
- static struct obstack irp;
- /* Declare vector types for various data structures: */
- typedef vec<vect_el_t> vla_hwint_t;
- /* Forward declarations of functions used before their definitions, only. */
- static regexp_t gen_regexp_sequence (const char *);
- static void reserv_sets_or (reserv_sets_t, reserv_sets_t,
- reserv_sets_t);
- static reserv_sets_t get_excl_set (reserv_sets_t);
- static int check_presence_pattern_sets (reserv_sets_t,
- reserv_sets_t, int);
- static int check_absence_pattern_sets (reserv_sets_t, reserv_sets_t,
- int);
- static arc_t first_out_arc (const_state_t);
- static arc_t next_out_arc (arc_t);
- /* Options with the following names can be set up in automata_option
- construction. Because the strings occur more one time we use the
- macros. */
- #define NO_MINIMIZATION_OPTION "-no-minimization"
- #define TIME_OPTION "-time"
- #define STATS_OPTION "-stats"
- #define V_OPTION "-v"
- #define W_OPTION "-w"
- #define NDFA_OPTION "-ndfa"
- #define COLLAPSE_OPTION "-collapse-ndfa"
- #define NO_COMB_OPTION "-no-comb-vect"
- #define PROGRESS_OPTION "-progress"
- /* The following flags are set up by function `initiate_automaton_gen'. */
- /* Make automata with nondeterministic reservation by insns (`-ndfa'). */
- static int ndfa_flag;
- /* When making an NDFA, produce additional transitions that collapse
- NDFA state into a deterministic one suitable for querying CPU units.
- Provide avance-state transitions only for deterministic states. */
- static int collapse_flag;
- /* Do not make minimization of DFA (`-no-minimization'). */
- static int no_minimization_flag;
- /* Do not try to generate a comb vector (`-no-comb-vect'). */
- static int no_comb_flag;
- /* Value of this variable is number of automata being generated. The
- actual number of automata may be less this value if there is not
- sufficient number of units. This value is defined by argument of
- option `-split' or by constructions automaton if the value is zero
- (it is default value of the argument). */
- static int split_argument;
- /* Flag of output time statistics (`-time'). */
- static int time_flag;
- /* Flag of automata statistics (`-stats'). */
- static int stats_flag;
- /* Flag of creation of description file which contains description of
- result automaton and statistics information (`-v'). */
- static int v_flag;
- /* Flag of output of a progress bar showing how many states were
- generated so far for automaton being processed (`-progress'). */
- static int progress_flag;
- /* Flag of generating warning instead of error for non-critical errors
- (`-w'). */
- static int w_flag;
- /* Output file for pipeline hazard recognizer (PHR) being generated.
- The value is NULL if the file is not defined. */
- static FILE *output_file;
- /* Description file of PHR. The value is NULL if the file is not
- created. */
- static FILE *output_description_file;
- /* PHR description file name. */
- static char *output_description_file_name;
- /* Value of the following variable is node representing description
- being processed. This is start point of IR. */
- static struct description *description;
- /* This page contains description of IR structure (nodes). */
- enum decl_mode
- {
- dm_unit,
- dm_bypass,
- dm_automaton,
- dm_excl,
- dm_presence,
- dm_absence,
- dm_reserv,
- dm_insn_reserv
- };
- /* This describes define_cpu_unit and define_query_cpu_unit (see file
- rtl.def). */
- struct unit_decl
- {
- const char *name;
- /* NULL if the automaton name is absent. */
- const char *automaton_name;
- /* If the following value is not zero, the cpu unit reservation is
- described in define_query_cpu_unit. */
- char query_p;
- /* The following fields are defined by checker. */
- /* The following field value is nonzero if the unit is used in an
- regexp. */
- char unit_is_used;
- /* The following field value is order number (0, 1, ...) of given
- unit. */
- int unit_num;
- /* The following field value is corresponding declaration of
- automaton which was given in description. If the field value is
- NULL then automaton in the unit declaration was absent. */
- struct automaton_decl *automaton_decl;
- /* The following field value is maximal cycle number (1, ...) on
- which given unit occurs in insns. Zero value means that given
- unit is not used in insns. */
- int max_occ_cycle_num;
- /* The following field value is minimal cycle number (0, ...) on
- which given unit occurs in insns. -1 value means that given
- unit is not used in insns. */
- int min_occ_cycle_num;
- /* The following list contains units which conflict with given
- unit. */
- unit_set_el_t excl_list;
- /* The following list contains patterns which are required to
- reservation of given unit. */
- pattern_set_el_t presence_list;
- pattern_set_el_t final_presence_list;
- /* The following list contains patterns which should be not present
- in reservation for given unit. */
- pattern_set_el_t absence_list;
- pattern_set_el_t final_absence_list;
- /* The following is used only when `query_p' has nonzero value.
- This is query number for the unit. */
- int query_num;
- /* The following is the last cycle on which the unit was checked for
- correct distributions of units to automata in a regexp. */
- int last_distribution_check_cycle;
- /* The following fields are defined by automaton generator. */
- /* The following field value is number of the automaton to which
- given unit belongs. */
- int corresponding_automaton_num;
- /* If the following value is not zero, the cpu unit is present in a
- `exclusion_set' or in right part of a `presence_set',
- `final_presence_set', `absence_set', and
- `final_absence_set'define_query_cpu_unit. */
- char in_set_p;
- };
- /* This describes define_bypass (see file rtl.def). */
- struct bypass_decl
- {
- int latency;
- const char *out_pattern;
- const char *in_pattern;
- const char *bypass_guard_name;
- /* The following fields are defined by checker. */
- /* output and input insns of given bypass. */
- struct insn_reserv_decl *out_insn_reserv;
- struct insn_reserv_decl *in_insn_reserv;
- /* The next bypass for given output insn. */
- struct bypass_decl *next;
- };
- /* This describes define_automaton (see file rtl.def). */
- struct automaton_decl
- {
- const char *name;
- /* The following fields are defined by automaton generator. */
- /* The following field value is nonzero if the automaton is used in
- an regexp definition. */
- char automaton_is_used;
- /* The following fields are defined by checker. */
- /* The following field value is the corresponding automaton. This
- field is not NULL only if the automaton is present in unit
- declarations and the automatic partition on automata is not
- used. */
- automaton_t corresponding_automaton;
- };
- /* This describes exclusion relations: exclusion_set (see file
- rtl.def). */
- struct excl_rel_decl
- {
- int all_names_num;
- int first_list_length;
- char *names [1];
- };
- /* This describes unit relations: [final_]presence_set or
- [final_]absence_set (see file rtl.def). */
- struct unit_pattern_rel_decl
- {
- int final_p;
- int names_num;
- int patterns_num;
- char **names;
- char ***patterns;
- };
- /* This describes define_reservation (see file rtl.def). */
- struct reserv_decl
- {
- const char *name;
- regexp_t regexp;
- /* The following fields are defined by checker. */
- /* The following field value is nonzero if the unit is used in an
- regexp. */
- char reserv_is_used;
- /* The following field is used to check up cycle in expression
- definition. */
- int loop_pass_num;
- };
- /* This describes define_insn_reservation (see file rtl.def). */
- struct insn_reserv_decl
- {
- rtx condexp;
- int default_latency;
- regexp_t regexp;
- const char *name;
- /* The following fields are defined by checker. */
- /* The following field value is order number (0, 1, ...) of given
- insn. */
- int insn_num;
- /* The following field value is list of bypasses in which given insn
- is output insn. Bypasses with the same input insn stay one after
- another in the list in the same order as their occurrences in the
- description but the bypass without a guard stays always the last
- in a row of bypasses with the same input insn. */
- struct bypass_decl *bypass_list;
- /* The following fields are defined by automaton generator. */
- /* The following field is the insn regexp transformed that
- the regexp has not optional regexp, repetition regexp, and an
- reservation name (i.e. reservation identifiers are changed by the
- corresponding regexp) and all alternations are the top level
- of the regexp. The value can be NULL only if it is special
- insn `cycle advancing'. */
- regexp_t transformed_regexp;
- /* The following field value is list of arcs marked given
- insn. The field is used in transformation NDFA -> DFA. */
- arc_t arcs_marked_by_insn;
- /* The two following fields are used during minimization of a finite state
- automaton. */
- /* The field value is number of equivalence class of state into
- which arc marked by given insn enters from a state (fixed during
- an automaton minimization). */
- int equiv_class_num;
- /* The following member value is the list to automata which can be
- changed by the insn issue. */
- automata_list_el_t important_automata_list;
- /* The following member is used to process insn once for output. */
- int processed_p;
- };
- /* This contains a declaration mentioned above. */
- struct decl
- {
- /* What node in the union? */
- enum decl_mode mode;
- pos_t pos;
- union
- {
- struct unit_decl unit;
- struct bypass_decl bypass;
- struct automaton_decl automaton;
- struct excl_rel_decl excl;
- struct unit_pattern_rel_decl presence;
- struct unit_pattern_rel_decl absence;
- struct reserv_decl reserv;
- struct insn_reserv_decl insn_reserv;
- } decl;
- };
- /* The following structures represent parsed reservation strings. */
- enum regexp_mode
- {
- rm_unit,
- rm_reserv,
- rm_nothing,
- rm_sequence,
- rm_repeat,
- rm_allof,
- rm_oneof
- };
- /* Cpu unit in reservation. */
- struct unit_regexp
- {
- const char *name;
- unit_decl_t unit_decl;
- };
- /* Define_reservation in a reservation. */
- struct reserv_regexp
- {
- const char *name;
- struct reserv_decl *reserv_decl;
- };
- /* Absence of reservation (represented by string `nothing'). */
- struct nothing_regexp
- {
- /* This used to be empty but ISO C doesn't allow that. */
- char unused;
- };
- /* Representation of reservations separated by ',' (see file
- rtl.def). */
- struct sequence_regexp
- {
- int regexps_num;
- regexp_t regexps [1];
- };
- /* Representation of construction `repeat' (see file rtl.def). */
- struct repeat_regexp
- {
- int repeat_num;
- regexp_t regexp;
- };
- /* Representation of reservations separated by '+' (see file
- rtl.def). */
- struct allof_regexp
- {
- int regexps_num;
- regexp_t regexps [1];
- };
- /* Representation of reservations separated by '|' (see file
- rtl.def). */
- struct oneof_regexp
- {
- int regexps_num;
- regexp_t regexps [1];
- };
- /* Representation of a reservation string. */
- struct regexp
- {
- /* What node in the union? */
- enum regexp_mode mode;
- pos_t pos;
- union
- {
- struct unit_regexp unit;
- struct reserv_regexp reserv;
- struct nothing_regexp nothing;
- struct sequence_regexp sequence;
- struct repeat_regexp repeat;
- struct allof_regexp allof;
- struct oneof_regexp oneof;
- } regexp;
- };
- /* Represents description of pipeline hazard description based on
- NDFA. */
- struct description
- {
- int decls_num, normal_decls_num;
- /* The following fields are defined by checker. */
- /* The following fields values are correspondingly number of all
- units, query units, and insns in the description. */
- int units_num;
- int query_units_num;
- int insns_num;
- /* The following field value is max length (in cycles) of
- reservations of insns. The field value is defined only for
- correct programs. */
- int max_insn_reserv_cycles;
- /* The following fields are defined by automaton generator. */
- /* The following field value is the first automaton. */
- automaton_t first_automaton;
- /* The following field is created by pipeline hazard parser and
- contains all declarations. We allocate additional entries for
- two special insns which are added by the automaton generator. */
- decl_t decls [1];
- };
- /* The following nodes are created in automaton checker. */
- /* The following nodes represent exclusion set for cpu units. Each
- element is accessed through only one excl_list. */
- struct unit_set_el
- {
- unit_decl_t unit_decl;
- unit_set_el_t next_unit_set_el;
- };
- /* The following nodes represent presence or absence pattern for cpu
- units. Each element is accessed through only one presence_list or
- absence_list. */
- struct pattern_set_el
- {
- /* The number of units in unit_decls. */
- int units_num;
- /* The units forming the pattern. */
- struct unit_decl **unit_decls;
- pattern_set_el_t next_pattern_set_el;
- };
- /* The following nodes are created in automaton generator. */
- /* The following nodes represent presence or absence pattern for cpu
- units. Each element is accessed through only one element of
- unit_presence_set_table or unit_absence_set_table. */
- struct pattern_reserv
- {
- reserv_sets_t reserv;
- pattern_reserv_t next_pattern_reserv;
- };
- /* The following node type describes state automaton. The state may
- be deterministic or non-deterministic. Non-deterministic state has
- several component states which represent alternative cpu units
- reservations. The state also is used for describing a
- deterministic reservation of automaton insn. */
- struct state
- {
- /* The following member value is nonzero if there is a transition by
- cycle advancing. */
- int new_cycle_p;
- /* The following field is list of processor unit reservations on
- each cycle. */
- reserv_sets_t reservs;
- /* The following field is unique number of given state between other
- states. */
- int unique_num;
- /* The following field value is automaton to which given state
- belongs. */
- automaton_t automaton;
- /* The following field value is the first arc output from given
- state. */
- arc_t first_out_arc;
- unsigned int num_out_arcs;
- /* The following field is used to form NDFA. */
- char it_was_placed_in_stack_for_NDFA_forming;
- /* The following field is used to form DFA. */
- char it_was_placed_in_stack_for_DFA_forming;
- /* The following field is used to transform NDFA to DFA and DFA
- minimization. The field value is not NULL if the state is a
- compound state. In this case the value of field `unit_sets_list'
- is NULL. All states in the list are in the hash table. The list
- is formed through field `next_sorted_alt_state'. We should
- support only one level of nesting state. */
- alt_state_t component_states;
- /* The following field is used for passing graph of states. */
- int pass_num;
- /* The list of states belonging to one equivalence class is formed
- with the aid of the following field. */
- state_t next_equiv_class_state;
- /* The two following fields are used during minimization of a finite
- state automaton. */
- int equiv_class_num_1, equiv_class_num_2;
- /* The following field is used during minimization of a finite state
- automaton. The field value is state corresponding to equivalence
- class to which given state belongs. */
- state_t equiv_class_state;
- unsigned int *presence_signature;
- /* The following field value is the order number of given state.
- The states in final DFA is enumerated with the aid of the
- following field. */
- int order_state_num;
- /* This member is used for passing states for searching minimal
- delay time. */
- int state_pass_num;
- /* The following member is used to evaluate min issue delay of insn
- for a state. */
- int min_insn_issue_delay;
- };
- /* Automaton arc. */
- struct arc
- {
- /* The following field refers for the state into which given arc
- enters. */
- state_t to_state;
- /* The following field describes that the insn issue (with cycle
- advancing for special insn `cycle advancing' and without cycle
- advancing for others) makes transition from given state to
- another given state. */
- ainsn_t insn;
- /* The following field value is the next arc output from the same
- state. */
- arc_t next_out_arc;
- /* List of arcs marked given insn is formed with the following
- field. The field is used in transformation NDFA -> DFA. */
- arc_t next_arc_marked_by_insn;
- };
- /* The following node type describes a deterministic alternative in
- non-deterministic state which characterizes cpu unit reservations
- of automaton insn or which is part of NDFA. */
- struct alt_state
- {
- /* The following field is a deterministic state which characterizes
- unit reservations of the instruction. */
- state_t state;
- /* The following field refers to the next state which characterizes
- unit reservations of the instruction. */
- alt_state_t next_alt_state;
- /* The following field refers to the next state in sorted list. */
- alt_state_t next_sorted_alt_state;
- };
- /* The following node type describes insn of automaton. They are
- labels of FA arcs. */
- struct ainsn
- {
- /* The following field value is the corresponding insn declaration
- of description. */
- struct insn_reserv_decl *insn_reserv_decl;
- /* The following field value is the next insn declaration for an
- automaton. */
- ainsn_t next_ainsn;
- /* The following field is states which characterize automaton unit
- reservations of the instruction. The value can be NULL only if it
- is special insn `cycle advancing'. */
- alt_state_t alt_states;
- /* The following field is sorted list of states which characterize
- automaton unit reservations of the instruction. The value can be
- NULL only if it is special insn `cycle advancing'. */
- alt_state_t sorted_alt_states;
- /* The following field refers the next automaton insn with
- the same reservations. */
- ainsn_t next_same_reservs_insn;
- /* The following field is flag of the first automaton insn with the
- same reservations in the declaration list. Only arcs marked such
- insn is present in the automaton. This significantly decreases
- memory requirements especially when several automata are
- formed. */
- char first_insn_with_same_reservs;
- /* The following member has nonzero value if there is arc from state of
- the automaton marked by the ainsn. */
- char arc_exists_p;
- /* Cyclic list of insns of an equivalence class is formed with the
- aid of the following field. */
- ainsn_t next_equiv_class_insn;
- /* The following field value is nonzero if the insn declaration is
- the first insn declaration with given equivalence number. */
- char first_ainsn_with_given_equivalence_num;
- /* The following field is number of class of equivalence of insns.
- It is necessary because many insns may be equivalent with the
- point of view of pipeline hazards. */
- int insn_equiv_class_num;
- /* The following member value is TRUE if there is an arc in the
- automaton marked by the insn into another state. In other
- words, the insn can change the state of the automaton. */
- int important_p;
- };
- /* The following describes an automaton for PHR. */
- struct automaton
- {
- /* The following field value is the list of insn declarations for
- given automaton. */
- ainsn_t ainsn_list;
- /* Pointers to the ainsns corresponding to the special reservations. */
- ainsn_t advance_ainsn, collapse_ainsn;
- /* The following field value is the corresponding automaton
- declaration. This field is not NULL only if the automatic
- partition on automata is not used. */
- struct automaton_decl *corresponding_automaton_decl;
- /* The following field value is the next automaton. */
- automaton_t next_automaton;
- /* The following field is start state of FA. There are not unit
- reservations in the state. */
- state_t start_state;
- /* The following field value is number of equivalence classes of
- insns (see field `insn_equiv_class_num' in
- `insn_reserv_decl'). */
- int insn_equiv_classes_num;
- /* The following field value is number of states of final DFA. */
- int achieved_states_num;
- /* The following field value is the order number (0, 1, ...) of
- given automaton. */
- int automaton_order_num;
- /* The following fields contain statistics information about
- building automaton. */
- int NDFA_states_num, DFA_states_num;
- /* The following field value is defined only if minimization of DFA
- is used. */
- int minimal_DFA_states_num;
- int NDFA_arcs_num, DFA_arcs_num;
- /* The following field value is defined only if minimization of DFA
- is used. */
- int minimal_DFA_arcs_num;
- /* The following member refers for two table state x ainsn -> int.
- ??? Above sentence is incomprehensible. */
- state_ainsn_table_t trans_table;
- /* The following member value is maximal value of min issue delay
- for insns of the automaton. */
- int max_min_delay;
- /* Usually min issue delay is small and we can place several (2, 4,
- 8) elements in one vector element. So the compression factor can
- be 1 (no compression), 2, 4, 8. */
- int min_issue_delay_table_compression_factor;
- /* Total number of locked states in this automaton. */
- int locked_states;
- };
- /* The following is the element of the list of automata. */
- struct automata_list_el
- {
- /* The automaton itself. */
- automaton_t automaton;
- /* The next automata set element. */
- automata_list_el_t next_automata_list_el;
- };
- /* The following structure describes a table state X ainsn -> int(>= 0). */
- struct state_ainsn_table
- {
- /* Automaton to which given table belongs. */
- automaton_t automaton;
- /* The following tree vectors for comb vector implementation of the
- table. */
- vla_hwint_t comb_vect;
- vla_hwint_t check_vect;
- vla_hwint_t base_vect;
- /* This is simple implementation of the table. */
- vla_hwint_t full_vect;
- /* Minimal and maximal values of the previous vectors. */
- int min_comb_vect_el_value, max_comb_vect_el_value;
- int min_base_vect_el_value, max_base_vect_el_value;
- };
- /* Macros to access members of unions. Use only them for access to
- union members of declarations and regexps. */
- #if defined ENABLE_CHECKING && (GCC_VERSION >= 2007)
- #define DECL_UNIT(d) __extension__ \
- (({ __typeof (d) const _decl = (d); \
- if (_decl->mode != dm_unit) \
- decl_mode_check_failed (_decl->mode, "dm_unit", \
- __FILE__, __LINE__, __FUNCTION__); \
- &(_decl)->decl.unit; }))
- #define DECL_BYPASS(d) __extension__ \
- (({ __typeof (d) const _decl = (d); \
- if (_decl->mode != dm_bypass) \
- decl_mode_check_failed (_decl->mode, "dm_bypass", \
- __FILE__, __LINE__, __FUNCTION__); \
- &(_decl)->decl.bypass; }))
- #define DECL_AUTOMATON(d) __extension__ \
- (({ __typeof (d) const _decl = (d); \
- if (_decl->mode != dm_automaton) \
- decl_mode_check_failed (_decl->mode, "dm_automaton", \
- __FILE__, __LINE__, __FUNCTION__); \
- &(_decl)->decl.automaton; }))
- #define DECL_EXCL(d) __extension__ \
- (({ __typeof (d) const _decl = (d); \
- if (_decl->mode != dm_excl) \
- decl_mode_check_failed (_decl->mode, "dm_excl", \
- __FILE__, __LINE__, __FUNCTION__); \
- &(_decl)->decl.excl; }))
- #define DECL_PRESENCE(d) __extension__ \
- (({ __typeof (d) const _decl = (d); \
- if (_decl->mode != dm_presence) \
- decl_mode_check_failed (_decl->mode, "dm_presence", \
- __FILE__, __LINE__, __FUNCTION__); \
- &(_decl)->decl.presence; }))
- #define DECL_ABSENCE(d) __extension__ \
- (({ __typeof (d) const _decl = (d); \
- if (_decl->mode != dm_absence) \
- decl_mode_check_failed (_decl->mode, "dm_absence", \
- __FILE__, __LINE__, __FUNCTION__); \
- &(_decl)->decl.absence; }))
- #define DECL_RESERV(d) __extension__ \
- (({ __typeof (d) const _decl = (d); \
- if (_decl->mode != dm_reserv) \
- decl_mode_check_failed (_decl->mode, "dm_reserv", \
- __FILE__, __LINE__, __FUNCTION__); \
- &(_decl)->decl.reserv; }))
- #define DECL_INSN_RESERV(d) __extension__ \
- (({ __typeof (d) const _decl = (d); \
- if (_decl->mode != dm_insn_reserv) \
- decl_mode_check_failed (_decl->mode, "dm_insn_reserv", \
- __FILE__, __LINE__, __FUNCTION__); \
- &(_decl)->decl.insn_reserv; }))
- static const char *decl_name (enum decl_mode);
- static void decl_mode_check_failed (enum decl_mode, const char *,
- const char *, int, const char *)
- ATTRIBUTE_NORETURN;
- /* Return string representation of declaration mode MODE. */
- static const char *
- decl_name (enum decl_mode mode)
- {
- static char str [100];
- if (mode == dm_unit)
- return "dm_unit";
- else if (mode == dm_bypass)
- return "dm_bypass";
- else if (mode == dm_automaton)
- return "dm_automaton";
- else if (mode == dm_excl)
- return "dm_excl";
- else if (mode == dm_presence)
- return "dm_presence";
- else if (mode == dm_absence)
- return "dm_absence";
- else if (mode == dm_reserv)
- return "dm_reserv";
- else if (mode == dm_insn_reserv)
- return "dm_insn_reserv";
- else
- sprintf (str, "unknown (%d)", (int) mode);
- return str;
- }
- /* The function prints message about unexpected declaration and finish
- the program. */
- static void
- decl_mode_check_failed (enum decl_mode mode, const char *expected_mode_str,
- const char *file, int line, const char *func)
- {
- fprintf
- (stderr,
- "\n%s: %d: error in %s: DECL check: expected decl %s, have %s\n",
- file, line, func, expected_mode_str, decl_name (mode));
- exit (1);
- }
- #define REGEXP_UNIT(r) __extension__ \
- (({ struct regexp *const _regexp = (r); \
- if (_regexp->mode != rm_unit) \
- regexp_mode_check_failed (_regexp->mode, "rm_unit", \
- __FILE__, __LINE__, __FUNCTION__); \
- &(_regexp)->regexp.unit; }))
- #define REGEXP_RESERV(r) __extension__ \
- (({ struct regexp *const _regexp = (r); \
- if (_regexp->mode != rm_reserv) \
- regexp_mode_check_failed (_regexp->mode, "rm_reserv", \
- __FILE__, __LINE__, __FUNCTION__); \
- &(_regexp)->regexp.reserv; }))
- #define REGEXP_SEQUENCE(r) __extension__ \
- (({ struct regexp *const _regexp = (r); \
- if (_regexp->mode != rm_sequence) \
- regexp_mode_check_failed (_regexp->mode, "rm_sequence", \
- __FILE__, __LINE__, __FUNCTION__); \
- &(_regexp)->regexp.sequence; }))
- #define REGEXP_REPEAT(r) __extension__ \
- (({ struct regexp *const _regexp = (r); \
- if (_regexp->mode != rm_repeat) \
- regexp_mode_check_failed (_regexp->mode, "rm_repeat", \
- __FILE__, __LINE__, __FUNCTION__); \
- &(_regexp)->regexp.repeat; }))
- #define REGEXP_ALLOF(r) __extension__ \
- (({ struct regexp *const _regexp = (r); \
- if (_regexp->mode != rm_allof) \
- regexp_mode_check_failed (_regexp->mode, "rm_allof", \
- __FILE__, __LINE__, __FUNCTION__); \
- &(_regexp)->regexp.allof; }))
- #define REGEXP_ONEOF(r) __extension__ \
- (({ struct regexp *const _regexp = (r); \
- if (_regexp->mode != rm_oneof) \
- regexp_mode_check_failed (_regexp->mode, "rm_oneof", \
- __FILE__, __LINE__, __FUNCTION__); \
- &(_regexp)->regexp.oneof; }))
- static const char *regexp_name (enum regexp_mode);
- static void regexp_mode_check_failed (enum regexp_mode, const char *,
- const char *, int,
- const char *) ATTRIBUTE_NORETURN;
- /* Return string representation of regexp mode MODE. */
- static const char *
- regexp_name (enum regexp_mode mode)
- {
- switch (mode)
- {
- case rm_unit:
- return "rm_unit";
- case rm_reserv:
- return "rm_reserv";
- case rm_nothing:
- return "rm_nothing";
- case rm_sequence:
- return "rm_sequence";
- case rm_repeat:
- return "rm_repeat";
- case rm_allof:
- return "rm_allof";
- case rm_oneof:
- return "rm_oneof";
- default:
- gcc_unreachable ();
- }
- }
- /* The function prints message about unexpected regexp and finish the
- program. */
- static void
- regexp_mode_check_failed (enum regexp_mode mode,
- const char *expected_mode_str,
- const char *file, int line, const char *func)
- {
- fprintf
- (stderr,
- "\n%s: %d: error in %s: REGEXP check: expected decl %s, have %s\n",
- file, line, func, expected_mode_str, regexp_name (mode));
- exit (1);
- }
- #else /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
- #define DECL_UNIT(d) (&(d)->decl.unit)
- #define DECL_BYPASS(d) (&(d)->decl.bypass)
- #define DECL_AUTOMATON(d) (&(d)->decl.automaton)
- #define DECL_EXCL(d) (&(d)->decl.excl)
- #define DECL_PRESENCE(d) (&(d)->decl.presence)
- #define DECL_ABSENCE(d) (&(d)->decl.absence)
- #define DECL_RESERV(d) (&(d)->decl.reserv)
- #define DECL_INSN_RESERV(d) (&(d)->decl.insn_reserv)
- #define REGEXP_UNIT(r) (&(r)->regexp.unit)
- #define REGEXP_RESERV(r) (&(r)->regexp.reserv)
- #define REGEXP_SEQUENCE(r) (&(r)->regexp.sequence)
- #define REGEXP_REPEAT(r) (&(r)->regexp.repeat)
- #define REGEXP_ALLOF(r) (&(r)->regexp.allof)
- #define REGEXP_ONEOF(r) (&(r)->regexp.oneof)
- #endif /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
- #define XCREATENODE(T) ((T *) create_node (sizeof (T)))
- #define XCREATENODEVEC(T, N) ((T *) create_node (sizeof (T) * (N)))
- #define XCREATENODEVAR(T, S) ((T *) create_node ((S)))
- #define XCOPYNODE(T, P) ((T *) copy_node ((P), sizeof (T)))
- #define XCOPYNODEVEC(T, P, N) ((T *) copy_node ((P), sizeof (T) * (N)))
- #define XCOPYNODEVAR(T, P, S) ((T *) copy_node ((P), (S)))
- /* Create IR structure (node). */
- static void *
- create_node (size_t size)
- {
- void *result;
- obstack_blank (&irp, size);
- result = obstack_base (&irp);
- obstack_finish (&irp);
- /* Default values of members are NULL and zero. */
- memset (result, 0, size);
- return result;
- }
- /* Copy IR structure (node). */
- static void *
- copy_node (const void *from, size_t size)
- {
- void *const result = create_node (size);
- memcpy (result, from, size);
- return result;
- }
- /* The function checks that NAME does not contain quotes (`"'). */
- static const char *
- check_name (const char * name, pos_t pos ATTRIBUTE_UNUSED)
- {
- const char *str;
- for (str = name; *str != '\0'; str++)
- if (*str == '\"')
- error ("Name `%s' contains quotes", name);
- return name;
- }
- /* Pointers to all declarations during IR generation are stored in the
- following. */
- static vec<decl_t> decls;
- /* Given a pointer to a (char *) and a separator, return an alloc'ed
- string containing the next separated element, taking parentheses
- into account if PAR_FLAG has nonzero value. Advance the pointer to
- after the string scanned, or the end-of-string. Return NULL if at
- end of string. */
- static char *
- next_sep_el (const char **pstr, int sep, int par_flag)
- {
- char *out_str;
- const char *p;
- int pars_num;
- int n_spaces;
- /* Remove leading whitespaces. */
- while (ISSPACE ((int) **pstr))
- (*pstr)++;
- if (**pstr == '\0')
- return NULL;
- n_spaces = 0;
- for (pars_num = 0, p = *pstr; *p != '\0'; p++)
- {
- if (par_flag && *p == '(')
- pars_num++;
- else if (par_flag && *p == ')')
- pars_num--;
- else if (pars_num == 0 && *p == sep)
- break;
- if (pars_num == 0 && ISSPACE ((int) *p))
- n_spaces++;
- else
- {
- for (; n_spaces != 0; n_spaces--)
- obstack_1grow (&irp, p [-n_spaces]);
- obstack_1grow (&irp, *p);
- }
- }
- obstack_1grow (&irp, '\0');
- out_str = (char *) obstack_base (&irp);
- obstack_finish (&irp);
- *pstr = p;
- if (**pstr == sep)
- (*pstr)++;
- return out_str;
- }
- /* Given a string and a separator, return the number of separated
- elements in it, taking parentheses into account if PAR_FLAG has
- nonzero value. Return 0 for the null string, -1 if parentheses is
- not balanced. */
- static int
- n_sep_els (const char *s, int sep, int par_flag)
- {
- int n;
- int pars_num;
- if (*s == '\0')
- return 0;
- for (pars_num = 0, n = 1; *s; s++)
- if (par_flag && *s == '(')
- pars_num++;
- else if (par_flag && *s == ')')
- pars_num--;
- else if (pars_num == 0 && *s == sep)
- n++;
- return (pars_num != 0 ? -1 : n);
- }
- /* Given a string and a separator, return vector of strings which are
- elements in the string and number of elements through els_num.
- Take parentheses into account if PAREN_P has nonzero value. The
- function also inserts the end marker NULL at the end of vector.
- Return 0 for the null string, -1 if parentheses are not balanced. */
- static char **
- get_str_vect (const char *str, int *els_num, int sep, int paren_p)
- {
- int i;
- char **vect;
- const char **pstr;
- char *trail;
- *els_num = n_sep_els (str, sep, paren_p);
- if (*els_num <= 0)
- return NULL;
- obstack_blank (&irp, sizeof (char *) * (*els_num + 1));
- vect = (char **) obstack_base (&irp);
- obstack_finish (&irp);
- pstr = &str;
- for (i = 0; i < *els_num; i++)
- vect [i] = next_sep_el (pstr, sep, paren_p);
- trail = next_sep_el (pstr, sep, paren_p);
- gcc_assert (!trail);
- vect [i] = NULL;
- return vect;
- }
- /* Process a DEFINE_CPU_UNIT.
- This gives information about a unit contained in CPU. We fill a
- struct unit_decl with information used later by `expand_automata'. */
- static void
- gen_cpu_unit (rtx def)
- {
- decl_t decl;
- char **str_cpu_units;
- int vect_length;
- int i;
- str_cpu_units = get_str_vect (XSTR (def, 0), &vect_length, ',', FALSE);
- if (str_cpu_units == NULL)
- fatal ("invalid string `%s' in define_cpu_unit", XSTR (def, 0));
- for (i = 0; i < vect_length; i++)
- {
- decl = XCREATENODE (struct decl);
- decl->mode = dm_unit;
- decl->pos = 0;
- DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
- DECL_UNIT (decl)->automaton_name = XSTR (def, 1);
- DECL_UNIT (decl)->query_p = 0;
- DECL_UNIT (decl)->min_occ_cycle_num = -1;
- DECL_UNIT (decl)->in_set_p = 0;
- decls.safe_push (decl);
- }
- }
- /* Process a DEFINE_QUERY_CPU_UNIT.
- This gives information about a unit contained in CPU. We fill a
- struct unit_decl with information used later by `expand_automata'. */
- static void
- gen_query_cpu_unit (rtx def)
- {
- decl_t decl;
- char **str_cpu_units;
- int vect_length;
- int i;
- str_cpu_units = get_str_vect (XSTR (def, 0), &vect_length, ',',
- FALSE);
- if (str_cpu_units == NULL)
- fatal ("invalid string `%s' in define_query_cpu_unit", XSTR (def, 0));
- for (i = 0; i < vect_length; i++)
- {
- decl = XCREATENODE (struct decl);
- decl->mode = dm_unit;
- decl->pos = 0;
- DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
- DECL_UNIT (decl)->automaton_name = XSTR (def, 1);
- DECL_UNIT (decl)->query_p = 1;
- decls.safe_push (decl);
- }
- }
- /* Process a DEFINE_BYPASS.
- This gives information about a unit contained in the CPU. We fill
- in a struct bypass_decl with information used later by
- `expand_automata'. */
- static void
- gen_bypass (rtx def)
- {
- decl_t decl;
- char **out_patterns;
- int out_length;
- char **in_patterns;
- int in_length;
- int i, j;
- out_patterns = get_str_vect (XSTR (def, 1), &out_length, ',', FALSE);
- if (out_patterns == NULL)
- fatal ("invalid string `%s' in define_bypass", XSTR (def, 1));
- in_patterns = get_str_vect (XSTR (def, 2), &in_length, ',', FALSE);
- if (in_patterns == NULL)
- fatal ("invalid string `%s' in define_bypass", XSTR (def, 2));
- for (i = 0; i < out_length; i++)
- for (j = 0; j < in_length; j++)
- {
- decl = XCREATENODE (struct decl);
- decl->mode = dm_bypass;
- decl->pos = 0;
- DECL_BYPASS (decl)->latency = XINT (def, 0);
- DECL_BYPASS (decl)->out_pattern = out_patterns[i];
- DECL_BYPASS (decl)->in_pattern = in_patterns[j];
- DECL_BYPASS (decl)->bypass_guard_name = XSTR (def, 3);
- decls.safe_push (decl);
- }
- }
- /* Process an EXCLUSION_SET.
- This gives information about a cpu unit conflicts. We fill a
- struct excl_rel_decl (excl) with information used later by
- `expand_automata'. */
- static void
- gen_excl_set (rtx def)
- {
- decl_t decl;
- char **first_str_cpu_units;
- char **second_str_cpu_units;
- int first_vect_length;
- int length;
- int i;
- first_str_cpu_units
- = get_str_vect (XSTR (def, 0), &first_vect_length, ',', FALSE);
- if (first_str_cpu_units == NULL)
- fatal ("invalid first string `%s' in exclusion_set", XSTR (def, 0));
- second_str_cpu_units = get_str_vect (XSTR (def, 1), &length, ',',
- FALSE);
- if (second_str_cpu_units == NULL)
- fatal ("invalid second string `%s' in exclusion_set", XSTR (def, 1));
- length += first_vect_length;
- decl = XCREATENODEVAR (struct decl, sizeof (struct decl) + (length - 1) * sizeof (char *));
- decl->mode = dm_excl;
- decl->pos = 0;
- DECL_EXCL (decl)->all_names_num = length;
- DECL_EXCL (decl)->first_list_length = first_vect_length;
- for (i = 0; i < length; i++)
- if (i < first_vect_length)
- DECL_EXCL (decl)->names [i] = first_str_cpu_units [i];
- else
- DECL_EXCL (decl)->names [i]
- = second_str_cpu_units [i - first_vect_length];
- decls.safe_push (decl);
- }
- /* Process a PRESENCE_SET, a FINAL_PRESENCE_SET, an ABSENCE_SET,
- FINAL_ABSENCE_SET (it is depended on PRESENCE_P and FINAL_P).
- This gives information about a cpu unit reservation requirements.
- We fill a struct unit_pattern_rel_decl with information used later
- by `expand_automata'. */
- static void
- gen_presence_absence_set (rtx def, int presence_p, int final_p)
- {
- decl_t decl;
- char **str_cpu_units;
- char **str_pattern_lists;
- char ***str_patterns;
- int cpu_units_length;
- int length;
- int patterns_length;
- int i;
- str_cpu_units = get_str_vect (XSTR (def, 0), &cpu_units_length, ',',
- FALSE);
- if (str_cpu_units == NULL)
- fatal ((presence_p
- ? (final_p
- ? "invalid first string `%s' in final_presence_set"
- : "invalid first string `%s' in presence_set")
- : (final_p
- ? "invalid first string `%s' in final_absence_set"
- : "invalid first string `%s' in absence_set")),
- XSTR (def, 0));
- str_pattern_lists = get_str_vect (XSTR (def, 1),
- &patterns_length, ',', FALSE);
- if (str_pattern_lists == NULL)
- fatal ((presence_p
- ? (final_p
- ? "invalid second string `%s' in final_presence_set"
- : "invalid second string `%s' in presence_set")
- : (final_p
- ? "invalid second string `%s' in final_absence_set"
- : "invalid second string `%s' in absence_set")), XSTR (def, 1));
- str_patterns = XOBNEWVEC (&irp, char **, patterns_length);
- for (i = 0; i < patterns_length; i++)
- {
- str_patterns [i] = get_str_vect (str_pattern_lists [i],
- &length, ' ', FALSE);
- gcc_assert (str_patterns [i]);
- }
- decl = XCREATENODE (struct decl);
- decl->pos = 0;
- if (presence_p)
- {
- decl->mode = dm_presence;
- DECL_PRESENCE (decl)->names_num = cpu_units_length;
- DECL_PRESENCE (decl)->names = str_cpu_units;
- DECL_PRESENCE (decl)->patterns = str_patterns;
- DECL_PRESENCE (decl)->patterns_num = patterns_length;
- DECL_PRESENCE (decl)->final_p = final_p;
- }
- else
- {
- decl->mode = dm_absence;
- DECL_ABSENCE (decl)->names_num = cpu_units_length;
- DECL_ABSENCE (decl)->names = str_cpu_units;
- DECL_ABSENCE (decl)->patterns = str_patterns;
- DECL_ABSENCE (decl)->patterns_num = patterns_length;
- DECL_ABSENCE (decl)->final_p = final_p;
- }
- decls.safe_push (decl);
- }
- /* Process a PRESENCE_SET.
- This gives information about a cpu unit reservation requirements.
- We fill a struct unit_pattern_rel_decl (presence) with information
- used later by `expand_automata'. */
- static void
- gen_presence_set (rtx def)
- {
- gen_presence_absence_set (def, TRUE, FALSE);
- }
- /* Process a FINAL_PRESENCE_SET.
- This gives information about a cpu unit reservation requirements.
- We fill a struct unit_pattern_rel_decl (presence) with information
- used later by `expand_automata'. */
- static void
- gen_final_presence_set (rtx def)
- {
- gen_presence_absence_set (def, TRUE, TRUE);
- }
- /* Process an ABSENCE_SET.
- This gives information about a cpu unit reservation requirements.
- We fill a struct unit_pattern_rel_decl (absence) with information
- used later by `expand_automata'. */
- static void
- gen_absence_set (rtx def)
- {
- gen_presence_absence_set (def, FALSE, FALSE);
- }
- /* Process a FINAL_ABSENCE_SET.
- This gives information about a cpu unit reservation requirements.
- We fill a struct unit_pattern_rel_decl (absence) with information
- used later by `expand_automata'. */
- static void
- gen_final_absence_set (rtx def)
- {
- gen_presence_absence_set (def, FALSE, TRUE);
- }
- /* Process a DEFINE_AUTOMATON.
- This gives information about a finite state automaton used for
- recognizing pipeline hazards. We fill a struct automaton_decl
- with information used later by `expand_automata'. */
- static void
- gen_automaton (rtx def)
- {
- decl_t decl;
- char **str_automata;
- int vect_length;
- int i;
- str_automata = get_str_vect (XSTR (def, 0), &vect_length, ',', FALSE);
- if (str_automata == NULL)
- fatal ("invalid string `%s' in define_automaton", XSTR (def, 0));
- for (i = 0; i < vect_length; i++)
- {
- decl = XCREATENODE (struct decl);
- decl->mode = dm_automaton;
- decl->pos = 0;
- DECL_AUTOMATON (decl)->name = check_name (str_automata [i], decl->pos);
- decls.safe_push (decl);
- }
- }
- /* Process an AUTOMATA_OPTION.
- This gives information how to generate finite state automaton used
- for recognizing pipeline hazards. */
- static void
- gen_automata_option (rtx def)
- {
- if (strcmp (XSTR (def, 0), NO_MINIMIZATION_OPTION + 1) == 0)
- no_minimization_flag = 1;
- else if (strcmp (XSTR (def, 0), TIME_OPTION + 1) == 0)
- time_flag = 1;
- else if (strcmp (XSTR (def, 0), STATS_OPTION + 1) == 0)
- stats_flag = 1;
- else if (strcmp (XSTR (def, 0), V_OPTION + 1) == 0)
- v_flag = 1;
- else if (strcmp (XSTR (def, 0), W_OPTION + 1) == 0)
- w_flag = 1;
- else if (strcmp (XSTR (def, 0), NDFA_OPTION + 1) == 0)
- ndfa_flag = 1;
- else if (strcmp (XSTR (def, 0), COLLAPSE_OPTION + 1) == 0)
- collapse_flag = 1;
- else if (strcmp (XSTR (def, 0), NO_COMB_OPTION + 1) == 0)
- no_comb_flag = 1;
- else if (strcmp (XSTR (def, 0), PROGRESS_OPTION + 1) == 0)
- progress_flag = 1;
- else
- fatal ("invalid option `%s' in automata_option", XSTR (def, 0));
- }
- /* Name in reservation to denote absence reservation. */
- #define NOTHING_NAME "nothing"
- /* The following string contains original reservation string being
- parsed. */
- static const char *reserv_str;
- /* Parse an element in STR. */
- static regexp_t
- gen_regexp_el (const char *str)
- {
- regexp_t regexp;
- char *dstr;
- int len;
- if (*str == '(')
- {
- len = strlen (str);
- if (str [len - 1] != ')')
- fatal ("garbage after ) in reservation `%s'", reserv_str);
- dstr = XALLOCAVAR (char, len - 1);
- memcpy (dstr, str + 1, len - 2);
- dstr [len-2] = '\0';
- regexp = gen_regexp_sequence (dstr);
- }
- else if (strcmp (str, NOTHING_NAME) == 0)
- {
- regexp = XCREATENODE (struct regexp);
- regexp->mode = rm_nothing;
- }
- else
- {
- regexp = XCREATENODE (struct regexp);
- regexp->mode = rm_unit;
- REGEXP_UNIT (regexp)->name = str;
- }
- return regexp;
- }
- /* Parse construction `repeat' in STR. */
- static regexp_t
- gen_regexp_repeat (const char *str)
- {
- regexp_t regexp;
- regexp_t repeat;
- char **repeat_vect;
- int els_num;
- int i;
- repeat_vect = get_str_vect (str, &els_num, '*', TRUE);
- if (repeat_vect == NULL)
- fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
- if (els_num > 1)
- {
- regexp = gen_regexp_el (repeat_vect [0]);
- for (i = 1; i < els_num; i++)
- {
- repeat = XCREATENODE (struct regexp);
- repeat->mode = rm_repeat;
- REGEXP_REPEAT (repeat)->regexp = regexp;
- REGEXP_REPEAT (repeat)->repeat_num = atoi (repeat_vect [i]);
- if (REGEXP_REPEAT (repeat)->repeat_num <= 1)
- fatal ("repetition `%s' <= 1 in reservation `%s'",
- str, reserv_str);
- regexp = repeat;
- }
- return regexp;
- }
- else
- return gen_regexp_el (repeat_vect[0]);
- }
- /* Parse reservation STR which possibly contains separator '+'. */
- static regexp_t
- gen_regexp_allof (const char *str)
- {
- regexp_t allof;
- char **allof_vect;
- int els_num;
- int i;
- allof_vect = get_str_vect (str, &els_num, '+', TRUE);
- if (allof_vect == NULL)
- fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
- if (els_num > 1)
- {
- allof = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
- + sizeof (regexp_t) * (els_num - 1));
- allof->mode = rm_allof;
- REGEXP_ALLOF (allof)->regexps_num = els_num;
- for (i = 0; i < els_num; i++)
- REGEXP_ALLOF (allof)->regexps [i] = gen_regexp_repeat (allof_vect [i]);
- return allof;
- }
- else
- return gen_regexp_repeat (allof_vect[0]);
- }
- /* Parse reservation STR which possibly contains separator '|'. */
- static regexp_t
- gen_regexp_oneof (const char *str)
- {
- regexp_t oneof;
- char **oneof_vect;
- int els_num;
- int i;
- oneof_vect = get_str_vect (str, &els_num, '|', TRUE);
- if (oneof_vect == NULL)
- fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
- if (els_num > 1)
- {
- oneof = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
- + sizeof (regexp_t) * (els_num - 1));
- oneof->mode = rm_oneof;
- REGEXP_ONEOF (oneof)->regexps_num = els_num;
- for (i = 0; i < els_num; i++)
- REGEXP_ONEOF (oneof)->regexps [i] = gen_regexp_allof (oneof_vect [i]);
- return oneof;
- }
- else
- return gen_regexp_allof (oneof_vect[0]);
- }
- /* Parse reservation STR which possibly contains separator ','. */
- static regexp_t
- gen_regexp_sequence (const char *str)
- {
- regexp_t sequence;
- char **sequence_vect;
- int els_num;
- int i;
- sequence_vect = get_str_vect (str, &els_num, ',', TRUE);
- if (els_num == -1)
- fatal ("unbalanced parentheses in reservation `%s'", str);
- if (sequence_vect == NULL)
- fatal ("invalid reservation `%s'", str);
- if (els_num > 1)
- {
- sequence = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
- + sizeof (regexp_t) * (els_num - 1));
- sequence->mode = rm_sequence;
- REGEXP_SEQUENCE (sequence)->regexps_num = els_num;
- for (i = 0; i < els_num; i++)
- REGEXP_SEQUENCE (sequence)->regexps [i]
- = gen_regexp_oneof (sequence_vect [i]);
- return sequence;
- }
- else
- return gen_regexp_oneof (sequence_vect[0]);
- }
- /* Parse construction reservation STR. */
- static regexp_t
- gen_regexp (const char *str)
- {
- reserv_str = str;
- return gen_regexp_sequence (str);
- }
- /* Process a DEFINE_RESERVATION.
- This gives information about a reservation of cpu units. We fill
- in a struct reserv_decl with information used later by
- `expand_automata'. */
- static void
- gen_reserv (rtx def)
- {
- decl_t decl;
- decl = XCREATENODE (struct decl);
- decl->mode = dm_reserv;
- decl->pos = 0;
- DECL_RESERV (decl)->name = check_name (XSTR (def, 0), decl->pos);
- DECL_RESERV (decl)->regexp = gen_regexp (XSTR (def, 1));
- decls.safe_push (decl);
- }
- /* Process a DEFINE_INSN_RESERVATION.
- This gives information about the reservation of cpu units by an
- insn. We fill a struct insn_reserv_decl with information used
- later by `expand_automata'. */
- static void
- gen_insn_reserv (rtx def)
- {
- decl_t decl;
- decl = XCREATENODE (struct decl);
- decl->mode = dm_insn_reserv;
- decl->pos = 0;
- DECL_INSN_RESERV (decl)->name
- = check_name (XSTR (def, 0), decl->pos);
- DECL_INSN_RESERV (decl)->default_latency = XINT (def, 1);
- DECL_INSN_RESERV (decl)->condexp = XEXP (def, 2);
- DECL_INSN_RESERV (decl)->regexp = gen_regexp (XSTR (def, 3));
- decls.safe_push (decl);
- }
- /* The function evaluates hash value (0..UINT_MAX) of string. */
- static unsigned
- string_hash (const char *string)
- {
- unsigned result, i;
- for (result = i = 0;*string++ != '\0'; i++)
- result += ((unsigned char) *string << (i % CHAR_BIT));
- return result;
- }
- /* This page contains abstract data `table of automaton declarations'.
- Elements of the table is nodes representing automaton declarations.
- Key of the table elements is name of given automaton. Remember
- that automaton names have own space. */
- /* The function evaluates hash value of an automaton declaration. The
- function is used by abstract data `hashtab'. The function returns
- hash value (0..UINT_MAX) of given automaton declaration. */
- static hashval_t
- automaton_decl_hash (const void *automaton_decl)
- {
- const_decl_t const decl = (const_decl_t) automaton_decl;
- gcc_assert (decl->mode != dm_automaton
- || DECL_AUTOMATON (decl)->name);
- return string_hash (DECL_AUTOMATON (decl)->name);
- }
- /* The function tests automaton declarations on equality of their
- keys. The function is used by abstract data `hashtab'. The
- function returns 1 if the declarations have the same key, 0
- otherwise. */
- static int
- automaton_decl_eq_p (const void* automaton_decl_1,
- const void* automaton_decl_2)
- {
- const_decl_t const decl1 = (const_decl_t) automaton_decl_1;
- const_decl_t const decl2 = (const_decl_t) automaton_decl_2;
- gcc_assert (decl1->mode == dm_automaton
- && DECL_AUTOMATON (decl1)->name
- && decl2->mode == dm_automaton
- && DECL_AUTOMATON (decl2)->name);
- return strcmp (DECL_AUTOMATON (decl1)->name,
- DECL_AUTOMATON (decl2)->name) == 0;
- }
- /* The automaton declaration table itself is represented by the
- following variable. */
- static htab_t automaton_decl_table;
- /* The function inserts automaton declaration into the table. The
- function does nothing if an automaton declaration with the same key
- exists already in the table. The function returns automaton
- declaration node in the table with the same key as given automaton
- declaration node. */
- static decl_t
- insert_automaton_decl (decl_t automaton_decl)
- {
- void **entry_ptr;
- entry_ptr = htab_find_slot (automaton_decl_table, automaton_decl, INSERT);
- if (*entry_ptr == NULL)
- *entry_ptr = (void *) automaton_decl;
- return (decl_t) *entry_ptr;
- }
- /* The following variable value is node representing automaton
- declaration. The node used for searching automaton declaration
- with given name. */
- static struct decl work_automaton_decl;
- /* The function searches for automaton declaration in the table with
- the same key as node representing name of the automaton
- declaration. The function returns node found in the table, NULL if
- such node does not exist in the table. */
- static decl_t
- find_automaton_decl (const char *name)
- {
- void *entry;
- work_automaton_decl.mode = dm_automaton;
- DECL_AUTOMATON (&work_automaton_decl)->name = name;
- entry = htab_find (automaton_decl_table, &work_automaton_decl);
- return (decl_t) entry;
- }
- /* The function creates empty automaton declaration table and node
- representing automaton declaration and used for searching automaton
- declaration with given name. The function must be called only once
- before any work with the automaton declaration table. */
- static void
- initiate_automaton_decl_table (void)
- {
- work_automaton_decl.mode = dm_automaton;
- automaton_decl_table = htab_create (10, automaton_decl_hash,
- automaton_decl_eq_p, (htab_del) 0);
- }
- /* The function deletes the automaton declaration table. Only call of
- function `initiate_automaton_decl_table' is possible immediately
- after this function call. */
- static void
- finish_automaton_decl_table (void)
- {
- htab_delete (automaton_decl_table);
- }
- /* This page contains abstract data `table of insn declarations'.
- Elements of the table is nodes representing insn declarations. Key
- of the table elements is name of given insn (in corresponding
- define_insn_reservation). Remember that insn names have own
- space. */
- /* The function evaluates hash value of an insn declaration. The
- function is used by abstract data `hashtab'. The function returns
- hash value (0..UINT_MAX) of given insn declaration. */
- static hashval_t
- insn_decl_hash (const void *insn_decl)
- {
- const_decl_t const decl = (const_decl_t) insn_decl;
- gcc_assert (decl->mode == dm_insn_reserv
- && DECL_INSN_RESERV (decl)->name);
- return string_hash (DECL_INSN_RESERV (decl)->name);
- }
- /* The function tests insn declarations on equality of their keys.
- The function is used by abstract data `hashtab'. The function
- returns 1 if declarations have the same key, 0 otherwise. */
- static int
- insn_decl_eq_p (const void *insn_decl_1, const void *insn_decl_2)
- {
- const_decl_t const decl1 = (const_decl_t) insn_decl_1;
- const_decl_t const decl2 = (const_decl_t) insn_decl_2;
- gcc_assert (decl1->mode == dm_insn_reserv
- && DECL_INSN_RESERV (decl1)->name
- && decl2->mode == dm_insn_reserv
- && DECL_INSN_RESERV (decl2)->name);
- return strcmp (DECL_INSN_RESERV (decl1)->name,
- DECL_INSN_RESERV (decl2)->name) == 0;
- }
- /* The insn declaration table itself is represented by the following
- variable. The table does not contain insn reservation
- declarations. */
- static htab_t insn_decl_table;
- /* The function inserts insn declaration into the table. The function
- does nothing if an insn declaration with the same key exists
- already in the table. The function returns insn declaration node
- in the table with the same key as given insn declaration node. */
- static decl_t
- insert_insn_decl (decl_t insn_decl)
- {
- void **entry_ptr;
- entry_ptr = htab_find_slot (insn_decl_table, insn_decl, INSERT);
- if (*entry_ptr == NULL)
- *entry_ptr = (void *) insn_decl;
- return (decl_t) *entry_ptr;
- }
- /* The following variable value is node representing insn reservation
- declaration. The node used for searching insn reservation
- declaration with given name. */
- static struct decl work_insn_decl;
- /* The function searches for insn reservation declaration in the table
- with the same key as node representing name of the insn reservation
- declaration. The function returns node found in the table, NULL if
- such node does not exist in the table. */
- static decl_t
- find_insn_decl (const char *name)
- {
- void *entry;
- work_insn_decl.mode = dm_insn_reserv;
- DECL_INSN_RESERV (&work_insn_decl)->name = name;
- entry = htab_find (insn_decl_table, &work_insn_decl);
- return (decl_t) entry;
- }
- /* The function creates empty insn declaration table and node
- representing insn declaration and used for searching insn
- declaration with given name. The function must be called only once
- before any work with the insn declaration table. */
- static void
- initiate_insn_decl_table (void)
- {
- work_insn_decl.mode = dm_insn_reserv;
- insn_decl_table = htab_create (10, insn_decl_hash, insn_decl_eq_p,
- (htab_del) 0);
- }
- /* The function deletes the insn declaration table. Only call of
- function `initiate_insn_decl_table' is possible immediately after
- this function call. */
- static void
- finish_insn_decl_table (void)
- {
- htab_delete (insn_decl_table);
- }
- /* This page contains abstract data `table of declarations'. Elements
- of the table is nodes representing declarations (of units and
- reservations). Key of the table elements is names of given
- declarations. */
- /* The function evaluates hash value of a declaration. The function
- is used by abstract data `hashtab'. The function returns hash
- value (0..UINT_MAX) of given declaration. */
- static hashval_t
- decl_hash (const void *decl)
- {
- const_decl_t const d = (const_decl_t) decl;
- gcc_assert ((d->mode == dm_unit && DECL_UNIT (d)->name)
- || (d->mode == dm_reserv && DECL_RESERV (d)->name));
- return string_hash (d->mode == dm_unit
- ? DECL_UNIT (d)->name : DECL_RESERV (d)->name);
- }
- /* The function tests declarations on equality of their keys. The
- function is used by abstract data 'hashtab'. The function
- returns 1 if the declarations have the same key, 0 otherwise. */
- static int
- decl_eq_p (const void *decl_1, const void *decl_2)
- {
- const_decl_t const d1 = (const_decl_t) decl_1;
- const_decl_t const d2 = (const_decl_t) decl_2;
- gcc_assert ((d1->mode == dm_unit && DECL_UNIT (d1)->name)
- || (d1->mode == dm_reserv && DECL_RESERV (d1)->name));
- gcc_assert ((d2->mode == dm_unit && DECL_UNIT (d2)->name)
- || (d2->mode == dm_reserv && DECL_RESERV (d2)->name));
- return strcmp ((d1->mode == dm_unit
- ? DECL_UNIT (d1)->name : DECL_RESERV (d1)->name),
- (d2->mode == dm_unit
- ? DECL_UNIT (d2)->name : DECL_RESERV (d2)->name)) == 0;
- }
- /* The declaration table itself is represented by the following
- variable. */
- static htab_t decl_table;
- /* The function inserts declaration into the table. The function does
- nothing if a declaration with the same key exists already in the
- table. The function returns declaration node in the table with the
- same key as given declaration node. */
- static decl_t
- insert_decl (decl_t decl)
- {
- void **entry_ptr;
- entry_ptr = htab_find_slot (decl_table, decl, INSERT);
- if (*entry_ptr == NULL)
- *entry_ptr = (void *) decl;
- return (decl_t) *entry_ptr;
- }
- /* The following variable value is node representing declaration. The
- node used for searching declaration with given name. */
- static struct decl work_decl;
- /* The function searches for declaration in the table with the same
- key as node representing name of the declaration. The function
- returns node found in the table, NULL if such node does not exist
- in the table. */
- static decl_t
- find_decl (const char *name)
- {
- void *entry;
- work_decl.mode = dm_unit;
- DECL_UNIT (&work_decl)->name = name;
- entry = htab_find (decl_table, &work_decl);
- return (decl_t) entry;
- }
- /* The function creates empty declaration table and node representing
- declaration and used for searching declaration with given name.
- The function must be called only once before any work with the
- declaration table. */
- static void
- initiate_decl_table (void)
- {
- work_decl.mode = dm_unit;
- decl_table = htab_create (10, decl_hash, decl_eq_p, (htab_del) 0);
- }
- /* The function deletes the declaration table. Only call of function
- `initiate_declaration_table' is possible immediately after this
- function call. */
- static void
- finish_decl_table (void)
- {
- htab_delete (decl_table);
- }
- /* This page contains checker of pipeline hazard description. */
- /* Checking NAMES in an exclusion clause vector and returning formed
- unit_set_el_list. */
- static unit_set_el_t
- process_excls (char **names, int num, pos_t excl_pos ATTRIBUTE_UNUSED)
- {
- unit_set_el_t el_list;
- unit_set_el_t last_el;
- unit_set_el_t new_el;
- decl_t decl_in_table;
- int i;
- el_list = NULL;
- last_el = NULL;
- for (i = 0; i < num; i++)
- {
- decl_in_table = find_decl (names [i]);
- if (decl_in_table == NULL)
- error ("unit `%s' in exclusion is not declared", names [i]);
- else if (decl_in_table->mode != dm_unit)
- error ("`%s' in exclusion is not unit", names [i]);
- else
- {
- new_el = XCREATENODE (struct unit_set_el);
- new_el->unit_decl = DECL_UNIT (decl_in_table);
- new_el->next_unit_set_el = NULL;
- if (last_el == NULL)
- el_list = last_el = new_el;
- else
- {
- last_el->next_unit_set_el = new_el;
- last_el = last_el->next_unit_set_el;
- }
- }
- }
- return el_list;
- }
- /* The function adds each element from SOURCE_LIST to the exclusion
- list of the each element from DEST_LIST. Checking situation "unit
- excludes itself". */
- static void
- add_excls (unit_set_el_t dest_list, unit_set_el_t source_list,
- pos_t excl_pos ATTRIBUTE_UNUSED)
- {
- unit_set_el_t dst;
- unit_set_el_t src;
- unit_set_el_t curr_el;
- unit_set_el_t prev_el;
- unit_set_el_t copy;
- for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
- for (src = source_list; src != NULL; src = src->next_unit_set_el)
- {
- if (dst->unit_decl == src->unit_decl)
- {
- error ("unit `%s' excludes itself", src->unit_decl->name);
- continue;
- }
- if (dst->unit_decl->automaton_name != NULL
- && src->unit_decl->automaton_name != NULL
- && strcmp (dst->unit_decl->automaton_name,
- src->unit_decl->automaton_name) != 0)
- {
- error ("units `%s' and `%s' in exclusion set belong to different automata",
- src->unit_decl->name, dst->unit_decl->name);
- continue;
- }
- for (curr_el = dst->unit_decl->excl_list, prev_el = NULL;
- curr_el != NULL;
- prev_el = curr_el, curr_el = curr_el->next_unit_set_el)
- if (curr_el->unit_decl == src->unit_decl)
- break;
- if (curr_el == NULL)
- {
- /* Element not found - insert. */
- copy = XCOPYNODE (struct unit_set_el, src);
- copy->next_unit_set_el = NULL;
- if (prev_el == NULL)
- dst->unit_decl->excl_list = copy;
- else
- prev_el->next_unit_set_el = copy;
- }
- }
- }
- /* Checking NAMES in presence/absence clause and returning the
- formed unit_set_el_list. The function is called only after
- processing all exclusion sets. */
- static unit_set_el_t
- process_presence_absence_names (char **names, int num,
- pos_t req_pos ATTRIBUTE_UNUSED,
- int presence_p, int final_p)
- {
- unit_set_el_t el_list;
- unit_set_el_t last_el;
- unit_set_el_t new_el;
- decl_t decl_in_table;
- int i;
- el_list = NULL;
- last_el = NULL;
- for (i = 0; i < num; i++)
- {
- decl_in_table = find_decl (names [i]);
- if (decl_in_table == NULL)
- error ((presence_p
- ? (final_p
- ? "unit `%s' in final presence set is not declared"
- : "unit `%s' in presence set is not declared")
- : (final_p
- ? "unit `%s' in final absence set is not declared"
- : "unit `%s' in absence set is not declared")), names [i]);
- else if (decl_in_table->mode != dm_unit)
- error ((presence_p
- ? (final_p
- ? "`%s' in final presence set is not unit"
- : "`%s' in presence set is not unit")
- : (final_p
- ? "`%s' in final absence set is not unit"
- : "`%s' in absence set is not unit")), names [i]);
- else
- {
- new_el = XCREATENODE (struct unit_set_el);
- new_el->unit_decl = DECL_UNIT (decl_in_table);
- new_el->next_unit_set_el = NULL;
- if (last_el == NULL)
- el_list = last_el = new_el;
- else
- {
- last_el->next_unit_set_el = new_el;
- last_el = last_el->next_unit_set_el;
- }
- }
- }
- return el_list;
- }
- /* Checking NAMES in patterns of a presence/absence clause and
- returning the formed pattern_set_el_list. The function is called
- only after processing all exclusion sets. */
- static pattern_set_el_t
- process_presence_absence_patterns (char ***patterns, int num,
- pos_t req_pos ATTRIBUTE_UNUSED,
- int presence_p, int final_p)
- {
- pattern_set_el_t el_list;
- pattern_set_el_t last_el;
- pattern_set_el_t new_el;
- decl_t decl_in_table;
- int i, j;
- el_list = NULL;
- last_el = NULL;
- for (i = 0; i < num; i++)
- {
- for (j = 0; patterns [i] [j] != NULL; j++)
- ;
- new_el = XCREATENODEVAR (struct pattern_set_el,
- sizeof (struct pattern_set_el)
- + sizeof (struct unit_decl *) * j);
- new_el->unit_decls
- = (struct unit_decl **) ((char *) new_el
- + sizeof (struct pattern_set_el));
- new_el->next_pattern_set_el = NULL;
- if (last_el == NULL)
- el_list = last_el = new_el;
- else
- {
- last_el->next_pattern_set_el = new_el;
- last_el = last_el->next_pattern_set_el;
- }
- new_el->units_num = 0;
- for (j = 0; patterns [i] [j] != NULL; j++)
- {
- decl_in_table = find_decl (patterns [i] [j]);
- if (decl_in_table == NULL)
- error ((presence_p
- ? (final_p
- ? "unit `%s' in final presence set is not declared"
- : "unit `%s' in presence set is not declared")
- : (final_p
- ? "unit `%s' in final absence set is not declared"
- : "unit `%s' in absence set is not declared")),
- patterns [i] [j]);
- else if (decl_in_table->mode != dm_unit)
- error ((presence_p
- ? (final_p
- ? "`%s' in final presence set is not unit"
- : "`%s' in presence set is not unit")
- : (final_p
- ? "`%s' in final absence set is not unit"
- : "`%s' in absence set is not unit")),
- patterns [i] [j]);
- else
- {
- new_el->unit_decls [new_el->units_num]
- = DECL_UNIT (decl_in_table);
- new_el->units_num++;
- }
- }
- }
- return el_list;
- }
- /* The function adds each element from PATTERN_LIST to presence (if
- PRESENCE_P) or absence list of the each element from DEST_LIST.
- Checking situations "unit requires own absence", and "unit excludes
- and requires presence of ...", "unit requires absence and presence
- of ...", "units in (final) presence set belong to different
- automata", and "units in (final) absence set belong to different
- automata". Remember that we process absence sets only after all
- presence sets. */
- static void
- add_presence_absence (unit_set_el_t dest_list,
- pattern_set_el_t pattern_list,
- pos_t req_pos ATTRIBUTE_UNUSED,
- int presence_p, int final_p)
- {
- unit_set_el_t dst;
- pattern_set_el_t pat;
- struct unit_decl *unit;
- unit_set_el_t curr_excl_el;
- pattern_set_el_t curr_pat_el;
- pattern_set_el_t prev_el;
- pattern_set_el_t copy;
- int i;
- int no_error_flag;
- for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
- for (pat = pattern_list; pat != NULL; pat = pat->next_pattern_set_el)
- {
- for (i = 0; i < pat->units_num; i++)
- {
- unit = pat->unit_decls [i];
- if (dst->unit_decl == unit && pat->units_num == 1 && !presence_p)
- {
- error ("unit `%s' requires own absence", unit->name);
- continue;
- }
- if (dst->unit_decl->automaton_name != NULL
- && unit->automaton_name != NULL
- && strcmp (dst->unit_decl->automaton_name,
- unit->automaton_name) != 0)
- {
- error ((presence_p
- ? (final_p
- ? "units `%s' and `%s' in final presence set belong to different automata"
- : "units `%s' and `%s' in presence set belong to different automata")
- : (final_p
- ? "units `%s' and `%s' in final absence set belong to different automata"
- : "units `%s' and `%s' in absence set belong to different automata")),
- unit->name, dst->unit_decl->name);
- continue;
- }
- no_error_flag = 1;
- if (presence_p)
- for (curr_excl_el = dst->unit_decl->excl_list;
- curr_excl_el != NULL;
- curr_excl_el = curr_excl_el->next_unit_set_el)
- {
- if (unit == curr_excl_el->unit_decl && pat->units_num == 1)
- {
- if (!w_flag)
- {
- error ("unit `%s' excludes and requires presence of `%s'",
- dst->unit_decl->name, unit->name);
- no_error_flag = 0;
- }
- else
- warning ("unit `%s' excludes and requires presence of `%s'",
- dst->unit_decl->name, unit->name);
- }
- }
- else if (pat->units_num == 1)
- for (curr_pat_el = dst->unit_decl->presence_list;
- curr_pat_el != NULL;
- curr_pat_el = curr_pat_el->next_pattern_set_el)
- if (curr_pat_el->units_num == 1
- && unit == curr_pat_el->unit_decls [0])
- {
- if (!w_flag)
- {
- error ("unit `%s' requires absence and presence of `%s'",
- dst->unit_decl->name, unit->name);
- no_error_flag = 0;
- }
- else
- warning ("unit `%s' requires absence and presence of `%s'",
- dst->unit_decl->name, unit->name);
- }
- if (no_error_flag)
- {
- for (prev_el = (presence_p
- ? (final_p
- ? dst->unit_decl->final_presence_list
- : dst->unit_decl->presence_list)
- : (final_p
- ? dst->unit_decl->final_absence_list
- : dst->unit_decl->absence_list));
- prev_el != NULL && prev_el->next_pattern_set_el != NULL;
- prev_el = prev_el->next_pattern_set_el)
- ;
- copy = XCOPYNODE (struct pattern_set_el, pat);
- copy->next_pattern_set_el = NULL;
- if (prev_el == NULL)
- {
- if (presence_p)
- {
- if (final_p)
- dst->unit_decl->final_presence_list = copy;
- else
- dst->unit_decl->presence_list = copy;
- }
- else if (final_p)
- dst->unit_decl->final_absence_list = copy;
- else
- dst->unit_decl->absence_list = copy;
- }
- else
- prev_el->next_pattern_set_el = copy;
- }
- }
- }
- }
- /* The function inserts BYPASS in the list of bypasses of the
- corresponding output insn. The order of bypasses in the list is
- described in a comment for member `bypass_list' (see above). If
- there is already the same bypass in the list the function reports
- this and does nothing. */
- static void
- insert_bypass (struct bypass_decl *bypass)
- {
- struct bypass_decl *curr, *last;
- struct insn_reserv_decl *out_insn_reserv = bypass->out_insn_reserv;
- struct insn_reserv_decl *in_insn_reserv = bypass->in_insn_reserv;
- for (curr = out_insn_reserv->bypass_list, last = NULL;
- curr != NULL;
- last = curr, curr = curr->next)
- if (curr->in_insn_reserv == in_insn_reserv)
- {
- if ((bypass->bypass_guard_name != NULL
- && curr->bypass_guard_name != NULL
- && ! strcmp (bypass->bypass_guard_name, curr->bypass_guard_name))
- || bypass->bypass_guard_name == curr->bypass_guard_name)
- {
- if (bypass->bypass_guard_name == NULL)
- {
- if (!w_flag)
- error ("the same bypass `%s - %s' is already defined",
- bypass->out_pattern, bypass->in_pattern);
- else
- warning ("the same bypass `%s - %s' is already defined",
- bypass->out_pattern, bypass->in_pattern);
- }
- else if (!w_flag)
- error ("the same bypass `%s - %s' (guard %s) is already defined",
- bypass->out_pattern, bypass->in_pattern,
- bypass->bypass_guard_name);
- else
- warning
- ("the same bypass `%s - %s' (guard %s) is already defined",
- bypass->out_pattern, bypass->in_pattern,
- bypass->bypass_guard_name);
- return;
- }
- if (curr->bypass_guard_name == NULL)
- break;
- if (curr->next == NULL || curr->next->in_insn_reserv != in_insn_reserv)
- {
- last = curr;
- break;
- }
- }
- if (last == NULL)
- {
- bypass->next = out_insn_reserv->bypass_list;
- out_insn_reserv->bypass_list = bypass;
- }
- else
- {
- bypass->next = last->next;
- last->next = bypass;
- }
- }
- /* BYPASS is a define_bypass decl that includes glob pattern PATTERN.
- Call FN (BYPASS, INSN, DATA) for each matching instruction INSN. */
- static void
- for_each_matching_insn (decl_t bypass, const char *pattern,
- void (*fn) (decl_t, decl_t, void *), void *data)
- {
- decl_t insn_reserv;
- bool matched_p;
- int i;
- matched_p = false;
- if (strpbrk (pattern, "*?["))
- for (i = 0; i < description->decls_num; i++)
- {
- insn_reserv = description->decls[i];
- if (insn_reserv->mode == dm_insn_reserv
- && fnmatch (pattern, DECL_INSN_RESERV (insn_reserv)->name, 0) == 0)
- {
- fn (bypass, insn_reserv, data);
- matched_p = true;
- }
- }
- else
- {
- insn_reserv = find_insn_decl (pattern);
- if (insn_reserv)
- {
- fn (bypass, insn_reserv, data);
- matched_p = true;
- }
- }
- if (!matched_p)
- error ("there is no insn reservation that matches `%s'", pattern);
- }
- /* A subroutine of process_bypass that is called for each pair
- of matching instructions. OUT_INSN_RESERV is the output
- instruction and DATA is the input instruction. */
- static void
- process_bypass_2 (decl_t model, decl_t out_insn_reserv, void *data)
- {
- struct bypass_decl *bypass;
- decl_t in_insn_reserv;
- in_insn_reserv = (decl_t) data;
- if (strcmp (DECL_INSN_RESERV (in_insn_reserv)->name,
- DECL_BYPASS (model)->in_pattern) == 0
- && strcmp (DECL_INSN_RESERV (out_insn_reserv)->name,
- DECL_BYPASS (model)->out_pattern) == 0)
- bypass = DECL_BYPASS (model);
- else
- {
- bypass = XCNEW (struct bypass_decl);
- bypass->latency = DECL_BYPASS (model)->latency;
- bypass->out_pattern = DECL_INSN_RESERV (out_insn_reserv)->name;
- bypass->in_pattern = DECL_INSN_RESERV (in_insn_reserv)->name;
- bypass->bypass_guard_name = DECL_BYPASS (model)->bypass_guard_name;
- }
- bypass->out_insn_reserv = DECL_INSN_RESERV (out_insn_reserv);
- bypass->in_insn_reserv = DECL_INSN_RESERV (in_insn_reserv);
- insert_bypass (bypass);
- }
- /* A subroutine of process_bypass that is called for each input
- instruction IN_INSN_RESERV. */
- static void
- process_bypass_1 (decl_t bypass, decl_t in_insn_reserv,
- void *data ATTRIBUTE_UNUSED)
- {
- for_each_matching_insn (bypass, DECL_BYPASS (bypass)->out_pattern,
- process_bypass_2, in_insn_reserv);
- }
- /* Process define_bypass decl BYPASS, inserting a bypass for each specific
- pair of insn reservations. */
- static void
- process_bypass (decl_t bypass)
- {
- for_each_matching_insn (bypass, DECL_BYPASS (bypass)->in_pattern,
- process_bypass_1, NULL);
- }
- /* The function processes pipeline description declarations, checks
- their correctness, and forms exclusion/presence/absence sets. */
- static void
- process_decls (void)
- {
- decl_t decl;
- decl_t automaton_decl;
- decl_t decl_in_table;
- int automaton_presence;
- int i;
- /* Checking repeated automata declarations. */
- automaton_presence = 0;
- for (i = 0; i < description->decls_num; i++)
- {
- decl = description->decls [i];
- if (decl->mode == dm_automaton)
- {
- automaton_presence = 1;
- decl_in_table = insert_automaton_decl (decl);
- if (decl_in_table != decl)
- {
- if (!w_flag)
- error ("repeated declaration of automaton `%s'",
- DECL_AUTOMATON (decl)->name);
- else
- warning ("repeated declaration of automaton `%s'",
- DECL_AUTOMATON (decl)->name);
- }
- }
- }
- /* Checking undeclared automata, repeated declarations (except for
- automata) and correctness of their attributes (insn latency times
- etc.). */
- for (i = 0; i < description->decls_num; i++)
- {
- decl = description->decls [i];
- if (decl->mode == dm_insn_reserv)
- {
- if (DECL_INSN_RESERV (decl)->default_latency < 0)
- error ("define_insn_reservation `%s' has negative latency time",
- DECL_INSN_RESERV (decl)->name);
- DECL_INSN_RESERV (decl)->insn_num = description->insns_num;
- description->insns_num++;
- decl_in_table = insert_insn_decl (decl);
- if (decl_in_table != decl)
- error ("`%s' is already used as insn reservation name",
- DECL_INSN_RESERV (decl)->name);
- }
- else if (decl->mode == dm_bypass)
- {
- if (DECL_BYPASS (decl)->latency < 0)
- error ("define_bypass `%s - %s' has negative latency time",
- DECL_BYPASS (decl)->out_pattern,
- DECL_BYPASS (decl)->in_pattern);
- }
- else if (decl->mode == dm_unit || decl->mode == dm_reserv)
- {
- if (decl->mode == dm_unit)
- {
- DECL_UNIT (decl)->automaton_decl = NULL;
- if (DECL_UNIT (decl)->automaton_name != NULL)
- {
- automaton_decl
- = find_automaton_decl (DECL_UNIT (decl)->automaton_name);
- if (automaton_decl == NULL)
- error ("automaton `%s' is not declared",
- DECL_UNIT (decl)->automaton_name);
- else
- {
- DECL_AUTOMATON (automaton_decl)->automaton_is_used = 1;
- DECL_UNIT (decl)->automaton_decl
- = DECL_AUTOMATON (automaton_decl);
- }
- }
- else if (automaton_presence)
- error ("define_unit `%s' without automaton when one defined",
- DECL_UNIT (decl)->name);
- DECL_UNIT (decl)->unit_num = description->units_num;
- description->units_num++;
- if (strcmp (DECL_UNIT (decl)->name, NOTHING_NAME) == 0)
- {
- error ("`%s' is declared as cpu unit", NOTHING_NAME);
- continue;
- }
- decl_in_table = find_decl (DECL_UNIT (decl)->name);
- }
- else
- {
- if (strcmp (DECL_RESERV (decl)->name, NOTHING_NAME) == 0)
- {
- error ("`%s' is declared as cpu reservation", NOTHING_NAME);
- continue;
- }
- decl_in_table = find_decl (DECL_RESERV (decl)->name);
- }
- if (decl_in_table == NULL)
- decl_in_table = insert_decl (decl);
- else
- {
- if (decl->mode == dm_unit)
- error ("repeated declaration of unit `%s'",
- DECL_UNIT (decl)->name);
- else
- error ("repeated declaration of reservation `%s'",
- DECL_RESERV (decl)->name);
- }
- }
- }
- /* Check bypasses and form list of bypasses for each (output)
- insn. */
- for (i = 0; i < description->decls_num; i++)
- {
- decl = description->decls [i];
- if (decl->mode == dm_bypass)
- process_bypass (decl);
- }
- /* Check exclusion set declarations and form exclusion sets. */
- for (i = 0; i < description->decls_num; i++)
- {
- decl = description->decls [i];
- if (decl->mode == dm_excl)
- {
- unit_set_el_t unit_set_el_list;
- unit_set_el_t unit_set_el_list_2;
- unit_set_el_list
- = process_excls (DECL_EXCL (decl)->names,
- DECL_EXCL (decl)->first_list_length, decl->pos);
- unit_set_el_list_2
- = process_excls (&DECL_EXCL (decl)->names
- [DECL_EXCL (decl)->first_list_length],
- DECL_EXCL (decl)->all_names_num
- - DECL_EXCL (decl)->first_list_length,
- decl->pos);
- add_excls (unit_set_el_list, unit_set_el_list_2, decl->pos);
- add_excls (unit_set_el_list_2, unit_set_el_list, decl->pos);
- }
- }
- /* Check presence set declarations and form presence sets. */
- for (i = 0; i < description->decls_num; i++)
- {
- decl = description->decls [i];
- if (decl->mode == dm_presence)
- {
- unit_set_el_t unit_set_el_list;
- pattern_set_el_t pattern_set_el_list;
- unit_set_el_list
- = process_presence_absence_names
- (DECL_PRESENCE (decl)->names, DECL_PRESENCE (decl)->names_num,
- decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
- pattern_set_el_list
- = process_presence_absence_patterns
- (DECL_PRESENCE (decl)->patterns,
- DECL_PRESENCE (decl)->patterns_num,
- decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
- add_presence_absence (unit_set_el_list, pattern_set_el_list,
- decl->pos, TRUE,
- DECL_PRESENCE (decl)->final_p);
- }
- }
- /* Check absence set declarations and form absence sets. */
- for (i = 0; i < description->decls_num; i++)
- {
- decl = description->decls [i];
- if (decl->mode == dm_absence)
- {
- unit_set_el_t unit_set_el_list;
- pattern_set_el_t pattern_set_el_list;
- unit_set_el_list
- = process_presence_absence_names
- (DECL_ABSENCE (decl)->names, DECL_ABSENCE (decl)->names_num,
- decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
- pattern_set_el_list
- = process_presence_absence_patterns
- (DECL_ABSENCE (decl)->patterns,
- DECL_ABSENCE (decl)->patterns_num,
- decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
- add_presence_absence (unit_set_el_list, pattern_set_el_list,
- decl->pos, FALSE,
- DECL_ABSENCE (decl)->final_p);
- }
- }
- }
- /* The following function checks that declared automaton is used. If
- the automaton is not used, the function fixes error/warning. The
- following function must be called only after `process_decls'. */
- static void
- check_automaton_usage (void)
- {
- decl_t decl;
- int i;
- for (i = 0; i < description->decls_num; i++)
- {
- decl = description->decls [i];
- if (decl->mode == dm_automaton
- && !DECL_AUTOMATON (decl)->automaton_is_used)
- {
- if (!w_flag)
- error ("automaton `%s' is not used", DECL_AUTOMATON (decl)->name);
- else
- warning ("automaton `%s' is not used",
- DECL_AUTOMATON (decl)->name);
- }
- }
- }
- /* The following recursive function processes all regexp in order to
- fix usage of units or reservations and to fix errors of undeclared
- name. The function may change unit_regexp onto reserv_regexp.
- Remember that reserv_regexp does not exist before the function
- call. */
- static regexp_t
- process_regexp (regexp_t regexp)
- {
- decl_t decl_in_table;
- regexp_t new_regexp;
- int i;
- switch (regexp->mode)
- {
- case rm_unit:
- decl_in_table = find_decl (REGEXP_UNIT (regexp)->name);
- if (decl_in_table == NULL)
- error ("undeclared unit or reservation `%s'",
- REGEXP_UNIT (regexp)->name);
- else
- switch (decl_in_table->mode)
- {
- case dm_unit:
- DECL_UNIT (decl_in_table)->unit_is_used = 1;
- REGEXP_UNIT (regexp)->unit_decl = DECL_UNIT (decl_in_table);
- break;
- case dm_reserv:
- DECL_RESERV (decl_in_table)->reserv_is_used = 1;
- new_regexp = XCREATENODE (struct regexp);
- new_regexp->mode = rm_reserv;
- new_regexp->pos = regexp->pos;
- REGEXP_RESERV (new_regexp)->name = REGEXP_UNIT (regexp)->name;
- REGEXP_RESERV (new_regexp)->reserv_decl
- = DECL_RESERV (decl_in_table);
- regexp = new_regexp;
- break;
- default:
- gcc_unreachable ();
- }
- break;
- case rm_sequence:
- for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
- REGEXP_SEQUENCE (regexp)->regexps [i]
- = process_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
- break;
- case rm_allof:
- for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
- REGEXP_ALLOF (regexp)->regexps [i]
- = process_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
- break;
- case rm_oneof:
- for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
- REGEXP_ONEOF (regexp)->regexps [i]
- = process_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
- break;
- case rm_repeat:
- REGEXP_REPEAT (regexp)->regexp
- = process_regexp (REGEXP_REPEAT (regexp)->regexp);
- break;
- case rm_nothing:
- break;
- default:
- gcc_unreachable ();
- }
- return regexp;
- }
- /* The following function processes regexp of define_reservation and
- define_insn_reservation with the aid of function
- `process_regexp'. */
- static void
- process_regexp_decls (void)
- {
- decl_t decl;
- int i;
- for (i = 0; i < description->decls_num; i++)
- {
- decl = description->decls [i];
- if (decl->mode == dm_reserv)
- DECL_RESERV (decl)->regexp
- = process_regexp (DECL_RESERV (decl)->regexp);
- else if (decl->mode == dm_insn_reserv)
- DECL_INSN_RESERV (decl)->regexp
- = process_regexp (DECL_INSN_RESERV (decl)->regexp);
- }
- }
- /* The following function checks that declared unit is used. If the
- unit is not used, the function fixes errors/warnings. The
- following function must be called only after `process_decls',
- `process_regexp_decls'. */
- static void
- check_usage (void)
- {
- decl_t decl;
- int i;
- for (i = 0; i < description->decls_num; i++)
- {
- decl = description->decls [i];
- if (decl->mode == dm_unit && !DECL_UNIT (decl)->unit_is_used)
- {
- if (!w_flag)
- error ("unit `%s' is not used", DECL_UNIT (decl)->name);
- else
- warning ("unit `%s' is not used", DECL_UNIT (decl)->name);
- }
- else if (decl->mode == dm_reserv && !DECL_RESERV (decl)->reserv_is_used)
- {
- if (!w_flag)
- error ("reservation `%s' is not used", DECL_RESERV (decl)->name);
- else
- warning ("reservation `%s' is not used", DECL_RESERV (decl)->name);
- }
- }
- }
- /* The following variable value is number of reservation being
- processed on loop recognition. */
- static int curr_loop_pass_num;
- /* The following recursive function returns nonzero value if REGEXP
- contains given decl or reservations in given regexp refers for
- given decl. */
- static int
- loop_in_regexp (regexp_t regexp, decl_t start_decl)
- {
- int i;
- if (regexp == NULL)
- return 0;
- switch (regexp->mode)
- {
- case rm_unit:
- return 0;
- case rm_reserv:
- if (start_decl->mode == dm_reserv
- && REGEXP_RESERV (regexp)->reserv_decl == DECL_RESERV (start_decl))
- return 1;
- else if (REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
- == curr_loop_pass_num)
- /* declaration has been processed. */
- return 0;
- else
- {
- REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
- = curr_loop_pass_num;
- return loop_in_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp,
- start_decl);
- }
- case rm_sequence:
- for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
- if (loop_in_regexp (REGEXP_SEQUENCE (regexp)->regexps [i], start_decl))
- return 1;
- return 0;
- case rm_allof:
- for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
- if (loop_in_regexp (REGEXP_ALLOF (regexp)->regexps [i], start_decl))
- return 1;
- return 0;
- case rm_oneof:
- for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
- if (loop_in_regexp (REGEXP_ONEOF (regexp)->regexps [i], start_decl))
- return 1;
- return 0;
- case rm_repeat:
- return loop_in_regexp (REGEXP_REPEAT (regexp)->regexp, start_decl);
- case rm_nothing:
- return 0;
- default:
- gcc_unreachable ();
- }
- }
- /* The following function fixes errors "cycle in definition ...". The
- function uses function `loop_in_regexp' for that. */
- static void
- check_loops_in_regexps (void)
- {
- decl_t decl;
- int i;
- for (i = 0; i < description->decls_num; i++)
- {
- decl = description->decls [i];
- if (decl->mode == dm_reserv)
- DECL_RESERV (decl)->loop_pass_num = 0;
- }
- for (i = 0; i < description->decls_num; i++)
- {
- decl = description->decls [i];
- curr_loop_pass_num = i;
- if (decl->mode == dm_reserv)
- {
- DECL_RESERV (decl)->loop_pass_num = curr_loop_pass_num;
- if (loop_in_regexp (DECL_RESERV (decl)->regexp, decl))
- {
- gcc_assert (DECL_RESERV (decl)->regexp);
- error ("cycle in definition of reservation `%s'",
- DECL_RESERV (decl)->name);
- }
- }
- }
- }
- /* The function recursively processes IR of reservation and defines
- max and min cycle for reservation of unit. */
- static void
- process_regexp_cycles (regexp_t regexp, int max_start_cycle,
- int min_start_cycle, int *max_finish_cycle,
- int *min_finish_cycle)
- {
- int i;
- switch (regexp->mode)
- {
- case rm_unit:
- if (REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num < max_start_cycle)
- REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num = max_start_cycle;
- if (REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num > min_start_cycle
- || REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num == -1)
- REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num = min_start_cycle;
- *max_finish_cycle = max_start_cycle;
- *min_finish_cycle = min_start_cycle;
- break;
- case rm_reserv:
- process_regexp_cycles (REGEXP_RESERV (regexp)->reserv_decl->regexp,
- max_start_cycle, min_start_cycle,
- max_finish_cycle, min_finish_cycle);
- break;
- case rm_repeat:
- for (i = 0; i < REGEXP_REPEAT (regexp)->repeat_num; i++)
- {
- process_regexp_cycles (REGEXP_REPEAT (regexp)->regexp,
- max_start_cycle, min_start_cycle,
- max_finish_cycle, min_finish_cycle);
- max_start_cycle = *max_finish_cycle + 1;
- min_start_cycle = *min_finish_cycle + 1;
- }
- break;
- case rm_sequence:
- for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
- {
- process_regexp_cycles (REGEXP_SEQUENCE (regexp)->regexps [i],
- max_start_cycle, min_start_cycle,
- max_finish_cycle, min_finish_cycle);
- max_start_cycle = *max_finish_cycle + 1;
- min_start_cycle = *min_finish_cycle + 1;
- }
- break;
- case rm_allof:
- {
- int max_cycle = 0;
- int min_cycle = 0;
- for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
- {
- process_regexp_cycles (REGEXP_ALLOF (regexp)->regexps [i],
- max_start_cycle, min_start_cycle,
- max_finish_cycle, min_finish_cycle);
- if (max_cycle < *max_finish_cycle)
- max_cycle = *max_finish_cycle;
- if (i == 0 || min_cycle > *min_finish_cycle)
- min_cycle = *min_finish_cycle;
- }
- *max_finish_cycle = max_cycle;
- *min_finish_cycle = min_cycle;
- }
- break;
- case rm_oneof:
- {
- int max_cycle = 0;
- int min_cycle = 0;
- for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
- {
- process_regexp_cycles (REGEXP_ONEOF (regexp)->regexps [i],
- max_start_cycle, min_start_cycle,
- max_finish_cycle, min_finish_cycle);
- if (max_cycle < *max_finish_cycle)
- max_cycle = *max_finish_cycle;
- if (i == 0 || min_cycle > *min_finish_cycle)
- min_cycle = *min_finish_cycle;
- }
- *max_finish_cycle = max_cycle;
- *min_finish_cycle = min_cycle;
- }
- break;
- case rm_nothing:
- *max_finish_cycle = max_start_cycle;
- *min_finish_cycle = min_start_cycle;
- break;
- default:
- gcc_unreachable ();
- }
- }
- /* The following function is called only for correct program. The
- function defines max reservation of insns in cycles. */
- static void
- evaluate_max_reserv_cycles (void)
- {
- int max_insn_cycles_num;
- int min_insn_cycles_num;
- decl_t decl;
- int i;
- description->max_insn_reserv_cycles = 0;
- for (i = 0; i < description->decls_num; i++)
- {
- decl = description->decls [i];
- if (decl->mode == dm_insn_reserv)
- {
- process_regexp_cycles (DECL_INSN_RESERV (decl)->regexp, 0, 0,
- &max_insn_cycles_num, &min_insn_cycles_num);
- if (description->max_insn_reserv_cycles < max_insn_cycles_num)
- description->max_insn_reserv_cycles = max_insn_cycles_num;
- }
- }
- description->max_insn_reserv_cycles++;
- }
- /* The following function calls functions for checking all
- description. */
- static void
- check_all_description (void)
- {
- process_decls ();
- check_automaton_usage ();
- process_regexp_decls ();
- check_usage ();
- check_loops_in_regexps ();
- if (!have_error)
- evaluate_max_reserv_cycles ();
- }
- /* The page contains abstract data `ticker'. This data is used to
- report time of different phases of building automata. It is
- possibly to write a description for which automata will be built
- during several minutes even on fast machine. */
- /* The following function creates ticker and makes it active. */
- static ticker_t
- create_ticker (void)
- {
- ticker_t ticker;
- ticker.modified_creation_time = get_run_time ();
- ticker.incremented_off_time = 0;
- return ticker;
- }
- /* The following function switches off given ticker. */
- static void
- ticker_off (ticker_t *ticker)
- {
- if (ticker->incremented_off_time == 0)
- ticker->incremented_off_time = get_run_time () + 1;
- }
- /* The following function switches on given ticker. */
- static void
- ticker_on (ticker_t *ticker)
- {
- if (ticker->incremented_off_time != 0)
- {
- ticker->modified_creation_time
- += get_run_time () - ticker->incremented_off_time + 1;
- ticker->incremented_off_time = 0;
- }
- }
- /* The following function returns current time in milliseconds since
- the moment when given ticker was created. */
- static int
- active_time (ticker_t ticker)
- {
- if (ticker.incremented_off_time != 0)
- return ticker.incremented_off_time - 1 - ticker.modified_creation_time;
- else
- return get_run_time () - ticker.modified_creation_time;
- }
- /* The following function returns string representation of active time
- of given ticker. The result is string representation of seconds
- with accuracy of 1/100 second. Only result of the last call of the
- function exists. Therefore the following code is not correct
- printf ("parser time: %s\ngeneration time: %s\n",
- active_time_string (parser_ticker),
- active_time_string (generation_ticker));
- Correct code has to be the following
- printf ("parser time: %s\n", active_time_string (parser_ticker));
- printf ("generation time: %s\n",
- active_time_string (generation_ticker));
- */
- static void
- print_active_time (FILE *f, ticker_t ticker)
- {
- int msecs;
- msecs = active_time (ticker);
- fprintf (f, "%d.%06d", msecs / 1000000, msecs % 1000000);
- }
- /* The following variable value is number of automaton which are
- really being created. This value is defined on the base of
- argument of option `-split'. If the variable has zero value the
- number of automata is defined by the constructions `%automaton'.
- This case occurs when option `-split' is absent or has zero
- argument. If constructions `define_automaton' is absent only one
- automaton is created. */
- static int automata_num;
- /* The following variable values are times of
- o transformation of regular expressions
- o building NDFA (DFA if !ndfa_flag)
- o NDFA -> DFA (simply the same automaton if !ndfa_flag)
- o DFA minimization
- o building insn equivalence classes
- o all previous ones
- o code output */
- static ticker_t transform_time;
- static ticker_t NDFA_time;
- static ticker_t NDFA_to_DFA_time;
- static ticker_t minimize_time;
- static ticker_t equiv_time;
- static ticker_t automaton_generation_time;
- static ticker_t output_time;
- /* The following variable values are times of
- all checking
- all generation
- all pipeline hazard translator work */
- static ticker_t check_time;
- static ticker_t generation_time;
- static ticker_t all_time;
- /* Pseudo insn decl which denotes advancing cycle. */
- static decl_t advance_cycle_insn_decl;
- /* Pseudo insn decl which denotes collapsing the NDFA state. */
- static decl_t collapse_ndfa_insn_decl;
- /* Create and record a decl for the special advance-cycle transition. */
- static void
- add_advance_cycle_insn_decl (void)
- {
- advance_cycle_insn_decl = XCREATENODE (struct decl);
- advance_cycle_insn_decl->mode = dm_insn_reserv;
- advance_cycle_insn_decl->pos = no_pos;
- DECL_INSN_RESERV (advance_cycle_insn_decl)->regexp = NULL;
- DECL_INSN_RESERV (advance_cycle_insn_decl)->name = "$advance_cycle";
- DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num
- = description->insns_num;
- description->decls [description->decls_num] = advance_cycle_insn_decl;
- description->decls_num++;
- description->insns_num++;
- }
- /* Create and record a decl for the special collapse-NDFA transition. */
- static void
- add_collapse_ndfa_insn_decl (void)
- {
- collapse_ndfa_insn_decl = XCREATENODE (struct decl);
- collapse_ndfa_insn_decl->mode = dm_insn_reserv;
- collapse_ndfa_insn_decl->pos = no_pos;
- DECL_INSN_RESERV (collapse_ndfa_insn_decl)->regexp = NULL;
- DECL_INSN_RESERV (collapse_ndfa_insn_decl)->name = "$collapse_ndfa";
- DECL_INSN_RESERV (collapse_ndfa_insn_decl)->insn_num
- = description->insns_num;
- description->decls [description->decls_num] = collapse_ndfa_insn_decl;
- description->decls_num++;
- description->insns_num++;
- }
- /* True if DECL is either of the two special decls we created. */
- static bool
- special_decl_p (struct insn_reserv_decl *decl)
- {
- return (decl == DECL_INSN_RESERV (advance_cycle_insn_decl)
- || (collapse_flag
- && decl == DECL_INSN_RESERV (collapse_ndfa_insn_decl)));
- }
- /* Abstract data `alternative states' which represents
- nondeterministic nature of the description (see comments for
- structures alt_state and state). */
- /* List of free states. */
- static alt_state_t first_free_alt_state;
- #ifndef NDEBUG
- /* The following variables is maximal number of allocated nodes
- alt_state. */
- static int allocated_alt_states_num = 0;
- #endif
- /* The following function returns free node alt_state. It may be new
- allocated node or node freed earlier. */
- static alt_state_t
- get_free_alt_state (void)
- {
- alt_state_t result;
- if (first_free_alt_state != NULL)
- {
- result = first_free_alt_state;
- first_free_alt_state = first_free_alt_state->next_alt_state;
- }
- else
- {
- #ifndef NDEBUG
- allocated_alt_states_num++;
- #endif
- result = XCREATENODE (struct alt_state);
- }
- result->state = NULL;
- result->next_alt_state = NULL;
- result->next_sorted_alt_state = NULL;
- return result;
- }
- /* The function frees node ALT_STATE. */
- static void
- free_alt_state (alt_state_t alt_state)
- {
- if (alt_state == NULL)
- return;
- alt_state->next_alt_state = first_free_alt_state;
- first_free_alt_state = alt_state;
- }
- /* The function frees list started with node ALT_STATE_LIST. */
- static void
- free_alt_states (alt_state_t alt_states_list)
- {
- alt_state_t curr_alt_state;
- alt_state_t next_alt_state;
- for (curr_alt_state = alt_states_list;
- curr_alt_state != NULL;
- curr_alt_state = next_alt_state)
- {
- next_alt_state = curr_alt_state->next_alt_state;
- free_alt_state (curr_alt_state);
- }
- }
- /* The function compares unique numbers of alt states. */
- static int
- alt_state_cmp (const void *alt_state_ptr_1, const void *alt_state_ptr_2)
- {
- if ((*(const alt_state_t *) alt_state_ptr_1)->state->unique_num
- == (*(const alt_state_t *) alt_state_ptr_2)->state->unique_num)
- return 0;
- else if ((*(const alt_state_t *) alt_state_ptr_1)->state->unique_num
- < (*(const alt_state_t *) alt_state_ptr_2)->state->unique_num)
- return -1;
- else
- return 1;
- }
- /* The function sorts ALT_STATES_LIST and removes duplicated alt
- states from the list. The comparison key is alt state unique
- number. */
- static alt_state_t
- uniq_sort_alt_states (alt_state_t alt_states_list)
- {
- alt_state_t curr_alt_state;
- size_t i;
- size_t prev_unique_state_ind;
- alt_state_t result;
- if (alt_states_list == 0)
- return 0;
- if (alt_states_list->next_alt_state == 0)
- return alt_states_list;
- auto_vec<alt_state_t, 150> alt_states;
- for (curr_alt_state = alt_states_list;
- curr_alt_state != NULL;
- curr_alt_state = curr_alt_state->next_alt_state)
- alt_states.safe_push (curr_alt_state);
- alt_states.qsort (alt_state_cmp);
- prev_unique_state_ind = 0;
- for (i = 1; i < alt_states.length (); i++)
- if (alt_states[prev_unique_state_ind]->state != alt_states[i]->state)
- {
- prev_unique_state_ind++;
- alt_states[prev_unique_state_ind] = alt_states[i];
- }
- alt_states.truncate (prev_unique_state_ind + 1);
- for (i = 1; i < alt_states.length (); i++)
- alt_states[i-1]->next_sorted_alt_state
- = alt_states[i];
- alt_states.last ()->next_sorted_alt_state = 0;
- result = alt_states[0];
- return result;
- }
- /* The function checks equality of alt state lists. Remember that the
- lists must be already sorted by the previous function. */
- static int
- alt_states_eq (alt_state_t alt_states_1, alt_state_t alt_states_2)
- {
- while (alt_states_1 != NULL && alt_states_2 != NULL
- && alt_state_cmp (&alt_states_1, &alt_states_2) == 0)
- {
- alt_states_1 = alt_states_1->next_sorted_alt_state;
- alt_states_2 = alt_states_2->next_sorted_alt_state;
- }
- return alt_states_1 == alt_states_2;
- }
- /* Initialization of the abstract data. */
- static void
- initiate_alt_states (void)
- {
- first_free_alt_state = NULL;
- }
- /* Finishing work with the abstract data. */
- static void
- finish_alt_states (void)
- {
- }
- /* The page contains macros for work with bits strings. We could use
- standard gcc bitmap or sbitmap but it would result in difficulties
- of building canadian cross. */
- /* Set bit number bitno in the bit string. The macro is not side
- effect proof. */
- #define bitmap_set_bit(bitstring, bitno) \
- ((bitstring)[(bitno) / (sizeof (*(bitstring)) * CHAR_BIT)] |= \
- (HOST_WIDE_INT)1 << (bitno) % (sizeof (*(bitstring)) * CHAR_BIT))
- #define CLEAR_BIT(bitstring, bitno) \
- ((bitstring)[(bitno) / (sizeof (*(bitstring)) * CHAR_BIT)] &= \
- ~((HOST_WIDE_INT)1 << (bitno) % (sizeof (*(bitstring)) * CHAR_BIT)))
- /* Test if bit number bitno in the bitstring is set. The macro is not
- side effect proof. */
- #define bitmap_bit_p(bitstring, bitno) \
- ((bitstring)[(bitno) / (sizeof (*(bitstring)) * CHAR_BIT)] >> \
- (bitno) % (sizeof (*(bitstring)) * CHAR_BIT) & 1)
- /* This page contains abstract data `state'. */
- /* Maximal length of reservations in cycles (>= 1). */
- static int max_cycles_num;
- /* Number of set elements (see type set_el_t) needed for
- representation of one cycle reservation. It is depended on units
- number. */
- static int els_in_cycle_reserv;
- /* Number of set elements (see type set_el_t) needed for
- representation of maximal length reservation. Deterministic
- reservation is stored as set (bit string) of length equal to the
- variable value * number of bits in set_el_t. */
- static int els_in_reservs;
- /* Array of pointers to unit declarations. */
- static unit_decl_t *units_array;
- /* Temporary reservation of maximal length. */
- static reserv_sets_t temp_reserv;
- /* The state table itself is represented by the following variable. */
- static htab_t state_table;
- /* Linked list of free 'state' structures to be recycled. The
- next_equiv_class_state pointer is borrowed for a free list. */
- static state_t first_free_state;
- static int curr_unique_state_num;
- #ifndef NDEBUG
- /* The following variables is maximal number of allocated nodes
- `state'. */
- static int allocated_states_num = 0;
- #endif
- /* Allocate new reservation set. */
- static reserv_sets_t
- alloc_empty_reserv_sets (void)
- {
- reserv_sets_t result;
- obstack_blank (&irp, els_in_reservs * sizeof (set_el_t));
- result = (reserv_sets_t) obstack_base (&irp);
- obstack_finish (&irp);
- memset (result, 0, els_in_reservs * sizeof (set_el_t));
- return result;
- }
- /* Hash value of reservation set. */
- static unsigned
- reserv_sets_hash_value (reserv_sets_t reservs)
- {
- set_el_t hash_value;
- unsigned result;
- int reservs_num, i;
- set_el_t *reserv_ptr;
- hash_value = 0;
- reservs_num = els_in_reservs;
- reserv_ptr = reservs;
- i = 0;
- while (reservs_num != 0)
- {
- reservs_num--;
- hash_value += ((*reserv_ptr >> i)
- | (*reserv_ptr << (((sizeof (set_el_t) * CHAR_BIT) - 1) & -i)));
- i++;
- if (i == sizeof (set_el_t) * CHAR_BIT)
- i = 0;
- reserv_ptr++;
- }
- if (sizeof (set_el_t) <= sizeof (unsigned))
- return hash_value;
- result = 0;
- for (i = sizeof (set_el_t); i > 0; i -= sizeof (unsigned) - 1)
- {
- result += (unsigned) hash_value;
- hash_value >>= (sizeof (unsigned) - 1) * CHAR_BIT;
- }
- return result;
- }
- /* Comparison of given reservation sets. */
- static int
- reserv_sets_cmp (const_reserv_sets_t reservs_1, const_reserv_sets_t reservs_2)
- {
- int reservs_num;
- const set_el_t *reserv_ptr_1;
- const set_el_t *reserv_ptr_2;
- gcc_assert (reservs_1 && reservs_2);
- reservs_num = els_in_reservs;
- reserv_ptr_1 = reservs_1;
- reserv_ptr_2 = reservs_2;
- while (reservs_num != 0 && *reserv_ptr_1 == *reserv_ptr_2)
- {
- reservs_num--;
- reserv_ptr_1++;
- reserv_ptr_2++;
- }
- if (reservs_num == 0)
- return 0;
- else if (*reserv_ptr_1 < *reserv_ptr_2)
- return -1;
- else
- return 1;
- }
- /* The function checks equality of the reservation sets. */
- static int
- reserv_sets_eq (const_reserv_sets_t reservs_1, const_reserv_sets_t reservs_2)
- {
- return reserv_sets_cmp (reservs_1, reservs_2) == 0;
- }
- /* Set up in the reservation set that unit with UNIT_NUM is used on
- CYCLE_NUM. */
- static void
- set_unit_reserv (reserv_sets_t reservs, int cycle_num, int unit_num)
- {
- gcc_assert (cycle_num < max_cycles_num);
- bitmap_set_bit (reservs, cycle_num * els_in_cycle_reserv
- * sizeof (set_el_t) * CHAR_BIT + unit_num);
- }
- /* Set up in the reservation set RESERVS that unit with UNIT_NUM is
- used on CYCLE_NUM. */
- static int
- test_unit_reserv (reserv_sets_t reservs, int cycle_num, int unit_num)
- {
- gcc_assert (cycle_num < max_cycles_num);
- return bitmap_bit_p (reservs, cycle_num * els_in_cycle_reserv
- * sizeof (set_el_t) * CHAR_BIT + unit_num);
- }
- /* The function checks that the reservation sets are intersected,
- i.e. there is a unit reservation on a cycle in both reservation
- sets. */
- static int
- reserv_sets_are_intersected (reserv_sets_t operand_1,
- reserv_sets_t operand_2)
- {
- set_el_t *el_ptr_1;
- set_el_t *el_ptr_2;
- set_el_t *cycle_ptr_1;
- set_el_t *cycle_ptr_2;
- gcc_assert (operand_1 && operand_2);
- for (el_ptr_1 = operand_1, el_ptr_2 = operand_2;
- el_ptr_1 < operand_1 + els_in_reservs;
- el_ptr_1++, el_ptr_2++)
- if (*el_ptr_1 & *el_ptr_2)
- return 1;
- reserv_sets_or (temp_reserv, operand_1, operand_2);
- for (cycle_ptr_1 = operand_1, cycle_ptr_2 = operand_2;
- cycle_ptr_1 < operand_1 + els_in_reservs;
- cycle_ptr_1 += els_in_cycle_reserv, cycle_ptr_2 += els_in_cycle_reserv)
- {
- for (el_ptr_1 = cycle_ptr_1, el_ptr_2 = get_excl_set (cycle_ptr_2);
- el_ptr_1 < cycle_ptr_1 + els_in_cycle_reserv;
- el_ptr_1++, el_ptr_2++)
- if (*el_ptr_1 & *el_ptr_2)
- return 1;
- if (!check_presence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE))
- return 1;
- if (!check_presence_pattern_sets (temp_reserv + (cycle_ptr_2
- - operand_2),
- cycle_ptr_2, TRUE))
- return 1;
- if (!check_absence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE))
- return 1;
- if (!check_absence_pattern_sets (temp_reserv + (cycle_ptr_2 - operand_2),
- cycle_ptr_2, TRUE))
- return 1;
- }
- return 0;
- }
- /* The function sets up RESULT bits by bits of OPERAND shifted on one
- cpu cycle. The remaining bits of OPERAND (representing the last
- cycle unit reservations) are not changed. */
- static void
- reserv_sets_shift (reserv_sets_t result, reserv_sets_t operand)
- {
- int i;
- gcc_assert (result && operand && result != operand);
- for (i = els_in_cycle_reserv; i < els_in_reservs; i++)
- result [i - els_in_cycle_reserv] = operand [i];
- }
- /* OR of the reservation sets. */
- static void
- reserv_sets_or (reserv_sets_t result, reserv_sets_t operand_1,
- reserv_sets_t operand_2)
- {
- set_el_t *el_ptr_1;
- set_el_t *el_ptr_2;
- set_el_t *result_set_el_ptr;
- gcc_assert (result && operand_1 && operand_2);
- for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
- el_ptr_1 < operand_1 + els_in_reservs;
- el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
- *result_set_el_ptr = *el_ptr_1 | *el_ptr_2;
- }
- /* AND of the reservation sets. */
- static void
- reserv_sets_and (reserv_sets_t result, reserv_sets_t operand_1,
- reserv_sets_t operand_2)
- {
- set_el_t *el_ptr_1;
- set_el_t *el_ptr_2;
- set_el_t *result_set_el_ptr;
- gcc_assert (result && operand_1 && operand_2);
- for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
- el_ptr_1 < operand_1 + els_in_reservs;
- el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
- *result_set_el_ptr = *el_ptr_1 & *el_ptr_2;
- }
- /* The function outputs string representation of units reservation on
- cycle START_CYCLE in the reservation set. The function uses repeat
- construction if REPETITION_NUM > 1. */
- static void
- output_cycle_reservs (FILE *f, reserv_sets_t reservs, int start_cycle,
- int repetition_num)
- {
- int unit_num;
- int reserved_units_num;
- reserved_units_num = 0;
- for (unit_num = 0; unit_num < description->units_num; unit_num++)
- if (bitmap_bit_p (reservs, start_cycle * els_in_cycle_reserv
- * sizeof (set_el_t) * CHAR_BIT + unit_num))
- reserved_units_num++;
- gcc_assert (repetition_num > 0);
- if (repetition_num != 1 && reserved_units_num > 1)
- fprintf (f, "(");
- reserved_units_num = 0;
- for (unit_num = 0;
- unit_num < description->units_num;
- unit_num++)
- if (bitmap_bit_p (reservs, start_cycle * els_in_cycle_reserv
- * sizeof (set_el_t) * CHAR_BIT + unit_num))
- {
- if (reserved_units_num != 0)
- fprintf (f, "+");
- reserved_units_num++;
- fprintf (f, "%s", units_array [unit_num]->name);
- }
- if (reserved_units_num == 0)
- fprintf (f, NOTHING_NAME);
- gcc_assert (repetition_num > 0);
- if (repetition_num != 1 && reserved_units_num > 1)
- fprintf (f, ")");
- if (repetition_num != 1)
- fprintf (f, "*%d", repetition_num);
- }
- /* The function outputs string representation of units reservation in
- the reservation set. */
- static void
- output_reserv_sets (FILE *f, reserv_sets_t reservs)
- {
- int start_cycle = 0;
- int cycle;
- int repetition_num;
- repetition_num = 0;
- for (cycle = 0; cycle < max_cycles_num; cycle++)
- if (repetition_num == 0)
- {
- repetition_num++;
- start_cycle = cycle;
- }
- else if (memcmp
- ((char *) reservs + start_cycle * els_in_cycle_reserv
- * sizeof (set_el_t),
- (char *) reservs + cycle * els_in_cycle_reserv
- * sizeof (set_el_t),
- els_in_cycle_reserv * sizeof (set_el_t)) == 0)
- repetition_num++;
- else
- {
- if (start_cycle != 0)
- fprintf (f, ", ");
- output_cycle_reservs (f, reservs, start_cycle, repetition_num);
- repetition_num = 1;
- start_cycle = cycle;
- }
- if (start_cycle < max_cycles_num)
- {
- if (start_cycle != 0)
- fprintf (f, ", ");
- output_cycle_reservs (f, reservs, start_cycle, repetition_num);
- }
- }
- /* The following function returns free node state for AUTOMATON. It
- may be new allocated node or node freed earlier. The function also
- allocates reservation set if WITH_RESERVS has nonzero value. */
- static state_t
- get_free_state (int with_reservs, automaton_t automaton)
- {
- state_t result;
- gcc_assert (max_cycles_num > 0 && automaton);
- if (first_free_state)
- {
- result = first_free_state;
- first_free_state = result->next_equiv_class_state;
- result->next_equiv_class_state = NULL;
- result->automaton = automaton;
- result->first_out_arc = NULL;
- result->it_was_placed_in_stack_for_NDFA_forming = 0;
- result->it_was_placed_in_stack_for_DFA_forming = 0;
- result->component_states = NULL;
- }
- else
- {
- #ifndef NDEBUG
- allocated_states_num++;
- #endif
- result = XCREATENODE (struct state);
- result->automaton = automaton;
- result->first_out_arc = NULL;
- result->unique_num = curr_unique_state_num;
- curr_unique_state_num++;
- }
- if (with_reservs)
- {
- if (result->reservs == NULL)
- result->reservs = alloc_empty_reserv_sets ();
- else
- memset (result->reservs, 0, els_in_reservs * sizeof (set_el_t));
- }
- return result;
- }
- /* The function frees node STATE. */
- static void
- free_state (state_t state)
- {
- free_alt_states (state->component_states);
- state->next_equiv_class_state = first_free_state;
- first_free_state = state;
- }
- /* Hash value of STATE. If STATE represents deterministic state it is
- simply hash value of the corresponding reservation set. Otherwise
- it is formed from hash values of the component deterministic
- states. One more key is order number of state automaton. */
- static hashval_t
- state_hash (const void *state)
- {
- unsigned int hash_value;
- alt_state_t alt_state;
- if (((const_state_t) state)->component_states == NULL)
- hash_value = reserv_sets_hash_value (((const_state_t) state)->reservs);
- else
- {
- hash_value = 0;
- for (alt_state = ((const_state_t) state)->component_states;
- alt_state != NULL;
- alt_state = alt_state->next_sorted_alt_state)
- hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
- | (hash_value << CHAR_BIT))
- + alt_state->state->unique_num);
- }
- hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
- | (hash_value << CHAR_BIT))
- + ((const_state_t) state)->automaton->automaton_order_num);
- return hash_value;
- }
- /* Return nonzero value if the states are the same. */
- static int
- state_eq_p (const void *state_1, const void *state_2)
- {
- alt_state_t alt_state_1;
- alt_state_t alt_state_2;
- if (((const_state_t) state_1)->automaton != ((const_state_t) state_2)->automaton)
- return 0;
- else if (((const_state_t) state_1)->component_states == NULL
- && ((const_state_t) state_2)->component_states == NULL)
- return reserv_sets_eq (((const_state_t) state_1)->reservs,
- ((const_state_t) state_2)->reservs);
- else if (((const_state_t) state_1)->component_states != NULL
- && ((const_state_t) state_2)->component_states != NULL)
- {
- for (alt_state_1 = ((const_state_t) state_1)->component_states,
- alt_state_2 = ((const_state_t) state_2)->component_states;
- alt_state_1 != NULL && alt_state_2 != NULL;
- alt_state_1 = alt_state_1->next_sorted_alt_state,
- alt_state_2 = alt_state_2->next_sorted_alt_state)
- /* All state in the list must be already in the hash table.
- Also the lists must be sorted. */
- if (alt_state_1->state != alt_state_2->state)
- return 0;
- return alt_state_1 == alt_state_2;
- }
- else
- return 0;
- }
- /* Insert STATE into the state table. */
- static state_t
- insert_state (state_t state)
- {
- void **entry_ptr;
- entry_ptr = htab_find_slot (state_table, (void *) state, INSERT);
- if (*entry_ptr == NULL)
- *entry_ptr = (void *) state;
- return (state_t) *entry_ptr;
- }
- /* Add reservation of unit with UNIT_NUM on cycle CYCLE_NUM to
- deterministic STATE. */
- static void
- set_state_reserv (state_t state, int cycle_num, int unit_num)
- {
- set_unit_reserv (state->reservs, cycle_num, unit_num);
- }
- /* Return nonzero value if the deterministic states contains a
- reservation of the same cpu unit on the same cpu cycle. */
- static int
- intersected_state_reservs_p (state_t state1, state_t state2)
- {
- gcc_assert (state1->automaton == state2->automaton);
- return reserv_sets_are_intersected (state1->reservs, state2->reservs);
- }
- /* Return deterministic state (inserted into the table) which
- representing the automaton state which is union of reservations of
- the deterministic states masked by RESERVS. */
- static state_t
- states_union (state_t state1, state_t state2, reserv_sets_t reservs)
- {
- state_t result;
- state_t state_in_table;
- gcc_assert (state1->automaton == state2->automaton);
- result = get_free_state (1, state1->automaton);
- reserv_sets_or (result->reservs, state1->reservs, state2->reservs);
- reserv_sets_and (result->reservs, result->reservs, reservs);
- state_in_table = insert_state (result);
- if (result != state_in_table)
- {
- free_state (result);
- result = state_in_table;
- }
- return result;
- }
- /* Return deterministic state (inserted into the table) which
- represent the automaton state is obtained from deterministic STATE
- by advancing cpu cycle and masking by RESERVS. */
- static state_t
- state_shift (state_t state, reserv_sets_t reservs)
- {
- state_t result;
- state_t state_in_table;
- result = get_free_state (1, state->automaton);
- reserv_sets_shift (result->reservs, state->reservs);
- reserv_sets_and (result->reservs, result->reservs, reservs);
- state_in_table = insert_state (result);
- if (result != state_in_table)
- {
- free_state (result);
- result = state_in_table;
- }
- return result;
- }
- /* Initialization of the abstract data. */
- static void
- initiate_states (void)
- {
- decl_t decl;
- int i;
- if (description->units_num)
- units_array = XNEWVEC (unit_decl_t, description->units_num);
- else
- units_array = 0;
- for (i = 0; i < description->decls_num; i++)
- {
- decl = description->decls [i];
- if (decl->mode == dm_unit)
- units_array [DECL_UNIT (decl)->unit_num] = DECL_UNIT (decl);
- }
- max_cycles_num = description->max_insn_reserv_cycles;
- els_in_cycle_reserv
- = ((description->units_num + sizeof (set_el_t) * CHAR_BIT - 1)
- / (sizeof (set_el_t) * CHAR_BIT));
- els_in_reservs = els_in_cycle_reserv * max_cycles_num;
- curr_unique_state_num = 0;
- initiate_alt_states ();
- state_table = htab_create (1500, state_hash, state_eq_p, (htab_del) 0);
- temp_reserv = alloc_empty_reserv_sets ();
- }
- /* Finishing work with the abstract data. */
- static void
- finish_states (void)
- {
- free (units_array);
- units_array = 0;
- htab_delete (state_table);
- first_free_state = NULL;
- finish_alt_states ();
- }
- /* Abstract data `arcs'. */
- /* List of free arcs. */
- static arc_t first_free_arc;
- #ifndef NDEBUG
- /* The following variables is maximal number of allocated nodes
- `arc'. */
- static int allocated_arcs_num = 0;
- #endif
- /* The function frees node ARC. */
- static void
- free_arc (arc_t arc)
- {
- arc->next_out_arc = first_free_arc;
- first_free_arc = arc;
- }
- /* The function removes and frees ARC staring from FROM_STATE. */
- static void
- remove_arc (state_t from_state, arc_t arc)
- {
- arc_t prev_arc;
- arc_t curr_arc;
- gcc_assert (arc);
- for (prev_arc = NULL, curr_arc = from_state->first_out_arc;
- curr_arc != NULL;
- prev_arc = curr_arc, curr_arc = curr_arc->next_out_arc)
- if (curr_arc == arc)
- break;
- gcc_assert (curr_arc);
- if (prev_arc == NULL)
- from_state->first_out_arc = arc->next_out_arc;
- else
- prev_arc->next_out_arc = arc->next_out_arc;
- from_state->num_out_arcs--;
- free_arc (arc);
- }
- /* The functions returns arc with given characteristics (or NULL if
- the arc does not exist). */
- static arc_t
- find_arc (state_t from_state, state_t to_state, ainsn_t insn)
- {
- arc_t arc;
- for (arc = first_out_arc (from_state); arc != NULL; arc = next_out_arc (arc))
- if (arc->insn == insn
- && (arc->to_state == to_state
- || (collapse_flag
- /* Any arc is good enough for a collapse-ndfa transition. */
- && (insn->insn_reserv_decl
- == DECL_INSN_RESERV (collapse_ndfa_insn_decl)))))
- return arc;
- return NULL;
- }
- /* The function adds arc from FROM_STATE to TO_STATE marked by AINSN,
- unless such an arc already exists. */
- static void
- add_arc (state_t from_state, state_t to_state, ainsn_t ainsn)
- {
- arc_t new_arc;
- new_arc = find_arc (from_state, to_state, ainsn);
- if (new_arc != NULL)
- return;
- if (first_free_arc == NULL)
- {
- #ifndef NDEBUG
- allocated_arcs_num++;
- #endif
- new_arc = XCREATENODE (struct arc);
- new_arc->to_state = NULL;
- new_arc->insn = NULL;
- new_arc->next_out_arc = NULL;
- }
- else
- {
- new_arc = first_free_arc;
- first_free_arc = first_free_arc->next_out_arc;
- }
- new_arc->to_state = to_state;
- new_arc->insn = ainsn;
- ainsn->arc_exists_p = 1;
- new_arc->next_out_arc = from_state->first_out_arc;
- from_state->first_out_arc = new_arc;
- from_state->num_out_arcs++;
- new_arc->next_arc_marked_by_insn = NULL;
- }
- /* The function returns the first arc starting from STATE. */
- static arc_t
- first_out_arc (const_state_t state)
- {
- return state->first_out_arc;
- }
- /* The function returns next out arc after ARC. */
- static arc_t
- next_out_arc (arc_t arc)
- {
- return arc->next_out_arc;
- }
- /* Initialization of the abstract data. */
- static void
- initiate_arcs (void)
- {
- first_free_arc = NULL;
- }
- /* Finishing work with the abstract data. */
- static void
- finish_arcs (void)
- {
- }
- /* Abstract data `automata lists'. */
- /* List of free states. */
- static automata_list_el_t first_free_automata_list_el;
- /* The list being formed. */
- static automata_list_el_t current_automata_list;
- /* Hash table of automata lists. */
- static htab_t automata_list_table;
- /* The following function returns free automata list el. It may be
- new allocated node or node freed earlier. */
- static automata_list_el_t
- get_free_automata_list_el (void)
- {
- automata_list_el_t result;
- if (first_free_automata_list_el != NULL)
- {
- result = first_free_automata_list_el;
- first_free_automata_list_el
- = first_free_automata_list_el->next_automata_list_el;
- }
- else
- result = XCREATENODE (struct automata_list_el);
- result->automaton = NULL;
- result->next_automata_list_el = NULL;
- return result;
- }
- /* The function frees node AUTOMATA_LIST_EL. */
- static void
- free_automata_list_el (automata_list_el_t automata_list_el)
- {
- if (automata_list_el == NULL)
- return;
- automata_list_el->next_automata_list_el = first_free_automata_list_el;
- first_free_automata_list_el = automata_list_el;
- }
- /* The function frees list AUTOMATA_LIST. */
- static void
- free_automata_list (automata_list_el_t automata_list)
- {
- automata_list_el_t curr_automata_list_el;
- automata_list_el_t next_automata_list_el;
- for (curr_automata_list_el = automata_list;
- curr_automata_list_el != NULL;
- curr_automata_list_el = next_automata_list_el)
- {
- next_automata_list_el = curr_automata_list_el->next_automata_list_el;
- free_automata_list_el (curr_automata_list_el);
- }
- }
- /* Hash value of AUTOMATA_LIST. */
- static hashval_t
- automata_list_hash (const void *automata_list)
- {
- unsigned int hash_value;
- const_automata_list_el_t curr_automata_list_el;
- hash_value = 0;
- for (curr_automata_list_el = (const_automata_list_el_t) automata_list;
- curr_automata_list_el != NULL;
- curr_automata_list_el = curr_automata_list_el->next_automata_list_el)
- hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
- | (hash_value << CHAR_BIT))
- + curr_automata_list_el->automaton->automaton_order_num);
- return hash_value;
- }
- /* Return nonzero value if the automata_lists are the same. */
- static int
- automata_list_eq_p (const void *automata_list_1, const void *automata_list_2)
- {
- const_automata_list_el_t automata_list_el_1;
- const_automata_list_el_t automata_list_el_2;
- for (automata_list_el_1 = (const_automata_list_el_t) automata_list_1,
- automata_list_el_2 = (const_automata_list_el_t) automata_list_2;
- automata_list_el_1 != NULL && automata_list_el_2 != NULL;
- automata_list_el_1 = automata_list_el_1->next_automata_list_el,
- automata_list_el_2 = automata_list_el_2->next_automata_list_el)
- if (automata_list_el_1->automaton != automata_list_el_2->automaton)
- return 0;
- return automata_list_el_1 == automata_list_el_2;
- }
- /* Initialization of the abstract data. */
- static void
- initiate_automata_lists (void)
- {
- first_free_automata_list_el = NULL;
- automata_list_table = htab_create (1500, automata_list_hash,
- automata_list_eq_p, (htab_del) 0);
- }
- /* The following function starts new automata list and makes it the
- current one. */
- static void
- automata_list_start (void)
- {
- current_automata_list = NULL;
- }
- /* The following function adds AUTOMATON to the current list. */
- static void
- automata_list_add (automaton_t automaton)
- {
- automata_list_el_t el;
- el = get_free_automata_list_el ();
- el->automaton = automaton;
- el->next_automata_list_el = current_automata_list;
- current_automata_list = el;
- }
- /* The following function finishes forming the current list, inserts
- it into the table and returns it. */
- static automata_list_el_t
- automata_list_finish (void)
- {
- void **entry_ptr;
- if (current_automata_list == NULL)
- return NULL;
- entry_ptr = htab_find_slot (automata_list_table,
- (void *) current_automata_list, INSERT);
- if (*entry_ptr == NULL)
- *entry_ptr = (void *) current_automata_list;
- else
- free_automata_list (current_automata_list);
- current_automata_list = NULL;
- return (automata_list_el_t) *entry_ptr;
- }
- /* Finishing work with the abstract data. */
- static void
- finish_automata_lists (void)
- {
- htab_delete (automata_list_table);
- }
- /* The page contains abstract data for work with exclusion sets (see
- exclusion_set in file rtl.def). */
- /* The following variable refers to an exclusion set returned by
- get_excl_set. This is bit string of length equal to cpu units
- number. If exclusion set for given unit contains 1 for a unit,
- then simultaneous reservation of the units is prohibited. */
- static reserv_sets_t excl_set;
- /* The array contains exclusion sets for each unit. */
- static reserv_sets_t *unit_excl_set_table;
- /* The following function forms the array containing exclusion sets
- for each unit. */
- static void
- initiate_excl_sets (void)
- {
- decl_t decl;
- reserv_sets_t unit_excl_set;
- unit_set_el_t el;
- int i;
- obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
- excl_set = (reserv_sets_t) obstack_base (&irp);
- obstack_finish (&irp);
- obstack_blank (&irp, description->units_num * sizeof (reserv_sets_t));
- unit_excl_set_table = (reserv_sets_t *) obstack_base (&irp);
- obstack_finish (&irp);
- /* Evaluate unit exclusion sets. */
- for (i = 0; i < description->decls_num; i++)
- {
- decl = description->decls [i];
- if (decl->mode == dm_unit)
- {
- obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
- unit_excl_set = (reserv_sets_t) obstack_base (&irp);
- obstack_finish (&irp);
- memset (unit_excl_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
- for (el = DECL_UNIT (decl)->excl_list;
- el != NULL;
- el = el->next_unit_set_el)
- {
- bitmap_set_bit (unit_excl_set, el->unit_decl->unit_num);
- el->unit_decl->in_set_p = TRUE;
- }
- unit_excl_set_table [DECL_UNIT (decl)->unit_num] = unit_excl_set;
- }
- }
- }
- /* The function sets up and return EXCL_SET which is union of
- exclusion sets for each unit in IN_SET. */
- static reserv_sets_t
- get_excl_set (reserv_sets_t in_set)
- {
- int el;
- unsigned int i;
- int start_unit_num;
- int unit_num;
- memset (excl_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
- for (el = 0; el < els_in_cycle_reserv; el++)
- if (in_set[el])
- for (i = 0; i < CHAR_BIT * sizeof (set_el_t); i++)
- if ((in_set[el] >> i) & 1)
- {
- start_unit_num = el * CHAR_BIT * sizeof (set_el_t) + i;
- if (start_unit_num >= description->units_num)
- return excl_set;
- for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
- {
- excl_set [unit_num]
- |= unit_excl_set_table [start_unit_num] [unit_num];
- }
- }
- return excl_set;
- }
- /* The page contains abstract data for work with presence/absence
- pattern sets (see presence_set/absence_set in file rtl.def). */
- /* The following arrays contain correspondingly presence, final
- presence, absence, and final absence patterns for each unit. */
- static pattern_reserv_t *unit_presence_set_table;
- static pattern_reserv_t *unit_final_presence_set_table;
- static pattern_reserv_t *unit_absence_set_table;
- static pattern_reserv_t *unit_final_absence_set_table;
- /* The following function forms list of reservation sets for given
- PATTERN_LIST. */
- static pattern_reserv_t
- form_reserv_sets_list (pattern_set_el_t pattern_list)
- {
- pattern_set_el_t el;
- pattern_reserv_t first, curr, prev;
- int i;
- prev = first = NULL;
- for (el = pattern_list; el != NULL; el = el->next_pattern_set_el)
- {
- curr = XCREATENODE (struct pattern_reserv);
- curr->reserv = alloc_empty_reserv_sets ();
- curr->next_pattern_reserv = NULL;
- for (i = 0; i < el->units_num; i++)
- {
- bitmap_set_bit (curr->reserv, el->unit_decls [i]->unit_num);
- el->unit_decls [i]->in_set_p = TRUE;
- }
- if (prev != NULL)
- prev->next_pattern_reserv = curr;
- else
- first = curr;
- prev = curr;
- }
- return first;
- }
- /* The following function forms the array containing presence and
- absence pattern sets for each unit. */
- static void
- initiate_presence_absence_pattern_sets (void)
- {
- decl_t decl;
- int i;
- obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
- unit_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
- obstack_finish (&irp);
- obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
- unit_final_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
- obstack_finish (&irp);
- obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
- unit_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
- obstack_finish (&irp);
- obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
- unit_final_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
- obstack_finish (&irp);
- /* Evaluate unit presence/absence sets. */
- for (i = 0; i < description->decls_num; i++)
- {
- decl = description->decls [i];
- if (decl->mode == dm_unit)
- {
- unit_presence_set_table [DECL_UNIT (decl)->unit_num]
- = form_reserv_sets_list (DECL_UNIT (decl)->presence_list);
- unit_final_presence_set_table [DECL_UNIT (decl)->unit_num]
- = form_reserv_sets_list (DECL_UNIT (decl)->final_presence_list);
- unit_absence_set_table [DECL_UNIT (decl)->unit_num]
- = form_reserv_sets_list (DECL_UNIT (decl)->absence_list);
- unit_final_absence_set_table [DECL_UNIT (decl)->unit_num]
- = form_reserv_sets_list (DECL_UNIT (decl)->final_absence_list);
- }
- }
- }
- /* The function checks that CHECKED_SET satisfies all presence pattern
- sets for units in ORIGINAL_SET. The function returns TRUE if it
- is ok. */
- static int
- check_presence_pattern_sets (reserv_sets_t checked_set,
- reserv_sets_t original_set,
- int final_p)
- {
- int el;
- unsigned int i;
- int start_unit_num;
- int unit_num;
- int presence_p;
- pattern_reserv_t pat_reserv;
- for (el = 0; el < els_in_cycle_reserv; el++)
- if (original_set[el])
- for (i = 0; i < CHAR_BIT * sizeof (set_el_t); i++)
- if ((original_set[el] >> i) & 1)
- {
- start_unit_num = el * CHAR_BIT * sizeof (set_el_t) + i;
- if (start_unit_num >= description->units_num)
- break;
- if ((final_p
- && unit_final_presence_set_table [start_unit_num] == NULL)
- || (!final_p
- && unit_presence_set_table [start_unit_num] == NULL))
- continue;
- presence_p = FALSE;
- for (pat_reserv = (final_p
- ? unit_final_presence_set_table [start_unit_num]
- : unit_presence_set_table [start_unit_num]);
- pat_reserv != NULL;
- pat_reserv = pat_reserv->next_pattern_reserv)
- {
- for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
- if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
- != pat_reserv->reserv [unit_num])
- break;
- presence_p = presence_p || unit_num >= els_in_cycle_reserv;
- }
- if (!presence_p)
- return FALSE;
- }
- return TRUE;
- }
- /* The function checks that CHECKED_SET satisfies all absence pattern
- sets for units in ORIGINAL_SET. The function returns TRUE if it
- is ok. */
- static int
- check_absence_pattern_sets (reserv_sets_t checked_set,
- reserv_sets_t original_set,
- int final_p)
- {
- int el;
- unsigned int i;
- int start_unit_num;
- int unit_num;
- pattern_reserv_t pat_reserv;
- for (el = 0; el < els_in_cycle_reserv; el++)
- if (original_set[el])
- for (i = 0; i < CHAR_BIT * sizeof (set_el_t); i++)
- if ((original_set[el] >> i) & 1)
- {
- start_unit_num = el * CHAR_BIT * sizeof (set_el_t) + i;
- if (start_unit_num >= description->units_num)
- break;
- for (pat_reserv = (final_p
- ? unit_final_absence_set_table [start_unit_num]
- : unit_absence_set_table [start_unit_num]);
- pat_reserv != NULL;
- pat_reserv = pat_reserv->next_pattern_reserv)
- {
- for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
- if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
- != pat_reserv->reserv [unit_num]
- && pat_reserv->reserv [unit_num])
- break;
- if (unit_num >= els_in_cycle_reserv)
- return FALSE;
- }
- }
- return TRUE;
- }
- /* This page contains code for transformation of original reservations
- described in .md file. The main goal of transformations is
- simplifying reservation and lifting up all `|' on the top of IR
- reservation representation. */
- /* The following function makes copy of IR representation of
- reservation. The function also substitutes all reservations
- defined by define_reservation by corresponding value during making
- the copy. */
- static regexp_t
- copy_insn_regexp (regexp_t regexp)
- {
- regexp_t result;
- int i;
- switch (regexp->mode)
- {
- case rm_reserv:
- result = copy_insn_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp);
- break;
- case rm_unit:
- result = XCOPYNODE (struct regexp, regexp);
- break;
- case rm_repeat:
- result = XCOPYNODE (struct regexp, regexp);
- REGEXP_REPEAT (result)->regexp
- = copy_insn_regexp (REGEXP_REPEAT (regexp)->regexp);
- break;
- case rm_sequence:
- result = XCOPYNODEVAR (struct regexp, regexp,
- sizeof (struct regexp) + sizeof (regexp_t)
- * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
- for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
- REGEXP_SEQUENCE (result)->regexps [i]
- = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
- break;
- case rm_allof:
- result = XCOPYNODEVAR (struct regexp, regexp,
- sizeof (struct regexp) + sizeof (regexp_t)
- * (REGEXP_ALLOF (regexp)->regexps_num - 1));
- for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
- REGEXP_ALLOF (result)->regexps [i]
- = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
- break;
- case rm_oneof:
- result = XCOPYNODEVAR (struct regexp, regexp,
- sizeof (struct regexp) + sizeof (regexp_t)
- * (REGEXP_ONEOF (regexp)->regexps_num - 1));
- for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
- REGEXP_ONEOF (result)->regexps [i]
- = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
- break;
- case rm_nothing:
- result = XCOPYNODE (struct regexp, regexp);
- break;
- default:
- gcc_unreachable ();
- }
- return result;
- }
- /* The following variable is set up 1 if a transformation has been
- applied. */
- static int regexp_transformed_p;
- /* The function makes transformation
- A*N -> A, A, ... */
- static regexp_t
- transform_1 (regexp_t regexp)
- {
- int i;
- int repeat_num;
- regexp_t operand;
- pos_t pos;
- if (regexp->mode == rm_repeat)
- {
- repeat_num = REGEXP_REPEAT (regexp)->repeat_num;
- gcc_assert (repeat_num > 1);
- operand = REGEXP_REPEAT (regexp)->regexp;
- pos = regexp->mode;
- regexp = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
- + sizeof (regexp_t) * (repeat_num - 1));
- regexp->mode = rm_sequence;
- regexp->pos = pos;
- REGEXP_SEQUENCE (regexp)->regexps_num = repeat_num;
- for (i = 0; i < repeat_num; i++)
- REGEXP_SEQUENCE (regexp)->regexps [i] = copy_insn_regexp (operand);
- regexp_transformed_p = 1;
- }
- return regexp;
- }
- /* The function makes transformations
- ...,(A,B,...),C,... -> ...,A,B,...,C,...
- ...+(A+B+...)+C+... -> ...+A+B+...+C+...
- ...|(A|B|...)|C|... -> ...|A|B|...|C|... */
- static regexp_t
- transform_2 (regexp_t regexp)
- {
- if (regexp->mode == rm_sequence)
- {
- regexp_t sequence = NULL;
- regexp_t result;
- int sequence_index = 0;
- int i, j;
- for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
- if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_sequence)
- {
- sequence_index = i;
- sequence = REGEXP_SEQUENCE (regexp)->regexps [i];
- break;
- }
- if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
- {
- gcc_assert (REGEXP_SEQUENCE (sequence)->regexps_num > 1
- && REGEXP_SEQUENCE (regexp)->regexps_num > 1);
- result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
- + sizeof (regexp_t)
- * (REGEXP_SEQUENCE (regexp)->regexps_num
- + REGEXP_SEQUENCE (sequence)->regexps_num
- - 2));
- result->mode = rm_sequence;
- result->pos = regexp->pos;
- REGEXP_SEQUENCE (result)->regexps_num
- = (REGEXP_SEQUENCE (regexp)->regexps_num
- + REGEXP_SEQUENCE (sequence)->regexps_num - 1);
- for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
- if (i < sequence_index)
- REGEXP_SEQUENCE (result)->regexps [i]
- = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
- else if (i > sequence_index)
- REGEXP_SEQUENCE (result)->regexps
- [i + REGEXP_SEQUENCE (sequence)->regexps_num - 1]
- = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
- else
- for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
- REGEXP_SEQUENCE (result)->regexps [i + j]
- = copy_insn_regexp (REGEXP_SEQUENCE (sequence)->regexps [j]);
- regexp_transformed_p = 1;
- regexp = result;
- }
- }
- else if (regexp->mode == rm_allof)
- {
- regexp_t allof = NULL;
- regexp_t result;
- int allof_index = 0;
- int i, j;
- for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
- if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_allof)
- {
- allof_index = i;
- allof = REGEXP_ALLOF (regexp)->regexps [i];
- break;
- }
- if (i < REGEXP_ALLOF (regexp)->regexps_num)
- {
- gcc_assert (REGEXP_ALLOF (allof)->regexps_num > 1
- && REGEXP_ALLOF (regexp)->regexps_num > 1);
- result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
- + sizeof (regexp_t)
- * (REGEXP_ALLOF (regexp)->regexps_num
- + REGEXP_ALLOF (allof)->regexps_num - 2));
- result->mode = rm_allof;
- result->pos = regexp->pos;
- REGEXP_ALLOF (result)->regexps_num
- = (REGEXP_ALLOF (regexp)->regexps_num
- + REGEXP_ALLOF (allof)->regexps_num - 1);
- for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
- if (i < allof_index)
- REGEXP_ALLOF (result)->regexps [i]
- = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
- else if (i > allof_index)
- REGEXP_ALLOF (result)->regexps
- [i + REGEXP_ALLOF (allof)->regexps_num - 1]
- = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
- else
- for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
- REGEXP_ALLOF (result)->regexps [i + j]
- = copy_insn_regexp (REGEXP_ALLOF (allof)->regexps [j]);
- regexp_transformed_p = 1;
- regexp = result;
- }
- }
- else if (regexp->mode == rm_oneof)
- {
- regexp_t oneof = NULL;
- regexp_t result;
- int oneof_index = 0;
- int i, j;
- for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
- if (REGEXP_ONEOF (regexp)->regexps [i]->mode == rm_oneof)
- {
- oneof_index = i;
- oneof = REGEXP_ONEOF (regexp)->regexps [i];
- break;
- }
- if (i < REGEXP_ONEOF (regexp)->regexps_num)
- {
- gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
- && REGEXP_ONEOF (regexp)->regexps_num > 1);
- result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
- + sizeof (regexp_t)
- * (REGEXP_ONEOF (regexp)->regexps_num
- + REGEXP_ONEOF (oneof)->regexps_num - 2));
- result->mode = rm_oneof;
- result->pos = regexp->pos;
- REGEXP_ONEOF (result)->regexps_num
- = (REGEXP_ONEOF (regexp)->regexps_num
- + REGEXP_ONEOF (oneof)->regexps_num - 1);
- for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
- if (i < oneof_index)
- REGEXP_ONEOF (result)->regexps [i]
- = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
- else if (i > oneof_index)
- REGEXP_ONEOF (result)->regexps
- [i + REGEXP_ONEOF (oneof)->regexps_num - 1]
- = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
- else
- for (j = 0; j < REGEXP_ONEOF (oneof)->regexps_num; j++)
- REGEXP_ONEOF (result)->regexps [i + j]
- = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [j]);
- regexp_transformed_p = 1;
- regexp = result;
- }
- }
- return regexp;
- }
- /* The function makes transformations
- ...,A|B|...,C,... -> (...,A,C,...)|(...,B,C,...)|...
- ...+(A|B|...)+C+... -> (...+A+C+...)|(...+B+C+...)|...
- ...+(A,B,...)+C+... -> (...+A+C+...),B,...
- ...+(A,B,...)+(C,D,...) -> (A+C),(B+D),... */
- static regexp_t
- transform_3 (regexp_t regexp)
- {
- if (regexp->mode == rm_sequence)
- {
- regexp_t oneof = NULL;
- int oneof_index = 0;
- regexp_t result;
- regexp_t sequence;
- int i, j;
- for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
- if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_oneof)
- {
- oneof_index = i;
- oneof = REGEXP_SEQUENCE (regexp)->regexps [i];
- break;
- }
- if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
- {
- gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
- && REGEXP_SEQUENCE (regexp)->regexps_num > 1);
- result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
- + sizeof (regexp_t)
- * (REGEXP_ONEOF (oneof)->regexps_num - 1));
- result->mode = rm_oneof;
- result->pos = regexp->pos;
- REGEXP_ONEOF (result)->regexps_num
- = REGEXP_ONEOF (oneof)->regexps_num;
- for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
- {
- sequence
- = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
- + sizeof (regexp_t)
- * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
- sequence->mode = rm_sequence;
- sequence->pos = regexp->pos;
- REGEXP_SEQUENCE (sequence)->regexps_num
- = REGEXP_SEQUENCE (regexp)->regexps_num;
- REGEXP_ONEOF (result)->regexps [i] = sequence;
- for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
- if (j != oneof_index)
- REGEXP_SEQUENCE (sequence)->regexps [j]
- = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [j]);
- else
- REGEXP_SEQUENCE (sequence)->regexps [j]
- = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
- }
- regexp_transformed_p = 1;
- regexp = result;
- }
- }
- else if (regexp->mode == rm_allof)
- {
- regexp_t oneof = NULL;
- regexp_t seq;
- int oneof_index = 0;
- int max_seq_length, allof_length;
- regexp_t result;
- regexp_t allof = NULL;
- regexp_t allof_op = NULL;
- int i, j;
- for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
- if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_oneof)
- {
- oneof_index = i;
- oneof = REGEXP_ALLOF (regexp)->regexps [i];
- break;
- }
- if (i < REGEXP_ALLOF (regexp)->regexps_num)
- {
- gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
- && REGEXP_ALLOF (regexp)->regexps_num > 1);
- result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
- + sizeof (regexp_t)
- * (REGEXP_ONEOF (oneof)->regexps_num - 1));
- result->mode = rm_oneof;
- result->pos = regexp->pos;
- REGEXP_ONEOF (result)->regexps_num
- = REGEXP_ONEOF (oneof)->regexps_num;
- for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
- {
- allof
- = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
- + sizeof (regexp_t)
- * (REGEXP_ALLOF (regexp)->regexps_num - 1));
- allof->mode = rm_allof;
- allof->pos = regexp->pos;
- REGEXP_ALLOF (allof)->regexps_num
- = REGEXP_ALLOF (regexp)->regexps_num;
- REGEXP_ONEOF (result)->regexps [i] = allof;
- for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
- if (j != oneof_index)
- REGEXP_ALLOF (allof)->regexps [j]
- = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [j]);
- else
- REGEXP_ALLOF (allof)->regexps [j]
- = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
- }
- regexp_transformed_p = 1;
- regexp = result;
- }
- max_seq_length = 0;
- if (regexp->mode == rm_allof)
- for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
- {
- switch (REGEXP_ALLOF (regexp)->regexps [i]->mode)
- {
- case rm_sequence:
- seq = REGEXP_ALLOF (regexp)->regexps [i];
- if (max_seq_length < REGEXP_SEQUENCE (seq)->regexps_num)
- max_seq_length = REGEXP_SEQUENCE (seq)->regexps_num;
- break;
- case rm_unit:
- case rm_nothing:
- break;
- default:
- max_seq_length = 0;
- goto break_for;
- }
- }
- break_for:
- if (max_seq_length != 0)
- {
- gcc_assert (max_seq_length != 1
- && REGEXP_ALLOF (regexp)->regexps_num > 1);
- result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
- + sizeof (regexp_t) * (max_seq_length - 1));
- result->mode = rm_sequence;
- result->pos = regexp->pos;
- REGEXP_SEQUENCE (result)->regexps_num = max_seq_length;
- for (i = 0; i < max_seq_length; i++)
- {
- allof_length = 0;
- for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
- switch (REGEXP_ALLOF (regexp)->regexps [j]->mode)
- {
- case rm_sequence:
- if (i < (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
- ->regexps [j])->regexps_num))
- {
- allof_op
- = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
- ->regexps [j])
- ->regexps [i]);
- allof_length++;
- }
- break;
- case rm_unit:
- case rm_nothing:
- if (i == 0)
- {
- allof_op = REGEXP_ALLOF (regexp)->regexps [j];
- allof_length++;
- }
- break;
- default:
- break;
- }
- if (allof_length == 1)
- REGEXP_SEQUENCE (result)->regexps [i] = allof_op;
- else
- {
- allof = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
- + sizeof (regexp_t)
- * (allof_length - 1));
- allof->mode = rm_allof;
- allof->pos = regexp->pos;
- REGEXP_ALLOF (allof)->regexps_num = allof_length;
- REGEXP_SEQUENCE (result)->regexps [i] = allof;
- allof_length = 0;
- for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
- if (REGEXP_ALLOF (regexp)->regexps [j]->mode == rm_sequence
- && (i <
- (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
- ->regexps [j])->regexps_num)))
- {
- allof_op = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
- ->regexps [j])
- ->regexps [i]);
- REGEXP_ALLOF (allof)->regexps [allof_length]
- = allof_op;
- allof_length++;
- }
- else if (i == 0
- && (REGEXP_ALLOF (regexp)->regexps [j]->mode
- == rm_unit
- || (REGEXP_ALLOF (regexp)->regexps [j]->mode
- == rm_nothing)))
- {
- allof_op = REGEXP_ALLOF (regexp)->regexps [j];
- REGEXP_ALLOF (allof)->regexps [allof_length]
- = allof_op;
- allof_length++;
- }
- }
- }
- regexp_transformed_p = 1;
- regexp = result;
- }
- }
- return regexp;
- }
- /* The function traverses IR of reservation and applies transformations
- implemented by FUNC. */
- static regexp_t
- regexp_transform_func (regexp_t regexp, regexp_t (*func) (regexp_t regexp))
- {
- int i;
- switch (regexp->mode)
- {
- case rm_sequence:
- for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
- REGEXP_SEQUENCE (regexp)->regexps [i]
- = regexp_transform_func (REGEXP_SEQUENCE (regexp)->regexps [i],
- func);
- break;
- case rm_allof:
- for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
- REGEXP_ALLOF (regexp)->regexps [i]
- = regexp_transform_func (REGEXP_ALLOF (regexp)->regexps [i], func);
- break;
- case rm_oneof:
- for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
- REGEXP_ONEOF (regexp)->regexps [i]
- = regexp_transform_func (REGEXP_ONEOF (regexp)->regexps [i], func);
- break;
- case rm_repeat:
- REGEXP_REPEAT (regexp)->regexp
- = regexp_transform_func (REGEXP_REPEAT (regexp)->regexp, func);
- break;
- case rm_nothing:
- case rm_unit:
- break;
- default:
- gcc_unreachable ();
- }
- return (*func) (regexp);
- }
- /* The function applies all transformations for IR representation of
- reservation REGEXP. */
- static regexp_t
- transform_regexp (regexp_t regexp)
- {
- regexp = regexp_transform_func (regexp, transform_1);
- do
- {
- regexp_transformed_p = 0;
- regexp = regexp_transform_func (regexp, transform_2);
- regexp = regexp_transform_func (regexp, transform_3);
- }
- while (regexp_transformed_p);
- return regexp;
- }
- /* The function applies all transformations for reservations of all
- insn declarations. */
- static void
- transform_insn_regexps (void)
- {
- decl_t decl;
- int i;
- transform_time = create_ticker ();
- add_advance_cycle_insn_decl ();
- if (collapse_flag)
- add_collapse_ndfa_insn_decl ();
- if (progress_flag)
- fprintf (stderr, "Reservation transformation...");
- for (i = 0; i < description->normal_decls_num; i++)
- {
- decl = description->decls [i];
- if (decl->mode == dm_insn_reserv)
- DECL_INSN_RESERV (decl)->transformed_regexp
- = transform_regexp (copy_insn_regexp
- (DECL_INSN_RESERV (decl)->regexp));
- }
- if (progress_flag)
- fprintf (stderr, "done\n");
- ticker_off (&transform_time);
- }
- /* The following variable value is TRUE if the first annotated message
- about units to automata distribution has been output. */
- static int annotation_message_reported_p;
- /* The vector contains all decls which are automata. */
- static vec<decl_t> automaton_decls;
- /* The following structure describes usage of a unit in a reservation. */
- struct unit_usage
- {
- unit_decl_t unit_decl;
- /* The following forms a list of units used on the same cycle in the
- same alternative. The list is ordered by the correspdoning unit
- declarations and there is no unit declaration duplication in the
- list. */
- struct unit_usage *next;
- };
- typedef struct unit_usage *unit_usage_t;
- /* Obstack for unit_usage structures. */
- static struct obstack unit_usages;
- /* VLA for representation of array of pointers to unit usage
- structures. There is an element for each combination of
- (alternative number, cycle). Unit usages on given cycle in
- alternative with given number are referred through element with
- index equals to the cycle * number of all alternatives in the
- regexp + the alternative number. */
- static vec<unit_usage_t> cycle_alt_unit_usages;
- /* The following function creates the structure unit_usage for UNIT on
- CYCLE in REGEXP alternative with ALT_NUM. The structure is made
- accessed through cycle_alt_unit_usages. */
- static void
- store_alt_unit_usage (regexp_t regexp, regexp_t unit, int cycle,
- int alt_num)
- {
- size_t length;
- unit_decl_t unit_decl;
- unit_usage_t unit_usage_ptr, curr, prev;
- int index;
- gcc_assert (regexp && regexp->mode == rm_oneof
- && alt_num < REGEXP_ONEOF (regexp)->regexps_num);
- unit_decl = REGEXP_UNIT (unit)->unit_decl;
- length = (cycle + 1) * REGEXP_ONEOF (regexp)->regexps_num;
- while (cycle_alt_unit_usages.length () < length)
- cycle_alt_unit_usages.safe_push (NULL);
- index = cycle * REGEXP_ONEOF (regexp)->regexps_num + alt_num;
- prev = NULL;
- for (curr = cycle_alt_unit_usages[index];
- curr != NULL;
- prev = curr, curr = curr->next)
- if (curr->unit_decl >= unit_decl)
- break;
- if (curr != NULL && curr->unit_decl == unit_decl)
- return;
- obstack_blank (&unit_usages, sizeof (struct unit_usage));
- unit_usage_ptr = (struct unit_usage *) obstack_base (&unit_usages);
- obstack_finish (&unit_usages);
- unit_usage_ptr->unit_decl = unit_decl;
- unit_decl->last_distribution_check_cycle = -1; /* undefined */
- unit_usage_ptr->next = curr;
- if (prev == NULL)
- cycle_alt_unit_usages[index] = unit_usage_ptr;
- else
- prev->next = unit_usage_ptr;
- }
- /* Return true if unit UNIT_DECL is present on the LIST. */
- static bool
- unit_present_on_list_p (unit_usage_t list, unit_decl_t unit_decl)
- {
- while (list != NULL)
- {
- if (list->unit_decl == unit_decl)
- return true;
- list = list->next;
- }
- return false;
- }
- /* The function returns true if reservations of alternatives ALT1 and
- ALT2 are equal after excluding reservations of units of
- EXCLUDED_AUTOMATON_DECL. */
- static bool
- equal_alternatives_p (int alt1, int alt2, int n_alts,
- struct automaton_decl *excluded_automaton_decl)
- {
- int i;
- unit_usage_t list1, list2;
- for (i = 0;
- i < (int) cycle_alt_unit_usages.length ();
- i += n_alts)
- {
- for (list1 = cycle_alt_unit_usages[i + alt1],
- list2 = cycle_alt_unit_usages[i + alt2];;
- list1 = list1->next, list2 = list2->next)
- {
- while (list1 != NULL
- && list1->unit_decl->automaton_decl == excluded_automaton_decl)
- list1 = list1->next;
- while (list2 != NULL
- && list2->unit_decl->automaton_decl == excluded_automaton_decl)
- list2 = list2->next;
- if (list1 == NULL || list2 == NULL)
- {
- if (list1 != list2)
- return false;
- else
- break;
- }
- if (list1->unit_decl != list2->unit_decl)
- return false;
- }
- }
- return true;
- }
- /* The function processes given REGEXP to find units with the wrong
- distribution. */
- static void
- check_regexp_units_distribution (const char *insn_reserv_name,
- regexp_t regexp)
- {
- int i, j, k, cycle, start, n_alts, alt, alt2;
- bool annotation_reservation_message_reported_p;
- regexp_t seq, allof, unit;
- struct unit_usage *unit_usage_ptr;
- if (regexp == NULL || regexp->mode != rm_oneof)
- return;
- /* Store all unit usages in the regexp: */
- obstack_init (&unit_usages);
- cycle_alt_unit_usages.create (10);
- for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
- {
- seq = REGEXP_ONEOF (regexp)->regexps [i];
- switch (seq->mode)
- {
- case rm_sequence:
- for (j = 0; j < REGEXP_SEQUENCE (seq)->regexps_num; j++)
- {
- allof = REGEXP_SEQUENCE (seq)->regexps [j];
- switch (allof->mode)
- {
- case rm_allof:
- for (k = 0; k < REGEXP_ALLOF (allof)->regexps_num; k++)
- {
- unit = REGEXP_ALLOF (allof)->regexps [k];
- if (unit->mode == rm_unit)
- store_alt_unit_usage (regexp, unit, j, i);
- else
- gcc_assert (unit->mode == rm_nothing);
- }
- break;
- case rm_unit:
- store_alt_unit_usage (regexp, allof, j, i);
- break;
- case rm_nothing:
- break;
- default:
- gcc_unreachable ();
- }
- }
- break;
- case rm_allof:
- for (k = 0; k < REGEXP_ALLOF (seq)->regexps_num; k++)
- {
- unit = REGEXP_ALLOF (seq)->regexps [k];
- switch (unit->mode)
- {
- case rm_unit:
- store_alt_unit_usage (regexp, unit, 0, i);
- break;
- case rm_nothing:
- break;
- default:
- gcc_unreachable ();
- }
- }
- break;
- case rm_unit:
- store_alt_unit_usage (regexp, seq, 0, i);
- break;
- case rm_nothing:
- break;
- default:
- gcc_unreachable ();
- }
- }
- /* Check distribution: */
- for (i = 0; i < (int) cycle_alt_unit_usages.length (); i++)
- for (unit_usage_ptr = cycle_alt_unit_usages[i];
- unit_usage_ptr != NULL;
- unit_usage_ptr = unit_usage_ptr->next)
- unit_usage_ptr->unit_decl->last_distribution_check_cycle = -1;
- n_alts = REGEXP_ONEOF (regexp)->regexps_num;
- auto_vec<int> marked (n_alts);
- for (i = 0; i < n_alts; i++)
- marked.safe_push (0);
- annotation_reservation_message_reported_p = false;
- for (i = 0; i < (int) cycle_alt_unit_usages.length (); i++)
- {
- cycle = i / n_alts;
- start = cycle * n_alts;
- for (unit_usage_ptr = cycle_alt_unit_usages[i];
- unit_usage_ptr != NULL;
- unit_usage_ptr = unit_usage_ptr->next)
- {
- if (unit_usage_ptr->unit_decl->last_distribution_check_cycle == cycle)
- continue;
- unit_usage_ptr->unit_decl->last_distribution_check_cycle = cycle;
- for (alt = 0; alt < n_alts; alt++)
- if (! unit_present_on_list_p (cycle_alt_unit_usages[start + alt],
- unit_usage_ptr->unit_decl))
- break;
- if (alt >= n_alts)
- continue;
- memset (marked.address (), 0, n_alts * sizeof (int));
- for (alt = 0; alt < n_alts; alt++)
- {
- if (! unit_present_on_list_p (cycle_alt_unit_usages[start + alt],
- unit_usage_ptr->unit_decl))
- continue;
- for (j = 0;
- j < (int) cycle_alt_unit_usages.length ();
- j++)
- {
- alt2 = j % n_alts;
- if (! unit_present_on_list_p
- (cycle_alt_unit_usages[start + alt2],
- unit_usage_ptr->unit_decl)
- && equal_alternatives_p (alt, alt2, n_alts,
- unit_usage_ptr
- ->unit_decl->automaton_decl))
- {
- marked[alt] = 1;
- marked[alt2] = 1;
- }
- }
- }
- for (alt = 0; alt < n_alts && marked[alt]; alt++)
- ;
- if (alt < n_alts && 0)
- {
- if (! annotation_message_reported_p)
- {
- fprintf (stderr, "\n");
- error ("The following units do not satisfy units-automata distribution rule");
- error ("(Unit presence on one alt and its absence on other alt\n");
- error (" result in different other automata reservations)");
- annotation_message_reported_p = TRUE;
- }
- if (! annotation_reservation_message_reported_p)
- {
- error ("Reserv %s:", insn_reserv_name);
- annotation_reservation_message_reported_p = true;
- }
- error (" Unit %s, cycle %d, alt %d, another alt %d",
- unit_usage_ptr->unit_decl->name, cycle, i % n_alts, alt);
- }
- }
- }
- cycle_alt_unit_usages.release ();
- obstack_free (&unit_usages, NULL);
- }
- /* The function finds units which violates units to automata
- distribution rule. If the units exist, report about them. */
- static void
- check_unit_distributions_to_automata (void)
- {
- decl_t decl;
- int i;
- if (progress_flag)
- fprintf (stderr, "Check unit distributions to automata...");
- automaton_decls.create (0);
- for (i = 0; i < description->decls_num; i++)
- {
- decl = description->decls [i];
- if (decl->mode == dm_automaton)
- automaton_decls.safe_push (decl);
- }
- if (automaton_decls.length () > 1)
- {
- annotation_message_reported_p = FALSE;
- for (i = 0; i < description->decls_num; i++)
- {
- decl = description->decls [i];
- if (decl->mode == dm_insn_reserv)
- check_regexp_units_distribution
- (DECL_INSN_RESERV (decl)->name,
- DECL_INSN_RESERV (decl)->transformed_regexp);
- }
- }
- automaton_decls.release ();
- if (progress_flag)
- fprintf (stderr, "done\n");
- }
- /* The page contains code for building alt_states (see comments for
- IR) describing all possible insns reservations of an automaton. */
- /* Current state being formed for which the current alt_state
- refers. */
- static state_t state_being_formed;
- /* Current alt_state being formed. */
- static alt_state_t alt_state_being_formed;
- /* This recursive function processes `,' and units in reservation
- REGEXP for forming alt_states of AUTOMATON. It is believed that
- CURR_CYCLE is start cycle of all reservation REGEXP. */
- static int
- process_seq_for_forming_states (regexp_t regexp, automaton_t automaton,
- int curr_cycle)
- {
- int i;
- if (regexp == NULL)
- return curr_cycle;
- switch (regexp->mode)
- {
- case rm_unit:
- if (REGEXP_UNIT (regexp)->unit_decl->corresponding_automaton_num
- == automaton->automaton_order_num)
- set_state_reserv (state_being_formed, curr_cycle,
- REGEXP_UNIT (regexp)->unit_decl->unit_num);
- return curr_cycle;
- case rm_sequence:
- for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
- curr_cycle
- = process_seq_for_forming_states
- (REGEXP_SEQUENCE (regexp)->regexps [i], automaton, curr_cycle) + 1;
- return curr_cycle;
- case rm_allof:
- {
- int finish_cycle = 0;
- int cycle;
- for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
- {
- cycle = process_seq_for_forming_states (REGEXP_ALLOF (regexp)
- ->regexps [i],
- automaton, curr_cycle);
- if (finish_cycle < cycle)
- finish_cycle = cycle;
- }
- return finish_cycle;
- }
- case rm_nothing:
- return curr_cycle;
- default:
- gcc_unreachable ();
- }
- }
- /* This recursive function finishes forming ALT_STATE of AUTOMATON and
- inserts alt_state into the table. */
- static void
- finish_forming_alt_state (alt_state_t alt_state,
- automaton_t automaton ATTRIBUTE_UNUSED)
- {
- state_t state_in_table;
- state_t corresponding_state;
- corresponding_state = alt_state->state;
- state_in_table = insert_state (corresponding_state);
- if (state_in_table != corresponding_state)
- {
- free_state (corresponding_state);
- alt_state->state = state_in_table;
- }
- }
- /* The following variable value is current automaton insn for whose
- reservation the alt states are created. */
- static ainsn_t curr_ainsn;
- /* This recursive function processes `|' in reservation REGEXP for
- forming alt_states of AUTOMATON. List of the alt states should
- have the same order as in the description. */
- static void
- process_alts_for_forming_states (regexp_t regexp, automaton_t automaton,
- int inside_oneof_p)
- {
- int i;
- if (regexp->mode != rm_oneof)
- {
- alt_state_being_formed = get_free_alt_state ();
- state_being_formed = get_free_state (1, automaton);
- alt_state_being_formed->state = state_being_formed;
- /* We inserts in reverse order but we process alternatives also
- in reverse order. So we have the same order of alternative
- as in the description. */
- alt_state_being_formed->next_alt_state = curr_ainsn->alt_states;
- curr_ainsn->alt_states = alt_state_being_formed;
- (void) process_seq_for_forming_states (regexp, automaton, 0);
- finish_forming_alt_state (alt_state_being_formed, automaton);
- }
- else
- {
- gcc_assert (!inside_oneof_p);
- /* We processes it in reverse order to get list with the same
- order as in the description. See also the previous
- commentary. */
- for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
- process_alts_for_forming_states (REGEXP_ONEOF (regexp)->regexps [i],
- automaton, 1);
- }
- }
- /* Create nodes alt_state for all AUTOMATON insns. */
- static void
- create_alt_states (automaton_t automaton)
- {
- struct insn_reserv_decl *reserv_decl;
- for (curr_ainsn = automaton->ainsn_list;
- curr_ainsn != NULL;
- curr_ainsn = curr_ainsn->next_ainsn)
- {
- reserv_decl = curr_ainsn->insn_reserv_decl;
- if (!special_decl_p (reserv_decl))
- {
- curr_ainsn->alt_states = NULL;
- process_alts_for_forming_states (reserv_decl->transformed_regexp,
- automaton, 0);
- curr_ainsn->sorted_alt_states
- = uniq_sort_alt_states (curr_ainsn->alt_states);
- }
- }
- }
- /* The page contains major code for building DFA(s) for fast pipeline
- hazards recognition. */
- /* The function forms list of ainsns of AUTOMATON with the same
- reservation. */
- static void
- form_ainsn_with_same_reservs (automaton_t automaton)
- {
- ainsn_t curr_ainsn;
- size_t i;
- auto_vec<ainsn_t, 150> last_insns;
- for (curr_ainsn = automaton->ainsn_list;
- curr_ainsn != NULL;
- curr_ainsn = curr_ainsn->next_ainsn)
- if (special_decl_p (curr_ainsn->insn_reserv_decl))
- {
- curr_ainsn->next_same_reservs_insn = NULL;
- curr_ainsn->first_insn_with_same_reservs = 1;
- }
- else
- {
- for (i = 0; i < last_insns.length (); i++)
- if (alt_states_eq
- (curr_ainsn->sorted_alt_states,
- last_insns[i]->sorted_alt_states))
- break;
- curr_ainsn->next_same_reservs_insn = NULL;
- if (i < last_insns.length ())
- {
- curr_ainsn->first_insn_with_same_reservs = 0;
- last_insns[i]->next_same_reservs_insn = curr_ainsn;
- last_insns[i] = curr_ainsn;
- }
- else
- {
- last_insns.safe_push (curr_ainsn);
- curr_ainsn->first_insn_with_same_reservs = 1;
- }
- }
- }
- /* Forming unit reservations which can affect creating the automaton
- states achieved from a given state. It permits to build smaller
- automata in many cases. We would have the same automata after
- the minimization without such optimization, but the automaton
- right after the building could be huge. So in other words, usage
- of reservs_matter means some minimization during building the
- automaton. */
- static reserv_sets_t
- form_reservs_matter (automaton_t automaton)
- {
- int cycle, unit;
- reserv_sets_t reservs_matter = alloc_empty_reserv_sets ();
- for (cycle = 0; cycle < max_cycles_num; cycle++)
- for (unit = 0; unit < description->units_num; unit++)
- if (units_array [unit]->automaton_decl
- == automaton->corresponding_automaton_decl
- && (cycle >= units_array [unit]->min_occ_cycle_num
- /* We can not remove queried unit from reservations. */
- || units_array [unit]->query_p
- /* We can not remove units which are used
- `exclusion_set', `presence_set',
- `final_presence_set', `absence_set', and
- `final_absence_set'. */
- || units_array [unit]->in_set_p))
- set_unit_reserv (reservs_matter, cycle, unit);
- return reservs_matter;
- }
- /* The following function creates all states of nondeterministic AUTOMATON. */
- static void
- make_automaton (automaton_t automaton)
- {
- ainsn_t ainsn;
- struct insn_reserv_decl *insn_reserv_decl;
- alt_state_t alt_state;
- state_t state;
- state_t start_state;
- state_t state2;
- auto_vec<state_t, 150> state_stack;
- int states_n;
- reserv_sets_t reservs_matter = form_reservs_matter (automaton);
- /* Create the start state (empty state). */
- start_state = insert_state (get_free_state (1, automaton));
- automaton->start_state = start_state;
- start_state->it_was_placed_in_stack_for_NDFA_forming = 1;
- state_stack.safe_push (start_state);
- states_n = 1;
- while (state_stack.length () != 0)
- {
- state = state_stack.pop ();
- for (ainsn = automaton->ainsn_list;
- ainsn != NULL;
- ainsn = ainsn->next_ainsn)
- if (ainsn->first_insn_with_same_reservs)
- {
- insn_reserv_decl = ainsn->insn_reserv_decl;
- if (!special_decl_p (insn_reserv_decl))
- {
- /* We process alt_states in the same order as they are
- present in the description. */
- for (alt_state = ainsn->alt_states;
- alt_state != NULL;
- alt_state = alt_state->next_alt_state)
- {
- state2 = alt_state->state;
- if (!intersected_state_reservs_p (state, state2))
- {
- state2 = states_union (state, state2, reservs_matter);
- if (!state2->it_was_placed_in_stack_for_NDFA_forming)
- {
- state2->it_was_placed_in_stack_for_NDFA_forming
- = 1;
- state_stack.safe_push (state2);
- states_n++;
- if (progress_flag && states_n % 100 == 0)
- fprintf (stderr, ".");
- }
- add_arc (state, state2, ainsn);
- if (!ndfa_flag)
- break;
- }
- }
- }
- }
- /* Add transition to advance cycle. */
- state2 = state_shift (state, reservs_matter);
- if (!state2->it_was_placed_in_stack_for_NDFA_forming)
- {
- state2->it_was_placed_in_stack_for_NDFA_forming = 1;
- state_stack.safe_push (state2);
- states_n++;
- if (progress_flag && states_n % 100 == 0)
- fprintf (stderr, ".");
- }
- add_arc (state, state2, automaton->advance_ainsn);
- }
- }
- /* Form lists of all arcs of STATE marked by the same ainsn. */
- static void
- form_arcs_marked_by_insn (state_t state)
- {
- decl_t decl;
- arc_t arc;
- int i;
- for (i = 0; i < description->decls_num; i++)
- {
- decl = description->decls [i];
- if (decl->mode == dm_insn_reserv)
- DECL_INSN_RESERV (decl)->arcs_marked_by_insn = NULL;
- }
- for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
- {
- gcc_assert (arc->insn);
- arc->next_arc_marked_by_insn
- = arc->insn->insn_reserv_decl->arcs_marked_by_insn;
- arc->insn->insn_reserv_decl->arcs_marked_by_insn = arc;
- }
- }
- /* The function creates composed state (see comments for IR) from
- ORIGINAL_STATE and list of arcs ARCS_MARKED_BY_INSN marked by the
- same insn. If the composed state is not in STATE_STACK yet, it is
- pushed into STATE_STACK. */
- static int
- create_composed_state (state_t original_state, arc_t arcs_marked_by_insn,
- vec<state_t> *state_stack)
- {
- state_t state;
- alt_state_t alt_state, curr_alt_state;
- alt_state_t new_alt_state;
- arc_t curr_arc;
- arc_t next_arc;
- state_t state_in_table;
- state_t temp_state;
- alt_state_t canonical_alt_states_list;
- int alts_number;
- int new_state_p = 0;
- if (arcs_marked_by_insn == NULL)
- return new_state_p;
- if (arcs_marked_by_insn->next_arc_marked_by_insn == NULL)
- state = arcs_marked_by_insn->to_state;
- else
- {
- gcc_assert (ndfa_flag);
- /* Create composed state. */
- state = get_free_state (0, arcs_marked_by_insn->to_state->automaton);
- curr_alt_state = NULL;
- for (curr_arc = arcs_marked_by_insn;
- curr_arc != NULL;
- curr_arc = curr_arc->next_arc_marked_by_insn)
- if (curr_arc->to_state->component_states == NULL)
- {
- new_alt_state = get_free_alt_state ();
- new_alt_state->next_alt_state = curr_alt_state;
- new_alt_state->state = curr_arc->to_state;
- curr_alt_state = new_alt_state;
- }
- else
- for (alt_state = curr_arc->to_state->component_states;
- alt_state != NULL;
- alt_state = alt_state->next_sorted_alt_state)
- {
- new_alt_state = get_free_alt_state ();
- new_alt_state->next_alt_state = curr_alt_state;
- new_alt_state->state = alt_state->state;
- gcc_assert (!alt_state->state->component_states);
- curr_alt_state = new_alt_state;
- }
- /* There are not identical sets in the alt state list. */
- canonical_alt_states_list = uniq_sort_alt_states (curr_alt_state);
- if (canonical_alt_states_list->next_sorted_alt_state == NULL)
- {
- temp_state = state;
- state = canonical_alt_states_list->state;
- free_state (temp_state);
- }
- else
- {
- state->component_states = canonical_alt_states_list;
- state_in_table = insert_state (state);
- if (state_in_table != state)
- {
- gcc_assert
- (state_in_table->it_was_placed_in_stack_for_DFA_forming);
- free_state (state);
- state = state_in_table;
- }
- else
- {
- gcc_assert (!state->it_was_placed_in_stack_for_DFA_forming);
- new_state_p = 1;
- for (curr_alt_state = state->component_states;
- curr_alt_state != NULL;
- curr_alt_state = curr_alt_state->next_sorted_alt_state)
- for (curr_arc = first_out_arc (curr_alt_state->state);
- curr_arc != NULL;
- curr_arc = next_out_arc (curr_arc))
- if (!collapse_flag
- /* When producing collapse-NDFA transitions, we
- only add advance-cycle transitions to the
- collapsed states. */
- || (curr_arc->insn->insn_reserv_decl
- != DECL_INSN_RESERV (advance_cycle_insn_decl)))
- add_arc (state, curr_arc->to_state, curr_arc->insn);
- }
- arcs_marked_by_insn->to_state = state;
- for (alts_number = 0,
- curr_arc = arcs_marked_by_insn->next_arc_marked_by_insn;
- curr_arc != NULL;
- curr_arc = next_arc)
- {
- next_arc = curr_arc->next_arc_marked_by_insn;
- remove_arc (original_state, curr_arc);
- alts_number++;
- }
- }
- }
- if (!state->it_was_placed_in_stack_for_DFA_forming)
- {
- state->it_was_placed_in_stack_for_DFA_forming = 1;
- state_stack->safe_push (state);
- }
- return new_state_p;
- }
- /* The function transforms nondeterministic AUTOMATON into
- deterministic. */
- static void
- NDFA_to_DFA (automaton_t automaton)
- {
- state_t start_state;
- state_t state;
- decl_t decl;
- auto_vec<state_t> state_stack;
- int i;
- int states_n;
- /* Create the start state (empty state). */
- start_state = automaton->start_state;
- start_state->it_was_placed_in_stack_for_DFA_forming = 1;
- state_stack.safe_push (start_state);
- states_n = 1;
- while (state_stack.length () != 0)
- {
- state = state_stack.pop ();
- form_arcs_marked_by_insn (state);
- for (i = 0; i < description->decls_num; i++)
- {
- decl = description->decls [i];
- if (decl->mode == dm_insn_reserv
- && decl != collapse_ndfa_insn_decl
- && create_composed_state
- (state, DECL_INSN_RESERV (decl)->arcs_marked_by_insn,
- &state_stack))
- {
- states_n++;
- if (progress_flag && states_n % 100 == 0)
- fprintf (stderr, ".");
- }
- }
- /* Add a transition to collapse the NDFA. */
- if (collapse_flag)
- {
- if (state->component_states != NULL)
- {
- state_t state2 = state->component_states->state;
- if (!state2->it_was_placed_in_stack_for_DFA_forming)
- {
- state2->it_was_placed_in_stack_for_DFA_forming = 1;
- state_stack.safe_push (state2);
- }
- add_arc (state, state2, automaton->collapse_ainsn);
- }
- else
- add_arc (state, state, automaton->collapse_ainsn);
- }
- }
- }
- /* The following variable value is current number (1, 2, ...) of passing
- graph of states. */
- static int curr_state_graph_pass_num;
- /* This recursive function passes all states achieved from START_STATE
- and applies APPLIED_FUNC to them. */
- static void
- pass_state_graph (state_t start_state, void (*applied_func) (state_t state))
- {
- arc_t arc;
- if (start_state->pass_num == curr_state_graph_pass_num)
- return;
- start_state->pass_num = curr_state_graph_pass_num;
- (*applied_func) (start_state);
- for (arc = first_out_arc (start_state);
- arc != NULL;
- arc = next_out_arc (arc))
- pass_state_graph (arc->to_state, applied_func);
- }
- /* This recursive function passes all states of AUTOMATON and applies
- APPLIED_FUNC to them. */
- static void
- pass_states (automaton_t automaton, void (*applied_func) (state_t state))
- {
- curr_state_graph_pass_num++;
- pass_state_graph (automaton->start_state, applied_func);
- }
- /* The function initializes code for passing of all states. */
- static void
- initiate_pass_states (void)
- {
- curr_state_graph_pass_num = 0;
- }
- /* The following vla is used for storing pointers to all achieved
- states. */
- static vec<state_t> all_achieved_states;
- /* This function is called by function pass_states to add an achieved
- STATE. */
- static void
- add_achieved_state (state_t state)
- {
- all_achieved_states.safe_push (state);
- }
- /* The function sets up equivalence numbers of insns which mark all
- out arcs of STATE by equiv_class_num_1 (if ODD_ITERATION_FLAG has
- nonzero value) or by equiv_class_num_2 of the destination state. */
- static void
- set_out_arc_insns_equiv_num (state_t state, int odd_iteration_flag)
- {
- arc_t arc;
- for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
- {
- gcc_assert (!arc->insn->insn_reserv_decl->equiv_class_num);
- arc->insn->insn_reserv_decl->equiv_class_num
- = (odd_iteration_flag
- ? arc->to_state->equiv_class_num_1
- : arc->to_state->equiv_class_num_2);
- gcc_assert (arc->insn->insn_reserv_decl->equiv_class_num);
- }
- }
- /* The function clears equivalence numbers and alt_states in all insns
- which mark all out arcs of STATE. */
- static void
- clear_arc_insns_equiv_num (state_t state)
- {
- arc_t arc;
- for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
- arc->insn->insn_reserv_decl->equiv_class_num = 0;
- }
- /* The following function returns TRUE if STATE reserves the unit with
- UNIT_NUM on the first cycle. */
- static int
- first_cycle_unit_presence (state_t state, int unit_num)
- {
- alt_state_t alt_state;
- if (state->component_states == NULL)
- return test_unit_reserv (state->reservs, 0, unit_num);
- else
- {
- for (alt_state = state->component_states;
- alt_state != NULL;
- alt_state = alt_state->next_sorted_alt_state)
- if (test_unit_reserv (alt_state->state->reservs, 0, unit_num))
- return true;
- }
- return false;
- }
- /* This fills in the presence_signature[] member of STATE. */
- static void
- cache_presence (state_t state)
- {
- int i, num = 0;
- unsigned int sz;
- sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
- / (sizeof (int) * CHAR_BIT);
- state->presence_signature = XCREATENODEVEC (unsigned int, sz);
- for (i = 0; i < description->units_num; i++)
- if (units_array [i]->query_p)
- {
- int presence1_p = first_cycle_unit_presence (state, i);
- state->presence_signature[num / (sizeof (int) * CHAR_BIT)]
- |= (!!presence1_p) << (num % (sizeof (int) * CHAR_BIT));
- num++;
- }
- }
- /* The function returns nonzero value if STATE is not equivalent to
- ANOTHER_STATE from the same current partition on equivalence
- classes. Another state has ANOTHER_STATE_OUT_ARCS_NUM number of
- output arcs. Iteration of making equivalence partition is defined
- by ODD_ITERATION_FLAG. */
- static int
- state_is_differed (state_t state, state_t another_state,
- int odd_iteration_flag)
- {
- arc_t arc;
- unsigned int sz, si;
- gcc_assert (state->num_out_arcs == another_state->num_out_arcs);
- sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
- / (sizeof (int) * CHAR_BIT);
- for (si = 0; si < sz; si++)
- gcc_assert (state->presence_signature[si]
- == another_state->presence_signature[si]);
- for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
- {
- if ((odd_iteration_flag
- ? arc->to_state->equiv_class_num_1
- : arc->to_state->equiv_class_num_2)
- != arc->insn->insn_reserv_decl->equiv_class_num)
- return 1;
- }
- return 0;
- }
- /* Compares two states pointed to by STATE_PTR_1 and STATE_PTR_2
- and return -1, 0 or 1. This function can be used as predicate for
- qsort(). It requires the member presence_signature[] of both
- states be filled. */
- static int
- compare_states_for_equiv (const void *state_ptr_1,
- const void *state_ptr_2)
- {
- const_state_t const s1 = *(const_state_t const*)state_ptr_1;
- const_state_t const s2 = *(const_state_t const*)state_ptr_2;
- unsigned int sz, si;
- if (s1->num_out_arcs < s2->num_out_arcs)
- return -1;
- else if (s1->num_out_arcs > s2->num_out_arcs)
- return 1;
- sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
- / (sizeof (int) * CHAR_BIT);
- for (si = 0; si < sz; si++)
- if (s1->presence_signature[si] < s2->presence_signature[si])
- return -1;
- else if (s1->presence_signature[si] > s2->presence_signature[si])
- return 1;
- return 0;
- }
- /* The function makes initial partition of STATES on equivalent
- classes and saves it into CLASSES. This function requires the input
- to be sorted via compare_states_for_equiv(). */
- static int
- init_equiv_class (vec<state_t> states, vec<state_t> *classes)
- {
- size_t i;
- state_t prev = 0;
- int class_num = 1;
- classes->create (150);
- for (i = 0; i < states.length (); i++)
- {
- state_t state = states[i];
- if (prev)
- {
- if (compare_states_for_equiv (&prev, &state) != 0)
- {
- classes->safe_push (prev);
- class_num++;
- prev = NULL;
- }
- }
- state->equiv_class_num_1 = class_num;
- state->next_equiv_class_state = prev;
- prev = state;
- }
- if (prev)
- classes->safe_push (prev);
- return class_num;
- }
- /* The function copies pointers to equivalent states from vla FROM
- into vla TO. */
- static void
- copy_equiv_class (vec<state_t> *to, vec<state_t> from)
- {
- to->release ();
- *to = from.copy ();
- }
- /* The function processes equivalence class given by its first state,
- FIRST_STATE, on odd iteration if ODD_ITERATION_FLAG. If there
- are not equivalent states, the function partitions the class
- removing nonequivalent states and placing them in
- *NEXT_ITERATION_CLASSES, increments *NEW_EQUIV_CLASS_NUM_PTR ans
- assigns it to the state equivalence number. If the class has been
- partitioned, the function returns nonzero value. */
- static int
- partition_equiv_class (state_t first_state, int odd_iteration_flag,
- vec<state_t> *next_iteration_classes,
- int *new_equiv_class_num_ptr)
- {
- state_t new_equiv_class;
- int partition_p;
- state_t curr_state;
- state_t prev_state;
- state_t next_state;
- partition_p = 0;
- while (first_state != NULL)
- {
- new_equiv_class = NULL;
- if (first_state->next_equiv_class_state != NULL)
- {
- /* There are more one states in the class equivalence. */
- set_out_arc_insns_equiv_num (first_state, odd_iteration_flag);
- for (prev_state = first_state,
- curr_state = first_state->next_equiv_class_state;
- curr_state != NULL;
- curr_state = next_state)
- {
- next_state = curr_state->next_equiv_class_state;
- if (state_is_differed (curr_state, first_state,
- odd_iteration_flag))
- {
- /* Remove curr state from the class equivalence. */
- prev_state->next_equiv_class_state = next_state;
- /* Add curr state to the new class equivalence. */
- curr_state->next_equiv_class_state = new_equiv_class;
- if (new_equiv_class == NULL)
- (*new_equiv_class_num_ptr)++;
- if (odd_iteration_flag)
- curr_state->equiv_class_num_2 = *new_equiv_class_num_ptr;
- else
- curr_state->equiv_class_num_1 = *new_equiv_class_num_ptr;
- new_equiv_class = curr_state;
- partition_p = 1;
- }
- else
- prev_state = curr_state;
- }
- clear_arc_insns_equiv_num (first_state);
- }
- if (new_equiv_class != NULL)
- next_iteration_classes->safe_push (new_equiv_class);
- first_state = new_equiv_class;
- }
- return partition_p;
- }
- /* The function finds equivalent states of AUTOMATON. */
- static void
- evaluate_equiv_classes (automaton_t automaton, vec<state_t> *equiv_classes)
- {
- int new_equiv_class_num;
- int odd_iteration_flag;
- int finish_flag;
- vec<state_t> next_iteration_classes;
- size_t i;
- all_achieved_states.create (1500);
- pass_states (automaton, add_achieved_state);
- pass_states (automaton, cache_presence);
- all_achieved_states.qsort (compare_states_for_equiv);
- odd_iteration_flag = 0;
- new_equiv_class_num = init_equiv_class (all_achieved_states,
- &next_iteration_classes);
- do
- {
- odd_iteration_flag = !odd_iteration_flag;
- finish_flag = 1;
- copy_equiv_class (equiv_classes, next_iteration_classes);
- /* Transfer equiv numbers for the next iteration. */
- for (i = 0; i < all_achieved_states.length (); i++)
- if (odd_iteration_flag)
- all_achieved_states[i]->equiv_class_num_2
- = all_achieved_states[i]->equiv_class_num_1;
- else
- all_achieved_states[i]->equiv_class_num_1
- = all_achieved_states[i]->equiv_class_num_2;
- for (i = 0; i < equiv_classes->length (); i++)
- if (partition_equiv_class ((*equiv_classes)[i],
- odd_iteration_flag,
- &next_iteration_classes,
- &new_equiv_class_num))
- finish_flag = 0;
- }
- while (!finish_flag);
- next_iteration_classes.release ();
- all_achieved_states.release ();
- }
- /* The function merges equivalent states of AUTOMATON. */
- static void
- merge_states (automaton_t automaton, vec<state_t> equiv_classes)
- {
- state_t curr_state;
- state_t new_state;
- state_t first_class_state;
- alt_state_t alt_states;
- alt_state_t alt_state, new_alt_state;
- arc_t curr_arc;
- arc_t next_arc;
- size_t i;
- /* Create states corresponding to equivalence classes containing two
- or more states. */
- for (i = 0; i < equiv_classes.length (); i++)
- {
- curr_state = equiv_classes[i];
- if (curr_state->next_equiv_class_state != NULL)
- {
- /* There are more one states in the class equivalence. */
- /* Create new compound state. */
- new_state = get_free_state (0, automaton);
- alt_states = NULL;
- first_class_state = curr_state;
- for (curr_state = first_class_state;
- curr_state != NULL;
- curr_state = curr_state->next_equiv_class_state)
- {
- curr_state->equiv_class_state = new_state;
- if (curr_state->component_states == NULL)
- {
- new_alt_state = get_free_alt_state ();
- new_alt_state->state = curr_state;
- new_alt_state->next_alt_state = alt_states;
- alt_states = new_alt_state;
- }
- else
- for (alt_state = curr_state->component_states;
- alt_state != NULL;
- alt_state = alt_state->next_sorted_alt_state)
- {
- new_alt_state = get_free_alt_state ();
- new_alt_state->state = alt_state->state;
- new_alt_state->next_alt_state = alt_states;
- alt_states = new_alt_state;
- }
- }
- /* It is important that alt states were sorted before and
- after merging to have the same querying results. */
- new_state->component_states = uniq_sort_alt_states (alt_states);
- }
- else
- curr_state->equiv_class_state = curr_state;
- }
- for (i = 0; i < equiv_classes.length (); i++)
- {
- curr_state = equiv_classes[i];
- if (curr_state->next_equiv_class_state != NULL)
- {
- first_class_state = curr_state;
- /* Create new arcs output from the state corresponding to
- equiv class. */
- for (curr_arc = first_out_arc (first_class_state);
- curr_arc != NULL;
- curr_arc = next_out_arc (curr_arc))
- add_arc (first_class_state->equiv_class_state,
- curr_arc->to_state->equiv_class_state,
- curr_arc->insn);
- /* Delete output arcs from states of given class equivalence. */
- for (curr_state = first_class_state;
- curr_state != NULL;
- curr_state = curr_state->next_equiv_class_state)
- {
- if (automaton->start_state == curr_state)
- automaton->start_state = curr_state->equiv_class_state;
- /* Delete the state and its output arcs. */
- for (curr_arc = first_out_arc (curr_state);
- curr_arc != NULL;
- curr_arc = next_arc)
- {
- next_arc = next_out_arc (curr_arc);
- free_arc (curr_arc);
- }
- }
- }
- else
- {
- /* Change `to_state' of arcs output from the state of given
- equivalence class. */
- for (curr_arc = first_out_arc (curr_state);
- curr_arc != NULL;
- curr_arc = next_out_arc (curr_arc))
- curr_arc->to_state = curr_arc->to_state->equiv_class_state;
- }
- }
- }
- /* The function sets up new_cycle_p for states if there is arc to the
- state marked by advance_cycle_insn_decl. */
- static void
- set_new_cycle_flags (state_t state)
- {
- arc_t arc;
- for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
- if (arc->insn->insn_reserv_decl
- == DECL_INSN_RESERV (advance_cycle_insn_decl))
- arc->to_state->new_cycle_p = 1;
- }
- /* The top level function for minimization of deterministic
- AUTOMATON. */
- static void
- minimize_DFA (automaton_t automaton)
- {
- auto_vec<state_t> equiv_classes;
- evaluate_equiv_classes (automaton, &equiv_classes);
- merge_states (automaton, equiv_classes);
- pass_states (automaton, set_new_cycle_flags);
- }
- /* Values of two variables are counted number of states and arcs in an
- automaton. */
- static int curr_counted_states_num;
- static int curr_counted_arcs_num;
- /* The function is called by function `pass_states' to count states
- and arcs of an automaton. */
- static void
- incr_states_and_arcs_nums (state_t state)
- {
- arc_t arc;
- curr_counted_states_num++;
- for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
- curr_counted_arcs_num++;
- }
- /* The function counts states and arcs of AUTOMATON. */
- static void
- count_states_and_arcs (automaton_t automaton, int *states_num,
- int *arcs_num)
- {
- curr_counted_states_num = 0;
- curr_counted_arcs_num = 0;
- pass_states (automaton, incr_states_and_arcs_nums);
- *states_num = curr_counted_states_num;
- *arcs_num = curr_counted_arcs_num;
- }
- /* The function builds one DFA AUTOMATON for fast pipeline hazards
- recognition after checking and simplifying IR of the
- description. */
- static void
- build_automaton (automaton_t automaton)
- {
- int states_num;
- int arcs_num;
- ticker_on (&NDFA_time);
- if (progress_flag)
- {
- if (automaton->corresponding_automaton_decl == NULL)
- fprintf (stderr, "Create anonymous automaton");
- else
- fprintf (stderr, "Create automaton `%s'",
- automaton->corresponding_automaton_decl->name);
- fprintf (stderr, " (1 dot is 100 new states):");
- }
- make_automaton (automaton);
- if (progress_flag)
- fprintf (stderr, " done\n");
- ticker_off (&NDFA_time);
- count_states_and_arcs (automaton, &states_num, &arcs_num);
- automaton->NDFA_states_num = states_num;
- automaton->NDFA_arcs_num = arcs_num;
- ticker_on (&NDFA_to_DFA_time);
- if (progress_flag)
- {
- if (automaton->corresponding_automaton_decl == NULL)
- fprintf (stderr, "Make anonymous DFA");
- else
- fprintf (stderr, "Make DFA `%s'",
- automaton->corresponding_automaton_decl->name);
- fprintf (stderr, " (1 dot is 100 new states):");
- }
- NDFA_to_DFA (automaton);
- if (progress_flag)
- fprintf (stderr, " done\n");
- ticker_off (&NDFA_to_DFA_time);
- count_states_and_arcs (automaton, &states_num, &arcs_num);
- automaton->DFA_states_num = states_num;
- automaton->DFA_arcs_num = arcs_num;
- if (!no_minimization_flag)
- {
- ticker_on (&minimize_time);
- if (progress_flag)
- {
- if (automaton->corresponding_automaton_decl == NULL)
- fprintf (stderr, "Minimize anonymous DFA...");
- else
- fprintf (stderr, "Minimize DFA `%s'...",
- automaton->corresponding_automaton_decl->name);
- }
- minimize_DFA (automaton);
- if (progress_flag)
- fprintf (stderr, "done\n");
- ticker_off (&minimize_time);
- count_states_and_arcs (automaton, &states_num, &arcs_num);
- automaton->minimal_DFA_states_num = states_num;
- automaton->minimal_DFA_arcs_num = arcs_num;
- }
- }
- /* The page contains code for enumeration of all states of an automaton. */
- /* Variable used for enumeration of all states of an automaton. Its
- value is current number of automaton states. */
- static int curr_state_order_num;
- /* The function is called by function `pass_states' for enumerating
- states. */
- static void
- set_order_state_num (state_t state)
- {
- state->order_state_num = curr_state_order_num;
- curr_state_order_num++;
- }
- /* The function enumerates all states of AUTOMATON. */
- static void
- enumerate_states (automaton_t automaton)
- {
- curr_state_order_num = 0;
- pass_states (automaton, set_order_state_num);
- automaton->achieved_states_num = curr_state_order_num;
- }
- /* The page contains code for finding equivalent automaton insns
- (ainsns). */
- /* The function inserts AINSN into cyclic list
- CYCLIC_EQUIV_CLASS_INSN_LIST of ainsns. */
- static ainsn_t
- insert_ainsn_into_equiv_class (ainsn_t ainsn,
- ainsn_t cyclic_equiv_class_insn_list)
- {
- if (cyclic_equiv_class_insn_list == NULL)
- ainsn->next_equiv_class_insn = ainsn;
- else
- {
- ainsn->next_equiv_class_insn
- = cyclic_equiv_class_insn_list->next_equiv_class_insn;
- cyclic_equiv_class_insn_list->next_equiv_class_insn = ainsn;
- }
- return ainsn;
- }
- /* The function deletes equiv_class_insn into cyclic list of
- equivalent ainsns. */
- static void
- delete_ainsn_from_equiv_class (ainsn_t equiv_class_insn)
- {
- ainsn_t curr_equiv_class_insn;
- ainsn_t prev_equiv_class_insn;
- prev_equiv_class_insn = equiv_class_insn;
- for (curr_equiv_class_insn = equiv_class_insn->next_equiv_class_insn;
- curr_equiv_class_insn != equiv_class_insn;
- curr_equiv_class_insn = curr_equiv_class_insn->next_equiv_class_insn)
- prev_equiv_class_insn = curr_equiv_class_insn;
- if (prev_equiv_class_insn != equiv_class_insn)
- prev_equiv_class_insn->next_equiv_class_insn
- = equiv_class_insn->next_equiv_class_insn;
- }
- /* The function processes AINSN of a state in order to find equivalent
- ainsns. INSN_ARCS_ARRAY is table: code of insn -> out arc of the
- state. */
- static void
- process_insn_equiv_class (ainsn_t ainsn, arc_t *insn_arcs_array)
- {
- ainsn_t next_insn;
- ainsn_t curr_insn;
- ainsn_t cyclic_insn_list;
- arc_t arc;
- gcc_assert (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]);
- curr_insn = ainsn;
- /* New class of ainsns which are not equivalent to given ainsn. */
- cyclic_insn_list = NULL;
- do
- {
- next_insn = curr_insn->next_equiv_class_insn;
- arc = insn_arcs_array [curr_insn->insn_reserv_decl->insn_num];
- if (arc == NULL
- || (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]->to_state
- != arc->to_state))
- {
- delete_ainsn_from_equiv_class (curr_insn);
- cyclic_insn_list = insert_ainsn_into_equiv_class (curr_insn,
- cyclic_insn_list);
- }
- curr_insn = next_insn;
- }
- while (curr_insn != ainsn);
- }
- /* The function processes STATE in order to find equivalent ainsns. */
- static void
- process_state_for_insn_equiv_partition (state_t state)
- {
- arc_t arc;
- arc_t *insn_arcs_array = XCNEWVEC (arc_t, description->insns_num);
- /* Process insns of the arcs. */
- for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
- insn_arcs_array [arc->insn->insn_reserv_decl->insn_num] = arc;
- for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
- process_insn_equiv_class (arc->insn, insn_arcs_array);
- free (insn_arcs_array);
- }
- /* The function searches for equivalent ainsns of AUTOMATON. */
- static void
- set_insn_equiv_classes (automaton_t automaton)
- {
- ainsn_t ainsn;
- ainsn_t first_insn;
- ainsn_t curr_insn;
- ainsn_t cyclic_insn_list;
- ainsn_t insn_with_same_reservs;
- int equiv_classes_num;
- /* All insns are included in one equivalence class. */
- cyclic_insn_list = NULL;
- for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
- if (ainsn->first_insn_with_same_reservs)
- cyclic_insn_list = insert_ainsn_into_equiv_class (ainsn,
- cyclic_insn_list);
- /* Process insns in order to make equivalence partition. */
- pass_states (automaton, process_state_for_insn_equiv_partition);
- /* Enumerate equiv classes. */
- for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
- /* Set undefined value. */
- ainsn->insn_equiv_class_num = -1;
- equiv_classes_num = 0;
- for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
- if (ainsn->insn_equiv_class_num < 0)
- {
- first_insn = ainsn;
- gcc_assert (first_insn->first_insn_with_same_reservs);
- first_insn->first_ainsn_with_given_equivalence_num = 1;
- curr_insn = first_insn;
- do
- {
- for (insn_with_same_reservs = curr_insn;
- insn_with_same_reservs != NULL;
- insn_with_same_reservs
- = insn_with_same_reservs->next_same_reservs_insn)
- insn_with_same_reservs->insn_equiv_class_num = equiv_classes_num;
- curr_insn = curr_insn->next_equiv_class_insn;
- }
- while (curr_insn != first_insn);
- equiv_classes_num++;
- }
- automaton->insn_equiv_classes_num = equiv_classes_num;
- }
- /* This page contains code for creating DFA(s) and calls functions
- building them. */
- /* The following value is used to prevent floating point overflow for
- estimating an automaton bound. The value should be less DBL_MAX on
- the host machine. We use here approximate minimum of maximal
- double floating point value required by ANSI C standard. It
- will work for non ANSI sun compiler too. */
- #define MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND 1.0E37
- /* The function estimate size of the single DFA used by PHR (pipeline
- hazards recognizer). */
- static double
- estimate_one_automaton_bound (void)
- {
- decl_t decl;
- double one_automaton_estimation_bound;
- double root_value;
- int i;
- one_automaton_estimation_bound = 1.0;
- for (i = 0; i < description->decls_num; i++)
- {
- decl = description->decls [i];
- if (decl->mode == dm_unit)
- {
- root_value = exp (log (DECL_UNIT (decl)->max_occ_cycle_num
- - DECL_UNIT (decl)->min_occ_cycle_num + 1.0)
- / automata_num);
- if (MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND / root_value
- > one_automaton_estimation_bound)
- one_automaton_estimation_bound *= root_value;
- }
- }
- return one_automaton_estimation_bound;
- }
- /* The function compares unit declarations according to their maximal
- cycle in reservations. */
- static int
- compare_max_occ_cycle_nums (const void *unit_decl_1,
- const void *unit_decl_2)
- {
- if ((DECL_UNIT (*(const_decl_t const*) unit_decl_1)->max_occ_cycle_num)
- < (DECL_UNIT (*(const_decl_t const*) unit_decl_2)->max_occ_cycle_num))
- return 1;
- else if ((DECL_UNIT (*(const_decl_t const*) unit_decl_1)->max_occ_cycle_num)
- == (DECL_UNIT (*(const_decl_t const*) unit_decl_2)->max_occ_cycle_num))
- return 0;
- else
- return -1;
- }
- /* The function makes heuristic assigning automata to units. Actually
- efficacy of the algorithm has been checked yet??? */
- static void
- units_to_automata_heuristic_distr (void)
- {
- double estimation_bound;
- int automaton_num;
- int rest_units_num;
- double bound_value;
- unit_decl_t *unit_decls;
- int i, j;
- if (description->units_num == 0)
- return;
- estimation_bound = estimate_one_automaton_bound ();
- unit_decls = XNEWVEC (unit_decl_t, description->units_num);
- for (i = 0, j = 0; i < description->decls_num; i++)
- if (description->decls[i]->mode == dm_unit)
- unit_decls[j++] = DECL_UNIT (description->decls[i]);
- gcc_assert (j == description->units_num);
- qsort (unit_decls, description->units_num,
- sizeof (unit_decl_t), compare_max_occ_cycle_nums);
- automaton_num = 0;
- bound_value = unit_decls[0]->max_occ_cycle_num;
- unit_decls[0]->corresponding_automaton_num = automaton_num;
- for (i = 1; i < description->units_num; i++)
- {
- rest_units_num = description->units_num - i + 1;
- gcc_assert (automata_num - automaton_num - 1 <= rest_units_num);
- if (automaton_num < automata_num - 1
- && ((automata_num - automaton_num - 1 == rest_units_num)
- || (bound_value
- > (estimation_bound
- / unit_decls[i]->max_occ_cycle_num))))
- {
- bound_value = unit_decls[i]->max_occ_cycle_num;
- automaton_num++;
- }
- else
- bound_value *= unit_decls[i]->max_occ_cycle_num;
- unit_decls[i]->corresponding_automaton_num = automaton_num;
- }
- gcc_assert (automaton_num == automata_num - 1);
- free (unit_decls);
- }
- /* The functions creates automaton insns for each automata. Automaton
- insn is simply insn for given automaton which makes reservation
- only of units of the automaton. */
- static void
- create_ainsns (automaton_t automaton)
- {
- decl_t decl;
- ainsn_t first_ainsn;
- ainsn_t curr_ainsn;
- ainsn_t prev_ainsn;
- int i;
- first_ainsn = NULL;
- prev_ainsn = NULL;
- for (i = 0; i < description->decls_num; i++)
- {
- decl = description->decls [i];
- if (decl->mode == dm_insn_reserv)
- {
- curr_ainsn = XCREATENODE (struct ainsn);
- curr_ainsn->insn_reserv_decl = DECL_INSN_RESERV (decl);
- curr_ainsn->important_p = FALSE;
- curr_ainsn->next_ainsn = NULL;
- if (prev_ainsn == NULL)
- first_ainsn = curr_ainsn;
- else
- prev_ainsn->next_ainsn = curr_ainsn;
- if (decl == advance_cycle_insn_decl)
- automaton->advance_ainsn = curr_ainsn;
- else if (decl == collapse_ndfa_insn_decl)
- automaton->collapse_ainsn = curr_ainsn;
- prev_ainsn = curr_ainsn;
- }
- }
- automaton->ainsn_list = first_ainsn;
- }
- /* The function assigns automata to units according to constructions
- `define_automaton' in the description. */
- static void
- units_to_automata_distr (void)
- {
- decl_t decl;
- int i;
- for (i = 0; i < description->decls_num; i++)
- {
- decl = description->decls [i];
- if (decl->mode == dm_unit)
- {
- if (DECL_UNIT (decl)->automaton_decl == NULL
- || (DECL_UNIT (decl)->automaton_decl->corresponding_automaton
- == NULL))
- /* Distribute to the first automaton. */
- DECL_UNIT (decl)->corresponding_automaton_num = 0;
- else
- DECL_UNIT (decl)->corresponding_automaton_num
- = (DECL_UNIT (decl)->automaton_decl
- ->corresponding_automaton->automaton_order_num);
- }
- }
- }
- /* The function creates DFA(s) for fast pipeline hazards recognition
- after checking and simplifying IR of the description. */
- static void
- create_automata (void)
- {
- automaton_t curr_automaton;
- automaton_t prev_automaton;
- decl_t decl;
- int curr_automaton_num;
- int i;
- if (automata_num != 0)
- {
- units_to_automata_heuristic_distr ();
- for (prev_automaton = NULL, curr_automaton_num = 0;
- curr_automaton_num < automata_num;
- curr_automaton_num++, prev_automaton = curr_automaton)
- {
- curr_automaton = XCREATENODE (struct automaton);
- create_ainsns (curr_automaton);
- curr_automaton->corresponding_automaton_decl = NULL;
- curr_automaton->next_automaton = NULL;
- curr_automaton->automaton_order_num = curr_automaton_num;
- if (prev_automaton == NULL)
- description->first_automaton = curr_automaton;
- else
- prev_automaton->next_automaton = curr_automaton;
- }
- }
- else
- {
- curr_automaton_num = 0;
- prev_automaton = NULL;
- for (i = 0; i < description->decls_num; i++)
- {
- decl = description->decls [i];
- if (decl->mode == dm_automaton
- && DECL_AUTOMATON (decl)->automaton_is_used)
- {
- curr_automaton = XCREATENODE (struct automaton);
- create_ainsns (curr_automaton);
- curr_automaton->corresponding_automaton_decl
- = DECL_AUTOMATON (decl);
- curr_automaton->next_automaton = NULL;
- DECL_AUTOMATON (decl)->corresponding_automaton = curr_automaton;
- curr_automaton->automaton_order_num = curr_automaton_num;
- if (prev_automaton == NULL)
- description->first_automaton = curr_automaton;
- else
- prev_automaton->next_automaton = curr_automaton;
- curr_automaton_num++;
- prev_automaton = curr_automaton;
- }
- }
- if (curr_automaton_num == 0)
- {
- curr_automaton = XCREATENODE (struct automaton);
- create_ainsns (curr_automaton);
- curr_automaton->corresponding_automaton_decl = NULL;
- curr_automaton->next_automaton = NULL;
- description->first_automaton = curr_automaton;
- }
- units_to_automata_distr ();
- }
- NDFA_time = create_ticker ();
- ticker_off (&NDFA_time);
- NDFA_to_DFA_time = create_ticker ();
- ticker_off (&NDFA_to_DFA_time);
- minimize_time = create_ticker ();
- ticker_off (&minimize_time);
- equiv_time = create_ticker ();
- ticker_off (&equiv_time);
- for (curr_automaton = description->first_automaton;
- curr_automaton != NULL;
- curr_automaton = curr_automaton->next_automaton)
- {
- if (progress_flag)
- {
- if (curr_automaton->corresponding_automaton_decl == NULL)
- fprintf (stderr, "Prepare anonymous automaton creation ... ");
- else
- fprintf (stderr, "Prepare automaton `%s' creation...",
- curr_automaton->corresponding_automaton_decl->name);
- }
- create_alt_states (curr_automaton);
- form_ainsn_with_same_reservs (curr_automaton);
- if (progress_flag)
- fprintf (stderr, "done\n");
- build_automaton (curr_automaton);
- enumerate_states (curr_automaton);
- ticker_on (&equiv_time);
- set_insn_equiv_classes (curr_automaton);
- ticker_off (&equiv_time);
- }
- }
- /* This page contains code for forming string representation of
- regexp. The representation is formed on IR obstack. So you should
- not work with IR obstack between regexp_representation and
- finish_regexp_representation calls. */
- /* This recursive function forms string representation of regexp
- (without tailing '\0'). */
- static void
- form_regexp (regexp_t regexp)
- {
- int i;
- switch (regexp->mode)
- {
- case rm_unit: case rm_reserv:
- {
- const char *name = (regexp->mode == rm_unit
- ? REGEXP_UNIT (regexp)->name
- : REGEXP_RESERV (regexp)->name);
- obstack_grow (&irp, name, strlen (name));
- break;
- }
- case rm_sequence:
- for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
- {
- if (i != 0)
- obstack_1grow (&irp, ',');
- form_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
- }
- break;
- case rm_allof:
- obstack_1grow (&irp, '(');
- for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
- {
- if (i != 0)
- obstack_1grow (&irp, '+');
- if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
- || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
- obstack_1grow (&irp, '(');
- form_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
- if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
- || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
- obstack_1grow (&irp, ')');
- }
- obstack_1grow (&irp, ')');
- break;
- case rm_oneof:
- for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
- {
- if (i != 0)
- obstack_1grow (&irp, '|');
- if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
- obstack_1grow (&irp, '(');
- form_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
- if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
- obstack_1grow (&irp, ')');
- }
- break;
- case rm_repeat:
- {
- char digits [30];
- if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
- || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
- || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
- obstack_1grow (&irp, '(');
- form_regexp (REGEXP_REPEAT (regexp)->regexp);
- if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
- || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
- || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
- obstack_1grow (&irp, ')');
- sprintf (digits, "*%d", REGEXP_REPEAT (regexp)->repeat_num);
- obstack_grow (&irp, digits, strlen (digits));
- break;
- }
- case rm_nothing:
- obstack_grow (&irp, NOTHING_NAME, strlen (NOTHING_NAME));
- break;
- default:
- gcc_unreachable ();
- }
- }
- /* The function returns string representation of REGEXP on IR
- obstack. */
- static const char *
- regexp_representation (regexp_t regexp)
- {
- form_regexp (regexp);
- obstack_1grow (&irp, '\0');
- return (char *) obstack_base (&irp);
- }
- /* The function frees memory allocated for last formed string
- representation of regexp. */
- static void
- finish_regexp_representation (void)
- {
- int length = obstack_object_size (&irp);
- obstack_blank_fast (&irp, -length);
- }
- /* This page contains code for output PHR (pipeline hazards recognizer). */
- /* The function outputs minimal C type which is sufficient for
- representation numbers in range min_range_value and
- max_range_value. Because host machine and build machine may be
- different, we use here minimal values required by ANSI C standard
- instead of UCHAR_MAX, SHRT_MAX, SHRT_MIN, etc. This is a good
- approximation. */
- static void
- output_range_type (FILE *f, long int min_range_value,
- long int max_range_value)
- {
- if (min_range_value >= 0 && max_range_value <= 255)
- fprintf (f, "unsigned char");
- else if (min_range_value >= -127 && max_range_value <= 127)
- fprintf (f, "signed char");
- else if (min_range_value >= 0 && max_range_value <= 65535)
- fprintf (f, "unsigned short");
- else if (min_range_value >= -32767 && max_range_value <= 32767)
- fprintf (f, "short");
- else
- fprintf (f, "int");
- }
- /* The function outputs all initialization values of VECT. */
- static void
- output_vect (vla_hwint_t vect)
- {
- int els_on_line;
- size_t vect_length = vect.length ();
- size_t i;
- els_on_line = 1;
- if (vect_length == 0)
- fputs ("0 /* This is dummy el because the vect is empty */", output_file);
- else
- for (i = 0; i < vect_length; i++)
- {
- fprintf (output_file, "%5ld", (long) vect[i]);
- if (els_on_line == 10)
- {
- els_on_line = 0;
- fputs (",\n", output_file);
- }
- else if (i < vect_length-1)
- fputs (", ", output_file);
- els_on_line++;
- }
- }
- /* The following is name of the structure which represents DFA(s) for
- PHR. */
- #define CHIP_NAME "DFA_chip"
- /* The following is name of member which represents state of a DFA for
- PHR. */
- static void
- output_chip_member_name (FILE *f, automaton_t automaton)
- {
- if (automaton->corresponding_automaton_decl == NULL)
- fprintf (f, "automaton_state_%d", automaton->automaton_order_num);
- else
- fprintf (f, "%s_automaton_state",
- automaton->corresponding_automaton_decl->name);
- }
- /* The following is name of temporary variable which stores state of a
- DFA for PHR. */
- static void
- output_temp_chip_member_name (FILE *f, automaton_t automaton)
- {
- fprintf (f, "_");
- output_chip_member_name (f, automaton);
- }
- /* This is name of macro value which is code of pseudo_insns
- representing advancing cpu cycle and collapsing the NDFA.
- Its value is used as internal code unknown insn. */
- #define ADVANCE_CYCLE_VALUE_NAME "DFA__ADVANCE_CYCLE"
- #define COLLAPSE_NDFA_VALUE_NAME "NDFA__COLLAPSE"
- /* Output name of translate vector for given automaton. */
- static void
- output_translate_vect_name (FILE *f, automaton_t automaton)
- {
- if (automaton->corresponding_automaton_decl == NULL)
- fprintf (f, "translate_%d", automaton->automaton_order_num);
- else
- fprintf (f, "%s_translate", automaton->corresponding_automaton_decl->name);
- }
- /* Output name for simple transition table representation. */
- static void
- output_trans_full_vect_name (FILE *f, automaton_t automaton)
- {
- if (automaton->corresponding_automaton_decl == NULL)
- fprintf (f, "transitions_%d", automaton->automaton_order_num);
- else
- fprintf (f, "%s_transitions",
- automaton->corresponding_automaton_decl->name);
- }
- /* Output name of comb vector of the transition table for given
- automaton. */
- static void
- output_trans_comb_vect_name (FILE *f, automaton_t automaton)
- {
- if (automaton->corresponding_automaton_decl == NULL)
- fprintf (f, "transitions_%d", automaton->automaton_order_num);
- else
- fprintf (f, "%s_transitions",
- automaton->corresponding_automaton_decl->name);
- }
- /* Output name of check vector of the transition table for given
- automaton. */
- static void
- output_trans_check_vect_name (FILE *f, automaton_t automaton)
- {
- if (automaton->corresponding_automaton_decl == NULL)
- fprintf (f, "check_%d", automaton->automaton_order_num);
- else
- fprintf (f, "%s_check", automaton->corresponding_automaton_decl->name);
- }
- /* Output name of base vector of the transition table for given
- automaton. */
- static void
- output_trans_base_vect_name (FILE *f, automaton_t automaton)
- {
- if (automaton->corresponding_automaton_decl == NULL)
- fprintf (f, "base_%d", automaton->automaton_order_num);
- else
- fprintf (f, "%s_base", automaton->corresponding_automaton_decl->name);
- }
- /* Output name of simple min issue delay table representation. */
- static void
- output_min_issue_delay_vect_name (FILE *f, automaton_t automaton)
- {
- if (automaton->corresponding_automaton_decl == NULL)
- fprintf (f, "min_issue_delay_%d", automaton->automaton_order_num);
- else
- fprintf (f, "%s_min_issue_delay",
- automaton->corresponding_automaton_decl->name);
- }
- /* Output name of deadlock vector for given automaton. */
- static void
- output_dead_lock_vect_name (FILE *f, automaton_t automaton)
- {
- if (automaton->corresponding_automaton_decl == NULL)
- fprintf (f, "dead_lock_%d", automaton->automaton_order_num);
- else
- fprintf (f, "%s_dead_lock", automaton->corresponding_automaton_decl->name);
- }
- /* Output name of reserved units table for AUTOMATON into file F. */
- static void
- output_reserved_units_table_name (FILE *f, automaton_t automaton)
- {
- if (automaton->corresponding_automaton_decl == NULL)
- fprintf (f, "reserved_units_%d", automaton->automaton_order_num);
- else
- fprintf (f, "%s_reserved_units",
- automaton->corresponding_automaton_decl->name);
- }
- /* Name of the PHR interface macro. */
- #define CPU_UNITS_QUERY_MACRO_NAME "CPU_UNITS_QUERY"
- /* Names of an internal functions: */
- #define INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME "internal_min_issue_delay"
- /* This is external type of DFA(s) state. */
- #define STATE_TYPE_NAME "state_t"
- #define INTERNAL_TRANSITION_FUNC_NAME "internal_state_transition"
- #define INTERNAL_RESET_FUNC_NAME "internal_reset"
- #define INTERNAL_DEAD_LOCK_FUNC_NAME "internal_state_dead_lock_p"
- #define INTERNAL_INSN_LATENCY_FUNC_NAME "internal_insn_latency"
- /* Name of cache of insn dfa codes. */
- #define DFA_INSN_CODES_VARIABLE_NAME "dfa_insn_codes"
- /* Name of length of cache of insn dfa codes. */
- #define DFA_INSN_CODES_LENGTH_VARIABLE_NAME "dfa_insn_codes_length"
- /* Names of the PHR interface functions: */
- #define SIZE_FUNC_NAME "state_size"
- #define TRANSITION_FUNC_NAME "state_transition"
- #define MIN_ISSUE_DELAY_FUNC_NAME "min_issue_delay"
- #define MIN_INSN_CONFLICT_DELAY_FUNC_NAME "min_insn_conflict_delay"
- #define DEAD_LOCK_FUNC_NAME "state_dead_lock_p"
- #define RESET_FUNC_NAME "state_reset"
- #define INSN_LATENCY_FUNC_NAME "insn_latency"
- #define PRINT_RESERVATION_FUNC_NAME "print_reservation"
- #define GET_CPU_UNIT_CODE_FUNC_NAME "get_cpu_unit_code"
- #define CPU_UNIT_RESERVATION_P_FUNC_NAME "cpu_unit_reservation_p"
- #define INSN_HAS_DFA_RESERVATION_P_FUNC_NAME "insn_has_dfa_reservation_p"
- #define DFA_CLEAN_INSN_CACHE_FUNC_NAME "dfa_clean_insn_cache"
- #define DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME "dfa_clear_single_insn_cache"
- #define DFA_START_FUNC_NAME "dfa_start"
- #define DFA_FINISH_FUNC_NAME "dfa_finish"
- /* Names of parameters of the PHR interface functions. */
- #define STATE_NAME "state"
- #define INSN_PARAMETER_NAME "insn"
- #define INSN2_PARAMETER_NAME "insn2"
- #define CHIP_PARAMETER_NAME "chip"
- #define FILE_PARAMETER_NAME "f"
- #define CPU_UNIT_NAME_PARAMETER_NAME "cpu_unit_name"
- #define CPU_CODE_PARAMETER_NAME "cpu_unit_code"
- /* Names of the variables whose values are internal insn code of rtx
- insn. */
- #define INTERNAL_INSN_CODE_NAME "insn_code"
- #define INTERNAL_INSN2_CODE_NAME "insn2_code"
- /* Names of temporary variables in some functions. */
- #define TEMPORARY_VARIABLE_NAME "temp"
- #define I_VARIABLE_NAME "i"
- /* Name of result variable in some functions. */
- #define RESULT_VARIABLE_NAME "res"
- /* Name of function (attribute) to translate insn into internal insn
- code. */
- #define INTERNAL_DFA_INSN_CODE_FUNC_NAME "internal_dfa_insn_code"
- /* Name of function (attribute) to translate insn into internal insn
- code with caching. */
- #define DFA_INSN_CODE_FUNC_NAME "dfa_insn_code"
- /* Output C type which is used for representation of codes of states
- of AUTOMATON. */
- static void
- output_state_member_type (FILE *f, automaton_t automaton)
- {
- output_range_type (f, 0, automaton->achieved_states_num);
- }
- /* Output definition of the structure representing current DFA(s)
- state(s). */
- static void
- output_chip_definitions (void)
- {
- automaton_t automaton;
- fprintf (output_file, "struct %s\n{\n", CHIP_NAME);
- for (automaton = description->first_automaton;
- automaton != NULL;
- automaton = automaton->next_automaton)
- {
- fprintf (output_file, " ");
- output_state_member_type (output_file, automaton);
- fprintf (output_file, " ");
- output_chip_member_name (output_file, automaton);
- fprintf (output_file, ";\n");
- }
- fprintf (output_file, "};\n\n");
- #if 0
- fprintf (output_file, "static struct %s %s;\n\n", CHIP_NAME, CHIP_NAME);
- #endif
- }
- /* The function outputs translate vector of internal insn code into
- insn equivalence class number. The equivalence class number is
- used to access to table and vectors representing DFA(s). */
- static void
- output_translate_vect (automaton_t automaton)
- {
- ainsn_t ainsn;
- int insn_value;
- vla_hwint_t translate_vect;
- translate_vect.create (description->insns_num);
- for (insn_value = 0; insn_value < description->insns_num; insn_value++)
- /* Undefined value */
- translate_vect.quick_push (automaton->insn_equiv_classes_num);
- for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
- translate_vect[ainsn->insn_reserv_decl->insn_num] =
- ainsn->insn_equiv_class_num;
- fprintf (output_file,
- "/* Vector translating external insn codes to internal ones.*/\n");
- fprintf (output_file, "static const ");
- output_range_type (output_file, 0, automaton->insn_equiv_classes_num);
- fprintf (output_file, " ");
- output_translate_vect_name (output_file, automaton);
- fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
- output_vect (translate_vect);
- fprintf (output_file, "};\n\n");
- translate_vect.release ();
- }
- /* The value in a table state x ainsn -> something which represents
- undefined value. */
- static int undefined_vect_el_value;
- /* The following function returns nonzero value if the best
- representation of the table is comb vector. */
- static int
- comb_vect_p (state_ainsn_table_t tab)
- {
- if (no_comb_flag)
- return false;
- return (2 * tab->full_vect.length () > 5 * tab->comb_vect.length ());
- }
- /* The following function creates new table for AUTOMATON. */
- static state_ainsn_table_t
- create_state_ainsn_table (automaton_t automaton)
- {
- state_ainsn_table_t tab;
- int full_vect_length;
- int i;
- tab = XCREATENODE (struct state_ainsn_table);
- tab->automaton = automaton;
- tab->comb_vect.create (10000);
- tab->check_vect.create (10000);
- tab->base_vect.create (0);
- tab->base_vect.safe_grow (automaton->achieved_states_num);
- full_vect_length = (automaton->insn_equiv_classes_num
- * automaton->achieved_states_num);
- tab->full_vect.create (full_vect_length);
- for (i = 0; i < full_vect_length; i++)
- tab->full_vect.quick_push (undefined_vect_el_value);
- tab->min_base_vect_el_value = 0;
- tab->max_base_vect_el_value = 0;
- tab->min_comb_vect_el_value = 0;
- tab->max_comb_vect_el_value = 0;
- return tab;
- }
- /* The following function outputs the best C representation of the
- table TAB of given TABLE_NAME. */
- static void
- output_state_ainsn_table (state_ainsn_table_t tab, const char *table_name,
- void (*output_full_vect_name_func) (FILE *, automaton_t),
- void (*output_comb_vect_name_func) (FILE *, automaton_t),
- void (*output_check_vect_name_func) (FILE *, automaton_t),
- void (*output_base_vect_name_func) (FILE *, automaton_t))
- {
- if (!comb_vect_p (tab))
- {
- fprintf (output_file, "/* Vector for %s. */\n", table_name);
- fprintf (output_file, "static const ");
- output_range_type (output_file, tab->min_comb_vect_el_value,
- tab->max_comb_vect_el_value);
- fprintf (output_file, " ");
- (*output_full_vect_name_func) (output_file, tab->automaton);
- fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
- output_vect (tab->full_vect);
- fprintf (output_file, "};\n\n");
- }
- else
- {
- fprintf (output_file, "/* Comb vector for %s. */\n", table_name);
- fprintf (output_file, "static const ");
- output_range_type (output_file, tab->min_comb_vect_el_value,
- tab->max_comb_vect_el_value);
- fprintf (output_file, " ");
- (*output_comb_vect_name_func) (output_file, tab->automaton);
- fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
- output_vect (tab->comb_vect);
- fprintf (output_file, "};\n\n");
- fprintf (output_file, "/* Check vector for %s. */\n", table_name);
- fprintf (output_file, "static const ");
- output_range_type (output_file, 0, tab->automaton->achieved_states_num);
- fprintf (output_file, " ");
- (*output_check_vect_name_func) (output_file, tab->automaton);
- fprintf (output_file, "[] = {\n");
- output_vect (tab->check_vect);
- fprintf (output_file, "};\n\n");
- fprintf (output_file, "/* Base vector for %s. */\n", table_name);
- fprintf (output_file, "static const ");
- output_range_type (output_file, tab->min_base_vect_el_value,
- tab->max_base_vect_el_value);
- fprintf (output_file, " ");
- (*output_base_vect_name_func) (output_file, tab->automaton);
- fprintf (output_file, "[] = {\n");
- output_vect (tab->base_vect);
- fprintf (output_file, "};\n\n");
- }
- }
- /* The following function adds vector VECT to table TAB as its line
- with number VECT_NUM. */
- static void
- add_vect (state_ainsn_table_t tab, int vect_num, vla_hwint_t vect)
- {
- int vect_length;
- size_t real_vect_length;
- int comb_vect_index;
- int comb_vect_els_num;
- int vect_index;
- int first_unempty_vect_index;
- int additional_els_num;
- int no_state_value;
- vect_el_t vect_el;
- int i;
- unsigned long vect_mask, comb_vect_mask;
- vect_length = vect.length ();
- gcc_assert (vect_length);
- gcc_assert (vect.last () != undefined_vect_el_value);
- real_vect_length = tab->automaton->insn_equiv_classes_num;
- /* Form full vector in the table: */
- {
- size_t full_base = tab->automaton->insn_equiv_classes_num * vect_num;
- if (tab->full_vect.length () < full_base + vect_length)
- tab->full_vect.safe_grow (full_base + vect_length);
- for (i = 0; i < vect_length; i++)
- tab->full_vect[full_base + i] = vect[i];
- }
- /* The comb_vect min/max values are also used for the full vector, so
- compute them now. */
- for (vect_index = 0; vect_index < vect_length; vect_index++)
- if (vect[vect_index] != undefined_vect_el_value)
- {
- vect_el_t x = vect[vect_index];
- gcc_assert (x >= 0);
- if (tab->max_comb_vect_el_value < x)
- tab->max_comb_vect_el_value = x;
- if (tab->min_comb_vect_el_value > x)
- tab->min_comb_vect_el_value = x;
- }
- if (no_comb_flag)
- return;
- /* Form comb vector in the table: */
- gcc_assert (tab->comb_vect.length () == tab->check_vect.length ());
- comb_vect_els_num = tab->comb_vect.length ();
- for (first_unempty_vect_index = 0;
- first_unempty_vect_index < vect_length;
- first_unempty_vect_index++)
- if (vect[first_unempty_vect_index]
- != undefined_vect_el_value)
- break;
- /* Search for the place in comb vect for the inserted vect. */
- /* Slow case. */
- if (vect_length - first_unempty_vect_index >= SIZEOF_LONG * CHAR_BIT)
- {
- for (comb_vect_index = 0;
- comb_vect_index < comb_vect_els_num;
- comb_vect_index++)
- {
- for (vect_index = first_unempty_vect_index;
- vect_index < vect_length
- && vect_index + comb_vect_index < comb_vect_els_num;
- vect_index++)
- if (vect[vect_index]
- != undefined_vect_el_value
- && (tab->comb_vect[vect_index + comb_vect_index]
- != undefined_vect_el_value))
- break;
- if (vect_index >= vect_length
- || vect_index + comb_vect_index >= comb_vect_els_num)
- break;
- }
- goto found;
- }
- /* Fast case. */
- vect_mask = 0;
- for (vect_index = first_unempty_vect_index;
- vect_index < vect_length;
- vect_index++)
- {
- vect_mask = vect_mask << 1;
- if (vect[vect_index] != undefined_vect_el_value)
- vect_mask |= 1;
- }
- /* Search for the place in comb vect for the inserted vect. */
- comb_vect_index = 0;
- if (comb_vect_els_num == 0)
- goto found;
- comb_vect_mask = 0;
- for (vect_index = first_unempty_vect_index;
- vect_index < vect_length && vect_index < comb_vect_els_num;
- vect_index++)
- {
- comb_vect_mask <<= 1;
- if (vect_index + comb_vect_index < comb_vect_els_num
- && tab->comb_vect[vect_index + comb_vect_index]
- != undefined_vect_el_value)
- comb_vect_mask |= 1;
- }
- if ((vect_mask & comb_vect_mask) == 0)
- goto found;
- for (comb_vect_index = 1, i = vect_length; i < comb_vect_els_num;
- comb_vect_index++, i++)
- {
- comb_vect_mask = (comb_vect_mask << 1) | 1;
- comb_vect_mask ^= (tab->comb_vect[i]
- == undefined_vect_el_value);
- if ((vect_mask & comb_vect_mask) == 0)
- goto found;
- }
- for ( ; comb_vect_index < comb_vect_els_num; comb_vect_index++)
- {
- comb_vect_mask <<= 1;
- if ((vect_mask & comb_vect_mask) == 0)
- goto found;
- }
- found:
- /* Slot was found. */
- additional_els_num = comb_vect_index + real_vect_length - comb_vect_els_num;
- if (additional_els_num < 0)
- additional_els_num = 0;
- /* Expand comb and check vectors. */
- vect_el = undefined_vect_el_value;
- no_state_value = tab->automaton->achieved_states_num;
- while (additional_els_num > 0)
- {
- tab->comb_vect.safe_push (vect_el);
- tab->check_vect.safe_push (no_state_value);
- additional_els_num--;
- }
- gcc_assert (tab->comb_vect.length ()
- >= comb_vect_index + real_vect_length);
- /* Fill comb and check vectors. */
- for (vect_index = 0; vect_index < vect_length; vect_index++)
- if (vect[vect_index] != undefined_vect_el_value)
- {
- vect_el_t x = vect[vect_index];
- gcc_assert (tab->comb_vect[comb_vect_index + vect_index]
- == undefined_vect_el_value);
- gcc_assert (x >= 0);
- tab->comb_vect[comb_vect_index + vect_index] = x;
- tab->check_vect[comb_vect_index + vect_index] = vect_num;
- }
- if (tab->max_comb_vect_el_value < undefined_vect_el_value)
- tab->max_comb_vect_el_value = undefined_vect_el_value;
- if (tab->min_comb_vect_el_value > undefined_vect_el_value)
- tab->min_comb_vect_el_value = undefined_vect_el_value;
- if (tab->max_base_vect_el_value < comb_vect_index)
- tab->max_base_vect_el_value = comb_vect_index;
- if (tab->min_base_vect_el_value > comb_vect_index)
- tab->min_base_vect_el_value = comb_vect_index;
- tab->base_vect[vect_num] = comb_vect_index;
- }
- /* Return number of out arcs of STATE. */
- static int
- out_state_arcs_num (const_state_t state)
- {
- int result;
- arc_t arc;
- result = 0;
- for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
- {
- gcc_assert (arc->insn);
- if (arc->insn->first_ainsn_with_given_equivalence_num)
- result++;
- }
- return result;
- }
- /* Compare number of possible transitions from the states. */
- static int
- compare_transition_els_num (const void *state_ptr_1,
- const void *state_ptr_2)
- {
- const int transition_els_num_1
- = out_state_arcs_num (*(const_state_t const*) state_ptr_1);
- const int transition_els_num_2
- = out_state_arcs_num (*(const_state_t const*) state_ptr_2);
- if (transition_els_num_1 < transition_els_num_2)
- return 1;
- else if (transition_els_num_1 == transition_els_num_2)
- return 0;
- else
- return -1;
- }
- /* The function adds element EL_VALUE to vector VECT for a table state
- x AINSN. */
- static void
- add_vect_el (vla_hwint_t &vect, ainsn_t ainsn, int el_value)
- {
- int equiv_class_num;
- int vect_index;
- gcc_assert (ainsn);
- equiv_class_num = ainsn->insn_equiv_class_num;
- for (vect_index = vect.length ();
- vect_index <= equiv_class_num;
- vect_index++)
- vect.safe_push (undefined_vect_el_value);
- vect[equiv_class_num] = el_value;
- }
- /* This is for forming vector of states of an automaton. */
- static vec<state_t> output_states_vect;
- /* The function is called by function pass_states. The function adds
- STATE to `output_states_vect'. */
- static void
- add_states_vect_el (state_t state)
- {
- output_states_vect.safe_push (state);
- }
- /* Form and output vectors (comb, check, base or full vector)
- representing transition table of AUTOMATON. */
- static void
- output_trans_table (automaton_t automaton)
- {
- size_t i;
- arc_t arc;
- vla_hwint_t transition_vect = vla_hwint_t ();
- undefined_vect_el_value = automaton->achieved_states_num;
- automaton->trans_table = create_state_ainsn_table (automaton);
- /* Create vect of pointers to states ordered by num of transitions
- from the state (state with the maximum num is the first). */
- output_states_vect.create (0);
- pass_states (automaton, add_states_vect_el);
- output_states_vect.qsort (compare_transition_els_num);
- for (i = 0; i < output_states_vect.length (); i++)
- {
- transition_vect.truncate (0);
- for (arc = first_out_arc (output_states_vect[i]);
- arc != NULL;
- arc = next_out_arc (arc))
- {
- gcc_assert (arc->insn);
- if (arc->insn->first_ainsn_with_given_equivalence_num)
- add_vect_el (transition_vect, arc->insn,
- arc->to_state->order_state_num);
- }
- add_vect (automaton->trans_table,
- output_states_vect[i]->order_state_num,
- transition_vect);
- }
- output_state_ainsn_table
- (automaton->trans_table, "state transitions",
- output_trans_full_vect_name, output_trans_comb_vect_name,
- output_trans_check_vect_name, output_trans_base_vect_name);
- output_states_vect.release ();
- transition_vect.release ();
- }
- /* Form and output vectors representing minimal issue delay table of
- AUTOMATON. The table is state x ainsn -> minimal issue delay of
- the ainsn. */
- static void
- output_min_issue_delay_table (automaton_t automaton)
- {
- vla_hwint_t min_issue_delay_vect;
- vla_hwint_t compressed_min_issue_delay_vect;
- ainsn_t ainsn;
- size_t i;
- size_t min_issue_delay_len, compressed_min_issue_delay_len;
- size_t cfactor;
- int changed;
- /* Create vect of pointers to states ordered by num of transitions
- from the state (state with the maximum num is the first). */
- output_states_vect.create (0);
- pass_states (automaton, add_states_vect_el);
- min_issue_delay_len = (output_states_vect.length ()
- * automaton->insn_equiv_classes_num);
- min_issue_delay_vect.create (min_issue_delay_len);
- for (i = 0; i < min_issue_delay_len; i++)
- min_issue_delay_vect.quick_push (-1);
- automaton->max_min_delay = 0;
- do
- {
- size_t state_no;
- changed = 0;
- for (state_no = 0; state_no < output_states_vect.length ();
- state_no++)
- {
- state_t s = output_states_vect[state_no];
- arc_t arc;
- for (arc = first_out_arc (s); arc; arc = next_out_arc (arc))
- {
- int k;
- size_t asn = s->order_state_num
- * automaton->insn_equiv_classes_num
- + arc->insn->insn_equiv_class_num;
- if (min_issue_delay_vect[asn])
- {
- min_issue_delay_vect[asn] = (vect_el_t) 0;
- changed = 1;
- }
- for (k = 0; k < automaton->insn_equiv_classes_num; k++)
- {
- size_t n0, n1;
- vect_el_t delay0, delay1;
- n0 = s->order_state_num
- * automaton->insn_equiv_classes_num
- + k;
- n1 = arc->to_state->order_state_num
- * automaton->insn_equiv_classes_num
- + k;
- delay0 = min_issue_delay_vect[n0];
- delay1 = min_issue_delay_vect[n1];
- if (delay1 != -1)
- {
- if (arc->insn->insn_reserv_decl
- == DECL_INSN_RESERV (advance_cycle_insn_decl))
- delay1++;
- if (delay1 < delay0 || delay0 == -1)
- {
- min_issue_delay_vect[n0] = delay1;
- changed = 1;
- }
- }
- }
- }
- }
- }
- while (changed);
- automaton->max_min_delay = 0;
- for (ainsn = automaton->ainsn_list; ainsn; ainsn = ainsn->next_ainsn)
- if (ainsn->first_ainsn_with_given_equivalence_num)
- {
- for (i = 0; i < output_states_vect.length (); i++)
- {
- state_t s = output_states_vect[i];
- size_t np = s->order_state_num
- * automaton->insn_equiv_classes_num
- + ainsn->insn_equiv_class_num;
- vect_el_t x = min_issue_delay_vect[np];
- if (automaton->max_min_delay < x)
- automaton->max_min_delay = x;
- if (x == -1)
- min_issue_delay_vect[np] = (vect_el_t) 0;
- }
- }
- fprintf (output_file, "/* Vector of min issue delay of insns. */\n");
- fprintf (output_file, "static const ");
- output_range_type (output_file, 0, automaton->max_min_delay);
- fprintf (output_file, " ");
- output_min_issue_delay_vect_name (output_file, automaton);
- fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
- /* Compress the vector. */
- if (automaton->max_min_delay < 2)
- cfactor = 8;
- else if (automaton->max_min_delay < 4)
- cfactor = 4;
- else if (automaton->max_min_delay < 16)
- cfactor = 2;
- else
- cfactor = 1;
- automaton->min_issue_delay_table_compression_factor = cfactor;
- compressed_min_issue_delay_len = (min_issue_delay_len+cfactor-1) / cfactor;
- compressed_min_issue_delay_vect.create (compressed_min_issue_delay_len);
- for (i = 0; i < compressed_min_issue_delay_len; i++)
- compressed_min_issue_delay_vect.quick_push (0);
- for (i = 0; i < min_issue_delay_len; i++)
- {
- size_t ci = i / cfactor;
- vect_el_t x = min_issue_delay_vect[i];
- vect_el_t cx = compressed_min_issue_delay_vect[ci];
- cx |= x << (8 - (i % cfactor + 1) * (8 / cfactor));
- compressed_min_issue_delay_vect[ci] = cx;
- }
- output_vect (compressed_min_issue_delay_vect);
- fprintf (output_file, "};\n\n");
- output_states_vect.release ();
- min_issue_delay_vect.release ();
- compressed_min_issue_delay_vect.release ();
- }
- /* Form and output vector representing the locked states of
- AUTOMATON. */
- static void
- output_dead_lock_vect (automaton_t automaton)
- {
- size_t i;
- arc_t arc;
- vla_hwint_t dead_lock_vect = vla_hwint_t ();
- /* Create vect of pointers to states ordered by num of
- transitions from the state (state with the maximum num is the
- first). */
- automaton->locked_states = 0;
- output_states_vect.create (0);
- pass_states (automaton, add_states_vect_el);
- dead_lock_vect.safe_grow (output_states_vect.length ());
- for (i = 0; i < output_states_vect.length (); i++)
- {
- state_t s = output_states_vect[i];
- arc = first_out_arc (s);
- gcc_assert (arc);
- if (next_out_arc (arc) == NULL
- && (arc->insn->insn_reserv_decl
- == DECL_INSN_RESERV (advance_cycle_insn_decl)))
- {
- dead_lock_vect[s->order_state_num] = 1;
- automaton->locked_states++;
- }
- else
- dead_lock_vect[s->order_state_num] = (vect_el_t) 0;
- }
- if (automaton->locked_states == 0)
- return;
- fprintf (output_file, "/* Vector for locked state flags. */\n");
- fprintf (output_file, "static const ");
- output_range_type (output_file, 0, 1);
- fprintf (output_file, " ");
- output_dead_lock_vect_name (output_file, automaton);
- fprintf (output_file, "[] = {\n");
- output_vect (dead_lock_vect);
- fprintf (output_file, "};\n\n");
- output_states_vect.release ();
- dead_lock_vect.release ();
- }
- /* Form and output vector representing reserved units of the states of
- AUTOMATON. */
- static void
- output_reserved_units_table (automaton_t automaton)
- {
- vla_hwint_t reserved_units_table = vla_hwint_t ();
- int state_byte_size;
- int reserved_units_size;
- size_t n;
- int i;
- if (description->query_units_num == 0)
- return;
- /* Create vect of pointers to states. */
- output_states_vect.create (0);
- pass_states (automaton, add_states_vect_el);
- /* Create vector. */
- state_byte_size = (description->query_units_num + 7) / 8;
- reserved_units_size = (output_states_vect.length ()
- * state_byte_size);
- reserved_units_table.create (reserved_units_size);
- for (i = 0; i < reserved_units_size; i++)
- reserved_units_table.quick_push (0);
- for (n = 0; n < output_states_vect.length (); n++)
- {
- state_t s = output_states_vect[n];
- for (i = 0; i < description->units_num; i++)
- if (units_array [i]->query_p
- && first_cycle_unit_presence (s, i))
- {
- int ri = (s->order_state_num * state_byte_size
- + units_array [i]->query_num / 8);
- vect_el_t x = reserved_units_table[ri];
- x += 1 << (units_array [i]->query_num % 8);
- reserved_units_table[ri] = x;
- }
- }
- fprintf (output_file, "\n#if %s\n", CPU_UNITS_QUERY_MACRO_NAME);
- fprintf (output_file, "/* Vector for reserved units of states. */\n");
- fprintf (output_file, "static const ");
- output_range_type (output_file, 0, 255);
- fprintf (output_file, " ");
- output_reserved_units_table_name (output_file, automaton);
- fprintf (output_file, "[] = {\n");
- output_vect (reserved_units_table);
- fprintf (output_file, "};\n#endif /* #if %s */\n\n",
- CPU_UNITS_QUERY_MACRO_NAME);
- output_states_vect.release ();
- reserved_units_table.release ();
- }
- /* The function outputs all tables representing DFA(s) used for fast
- pipeline hazards recognition. */
- static void
- output_tables (void)
- {
- automaton_t automaton;
- for (automaton = description->first_automaton;
- automaton != NULL;
- automaton = automaton->next_automaton)
- {
- output_translate_vect (automaton);
- output_trans_table (automaton);
- output_min_issue_delay_table (automaton);
- output_dead_lock_vect (automaton);
- output_reserved_units_table (automaton);
- }
- fprintf (output_file, "\n#define %s %d\n\n", ADVANCE_CYCLE_VALUE_NAME,
- DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
- if (collapse_flag)
- fprintf (output_file, "\n#define %s %d\n\n", COLLAPSE_NDFA_VALUE_NAME,
- DECL_INSN_RESERV (collapse_ndfa_insn_decl)->insn_num);
- }
- /* The function outputs definition and value of PHR interface variable
- `max_insn_queue_index'. Its value is not less than maximal queue
- length needed for the insn scheduler. */
- static void
- output_max_insn_queue_index_def (void)
- {
- int i, max, latency;
- decl_t decl;
- max = description->max_insn_reserv_cycles;
- for (i = 0; i < description->decls_num; i++)
- {
- decl = description->decls [i];
- if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
- {
- latency = DECL_INSN_RESERV (decl)->default_latency;
- if (latency > max)
- max = latency;
- }
- else if (decl->mode == dm_bypass)
- {
- latency = DECL_BYPASS (decl)->latency;
- if (latency > max)
- max = latency;
- }
- }
- for (i = 0; (1 << i) <= max; i++)
- ;
- gcc_assert (i >= 0);
- fprintf (output_file, "\nconst int max_insn_queue_index = %d;\n\n",
- (1 << i) - 1);
- }
- /* The function outputs switch cases for insn reservations using
- function *output_automata_list_code. */
- static void
- output_insn_code_cases (void (*output_automata_list_code)
- (automata_list_el_t))
- {
- decl_t decl, decl2;
- int i, j;
- for (i = 0; i < description->decls_num; i++)
- {
- decl = description->decls [i];
- if (decl->mode == dm_insn_reserv)
- DECL_INSN_RESERV (decl)->processed_p = FALSE;
- }
- for (i = 0; i < description->decls_num; i++)
- {
- decl = description->decls [i];
- if (decl->mode == dm_insn_reserv
- && !DECL_INSN_RESERV (decl)->processed_p)
- {
- for (j = i; j < description->decls_num; j++)
- {
- decl2 = description->decls [j];
- if (decl2->mode == dm_insn_reserv
- && (DECL_INSN_RESERV (decl2)->important_automata_list
- == DECL_INSN_RESERV (decl)->important_automata_list))
- {
- DECL_INSN_RESERV (decl2)->processed_p = TRUE;
- fprintf (output_file, " case %d: /* %s */\n",
- DECL_INSN_RESERV (decl2)->insn_num,
- DECL_INSN_RESERV (decl2)->name);
- }
- }
- (*output_automata_list_code)
- (DECL_INSN_RESERV (decl)->important_automata_list);
- }
- }
- }
- /* The function outputs a code for evaluation of a minimal delay of
- issue of insns which have reservations in given AUTOMATA_LIST. */
- static void
- output_automata_list_min_issue_delay_code (automata_list_el_t automata_list)
- {
- automata_list_el_t el;
- automaton_t automaton;
- for (el = automata_list; el != NULL; el = el->next_automata_list_el)
- {
- automaton = el->automaton;
- fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
- output_min_issue_delay_vect_name (output_file, automaton);
- fprintf (output_file,
- (automaton->min_issue_delay_table_compression_factor != 1
- ? " [(" : " ["));
- output_translate_vect_name (output_file, automaton);
- fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
- fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
- output_chip_member_name (output_file, automaton);
- fprintf (output_file, " * %d", automaton->insn_equiv_classes_num);
- if (automaton->min_issue_delay_table_compression_factor == 1)
- fprintf (output_file, "];\n");
- else
- {
- fprintf (output_file, ") / %d];\n",
- automaton->min_issue_delay_table_compression_factor);
- fprintf (output_file, " %s = (%s >> (8 - ((",
- TEMPORARY_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
- output_translate_vect_name (output_file, automaton);
- fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
- fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
- output_chip_member_name (output_file, automaton);
- fprintf (output_file, " * %d)", automaton->insn_equiv_classes_num);
- fprintf
- (output_file, " %% %d + 1) * %d)) & %d;\n",
- automaton->min_issue_delay_table_compression_factor,
- 8 / automaton->min_issue_delay_table_compression_factor,
- (1 << (8 / automaton->min_issue_delay_table_compression_factor))
- - 1);
- }
- if (el == automata_list)
- fprintf (output_file, " %s = %s;\n",
- RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
- else
- {
- fprintf (output_file, " if (%s > %s)\n",
- TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
- fprintf (output_file, " %s = %s;\n",
- RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
- }
- }
- fprintf (output_file, " break;\n\n");
- }
- /* Output function `internal_min_issue_delay'. */
- static void
- output_internal_min_issue_delay_func (void)
- {
- fprintf (output_file,
- "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
- INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
- CHIP_NAME, CHIP_PARAMETER_NAME);
- fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n int %s = -1;\n",
- TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
- fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
- output_insn_code_cases (output_automata_list_min_issue_delay_code);
- fprintf (output_file,
- "\n default:\n %s = -1;\n break;\n }\n",
- RESULT_VARIABLE_NAME);
- fprintf (output_file, " return %s;\n", RESULT_VARIABLE_NAME);
- fprintf (output_file, "}\n\n");
- }
- /* The function outputs a code changing state after issue of insns
- which have reservations in given AUTOMATA_LIST. */
- static void
- output_automata_list_transition_code (automata_list_el_t automata_list)
- {
- automata_list_el_t el, next_el;
- fprintf (output_file, " {\n");
- if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
- for (el = automata_list;; el = next_el)
- {
- next_el = el->next_automata_list_el;
- if (next_el == NULL)
- break;
- fprintf (output_file, " ");
- output_state_member_type (output_file, el->automaton);
- fprintf (output_file, " ");
- output_temp_chip_member_name (output_file, el->automaton);
- fprintf (output_file, ";\n");
- }
- for (el = automata_list; el != NULL; el = el->next_automata_list_el)
- if (comb_vect_p (el->automaton->trans_table))
- {
- fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
- output_trans_base_vect_name (output_file, el->automaton);
- fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
- output_chip_member_name (output_file, el->automaton);
- fprintf (output_file, "] + ");
- output_translate_vect_name (output_file, el->automaton);
- fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
- fprintf (output_file, " if (");
- output_trans_check_vect_name (output_file, el->automaton);
- fprintf (output_file, " [%s] != %s->",
- TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
- output_chip_member_name (output_file, el->automaton);
- fprintf (output_file, ")\n");
- fprintf (output_file, " return %s (%s, %s);\n",
- INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
- CHIP_PARAMETER_NAME);
- fprintf (output_file, " else\n");
- fprintf (output_file, " ");
- if (el->next_automata_list_el != NULL)
- output_temp_chip_member_name (output_file, el->automaton);
- else
- {
- fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
- output_chip_member_name (output_file, el->automaton);
- }
- fprintf (output_file, " = ");
- output_trans_comb_vect_name (output_file, el->automaton);
- fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
- }
- else
- {
- fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
- output_trans_full_vect_name (output_file, el->automaton);
- fprintf (output_file, " [");
- output_translate_vect_name (output_file, el->automaton);
- fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
- fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
- output_chip_member_name (output_file, el->automaton);
- fprintf (output_file, " * %d];\n",
- el->automaton->insn_equiv_classes_num);
- fprintf (output_file, " if (%s >= %d)\n",
- TEMPORARY_VARIABLE_NAME, el->automaton->achieved_states_num);
- fprintf (output_file, " return %s (%s, %s);\n",
- INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
- CHIP_PARAMETER_NAME);
- fprintf (output_file, " else\n ");
- if (el->next_automata_list_el != NULL)
- output_temp_chip_member_name (output_file, el->automaton);
- else
- {
- fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
- output_chip_member_name (output_file, el->automaton);
- }
- fprintf (output_file, " = %s;\n", TEMPORARY_VARIABLE_NAME);
- }
- if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
- for (el = automata_list;; el = next_el)
- {
- next_el = el->next_automata_list_el;
- if (next_el == NULL)
- break;
- fprintf (output_file, " %s->", CHIP_PARAMETER_NAME);
- output_chip_member_name (output_file, el->automaton);
- fprintf (output_file, " = ");
- output_temp_chip_member_name (output_file, el->automaton);
- fprintf (output_file, ";\n");
- }
- fprintf (output_file, " return -1;\n");
- fprintf (output_file, " }\n");
- }
- /* Output function `internal_state_transition'. */
- static void
- output_internal_trans_func (void)
- {
- fprintf (output_file,
- "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
- INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
- CHIP_NAME, CHIP_PARAMETER_NAME);
- fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n", TEMPORARY_VARIABLE_NAME);
- fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
- output_insn_code_cases (output_automata_list_transition_code);
- fprintf (output_file, "\n default:\n return -1;\n }\n");
- fprintf (output_file, "}\n\n");
- }
- /* Output code
- if (insn != 0)
- {
- insn_code = dfa_insn_code (insn);
- if (insn_code > DFA__ADVANCE_CYCLE)
- return code;
- }
- else
- insn_code = DFA__ADVANCE_CYCLE;
- where insn denotes INSN_NAME, insn_code denotes INSN_CODE_NAME, and
- code denotes CODE. */
- static void
- output_internal_insn_code_evaluation (const char *insn_name,
- const char *insn_code_name,
- int code)
- {
- fprintf (output_file, "\n if (%s == 0)\n", insn_name);
- fprintf (output_file, " %s = %s;\n\n",
- insn_code_name, ADVANCE_CYCLE_VALUE_NAME);
- if (collapse_flag)
- {
- fprintf (output_file, "\n else if (%s == const0_rtx)\n", insn_name);
- fprintf (output_file, " %s = %s;\n\n",
- insn_code_name, COLLAPSE_NDFA_VALUE_NAME);
- }
- fprintf (output_file, "\n else\n {\n");
- fprintf (output_file,
- " %s = %s (as_a <rtx_insn *> (%s));\n",
- insn_code_name, DFA_INSN_CODE_FUNC_NAME, insn_name);
- fprintf (output_file, " if (%s > %s)\n return %d;\n }\n",
- insn_code_name, ADVANCE_CYCLE_VALUE_NAME, code);
- }
- /* This function outputs `dfa_insn_code' and its helper function
- `dfa_insn_code_enlarge'. */
- static void
- output_dfa_insn_code_func (void)
- {
- /* Emacs c-mode gets really confused if there's a { or } in column 0
- inside a string, so don't do that. */
- fprintf (output_file, "\
- static void\n\
- dfa_insn_code_enlarge (int uid)\n\
- {\n\
- int i = %s;\n\
- %s = 2 * uid;\n\
- %s = XRESIZEVEC (int, %s,\n\
- %s);\n\
- for (; i < %s; i++)\n\
- %s[i] = -1;\n}\n\n",
- DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
- DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
- DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
- DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
- DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
- DFA_INSN_CODES_VARIABLE_NAME);
- fprintf (output_file, "\
- static inline int\n%s (rtx_insn *%s)\n\
- {\n\
- int uid = INSN_UID (%s);\n\
- int %s;\n\n",
- DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
- INSN_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME);
- fprintf (output_file,
- " if (uid >= %s)\n dfa_insn_code_enlarge (uid);\n\n",
- DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
- fprintf (output_file, " %s = %s[uid];\n",
- INTERNAL_INSN_CODE_NAME, DFA_INSN_CODES_VARIABLE_NAME);
- fprintf (output_file, "\
- if (%s < 0)\n\
- {\n\
- %s = %s (%s);\n\
- %s[uid] = %s;\n\
- }\n",
- INTERNAL_INSN_CODE_NAME,
- INTERNAL_INSN_CODE_NAME,
- INTERNAL_DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
- DFA_INSN_CODES_VARIABLE_NAME, INTERNAL_INSN_CODE_NAME);
- fprintf (output_file, " return %s;\n}\n\n", INTERNAL_INSN_CODE_NAME);
- }
- /* The function outputs PHR interface function `state_transition'. */
- static void
- output_trans_func (void)
- {
- fprintf (output_file, "int\n%s (%s %s, rtx %s)\n",
- TRANSITION_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
- INSN_PARAMETER_NAME);
- fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
- output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
- INTERNAL_INSN_CODE_NAME, -1);
- fprintf (output_file, " return %s (%s, (struct %s *) %s);\n}\n\n",
- INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME, STATE_NAME);
- }
- /* Output function `min_issue_delay'. */
- static void
- output_min_issue_delay_func (void)
- {
- fprintf (output_file, "int\n%s (%s %s, rtx_insn *%s)\n",
- MIN_ISSUE_DELAY_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
- INSN_PARAMETER_NAME);
- fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
- fprintf (output_file, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME);
- fprintf (output_file, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME,
- DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME);
- fprintf (output_file, " if (%s > %s)\n return 0;\n",
- INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
- fprintf (output_file, " }\n else\n %s = %s;\n",
- INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
- fprintf (output_file, "\n return %s (%s, (struct %s *) %s);\n",
- INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
- CHIP_NAME, STATE_NAME);
- fprintf (output_file, "}\n\n");
- }
- /* Output function `internal_dead_lock'. */
- static void
- output_internal_dead_lock_func (void)
- {
- automaton_t automaton;
- fprintf (output_file, "static int\n%s (struct %s *ARG_UNUSED (%s))\n",
- INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
- fprintf (output_file, "{\n");
- for (automaton = description->first_automaton;
- automaton != NULL;
- automaton = automaton->next_automaton)
- if (automaton->locked_states)
- {
- fprintf (output_file, " if (");
- output_dead_lock_vect_name (output_file, automaton);
- fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
- output_chip_member_name (output_file, automaton);
- fprintf (output_file, "])\n return 1/* TRUE */;\n");
- }
- fprintf (output_file, " return 0/* FALSE */;\n}\n\n");
- }
- /* The function outputs PHR interface function `state_dead_lock_p'. */
- static void
- output_dead_lock_func (void)
- {
- fprintf (output_file, "int\n%s (%s %s)\n",
- DEAD_LOCK_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
- fprintf (output_file, "{\n return %s ((struct %s *) %s);\n}\n\n",
- INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME, STATE_NAME);
- }
- /* Output function `internal_reset'. */
- static void
- output_internal_reset_func (void)
- {
- fprintf (output_file, "static inline void\n%s (struct %s *%s)\n",
- INTERNAL_RESET_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
- fprintf (output_file, "{\n memset (%s, 0, sizeof (struct %s));\n}\n\n",
- CHIP_PARAMETER_NAME, CHIP_NAME);
- }
- /* The function outputs PHR interface function `state_size'. */
- static void
- output_size_func (void)
- {
- fprintf (output_file, "int\n%s (void)\n", SIZE_FUNC_NAME);
- fprintf (output_file, "{\n return sizeof (struct %s);\n}\n\n", CHIP_NAME);
- }
- /* The function outputs PHR interface function `state_reset'. */
- static void
- output_reset_func (void)
- {
- fprintf (output_file, "void\n%s (%s %s)\n",
- RESET_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
- fprintf (output_file, "{\n %s ((struct %s *) %s);\n}\n\n", INTERNAL_RESET_FUNC_NAME,
- CHIP_NAME, STATE_NAME);
- }
- /* Output function `min_insn_conflict_delay'. */
- static void
- output_min_insn_conflict_delay_func (void)
- {
- fprintf (output_file,
- "int\n%s (%s %s, rtx %s, rtx %s)\n",
- MIN_INSN_CONFLICT_DELAY_FUNC_NAME, STATE_TYPE_NAME,
- STATE_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
- fprintf (output_file, "{\n struct %s %s;\n int %s, %s, transition;\n",
- CHIP_NAME, CHIP_NAME, INTERNAL_INSN_CODE_NAME,
- INTERNAL_INSN2_CODE_NAME);
- output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
- INTERNAL_INSN_CODE_NAME, 0);
- output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
- INTERNAL_INSN2_CODE_NAME, 0);
- fprintf (output_file, " memcpy (&%s, %s, sizeof (%s));\n",
- CHIP_NAME, STATE_NAME, CHIP_NAME);
- fprintf (output_file, " %s (&%s);\n", INTERNAL_RESET_FUNC_NAME, CHIP_NAME);
- fprintf (output_file, " transition = %s (%s, &%s);\n",
- INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME);
- fprintf (output_file, " gcc_assert (transition <= 0);\n");
- fprintf (output_file, " return %s (%s, &%s);\n",
- INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN2_CODE_NAME,
- CHIP_NAME);
- fprintf (output_file, "}\n\n");
- }
- /* Output the array holding default latency values. These are used in
- insn_latency and maximal_insn_latency function implementations. */
- static void
- output_default_latencies (void)
- {
- int i, j, col;
- decl_t decl;
- const char *tabletype = "unsigned char";
- /* Find the smallest integer type that can hold all the default
- latency values. */
- for (i = 0; i < description->decls_num; i++)
- if (description->decls[i]->mode == dm_insn_reserv)
- {
- decl = description->decls[i];
- if (DECL_INSN_RESERV (decl)->default_latency > UCHAR_MAX
- && tabletype[0] != 'i') /* Don't shrink it. */
- tabletype = "unsigned short";
- if (DECL_INSN_RESERV (decl)->default_latency > USHRT_MAX)
- tabletype = "int";
- }
- fprintf (output_file, " static const %s default_latencies[] =\n {",
- tabletype);
- for (i = 0, j = 0, col = 7; i < description->normal_decls_num; i++)
- if (description->decls[i]->mode == dm_insn_reserv)
- {
- if ((col = (col+1) % 8) == 0)
- fputs ("\n ", output_file);
- decl = description->decls[i];
- gcc_assert (j++ == DECL_INSN_RESERV (decl)->insn_num);
- fprintf (output_file, "% 4d,",
- DECL_INSN_RESERV (decl)->default_latency);
- }
- gcc_assert (j == description->insns_num - (collapse_flag ? 2 : 1));
- fputs ("\n };\n", output_file);
- }
- /* Output function `internal_insn_latency'. */
- static void
- output_internal_insn_latency_func (void)
- {
- int i;
- decl_t decl;
- struct bypass_decl *bypass;
- fprintf (output_file, "static int\n%s (int %s ATTRIBUTE_UNUSED,\n\tint %s ATTRIBUTE_UNUSED,\n\trtx %s ATTRIBUTE_UNUSED,\n\trtx %s ATTRIBUTE_UNUSED)\n",
- INTERNAL_INSN_LATENCY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
- INTERNAL_INSN2_CODE_NAME, "insn_or_const0",
- "insn2_or_const0");
- fprintf (output_file, "{\n");
- if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
- {
- fputs (" return 0;\n}\n\n", output_file);
- return;
- }
- fprintf (output_file, " if (%s >= %s || %s >= %s)\n return 0;\n",
- INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
- INTERNAL_INSN2_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
- /* We've now rejected the case that
- INTERNAL_INSN_CODE_NAME >= ADVANCE_CYCLE_VALUE_NAME
- i.e. that
- insn_code >= DFA__ADVANCE_CYCLE,
- and similarly for insn2_code. */
- fprintf (output_file,
- " /* Within output_internal_insn_code_evaluation, the generated\n"
- " code sets \"code\" to NDFA__COLLAPSE for const0_rtx, and\n"
- " NDFA__COLLAPSE > DFA__ADVANCE_CYCLE. Hence we can't be\n"
- " dealing with const0_rtx instances at this point. */\n");
- if (collapse_flag)
- fprintf (output_file,
- " gcc_assert (NDFA__COLLAPSE > DFA__ADVANCE_CYCLE);\n");
- fprintf (output_file,
- (" gcc_assert (insn_or_const0 != const0_rtx);\n"
- " rtx_insn *%s ATTRIBUTE_UNUSED = safe_as_a <rtx_insn *> (insn_or_const0);\n"),
- INSN_PARAMETER_NAME);
- fprintf (output_file,
- (" gcc_assert (insn2_or_const0 != const0_rtx);\n"
- " rtx_insn *%s ATTRIBUTE_UNUSED = safe_as_a <rtx_insn *> (insn2_or_const0);\n"),
- INSN2_PARAMETER_NAME);
- fprintf (output_file, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
- for (i = 0; i < description->decls_num; i++)
- if (description->decls[i]->mode == dm_insn_reserv
- && DECL_INSN_RESERV (description->decls[i])->bypass_list)
- {
- decl = description->decls [i];
- fprintf (output_file,
- " case %d:\n switch (%s)\n {\n",
- DECL_INSN_RESERV (decl)->insn_num,
- INTERNAL_INSN2_CODE_NAME);
- for (bypass = DECL_INSN_RESERV (decl)->bypass_list;
- bypass != NULL;
- bypass = bypass->next)
- {
- gcc_assert (bypass->in_insn_reserv->insn_num
- != (DECL_INSN_RESERV
- (advance_cycle_insn_decl)->insn_num));
- fprintf (output_file, " case %d:\n",
- bypass->in_insn_reserv->insn_num);
- for (;;)
- {
- if (bypass->bypass_guard_name == NULL)
- {
- gcc_assert (bypass->next == NULL
- || (bypass->in_insn_reserv
- != bypass->next->in_insn_reserv));
- fprintf (output_file, " return %d;\n",
- bypass->latency);
- }
- else
- {
- fprintf (output_file,
- " if (%s (%s, %s))\n",
- bypass->bypass_guard_name, INSN_PARAMETER_NAME,
- INSN2_PARAMETER_NAME);
- fprintf (output_file, " return %d;\n",
- bypass->latency);
- }
- if (bypass->next == NULL
- || bypass->in_insn_reserv != bypass->next->in_insn_reserv)
- break;
- bypass = bypass->next;
- }
- if (bypass->bypass_guard_name != NULL)
- fprintf (output_file, " break;\n");
- }
- fputs (" }\n break;\n", output_file);
- }
- fprintf (output_file, " }\n return default_latencies[%s];\n}\n\n",
- INTERNAL_INSN_CODE_NAME);
- }
- /* Output function `internal_maximum_insn_latency'. */
- static void
- output_internal_maximal_insn_latency_func (void)
- {
- decl_t decl;
- struct bypass_decl *bypass;
- int i;
- int max;
- fprintf (output_file, "static int\n%s (int %s ATTRIBUTE_UNUSED,\n\trtx %s ATTRIBUTE_UNUSED)\n",
- "internal_maximal_insn_latency", INTERNAL_INSN_CODE_NAME,
- INSN_PARAMETER_NAME);
- fprintf (output_file, "{\n");
- if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
- {
- fputs (" return 0;\n}\n\n", output_file);
- return;
- }
- fprintf (output_file, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
- for (i = 0; i < description->decls_num; i++)
- if (description->decls[i]->mode == dm_insn_reserv
- && DECL_INSN_RESERV (description->decls[i])->bypass_list)
- {
- decl = description->decls [i];
- max = DECL_INSN_RESERV (decl)->default_latency;
- fprintf (output_file,
- " case %d: {",
- DECL_INSN_RESERV (decl)->insn_num);
- for (bypass = DECL_INSN_RESERV (decl)->bypass_list;
- bypass != NULL;
- bypass = bypass->next)
- {
- if (bypass->latency > max)
- max = bypass->latency;
- }
- fprintf (output_file, " return %d; }\n break;\n", max);
- }
- fprintf (output_file, " }\n return default_latencies[%s];\n}\n\n",
- INTERNAL_INSN_CODE_NAME);
- }
- /* The function outputs PHR interface function `insn_latency'. */
- static void
- output_insn_latency_func (void)
- {
- fprintf (output_file, "int\n%s (rtx %s, rtx %s)\n",
- INSN_LATENCY_FUNC_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
- fprintf (output_file, "{\n int %s, %s;\n",
- INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME);
- output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
- INTERNAL_INSN_CODE_NAME, 0);
- output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
- INTERNAL_INSN2_CODE_NAME, 0);
- fprintf (output_file, " return %s (%s, %s, %s, %s);\n}\n\n",
- INTERNAL_INSN_LATENCY_FUNC_NAME,
- INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME,
- INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
- }
- /* The function outputs PHR interface function `maximal_insn_latency'. */
- static void
- output_maximal_insn_latency_func (void)
- {
- fprintf (output_file, "int\n%s (rtx %s)\n",
- "maximal_insn_latency", INSN_PARAMETER_NAME);
- fprintf (output_file, "{\n int %s;\n",
- INTERNAL_INSN_CODE_NAME);
- output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
- INTERNAL_INSN_CODE_NAME, 0);
- fprintf (output_file, " return %s (%s, %s);\n}\n\n",
- "internal_maximal_insn_latency",
- INTERNAL_INSN_CODE_NAME, INSN_PARAMETER_NAME);
- }
- /* The function outputs PHR interface function `print_reservation'. */
- static void
- output_print_reservation_func (void)
- {
- decl_t decl;
- int i, j;
- fprintf (output_file,
- "void\n%s (FILE *%s, rtx_insn *%s ATTRIBUTE_UNUSED)\n{\n",
- PRINT_RESERVATION_FUNC_NAME, FILE_PARAMETER_NAME,
- INSN_PARAMETER_NAME);
- if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
- {
- fprintf (output_file, " fputs (\"%s\", %s);\n}\n\n",
- NOTHING_NAME, FILE_PARAMETER_NAME);
- return;
- }
- fputs (" static const char *const reservation_names[] =\n {",
- output_file);
- for (i = 0, j = 0; i < description->normal_decls_num; i++)
- {
- decl = description->decls [i];
- if (decl->mode == dm_insn_reserv)
- {
- gcc_assert (j == DECL_INSN_RESERV (decl)->insn_num);
- j++;
- fprintf (output_file, "\n \"%s\",",
- regexp_representation (DECL_INSN_RESERV (decl)->regexp));
- finish_regexp_representation ();
- }
- }
- gcc_assert (j == description->insns_num - (collapse_flag ? 2 : 1));
- fprintf (output_file, "\n \"%s\"\n };\n int %s;\n\n",
- NOTHING_NAME, INTERNAL_INSN_CODE_NAME);
- fprintf (output_file, " if (%s == 0)\n %s = %s;\n",
- INSN_PARAMETER_NAME,
- INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
- fprintf (output_file, " else\n\
- {\n\
- %s = %s (%s);\n\
- if (%s > %s)\n\
- %s = %s;\n\
- }\n",
- INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
- INSN_PARAMETER_NAME,
- INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
- INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
- fprintf (output_file, " fputs (reservation_names[%s], %s);\n}\n\n",
- INTERNAL_INSN_CODE_NAME, FILE_PARAMETER_NAME);
- }
- /* The following function is used to sort unit declaration by their
- names. */
- static int
- units_cmp (const void *unit1, const void *unit2)
- {
- const_unit_decl_t const u1 = *(const_unit_decl_t const*) unit1;
- const_unit_decl_t const u2 = *(const_unit_decl_t const*) unit2;
- return strcmp (u1->name, u2->name);
- }
- /* The following macro value is name of struct containing unit name
- and unit code. */
- #define NAME_CODE_STRUCT_NAME "name_code"
- /* The following macro value is name of table of struct name_code. */
- #define NAME_CODE_TABLE_NAME "name_code_table"
- /* The following macro values are member names for struct name_code. */
- #define NAME_MEMBER_NAME "name"
- #define CODE_MEMBER_NAME "code"
- /* The following macro values are local variable names for function
- `get_cpu_unit_code'. */
- #define CMP_VARIABLE_NAME "cmp"
- #define LOW_VARIABLE_NAME "l"
- #define MIDDLE_VARIABLE_NAME "m"
- #define HIGH_VARIABLE_NAME "h"
- /* The following function outputs function to obtain internal cpu unit
- code by the cpu unit name. */
- static void
- output_get_cpu_unit_code_func (void)
- {
- int i;
- unit_decl_t *units;
- fprintf (output_file, "int\n%s (const char *%s)\n",
- GET_CPU_UNIT_CODE_FUNC_NAME, CPU_UNIT_NAME_PARAMETER_NAME);
- fprintf (output_file, "{\n struct %s {const char *%s; int %s;};\n",
- NAME_CODE_STRUCT_NAME, NAME_MEMBER_NAME, CODE_MEMBER_NAME);
- fprintf (output_file, " int %s, %s, %s, %s;\n", CMP_VARIABLE_NAME,
- LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME, HIGH_VARIABLE_NAME);
- fprintf (output_file, " static struct %s %s [] =\n {\n",
- NAME_CODE_STRUCT_NAME, NAME_CODE_TABLE_NAME);
- units = XNEWVEC (unit_decl_t, description->units_num);
- memcpy (units, units_array, sizeof (unit_decl_t) * description->units_num);
- qsort (units, description->units_num, sizeof (unit_decl_t), units_cmp);
- for (i = 0; i < description->units_num; i++)
- if (units [i]->query_p)
- fprintf (output_file, " {\"%s\", %d},\n",
- units[i]->name, units[i]->query_num);
- fprintf (output_file, " };\n\n");
- fprintf (output_file, " /* The following is binary search: */\n");
- fprintf (output_file, " %s = 0;\n", LOW_VARIABLE_NAME);
- fprintf (output_file, " %s = sizeof (%s) / sizeof (struct %s) - 1;\n",
- HIGH_VARIABLE_NAME, NAME_CODE_TABLE_NAME, NAME_CODE_STRUCT_NAME);
- fprintf (output_file, " while (%s <= %s)\n {\n",
- LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
- fprintf (output_file, " %s = (%s + %s) / 2;\n",
- MIDDLE_VARIABLE_NAME, LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
- fprintf (output_file, " %s = strcmp (%s, %s [%s].%s);\n",
- CMP_VARIABLE_NAME, CPU_UNIT_NAME_PARAMETER_NAME,
- NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, NAME_MEMBER_NAME);
- fprintf (output_file, " if (%s < 0)\n", CMP_VARIABLE_NAME);
- fprintf (output_file, " %s = %s - 1;\n",
- HIGH_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
- fprintf (output_file, " else if (%s > 0)\n", CMP_VARIABLE_NAME);
- fprintf (output_file, " %s = %s + 1;\n",
- LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
- fprintf (output_file, " else\n");
- fprintf (output_file, " return %s [%s].%s;\n }\n",
- NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, CODE_MEMBER_NAME);
- fprintf (output_file, " return -1;\n}\n\n");
- free (units);
- }
- /* The following function outputs function to check reservation of cpu
- unit (its internal code will be passed as the function argument) in
- given cpu state. */
- static void
- output_cpu_unit_reservation_p (void)
- {
- automaton_t automaton;
- fprintf (output_file, "int\n%s (%s %s, int %s)\n",
- CPU_UNIT_RESERVATION_P_FUNC_NAME,
- STATE_TYPE_NAME, STATE_NAME,
- CPU_CODE_PARAMETER_NAME);
- fprintf (output_file, "{\n gcc_assert (%s >= 0 && %s < %d);\n",
- CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME,
- description->query_units_num);
- if (description->query_units_num > 0)
- for (automaton = description->first_automaton;
- automaton != NULL;
- automaton = automaton->next_automaton)
- {
- fprintf (output_file, " if ((");
- output_reserved_units_table_name (output_file, automaton);
- fprintf (output_file, " [((struct %s *) %s)->", CHIP_NAME, STATE_NAME);
- output_chip_member_name (output_file, automaton);
- fprintf (output_file, " * %d + %s / 8] >> (%s %% 8)) & 1)\n",
- (description->query_units_num + 7) / 8,
- CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME);
- fprintf (output_file, " return 1;\n");
- }
- fprintf (output_file, " return 0;\n}\n\n");
- }
- /* The following function outputs a function to check if insn
- has a dfa reservation. */
- static void
- output_insn_has_dfa_reservation_p (void)
- {
- fprintf (output_file,
- "bool\n%s (rtx_insn *%s ATTRIBUTE_UNUSED)\n{\n",
- INSN_HAS_DFA_RESERVATION_P_FUNC_NAME,
- INSN_PARAMETER_NAME);
- if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
- {
- fprintf (output_file, " return false;\n}\n\n");
- return;
- }
- fprintf (output_file, " int %s;\n\n", INTERNAL_INSN_CODE_NAME);
- fprintf (output_file, " if (%s == 0)\n %s = %s;\n",
- INSN_PARAMETER_NAME,
- INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
- fprintf (output_file, " else\n\
- {\n\
- %s = %s (%s);\n\
- if (%s > %s)\n\
- %s = %s;\n\
- }\n\n",
- INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
- INSN_PARAMETER_NAME,
- INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
- INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
- fprintf (output_file, " return %s != %s;\n}\n\n",
- INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
- }
- /* The function outputs PHR interface functions `dfa_clean_insn_cache'
- and 'dfa_clear_single_insn_cache'. */
- static void
- output_dfa_clean_insn_cache_func (void)
- {
- fprintf (output_file,
- "void\n%s (void)\n{\n int %s;\n\n",
- DFA_CLEAN_INSN_CACHE_FUNC_NAME, I_VARIABLE_NAME);
- fprintf (output_file,
- " for (%s = 0; %s < %s; %s++)\n %s [%s] = -1;\n}\n\n",
- I_VARIABLE_NAME, I_VARIABLE_NAME,
- DFA_INSN_CODES_LENGTH_VARIABLE_NAME, I_VARIABLE_NAME,
- DFA_INSN_CODES_VARIABLE_NAME, I_VARIABLE_NAME);
- fprintf (output_file,
- "void\n%s (rtx_insn *%s)\n{\n int %s;\n\n",
- DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME, INSN_PARAMETER_NAME,
- I_VARIABLE_NAME);
- fprintf (output_file,
- " %s = INSN_UID (%s);\n if (%s < %s)\n %s [%s] = -1;\n}\n\n",
- I_VARIABLE_NAME, INSN_PARAMETER_NAME, I_VARIABLE_NAME,
- DFA_INSN_CODES_LENGTH_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
- I_VARIABLE_NAME);
- }
- /* The function outputs PHR interface function `dfa_start'. */
- static void
- output_dfa_start_func (void)
- {
- fprintf (output_file,
- "void\n%s (void)\n{\n %s = get_max_uid ();\n",
- DFA_START_FUNC_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
- fprintf (output_file, " %s = XNEWVEC (int, %s);\n",
- DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
- fprintf (output_file, " %s ();\n}\n\n", DFA_CLEAN_INSN_CACHE_FUNC_NAME);
- }
- /* The function outputs PHR interface function `dfa_finish'. */
- static void
- output_dfa_finish_func (void)
- {
- fprintf (output_file, "void\n%s (void)\n{\n free (%s);\n}\n\n",
- DFA_FINISH_FUNC_NAME, DFA_INSN_CODES_VARIABLE_NAME);
- }
- /* The page contains code for output description file (readable
- representation of original description and generated DFA(s). */
- /* The function outputs string representation of IR reservation. */
- static void
- output_regexp (regexp_t regexp)
- {
- fprintf (output_description_file, "%s", regexp_representation (regexp));
- finish_regexp_representation ();
- }
- /* Output names of units in LIST separated by comma. */
- static void
- output_unit_set_el_list (unit_set_el_t list)
- {
- unit_set_el_t el;
- for (el = list; el != NULL; el = el->next_unit_set_el)
- {
- if (el != list)
- fprintf (output_description_file, ", ");
- fprintf (output_description_file, "%s", el->unit_decl->name);
- }
- }
- /* Output patterns in LIST separated by comma. */
- static void
- output_pattern_set_el_list (pattern_set_el_t list)
- {
- pattern_set_el_t el;
- int i;
- for (el = list; el != NULL; el = el->next_pattern_set_el)
- {
- if (el != list)
- fprintf (output_description_file, ", ");
- for (i = 0; i < el->units_num; i++)
- fprintf (output_description_file, (i == 0 ? "%s" : " %s"),
- el->unit_decls [i]->name);
- }
- }
- /* The function outputs string representation of IR define_reservation
- and define_insn_reservation. */
- static void
- output_description (void)
- {
- decl_t decl;
- int i;
- for (i = 0; i < description->decls_num; i++)
- {
- decl = description->decls [i];
- if (decl->mode == dm_unit)
- {
- if (DECL_UNIT (decl)->excl_list != NULL)
- {
- fprintf (output_description_file, "unit %s exclusion_set: ",
- DECL_UNIT (decl)->name);
- output_unit_set_el_list (DECL_UNIT (decl)->excl_list);
- fprintf (output_description_file, "\n");
- }
- if (DECL_UNIT (decl)->presence_list != NULL)
- {
- fprintf (output_description_file, "unit %s presence_set: ",
- DECL_UNIT (decl)->name);
- output_pattern_set_el_list (DECL_UNIT (decl)->presence_list);
- fprintf (output_description_file, "\n");
- }
- if (DECL_UNIT (decl)->final_presence_list != NULL)
- {
- fprintf (output_description_file, "unit %s final_presence_set: ",
- DECL_UNIT (decl)->name);
- output_pattern_set_el_list
- (DECL_UNIT (decl)->final_presence_list);
- fprintf (output_description_file, "\n");
- }
- if (DECL_UNIT (decl)->absence_list != NULL)
- {
- fprintf (output_description_file, "unit %s absence_set: ",
- DECL_UNIT (decl)->name);
- output_pattern_set_el_list (DECL_UNIT (decl)->absence_list);
- fprintf (output_description_file, "\n");
- }
- if (DECL_UNIT (decl)->final_absence_list != NULL)
- {
- fprintf (output_description_file, "unit %s final_absence_set: ",
- DECL_UNIT (decl)->name);
- output_pattern_set_el_list
- (DECL_UNIT (decl)->final_absence_list);
- fprintf (output_description_file, "\n");
- }
- }
- }
- fprintf (output_description_file, "\n");
- for (i = 0; i < description->normal_decls_num; i++)
- {
- decl = description->decls [i];
- if (decl->mode == dm_reserv)
- {
- fprintf (output_description_file, "reservation %s: ",
- DECL_RESERV (decl)->name);
- output_regexp (DECL_RESERV (decl)->regexp);
- fprintf (output_description_file, "\n");
- }
- else if (decl->mode == dm_insn_reserv)
- {
- fprintf (output_description_file, "insn reservation %s ",
- DECL_INSN_RESERV (decl)->name);
- print_rtl (output_description_file,
- DECL_INSN_RESERV (decl)->condexp);
- fprintf (output_description_file, ": ");
- output_regexp (DECL_INSN_RESERV (decl)->regexp);
- fprintf (output_description_file, "\n");
- }
- else if (decl->mode == dm_bypass)
- fprintf (output_description_file, "bypass %d %s %s\n",
- DECL_BYPASS (decl)->latency,
- DECL_BYPASS (decl)->out_pattern,
- DECL_BYPASS (decl)->in_pattern);
- }
- fprintf (output_description_file, "\n\f\n");
- }
- /* The function outputs name of AUTOMATON. */
- static void
- output_automaton_name (FILE *f, automaton_t automaton)
- {
- if (automaton->corresponding_automaton_decl == NULL)
- fprintf (f, "#%d", automaton->automaton_order_num);
- else
- fprintf (f, "`%s'", automaton->corresponding_automaton_decl->name);
- }
- /* Maximal length of line for pretty printing into description
- file. */
- #define MAX_LINE_LENGTH 70
- /* The function outputs units name belonging to AUTOMATON. */
- static void
- output_automaton_units (automaton_t automaton)
- {
- decl_t decl;
- const char *name;
- int curr_line_length;
- int there_is_an_automaton_unit;
- int i;
- fprintf (output_description_file, "\n Corresponding units:\n");
- fprintf (output_description_file, " ");
- curr_line_length = 4;
- there_is_an_automaton_unit = 0;
- for (i = 0; i < description->decls_num; i++)
- {
- decl = description->decls [i];
- if (decl->mode == dm_unit
- && (DECL_UNIT (decl)->corresponding_automaton_num
- == automaton->automaton_order_num))
- {
- there_is_an_automaton_unit = 1;
- name = DECL_UNIT (decl)->name;
- if (curr_line_length + strlen (name) + 1 > MAX_LINE_LENGTH )
- {
- curr_line_length = strlen (name) + 4;
- fprintf (output_description_file, "\n ");
- }
- else
- {
- curr_line_length += strlen (name) + 1;
- fprintf (output_description_file, " ");
- }
- fprintf (output_description_file, "%s", name);
- }
- }
- if (!there_is_an_automaton_unit)
- fprintf (output_description_file, "<None>");
- fprintf (output_description_file, "\n\n");
- }
- /* The following variable is used for forming array of all possible cpu unit
- reservations described by the current DFA state. */
- static vec<reserv_sets_t> state_reservs;
- /* The function forms `state_reservs' for STATE. */
- static void
- add_state_reservs (state_t state)
- {
- alt_state_t curr_alt_state;
- if (state->component_states != NULL)
- for (curr_alt_state = state->component_states;
- curr_alt_state != NULL;
- curr_alt_state = curr_alt_state->next_sorted_alt_state)
- add_state_reservs (curr_alt_state->state);
- else
- state_reservs.safe_push (state->reservs);
- }
- /* The function outputs readable representation of all out arcs of
- STATE. */
- static void
- output_state_arcs (state_t state)
- {
- arc_t arc;
- ainsn_t ainsn;
- const char *insn_name;
- int curr_line_length;
- for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
- {
- ainsn = arc->insn;
- gcc_assert (ainsn->first_insn_with_same_reservs);
- fprintf (output_description_file, " ");
- curr_line_length = 7;
- fprintf (output_description_file, "%2d: ", ainsn->insn_equiv_class_num);
- do
- {
- insn_name = ainsn->insn_reserv_decl->name;
- if (curr_line_length + strlen (insn_name) > MAX_LINE_LENGTH)
- {
- if (ainsn != arc->insn)
- {
- fprintf (output_description_file, ",\n ");
- curr_line_length = strlen (insn_name) + 6;
- }
- else
- curr_line_length += strlen (insn_name);
- }
- else
- {
- curr_line_length += strlen (insn_name);
- if (ainsn != arc->insn)
- {
- curr_line_length += 2;
- fprintf (output_description_file, ", ");
- }
- }
- fprintf (output_description_file, "%s", insn_name);
- ainsn = ainsn->next_same_reservs_insn;
- }
- while (ainsn != NULL);
- fprintf (output_description_file, " %d \n",
- arc->to_state->order_state_num);
- }
- fprintf (output_description_file, "\n");
- }
- /* The following function is used for sorting possible cpu unit
- reservation of a DFA state. */
- static int
- state_reservs_cmp (const void *reservs_ptr_1, const void *reservs_ptr_2)
- {
- return reserv_sets_cmp (*(const_reserv_sets_t const*) reservs_ptr_1,
- *(const_reserv_sets_t const*) reservs_ptr_2);
- }
- /* The following function is used for sorting possible cpu unit
- reservation of a DFA state. */
- static void
- remove_state_duplicate_reservs (void)
- {
- size_t i, j;
- for (i = 1, j = 0; i < state_reservs.length (); i++)
- if (reserv_sets_cmp (state_reservs[j], state_reservs[i]))
- {
- j++;
- state_reservs[j] = state_reservs[i];
- }
- state_reservs.truncate (j + 1);
- }
- /* The following function output readable representation of DFA(s)
- state used for fast recognition of pipeline hazards. State is
- described by possible (current and scheduled) cpu unit
- reservations. */
- static void
- output_state (state_t state)
- {
- size_t i;
- state_reservs.create (0);
- fprintf (output_description_file, " State #%d", state->order_state_num);
- fprintf (output_description_file,
- state->new_cycle_p ? " (new cycle)\n" : "\n");
- add_state_reservs (state);
- state_reservs.qsort (state_reservs_cmp);
- remove_state_duplicate_reservs ();
- for (i = 0; i < state_reservs.length (); i++)
- {
- fprintf (output_description_file, " ");
- output_reserv_sets (output_description_file, state_reservs[i]);
- fprintf (output_description_file, "\n");
- }
- fprintf (output_description_file, "\n");
- output_state_arcs (state);
- state_reservs.release ();
- }
- /* The following function output readable representation of
- DFAs used for fast recognition of pipeline hazards. */
- static void
- output_automaton_descriptions (void)
- {
- automaton_t automaton;
- for (automaton = description->first_automaton;
- automaton != NULL;
- automaton = automaton->next_automaton)
- {
- fprintf (output_description_file, "\nAutomaton ");
- output_automaton_name (output_description_file, automaton);
- fprintf (output_description_file, "\n");
- output_automaton_units (automaton);
- pass_states (automaton, output_state);
- }
- }
- /* The page contains top level function for generation DFA(s) used for
- PHR. */
- /* The function outputs statistics about work of different phases of
- DFA generator. */
- static void
- output_statistics (FILE *f)
- {
- automaton_t automaton;
- int states_num;
- #ifndef NDEBUG
- int transition_comb_vect_els = 0;
- int transition_full_vect_els = 0;
- int min_issue_delay_vect_els = 0;
- int locked_states = 0;
- #endif
- for (automaton = description->first_automaton;
- automaton != NULL;
- automaton = automaton->next_automaton)
- {
- fprintf (f, "\nAutomaton ");
- output_automaton_name (f, automaton);
- fprintf (f, "\n %5d NDFA states, %5d NDFA arcs\n",
- automaton->NDFA_states_num, automaton->NDFA_arcs_num);
- fprintf (f, " %5d DFA states, %5d DFA arcs\n",
- automaton->DFA_states_num, automaton->DFA_arcs_num);
- states_num = automaton->DFA_states_num;
- if (!no_minimization_flag)
- {
- fprintf (f, " %5d minimal DFA states, %5d minimal DFA arcs\n",
- automaton->minimal_DFA_states_num,
- automaton->minimal_DFA_arcs_num);
- states_num = automaton->minimal_DFA_states_num;
- }
- fprintf (f, " %5d all insns %5d insn equivalence classes\n",
- description->insns_num, automaton->insn_equiv_classes_num);
- fprintf (f, " %d locked states\n", automaton->locked_states);
- #ifndef NDEBUG
- fprintf
- (f, "%5ld transition comb vector els, %5ld trans table els: %s\n",
- (long) automaton->trans_table->comb_vect.length (),
- (long) automaton->trans_table->full_vect.length (),
- (comb_vect_p (automaton->trans_table)
- ? "use comb vect" : "use simple vect"));
- fprintf
- (f, "%5ld min delay table els, compression factor %d\n",
- (long) states_num * automaton->insn_equiv_classes_num,
- automaton->min_issue_delay_table_compression_factor);
- transition_comb_vect_els
- += automaton->trans_table->comb_vect.length ();
- transition_full_vect_els
- += automaton->trans_table->full_vect.length ();
- min_issue_delay_vect_els
- += states_num * automaton->insn_equiv_classes_num;
- locked_states
- += automaton->locked_states;
- #endif
- }
- #ifndef NDEBUG
- fprintf (f, "\n%5d all allocated states, %5d all allocated arcs\n",
- allocated_states_num, allocated_arcs_num);
- fprintf (f, "%5d all allocated alternative states\n",
- allocated_alt_states_num);
- fprintf (f, "%5d all transition comb vector els, %5d all trans table els\n",
- transition_comb_vect_els, transition_full_vect_els);
- fprintf (f, "%5d all min delay table els\n", min_issue_delay_vect_els);
- fprintf (f, "%5d all locked states\n", locked_states);
- #endif
- }
- /* The function output times of work of different phases of DFA
- generator. */
- static void
- output_time_statistics (FILE *f)
- {
- fprintf (f, "\n transformation: ");
- print_active_time (f, transform_time);
- fprintf (f, (!ndfa_flag ? ", building DFA: " : ", building NDFA: "));
- print_active_time (f, NDFA_time);
- if (ndfa_flag)
- {
- fprintf (f, ", NDFA -> DFA: ");
- print_active_time (f, NDFA_to_DFA_time);
- }
- fprintf (f, "\n DFA minimization: ");
- print_active_time (f, minimize_time);
- fprintf (f, ", making insn equivalence: ");
- print_active_time (f, equiv_time);
- fprintf (f, "\n all automaton generation: ");
- print_active_time (f, automaton_generation_time);
- fprintf (f, ", output: ");
- print_active_time (f, output_time);
- fprintf (f, "\n");
- }
- /* The function generates DFA (deterministic finite state automaton)
- for fast recognition of pipeline hazards. No errors during
- checking must be fixed before this function call. */
- static void
- generate (void)
- {
- automata_num = split_argument;
- if (description->units_num < automata_num)
- automata_num = description->units_num;
- initiate_states ();
- initiate_arcs ();
- initiate_automata_lists ();
- initiate_pass_states ();
- initiate_excl_sets ();
- initiate_presence_absence_pattern_sets ();
- automaton_generation_time = create_ticker ();
- create_automata ();
- ticker_off (&automaton_generation_time);
- }
- /* This page mainly contains top level functions of pipeline hazards
- description translator. */
- /* The following macro value is suffix of name of description file of
- pipeline hazards description translator. */
- #define STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX ".dfa"
- /* The function returns suffix of given file name. The returned
- string can not be changed. */
- static const char *
- file_name_suffix (const char *file_name)
- {
- const char *last_period;
- for (last_period = NULL; *file_name != '\0'; file_name++)
- if (*file_name == '.')
- last_period = file_name;
- return (last_period == NULL ? file_name : last_period);
- }
- /* The function returns base name of given file name, i.e. pointer to
- first char after last `/' (or `\' for WIN32) in given file name,
- given file name itself if the directory name is absent. The
- returned string can not be changed. */
- static const char *
- base_file_name (const char *file_name)
- {
- int directory_name_length;
- directory_name_length = strlen (file_name);
- #ifdef WIN32
- while (directory_name_length >= 0 && file_name[directory_name_length] != '/'
- && file_name[directory_name_length] != '\\')
- #else
- while (directory_name_length >= 0 && file_name[directory_name_length] != '/')
- #endif
- directory_name_length--;
- return file_name + directory_name_length + 1;
- }
- /* A function passed as argument to init_rtx_reader_args_cb. It parses the
- options available for genautomata. Returns true if the option was
- recognized. */
- static bool
- parse_automata_opt (const char *str)
- {
- if (strcmp (str, NO_MINIMIZATION_OPTION) == 0)
- no_minimization_flag = 1;
- else if (strcmp (str, TIME_OPTION) == 0)
- time_flag = 1;
- else if (strcmp (str, STATS_OPTION) == 0)
- stats_flag = 1;
- else if (strcmp (str, V_OPTION) == 0)
- v_flag = 1;
- else if (strcmp (str, W_OPTION) == 0)
- w_flag = 1;
- else if (strcmp (str, NDFA_OPTION) == 0)
- ndfa_flag = 1;
- else if (strcmp (str, COLLAPSE_OPTION) == 0)
- collapse_flag = 1;
- else if (strcmp (str, PROGRESS_OPTION) == 0)
- progress_flag = 1;
- else if (strcmp (str, "-split") == 0)
- {
- fatal ("option `-split' has not been implemented yet\n");
- /* split_argument = atoi (argument_vect [i + 1]); */
- }
- else
- return false;
- return true;
- }
- /* The following is top level function to initialize the work of
- pipeline hazards description translator. */
- static void
- initiate_automaton_gen (char **argv)
- {
- const char *base_name;
- /* Initialize IR storage. */
- obstack_init (&irp);
- initiate_automaton_decl_table ();
- initiate_insn_decl_table ();
- initiate_decl_table ();
- output_file = stdout;
- output_description_file = NULL;
- base_name = base_file_name (argv[1]);
- obstack_grow (&irp, base_name,
- strlen (base_name) - strlen (file_name_suffix (base_name)));
- obstack_grow (&irp, STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX,
- strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX) + 1);
- obstack_1grow (&irp, '\0');
- output_description_file_name = (char *) obstack_base (&irp);
- obstack_finish (&irp);
- }
- /* The following function checks existence at least one arc marked by
- each insn. */
- static void
- check_automata_insn_issues (void)
- {
- automaton_t automaton;
- ainsn_t ainsn, reserv_ainsn;
- for (automaton = description->first_automaton;
- automaton != NULL;
- automaton = automaton->next_automaton)
- {
- for (ainsn = automaton->ainsn_list;
- ainsn != NULL;
- ainsn = ainsn->next_ainsn)
- if (ainsn->first_insn_with_same_reservs && !ainsn->arc_exists_p
- && ainsn != automaton->collapse_ainsn)
- {
- for (reserv_ainsn = ainsn;
- reserv_ainsn != NULL;
- reserv_ainsn = reserv_ainsn->next_same_reservs_insn)
- if (automaton->corresponding_automaton_decl != NULL)
- {
- if (!w_flag)
- error ("Automaton `%s': Insn `%s' will never be issued",
- automaton->corresponding_automaton_decl->name,
- reserv_ainsn->insn_reserv_decl->name);
- else
- warning ("Automaton `%s': Insn `%s' will never be issued",
- automaton->corresponding_automaton_decl->name,
- reserv_ainsn->insn_reserv_decl->name);
- }
- else
- {
- if (!w_flag)
- error ("Insn `%s' will never be issued",
- reserv_ainsn->insn_reserv_decl->name);
- else
- warning ("Insn `%s' will never be issued",
- reserv_ainsn->insn_reserv_decl->name);
- }
- }
- }
- }
- /* The following vla is used for storing pointers to all achieved
- states. */
- static vec<state_t> automaton_states;
- /* This function is called by function pass_states to add an achieved
- STATE. */
- static void
- add_automaton_state (state_t state)
- {
- automaton_states.safe_push (state);
- }
- /* The following function forms list of important automata (whose
- states may be changed after the insn issue) for each insn. */
- static void
- form_important_insn_automata_lists (void)
- {
- automaton_t automaton;
- decl_t decl;
- ainsn_t ainsn;
- arc_t arc;
- int i;
- size_t n;
- automaton_states.create (0);
- /* Mark important ainsns. */
- for (automaton = description->first_automaton;
- automaton != NULL;
- automaton = automaton->next_automaton)
- {
- automaton_states.truncate (0);
- pass_states (automaton, add_automaton_state);
- for (n = 0; n < automaton_states.length (); n++)
- {
- state_t s = automaton_states[n];
- for (arc = first_out_arc (s);
- arc != NULL;
- arc = next_out_arc (arc))
- if (arc->to_state != s)
- {
- gcc_assert (arc->insn->first_insn_with_same_reservs);
- for (ainsn = arc->insn;
- ainsn != NULL;
- ainsn = ainsn->next_same_reservs_insn)
- ainsn->important_p = TRUE;
- }
- }
- }
- automaton_states.release ();
- /* Create automata sets for the insns. */
- for (i = 0; i < description->decls_num; i++)
- {
- decl = description->decls [i];
- if (decl->mode == dm_insn_reserv)
- {
- automata_list_start ();
- for (automaton = description->first_automaton;
- automaton != NULL;
- automaton = automaton->next_automaton)
- for (ainsn = automaton->ainsn_list;
- ainsn != NULL;
- ainsn = ainsn->next_ainsn)
- if (ainsn->important_p
- && ainsn->insn_reserv_decl == DECL_INSN_RESERV (decl))
- {
- automata_list_add (automaton);
- break;
- }
- DECL_INSN_RESERV (decl)->important_automata_list
- = automata_list_finish ();
- }
- }
- }
- /* The following is top level function to generate automat(a,on) for
- fast recognition of pipeline hazards. */
- static void
- expand_automata (void)
- {
- int i;
- description = XCREATENODEVAR (struct description,
- sizeof (struct description)
- /* Two entries for special insns. */
- + sizeof (decl_t) * (decls.length () + 1));
- description->decls_num = decls.length ();
- description->normal_decls_num = description->decls_num;
- description->query_units_num = 0;
- for (i = 0; i < description->decls_num; i++)
- {
- description->decls [i] = decls[i];
- if (description->decls [i]->mode == dm_unit
- && DECL_UNIT (description->decls [i])->query_p)
- DECL_UNIT (description->decls [i])->query_num
- = description->query_units_num++;
- }
- all_time = create_ticker ();
- check_time = create_ticker ();
- if (progress_flag)
- fprintf (stderr, "Check description...");
- check_all_description ();
- if (progress_flag)
- fprintf (stderr, "done\n");
- ticker_off (&check_time);
- generation_time = create_ticker ();
- if (!have_error)
- {
- transform_insn_regexps ();
- check_unit_distributions_to_automata ();
- }
- if (!have_error)
- {
- generate ();
- check_automata_insn_issues ();
- }
- if (!have_error)
- {
- form_important_insn_automata_lists ();
- }
- ticker_off (&generation_time);
- }
- /* The following is top level function to output PHR and to finish
- work with pipeline description translator. */
- static void
- write_automata (void)
- {
- output_time = create_ticker ();
- if (progress_flag)
- fprintf (stderr, "Forming and outputting automata tables...");
- output_tables ();
- if (progress_flag)
- {
- fprintf (stderr, "done\n");
- fprintf (stderr, "Output functions to work with automata...");
- }
- output_chip_definitions ();
- output_max_insn_queue_index_def ();
- output_internal_min_issue_delay_func ();
- output_internal_trans_func ();
- /* Cache of insn dfa codes: */
- fprintf (output_file, "\nstatic int *%s;\n", DFA_INSN_CODES_VARIABLE_NAME);
- fprintf (output_file, "\nstatic int %s;\n\n",
- DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
- output_dfa_insn_code_func ();
- output_trans_func ();
- output_min_issue_delay_func ();
- output_internal_dead_lock_func ();
- output_dead_lock_func ();
- output_size_func ();
- output_internal_reset_func ();
- output_reset_func ();
- output_min_insn_conflict_delay_func ();
- output_default_latencies ();
- output_internal_insn_latency_func ();
- output_insn_latency_func ();
- output_internal_maximal_insn_latency_func ();
- output_maximal_insn_latency_func ();
- output_print_reservation_func ();
- /* Output function get_cpu_unit_code. */
- fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME);
- output_get_cpu_unit_code_func ();
- output_cpu_unit_reservation_p ();
- output_insn_has_dfa_reservation_p ();
- fprintf (output_file, "\n#endif /* #if %s */\n\n",
- CPU_UNITS_QUERY_MACRO_NAME);
- output_dfa_clean_insn_cache_func ();
- output_dfa_start_func ();
- output_dfa_finish_func ();
- if (progress_flag)
- fprintf (stderr, "done\n");
- if (v_flag)
- {
- output_description_file = fopen (output_description_file_name, "w");
- if (output_description_file == NULL)
- {
- perror (output_description_file_name);
- exit (FATAL_EXIT_CODE);
- }
- if (progress_flag)
- fprintf (stderr, "Output automata description...");
- output_description ();
- output_automaton_descriptions ();
- if (progress_flag)
- fprintf (stderr, "done\n");
- output_statistics (output_description_file);
- }
- if (stats_flag)
- output_statistics (stderr);
- ticker_off (&output_time);
- if (time_flag)
- output_time_statistics (stderr);
- finish_states ();
- finish_arcs ();
- finish_automata_lists ();
- if (time_flag)
- {
- fprintf (stderr, "Summary:\n");
- fprintf (stderr, " check time ");
- print_active_time (stderr, check_time);
- fprintf (stderr, ", generation time ");
- print_active_time (stderr, generation_time);
- fprintf (stderr, ", all time ");
- print_active_time (stderr, all_time);
- fprintf (stderr, "\n");
- }
- /* Finish all work. */
- if (output_description_file != NULL)
- {
- fflush (output_description_file);
- if (ferror (stdout) != 0)
- fatal ("Error in writing DFA description file %s: %s",
- output_description_file_name, xstrerror (errno));
- fclose (output_description_file);
- }
- finish_automaton_decl_table ();
- finish_insn_decl_table ();
- finish_decl_table ();
- obstack_free (&irp, NULL);
- if (have_error && output_description_file != NULL)
- remove (output_description_file_name);
- }
- int
- main (int argc, char **argv)
- {
- rtx desc;
- progname = "genautomata";
- if (!init_rtx_reader_args_cb (argc, argv, parse_automata_opt))
- return (FATAL_EXIT_CODE);
- initiate_automaton_gen (argv);
- while (1)
- {
- int lineno;
- int insn_code_number;
- desc = read_md_rtx (&lineno, &insn_code_number);
- if (desc == NULL)
- break;
- switch (GET_CODE (desc))
- {
- case DEFINE_CPU_UNIT:
- gen_cpu_unit (desc);
- break;
- case DEFINE_QUERY_CPU_UNIT:
- gen_query_cpu_unit (desc);
- break;
- case DEFINE_BYPASS:
- gen_bypass (desc);
- break;
- case EXCLUSION_SET:
- gen_excl_set (desc);
- break;
- case PRESENCE_SET:
- gen_presence_set (desc);
- break;
- case FINAL_PRESENCE_SET:
- gen_final_presence_set (desc);
- break;
- case ABSENCE_SET:
- gen_absence_set (desc);
- break;
- case FINAL_ABSENCE_SET:
- gen_final_absence_set (desc);
- break;
- case DEFINE_AUTOMATON:
- gen_automaton (desc);
- break;
- case AUTOMATA_OPTION:
- gen_automata_option (desc);
- break;
- case DEFINE_RESERVATION:
- gen_reserv (desc);
- break;
- case DEFINE_INSN_RESERVATION:
- gen_insn_reserv (desc);
- break;
- default:
- break;
- }
- }
- if (have_error)
- return FATAL_EXIT_CODE;
- if (decls.length () > 0)
- {
- expand_automata ();
- if (!have_error)
- {
- puts ("/* Generated automatically by the program `genautomata'\n"
- " from the machine description file `md'. */\n\n"
- "#include \"config.h\"\n"
- "#include \"system.h\"\n"
- "#include \"coretypes.h\"\n"
- "#include \"tm.h\"\n"
- "#include \"hash-set.h\"\n"
- "#include \"machmode.h\"\n"
- "#include \"vec.h\"\n"
- "#include \"double-int.h\"\n"
- "#include \"input.h\"\n"
- "#include \"alias.h\"\n"
- "#include \"symtab.h\"\n"
- "#include \"wide-int.h\"\n"
- "#include \"inchash.h\"\n"
- "#include \"tree.h\"\n"
- "#include \"varasm.h\"\n"
- "#include \"stor-layout.h\"\n"
- "#include \"calls.h\"\n"
- "#include \"rtl.h\"\n"
- "#include \"tm_p.h\"\n"
- "#include \"insn-config.h\"\n"
- "#include \"recog.h\"\n"
- "#include \"regs.h\"\n"
- "#include \"output.h\"\n"
- "#include \"insn-attr.h\"\n"
- "#include \"diagnostic-core.h\"\n"
- "#include \"flags.h\"\n"
- "#include \"function.h\"\n"
- "#include \"emit-rtl.h\"\n");
- /* FIXME: emit-rtl.h can go away once crtl is in rtl.h. */
- write_automata ();
- }
- }
- else
- {
- puts ("/* Generated automatically by the program `genautomata'\n"
- " from the machine description file `md'. */\n\n"
- "/* There is no automaton, but ISO C forbids empty\n"
- " translation units, so include a header file with some\n"
- " declarations, and its pre-requisite header file. */\n"
- "#include \"config.h\"\n"
- "#include \"system.h\"\n");
- }
- fflush (stdout);
- return (ferror (stdout) != 0 || have_error
- ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
- }
|