blob: 07ce18cb6a5b09b4c9462e5cf81e2b268bedb26f [file] [log] [blame]
// 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 "src/compiler/feedback-source.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<ClosureFeedbackCellArray> closure_feedback_cell_array =
ClosureFeedbackCellArray::New(isolate(), shared);
IsCompiledScope is_compiled_scope(shared->is_compiled_scope(isolate()));
Handle<FeedbackVector> feedback_vector = FeedbackVector::New(
isolate(), shared, closure_feedback_cell_array, &is_compiled_scope);
vector_slot_pairs_.push_back(FeedbackSource());
vector_slot_pairs_.push_back(FeedbackSource(feedback_vector, slot1));
vector_slot_pairs_.push_back(FeedbackSource(feedback_vector, slot2));
}
~RedundancyEliminationTest() override = default;
protected:
Reduction Reduce(Node* node) { return reducer_.Reduce(node); }
std::vector<FeedbackSource> const& vector_slot_pairs() const {
return vector_slot_pairs_;
}
SimplifiedOperatorBuilder* simplified() { return &simplified_; }
private:
NiceMock<MockAdvancedReducerEditor> editor_;
std::vector<FeedbackSource> vector_slot_pairs_;
FeedbackSource 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(FeedbackSource, feedback1, vector_slot_pairs()) {
TRACED_FOREACH(FeedbackSource, 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(FeedbackSource, feedback1, vector_slot_pairs()) {
TRACED_FOREACH(FeedbackSource, 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(FeedbackSource, 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(FeedbackSource, feedback1, vector_slot_pairs()) {
TRACED_FOREACH(FeedbackSource, 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(FeedbackSource, feedback1, vector_slot_pairs()) {
TRACED_FOREACH(FeedbackSource, 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);
}
}
}
}
// -----------------------------------------------------------------------------
// CheckedInt32ToTaggedSigned
TEST_F(RedundancyEliminationTest, CheckedInt32ToTaggedSigned) {
TRACED_FOREACH(FeedbackSource, feedback1, vector_slot_pairs()) {
TRACED_FOREACH(FeedbackSource, 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(FeedbackSource, feedback1, vector_slot_pairs()) {
TRACED_FOREACH(FeedbackSource, 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(FeedbackSource, feedback1, vector_slot_pairs()) {
TRACED_FOREACH(FeedbackSource, 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(FeedbackSource, feedback1, vector_slot_pairs()) {
TRACED_FOREACH(FeedbackSource, 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(FeedbackSource, feedback1, vector_slot_pairs()) {
TRACED_FOREACH(FeedbackSource, 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(FeedbackSource, feedback1, vector_slot_pairs()) {
TRACED_FOREACH(FeedbackSource, 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(FeedbackSource, feedback1, vector_slot_pairs()) {
TRACED_FOREACH(FeedbackSource, 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(FeedbackSource, feedback1, vector_slot_pairs()) {
TRACED_FOREACH(FeedbackSource, 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(FeedbackSource, feedback1, vector_slot_pairs()) {
TRACED_FOREACH(FeedbackSource, 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(FeedbackSource, feedback1, vector_slot_pairs()) {
TRACED_FOREACH(FeedbackSource, 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(FeedbackSource, feedback1, vector_slot_pairs()) {
TRACED_FOREACH(FeedbackSource, 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(FeedbackSource, feedback1, vector_slot_pairs()) {
TRACED_FOREACH(FeedbackSource, 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(FeedbackSource, feedback1, vector_slot_pairs()) {
TRACED_FOREACH(FeedbackSource, 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(FeedbackSource, feedback1, vector_slot_pairs()) {
TRACED_FOREACH(FeedbackSource, 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, {}),
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, {}),
index, length, effect, control);
Reduction r2 = Reduce(check2);
ASSERT_TRUE(r2.Changed());
EXPECT_EQ(r2.replacement(), check1);
}
}
}
// -----------------------------------------------------------------------------
// CheckedUint32ToInt32
TEST_F(RedundancyEliminationTest, CheckedUint32ToInt32) {
TRACED_FOREACH(FeedbackSource, feedback1, vector_slot_pairs()) {
TRACED_FOREACH(FeedbackSource, 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(FeedbackSource, feedback1, vector_slot_pairs()) {
TRACED_FOREACH(FeedbackSource, 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(FeedbackSource, feedback1, vector_slot_pairs()) {
TRACED_FOREACH(FeedbackSource, 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(FeedbackSource, feedback1, vector_slot_pairs()) {
TRACED_FOREACH(FeedbackSource, 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(FeedbackSource, feedback1, vector_slot_pairs()) {
TRACED_FOREACH(FeedbackSource, 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(FeedbackSource, feedback1, vector_slot_pairs()) {
TRACED_FOREACH(FeedbackSource, 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(FeedbackSource, feedback1, vector_slot_pairs()) {
TRACED_FOREACH(FeedbackSource, 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(FeedbackSource, feedback1, vector_slot_pairs()) {
TRACED_FOREACH(FeedbackSource, 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(FeedbackSource, feedback1, vector_slot_pairs()) {
TRACED_FOREACH(FeedbackSource, 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(FeedbackSource, feedback1, vector_slot_pairs()) {
TRACED_FOREACH(FeedbackSource, 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(FeedbackSource, feedback1, vector_slot_pairs()) {
TRACED_FOREACH(FeedbackSource, 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(FeedbackSource, 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(FeedbackSource, 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(FeedbackSource, 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(FeedbackSource, 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(FeedbackSource, 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(FeedbackSource, 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(FeedbackSource, 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(FeedbackSource, 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(FeedbackSource, feedback1, vector_slot_pairs()) {
TRACED_FOREACH(FeedbackSource, 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(FeedbackSource, feedback1, vector_slot_pairs()) {
TRACED_FOREACH(FeedbackSource, 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