// Copyright 2018 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "src/compiler/redundancy-elimination.h" #include "src/codegen/tick-counter.h" #include "src/compiler/common-operator.h" #include "test/unittests/compiler/graph-reducer-unittest.h" #include "test/unittests/compiler/graph-unittest.h" #include "test/unittests/compiler/node-test-utils.h" #include "testing/gmock-support.h" using testing::_; using testing::NiceMock; namespace v8 { namespace internal { namespace compiler { namespace redundancy_elimination_unittest { class RedundancyEliminationTest : public GraphTest { public: explicit RedundancyEliminationTest(int num_parameters = 4) : GraphTest(num_parameters), reducer_(&editor_, zone()), simplified_(zone()) { // Initialize the {reducer_} state for the Start node. reducer_.Reduce(graph()->start()); // Create a feedback vector with two CALL_IC slots. FeedbackVectorSpec spec(zone()); FeedbackSlot slot1 = spec.AddCallICSlot(); FeedbackSlot slot2 = spec.AddCallICSlot(); Handle metadata = FeedbackMetadata::New(isolate(), &spec); Handle shared = isolate()->factory()->NewSharedFunctionInfoForBuiltin( isolate()->factory()->empty_string(), Builtins::kIllegal); shared->set_raw_outer_scope_info_or_feedback_metadata(*metadata); Handle closure_feedback_cell_array = ClosureFeedbackCellArray::New(isolate(), shared); Handle feedback_vector = FeedbackVector::New(isolate(), shared, closure_feedback_cell_array); vector_slot_pairs_.push_back(VectorSlotPair()); vector_slot_pairs_.push_back( VectorSlotPair(feedback_vector, slot1, UNINITIALIZED)); vector_slot_pairs_.push_back( VectorSlotPair(feedback_vector, slot2, UNINITIALIZED)); } ~RedundancyEliminationTest() override = default; protected: Reduction Reduce(Node* node) { return reducer_.Reduce(node); } std::vector const& vector_slot_pairs() const { return vector_slot_pairs_; } SimplifiedOperatorBuilder* simplified() { return &simplified_; } private: NiceMock editor_; std::vector vector_slot_pairs_; VectorSlotPair feedback2_; RedundancyElimination reducer_; SimplifiedOperatorBuilder simplified_; }; namespace { const CheckForMinusZeroMode kCheckForMinusZeroModes[] = { CheckForMinusZeroMode::kCheckForMinusZero, CheckForMinusZeroMode::kDontCheckForMinusZero, }; const CheckTaggedInputMode kCheckTaggedInputModes[] = { CheckTaggedInputMode::kNumber, CheckTaggedInputMode::kNumberOrOddball}; const NumberOperationHint kNumberOperationHints[] = { NumberOperationHint::kSignedSmall, NumberOperationHint::kSignedSmallInputs, NumberOperationHint::kSigned32, NumberOperationHint::kNumber, NumberOperationHint::kNumberOrOddball, }; } // namespace // ----------------------------------------------------------------------------- // CheckBounds TEST_F(RedundancyEliminationTest, CheckBounds) { TRACED_FOREACH(VectorSlotPair, feedback1, vector_slot_pairs()) { TRACED_FOREACH(VectorSlotPair, feedback2, vector_slot_pairs()) { Node* index = Parameter(0); Node* length = Parameter(1); Node* effect = graph()->start(); Node* control = graph()->start(); Node* check1 = effect = graph()->NewNode( simplified()->CheckBounds(feedback1), index, length, effect, control); Reduction r1 = Reduce(check1); ASSERT_TRUE(r1.Changed()); EXPECT_EQ(r1.replacement(), check1); Node* check2 = effect = graph()->NewNode( simplified()->CheckBounds(feedback2), index, length, effect, control); Reduction r2 = Reduce(check2); ASSERT_TRUE(r2.Changed()); EXPECT_EQ(r2.replacement(), check1); } } } // ----------------------------------------------------------------------------- // CheckNumber TEST_F(RedundancyEliminationTest, CheckNumberSubsumedByCheckSmi) { TRACED_FOREACH(VectorSlotPair, feedback1, vector_slot_pairs()) { TRACED_FOREACH(VectorSlotPair, feedback2, vector_slot_pairs()) { Node* value = Parameter(0); Node* effect = graph()->start(); Node* control = graph()->start(); Node* check1 = effect = graph()->NewNode( simplified()->CheckSmi(feedback1), value, effect, control); Reduction r1 = Reduce(check1); ASSERT_TRUE(r1.Changed()); EXPECT_EQ(r1.replacement(), check1); Node* check2 = effect = graph()->NewNode( simplified()->CheckNumber(feedback2), value, effect, control); Reduction r2 = Reduce(check2); ASSERT_TRUE(r2.Changed()); EXPECT_EQ(r2.replacement(), check1); } } } // ----------------------------------------------------------------------------- // CheckReceiver TEST_F(RedundancyEliminationTest, CheckReceiver) { Node* value = Parameter(0); Node* effect = graph()->start(); Node* control = graph()->start(); Node* check1 = effect = graph()->NewNode(simplified()->CheckReceiver(), value, effect, control); Reduction r1 = Reduce(check1); ASSERT_TRUE(r1.Changed()); EXPECT_EQ(r1.replacement(), check1); Node* check2 = effect = graph()->NewNode(simplified()->CheckReceiver(), value, effect, control); Reduction r2 = Reduce(check2); ASSERT_TRUE(r2.Changed()); EXPECT_EQ(r2.replacement(), check1); } // ----------------------------------------------------------------------------- // CheckReceiverOrNullOrUndefined TEST_F(RedundancyEliminationTest, CheckReceiverOrNullOrUndefined) { Node* value = Parameter(0); Node* effect = graph()->start(); Node* control = graph()->start(); Node* check1 = effect = graph()->NewNode( simplified()->CheckReceiverOrNullOrUndefined(), value, effect, control); Reduction r1 = Reduce(check1); ASSERT_TRUE(r1.Changed()); EXPECT_EQ(r1.replacement(), check1); Node* check2 = effect = graph()->NewNode( simplified()->CheckReceiverOrNullOrUndefined(), value, effect, control); Reduction r2 = Reduce(check2); ASSERT_TRUE(r2.Changed()); EXPECT_EQ(r2.replacement(), check1); } TEST_F(RedundancyEliminationTest, CheckReceiverOrNullOrUndefinedSubsumedByCheckReceiver) { Node* value = Parameter(0); Node* effect = graph()->start(); Node* control = graph()->start(); Node* check1 = effect = graph()->NewNode(simplified()->CheckReceiver(), value, effect, control); Reduction r1 = Reduce(check1); ASSERT_TRUE(r1.Changed()); EXPECT_EQ(r1.replacement(), check1); Node* check2 = effect = graph()->NewNode( simplified()->CheckReceiverOrNullOrUndefined(), value, effect, control); Reduction r2 = Reduce(check2); ASSERT_TRUE(r2.Changed()); EXPECT_EQ(r2.replacement(), check1); } // ----------------------------------------------------------------------------- // CheckString TEST_F(RedundancyEliminationTest, CheckStringSubsumedByCheckInternalizedString) { TRACED_FOREACH(VectorSlotPair, feedback, vector_slot_pairs()) { Node* value = Parameter(0); Node* effect = graph()->start(); Node* control = graph()->start(); Node* check1 = effect = graph()->NewNode( simplified()->CheckInternalizedString(), value, effect, control); Reduction r1 = Reduce(check1); ASSERT_TRUE(r1.Changed()); EXPECT_EQ(r1.replacement(), check1); Node* check2 = effect = graph()->NewNode( simplified()->CheckString(feedback), value, effect, control); Reduction r2 = Reduce(check2); ASSERT_TRUE(r2.Changed()); EXPECT_EQ(r2.replacement(), check1); } } // ----------------------------------------------------------------------------- // CheckSymbol TEST_F(RedundancyEliminationTest, CheckSymbol) { Node* value = Parameter(0); Node* effect = graph()->start(); Node* control = graph()->start(); Node* check1 = effect = graph()->NewNode(simplified()->CheckSymbol(), value, effect, control); Reduction r1 = Reduce(check1); ASSERT_TRUE(r1.Changed()); EXPECT_EQ(r1.replacement(), check1); Node* check2 = effect = graph()->NewNode(simplified()->CheckSymbol(), value, effect, control); Reduction r2 = Reduce(check2); ASSERT_TRUE(r2.Changed()); EXPECT_EQ(r2.replacement(), check1); } // ----------------------------------------------------------------------------- // CheckedFloat64ToInt32 TEST_F(RedundancyEliminationTest, CheckedFloat64ToInt32) { TRACED_FOREACH(VectorSlotPair, feedback1, vector_slot_pairs()) { TRACED_FOREACH(VectorSlotPair, feedback2, vector_slot_pairs()) { TRACED_FOREACH(CheckForMinusZeroMode, mode, kCheckForMinusZeroModes) { Node* value = Parameter(0); Node* effect = graph()->start(); Node* control = graph()->start(); Node* check1 = effect = graph()->NewNode( simplified()->CheckedFloat64ToInt32(mode, feedback1), value, effect, control); Reduction r1 = Reduce(check1); ASSERT_TRUE(r1.Changed()); EXPECT_EQ(r1.replacement(), check1); Node* check2 = effect = graph()->NewNode( simplified()->CheckedFloat64ToInt32(mode, feedback2), value, effect, control); Reduction r2 = Reduce(check2); ASSERT_TRUE(r2.Changed()); EXPECT_EQ(r2.replacement(), check1); } } } } // ----------------------------------------------------------------------------- // CheckedFloat64ToInt64 TEST_F(RedundancyEliminationTest, CheckedFloat64ToInt64) { TRACED_FOREACH(VectorSlotPair, feedback1, vector_slot_pairs()) { TRACED_FOREACH(VectorSlotPair, feedback2, vector_slot_pairs()) { TRACED_FOREACH(CheckForMinusZeroMode, mode, kCheckForMinusZeroModes) { Node* value = Parameter(0); Node* effect = graph()->start(); Node* control = graph()->start(); Node* check1 = effect = graph()->NewNode( simplified()->CheckedFloat64ToInt64(mode, feedback1), value, effect, control); Reduction r1 = Reduce(check1); ASSERT_TRUE(r1.Changed()); EXPECT_EQ(r1.replacement(), check1); Node* check2 = effect = graph()->NewNode( simplified()->CheckedFloat64ToInt64(mode, feedback2), value, effect, control); Reduction r2 = Reduce(check2); ASSERT_TRUE(r2.Changed()); EXPECT_EQ(r2.replacement(), check1); } } } } // ----------------------------------------------------------------------------- // CheckedInt32ToCompressedSigned TEST_F(RedundancyEliminationTest, CheckedInt32ToCompressedSigned) { if (!COMPRESS_POINTERS_BOOL) { return; } TRACED_FOREACH(VectorSlotPair, feedback1, vector_slot_pairs()) { TRACED_FOREACH(VectorSlotPair, feedback2, vector_slot_pairs()) { Node* value = Parameter(0); Node* effect = graph()->start(); Node* control = graph()->start(); Node* check1 = effect = graph()->NewNode( simplified()->CheckedInt32ToCompressedSigned(feedback1), value, effect, control); Reduction r1 = Reduce(check1); ASSERT_TRUE(r1.Changed()); EXPECT_EQ(r1.replacement(), check1); Node* check2 = effect = graph()->NewNode( simplified()->CheckedInt32ToCompressedSigned(feedback2), value, effect, control); Reduction r2 = Reduce(check2); ASSERT_TRUE(r2.Changed()); EXPECT_EQ(r2.replacement(), check1); } } } // ----------------------------------------------------------------------------- // CheckedInt32ToTaggedSigned TEST_F(RedundancyEliminationTest, CheckedInt32ToTaggedSigned) { TRACED_FOREACH(VectorSlotPair, feedback1, vector_slot_pairs()) { TRACED_FOREACH(VectorSlotPair, feedback2, vector_slot_pairs()) { Node* value = Parameter(0); Node* effect = graph()->start(); Node* control = graph()->start(); Node* check1 = effect = graph()->NewNode(simplified()->CheckedInt32ToTaggedSigned(feedback1), value, effect, control); Reduction r1 = Reduce(check1); ASSERT_TRUE(r1.Changed()); EXPECT_EQ(r1.replacement(), check1); Node* check2 = effect = graph()->NewNode(simplified()->CheckedInt32ToTaggedSigned(feedback2), value, effect, control); Reduction r2 = Reduce(check2); ASSERT_TRUE(r2.Changed()); EXPECT_EQ(r2.replacement(), check1); } } } // ----------------------------------------------------------------------------- // CheckedInt64ToInt32 TEST_F(RedundancyEliminationTest, CheckedInt64ToInt32) { TRACED_FOREACH(VectorSlotPair, feedback1, vector_slot_pairs()) { TRACED_FOREACH(VectorSlotPair, feedback2, vector_slot_pairs()) { Node* value = Parameter(0); Node* effect = graph()->start(); Node* control = graph()->start(); Node* check1 = effect = graph()->NewNode( simplified()->CheckedInt64ToInt32(feedback1), value, effect, control); Reduction r1 = Reduce(check1); ASSERT_TRUE(r1.Changed()); EXPECT_EQ(r1.replacement(), check1); Node* check2 = effect = graph()->NewNode( simplified()->CheckedInt64ToInt32(feedback2), value, effect, control); Reduction r2 = Reduce(check2); ASSERT_TRUE(r2.Changed()); EXPECT_EQ(r2.replacement(), check1); } } } // ----------------------------------------------------------------------------- // CheckedInt64ToTaggedSigned TEST_F(RedundancyEliminationTest, CheckedInt64ToTaggedSigned) { TRACED_FOREACH(VectorSlotPair, feedback1, vector_slot_pairs()) { TRACED_FOREACH(VectorSlotPair, feedback2, vector_slot_pairs()) { Node* value = Parameter(0); Node* effect = graph()->start(); Node* control = graph()->start(); Node* check1 = effect = graph()->NewNode(simplified()->CheckedInt64ToTaggedSigned(feedback1), value, effect, control); Reduction r1 = Reduce(check1); ASSERT_TRUE(r1.Changed()); EXPECT_EQ(r1.replacement(), check1); Node* check2 = effect = graph()->NewNode(simplified()->CheckedInt64ToTaggedSigned(feedback2), value, effect, control); Reduction r2 = Reduce(check2); ASSERT_TRUE(r2.Changed()); EXPECT_EQ(r2.replacement(), check1); } } } // ----------------------------------------------------------------------------- // CheckedTaggedSignedToInt32 TEST_F(RedundancyEliminationTest, CheckedTaggedSignedToInt32) { TRACED_FOREACH(VectorSlotPair, feedback1, vector_slot_pairs()) { TRACED_FOREACH(VectorSlotPair, feedback2, vector_slot_pairs()) { Node* value = Parameter(0); Node* effect = graph()->start(); Node* control = graph()->start(); Node* check1 = effect = graph()->NewNode(simplified()->CheckedTaggedSignedToInt32(feedback1), value, effect, control); Reduction r1 = Reduce(check1); ASSERT_TRUE(r1.Changed()); EXPECT_EQ(r1.replacement(), check1); Node* check2 = effect = graph()->NewNode(simplified()->CheckedTaggedSignedToInt32(feedback2), value, effect, control); Reduction r2 = Reduce(check2); ASSERT_TRUE(r2.Changed()); EXPECT_EQ(r2.replacement(), check1); } } } // ----------------------------------------------------------------------------- // CheckedTaggedToFloat64 TEST_F(RedundancyEliminationTest, CheckedTaggedToFloat64) { TRACED_FOREACH(VectorSlotPair, feedback1, vector_slot_pairs()) { TRACED_FOREACH(VectorSlotPair, feedback2, vector_slot_pairs()) { TRACED_FOREACH(CheckTaggedInputMode, mode, kCheckTaggedInputModes) { Node* value = Parameter(0); Node* effect = graph()->start(); Node* control = graph()->start(); Node* check1 = effect = graph()->NewNode( simplified()->CheckedTaggedToFloat64(mode, feedback1), value, effect, control); Reduction r1 = Reduce(check1); ASSERT_TRUE(r1.Changed()); EXPECT_EQ(r1.replacement(), check1); Node* check2 = effect = graph()->NewNode( simplified()->CheckedTaggedToFloat64(mode, feedback2), value, effect, control); Reduction r2 = Reduce(check2); ASSERT_TRUE(r2.Changed()); EXPECT_EQ(r2.replacement(), check1); } } } } TEST_F(RedundancyEliminationTest, CheckedTaggedToFloat64SubsubmedByCheckedTaggedToFloat64) { TRACED_FOREACH(VectorSlotPair, feedback1, vector_slot_pairs()) { TRACED_FOREACH(VectorSlotPair, feedback2, vector_slot_pairs()) { Node* value = Parameter(0); Node* effect = graph()->start(); Node* control = graph()->start(); // If the check passed for CheckTaggedInputMode::kNumber, it'll // also pass later for CheckTaggedInputMode::kNumberOrOddball. Node* check1 = effect = graph()->NewNode(simplified()->CheckedTaggedToFloat64( CheckTaggedInputMode::kNumber, feedback1), value, effect, control); Reduction r1 = Reduce(check1); ASSERT_TRUE(r1.Changed()); EXPECT_EQ(r1.replacement(), check1); Node* check2 = effect = graph()->NewNode( simplified()->CheckedTaggedToFloat64( CheckTaggedInputMode::kNumberOrOddball, feedback2), value, effect, control); Reduction r2 = Reduce(check2); ASSERT_TRUE(r2.Changed()); EXPECT_EQ(r2.replacement(), check1); } } } // ----------------------------------------------------------------------------- // CheckedTaggedToInt32 TEST_F(RedundancyEliminationTest, CheckedTaggedToInt32) { TRACED_FOREACH(VectorSlotPair, feedback1, vector_slot_pairs()) { TRACED_FOREACH(VectorSlotPair, feedback2, vector_slot_pairs()) { TRACED_FOREACH(CheckForMinusZeroMode, mode, kCheckForMinusZeroModes) { Node* value = Parameter(0); Node* effect = graph()->start(); Node* control = graph()->start(); Node* check1 = effect = graph()->NewNode( simplified()->CheckedTaggedToInt32(mode, feedback1), value, effect, control); Reduction r1 = Reduce(check1); ASSERT_TRUE(r1.Changed()); EXPECT_EQ(r1.replacement(), check1); Node* check2 = effect = graph()->NewNode( simplified()->CheckedTaggedToInt32(mode, feedback2), value, effect, control); Reduction r2 = Reduce(check2); ASSERT_TRUE(r2.Changed()); EXPECT_EQ(r2.replacement(), check1); } } } } TEST_F(RedundancyEliminationTest, CheckedTaggedToInt32SubsumedByCheckedTaggedSignedToInt32) { TRACED_FOREACH(VectorSlotPair, feedback1, vector_slot_pairs()) { TRACED_FOREACH(VectorSlotPair, feedback2, vector_slot_pairs()) { TRACED_FOREACH(CheckForMinusZeroMode, mode, kCheckForMinusZeroModes) { Node* value = Parameter(0); Node* effect = graph()->start(); Node* control = graph()->start(); Node* check1 = effect = graph()->NewNode( simplified()->CheckedTaggedSignedToInt32(feedback1), value, effect, control); Reduction r1 = Reduce(check1); ASSERT_TRUE(r1.Changed()); EXPECT_EQ(r1.replacement(), check1); Node* check2 = effect = graph()->NewNode( simplified()->CheckedTaggedToInt32(mode, feedback2), value, effect, control); Reduction r2 = Reduce(check2); ASSERT_TRUE(r2.Changed()); EXPECT_EQ(r2.replacement(), check1); } } } } // ----------------------------------------------------------------------------- // CheckedTaggedToInt64 TEST_F(RedundancyEliminationTest, CheckedTaggedToInt64) { TRACED_FOREACH(VectorSlotPair, feedback1, vector_slot_pairs()) { TRACED_FOREACH(VectorSlotPair, feedback2, vector_slot_pairs()) { TRACED_FOREACH(CheckForMinusZeroMode, mode, kCheckForMinusZeroModes) { Node* value = Parameter(0); Node* effect = graph()->start(); Node* control = graph()->start(); Node* check1 = effect = graph()->NewNode( simplified()->CheckedTaggedToInt64(mode, feedback1), value, effect, control); Reduction r1 = Reduce(check1); ASSERT_TRUE(r1.Changed()); EXPECT_EQ(r1.replacement(), check1); Node* check2 = effect = graph()->NewNode( simplified()->CheckedTaggedToInt64(mode, feedback2), value, effect, control); Reduction r2 = Reduce(check2); ASSERT_TRUE(r2.Changed()); EXPECT_EQ(r2.replacement(), check1); } } } } // ----------------------------------------------------------------------------- // CheckedTaggedToTaggedPointer TEST_F(RedundancyEliminationTest, CheckedTaggedToTaggedPointer) { TRACED_FOREACH(VectorSlotPair, feedback1, vector_slot_pairs()) { TRACED_FOREACH(VectorSlotPair, feedback2, vector_slot_pairs()) { Node* value = Parameter(0); Node* effect = graph()->start(); Node* control = graph()->start(); Node* check1 = effect = graph()->NewNode( simplified()->CheckedTaggedToTaggedPointer(feedback1), value, effect, control); Reduction r1 = Reduce(check1); ASSERT_TRUE(r1.Changed()); EXPECT_EQ(r1.replacement(), check1); Node* check2 = effect = graph()->NewNode( simplified()->CheckedTaggedToTaggedPointer(feedback2), value, effect, control); Reduction r2 = Reduce(check2); ASSERT_TRUE(r2.Changed()); EXPECT_EQ(r2.replacement(), check1); } } } // ----------------------------------------------------------------------------- // CheckedTaggedToTaggedSigned TEST_F(RedundancyEliminationTest, CheckedTaggedToTaggedSigned) { TRACED_FOREACH(VectorSlotPair, feedback1, vector_slot_pairs()) { TRACED_FOREACH(VectorSlotPair, feedback2, vector_slot_pairs()) { Node* value = Parameter(0); Node* effect = graph()->start(); Node* control = graph()->start(); Node* check1 = effect = graph()->NewNode(simplified()->CheckedTaggedToTaggedSigned(feedback1), value, effect, control); Reduction r1 = Reduce(check1); ASSERT_TRUE(r1.Changed()); EXPECT_EQ(r1.replacement(), check1); Node* check2 = effect = graph()->NewNode(simplified()->CheckedTaggedToTaggedSigned(feedback2), value, effect, control); Reduction r2 = Reduce(check2); ASSERT_TRUE(r2.Changed()); EXPECT_EQ(r2.replacement(), check1); } } } // ----------------------------------------------------------------------------- // CheckedCompressedToTaggedPointer TEST_F(RedundancyEliminationTest, CheckedCompressedToTaggedPointer) { TRACED_FOREACH(VectorSlotPair, feedback1, vector_slot_pairs()) { TRACED_FOREACH(VectorSlotPair, feedback2, vector_slot_pairs()) { Node* value = Parameter(0); Node* effect = graph()->start(); Node* control = graph()->start(); Node* check1 = effect = graph()->NewNode( simplified()->CheckedCompressedToTaggedPointer(feedback1), value, effect, control); Reduction r1 = Reduce(check1); ASSERT_TRUE(r1.Changed()); EXPECT_EQ(r1.replacement(), check1); Node* check2 = effect = graph()->NewNode( simplified()->CheckedCompressedToTaggedPointer(feedback2), value, effect, control); Reduction r2 = Reduce(check2); ASSERT_TRUE(r2.Changed()); EXPECT_EQ(r2.replacement(), check1); } } } // ----------------------------------------------------------------------------- // CheckedCompressedToTaggedSigned TEST_F(RedundancyEliminationTest, CheckedCompressedToTaggedSigned) { TRACED_FOREACH(VectorSlotPair, feedback1, vector_slot_pairs()) { TRACED_FOREACH(VectorSlotPair, feedback2, vector_slot_pairs()) { Node* value = Parameter(0); Node* effect = graph()->start(); Node* control = graph()->start(); Node* check1 = effect = graph()->NewNode( simplified()->CheckedCompressedToTaggedSigned(feedback1), value, effect, control); Reduction r1 = Reduce(check1); ASSERT_TRUE(r1.Changed()); EXPECT_EQ(r1.replacement(), check1); Node* check2 = effect = graph()->NewNode( simplified()->CheckedCompressedToTaggedSigned(feedback2), value, effect, control); Reduction r2 = Reduce(check2); ASSERT_TRUE(r2.Changed()); EXPECT_EQ(r2.replacement(), check1); } } } // ----------------------------------------------------------------------------- // CheckedTaggedToCompressedPointer TEST_F(RedundancyEliminationTest, CheckedTaggedToCompressedPointer) { TRACED_FOREACH(VectorSlotPair, feedback1, vector_slot_pairs()) { TRACED_FOREACH(VectorSlotPair, feedback2, vector_slot_pairs()) { Node* value = Parameter(0); Node* effect = graph()->start(); Node* control = graph()->start(); Node* check1 = effect = graph()->NewNode( simplified()->CheckedTaggedToCompressedPointer(feedback1), value, effect, control); Reduction r1 = Reduce(check1); ASSERT_TRUE(r1.Changed()); EXPECT_EQ(r1.replacement(), check1); Node* check2 = effect = graph()->NewNode( simplified()->CheckedTaggedToCompressedPointer(feedback2), value, effect, control); Reduction r2 = Reduce(check2); ASSERT_TRUE(r2.Changed()); EXPECT_EQ(r2.replacement(), check1); } } } // ----------------------------------------------------------------------------- // CheckedTaggedToCompressedSigned TEST_F(RedundancyEliminationTest, CheckedTaggedToCompressedSigned) { TRACED_FOREACH(VectorSlotPair, feedback1, vector_slot_pairs()) { TRACED_FOREACH(VectorSlotPair, feedback2, vector_slot_pairs()) { Node* value = Parameter(0); Node* effect = graph()->start(); Node* control = graph()->start(); Node* check1 = effect = graph()->NewNode( simplified()->CheckedTaggedToCompressedSigned(feedback1), value, effect, control); Reduction r1 = Reduce(check1); ASSERT_TRUE(r1.Changed()); EXPECT_EQ(r1.replacement(), check1); Node* check2 = effect = graph()->NewNode( simplified()->CheckedTaggedToCompressedSigned(feedback2), value, effect, control); Reduction r2 = Reduce(check2); ASSERT_TRUE(r2.Changed()); EXPECT_EQ(r2.replacement(), check1); } } } // ----------------------------------------------------------------------------- // CheckedTruncateTaggedToWord32 TEST_F(RedundancyEliminationTest, CheckedTruncateTaggedToWord32) { TRACED_FOREACH(VectorSlotPair, feedback1, vector_slot_pairs()) { TRACED_FOREACH(VectorSlotPair, feedback2, vector_slot_pairs()) { TRACED_FOREACH(CheckTaggedInputMode, mode, kCheckTaggedInputModes) { Node* value = Parameter(0); Node* effect = graph()->start(); Node* control = graph()->start(); Node* check1 = effect = graph()->NewNode( simplified()->CheckedTruncateTaggedToWord32(mode, feedback1), value, effect, control); Reduction r1 = Reduce(check1); ASSERT_TRUE(r1.Changed()); EXPECT_EQ(r1.replacement(), check1); Node* check2 = effect = graph()->NewNode( simplified()->CheckedTruncateTaggedToWord32(mode, feedback2), value, effect, control); Reduction r2 = Reduce(check2); ASSERT_TRUE(r2.Changed()); EXPECT_EQ(r2.replacement(), check1); } } } } TEST_F(RedundancyEliminationTest, CheckedTruncateTaggedToWord32SubsumedByCheckedTruncateTaggedToWord32) { TRACED_FOREACH(VectorSlotPair, feedback1, vector_slot_pairs()) { TRACED_FOREACH(VectorSlotPair, feedback2, vector_slot_pairs()) { Node* value = Parameter(0); Node* effect = graph()->start(); Node* control = graph()->start(); // If the check passed for CheckTaggedInputMode::kNumber, it'll // also pass later for CheckTaggedInputMode::kNumberOrOddball. Node* check1 = effect = graph()->NewNode(simplified()->CheckedTruncateTaggedToWord32( CheckTaggedInputMode::kNumber, feedback1), value, effect, control); Reduction r1 = Reduce(check1); ASSERT_TRUE(r1.Changed()); EXPECT_EQ(r1.replacement(), check1); Node* check2 = effect = graph()->NewNode( simplified()->CheckedTruncateTaggedToWord32( CheckTaggedInputMode::kNumberOrOddball, feedback2), value, effect, control); Reduction r2 = Reduce(check2); ASSERT_TRUE(r2.Changed()); EXPECT_EQ(r2.replacement(), check1); } } } // ----------------------------------------------------------------------------- // CheckedUint32Bounds TEST_F(RedundancyEliminationTest, CheckedUint32Bounds) { TRACED_FOREACH(VectorSlotPair, feedback1, vector_slot_pairs()) { TRACED_FOREACH(VectorSlotPair, feedback2, vector_slot_pairs()) { Node* index = Parameter(0); Node* length = Parameter(1); Node* effect = graph()->start(); Node* control = graph()->start(); Node* check1 = effect = graph()->NewNode( simplified()->CheckedUint32Bounds( feedback1, CheckBoundsParameters::kDeoptOnOutOfBounds), index, length, effect, control); Reduction r1 = Reduce(check1); ASSERT_TRUE(r1.Changed()); EXPECT_EQ(r1.replacement(), check1); Node* check2 = effect = graph()->NewNode( simplified()->CheckedUint32Bounds( feedback2, CheckBoundsParameters::kDeoptOnOutOfBounds), index, length, effect, control); Reduction r2 = Reduce(check2); ASSERT_TRUE(r2.Changed()); EXPECT_EQ(r2.replacement(), check1); } } } // ----------------------------------------------------------------------------- // CheckedUint32ToInt32 TEST_F(RedundancyEliminationTest, CheckedUint32ToInt32) { TRACED_FOREACH(VectorSlotPair, feedback1, vector_slot_pairs()) { TRACED_FOREACH(VectorSlotPair, feedback2, vector_slot_pairs()) { Node* value = Parameter(0); Node* effect = graph()->start(); Node* control = graph()->start(); Node* check1 = effect = graph()->NewNode(simplified()->CheckedUint32ToInt32(feedback1), value, effect, control); Reduction r1 = Reduce(check1); ASSERT_TRUE(r1.Changed()); EXPECT_EQ(r1.replacement(), check1); Node* check2 = effect = graph()->NewNode(simplified()->CheckedUint32ToInt32(feedback2), value, effect, control); Reduction r2 = Reduce(check2); ASSERT_TRUE(r2.Changed()); EXPECT_EQ(r2.replacement(), check1); } } } // ----------------------------------------------------------------------------- // CheckedUint32ToTaggedSigned TEST_F(RedundancyEliminationTest, CheckedUint32ToTaggedSigned) { TRACED_FOREACH(VectorSlotPair, feedback1, vector_slot_pairs()) { TRACED_FOREACH(VectorSlotPair, feedback2, vector_slot_pairs()) { Node* value = Parameter(0); Node* effect = graph()->start(); Node* control = graph()->start(); Node* check1 = effect = graph()->NewNode(simplified()->CheckedUint32ToTaggedSigned(feedback1), value, effect, control); Reduction r1 = Reduce(check1); ASSERT_TRUE(r1.Changed()); EXPECT_EQ(r1.replacement(), check1); Node* check2 = effect = graph()->NewNode(simplified()->CheckedUint32ToTaggedSigned(feedback2), value, effect, control); Reduction r2 = Reduce(check2); ASSERT_TRUE(r2.Changed()); EXPECT_EQ(r2.replacement(), check1); } } } // ----------------------------------------------------------------------------- // CheckedUint64Bounds TEST_F(RedundancyEliminationTest, CheckedUint64Bounds) { TRACED_FOREACH(VectorSlotPair, feedback1, vector_slot_pairs()) { TRACED_FOREACH(VectorSlotPair, feedback2, vector_slot_pairs()) { Node* index = Parameter(0); Node* length = Parameter(1); Node* effect = graph()->start(); Node* control = graph()->start(); Node* check1 = effect = graph()->NewNode(simplified()->CheckedUint64Bounds(feedback1), index, length, effect, control); Reduction r1 = Reduce(check1); ASSERT_TRUE(r1.Changed()); EXPECT_EQ(r1.replacement(), check1); Node* check2 = effect = graph()->NewNode(simplified()->CheckedUint64Bounds(feedback2), index, length, effect, control); Reduction r2 = Reduce(check2); ASSERT_TRUE(r2.Changed()); EXPECT_EQ(r2.replacement(), check1); } } } // ----------------------------------------------------------------------------- // CheckedUint64ToInt32 TEST_F(RedundancyEliminationTest, CheckedUint64ToInt32) { TRACED_FOREACH(VectorSlotPair, feedback1, vector_slot_pairs()) { TRACED_FOREACH(VectorSlotPair, feedback2, vector_slot_pairs()) { Node* value = Parameter(0); Node* effect = graph()->start(); Node* control = graph()->start(); Node* check1 = effect = graph()->NewNode(simplified()->CheckedUint64ToInt32(feedback1), value, effect, control); Reduction r1 = Reduce(check1); ASSERT_TRUE(r1.Changed()); EXPECT_EQ(r1.replacement(), check1); Node* check2 = effect = graph()->NewNode(simplified()->CheckedUint64ToInt32(feedback2), value, effect, control); Reduction r2 = Reduce(check2); ASSERT_TRUE(r2.Changed()); EXPECT_EQ(r2.replacement(), check1); } } } // ----------------------------------------------------------------------------- // CheckedUint64ToTaggedSigned TEST_F(RedundancyEliminationTest, CheckedUint64ToTaggedSigned) { TRACED_FOREACH(VectorSlotPair, feedback1, vector_slot_pairs()) { TRACED_FOREACH(VectorSlotPair, feedback2, vector_slot_pairs()) { Node* value = Parameter(0); Node* effect = graph()->start(); Node* control = graph()->start(); Node* check1 = effect = graph()->NewNode(simplified()->CheckedUint64ToTaggedSigned(feedback1), value, effect, control); Reduction r1 = Reduce(check1); ASSERT_TRUE(r1.Changed()); EXPECT_EQ(r1.replacement(), check1); Node* check2 = effect = graph()->NewNode(simplified()->CheckedUint64ToTaggedSigned(feedback2), value, effect, control); Reduction r2 = Reduce(check2); ASSERT_TRUE(r2.Changed()); EXPECT_EQ(r2.replacement(), check1); } } } // ----------------------------------------------------------------------------- // SpeculativeNumberEqual TEST_F(RedundancyEliminationTest, SpeculativeNumberEqualWithCheckBoundsBetterType) { Typer typer(broker(), Typer::kNoFlags, graph(), tick_counter()); TRACED_FOREACH(VectorSlotPair, feedback1, vector_slot_pairs()) { TRACED_FOREACH(VectorSlotPair, feedback2, vector_slot_pairs()) { Node* lhs = Parameter(Type::Any(), 0); Node* rhs = Parameter(Type::Any(), 1); Node* length = Parameter(Type::Unsigned31(), 2); Node* effect = graph()->start(); Node* control = graph()->start(); Node* check1 = effect = graph()->NewNode( simplified()->CheckBounds(feedback1), lhs, length, effect, control); Reduction r1 = Reduce(check1); ASSERT_TRUE(r1.Changed()); EXPECT_EQ(r1.replacement(), check1); Node* check2 = effect = graph()->NewNode( simplified()->CheckBounds(feedback2), rhs, length, effect, control); Reduction r2 = Reduce(check2); ASSERT_TRUE(r2.Changed()); EXPECT_EQ(r2.replacement(), check2); Node* cmp3 = effect = graph()->NewNode(simplified()->SpeculativeNumberEqual( NumberOperationHint::kSignedSmall), lhs, rhs, effect, control); Reduction r3 = Reduce(cmp3); ASSERT_TRUE(r3.Changed()); EXPECT_THAT(r3.replacement(), IsSpeculativeNumberEqual(NumberOperationHint::kSignedSmall, check1, check2, _, _)); } } } TEST_F(RedundancyEliminationTest, SpeculativeNumberEqualWithCheckBoundsSameType) { Typer typer(broker(), Typer::kNoFlags, graph(), tick_counter()); TRACED_FOREACH(VectorSlotPair, feedback1, vector_slot_pairs()) { TRACED_FOREACH(VectorSlotPair, feedback2, vector_slot_pairs()) { Node* lhs = Parameter(Type::UnsignedSmall(), 0); Node* rhs = Parameter(Type::UnsignedSmall(), 1); Node* length = Parameter(Type::Unsigned31(), 2); Node* effect = graph()->start(); Node* control = graph()->start(); Node* check1 = effect = graph()->NewNode( simplified()->CheckBounds(feedback1), lhs, length, effect, control); Reduction r1 = Reduce(check1); ASSERT_TRUE(r1.Changed()); EXPECT_EQ(r1.replacement(), check1); Node* check2 = effect = graph()->NewNode( simplified()->CheckBounds(feedback2), rhs, length, effect, control); Reduction r2 = Reduce(check2); ASSERT_TRUE(r2.Changed()); EXPECT_EQ(r2.replacement(), check2); Node* cmp3 = effect = graph()->NewNode(simplified()->SpeculativeNumberEqual( NumberOperationHint::kSignedSmall), lhs, rhs, effect, control); Reduction r3 = Reduce(cmp3); ASSERT_TRUE(r3.Changed()); EXPECT_THAT(r3.replacement(), IsSpeculativeNumberEqual(NumberOperationHint::kSignedSmall, lhs, rhs, _, _)); } } } // ----------------------------------------------------------------------------- // SpeculativeNumberLessThan TEST_F(RedundancyEliminationTest, SpeculativeNumberLessThanWithCheckBoundsBetterType) { Typer typer(broker(), Typer::kNoFlags, graph(), tick_counter()); TRACED_FOREACH(VectorSlotPair, feedback1, vector_slot_pairs()) { TRACED_FOREACH(VectorSlotPair, feedback2, vector_slot_pairs()) { Node* lhs = Parameter(Type::Any(), 0); Node* rhs = Parameter(Type::Any(), 1); Node* length = Parameter(Type::Unsigned31(), 2); Node* effect = graph()->start(); Node* control = graph()->start(); Node* check1 = effect = graph()->NewNode( simplified()->CheckBounds(feedback1), lhs, length, effect, control); Reduction r1 = Reduce(check1); ASSERT_TRUE(r1.Changed()); EXPECT_EQ(r1.replacement(), check1); Node* check2 = effect = graph()->NewNode( simplified()->CheckBounds(feedback2), rhs, length, effect, control); Reduction r2 = Reduce(check2); ASSERT_TRUE(r2.Changed()); EXPECT_EQ(r2.replacement(), check2); Node* cmp3 = effect = graph()->NewNode(simplified()->SpeculativeNumberLessThan( NumberOperationHint::kSignedSmall), lhs, rhs, effect, control); Reduction r3 = Reduce(cmp3); ASSERT_TRUE(r3.Changed()); EXPECT_THAT(r3.replacement(), IsSpeculativeNumberLessThan(NumberOperationHint::kSignedSmall, check1, check2, _, _)); } } } TEST_F(RedundancyEliminationTest, SpeculativeNumberLessThanWithCheckBoundsSameType) { Typer typer(broker(), Typer::kNoFlags, graph(), tick_counter()); TRACED_FOREACH(VectorSlotPair, feedback1, vector_slot_pairs()) { TRACED_FOREACH(VectorSlotPair, feedback2, vector_slot_pairs()) { Node* lhs = Parameter(Type::UnsignedSmall(), 0); Node* rhs = Parameter(Type::UnsignedSmall(), 1); Node* length = Parameter(Type::Unsigned31(), 2); Node* effect = graph()->start(); Node* control = graph()->start(); Node* check1 = effect = graph()->NewNode( simplified()->CheckBounds(feedback1), lhs, length, effect, control); Reduction r1 = Reduce(check1); ASSERT_TRUE(r1.Changed()); EXPECT_EQ(r1.replacement(), check1); Node* check2 = effect = graph()->NewNode( simplified()->CheckBounds(feedback2), rhs, length, effect, control); Reduction r2 = Reduce(check2); ASSERT_TRUE(r2.Changed()); EXPECT_EQ(r2.replacement(), check2); Node* cmp3 = effect = graph()->NewNode(simplified()->SpeculativeNumberLessThan( NumberOperationHint::kSignedSmall), lhs, rhs, effect, control); Reduction r3 = Reduce(cmp3); ASSERT_TRUE(r3.Changed()); EXPECT_THAT(r3.replacement(), IsSpeculativeNumberLessThan(NumberOperationHint::kSignedSmall, lhs, rhs, _, _)); } } } // ----------------------------------------------------------------------------- // SpeculativeNumberLessThanOrEqual TEST_F(RedundancyEliminationTest, SpeculativeNumberLessThanOrEqualWithCheckBoundsBetterType) { Typer typer(broker(), Typer::kNoFlags, graph(), tick_counter()); TRACED_FOREACH(VectorSlotPair, feedback1, vector_slot_pairs()) { TRACED_FOREACH(VectorSlotPair, feedback2, vector_slot_pairs()) { Node* lhs = Parameter(Type::Any(), 0); Node* rhs = Parameter(Type::Any(), 1); Node* length = Parameter(Type::Unsigned31(), 2); Node* effect = graph()->start(); Node* control = graph()->start(); Node* check1 = effect = graph()->NewNode( simplified()->CheckBounds(feedback1), lhs, length, effect, control); Reduction r1 = Reduce(check1); ASSERT_TRUE(r1.Changed()); EXPECT_EQ(r1.replacement(), check1); Node* check2 = effect = graph()->NewNode( simplified()->CheckBounds(feedback2), rhs, length, effect, control); Reduction r2 = Reduce(check2); ASSERT_TRUE(r2.Changed()); EXPECT_EQ(r2.replacement(), check2); Node* cmp3 = effect = graph()->NewNode(simplified()->SpeculativeNumberLessThanOrEqual( NumberOperationHint::kSignedSmall), lhs, rhs, effect, control); Reduction r3 = Reduce(cmp3); ASSERT_TRUE(r3.Changed()); EXPECT_THAT(r3.replacement(), IsSpeculativeNumberLessThanOrEqual( NumberOperationHint::kSignedSmall, check1, check2, _, _)); } } } TEST_F(RedundancyEliminationTest, SpeculativeNumberLessThanOrEqualWithCheckBoundsSameType) { Typer typer(broker(), Typer::kNoFlags, graph(), tick_counter()); TRACED_FOREACH(VectorSlotPair, feedback1, vector_slot_pairs()) { TRACED_FOREACH(VectorSlotPair, feedback2, vector_slot_pairs()) { Node* lhs = Parameter(Type::UnsignedSmall(), 0); Node* rhs = Parameter(Type::UnsignedSmall(), 1); Node* length = Parameter(Type::Unsigned31(), 2); Node* effect = graph()->start(); Node* control = graph()->start(); Node* check1 = effect = graph()->NewNode( simplified()->CheckBounds(feedback1), lhs, length, effect, control); Reduction r1 = Reduce(check1); ASSERT_TRUE(r1.Changed()); EXPECT_EQ(r1.replacement(), check1); Node* check2 = effect = graph()->NewNode( simplified()->CheckBounds(feedback2), rhs, length, effect, control); Reduction r2 = Reduce(check2); ASSERT_TRUE(r2.Changed()); EXPECT_EQ(r2.replacement(), check2); Node* cmp3 = effect = graph()->NewNode(simplified()->SpeculativeNumberLessThanOrEqual( NumberOperationHint::kSignedSmall), lhs, rhs, effect, control); Reduction r3 = Reduce(cmp3); ASSERT_TRUE(r3.Changed()); EXPECT_THAT(r3.replacement(), IsSpeculativeNumberLessThanOrEqual( NumberOperationHint::kSignedSmall, lhs, rhs, _, _)); } } } // ----------------------------------------------------------------------------- // SpeculativeNumberAdd TEST_F(RedundancyEliminationTest, SpeculativeNumberAddWithCheckBoundsBetterType) { Typer typer(broker(), Typer::kNoFlags, graph(), tick_counter()); TRACED_FOREACH(VectorSlotPair, feedback, vector_slot_pairs()) { TRACED_FOREACH(NumberOperationHint, hint, kNumberOperationHints) { Node* lhs = Parameter(Type::Any(), 0); Node* rhs = Parameter(Type::Any(), 1); Node* length = Parameter(Type::Unsigned31(), 2); Node* effect = graph()->start(); Node* control = graph()->start(); Node* check1 = effect = graph()->NewNode( simplified()->CheckBounds(feedback), lhs, length, effect, control); Reduction r1 = Reduce(check1); ASSERT_TRUE(r1.Changed()); EXPECT_EQ(r1.replacement(), check1); Node* add2 = effect = graph()->NewNode( simplified()->SpeculativeNumberAdd(hint), lhs, rhs, effect, control); Reduction r2 = Reduce(add2); ASSERT_TRUE(r2.Changed()); EXPECT_THAT(r2.replacement(), IsSpeculativeNumberAdd(hint, check1, rhs, _, _)); } } } TEST_F(RedundancyEliminationTest, SpeculativeNumberAddWithCheckBoundsSameType) { Typer typer(broker(), Typer::kNoFlags, graph(), tick_counter()); TRACED_FOREACH(VectorSlotPair, feedback, vector_slot_pairs()) { TRACED_FOREACH(NumberOperationHint, hint, kNumberOperationHints) { Node* lhs = Parameter(Type::Range(42.0, 42.0, zone()), 0); Node* rhs = Parameter(Type::Any(), 0); Node* length = Parameter(Type::Unsigned31(), 1); Node* effect = graph()->start(); Node* control = graph()->start(); Node* check1 = effect = graph()->NewNode( simplified()->CheckBounds(feedback), lhs, length, effect, control); Reduction r1 = Reduce(check1); ASSERT_TRUE(r1.Changed()); EXPECT_EQ(r1.replacement(), check1); Node* add2 = effect = graph()->NewNode( simplified()->SpeculativeNumberAdd(hint), lhs, rhs, effect, control); Reduction r2 = Reduce(add2); ASSERT_TRUE(r2.Changed()); EXPECT_THAT(r2.replacement(), IsSpeculativeNumberAdd(hint, lhs, rhs, _, _)); } } } // ----------------------------------------------------------------------------- // SpeculativeNumberSubtract TEST_F(RedundancyEliminationTest, SpeculativeNumberSubtractWithCheckBoundsBetterType) { Typer typer(broker(), Typer::kNoFlags, graph(), tick_counter()); TRACED_FOREACH(VectorSlotPair, feedback, vector_slot_pairs()) { TRACED_FOREACH(NumberOperationHint, hint, kNumberOperationHints) { Node* lhs = Parameter(Type::Any(), 0); Node* rhs = Parameter(Type::Any(), 1); Node* length = Parameter(Type::Unsigned31(), 2); Node* effect = graph()->start(); Node* control = graph()->start(); Node* check1 = effect = graph()->NewNode( simplified()->CheckBounds(feedback), lhs, length, effect, control); Reduction r1 = Reduce(check1); ASSERT_TRUE(r1.Changed()); EXPECT_EQ(r1.replacement(), check1); Node* subtract2 = effect = graph()->NewNode(simplified()->SpeculativeNumberSubtract(hint), lhs, rhs, effect, control); Reduction r2 = Reduce(subtract2); ASSERT_TRUE(r2.Changed()); EXPECT_THAT(r2.replacement(), IsSpeculativeNumberSubtract(hint, check1, rhs, _, _)); } } } TEST_F(RedundancyEliminationTest, SpeculativeNumberSubtractWithCheckBoundsSameType) { Typer typer(broker(), Typer::kNoFlags, graph(), tick_counter()); TRACED_FOREACH(VectorSlotPair, feedback, vector_slot_pairs()) { TRACED_FOREACH(NumberOperationHint, hint, kNumberOperationHints) { Node* lhs = Parameter(Type::Range(42.0, 42.0, zone()), 0); Node* rhs = Parameter(Type::Any(), 0); Node* length = Parameter(Type::Unsigned31(), 1); Node* effect = graph()->start(); Node* control = graph()->start(); Node* check1 = effect = graph()->NewNode( simplified()->CheckBounds(feedback), lhs, length, effect, control); Reduction r1 = Reduce(check1); ASSERT_TRUE(r1.Changed()); EXPECT_EQ(r1.replacement(), check1); Node* subtract2 = effect = graph()->NewNode(simplified()->SpeculativeNumberSubtract(hint), lhs, rhs, effect, control); Reduction r2 = Reduce(subtract2); ASSERT_TRUE(r2.Changed()); EXPECT_THAT(r2.replacement(), IsSpeculativeNumberSubtract(hint, lhs, rhs, _, _)); } } } // ----------------------------------------------------------------------------- // SpeculativeSafeIntegerAdd TEST_F(RedundancyEliminationTest, SpeculativeSafeIntegerAddWithCheckBoundsBetterType) { Typer typer(broker(), Typer::kNoFlags, graph(), tick_counter()); TRACED_FOREACH(VectorSlotPair, feedback, vector_slot_pairs()) { TRACED_FOREACH(NumberOperationHint, hint, kNumberOperationHints) { Node* lhs = Parameter(Type::Any(), 0); Node* rhs = Parameter(Type::Any(), 1); Node* length = Parameter(Type::Unsigned31(), 2); Node* effect = graph()->start(); Node* control = graph()->start(); Node* check1 = effect = graph()->NewNode( simplified()->CheckBounds(feedback), lhs, length, effect, control); Reduction r1 = Reduce(check1); ASSERT_TRUE(r1.Changed()); EXPECT_EQ(r1.replacement(), check1); Node* add2 = effect = graph()->NewNode(simplified()->SpeculativeSafeIntegerAdd(hint), lhs, rhs, effect, control); Reduction r2 = Reduce(add2); ASSERT_TRUE(r2.Changed()); EXPECT_THAT(r2.replacement(), IsSpeculativeSafeIntegerAdd(hint, check1, rhs, _, _)); } } } TEST_F(RedundancyEliminationTest, SpeculativeSafeIntegerAddWithCheckBoundsSameType) { Typer typer(broker(), Typer::kNoFlags, graph(), tick_counter()); TRACED_FOREACH(VectorSlotPair, feedback, vector_slot_pairs()) { TRACED_FOREACH(NumberOperationHint, hint, kNumberOperationHints) { Node* lhs = Parameter(Type::Range(42.0, 42.0, zone()), 0); Node* rhs = Parameter(Type::Any(), 0); Node* length = Parameter(Type::Unsigned31(), 1); Node* effect = graph()->start(); Node* control = graph()->start(); Node* check1 = effect = graph()->NewNode( simplified()->CheckBounds(feedback), lhs, length, effect, control); Reduction r1 = Reduce(check1); ASSERT_TRUE(r1.Changed()); EXPECT_EQ(r1.replacement(), check1); Node* add2 = effect = graph()->NewNode(simplified()->SpeculativeSafeIntegerAdd(hint), lhs, rhs, effect, control); Reduction r2 = Reduce(add2); ASSERT_TRUE(r2.Changed()); EXPECT_THAT(r2.replacement(), IsSpeculativeSafeIntegerAdd(hint, lhs, rhs, _, _)); } } } // ----------------------------------------------------------------------------- // SpeculativeSafeIntegerSubtract TEST_F(RedundancyEliminationTest, SpeculativeSafeIntegerSubtractWithCheckBoundsBetterType) { Typer typer(broker(), Typer::kNoFlags, graph(), tick_counter()); TRACED_FOREACH(VectorSlotPair, feedback, vector_slot_pairs()) { TRACED_FOREACH(NumberOperationHint, hint, kNumberOperationHints) { Node* lhs = Parameter(Type::Any(), 0); Node* rhs = Parameter(Type::Any(), 1); Node* length = Parameter(Type::Unsigned31(), 2); Node* effect = graph()->start(); Node* control = graph()->start(); Node* check1 = effect = graph()->NewNode( simplified()->CheckBounds(feedback), lhs, length, effect, control); Reduction r1 = Reduce(check1); ASSERT_TRUE(r1.Changed()); EXPECT_EQ(r1.replacement(), check1); Node* subtract2 = effect = graph()->NewNode(simplified()->SpeculativeSafeIntegerSubtract(hint), lhs, rhs, effect, control); Reduction r2 = Reduce(subtract2); ASSERT_TRUE(r2.Changed()); EXPECT_THAT(r2.replacement(), IsSpeculativeSafeIntegerSubtract(hint, check1, rhs, _, _)); } } } TEST_F(RedundancyEliminationTest, SpeculativeSafeIntegerSubtractWithCheckBoundsSameType) { Typer typer(broker(), Typer::kNoFlags, graph(), tick_counter()); TRACED_FOREACH(VectorSlotPair, feedback, vector_slot_pairs()) { TRACED_FOREACH(NumberOperationHint, hint, kNumberOperationHints) { Node* lhs = Parameter(Type::Range(42.0, 42.0, zone()), 0); Node* rhs = Parameter(Type::Any(), 0); Node* length = Parameter(Type::Unsigned31(), 1); Node* effect = graph()->start(); Node* control = graph()->start(); Node* check1 = effect = graph()->NewNode( simplified()->CheckBounds(feedback), lhs, length, effect, control); Reduction r1 = Reduce(check1); ASSERT_TRUE(r1.Changed()); EXPECT_EQ(r1.replacement(), check1); Node* subtract2 = effect = graph()->NewNode(simplified()->SpeculativeSafeIntegerSubtract(hint), lhs, rhs, effect, control); Reduction r2 = Reduce(subtract2); ASSERT_TRUE(r2.Changed()); EXPECT_THAT(r2.replacement(), IsSpeculativeSafeIntegerSubtract(hint, lhs, rhs, _, _)); } } } // ----------------------------------------------------------------------------- // SpeculativeToNumber TEST_F(RedundancyEliminationTest, SpeculativeToNumberWithCheckBoundsBetterType) { Typer typer(broker(), Typer::kNoFlags, graph(), tick_counter()); TRACED_FOREACH(VectorSlotPair, feedback1, vector_slot_pairs()) { TRACED_FOREACH(VectorSlotPair, feedback2, vector_slot_pairs()) { TRACED_FOREACH(NumberOperationHint, hint, kNumberOperationHints) { Node* index = Parameter(Type::Any(), 0); Node* length = Parameter(Type::Unsigned31(), 1); Node* effect = graph()->start(); Node* control = graph()->start(); Node* check1 = effect = graph()->NewNode(simplified()->CheckBounds(feedback1), index, length, effect, control); Reduction r1 = Reduce(check1); ASSERT_TRUE(r1.Changed()); EXPECT_EQ(r1.replacement(), check1); Node* to_number2 = effect = graph()->NewNode(simplified()->SpeculativeToNumber(hint, feedback2), index, effect, control); Reduction r2 = Reduce(to_number2); ASSERT_TRUE(r2.Changed()); EXPECT_THAT(r2.replacement(), IsSpeculativeToNumber(check1)); } } } } TEST_F(RedundancyEliminationTest, SpeculativeToNumberWithCheckBoundsSameType) { Typer typer(broker(), Typer::kNoFlags, graph(), tick_counter()); TRACED_FOREACH(VectorSlotPair, feedback1, vector_slot_pairs()) { TRACED_FOREACH(VectorSlotPair, feedback2, vector_slot_pairs()) { TRACED_FOREACH(NumberOperationHint, hint, kNumberOperationHints) { Node* index = Parameter(Type::Range(42.0, 42.0, zone()), 0); Node* length = Parameter(Type::Unsigned31(), 1); Node* effect = graph()->start(); Node* control = graph()->start(); Node* check1 = effect = graph()->NewNode(simplified()->CheckBounds(feedback1), index, length, effect, control); Reduction r1 = Reduce(check1); ASSERT_TRUE(r1.Changed()); EXPECT_EQ(r1.replacement(), check1); Node* to_number2 = effect = graph()->NewNode(simplified()->SpeculativeToNumber(hint, feedback2), index, effect, control); Reduction r2 = Reduce(to_number2); ASSERT_TRUE(r2.Changed()); EXPECT_THAT(r2.replacement(), IsSpeculativeToNumber(index)); } } } } } // namespace redundancy_elimination_unittest } // namespace compiler } // namespace internal } // namespace v8