Commit cd339784 authored by titzer's avatar titzer Committed by Commit bot

[turbofan] Remove last_use_ field from Node.

R=mstarzinger@chromium.org
BUG=

Review URL: https://codereview.chromium.org/1022783002

Cr-Commit-Position: refs/heads/master@{#27319}
parent 84363499
......@@ -118,33 +118,23 @@ int Node::UseCount() const {
}
Node* Node::UseAt(int index) const {
DCHECK_LE(0, index);
DCHECK_LT(index, UseCount());
const Use* use = first_use_;
while (index-- != 0) {
use = use->next;
}
return use->from;
}
void Node::ReplaceUses(Node* replace_to) {
for (Use* use = first_use_; use; use = use->next) {
use->from->GetInputRecordPtr(use->input_index)->to = replace_to;
void Node::ReplaceUses(Node* that) {
DCHECK(this->first_use_ == nullptr || this->first_use_->prev == nullptr);
DCHECK(that->first_use_ == nullptr || that->first_use_->prev == nullptr);
// Update the pointers to {this} to point to {that}.
Use* last_use = nullptr;
for (Use* use = this->first_use_; use; use = use->next) {
use->from->GetInputRecordPtr(use->input_index)->to = that;
last_use = use;
}
if (!replace_to->last_use_) {
DCHECK(!replace_to->first_use_);
replace_to->first_use_ = first_use_;
replace_to->last_use_ = last_use_;
} else if (first_use_) {
DCHECK_NOT_NULL(replace_to->first_use_);
replace_to->last_use_->next = first_use_;
first_use_->prev = replace_to->last_use_;
replace_to->last_use_ = last_use_;
if (last_use) {
// Concat the use list of {this} and {that}.
last_use->next = that->first_use_;
if (that->first_use_) that->first_use_->prev = last_use;
that->first_use_ = this->first_use_;
}
first_use_ = nullptr;
last_use_ = nullptr;
}
......@@ -174,8 +164,7 @@ Node::Node(NodeId id, const Operator* op, int input_count,
bit_field_(InputCountField::encode(input_count) |
ReservedInputCountField::encode(reserved_input_count) |
HasAppendableInputsField::encode(false)),
first_use_(nullptr),
last_use_(nullptr) {}
first_use_(nullptr) {}
void Node::EnsureAppendableInputs(Zone* zone) {
......@@ -192,24 +181,21 @@ void Node::EnsureAppendableInputs(Zone* zone) {
void Node::AppendUse(Use* const use) {
use->next = nullptr;
use->prev = last_use_;
if (last_use_) {
last_use_->next = use;
} else {
first_use_ = use;
}
last_use_ = use;
DCHECK(first_use_ == nullptr || first_use_->prev == nullptr);
use->next = first_use_;
use->prev = nullptr;
if (first_use_) first_use_->prev = use;
first_use_ = use;
}
void Node::RemoveUse(Use* const use) {
if (use == last_use_) {
last_use_ = use->prev;
}
DCHECK(first_use_ == nullptr || first_use_->prev == nullptr);
if (use->prev) {
DCHECK_NE(first_use_, use);
use->prev->next = use->next;
} else {
DCHECK_EQ(first_use_, use);
first_use_ = use->next;
}
if (use->next) {
......
......@@ -67,7 +67,6 @@ class Node FINAL {
void TrimInputCount(int new_input_count);
int UseCount() const;
Node* UseAt(int index) const;
void ReplaceUses(Node* replace_to);
class InputEdges FINAL {
......@@ -226,7 +225,6 @@ class Node FINAL {
NodeId const id_;
unsigned bit_field_;
Use* first_use_;
Use* last_use_;
union {
// When a node is initially allocated, it uses a static buffer to hold its
// inputs under the assumption that the number of outputs will not increase.
......
......@@ -13,32 +13,143 @@
using namespace v8::internal;
using namespace v8::internal::compiler;
#define NONE reinterpret_cast<Node*>(1)
static Operator dummy_operator(IrOpcode::kParameter, Operator::kNoWrite,
"dummy", 0, 0, 0, 1, 0, 0);
#define CHECK_USES(node, ...) \
do { \
Node* __array[] = {__VA_ARGS__}; \
int __size = \
__array[0] != NONE ? static_cast<int>(arraysize(__array)) : 0; \
CheckUseChain(node, __array, __size); \
} while (false)
typedef std::multiset<Node*, std::less<Node*>> NodeMSet;
static void CheckUseChain(Node* node, Node** uses, int use_count) {
// Check ownership.
if (use_count == 1) CHECK(node->OwnedBy(uses[0]));
if (use_count > 1) {
for (int i = 0; i < use_count; i++) {
CHECK(!node->OwnedBy(uses[i]));
}
}
// Check the self-reported use count.
CHECK_EQ(use_count, node->UseCount());
// Build the expectation set.
NodeMSet expect_set;
for (int i = 0; i < use_count; i++) {
expect_set.insert(uses[i]);
}
{
// Check that iterating over the uses gives the right counts.
NodeMSet use_set;
for (auto use : node->uses()) {
use_set.insert(use);
}
CHECK(expect_set == use_set);
}
{
// Check that iterating over the use edges gives the right counts,
// input indices, from(), and to() pointers.
NodeMSet use_set;
for (auto edge : node->use_edges()) {
CHECK_EQ(node, edge.to());
CHECK_EQ(node, edge.from()->InputAt(edge.index()));
use_set.insert(edge.from());
}
CHECK(expect_set == use_set);
}
{
// Check the use nodes actually have the node as inputs.
for (Node* use : node->uses()) {
size_t count = 0;
for (Node* input : use->inputs()) {
if (input == node) count++;
}
CHECK_EQ(count, expect_set.count(use));
}
}
}
#define CHECK_INPUTS(node, ...) \
do { \
Node* __array[] = {__VA_ARGS__}; \
int __size = \
__array[0] != NONE ? static_cast<int>(arraysize(__array)) : 0; \
CheckInputs(node, __array, __size); \
} while (false)
static void CheckInputs(Node* node, Node** inputs, int input_count) {
CHECK_EQ(input_count, node->InputCount());
// Check InputAt().
for (int i = 0; i < static_cast<int>(input_count); i++) {
CHECK_EQ(inputs[i], node->InputAt(i));
}
// Check input iterator.
int index = 0;
for (Node* input : node->inputs()) {
CHECK_EQ(inputs[index], input);
index++;
}
// Check use lists of inputs.
for (int i = 0; i < static_cast<int>(input_count); i++) {
Node* input = inputs[i];
if (!input) continue; // skip null inputs
bool found = false;
// Check regular use list.
for (Node* use : input->uses()) {
if (use == node) {
found = true;
break;
}
}
CHECK(found);
int count = 0;
// Check use edge list.
for (auto edge : input->use_edges()) {
if (edge.from() == node && edge.to() == input && edge.index() == i) {
count++;
}
}
CHECK_EQ(1, count);
}
}
TEST(NodeUseIteratorReplaceUses) {
GraphTester graph;
Node* n0 = graph.NewNode(&dummy_operator);
Node* n1 = graph.NewNode(&dummy_operator, n0);
Node* n2 = graph.NewNode(&dummy_operator, n0);
Node* n3 = graph.NewNode(&dummy_operator);
auto i1(n0->uses().begin());
CHECK_EQ(n1, *i1);
++i1;
CHECK_EQ(n2, *i1);
CHECK_USES(n0, n1, n2);
CHECK_INPUTS(n1, n0);
CHECK_INPUTS(n2, n0);
n0->ReplaceUses(n3);
auto i2(n3->uses().begin());
CHECK_EQ(n1, *i2);
++i2;
CHECK_EQ(n2, *i2);
auto i3(n1->inputs().begin());
CHECK_EQ(n3, *i3);
++i3;
CHECK(n1->inputs().end() == i3);
auto i4(n2->inputs().begin());
CHECK_EQ(n3, *i4);
++i4;
CHECK(n2->inputs().end() == i4);
CHECK_USES(n0, NONE);
CHECK_USES(n1, NONE);
CHECK_USES(n2, NONE);
CHECK_USES(n3, n1, n2);
CHECK_INPUTS(n1, n3);
CHECK_INPUTS(n2, n3);
}
......@@ -46,21 +157,22 @@ TEST(NodeUseIteratorReplaceUsesSelf) {
GraphTester graph;
Node* n0 = graph.NewNode(&dummy_operator);
Node* n1 = graph.NewNode(&dummy_operator, n0);
Node* n3 = graph.NewNode(&dummy_operator);
CHECK_USES(n0, n1);
CHECK_USES(n1, NONE);
n1->ReplaceInput(0, n1); // Create self-reference.
auto i1(n1->uses().begin());
CHECK_EQ(n1, *i1);
CHECK_USES(n0, NONE);
CHECK_USES(n1, n1);
n1->ReplaceUses(n3);
Node* n2 = graph.NewNode(&dummy_operator);
CHECK(n1->uses().begin() == n1->uses().end());
n1->ReplaceUses(n2);
auto i2(n3->uses().begin());
CHECK_EQ(n1, *i2);
++i2;
CHECK(n1->uses().end() == i2);
CHECK_USES(n0, NONE);
CHECK_USES(n1, NONE);
CHECK_USES(n2, n1);
}
......@@ -70,48 +182,22 @@ TEST(ReplaceInput) {
Node* n1 = graph.NewNode(&dummy_operator);
Node* n2 = graph.NewNode(&dummy_operator);
Node* n3 = graph.NewNode(&dummy_operator, n0, n1, n2);
auto i1(n3->inputs().begin());
CHECK(n0 == *i1);
CHECK_EQ(n0, n3->InputAt(0));
++i1;
CHECK_EQ(n1, *i1);
CHECK_EQ(n1, n3->InputAt(1));
++i1;
CHECK_EQ(n2, *i1);
CHECK_EQ(n2, n3->InputAt(2));
++i1;
CHECK(i1 == n3->inputs().end());
auto i2(n1->uses().begin());
CHECK_EQ(n3, *i2);
++i2;
CHECK(i2 == n1->uses().end());
Node* n4 = graph.NewNode(&dummy_operator);
auto i3(n4->uses().begin());
CHECK(i3 == n4->uses().end());
CHECK_USES(n0, n3);
CHECK_USES(n1, n3);
CHECK_USES(n2, n3);
CHECK_USES(n3, NONE);
CHECK_USES(n4, NONE);
CHECK_INPUTS(n3, n0, n1, n2);
n3->ReplaceInput(1, n4);
auto i4(n1->uses().begin());
CHECK(i4 == n1->uses().end());
auto i5(n4->uses().begin());
CHECK_EQ(n3, *i5);
++i5;
CHECK(i5 == n4->uses().end());
auto i6(n3->inputs().begin());
CHECK(n0 == *i6);
CHECK_EQ(n0, n3->InputAt(0));
++i6;
CHECK_EQ(n4, *i6);
CHECK_EQ(n4, n3->InputAt(1));
++i6;
CHECK_EQ(n2, *i6);
CHECK_EQ(n2, n3->InputAt(2));
++i6;
CHECK(i6 == n3->inputs().end());
CHECK_USES(n1, NONE);
CHECK_USES(n4, n3);
CHECK_INPUTS(n3, n0, n4, n2);
}
......@@ -169,16 +255,19 @@ TEST(Uses) {
Node* n0 = graph.NewNode(&dummy_operator);
Node* n1 = graph.NewNode(&dummy_operator, n0);
CHECK_EQ(1, n0->UseCount());
printf("A: %d vs %d\n", n0->UseAt(0)->id(), n1->id());
CHECK(n0->UseAt(0) == n1);
CHECK_USES(n0, n1);
CHECK_USES(n1, NONE);
Node* n2 = graph.NewNode(&dummy_operator, n0);
CHECK_EQ(2, n0->UseCount());
printf("B: %d vs %d\n", n0->UseAt(1)->id(), n2->id());
CHECK(n0->UseAt(1) == n2);
CHECK_USES(n0, n1, n2);
CHECK_USES(n2, NONE);
Node* n3 = graph.NewNode(&dummy_operator, n0);
CHECK_EQ(3, n0->UseCount());
CHECK(n0->UseAt(2) == n3);
CHECK_USES(n0, n1, n2, n3);
CHECK_USES(n3, NONE);
}
......@@ -189,39 +278,23 @@ TEST(Inputs) {
Node* n1 = graph.NewNode(&dummy_operator, n0);
Node* n2 = graph.NewNode(&dummy_operator, n0);
Node* n3 = graph.NewNode(&dummy_operator, n0, n1, n2);
CHECK_EQ(3, n3->InputCount());
CHECK(n3->InputAt(0) == n0);
CHECK(n3->InputAt(1) == n1);
CHECK(n3->InputAt(2) == n2);
CHECK_INPUTS(n3, n0, n1, n2);
Node* n4 = graph.NewNode(&dummy_operator, n0, n1, n2);
n3->AppendInput(graph.zone(), n4);
CHECK_EQ(4, n3->InputCount());
CHECK(n3->InputAt(0) == n0);
CHECK(n3->InputAt(1) == n1);
CHECK(n3->InputAt(2) == n2);
CHECK(n3->InputAt(3) == n4);
Node* n5 = graph.NewNode(&dummy_operator, n4);
CHECK_INPUTS(n3, n0, n1, n2, n4);
CHECK_USES(n4, n3);
n3->AppendInput(graph.zone(), n4);
CHECK_EQ(5, n3->InputCount());
CHECK(n3->InputAt(0) == n0);
CHECK(n3->InputAt(1) == n1);
CHECK(n3->InputAt(2) == n2);
CHECK(n3->InputAt(3) == n4);
CHECK(n3->InputAt(4) == n4);
// Make sure uses have been hooked op correctly.
Node::Uses uses(n4->uses());
auto current = uses.begin();
CHECK(current != uses.end());
CHECK(*current == n3);
++current;
CHECK(current != uses.end());
CHECK(*current == n5);
++current;
CHECK(current != uses.end());
CHECK(*current == n3);
++current;
CHECK(current == uses.end());
CHECK_INPUTS(n3, n0, n1, n2, n4, n4);
CHECK_USES(n4, n3, n3);
Node* n5 = graph.NewNode(&dummy_operator, n4);
CHECK_USES(n4, n3, n3, n5);
}
......@@ -232,17 +305,25 @@ TEST(RemoveInput) {
Node* n1 = graph.NewNode(&dummy_operator, n0);
Node* n2 = graph.NewNode(&dummy_operator, n0, n1);
CHECK_INPUTS(n0, NONE);
CHECK_INPUTS(n1, n0);
CHECK_INPUTS(n2, n0, n1);
CHECK_USES(n0, n1, n2);
n1->RemoveInput(0);
CHECK_EQ(0, n1->InputCount());
CHECK_EQ(1, n0->UseCount());
CHECK_INPUTS(n1, NONE);
CHECK_USES(n0, n2);
n2->RemoveInput(0);
CHECK_EQ(1, n2->InputCount());
CHECK_EQ(0, n0->UseCount());
CHECK_EQ(1, n1->UseCount());
CHECK_INPUTS(n2, n1);
CHECK_USES(n0, NONE);
CHECK_USES(n1, n2);
n2->RemoveInput(0);
CHECK_EQ(0, n2->InputCount());
CHECK_INPUTS(n2, NONE);
CHECK_USES(n0, NONE);
CHECK_USES(n1, NONE);
CHECK_USES(n2, NONE);
}
......@@ -253,33 +334,17 @@ TEST(AppendInputsAndIterator) {
Node* n1 = graph.NewNode(&dummy_operator, n0);
Node* n2 = graph.NewNode(&dummy_operator, n0, n1);
Node::InputEdges inputs(n2->input_edges());
Node::InputEdges::iterator current = inputs.begin();
CHECK(current != inputs.end());
CHECK((*current).to() == n0);
++current;
CHECK(current != inputs.end());
CHECK((*current).to() == n1);
++current;
CHECK(current == inputs.end());
CHECK_INPUTS(n0, NONE);
CHECK_INPUTS(n1, n0);
CHECK_INPUTS(n2, n0, n1);
CHECK_USES(n0, n1, n2);
Node* n3 = graph.NewNode(&dummy_operator);
n2->AppendInput(graph.zone(), n3);
inputs = n2->input_edges();
current = inputs.begin();
CHECK(current != inputs.end());
CHECK((*current).to() == n0);
CHECK_EQ(0, (*current).index());
++current;
CHECK(current != inputs.end());
CHECK((*current).to() == n1);
CHECK_EQ(1, (*current).index());
++current;
CHECK(current != inputs.end());
CHECK((*current).to() == n3);
CHECK_EQ(2, (*current).index());
++current;
CHECK(current == inputs.end());
CHECK_INPUTS(n2, n0, n1, n3);
CHECK_USES(n3, n2);
}
......@@ -289,15 +354,23 @@ TEST(NullInputsSimple) {
Node* n0 = graph.NewNode(&dummy_operator);
Node* n1 = graph.NewNode(&dummy_operator, n0);
Node* n2 = graph.NewNode(&dummy_operator, n0, n1);
CHECK_EQ(2, n2->InputCount());
CHECK(n0 == n2->InputAt(0));
CHECK(n1 == n2->InputAt(1));
CHECK_EQ(2, n0->UseCount());
n2->ReplaceInput(0, NULL);
CHECK(NULL == n2->InputAt(0));
CHECK(n1 == n2->InputAt(1));
CHECK_EQ(1, n0->UseCount());
CHECK_INPUTS(n0, NONE);
CHECK_INPUTS(n1, n0);
CHECK_INPUTS(n2, n0, n1);
CHECK_USES(n0, n1, n2);
n2->ReplaceInput(0, nullptr);
CHECK_INPUTS(n2, NULL, n1);
CHECK_USES(n0, n1);
n2->ReplaceInput(1, nullptr);
CHECK_INPUTS(n2, NULL, NULL);
CHECK_USES(n1, NONE);
}
......@@ -310,17 +383,16 @@ TEST(NullInputsAppended) {
Node* n3 = graph.NewNode(&dummy_operator, n0);
n3->AppendInput(graph.zone(), n1);
n3->AppendInput(graph.zone(), n2);
CHECK_EQ(3, n3->InputCount());
CHECK(n0 == n3->InputAt(0));
CHECK(n1 == n3->InputAt(1));
CHECK(n2 == n3->InputAt(2));
CHECK_EQ(1, n1->UseCount());
CHECK_INPUTS(n3, n0, n1, n2);
CHECK_USES(n0, n1, n2, n3);
CHECK_USES(n1, n3);
CHECK_USES(n2, n3);
n3->ReplaceInput(1, NULL);
CHECK(n0 == n3->InputAt(0));
CHECK(NULL == n3->InputAt(1));
CHECK(n2 == n3->InputAt(2));
CHECK_EQ(0, n1->UseCount());
CHECK_USES(n1, NONE);
CHECK_INPUTS(n3, n0, NULL, n2);
}
......@@ -331,26 +403,23 @@ TEST(ReplaceUsesFromAppendedInputs) {
Node* n1 = graph.NewNode(&dummy_operator, n0);
Node* n2 = graph.NewNode(&dummy_operator, n0);
Node* n3 = graph.NewNode(&dummy_operator);
CHECK_INPUTS(n2, n0);
n2->AppendInput(graph.zone(), n1);
CHECK_INPUTS(n2, n0, n1);
CHECK_USES(n1, n2);
n2->AppendInput(graph.zone(), n0);
CHECK_EQ(0, n3->UseCount());
CHECK_EQ(3, n0->UseCount());
CHECK_INPUTS(n2, n0, n1, n0);
CHECK_USES(n1, n2);
CHECK_USES(n0, n2, n1, n2);
n0->ReplaceUses(n3);
CHECK_EQ(0, n0->UseCount());
CHECK_EQ(3, n3->UseCount());
Node::Uses uses(n3->uses());
auto current = uses.begin();
CHECK(current != uses.end());
CHECK(*current == n1);
++current;
CHECK(current != uses.end());
CHECK(*current == n2);
++current;
CHECK(current != uses.end());
CHECK(*current == n2);
++current;
CHECK(current == uses.end());
CHECK_USES(n0, NONE);
CHECK_INPUTS(n2, n3, n1, n3);
CHECK_USES(n3, n2, n1, n2);
}
......@@ -378,17 +447,16 @@ TEST(TrimInputCountInline) {
Node* n0 = graph.NewNode(&dummy_operator);
Node* n1 = graph.NewNode(&dummy_operator, n0);
n1->TrimInputCount(1);
CHECK_EQ(1, n1->InputCount());
CHECK_EQ(n0, n1->InputAt(0));
CHECK_EQ(1, n0->UseCount());
CHECK_INPUTS(n1, n0);
CHECK_USES(n0, n1);
}
{
Node* n0 = graph.NewNode(&dummy_operator);
Node* n1 = graph.NewNode(&dummy_operator, n0);
n1->TrimInputCount(0);
CHECK_EQ(0, n1->InputCount());
CHECK_EQ(0, n0->UseCount());
CHECK_INPUTS(n1, NONE);
CHECK_USES(n0, NONE);
}
{
......@@ -396,10 +464,9 @@ TEST(TrimInputCountInline) {
Node* n1 = graph.NewNode(&dummy_operator);
Node* n2 = graph.NewNode(&dummy_operator, n0, n1);
n2->TrimInputCount(2);
CHECK_EQ(2, n2->InputCount());
CHECK_EQ(1, n0->UseCount());
CHECK_EQ(1, n1->UseCount());
CHECK_EQ(0, n2->UseCount());
CHECK_INPUTS(n2, n0, n1);
CHECK_USES(n0, n2);
CHECK_USES(n1, n2);
}
{
......@@ -407,10 +474,9 @@ TEST(TrimInputCountInline) {
Node* n1 = graph.NewNode(&dummy_operator);
Node* n2 = graph.NewNode(&dummy_operator, n0, n1);
n2->TrimInputCount(1);
CHECK_EQ(1, n2->InputCount());
CHECK_EQ(1, n0->UseCount());
CHECK_EQ(0, n1->UseCount());
CHECK_EQ(0, n2->UseCount());
CHECK_INPUTS(n2, n0);
CHECK_USES(n0, n2);
CHECK_USES(n1, NONE);
}
{
......@@ -418,28 +484,25 @@ TEST(TrimInputCountInline) {
Node* n1 = graph.NewNode(&dummy_operator);
Node* n2 = graph.NewNode(&dummy_operator, n0, n1);
n2->TrimInputCount(0);
CHECK_EQ(0, n2->InputCount());
CHECK_EQ(0, n0->UseCount());
CHECK_EQ(0, n1->UseCount());
CHECK_EQ(0, n2->UseCount());
CHECK_INPUTS(n2, NONE);
CHECK_USES(n0, NONE);
CHECK_USES(n1, NONE);
}
{
Node* n0 = graph.NewNode(&dummy_operator);
Node* n2 = graph.NewNode(&dummy_operator, n0, n0);
n2->TrimInputCount(1);
CHECK_EQ(1, n2->InputCount());
CHECK_EQ(1, n0->UseCount());
CHECK_EQ(0, n2->UseCount());
CHECK_INPUTS(n2, n0);
CHECK_USES(n0, n2);
}
{
Node* n0 = graph.NewNode(&dummy_operator);
Node* n2 = graph.NewNode(&dummy_operator, n0, n0);
n2->TrimInputCount(0);
CHECK_EQ(0, n2->InputCount());
CHECK_EQ(0, n0->UseCount());
CHECK_EQ(0, n2->UseCount());
CHECK_INPUTS(n2, NONE);
CHECK_USES(n0, NONE);
}
}
......@@ -451,10 +514,12 @@ TEST(TrimInputCountOutOfLine1) {
Node* n0 = graph.NewNode(&dummy_operator);
Node* n1 = graph.NewNode(&dummy_operator);
n1->AppendInput(graph.zone(), n0);
CHECK_INPUTS(n1, n0);
CHECK_USES(n0, n1);
n1->TrimInputCount(1);
CHECK_EQ(1, n1->InputCount());
CHECK_EQ(n0, n1->InputAt(0));
CHECK_EQ(1, n0->UseCount());
CHECK_INPUTS(n1, n0);
CHECK_USES(n0, n1);
}
{
......@@ -473,14 +538,12 @@ TEST(TrimInputCountOutOfLine1) {
Node* n2 = graph.NewNode(&dummy_operator);
n2->AppendInput(graph.zone(), n0);
n2->AppendInput(graph.zone(), n1);
CHECK_EQ(2, n2->InputCount());
CHECK_INPUTS(n2, n0, n1);
n2->TrimInputCount(2);
CHECK_EQ(2, n2->InputCount());
CHECK_EQ(n0, n2->InputAt(0));
CHECK_EQ(n1, n2->InputAt(1));
CHECK_EQ(1, n0->UseCount());
CHECK_EQ(1, n1->UseCount());
CHECK_EQ(0, n2->UseCount());
CHECK_INPUTS(n2, n0, n1);
CHECK_USES(n0, n2);
CHECK_USES(n1, n2);
CHECK_USES(n2, NONE);
}
{
......@@ -489,13 +552,12 @@ TEST(TrimInputCountOutOfLine1) {
Node* n2 = graph.NewNode(&dummy_operator);
n2->AppendInput(graph.zone(), n0);
n2->AppendInput(graph.zone(), n1);
CHECK_EQ(2, n2->InputCount());
CHECK_INPUTS(n2, n0, n1);
n2->TrimInputCount(1);
CHECK_EQ(1, n2->InputCount());
CHECK_EQ(n0, n2->InputAt(0));
CHECK_EQ(1, n0->UseCount());
CHECK_EQ(0, n1->UseCount());
CHECK_EQ(0, n2->UseCount());
CHECK_INPUTS(n2, n0);
CHECK_USES(n0, n2);
CHECK_USES(n1, NONE);
CHECK_USES(n2, NONE);
}
{
......@@ -504,12 +566,12 @@ TEST(TrimInputCountOutOfLine1) {
Node* n2 = graph.NewNode(&dummy_operator);
n2->AppendInput(graph.zone(), n0);
n2->AppendInput(graph.zone(), n1);
CHECK_EQ(2, n2->InputCount());
CHECK_INPUTS(n2, n0, n1);
n2->TrimInputCount(0);
CHECK_EQ(0, n2->InputCount());
CHECK_EQ(0, n0->UseCount());
CHECK_EQ(0, n1->UseCount());
CHECK_EQ(0, n2->UseCount());
CHECK_INPUTS(n2, NONE);
CHECK_USES(n0, NONE);
CHECK_USES(n1, NONE);
CHECK_USES(n2, NONE);
}
{
......@@ -517,12 +579,11 @@ TEST(TrimInputCountOutOfLine1) {
Node* n2 = graph.NewNode(&dummy_operator);
n2->AppendInput(graph.zone(), n0);
n2->AppendInput(graph.zone(), n0);
CHECK_EQ(2, n2->InputCount());
CHECK_EQ(2, n0->UseCount());
CHECK_INPUTS(n2, n0, n0);
CHECK_USES(n0, n2, n2);
n2->TrimInputCount(1);
CHECK_EQ(1, n2->InputCount());
CHECK_EQ(1, n0->UseCount());
CHECK_EQ(0, n2->UseCount());
CHECK_INPUTS(n2, n0);
CHECK_USES(n0, n2);
}
{
......@@ -530,12 +591,11 @@ TEST(TrimInputCountOutOfLine1) {
Node* n2 = graph.NewNode(&dummy_operator);
n2->AppendInput(graph.zone(), n0);
n2->AppendInput(graph.zone(), n0);
CHECK_EQ(2, n2->InputCount());
CHECK_EQ(2, n0->UseCount());
CHECK_INPUTS(n2, n0, n0);
CHECK_USES(n0, n2, n2);
n2->TrimInputCount(0);
CHECK_EQ(0, n2->InputCount());
CHECK_EQ(0, n0->UseCount());
CHECK_EQ(0, n2->UseCount());
CHECK_INPUTS(n2, NONE);
CHECK_USES(n0, NONE);
}
}
......@@ -548,14 +608,12 @@ TEST(TrimInputCountOutOfLine2) {
Node* n1 = graph.NewNode(&dummy_operator);
Node* n2 = graph.NewNode(&dummy_operator, n0);
n2->AppendInput(graph.zone(), n1);
CHECK_EQ(2, n2->InputCount());
CHECK_INPUTS(n2, n0, n1);
n2->TrimInputCount(2);
CHECK_EQ(2, n2->InputCount());
CHECK_EQ(n0, n2->InputAt(0));
CHECK_EQ(n1, n2->InputAt(1));
CHECK_EQ(1, n0->UseCount());
CHECK_EQ(1, n1->UseCount());
CHECK_EQ(0, n2->UseCount());
CHECK_INPUTS(n2, n0, n1);
CHECK_USES(n0, n2);
CHECK_USES(n1, n2);
CHECK_USES(n2, NONE);
}
{
......@@ -563,13 +621,12 @@ TEST(TrimInputCountOutOfLine2) {
Node* n1 = graph.NewNode(&dummy_operator);
Node* n2 = graph.NewNode(&dummy_operator, n0);
n2->AppendInput(graph.zone(), n1);
CHECK_EQ(2, n2->InputCount());
CHECK_INPUTS(n2, n0, n1);
n2->TrimInputCount(1);
CHECK_EQ(1, n2->InputCount());
CHECK_EQ(n0, n2->InputAt(0));
CHECK_EQ(1, n0->UseCount());
CHECK_EQ(0, n1->UseCount());
CHECK_EQ(0, n2->UseCount());
CHECK_INPUTS(n2, n0);
CHECK_USES(n0, n2);
CHECK_USES(n1, NONE);
CHECK_USES(n2, NONE);
}
{
......@@ -577,24 +634,24 @@ TEST(TrimInputCountOutOfLine2) {
Node* n1 = graph.NewNode(&dummy_operator);
Node* n2 = graph.NewNode(&dummy_operator, n0);
n2->AppendInput(graph.zone(), n1);
CHECK_EQ(2, n2->InputCount());
CHECK_INPUTS(n2, n0, n1);
n2->TrimInputCount(0);
CHECK_EQ(0, n2->InputCount());
CHECK_EQ(0, n0->UseCount());
CHECK_EQ(0, n1->UseCount());
CHECK_EQ(0, n2->UseCount());
CHECK_INPUTS(n2, NONE);
CHECK_USES(n0, NONE);
CHECK_USES(n1, NONE);
CHECK_USES(n2, NONE);
}
{
Node* n0 = graph.NewNode(&dummy_operator);
Node* n2 = graph.NewNode(&dummy_operator, n0);
n2->AppendInput(graph.zone(), n0);
CHECK_EQ(2, n2->InputCount());
CHECK_EQ(2, n0->UseCount());
CHECK_INPUTS(n2, n0, n0);
CHECK_USES(n0, n2, n2);
n2->TrimInputCount(1);
CHECK_EQ(1, n2->InputCount());
CHECK_EQ(1, n0->UseCount());
CHECK_EQ(0, n2->UseCount());
CHECK_INPUTS(n2, n0);
CHECK_USES(n0, n2);
CHECK_USES(n2, NONE);
}
{
......@@ -620,27 +677,27 @@ TEST(RemoveAllInputs) {
Node* n2;
if (i == 0) {
n2 = graph.NewNode(&dummy_operator, n0, n1);
CHECK_INPUTS(n2, n0, n1);
} else {
n2 = graph.NewNode(&dummy_operator, n0);
CHECK_INPUTS(n2, n0);
n2->AppendInput(graph.zone(), n1); // with out-of-line input.
CHECK_INPUTS(n2, n0, n1);
}
n0->RemoveAllInputs();
CHECK_EQ(0, n0->InputCount());
CHECK_INPUTS(n0, NONE);
CHECK_EQ(2, n0->UseCount());
CHECK_USES(n0, n1, n2);
n1->RemoveAllInputs();
CHECK_EQ(1, n1->InputCount());
CHECK_EQ(1, n0->UseCount());
CHECK(!n1->InputAt(0));
CHECK_INPUTS(n1, NULL);
CHECK_INPUTS(n2, n0, n1);
CHECK_USES(n0, n2);
CHECK_EQ(1, n1->UseCount());
n2->RemoveAllInputs();
CHECK_EQ(2, n2->InputCount());
CHECK_EQ(0, n0->UseCount());
CHECK_EQ(0, n1->UseCount());
CHECK(!n2->InputAt(0));
CHECK(!n2->InputAt(1));
CHECK_INPUTS(n1, NULL);
CHECK_INPUTS(n2, NULL, NULL);
CHECK_USES(n0, NONE);
}
{
......@@ -648,11 +705,53 @@ TEST(RemoveAllInputs) {
Node* n1 = graph.NewNode(&dummy_operator, n0);
n1->ReplaceInput(0, n1); // self-reference.
CHECK_EQ(0, n0->UseCount());
CHECK_EQ(1, n1->UseCount());
CHECK_INPUTS(n0, NONE);
CHECK_INPUTS(n1, n1);
CHECK_USES(n0, NONE);
CHECK_USES(n1, n1);
n1->RemoveAllInputs();
CHECK_EQ(1, n1->InputCount());
CHECK_EQ(0, n1->UseCount());
CHECK(!n1->InputAt(0));
CHECK_INPUTS(n0, NONE);
CHECK_INPUTS(n1, NULL);
CHECK_USES(n0, NONE);
CHECK_USES(n1, NONE);
}
}
TEST(AppendAndTrim) {
GraphTester graph;
Node* nodes[] = {
graph.NewNode(&dummy_operator), graph.NewNode(&dummy_operator),
graph.NewNode(&dummy_operator), graph.NewNode(&dummy_operator),
graph.NewNode(&dummy_operator)};
int max = static_cast<int>(arraysize(nodes));
Node* last = graph.NewNode(&dummy_operator);
for (int i = 0; i < max; i++) {
last->AppendInput(graph.zone(), nodes[i]);
CheckInputs(last, nodes, i + 1);
for (int j = 0; j < max; j++) {
if (j <= i) CHECK_USES(nodes[j], last);
if (j > i) CHECK_USES(nodes[j], NONE);
}
CHECK_USES(last, NONE);
}
for (int i = max; i >= 0; i--) {
last->TrimInputCount(i);
CheckInputs(last, nodes, i);
for (int j = 0; j < i; j++) {
if (j < i) CHECK_USES(nodes[j], last);
if (j >= i) CHECK_USES(nodes[j], NONE);
}
CHECK_USES(last, NONE);
}
}
......@@ -10,6 +10,7 @@
using testing::AnyOf;
using testing::ElementsAre;
using testing::IsNull;
using testing::UnorderedElementsAre;
namespace v8 {
namespace internal {
......@@ -56,7 +57,7 @@ TEST_F(NodePropertiesTest, ReplaceWithValue_EffectUse) {
EXPECT_EQ(0, node->UseCount());
EXPECT_EQ(2, start->UseCount());
EXPECT_EQ(0, replacement->UseCount());
EXPECT_THAT(start->uses(), ElementsAre(node, use_effect));
EXPECT_THAT(start->uses(), UnorderedElementsAre(use_effect, node));
}
......@@ -72,7 +73,7 @@ TEST_F(NodePropertiesTest, ReplaceWithValue_ControlUse) {
EXPECT_EQ(0, node->UseCount());
EXPECT_EQ(2, start->UseCount());
EXPECT_EQ(0, replacement->UseCount());
EXPECT_THAT(start->uses(), ElementsAre(node, use_control));
EXPECT_THAT(start->uses(), UnorderedElementsAre(use_control, node));
}
......
......@@ -543,11 +543,23 @@ class IsEffectSetMatcher FINAL : public NodeMatcher {
}
bool MatchAndExplain(Node* node, MatchResultListener* listener) const FINAL {
return (NodeMatcher::MatchAndExplain(node, listener) &&
PrintMatchAndExplain(NodeProperties::GetEffectInput(node, 0),
"effect0", effect0_matcher_, listener) &&
PrintMatchAndExplain(NodeProperties::GetEffectInput(node, 1),
"effect1", effect1_matcher_, listener));
if (!NodeMatcher::MatchAndExplain(node, listener)) return false;
Node* effect0 = NodeProperties::GetEffectInput(node, 0);
Node* effect1 = NodeProperties::GetEffectInput(node, 1);
{
// Try matching in the reverse order first.
StringMatchResultListener value_listener;
if (effect0_matcher_.MatchAndExplain(effect1, &value_listener) &&
effect1_matcher_.MatchAndExplain(effect0, &value_listener)) {
return true;
}
}
return PrintMatchAndExplain(effect0, "effect0", effect0_matcher_,
listener) &&
PrintMatchAndExplain(effect1, "effect1", effect1_matcher_, listener);
}
private:
......
......@@ -48,15 +48,15 @@ TEST_F(NodeTest, NewWithInputs) {
EXPECT_EQ(0, n0->InputCount());
Node* n1 = Node::New(zone(), 1, &kOp1, 1, &n0, false);
EXPECT_EQ(1, n0->UseCount());
EXPECT_EQ(n1, n0->UseAt(0));
EXPECT_THAT(n0->uses(), UnorderedElementsAre(n1));
EXPECT_EQ(0, n1->UseCount());
EXPECT_EQ(1, n1->InputCount());
EXPECT_EQ(n0, n1->InputAt(0));
Node* n0_n1[] = {n0, n1};
Node* n2 = Node::New(zone(), 2, &kOp2, 2, n0_n1, false);
EXPECT_EQ(2, n0->UseCount());
EXPECT_EQ(n1, n0->UseAt(0));
EXPECT_EQ(n2, n0->UseAt(1));
EXPECT_THAT(n0->uses(), UnorderedElementsAre(n1, n2));
EXPECT_THAT(n1->uses(), UnorderedElementsAre(n2));
EXPECT_EQ(2, n2->InputCount());
EXPECT_EQ(n0, n2->InputAt(0));
EXPECT_EQ(n1, n2->InputAt(1));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment