4 Bot
= -1, /* lattice bottom */
5 Top
= 0, /* lattice top (matches UNDEF) */
8 typedef struct Edge Edge
;
17 static Edge
*flowrk
, (*edge
)[2];
22 iscon(Con
*c
, int w
, uint64_t k
)
27 return (uint64_t)c
->bits
.i
== k
;
29 return (uint32_t)c
->bits
.i
== (uint32_t)k
;
46 latmerge(int v
, int m
)
48 return m
== Top
? v
: (v
== Top
|| v
== m
) ? m
: Bot
;
52 update(int t
, int m
, Fn
*fn
)
57 m
= latmerge(val
[t
], m
);
60 for (u
=0; u
<tmp
->nuse
; u
++) {
61 vgrow(&usewrk
, ++nuse
);
62 usewrk
[nuse
-1] = &tmp
->use
[u
];
69 deadedge(int s
, int d
)
74 if (e
[0].dest
== d
&& !e
[0].dead
)
76 if (e
[1].dest
== d
&& !e
[1].dead
)
82 visitphi(Phi
*p
, int n
, Fn
*fn
)
88 for (a
=0; a
<p
->narg
; a
++)
89 if (!deadedge(p
->blk
[a
]->id
, n
))
90 v
= latmerge(v
, latval(p
->arg
[a
]));
91 update(p
->to
.val
, v
, fn
);
94 static int opfold(int, int, Con
*, Con
*, Fn
*);
97 visitins(Ins
*i
, Fn
*fn
)
101 if (rtype(i
->to
) != RTmp
)
103 if (optab
[i
->op
].canfold
) {
104 l
= latval(i
->arg
[0]);
105 if (!req(i
->arg
[1], R
))
106 r
= latval(i
->arg
[1]);
109 if (l
== Bot
|| r
== Bot
)
111 else if (l
== Top
|| r
== Top
)
114 v
= opfold(i
->op
, i
->cls
, &fn
->con
[l
], &fn
->con
[r
], fn
);
117 /* fprintf(stderr, "\nvisiting %s (%p)", optab[i->op].name, (void *)i); */
118 update(i
->to
.val
, v
, fn
);
122 visitjmp(Blk
*b
, int n
, Fn
*fn
)
126 switch (b
->jmp
.type
) {
128 l
= latval(b
->jmp
.arg
);
130 edge
[n
][1].work
= flowrk
;
131 edge
[n
][0].work
= &edge
[n
][1];
132 flowrk
= &edge
[n
][0];
134 else if (iscon(&fn
->con
[l
], 0, 0)) {
135 assert(edge
[n
][0].dead
);
136 edge
[n
][1].work
= flowrk
;
137 flowrk
= &edge
[n
][1];
140 assert(edge
[n
][1].dead
);
141 edge
[n
][0].work
= flowrk
;
142 flowrk
= &edge
[n
][0];
146 edge
[n
][0].work
= flowrk
;
147 flowrk
= &edge
[n
][0];
152 if (isret(b
->jmp
.type
))
159 initedge(Edge
*e
, Blk
*s
)
174 if (rtype(*r
) == RTmp
)
175 if ((l
=val
[r
->val
]) != Bot
) {
182 /* require rpo, use, pred */
194 val
= emalloc(fn
->ntmp
* sizeof val
[0]);
195 edge
= emalloc(fn
->nblk
* sizeof edge
[0]);
196 usewrk
= vnew(0, sizeof usewrk
[0], PHeap
);
198 for (t
=0; t
<fn
->ntmp
; t
++)
200 for (n
=0; n
<fn
->nblk
; n
++) {
203 initedge(&edge
[n
][0], b
->s1
);
204 initedge(&edge
[n
][1], b
->s2
);
206 initedge(&start
, fn
->start
);
210 /* 1. find out constants and dead cfg edges */
216 if (e
->dest
== -1 || !e
->dead
)
221 for (p
=b
->phi
; p
; p
=p
->link
)
224 for (i
=b
->ins
; i
<&b
->ins
[b
->nins
]; i
++)
229 assert(b
->jmp
.type
!= Jjmp
231 || flowrk
== &edge
[n
][0]);
241 visitphi(u
->u
.phi
, u
->bid
, fn
);
244 visitins(u
->u
.ins
, fn
);
258 fprintf(stderr
, "\n> SCCP findings:");
259 for (t
=Tmp0
; t
<fn
->ntmp
; t
++) {
262 fprintf(stderr
, "\n%10s: ", fn
->tmp
[t
].name
);
264 fprintf(stderr
, "Top");
266 printref(CON(val
[t
]), fn
, stderr
);
268 fprintf(stderr
, "\n dead code: ");
271 /* 2. trim dead code, replace constants */
273 for (pb
=&fn
->start
; (b
=*pb
);) {
277 fprintf(stderr
, "%s ", b
->name
);
283 for (pp
=&b
->phi
; (p
=*pp
);)
284 if (val
[p
->to
.val
] != Bot
)
287 for (a
=0; a
<p
->narg
; a
++)
288 if (!deadedge(p
->blk
[a
]->id
, b
->id
))
292 for (i
=b
->ins
; i
<&b
->ins
[b
->nins
]; i
++)
294 *i
= (Ins
){.op
= Onop
};
299 if (req(i
->arg
[0], UNDEF
))
300 *i
= (Ins
){.op
= Onop
};
303 if (b
->jmp
.type
== Jjnz
&& rtype(b
->jmp
.arg
) == RCon
) {
304 if (iscon(&fn
->con
[b
->jmp
.arg
.val
], 0, 0)) {
318 fprintf(stderr
, "(none)");
319 fprintf(stderr
, "\n\n> After constant folding:\n");
328 /* boring folding code */
331 foldint(Con
*res
, int op
, int w
, Con
*cl
, Con
*cr
)
343 memset(&sym
, 0, sizeof sym
);
348 if (cl
->type
== CAddr
) {
349 if (cr
->type
== CAddr
)
354 else if (cr
->type
== CAddr
) {
359 else if (op
== Osub
) {
360 if (cl
->type
== CAddr
) {
361 if (cr
->type
!= CAddr
) {
364 } else if (!symeq(cl
->sym
, cr
->sym
))
367 else if (cr
->type
== CAddr
)
370 else if (cl
->type
== CAddr
|| cr
->type
== CAddr
)
372 if (op
== Odiv
|| op
== Orem
|| op
== Oudiv
|| op
== Ourem
) {
375 if (op
== Odiv
|| op
== Orem
) {
376 x
= w
? INT64_MIN
: INT32_MIN
;
377 if (iscon(cr
, w
, -1))
383 case Oadd
: x
= l
.u
+ r
.u
; break;
384 case Osub
: x
= l
.u
- r
.u
; break;
385 case Oneg
: x
= -l
.u
; break;
386 case Odiv
: x
= w
? l
.s
/ r
.s
: (int32_t)l
.s
/ (int32_t)r
.s
; break;
387 case Orem
: x
= w
? l
.s
% r
.s
: (int32_t)l
.s
% (int32_t)r
.s
; break;
388 case Oudiv
: x
= w
? l
.u
/ r
.u
: (uint32_t)l
.u
/ (uint32_t)r
.u
; break;
389 case Ourem
: x
= w
? l
.u
% r
.u
: (uint32_t)l
.u
% (uint32_t)r
.u
; break;
390 case Omul
: x
= l
.u
* r
.u
; break;
391 case Oand
: x
= l
.u
& r
.u
; break;
392 case Oor
: x
= l
.u
| r
.u
; break;
393 case Oxor
: x
= l
.u
^ r
.u
; break;
394 case Osar
: x
= (w
? l
.s
: (int32_t)l
.s
) >> (r
.u
& (31|w
<<5)); break;
395 case Oshr
: x
= (w
? l
.u
: (uint32_t)l
.u
) >> (r
.u
& (31|w
<<5)); break;
396 case Oshl
: x
= l
.u
<< (r
.u
& (31|w
<<5)); break;
397 case Oextsb
: x
= (int8_t)l
.u
; break;
398 case Oextub
: x
= (uint8_t)l
.u
; break;
399 case Oextsh
: x
= (int16_t)l
.u
; break;
400 case Oextuh
: x
= (uint16_t)l
.u
; break;
401 case Oextsw
: x
= (int32_t)l
.u
; break;
402 case Oextuw
: x
= (uint32_t)l
.u
; break;
403 case Ostosi
: x
= w
? (int64_t)cl
->bits
.s
: (int32_t)cl
->bits
.s
; break;
404 case Ostoui
: x
= w
? (uint64_t)cl
->bits
.s
: (uint32_t)cl
->bits
.s
; break;
405 case Odtosi
: x
= w
? (int64_t)cl
->bits
.d
: (int32_t)cl
->bits
.d
; break;
406 case Odtoui
: x
= w
? (uint64_t)cl
->bits
.d
: (uint32_t)cl
->bits
.d
; break;
409 if (cl
->type
== CAddr
) {
415 if (Ocmpw
<= op
&& op
<= Ocmpl1
) {
421 switch (op
- Ocmpw
) {
422 case Ciule
: x
= l
.u
<= r
.u
; break;
423 case Ciult
: x
= l
.u
< r
.u
; break;
424 case Cisle
: x
= l
.s
<= r
.s
; break;
425 case Cislt
: x
= l
.s
< r
.s
; break;
426 case Cisgt
: x
= l
.s
> r
.s
; break;
427 case Cisge
: x
= l
.s
>= r
.s
; break;
428 case Ciugt
: x
= l
.u
> r
.u
; break;
429 case Ciuge
: x
= l
.u
>= r
.u
; break;
430 case Cieq
: x
= l
.u
== r
.u
; break;
431 case Cine
: x
= l
.u
!= r
.u
; break;
432 default: die("unreachable");
435 else if (Ocmps
<= op
&& op
<= Ocmps1
) {
436 switch (op
- Ocmps
) {
437 case Cfle
: x
= l
.fs
<= r
.fs
; break;
438 case Cflt
: x
= l
.fs
< r
.fs
; break;
439 case Cfgt
: x
= l
.fs
> r
.fs
; break;
440 case Cfge
: x
= l
.fs
>= r
.fs
; break;
441 case Cfne
: x
= l
.fs
!= r
.fs
; break;
442 case Cfeq
: x
= l
.fs
== r
.fs
; break;
443 case Cfo
: x
= l
.fs
< r
.fs
|| l
.fs
>= r
.fs
; break;
444 case Cfuo
: x
= !(l
.fs
< r
.fs
|| l
.fs
>= r
.fs
); break;
445 default: die("unreachable");
448 else if (Ocmpd
<= op
&& op
<= Ocmpd1
) {
449 switch (op
- Ocmpd
) {
450 case Cfle
: x
= l
.fd
<= r
.fd
; break;
451 case Cflt
: x
= l
.fd
< r
.fd
; break;
452 case Cfgt
: x
= l
.fd
> r
.fd
; break;
453 case Cfge
: x
= l
.fd
>= r
.fd
; break;
454 case Cfne
: x
= l
.fd
!= r
.fd
; break;
455 case Cfeq
: x
= l
.fd
== r
.fd
; break;
456 case Cfo
: x
= l
.fd
< r
.fd
|| l
.fd
>= r
.fd
; break;
457 case Cfuo
: x
= !(l
.fd
< r
.fd
|| l
.fd
>= r
.fd
); break;
458 default: die("unreachable");
464 *res
= (Con
){.type
=typ
, .sym
=sym
, .bits
={.i
=x
}};
469 foldflt(Con
*res
, int op
, int w
, Con
*cl
, Con
*cr
)
474 if (cl
->type
!= CBits
|| cr
->type
!= CBits
)
475 err("invalid address operand for '%s'", optab
[op
].name
);
476 *res
= (Con
){.type
= CBits
};
477 memset(&res
->bits
, 0, sizeof(res
->bits
));
482 case Oadd
: xd
= ld
+ rd
; break;
483 case Osub
: xd
= ld
- rd
; break;
484 case Oneg
: xd
= -ld
; break;
485 case Odiv
: xd
= ld
/ rd
; break;
486 case Omul
: xd
= ld
* rd
; break;
487 case Oswtof
: xd
= (int32_t)cl
->bits
.i
; break;
488 case Ouwtof
: xd
= (uint32_t)cl
->bits
.i
; break;
489 case Osltof
: xd
= (int64_t)cl
->bits
.i
; break;
490 case Oultof
: xd
= (uint64_t)cl
->bits
.i
; break;
491 case Oexts
: xd
= cl
->bits
.s
; break;
492 case Ocast
: xd
= ld
; break;
493 default: die("unreachable");
501 case Oadd
: xs
= ls
+ rs
; break;
502 case Osub
: xs
= ls
- rs
; break;
503 case Oneg
: xs
= -ls
; break;
504 case Odiv
: xs
= ls
/ rs
; break;
505 case Omul
: xs
= ls
* rs
; break;
506 case Oswtof
: xs
= (int32_t)cl
->bits
.i
; break;
507 case Ouwtof
: xs
= (uint32_t)cl
->bits
.i
; break;
508 case Osltof
: xs
= (int64_t)cl
->bits
.i
; break;
509 case Oultof
: xs
= (uint64_t)cl
->bits
.i
; break;
510 case Otruncd
: xs
= cl
->bits
.d
; break;
511 case Ocast
: xs
= ls
; break;
512 default: die("unreachable");
520 opfold(int op
, int cls
, Con
*cl
, Con
*cr
, Fn
*fn
)
525 if (cls
== Kw
|| cls
== Kl
) {
526 if (foldint(&c
, op
, cls
== Kl
, cl
, cr
))
529 foldflt(&c
, op
, cls
== Kd
, cl
, cr
);
531 c
.bits
.i
&= 0xffffffff;
533 assert(!(cls
== Ks
|| cls
== Kd
) || c
.flt
);