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 ad3512339b39448f7698e4cc16f29c02f85380c6..f14da4f7cd1d41fe2e7b53876a6b22f91de5ce9c 100644 |
--- a/src/compiler/arm64/instruction-selector-arm64.cc |
+++ b/src/compiler/arm64/instruction-selector-arm64.cc |
@@ -161,7 +161,6 @@ void VisitRRO(InstructionSelector* selector, ArchOpcode opcode, Node* node, |
g.UseOperand(node->InputAt(1), operand_mode)); |
} |
- |
bool TryMatchAnyShift(InstructionSelector* selector, Node* node, |
Node* input_node, InstructionCode* opcode, bool try_ror) { |
Arm64OperandGenerator g(selector); |
@@ -458,18 +457,43 @@ int32_t LeftShiftForReducedMultiply(Matcher* m) { |
} // namespace |
- |
-void InstructionSelector::VisitLoad(Node* node) { |
- LoadRepresentation load_rep = LoadRepresentationOf(node->op()); |
- MachineRepresentation rep = load_rep.representation(); |
- Arm64OperandGenerator g(this); |
+void EmitLoad(InstructionSelector* selector, Node* node, InstructionCode opcode, |
+ ImmediateMode immediate_mode, MachineRepresentation rep, |
+ Node* output = nullptr) { |
+ Arm64OperandGenerator g(selector); |
Node* base = node->InputAt(0); |
Node* index = node->InputAt(1); |
- InstructionCode opcode = kArchNop; |
- ImmediateMode immediate_mode = kNoImmediate; |
InstructionOperand inputs[3]; |
size_t input_count = 0; |
InstructionOperand outputs[1]; |
+ |
+ // If output is not nullptr, use that as the output register. This |
+ // is used when we merge a conversion into the load. |
+ outputs[0] = g.DefineAsRegister(output == nullptr ? node : output); |
+ inputs[0] = g.UseRegister(base); |
+ |
+ if (g.CanBeImmediate(index, immediate_mode)) { |
+ input_count = 2; |
+ inputs[1] = g.UseImmediate(index); |
+ opcode |= AddressingModeField::encode(kMode_MRI); |
+ } else if (TryMatchLoadStoreShift(&g, selector, rep, node, index, &inputs[1], |
+ &inputs[2])) { |
+ input_count = 3; |
+ opcode |= AddressingModeField::encode(kMode_Operand2_R_LSL_I); |
+ } else { |
+ input_count = 2; |
+ inputs[1] = g.UseRegister(index); |
+ opcode |= AddressingModeField::encode(kMode_MRR); |
+ } |
+ |
+ selector->Emit(opcode, arraysize(outputs), outputs, input_count, inputs); |
+} |
+ |
+void InstructionSelector::VisitLoad(Node* node) { |
+ InstructionCode opcode = kArchNop; |
+ ImmediateMode immediate_mode = kNoImmediate; |
+ LoadRepresentation load_rep = LoadRepresentationOf(node->op()); |
+ MachineRepresentation rep = load_rep.representation(); |
switch (rep) { |
case MachineRepresentation::kFloat32: |
opcode = kArm64LdrS; |
@@ -502,25 +526,7 @@ void InstructionSelector::VisitLoad(Node* node) { |
UNREACHABLE(); |
return; |
} |
- |
- outputs[0] = g.DefineAsRegister(node); |
- inputs[0] = g.UseRegister(base); |
- |
- if (g.CanBeImmediate(index, immediate_mode)) { |
- 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 { |
- input_count = 2; |
- inputs[1] = g.UseRegister(index); |
- opcode |= AddressingModeField::encode(kMode_MRR); |
- } |
- |
- Emit(opcode, arraysize(outputs), outputs, input_count, inputs); |
+ EmitLoad(this, node, opcode, immediate_mode, rep); |
} |
@@ -959,7 +965,7 @@ void InstructionSelector::VisitWord64Shl(Node* node) { |
Arm64OperandGenerator g(this); |
Int64BinopMatcher m(node); |
if ((m.left().IsChangeInt32ToInt64() || m.left().IsChangeUint32ToUint64()) && |
- m.right().IsInRange(32, 63)) { |
+ m.right().IsInRange(32, 63) && CanCover(node, m.left().node())) { |
// There's no need to sign/zero-extend to 64-bit if we shift out the upper |
// 32 bits anyway. |
Emit(kArm64Lsl, g.DefineAsRegister(node), |
@@ -1563,7 +1569,35 @@ void InstructionSelector::VisitTryTruncateFloat64ToUint64(Node* node) { |
void InstructionSelector::VisitChangeInt32ToInt64(Node* node) { |
- VisitRR(this, kArm64Sxtw, node); |
+ Node* value = node->InputAt(0); |
+ if (value->opcode() == IrOpcode::kLoad && CanCover(node, value)) { |
+ // Generate sign-extending load. |
+ LoadRepresentation load_rep = LoadRepresentationOf(value->op()); |
+ MachineRepresentation rep = load_rep.representation(); |
+ InstructionCode opcode = kArchNop; |
+ ImmediateMode immediate_mode = kNoImmediate; |
+ switch (rep) { |
+ case MachineRepresentation::kBit: // Fall through. |
+ case MachineRepresentation::kWord8: |
+ opcode = load_rep.IsSigned() ? kArm64Ldrsb : kArm64Ldrb; |
+ immediate_mode = kLoadStoreImm8; |
+ break; |
+ case MachineRepresentation::kWord16: |
+ opcode = load_rep.IsSigned() ? kArm64Ldrsh : kArm64Ldrh; |
+ immediate_mode = kLoadStoreImm16; |
+ break; |
+ case MachineRepresentation::kWord32: |
+ opcode = kArm64Ldrsw; |
+ immediate_mode = kLoadStoreImm32; |
+ break; |
+ default: |
+ UNREACHABLE(); |
+ return; |
+ } |
+ EmitLoad(this, value, opcode, immediate_mode, rep, node); |
+ } else { |
+ VisitRR(this, kArm64Sxtw, node); |
+ } |
} |