aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--aarch64/emit.c3
-rw-r--r--ir/regalloc.c15
2 files changed, 16 insertions, 2 deletions
diff --git a/aarch64/emit.c b/aarch64/emit.c
index 3fd3278..fdcb866 100644
--- a/aarch64/emit.c
+++ b/aarch64/emit.c
@@ -831,7 +831,8 @@ emitinstr(uchar **pcode, struct function *fn, struct block *blk, int curi, struc
case Ostorei32: cls = KI32; X2 = Xstr; goto Store;
case Ostorei64: cls = KI64; X2 = Xstr;
Store:
- X2(pcode, cls, ref2oper(ins->r), mkmemoper(1<<(ins->op-Ostorei8), ins->l));
+ X2(pcode, cls, ins->r.bits == ZEROREF.bits ? REGZR : ref2oper(ins->r),
+ mkmemoper(1<<(ins->op-Ostorei8), ins->l));
break;
case Ostoref32: case Ostoref64:
Xfstr(pcode, KF32 + ins->op-Ostoref32, ref2oper(ins->r), mkmemoper(ins->op == Oloadf32 ? 4 : 8, ins->l));
diff --git a/ir/regalloc.c b/ir/regalloc.c
index 85b6a65..aa18e10 100644
--- a/ir/regalloc.c
+++ b/ir/regalloc.c
@@ -1033,6 +1033,19 @@ linearscan(struct rega *ra)
DBG("\n");
}
+static bool
+isstoreimm(union ref r)
+{
+ if (r.t == RTMP) return 1; /* register OK */
+ if (isintcon(r)) switch (target.arch) {
+ case ISxxx: assert(0);
+ /* TODO don't hard code this architecture dependent dispatch */
+ case ISx86_64: return concls(r) == KI32; /* x86: MOV [addr], imm32 */
+ case ISaarch64: return r.i == 0; /* arm doesn't have STR <imm>, but has zero register */
+ }
+ return 0;
+}
+
/* replace temps with physical regs, add loads & stores for spilled temps */
static bool
devirt(struct rega *ra, struct block *blk)
@@ -1139,7 +1152,7 @@ devirt(struct rega *ra, struct block *blk)
enum irclass cls = insrescls(*ins);
int store = cls2store[cls];
/* t was spilled, gen store */
- if (ins->op == Ocopy && ins->l.t != RADDR && !isaddrcon(ins->l,0)) {
+ if (ins->op == Ocopy && isstoreimm(ins->l)) {
ins->op = store;
ins->r = ins->l;
addstkslotref(temp, alloc->a*8);