/* $VER: vbcc (loop.c) V0.8 */ /* schleifenorientierte Optimierungen */ #include "opt.h" static char FILE_[]=__FILE__; #define MOVE_IC 1 #define MOVE_COMP 2 /* Liste, in die ICs eingetragen werden, die aus Schleifen */ /* gezogen werden sollen. */ struct movlist{ struct movlist *next; struct IC *IC; struct flowgraph *target_fg; int flags; }; struct movlist *first_mov,*last_mov; int report_weird_code,report_suspicious_loops; /* Bitvektoren fuer schleifeninvariante ICs */ bvtype *invariant,*inloop,*moved,*moved_completely; bvtype *fg_tmp; bvtype *not_movable; size_t bsize; /* Liste, in die ICs fuer strength-reduction eingetragen */ /* werden. */ struct srlist{ struct srlist *next; struct IC *ind_var; struct IC *IC; struct flowgraph *target_fg; /* Hilfsvariable, falls eine aequivalente Operation schon reduziert */ /* wurde. */ struct Var *hv; }; struct srlist *first_sr,*last_sr; /* Liste, in die Daten fuer loop-unrolling eingetragen werden. */ struct urlist{ int flags; long total,unroll; struct IC *cmp,*branch,*ind; struct flowgraph *start,*head; struct urlist *next; } *first_ur; #define UNROLL_COMPLETELY 1 #define UNROLL_MODULO 2 #define UNROLL_INVARIANT 4 #define UNROLL_REVERSE 8 #define IND_ONLY_COUNTS 16 #define MULTIPLE_EXITS 32 /* Hier werden Induktionsvariablen vermerkt */ struct IC **ind_vars; static struct flowgraph *first_fg; void calc_movable(struct flowgraph *start,struct flowgraph *end) /* Berechnet, welche Definitionen nicht aus der Schleife start-end */ /* verschoben werden duerfen. Eine Def. p von z darf nur verschoben */ /* werden, wenn keine andere Def. von p existiert und alle */ /* Verwendungen von z nur von p erreicht werden. */ /* Benutzt rd_defs. */ { struct flowgraph *g;struct IC *p; int i,j,k,d; bvtype *changed_vars; if(DEBUG&1024) printf("calculating not_movable for blocks %d to %d\n",start->index,end->index); if(0/*!(optflags&1024)*/){ memset(not_movable,UCHAR_MAX,dsize); return; } memset(not_movable,0,dsize); changed_vars=mymalloc(vsize); memset(changed_vars,0,vsize); for(i=0;ivtyp->flags&VOLATILE) BSET(changed_vars,i); if(ivtyp->next||(vilist[i]->vtyp->next->flags&VOLATILE)) BSET(changed_vars,i+vcount-rcount); } } for(g=start;g;g=g->normalout){ if(!g->rd_in) ierror(0); memcpy(rd_defs,g->rd_in,dsize); for(p=g->start;p;p=p->next){ for(j=0;jchange_cnt;j++){ i=p->change_list[j].v->index; if(p->change_list[j].flags&DREFOBJ) i+=vcount-rcount; if(i>=vcount) continue; if(BTST(changed_vars,i)||(q1typ(p)&VOLATILE)||(q2typ(p)&VOLATILE)||(ztyp(p)&VOLATILE)){ bvunite(not_movable,var_defs[i],dsize); }else{ BSET(changed_vars,i); } } for(k=0;kuse_cnt;k++){ i=p->use_list[k].v->index; if(p->use_list[k].flags&DREFOBJ) i+=vcount-rcount; if(i>=vcount) continue; for(d=-1,j=1;j<=dcount;j++){ if(BTST(rd_defs,j)&&BTST(var_defs[i],j)){ if(d>=0){ /* mehr als eine Def. */ bvunite(not_movable,var_defs[i],dsize); d=-1;break; }else d=j; } if(BTST(rd_defs,UNDEF(j))&&BTST(var_defs[i],UNDEF(j))){ bvunite(not_movable,var_defs[i],dsize); d=-1;break; } } } /* Das hier, um rd_defs zu aktualisieren. */ rd_change(p); if(p==g->end) break; } if(g==end) break; } free(changed_vars); }