From 79ebd37d6590d2cc81d5acfc8296bea2af7c2d30 Mon Sep 17 00:00:00 2001 From: epertoso Date: Fri, 29 Jul 2016 04:03:57 -0700 Subject: [PATCH] [turbofan] Adds speculative opcodes for shift right. Drive-by fix: actually match the hint in the IsSpeculativeBinopMatcher. Review-Url: https://codereview.chromium.org/2191883002 Cr-Commit-Position: refs/heads/master@{#38176} --- src/compiler/js-typed-lowering.cc | 38 ++-- src/compiler/js-typed-lowering.h | 1 - src/compiler/opcodes.h | 172 +++++++++--------- src/compiler/simplified-lowering.cc | 58 ++++++ src/compiler/simplified-operator.cc | 8 +- src/compiler/simplified-operator.h | 3 + src/compiler/typer.cc | 8 + src/compiler/verifier.cc | 4 + .../mjsunit/compiler/turbo-number-feedback.js | 22 +++ .../compiler/js-typed-lowering-unittest.cc | 91 +++++---- test/unittests/compiler/node-test-utils.cc | 25 +++ test/unittests/compiler/node-test-utils.h | 10 + 12 files changed, 296 insertions(+), 144 deletions(-) diff --git a/src/compiler/js-typed-lowering.cc b/src/compiler/js-typed-lowering.cc index e7e43d080f..0964e46123 100644 --- a/src/compiler/js-typed-lowering.cc +++ b/src/compiler/js-typed-lowering.cc @@ -590,39 +590,39 @@ Reduction JSTypedLowering::ReduceInt32Binop(Node* node, const Operator* intOp) { return r.ChangeToPureOperator(intOp, Type::Integral32()); } -Reduction JSTypedLowering::ReduceShiftLeft(Node* node) { +Reduction JSTypedLowering::ReduceUI32Shift(Node* node, + Signedness left_signedness, + const Operator* shift_op) { if (flags() & kDisableIntegerBinaryOpReduction) return NoChange(); - JSBinopReduction r(this, node); BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback(); if (feedback != BinaryOperationHints::kAny) { + Operator const* speculative_op; + if (shift_op->opcode() == IrOpcode::kNumberShiftLeft) { + speculative_op = simplified()->SpeculativeNumberShiftLeft(feedback); + } else if (shift_op->opcode() == IrOpcode::kNumberShiftRightLogical) { + speculative_op = + simplified()->SpeculativeNumberShiftRightLogical(feedback); + } else { + DCHECK(shift_op->opcode() == IrOpcode::kNumberShiftRight); + speculative_op = simplified()->SpeculativeNumberShiftRight(feedback); + } return r.ChangeToSpeculativeOperator( - simplified()->SpeculativeNumberShiftLeft(feedback), Type::Signed32()); + speculative_op, shift_op->opcode() == IrOpcode::kNumberShiftRightLogical + ? Type::Unsigned32() + : Type::Signed32()); } // If deoptimization is enabled we rely on type feedback. if (r.BothInputsAre(Type::PlainPrimitive()) || !(flags() & kDeoptimizationEnabled)) { r.ConvertInputsToNumber(); - r.ConvertInputsToUI32(kSigned, kUnsigned); - return r.ChangeToPureOperator(simplified()->NumberShiftLeft(), - Type::Number()); + r.ConvertInputsToUI32(left_signedness, kUnsigned); + return r.ChangeToPureOperator(shift_op); } return NoChange(); } -Reduction JSTypedLowering::ReduceUI32Shift(Node* node, - Signedness left_signedness, - const Operator* shift_op) { - if (flags() & kDisableIntegerBinaryOpReduction) return NoChange(); - - JSBinopReduction r(this, node); - r.ConvertInputsToNumber(); - r.ConvertInputsToUI32(left_signedness, kUnsigned); - return r.ChangeToPureOperator(shift_op); -} - - Reduction JSTypedLowering::ReduceJSComparison(Node* node) { JSBinopReduction r(this, node); if (r.BothInputsAre(Type::String())) { @@ -2049,7 +2049,7 @@ Reduction JSTypedLowering::Reduce(Node* node) { case IrOpcode::kJSBitwiseAnd: return ReduceInt32Binop(node, simplified()->NumberBitwiseAnd()); case IrOpcode::kJSShiftLeft: - return ReduceShiftLeft(node); + return ReduceUI32Shift(node, kSigned, simplified()->NumberShiftLeft()); case IrOpcode::kJSShiftRight: return ReduceUI32Shift(node, kSigned, simplified()->NumberShiftRight()); case IrOpcode::kJSShiftRightLogical: diff --git a/src/compiler/js-typed-lowering.h b/src/compiler/js-typed-lowering.h index 8e9ac6cf7d..123fd99dec 100644 --- a/src/compiler/js-typed-lowering.h +++ b/src/compiler/js-typed-lowering.h @@ -86,7 +86,6 @@ class JSTypedLowering final : public AdvancedReducer { Reduction ReduceJSSubtract(Node* node); Reduction ReduceJSDivide(Node* node); Reduction ReduceInt32Binop(Node* node, const Operator* intOp); - Reduction ReduceShiftLeft(Node* node); Reduction ReduceUI32Shift(Node* node, Signedness left_signedness, const Operator* shift_op); diff --git a/src/compiler/opcodes.h b/src/compiler/opcodes.h index c3179d73fb..1545e6ddf7 100644 --- a/src/compiler/opcodes.h +++ b/src/compiler/opcodes.h @@ -204,91 +204,93 @@ V(StringLessThan) \ V(StringLessThanOrEqual) -#define SIMPLIFIED_OTHER_OP_LIST(V) \ - V(PlainPrimitiveToNumber) \ - V(PlainPrimitiveToWord32) \ - V(PlainPrimitiveToFloat64) \ - V(BooleanNot) \ - V(SpeculativeNumberAdd) \ - V(SpeculativeNumberSubtract) \ - V(SpeculativeNumberMultiply) \ - V(SpeculativeNumberDivide) \ - V(SpeculativeNumberModulus) \ - V(SpeculativeNumberEqual) \ - V(SpeculativeNumberLessThan) \ - V(SpeculativeNumberLessThanOrEqual) \ - V(NumberAdd) \ - V(NumberSubtract) \ - V(NumberMultiply) \ - V(NumberDivide) \ - V(NumberModulus) \ - V(NumberBitwiseOr) \ - V(NumberBitwiseXor) \ - V(NumberBitwiseAnd) \ - V(NumberShiftLeft) \ - V(SpeculativeNumberShiftLeft) \ - V(NumberShiftRight) \ - V(NumberShiftRightLogical) \ - V(NumberImul) \ - V(NumberAbs) \ - V(NumberClz32) \ - V(NumberCeil) \ - V(NumberCos) \ - V(NumberCosh) \ - V(NumberFloor) \ - V(NumberFround) \ - V(NumberAcos) \ - V(NumberAcosh) \ - V(NumberAsin) \ - V(NumberAsinh) \ - V(NumberAtan) \ - V(NumberAtanh) \ - V(NumberAtan2) \ - V(NumberExp) \ - V(NumberExpm1) \ - V(NumberLog) \ - V(NumberLog1p) \ - V(NumberLog2) \ - V(NumberLog10) \ - V(NumberMax) \ - V(NumberMin) \ - V(NumberCbrt) \ - V(NumberPow) \ - V(NumberRound) \ - V(NumberSign) \ - V(NumberSin) \ - V(NumberSinh) \ - V(NumberSqrt) \ - V(NumberTan) \ - V(NumberTanh) \ - V(NumberTrunc) \ - V(NumberToInt32) \ - V(NumberToUint32) \ - V(NumberSilenceNaN) \ - V(StringCharCodeAt) \ - V(StringFromCharCode) \ - V(CheckBounds) \ - V(CheckIf) \ - V(CheckMaps) \ - V(CheckNumber) \ - V(CheckString) \ - V(CheckTaggedPointer) \ - V(CheckTaggedSigned) \ - V(CheckFloat64Hole) \ - V(CheckTaggedHole) \ - V(Allocate) \ - V(LoadField) \ - V(LoadBuffer) \ - V(LoadElement) \ - V(StoreField) \ - V(StoreBuffer) \ - V(StoreElement) \ - V(ObjectIsCallable) \ - V(ObjectIsNumber) \ - V(ObjectIsReceiver) \ - V(ObjectIsSmi) \ - V(ObjectIsString) \ - V(ObjectIsUndetectable) \ +#define SIMPLIFIED_OTHER_OP_LIST(V) \ + V(PlainPrimitiveToNumber) \ + V(PlainPrimitiveToWord32) \ + V(PlainPrimitiveToFloat64) \ + V(BooleanNot) \ + V(SpeculativeNumberAdd) \ + V(SpeculativeNumberSubtract) \ + V(SpeculativeNumberMultiply) \ + V(SpeculativeNumberDivide) \ + V(SpeculativeNumberModulus) \ + V(SpeculativeNumberEqual) \ + V(SpeculativeNumberLessThan) \ + V(SpeculativeNumberLessThanOrEqual) \ + V(NumberAdd) \ + V(NumberSubtract) \ + V(NumberMultiply) \ + V(NumberDivide) \ + V(NumberModulus) \ + V(NumberBitwiseOr) \ + V(NumberBitwiseXor) \ + V(NumberBitwiseAnd) \ + V(NumberShiftLeft) \ + V(SpeculativeNumberShiftLeft) \ + V(SpeculativeNumberShiftRight) \ + V(SpeculativeNumberShiftRightLogical) \ + V(NumberShiftRight) \ + V(NumberShiftRightLogical) \ + V(NumberImul) \ + V(NumberAbs) \ + V(NumberClz32) \ + V(NumberCeil) \ + V(NumberCos) \ + V(NumberCosh) \ + V(NumberFloor) \ + V(NumberFround) \ + V(NumberAcos) \ + V(NumberAcosh) \ + V(NumberAsin) \ + V(NumberAsinh) \ + V(NumberAtan) \ + V(NumberAtanh) \ + V(NumberAtan2) \ + V(NumberExp) \ + V(NumberExpm1) \ + V(NumberLog) \ + V(NumberLog1p) \ + V(NumberLog2) \ + V(NumberLog10) \ + V(NumberMax) \ + V(NumberMin) \ + V(NumberCbrt) \ + V(NumberPow) \ + V(NumberRound) \ + V(NumberSign) \ + V(NumberSin) \ + V(NumberSinh) \ + V(NumberSqrt) \ + V(NumberTan) \ + V(NumberTanh) \ + V(NumberTrunc) \ + V(NumberToInt32) \ + V(NumberToUint32) \ + V(NumberSilenceNaN) \ + V(StringCharCodeAt) \ + V(StringFromCharCode) \ + V(CheckBounds) \ + V(CheckIf) \ + V(CheckMaps) \ + V(CheckNumber) \ + V(CheckString) \ + V(CheckTaggedPointer) \ + V(CheckTaggedSigned) \ + V(CheckFloat64Hole) \ + V(CheckTaggedHole) \ + V(Allocate) \ + V(LoadField) \ + V(LoadBuffer) \ + V(LoadElement) \ + V(StoreField) \ + V(StoreBuffer) \ + V(StoreElement) \ + V(ObjectIsCallable) \ + V(ObjectIsNumber) \ + V(ObjectIsReceiver) \ + V(ObjectIsSmi) \ + V(ObjectIsString) \ + V(ObjectIsUndetectable) \ V(TransitionElementsKind) #define SIMPLIFIED_OP_LIST(V) \ diff --git a/src/compiler/simplified-lowering.cc b/src/compiler/simplified-lowering.cc index 46cf22c2e6..093b09ecc0 100644 --- a/src/compiler/simplified-lowering.cc +++ b/src/compiler/simplified-lowering.cc @@ -1692,6 +1692,35 @@ class RepresentationSelector { } return; } + case IrOpcode::kSpeculativeNumberShiftRight: { + // ToNumber(x) can throw if x is either a Receiver or a Symbol, so we + // can only eliminate an unused speculative number operation if we know + // that the inputs are PlainPrimitive, which excludes everything that's + // might have side effects or throws during a ToNumber conversion. + if (BothInputsAre(node, Type::PlainPrimitive())) { + if (truncation.IsUnused()) return VisitUnused(node); + } + if (BothInputsAre(node, Type::NumberOrOddball())) { + Type* rhs_type = GetUpperBound(node->InputAt(1)); + VisitBinop(node, UseInfo::TruncatingWord32(), + UseInfo::TruncatingWord32(), + MachineRepresentation::kWord32); + if (lower()) { + lowering->DoShift(node, lowering->machine()->Word32Sar(), rhs_type); + } + return; + } + BinaryOperationHints::Hint hint = BinaryOperationHintOf(node->op()); + Type* rhs_type = GetUpperBound(node->InputAt(1)); + VisitBinop(node, hint == BinaryOperationHints::kNumberOrOddball + ? UseInfo::CheckedNumberOrOddballAsWord32() + : UseInfo::CheckedSigned32AsWord32(), + MachineRepresentation::kWord32, Type::Signed32()); + if (lower()) { + lowering->DoShift(node, lowering->machine()->Word32Sar(), rhs_type); + } + return; + } case IrOpcode::kNumberShiftRightLogical: { Type* rhs_type = GetUpperBound(node->InputAt(1)); VisitBinop(node, UseInfo::TruncatingWord32(), @@ -1701,6 +1730,35 @@ class RepresentationSelector { } return; } + case IrOpcode::kSpeculativeNumberShiftRightLogical: { + // ToNumber(x) can throw if x is either a Receiver or a Symbol, so we + // can only eliminate an unused speculative number operation if we know + // that the inputs are PlainPrimitive, which excludes everything that's + // might have side effects or throws during a ToNumber conversion. + if (BothInputsAre(node, Type::PlainPrimitive())) { + if (truncation.IsUnused()) return VisitUnused(node); + } + if (BothInputsAre(node, Type::NumberOrOddball())) { + Type* rhs_type = GetUpperBound(node->InputAt(1)); + VisitBinop(node, UseInfo::TruncatingWord32(), + UseInfo::TruncatingWord32(), + MachineRepresentation::kWord32); + if (lower()) { + lowering->DoShift(node, lowering->machine()->Word32Shr(), rhs_type); + } + return; + } + BinaryOperationHints::Hint hint = BinaryOperationHintOf(node->op()); + Type* rhs_type = GetUpperBound(node->InputAt(1)); + VisitBinop(node, hint == BinaryOperationHints::kNumberOrOddball + ? UseInfo::CheckedNumberOrOddballAsWord32() + : UseInfo::CheckedSigned32AsWord32(), + MachineRepresentation::kWord32, Type::Unsigned32()); + if (lower()) { + lowering->DoShift(node, lowering->machine()->Word32Shr(), rhs_type); + } + return; + } case IrOpcode::kNumberAbs: { if (TypeOf(node->InputAt(0))->Is(Type::Unsigned32())) { VisitUnop(node, UseInfo::TruncatingWord32(), diff --git a/src/compiler/simplified-operator.cc b/src/compiler/simplified-operator.cc index 66cfbb7be7..525e3a481f 100644 --- a/src/compiler/simplified-operator.cc +++ b/src/compiler/simplified-operator.cc @@ -267,7 +267,9 @@ BinaryOperationHints::Hint BinaryOperationHintOf(const Operator* op) { op->opcode() == IrOpcode::kSpeculativeNumberMultiply || op->opcode() == IrOpcode::kSpeculativeNumberDivide || op->opcode() == IrOpcode::kSpeculativeNumberModulus || - op->opcode() == IrOpcode::kSpeculativeNumberShiftLeft); + op->opcode() == IrOpcode::kSpeculativeNumberShiftLeft || + op->opcode() == IrOpcode::kSpeculativeNumberShiftRight || + op->opcode() == IrOpcode::kSpeculativeNumberShiftRightLogical); return OpParameter(op); } @@ -363,7 +365,9 @@ CompareOperationHints::Hint CompareOperationHintOf(const Operator* op) { V(SpeculativeNumberDivide) \ V(SpeculativeNumberMultiply) \ V(SpeculativeNumberModulus) \ - V(SpeculativeNumberShiftLeft) + V(SpeculativeNumberShiftLeft) \ + V(SpeculativeNumberShiftRight) \ + V(SpeculativeNumberShiftRightLogical) #define CHECKED_OP_LIST(V) \ V(CheckBounds, 2, 1) \ diff --git a/src/compiler/simplified-operator.h b/src/compiler/simplified-operator.h index 6cdcefeb0d..656e38b1fa 100644 --- a/src/compiler/simplified-operator.h +++ b/src/compiler/simplified-operator.h @@ -240,6 +240,9 @@ class SimplifiedOperatorBuilder final : public ZoneObject { const Operator* SpeculativeNumberDivide(BinaryOperationHints::Hint hint); const Operator* SpeculativeNumberModulus(BinaryOperationHints::Hint hint); const Operator* SpeculativeNumberShiftLeft(BinaryOperationHints::Hint hint); + const Operator* SpeculativeNumberShiftRight(BinaryOperationHints::Hint hint); + const Operator* SpeculativeNumberShiftRightLogical( + BinaryOperationHints::Hint hint); const Operator* SpeculativeNumberLessThan(CompareOperationHints::Hint hint); const Operator* SpeculativeNumberLessThanOrEqual( diff --git a/src/compiler/typer.cc b/src/compiler/typer.cc index 42bd3042a0..1e14725af7 100644 --- a/src/compiler/typer.cc +++ b/src/compiler/typer.cc @@ -1697,6 +1697,14 @@ Type* Typer::Visitor::TypeSpeculativeNumberShiftLeft(Node* node) { return Type::Signed32(); } +Type* Typer::Visitor::TypeSpeculativeNumberShiftRight(Node* node) { + return Type::Signed32(); +} + +Type* Typer::Visitor::TypeSpeculativeNumberShiftRightLogical(Node* node) { + return Type::Unsigned32(); +} + Type* Typer::Visitor::TypeNumberMultiply(Node* node) { return Type::Number(); } Type* Typer::Visitor::TypeNumberDivide(Node* node) { return Type::Number(); } diff --git a/src/compiler/verifier.cc b/src/compiler/verifier.cc index e111505ec9..49379c84af 100644 --- a/src/compiler/verifier.cc +++ b/src/compiler/verifier.cc @@ -721,6 +721,7 @@ void Verifier::Visitor::Check(Node* node) { CheckUpperIs(node, Type::Signed32()); break; case IrOpcode::kSpeculativeNumberShiftLeft: + case IrOpcode::kSpeculativeNumberShiftRight: CheckUpperIs(node, Type::Signed32()); break; case IrOpcode::kNumberShiftRightLogical: @@ -729,6 +730,9 @@ void Verifier::Visitor::Check(Node* node) { CheckValueInputIs(node, 1, Type::Unsigned32()); CheckUpperIs(node, Type::Unsigned32()); break; + case IrOpcode::kSpeculativeNumberShiftRightLogical: + CheckUpperIs(node, Type::Unsigned32()); + break; case IrOpcode::kNumberImul: // (Unsigned32, Unsigned32) -> Signed32 CheckValueInputIs(node, 0, Type::Unsigned32()); diff --git a/test/mjsunit/compiler/turbo-number-feedback.js b/test/mjsunit/compiler/turbo-number-feedback.js index 1462c385e8..8dcc42c8a1 100644 --- a/test/mjsunit/compiler/turbo-number-feedback.js +++ b/test/mjsunit/compiler/turbo-number-feedback.js @@ -78,3 +78,25 @@ %OptimizeFunctionOnNextCall(f5); assertEquals(64, f5(4.9, 4.1)); })(); + +(function ShiftRightNumbers() { + function f6(a, b) { + return a >> b; + } + + assertEquals(1, f6(8.3, 3.4)); + assertEquals(-2, f6(-16.1, 3.9)); + %OptimizeFunctionOnNextCall(f6); + assertEquals(0, f6(16.2, 5.1)); +})(); + +(function ShiftRightLogicalNumbers() { + function f7(a, b) { + return a >>> b; + } + + assertEquals(1, f7(8.3, 3.4)); + assertEquals(536870910, f7(-16.1, 3.9)); + %OptimizeFunctionOnNextCall(f7); + assertEquals(0, f7(16.2, 5.1)); +})(); diff --git a/test/unittests/compiler/js-typed-lowering-unittest.cc b/test/unittests/compiler/js-typed-lowering-unittest.cc index 4ae44ee97f..64dfeaa0e4 100644 --- a/test/unittests/compiler/js-typed-lowering-unittest.cc +++ b/test/unittests/compiler/js-typed-lowering-unittest.cc @@ -448,6 +448,24 @@ TEST_F(JSTypedLoweringTest, JSShiftLeftWithSigned32AndUnsigned32) { EXPECT_THAT(r.replacement(), IsNumberShiftLeft(lhs, rhs)); } +TEST_F(JSTypedLoweringTest, JSShiftLeftWithTypeFeedback) { + BinaryOperationHints::Hint const feedback_types[] = { + BinaryOperationHints::kSignedSmall, + BinaryOperationHints::kNumberOrOddball}; + for (BinaryOperationHints::Hint feedback : feedback_types) { + BinaryOperationHints const hints(feedback, feedback, feedback); + Node* lhs = Parameter(Type::Number(), 2); + Node* rhs = Parameter(Type::Number(), 3); + Node* effect = graph()->start(); + Node* control = graph()->start(); + Reduction r = Reduce(graph()->NewNode( + javascript()->ShiftLeft(hints), lhs, rhs, UndefinedConstant(), + EmptyFrameState(), EmptyFrameState(), effect, control)); + ASSERT_TRUE(r.Changed()); + EXPECT_THAT(r.replacement(), IsSpeculativeNumberShiftLeft( + feedback, lhs, rhs, effect, control)); + } +} // ----------------------------------------------------------------------------- // JSShiftRight @@ -484,6 +502,24 @@ TEST_F(JSTypedLoweringTest, JSShiftRightWithSigned32AndUnsigned32) { EXPECT_THAT(r.replacement(), IsNumberShiftRight(lhs, rhs)); } +TEST_F(JSTypedLoweringTest, JSShiftRightWithTypeFeedback) { + BinaryOperationHints::Hint const feedback_types[] = { + BinaryOperationHints::kSignedSmall, + BinaryOperationHints::kNumberOrOddball}; + for (BinaryOperationHints::Hint feedback : feedback_types) { + BinaryOperationHints const hints(feedback, feedback, feedback); + Node* lhs = Parameter(Type::Number(), 2); + Node* rhs = Parameter(Type::Number(), 3); + Node* effect = graph()->start(); + Node* control = graph()->start(); + Reduction r = Reduce(graph()->NewNode( + javascript()->ShiftRight(hints), lhs, rhs, UndefinedConstant(), + EmptyFrameState(), EmptyFrameState(), effect, control)); + ASSERT_TRUE(r.Changed()); + EXPECT_THAT(r.replacement(), IsSpeculativeNumberShiftRight( + feedback, lhs, rhs, effect, control)); + } +} // ----------------------------------------------------------------------------- // JSShiftRightLogical @@ -521,6 +557,24 @@ TEST_F(JSTypedLoweringTest, JSShiftRightLogicalWithUnsigned32AndUnsigned32) { EXPECT_THAT(r.replacement(), IsNumberShiftRightLogical(lhs, rhs)); } +TEST_F(JSTypedLoweringTest, JSShiftRightLogicalWithTypeFeedback) { + BinaryOperationHints::Hint const feedback_types[] = { + BinaryOperationHints::kSignedSmall, + BinaryOperationHints::kNumberOrOddball}; + for (BinaryOperationHints::Hint feedback : feedback_types) { + BinaryOperationHints const hints(feedback, feedback, feedback); + Node* lhs = Parameter(Type::Number(), 2); + Node* rhs = Parameter(Type::Number(), 3); + Node* effect = graph()->start(); + Node* control = graph()->start(); + Reduction r = Reduce(graph()->NewNode( + javascript()->ShiftRightLogical(hints), lhs, rhs, UndefinedConstant(), + EmptyFrameState(), EmptyFrameState(), effect, control)); + ASSERT_TRUE(r.Changed()); + EXPECT_THAT(r.replacement(), IsSpeculativeNumberShiftRightLogical( + feedback, lhs, rhs, effect, control)); + } +} // ----------------------------------------------------------------------------- // JSLoadContext @@ -890,43 +944,6 @@ TEST_F(JSTypedLoweringTest, JSSubtractSmis) { lhs, rhs, effect, control)); } -// ----------------------------------------------------------------------------- -// JSShiftLeft - -TEST_F(JSTypedLoweringTest, JSShiftLeftSmis) { - BinaryOperationHints const hints(BinaryOperationHints::kSignedSmall, - BinaryOperationHints::kSignedSmall, - BinaryOperationHints::kSignedSmall); - Node* lhs = Parameter(Type::Number(), 2); - Node* rhs = Parameter(Type::Number(), 3); - Node* effect = graph()->start(); - Node* control = graph()->start(); - Reduction r = Reduce(graph()->NewNode( - javascript()->ShiftLeft(hints), lhs, rhs, UndefinedConstant(), - EmptyFrameState(), EmptyFrameState(), effect, control)); - ASSERT_TRUE(r.Changed()); - EXPECT_THAT(r.replacement(), - IsSpeculativeNumberShiftLeft(BinaryOperationHints::kSignedSmall, - lhs, rhs, effect, control)); -} - -TEST_F(JSTypedLoweringTest, JSShiftLeftNumberOrOddball) { - BinaryOperationHints const hints(BinaryOperationHints::kNumberOrOddball, - BinaryOperationHints::kNumberOrOddball, - BinaryOperationHints::kNumberOrOddball); - Node* lhs = Parameter(Type::Number(), 2); - Node* rhs = Parameter(Type::Number(), 3); - Node* effect = graph()->start(); - Node* control = graph()->start(); - Reduction r = Reduce(graph()->NewNode( - javascript()->ShiftLeft(hints), lhs, rhs, UndefinedConstant(), - EmptyFrameState(), EmptyFrameState(), effect, control)); - ASSERT_TRUE(r.Changed()); - EXPECT_THAT(r.replacement(), IsSpeculativeNumberShiftLeft( - BinaryOperationHints::kNumberOrOddball, lhs, - rhs, effect, control)); -} - // ----------------------------------------------------------------------------- // JSInstanceOf // Test that instanceOf is reduced if and only if the right-hand side is a diff --git a/test/unittests/compiler/node-test-utils.cc b/test/unittests/compiler/node-test-utils.cc index cf2be44505..51100fa989 100644 --- a/test/unittests/compiler/node-test-utils.cc +++ b/test/unittests/compiler/node-test-utils.cc @@ -809,6 +809,7 @@ class IsSpeculativeBinopMatcher final : public NodeMatcher { const Matcher& effect_matcher, const Matcher& control_matcher) : NodeMatcher(opcode), + hint_matcher_(hint_matcher), lhs_matcher_(lhs_matcher), rhs_matcher_(rhs_matcher), effect_matcher_(effect_matcher), @@ -817,6 +818,9 @@ class IsSpeculativeBinopMatcher final : public NodeMatcher { bool MatchAndExplain(Node* node, MatchResultListener* listener) const final { return (NodeMatcher::MatchAndExplain(node, listener) && // TODO(bmeurer): The type parameter is currently ignored. + PrintMatchAndExplain( + OpParameter(node->op()), "hints", + hint_matcher_, listener) && PrintMatchAndExplain(NodeProperties::GetValueInput(node, 0), "lhs", lhs_matcher_, listener) && PrintMatchAndExplain(NodeProperties::GetValueInput(node, 1), "rhs", @@ -828,6 +832,7 @@ class IsSpeculativeBinopMatcher final : public NodeMatcher { } private: + const Matcher hint_matcher_; const Matcher type_matcher_; const Matcher lhs_matcher_; const Matcher rhs_matcher_; @@ -2068,6 +2073,26 @@ Matcher IsSpeculativeNumberShiftLeft( rhs_matcher, effect_matcher, control_matcher)); } +Matcher IsSpeculativeNumberShiftRight( + const Matcher& hint_matcher, + const Matcher& lhs_matcher, const Matcher& rhs_matcher, + const Matcher& effect_matcher, + const Matcher& control_matcher) { + return MakeMatcher(new IsSpeculativeBinopMatcher( + IrOpcode::kSpeculativeNumberShiftRight, hint_matcher, lhs_matcher, + rhs_matcher, effect_matcher, control_matcher)); +} + +Matcher IsSpeculativeNumberShiftRightLogical( + const Matcher& hint_matcher, + const Matcher& lhs_matcher, const Matcher& rhs_matcher, + const Matcher& effect_matcher, + const Matcher& control_matcher) { + return MakeMatcher(new IsSpeculativeBinopMatcher( + IrOpcode::kSpeculativeNumberShiftRightLogical, hint_matcher, lhs_matcher, + rhs_matcher, effect_matcher, control_matcher)); +} + Matcher IsAllocate(const Matcher& size_matcher, const Matcher& effect_matcher, const Matcher& control_matcher) { diff --git a/test/unittests/compiler/node-test-utils.h b/test/unittests/compiler/node-test-utils.h index 124080e6c4..d1cadb64c2 100644 --- a/test/unittests/compiler/node-test-utils.h +++ b/test/unittests/compiler/node-test-utils.h @@ -217,6 +217,16 @@ Matcher IsSpeculativeNumberShiftLeft( const Matcher& lhs_matcher, const Matcher& rhs_matcher, const Matcher& effect_matcher, const Matcher& control_matcher); +Matcher IsSpeculativeNumberShiftRight( + const Matcher& hint_matcher, + const Matcher& lhs_matcher, const Matcher& rhs_matcher, + const Matcher& effect_matcher, + const Matcher& control_matcher); +Matcher IsSpeculativeNumberShiftRightLogical( + const Matcher& hint_matcher, + const Matcher& lhs_matcher, const Matcher& rhs_matcher, + const Matcher& effect_matcher, + const Matcher& control_matcher); Matcher IsNumberSubtract(const Matcher& lhs_matcher, const Matcher& rhs_matcher); Matcher IsNumberMultiply(const Matcher& lhs_matcher,