diff options
| author | 2025-11-23 21:54:40 +0100 | |
|---|---|---|
| committer | 2025-11-23 21:57:01 +0100 | |
| commit | 6464ec389e2da17b1674858858406e211b16e5f6 (patch) | |
| tree | 1b82b733851b88a0868635c6ab5afe1ea2298b7c /ir/builder.c | |
| parent | d79251d487b57ea0e3b10640747eed723a06365c (diff) | |
ir: implement cvtu64f. and other bug fixes
compiler is bootstrapping?! however, stage1 and stage2+ executables
aren't bit-identical.. small differences in the codegen.. need to look into that
Diffstat (limited to 'ir/builder.c')
| -rw-r--r-- | ir/builder.c | 37 |
1 files changed, 35 insertions, 2 deletions
diff --git a/ir/builder.c b/ir/builder.c index 752c1bc..c793f80 100644 --- a/ir/builder.c +++ b/ir/builder.c @@ -20,6 +20,7 @@ irbinop(struct function *fn, enum op op, enum irclass k, union ref l, union ref break; case Omul: if (isnumcon(l)) rswap(l, r); /* put const in rhs */ + if (kisflt(k)) break; if (r.bits == ZEROREF.bits) /* x * 0 ==> 0 */ return ZEROREF; if (r.bits == ONE.bits) /* x * 1 ==> x */ @@ -33,6 +34,7 @@ irbinop(struct function *fn, enum op op, enum irclass k, union ref l, union ref case Odiv: break; case Oudiv: + if (kisflt(k)) break; if (isintcon(r) && ispo2(iv = intconval(r))) { /* x / 2^y ==> x >> y */ op = Oslr; @@ -42,6 +44,7 @@ irbinop(struct function *fn, enum op op, enum irclass k, union ref l, union ref case Orem: break; case Ourem: + if (kisflt(k)) break; if (isintcon(r) && ispo2(iv = intconval(r))) { /* x % 2^y ==> x & 2^y-1 */ op = Oand; @@ -123,6 +126,33 @@ cvtfu64(struct function *fn, enum irclass from, union ref x) return addphi(fn, KI64, phiarg); } +/* implements u64 -> f32/f64 conversion */ +static union ref +cvtu64f(struct function *fn, enum irclass to, union ref x) +{ + struct block *t, *f, *merge; + union ref t1, t2, phiarg[2]; + + /* if ((s64)x >= 0) cvts64f(x) else cvts64f((x>>1)|(x&1))*2 */ + + putcondbranch(fn, irbinop(fn, Ogte, KI64, x, ZEROREF), t = newblk(fn), f = newblk(fn)); + + useblk(fn, t); + phiarg[0] = irunop(fn, Ocvts64f, to, x); + putbranch(fn, merge = newblk(fn)); + + useblk(fn, f); + t1 = irbinop(fn, Oslr, KI64, x, mkref(RICON, 1)); + t2 = irbinop(fn, Oand, KI64, x, mkref(RICON, 1)); + t1 = irbinop(fn, Oior, KI64, t1, t2); + t1 = irunop(fn, Ocvts64f, to, t1); + phiarg[1] = irbinop(fn, Oadd, to, t1, t1); + putbranch(fn, merge); + + useblk(fn, merge); + return addphi(fn, to, phiarg); +} + union ref irunop(struct function *fn, enum op op, enum irclass k, union ref a) { @@ -141,6 +171,8 @@ irunop(struct function *fn, enum op op, enum irclass k, union ref a) return ins->l; break; case Ocvtf32s: case Ocvtf32f64: case Ocvtf64s: + case Ocvtf64f32: case Ocvts32f: case Ocvtu32f: + case Ocvts64f: break; case Ocvtf32u: case Ocvtf64u: if (k == KI64) { @@ -150,8 +182,9 @@ irunop(struct function *fn, enum op op, enum irclass k, union ref a) return cvtfu64(fn, op == Ocvtf32u ? KF32 : KF64, a); } break; - case Ocvtf64f32: case Ocvts32f: case Ocvtu32f: - case Ocvts64f: case Ocvtu64f: + case Ocvtu64f: + /* XXX see above */ + return cvtu64f(fn, k, a); case Oexts8: case Oextu8: case Oexts16: case Oextu16: case Oexts32: case Oextu32: case Ocopy: |