/* $VER: vbcc (regs.c) V0.8 *//* Registerzuteilung */ #include "opt.h" static char FILE_[]=__FILE__; #ifndef NO_OPTIMIZER int (*savings)[MAXR+1],regu[MAXR+1];int *rvlist; static int const_vars; struct regp {int treg;struct Var *tvar,*tmp;};void do_load_parms(struct regp [],struct flowgraph *);void load_one_parm(int,int,struct Var *,struct Var *,struct flowgraph *); static void insert_cobj(struct obj *o,struct obj *co); #ifndef HAVE_TARGET_RALLOCint reg_prio[MAXR+1];#define cost_move_reg(x,y) 1#define cost_load_reg(x,y) 2#define cost_save_reg(x,y) 2#define cost_pushpop_reg(x) 4 int cost_savings(struct IC *p,int r,struct obj *o){ int c=p->code; if(o->flags&VKONST) return 0; if(o->flags&DREFOBJ){ int t; if(o==&p->q1){ t=q1typ(p); }else if(o==&p->q2){ t=q2typ(p); }else{ t=ztyp(p); } if(regok(r,o->v->vtyp->flags,t)) return 4; } if(c==SETRETURN&&r==p->z.reg&&!(o->flags&DREFOBJ)) return 3; if(c==GETRETURN&&r==p->q1.reg&&!(o->flags&DREFOBJ)) return 3; return 2;}#endif int cmp_savings(const void *v1,const void *v2)/* Vergleichsfkt, um rvlist nach savings zu sortieren */{ return savings[*(int *)v2][0]-savings[*(int *)v1][0];}int entry_load(struct flowgraph *fg,int i)/* Testet, ob die Variable in Register i am Anfang von Block fg geladen *//* werden muss, d.h. ein Vorgaenger sie nicht im selben Register hat. */{ struct flowlist *lp; lp=fg->in; while(lp){ if(lp->graph&&lp->graph->regv[i]!=fg->regv[i]&&(fg->regv[i]->index>=vcount-rcount||BTST(lp->graph->av_out,fg->regv[i]->index))) return 1; lp=lp->next; } return 0;} /* checks if variable i can be held in a register in loop start-end *//* currently we check whether an IC uses/modifies the variable and *//* has a corresponding drefobj which might alias the variable */int check_cacheable(int i,struct flowgraph *start,struct flowgraph *end){ int j,k; struct IC *p;struct Var *v; struct flowgraph *g; /* constants are always cacheable */ if(vilist[i]->identifier[0]==' ') return 1; if(i<vcount-rcount){ /* simple local variables are also easy */ v=vilist[i]; if(v->storage_class!=STATIC&&v->storage_class!=EXTERN&&!(v->flags&USEDASADR)) return 1; } if(disable&16384) return 0; for(g=start;g;g=g->normalout){ for(p=g->start;p;p=p->next){ for(j=0;j<p->use_cnt;j++){ k=p->use_list[j].v->index; if(p->use_list[j].flags&DREFOBJ) k+=vcount-rcount; if(k==i&&(p->code==CALL||(p->q1.flags&DREFOBJ)||(p->q2.flags&DREFOBJ))) return 0; } for(j=0;j<p->change_cnt;j++){ k=p->change_list[j].v->index; if(p->change_list[j].flags&DREFOBJ) k+=vcount-rcount; if(k==i&&(p->code==CALL||(p->z.flags&DREFOBJ))) return 0; } if(p==g->end) break; } if(g==end) break; } /*printf("assigned static %s to reg\n",vilist[i]->identifier);*/ return 1;}int exit_save(struct flowgraph *fg,int i)/* Testet, ob die Variable in Register i am Ende von Block fg gespeichert *//* werden muss, d.h. der Vorgaenger eines Nachfolgers nicht dieselbe *//* Variable im selben Register hat. */{ struct flowlist *lp; /* Konstanten muessen nie gespeichert werden */ if(fg->regv[i]->index>=vcount-rcount) return 0; if(!fg->normalout){ /* letzter Block, statische Variablen und drefobjs aktiv */ int sc=fg->regv[i]->storage_class; return sc==STATIC||sc==EXTERN; } if((fg->normalout&&(!fg->end||fg->end->code!=BRA))&&BTST(fg->normalout->av_in,fg->regv[i]->index)){ if(fg->normalout->regv[i]!=fg->regv[i]) return 1; lp=fg->normalout->in; while(lp){ if(lp->graph&&lp->graph->regv[i]!=fg->regv[i]) return 1; lp=lp->next; } } if(fg->branchout&&BTST(fg->branchout->av_in,fg->regv[i]->index)){ if(fg->branchout->regv[i]!=fg->regv[i]) return 1; lp=fg->branchout->in; while(lp){ if(lp->graph&&lp->graph->regv[i]!=fg->regv[i]) return 1; lp=lp->next; } } return 0;}void load_reg_parms(struct flowgraph *fg)/* Laedt Registerparameter, falls noetig. */{ int i,j; struct Var *v; struct regp regp[MAXR+1]={0};/* for(i=1;i<=MAXR;i++){ regp[i].treg=0;regp[i].tvar=0;} */ for(i=0;i<vcount-rcount;i++){ v=vilist[i]; if((v->flags®PARM)&&(fg->regv[abs(v->reg)]!=v||(v->flags&CONVPARAMETER))&&(BTST(fg->av_in,i)||(v->flags&USEDASADR))){ regp[abs(v->reg)].tvar=v; for(j=1;j<=MAXR;j++) if(fg->regv[j]==v) regp[abs(v->reg)].treg=j; } } do_load_parms(regp,fg);} void insert_regs(struct flowgraph *fg1)/* Fuegt Registervariablen in die ICs ein. */{ int i;struct IC *p,*lic=0,*new;struct flowgraph *lfg=0,*fg; if(DEBUG&9216) printf("inserting register variables\n"); fg=fg1; while(fg){ if(DEBUG&8192) printf("block %d:\n",fg->index); p=fg->start; while(p){ for(i=1;i<=MAXR;i++){ if(!fg->regv[i]) continue; if(p->code==ALLOCREG&&p->q1.reg==i) ierror(0); if((p->q1.flags&(VAR|REG|DONTREGISTERIZE))==VAR&&p->q1.v==fg->regv[i]){ if(p->q1.v->index>=vcount-rcount) p->q1.flags&=~(KONST|VAR|VARADR); p->q1.flags|=REG; p->q1.reg=i; } if((p->q2.flags&(VAR|REG|DONTREGISTERIZE))==VAR&&p->q2.v==fg->regv[i]){ if(p->q2.v->index>=vcount-rcount) p->q2.flags&=~(KONST|VAR|VARADR); p->q2.flags|=REG; p->q2.reg=i; } if((p->z.flags&(VAR|REG|DONTREGISTERIZE))==VAR&&p->z.v==fg->regv[i]){ if(p->z.v->index>=vcount-rcount) p->z.flags&=~(KONST|VAR|VARADR); p->z.flags|=REG; p->z.reg=i; } } /* evtl. const-Variablen ruecksubstituieren */ if((p->q1.flags&VAR)&&p->q1.v->index>=vcount-rcount){ insert_cobj(&p->q1,&p->q1.v->cobj); } if((p->q2.flags&VAR)&&p->q2.v->index>=vcount-rcount){ insert_cobj(&p->q2,&p->q2.v->cobj); } if((p->z.flags&VAR)&&p->z.v->index>=vcount-rcount){ insert_cobj(&p->z,&p->z.v->cobj); } if(DEBUG&8192) pric2(stdout,p); if(p==fg->end) break; p=p->next; } if(fg->start&&fg->start->code==LABEL) lic=fg->start; for(i=1;i<=MAXR;i++){ if(fg->regv[i]){ if(DEBUG&8192){ printf("(%s),%ld(%p) assigned to %s\n",fg->regv[i]->identifier,zm2l(fg->regv[i]->offset),(void *)fg->regv[i],regnames[i]); if(fg->regv[i]->index>=vcount-rcount||BTST(fg->av_in,fg->regv[i]->index)) printf("active at the start of block\n"); if(fg->regv[i]->index<vcount-rcount&&BTST(fg->av_out,fg->regv[i]->index)) printf("active at the end of block\n"); } if(fg->regv[i]->index<vcount-rcount&&BTST(fg->av_out,fg->regv[i]->index)){ /* Variable beim Austritt aktiv? */ if(exit_save(fg,i)){ struct IC *tp; if(DEBUG&8192) printf("\thave to save it at end of block\n"); new=new_IC(); new->line=0; new->file=0; new->code=ASSIGN; new->typf=fg->regv[i]->vtyp->flags; /* vla */ if(ISARRAY(new->typf)) new->typf=POINTER_TYPE(fg->regv[i]->vtyp->next); /* cc */ if(new->typf==0) ierror(0); new->q1.flags=VAR|REG; new->q1.val.vmax=l2zm(0L); new->q1.v=fg->regv[i]; new->q1.reg=i; new->q2.flags=0; new->q2.val.vmax=szof(fg->regv[i]->vtyp); new->z.flags=VAR|DONTREGISTERIZE; new->z.val.vmax=l2zm(0L); new->z.v=fg->regv[i]; new->q1.am=new->q2.am=new->z.am=0; new->use_cnt=new->change_cnt=0; new->use_list=new->change_list=0; /* Vor FREEREGs und evtl. Branch+COMPARE/TEST setzen */ if(fg->end){ tp=fg->end; while(tp!=fg->start&&(tp->code==FREEREG||tp->code==SETRETURN)) tp=tp->prev; if(tp&&tp->code>=BEQ&&tp->code<=BRA){ if(tp->code<BRA){ int c; do{ tp=tp->prev; c=tp->code; if(c!=FREEREG&&c!=COMPARE&&c!=TEST) ierror(0); }while(c!=COMPARE&&c!=TEST); } tp=tp->prev; } }else tp=lic; insert_IC_fg(fg,tp,new); } } if(fg->regv[i]->index>=vcount-rcount||BTST(fg->av_in,fg->regv[i]->index)){ if((fg==fg1||entry_load(fg,i))&&(fg!=fg1||!(fg->regv[i]->flags®PARM))){ if(DEBUG&8192) printf("\thave to load it at start of block\n"); new=new_IC(); new->line=0; new->file=0; new->code=ASSIGN; new->typf=fg->regv[i]->vtyp->flags; /* vla */ if(ISARRAY(new->typf)) new->typf=POINTER_TYPE(fg->regv[i]->vtyp->next); /* cc */ if(new->typf==0) ierror(0); if(fg->regv[i]->index>=vcount-rcount){ insert_cobj(&new->q1,&fg->regv[i]->cobj); }else{ new->q1.flags=VAR|DONTREGISTERIZE; new->q1.val.vmax=l2zm(0L); new->q1.v=fg->regv[i]; } new->q2.flags=0; new->q2.val.vmax=szof(fg->regv[i]->vtyp); if(fg->regv[i]->index>=vcount-rcount) new->z.flags=REG; else new->z.flags=VAR|REG; new->z.val.vmax=l2zm(0L); new->z.v=fg->regv[i]; new->z.reg=i; new->q1.am=new->q2.am=new->z.am=0; new->use_cnt=new->change_cnt=0; new->use_list=new->change_list=0; insert_IC_fg(fg,lic,new); } } if(!lfg||!lfg->regv[i]) insert_allocreg(fg,lic,ALLOCREG,i); if(!fg->normalout||!fg->normalout->regv[i]) insert_allocreg(fg,fg->end?fg->end:lic,FREEREG,i); } } if(fg->end) lic=fg->end; lfg=fg; fg=fg->normalout; } load_reg_parms(fg1);} void do_loop_regs(struct flowgraph *start,struct flowgraph *end,int intask)/* Macht die Variablenzuweisung in Schleife start-end. *//* Wenn end==0 Registerzuweisung fuer die ganze Funktion, ansonsten *//* fuer die Schleife, die zum Header start gehoert. */{ struct flowgraph *g,*lend; int i,r,iterations; struct Var *lregs[MAXR+1]={0}; unsigned char regu[MAXR+1]={0}; bvtype *isused=mymalloc(vsize); /* Berechnen, wieviel ungefaehr eingespart wird, wenn eine Variable */ /* fuer diese Schleife in einem best. Register gehalten wird. */ /* Die savings in einer Schleife werden multipliziert, um das */ /* Laden/Speichern ausserhalb der Schleife geringer zu wichten. */ /* if(end&&(!g->normalout||!g->normalout->loopend||g->normalout->loopend->normalout->index!=-2)) ierror(0);*/ /* alle auf 0 */ for(i=0;i<vcount-rcount+const_vars;i++){ if(i<vcount-rcount&&(vilist[i]->vtyp->flags&VOLATILE)){ for(r=1;r<=MAXR;r++){ savings[i][r]=INT_MIN; } }else{ for(r=1;r<=MAXR;r++){ savings[i][r]=0; } } } if(end){ struct Var *v; /* estimated number of iterations, avoid too big values */ if(optsize) iterations=1; else iterations=4; /* Evtl. Kosten fuers Laden/Speichern beim Ein-/Austritt in die */ /* Schleife. */ end=start->normalout->loopend; g=end->normalout; if(DEBUG&9216) printf("assigning regs to blocks %d to %d\n",start->normalout->index,end->index); /* Werte modifizieren, falls Variable am Anfang/Ende der Schleife */ /* geladen/gespeichert werden muss. */ /* FIXME: Evtl. noetige stores/loads in anderen Bloecken! */ for(i=0;i<vcount-rcount+const_vars;i++){ v=vilist[i]; if(i>=vcount-rcount||BTST(start->av_in,i)){ for(r=1;r<=MAXR;r++) if(start->regv[r]!=v&&savings[i][r]!=INT_MIN) savings[i][r]-=cost_load_reg(r,v); } if(i<vcount-rcount&&BTST(g->av_out,i)){ for(r=1;r<=MAXR;r++) if(g->regv[r]!=v&&savings[i][r]!=INT_MIN) savings[i][r]-=cost_save_reg(r,v); } } /* Werte modifizieren, falls eine andere Variable gespeichert oder */ /* geladen werden muss. Hmm..stimmt das so? */ for(r=1;r<=MAXR;r++){ v=start->regv[r]; if(v&&v->index<vcount-rcount&&BTST(start->av_in,v->index)){ for(i=0;i<vcount-rcount;i++) if(v->index!=i&&savings[i][r]!=INT_MIN) savings[i][r]-=cost_load_reg(r,vilist[i]); } if(v&&v->index<vcount-rcount&&BTST(g->av_out,v->index)){ for(i=0;i<vcount-rcount;i++) if(v->index!=i&&savings[i][r]!=INT_MIN) savings[i][r]-=cost_save_reg(r,vilist[i]); } } g=start->normalout; }else{ iterations=1; /* Bei Registervergabe fuer die ganze Funktion muessen alle beim */ /* Eintritt der Funktion aktiven Variablen geladen werden. */ /* statics have to be saved at the end */ if(DEBUG&9216) printf("assigning regs to whole function\n"); for(i=0;i<vcount-rcount+const_vars;i++){ if(i<vcount-rcount&&(vilist[i]->storage_class==STATIC||vilist[i]->storage_class==EXTERN)){ for(r=1;r<=MAXR;r++) if(savings[i][r]!=INT_MIN) savings[i][r]-=cost_save_reg(r,vilist[i]); } if(i>=vcount-rcount||BTST(start->av_in,i)){ int pr=abs(vilist[i]->reg); for(r=1;r<=MAXR;r++){ if(savings[i][r]!=INT_MIN){ if(pr==0){ savings[i][r]-=cost_load_reg(r,vilist[i]); }else if(!regsa[r]){ if(r==pr) savings[i][r]+=cost_save_reg(r,vilist[i]); else savings[i][r]+=(cost_save_reg(r,vilist[i])-cost_move_reg(pr,r)); } } } } } /* Nonscratchregister muessen geladen/gesichert werden. */ /*FIXME: einige unschoene Effekte(?) */ if(!intask){ for(r=1;r<=MAXR;r++){ if(!regscratch[r]&&!regsa[r]){ for(i=0;i<vcount-rcount+const_vars;i++) if(savings[i][r]!=INT_MIN) savings[i][r]-=cost_pushpop_reg(r); } } } g=start; } if(DEBUG&9216) printf("calculating approximate savings\n"); lend=0; for(;g;g=g->normalout){ struct IC *p;struct Var *v; int t,vt; if(!end&&!lend){ lend=g->loopend; if(lend&&iterations==1&&!optsize) iterations=4; } /* Wenn das Register in dem Block benutzt wird, muss man es retten */ for(r=1;r<=MAXR;r++){ if(BTST(g->regused,r)||(reg_pair(r,&rp)&&(BTST(g->regused,rp.r1)||BTST(g->regused,rp.r2)))){ int vi; if(g->regv[r]) vi=g->regv[r]->index; else vi=-1; for(i=0;i<vcount-rcount+const_vars;i++){ if(i>=vcount-rcount||BTST(g->av_out,i)||BTST(g->av_gen,i)) if(vi!=i&&savings[i][r]!=INT_MIN) savings[i][r]-=iterations*cost_load_reg(r,vilist[i])+cost_save_reg(r,vilist[i]); } } } memcpy(isused,g->av_out,vsize); p=g->end; while(p){ if((p->q1.flags&(VAR|VARADR|REG))==VAR){ v=p->q1.v;vt=v->vtyp->flags; /* vla */ if(ISARRAY(vt)&&is_vlength(v->vtyp)) vt=POINTER_TYPE(v->vtyp->next); if((optflags&1024)||((v->storage_class==AUTO||v->storage_class==REGISTER)&&!(v->flags&USEDASADR))){ i=v->index; if(p->code==ADDRESS||((p->code==ASSIGN||p->code==PUSH)&&(q1typ(p)&NQ)==(CHAR)&&!zmeqto(p->q2.val.vmax,l2zm(1L)))){ for(r=1;r<=MAXR;r++) savings[i][r]=INT_MIN; }else{ for(r=1;r<=MAXR;r++){ if(!regsa[r]&&!BTST(g->regused,r)&&savings[i][r]!=INT_MIN&®ok(r,vt,-1)&&(!reg_pair(r,&rp)||(!regsa[rp.r1]&&!regsa[rp.r2]&&!BTST(g->regused,rp.r1)&&!BTST(g->regused,rp.r2)))){ int s=cost_savings(p,r,&p->q1); if(s==INT_MIN) savings[i][r]=INT_MIN; else savings[i][r]+=iterations*s; } } } } } if((p->q2.flags&(VAR|VARADR|REG))==VAR){ v=p->q2.v;vt=v->vtyp->flags; /* vla */ if(ISARRAY(vt)&&is_vlength(v->vtyp)) vt=POINTER_TYPE(v->vtyp->next); if((optflags&1024)||((v->storage_class==AUTO||v->storage_class==REGISTER)&&!(v->flags&USEDASADR))){ i=v->index; for(r=1;r<=MAXR;r++){ if(!regsa[r]&&!BTST(g->regused,r)&&savings[i][r]!=INT_MIN&®ok(r,vt,-1)&&(!reg_pair(r,&rp)||(!regsa[rp.r1]&&!regsa[rp.r2]&&!BTST(g->regused,rp.r1)&&!BTST(g->regused,rp.r2)))){ int s=cost_savings(p,r,&p->q2); if(s==INT_MIN) savings[i][r]=INT_MIN; else savings[i][r]+=iterations*s; } } } } if((p->z.flags&(VAR|VARADR|REG))==VAR){ v=p->z.v;vt=v->vtyp->flags; if(ISARRAY(vt)&&is_vlength(v->vtyp)) vt=POINTER_TYPE(v->vtyp->next); if((optflags&1024)||((v->storage_class==AUTO||v->storage_class==REGISTER)&&!(v->flags&USEDASADR))){ i=v->index; if(p->code==ASSIGN&&(ztyp(p)&NQ)==(CHAR)&&!zmeqto(p->q2.val.vmax,l2zm(1L))){ for(r=1;r<=MAXR;r++) savings[i][r]=INT_MIN; } for(r=1;r<=MAXR;r++){ if(!regsa[r]&&!BTST(g->regused,r)&&savings[i][r]!=INT_MIN&®ok(r,vt,-1)&&(!reg_pair(r,&rp)||(!regsa[rp.r1]&&!regsa[rp.r2]&&!BTST(g->regused,rp.r1)&&!BTST(g->regused,rp.r2)))){ int s=cost_savings(p,r,&p->z); if(s==INT_MIN) savings[i][r]=INT_MIN; else savings[i][r]+=iterations*s;Lines 1–500 of 1865. Load more
/* $VER: vbcc (regs.c) V0.8 */ /* Registerzuteilung */ #include "opt.h" static char FILE_[]=__FILE__; #ifndef NO_OPTIMIZER int (*savings)[MAXR+1],regu[MAXR+1]; int *rvlist; static int const_vars; struct regp {int treg;struct Var *tvar,*tmp;}; void do_load_parms(struct regp [],struct flowgraph *); void load_one_parm(int,int,struct Var *,struct Var *,struct flowgraph *); static void insert_cobj(struct obj *o,struct obj *co); #ifndef HAVE_TARGET_RALLOC int reg_prio[MAXR+1]; #define cost_move_reg(x,y) 1 #define cost_load_reg(x,y) 2 #define cost_save_reg(x,y) 2 #define cost_pushpop_reg(x) 4 int cost_savings(struct IC *p,int r,struct obj *o) { int c=p->code; if(o->flags&VKONST) return 0; if(o->flags&DREFOBJ){ int t; if(o==&p->q1){ t=q1typ(p); }else if(o==&p->q2){ t=q2typ(p); }else{ t=ztyp(p); } if(regok(r,o->v->vtyp->flags,t)) return 4; } if(c==SETRETURN&&r==p->z.reg&&!(o->flags&DREFOBJ)) return 3; if(c==GETRETURN&&r==p->q1.reg&&!(o->flags&DREFOBJ)) return 3; return 2; } #endif int cmp_savings(const void *v1,const void *v2) /* Vergleichsfkt, um rvlist nach savings zu sortieren */ { return savings[*(int *)v2][0]-savings[*(int *)v1][0]; } int entry_load(struct flowgraph *fg,int i) /* Testet, ob die Variable in Register i am Anfang von Block fg geladen */ /* werden muss, d.h. ein Vorgaenger sie nicht im selben Register hat. */ { struct flowlist *lp; lp=fg->in; while(lp){ if(lp->graph&&lp->graph->regv[i]!=fg->regv[i]&&(fg->regv[i]->index>=vcount-rcount||BTST(lp->graph->av_out,fg->regv[i]->index))) return 1; lp=lp->next; } return 0; } /* checks if variable i can be held in a register in loop start-end */ /* currently we check whether an IC uses/modifies the variable and */ /* has a corresponding drefobj which might alias the variable */ int check_cacheable(int i,struct flowgraph *start,struct flowgraph *end) { int j,k; struct IC *p;struct Var *v; struct flowgraph *g; /* constants are always cacheable */ if(vilist[i]->identifier[0]==' ') return 1; if(i<vcount-rcount){ /* simple local variables are also easy */ v=vilist[i]; if(v->storage_class!=STATIC&&v->storage_class!=EXTERN&&!(v->flags&USEDASADR)) return 1; } if(disable&16384) return 0; for(g=start;g;g=g->normalout){ for(p=g->start;p;p=p->next){ for(j=0;j<p->use_cnt;j++){ k=p->use_list[j].v->index; if(p->use_list[j].flags&DREFOBJ) k+=vcount-rcount; if(k==i&&(p->code==CALL||(p->q1.flags&DREFOBJ)||(p->q2.flags&DREFOBJ))) return 0; } for(j=0;j<p->change_cnt;j++){ k=p->change_list[j].v->index; if(p->change_list[j].flags&DREFOBJ) k+=vcount-rcount; if(k==i&&(p->code==CALL||(p->z.flags&DREFOBJ))) return 0; } if(p==g->end) break; } if(g==end) break; } /*printf("assigned static %s to reg\n",vilist[i]->identifier);*/ return 1; } int exit_save(struct flowgraph *fg,int i) /* Testet, ob die Variable in Register i am Ende von Block fg gespeichert */ /* werden muss, d.h. der Vorgaenger eines Nachfolgers nicht dieselbe */ /* Variable im selben Register hat. */ { struct flowlist *lp; /* Konstanten muessen nie gespeichert werden */ if(fg->regv[i]->index>=vcount-rcount) return 0; if(!fg->normalout){ /* letzter Block, statische Variablen und drefobjs aktiv */ int sc=fg->regv[i]->storage_class; return sc==STATIC||sc==EXTERN; } if((fg->normalout&&(!fg->end||fg->end->code!=BRA))&&BTST(fg->normalout->av_in,fg->regv[i]->index)){ if(fg->normalout->regv[i]!=fg->regv[i]) return 1; lp=fg->normalout->in; while(lp){ if(lp->graph&&lp->graph->regv[i]!=fg->regv[i]) return 1; lp=lp->next; } } if(fg->branchout&&BTST(fg->branchout->av_in,fg->regv[i]->index)){ if(fg->branchout->regv[i]!=fg->regv[i]) return 1; lp=fg->branchout->in; while(lp){ if(lp->graph&&lp->graph->regv[i]!=fg->regv[i]) return 1; lp=lp->next; } } return 0; } void load_reg_parms(struct flowgraph *fg) /* Laedt Registerparameter, falls noetig. */ { int i,j; struct Var *v; struct regp regp[MAXR+1]={0}; /* for(i=1;i<=MAXR;i++){ regp[i].treg=0;regp[i].tvar=0;} */ for(i=0;i<vcount-rcount;i++){ v=vilist[i]; if((v->flags®PARM)&&(fg->regv[abs(v->reg)]!=v||(v->flags&CONVPARAMETER))&&(BTST(fg->av_in,i)||(v->flags&USEDASADR))){ regp[abs(v->reg)].tvar=v; for(j=1;j<=MAXR;j++) if(fg->regv[j]==v) regp[abs(v->reg)].treg=j; } } do_load_parms(regp,fg); } void insert_regs(struct flowgraph *fg1) /* Fuegt Registervariablen in die ICs ein. */ { int i;struct IC *p,*lic=0,*new;struct flowgraph *lfg=0,*fg; if(DEBUG&9216) printf("inserting register variables\n"); fg=fg1; while(fg){ if(DEBUG&8192) printf("block %d:\n",fg->index); p=fg->start; while(p){ for(i=1;i<=MAXR;i++){ if(!fg->regv[i]) continue; if(p->code==ALLOCREG&&p->q1.reg==i) ierror(0); if((p->q1.flags&(VAR|REG|DONTREGISTERIZE))==VAR&&p->q1.v==fg->regv[i]){ if(p->q1.v->index>=vcount-rcount) p->q1.flags&=~(KONST|VAR|VARADR); p->q1.flags|=REG; p->q1.reg=i; } if((p->q2.flags&(VAR|REG|DONTREGISTERIZE))==VAR&&p->q2.v==fg->regv[i]){ if(p->q2.v->index>=vcount-rcount) p->q2.flags&=~(KONST|VAR|VARADR); p->q2.flags|=REG; p->q2.reg=i; } if((p->z.flags&(VAR|REG|DONTREGISTERIZE))==VAR&&p->z.v==fg->regv[i]){ if(p->z.v->index>=vcount-rcount) p->z.flags&=~(KONST|VAR|VARADR); p->z.flags|=REG; p->z.reg=i; } } /* evtl. const-Variablen ruecksubstituieren */ if((p->q1.flags&VAR)&&p->q1.v->index>=vcount-rcount){ insert_cobj(&p->q1,&p->q1.v->cobj); } if((p->q2.flags&VAR)&&p->q2.v->index>=vcount-rcount){ insert_cobj(&p->q2,&p->q2.v->cobj); } if((p->z.flags&VAR)&&p->z.v->index>=vcount-rcount){ insert_cobj(&p->z,&p->z.v->cobj); } if(DEBUG&8192) pric2(stdout,p); if(p==fg->end) break; p=p->next; } if(fg->start&&fg->start->code==LABEL) lic=fg->start; for(i=1;i<=MAXR;i++){ if(fg->regv[i]){ if(DEBUG&8192){ printf("(%s),%ld(%p) assigned to %s\n",fg->regv[i]->identifier,zm2l(fg->regv[i]->offset),(void *)fg->regv[i],regnames[i]); if(fg->regv[i]->index>=vcount-rcount||BTST(fg->av_in,fg->regv[i]->index)) printf("active at the start of block\n"); if(fg->regv[i]->index<vcount-rcount&&BTST(fg->av_out,fg->regv[i]->index)) printf("active at the end of block\n"); } if(fg->regv[i]->index<vcount-rcount&&BTST(fg->av_out,fg->regv[i]->index)){ /* Variable beim Austritt aktiv? */ if(exit_save(fg,i)){ struct IC *tp; if(DEBUG&8192) printf("\thave to save it at end of block\n"); new=new_IC(); new->line=0; new->file=0; new->code=ASSIGN; new->typf=fg->regv[i]->vtyp->flags; /* vla */ if(ISARRAY(new->typf)) new->typf=POINTER_TYPE(fg->regv[i]->vtyp->next); /* cc */ if(new->typf==0) ierror(0); new->q1.flags=VAR|REG; new->q1.val.vmax=l2zm(0L); new->q1.v=fg->regv[i]; new->q1.reg=i; new->q2.flags=0; new->q2.val.vmax=szof(fg->regv[i]->vtyp); new->z.flags=VAR|DONTREGISTERIZE; new->z.val.vmax=l2zm(0L); new->z.v=fg->regv[i]; new->q1.am=new->q2.am=new->z.am=0; new->use_cnt=new->change_cnt=0; new->use_list=new->change_list=0; /* Vor FREEREGs und evtl. Branch+COMPARE/TEST setzen */ if(fg->end){ tp=fg->end; while(tp!=fg->start&&(tp->code==FREEREG||tp->code==SETRETURN)) tp=tp->prev; if(tp&&tp->code>=BEQ&&tp->code<=BRA){ if(tp->code<BRA){ int c; do{ tp=tp->prev; c=tp->code; if(c!=FREEREG&&c!=COMPARE&&c!=TEST) ierror(0); }while(c!=COMPARE&&c!=TEST); } tp=tp->prev; } }else tp=lic; insert_IC_fg(fg,tp,new); } } if(fg->regv[i]->index>=vcount-rcount||BTST(fg->av_in,fg->regv[i]->index)){ if((fg==fg1||entry_load(fg,i))&&(fg!=fg1||!(fg->regv[i]->flags®PARM))){ if(DEBUG&8192) printf("\thave to load it at start of block\n"); new=new_IC(); new->line=0; new->file=0; new->code=ASSIGN; new->typf=fg->regv[i]->vtyp->flags; /* vla */ if(ISARRAY(new->typf)) new->typf=POINTER_TYPE(fg->regv[i]->vtyp->next); /* cc */ if(new->typf==0) ierror(0); if(fg->regv[i]->index>=vcount-rcount){ insert_cobj(&new->q1,&fg->regv[i]->cobj); }else{ new->q1.flags=VAR|DONTREGISTERIZE; new->q1.val.vmax=l2zm(0L); new->q1.v=fg->regv[i]; } new->q2.flags=0; new->q2.val.vmax=szof(fg->regv[i]->vtyp); if(fg->regv[i]->index>=vcount-rcount) new->z.flags=REG; else new->z.flags=VAR|REG; new->z.val.vmax=l2zm(0L); new->z.v=fg->regv[i]; new->z.reg=i; new->q1.am=new->q2.am=new->z.am=0; new->use_cnt=new->change_cnt=0; new->use_list=new->change_list=0; insert_IC_fg(fg,lic,new); } } if(!lfg||!lfg->regv[i]) insert_allocreg(fg,lic,ALLOCREG,i); if(!fg->normalout||!fg->normalout->regv[i]) insert_allocreg(fg,fg->end?fg->end:lic,FREEREG,i); } } if(fg->end) lic=fg->end; lfg=fg; fg=fg->normalout; } load_reg_parms(fg1); } void do_loop_regs(struct flowgraph *start,struct flowgraph *end,int intask) /* Macht die Variablenzuweisung in Schleife start-end. */ /* Wenn end==0 Registerzuweisung fuer die ganze Funktion, ansonsten */ /* fuer die Schleife, die zum Header start gehoert. */ { struct flowgraph *g,*lend; int i,r,iterations; struct Var *lregs[MAXR+1]={0}; unsigned char regu[MAXR+1]={0}; bvtype *isused=mymalloc(vsize); /* Berechnen, wieviel ungefaehr eingespart wird, wenn eine Variable */ /* fuer diese Schleife in einem best. Register gehalten wird. */ /* Die savings in einer Schleife werden multipliziert, um das */ /* Laden/Speichern ausserhalb der Schleife geringer zu wichten. */ /* if(end&&(!g->normalout||!g->normalout->loopend||g->normalout->loopend->normalout->index!=-2)) ierror(0);*/ /* alle auf 0 */ for(i=0;i<vcount-rcount+const_vars;i++){ if(i<vcount-rcount&&(vilist[i]->vtyp->flags&VOLATILE)){ for(r=1;r<=MAXR;r++){ savings[i][r]=INT_MIN; } }else{ for(r=1;r<=MAXR;r++){ savings[i][r]=0; } } } if(end){ struct Var *v; /* estimated number of iterations, avoid too big values */ if(optsize) iterations=1; else iterations=4; /* Evtl. Kosten fuers Laden/Speichern beim Ein-/Austritt in die */ /* Schleife. */ end=start->normalout->loopend; g=end->normalout; if(DEBUG&9216) printf("assigning regs to blocks %d to %d\n",start->normalout->index,end->index); /* Werte modifizieren, falls Variable am Anfang/Ende der Schleife */ /* geladen/gespeichert werden muss. */ /* FIXME: Evtl. noetige stores/loads in anderen Bloecken! */ for(i=0;i<vcount-rcount+const_vars;i++){ v=vilist[i]; if(i>=vcount-rcount||BTST(start->av_in,i)){ for(r=1;r<=MAXR;r++) if(start->regv[r]!=v&&savings[i][r]!=INT_MIN) savings[i][r]-=cost_load_reg(r,v); } if(i<vcount-rcount&&BTST(g->av_out,i)){ for(r=1;r<=MAXR;r++) if(g->regv[r]!=v&&savings[i][r]!=INT_MIN) savings[i][r]-=cost_save_reg(r,v); } } /* Werte modifizieren, falls eine andere Variable gespeichert oder */ /* geladen werden muss. Hmm..stimmt das so? */ for(r=1;r<=MAXR;r++){ v=start->regv[r]; if(v&&v->index<vcount-rcount&&BTST(start->av_in,v->index)){ for(i=0;i<vcount-rcount;i++) if(v->index!=i&&savings[i][r]!=INT_MIN) savings[i][r]-=cost_load_reg(r,vilist[i]); } if(v&&v->index<vcount-rcount&&BTST(g->av_out,v->index)){ for(i=0;i<vcount-rcount;i++) if(v->index!=i&&savings[i][r]!=INT_MIN) savings[i][r]-=cost_save_reg(r,vilist[i]); } } g=start->normalout; }else{ iterations=1; /* Bei Registervergabe fuer die ganze Funktion muessen alle beim */ /* Eintritt der Funktion aktiven Variablen geladen werden. */ /* statics have to be saved at the end */ if(DEBUG&9216) printf("assigning regs to whole function\n"); for(i=0;i<vcount-rcount+const_vars;i++){ if(i<vcount-rcount&&(vilist[i]->storage_class==STATIC||vilist[i]->storage_class==EXTERN)){ for(r=1;r<=MAXR;r++) if(savings[i][r]!=INT_MIN) savings[i][r]-=cost_save_reg(r,vilist[i]); } if(i>=vcount-rcount||BTST(start->av_in,i)){ int pr=abs(vilist[i]->reg); for(r=1;r<=MAXR;r++){ if(savings[i][r]!=INT_MIN){ if(pr==0){ savings[i][r]-=cost_load_reg(r,vilist[i]); }else if(!regsa[r]){ if(r==pr) savings[i][r]+=cost_save_reg(r,vilist[i]); else savings[i][r]+=(cost_save_reg(r,vilist[i])-cost_move_reg(pr,r)); } } } } } /* Nonscratchregister muessen geladen/gesichert werden. */ /*FIXME: einige unschoene Effekte(?) */ if(!intask){ for(r=1;r<=MAXR;r++){ if(!regscratch[r]&&!regsa[r]){ for(i=0;i<vcount-rcount+const_vars;i++) if(savings[i][r]!=INT_MIN) savings[i][r]-=cost_pushpop_reg(r); } } } g=start; } if(DEBUG&9216) printf("calculating approximate savings\n"); lend=0; for(;g;g=g->normalout){ struct IC *p;struct Var *v; int t,vt; if(!end&&!lend){ lend=g->loopend; if(lend&&iterations==1&&!optsize) iterations=4; } /* Wenn das Register in dem Block benutzt wird, muss man es retten */ for(r=1;r<=MAXR;r++){ if(BTST(g->regused,r)||(reg_pair(r,&rp)&&(BTST(g->regused,rp.r1)||BTST(g->regused,rp.r2)))){ int vi; if(g->regv[r]) vi=g->regv[r]->index; else vi=-1; for(i=0;i<vcount-rcount+const_vars;i++){ if(i>=vcount-rcount||BTST(g->av_out,i)||BTST(g->av_gen,i)) if(vi!=i&&savings[i][r]!=INT_MIN) savings[i][r]-=iterations*cost_load_reg(r,vilist[i])+cost_save_reg(r,vilist[i]); } } } memcpy(isused,g->av_out,vsize); p=g->end; while(p){ if((p->q1.flags&(VAR|VARADR|REG))==VAR){ v=p->q1.v;vt=v->vtyp->flags; /* vla */ if(ISARRAY(vt)&&is_vlength(v->vtyp)) vt=POINTER_TYPE(v->vtyp->next); if((optflags&1024)||((v->storage_class==AUTO||v->storage_class==REGISTER)&&!(v->flags&USEDASADR))){ i=v->index; if(p->code==ADDRESS||((p->code==ASSIGN||p->code==PUSH)&&(q1typ(p)&NQ)==(CHAR)&&!zmeqto(p->q2.val.vmax,l2zm(1L)))){ for(r=1;r<=MAXR;r++) savings[i][r]=INT_MIN; }else{ for(r=1;r<=MAXR;r++){ if(!regsa[r]&&!BTST(g->regused,r)&&savings[i][r]!=INT_MIN&®ok(r,vt,-1)&&(!reg_pair(r,&rp)||(!regsa[rp.r1]&&!regsa[rp.r2]&&!BTST(g->regused,rp.r1)&&!BTST(g->regused,rp.r2)))){ int s=cost_savings(p,r,&p->q1); if(s==INT_MIN) savings[i][r]=INT_MIN; else savings[i][r]+=iterations*s; } } } } } if((p->q2.flags&(VAR|VARADR|REG))==VAR){ v=p->q2.v;vt=v->vtyp->flags; /* vla */ if(ISARRAY(vt)&&is_vlength(v->vtyp)) vt=POINTER_TYPE(v->vtyp->next); if((optflags&1024)||((v->storage_class==AUTO||v->storage_class==REGISTER)&&!(v->flags&USEDASADR))){ i=v->index; for(r=1;r<=MAXR;r++){ if(!regsa[r]&&!BTST(g->regused,r)&&savings[i][r]!=INT_MIN&®ok(r,vt,-1)&&(!reg_pair(r,&rp)||(!regsa[rp.r1]&&!regsa[rp.r2]&&!BTST(g->regused,rp.r1)&&!BTST(g->regused,rp.r2)))){ int s=cost_savings(p,r,&p->q2); if(s==INT_MIN) savings[i][r]=INT_MIN; else savings[i][r]+=iterations*s; } } } } if((p->z.flags&(VAR|VARADR|REG))==VAR){ v=p->z.v;vt=v->vtyp->flags; if(ISARRAY(vt)&&is_vlength(v->vtyp)) vt=POINTER_TYPE(v->vtyp->next); if((optflags&1024)||((v->storage_class==AUTO||v->storage_class==REGISTER)&&!(v->flags&USEDASADR))){ i=v->index; if(p->code==ASSIGN&&(ztyp(p)&NQ)==(CHAR)&&!zmeqto(p->q2.val.vmax,l2zm(1L))){ for(r=1;r<=MAXR;r++) savings[i][r]=INT_MIN; } for(r=1;r<=MAXR;r++){ if(!regsa[r]&&!BTST(g->regused,r)&&savings[i][r]!=INT_MIN&®ok(r,vt,-1)&&(!reg_pair(r,&rp)||(!regsa[rp.r1]&&!regsa[rp.r2]&&!BTST(g->regused,rp.r1)&&!BTST(g->regused,rp.r2)))){ int s=cost_savings(p,r,&p->z); if(s==INT_MIN) savings[i][r]=INT_MIN; else savings[i][r]+=iterations*s;