| /* $VER: vbcc (flow.c) $Revision: 1.13 $ */ |
| /* Generierung des FLussgraphs und Optimierungen des Kontrollflusses */ |
| |
| #include "opt.h" |
| |
| static char FILE_[]=__FILE__; |
| |
| int bvcmp(bvtype *dest,bvtype *src,size_t len) |
| /* vergleicht zwei Bitvektoren */ |
| { |
| len/=sizeof(bvtype); |
| for(;len>0;len--) |
| if(*dest++!=*src++) return(0); |
| return(1); |
| } |
| /* Schnittmenge nicht leer? */ |
| int bvdointersect(bvtype *p1,bvtype *p2,size_t len) |
| { |
| len/=sizeof(bvtype); |
| for(;len>0;len--) |
| if(*p1++&*p2++) |
| return 1; |
| return 0; |
| } |
| void bvunite(bvtype *dest,bvtype *src,size_t len) |
| /* berechnet Vereinigung zweier Bitvektoren */ |
| { |
| len/=sizeof(bvtype); |
| for(;len>0;len--) |
| *dest++|=*src++; |
| } |
| void bvintersect(bvtype *dest,bvtype *src,size_t len) |
| /* berechnet Durchschnitt zweier Bitvektoren */ |
| { |
| len/=sizeof(bvtype); |
| for(;len>0;len--) |
| *dest++&=*src++; |
| } |
| void bvdiff(bvtype *dest,bvtype *src,size_t len) |
| /* berechnet 'Differenz' zweier Bitvektoren */ |
| { |
| len/=sizeof(bvtype); |
| for(;len>0;len--) |
| *dest++&=~(*src++); |
| } |
| |
| unsigned int basic_blocks; |
| |
| flowgraph *new_flowgraph(void) |
| { |
| flowgraph *new; |
| new=mymalloc(sizeof(*new)); |
| new->av_in=new->av_out=new->av_gen=new->av_kill=0; |
| new->rd_in=new->rd_out=new->rd_gen=new->rd_kill=0; |
| new->ae_in=new->ae_out=new->ae_gen=new->ae_kill=0; |
| new->cp_in=new->cp_out=new->cp_gen=new->cp_kill=0; |
| new->pt=0; |
| new->start=new->end=0; |
| new->normalout=new->branchout=0; |
| new->in=0; |
| new->loopend=0; |
| #if ALEX_REG |
| new->loop_depth=0; |
| #endif |
| return new; |
| } |
| |
| flowgraph *construct_flowgraph(void) |
| /* entfernt ueberfluessige Labels und erzeugt Flussgraph */ |
| { |
| IC *p,*cl; |
| int firstl,lcnt,currentl,i,code,l; |
| int *iseq,*used; |
| flowgraph **lg,*g,*fg; |
| if(cross_module){ |
| int lastl; |
| firstl=0;lastl=0;lcnt=0; |
| for(p=first_ic;p;p=p->next){ |
| if(p->code==LABEL){ |
| if(p->typf<firstl) firstl=p->typf; |
| if(p->typf>lastl) lastl=p->typf; |
| } |
| } |
| lcnt=lastl-firstl+1; |
| }else{ |
| firstl=lastlabel; |
| lcnt=label-firstl; |
| } |
| return_label=0; |
| if(last_ic&&last_ic->code==LABEL) return_label=last_ic->typf; |
| if(last_ic&&last_ic->code==SETRETURN&&last_ic->prev&&last_ic->prev->code==LABEL) return_label=last_ic->prev->typf; |
| |
| iseq=mymalloc(lcnt*sizeof(int)); |
| used=mymalloc(lcnt*sizeof(int)); |
| lg=mymalloc(lcnt*sizeof(flowgraph *)); |
| g=new_flowgraph(); |
| fg=g; |
| g->start=first_ic;g->in=0;g->branchout=0;g->loopend=0; |
| |
| for(i=0;i<lcnt;i++) {iseq[i]=used[i]=0;lg[i]=0;} |
| currentl=0;firstl++; |
| /* Diese Schleife entfernt alle Labels, die mit anderen */ |
| /* uebereinstimmen, merkt sich das und kennzeichnet alle */ |
| /* Labels, die benutzt werden. */ |
| /* Ausserdem wird der Flussgraph teilweise aufgebaut. */ |
| if(DEBUG&1024) {puts("construct_flowgraph(): loop1");/*scanf("%d",&i);*/} |
| i=1;g->index=i; |
| for(p=first_ic;p;){ |
| code=p->code; |
| if(code>=BEQ&&code<=BRA){ |
| l=p->typf; |
| /* als used markieren; falls aequivalent, das erste markieren */ |
| if(iseq[l-firstl]) used[iseq[l-firstl]-firstl]=1; |
| else used[l-firstl]=1; |
| /* Flussgraph beenden und evtl. naechsten Knoten erzeugen */ |
| g->end=p; |
| if(p->next){ |
| g->normalout=new_flowgraph(); |
| g->normalout->in=mymalloc(sizeof(flowlist)); |
| g->normalout->in->next=0; |
| g->normalout->in->graph=g; |
| g=g->normalout; |
| g->start=p->next; |
| g->branchout=0; |
| g->loopend=0; |
| g->index=++i; |
| }else g->normalout=0; |
| |
| currentl=0;p=p->next;continue; |
| } |
| if(code==ALLOCREG||code==FREEREG){p=p->next; continue;} |
| if(code!=LABEL){currentl=0;p=p->next;continue;} |
| /* ist ein Label */ |
| l=p->typf; |
| if(currentl){ |
| IC *m; |
| iseq[l-firstl]=currentl; |
| if(l==return_label) return_label=currentl; |
| if(used[l-firstl]) used[currentl-firstl]=1; |
| cl->flags|=p->flags; |
| m=p;p=p->next; |
| remove_IC(m); |
| continue; |
| /* if(DEBUG&1024) printf("label %d==%d\n",l,iseq[l-firstl]);*/ |
| }else{ |
| currentl=l;cl=p; |
| if(g->start!=p){ |
| g->end=p->prev; |
| g->normalout=new_flowgraph(); |
| g->normalout->in=mymalloc(sizeof(flowlist)); |
| g->normalout->in->next=0; |
| g->normalout->in->graph=g; |
| g=g->normalout; |
| g->start=p; |
| g->branchout=0; |
| g->loopend=0; |
| g->index=++i; |
| }else g->branchout=0; |
| lg[l-firstl]=g; |
| } |
| p=p->next; |
| } |
| g->end=last_ic;g->normalout=g->branchout=0; |
| if(DEBUG&(16384|1024)) printf("%d basic blocks\n",i); |
| basic_blocks=i; |
| |
| /* if(DEBUG&1024) for(i=firstl;i<=lcnt;i++) printf("L%d used: %d\n",i,used[i-firstl]);*/ |
| /* Diese Schleife entfernt alle nicht benutzten Labels und biegt alle */ |
| /* Branches auf aequivalente Labels um. */ |
| if(DEBUG&1024) {puts("construct_flowgraph(): loop2");/*scanf("%d",&i);*/} |
| g=fg; |
| while(g){ |
| int flag=0;flowlist *lp; |
| /* printf("g=%p\n",(void *)g);*/ |
| g->av_in=g->av_out=g->av_gen=g->av_kill=0; |
| g->rd_in=g->rd_out=g->rd_gen=g->rd_kill=0; |
| g->ae_in=g->ae_out=g->ae_gen=g->ae_kill=0; |
| g->cp_in=g->cp_out=g->cp_gen=g->cp_kill=0; |
| g->pt=0; |
| p=g->start; |
| while(p&&!flag){ |
| /* pric2(stdout,p);*/ |
| code=p->code; |
| if(code>=BEQ&&code<=BRA){ |
| l=p->typf; |
| if(iseq[l-firstl]) p->typf=l=iseq[l-firstl]; |
| /* in Flussgraph eintragen */ |
| g->branchout=lg[l-firstl]; |
| if(!lg[l-firstl]) error(353); |
| lp=lg[l-firstl]->in; |
| /* das hier sollte man noch schoener machen */ |
| if(!lp){ |
| lg[l-firstl]->in=mymalloc(sizeof(flowlist)); |
| lg[l-firstl]->in->next=0; |
| lg[l-firstl]->in->graph=g; |
| }else{ |
| while(lp&&lp->next) lp=lp->next; |
| lp->next=mymalloc(sizeof(flowlist)); |
| lp->next->next=0; |
| lp->next->graph=g; |
| } |
| } |
| /* if(code==LABEL&&!used[p->typf-firstl]) remove_IC(p);*/ |
| if(p==g->end) flag=1; |
| p=p->next; |
| } |
| g=g->normalout; |
| } |
| /* Unbenutzte Labels entfernen und Bloecke verbinden */ |
| if(DEBUG&1024) {puts("construct_flowgraph(): loop3");/*scanf("%d",&i);*/} |
| for(g=fg;g;g=g->normalout){ |
| if(g->end&&(g->end->code<BEQ||g->end->code>BRA)){ |
| flowgraph *next=g->normalout;flowlist *lp; |
| if(next&&next->start&&next->start->code==LABEL&&!used[next->start->typf-firstl]){ |
| if(next->end!=next->start) g->end=next->end; |
| g->normalout=next->normalout; |
| g->branchout=next->branchout; |
| free(next->in); /* darf eigentlich nur einen Vorgaenger haben */ |
| /* in im Nachfolgeknoten auf den ersten der beiden setzen */ |
| if(next->normalout&&next->normalout->in) next->normalout->in->graph=g; |
| /* in im Ziel von next->branchout auf den ersten setzen */ |
| if(next->branchout){ |
| lp=next->branchout->in; |
| while(1){ |
| if(lp->graph==next){ lp->graph=g;break;} |
| lp=lp->next;if(!lp) ierror(0); |
| } |
| } |
| if(DEBUG&1024){ printf("unused label deleted:\n");pric2(stdout,next->start);} |
| remove_IC(next->start); |
| free(next); |
| } |
| } |
| /* unbenutzte Labels entfernen */ |
| if(g->start&&g->start->code==LABEL&&!used[g->start->typf-firstl]) |
| remove_IC_fg(g,g->start); |
| } |
| free(iseq); |
| free(used); |
| return(fg); |
| } |
| |
| void print_flowgraph(flowgraph *g) |
| /* Gibt Flussgraph auf Bildschirm aus */ |
| { |
| static int dontprint=0; |
| int flag,i;flowlist *lp;IC *ip; |
| if(dontprint>0) {dontprint--;return;} |
| if(dontprint!=-1){ |
| puts("print_flowgraph()");scanf("%d",&i); |
| if(i<-1){dontprint=-i;return;} |
| if(!i) return; |
| if(i==-1){dontprint=-1; i=1;} |
| }else{ |
| i=1; |
| } |
| while(g){ |
| printf("\nBasic Block nr. %d\n",g->index); |
| printf("\tin from "); |
| lp=g->in; |
| while(lp){if(lp->graph) printf("%d ",lp->graph->index);lp=lp->next;} |
| printf("\n\tout to %d %d\n",g->normalout?g->normalout->index:0,g->branchout?g->branchout->index:0); |
| if(g->loopend) printf("head of a loop ending at block %d\n",g->loopend->index); |
| if(!(optflags&32)&&g->pt) |
| ierror(0); |
| if(i&2){ |
| printf("av_gen:\n"); print_av(g->av_gen); |
| printf("av_kill:\n"); print_av(g->av_kill); |
| printf("av_in:\n"); print_av(g->av_in); |
| printf("av_out:\n"); print_av(g->av_out); |
| } |
| if(i&4){ |
| printf("rd_gen:\n"); print_rd(g->rd_gen); |
| printf("rd_kill:\n"); print_rd(g->rd_kill); |
| printf("rd_in:\n"); print_rd(g->rd_in); |
| printf("rd_out:\n"); print_rd(g->rd_out); |
| } |
| if(i&8){ |
| printf("ae_gen:\n"); print_ae(g->ae_gen); |
| printf("ae_kill:\n"); print_ae(g->ae_kill); |
| printf("ae_in:\n"); print_ae(g->ae_in); |
| printf("ae_out:\n"); print_ae(g->ae_out); |
| } |
| if(i&16){ |
| printf("cp_gen:\n"); print_cp(g->cp_gen); |
| printf("cp_kill:\n"); print_cp(g->cp_kill); |
| printf("cp_in:\n"); print_cp(g->cp_in); |
| printf("cp_out:\n"); print_cp(g->cp_out); |
| } |
| if(i&32){ |
| int r; |
| for(r=1;r<=MAXR;r++) |
| if(g->regv[r]) printf("(%s),%ld assigned to %s\n",g->regv[r]->identifier,(long)zm2l(g->regv[r]->offset),regnames[r]); |
| } |
| if(i&64){ |
| print_pt(g->pt); |
| } |
| flag=0;ip=g->start; |
| while(ip&&!flag){ |
| pric2(stdout,ip); |
| if(i&64){ |
| int r; |
| printf("changes: "); |
| for(r=0;r<ip->change_cnt;r++) |
| printf("(%s,%ld,%d,%d)",ip->change_list[r].v->identifier,(long)zm2l(ip->change_list[r].v->offset),ip->change_list[r].flags,ip->change_list[r].v->index); |
| printf("\nuses: "); |
| for(r=0;r<ip->use_cnt;r++) |
| printf("(%s,%ld,%d,%d)",ip->use_list[r].v->identifier,(long)zm2l(ip->use_list[r].v->offset),ip->use_list[r].flags,ip->use_list[r].v->index); |
| printf("\n"); |
| } |
| if(ip==g->end) flag=1; |
| ip=ip->next; |
| } |
| g=g->normalout; |
| } |
| printf("return_label=%d\n",return_label); |
| } |
| void free_flowgraph(flowgraph *g) |
| /* Gibt Flussgraph frei */ |
| { |
| flowgraph *pm;flowlist *lp,*lpm; |
| if(DEBUG&(16384|1024)) puts("free_flowgraph()"); |
| while(g){ |
| lp=g->in; |
| while(lp){ |
| lpm=lp->next; |
| free(lp); |
| lp=lpm; |
| } |
| free(g->av_in); |
| free(g->av_out); |
| free(g->av_gen); |
| free(g->av_kill); |
| free(g->rd_in); |
| free(g->rd_out); |
| free(g->rd_gen); |
| free(g->rd_kill); |
| free(g->ae_in); |
| free(g->ae_out); |
| free(g->ae_gen); |
| free(g->ae_kill); |
| free(g->cp_in); |
| free(g->cp_out); |
| free(g->cp_gen); |
| free(g->cp_kill); |
| free_pt(g->pt); |
| |
| pm=g->normalout; |
| free(g); |
| g=pm; |
| } |
| } |
| static void mark_reachable(flowgraph *fg) |
| /* negiert den index aller Bloecke, die reachable sind */ |
| { |
| fg->index=-fg->index; |
| if(fg->branchout&&fg->branchout->index>=0) |
| mark_reachable(fg->branchout); |
| if(fg->normalout&&(!fg->end||fg->end->code!=BRA)&&fg->normalout->index>=0) |
| mark_reachable(fg->normalout); |
| } |
| flowgraph *jump_optimization(void) |
| /* entfernt ueberfluessige Spruenge etc. */ |
| { |
| flowgraph *fg,*g;IC *p;int changed,i; |
| flowlist *lp; |
| do{ |
| changed=0; |
| fg=construct_flowgraph(); |
| mark_reachable(fg); |
| if(DEBUG&1024) {printf("jump_optimization() pass\n");print_flowgraph(fg);} |
| g=fg; |
| while(g){ |
| /* tote Bloecke entfernen */ |
| if(g->index<0){ |
| g->index=-g->index; |
| }else{ |
| IC *m; |
| if(DEBUG&1024) printf("deleting dead block %d\n",g->index); |
| #ifdef HAVE_MISRA |
| /* removed */ |
| #endif |
| p=g->start;i=0; |
| while(p&&!i){ |
| if(p==g->end) i=1; |
| if(DEBUG&1024) pric2(stdout,p); |
| m=p->next; |
| remove_IC_fg(g,p);changed=gchanged=1; |
| p=m; |
| } |
| if(g->branchout){ |
| /* Eintrag in Ziel loeschen (nur einmal, falls auch normalout) */ |
| lp=g->branchout->in; |
| while(lp){ |
| if(lp->graph==g){ lp->graph=0;break;} |
| lp=lp->next; |
| } |
| g->branchout=0; |
| } |
| g=g->normalout;continue; |
| } |
| /* Spruenge zum folgenden Code entfernen */ |
| if(g->normalout&&g->normalout==g->branchout){ |
| p=g->end; |
| if(!p||p->code<BEQ||p->code>BRA) ierror(0); |
| if(DEBUG&1024){printf("branch to following label deleted:\n");pric2(stdout,p);} |
| remove_IC_fg(g,p);g->branchout=0;changed=gchanged=1; |
| p=g->end; |
| /* vorangehenden Vergleich auch entfernen */ |
| if(p&&(p->code==COMPARE||p->code==TEST)){ |
| if(DEBUG&1024){printf("preceding comparison also deleted:\n");pric2(stdout,p);} |
| remove_IC_fg(g,p); |
| } |
| } |
| |
| /* bcc l1;bra l2;l1 aendern */ |
| p=g->end; |
| if(p&&p->code>=BEQ&&p->code<BRA&&g->normalout){ |
| if(g->normalout->start&&g->normalout->start->code==BRA){ |
| if(g->normalout->normalout==g->branchout){ |
| g->branchout=g->normalout->branchout; |
| i=p->typf; |
| p->typf=g->normalout->start->typf; |
| if(DEBUG&1024) printf("changing bcc l%d;bra l%d;l%d to b!cc l%d\n",i,p->typf,i,p->typf); |
| switch(p->code){ |
| case BEQ: p->code=BNE;break; |
| case BNE: p->code=BEQ;break; |
| case BLT: p->code=BGE;break; |
| case BGE: p->code=BLT;break; |
| case BGT: p->code=BLE;break; |
| case BLE: p->code=BGT;break; |
| } |
| g->normalout->branchout=g->normalout->normalout; |
| g->normalout->start->typf=i; |
| changed=gchanged=1; |
| } |
| } |
| } |
| /* Haben alle Vorgaenger eines Blocks die selbe Anweisung am */ |
| /* Blockende und keinen weiteren Nachfolger, dann kann die */ |
| /* Anweisung in den Nachfogerblock geschoben werden */ |
| i=0;p=0; |
| for(lp=g->in;lp;lp=lp->next){ |
| if(lp->graph){ |
| IC *np; |
| flowgraph *ng=lp->graph; |
| flowlist *l2; |
| /* doppelte Bloecke loeschen und ueberspringen */ |
| for(l2=g->in;l2;l2=l2->next) |
| if(l2!=lp&&l2->graph==ng) break; |
| if(l2){ lp->graph=0;continue;} |
| np=ng->end; |
| if(!np){ i=-1;break;} |
| if(ng->branchout&&(np->code!=BRA||ng->branchout!=g)){i=-1;break;} |
| if(np->code==BRA) np=np->prev; |
| if(!np){ i=-1;break;} |
| if(!p){ |
| i=1; |
| p=np; |
| }else{ |
| if(p->code==np->code&&p->typf==np->typf&& |
| p->code!=CALL&&p->code!=GETRETURN&&p->code!=PUSH&&(p->code<TEST||p->code>COMPARE)&& |
| !compare_objs(&p->q1,&np->q1,p->typf)&& |
| !compare_objs(&p->q2,&np->q2,p->typf)&& |
| !compare_objs(&p->z,&np->z,p->typf)){ |
| i++; |
| }else{ |
| i=-1; |
| break; |
| } |
| } |
| } |
| } |
| if(i>1&&g->start){ |
| IC *new=new_IC(); |
| if(DEBUG&1024){ printf("moving instruction from preceding blocks to successor:\n");pric2(stdout,p);} |
| changed=gchanged=1; |
| memcpy(new,p,ICS); |
| new->use_cnt=new->change_cnt=0; |
| new->use_list=new->change_list=0; |
| if(g->start->code==LABEL){ |
| insert_IC_fg(g,g->start,new); |
| }else{ |
| insert_IC_fg(g,g->start->prev,new); |
| } |
| for(lp=g->in;lp;lp=lp->next){ |
| flowgraph *ng=lp->graph; |
| if(ng){ |
| if(!ng->end) ierror(0); |
| if(ng->end->code==BRA){ |
| remove_IC_fg(ng,ng->end->prev); |
| }else{ |
| remove_IC_fg(ng,ng->end); |
| } |
| } |
| } |
| } |
| /* Haben alle Nachfolger eines Blocks die selbe Anweisung am */ |
| /* Blockbeginn und keinen weiteren Vorgaenger, dann kann die */ |
| /* Anweisung in den Vorgaengerblock geschoben werden */ |
| if(g->branchout&&g->normalout&&g->branchout!=g->normalout&&g->end&&g->end->code!=BRA){ |
| flowgraph *a=g->normalout,*b=g->branchout; |
| IC *as=a->start,*bs=b->start,*tp; |
| int destroys; |
| if(as&&as->code==LABEL&&as!=a->end) as=as->next; |
| if(bs&&bs->code==LABEL&&bs!=b->end) bs=bs->next; |
| |
| if(as&&bs&&as->code==bs->code&&as->code!=PUSH&&(as->code<TEST||as->code>COMPARE)&&as->typf==bs->typf&& |
| !compare_objs(&as->q1,&bs->q1,as->typf)&& |
| !compare_objs(&as->q2,&bs->q2,as->typf)&& |
| !compare_objs(&as->z,&bs->z,as->typf)){ |
| i=0; |
| for(lp=a->in;lp;lp=lp->next) |
| if(lp->graph&&lp->graph!=g&&(lp->graph->branchout==a||!lp->graph->end||lp->graph->end->code!=BRA)) i=1; |
| for(lp=b->in;lp;lp=lp->next) |
| if(lp->graph&&lp->graph!=g&&(lp->graph->branchout==b||!lp->graph->end||lp->graph->end->code!=BRA)) i=1; |
| if(as->code==CALL&&as->next&&(as->next->code==GETRETURN||as->code==NOP)) i=1; |
| if(bs->code==CALL&&bs->next&&(bs->next->code==GETRETURN||bs->code==NOP)) i=1; |
| if(!i){ |
| if(!(tp=g->end->prev)) ierror(0); |
| if(tp->code!=TEST&&tp->code!=COMPARE) |
| ierror(0); |
| /* schauen, ob die Anweisung eine evtl. TEST */ |
| /* oder COMPARE-Anweisung beeinflusst */ |
| destroys=0; |
| if(as->z.flags&DREFOBJ) destroys|=1; |
| if(as->code==CALL) destroys|=2; |
| if(tp->q1.flags&VAR){ |
| if(destroys&3){ |
| if((tp->q1.v->flags&USEDASADR)|| |
| (tp->q1.flags&DREFOBJ)|| |
| (tp->q1.v->storage_class==EXTERN)|| |
| (tp->q1.v->nesting==0)) |
| i=1; |
| if((destroys&2)&&tp->q1.v->storage_class==STATIC) |
| i=1; |
| } |
| if((as->z.flags&VAR)&&as->z.v==tp->q1.v) |
| i=1; |
| } |
| if(tp->q2.flags&VAR){ |
| if(destroys&3){ |
| if((tp->q2.v->flags&USEDASADR)|| |
| (tp->q2.flags&DREFOBJ)|| |
| (tp->q2.v->storage_class==EXTERN)|| |
| (tp->q2.v->nesting==0)) |
| i=1; |
| if((destroys&2)&&tp->q2.v->storage_class==STATIC) |
| i=1; |
| } |
| if((as->z.flags&VAR)&&as->z.v==tp->q2.v) |
| i=1; |
| } |
| if(!i&&!(disable&2)){ |
| if(DEBUG&1024){ printf("moving instruction from following blocks to predecessor:\n");pric2(stdout,as);} |
| p=new_IC(); |
| memcpy(p,as,ICS); |
| remove_IC_fg(a,as); |
| remove_IC_fg(b,bs); |
| p->use_cnt=p->change_cnt=0; |
| p->use_list=p->change_list=0; |
| insert_IC_fg(g,g->end->prev->prev,p); |
| changed=gchanged=1; |
| } |
| } |
| } |
| } |
| g=g->normalout; |
| } |
| g=fg; |
| while(g){ |
| /* Spruenge zu Spruengen umsetzen; einige Zeiger im Flussgraph */ |
| /* werden nicht korrekt aktualisiert, aber das sollte egal sein*/ |
| p=g->start; |
| for(i=0;i<2;i++){ |
| if(i){if(p&&p->code==LABEL) p=p->next; else break;} |
| if(p&&p->code>=BEQ&&p->code<=BRA){ |
| lp=g->in; |
| while(lp){ |
| if(lp->graph&&lp->graph->branchout==g&&(/*lp->graph->end->code==p->code||*/p->code==BRA)&&lp->graph->end->typf!=p->typf){ |
| if(DEBUG&1024){printf("branch bypassed to L%d:\n",p->typf);pric2(stdout,lp->graph->end);} |
| if(lp->graph->end->code<BEQ||lp->graph->end->code>BRA) ierror(0); |
| lp->graph->branchout=g->branchout; |
| lp->graph->end->typf=p->typf;changed=gchanged=1; |
| } |
| lp=lp->next; |
| } |
| } |
| } |
| |
| |
| g=g->normalout; |
| } |
| if(changed) free_flowgraph(fg); |
| }while(changed); |
| return fg; |
| } |
| |
| void insert_IC_fg(flowgraph *fg,IC *p,IC *new) |
| /* fuegt ein IC hinter p ein unter Beibehaltung des Flussgraphen */ |
| { |
| if(fg->start){ |
| if(!p||p==fg->start->prev) fg->start=new; |
| if(p==fg->end) fg->end=new; |
| }else{ |
| fg->start=fg->end=new; |
| } |
| insert_IC(p,new); |
| } |