8131362: aarch64: C2 does not handle large stack offsets

Change spill code to allow large offsets

Reviewed-by: kvn, aph
This commit is contained in:
Ed Nevill 2015-07-17 07:50:36 +00:00
parent 259aeb3399
commit b73ef8ebc6
3 changed files with 159 additions and 308 deletions

View File

@ -2167,8 +2167,12 @@ uint MachSpillCopyNode::implementation(CodeBuffer *cbuf, PhaseRegAlloc *ra_, boo
return 0; // Self copy, no move. return 0; // Self copy, no move.
} }
bool is64 = (src_lo & 1) == 0 && src_lo + 1 == src_hi &&
(dst_lo & 1) == 0 && dst_lo + 1 == dst_hi;
int src_offset = ra_->reg2offset(src_lo);
int dst_offset = ra_->reg2offset(dst_lo);
if (bottom_type()->isa_vect() != NULL) { if (bottom_type()->isa_vect() != NULL) {
uint len = 4;
uint ireg = ideal_reg(); uint ireg = ideal_reg();
assert(ireg == Op_VecD || ireg == Op_VecX, "must be 64 bit or 128 bit vector"); assert(ireg == Op_VecD || ireg == Op_VecX, "must be 64 bit or 128 bit vector");
if (cbuf) { if (cbuf) {
@ -2176,334 +2180,115 @@ uint MachSpillCopyNode::implementation(CodeBuffer *cbuf, PhaseRegAlloc *ra_, boo
assert((src_lo_rc != rc_int && dst_lo_rc != rc_int), "sanity"); assert((src_lo_rc != rc_int && dst_lo_rc != rc_int), "sanity");
if (src_lo_rc == rc_stack && dst_lo_rc == rc_stack) { if (src_lo_rc == rc_stack && dst_lo_rc == rc_stack) {
// stack->stack // stack->stack
int src_offset = ra_->reg2offset(src_lo);
int dst_offset = ra_->reg2offset(dst_lo);
assert((src_offset & 7) && (dst_offset & 7), "unaligned stack offset"); assert((src_offset & 7) && (dst_offset & 7), "unaligned stack offset");
len = 8;
if (ireg == Op_VecD) { if (ireg == Op_VecD) {
__ ldr(rscratch1, Address(sp, src_offset)); __ unspill(rscratch1, true, src_offset);
__ str(rscratch1, Address(sp, dst_offset)); __ spill(rscratch1, true, dst_offset);
} else { } else {
if (src_offset < 512) { __ spill_copy128(src_offset, dst_offset);
__ ldp(rscratch1, rscratch2, Address(sp, src_offset));
} else {
__ ldr(rscratch1, Address(sp, src_offset));
__ ldr(rscratch2, Address(sp, src_offset+4));
len += 4;
}
if (dst_offset < 512) {
__ stp(rscratch1, rscratch2, Address(sp, dst_offset));
} else {
__ str(rscratch1, Address(sp, dst_offset));
__ str(rscratch2, Address(sp, dst_offset+4));
len += 4;
}
} }
} else if (src_lo_rc == rc_float && dst_lo_rc == rc_float) { } else if (src_lo_rc == rc_float && dst_lo_rc == rc_float) {
__ orr(as_FloatRegister(Matcher::_regEncode[dst_lo]), __ mov(as_FloatRegister(Matcher::_regEncode[dst_lo]),
ireg == Op_VecD ? __ T8B : __ T16B, ireg == Op_VecD ? __ T8B : __ T16B,
as_FloatRegister(Matcher::_regEncode[src_lo]),
as_FloatRegister(Matcher::_regEncode[src_lo])); as_FloatRegister(Matcher::_regEncode[src_lo]));
} else if (src_lo_rc == rc_float && dst_lo_rc == rc_stack) { } else if (src_lo_rc == rc_float && dst_lo_rc == rc_stack) {
__ str(as_FloatRegister(Matcher::_regEncode[src_lo]), __ spill(as_FloatRegister(Matcher::_regEncode[src_lo]),
ireg == Op_VecD ? __ D : __ Q, ireg == Op_VecD ? __ D : __ Q,
Address(sp, ra_->reg2offset(dst_lo))); ra_->reg2offset(dst_lo));
} else if (src_lo_rc == rc_stack && dst_lo_rc == rc_float) { } else if (src_lo_rc == rc_stack && dst_lo_rc == rc_float) {
__ ldr(as_FloatRegister(Matcher::_regEncode[dst_lo]), __ unspill(as_FloatRegister(Matcher::_regEncode[dst_lo]),
ireg == Op_VecD ? __ D : __ Q, ireg == Op_VecD ? __ D : __ Q,
Address(sp, ra_->reg2offset(src_lo))); ra_->reg2offset(src_lo));
} else { } else {
ShouldNotReachHere(); ShouldNotReachHere();
} }
} else if (st) { }
if (src_lo_rc == rc_stack && dst_lo_rc == rc_stack) { } else if (cbuf) {
// stack->stack MacroAssembler _masm(cbuf);
int src_offset = ra_->reg2offset(src_lo); switch (src_lo_rc) {
int dst_offset = ra_->reg2offset(dst_lo); case rc_int:
if (ireg == Op_VecD) { if (dst_lo_rc == rc_int) { // gpr --> gpr copy
st->print("ldr rscratch1, [sp, #%d]", src_offset); if (is64) {
st->print("str rscratch1, [sp, #%d]", dst_offset); __ mov(as_Register(Matcher::_regEncode[dst_lo]),
as_Register(Matcher::_regEncode[src_lo]));
} else { } else {
if (src_offset < 512) { MacroAssembler _masm(cbuf);
st->print("ldp rscratch1, rscratch2, [sp, #%d]", src_offset); __ movw(as_Register(Matcher::_regEncode[dst_lo]),
} else { as_Register(Matcher::_regEncode[src_lo]));
st->print("ldr rscratch1, [sp, #%d]", src_offset);
st->print("\nldr rscratch2, [sp, #%d]", src_offset+4);
}
if (dst_offset < 512) {
st->print("\nstp rscratch1, rscratch2, [sp, #%d]", dst_offset);
} else {
st->print("\nstr rscratch1, [sp, #%d]", dst_offset);
st->print("\nstr rscratch2, [sp, #%d]", dst_offset+4);
}
} }
st->print("\t# vector spill, stack to stack"); } else if (dst_lo_rc == rc_float) { // gpr --> fpr copy
} else if (src_lo_rc == rc_float && dst_lo_rc == rc_float) { if (is64) {
st->print("mov %s, %s\t# vector spill, reg to reg", __ fmovd(as_FloatRegister(Matcher::_regEncode[dst_lo]),
Matcher::regName[dst_lo], Matcher::regName[src_lo]); as_Register(Matcher::_regEncode[src_lo]));
} else if (src_lo_rc == rc_float && dst_lo_rc == rc_stack) { } else {
st->print("str %s, [sp, #%d]\t# vector spill, reg to stack", __ fmovs(as_FloatRegister(Matcher::_regEncode[dst_lo]),
Matcher::regName[src_lo], ra_->reg2offset(dst_lo)); as_Register(Matcher::_regEncode[src_lo]));
} else if (src_lo_rc == rc_stack && dst_lo_rc == rc_float) { }
st->print("ldr %s, [sp, #%d]\t# vector spill, stack to reg", } else { // gpr --> stack spill
Matcher::regName[dst_lo], ra_->reg2offset(src_lo)); assert(dst_lo_rc == rc_stack, "spill to bad register class");
__ spill(as_Register(Matcher::_regEncode[src_lo]), is64, dst_offset);
} }
} break;
return len; case rc_float:
} if (dst_lo_rc == rc_int) { // fpr --> gpr copy
if (is64) {
switch (src_lo_rc) { __ fmovd(as_Register(Matcher::_regEncode[dst_lo]),
case rc_int: as_FloatRegister(Matcher::_regEncode[src_lo]));
if (dst_lo_rc == rc_int) { // gpr --> gpr copy } else {
if (((src_lo & 1) == 0 && src_lo + 1 == src_hi) && __ fmovs(as_Register(Matcher::_regEncode[dst_lo]),
(dst_lo & 1) == 0 && dst_lo + 1 == dst_hi) { as_FloatRegister(Matcher::_regEncode[src_lo]));
// 64 bit
if (cbuf) {
MacroAssembler _masm(cbuf);
__ mov(as_Register(Matcher::_regEncode[dst_lo]),
as_Register(Matcher::_regEncode[src_lo]));
} else if (st) {
st->print("mov %s, %s\t# shuffle",
Matcher::regName[dst_lo],
Matcher::regName[src_lo]);
} }
} else { } else if (dst_lo_rc == rc_float) { // fpr --> fpr copy
// 32 bit if (cbuf) {
if (cbuf) { __ fmovd(as_FloatRegister(Matcher::_regEncode[dst_lo]),
MacroAssembler _masm(cbuf); as_FloatRegister(Matcher::_regEncode[src_lo]));
__ movw(as_Register(Matcher::_regEncode[dst_lo]), } else {
as_Register(Matcher::_regEncode[src_lo])); __ fmovs(as_FloatRegister(Matcher::_regEncode[dst_lo]),
} else if (st) { as_FloatRegister(Matcher::_regEncode[src_lo]));
st->print("movw %s, %s\t# shuffle",
Matcher::regName[dst_lo],
Matcher::regName[src_lo]);
} }
} else { // fpr --> stack spill
assert(dst_lo_rc == rc_stack, "spill to bad register class");
__ spill(as_FloatRegister(Matcher::_regEncode[src_lo]),
is64 ? __ D : __ S, dst_offset);
} }
} else if (dst_lo_rc == rc_float) { // gpr --> fpr copy break;
if (((src_lo & 1) == 0 && src_lo + 1 == src_hi) && case rc_stack:
(dst_lo & 1) == 0 && dst_lo + 1 == dst_hi) { if (dst_lo_rc == rc_int) { // stack --> gpr load
// 64 bit __ unspill(as_Register(Matcher::_regEncode[dst_lo]), is64, src_offset);
if (cbuf) { } else if (dst_lo_rc == rc_float) { // stack --> fpr load
MacroAssembler _masm(cbuf); __ unspill(as_FloatRegister(Matcher::_regEncode[dst_lo]),
__ fmovd(as_FloatRegister(Matcher::_regEncode[dst_lo]), is64 ? __ D : __ S, src_offset);
as_Register(Matcher::_regEncode[src_lo])); } else { // stack --> stack copy
} else if (st) { assert(dst_lo_rc == rc_stack, "spill to bad register class");
st->print("fmovd %s, %s\t# shuffle", __ unspill(rscratch1, is64, src_offset);
Matcher::regName[dst_lo], __ spill(rscratch1, is64, dst_offset);
Matcher::regName[src_lo]);
}
} else {
// 32 bit
if (cbuf) {
MacroAssembler _masm(cbuf);
__ fmovs(as_FloatRegister(Matcher::_regEncode[dst_lo]),
as_Register(Matcher::_regEncode[src_lo]));
} else if (st) {
st->print("fmovs %s, %s\t# shuffle",
Matcher::regName[dst_lo],
Matcher::regName[src_lo]);
}
} }
} else { // gpr --> stack spill break;
assert(dst_lo_rc == rc_stack, "spill to bad register class"); default:
int dst_offset = ra_->reg2offset(dst_lo); assert(false, "bad rc_class for spill");
if (((src_lo & 1) == 0 && src_lo + 1 == src_hi) && ShouldNotReachHere();
(dst_lo & 1) == 0 && dst_lo + 1 == dst_hi) { }
// 64 bit }
if (cbuf) {
MacroAssembler _masm(cbuf); if (st) {
__ str(as_Register(Matcher::_regEncode[src_lo]), st->print("spill ");
Address(sp, dst_offset)); if (src_lo_rc == rc_stack) {
} else if (st) { st->print("[sp, #%d] -> ", ra_->reg2offset(src_lo));
st->print("str %s, [sp, #%d]\t# spill", } else {
Matcher::regName[src_lo], st->print("%s -> ", Matcher::regName[src_lo]);
dst_offset); }
} if (dst_lo_rc == rc_stack) {
} else { st->print("[sp, #%d]", ra_->reg2offset(dst_lo));
// 32 bit } else {
if (cbuf) { st->print("%s", Matcher::regName[dst_lo]);
MacroAssembler _masm(cbuf); }
__ strw(as_Register(Matcher::_regEncode[src_lo]), if (bottom_type()->isa_vect() != NULL) {
Address(sp, dst_offset)); st->print("\t# vector spill size = %d", ideal_reg()==Op_VecD ? 64:128);
} else if (st) { } else {
st->print("strw %s, [sp, #%d]\t# spill", st->print("\t# spill size = %d", is64 ? 64:32);
Matcher::regName[src_lo],
dst_offset);
}
}
}
return 4;
case rc_float:
if (dst_lo_rc == rc_int) { // fpr --> gpr copy
if (((src_lo & 1) == 0 && src_lo + 1 == src_hi) &&
(dst_lo & 1) == 0 && dst_lo + 1 == dst_hi) {
// 64 bit
if (cbuf) {
MacroAssembler _masm(cbuf);
__ fmovd(as_Register(Matcher::_regEncode[dst_lo]),
as_FloatRegister(Matcher::_regEncode[src_lo]));
} else if (st) {
st->print("fmovd %s, %s\t# shuffle",
Matcher::regName[dst_lo],
Matcher::regName[src_lo]);
}
} else {
// 32 bit
if (cbuf) {
MacroAssembler _masm(cbuf);
__ fmovs(as_Register(Matcher::_regEncode[dst_lo]),
as_FloatRegister(Matcher::_regEncode[src_lo]));
} else if (st) {
st->print("fmovs %s, %s\t# shuffle",
Matcher::regName[dst_lo],
Matcher::regName[src_lo]);
}
}
} else if (dst_lo_rc == rc_float) { // fpr --> fpr copy
if (((src_lo & 1) == 0 && src_lo + 1 == src_hi) &&
(dst_lo & 1) == 0 && dst_lo + 1 == dst_hi) {
// 64 bit
if (cbuf) {
MacroAssembler _masm(cbuf);
__ fmovd(as_FloatRegister(Matcher::_regEncode[dst_lo]),
as_FloatRegister(Matcher::_regEncode[src_lo]));
} else if (st) {
st->print("fmovd %s, %s\t# shuffle",
Matcher::regName[dst_lo],
Matcher::regName[src_lo]);
}
} else {
// 32 bit
if (cbuf) {
MacroAssembler _masm(cbuf);
__ fmovs(as_FloatRegister(Matcher::_regEncode[dst_lo]),
as_FloatRegister(Matcher::_regEncode[src_lo]));
} else if (st) {
st->print("fmovs %s, %s\t# shuffle",
Matcher::regName[dst_lo],
Matcher::regName[src_lo]);
}
}
} else { // fpr --> stack spill
assert(dst_lo_rc == rc_stack, "spill to bad register class");
int dst_offset = ra_->reg2offset(dst_lo);
if (((src_lo & 1) == 0 && src_lo + 1 == src_hi) &&
(dst_lo & 1) == 0 && dst_lo + 1 == dst_hi) {
// 64 bit
if (cbuf) {
MacroAssembler _masm(cbuf);
__ strd(as_FloatRegister(Matcher::_regEncode[src_lo]),
Address(sp, dst_offset));
} else if (st) {
st->print("strd %s, [sp, #%d]\t# spill",
Matcher::regName[src_lo],
dst_offset);
}
} else {
// 32 bit
if (cbuf) {
MacroAssembler _masm(cbuf);
__ strs(as_FloatRegister(Matcher::_regEncode[src_lo]),
Address(sp, dst_offset));
} else if (st) {
st->print("strs %s, [sp, #%d]\t# spill",
Matcher::regName[src_lo],
dst_offset);
}
}
}
return 4;
case rc_stack:
int src_offset = ra_->reg2offset(src_lo);
if (dst_lo_rc == rc_int) { // stack --> gpr load
if (((src_lo & 1) == 0 && src_lo + 1 == src_hi) &&
(dst_lo & 1) == 0 && dst_lo + 1 == dst_hi) {
// 64 bit
if (cbuf) {
MacroAssembler _masm(cbuf);
__ ldr(as_Register(Matcher::_regEncode[dst_lo]),
Address(sp, src_offset));
} else if (st) {
st->print("ldr %s, [sp, %d]\t# restore",
Matcher::regName[dst_lo],
src_offset);
}
} else {
// 32 bit
if (cbuf) {
MacroAssembler _masm(cbuf);
__ ldrw(as_Register(Matcher::_regEncode[dst_lo]),
Address(sp, src_offset));
} else if (st) {
st->print("ldr %s, [sp, %d]\t# restore",
Matcher::regName[dst_lo],
src_offset);
}
}
return 4;
} else if (dst_lo_rc == rc_float) { // stack --> fpr load
if (((src_lo & 1) == 0 && src_lo + 1 == src_hi) &&
(dst_lo & 1) == 0 && dst_lo + 1 == dst_hi) {
// 64 bit
if (cbuf) {
MacroAssembler _masm(cbuf);
__ ldrd(as_FloatRegister(Matcher::_regEncode[dst_lo]),
Address(sp, src_offset));
} else if (st) {
st->print("ldrd %s, [sp, %d]\t# restore",
Matcher::regName[dst_lo],
src_offset);
}
} else {
// 32 bit
if (cbuf) {
MacroAssembler _masm(cbuf);
__ ldrs(as_FloatRegister(Matcher::_regEncode[dst_lo]),
Address(sp, src_offset));
} else if (st) {
st->print("ldrs %s, [sp, %d]\t# restore",
Matcher::regName[dst_lo],
src_offset);
}
}
return 4;
} else { // stack --> stack copy
assert(dst_lo_rc == rc_stack, "spill to bad register class");
int dst_offset = ra_->reg2offset(dst_lo);
if (((src_lo & 1) == 0 && src_lo + 1 == src_hi) &&
(dst_lo & 1) == 0 && dst_lo + 1 == dst_hi) {
// 64 bit
if (cbuf) {
MacroAssembler _masm(cbuf);
__ ldr(rscratch1, Address(sp, src_offset));
__ str(rscratch1, Address(sp, dst_offset));
} else if (st) {
st->print("ldr rscratch1, [sp, %d]\t# mem-mem spill",
src_offset);
st->print("\n\t");
st->print("str rscratch1, [sp, %d]",
dst_offset);
}
} else {
// 32 bit
if (cbuf) {
MacroAssembler _masm(cbuf);
__ ldrw(rscratch1, Address(sp, src_offset));
__ strw(rscratch1, Address(sp, dst_offset));
} else if (st) {
st->print("ldrw rscratch1, [sp, %d]\t# mem-mem spill",
src_offset);
st->print("\n\t");
st->print("strw rscratch1, [sp, %d]",
dst_offset);
}
}
return 8;
} }
} }
assert(false," bad rc_class for spill ");
Unimplemented();
return 0; return 0;
} }
@ -2522,7 +2307,7 @@ void MachSpillCopyNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
} }
uint MachSpillCopyNode::size(PhaseRegAlloc *ra_) const { uint MachSpillCopyNode::size(PhaseRegAlloc *ra_) const {
return implementation(NULL, ra_, true, NULL); return MachNode::size(ra_);
} }
//============================================================================= //=============================================================================

