Commit 074fdf1f authored by Pierre Langlois's avatar Pierre Langlois Committed by Commit Bot

[turbofan][arm64] Relax immediate offset conditions on stores with barriers.

With a write barrier, stores with negative offsets would allocate a temporary
register to hold the offset when the `str` instruction is able to encode it.

For instance, when writing the object map:

```
;; This could be 'str x2, [x5, #-1]'
movn x4, #0x0
str x2, [x5, x4]
and x16, x5, #0xfffffffffffc0000
ldr x16, [x16, #8]
tbnz w16, #2, #+0xba8  ; Jump out-of-line
```

The reason behind this is that the out-of-line code uses an 'add' instruction on
the offset to compute the field address, putting pressure on the instruction
selector to make sure the immediate fits in both 'str' and 'add'.

But, this is not necessary since the macro-assembler is able to turn the 'add'
into a 'sub' or use a temporary register if needed.

Change-Id: I8838e4b81a0c0c1f90aa3d67861a9da1a6dfed06
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1708471Reviewed-by: 's avatarRoss McIlroy <rmcilroy@chromium.org>
Reviewed-by: 's avatarSigurd Schneider <sigurds@chromium.org>
Commit-Queue: Pierre Langlois <pierre.langlois@arm.com>
Cr-Commit-Position: refs/heads/master@{#62803}
parent ee16525e
......@@ -676,10 +676,10 @@ void InstructionSelector::VisitStore(Node* node) {
InstructionOperand inputs[3];
size_t input_count = 0;
inputs[input_count++] = g.UseUniqueRegister(base);
// OutOfLineRecordWrite uses the index in an arithmetic instruction, so we
// must check kArithmeticImm as well as kLoadStoreImm64.
if (g.CanBeImmediate(index, kArithmeticImm) &&
g.CanBeImmediate(index, kLoadStoreImm64)) {
// OutOfLineRecordWrite uses the index in an add or sub instruction, but we
// can trust the assembler to generate extra instructions if the index does
// not fit into add or sub. So here only check the immediate for a store.
if (g.CanBeImmediate(index, kLoadStoreImm64)) {
inputs[input_count++] = g.UseImmediate(index);
addressing_mode = kMode_MRI;
} else {
......
......@@ -2844,6 +2844,59 @@ INSTANTIATE_TEST_SUITE_P(InstructionSelectorTest,
InstructionSelectorMemoryAccessTest,
::testing::ValuesIn(kMemoryAccesses));
static const WriteBarrierKind kWriteBarrierKinds[] = {
kMapWriteBarrier, kPointerWriteBarrier, kEphemeronKeyWriteBarrier,
kFullWriteBarrier};
const int32_t kStoreWithBarrierImmediates[] = {
-256, -255, -3, -2, -1, 0, 1, 2, 3, 255,
256, 264, 4096, 4104, 8192, 8200, 16384, 16392, 32752, 32760};
using InstructionSelectorStoreWithBarrierTest =
InstructionSelectorTestWithParam<WriteBarrierKind>;
TEST_P(InstructionSelectorStoreWithBarrierTest,
StoreWithWriteBarrierParameters) {
const WriteBarrierKind barrier_kind = GetParam();
StreamBuilder m(this, MachineType::Int32(),
MachineType::TypeCompressedTaggedPointer(),
MachineType::Int32(), MachineType::TypeCompressedTagged());
m.Store(MachineType::RepCompressedTagged(), m.Parameter(0), m.Parameter(1),
m.Parameter(2), barrier_kind);
m.Return(m.Int32Constant(0));
Stream s = m.Build(kAllExceptNopInstructions);
// We have two instructions that are not nops: Store and Return.
ASSERT_EQ(2U, s.size());
EXPECT_EQ(kArchStoreWithWriteBarrier, s[0]->arch_opcode());
EXPECT_EQ(kMode_MRR, s[0]->addressing_mode());
EXPECT_EQ(3U, s[0]->InputCount());
EXPECT_EQ(0U, s[0]->OutputCount());
}
TEST_P(InstructionSelectorStoreWithBarrierTest,
StoreWithWriteBarrierImmediate) {
const WriteBarrierKind barrier_kind = GetParam();
TRACED_FOREACH(int32_t, index, kStoreWithBarrierImmediates) {
StreamBuilder m(this, MachineType::Int32(),
MachineType::TypeCompressedTaggedPointer(),
MachineType::TypeCompressedTagged());
m.Store(MachineType::RepCompressedTagged(), m.Parameter(0),
m.Int32Constant(index), m.Parameter(1), barrier_kind);
m.Return(m.Int32Constant(0));
Stream s = m.Build(kAllExceptNopInstructions);
// We have two instructions that are not nops: Store and Return.
ASSERT_EQ(2U, s.size());
EXPECT_EQ(kArchStoreWithWriteBarrier, s[0]->arch_opcode());
EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
EXPECT_EQ(3U, s[0]->InputCount());
EXPECT_EQ(0U, s[0]->OutputCount());
}
}
INSTANTIATE_TEST_SUITE_P(InstructionSelectorTest,
InstructionSelectorStoreWithBarrierTest,
::testing::ValuesIn(kWriteBarrierKinds));
// -----------------------------------------------------------------------------
// Comparison instructions.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment