[vm, compiler] Use shorter sequences for load/store with larger offsets on ARM64.

flutter_gallery
Instructions(CodeSize): 4634496 -> 4629408 (-0.11%)
       Total(CodeSize): 7312019 -> 7306931 (-0.07%)

TEST=ci
Change-Id: Iae104eb7da82590dee2bc2018905f51efe344597
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/243382
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Ryan Macnak <rmacnak@google.com>
This commit is contained in:
Ryan Macnak 2022-05-05 22:37:26 +00:00 committed by Commit Bot
parent 322410e5cd
commit df21baa407
2 changed files with 34 additions and 84 deletions

View file

@ -854,91 +854,62 @@ void Assembler::CompareImmediate(Register rn, int64_t imm, OperandSize sz) {
}
}
Address Assembler::PrepareLargeOffset(Register base,
int32_t offset,
OperandSize sz) {
if (Address::CanHoldOffset(offset, Address::Offset, sz)) {
return Address(base, offset, Address::Offset, sz);
}
ASSERT(base != TMP2);
Operand op;
const uint32_t upper20 = offset & 0xfffff000;
const uint32_t lower12 = offset & 0x00000fff;
if ((base != CSP) &&
(Operand::CanHold(upper20, kXRegSizeInBits, &op) == Operand::Immediate) &&
Address::CanHoldOffset(lower12, Address::Offset, sz)) {
add(TMP2, base, op);
return Address(TMP2, lower12, Address::Offset, sz);
}
LoadImmediate(TMP2, offset);
return Address(base, TMP2);
}
void Assembler::LoadFromOffset(Register dest,
Register base,
int32_t offset,
OperandSize sz) {
if (Address::CanHoldOffset(offset, Address::Offset, sz)) {
LoadFromOffset(dest, Address(base, offset, Address::Offset, sz), sz);
} else {
ASSERT(base != TMP2);
AddImmediate(TMP2, base, offset);
LoadFromOffset(dest, Address(TMP2), sz);
}
LoadFromOffset(dest, PrepareLargeOffset(base, offset, sz), sz);
}
void Assembler::LoadSFromOffset(VRegister dest, Register base, int32_t offset) {
if (Address::CanHoldOffset(offset, Address::Offset, kSWord)) {
fldrs(dest, Address(base, offset, Address::Offset, kSWord));
} else {
ASSERT(base != TMP2);
AddImmediate(TMP2, base, offset);
fldrs(dest, Address(TMP2));
}
fldrs(dest, PrepareLargeOffset(base, offset, kSWord));
}
void Assembler::LoadDFromOffset(VRegister dest, Register base, int32_t offset) {
if (Address::CanHoldOffset(offset, Address::Offset, kDWord)) {
fldrd(dest, Address(base, offset, Address::Offset, kDWord));
} else {
ASSERT(base != TMP2);
AddImmediate(TMP2, base, offset);
fldrd(dest, Address(TMP2));
}
fldrd(dest, PrepareLargeOffset(base, offset, kDWord));
}
void Assembler::LoadQFromOffset(VRegister dest, Register base, int32_t offset) {
if (Address::CanHoldOffset(offset, Address::Offset, kQWord)) {
fldrq(dest, Address(base, offset, Address::Offset, kQWord));
} else {
ASSERT(base != TMP2);
AddImmediate(TMP2, base, offset);
fldrq(dest, Address(TMP2));
}
fldrq(dest, PrepareLargeOffset(base, offset, kQWord));
}
void Assembler::StoreToOffset(Register src,
Register base,
int32_t offset,
OperandSize sz) {
ASSERT(base != TMP2);
if (Address::CanHoldOffset(offset, Address::Offset, sz)) {
StoreToOffset(src, Address(base, offset, Address::Offset, sz), sz);
} else {
ASSERT(src != TMP2);
AddImmediate(TMP2, base, offset);
StoreToOffset(src, Address(TMP2), sz);
}
StoreToOffset(src, PrepareLargeOffset(base, offset, sz), sz);
}
void Assembler::StoreSToOffset(VRegister src, Register base, int32_t offset) {
if (Address::CanHoldOffset(offset, Address::Offset, kSWord)) {
fstrs(src, Address(base, offset, Address::Offset, kSWord));
} else {
ASSERT(base != TMP2);
AddImmediate(TMP2, base, offset);
fstrs(src, Address(TMP2));
}
fstrs(src, PrepareLargeOffset(base, offset, kSWord));
}
void Assembler::StoreDToOffset(VRegister src, Register base, int32_t offset) {
if (Address::CanHoldOffset(offset, Address::Offset, kDWord)) {
fstrd(src, Address(base, offset, Address::Offset, kDWord));
} else {
ASSERT(base != TMP2);
AddImmediate(TMP2, base, offset);
fstrd(src, Address(TMP2));
}
fstrd(src, PrepareLargeOffset(base, offset, kDWord));
}
void Assembler::StoreQToOffset(VRegister src, Register base, int32_t offset) {
if (Address::CanHoldOffset(offset, Address::Offset, kQWord)) {
fstrq(src, Address(base, offset, Address::Offset, kQWord));
} else {
ASSERT(base != TMP2);
AddImmediate(TMP2, base, offset);
fstrq(src, Address(TMP2));
}
fstrq(src, PrepareLargeOffset(base, offset, kQWord));
}
void Assembler::VRecps(VRegister vd, VRegister vn) {
@ -984,17 +955,9 @@ void Assembler::LoadCompressedFromOffset(Register dest,
Register base,
int32_t offset) {
#if !defined(DART_COMPRESSED_POINTERS)
LoadFromOffset(dest, base, offset);
LoadFromOffset(dest, base, offset, kObjectBytes);
#else
if (Address::CanHoldOffset(offset, Address::Offset, kObjectBytes)) {
ldr(dest, Address(base, offset, Address::Offset, kObjectBytes),
kUnsignedFourBytes); // Zero-extension.
} else {
ASSERT(base != TMP2);
AddImmediate(TMP2, base, offset);
ldr(dest, Address(TMP2, 0, Address::Offset, kObjectBytes),
kUnsignedFourBytes); // Zero-extension.
}
LoadFromOffset(dest, base, offset, kUnsignedFourBytes); // Zero-extension.
add(dest, dest, Operand(HEAP_BITS, LSL, 32));
#endif
}
@ -1019,15 +982,7 @@ void Assembler::LoadCompressedSmiFromOffset(Register dest,
#if !defined(DART_COMPRESSED_POINTERS)
LoadFromOffset(dest, base, offset);
#else
if (Address::CanHoldOffset(offset, Address::Offset, kObjectBytes)) {
ldr(dest, Address(base, offset, Address::Offset, kObjectBytes),
kUnsignedFourBytes); // Zero-extension.
} else {
ASSERT(base != TMP2);
AddImmediate(TMP2, base, offset);
ldr(dest, Address(TMP2, 0, Address::Offset, kObjectBytes),
kUnsignedFourBytes); // Zero-extension.
}
LoadFromOffset(dest, base, offset, kUnsignedFourBytes); // Zero-extension.
#endif
#if defined(DEBUG)
Label done;
@ -1081,11 +1036,8 @@ void Assembler::StoreIntoObjectOffset(Register object,
MemoryOrder memory_order) {
if (memory_order == kRelease) {
StoreRelease(value, object, offset);
} else if (FieldAddress::CanHoldOffset(offset)) {
str(value, FieldAddress(object, offset));
} else {
AddImmediate(TMP, object, offset - kHeapObjectTag);
str(value, Address(TMP));
StoreToOffset(value, object, offset - kHeapObjectTag);
}
StoreBarrier(object, value, value_can_be_smi);
}
@ -1097,11 +1049,8 @@ void Assembler::StoreCompressedIntoObjectOffset(Register object,
MemoryOrder memory_order) {
if (memory_order == kRelease) {
StoreReleaseCompressed(value, object, offset);
} else if (FieldAddress::CanHoldOffset(offset)) {
str(value, FieldAddress(object, offset), kObjectBytes);
} else {
AddImmediate(TMP, object, offset - kHeapObjectTag);
str(value, Address(TMP), kObjectBytes);
StoreToOffset(value, object, offset - kHeapObjectTag, kObjectBytes);
}
StoreBarrier(object, value, value_can_be_smi);
}

View file

@ -1840,6 +1840,7 @@ class Assembler : public AssemblerBase {
void TestImmediate(Register rn, int64_t imm, OperandSize sz = kEightBytes);
void CompareImmediate(Register rn, int64_t imm, OperandSize sz = kEightBytes);
Address PrepareLargeOffset(Register base, int32_t offset, OperandSize sz);
void LoadFromOffset(Register dest,
const Address& address,
OperandSize sz = kEightBytes) override {