diff options
Diffstat (limited to 'deps/v8/test/unittests/compiler/redundancy-elimination-unittest.cc')
-rw-r--r-- | deps/v8/test/unittests/compiler/redundancy-elimination-unittest.cc | 1170 |
1 files changed, 1170 insertions, 0 deletions
diff --git a/deps/v8/test/unittests/compiler/redundancy-elimination-unittest.cc b/deps/v8/test/unittests/compiler/redundancy-elimination-unittest.cc new file mode 100644 index 0000000000..f3ecd228a5 --- /dev/null +++ b/deps/v8/test/unittests/compiler/redundancy-elimination-unittest.cc @@ -0,0 +1,1170 @@ +// 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/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<FeedbackMetadata> metadata = FeedbackMetadata::New(isolate(), &spec); + Handle<SharedFunctionInfo> shared = + isolate()->factory()->NewSharedFunctionInfoForBuiltin( + isolate()->factory()->empty_string(), Builtins::kIllegal); + shared->set_raw_outer_scope_info_or_feedback_metadata(*metadata); + Handle<FeedbackVector> feedback_vector = + FeedbackVector::New(isolate(), shared); + 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<VectorSlotPair> const& vector_slot_pairs() const { + return vector_slot_pairs_; + } + SimplifiedOperatorBuilder* simplified() { return &simplified_; } + + private: + NiceMock<MockAdvancedReducerEditor> editor_; + std::vector<VectorSlotPair> 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); + } + } +} + +// ----------------------------------------------------------------------------- +// 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); + } + } + } +} + +// ----------------------------------------------------------------------------- +// 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); + } + } + } +} + +// ----------------------------------------------------------------------------- +// 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); + } + } +} + +// ----------------------------------------------------------------------------- +// 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); + } + } +} + +// ----------------------------------------------------------------------------- +// 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); + } + } +} + +// ----------------------------------------------------------------------------- +// 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(js_heap_broker(), Typer::kNoFlags, graph()); + 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(js_heap_broker(), Typer::kNoFlags, graph()); + 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(js_heap_broker(), Typer::kNoFlags, graph()); + 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(js_heap_broker(), Typer::kNoFlags, graph()); + 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(js_heap_broker(), Typer::kNoFlags, graph()); + 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(js_heap_broker(), Typer::kNoFlags, graph()); + 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(js_heap_broker(), Typer::kNoFlags, graph()); + 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(js_heap_broker(), Typer::kNoFlags, graph()); + 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(js_heap_broker(), Typer::kNoFlags, graph()); + 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(js_heap_broker(), Typer::kNoFlags, graph()); + 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(js_heap_broker(), Typer::kNoFlags, graph()); + 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(js_heap_broker(), Typer::kNoFlags, graph()); + 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(js_heap_broker(), Typer::kNoFlags, graph()); + 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(js_heap_broker(), Typer::kNoFlags, graph()); + 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(js_heap_broker(), Typer::kNoFlags, graph()); + 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(js_heap_broker(), Typer::kNoFlags, graph()); + 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 |