Index: src/compiler/x64/instruction-selector-x64.cc |
diff --git a/src/compiler/x64/instruction-selector-x64.cc b/src/compiler/x64/instruction-selector-x64.cc |
index edcf62a5ecbcd19db8a68d1a0c2abf08ecd508c9..282049e8130d3593894b001a160e7bb9b5fae300 100644 |
--- a/src/compiler/x64/instruction-selector-x64.cc |
+++ b/src/compiler/x64/instruction-selector-x64.cc |
@@ -63,6 +63,17 @@ class X64OperandGenerator final : public OperandGenerator { |
return false; |
} |
+ AddressingMode EnsureHasDisplacement( |
+ const BaseWithIndexAndDisplacement64Matcher& matcher, |
+ AddressingMode mode) { |
+ if (matcher.displacement() != nullptr) { |
+ return mode; |
+ } |
+ DCHECK(mode == kMode_MR || (kMode_MR1 <= mode && mode <= kMode_MR8) || |
Benedikt Meurer
2016/04/01 08:33:00
As discussed offline, please do a switch here. And
epertoso
2016/04/01 09:16:44
Done.
|
+ (kMode_M4 == mode || kMode_M8 == mode)); |
+ return mode == kMode_MR ? kMode_MRI : static_cast<AddressingMode>(mode + 4); |
+ } |
+ |
AddressingMode GenerateMemoryOperandInputs(Node* index, int scale_exponent, |
Node* base, Node* displacement, |
InstructionOperand inputs[], |
@@ -618,6 +629,33 @@ void InstructionSelector::VisitWord32Sar(Node* node) { |
void InstructionSelector::VisitWord64Sar(Node* node) { |
+ X64OperandGenerator g(this); |
+ Int64BinopMatcher m(node); |
+ if (CanCover(m.node(), m.left().node()) && m.left().IsLoad() && |
+ m.right().Is(32)) { |
+ // Just load and sign-extend the interesting 4 bytes instead. This happens, |
+ // for example, when we're loading and untagging SMIs. |
+ BaseWithIndexAndDisplacement64Matcher mleft(m.left().node(), true); |
+ if (mleft.matches() && (mleft.displacement() == nullptr || |
+ g.CanBeImmediate(mleft.displacement()))) { |
+ size_t input_count = 0; |
+ InstructionOperand inputs[3]; |
+ AddressingMode mode = g.GetEffectiveAddressMemoryOperand( |
+ m.left().node(), inputs, &input_count); |
+ mode = g.EnsureHasDisplacement(mleft, mode); |
+ if (mleft.displacement() == nullptr) { |
+ inputs[input_count++] = ImmediateOperand(ImmediateOperand::INLINE, 4); |
+ } else { |
+ ImmediateOperand* op = ImmediateOperand::cast(&inputs[input_count - 1]); |
+ int32_t displacement = sequence()->GetImmediate(op).ToInt32(); |
+ *op = ImmediateOperand(ImmediateOperand::INLINE, displacement + 4); |
+ } |
+ InstructionOperand outputs[] = {g.DefineAsRegister(node)}; |
+ InstructionCode code = kX64Movsxlq | AddressingModeField::encode(mode); |
+ Emit(code, 1, outputs, input_count, inputs); |
+ return; |
+ } |
+ } |
VisitWord64Shift(this, node, kX64Sar); |
} |