blob: 6696f9549ea527dfece63b4f11a3ce7d899dfdfa [file] [log] [blame]
PulkoMandy17fc7592022-07-28 18:27:54 +02001/* $VER: vbcc (range.c) $Revision: 1.1 $ */
2/* range analysis and related optimizations */
3
4#include "opt.h"
5
6static char FILE_[]=__FILE__;
7
8
9#define RANGESIZE (sizeof(range)*(vcount+1))
10
11range *rangebuf;
12
13static 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
31void 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
54static 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
77static 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
109void 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
142static 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
157static 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
172static 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
183static 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
194void 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}