cgframe.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622
  1. #include "cgstd.h"
  2. #include "cgframe.h"
  3. #include "cgallocregs.h"
  4. #include "cgutil.h"
  5. #include "cgdebug.h"
  6. #include "cgint64.h"
  7. typedef map<string,CGExp*> IdExpMap;
  8. CGFrame::CGFrame( CGFun *_fun ):fun(_fun),flow(0),int64ret(0){
  9. asm_it=assem.end;
  10. big_endian=!(little_endian=env_config.count("x86")?true:false);
  11. }
  12. CGFrame::~CGFrame(){
  13. deleteFlow();
  14. }
  15. CGMem *CGFrame::int64el( CGMem *i64,int n ){
  16. CGMem *m=CG::mem(CG_INT32,i64->exp,i64->offset+n);
  17. m->flags=i64->flags;
  18. return m;
  19. }
  20. CGMem *CGFrame::int64lo( CGMem *i64 ){
  21. return int64el( i64,big_endian ? 4 : 0 );
  22. }
  23. CGMem *CGFrame::int64hi( CGMem *i64 ){
  24. return int64el( i64,big_endian ? 0 : 4 );
  25. }
  26. //****************** Linearize ********************
  27. struct CGLinearizer : public CGVisitor{
  28. CGFrame *frame;
  29. CGLinearizer( CGFrame *f ):frame(f){}
  30. CGStm *visit( CGStm *stm ){
  31. if( stm->nop() || stm->seq() ) return stm;
  32. frame->fun->stms.push_back(stm);
  33. return stm;
  34. }
  35. CGExp *visit( CGExp *exp ){
  36. if( CGEsq *t=exp->esq() ) return t->rhs;
  37. if( exp->type==CG_INT64 ) return exp;
  38. if( CGCvt *t=exp->cvt() ){
  39. if( t->isint() && t->exp->isfloat() ){
  40. if( env_config.count("x86") ){
  41. exp=CG::cvt(t->type,CG::jsr(CG_INT32,"bbFloatToInt",CG::cvt(CG_FLOAT64,t->exp)));
  42. }
  43. }
  44. }else if( CGUop *t=exp->uop() ){
  45. string iop,fop;
  46. switch( t->op ){
  47. case CG_ABS:iop="bbIntAbs";fop="bbFloatAbs";break;
  48. case CG_SGN:iop="bbIntSgn";fop="bbFloatSgn";break;
  49. }
  50. if( t->isint() && iop.size() ){
  51. exp=CG::cvt(t->type,CG::jsr(CG_INT32,iop,CG::cvt(CG_INT32,t->exp)));
  52. }else if( t->isfloat() && fop.size() ){
  53. exp=CG::cvt(t->type,CG::jsr(CG_FLOAT64,fop,CG::cvt(CG_FLOAT64,t->exp)));
  54. }
  55. }else if( CGBop *t=exp->bop() ){
  56. string iop,fop;
  57. switch( t->op ){
  58. case CG_MOD:fop="bbFloatMod";break;
  59. case CG_MIN:iop="bbIntMin";fop="bbFloatMin";break;
  60. case CG_MAX:iop="bbIntMax";fop="bbFloatMax";break;
  61. }
  62. if( t->isint() && iop.size() ){
  63. exp=CG::cvt(t->type,CG::jsr(CG_INT32,iop,CG::cvt(CG_INT32,t->lhs),CG::cvt(CG_INT32,t->rhs)));
  64. }else if( t->isfloat() && fop.size() ){
  65. exp=CG::cvt(t->type,CG::jsr(CG_FLOAT64,fop,CG::cvt(CG_FLOAT64,t->lhs),CG::cvt(CG_FLOAT64,t->rhs)));
  66. }
  67. }
  68. return exp;
  69. }
  70. };
  71. void CGFrame::linearize(){
  72. CGFun *in=fun;
  73. fun=CG::fun( in->type,in->call_conv,in->sym,in->self );
  74. if( int64ret ) fun->args.push_back( int64ret );
  75. int k;
  76. for( k=0;k<in->args.size();++k ){
  77. CGExp *arg=in->args[k];
  78. if( arg->type!=CG_INT64 ){
  79. fun->args.push_back( arg );
  80. continue;
  81. }
  82. assert( arg->mem() );
  83. fun->args.push_back( int64el(arg->mem(),0) );
  84. fun->args.push_back( int64el(arg->mem(),4) );
  85. }
  86. CGLinearizer vis( this );
  87. for( k=0;k<in->stms.size();++k ) in->stms[k]->visit( vis );
  88. }
  89. //**************** Fix Symbols ********************
  90. struct CGSymFixer : public CGVisitor{
  91. CGFrame *frame;
  92. map<CGExp*,CGExp*> done;
  93. CGSymFixer( CGFrame *f ):frame(f){}
  94. CGExp *visit( CGExp *exp ){
  95. CGSym *t=exp->sym();
  96. if( !t || t->linkage==CG_INTERNAL ) return exp;
  97. map<CGExp*,CGExp*>::iterator it=done.find(t);
  98. if( it!=done.end() ) return it->second;
  99. string id=frame->fixSym( t->value );
  100. if( id==t->value ){
  101. exp=t;
  102. }else if( CGDat *d=exp->dat() ){
  103. CGDat *t;
  104. if( d->linkage==CG_INTERNAL ) t=CG::dat();
  105. else t=CG::dat(id);
  106. t->exps=d->exps;
  107. exp=t;
  108. }else{
  109. exp=CG::sym(id,t->linkage);
  110. }
  111. done.insert( make_pair(t,exp) );
  112. return exp;
  113. }
  114. };
  115. void CGFrame::fixSymbols(){
  116. CGSymFixer vis( this );
  117. fun=CG::visitFun( fun,vis );
  118. }
  119. //************* Find Escaping Tmps ****************
  120. struct CGEscFinder : public CGVisitor{
  121. CGFrame *frame;
  122. CGEscFinder( CGFrame *f ):frame(f){}
  123. CGExp *visit( CGExp *exp ){
  124. if( CGLea *p=exp->lea() ){
  125. CGTmp *t=p->exp->tmp();
  126. if( !t ) return exp;
  127. if( frame->tmps.find(t->ident)==frame->tmps.end() ){
  128. frame->tmps.insert( make_pair(t->ident,frame->allocLocal(t->type)) );
  129. }
  130. }else if( CGTmp *t=exp->tmp() ){
  131. //always spill bytes, shorts, longs...
  132. if( t->type==CG_INT8 || t->type==CG_INT16 || t->type==CG_INT64 ){
  133. if( frame->tmps.find(t->ident)==frame->tmps.end() ){
  134. frame->tmps.insert( make_pair(t->ident,frame->allocLocal(t->type)) );
  135. }
  136. }
  137. }
  138. return exp;
  139. }
  140. };
  141. void CGFrame::findEscapes(){
  142. if( fun->type==CG_INT64 ) int64ret=reg(CG_PTR);
  143. CGEscFinder vis( this );
  144. fun=CG::visitFun( fun,vis );
  145. }
  146. //**************** Rename tmps ********************
  147. struct CGTmpRenamer : public CGVisitor{
  148. CGFrame *frame;
  149. CGTmpRenamer( CGFrame *f ):frame(f){}
  150. CGExp *visit( CGExp *exp ){
  151. if( CGTmp *t=exp->tmp() ){
  152. return tmpReg( t );
  153. }
  154. return exp;
  155. }
  156. CGExp *tmpReg( CGTmp *t ){
  157. IdExpMap::iterator it=frame->tmps.find(t->ident);
  158. if( it==frame->tmps.end() ){
  159. CGReg *owner=0;
  160. if( t->owner ) owner=tmpReg( t->owner )->reg();
  161. it=frame->tmps.insert( make_pair(t->ident,frame->reg(t->type,owner)) ).first;
  162. }
  163. return it->second;
  164. }
  165. };
  166. void CGFrame::renameTmps(){
  167. CGTmpRenamer vis( this );
  168. fun=CG::visitFun( fun,vis );
  169. }
  170. //**************** PreOptimize ********************
  171. static int shifter( int n ){
  172. int k;
  173. for( k=0;k<32;++k ) if( n==(1<<k) ) return k;
  174. return -1;
  175. }
  176. struct CGPreOpter : public CGVisitor{
  177. CGFrame *frame;
  178. CGPreOpter( CGFrame *f ):frame(f){}
  179. CGStm *visit( CGStm *stm ){
  180. if( CGBcc *t=stm->bcc() ){
  181. if( CGScc *p=t->lhs->scc() ){
  182. if( CGLit *q=t->rhs->lit() ){
  183. if( !q->int_value ){
  184. if( t->cc==CG_NE ){
  185. //bcc NE,scc,0,sym
  186. return CG::bcc( p->cc,p->lhs,p->rhs,t->sym );
  187. }else if( t->cc==CG_EQ ){
  188. //bcc EQ,scc,0,sym
  189. return CG::bcc( CG::swapcc(p->cc),p->lhs,p->rhs,t->sym );
  190. }
  191. }
  192. }
  193. }
  194. return stm;
  195. }
  196. return stm;
  197. }
  198. CGExp *visit( CGExp *exp ){
  199. if( CGCvt *t=exp->cvt() ){
  200. //remove cvt between same types
  201. CGExp *e=t->exp;
  202. if( t->type==e->type ) exp=e;
  203. return exp;
  204. }
  205. if( CGMem *t=exp->mem() ){
  206. //remove mem(lea(mem),0)...
  207. CGExp *e=t->exp;
  208. CGLea *p=e->lea();
  209. assert( !p || p->exp->mem() );
  210. if( p && !t->offset && t->type==p->exp->mem()->type ) exp=p->exp;
  211. return exp;
  212. }
  213. if( CGUop *t=exp->uop() ){
  214. //const precalc unary op
  215. if( t->isfloat() ) return exp;
  216. if( CGLit *p=t->exp->lit() ){
  217. int n=p->int_value;
  218. switch( t->op ){
  219. case CG_NOT:exp=CG::lit(~n);break;
  220. case CG_NEG:exp=CG::lit(-n);break;
  221. }
  222. }
  223. return exp;
  224. }
  225. if( CGBop *t=exp->bop() ){
  226. if( t->isfloat() ) return exp;
  227. //const precalc binary op
  228. CGLit *p=t->lhs->lit(),*q=t->rhs->lit();
  229. if( p && !q && t->commutes() ){
  230. //put const on RHS in commuting const,non-const BOPs.
  231. std::swap(p,q);
  232. exp=t=CG::bop(t->op,t->rhs,q);
  233. }
  234. if( p && q ){
  235. //const,const
  236. int x=p->int_value,y=q->int_value;
  237. switch( t->op ){
  238. case CG_ADD:exp=CG::lit(x+y);break;
  239. case CG_SUB:exp=CG::lit(x-y);break;
  240. case CG_MUL:exp=CG::lit(x*y);break;
  241. case CG_DIV:assert(y);exp=CG::lit(x/y);break;
  242. case CG_MOD:assert(y);exp=CG::lit(x%y);break;
  243. case CG_AND:exp=CG::lit(x&y);break;
  244. case CG_ORL:exp=CG::lit(x|y);break;
  245. case CG_XOR:exp=CG::lit(x^y);break;
  246. case CG_SHL:exp=CG::lit(x<<y);break;
  247. case CG_SHR:exp=CG::lit((int)((unsigned)x>>(unsigned)y));break;
  248. case CG_SAR:exp=CG::lit(x>>y);break;
  249. }
  250. }else if( p ){
  251. //const,non-const (ie: non-commuting)
  252. switch( p->int_value ){
  253. case 0:
  254. switch( t->op ){
  255. case CG_DIV:case CG_MOD:
  256. case CG_SHL:case CG_SHR:case CG_SAR:
  257. exp=CG::lit0;break;
  258. }
  259. break;
  260. }
  261. }else if( q ){
  262. //non-const,const
  263. switch( q->int_value ){
  264. case 0:
  265. switch( t->op ){
  266. case CG_ADD:case CG_SUB:
  267. case CG_ORL:case CG_XOR:
  268. case CG_SHL:case CG_SHR:case CG_SAR:
  269. exp=t->lhs;break;
  270. case CG_MUL:case CG_AND:
  271. exp=CG::lit0;break;
  272. }
  273. break;
  274. case 1:
  275. switch( t->op ){
  276. case CG_MUL:case CG_DIV:
  277. exp=t->lhs;break;
  278. }
  279. break;
  280. }
  281. }
  282. return exp;
  283. }
  284. return exp;
  285. }
  286. };
  287. void CGFrame::preOptimize(){
  288. CGPreOpter vis( this );
  289. fun=CG::visitFun( fun,vis );
  290. }
  291. //****************** GenAssem *********************
  292. void CGFrame::genAssem(){
  293. assem.clear();
  294. asm_it=assem.end;
  295. genFun();
  296. }
  297. //**************** Create flow ********************
  298. void CGFrame::createFlow(){
  299. deleteFlow();
  300. flow=new CGFlow(assem);
  301. flow->liveness();
  302. }
  303. //**************** Create a reg *******************
  304. CGReg *CGFrame::reg( int type,CGReg *owner,int color ){
  305. assert( type!=CG_INT64 );
  306. CGReg *r=new CGReg;
  307. r->type=type;
  308. r->id=regs.size();
  309. r->owner=owner;
  310. r->color=color;
  311. regs.push_back(r);
  312. return r;
  313. }
  314. //*************** Generate assem ******************
  315. static CGIntSet *genUse;
  316. CGAsm *CGFrame::gen( CGStm *stm,const char *fmt,... ){
  317. CGAsm *as;
  318. if( fmt ){
  319. char buf[256];
  320. buf[255]=0;
  321. va_list args;
  322. va_start( args,fmt );
  323. vsprintf( buf,fmt,args );
  324. assert( !buf[255] );
  325. as=new CGAsm( stm,buf );
  326. }else{
  327. as=new CGAsm( stm,"" );
  328. }
  329. if( genUse ) as->use.insert( *genUse );
  330. asm_it=assem.insert(as,asm_it)->succ;
  331. return as;
  332. }
  333. //*************** Elim dead code ******************
  334. void CGFrame::optDeadCode(){
  335. for(;;){
  336. bool changed=false;
  337. CGBlockIter blk_it;
  338. for( blk_it=flow->blocks.begin();blk_it!=flow->blocks.end();++blk_it ){
  339. CGBlock *blk=*blk_it;
  340. CGAsm *as=blk->end;
  341. CGIntSet live=blk->live_out;
  342. while( as!=blk->begin ){
  343. as=as->pred;
  344. bool elim=false;
  345. CGMov *t=as->stm->mov();
  346. if( t ){
  347. CGReg *lhs=t->lhs->reg();
  348. CGReg *rhs=t->rhs->reg();
  349. if( lhs && rhs && lhs==rhs ){
  350. elim=true;
  351. }else if( lhs && !t->rhs->sideEffects() && !live.count(lhs->id) ){
  352. elim=true;
  353. }
  354. }
  355. if( elim ){
  356. as=assem.erase(as);
  357. changed=true;
  358. }else{
  359. live.erase( as->def );
  360. live.insert( as->use );
  361. }
  362. }
  363. }
  364. if( !changed ) break;
  365. flow->liveness();
  366. }
  367. }
  368. //*************** Optimize loads ******************
  369. /*
  370. This is dodgy and probably not worth it...
  371. CGMov to reg should eliminate any loads which depend on reg - this doesn't.
  372. */
  373. void CGFrame::optDupLoads(){
  374. /*
  375. vector<CGMov*> loads;
  376. bool changed=false;
  377. for( asm_it=assem.begin;asm_it!=assem.end;asm_it=asm_it->succ ){
  378. CGMov *t=asm_it->stm->mov();
  379. if( !t || t->lhs->mem() || t->rhs->sideEffects() ){
  380. loads.clear();
  381. continue;
  382. }
  383. if( !t->rhs->mem() ){
  384. continue;
  385. }
  386. int k;
  387. for( k=0;k<loads.size();++k ){
  388. if( !t->rhs->equals(loads[k]->rhs) ) continue;
  389. //found a load!
  390. cout<<"Eliminating load!"<<endl;
  391. asm_it=assem.erase(asm_it);
  392. genStm( CG::mov(t->lhs,loads[k]->lhs) );
  393. asm_it=asm_it->pred;
  394. changed=true;
  395. break;
  396. }
  397. if( k==loads.size() ) loads.push_back( t );
  398. }
  399. if( changed ) flow->liveness();
  400. */
  401. }
  402. //*************** Allocate regs *******************
  403. struct Spiller : public CGVisitor{
  404. CGReg *reg;
  405. CGExp *exp;
  406. CGIntSet owners;
  407. Spiller( CGReg *r,CGExp *e ):reg(r),exp(e){}
  408. CGExp *visit( CGExp *e ){
  409. CGReg *t=e->reg();
  410. if( t!=reg ) return e;
  411. while( t=t->owner ){
  412. owners.insert( t->id );
  413. }
  414. return exp;
  415. /*
  416. if( t==reg ) return exp;
  417. CGReg *r=reg;
  418. while( r=r->owner ){
  419. if( r==t ) owned.insert( r->id );
  420. }
  421. return e;
  422. */
  423. }
  424. };
  425. void CGFrame::spillReg( CGReg *reg,CGExp *exp ){
  426. if( !exp ) exp=allocSpill(reg);
  427. int i;
  428. for( i=0;i<regs.size();++i ){
  429. if( regs[i]->owner==reg ) regs[i]->owner=0;
  430. }
  431. Spiller spiller( reg,exp );
  432. asm_it=assem.begin;
  433. while( asm_it!=assem.end ){
  434. spiller.owners.clear();
  435. CGStm *stm=asm_it->stm->visit( spiller );
  436. if( stm==asm_it->stm ){
  437. asm_it->use.erase( reg->id );
  438. asm_it=asm_it->succ;
  439. continue;
  440. }
  441. asm_it=assem.erase( asm_it );
  442. genUse=&spiller.owners;
  443. genStm( stm );
  444. genUse=0;
  445. /*
  446. asm_it=assem.erase( asm_it );
  447. genStm( stm );
  448. asm_it->pred->use.insert( spiller.owned );
  449. */
  450. }
  451. }
  452. void CGFrame::allocRegs(){
  453. cgAllocRegs( this );
  454. CGAsm *as=assem.begin;
  455. while( as!=assem.end ){
  456. if( CGMov *t=as->stm->mov() ){
  457. CGReg *lhs=t->lhs->reg(),*rhs=t->rhs->reg();
  458. if( lhs && rhs && lhs->color==rhs->color ){
  459. as=assem.erase(as);
  460. continue;
  461. }
  462. }
  463. char buf[256],*q=buf;
  464. const char *p=as->assem;
  465. while( const char *t=strchr(p,'\'') ){
  466. memcpy(q,p,t-p);
  467. q+=t-p;
  468. int n=0,c;
  469. while( isdigit(c=*++t) ) n=n*10+(c-'0');
  470. CGReg *r=regs[n];
  471. int bank=reg_banks[r->type];
  472. const char *name=reg_names[bank][r->color];
  473. strcpy( q,name );
  474. q+=strlen(q);
  475. p=t;
  476. }
  477. if( q!=buf ){
  478. strcpy(q,p);
  479. as->assem=strdup(buf);
  480. }
  481. as=as->succ;
  482. }
  483. }
  484. void CGFrame::deleteFlow(){
  485. if( flow ){
  486. delete flow;
  487. flow=0;
  488. }
  489. }
  490. void CGFrame::peepOpt(){
  491. CGAsm *as;
  492. for( as=assem.begin;as!=assem.end;as=as->succ ){
  493. if( CGBra *p=as->stm->bra() ){
  494. if( CGLab *q=as->succ->stm->lab() ){
  495. if( p->sym->value==q->sym->value ){
  496. cout<<"Erasing:"<<as->assem<<endl;
  497. as=assem.erase( as );
  498. continue;
  499. }
  500. }
  501. }
  502. }
  503. }