/* $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;i<vcount-rcount;i++){ if(vilist[i]->vtyp->flags&VOLATILE) BSET(changed_vars,i); if(i<rcount){ if(!vilist[i]->vtyp->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;j<p->change_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;k<p->use_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);}
/* $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;i<vcount-rcount;i++){
if(vilist[i]->vtyp->flags&VOLATILE) BSET(changed_vars,i);
if(i<rcount){
if(!vilist[i]->vtyp->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;j<p->change_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;k<p->use_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);
}