qbe

Internal scc patchset buffer for QBE
Log | Files | Refs | README | LICENSE

commit 2a8584c9853f9392ef0ddcb0ed9b3d2b14b1db83
parent 81da1cdebb213077a1ce2c1aaed051de0751e13c
Author: Quentin Carbonneaux <quentin@c9x.me>
Date:   Mon, 15 Apr 2019 19:51:31 +0200

handle big constants moves to slots

There is no flavor of mov which can set 8 bytes
of memory to a constant not representable as an
int32.  The solution is simply to emit two movs
of 4 bytes each.

Diffstat:
Mamd64/emit.c | 47+++++++++++++++++++++++++++++++----------------
1 file changed, 31 insertions(+), 16 deletions(-)

diff --git a/amd64/emit.c b/amd64/emit.c @@ -430,33 +430,48 @@ emitins(Ins i, Fn *fn, FILE *f) } goto Table; case Ocopy: - /* make sure we don't emit useless copies, - * also, we can use a trick to load 64-bits - * registers, it's detailed in my note below - * http://c9x.me/art/notes.html?09/19/2015 */ - t0 = rtype(i.arg[0]); + /* copies are used for many things; see my note + * to understand how to load big constants: + * https://c9x.me/notes/2015-09-19.html */ + assert(rtype(i.to) != RMem); if (req(i.to, R) || req(i.arg[0], R)) break; - if (isreg(i.to) + if (req(i.to, i.arg[0])) + break; + t0 = rtype(i.arg[0]); + if (i.cls == Kl && t0 == RCon - && i.cls == Kl - && fn->con[i.arg[0].val].type == CBits - && (val = fn->con[i.arg[0].val].bits.i) >= 0 - && val <= UINT32_MAX) { - emitf("movl %W0, %W=", &i, fn, f); - } else if (isreg(i.to) + && fn->con[i.arg[0].val].type == CBits) { + val = fn->con[i.arg[0].val].bits.i; + if (isreg(i.to)) + if (val >= 0 && val <= UINT32_MAX) { + emitf("movl %W0, %W=", &i, fn, f); + break; + } + if (rtype(i.to) == RSlot) + if (val < INT32_MIN || val > INT32_MAX) { + emitf("movl %0, %=", &i, fn, f); + emitf("movl %0>>32, 4+%=", &i, fn, f); + break; + } + } + if (isreg(i.to) && t0 == RCon && fn->con[i.arg[0].val].type == CAddr) { emitf("lea%k %M0, %=", &i, fn, f); - } else if (rtype(i.to) == RSlot + break; + } + if (rtype(i.to) == RSlot && (t0 == RSlot || t0 == RMem)) { i.cls = KWIDE(i.cls) ? Kd : Ks; i.arg[1] = TMP(XMM0+15); emitf("mov%k %0, %1", &i, fn, f); emitf("mov%k %1, %=", &i, fn, f); - - } else if (!req(i.arg[0], i.to)) - emitf("mov%k %0, %=", &i, fn, f); + break; + } + /* conveniently, the assembler knows if it + * should use movabsq when reading movq */ + emitf("mov%k %0, %=", &i, fn, f); break; case Ocall: /* calls simply have a weird syntax in AT&T