View File

@ -2306,6 +2306,28 @@ Address MacroAssembler::offsetted_address(Register r, Register r1,
} }
} }
Address MacroAssembler::spill_address(int size, int offset, Register tmp)
{
assert(offset >= 0, "spill to negative address?");
// Offset reachable ?
// Not aligned - 9 bits signed offset
// Aligned - 12 bits unsigned offset shifted
Register base = sp;
if ((offset & (size-1)) && offset >= (1<<8)) {
add(tmp, base, offset & ((1<<12)-1));
base = tmp;
offset &= -1<<12;
}
if (offset >= (1<<12) * size) {
add(tmp, base, offset & (((1<<12)-1)<<12));
base = tmp;
offset &= ~(((1<<12)-1)<<12);
}
return Address(base, offset);
}
/** /**
* Multiply 64 bit by 64 bit first loop. * Multiply 64 bit by 64 bit first loop.
*/ */

View File

@ -468,6 +468,10 @@ public:
void mov(FloatRegister Vd, SIMD_Arrangement T, u_int32_t imm32); void mov(FloatRegister Vd, SIMD_Arrangement T, u_int32_t imm32);
void mov(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn) {
orr(Vd, T, Vn, Vn);
}
// macro instructions for accessing and updating floating point // macro instructions for accessing and updating floating point
// status register // status register
// //
@ -1161,6 +1165,46 @@ private:
// Uses rscratch2. // Uses rscratch2.
Address offsetted_address(Register r, Register r1, Address::extend ext, Address offsetted_address(Register r, Register r1, Address::extend ext,
int offset, int size); int offset, int size);
private:
// Returns an address on the stack which is reachable with a ldr/str of size
// Uses rscratch2 if the address is not directly reachable
Address spill_address(int size, int offset, Register tmp=rscratch2);
public:
void spill(Register Rx, bool is64, int offset) {
if (is64) {
str(Rx, spill_address(8, offset));
} else {
strw(Rx, spill_address(4, offset));
}
}
void spill(FloatRegister Vx, SIMD_RegVariant T, int offset) {
str(Vx, T, spill_address(1 << (int)T, offset));
}
void unspill(Register Rx, bool is64, int offset) {
if (is64) {
ldr(Rx, spill_address(8, offset));
} else {
ldrw(Rx, spill_address(4, offset));
}
}
void unspill(FloatRegister Vx, SIMD_RegVariant T, int offset) {
ldr(Vx, T, spill_address(1 << (int)T, offset));
}
void spill_copy128(int src_offset, int dst_offset,
Register tmp1=rscratch1, Register tmp2=rscratch2) {
if (src_offset < 512 && (src_offset & 7) == 0 &&
dst_offset < 512 && (dst_offset & 7) == 0) {
ldp(tmp1, tmp2, Address(sp, src_offset));
stp(tmp1, tmp2, Address(sp, dst_offset));
} else {
unspill(tmp1, true, src_offset);
spill(tmp1, true, dst_offset);
unspill(tmp1, true, src_offset+8);
spill(tmp1, true, dst_offset+8);
}
}
}; };
#ifdef ASSERT #ifdef ASSERT