diff --git a/all.h b/all.h index 560f5bd..d00a87f 100644 --- a/all.h +++ b/all.h @@ -240,11 +240,11 @@ struct Ins { struct Phi { Ref to; + short cls; + int visit; + uint narg; Ref *arg; Blk **blk; - uint narg; - short cls; - uint visit:1; Phi *link; }; diff --git a/copy.c b/copy.c index e7d7e72..658a381 100644 --- a/copy.c +++ b/copy.c @@ -41,6 +41,20 @@ bitwidth(uint64_t v) return n+v; } +static int +visit(Fn *fn, Ref r, int w, int f(Fn *, Ref, int)) +{ + Blk *b; + Phi *p; + int ret; + + ret = f(fn, r, w); + for (b=fn->start; b; b=b->link) + for (p=b->phi; p; p=p->link) + p->visit = 0; + return ret; +} + static int uwl(Fn *fn, Ref r, int w) { @@ -107,15 +121,7 @@ uwl(Fn *fn, Ref r, int w) static int usewidthle(Fn *fn, Ref r, int w) { - Blk *b; - Phi *p; - int ret; - - ret = uwl(fn, r, w); - for (b=fn->start; b; b=b->link) - for (p=b->phi; p; p=p->link) - p->visit = 0; - return ret; + return visit(fn, r, w, uwl); } static int @@ -124,9 +130,8 @@ min(int v1, int v2) return v1 < v2 ? v1 : v2; } -/* is the ref narrower than w bits */ static int -defwidthle(Fn *fn, Ref r, int w) +dwl(Fn *fn, Ref r, int w) { Ext e; Tmp *t; @@ -139,6 +144,8 @@ defwidthle(Fn *fn, Ref r, int w) if (isconbits(fn, r, &v) && bitwidth(v) <= w) return 1; + if (w <= 0) + return 0; if (rtype(r) != RTmp) return 0; t = &fn->tmp[r.val]; @@ -151,21 +158,18 @@ defwidthle(Fn *fn, Ref r, int w) if (req(p->to, r)) break; assert(p); - if (p->visit) + if (p->visit && p->visit <= w) return 1; - p->visit = 1; + p->visit = w; for (n=0; nnarg; n++) - if (!defwidthle(fn, p->arg[n], w)) { - p->visit = 0; + if (!dwl(fn, p->arg[n], w)) return 0; - } - p->visit = 0; return 1; } i = t->def; if (i->op == Ocopy) - return defwidthle(fn, i->arg[0], w); + return dwl(fn, i->arg[0], w); if (i->op == Oshr || i->op == Osar) { if (isconbits(fn, i->arg[1], &v)) if (0 < v && v <= 32) { @@ -178,19 +182,19 @@ defwidthle(Fn *fn, Ref r, int w) w = min(32, w+v); } } - return defwidthle(fn, i->arg[0], w); + return dwl(fn, i->arg[0], w); } if (iscmp(i->op, &x, &x)) return w >= 1; if (i->op == Oand) { - if (defwidthle(fn, i->arg[0], w) - || defwidthle(fn, i->arg[1], w)) + if (dwl(fn, i->arg[0], w) + || dwl(fn, i->arg[1], w)) return 1; return 0; } if (i->op == Oor || i->op == Oxor) { - if (defwidthle(fn, i->arg[0], w) - && defwidthle(fn, i->arg[1], w)) + if (dwl(fn, i->arg[0], w) + && dwl(fn, i->arg[1], w)) return 1; return 0; } @@ -198,12 +202,19 @@ defwidthle(Fn *fn, Ref r, int w) if (e.zext && e.usew <= w) return 1; w = min(w, e.nopw); - return defwidthle(fn, i->arg[0], w); + return dwl(fn, i->arg[0], w); } return 0; } +/* is the ref narrower than w bits */ +static int +defwidthle(Fn *fn, Ref r, int w) +{ + return visit(fn, r, w, dwl); +} + static int isw1(Fn *fn, Ref r) { diff --git a/test/copy.ssa b/test/copy.ssa index 5c2a4d0..83f9ec7 100644 --- a/test/copy.ssa +++ b/test/copy.ssa @@ -8,8 +8,23 @@ export function w $f() { ret %c } +export function w $g(w %arg) { +@start + %a0 =w extuh %arg # 1 + %a1 =w or 65536, %a0 # 65537 +@loop + %a2 =w phi @loop %a2, @start %a1 # 65537 + jnz %arg, @end, @loop +@end + %a3 =w shr %a2, 1 # 32768 + %a4 =w or %a2, 1 # 65537 + %a5 =w or %a3, %a4 # 98305 + %ret =w extuh %a5 # 32769 + ret %ret +} + # >>> driver # char a = -1; -# extern int f(); -# int main() { return !(f() == 1); } +# extern int f(), g(int); +# int main() { return !(f() == 1 && g(1) == 32769); } # <<<