diff --git a/src/compiler/js-typed-lowering.cc b/src/compiler/js-typed-lowering.cc index a88658c408..b456516aa1 100644 --- a/src/compiler/js-typed-lowering.cc +++ b/src/compiler/js-typed-lowering.cc @@ -595,8 +595,7 @@ Reduction JSTypedLowering::ReduceShiftLeft(Node* node) { JSBinopReduction r(this, node); BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback(); - if (feedback == BinaryOperationHints::kSigned32 || - feedback == BinaryOperationHints::kSignedSmall) { + if (feedback != BinaryOperationHints::kAny) { return r.ChangeToSpeculativeOperator( simplified()->SpeculativeNumberShiftLeft(feedback), Type::Signed32()); } diff --git a/src/compiler/representation-change.cc b/src/compiler/representation-change.cc index 5e900ed4ea..28548ef808 100644 --- a/src/compiler/representation-change.cc +++ b/src/compiler/representation-change.cc @@ -457,6 +457,16 @@ Node* RepresentationChanger::GetWord32RepresentationFor( } else if (output_type->Is(Type::Signed32())) { op = simplified()->ChangeTaggedToInt32(); } else if (use_info.truncation().IsUsedAsWord32()) { + if (use_info.type_check() == TypeCheckKind::kNumberOrOddball) { + op = simplified()->CheckedTaggedToFloat64(); + Node* effect = NodeProperties::GetEffectInput(use_node); + Node* control = NodeProperties::GetControlInput(use_node); + Node* to_float_checked = + jsgraph()->graph()->NewNode(op, node, effect, control); + NodeProperties::ReplaceEffectInput(use_node, to_float_checked); + return jsgraph()->graph()->NewNode(machine()->TruncateFloat64ToWord32(), + to_float_checked); + } op = simplified()->TruncateTaggedToWord32(); } else if (use_info.type_check() == TypeCheckKind::kSigned32) { op = simplified()->CheckedTaggedToInt32(); @@ -464,11 +474,15 @@ Node* RepresentationChanger::GetWord32RepresentationFor( } else if (output_rep == MachineRepresentation::kWord32) { // Only the checked case should get here, the non-checked case is // handled in GetRepresentationFor. - DCHECK(use_info.type_check() == TypeCheckKind::kSigned32); - if (output_type->Is(Type::Signed32())) { + if (use_info.type_check() == TypeCheckKind::kSigned32) { + if (output_type->Is(Type::Signed32())) { + return node; + } else if (output_type->Is(Type::Unsigned32())) { + op = simplified()->CheckedUint32ToInt32(); + } + } else { + DCHECK_EQ(TypeCheckKind::kNumberOrOddball, use_info.type_check()); return node; - } else if (output_type->Is(Type::Unsigned32())) { - op = simplified()->CheckedUint32ToInt32(); } } else if (output_rep == MachineRepresentation::kWord8 || output_rep == MachineRepresentation::kWord16) { diff --git a/src/compiler/representation-change.h b/src/compiler/representation-change.h index 5514bfc738..a9fc283c7e 100644 --- a/src/compiler/representation-change.h +++ b/src/compiler/representation-change.h @@ -139,6 +139,10 @@ class UseInfo { return UseInfo(MachineRepresentation::kFloat64, Truncation::Any(), TypeCheckKind::kNumberOrOddball); } + static UseInfo CheckedNumberOrOddballAsWord32() { + return UseInfo(MachineRepresentation::kWord32, Truncation::Word32(), + TypeCheckKind::kNumberOrOddball); + } // Undetermined representation. static UseInfo Any() { diff --git a/src/compiler/simplified-lowering.cc b/src/compiler/simplified-lowering.cc index 924a319f91..09a157f935 100644 --- a/src/compiler/simplified-lowering.cc +++ b/src/compiler/simplified-lowering.cc @@ -1666,27 +1666,15 @@ class RepresentationSelector { return; } BinaryOperationHints::Hint hint = BinaryOperationHintOf(node->op()); - if (hint == BinaryOperationHints::kSignedSmall || - hint == BinaryOperationHints::kSigned32) { - Type* rhs_type = GetUpperBound(node->InputAt(1)); - if (truncation.IsUsedAsWord32()) { - VisitBinop(node, UseInfo::CheckedSigned32AsWord32(), - MachineRepresentation::kWord32); - if (lower()) { - lowering->DoShift(node, lowering->machine()->Word32Shl(), - rhs_type); - } - } else { - VisitBinop(node, UseInfo::CheckedSigned32AsWord32(), - MachineRepresentation::kWord32, Type::Signed32()); - if (lower()) { - lowering->DoShift(node, lowering->machine()->Word32Shl(), - rhs_type); - } - } - return; + 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()->Word32Shl(), rhs_type); } - UNREACHABLE(); + return; } case IrOpcode::kNumberShiftRight: { Type* rhs_type = GetUpperBound(node->InputAt(1)); diff --git a/test/mjsunit/compiler/turbo-number-feedback.js b/test/mjsunit/compiler/turbo-number-feedback.js index 896d154242..1462c385e8 100644 --- a/test/mjsunit/compiler/turbo-number-feedback.js +++ b/test/mjsunit/compiler/turbo-number-feedback.js @@ -67,3 +67,14 @@ %OptimizeFunctionOnNextCall(f4); assertEquals(64, f4(4, 4)); })(); + +(function ShiftLeftNumbers() { + function f5(a, b) { + return a << b; + } + + assertEquals(24, f5(3.3, 3.4)); + assertEquals(40, f5(5.1, 3.9)); + %OptimizeFunctionOnNextCall(f5); + assertEquals(64, f5(4.9, 4.1)); +})(); diff --git a/test/unittests/compiler/js-typed-lowering-unittest.cc b/test/unittests/compiler/js-typed-lowering-unittest.cc index 8253418519..4ae44ee97f 100644 --- a/test/unittests/compiler/js-typed-lowering-unittest.cc +++ b/test/unittests/compiler/js-typed-lowering-unittest.cc @@ -910,6 +910,23 @@ TEST_F(JSTypedLoweringTest, JSShiftLeftSmis) { 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