/* $VER: vbcc (opt.c) V0.8 *//* allgemeine Routinen fuer den Optimizer und Steuerung der einzelnen *//* Laeufe */ #include "opt.h" static char FILE_[]=__FILE__; /* die naechsten Funktionen sollten evtl. in ic.c */ /* Sind use/change-Listen initialisiert? */int have_alias; int static_cse=1,dref_cse=1; #ifdef ALEX_REGextern struct flowgraph *pFg;#endif void insert_IC(struct IC *p,struct IC *new)/* fuegt new hinter p ein; p darf 0 sein */{ if((new->code==ADDI2P||new->code==SUBIFP||new->code==SUBPFP)&&!ISPOINTER(new->typf2)) ierror(0); new->prev=p; if(p){ new->next=p->next; p->next=new; }else{ new->next=first_ic; first_ic=new; } if(new->next) new->next->prev=new; else last_ic=new; new->q1.am=new->q2.am=new->z.am=0;} #ifndef NO_OPTIMIZER int gchanged; /* Merker, ob Optimierungslauf etwas geaendert hat */int norek; /* diese Funktion wird nicht rekursiv auf */int nocall; /* diese Funktion kehrt nicht zum Caller zurueck */ #if HAVE_LIBCALLSextern np gen_libcall(char *fname,np arg1,struct Typ *t1,np arg2,struct Typ *t2); /* insert libcalls just before register allocation */static int insert_libcalls(struct flowgraph *fg){ struct IC *p,*next,*add; int replaced=0; static struct node n,nl,nr; static struct Typ t,tl,tr; if(DEBUG&1024) printf("insert_libcalls\n"); while(fg){ for(p=fg->start;p;p=next){ int c=p->code,end=0; char *libname; next=p->next; if((c>=OR&&c<=XOR)||(c>=LSHIFT&&c<=KOMPLEMENT)||c==COMPARE||c==CONVERT||c==MINUS||c==TEST){ if(libname=use_libcall(c,p->typf,p->typf2)){ struct IC *merk_first,*merk_last; static struct node n1,n2; static struct Typ t1,t2; if(DEBUG&1024){ printf("converting IC to libcall:\n"); pric2(stdout,p); } replaced=1; merk_last=last_ic; merk_first=first_ic; first_ic=last_ic=0; n1.flags=REINTERPRET; n1.o=p->q1; n1.ntyp=&t1; t1.flags=q1typ(p); if(p->q2.flags){ n2.flags=REINTERPRET; n2.o=p->q2; n2.ntyp=&t2; t2.flags=q2typ(p); gen_libcall(libname,&n1,&t1,&n2,&t2); }else gen_libcall(libname,&n1,&t1,0,0); if(!last_ic||last_ic->code!=GETRETURN) ierror(0); last_ic->z=p->z; add=first_ic; last_ic=merk_last; first_ic=merk_first; for(;add;add=next){ next=add->next; insert_IC_fg(fg,p->prev,add); } next=p->next; if(fg->end==p) end=1; if(p->z.flags){ remove_IC_fg(fg,p); }else{ struct Typ *t=new_typ(); t->flags=INT; p->code=TEST; p->typf=INT; p->q1.flags=VAR; p->q1.v=add_tmp_var(t); p->q1.val.vmax=l2zm(0L); p->prev->z=p->q1; p->q2.flags=p->z.flags=0; } } } if(end||p==fg->end) break; } fg=fg->normalout; } return replaced;}#endif /* temporary fuer verschiedene Bitvektoren */bvtype *tmp; int in_varlist(struct varlist *vl,int cnt,struct Var *v,int flags){ int i; /*FIXME: slow */ for(i=0;i<cnt;i++){ if(vl[i].v==v&&vl[i].flags==flags) return 1; } return 0;} static void add_call_list(void){ struct IC *p; for(p=first_ic;p;p=p->next){ if(p->code==CALL&&p->call_cnt==0){ if((p->q1.flags&(VAR|DREFOBJ))==VAR){ p->call_cnt=1; p->call_list=mymalloc(sizeof(*p->call_list)); p->call_list[0].v=p->q1.v; p->call_list[0].flags=0; } } }} void calc_finfo(struct Var *v,int flags){ struct IC *p;int i,known,maxtyp,t,c; /* 128 types should be enough for everyone :-) */ #define TSIZE BVSIZE(128) static bvtype tf[TSIZE]; if(!v->fi) ierror(0); if(flags&CALC_USES){ if(v->fi->flags&ALL_USES) return; free(v->fi->use_list); v->fi->use_cnt=0; v->fi->use_list=0; memset(tf,0,TSIZE); known=1;maxtyp=-1; for(p=first_ic;p;p=p->next){ c=p->code; if(p->q1.flags&DREFOBJ){ t=(q1typ(p)&NQ); if(t>maxtyp) maxtyp=t; BSET(tf,t); } if(p->q2.flags&DREFOBJ){ t=(q2typ(p)&NQ); if(t>maxtyp) maxtyp=t; BSET(tf,t); } if(c==CALL){ if((p->q1.flags&(VAR|DREFOBJ))!=VAR||!p->q1.v->fi||!(p->q1.v->fi->flags&ALL_USES)){ free(v->fi->use_list); v->fi->use_cnt=0; v->fi->use_list=0; known=0; break; }else{ for(i=0;i<p->q1.v->fi->use_cnt;i++){ if(p->q1.v->fi->use_list[i].v){ if(!in_varlist(v->fi->use_list,v->fi->use_cnt,p->q1.v->fi->use_list[i].v,p->q1.v->fi->use_list[i].flags)){ v->fi->use_cnt++; v->fi->use_list=myrealloc(v->fi->use_list,v->fi->use_cnt*sizeof(struct varlist)); v->fi->use_list[v->fi->use_cnt-1]=p->q1.v->fi->use_list[i]; } }else{ BSET(tf,p->q1.v->fi->use_list[i].flags&NQ); } } } }else{ for(i=0;i<p->use_cnt;i++){ if(p->use_list[i].v->nesting!=0) continue; if(!in_varlist(v->fi->use_list,v->fi->use_cnt,p->use_list[i].v,p->use_list[i].flags)){ v->fi->use_cnt++; v->fi->use_list=myrealloc(v->fi->use_list,v->fi->use_cnt*sizeof(struct varlist)); v->fi->use_list[v->fi->use_cnt-1]=p->use_list[i]; } } } } for(c=0;c<=maxtyp;c++){ if(BTST(tf,c)){ v->fi->use_cnt++; v->fi->use_list=myrealloc(v->fi->use_list,v->fi->use_cnt*sizeof(struct varlist)); v->fi->use_list[v->fi->use_cnt-1].v=0; v->fi->use_list[v->fi->use_cnt-1].flags=c; } } if(known) v->fi->flags|=ALL_USES; } if(flags&CALC_CHANGES){ if(v->fi->flags&ALL_MODS) return; free(v->fi->change_list); v->fi->change_cnt=0; v->fi->change_list=0; memset(tf,0,TSIZE); known=1;maxtyp=-1; for(p=first_ic;p;p=p->next){ c=p->code; if(p->z.flags&DREFOBJ){ t=(ztyp(p)&NQ); if(t>maxtyp) maxtyp=t; BSET(tf,t); } if(c==CALL){ if((p->q1.flags&(VAR|DREFOBJ))!=VAR||!p->q1.v->fi||!(p->q1.v->fi->flags&ALL_MODS)){ free(v->fi->change_list); v->fi->change_cnt=0; v->fi->change_list=0; known=0; break; }else{ for(i=0;i<p->q1.v->fi->change_cnt;i++){ if(p->q1.v->fi->change_list[i].v){ if(!in_varlist(v->fi->change_list,v->fi->change_cnt,p->q1.v->fi->change_list[i].v,p->q1.v->fi->change_list[i].flags)){ v->fi->change_cnt++; v->fi->change_list=myrealloc(v->fi->change_list,v->fi->change_cnt*sizeof(struct varlist)); v->fi->change_list[v->fi->change_cnt-1]=p->q1.v->fi->change_list[i]; } }else{ BSET(tf,p->q1.v->fi->change_list[i].flags&NQ); } } } }else{ for(i=0;i<p->change_cnt;i++){ if(p->change_list[i].v->nesting!=0) continue; if(!in_varlist(v->fi->change_list,v->fi->change_cnt,p->change_list[i].v,p->change_list[i].flags)){ v->fi->change_cnt++; v->fi->change_list=myrealloc(v->fi->change_list,v->fi->change_cnt*sizeof(struct varlist)); v->fi->change_list[v->fi->change_cnt-1]=p->change_list[i]; } } } } for(c=0;c<=maxtyp;c++){ if(BTST(tf,c)){ v->fi->change_cnt++; v->fi->change_list=myrealloc(v->fi->change_list,v->fi->change_cnt*sizeof(struct varlist)); v->fi->change_list[v->fi->change_cnt-1].v=0; v->fi->change_list[v->fi->change_cnt-1].flags=c; } } if(known) v->fi->flags|=ALL_MODS; } if(flags&CALC_CALLS){ if(v->fi->flags&ALL_CALLS) return; free(v->fi->call_list); v->fi->call_list=0; v->fi->call_cnt=0; p=v->fi->opt_ic; if(!p) p=v->fi->first_ic; for(;p;p=p->next){ if(p->code==CALL){ if(p->q1.flags&DREFOBJ) return; if(!in_varlist(v->fi->call_list,v->fi->call_cnt,p->q1.v,0)){ v->fi->call_cnt++; v->fi->call_list=myrealloc(v->fi->call_list,v->fi->call_cnt*sizeof(struct varlist)); v->fi->call_list[v->fi->call_cnt-1].v=p->q1.v; v->fi->call_list[v->fi->call_cnt-1].flags=0; } } } v->fi->flags|=ALL_CALLS; }} void used_clist(struct Typ *t,struct const_list *cl){ int i;zmax l; if(ISARRAY(t->flags)){ for(l=l2zm(0L);!zmleq(t->size,l)&&cl;l=zmadd(l,l2zm(1L)),cl=cl->next){ if(!cl->other){ierror(0);return;} used_clist(t->next,cl->other); } return; } if(ISUNION(t->flags)){ used_clist((*t->exact->sl)[0].styp,cl); return; } if(ISSTRUCT(t->flags)){ struct Typ *st; for(i=0;i<t->exact->count&&cl;i++){ st=(*t->exact->sl)[i].styp; if(!(*t->exact->sl)[i].identifier) ierror(0); if((*t->exact->sl)[i].identifier[0]){ if(cl->other) used_clist(st,cl->other); cl=cl->next; } } return; } if(cl->tree&&(cl->tree->o.flags&VAR)) used_objects(cl->tree->o.v); return;} void used_objects(struct Var *v){ int i; if(v->flags&REFERENCED) return; v->flags|=REFERENCED; if(ISFUNC(v->vtyp->flags)){ struct IC *p; if(!(v->flags&DEFINED)) return; if(!v->fi) ierror(0); for(i=0;i<v->fi->call_cnt;i++){ if(v->fi->call_list[i].v->flags&DEFINED) used_objects(v->fi->call_list[i].v); } /*FIXME: use/change aus fi */ for(p=v->fi->opt_ic;p;p=p->next){ if(p->q1.flags&VAR) used_objects(p->q1.v); if(p->q2.flags&VAR) used_objects(p->q2.v); if(p->z.flags&VAR) used_objects(p->z.v); } }else{ if(v->clist) used_clist(v->vtyp,v->clist); }} zmax recalc_start_offset; void recalc_offsets(struct flowgraph *fg)/* berechnet Offsets fuer auto-Variablen neu und versucht, fuer Variablen, *//* die nicht gleichzeitig aktiv sind, den gleichen Platz zu belegen */{ int i,b,*eqto;size_t bsize;zmax *al,*sz; bvtype **used,*tmp,*empty; struct IC *p; if(DEBUG&1024) printf("recalculating offsets\n"); if(DEBUG&1024) printf("setting up arrays\n"); /*bsize=(basic_blocks+CHAR_BIT-1)/CHAR_BIT; /* we don's use fg->index but count from 0 */ bsize=BVSIZE(basic_blocks); if(DEBUG&1024) printf("bsize=%lu\n",(unsigned long)bsize); tmp=mymalloc(bsize); al=mymalloc(sizeof(*al)*(vcount-rcount)); eqto=mymalloc(sizeof(int)*(vcount-rcount)); sz=mymalloc(sizeof(*sz)*(vcount-rcount)); empty=mymalloc(bsize); memset(empty,0,bsize); used=mymalloc(sizeof(bvtype *)*(vcount-rcount)); /* Tabelle, welche Variable in welchem Block belegt ist, aufbauen */ for(i=0;i<vcount-rcount;i++){ if(zmleq(l2zm(0L),vilist[i]->offset)&&(vilist[i]->storage_class==AUTO||vilist[i]->storage_class==REGISTER)){ if(DEBUG&2048) printf("setting up for %s,%ld\n",vilist[i]->identifier,zm2l(vilist[i]->offset)); used[i]=mymalloc(bsize); memset(used[i],0,bsize); }else{ used[i]=0; } sz[i]=szof(vilist[i]->vtyp); al[i]=falign(vilist[i]->vtyp); eqto[i]=-1; } b=0; while(fg){ if(b>=basic_blocks) ierror(0); for(i=0;i<vcount-rcount;i++){ if(used[i]&&(BTST(fg->av_in,i)||BTST(fg->av_out,i))){ int r; BSET(used[i],b); for(r=1;r<=MAXR;r++) if(fg->regv[r]&&fg->regv[r]->index==i) BCLR(used[i],b); } } for(p=fg->start;p;p=p->next){ if((p->q1.flags&(VAR|REG))==VAR){ i=p->q1.v->index; if(i!=-1){ if(i<0||i>=vcount) ierror(0); if(i>=0&&used[i]){ BSET(used[i],b); } } } if((p->q2.flags&(VAR|REG))==VAR){ i=p->q2.v->index; if(i!=-1){ if(i<0||i>=vcount) ierror(0); if(i>=0&&used[i]){ BSET(used[i],b); } } } if((p->z.flags&(VAR|REG))==VAR){ i=p->z.v->index; if(i!=-1){ if(i<0||i>=vcount) ierror(0); if(i>=0&&used[i]){ BSET(used[i],b); } } } if(p==fg->end) break; } fg=fg->normalout; b++; } /* schauen, ob Variablen in gleichen Speicher koennen */ if(DEBUG&1024) printf("looking for distinct variables\n"); for(i=0;i<vcount-rcount;i++){ if(!used[i]||eqto[i]>=0) continue; if(!memcmp(used[i],empty,bsize)){ free(used[i]);used[i]=0;continue;} for(b=i+1;b<vcount-rcount;b++){ if(!used[b]||eqto[b]>=0) continue; if(!memcmp(used[b],empty,bsize)){ free(used[b]);used[b]=0;continue;} if(DEBUG&2048) printf("comparing %s(%p) and %s(%p)\n",vilist[i]->identifier,(void *)vilist[i],vilist[b]->identifier,(void *)vilist[b]); memcpy(tmp,used[i],bsize); bvintersect(tmp,used[b],bsize); if(!memcmp(tmp,empty,bsize)){ if(DEBUG&1024) printf("memory for %s(%p) and %s(%p) equal\n",vilist[i]->identifier,(void *)vilist[i],vilist[b]->identifier,(void *)vilist[b]); eqto[b]=i; if(!zmleq(al[b],al[i])) al[i]=al[b]; if(!zmleq(sz[b],sz[i])) sz[i]=sz[b]; bvunite(used[i],used[b],bsize); } } } if(DEBUG&1024) printf("final recalculating\n"); max_offset=recalc_start_offset; for(i=0;i<vcount-rcount;i++){ if(!used[i]) continue; free(used[i]); if(DEBUG&2048) printf("adjusting offset for %s,%ld\n",vilist[i]->identifier,zm2l(vilist[i]->offset)); if(eqto[i]>=0){ vilist[i]->offset=vilist[eqto[i]]->offset; continue; } vilist[i]->offset=zmmult(zmdiv(zmadd(max_offset,zmsub(al[i],l2zm(1L))),al[i]),al[i]); max_offset=zmadd(vilist[i]->offset,sz[i]); } recalc_start_offset=l2zm(0L); free(used); free(sz); free(al); free(tmp); free(empty); free(eqto);}void remove_IC_fg(struct flowgraph *g,struct IC *p)/* Entfernt IC p und beachtet Flussgraph. Ausserdem werden *//* use/change-Listen freigegeben. */{ if(p->q1.am||p->q2.am||p->z.am) ierror(0); if(have_alias){ free(p->use_list); free(p->change_list); } if(g->start==g->end){ g->start=g->end=0; }else{ if(p==g->end) g->end=p->prev; if(p==g->start) g->start=p->next; } remove_IC(p);} /* allowed to create new variables */int early_peephole(void){ struct IC *p; int changed,gchanged=0,c,t; do{ changed=0; p=first_ic; while(p){ c=p->code; t=p->typf; if(c==COMPARE&&(p->q2.flags&KONST)&&ISINT(p->typf)){ struct case_table *ct; if((ct=calc_case_table(p,JUMP_TABLE_DENSITY))&&ct->num>1&&ct->density==1){Lines 1–500 of 1570. Load more
/* $VER: vbcc (opt.c) V0.8 */ /* allgemeine Routinen fuer den Optimizer und Steuerung der einzelnen */ /* Laeufe */ #include "opt.h" static char FILE_[]=__FILE__; /* die naechsten Funktionen sollten evtl. in ic.c */ /* Sind use/change-Listen initialisiert? */ int have_alias; int static_cse=1,dref_cse=1; #ifdef ALEX_REG extern struct flowgraph *pFg; #endif void insert_IC(struct IC *p,struct IC *new) /* fuegt new hinter p ein; p darf 0 sein */ { if((new->code==ADDI2P||new->code==SUBIFP||new->code==SUBPFP)&&!ISPOINTER(new->typf2)) ierror(0); new->prev=p; if(p){ new->next=p->next; p->next=new; }else{ new->next=first_ic; first_ic=new; } if(new->next) new->next->prev=new; else last_ic=new; new->q1.am=new->q2.am=new->z.am=0; } #ifndef NO_OPTIMIZER int gchanged; /* Merker, ob Optimierungslauf etwas geaendert hat */ int norek; /* diese Funktion wird nicht rekursiv auf */ int nocall; /* diese Funktion kehrt nicht zum Caller zurueck */ #if HAVE_LIBCALLS extern np gen_libcall(char *fname,np arg1,struct Typ *t1,np arg2,struct Typ *t2); /* insert libcalls just before register allocation */ static int insert_libcalls(struct flowgraph *fg) { struct IC *p,*next,*add; int replaced=0; static struct node n,nl,nr; static struct Typ t,tl,tr; if(DEBUG&1024) printf("insert_libcalls\n"); while(fg){ for(p=fg->start;p;p=next){ int c=p->code,end=0; char *libname; next=p->next; if((c>=OR&&c<=XOR)||(c>=LSHIFT&&c<=KOMPLEMENT)||c==COMPARE||c==CONVERT||c==MINUS||c==TEST){ if(libname=use_libcall(c,p->typf,p->typf2)){ struct IC *merk_first,*merk_last; static struct node n1,n2; static struct Typ t1,t2; if(DEBUG&1024){ printf("converting IC to libcall:\n"); pric2(stdout,p); } replaced=1; merk_last=last_ic; merk_first=first_ic; first_ic=last_ic=0; n1.flags=REINTERPRET; n1.o=p->q1; n1.ntyp=&t1; t1.flags=q1typ(p); if(p->q2.flags){ n2.flags=REINTERPRET; n2.o=p->q2; n2.ntyp=&t2; t2.flags=q2typ(p); gen_libcall(libname,&n1,&t1,&n2,&t2); }else gen_libcall(libname,&n1,&t1,0,0); if(!last_ic||last_ic->code!=GETRETURN) ierror(0); last_ic->z=p->z; add=first_ic; last_ic=merk_last; first_ic=merk_first; for(;add;add=next){ next=add->next; insert_IC_fg(fg,p->prev,add); } next=p->next; if(fg->end==p) end=1; if(p->z.flags){ remove_IC_fg(fg,p); }else{ struct Typ *t=new_typ(); t->flags=INT; p->code=TEST; p->typf=INT; p->q1.flags=VAR; p->q1.v=add_tmp_var(t); p->q1.val.vmax=l2zm(0L); p->prev->z=p->q1; p->q2.flags=p->z.flags=0; } } } if(end||p==fg->end) break; } fg=fg->normalout; } return replaced; } #endif /* temporary fuer verschiedene Bitvektoren */ bvtype *tmp; int in_varlist(struct varlist *vl,int cnt,struct Var *v,int flags) { int i; /*FIXME: slow */ for(i=0;i<cnt;i++){ if(vl[i].v==v&&vl[i].flags==flags) return 1; } return 0; } static void add_call_list(void) { struct IC *p; for(p=first_ic;p;p=p->next){ if(p->code==CALL&&p->call_cnt==0){ if((p->q1.flags&(VAR|DREFOBJ))==VAR){ p->call_cnt=1; p->call_list=mymalloc(sizeof(*p->call_list)); p->call_list[0].v=p->q1.v; p->call_list[0].flags=0; } } } } void calc_finfo(struct Var *v,int flags) { struct IC *p;int i,known,maxtyp,t,c; /* 128 types should be enough for everyone :-) */ #define TSIZE BVSIZE(128) static bvtype tf[TSIZE]; if(!v->fi) ierror(0); if(flags&CALC_USES){ if(v->fi->flags&ALL_USES) return; free(v->fi->use_list); v->fi->use_cnt=0; v->fi->use_list=0; memset(tf,0,TSIZE); known=1;maxtyp=-1; for(p=first_ic;p;p=p->next){ c=p->code; if(p->q1.flags&DREFOBJ){ t=(q1typ(p)&NQ); if(t>maxtyp) maxtyp=t; BSET(tf,t); } if(p->q2.flags&DREFOBJ){ t=(q2typ(p)&NQ); if(t>maxtyp) maxtyp=t; BSET(tf,t); } if(c==CALL){ if((p->q1.flags&(VAR|DREFOBJ))!=VAR||!p->q1.v->fi||!(p->q1.v->fi->flags&ALL_USES)){ free(v->fi->use_list); v->fi->use_cnt=0; v->fi->use_list=0; known=0; break; }else{ for(i=0;i<p->q1.v->fi->use_cnt;i++){ if(p->q1.v->fi->use_list[i].v){ if(!in_varlist(v->fi->use_list,v->fi->use_cnt,p->q1.v->fi->use_list[i].v,p->q1.v->fi->use_list[i].flags)){ v->fi->use_cnt++; v->fi->use_list=myrealloc(v->fi->use_list,v->fi->use_cnt*sizeof(struct varlist)); v->fi->use_list[v->fi->use_cnt-1]=p->q1.v->fi->use_list[i]; } }else{ BSET(tf,p->q1.v->fi->use_list[i].flags&NQ); } } } }else{ for(i=0;i<p->use_cnt;i++){ if(p->use_list[i].v->nesting!=0) continue; if(!in_varlist(v->fi->use_list,v->fi->use_cnt,p->use_list[i].v,p->use_list[i].flags)){ v->fi->use_cnt++; v->fi->use_list=myrealloc(v->fi->use_list,v->fi->use_cnt*sizeof(struct varlist)); v->fi->use_list[v->fi->use_cnt-1]=p->use_list[i]; } } } } for(c=0;c<=maxtyp;c++){ if(BTST(tf,c)){ v->fi->use_cnt++; v->fi->use_list=myrealloc(v->fi->use_list,v->fi->use_cnt*sizeof(struct varlist)); v->fi->use_list[v->fi->use_cnt-1].v=0; v->fi->use_list[v->fi->use_cnt-1].flags=c; } } if(known) v->fi->flags|=ALL_USES; } if(flags&CALC_CHANGES){ if(v->fi->flags&ALL_MODS) return; free(v->fi->change_list); v->fi->change_cnt=0; v->fi->change_list=0; memset(tf,0,TSIZE); known=1;maxtyp=-1; for(p=first_ic;p;p=p->next){ c=p->code; if(p->z.flags&DREFOBJ){ t=(ztyp(p)&NQ); if(t>maxtyp) maxtyp=t; BSET(tf,t); } if(c==CALL){ if((p->q1.flags&(VAR|DREFOBJ))!=VAR||!p->q1.v->fi||!(p->q1.v->fi->flags&ALL_MODS)){ free(v->fi->change_list); v->fi->change_cnt=0; v->fi->change_list=0; known=0; break; }else{ for(i=0;i<p->q1.v->fi->change_cnt;i++){ if(p->q1.v->fi->change_list[i].v){ if(!in_varlist(v->fi->change_list,v->fi->change_cnt,p->q1.v->fi->change_list[i].v,p->q1.v->fi->change_list[i].flags)){ v->fi->change_cnt++; v->fi->change_list=myrealloc(v->fi->change_list,v->fi->change_cnt*sizeof(struct varlist)); v->fi->change_list[v->fi->change_cnt-1]=p->q1.v->fi->change_list[i]; } }else{ BSET(tf,p->q1.v->fi->change_list[i].flags&NQ); } } } }else{ for(i=0;i<p->change_cnt;i++){ if(p->change_list[i].v->nesting!=0) continue; if(!in_varlist(v->fi->change_list,v->fi->change_cnt,p->change_list[i].v,p->change_list[i].flags)){ v->fi->change_cnt++; v->fi->change_list=myrealloc(v->fi->change_list,v->fi->change_cnt*sizeof(struct varlist)); v->fi->change_list[v->fi->change_cnt-1]=p->change_list[i]; } } } } for(c=0;c<=maxtyp;c++){ if(BTST(tf,c)){ v->fi->change_cnt++; v->fi->change_list=myrealloc(v->fi->change_list,v->fi->change_cnt*sizeof(struct varlist)); v->fi->change_list[v->fi->change_cnt-1].v=0; v->fi->change_list[v->fi->change_cnt-1].flags=c; } } if(known) v->fi->flags|=ALL_MODS; } if(flags&CALC_CALLS){ if(v->fi->flags&ALL_CALLS) return; free(v->fi->call_list); v->fi->call_list=0; v->fi->call_cnt=0; p=v->fi->opt_ic; if(!p) p=v->fi->first_ic; for(;p;p=p->next){ if(p->code==CALL){ if(p->q1.flags&DREFOBJ) return; if(!in_varlist(v->fi->call_list,v->fi->call_cnt,p->q1.v,0)){ v->fi->call_cnt++; v->fi->call_list=myrealloc(v->fi->call_list,v->fi->call_cnt*sizeof(struct varlist)); v->fi->call_list[v->fi->call_cnt-1].v=p->q1.v; v->fi->call_list[v->fi->call_cnt-1].flags=0; } } } v->fi->flags|=ALL_CALLS; } } void used_clist(struct Typ *t,struct const_list *cl) { int i;zmax l; if(ISARRAY(t->flags)){ for(l=l2zm(0L);!zmleq(t->size,l)&&cl;l=zmadd(l,l2zm(1L)),cl=cl->next){ if(!cl->other){ierror(0);return;} used_clist(t->next,cl->other); } return; } if(ISUNION(t->flags)){ used_clist((*t->exact->sl)[0].styp,cl); return; } if(ISSTRUCT(t->flags)){ struct Typ *st; for(i=0;i<t->exact->count&&cl;i++){ st=(*t->exact->sl)[i].styp; if(!(*t->exact->sl)[i].identifier) ierror(0); if((*t->exact->sl)[i].identifier[0]){ if(cl->other) used_clist(st,cl->other); cl=cl->next; } } return; } if(cl->tree&&(cl->tree->o.flags&VAR)) used_objects(cl->tree->o.v); return; } void used_objects(struct Var *v) { int i; if(v->flags&REFERENCED) return; v->flags|=REFERENCED; if(ISFUNC(v->vtyp->flags)){ struct IC *p; if(!(v->flags&DEFINED)) return; if(!v->fi) ierror(0); for(i=0;i<v->fi->call_cnt;i++){ if(v->fi->call_list[i].v->flags&DEFINED) used_objects(v->fi->call_list[i].v); } /*FIXME: use/change aus fi */ for(p=v->fi->opt_ic;p;p=p->next){ if(p->q1.flags&VAR) used_objects(p->q1.v); if(p->q2.flags&VAR) used_objects(p->q2.v); if(p->z.flags&VAR) used_objects(p->z.v); } }else{ if(v->clist) used_clist(v->vtyp,v->clist); } } zmax recalc_start_offset; void recalc_offsets(struct flowgraph *fg) /* berechnet Offsets fuer auto-Variablen neu und versucht, fuer Variablen, */ /* die nicht gleichzeitig aktiv sind, den gleichen Platz zu belegen */ { int i,b,*eqto;size_t bsize;zmax *al,*sz; bvtype **used,*tmp,*empty; struct IC *p; if(DEBUG&1024) printf("recalculating offsets\n"); if(DEBUG&1024) printf("setting up arrays\n"); /*bsize=(basic_blocks+CHAR_BIT-1)/CHAR_BIT; /* we don's use fg->index but count from 0 */ bsize=BVSIZE(basic_blocks); if(DEBUG&1024) printf("bsize=%lu\n",(unsigned long)bsize); tmp=mymalloc(bsize); al=mymalloc(sizeof(*al)*(vcount-rcount)); eqto=mymalloc(sizeof(int)*(vcount-rcount)); sz=mymalloc(sizeof(*sz)*(vcount-rcount)); empty=mymalloc(bsize); memset(empty,0,bsize); used=mymalloc(sizeof(bvtype *)*(vcount-rcount)); /* Tabelle, welche Variable in welchem Block belegt ist, aufbauen */ for(i=0;i<vcount-rcount;i++){ if(zmleq(l2zm(0L),vilist[i]->offset)&&(vilist[i]->storage_class==AUTO||vilist[i]->storage_class==REGISTER)){ if(DEBUG&2048) printf("setting up for %s,%ld\n",vilist[i]->identifier,zm2l(vilist[i]->offset)); used[i]=mymalloc(bsize); memset(used[i],0,bsize); }else{ used[i]=0; } sz[i]=szof(vilist[i]->vtyp); al[i]=falign(vilist[i]->vtyp); eqto[i]=-1; } b=0; while(fg){ if(b>=basic_blocks) ierror(0); for(i=0;i<vcount-rcount;i++){ if(used[i]&&(BTST(fg->av_in,i)||BTST(fg->av_out,i))){ int r; BSET(used[i],b); for(r=1;r<=MAXR;r++) if(fg->regv[r]&&fg->regv[r]->index==i) BCLR(used[i],b); } } for(p=fg->start;p;p=p->next){ if((p->q1.flags&(VAR|REG))==VAR){ i=p->q1.v->index; if(i!=-1){ if(i<0||i>=vcount) ierror(0); if(i>=0&&used[i]){ BSET(used[i],b); } } } if((p->q2.flags&(VAR|REG))==VAR){ i=p->q2.v->index; if(i!=-1){ if(i<0||i>=vcount) ierror(0); if(i>=0&&used[i]){ BSET(used[i],b); } } } if((p->z.flags&(VAR|REG))==VAR){ i=p->z.v->index; if(i!=-1){ if(i<0||i>=vcount) ierror(0); if(i>=0&&used[i]){ BSET(used[i],b); } } } if(p==fg->end) break; } fg=fg->normalout; b++; } /* schauen, ob Variablen in gleichen Speicher koennen */ if(DEBUG&1024) printf("looking for distinct variables\n"); for(i=0;i<vcount-rcount;i++){ if(!used[i]||eqto[i]>=0) continue; if(!memcmp(used[i],empty,bsize)){ free(used[i]);used[i]=0;continue;} for(b=i+1;b<vcount-rcount;b++){ if(!used[b]||eqto[b]>=0) continue; if(!memcmp(used[b],empty,bsize)){ free(used[b]);used[b]=0;continue;} if(DEBUG&2048) printf("comparing %s(%p) and %s(%p)\n",vilist[i]->identifier,(void *)vilist[i],vilist[b]->identifier,(void *)vilist[b]); memcpy(tmp,used[i],bsize); bvintersect(tmp,used[b],bsize); if(!memcmp(tmp,empty,bsize)){ if(DEBUG&1024) printf("memory for %s(%p) and %s(%p) equal\n",vilist[i]->identifier,(void *)vilist[i],vilist[b]->identifier,(void *)vilist[b]); eqto[b]=i; if(!zmleq(al[b],al[i])) al[i]=al[b]; if(!zmleq(sz[b],sz[i])) sz[i]=sz[b]; bvunite(used[i],used[b],bsize); } } } if(DEBUG&1024) printf("final recalculating\n"); max_offset=recalc_start_offset; for(i=0;i<vcount-rcount;i++){ if(!used[i]) continue; free(used[i]); if(DEBUG&2048) printf("adjusting offset for %s,%ld\n",vilist[i]->identifier,zm2l(vilist[i]->offset)); if(eqto[i]>=0){ vilist[i]->offset=vilist[eqto[i]]->offset; continue; } vilist[i]->offset=zmmult(zmdiv(zmadd(max_offset,zmsub(al[i],l2zm(1L))),al[i]),al[i]); max_offset=zmadd(vilist[i]->offset,sz[i]); } recalc_start_offset=l2zm(0L); free(used); free(sz); free(al); free(tmp); free(empty); free(eqto); } void remove_IC_fg(struct flowgraph *g,struct IC *p) /* Entfernt IC p und beachtet Flussgraph. Ausserdem werden */ /* use/change-Listen freigegeben. */ { if(p->q1.am||p->q2.am||p->z.am) ierror(0); if(have_alias){ free(p->use_list); free(p->change_list); } if(g->start==g->end){ g->start=g->end=0; }else{ if(p==g->end) g->end=p->prev; if(p==g->start) g->start=p->next; } remove_IC(p); } /* allowed to create new variables */ int early_peephole(void) { struct IC *p; int changed,gchanged=0,c,t; do{ changed=0; p=first_ic; while(p){ c=p->code; t=p->typf; if(c==COMPARE&&(p->q2.flags&KONST)&&ISINT(p->typf)){ struct case_table *ct; if((ct=calc_case_table(p,JUMP_TABLE_DENSITY))&&ct->num>1&&ct->density==1){