[codegen] Optimize ExternalReference accesses on ARM

Load and store external references using the root register rather than
generating a constant and dereferencing it. This typically uses 1
instruction rather than up to 4.

Also adds external reference store optimisation for arm64.

Bug: v8:7844
Change-Id: I5f73728e7a72e366a31bfb694581e2e7d8250947
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2007270
Commit-Queue: Dan Elphick <delphick@chromium.org>
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#65950}
This commit is contained in:
Dan Elphick 2020-01-20 15:28:46 +00:00 committed by Commit Bot
parent 108cd50b84
commit d9cb964e57
4 changed files with 59 additions and 1 deletions

View File

@ -9,6 +9,7 @@
#include "src/codegen/optimized-compilation-info.h"
#include "src/compiler/backend/code-generator-impl.h"
#include "src/compiler/backend/gap-resolver.h"
#include "src/compiler/backend/instruction-codes.h"
#include "src/compiler/node-matchers.h"
#include "src/compiler/osr.h"
#include "src/heap/heap-inl.h" // crbug.com/v8/8499
@ -54,6 +55,7 @@ class ArmOperandConverter final : public InstructionOperandConverter {
case kMode_None:
case kMode_Offset_RI:
case kMode_Offset_RR:
case kMode_Root:
break;
case kMode_Operand2_I:
return InputImmediate(index + 0);
@ -103,6 +105,9 @@ class ArmOperandConverter final : public InstructionOperandConverter {
case kMode_Offset_RR:
*first_index += 2;
return MemOperand(InputRegister(index + 0), InputRegister(index + 1));
case kMode_Root:
*first_index += 1;
return MemOperand(kRootRegister, InputInt32(index));
}
UNREACHABLE();
}

View File

@ -340,7 +340,8 @@ namespace compiler {
V(Operand2_R_ASR_R) /* %r0 ASR %r1 */ \
V(Operand2_R_LSL_R) /* %r0 LSL %r1 */ \
V(Operand2_R_LSR_R) /* %r0 LSR %r1 */ \
V(Operand2_R_ROR_R) /* %r0 ROR %r1 */
V(Operand2_R_ROR_R) /* %r0 ROR %r1 */ \
V(Root) /* [%rr + K] */
} // namespace compiler
} // namespace internal

View File

@ -377,6 +377,22 @@ void EmitLoad(InstructionSelector* selector, InstructionCode opcode,
InstructionOperand inputs[3];
size_t input_count = 2;
ExternalReferenceMatcher m(base);
if (m.HasValue() && selector->CanAddressRelativeToRootsRegister(m.Value())) {
Int32Matcher int_matcher(index);
if (int_matcher.HasValue()) {
ptrdiff_t const delta =
int_matcher.Value() +
TurboAssemblerBase::RootRegisterOffsetForExternalReference(
selector->isolate(), m.Value());
input_count = 1;
inputs[0] = g.UseImmediate(static_cast<int32_t>(delta));
opcode |= AddressingModeField::encode(kMode_Root);
selector->Emit(opcode, 1, output, input_count, inputs);
return;
}
}
inputs[0] = g.UseRegister(base);
if (g.CanBeImmediate(index, opcode)) {
inputs[1] = g.UseImmediate(index);
@ -637,6 +653,24 @@ void InstructionSelector::VisitStore(Node* node) {
return;
}
ExternalReferenceMatcher m(base);
if (m.HasValue() && CanAddressRelativeToRootsRegister(m.Value())) {
Int32Matcher int_matcher(index);
if (int_matcher.HasValue()) {
ptrdiff_t const delta =
int_matcher.Value() +
TurboAssemblerBase::RootRegisterOffsetForExternalReference(
isolate(), m.Value());
int input_count = 2;
InstructionOperand inputs[2];
inputs[0] = g.UseRegister(value);
inputs[1] = g.UseImmediate(static_cast<int32_t>(delta));
opcode |= AddressingModeField::encode(kMode_Root);
Emit(opcode, 0, nullptr, input_count, inputs);
return;
}
}
InstructionOperand inputs[4];
size_t input_count = 0;
inputs[input_count++] = g.UseRegister(value);

View File

@ -823,6 +823,24 @@ void InstructionSelector::VisitStore(Node* node) {
UNREACHABLE();
}
ExternalReferenceMatcher m(base);
if (m.HasValue() && g.IsIntegerConstant(index) &&
CanAddressRelativeToRootsRegister(m.Value())) {
ptrdiff_t const delta =
g.GetIntegerConstantValue(index) +
TurboAssemblerBase::RootRegisterOffsetForExternalReference(isolate(),
m.Value());
if (is_int32(delta)) {
input_count = 2;
InstructionOperand inputs[2];
inputs[0] = g.UseRegister(value);
inputs[1] = g.UseImmediate(static_cast<int32_t>(delta));
opcode |= AddressingModeField::encode(kMode_Root);
Emit(opcode, 0, nullptr, input_count, inputs);
return;
}
}
inputs[0] = g.UseRegisterOrImmediateZero(value);
inputs[1] = g.UseRegister(base);