Index: src/compiler/mips64/instruction-selector-mips64.cc |
diff --git a/src/compiler/mips64/instruction-selector-mips64.cc b/src/compiler/mips64/instruction-selector-mips64.cc |
index 60790b51b220e6fafa7821fd2bcb2097a62aa2fb..6d2b4d30b8cd9db29ca99d3698c07731f673c0aa 100644 |
--- a/src/compiler/mips64/instruction-selector-mips64.cc |
+++ b/src/compiler/mips64/instruction-selector-mips64.cc |
@@ -142,12 +142,29 @@ static void VisitBinop(InstructionSelector* selector, Node* node, |
VisitBinop(selector, node, opcode, &cont); |
} |
+void EmitLoad(InstructionSelector* selector, Node* node, InstructionCode opcode, |
+ Node* output = nullptr) { |
+ Mips64OperandGenerator g(selector); |
+ Node* base = node->InputAt(0); |
+ Node* index = node->InputAt(1); |
+ |
+ if (g.CanBeImmediate(index, opcode)) { |
+ selector->Emit(opcode | AddressingModeField::encode(kMode_MRI), |
+ g.DefineAsRegister(output == nullptr ? node : output), |
+ g.UseRegister(base), g.UseImmediate(index)); |
+ } else { |
+ InstructionOperand addr_reg = g.TempRegister(); |
+ selector->Emit(kMips64Dadd | AddressingModeField::encode(kMode_None), |
+ addr_reg, g.UseRegister(index), g.UseRegister(base)); |
+ // Emit desired load opcode, using temp addr_reg. |
+ selector->Emit(opcode | AddressingModeField::encode(kMode_MRI), |
+ g.DefineAsRegister(output == nullptr ? node : output), |
+ addr_reg, g.TempImmediate(0)); |
+ } |
+} |
void InstructionSelector::VisitLoad(Node* node) { |
LoadRepresentation load_rep = LoadRepresentationOf(node->op()); |
- Mips64OperandGenerator g(this); |
- Node* base = node->InputAt(0); |
- Node* index = node->InputAt(1); |
ArchOpcode opcode = kArchNop; |
switch (load_rep.representation()) { |
@@ -179,17 +196,7 @@ void InstructionSelector::VisitLoad(Node* node) { |
return; |
} |
- if (g.CanBeImmediate(index, opcode)) { |
- Emit(opcode | AddressingModeField::encode(kMode_MRI), |
- g.DefineAsRegister(node), g.UseRegister(base), g.UseImmediate(index)); |
- } else { |
- InstructionOperand addr_reg = g.TempRegister(); |
- Emit(kMips64Dadd | AddressingModeField::encode(kMode_None), addr_reg, |
- g.UseRegister(index), g.UseRegister(base)); |
- // Emit desired load opcode, using temp addr_reg. |
- Emit(opcode | AddressingModeField::encode(kMode_MRI), |
- g.DefineAsRegister(node), addr_reg, g.TempImmediate(0)); |
- } |
+ EmitLoad(this, node, opcode); |
} |
@@ -501,7 +508,7 @@ void InstructionSelector::VisitWord64Shl(Node* node) { |
Mips64OperandGenerator 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(kMips64Dshl, g.DefineSameAsFirst(node), |
@@ -1064,9 +1071,32 @@ void InstructionSelector::VisitTryTruncateFloat64ToUint64(Node* node) { |
void InstructionSelector::VisitChangeInt32ToInt64(Node* node) { |
- Mips64OperandGenerator g(this); |
- Emit(kMips64Shl, g.DefineAsRegister(node), g.UseRegister(node->InputAt(0)), |
- g.TempImmediate(0)); |
+ Node* value = node->InputAt(0); |
+ if (value->opcode() == IrOpcode::kLoad && CanCover(node, value)) { |
+ // Generate sign-extending load. |
+ LoadRepresentation load_rep = LoadRepresentationOf(value->op()); |
+ InstructionCode opcode = kArchNop; |
+ switch (load_rep.representation()) { |
+ case MachineRepresentation::kBit: // Fall through. |
+ case MachineRepresentation::kWord8: |
+ opcode = load_rep.IsUnsigned() ? kMips64Lbu : kMips64Lb; |
+ break; |
+ case MachineRepresentation::kWord16: |
+ opcode = load_rep.IsUnsigned() ? kMips64Lhu : kMips64Lh; |
+ break; |
+ case MachineRepresentation::kWord32: |
+ opcode = kMips64Lw; |
+ break; |
+ default: |
+ UNREACHABLE(); |
+ return; |
+ } |
+ EmitLoad(this, value, opcode, node); |
+ } else { |
+ Mips64OperandGenerator g(this); |
+ Emit(kMips64Shl, g.DefineAsRegister(node), g.UseRegister(node->InputAt(0)), |
+ g.TempImmediate(0)); |
+ } |
} |