commit ef68ab406682f3200796e5e302ba984ff56d7b0d
parent fb742ec0e4d8992a9f55bbf40920bd173dde41db
Author: Quentin Carbonneaux <quentin@c9x.me>
Date: Wed, 11 May 2022 18:11:00 +0200
avoid folding overflowing divisions
Thanks to Paul Ouellette for reporting.
Diffstat:
M | fold.c | | | 23 | +++++++++++++++-------- |
1 file changed, 15 insertions(+), 8 deletions(-)
diff --git a/fold.c b/fold.c
@@ -19,14 +19,14 @@ static Use **usewrk;
static uint nuse;
static int
-czero(Con *c, int w)
+iscon(Con *c, int w, uint64_t k)
{
if (c->type != CBits)
return 0;
if (w)
- return c->bits.i == 0;
+ return (uint64_t)c->bits.i == k;
else
- return (uint32_t)c->bits.i == 0;
+ return (uint32_t)c->bits.i == (uint32_t)k;
}
static int
@@ -132,7 +132,7 @@ visitjmp(Blk *b, int n, Fn *fn)
edge[n][0].work = &edge[n][1];
flowrk = &edge[n][0];
}
- else if (czero(&fn->con[l], 0)) {
+ else if (iscon(&fn->con[l], 0, 0)) {
assert(edge[n][0].dead);
edge[n][1].work = flowrk;
flowrk = &edge[n][1];
@@ -297,7 +297,7 @@ fold(Fn *fn)
renref(&i->arg[n]);
renref(&b->jmp.arg);
if (b->jmp.type == Jjnz && rtype(b->jmp.arg) == RCon) {
- if (czero(&fn->con[b->jmp.arg.val], 0)) {
+ if (iscon(&fn->con[b->jmp.arg.val], 0, 0)) {
edgedel(b, &b->s1);
b->s1 = b->s2;
b->s2 = 0;
@@ -365,6 +365,16 @@ foldint(Con *res, int op, int w, Con *cl, Con *cr)
}
else if (cl->type == CAddr || cr->type == CAddr)
return 1;
+ if (op == Odiv || op == Orem || op == Oudiv || op == Ourem) {
+ if (iscon(cr, w, 0))
+ return 1;
+ if (op == Odiv || op == Orem) {
+ x = w ? INT64_MIN : INT32_MIN;
+ if (iscon(cr, w, -1))
+ if (iscon(cl, w, x))
+ return 1;
+ }
+ }
switch (op) {
case Oadd: x = l.u + r.u; break;
case Osub: x = l.u - r.u; break;
@@ -508,9 +518,6 @@ opfold(int op, int cls, Con *cl, Con *cr, Fn *fn)
Ref r;
Con c;
- if ((op == Odiv || op == Oudiv
- || op == Orem || op == Ourem) && czero(cr, KWIDE(cls)))
- return Bot;
if (cls == Kw || cls == Kl) {
if (foldint(&c, op, cls == Kl, cl, cr))
return Bot;