diff --git a/src/lj_asm.c b/src/lj_asm.c index 73df6850..b8d20f2d 100644 --- a/src/lj_asm.c +++ b/src/lj_asm.c @@ -1040,7 +1040,19 @@ static void asm_tvptr(ASMState *as, Reg dest, IRRef ref); static void asm_bufhdr(ASMState *as, IRIns *ir) { Reg sb = ra_dest(as, ir, RSET_GPR); - if (!(ir->op2 & IRBUFHDR_APPEND)) { + if ((ir->op2 & IRBUFHDR_APPEND)) { + /* Rematerialize const buffer pointer instead of likely spill. */ + IRIns *irp = IR(ir->op1); + if (!(ra_hasreg(irp->r) || irp == ir-1 || + (irp == ir-2 && !ra_used(ir-1)))) { + while (!(irp->o == IR_BUFHDR && !(irp->op2 & IRBUFHDR_APPEND))) + irp = IR(irp->op1); + if (irref_isk(irp->op1)) { + ra_weak(as, ra_allocref(as, ir->op1, RSET_GPR)); + ir = irp; + } + } + } else { Reg tmp = ra_scratch(as, rset_exclude(RSET_GPR, sb)); /* Passing ir isn't strictly correct, but it's an IRT_P32, too. */ emit_storeofs(as, ir, tmp, sb, offsetof(SBuf, p));