4 Bot
= -2, /* lattice bottom */
5 Top
= -1, /* lattice top */
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
);
129 assert(l
!= Top
&& "ssa invariant broken");
131 edge
[n
][1].work
= flowrk
;
132 edge
[n
][0].work
= &edge
[n
][1];
133 flowrk
= &edge
[n
][0];
135 else if (iscon(&fn
->con
[l
], 0, 0)) {
136 assert(edge
[n
][0].dead
);
137 edge
[n
][1].work
= flowrk
;
138 flowrk
= &edge
[n
][1];
141 assert(edge
[n
][1].dead
);
142 edge
[n
][0].work
= flowrk
;
143 flowrk
= &edge
[n
][0];
147 edge
[n
][0].work
= flowrk
;
148 flowrk
= &edge
[n
][0];
153 if (isret(b
->jmp
.type
))
160 initedge(Edge
*e
, Blk
*s
)
175 if (rtype(*r
) == RTmp
)
176 if ((l
=val
[r
->val
]) != Bot
) {
177 assert(l
!= Top
&& "ssa invariant broken");
184 /* require rpo, use, pred */
196 val
= emalloc(fn
->ntmp
* sizeof val
[0]);
197 edge
= emalloc(fn
->nblk
* sizeof edge
[0]);
198 usewrk
= vnew(0, sizeof usewrk
[0], PHeap
);
200 for (t
=0; t
<fn
->ntmp
; t
++)
202 for (n
=0; n
<fn
->nblk
; n
++) {
205 initedge(&edge
[n
][0], b
->s1
);
206 initedge(&edge
[n
][1], b
->s2
);
208 initedge(&start
, fn
->start
);
212 /* 1. find out constants and dead cfg edges */
218 if (e
->dest
== -1 || !e
->dead
)
223 for (p
=b
->phi
; p
; p
=p
->link
)
226 for (i
=b
->ins
; i
<&b
->ins
[b
->nins
]; i
++)
231 assert(b
->jmp
.type
!= Jjmp
233 || flowrk
== &edge
[n
][0]);
243 visitphi(u
->u
.phi
, u
->bid
, fn
);
246 visitins(u
->u
.ins
, fn
);
260 fprintf(stderr
, "\n> SCCP findings:");
261 for (t
=Tmp0
; t
<fn
->ntmp
; t
++) {
264 fprintf(stderr
, "\n%10s: ", fn
->tmp
[t
].name
);
266 fprintf(stderr
, "Top");
268 printref(CON(val
[t
]), fn
, stderr
);
270 fprintf(stderr
, "\n dead code: ");
273 /* 2. trim dead code, replace constants */
275 for (pb
=&fn
->start
; (b
=*pb
);) {
279 fprintf(stderr
, "%s ", b
->name
);
285 for (pp
=&b
->phi
; (p
=*pp
);)
286 if (val
[p
->to
.val
] != Bot
)
289 for (a
=0; a
<p
->narg
; a
++)
290 if (!deadedge(p
->blk
[a
]->id
, b
->id
))
294 for (i
=b
->ins
; i
<&b
->ins
[b
->nins
]; i
++)
296 *i
= (Ins
){.op
= Onop
};
301 if (b
->jmp
.type
== Jjnz
&& rtype(b
->jmp
.arg
) == RCon
) {
302 if (iscon(&fn
->con
[b
->jmp
.arg
.val
], 0, 0)) {
316 fprintf(stderr
, "(none)");
317 fprintf(stderr
, "\n\n> After constant folding:\n");
326 /* boring folding code */
329 foldint(Con
*res
, int op
, int w
, Con
*cl
, Con
*cr
)
341 memset(&sym
, 0, sizeof sym
);
346 if (cl
->type
== CAddr
) {
347 if (cr
->type
== CAddr
)
352 else if (cr
->type
== CAddr
) {
357 else if (op
== Osub
) {
358 if (cl
->type
== CAddr
) {
359 if (cr
->type
!= CAddr
) {
362 } else if (!symeq(cl
->sym
, cr
->sym
))
365 else if (cr
->type
== CAddr
)
368 else if (cl
->type
== CAddr
|| cr
->type
== CAddr
)
370 if (op
== Odiv
|| op
== Orem
|| op
== Oudiv
|| op
== Ourem
) {
373 if (op
== Odiv
|| op
== Orem
) {
374 x
= w
? INT64_MIN
: INT32_MIN
;
375 if (iscon(cr
, w
, -1))
381 case Oadd
: x
= l
.u
+ r
.u
; break;
382 case Osub
: x
= l
.u
- r
.u
; break;
383 case Oneg
: x
= -l
.u
; break;
384 case Odiv
: x
= w
? l
.s
/ r
.s
: (int32_t)l
.s
/ (int32_t)r
.s
; break;
385 case Orem
: x
= w
? l
.s
% r
.s
: (int32_t)l
.s
% (int32_t)r
.s
; break;
386 case Oudiv
: x
= w
? l
.u
/ r
.u
: (uint32_t)l
.u
/ (uint32_t)r
.u
; break;
387 case Ourem
: x
= w
? l
.u
% r
.u
: (uint32_t)l
.u
% (uint32_t)r
.u
; break;
388 case Omul
: x
= l
.u
* r
.u
; break;
389 case Oand
: x
= l
.u
& r
.u
; break;
390 case Oor
: x
= l
.u
| r
.u
; break;
391 case Oxor
: x
= l
.u
^ r
.u
; break;
392 case Osar
: x
= (w
? l
.s
: (int32_t)l
.s
) >> (r
.u
& (31|w
<<5)); break;
393 case Oshr
: x
= (w
? l
.u
: (uint32_t)l
.u
) >> (r
.u
& (31|w
<<5)); break;
394 case Oshl
: x
= l
.u
<< (r
.u
& (31|w
<<5)); break;
395 case Oextsb
: x
= (int8_t)l
.u
; break;
396 case Oextub
: x
= (uint8_t)l
.u
; break;
397 case Oextsh
: x
= (int16_t)l
.u
; break;
398 case Oextuh
: x
= (uint16_t)l
.u
; break;
399 case Oextsw
: x
= (int32_t)l
.u
; break;
400 case Oextuw
: x
= (uint32_t)l
.u
; break;
401 case Ostosi
: x
= w
? (int64_t)cl
->bits
.s
: (int32_t)cl
->bits
.s
; break;
402 case Ostoui
: x
= w
? (uint64_t)cl
->bits
.s
: (uint32_t)cl
->bits
.s
; break;
403 case Odtosi
: x
= w
? (int64_t)cl
->bits
.d
: (int32_t)cl
->bits
.d
; break;
404 case Odtoui
: x
= w
? (uint64_t)cl
->bits
.d
: (uint32_t)cl
->bits
.d
; break;
407 if (cl
->type
== CAddr
) {
413 if (Ocmpw
<= op
&& op
<= Ocmpl1
) {
419 switch (op
- Ocmpw
) {
420 case Ciule
: x
= l
.u
<= r
.u
; break;
421 case Ciult
: x
= l
.u
< r
.u
; break;
422 case Cisle
: x
= l
.s
<= r
.s
; break;
423 case Cislt
: x
= l
.s
< r
.s
; break;
424 case Cisgt
: x
= l
.s
> r
.s
; break;
425 case Cisge
: x
= l
.s
>= r
.s
; break;
426 case Ciugt
: x
= l
.u
> r
.u
; break;
427 case Ciuge
: x
= l
.u
>= r
.u
; break;
428 case Cieq
: x
= l
.u
== r
.u
; break;
429 case Cine
: x
= l
.u
!= r
.u
; break;
430 default: die("unreachable");
433 else if (Ocmps
<= op
&& op
<= Ocmps1
) {
434 switch (op
- Ocmps
) {
435 case Cfle
: x
= l
.fs
<= r
.fs
; break;
436 case Cflt
: x
= l
.fs
< r
.fs
; break;
437 case Cfgt
: x
= l
.fs
> r
.fs
; break;
438 case Cfge
: x
= l
.fs
>= r
.fs
; break;
439 case Cfne
: x
= l
.fs
!= r
.fs
; break;
440 case Cfeq
: x
= l
.fs
== r
.fs
; break;
441 case Cfo
: x
= l
.fs
< r
.fs
|| l
.fs
>= r
.fs
; break;
442 case Cfuo
: x
= !(l
.fs
< r
.fs
|| l
.fs
>= r
.fs
); break;
443 default: die("unreachable");
446 else if (Ocmpd
<= op
&& op
<= Ocmpd1
) {
447 switch (op
- Ocmpd
) {
448 case Cfle
: x
= l
.fd
<= r
.fd
; break;
449 case Cflt
: x
= l
.fd
< r
.fd
; break;
450 case Cfgt
: x
= l
.fd
> r
.fd
; break;
451 case Cfge
: x
= l
.fd
>= r
.fd
; break;
452 case Cfne
: x
= l
.fd
!= r
.fd
; break;
453 case Cfeq
: x
= l
.fd
== r
.fd
; break;
454 case Cfo
: x
= l
.fd
< r
.fd
|| l
.fd
>= r
.fd
; break;
455 case Cfuo
: x
= !(l
.fd
< r
.fd
|| l
.fd
>= r
.fd
); break;
456 default: die("unreachable");
462 *res
= (Con
){.type
=typ
, .sym
=sym
, .bits
={.i
=x
}};
467 foldflt(Con
*res
, int op
, int w
, Con
*cl
, Con
*cr
)
472 if (cl
->type
!= CBits
|| cr
->type
!= CBits
)
473 err("invalid address operand for '%s'", optab
[op
].name
);
474 *res
= (Con
){.type
= CBits
};
475 memset(&res
->bits
, 0, sizeof(res
->bits
));
480 case Oadd
: xd
= ld
+ rd
; break;
481 case Osub
: xd
= ld
- rd
; break;
482 case Oneg
: xd
= -ld
; break;
483 case Odiv
: xd
= ld
/ rd
; break;
484 case Omul
: xd
= ld
* rd
; break;
485 case Oswtof
: xd
= (int32_t)cl
->bits
.i
; break;
486 case Ouwtof
: xd
= (uint32_t)cl
->bits
.i
; break;
487 case Osltof
: xd
= (int64_t)cl
->bits
.i
; break;
488 case Oultof
: xd
= (uint64_t)cl
->bits
.i
; break;
489 case Oexts
: xd
= cl
->bits
.s
; break;
490 case Ocast
: xd
= ld
; break;
491 default: die("unreachable");
499 case Oadd
: xs
= ls
+ rs
; break;
500 case Osub
: xs
= ls
- rs
; break;
501 case Oneg
: xs
= -ls
; break;
502 case Odiv
: xs
= ls
/ rs
; break;
503 case Omul
: xs
= ls
* rs
; break;
504 case Oswtof
: xs
= (int32_t)cl
->bits
.i
; break;
505 case Ouwtof
: xs
= (uint32_t)cl
->bits
.i
; break;
506 case Osltof
: xs
= (int64_t)cl
->bits
.i
; break;
507 case Oultof
: xs
= (uint64_t)cl
->bits
.i
; break;
508 case Otruncd
: xs
= cl
->bits
.d
; break;
509 case Ocast
: xs
= ls
; break;
510 default: die("unreachable");
518 opfold(int op
, int cls
, Con
*cl
, Con
*cr
, Fn
*fn
)
523 if (cls
== Kw
|| cls
== Kl
) {
524 if (foldint(&c
, op
, cls
== Kl
, cl
, cr
))
527 foldflt(&c
, op
, cls
== Kd
, cl
, cr
);
529 c
.bits
.i
&= 0xffffffff;
531 assert(!(cls
== Ks
|| cls
== Kd
) || c
.flt
);