| 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 5f1015131a63215869805b569d143dcbeeb92d99..9f0adbc9afea1c70b415da410b3d439b381083a9 100644
|
| --- a/src/compiler/x64/instruction-selector-x64.cc
|
| +++ b/src/compiler/x64/instruction-selector-x64.cc
|
| @@ -37,6 +37,15 @@ class X64OperandGenerator final : public OperandGenerator {
|
| }
|
| }
|
|
|
| + int32_t GetImmediateIntegerValue(Node* node) {
|
| + DCHECK(CanBeImmediate(node));
|
| + if (node->opcode() == IrOpcode::kInt32Constant) {
|
| + return OpParameter<int32_t>(node);
|
| + }
|
| + DCHECK_EQ(IrOpcode::kInt64Constant, node->opcode());
|
| + return static_cast<int32_t>(OpParameter<int64_t>(node));
|
| + }
|
| +
|
| bool CanBeMemoryOperand(InstructionCode opcode, Node* node, Node* input,
|
| int effect_level) {
|
| if (input->opcode() != IrOpcode::kLoad ||
|
| @@ -631,33 +640,14 @@ void InstructionSelector::VisitWord32Shr(Node* node) {
|
| VisitWord32Shift(this, node, kX64Shr32);
|
| }
|
|
|
| -
|
| -void InstructionSelector::VisitWord64Shr(Node* node) {
|
| - VisitWord64Shift(this, node, kX64Shr);
|
| -}
|
| -
|
| -
|
| -void InstructionSelector::VisitWord32Sar(Node* node) {
|
| - X64OperandGenerator g(this);
|
| - Int32BinopMatcher m(node);
|
| - if (CanCover(m.node(), m.left().node()) && m.left().IsWord32Shl()) {
|
| - Int32BinopMatcher mleft(m.left().node());
|
| - if (mleft.right().Is(16) && m.right().Is(16)) {
|
| - Emit(kX64Movsxwl, g.DefineAsRegister(node), g.Use(mleft.left().node()));
|
| - return;
|
| - } else if (mleft.right().Is(24) && m.right().Is(24)) {
|
| - Emit(kX64Movsxbl, g.DefineAsRegister(node), g.Use(mleft.left().node()));
|
| - return;
|
| - }
|
| - }
|
| - VisitWord32Shift(this, node, kX64Sar32);
|
| -}
|
| -
|
| -
|
| -void InstructionSelector::VisitWord64Sar(Node* node) {
|
| - X64OperandGenerator g(this);
|
| +namespace {
|
| +bool TryMatchLoadWord64AndShiftRight(InstructionSelector* selector, Node* node,
|
| + InstructionCode opcode) {
|
| + DCHECK(IrOpcode::kWord64Sar == node->opcode() ||
|
| + IrOpcode::kWord64Shr == node->opcode());
|
| + X64OperandGenerator g(selector);
|
| Int64BinopMatcher m(node);
|
| - if (CanCover(m.node(), m.left().node()) && m.left().IsLoad() &&
|
| + if (selector->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.
|
| @@ -715,16 +705,43 @@ void InstructionSelector::VisitWord64Sar(Node* node) {
|
| }
|
| 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);
|
| + int32_t displacement = g.GetImmediateIntegerValue(mleft.displacement());
|
| + inputs[input_count - 1] =
|
| + ImmediateOperand(ImmediateOperand::INLINE, displacement + 4);
|
| }
|
| InstructionOperand outputs[] = {g.DefineAsRegister(node)};
|
| - InstructionCode code = kX64Movsxlq | AddressingModeField::encode(mode);
|
| - Emit(code, 1, outputs, input_count, inputs);
|
| + InstructionCode code = opcode | AddressingModeField::encode(mode);
|
| + selector->Emit(code, 1, outputs, input_count, inputs);
|
| + return true;
|
| + }
|
| + }
|
| + return false;
|
| +}
|
| +} // namespace
|
| +
|
| +void InstructionSelector::VisitWord64Shr(Node* node) {
|
| + if (TryMatchLoadWord64AndShiftRight(this, node, kX64Movl)) return;
|
| + VisitWord64Shift(this, node, kX64Shr);
|
| +}
|
| +
|
| +void InstructionSelector::VisitWord32Sar(Node* node) {
|
| + X64OperandGenerator g(this);
|
| + Int32BinopMatcher m(node);
|
| + if (CanCover(m.node(), m.left().node()) && m.left().IsWord32Shl()) {
|
| + Int32BinopMatcher mleft(m.left().node());
|
| + if (mleft.right().Is(16) && m.right().Is(16)) {
|
| + Emit(kX64Movsxwl, g.DefineAsRegister(node), g.Use(mleft.left().node()));
|
| + return;
|
| + } else if (mleft.right().Is(24) && m.right().Is(24)) {
|
| + Emit(kX64Movsxbl, g.DefineAsRegister(node), g.Use(mleft.left().node()));
|
| return;
|
| }
|
| }
|
| + VisitWord32Shift(this, node, kX64Sar32);
|
| +}
|
| +
|
| +void InstructionSelector::VisitWord64Sar(Node* node) {
|
| + if (TryMatchLoadWord64AndShiftRight(this, node, kX64Movsxlq)) return;
|
| VisitWord64Shift(this, node, kX64Sar);
|
| }
|
|
|
| @@ -1258,6 +1275,10 @@ void InstructionSelector::VisitTruncateInt64ToInt32(Node* node) {
|
| case IrOpcode::kWord64Shr: {
|
| Int64BinopMatcher m(value);
|
| if (m.right().Is(32)) {
|
| + if (TryMatchLoadWord64AndShiftRight(this, value, kX64Movl)) {
|
| + Emit(kArchNop, g.DefineSameAsFirst(node), g.Use(value));
|
| + return;
|
| + }
|
| Emit(kX64Shr, g.DefineSameAsFirst(node),
|
| g.UseRegister(m.left().node()), g.TempImmediate(32));
|
| return;
|
|
|