[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:
parent
108cd50b84
commit
d9cb964e57
@ -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();
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user