blob: c3cec77c7f9de5e16c16b93d2a8cda61507d8d26 [file] [log] [blame]
PulkoMandy17fc7592022-07-28 18:27:54 +02001/* $VER: vbcc (opt.c) $Revision: 1.52 $ */
2/* allgemeine Routinen fuer den Optimizer und Steuerung der einzelnen */
3/* Laeufe */
4
5#include "opt.h"
6#include "vbc.h"
7
8static char FILE_[]=__FILE__;
9
10/* die naechsten Funktionen sollten evtl. in ic.c */
11
12/* Sind use/change-Listen initialisiert? */
13int have_alias;
14
15int static_cse=1,dref_cse=1;
16int no_eff_ics,early_eff_ics;
17
18#ifdef ALEX_REG
19extern flowgraph *pFg;
20#endif
21
22void insert_IC(IC *p,IC *new)
23/* fuegt new hinter p ein; p darf 0 sein */
24{
25 if((new->code==ADDI2P||new->code==SUBIFP||new->code==SUBPFP)&&!ISPOINTER(new->typf2))
26 ierror(0);
27 new->prev=p;
28 if(p){
29 new->next=p->next; p->next=new;
30 }else{
31 new->next=first_ic; first_ic=new;
32 }
33 if(new->next)
34 new->next->prev=new;
35 else
36 last_ic=new;
37 new->q1.am=new->q2.am=new->z.am=0;
38}
39
40#ifndef NO_OPTIMIZER
41
42int gchanged; /* Merker, ob Optimierungslauf etwas geaendert hat */
43int norek; /* diese Funktion wird nicht rekursiv auf */
44int nocall; /* diese Funktion kehrt nicht zum Caller zurueck */
45
46void fix_shortop(flowgraph *fg,IC *p)
47{
48 if((p->typf&NQ)<INT&&!shortcut(p->code,p->typf)){
49 static type ta;
50 type *t;
51 IC *new;
52 if(DEBUG&1024){puts("fix shortop");pric2(stdout,p);puts("to;");}
53 ta.flags=int_erw(p->typf);
54 t=arith_typ(&ta,&ta);
55 new=new_IC();
56 new->code=CONVERT;
57 new->q1=p->q1;
58 new->z.flags=VAR;
59 new->z.v=add_tmp_var(clone_typ(t));
60 new->typf2=p->typf|UNSIGNED;
61 new->typf=t->flags|UNSIGNED;
62 p->q1=new->z;
63 insert_IC_fg(fg,p->prev,new);
64 new=new_IC();
65 new->code=CONVERT;
66 new->q1=p->q2;
67 new->z.flags=VAR;
68 new->z.v=add_tmp_var(clone_typ(t));
69 new->typf2=p->typf|UNSIGNED;
70 new->typf=t->flags|UNSIGNED;
71 p->q2=new->z;
72 insert_IC_fg(fg,p->prev,new);
73 new=new_IC();
74 new->code=CONVERT;
75 new->z=p->z;
76 new->q1.flags=VAR;
77 new->q1.v=add_tmp_var(t);
78 new->typf=p->typf|UNSIGNED;
79 new->typf2=t->flags|UNSIGNED;
80 p->z=new->q1;
81 insert_IC_fg(fg,p,new);
82 p->typf=t->flags|UNSIGNED;
83 if(DEBUG&1024){
84 pric2(stdout,p->prev->prev);
85 pric2(stdout,p->prev);
86 pric2(stdout,p);
87 pric2(stdout,p->next);
88 }
89 }
90}
91
92#if HAVE_LIBCALLS
93extern np gen_libcall(char *fname,np arg1,type *t1,np arg2,type *t2);
94
95
96/* insert libcalls just before register allocation */
97static int insert_libcalls(flowgraph *fg)
98{
99 IC *p,*next,*add;
100 int replaced=0;
101 static node n,nl,nr;
102 static type t,tl,tr;
103 if(DEBUG&1024) printf("insert_libcalls\n");
104 while(fg){
105 for(p=fg->start;p;p=next){
106 int c=p->code,end=0;
107 char *libname;
108 next=p->next;
109 if((c>=OR&&c<=AND)||(c>=LSHIFT&&c<=KOMPLEMENT)||c==COMPARE||c==CONVERT||c==MINUS||c==TEST){
110 if(libname=use_libcall(c,p->typf,p->typf2)){
111 IC *merk_first,*merk_last;
112 static node n1,n2;
113 static type t1,t2;
114 if(DEBUG&1024){
115 printf("converting IC to libcall:\n");
116 pric2(stdout,p);
117 }
118#if FIXED_SP
119 {
120 /* move nested pushs */
121 IC *m;flowgraph *g=fg;int fd=0,i;
122 for(i=0;i<p->arg_cnt;i++){
123 m=p->arg_list[i];
124 if(m->code==PUSH){
125 Var *v;type *t;IC *new;
126 fd=1;
127 if(DEBUG&1024){
128 printf("moving push\n");
129 pric2(stdout,m);
130 }
131 if((m->typf&NQ)==STRUCT) ierror(0);
132 if((m->typf&NQ)==CHAR&&!zmeqto(m->q2.val.vmax,Z1)) ierror(0);
133 t=new_typ();
134 t->flags=m->typf;
135 v=add_tmp_var(t);
136 new=new_IC();
137 new->code=PUSH;
138 new->q2.val.vmax=m->q2.val.vmax;
139 new->typf=m->typf;
140 new->q1.flags=VAR;
141 new->q1.v=v;
142 new->q1.val.vmax=Z0;
143 m->z=new->q1;
144 m->code=ASSIGN;
145 insert_IC_fg(g,p,new);
146 if(DEBUG&1024){
147 pric2(stdout,m);
148 pric2(stdout,new);
149 }
150 p->arg_list[i]=new;
151 }
152 }
153 }
154#endif
155 replaced=1;
156 merk_last=last_ic;
157 merk_first=first_ic;
158 first_ic=last_ic=0;
159 n1.flags=REINTERPRET;
160 n1.o=p->q1;
161 n1.ntyp=&t1;
162 t1.flags=q1typ(p);
163 if(p->q2.flags){
164 n2.flags=REINTERPRET;
165 n2.o=p->q2;
166 n2.ntyp=&t2;
167 t2.flags=q2typ(p);
168 gen_libcall(libname,&n1,&t1,&n2,&t2);
169 }else
170 gen_libcall(libname,&n1,&t1,0,0);
171 if(!last_ic||last_ic->code!=GETRETURN) ierror(0);
172 last_ic->z=p->z;
173 add=first_ic;
174 last_ic=merk_last;
175 first_ic=merk_first;
176 for(;add;add=next){
177 next=add->next;
178 insert_IC_fg(fg,p->prev,add);
179 }
180 next=p->next;
181 if(fg->end==p) end=1;
182 if(p->z.flags){
183 remove_IC_fg(fg,p);
184 }else{
185 type *t=new_typ();
186 t->flags=LIBCALL_CMPTYPE;
187 p->code=COMPARE;
188 p->q2.flags=KONST;
189 gval.vmax=Z0;
190 eval_const(&gval,MAXINT);
191 insert_const(&p->q2.val,LIBCALL_CMPTYPE);
192 p->typf=LIBCALL_CMPTYPE;
193 p->q1.flags=VAR;
194 p->q1.v=add_tmp_var(t);
195 p->q1.val.vmax=l2zm(0L);
196 p->prev->z=p->q1;
197 p->z.flags=0;
198 }
199 }
200 }
201 if(end||p==fg->end) break;
202 }
203 fg=fg->normalout;
204 }
205 return replaced;
206}
207#endif
208
209/* temporary fuer verschiedene Bitvektoren */
210bvtype *tmp;
211
212int in_varlist(varlist *vl,int cnt,Var *v,int flags)
213{
214 int i;
215 /*FIXME: slow */
216 for(i=0;i<cnt;i++){
217 if(vl[i].v==v&&vl[i].flags==flags) return 1;
218 }
219 return 0;
220}
221
222static void add_call_list(void)
223{
224 IC *p;
225 for(p=first_ic;p;p=p->next){
226 if(p->code==CALL&&p->call_cnt==0){
227 if((p->q1.flags&(VAR|DREFOBJ))==VAR){
228 p->call_cnt=1;
229 p->call_list=mymalloc(sizeof(*p->call_list));
230 p->call_list[0].v=p->q1.v;
231 p->call_list[0].flags=0;
232 }
233 }
234 }
235}
236
237void calc_finfo(Var *v,int flags)
238{
239 IC *p;int i,known,maxtyp,t,c;
240 /* 128 types should be enough for everyone :-) */
241 #define TSIZE BVSIZE(128)
242 static bvtype tf[TSIZE];
243 if(!v->fi) ierror(0);
244 if(flags&CALC_USES){
245 if(v->fi->flags&ALL_USES) return;
246 free(v->fi->use_list);
247 v->fi->use_cnt=0;
248 v->fi->use_list=0;
249 memset(tf,0,TSIZE);
250 known=1;maxtyp=-1;
251 for(p=first_ic;p;p=p->next){
252 c=p->code;
253 if(p->q1.flags&DREFOBJ){
254 t=(q1typ(p)&NQ);
255 if(t>maxtyp) maxtyp=t;
256 BSET(tf,t);
257 }
258 if(p->q2.flags&DREFOBJ){
259 t=(q2typ(p)&NQ);
260 if(t>maxtyp) maxtyp=t;
261 BSET(tf,t);
262 }
263 if(c==CALL){
264 if((p->q1.flags&(VAR|DREFOBJ))!=VAR||!p->q1.v->fi||!(p->q1.v->fi->flags&ALL_USES)){
265 free(v->fi->use_list);
266 v->fi->use_cnt=0;
267 v->fi->use_list=0;
268 known=0;
269 break;
270 }else{
271 for(i=0;i<p->q1.v->fi->use_cnt;i++){
272 if(p->q1.v->fi->use_list[i].v){
273 if(!in_varlist(v->fi->use_list,v->fi->use_cnt,p->q1.v->fi->use_list[i].v,p->q1.v->fi->use_list[i].flags)){
274 v->fi->use_cnt++;
275 v->fi->use_list=myrealloc(v->fi->use_list,v->fi->use_cnt*sizeof(varlist));
276 v->fi->use_list[v->fi->use_cnt-1]=p->q1.v->fi->use_list[i];
277 }
278 }else{
279 BSET(tf,p->q1.v->fi->use_list[i].flags&NQ);
280 }
281 }
282 }
283 }else{
284 for(i=0;i<p->use_cnt;i++){
285 if(p->use_list[i].v->nesting!=0) continue;
286 if(!in_varlist(v->fi->use_list,v->fi->use_cnt,p->use_list[i].v,p->use_list[i].flags)){
287 v->fi->use_cnt++;
288 v->fi->use_list=myrealloc(v->fi->use_list,v->fi->use_cnt*sizeof(varlist));
289 v->fi->use_list[v->fi->use_cnt-1]=p->use_list[i];
290 }
291 }
292 }
293 }
294 for(c=0;c<=maxtyp;c++){
295 if(BTST(tf,c)){
296 v->fi->use_cnt++;
297 v->fi->use_list=myrealloc(v->fi->use_list,v->fi->use_cnt*sizeof(varlist));
298 v->fi->use_list[v->fi->use_cnt-1].v=0;
299 v->fi->use_list[v->fi->use_cnt-1].flags=c;
300 }
301 }
302 if(known) v->fi->flags|=ALL_USES;
303 }
304 if(flags&CALC_CHANGES){
305 if(v->fi->flags&ALL_MODS) return;
306 free(v->fi->change_list);
307 v->fi->change_cnt=0;
308 v->fi->change_list=0;
309 memset(tf,0,TSIZE);
310 known=1;maxtyp=-1;
311 for(p=first_ic;p;p=p->next){
312 c=p->code;
313 if(p->z.flags&DREFOBJ){
314 t=(ztyp(p)&NQ);
315 if(t>maxtyp) maxtyp=t;
316 BSET(tf,t);
317 }
318 if(c==CALL){
319 if((p->q1.flags&(VAR|DREFOBJ))!=VAR||!p->q1.v->fi||!(p->q1.v->fi->flags&ALL_MODS)){
320 free(v->fi->change_list);
321 v->fi->change_cnt=0;
322 v->fi->change_list=0;
323 known=0;
324 break;
325 }else{
326 for(i=0;i<p->q1.v->fi->change_cnt;i++){
327 if(p->q1.v->fi->change_list[i].v){
328 if(!in_varlist(v->fi->change_list,v->fi->change_cnt,p->q1.v->fi->change_list[i].v,p->q1.v->fi->change_list[i].flags)){
329 v->fi->change_cnt++;
330 v->fi->change_list=myrealloc(v->fi->change_list,v->fi->change_cnt*sizeof(varlist));
331 v->fi->change_list[v->fi->change_cnt-1]=p->q1.v->fi->change_list[i];
332 }
333 }else{
334 BSET(tf,p->q1.v->fi->change_list[i].flags&NQ);
335 }
336 }
337 }
338 }else{
339 for(i=0;i<p->change_cnt;i++){
340 if(p->change_list[i].v->nesting!=0) continue;
341 if(!in_varlist(v->fi->change_list,v->fi->change_cnt,p->change_list[i].v,p->change_list[i].flags)){
342 v->fi->change_cnt++;
343 v->fi->change_list=myrealloc(v->fi->change_list,v->fi->change_cnt*sizeof(varlist));
344 v->fi->change_list[v->fi->change_cnt-1]=p->change_list[i];
345 }
346 }
347 }
348 }
349 for(c=0;c<=maxtyp;c++){
350 if(BTST(tf,c)){
351 v->fi->change_cnt++;
352 v->fi->change_list=myrealloc(v->fi->change_list,v->fi->change_cnt*sizeof(varlist));
353 v->fi->change_list[v->fi->change_cnt-1].v=0;
354 v->fi->change_list[v->fi->change_cnt-1].flags=c;
355 }
356 }
357 if(known) v->fi->flags|=ALL_MODS;
358 }
359 if(flags&CALC_CALLS){
360 if(v->fi->flags&ALL_CALLS) return;
361 free(v->fi->call_list);
362 v->fi->call_list=0;
363 v->fi->call_cnt=0;
364 p=v->fi->opt_ic;
365 if(!p)
366 p=v->fi->first_ic;
367 for(;p;p=p->next){
368 if(p->code==CALL){
369 if(p->q1.flags&DREFOBJ) return;
370 if(!in_varlist(v->fi->call_list,v->fi->call_cnt,p->q1.v,0)){
371 v->fi->call_cnt++;
372 v->fi->call_list=myrealloc(v->fi->call_list,v->fi->call_cnt*sizeof(varlist));
373 v->fi->call_list[v->fi->call_cnt-1].v=p->q1.v;
374 v->fi->call_list[v->fi->call_cnt-1].flags=0;
375 }
376 }
377 }
378 v->fi->flags|=ALL_CALLS;
379 }
380}
381
382void used_clist(type *t,const_list *cl)
383{
384 int i;zmax l;
385
386 if(ISARRAY(t->flags)){
387 for(l=l2zm(0L);!zmleq(t->size,l)&&cl;l=zmadd(l,l2zm(1L)),cl=cl->next){
388 if(!cl->other){ierror(0);return;}
389 used_clist(t->next,cl->other);
390 }
391 return;
392 }
393 if(ISUNION(t->flags)&&!cl->tree){
394 used_clist((*t->exact->sl)[zm2l(cl->idx)].styp,cl->other);
395 return;
396 }
397 if(ISSTRUCT(t->flags)){
398 type *st;
399 if(!cl||!cl->tree){
400 for(i=0;i<t->exact->count&&cl;i++){
401 st=(*t->exact->sl)[i].styp;
402 if(!(*t->exact->sl)[i].identifier) ierror(0);
403 if(zmeqto(l2zm((long)i),cl->idx)){
404 if((*t->exact->sl)[i].identifier[0]){
405 if(cl->other) used_clist(st,cl->other);
406 cl=cl->next;
407 }
408 }
409 }
410 }
411 return;
412 }
413 if(cl->tree&&(cl->tree->o.flags&VAR))
414 used_objects(cl->tree->o.v);
415 return;
416}
417
418void used_objects(Var *v)
419{
420 int i;
421 if(v->flags&REFERENCED) return;
422 v->flags|=REFERENCED;
423 if(ISFUNC(v->vtyp->flags)){
424 IC *p;
425 if(!(v->flags&DEFINED)) return;
426 if(!v->fi) ierror(0);
427 for(i=0;i<v->fi->call_cnt;i++){
428 if(v->fi->call_list[i].v->flags&DEFINED)
429 used_objects(v->fi->call_list[i].v);
430 }
431 /*FIXME: use/change aus fi */
432 for(p=v->fi->opt_ic;p;p=p->next){
433 if(p->q1.flags&VAR) used_objects(p->q1.v);
434 if(p->q2.flags&VAR) used_objects(p->q2.v);
435 if(p->z.flags&VAR) used_objects(p->z.v);
436 }
437 }else{
438 if(v->clist) used_clist(v->vtyp,v->clist);
439 }
440}
441
442zmax recalc_start_offset;
443
444static void mark_na(bvtype *tmp,int r,int *eqto)
445{
446 int i;
447 if(r<0||r>=vcount-rcount||BTST(tmp,r)) return;
448 /*if(DEBUG&1024) printf("mark_na %s(%p):\n",vilist[r]->identifier,(void*)vilist[r]);*/
449 BSET(tmp,r);
450 for(i=0;i<vcount-rcount;i++){
451 if(eqto[i]!=r&&eqto[r]!=i) continue;
452 /*if((DEBUG&1024)&&!BTST(tmp,i)) printf(" mark_na %s(%p)\n",vilist[i]->identifier,(void*)vilist[i]);*/
453 mark_na(tmp,i,eqto);
454 }
455}
456
457/* TODO: remove ugly hack by decent exit criteria */
458static int reccheck_maxcnt;
459
460/* check if function v can not call callee */
461static int check_nonrecursive(Var *v,Var *callee)
462{
463 int i;
464 Var *f;
465 if(--reccheck_maxcnt==0) return 0;
466 if(v->fi&&(v->fi->flags&ALL_CALLS)){
467 for(i=0;i<v->fi->call_cnt;i++){
468 f=v->fi->call_list[i].v;
469 if(f==v)
470 return 0;
471 if(!check_nonrecursive(f,callee))
472 return 0;
473 }
474 return 1;
475 }
476 return 0;
477}
478
479static void cnv_static(Var *v)
480{
481 if((v->storage_class==AUTO||v->storage_class==REGISTER)&&zmleq(Z0,v->offset)&&v->reg==0/*&&!(v->flags&CONVPARAMETER)*/){
482 v->storage_class=STATIC;
483 v->offset=++label;
484 v->flags|=(USEDASSOURCE|USEDASDEST|DEFINED|STATICAUTO);
485 if(v->clist){free_clist(v->clist);v->clist=0;}
486 if(DEBUG&1024) printf("changing %s(%p) to static (L%ld)\n",v->identifier,v,zm2l(v->offset));
487 }
488}
489
490/* replace auto variables by statics if possible */
491void replace_statics(Var *v)
492{
493 IC *p;
494 if(DEBUG&1024) printf("replace_statics()\n");
495 if(force_statics||(v->fi&&(v->fi->flags&ALL_CALLS))){
496 if(!force_statics){
497 reccheck_maxcnt=100;
498 if(!check_nonrecursive(v,v))
499 return;
500 if(DEBUG&1024) printf("non-recursive\n");
501 }
502
503 for(p=first_ic;p;p=p->next){
504 if((p->q1.flags&(VAR|REG))==VAR) cnv_static(p->q1.v);
505 if((p->q2.flags&(VAR|REG))==VAR) cnv_static(p->q2.v);
506 if((p->z.flags&(VAR|REG))==VAR) cnv_static(p->z.v);
507
508 if(p->code==ADDRESS&&p->q1.v->storage_class==STATIC){
509 p->code=ASSIGN;
510 p->q1.flags|=VARADR;
511 p->q2.val.vmax=sizetab[p->typf2&NQ];
512 p->typf=p->typf2;
513 }
514 }
515 }
516}
517
518
519void recalc_offsets(flowgraph *g)
520/* berechnet Offsets fuer auto-Variablen neu und versucht, fuer Variablen, */
521/* die nicht gleichzeitig aktiv sind, den gleichen Platz zu belegen */
522{
523 int i,j,b,bcnt,r,*eqto,pass;size_t bsize,vsize;zmax *al,*sz;
524 bvtype **used,*tmp,*empty,*vtmp,*vpos;
525 IC *p;
526 flowgraph *fg;
527
528 if(DEBUG&1024) printf("recalculating offsets\n");
529 if(DEBUG&1024) printf("setting up arrays\n");
530 /*bsize=(basic_blocks+CHAR_BIT-1)/CHAR_BIT; /* we don's use fg->index but count from 0 */
531 bsize=BVSIZE(basic_blocks);
532 if(DEBUG&1024) printf("bsize=%lu\n",(unsigned long)bsize);
533 tmp=mymalloc(bsize);
534 al=mymalloc(sizeof(*al)*(vcount-rcount));
535 eqto=mymalloc(sizeof(int)*(vcount-rcount));
536 sz=mymalloc(sizeof(*sz)*(vcount-rcount));
537 empty=mymalloc(bsize);
538 memset(empty,0,bsize);
539 used=mymalloc(sizeof(bvtype *)*(vcount-rcount));
540 /* Tabelle, welche Variable in welchem Block belegt ist, aufbauen */
541 for(i=0;i<vcount-rcount;i++){
542 if((vilist[i]->storage_class==AUTO||vilist[i]->storage_class==REGISTER)&&zmleq(l2zm(0L),vilist[i]->offset)){
543 if(DEBUG&2048) printf("setting up for %s,%ld\n",vilist[i]->identifier,zm2l(vilist[i]->offset));
544 used[i]=mymalloc(bsize);
545 memset(used[i],0,bsize);
546 }else{
547 used[i]=0;
548 }
549 sz[i]=szof(vilist[i]->vtyp);
550 al[i]=falign(vilist[i]->vtyp);
551 eqto[i]=-1;
552 }
553 b=0; fg=g;
554 while(fg){
555 if(b>=basic_blocks) ierror(0);
556 for(i=0;i<vcount-rcount;i++){
557 if(used[i]&&(BTST(fg->av_in,i)||BTST(fg->av_out,i))){
558 BSET(used[i],b);
559 for(r=1;r<=MAXR;r++)
560 if(fg->regv[r]&&fg->regv[r]->index==i) BCLR(used[i],b);
561 }
562 }
563 for(p=fg->start;p;p=p->next){
564 if((p->q1.flags&(VAR|REG))==VAR){
565 i=p->q1.v->index;
566 if(i!=-1&&i<vcount-rcount){
567 if(i<0||i>=vcount) ierror(0);
568 if(i>=0&&used[i]){
569 BSET(used[i],b);
570 }
571 }
572 }
573 if((p->q2.flags&(VAR|REG))==VAR){
574 i=p->q2.v->index;
575 if(i!=-1&&i<vcount-rcount){
576 if(i<0||i>=vcount) ierror(0);
577 if(i>=0&&used[i]){
578 BSET(used[i],b);
579 }
580 }
581 }
582 if((p->z.flags&(VAR|REG))==VAR){
583 i=p->z.v->index;
584 if(i!=-1){
585 if(i<0||i>=vcount) ierror(0);
586 if(i>=0&&used[i]){
587 BSET(used[i],b);
588 }
589 }
590 }
591 if(p==fg->end) break;
592 }
593 fg=fg->normalout;
594 b++;
595 }
596 bcnt=b;
597
598 if(DEBUG&1024) printf("local recalc\n");
599 vsize=BVSIZE(vcount-rcount);
600 vtmp=mymalloc(vsize);
601 vpos=mymalloc(vsize);
602 j=0;
603 for(fg=g;fg;fg=fg->normalout){
604 bvcopy(vtmp,fg->av_in,vsize);
605 bvunite(vtmp,fg->av_out,vsize);
606 for(r=1;r<=MAXR;r++)
607 if(fg->regv[r]&&fg->regv[r]->index<vcount-rcount) BSET(vtmp,fg->regv[r]->index);
608 for(i=0;i<vcount-rcount;i++){
609 if(!BTST(vtmp,i)){
610 if(!used[i]||!BTST(used[i],j)||(vilist[i]->storage_class!=AUTO&&vilist[i]->storage_class!=REGISTER))
611 BSET(vtmp,i);
612 else{
613 for(r=0;r<bcnt;r++)
614 if(r!=j&&BTST(used[i],r))
615 BSET(vtmp,i);
616 }
617 }
618 }
619#if 1
620 if(DEBUG&1024){
621 printf("possible for local recalc block %d (%d):\n",j,fg->index);
622 for(i=0;i<vcount-rcount;i++)
623 if(!BTST(vtmp,i))
624 printf(" %s(%p)\n",vilist[i]->identifier,(void*)vilist[i]);
625 }
626#endif
627 for(p=fg->start;p;p=p->next){
628 if((p->z.flags&(VAR|DREFOBJ))==VAR){
629 b=p->z.v->index;
630 if(b>=0&&b<vcount-rcount&&eqto[b]<0&&!BTST(vtmp,b)){
631 /* imprecise, but should do the job */
632 IC *m;
633 /*if(DEBUG&1024) printf("checking %s(%p)\n",vilist[b]->identifier,(void*)vilist[b]);*/
634 bvcopy(vpos,vtmp,vsize);
635 for(m=p->next;m;m=m->next){
636 if(m->q1.flags&VAR) mark_na(vpos,m->q1.v->index,eqto);
637 if(m->q2.flags&VAR) mark_na(vpos,m->q2.v->index,eqto);
638 if(m->z.flags&VAR){
639 mark_na(vpos,m->z.v->index,eqto);
640 if(m->z.v->index==b) BSET(vtmp,b);
641 }
642 if(m==fg->end) break;
643 }
644 for(i=vcount-rcount-1;i>=0;i--){
645 if(!BTST(vpos,i)&&i!=b){
646 if(DEBUG&1024) printf("local memory for %s(%p) and %s(%p) equal",vilist[i]->identifier,(void *)vilist[i],vilist[b]->identifier,(void *)vilist[b]);
647 eqto[b]=i;
648 if(!zmleq(al[b],al[i])) al[i]=al[b];
649 if(!zmleq(sz[b],sz[i])) sz[i]=sz[b];
650 if(!zmleq(al[i],al[b])) al[b]=al[i];
651 if(!zmleq(sz[i],sz[b])) sz[b]=sz[i];
652 if(DEBUG&1024) printf(" sz=%ld al=%ld\n",(long)zm2l(al[i]),(long)zm2l(sz[i]));
653 BSET(vtmp,i);
654 /*bvunite(used[i],used[b],bsize);*/
655 break;
656 }
657 }
658 }
659 }
660 if(p==fg->end) break;
661 }
662 j++;
663 }
664 free(vtmp);
665 free(vpos);
666
667
668 /* schauen, ob Variablen in gleichen Speicher koennen */
669 if(DEBUG&1024) printf("looking for distinct variables\n");
670 for(i=0;i<vcount-rcount;i++){
671
672 if(!used[i]||eqto[i]>=0) continue;
673 if(!memcmp(used[i],empty,bsize)){ free(used[i]);used[i]=0;continue;}
674 for(b=i+1;b<vcount-rcount;b++){
675 if(!used[b]||eqto[b]>=0) continue;
676 if(!memcmp(used[b],empty,bsize)){ free(used[b]);used[b]=0;continue;}
677 if(DEBUG&2048) printf("comparing %s(%p) and %s(%p)\n",vilist[i]->identifier,(void *)vilist[i],vilist[b]->identifier,(void *)vilist[b]);
678
679 memcpy(tmp,used[i],bsize);
680 bvintersect(tmp,used[b],bsize);
681 if(!memcmp(tmp,empty,bsize)){
682 if(DEBUG&1024) printf("memory for %s(%p) and %s(%p) equal\n",vilist[i]->identifier,(void *)vilist[i],vilist[b]->identifier,(void *)vilist[b]);
683 eqto[b]=i;
684 if(!zmleq(al[b],al[i])) al[i]=al[b];
685 if(!zmleq(sz[b],sz[i])) sz[i]=sz[b];
686 if(!zmleq(al[i],al[b])) al[b]=al[i];
687 if(!zmleq(sz[i],sz[b])) sz[b]=sz[i];
688 bvunite(used[i],used[b],bsize);
689 }
690 }
691 }
692
693 if(DEBUG&1024) printf("propagating sz/al\n");
694 do{
695 if(DEBUG&1024) printf("ppass\n");
696 b=0;
697 for(i=0;i<vcount-rcount;i++){
698 j=i;
699 while((j=eqto[j])>=0){
700 if(!zmleq(sz[j],sz[i])){sz[i]=sz[j];b=1;j=i;if(DEBUG&1024) printf("lmset %d(%p) to sz %ld\n",i,vilist[i],zm2l(sz[i]));}
701 if(!zmleq(sz[i],sz[j])){sz[j]=sz[i];b=1;if(DEBUG&1024) printf("lmset %d(%p) to sz %ld\n",j,vilist[j],zm2l(sz[j]));}
702 if(!zmleq(al[j],al[i])){al[i]=al[j];b=1;j=i;if(DEBUG&1024) printf("lmset %d(%p) to al %ld\n",i,vilist[i],zm2l(al[i]));}
703 if(!zmleq(al[i],al[j])){al[j]=al[i];b=1;if(DEBUG&1024) printf("lmset %d(%p) to al %ld\n",j,vilist[j],zm2l(al[j]));}
704
705 }
706 }
707 }while(b);
708
709 if(DEBUG&1024) printf("final recalculating\n");
710 max_offset=recalc_start_offset;
711 for(pass=0;pass<3;pass++){
712 zmax a;
713 for(a=maxalign;!zmeqto(a,Z0);a=zmsub(a,Z1)){
714 for(i=0;i<vcount-rcount;i++){
715 if(!used[i]) continue;
716 if(!zmeqto(a,al[i])) continue;
717 if(eqto[i]>=0&&pass<2) continue;
718
719 if(pass==0){
720 if(!zmleq(sz[i],sizetab[MAXINT])&&!zmleq(sz[i],sizetab[LDOUBLE])) continue;
721 }
722 free(used[i]);
723 used[i]=0;
724 if(DEBUG&2048) printf("adjusting offset for %s,%ld(%p)\n",vilist[i]->identifier,zm2l(vilist[i]->offset),(void*)vilist[i]);
725 if(eqto[i]>=0){
726 j=eqto[i];
727 do{
728 }while(used[j]&&(j=eqto[j])>=0);
729 if(j<0) ierror(0);
730 if(!zmleq(sz[i],sz[j]))
731 {printf("%d(%p) %d(%p) %ld %ld\n",i,vilist[i],j,vilist[j],zm2l(sz[i]),zm2l(sz[j]));ierror(0);}
732 if(!zmleq(al[i],al[j]))
733 {printf("%d(%p) %d(%p) %ld %ld\n",i,vilist[i],j,vilist[j],zm2l(al[i]),zm2l(al[j]));ierror(0);}
734 vilist[i]->offset=vilist[j]->offset;
735 if(DEBUG&2048) printf("set to %ld (eqto)\n",(long)zm2l(vilist[i]->offset));
736 continue;
737 }
738 vilist[i]->offset=zmmult(zmdiv(zmadd(max_offset,zmsub(al[i],l2zm(1L))),al[i]),al[i]);
739 max_offset=zmadd(vilist[i]->offset,sz[i]);
740 if(DEBUG&2048) printf("set to %ld (std)\n",(long)zm2l(vilist[i]->offset));
741 }
742 }
743 }
744 recalc_start_offset=l2zm(0L);
745 free(used);
746 free(sz);
747 free(al);
748 free(tmp);
749 free(empty);
750 free(eqto);
751}
752void remove_IC_fg(flowgraph *g,IC *p)
753/* Entfernt IC p und beachtet Flussgraph. Ausserdem werden */
754/* use/change-Listen freigegeben. */
755{
756 if(p->q1.am||p->q2.am||p->z.am) ierror(0);
757 if(have_alias){
758 free(p->use_list);
759 free(p->change_list);
760 }
761 if(g->start==g->end){
762 g->start=g->end=0;
763 }else{
764 if(p==g->end) g->end=p->prev;
765 if(p==g->start) g->start=p->next;
766 }
767 remove_IC(p);
768}
769
770/* function to decide whether a possible const memcpy shall
771 be implemented using typ t; if noptr is non-zero decide
772 if not introducing a pointer is preferable */
773int decide_const_memcpy(IC *p,int typ,int noptr)
774{
775 zmax cnt;
776
777 /* usually int is the most efficient */
778 if(typ==CHAR){
779 }else if(typ==BESTCOPYT){
780 if((p->z.flags&(VAR|DREFOBJ))!=VAR)
781 return 0;
782 if(!zmleq(align[typ],falign(p->z.v->vtyp)))
783 return 0;
784 if(!zmeqto(zmmod(p->z.val.vmax,align[typ]),Z0))
785 return 0;
786 }else
787 return 0;
788
789 cnt=zmdiv(p->q2.val.vmax,sizetab[typ]);
790
791 if((p->z.flags&(DREFOBJ|KONST))!=DREFOBJ){
792 int sc;
793 if(p->z.flags&DREFOBJ)
794 sc=STATIC;
795 else
796 sc=p->z.v->storage_class;
797 if(sc==AUTO||sc==REGISTER){
798 /* we assume that writes on the stack can be combined */
799 if(typ==CHAR&&noptr)
800 if(zmleq(cnt,zmmult(clist_copy_pointer,sizetab[BESTCOPYT])))
801 return 1;
802 if(zmleq(cnt,l2zm(clist_copy_stack)))
803 return 1;
804 }else{
805 if(zmleq(cnt,l2zm(clist_copy_static)))
806 return 1;
807 }
808 }
809
810 if(noptr==0&&zmleq(cnt,l2zm(clist_copy_pointer)))
811 return 1;
812
813 return 0;
814}
815
816int insert_const_memcpy(flowgraph *fg)
817{
818 int changed =0;
819 flowgraph *g;
820 for(g=fg;g;g=g->normalout){
821 IC *p;
822 for(p=g->start;p;p=p->next){
823 int c=p->code;
824
825 /* TODO: finish support for PUSH */
826 if((c==ASSIGN/*||c==PUSH*/)&&(p->q1.flags&(VAR|VARADR|DREFOBJ))==VAR&&p->q1.v->clist&&is_const(p->q1.v->vtyp)){
827 zmax i,sz=p->q2.val.vmax;
828 zuchar zuc;
829 Var *v=p->q1.v;
830 type *t=v->vtyp;
831 int ok=1;
832
833 for(i=Z0;zmleq(i,sz);i=zmadd(i,Z1)){
834 if(!get_clist_byte(t,v->clist,i,&zuc))
835 ok=0;
836 }
837
838 if(ok==1){
839 int typ=0,noptr=1;
840 int a1,a2;
841 if(DEBUG&1024) {printf("can replace const memcpy:\n");pric2(stdout,p);}
842
843 if(c==ASSIGN&&(p->z.flags&(DREFOBJ|KONST))!=DREFOBJ){
844 if(decide_const_memcpy(p,BESTCOPYT,noptr))
845 typ=BESTCOPYT;
846 else if(decide_const_memcpy(p,CHAR,noptr))
847 typ=CHAR;
848 }
849 if(typ==0){
850 noptr=0;
851 if(decide_const_memcpy(p,BESTCOPYT,noptr))
852 typ=BESTCOPYT;
853 else if(decide_const_memcpy(p,CHAR,noptr))
854 typ=CHAR;
855 }
856
857 if(typ){
858 Var *ptr;
859 IC *new;
860
861 if(DEBUG&1024) printf("will do it (typ=%d noptr=%d)\n",typ,noptr);
862 if(!noptr){
863 type *pt;
864 if(p->z.flags&VAR){
865 if(p->z.flags&DREFOBJ){
866 type *new=new_typ();
867 new->flags=p->z.dtyp&NQ;
868 new->next=new_typ();
869 new->next->flags=typ;
870 pt=new;
871 }else{
872 pt=new_typ();
873 pt->flags=POINTER_TYPE(p->z.v->vtyp);
874 pt->next=clone_typ(p->z.v->vtyp);
875 }
876 }else{
877 static type ct={CHAR};
878 type *new;
879 ct.flags=typ;
880 new=new_typ();
881 new->flags=POINTER_TYPE(&ct);
882 new->next=new_typ();
883 new->next->flags=typ;
884 pt=new;
885 }
886
887 ptr=add_tmp_var(pt);
888 new=new_IC();
889 new->z.flags=VAR;
890 new->z.v=ptr;
891 new->q1=p->z;
892 if(p->z.flags&DREFOBJ){
893 new->code=ASSIGN;
894 new->q1.flags&=~DREFOBJ;
895 new->typf=ptr->vtyp->flags;
896 }else if(p->z.v->storage_class==STATIC||p->z.v->storage_class==EXTERN){
897 new->code=ASSIGN;
898 new->q1.flags|=VARADR;
899 new->typf=ptr->vtyp->flags;
900 }else if(p->z.v->storage_class==AUTO||p->z.v->storage_class==REGISTER){
901 new->code=ADDRESS;
902 new->typf=p->z.v->vtyp->flags;
903 new->typf2=ptr->vtyp->flags;
904 }else
905 ierror(0);
906 new->q2.val.vmax=sizetab[new->typf];
907 insert_IC_fg(g,p->prev,new);
908 }
909 i=Z0;
910 while(!zmleq(sz,i)){
911 /* use CHAR for possibly remaining bytes */
912 if(!zmleq(zmadd(sizetab[typ],i),sz))
913 typ=CHAR;
914 new=new_IC();
915 new->code=p->code;
916 new->typf=typ;
917 new->q1.flags=KONST;
918 if(typ==CHAR){
919 if(!get_clist_byte(t,v->clist,zmadd(i,p->q1.val.vmax),&zuc))
920 ierror(0);
921 new->q1.val.vuchar=zuc;
922 }else{
923 int state;
924 gval.vmax=get_clist_int(t,v->clist,zmadd(i,p->q1.val.vmax),zm2l(sizetab[typ]),&state);
925 if(!state) ierror(0);
926 eval_const(&gval,MAXINT);
927 insert_const(&new->q1.val,typ);
928 }
929 new->q2.val.vmax=sizetab[new->typf];
930 if(new->code==ASSIGN){
931 if(noptr){
932 new->z=p->z;
933 new->z.val.vmax=zmadd(new->z.val.vmax,i);
934 }else{
935 new->z.flags=VAR|DREFOBJ;
936 new->z.v=ptr;
937 new->z.dtyp=ptr->vtyp->flags;
938 }
939 }else
940 ierror(0); /* TODO: PUSH */
941 insert_IC_fg(g,p->prev,new);
942 if(!noptr){
943 new=new_IC();
944 new->code=ADDI2P;
945 new->q1.flags=VAR;
946 new->q1.v=ptr;
947 new->z=new->q1;
948 new->q2.flags=KONST;
949 new->q2.val.vint=zm2zi(sizetab[typ]);
950 new->typf=INT;
951 new->typf2=ptr->vtyp->flags;
952 insert_IC_fg(g,p->prev,new);
953 }
954 i=zmadd(i,sizetab[typ]);
955
956 }
957 remove_IC_fg(g,p);
958 p=new;
959 changed=1;
960 }
961 }
962 }
963
964 if(p==g->end) break;
965 }
966 }
967 return changed;
968}
969
970/* combines assignments of constants into a larger type */
971void combine_const_assigns(void)
972{
973 static int ctype[BESTCOPYT],i,j;
974 IC *p=first_ic;
975
976 /* calculate table of combine types */
977 for(i=CHAR;i<BESTCOPYT;i++){
978 ctype[i]=0;
979 for(j=BESTCOPYT;j>CHAR;j--){
980 if(zmeqto(sizetab[j],zmadd(sizetab[i],sizetab[i]))){
981 if(DEBUG&1024) printf("possible combine type %s=>%s\n",typname[i],typname[j]);
982 ctype[i]=j;
983 break;
984 }
985 }
986 }
987 while(p){
988 if(p->code==ASSIGN&&(p->q1.flags&(KONST|DREFOBJ))==KONST&&(p->z.flags&(DREFOBJ|VAR))==VAR){
989 IC *p2=p->next;
990 if(p2&&p2->code==ASSIGN&&(p2->q1.flags&(KONST|DREFOBJ))==KONST&&(p2->z.flags&(DREFOBJ|VAR))==VAR&&p->z.v==p2->z.v&&p->typf==p2->typf&&zmeqto(p->q2.val.vmax,p2->q2.val.vmax)&&zmeqto(p2->z.val.vmax,zmadd(p->z.val.vmax,sizetab[p->typf&NQ]))){
991 int dt,t=p->typf&NQ,sc=p->z.v->storage_class;
992 if(t<BESTCOPYT&&(dt=ctype[t])){
993 zmax os;
994 /* for stack variables we can use the actual offset, for statics
995 we rely on the type alignment */
996 if(sc==AUTO||sc==REGISTER)
997 os=zmadd(p->z.v->offset,p->z.val.vmax);
998 else{
999 if(zmeqto(zmmod(falign(p->z.v->vtyp),align[dt]),Z0))
1000 os=p->z.val.vmax;
1001 else
1002 os=Z1;
1003 }
1004 if(zmeqto(zmmod(os,align[dt]),Z0)){
1005 zumax v1,v2;
1006 if(DEBUG&1024){
1007 printf("combine const assignment:\n");
1008 pric2(stdout,p);
1009 pric2(stdout,p2);
1010 }
1011 p->typf=dt;
1012 p->q2.val.vmax=sizetab[dt];
1013 eval_const(&p->q1.val,t|UNSIGNED);
1014 v1=vmax;
1015 eval_const(&p2->q1.val,t|UNSIGNED);
1016 v2=vmax;
1017 if(BIGENDIAN)
1018 v1=zmlshift(v1,zmmult(sizetab[t],char_bit));
1019 else
1020 v2=zmlshift(v2,zmmult(sizetab[t],char_bit));
1021 gval.vmax=zmor(v1,v2);
1022 eval_const(&gval,MAXINT);
1023 insert_const(&p->q1.val,dt);
1024 if(DEBUG&1024){printf("to:\n"); pric2(stdout,p);}
1025 remove_IC(p2);
1026 if(p->prev) p=p->prev; /* retry for more combining */
1027 continue;
1028 }
1029 }
1030 }
1031 }
1032 p=p->next;
1033 }
1034}
1035
1036
1037/* allowed to create new variables */
1038int early_peephole(void)
1039{
1040 IC *p;
1041 int changed,gchanged=0,c,t;
1042 do{
1043 changed=0;
1044 p=first_ic;
1045 while(p){
1046 c=p->code;
1047 t=p->typf;
1048 if(c==COMPARE&&(p->q2.flags&KONST)&&ISINT(p->typf)){
1049 case_table *ct;
1050 /* TODO: support multiple_ccs */
1051 if(!multiple_ccs&&(ct=calc_case_table(p,JUMP_TABLE_DENSITY))&&ct->num>1&&ct->density==1){
1052 int i;
1053 for(i=0;i<ct->num;i++){
1054 if(ct->labels[i]!=ct->labels[0])
1055 break;
1056 }
1057 if(i>=ct->num){
1058 IC *new;
1059 static type ityp;
1060 if(DEBUG&1024) printf("converting cases to range-check\n");
1061 if(multiple_ccs) ierror(0);
1062 new=new_IC();
1063 new->code=SUB;
1064 new->typf=ct->typf;
1065 new->q1=p->q1;
1066 new->q2.flags=KONST;
1067 if(ct->typf&UNSIGNED)
1068 eval_const(&ct->min,UNSIGNED|MAXINT);
1069 else
1070 eval_const(&ct->min,MAXINT);
1071 insert_const(&new->q2.val,ct->typf);
1072 new->z.flags=VAR;
1073 ityp.flags=ct->typf;
1074 new->z.v=add_tmp_var(clone_typ(&ityp));
1075 new->z.val.vmax=l2zm(0L);
1076 insert_IC(p->prev,new);
1077 new=new_IC();
1078 new->code=COMPARE;
1079 new->q1=p->prev->z;
1080 new->z.flags=0;
1081 new->q2.flags=KONST;
1082 new->typf=(ct->typf|UNSIGNED);
1083 gval.vumax=ct->diff;
1084 eval_const(&gval,UNSIGNED|MAXINT);
1085 insert_const(&new->q2.val,new->typf);
1086 insert_IC(p->prev,new);
1087 new=new_IC();
1088 new->code=BLE;
1089 new->typf=ct->labels[0];
1090 insert_IC(p->prev,new);
1091 while(p!=ct->next_ic){
1092 IC *m=p->next;
1093 remove_IC(p);
1094 p=m;
1095 }
1096 changed=1;
1097 continue;
1098 }
1099 }
1100 }
1101 p=p->next;
1102 }
1103 gchanged|=changed;
1104 }while(changed);
1105 return gchanged;
1106}
1107
1108int peephole()
1109/* macht alle moeglichen Vereinfachungen/Vereinheitlichungen */
1110{
1111 IC *p;obj o;int t,c,null,eins,changed,done=0;
1112 function_calls=0;
1113 do{
1114 if(DEBUG&1024) printf("searching for peephole optimizations\n");
1115 changed=0;ic_count=0;
1116 p=first_ic;
1117 while(p){
1118 c=p->code;
1119 t=p->typf;
1120 if(c==NOP&&!p->q1.flags&&!p->q2.flags&&!p->z.flags){
1121 IC *m;
1122 if(DEBUG&1024) printf("removing nop\n");
1123 m=p;p=p->next;
1124 remove_IC(m);
1125 continue;
1126 }
1127 ic_count++;
1128 if(c==LABEL&&report_suspicious_loops&&p->next&&p->next->code==BRA&&p->next->typf==t){
1129 error(208);report_suspicious_loops=0;
1130 }
1131 if(c==COMPARE&&(p->q2.flags&(KONST|DREFOBJ))==KONST){
1132 eval_const(&p->q2.val,t);
1133 if(ISINT(t)&&zmeqto(vmax,l2zm(1L))&&zumeqto(vumax,ul2zum(1UL))){
1134 IC *p2=p->next;
1135 if(p2->code==BGE){
1136 vmax=l2zm(0L);insert_const(&gval,MAXINT);
1137 p->q2.val=gval;p2->code=BGT;changed=1;
1138 if(DEBUG&1024) printf("cmp #1 replaced by cmp #0(1)\n");
1139 }else if(p2->code==BLT){
1140 vmax=l2zm(0L);insert_const(&gval,MAXINT);
1141 p->q2.val=gval;p2->code=BLE;changed=1;
1142 if(DEBUG&1024) printf("cmp #1 replaced by cmp #0(2)\n");
1143 }
1144 }else if(ISINT(t)&&!(t&UNSIGNED)&&zmeqto(vmax,l2zm(-1L))){
1145 IC *p2=p->next;
1146 if(p2->code==BGT){
1147 vmax=l2zm(0L);insert_const(&gval,MAXINT);
1148 p->q2.val=gval;p2->code=BGE;changed=1;
1149 if(DEBUG&1024) printf("cmp #-1 replaced by cmp #0(1)\n");
1150 }else if(p2->code==BLE){
1151 vmax=l2zm(0L);insert_const(&gval,MAXINT);
1152 p->q2.val=gval;p2->code=BLT;changed=1;
1153 if(DEBUG&1024) printf("cmp #-1 replaced by cmp #0\n(2)");
1154 }
1155 }else if((t&UNSIGNED)&&zmeqto(vmax,Z0)){
1156 IC *p2=p->next;
1157 if(p2->code==BLT){
1158 if(DEBUG&1024){printf("cmp uns,#0; blt eliminated\n");pric2(stdout,p);}
1159 remove_IC(p);
1160 p=p2->next;
1161 remove_IC(p2);
1162 continue;
1163 }
1164 if(p2->code==BGE){
1165 if(DEBUG&1024){printf("cmp uns,#0; bge to bra\n");pric2(stdout,p);}
1166 remove_IC(p);
1167 p2->code=BRA;
1168 p=p2;
1169 continue;
1170 }
1171 if(p2->code==BLE){
1172 if(DEBUG&1024){printf("cmp uns,#0; ble to beq\n");pric2(stdout,p);}
1173 p2->code=BEQ;
1174 }else if(p2->code==BGT){
1175 if(DEBUG&1024){printf("cmp uns,#0; bgt to bne\n");pric2(stdout,p);}
1176 p2->code=BNE;
1177 }
1178 }else if((t&UNSIGNED)&&zmeqto(vmax,Z1)){
1179 IC *p2=p->next;
1180 if(p2->code==BLT){
1181 if(DEBUG&1024){printf("cmp uns,#1; blt to cmp #0;beq\n");pric2(stdout,p);}
1182 gval.vmax=Z0;
1183 eval_const(&gval,MAXINT);
1184 insert_const(&p->q2.val,p->typf);
1185 p2->code=BEQ;
1186 }else if(p2->code==BGE){
1187 if(DEBUG&1024){printf("cmp uns,#1; bge to cmp #0;bne\n");pric2(stdout,p);}
1188 gval.vmax=Z0;
1189 eval_const(&gval,MAXINT);
1190 insert_const(&p->q2.val,p->typf);
1191 p2->code=BNE;
1192 }
1193 }
1194 }
1195 if(c>=BEQ&&c<BRA&&p->next&&p->next->code==BRA&&p->typf==p->next->typf){
1196 IC *p2,*m;
1197 if(DEBUG&1024){
1198 printf("removing bcc followed by bra\n");
1199 pric2(stdout,p);
1200 }
1201 m=p->next;
1202 p2=p->prev;
1203 remove_IC(p);
1204 if(p2&&(p2->code==TEST||p2->code==COMPARE)&&p2->z.flags==0){
1205 if(DEBUG&1024){
1206 printf("removing comparison:\n");
1207 pric2(stdout,p2);
1208 }
1209 remove_IC(p2);
1210 }
1211 p=m;
1212 changed=1;
1213 continue;
1214 }
1215 if(c==CALL) function_calls++;
1216 if(p->code==COMPARE&&(p->q1.flags&(VAR|VARADR))==(VAR|VARADR)&&(p->q2.flags&(VAR|VARADR))==(VAR|VARADR)&&p->q1.v==p->q2.v){
1217 IC *old=p->prev;
1218 if(fold(p)){ changed=1; p=old;continue;}
1219 p=p->next;continue;
1220 }
1221 if((p->q1.flags&(KONST|DREFOBJ))==KONST){
1222 if(((p->q2.flags&(KONST|DREFOBJ))==KONST)||!p->q2.flags){
1223 IC *old=p->prev;
1224 if(fold(p)){ changed=1; p=old;continue;}
1225 p=p->next;continue;
1226 }else{
1227 if(c==ADD||c==MULT||(c>=OR&&c<=AND)||(c==COMPARE&&!(p->z.flags)&&p->next&&p->next->code>=BEQ&&p->next->code<BRA)){ /* const nach rechts */
1228 if(DEBUG&1024){ printf("swapped commutative op:\n");pric2(stdout,p);}
1229 o=p->q1;p->q1=p->q2;p->q2=o;
1230 if(c==COMPARE){
1231 IC *br=p->next;
1232 if(br->code==BLT) br->code=BGT;
1233 else if(br->code==BLE) br->code=BGE;
1234 else if(br->code==BGT) br->code=BLT;
1235 else if(br->code==BGE) br->code=BLE;
1236 }
1237 }
1238 }
1239 }
1240 if((p->q2.flags&(KONST|DREFOBJ))==KONST){
1241 /* algebraische Optimierungen */
1242 eval_const(&p->q2.val,q2typ(p));
1243 if(zmeqto(vmax,l2zm(0L))&&zumeqto(vumax,ul2zum(0UL))&&zldeqto(vldouble,d2zld(0.0))) null=1; else null=0;
1244 if(zmeqto(vmax,l2zm(1L))&&zumeqto(vumax,ul2zum(1UL))&&zldeqto(vldouble,d2zld(1.0))) eins=1; else eins=0;
1245 if(zmeqto(vmax,l2zm(-1L))&&zldeqto(vldouble,d2zld(-1.0))) eins=-1;
1246 if(eins<0&&(c==MULT||c==DIV)){
1247 if(DEBUG&1024){ printf("MULT/DIV with (-1) converted to MINUS:\n");pric2(stdout,p);}
1248 p->code=c=MINUS;p->q2.flags=0;
1249 changed=1;
1250 }
1251#if HAVE_POF2OPT
1252 if(((c==MULT)||((c==DIV||c==MOD)&&(t&UNSIGNED)))&&ISINT(t)){
1253 /* ersetzt mul etc. mit Zweierpotenzen */
1254 long ln;
1255 if(zmleq(l2zm(0L),vmax)&&zumleq(ul2zum(0UL),vumax)){
1256 if(ln=get_pof2(vumax)){
1257 if(c==MOD){
1258 vmax=zmsub(vmax,l2zm(1L));
1259 p->code=c=AND;
1260 }else{
1261 if(c==DIV) p->code=RSHIFT; else p->code=LSHIFT;
1262 vmax=l2zm(ln-1);
1263 }
1264 gval.vmax=vmax;
1265 eval_const(&gval,MAXINT);
1266 insert_const(&p->q2.val,t);
1267 p->typf2=p->typf;
1268 changed=1;
1269 }
1270 }
1271 }
1272#endif
1273 if(c==LSHIFT||c==RSHIFT){
1274 zmax size;
1275 size=zmmult(sizetab[q1typ(p)&NQ],char_bit);
1276 if(zmleq(size,vmax)){
1277 if(c==LSHIFT||(q1typ(p)&UNSIGNED)){
1278 if(DEBUG&1024){ printf("lshift converted to ASSIGN 0:\n");pric2(stdout,p);}
1279 o.val.vmax=l2zm(0L);eval_const(&o.val,MAXINT);
1280 insert_const(&p->q1.val,t);p->q1.flags=KONST;
1281 p->code=c=ASSIGN;p->q2.flags=0;p->q2.val.vmax=sizetab[t&NQ];
1282 changed=1;
1283 }else{
1284 if(DEBUG&1024){ printf("rshift changed to maxlength:\n");pric2(stdout,p);}
1285 o.val.vmax=zmsub(size,l2zm(1L));eval_const(&o.val,MAXINT);
1286 insert_const(&p->q2.val,t);
1287 changed=1;
1288 }
1289 }
1290 }
1291
1292 if((c==SUB||c==ADD||c==ADDI2P||c==SUBIFP)&&!(q2typ(p)&UNSIGNED)&&zmleq(vmax,l2zm(0L))&&zldleq(vldouble,d2zld(0.0))){
1293 obj o;int ct=q2typ(p);
1294 o=p->q2;
1295 calc(MINUS,ct,&o.val,0,&o.val,0);
1296 eval_const(&o.val,ct);
1297 if(!zmleq(vmax,l2zm(0L))&&!zldleq(vldouble,d2zld(0.0))){
1298 calc(MINUS,ct,&o.val,0,&o.val,0);
1299 if(!compare_objs(&p->q2,&o,ct)){
1300 if(DEBUG&1024){ printf("SUB converted to ADD:\n");pric2(stdout,p);}
1301 calc(MINUS,ct,&p->q2.val,0,&p->q2.val,0);
1302 if(p->code==ADD) p->code=SUB;
1303 else if(p->code==SUB) p->code=ADD;
1304 else if(p->code==ADDI2P) p->code=SUBIFP;
1305 else if(p->code==SUBIFP) p->code=ADDI2P;
1306 c=p->code;
1307 changed=1;
1308 }
1309 }
1310 }
1311 if((eins>0&&(c==MULT||c==DIV))||(null&&(c==ADD||c==SUB||c==ADDI2P||c==SUBIFP||c==LSHIFT||c==RSHIFT||c==OR||c==XOR))){
1312 if(DEBUG&1024){ printf("operation converted to simple assignment:\n");pric2(stdout,p);}
1313 if(c==ADDI2P||c==SUBIFP) p->typf=t=p->typf2;
1314 p->code=c=ASSIGN;p->q2.flags=0;p->q2.val.vmax=sizetab[t&NQ];
1315 changed=1;
1316 }
1317 if(null&&(c==MULT||c==DIV||c==MOD||c==AND)){
1318 if(c==DIV||c==MOD){ err_ic=p;error(210);err_ic=0;}
1319 if(DEBUG&1024){ printf("operation converted to ASSIGN 0:\n");pric2(stdout,p);}
1320 o.val.vmax=l2zm(0L);eval_const(&o.val,MAXINT);
1321 insert_const(&p->q1.val,t);p->q1.flags=KONST;
1322 p->code=c=ASSIGN;p->q2.flags=0;p->q2.val.vmax=sizetab[t&NQ];
1323 changed=1;
1324 }
1325 if((ISINT(t)||fp_assoc)&&(c==ADD||c==SUB||c==ADDI2P||c==SUBIFP||c==MULT||c==LSHIFT||c==RSHIFT||c==OR||c==AND)){
1326 /* assoziative Operatoren */
1327 IC *n=p->next;
1328 int nc,tp,tn;
1329 tp=q2typ(p);
1330 if(n){
1331 nc=n->code;
1332 tn=q2typ(n);
1333 if(c==ADD&&nc==SUB) nc=ADD;
1334 if(c==ADDI2P&&nc==SUBIFP) nc=ADDI2P;
1335 if(c==SUB&&nc==ADD) nc=SUB;
1336 if(c==SUBIFP&&nc==ADDI2P) nc=SUBIFP;
1337 }
1338 if(n&&nc==c&&(n->q2.flags&KONST)&&tn==tp&&(!(tn&VOLATILE))&&(p->z.flags&VAR)&&n->q1.flags==p->z.flags&&n->q1.v==p->z.v&&zmeqto(n->q1.val.vmax,p->z.val.vmax)&&!is_volatile_obj(&n->q1)&&!is_volatile_obj(&p->z)){
1339 if(p->q1.flags==p->z.flags&&p->q1.v==p->z.v&&zmeqto(p->q1.val.vmax,p->z.val.vmax)&&!is_volatile_obj(&p->q1)){
1340 if(n->q1.flags==n->z.flags&&n->q1.v==n->z.v&&zmeqto(n->q1.val.vmax,n->z.val.vmax)){
1341 if(DEBUG&1024){ printf("using associativity(1) with:\n");pric2(stdout,p);pric2(stdout,p->next);}
1342 n->q1=p->q1;
1343 if(nc!=n->code){
1344 gval.vmax=l2zm(0L);
1345 eval_const(&gval,MAXINT);
1346 insert_const(&gval,t);
1347 calc(SUB,tn,&gval,&n->q2.val,&n->q2.val,0);
1348 n->code=nc;
1349 }
1350 if(c==LSHIFT||c==RSHIFT||c==ADDI2P||c==SUB||c==SUBIFP)
1351 calc(ADD,tp,&p->q2.val,&n->q2.val,&n->q2.val,0);
1352 else
1353 calc(c,tp,&p->q2.val,&n->q2.val,&n->q2.val,0);
1354 changed=1;
1355 if(DEBUG&1024) printf("must remove first operation\n");
1356 n=p;p=p->next;
1357 if(have_alias){ free(n->use_list); free(n->change_list); }
1358 remove_IC(n);
1359 continue;
1360 }
1361 }else{
1362 if(DEBUG&1024){ printf("using associativity(2) with:\n");pric2(stdout,p);pric2(stdout,p->next);}
1363 n->q1=p->q1;
1364 if(nc!=n->code){
1365 gval.vmax=l2zm(0L);
1366 eval_const(&gval,MAXINT);
1367 insert_const(&gval,t);
1368 calc(SUB,tn,&gval,&n->q2.val,&n->q2.val,0);
1369 n->code=nc;
1370 }
1371 if(c==LSHIFT||c==RSHIFT||c==ADDI2P||c==SUB||c==SUBIFP)
1372 calc(ADD,tp,&p->q2.val,&n->q2.val,&n->q2.val,0);
1373 else
1374 calc(c,tp,&p->q2.val,&n->q2.val,&n->q2.val,0);
1375 changed=1;
1376 }
1377 }
1378 }
1379 if((c==ADDI2P||c==SUBIFP)&&(p->q1.flags&VARADR)){
1380 /* add #var,#const -> move #var+const */
1381 union atyps val;
1382 if(DEBUG&1024){printf("add/sub #var,#const changed to assign:\n");pric2(stdout,p);}
1383 eval_const(&p->q2.val,t);
1384 insert_const(&val,MAXINT);
1385 if(c==ADDI2P)
1386 calc(ADD,MAXINT,&p->q1.val,&val,&p->q1.val,0);
1387 else
1388 calc(SUB,MAXINT,&p->q1.val,&val,&p->q1.val,0);
1389 p->code=c=ASSIGN;
1390 p->q2.flags=0;
1391 p->typf=t=p->typf2;
1392 p->q2.val.vmax=sizetab[t&NQ];
1393 changed=1;
1394 }
1395 if((c==ADD||c==SUB)&&ISINT(t)&&p->next&&p->next->next){
1396 /*FIXME: using SCRATCH is not nice */
1397 IC *p1=p->next,*p2=p1->next;
1398 if(p1->code==MULT&&p2->code==ADDI2P&&
1399 p1->typf==t&&p2->typf==t&&
1400 (p1->q2.flags&KONST)&&(p->z.flags&(SCRATCH|DREFOBJ))==SCRATCH&&(p1->z.flags&(SCRATCH|DREFOBJ))==SCRATCH&&
1401 !compare_objs(&p->z,&p1->q1,t)&&
1402 !compare_objs(&p1->z,&p2->q2,t)){
1403
1404 if(DEBUG&1024){ printf("rearranging array-access(1):\n");pric2(stdout,p);pric2(stdout,p1);pric2(stdout,p2);}
1405 p1->q1=p->q1;
1406 p->q1=p2->q1;
1407 p2->q1=p2->z;
1408 p->z=p2->z;
1409 calc(MULT,t,&p->q2.val,&p1->q2.val,&p->q2.val,0);
1410 if(c==ADD) p->code=ADDI2P; else p->code=SUBIFP;
1411 p->typf2=p2->typf2;
1412 if(!(p->q1.flags&VARADR)){
1413 /* for static addresses it is best to add the constant
1414 part of the offset first (can be folded); for others
1415 the constant part might better be the last, as it can
1416 frequentlz be reduced bz addressing-modes */
1417 if(DEBUG&1024) printf("reversing\n");
1418 p2->q1=p->q1;
1419 p->q1=p->z;
1420 if(p->prev) p->prev->next=p1;
1421 p1->prev=p->prev;
1422 if(p==first_ic) first_ic=p1;
1423 p->next=p2->next;
1424 if(p->next) p->next->prev=p;
1425 p->prev=p2;
1426 p2->next=p;
1427 p=p1;
1428 }
1429 changed=1;continue;
1430 }
1431 }
1432 }
1433 if(p->q1.flags&KONST){
1434 /* algebraische Optimierungen */
1435 eval_const(&p->q1.val,t);
1436 if(zmeqto(vmax,l2zm(0L))&&zumeqto(vumax,ul2zum(0UL))&&zldeqto(vldouble,d2zld(0.0))) null=1; else null=0;
1437 if(null&&(c==DIV||c==MOD||c==LSHIFT||c==RSHIFT)){
1438 if(DEBUG&1024){ printf("operation converted to ASSIGN 0:\n");pric2(stdout,p);}
1439 o.val.vmax=l2zm(0L);eval_const(&o.val,MAXINT);
1440 insert_const(&p->q1.val,t);p->q1.flags=KONST;
1441 p->code=c=ASSIGN;p->q2.flags=0;p->q2.val.vmax=sizetab[t&NQ];
1442 changed=1;
1443 }
1444 }
1445 if(!USEQ2ASZ&&p->z.flags&&!compare_objs(&p->q2,&p->z,p->typf)){
1446 if(c==ADD||c==MULT||(c>=OR&&c<=AND)){
1447 obj o;
1448 if(DEBUG&1024){printf("swapping objs because USEQ2ASZ\n");pric2(stdout,p);}
1449 o=p->q2;p->q2=p->q1;p->q1=o;
1450 /* kein changed hier! */
1451 }else{pric2(stdout,p); ierror(0);}
1452 }
1453 if((c==ADD||c==SUB)&&p->next){
1454 /*FIXME: using SCRATCH is not nice */
1455 IC *p1=p->next;
1456 if(p1->code==ADDI2P&&p1->typf==t&&(p->z.flags&(SCRATCH|DREFOBJ))==SCRATCH&&!compare_objs(&p->z,&p1->q2,t)&&zmleq(sizetab[p1->typf2&NQ],sizetab[p1->typf&NQ])){
1457 if(DEBUG&1024){ printf("rearranging array-access(2):\n");pric2(stdout,p);pric2(stdout,p1);}
1458 p1->q2=p->q1;
1459 p->q1=p1->q1;
1460 p->z=p1->z;
1461 p1->q1=p1->z;
1462 if(c==ADD) p->code=c=ADDI2P; else p->code=c=SUBIFP;
1463 p->typf2=p1->typf2;
1464 changed=1;continue;
1465 }
1466 }
1467 if((c==SUB||c==DIV||c==MOD)&&!compare_objs(&p->q1,&p->q2,p->typf)){
1468 /* x-x=0, x/x=1, x%x=0 */
1469 if(DEBUG&1024){ printf("i-i, i/i, i%%i converted to ASSIGN 0/1:\n");pric2(stdout,p);}
1470 if(c==DIV) o.val.vmax=l2zm(1L); else o.val.vmax=l2zm(0L);
1471 eval_const(&o.val,MAXINT);insert_const(&p->q1.val,t);p->q1.flags=KONST;
1472 p->code=c=ASSIGN;p->q2.flags=0;p->q2.val.vmax=sizetab[t&NQ];
1473 changed=1;
1474 }
1475 if(c==ASSIGN&&(p->z.flags&VAR)&&p->z.flags==p->q1.flags&&p->z.v==p->q1.v&&zmeqto(p->z.val.vmax,p->q1.val.vmax)){
1476 IC *d;
1477 if(DEBUG&1024){ printf("removing redundant move:\n");pric2(stdout,p);}
1478 changed=1;
1479 d=p; p=p->next;
1480 if(have_alias){ free(d->use_list); free(d->change_list);}
1481 remove_IC(d); continue;
1482 }
1483#if 1
1484 /* TODO: better decision when to use for which targets? */
1485 if(c==CONVERT&&(p->q1.flags&(VAR|DREFOBJ))==VAR&&(p->z.flags&(VAR|DREFOBJ))==VAR&&!is_volatile_ic(p)){
1486 IC *p1=p->next;
1487 if(p1&&p1->code==CONVERT&&(p->typf2&NQ)==(p1->typf&NQ)&&(p->typf&NQ)==(p1->typf2&NQ)&&zmleq(sizetab[p->typf2&NQ],sizetab[p->typf&NQ])&&!compare_objs(&p->z,&p1->q1,p->typf2)&&!is_volatile_ic(p1)&&ISFLOAT(p->typf)==ISFLOAT(p->typf2)){
1488 if(DEBUG&1024){printf("propagating CONVERTS:\n");pric2(stdout,p);pric2(stdout,p1);}
1489 p1->q1=p->q1;
1490 p1->code=ASSIGN;
1491 p1->q2.val.vmax=sizetab[p1->typf&NQ];
1492 continue;
1493 }
1494 /* TODO: better decision when to use for which targets? */
1495 if(p1&&(p1->code==ADDI2P||p1->code==SUBIFP)&&(p1->typf&NU)==(p->typf&NU)&&!compare_objs(&p->z,&p1->q2,p1->typf)&&!is_volatile_ic(p1)&&(p->typf2&NQ)>=MINADDI2P&&(p->typf2&NQ)<=MAXADDI2P&&zmleq(sizetab[p->typf2&NQ],sizetab[p->typf&NQ])){
1496 if((p->typf2&UNSIGNED)&&(p->typf2&NU)>=MINADDUI2P){
1497 if(DEBUG&1024){printf("propagating CONVERT/ADDI2P:\n");pric2(stdout,p);pric2(stdout,p1);}
1498 p1->q2=p->q1;
1499 p1->typf=p->typf2;
1500 continue;
1501 }
1502 }
1503 }
1504#endif
1505 if(c>=BEQ&&c<=BGT){
1506 IC *p2=p->prev;
1507 if(p2&&p2->code==COMPARE&&!compare_objs(&p->q1,&p2->z,0)){
1508 IC *p3=p2->prev;
1509 if(p3&&p3->code==c){
1510 IC *p4=p3->prev;
1511 if(p4->code==COMPARE&&!compare_objs(&p3->q1,&p4->z,0)
1512 &&!compare_objs(&p2->q1,&p4->q1,p4->typf)&&!compare_objs(&p2->q2,&p4->q2,p4->typf)){
1513 if(DEBUG&1024){printf("removing redundant compare\n");pric2(stdout,p2);pric2(stdout,p);}
1514 p->code=NOP;
1515 p->q1.flags=p->q2.flags=p->z.flags=0;
1516 p->typf=0;
1517 p2->code=NOP;
1518 p2->typf=0;
1519 p2->q1.flags=p2->q2.flags=p2->z.flags=0;
1520 changed=1;
1521 }
1522 }
1523 }
1524 }
1525
1526 if((c==ADDI2P||c==SUBIFP)&&(p->q1.flags&(VARADR|DREFOBJ))==VARADR){
1527 IC *p2=p->next;
1528 if(p2->code==ADDI2P&&p->typf2==p2->typf2&&!compare_objs(&p->z,&p2->q1,p->typf2)&&(p2->q2.flags&(KONST|DREFOBJ))==KONST){
1529 if(DEBUG&1024){printf("rearranging ADDI2P to fold VARADR+const\n");pric2(stdout,p);pric2(stdout,p2);}
1530 eval_const(&p2->q2.val,p2->typf);
1531 p->q1.val.vmax=zmadd(p->q1.val.vmax,vmax);
1532 p2->code=ASSIGN;
1533 p2->typf=p2->typf2;
1534 p2->q2.val.vmax=sizetab[p2->typf&NQ];
1535 }
1536 }
1537
1538 p=p->next;
1539 }
1540 if(changed) done|=changed;
1541 gchanged|=changed;
1542 }while(changed);
1543 return done;
1544}
1545
1546void insert_loads()
1547/* Laedt Speicher in temporaere Variablen */
1548{
1549 IC *p,*new;
1550 type t={0},v={VOID};
1551 int c;
1552 if(DEBUG&1024) printf("insert_loads()\n");
1553 for(p=first_ic;p;p=p->next){
1554 c=p->code;
1555 if(p->typf&VOLATILE) continue;
1556 if(p->typf2&VOLATILE) continue;
1557 if(p->q2.flags||c==PUSH){
1558 if((dref_cse&&(p->q1.flags&DREFOBJ)&&!(p->q1.dtyp&(PVOLATILE|VOLATILE)))||(static_cse&&(p->q1.flags&(VAR|VARADR))==VAR&&(p->q1.v->storage_class==EXTERN||p->q1.v->storage_class==STATIC))){
1559 new=new_IC();
1560 new->code=ASSIGN;
1561 new->typf=q1typ(p);
1562 if(ISSCALAR(new->typf)){
1563 new->q1.am=new->q2.am=new->z.am;
1564 new->q1=p->q1;
1565 new->q2.flags=0;
1566 new->q2.val.vmax=sizetab[new->typf&NQ];
1567 new->z.flags=VAR;
1568 new->z.val.vmax=l2zm(0L);
1569 t.flags=new->typf;
1570 if(ISPOINTER(new->typf)) t.next=&v; else t.next=0;
1571 new->z.v=add_tmp_var(clone_typ(&t));
1572 insert_IC(p->prev,new);
1573 p->q1=new->z;
1574 }else
1575 free(new);
1576 }
1577 if((dref_cse&&(p->q2.flags&DREFOBJ)&&!(p->q2.dtyp&(PVOLATILE|VOLATILE)))||(static_cse&&(p->q2.flags&(VAR|VARADR))==VAR&&(p->q2.v->storage_class==EXTERN||p->q2.v->storage_class==STATIC))){
1578 new=new_IC();
1579 new->code=ASSIGN;
1580 new->typf=q2typ(p);
1581 if(ISSCALAR(new->typf)){
1582 new->q1.am=new->q2.am=new->z.am;
1583 new->q1=p->q2;
1584 new->q2.flags=0;
1585 new->q2.val.vmax=sizetab[new->typf&NQ];
1586 new->z.flags=VAR;
1587 new->z.val.vmax=l2zm(0L);
1588 t.flags=new->typf;
1589 if(ISPOINTER(new->typf)) t.next=&v; else t.next=0;
1590 new->z.v=add_tmp_var(clone_typ(&t));
1591 insert_IC(p->prev,new);
1592 p->q2=new->z;
1593 }else
1594 free(new);
1595 }
1596 if(p->q2.flags&&((dref_cse&&(p->z.flags&DREFOBJ)&&!(p->z.dtyp&(PVOLATILE|VOLATILE)))||(static_cse&&(p->z.flags&(VAR|VARADR))==VAR&&(p->z.v->storage_class==EXTERN||p->z.v->storage_class==STATIC)))){
1597 /* translate x op y -> mem to x op y -> tmp; move tmp -> mem */
1598 new=new_IC();
1599 new->code=ASSIGN;
1600 new->typf=ztyp(p);
1601 if(ISSCALAR(new->typf)){
1602 new->q1.am=new->q2.am=new->z.am;
1603 new->z=p->z;
1604 new->q2.flags=0;
1605 new->q2.val.vmax=sizetab[new->typf&NQ];
1606 new->q1.flags=VAR;
1607 new->q1.val.vmax=l2zm(0L);
1608 t.flags=new->typf;
1609 if(ISPOINTER(new->typf)) t.next=&v; else t.next=0;
1610 new->q1.v=add_tmp_var(clone_typ(&t));
1611 insert_IC(p,new);
1612 p->z=new->q1;
1613 }else
1614 free(new);
1615 }
1616 }
1617 }
1618}
1619
1620void insert_ccs(void)
1621/* Fuegt Variablen fuer ccs ein. */
1622{
1623 IC *p; Var *v; type *t;
1624 if(DEBUG&1024) printf("insert_ccs()\n");
1625 for(p=first_ic;p;p=p->next){
1626 if(p->code==COMPARE||p->code==TEST){
1627 p->z.flags=VAR;
1628 p->z.val.vmax=l2zm(0L);
1629 t=new_typ();
1630 t->flags=0;
1631 v=add_tmp_var(t);
1632 p->z.v=v;
1633 p=p->next;
1634 if(p->code<BEQ||p->code>BGT){
1635 p=p->prev;
1636 p->code=NOP;
1637 p->q1.flags=p->q2.flags=p->z.flags=0;
1638 p->typf=0;
1639 }else{
1640 p->q1.flags=VAR;
1641 p->q1.val.vmax=l2zm(0L);
1642 p->q1.v=v;
1643 }
1644 }
1645 }
1646}
1647
1648static int to_be_inlined(Var *v)
1649{
1650 /* decide whether function should be inlined */
1651 int c;IC *p;
1652 /* no code available */
1653 if(!v->fi||!v->fi->first_ic) return 0;
1654 /* marked as noinline */
1655 if(v->fi->flags&NO_INLINE) return 0;
1656 /* returns something not in a register (FIXME) */
1657 if(!ffreturn(v->vtyp->next)&&(v->vtyp->next->flags&NQ)!=VOID) return 0;
1658 /* varargs function */
1659 if((c=v->vtyp->exact->count)!=0&&(*v->vtyp->exact->sl)[c-1].styp->flags!=VOID)
1660 return 0;
1661 /* uses variable length arrays */
1662 if(v->fi->flags&USES_VLA) return 0;
1663 if(v->fi->inline_size>=0){
1664 c=v->fi->inline_size;
1665 }else{
1666 for(c=0,p=v->fi->first_ic;p;p=p->next) c++;
1667 }
1668 /* try to always inline functions specified as inline */
1669 if(v->flags&INLINEFUNC)
1670 return 1;
1671 if(c>inline_size) return 0;
1672 /* we assume that inlining saves size if the number of arguments
1673 is larger than the number of ICs + CALL +SETRETURN */
1674 if(optsize&&c-2>(v->vtyp->exact->count)) return 0;
1675 return 1;
1676}
1677
1678static int depth_reached;
1679
1680static int cross_module_inline(int only_full)
1681{
1682 IC *p,*np,*new,*ip,*cp,*getreturn;
1683 Var *v,*vp;
1684 int i,c,firstl,lastl,more_passes=0;
1685 if(DEBUG&1024) printf("cross_module_inline(only_full=%d)\n",only_full);
1686 for(p=first_ic;p;){
1687 np=p->next;
1688 if(p->code==CALL&&(p->q1.flags&(VAR|DREFOBJ))==VAR&&to_be_inlined(p->q1.v)){
1689 zmax pushed=p->q2.val.vmax;
1690 IC *gr;
1691 v=p->q1.v;
1692 if(only_full&&((p->q1.flags&(VAR|DREFOBJ))!=VAR||!p->q1.v->fi||!(p->q1.v->fi->flags&FULL_INLINE))){
1693 depth_reached=1;
1694 }else{
1695 more_passes=1;
1696 if(DEBUG&1024){
1697 printf("inlining call to %s\n",p->q1.v->identifier);
1698 for(vp=v->fi->vars;vp;vp=vp->next)
1699 printf("%s(%ld)/%p\n",vp->identifier,zm2l(vp->offset),(void*)vp);
1700 }
1701 gr=p->next;
1702 while(gr&&gr->code==NOP) gr=gr->next;
1703 if(gr&&gr->code==GETRETURN){
1704 getreturn=gr;
1705 np=getreturn->next;
1706 }else{
1707 getreturn=0;
1708 }
1709 /* Kopien der Variablen erzeugen */
1710 for(vp=v->fi->vars;vp;vp=vp->next){
1711 vp->inline_copy=0;
1712 }
1713 cp=p;
1714 /* find first and last label used */
1715 firstl=lastl=0;
1716 for(ip=v->fi->first_ic;ip;ip=ip->next){
1717 if(ip->code>=LABEL&&ip->code<=BRA){
1718 if(firstl==0||ip->typf<firstl) firstl=ip->typf;
1719 if(lastl==0||ip->typf>lastl) lastl=ip->typf;
1720 }
1721 }
1722 /* Argumente einfuegen */
1723 vp=v->fi->vars;
1724 for(i=0;i<p->arg_cnt;i++){
1725 while(vp&&(!*vp->identifier||(zmleq(l2zm(0L),vp->offset)&&!vp->reg)||(vp->storage_class!=REGISTER&&vp->storage_class!=AUTO))) vp=vp->next;
1726 if(!vp)
1727 continue;
1728 if(DEBUG&1024) printf("arg nr. %d to var <%s>\n",i,vp->identifier);
1729 vp->inline_copy=add_tmp_var(clone_typ(vp->vtyp));
1730 ip=p->arg_list[i];
1731 if(ip->code==ASSIGN){
1732 /* find and delete nop for register passing */
1733 IC *nop;
1734 if(!(ip->z.flags&VAR)||ip->z.v->reg==0) ierror(0);
1735 for(nop=ip->next;nop;nop=nop->next){
1736 if(nop->code==NOP&&(nop->q1.flags&(VAR|DREFOBJ))==VAR&&nop->q1.v==ip->z.v)
1737 break;
1738 }
1739 if(!nop) ierror(0);
1740 if(np==nop) np=nop->next;
1741 remove_IC(nop);
1742 }else if(ip->code==PUSH){
1743 ip->code=ASSIGN;
1744 pushed=zmsub(pushed,ip->q2.val.vmax);
1745 }else{
1746 pric2(stdout,ip);
1747 ierror(0);
1748 }
1749 ip->typf&=~VOLATILE;
1750 ip->z.flags=VAR;
1751 ip->z.v=vp->inline_copy;
1752 if((ip->z.v->vtyp->flags&NU)!=(ip->typf&NU)){
1753 /* have to convert */
1754 ip->typf2=ip->typf;
1755 ip->typf=ip->z.v->vtyp->flags;
1756 ip->code=CONVERT;
1757 }
1758 ip->z.val.vmax=l2zm(0L);
1759 vp=vp->next;
1760 }
1761
1762 if(!zmeqto(pushed,l2zm(0L))){
1763 /* ueberfluessige PUSHs entfernen */
1764 IC *m;
1765 ip=p->prev;
1766 while(1){
1767 m=ip->prev;
1768 if(ip->code==PUSH){
1769 if(0/*!(c_flags[26]&USEDFLAG)&&ip->q1.flags*/) ierror(0);
1770 if(!zmleq(ip->q2.val.vmax,pushed)) ierror(0);
1771 pushed=zmsub(pushed,ip->q2.val.vmax);
1772 if(np==ip) np=np->next;
1773 remove_IC(ip);
1774 if(zmeqto(pushed,l2zm(0L))) break;
1775 }
1776 if(!m) ierror(0);
1777 ip=m;
1778 }
1779 }
1780
1781 /* Code einfuegen und Labels umschreiben */
1782 ip=v->fi->first_ic;
1783 while(ip){
1784 Var *iv;
1785 int c;
1786 if(ip->code==CONVERT&&(ip->q1.flags&(VAR|DREFOBJ))==VAR&&(ip->q1.v->flags&CONVPARAMETER)&&(ip->z.flags&(VAR|DREFOBJ))==VAR&&ip->q1.v==ip->z.v){
1787 if(DEBUG&1024) {printf("eliminate oldstyle CONVERT:\n");pric2(stdout,ip);}
1788 ip=ip->next;
1789 continue;
1790 }
1791 new=new_IC();
1792 *new=*ip;
1793 ip->copy=new;
1794 c=ip->code;
1795 /* evtl. ist ein IC praktisch ein SETRETURN, falls das */
1796 /* Rueckgabeziel ueber Parameterzeiger angespr. wird */
1797 if(ip->z.flags&VAR){
1798 iv=ip->z.v;
1799 if(iv->storage_class==AUTO||iv->storage_class==REGISTER||(iv->flags&STATICAUTO)){
1800 if(0/*!*iv->identifier&&zmeqto(iv->offset,l2zm(0L))*/){
1801 if(getreturn){
1802 new->z=getreturn->z;
1803 }else{
1804 new->code=NOP;
1805 new->q1.flags=new->q2.flags=new->z.flags=0;
1806 new->typf=0;
1807 }
1808 }else{
1809 if(!iv->inline_copy){
1810 iv->inline_copy=add_tmp_var(clone_typ(iv->vtyp));
1811 iv->inline_copy->reg=iv->reg;
1812 }
1813 new->z.v=iv->inline_copy;
1814 }/*else if(iv->inline_copy) ierror(0);*/
1815 }
1816 }
1817 /* recreate ADDRESS when inlining STATICAUTO */
1818 if((new->q1.flags&(VAR|VARADR))==(VAR|VARADR)&&(new->q1.v->flags&STATICAUTO)){
1819 if(new->code!=ASSIGN) ierror(0);
1820 if(DEBUG&1024) printf("recreating ADDRESS from STATICAUTO:\n");
1821 if(DEBUG&1024) pric2(stdout,new);
1822 new->code=ADDRESS;
1823 new->q1.flags&=~VARADR;
1824 new->typf2=new->typf;
1825 new->typf=CHAR; /* TODO: Do we restore the old type? */
1826 if(DEBUG&1024) pric2(stdout,new);
1827 }
1828 /* Kopien aller auto/register Variablen erzeugen */
1829 if(ip->q1.flags&VAR){
1830 iv=ip->q1.v;
1831 if(iv->storage_class==AUTO||iv->storage_class==REGISTER||(iv->flags&STATICAUTO)){
1832 if(!iv->inline_copy){
1833 iv->inline_copy=add_tmp_var(clone_typ(iv->vtyp));
1834 iv->inline_copy->reg=iv->reg;
1835 }
1836 new->q1.v=iv->inline_copy;
1837 if(c==ADDRESS) new->q1.v->flags|=USEDASADR;
1838 }/*else if(iv->inline_copy) ierror(0);*/
1839 }
1840 if(ip->q2.flags&VAR){
1841 iv=ip->q2.v;
1842 if(iv->storage_class==AUTO||iv->storage_class==REGISTER||(iv->flags&STATICAUTO)){
1843 if(!iv->inline_copy){
1844 iv->inline_copy=add_tmp_var(clone_typ(iv->vtyp));
1845 iv->inline_copy->reg=iv->reg;
1846 }
1847 new->q2.v=iv->inline_copy;
1848 }/*else if(iv->inline_copy) ierror(0);*/
1849 }
1850 if(c==CALL){
1851 int i;
1852 function_calls+=1;
1853 new->arg_list=mymalloc(sizeof(*new->arg_list)*new->arg_cnt);
1854 for(i=0;i<new->arg_cnt;i++) new->arg_list[i]=ip->arg_list[i]->copy;
1855 }
1856 if(c>=LABEL&&c<=BRA){
1857 new->typf+=label+1-firstl;
1858 }
1859 if(c==SETRETURN){
1860 if(getreturn){
1861 new->code=ASSIGN;
1862 new->z=getreturn->z;
1863 }else{
1864 new->code=NOP;
1865 new->q1.flags=new->q2.flags=new->z.flags=0;
1866 new->typf=0;
1867 }
1868 }
1869 new->q1.flags&=~SCRATCH;
1870 new->q2.flags&=~SCRATCH;
1871 new->z.flags&=~SCRATCH;
1872 if(new->code==ASSIGN&&!new->q1.flags) ierror(0);
1873 insert_IC(cp,new);
1874 cp=new;
1875 ip=ip->next;
1876 }
1877
1878 label+=lastl-firstl+1;
1879 remove_IC(p);
1880 if(getreturn) remove_IC(getreturn);
1881 }
1882 }
1883 p=np;
1884 }
1885
1886 return more_passes;
1887}
1888
1889#endif
1890#define FREEAV free(av_globals);free(av_statics);free(av_drefs);free(av_address);
1891void optimize(long flags,Var *function)
1892/* flags: 1=Register, 2=optimize, 4=cse/cp, 8=constant_propagation, */
1893/* 16=dead_assignments, 32=global-optimizations */
1894/* 64=blockweise Registervergabe, 128=loop_optimizations (nur */
1895/* in Verbindung mit 32), 256=recalc_offsets */
1896{
1897#ifndef NO_OPTIMIZER
1898 flowgraph *g,*fg=0;
1899 int r,i,pass=0,mustrepeat,intask;
1900 int lc_freed,lc_done=0;
1901 if(!function) ierror(0);
1902 norek=nocall=0;
1903 report_suspicious_loops=report_weird_code=1;
1904 if(!strcmp(function->identifier,"main")){norek=1;nocall=1;}
1905 /* falls main() rekursiv aufgerufen werden kann, muss nomain==0 sein */
1906
1907 intask=(function->vattr&&strstr(function->vattr,"taskprio("));
1908
1909
1910#else
1911
1912 flags&=1;
1913
1914#endif
1915
1916
1917 if(flags&2){
1918#ifndef NO_OPTIMIZER
1919 if(DEBUG&1024) printf("\nOptimizing function %s\n",function->identifier);
1920 /* Variablen fuer ccs einsetzen. */
1921 if(cross_module&&(flags&4096)){
1922 int i,notdone=1;
1923 for(i=0;notdone;i++){
1924 depth_reached=0;
1925 notdone=cross_module_inline(i>=inline_depth);
1926 }
1927 if(!depth_reached){
1928 if(!function->fi) function->fi=new_fi();
1929 function->fi->flags|=FULL_INLINE;
1930 if(DEBUG&1024) printf("function %s set to full-inline\n",function->identifier);
1931 }
1932 }
1933 if(multiple_ccs) insert_ccs();
1934 /* Speicherzugriffe in extra tmp-Vars umleiten, wegen cse */
1935 if(flags&4) insert_loads();
1936 /* nur ein pass, wenn nur lokale Optimierungen */
1937 if(!(flags&32)) maxoptpasses=1;
1938 do{
1939 gchanged=0;pass++;
1940 av_globals=av_statics=av_address=av_drefs=0;
1941 ae_globals=ae_statics=ae_address=ae_drefs=0;
1942 cp_globals=cp_statics=cp_address=cp_drefs=0;
1943 dlist=0;vilist=0;elist=0;
1944
1945 if(DEBUG&1024) printf("\noptimizer (function %s) pass %d\n",function->identifier,pass);
1946 early_peephole();
1947 num_vars();
1948 peephole();
1949 fg=jump_optimization();
1950 create_alias(fg);
1951 if(DEBUG&2048) print_vi();
1952
1953#if 0
1954 if(DEBUG&1024) printf("range analysis\n");
1955 range_analysis(fg);
1956 myfree(rangebuf);
1957 rangebuf=0;
1958#endif
1959
1960 if(flags&8){
1961#if 0
1962 do{
1963 num_defs();
1964 if(flags&32){
1965 reaching_definitions(fg);
1966 if(DEBUG&1024) print_flowgraph(fg);
1967 r=constant_propagation(fg,1);
1968 }else{
1969 r=constant_propagation(fg,0);
1970 }
1971 if(DEBUG&1024) {printf("constant_propagation returned %d\n",r);print_flowgraph(fg);}
1972 if(r){
1973 if(peephole()){free_flowgraph(fg);fg=jump_optimization();}
1974 }
1975 if(r&2){
1976 if(DEBUG&1024) printf("must repeat num_vars\n");
1977 free(vilist);
1978 FREEAV;
1979 num_vars();
1980 }
1981 }while(r);
1982#endif
1983 num_defs();
1984 mustrepeat=0;
1985
1986
1987 if(DEBUG&1024) printf("trying constant propagation\n");
1988 if(DEBUG&1024) print_flowgraph(fg);
1989 if((flags&32)&&!(disable&4))
1990 reaching_definitions(fg);
1991 for(g=fg;g;g=g->normalout){
1992 do{
1993 r=constant_propagation(g,(flags&32)&&!(disable&4));
1994 gchanged|=r;
1995 if(r){
1996 IC *p;
1997 if(r&2) mustrepeat=1;
1998 r=0;
1999 for(p=g->start;p;p=p->next){
2000 if((p->q1.flags&(KONST|DREFOBJ))==KONST&&(!p->q2.flags||(p->q2.flags&(KONST|DREFOBJ))==KONST)){
2001 if(p->code!=TEST&&p->code!=COMPARE&&fold(p)) r=1;
2002 }
2003 if(p==g->end) break;
2004 }
2005 }
2006 }while(r);
2007 }
2008 if(DEBUG&1024) print_flowgraph(fg);
2009 free(rd_matrix);
2010 free(var_defs);
2011 free(defs_kill);
2012 free(defs_gen);
2013 free(dlist);
2014 free_flowgraph(fg);
2015 if(mustrepeat){
2016 if(DEBUG&1024) printf("must repeat num_vars()\n");
2017 free(vilist);
2018 FREEAV;
2019 early_peephole();
2020 num_vars();
2021 }
2022 peephole();
2023 fg=jump_optimization();
2024 }
2025 if(flags&4){
2026 int repeat;
2027
2028 if(early_eff_ics&&!no_eff_ics)
2029 mark_eff_ics();
2030
2031 do{
2032 do{
2033 num_exp();
2034 if(DEBUG&1024) print_flowgraph(fg);
2035 if(disable&32)
2036 repeat=r=0;
2037 else
2038 repeat=r=cse(fg,0); /* local cse */
2039 if(DEBUG&1024) printf("local cse returned %d\n",r);
2040 gchanged|=r;
2041 if(r){ /* neue Variablen eingefuegt */
2042 if(DEBUG&1024) printf("must repeat num_vars\n");
2043 free(vilist);
2044 FREEAV;
2045 num_vars();
2046 }
2047 do{
2048 num_copies();
2049 if(DEBUG&1024) print_flowgraph(fg);
2050 if(disable&128)
2051 r=0;
2052 else
2053 r=copy_propagation(fg,0); /* copy propagation */
2054 if(DEBUG&1024) printf("local copy propagation returned %d\n",r);
2055 if(r&2){
2056 if(DEBUG&1024) printf("must repeat num_vars\n");
2057 free(vilist);
2058 FREEAV;
2059 num_vars();
2060 }
2061 gchanged|=r;repeat|=r;
2062 }while(r);
2063 }while(repeat);
2064 repeat=0;
2065 if(flags&32){
2066 num_exp();
2067 if(DEBUG&1024) print_flowgraph(fg);
2068 available_expressions(fg);
2069 if(DEBUG&1024) print_flowgraph(fg);
2070 if(disable&48)
2071 r=0;
2072 else
2073 r=cse(fg,1);
2074 gchanged|=r;repeat|=r;
2075 if(DEBUG&1024) printf("global cse returned %d\n",r);
2076 if(r){ /* neue Variablen eingefuegt */
2077 if(DEBUG&1024) printf("must repeat num_vars\n");
2078 free(vilist);
2079 FREEAV;
2080 num_vars();
2081 gchanged|=r;repeat|=r;
2082 do{
2083 num_copies();
2084 if(DEBUG&1024) print_flowgraph(fg);
2085 if(disable&128)
2086 r=0;
2087 else
2088 r=copy_propagation(fg,0); /* copy propagation */
2089 if(DEBUG&1024) printf("local copy propagation returned %d\n",r);
2090 if(r&2){
2091 if(DEBUG&1024) printf("must repeat num_vars\n");
2092 free(vilist);
2093 FREEAV;
2094 num_vars();
2095 }
2096 gchanged|=r;repeat|=r;
2097 }while(r);
2098 }
2099 num_copies();
2100 available_copies(fg);
2101 if(DEBUG&1024) print_flowgraph(fg);
2102 if(disable&192)
2103 r=0;
2104 else
2105 r=copy_propagation(fg,1); /* copy propagation */
2106 if(DEBUG&1024) printf("global copy propagation returned %d\n",r);
2107 if(r&2){
2108 if(DEBUG&1024) printf("must repeat num_vars\n");
2109 free(vilist);
2110 FREEAV;
2111 num_vars();
2112 }
2113 gchanged|=r;repeat|=r;
2114 }
2115 }while(0/*repeat*/);
2116 }
2117 if((flags&160)==160){
2118 if(!no_eff_ics)
2119 mark_eff_ics();
2120
2121 r=loop_optimizations(fg);
2122 gchanged|=r;
2123 fg=jump_optimization();
2124 }
2125 if((flags&16)||((flags&1)&&pass>=maxoptpasses)){
2126 /* num_vars();*/
2127 free_alias(fg);
2128 create_alias(fg);
2129 active_vars(fg);
2130 if(DEBUG&1024) print_flowgraph(fg);
2131 if((flags&16)&&pass<=maxoptpasses){
2132 r=dead_assignments(fg);
2133 if(DEBUG&1024) printf("dead_assignments returned %d\n",r);
2134 gchanged|=r;
2135 }
2136 }
2137
2138 if(!gchanged){
2139 int r;
2140 r=insert_const_memcpy(fg);
2141 if(r){
2142 gchanged|=1;
2143 pass--;
2144 }
2145 }
2146
2147#if HAVE_LIBCALLS
2148 /* if no further optimizations are found, insert libcalls
2149 and look some more */
2150 if(!lc_done&&(!gchanged||pass>=maxoptpasses)){
2151 int r;
2152 r=insert_libcalls(fg);
2153 lc_done=1;
2154 if(r){
2155 gchanged|=1;
2156 pass--;
2157 }
2158 }
2159#endif
2160
2161 if((!gchanged||pass>=maxoptpasses)){
2162 /* Funktion evtl. fuer inlining vorbereiten und */
2163 /* Registervergabe */
2164 int varargs=0,c;
2165 if((c=function->vtyp->exact->count)!=0&&(*function->vtyp->exact->sl)[c-1].styp->flags!=VOID)
2166 varargs=1;
2167
2168 /* default-Wert fuer inline-Entscheidung */
2169 if(!cross_module&&!varargs&&(flags&4096)&&(only_inline||ic_count<=inline_size)){
2170 /* fuer function inlining vorbereiten */
2171 IC *p,*new;
2172 if(DEBUG&1024) printf("function <%s> prepared for inlining(ic_count=%d)\n",function->identifier,ic_count);
2173 if(!function->fi) function->fi=new_fi();
2174 function->fi->first_ic=first_ic;
2175 function->fi->last_ic=last_ic;
2176 first_ic=last_ic=0;
2177 p=function->fi->first_ic;
2178 while(p){
2179 new=new_IC();
2180 memcpy(new,p,ICS);
2181 p->copy=new;
2182 if((p->code>=BEQ&&p->code<=BRA)||p->code==LABEL)
2183 new->typf-=lastlabel;
2184 new->q1.flags&=~SCRATCH;
2185 new->q2.flags&=~SCRATCH;
2186 new->z.flags&=~SCRATCH;
2187 add_IC(new);
2188 new->file=p->file;
2189 new->line=p->line;
2190 if(new->code==CALL){
2191 int i;
2192 new->arg_list=mymalloc(sizeof(*new->arg_list)*new->arg_cnt);
2193 for(i=0;i<new->arg_cnt;i++) new->arg_list[i]=p->arg_list[i]->copy;
2194 }
2195 p=p->next;
2196 }
2197 p=first_ic;first_ic=function->fi->first_ic;function->fi->first_ic=p;
2198 p=last_ic;last_ic=function->fi->last_ic;function->fi->last_ic=p;
2199 function->fi->vars=0;
2200 }
2201
2202 if(cross_module) calc_finfo(function,CALC_USES|CALC_CHANGES|(prefer_statics?CALC_CALLS:0));
2203
2204
2205 if(flags&1){
2206 local_combine(fg);
2207 if(DEBUG&1024) print_flowgraph(fg);
2208 if(coloring){
2209#ifdef ALEX_REG
2210 if(DEBUG&1024) print_flowgraph(fg);
2211 loops(fg,1);
2212 num_defs();
2213 reaching_definitions(fg);
2214 GCAssignRegs(fg,function->identifier);
2215 {
2216 int stack_used;IC *p;
2217#if 1
2218 for(p=pFg->start;p;p=p->next){
2219 if((p->q1.flags&(REG|VAR))==VAR&&zmleq(l2zm(0L),p->q1.v->offset))
2220 break;
2221 if((p->q2.flags&(REG|VAR))==VAR&&zmleq(l2zm(0L),p->q2.v->offset))
2222 break;
2223 if((p->z.flags&(REG|VAR))==VAR&&zmleq(l2zm(0L),p->z.v->offset))
2224 break;
2225 }
2226 if(!p) max_offset=l2zm(0L);
2227#endif
2228 }
2229
2230 fg = pFg;
2231#else
2232 ierror(0);
2233#endif
2234 }else{
2235 local_regs(fg);
2236 if(DEBUG&1024) print_flowgraph(fg);
2237 loops(fg,1);
2238 if(DEBUG&1024) print_flowgraph(fg);
2239 fg=create_loop_headers(fg,1);
2240 if(DEBUG&1024) print_flowgraph(fg);
2241 fg=create_loop_footers(fg,1);
2242 if(DEBUG&1024) print_flowgraph(fg);
2243 if(!(disable&8192))
2244 create_const_vars(fg);
2245 loop_regs(fg,intask);
2246 if(DEBUG&1024) print_flowgraph(fg);
2247#if 0
2248 if(flags&64){
2249 block_regs(fg);
2250 if(DEBUG&1024) print_flowgraph(fg);
2251 }
2252#endif
2253 /* calculate optimized size for cross-module-inlining */
2254 {
2255 IC *p;
2256 if(!function->fi) function->fi=new_fi();
2257 function->fi->inline_size=0;
2258 for(p=first_ic;p;p=p->next) function->fi->inline_size++;
2259 if(DEBUG&1024) printf("inline_size=%ld\n",function->fi->inline_size);
2260 }
2261
2262 insert_regs(fg);
2263 insert_saves(fg);
2264 if(prefer_statics||force_statics) replace_statics(function);
2265
2266 if(flags&256) recalc_offsets(fg);
2267 free_const_vars();
2268 }
2269 }
2270 }
2271
2272 free_alias(fg);
2273 free_flowgraph(fg);
2274 free(vilist);
2275 FREEAV;
2276
2277 if((flags&32)&&gchanged&&pass>=maxoptpasses) error(172,maxoptpasses);
2278
2279 }while(gchanged&&pass<maxoptpasses);
2280 /* nur, um nochmal ueberfluessige Labels zu entfernen */
2281 fg=construct_flowgraph();
2282 free_flowgraph(fg);
2283 combine_const_assigns();
2284
2285#endif
2286
2287 }else{
2288 /* keine Optimierungen */
2289 if(flags&1) simple_regs();
2290 load_simple_reg_parms();
2291 }
2292#ifndef NO_OPTIMIZER
2293 add_call_list();
2294#endif
2295
2296 lastlabel=label;
2297}
2298
2299
2300