[turbofan] Tests and fixes for ARM64 load/store with immediate offset.

R=bmeurer@chromium.org, ulan@chromium.org
BUG=

Review URL: https://codereview.chromium.org/550113002

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@23906 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
baptiste.afsa@arm.com 2014-09-12 09:31:26 +00:00
parent 42054156ce
commit bca9d01dc5
3 changed files with 104 additions and 18 deletions

View File

@ -1850,6 +1850,9 @@ class Assembler : public AssemblerBase {
inline static Instr ImmBarrierType(int imm2);
inline static LSDataSize CalcLSDataSize(LoadStoreOp op);
static bool IsImmLSUnscaled(int64_t offset);
static bool IsImmLSScaled(int64_t offset, LSDataSize size);
// Move immediates encoding.
inline static Instr ImmMoveWide(uint64_t imm);
inline static Instr ShiftMoveWide(int64_t shift);
@ -1933,8 +1936,6 @@ class Assembler : public AssemblerBase {
void LoadStore(const CPURegister& rt,
const MemOperand& addr,
LoadStoreOp op);
static bool IsImmLSUnscaled(int64_t offset);
static bool IsImmLSScaled(int64_t offset, LSDataSize size);
void LoadStorePair(const CPURegister& rt, const CPURegister& rt2,
const MemOperand& addr, LoadStorePairOp op);

View File

@ -855,6 +855,7 @@ struct MemoryAccess {
MachineType type;
ArchOpcode ldr_opcode;
ArchOpcode str_opcode;
const int32_t immediates[20];
};
@ -868,16 +869,36 @@ std::ostream& operator<<(std::ostream& os, const MemoryAccess& memacc) {
static const MemoryAccess kMemoryAccesses[] = {
{kMachInt8, kArm64Ldrsb, kArm64Strb},
{kMachUint8, kArm64Ldrb, kArm64Strb},
{kMachInt16, kArm64Ldrsh, kArm64Strh},
{kMachUint16, kArm64Ldrh, kArm64Strh},
{kMachInt32, kArm64LdrW, kArm64StrW},
{kMachUint32, kArm64LdrW, kArm64StrW},
{kMachInt64, kArm64Ldr, kArm64Str},
{kMachUint64, kArm64Ldr, kArm64Str},
{kMachFloat32, kArm64LdrS, kArm64StrS},
{kMachFloat64, kArm64LdrD, kArm64StrD}};
{kMachInt8, kArm64Ldrsb, kArm64Strb,
{-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 257, 258, 1000, 1001,
2121, 2442, 4093, 4094, 4095}},
{kMachUint8, kArm64Ldrb, kArm64Strb,
{-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 257, 258, 1000, 1001,
2121, 2442, 4093, 4094, 4095}},
{kMachInt16, kArm64Ldrsh, kArm64Strh,
{-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 258, 260, 4096, 4098,
4100, 4242, 6786, 8188, 8190}},
{kMachUint16, kArm64Ldrh, kArm64Strh,
{-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 258, 260, 4096, 4098,
4100, 4242, 6786, 8188, 8190}},
{kMachInt32, kArm64LdrW, kArm64StrW,
{-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 260, 4096, 4100, 8192,
8196, 3276, 3280, 16376, 16380}},
{kMachUint32, kArm64LdrW, kArm64StrW,
{-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 260, 4096, 4100, 8192,
8196, 3276, 3280, 16376, 16380}},
{kMachInt64, kArm64Ldr, kArm64Str,
{-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 264, 4096, 4104, 8192,
8200, 16384, 16392, 32752, 32760}},
{kMachUint64, kArm64Ldr, kArm64Str,
{-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 264, 4096, 4104, 8192,
8200, 16384, 16392, 32752, 32760}},
{kMachFloat32, kArm64LdrS, kArm64StrS,
{-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 260, 4096, 4100, 8192,
8196, 3276, 3280, 16376, 16380}},
{kMachFloat64, kArm64LdrD, kArm64StrD,
{-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 264, 4096, 4104, 8192,
8200, 16384, 16392, 32752, 32760}}};
typedef InstructionSelectorTestWithParam<MemoryAccess>
@ -897,6 +918,23 @@ TEST_P(InstructionSelectorMemoryAccessTest, LoadWithParameters) {
}
TEST_P(InstructionSelectorMemoryAccessTest, LoadWithImmediateIndex) {
const MemoryAccess memacc = GetParam();
TRACED_FOREACH(int32_t, index, memacc.immediates) {
StreamBuilder m(this, memacc.type, kMachPtr);
m.Return(m.Load(memacc.type, m.Parameter(0), m.Int32Constant(index)));
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(memacc.ldr_opcode, s[0]->arch_opcode());
EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
EXPECT_EQ(2U, s[0]->InputCount());
ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
ASSERT_EQ(1U, s[0]->OutputCount());
}
}
TEST_P(InstructionSelectorMemoryAccessTest, StoreWithParameters) {
const MemoryAccess memacc = GetParam();
StreamBuilder m(this, kMachInt32, kMachPtr, kMachInt32, memacc.type);
@ -911,6 +949,25 @@ TEST_P(InstructionSelectorMemoryAccessTest, StoreWithParameters) {
}
TEST_P(InstructionSelectorMemoryAccessTest, StoreWithImmediateIndex) {
const MemoryAccess memacc = GetParam();
TRACED_FOREACH(int32_t, index, memacc.immediates) {
StreamBuilder m(this, kMachInt32, kMachPtr, memacc.type);
m.Store(memacc.type, m.Parameter(0), m.Int32Constant(index),
m.Parameter(1));
m.Return(m.Int32Constant(0));
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(memacc.str_opcode, s[0]->arch_opcode());
EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
ASSERT_EQ(3U, s[0]->InputCount());
ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
EXPECT_EQ(0U, s[0]->OutputCount());
}
}
INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
InstructionSelectorMemoryAccessTest,
::testing::ValuesIn(kMemoryAccesses));

View File

@ -15,7 +15,10 @@ enum ImmediateMode {
kShift64Imm, // 0 - 63
kLogical32Imm,
kLogical64Imm,
kLoadStoreImm, // unsigned 9 bit or signed 7 bit
kLoadStoreImm8, // signed 8 bit or 12 bit unsigned scaled by access size
kLoadStoreImm16,
kLoadStoreImm32,
kLoadStoreImm64,
kNoImmediate
};
@ -54,14 +57,25 @@ class Arm64OperandGenerator FINAL : public OperandGenerator {
return 0 <= value && value < 32;
case kShift64Imm:
return 0 <= value && value < 64;
case kLoadStoreImm:
return (0 <= value && value < (1 << 9)) ||
(-(1 << 6) <= value && value < (1 << 6));
case kLoadStoreImm8:
return IsLoadStoreImmediate(value, LSByte);
case kLoadStoreImm16:
return IsLoadStoreImmediate(value, LSHalfword);
case kLoadStoreImm32:
return IsLoadStoreImmediate(value, LSWord);
case kLoadStoreImm64:
return IsLoadStoreImmediate(value, LSDoubleWord);
case kNoImmediate:
return false;
}
return false;
}
private:
bool IsLoadStoreImmediate(int64_t value, LSDataSize size) {
return Assembler::IsImmLSScaled(value, size) ||
Assembler::IsImmLSUnscaled(value);
}
};
@ -142,32 +156,39 @@ void InstructionSelector::VisitLoad(Node* node) {
Node* base = node->InputAt(0);
Node* index = node->InputAt(1);
ArchOpcode opcode;
ImmediateMode immediate_mode = kNoImmediate;
switch (rep) {
case kRepFloat32:
opcode = kArm64LdrS;
immediate_mode = kLoadStoreImm32;
break;
case kRepFloat64:
opcode = kArm64LdrD;
immediate_mode = kLoadStoreImm64;
break;
case kRepBit: // Fall through.
case kRepWord8:
opcode = typ == kTypeInt32 ? kArm64Ldrsb : kArm64Ldrb;
immediate_mode = kLoadStoreImm8;
break;
case kRepWord16:
opcode = typ == kTypeInt32 ? kArm64Ldrsh : kArm64Ldrh;
immediate_mode = kLoadStoreImm16;
break;
case kRepWord32:
opcode = kArm64LdrW;
immediate_mode = kLoadStoreImm32;
break;
case kRepTagged: // Fall through.
case kRepWord64:
opcode = kArm64Ldr;
immediate_mode = kLoadStoreImm64;
break;
default:
UNREACHABLE();
return;
}
if (g.CanBeImmediate(index, kLoadStoreImm)) {
if (g.CanBeImmediate(index, immediate_mode)) {
Emit(opcode | AddressingModeField::encode(kMode_MRI),
g.DefineAsRegister(node), g.UseRegister(base), g.UseImmediate(index));
} else {
@ -198,32 +219,39 @@ void InstructionSelector::VisitStore(Node* node) {
}
DCHECK_EQ(kNoWriteBarrier, store_rep.write_barrier_kind());
ArchOpcode opcode;
ImmediateMode immediate_mode = kNoImmediate;
switch (rep) {
case kRepFloat32:
opcode = kArm64StrS;
immediate_mode = kLoadStoreImm32;
break;
case kRepFloat64:
opcode = kArm64StrD;
immediate_mode = kLoadStoreImm64;
break;
case kRepBit: // Fall through.
case kRepWord8:
opcode = kArm64Strb;
immediate_mode = kLoadStoreImm8;
break;
case kRepWord16:
opcode = kArm64Strh;
immediate_mode = kLoadStoreImm16;
break;
case kRepWord32:
opcode = kArm64StrW;
immediate_mode = kLoadStoreImm32;
break;
case kRepTagged: // Fall through.
case kRepWord64:
opcode = kArm64Str;
immediate_mode = kLoadStoreImm64;
break;
default:
UNREACHABLE();
return;
}
if (g.CanBeImmediate(index, kLoadStoreImm)) {
if (g.CanBeImmediate(index, immediate_mode)) {
Emit(opcode | AddressingModeField::encode(kMode_MRI), NULL,
g.UseRegister(base), g.UseImmediate(index), g.UseRegister(value));
} else {