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); |
} |
} |