[turbofan] Fix RedundancyElimination and add more test coverage.
Make the RedundancyElimination handle all simplified operators that are listed in the SIMPLIFIED_CHECKED_OP_LIST, and fix a couple of bugs and oversights in the code. This also adds a lot of test coverage for all the cases that we care about in RedundancyElimination (with respect to Check/Checked simplified operators). Bug: v8:8015 Change-Id: I57d29113389841b09abcd013313bf5dd1c67735f Reviewed-on: https://chromium-review.googlesource.com/1233655 Reviewed-by: Sigurd Schneider <sigurds@chromium.org> Commit-Queue: Benedikt Meurer <bmeurer@chromium.org> Cr-Commit-Position: refs/heads/master@{#56032}
This commit is contained in:
parent
196874aa08
commit
4491072507
@ -32,23 +32,9 @@ Reduction RedundancyElimination::Reduce(Node* node) {
|
||||
case IrOpcode::kCheckSmi:
|
||||
case IrOpcode::kCheckString:
|
||||
case IrOpcode::kCheckSymbol:
|
||||
case IrOpcode::kCheckedFloat64ToInt32:
|
||||
case IrOpcode::kCheckedInt32Add:
|
||||
case IrOpcode::kCheckedInt32Div:
|
||||
case IrOpcode::kCheckedInt32Mod:
|
||||
case IrOpcode::kCheckedInt32Mul:
|
||||
case IrOpcode::kCheckedInt32Sub:
|
||||
case IrOpcode::kCheckedInt32ToTaggedSigned:
|
||||
case IrOpcode::kCheckedTaggedSignedToInt32:
|
||||
case IrOpcode::kCheckedTaggedToFloat64:
|
||||
case IrOpcode::kCheckedTaggedToInt32:
|
||||
case IrOpcode::kCheckedTaggedToTaggedPointer:
|
||||
case IrOpcode::kCheckedTaggedToTaggedSigned:
|
||||
case IrOpcode::kCheckedTruncateTaggedToWord32:
|
||||
case IrOpcode::kCheckedUint32Div:
|
||||
case IrOpcode::kCheckedUint32Mod:
|
||||
case IrOpcode::kCheckedUint32ToInt32:
|
||||
case IrOpcode::kCheckedUint32ToTaggedSigned:
|
||||
#define SIMPLIFIED_CHECKED_OP(Opcode) case IrOpcode::k##Opcode:
|
||||
SIMPLIFIED_CHECKED_OP_LIST(SIMPLIFIED_CHECKED_OP)
|
||||
#undef SIMPLIFIED_CHECKED_OP
|
||||
return ReduceCheckNode(node);
|
||||
case IrOpcode::kSpeculativeNumberAdd:
|
||||
case IrOpcode::kSpeculativeNumberSubtract:
|
||||
@ -140,6 +126,12 @@ bool CheckSubsumes(Node const* a, Node const* b) {
|
||||
if (a->opcode() == IrOpcode::kCheckInternalizedString &&
|
||||
b->opcode() == IrOpcode::kCheckString) {
|
||||
// CheckInternalizedString(node) implies CheckString(node)
|
||||
} else if (a->opcode() == IrOpcode::kCheckSmi &&
|
||||
b->opcode() == IrOpcode::kCheckNumber) {
|
||||
// CheckSmi(node) implies CheckNumber(node)
|
||||
} else if (a->opcode() == IrOpcode::kCheckedTaggedSignedToInt32 &&
|
||||
b->opcode() == IrOpcode::kCheckedTaggedToInt32) {
|
||||
// CheckedTaggedSignedToInt32(node) implies CheckedTaggedToInt32(node)
|
||||
} else if (a->opcode() != b->opcode()) {
|
||||
return false;
|
||||
} else {
|
||||
@ -150,11 +142,15 @@ bool CheckSubsumes(Node const* a, Node const* b) {
|
||||
case IrOpcode::kCheckNumber:
|
||||
break;
|
||||
case IrOpcode::kCheckedInt32ToTaggedSigned:
|
||||
case IrOpcode::kCheckedInt64ToInt32:
|
||||
case IrOpcode::kCheckedInt64ToTaggedSigned:
|
||||
case IrOpcode::kCheckedTaggedSignedToInt32:
|
||||
case IrOpcode::kCheckedTaggedToTaggedPointer:
|
||||
case IrOpcode::kCheckedTaggedToTaggedSigned:
|
||||
case IrOpcode::kCheckedUint32ToInt32:
|
||||
case IrOpcode::kCheckedUint32ToTaggedSigned:
|
||||
case IrOpcode::kCheckedUint64ToInt32:
|
||||
case IrOpcode::kCheckedUint64ToTaggedSigned:
|
||||
break;
|
||||
case IrOpcode::kCheckedFloat64ToInt32:
|
||||
case IrOpcode::kCheckedTaggedToInt32: {
|
||||
@ -167,6 +163,20 @@ bool CheckSubsumes(Node const* a, Node const* b) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IrOpcode::kCheckedTaggedToFloat64:
|
||||
case IrOpcode::kCheckedTruncateTaggedToWord32: {
|
||||
CheckTaggedInputParameters const& ap =
|
||||
CheckTaggedInputParametersOf(a->op());
|
||||
CheckTaggedInputParameters const& bp =
|
||||
CheckTaggedInputParametersOf(b->op());
|
||||
// {a} subsumes {b} if the modes are either the same, or {a} checks
|
||||
// for Number, in which case {b} will be subsumed no matter what.
|
||||
if (ap.mode() != bp.mode() &&
|
||||
ap.mode() != CheckTaggedInputMode::kNumber) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
DCHECK(!IsCheckedWithFeedback(a->op()));
|
||||
return false;
|
||||
|
@ -11,7 +11,7 @@ namespace v8 {
|
||||
namespace internal {
|
||||
namespace compiler {
|
||||
|
||||
class RedundancyElimination final : public AdvancedReducer {
|
||||
class V8_EXPORT_PRIVATE RedundancyElimination final : public AdvancedReducer {
|
||||
public:
|
||||
RedundancyElimination(Editor* editor, Zone* zone);
|
||||
~RedundancyElimination() final;
|
||||
|
@ -228,7 +228,7 @@ enum class CheckTaggedInputMode : uint8_t {
|
||||
|
||||
size_t hash_value(CheckTaggedInputMode);
|
||||
|
||||
std::ostream& operator<<(std::ostream&, CheckTaggedInputMode);
|
||||
V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, CheckTaggedInputMode);
|
||||
|
||||
class CheckTaggedInputParameters {
|
||||
public:
|
||||
|
@ -40,7 +40,8 @@ class V8_EXPORT_PRIVATE VectorSlotPair {
|
||||
bool operator==(VectorSlotPair const&, VectorSlotPair const&);
|
||||
bool operator!=(VectorSlotPair const&, VectorSlotPair const&);
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, VectorSlotPair const&);
|
||||
V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
|
||||
VectorSlotPair const&);
|
||||
|
||||
size_t hash_value(VectorSlotPair const&);
|
||||
|
||||
|
@ -131,6 +131,7 @@ v8_source_set("unittests_sources") {
|
||||
"compiler/node-unittest.cc",
|
||||
"compiler/opcodes-unittest.cc",
|
||||
"compiler/persistent-unittest.cc",
|
||||
"compiler/redundancy-elimination-unittest.cc",
|
||||
"compiler/regalloc/live-range-unittest.cc",
|
||||
"compiler/regalloc/move-optimizer-unittest.cc",
|
||||
"compiler/regalloc/register-allocator-unittest.cc",
|
||||
|
643
test/unittests/compiler/redundancy-elimination-unittest.cc
Normal file
643
test/unittests/compiler/redundancy-elimination-unittest.cc
Normal file
@ -0,0 +1,643 @@
|
||||
// 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::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};
|
||||
|
||||
} // 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace redundancy_elimination_unittest
|
||||
} // namespace compiler
|
||||
} // namespace internal
|
||||
} // namespace v8
|
Loading…
Reference in New Issue
Block a user