PulkoMandy | 17fc759 | 2022-07-28 18:27:54 +0200 | [diff] [blame] | 1 | /* $VER: vbcc (range.c) $Revision: 1.1 $ */ |
| 2 | /* range analysis and related optimizations */ |
| 3 | |
| 4 | #include "opt.h" |
| 5 | |
| 6 | static char FILE_[]=__FILE__; |
| 7 | |
| 8 | |
| 9 | #define RANGESIZE (sizeof(range)*(vcount+1)) |
| 10 | |
| 11 | range *rangebuf; |
| 12 | |
| 13 | static void clear_range(range *p,int i) |
| 14 | { |
| 15 | Var *v; |
| 16 | int t; |
| 17 | |
| 18 | v=vilist[i]; |
| 19 | t=v->vtyp->flags; |
| 20 | if(ISINT(t)){ |
| 21 | if(t&UNSIGNED){ |
| 22 | p[i].min.vumax=Z0; |
| 23 | p[i].max.vumax=tu_max[t&NQ]; |
| 24 | }else{ |
| 25 | p[i].min.vmax=t_min[t&NQ]; |
| 26 | p[i].max.vmax=t_max[t&NQ]; |
| 27 | } |
| 28 | } |
| 29 | } |
| 30 | |
| 31 | void print_ranges(FILE *f,range *p) |
| 32 | { |
| 33 | int i,t; |
| 34 | Var *v; |
| 35 | for(i=0;i<vcount-rcount;i++){ |
| 36 | v=vilist[i]; |
| 37 | t=v->vtyp->flags; |
| 38 | if(ISINT(t)){ |
| 39 | fprintf(f,"%03d %s (%p): ",i,v->identifier,v); |
| 40 | if(t&UNSIGNED){ |
| 41 | printzum(f,p[i].min.vumax); |
| 42 | fprintf(f,"..."); |
| 43 | printzum(f,p[i].max.vumax); |
| 44 | }else{ |
| 45 | printzm(f,p[i].min.vmax); |
| 46 | fprintf(f,"..."); |
| 47 | printzm(f,p[i].max.vmax); |
| 48 | } |
| 49 | fprintf(f,"\n"); |
| 50 | } |
| 51 | } |
| 52 | } |
| 53 | |
| 54 | static void combine_ranges(range *d,range *n) |
| 55 | { |
| 56 | int i,t; |
| 57 | Var *v; |
| 58 | for(i=0;i<vcount-rcount;i++){ |
| 59 | v=vilist[i]; |
| 60 | t=v->vtyp->flags; |
| 61 | if(ISINT(t)){ |
| 62 | if(t&UNSIGNED){ |
| 63 | if(zumleq(n[i].min.vumax,d[i].min.vumax)) |
| 64 | d[i].min.vumax=n[i].min.vumax; |
| 65 | if(zumleq(d[i].max.vumax,n[i].max.vumax)) |
| 66 | d[i].max.vumax=n[i].max.vumax; |
| 67 | }else{ |
| 68 | if(zmleq(n[i].min.vmax,d[i].min.vmax)) |
| 69 | d[i].min.vmax=n[i].min.vmax; |
| 70 | if(zmleq(d[i].max.vmax,n[i].max.vmax)) |
| 71 | d[i].max.vmax=n[i].max.vmax; |
| 72 | } |
| 73 | } |
| 74 | } |
| 75 | } |
| 76 | |
| 77 | static int update_ranges(range *d,range *n) |
| 78 | { |
| 79 | int i,t,change=0; |
| 80 | Var *v; |
| 81 | for(i=0;i<vcount-rcount;i++){ |
| 82 | v=vilist[i]; |
| 83 | t=v->vtyp->flags; |
| 84 | if(ISINT(t)){ |
| 85 | if(t&UNSIGNED){ |
| 86 | if(!zumeqto(n[i].min.vumax,d[i].min.vumax)){ |
| 87 | d[i].min.vumax=n[i].min.vumax; |
| 88 | change=1; |
| 89 | } |
| 90 | if(!zumeqto(d[i].max.vumax,n[i].max.vumax)){ |
| 91 | d[i].max.vumax=n[i].max.vumax; |
| 92 | change=1; |
| 93 | } |
| 94 | }else{ |
| 95 | if(!zmeqto(n[i].min.vmax,d[i].min.vmax)){ |
| 96 | d[i].min.vmax=n[i].min.vmax; |
| 97 | change=1; |
| 98 | } |
| 99 | if(!zmeqto(d[i].max.vmax,n[i].max.vmax)){ |
| 100 | d[i].max.vmax=n[i].max.vmax; |
| 101 | change=1; |
| 102 | } |
| 103 | } |
| 104 | } |
| 105 | } |
| 106 | return change; |
| 107 | } |
| 108 | |
| 109 | void do_ranges(range *d,IC *p) |
| 110 | { |
| 111 | int i,j,t,c=p->code; |
| 112 | if((p->z.flags&(VAR|DREFOBJ))==VAR){ |
| 113 | i=p->z.v->index; |
| 114 | t=p->z.v->vtyp->flags; |
| 115 | if(c==ASSIGN){ |
| 116 | if((p->typf&NU)!=(t&NU)){ |
| 117 | clear_range(d,i); |
| 118 | }else if((p->q1.flags&(KONST|DREFOBJ))==KONST){ |
| 119 | eval_const(&p->q1.val,t); |
| 120 | if(t&UNSIGNED) |
| 121 | d[i].min.vumax=d[i].max.vumax=vumax; |
| 122 | else |
| 123 | d[i].min.vmax=d[i].max.vmax=vmax; |
| 124 | }else if((p->q1.flags&(VAR|DREFOBJ))==VAR&&(p->q1.v->vtyp->flags&NU)==(t&NU)){ |
| 125 | j=p->q1.v->index; |
| 126 | d[i].min=d[j].min; |
| 127 | d[i].max=d[j].max; |
| 128 | }else |
| 129 | clear_range(d,i); |
| 130 | }else{ |
| 131 | clear_range(d,i); |
| 132 | } |
| 133 | }else{ |
| 134 | j=p->change_cnt; |
| 135 | for(i=0;i<j;i++){ |
| 136 | if(!(p->change_list[i].flags&DREFOBJ)) |
| 137 | clear_range(d,p->change_list[i].v->index); |
| 138 | } |
| 139 | } |
| 140 | } |
| 141 | |
| 142 | static void insert_max(range *p,int t) |
| 143 | { |
| 144 | if(t&UNSIGNED){ |
| 145 | if(!zumleq(p->max.vumax,vumax)) |
| 146 | p->max.vumax=vumax; |
| 147 | if(!zumleq(p->min.vumax,p->max.vumax)) |
| 148 | p->min.vumax=vumax; |
| 149 | }else{ |
| 150 | if(!zmleq(p->max.vmax,vmax)) |
| 151 | p->max.vmax=vmax; |
| 152 | if(!zmleq(p->min.vmax,p->max.vmax)) |
| 153 | p->min.vmax=vmax; |
| 154 | } |
| 155 | } |
| 156 | |
| 157 | static void insert_min(range *p,int t) |
| 158 | { |
| 159 | if(t&UNSIGNED){ |
| 160 | if(!zumleq(vumax,p->min.vumax)) |
| 161 | p->min.vumax=vumax; |
| 162 | if(!zumleq(p->min.vumax,p->max.vumax)) |
| 163 | p->max.vumax=vumax; |
| 164 | }else{ |
| 165 | if(!zmleq(vmax,p->min.vmax)) |
| 166 | p->min.vmax=vmax; |
| 167 | if(!zmleq(p->min.vmax,p->max.vmax)) |
| 168 | p->max.vmax=vmax; |
| 169 | } |
| 170 | } |
| 171 | |
| 172 | static void inc_val(int t) |
| 173 | { |
| 174 | if(t&UNSIGNED){ |
| 175 | if(!zumeqto(vumax,tu_max[t&NU])) |
| 176 | vumax=zumadd(vumax,ZU1); |
| 177 | }else{ |
| 178 | if(!zmeqto(vmax,t_max[t&NU])) |
| 179 | vmax=zmadd(vmax,Z1); |
| 180 | } |
| 181 | } |
| 182 | |
| 183 | static void dec_val(int t) |
| 184 | { |
| 185 | if(t&UNSIGNED){ |
| 186 | if(!zumeqto(vumax,ZU0)) |
| 187 | vumax=zumsub(vumax,ZU1); |
| 188 | }else{ |
| 189 | if(!zmeqto(vmax,t_min[t&NU])) |
| 190 | vmax=zmsub(vmax,Z1); |
| 191 | } |
| 192 | } |
| 193 | |
| 194 | void range_analysis(flowgraph *fg) |
| 195 | { |
| 196 | flowgraph *g; |
| 197 | range *bp,*erange,*crange; |
| 198 | Var *v; |
| 199 | int i,t,done,pass; |
| 200 | rangebuf=mymalloc(RANGESIZE*(2*basic_blocks+3)); |
| 201 | bp=rangebuf; |
| 202 | for(i=0;i<vcount-rcount;i++) |
| 203 | clear_range(bp,i); |
| 204 | erange=bp; |
| 205 | bp+=RANGESIZE; |
| 206 | for(g=fg;g;g=g->normalout){ |
| 207 | g->ra_normalout=bp; |
| 208 | memcpy(bp,erange,RANGESIZE); |
| 209 | bp+=RANGESIZE; |
| 210 | g->ra_branchout=bp; |
| 211 | memcpy(bp,erange,RANGESIZE); |
| 212 | bp+=RANGESIZE; |
| 213 | } |
| 214 | crange=bp; |
| 215 | |
| 216 | pass=1; |
| 217 | do{ |
| 218 | if(DEBUG&1024) printf("range analysis pass %d\n",pass); |
| 219 | done=1; |
| 220 | for(g=fg;g;g=g->normalout){ |
| 221 | flowlist *lp; |
| 222 | IC *p; |
| 223 | int c,first=1; |
| 224 | memcpy(crange,erange,RANGESIZE); |
| 225 | for(lp=g->in;lp;lp=lp->next){ |
| 226 | if(lp->graph->normalout==g&&(!lp->graph->end||lp->graph->end->code!=BRA)){ |
| 227 | if(first){ |
| 228 | memcpy(crange,lp->graph->ra_normalout,RANGESIZE); |
| 229 | first=0; |
| 230 | }else |
| 231 | combine_ranges(crange,lp->graph->ra_normalout); |
| 232 | } |
| 233 | if(lp->graph->branchout==g){ |
| 234 | if(first) { |
| 235 | memcpy(crange,lp->graph->ra_branchout,RANGESIZE); |
| 236 | first=0; |
| 237 | }else |
| 238 | combine_ranges(crange,lp->graph->ra_branchout); |
| 239 | } |
| 240 | } |
| 241 | if(DEBUG&131072){ |
| 242 | printf("block %d, input:\n",g->index); |
| 243 | print_ranges(stdout,crange); |
| 244 | } |
| 245 | for(p=g->start;p;p=p->next){ |
| 246 | do_ranges(crange,p); |
| 247 | if(p==g->end||p->code==TEST||p->code==COMPARE) break; |
| 248 | } |
| 249 | if(p) c=p->code; else c=0; |
| 250 | if(c==COMPARE||c==TEST){ |
| 251 | if((p->q1.flags&(VAR|DREFOBJ))==VAR&&(c==TEST||(p->q2.flags&(KONST|DREFOBJ))==KONST)){ |
| 252 | IC *b=p->next; |
| 253 | range tmp; |
| 254 | while(b&&b->code<BEQ||b->code>BGT) b=b->next; |
| 255 | if(!b) ierror(0); |
| 256 | if(c==TEST){ |
| 257 | vmax=Z0; |
| 258 | vumax=ZU0; |
| 259 | }else |
| 260 | eval_const(&p->q2.val,p->typf); |
| 261 | i=p->q1.v->index; |
| 262 | t=p->q1.v->vtyp->flags; |
| 263 | if(b->code==BEQ){ |
| 264 | if(update_ranges(g->ra_normalout,crange)) done=0; |
| 265 | if(t&UNSIGNED) |
| 266 | crange[i].min.vumax=crange[i].max.vumax=vumax; |
| 267 | else |
| 268 | crange[i].min.vmax=crange[i].max.vmax=vmax; |
| 269 | if(update_ranges(g->ra_branchout,crange)) done=0; |
| 270 | }else if(b->code==BNE){ |
| 271 | if(update_ranges(g->ra_branchout,crange)) done=0; |
| 272 | if(t&UNSIGNED) |
| 273 | crange[i].min.vumax=crange[i].min.vumax=vumax; |
| 274 | else |
| 275 | crange[i].max.vumax=crange[i].max.vumax=vumax; |
| 276 | if(update_ranges(g->ra_normalout,crange)) done=0; |
| 277 | }else if(b->code==BLT||b->code==BLE){ |
| 278 | tmp=crange[i]; |
| 279 | if(b->code==BLT) dec_val(t); |
| 280 | insert_max(&crange[i],t); |
| 281 | if(update_ranges(g->ra_branchout,crange)) done=0; |
| 282 | crange[i]=tmp; |
| 283 | inc_val(t); |
| 284 | insert_min(&crange[i],t); |
| 285 | if(update_ranges(g->ra_normalout,crange)) done=0; |
| 286 | }else if(b->code==BGE||b->code==BGT){ |
| 287 | tmp=crange[i]; |
| 288 | if(b->code==BGT) inc_val(t); |
| 289 | insert_min(&crange[i],t); |
| 290 | if(update_ranges(g->ra_branchout,crange)) done=0; |
| 291 | crange[i]=tmp; |
| 292 | dec_val(t); |
| 293 | insert_max(&crange[i],t); |
| 294 | if(update_ranges(g->ra_normalout,crange)) done=0; |
| 295 | }else |
| 296 | ierror(0); |
| 297 | }else{ |
| 298 | if(update_ranges(g->ra_branchout,crange)) done=0; |
| 299 | if(update_ranges(g->ra_normalout,crange)) done=0; |
| 300 | } |
| 301 | }else{ |
| 302 | if(g->branchout){ |
| 303 | /* must be BRA as we checked for COMPARE/TEST above */ |
| 304 | if(update_ranges(g->ra_branchout,crange)) |
| 305 | done=0; |
| 306 | }else{ |
| 307 | if(update_ranges(g->ra_normalout,crange)) |
| 308 | done=0; |
| 309 | } |
| 310 | } |
| 311 | if(DEBUG&131072){ |
| 312 | printf("ra_branchout:\n"); |
| 313 | print_ranges(stdout,g->ra_branchout); |
| 314 | printf("ra_normalout:\n"); |
| 315 | print_ranges(stdout,g->ra_normalout); |
| 316 | } |
| 317 | } |
| 318 | pass++; |
| 319 | }while(!done); |
| 320 | |
| 321 | |
| 322 | } |