| Index: src/compiler/arm64/instruction-selector-arm64.cc
|
| diff --git a/src/compiler/arm64/instruction-selector-arm64.cc b/src/compiler/arm64/instruction-selector-arm64.cc
|
| index 6106c514f14468f0a86c57a7abebbcc321578ea2..fc57dcdf1473d0959de80ec733b8ef5cf56872ba 100644
|
| --- a/src/compiler/arm64/instruction-selector-arm64.cc
|
| +++ b/src/compiler/arm64/instruction-selector-arm64.cc
|
| @@ -121,6 +121,13 @@ class Arm64OperandGenerator final : public OperandGenerator {
|
| return false;
|
| }
|
|
|
| + bool CanBeLoadStoreShiftImmediate(Node* node, MachineRepresentation rep) {
|
| + // TODO(arm64): Load and Store on 128 bit Q registers is not supported yet.
|
| + DCHECK_NE(MachineRepresentation::kSimd128, rep);
|
| + return IsIntegerConstant(node) &&
|
| + (GetIntegerConstantValue(node) == ElementSizeLog2Of(rep));
|
| + }
|
| +
|
| private:
|
| bool IsLoadStoreImmediate(int64_t value, LSDataSize size) {
|
| return Assembler::IsImmLSScaled(value, size) ||
|
| @@ -226,6 +233,28 @@ bool TryMatchAnyExtend(Arm64OperandGenerator* g, InstructionSelector* selector,
|
| return false;
|
| }
|
|
|
| +bool TryMatchLoadStoreShift(Arm64OperandGenerator* g,
|
| + InstructionSelector* selector,
|
| + MachineRepresentation rep, Node* node, Node* index,
|
| + InstructionOperand* index_op,
|
| + InstructionOperand* shift_immediate_op) {
|
| + if (!selector->CanCover(node, index)) return false;
|
| + if (index->InputCount() != 2) return false;
|
| + Node* left = index->InputAt(0);
|
| + Node* right = index->InputAt(1);
|
| + switch (index->opcode()) {
|
| + case IrOpcode::kWord32Shl:
|
| + case IrOpcode::kWord64Shl:
|
| + if (!g->CanBeLoadStoreShiftImmediate(right, rep)) {
|
| + return false;
|
| + }
|
| + *index_op = g->UseRegister(left);
|
| + *shift_immediate_op = g->UseImmediate(right);
|
| + return true;
|
| + default:
|
| + return false;
|
| + }
|
| +}
|
|
|
| // Shared routine for multiple binary operations.
|
| template <typename Matcher>
|
| @@ -359,12 +388,16 @@ int32_t LeftShiftForReducedMultiply(Matcher* m) {
|
|
|
| void InstructionSelector::VisitLoad(Node* node) {
|
| LoadRepresentation load_rep = LoadRepresentationOf(node->op());
|
| + MachineRepresentation rep = load_rep.representation();
|
| Arm64OperandGenerator g(this);
|
| Node* base = node->InputAt(0);
|
| Node* index = node->InputAt(1);
|
| - ArchOpcode opcode = kArchNop;
|
| + InstructionCode opcode = kArchNop;
|
| ImmediateMode immediate_mode = kNoImmediate;
|
| - switch (load_rep.representation()) {
|
| + InstructionOperand inputs[3];
|
| + size_t input_count = 0;
|
| + InstructionOperand outputs[1];
|
| + switch (rep) {
|
| case MachineRepresentation::kFloat32:
|
| opcode = kArm64LdrS;
|
| immediate_mode = kLoadStoreImm32;
|
| @@ -396,13 +429,25 @@ void InstructionSelector::VisitLoad(Node* node) {
|
| UNREACHABLE();
|
| return;
|
| }
|
| +
|
| + outputs[0] = g.DefineAsRegister(node);
|
| + inputs[0] = g.UseRegister(base);
|
| +
|
| if (g.CanBeImmediate(index, immediate_mode)) {
|
| - Emit(opcode | AddressingModeField::encode(kMode_MRI),
|
| - g.DefineAsRegister(node), g.UseRegister(base), g.UseImmediate(index));
|
| + input_count = 2;
|
| + inputs[1] = g.UseImmediate(index);
|
| + opcode |= AddressingModeField::encode(kMode_MRI);
|
| + } else if (TryMatchLoadStoreShift(&g, this, rep, node, index, &inputs[1],
|
| + &inputs[2])) {
|
| + input_count = 3;
|
| + opcode |= AddressingModeField::encode(kMode_Operand2_R_LSL_I);
|
| } else {
|
| - Emit(opcode | AddressingModeField::encode(kMode_MRR),
|
| - g.DefineAsRegister(node), g.UseRegister(base), g.UseRegister(index));
|
| + input_count = 2;
|
| + inputs[1] = g.UseRegister(index);
|
| + opcode |= AddressingModeField::encode(kMode_MRR);
|
| }
|
| +
|
| + Emit(opcode, arraysize(outputs), outputs, input_count, inputs);
|
| }
|
|
|
|
|
| @@ -456,7 +501,9 @@ void InstructionSelector::VisitStore(Node* node) {
|
| code |= MiscField::encode(static_cast<int>(record_write_mode));
|
| Emit(code, 0, nullptr, input_count, inputs, temp_count, temps);
|
| } else {
|
| - ArchOpcode opcode = kArchNop;
|
| + InstructionOperand inputs[4];
|
| + size_t input_count = 0;
|
| + InstructionCode opcode = kArchNop;
|
| ImmediateMode immediate_mode = kNoImmediate;
|
| switch (rep) {
|
| case MachineRepresentation::kFloat32:
|
| @@ -490,15 +537,25 @@ void InstructionSelector::VisitStore(Node* node) {
|
| UNREACHABLE();
|
| return;
|
| }
|
| +
|
| + inputs[0] = g.UseRegisterOrImmediateZero(value);
|
| + inputs[1] = g.UseRegister(base);
|
| +
|
| if (g.CanBeImmediate(index, immediate_mode)) {
|
| - Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(),
|
| - g.UseRegister(base), g.UseImmediate(index),
|
| - g.UseRegisterOrImmediateZero(value));
|
| + input_count = 3;
|
| + inputs[2] = g.UseImmediate(index);
|
| + opcode |= AddressingModeField::encode(kMode_MRI);
|
| + } else if (TryMatchLoadStoreShift(&g, this, rep, node, index, &inputs[2],
|
| + &inputs[3])) {
|
| + input_count = 4;
|
| + opcode |= AddressingModeField::encode(kMode_Operand2_R_LSL_I);
|
| } else {
|
| - Emit(opcode | AddressingModeField::encode(kMode_MRR), g.NoOutput(),
|
| - g.UseRegister(base), g.UseRegister(index),
|
| - g.UseRegisterOrImmediateZero(value));
|
| + input_count = 3;
|
| + inputs[2] = g.UseRegister(index);
|
| + opcode |= AddressingModeField::encode(kMode_MRR);
|
| }
|
| +
|
| + Emit(opcode, 0, nullptr, input_count, inputs);
|
| }
|
| }
|
|
|
|
|