[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:
parent
42054156ce
commit
bca9d01dc5
@ -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);
|
||||
|
@ -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));
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user