Commit f6e5bc16 authored by danno's avatar danno Committed by Commit bot

Clean up node iteration

- Create a first-class Edge type.
- Separate node and edge iterators
- Make iterators only responsible for iteration
- Make it possible to modify the use edge iterator while iterating.
- Add the ability to update inputs to Edges directly.

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

Cr-Commit-Position: refs/heads/master@{#25616}
parent 2ac522ab
......@@ -199,9 +199,9 @@ namespace {
bool CanCover(Node* value, IrOpcode::Value opcode) {
if (value->opcode() != opcode) return false;
bool first = true;
for (auto i = value->uses().begin(); i != value->uses().end(); ++i) {
if (NodeProperties::IsEffectEdge(i.edge())) continue;
DCHECK(NodeProperties::IsValueEdge(i.edge()));
for (Edge const edge : value->use_edges()) {
if (NodeProperties::IsEffectEdge(edge)) continue;
DCHECK(NodeProperties::IsValueEdge(edge));
if (!first) return false;
first = false;
}
......@@ -236,11 +236,9 @@ Reduction ChangeLowering::ChangeTaggedToFloat64(Node* value, Node* control) {
Node* phi1 = d1.Phi(kMachFloat64, phi2, ChangeSmiToFloat64(object));
Node* ephi1 = d1.EffectPhi(number, effect);
for (auto i = value->uses().begin(); i != value->uses().end();) {
if (NodeProperties::IsEffectEdge(i.edge())) {
i.UpdateToAndIncrement(ephi1);
} else {
++i;
for (Edge edge : value->use_edges()) {
if (NodeProperties::IsEffectEdge(edge)) {
edge.UpdateTo(ephi1);
}
}
return Replace(phi1);
......
......@@ -237,14 +237,13 @@ class ControlReducerImpl {
// Remove dead->live edges.
for (size_t j = 0; j < nodes.size(); j++) {
Node* node = nodes[j];
for (UseIter i = node->uses().begin(); i != node->uses().end();) {
if (!marked.IsReachableFromEnd(*i)) {
TRACE(("DeadLink: #%d:%s(%d) -> #%d:%s\n", (*i)->id(),
(*i)->op()->mnemonic(), i.index(), node->id(),
for (Edge edge : node->use_edges()) {
Node* use = edge.from();
if (!marked.IsReachableFromEnd(use)) {
TRACE(("DeadLink: #%d:%s(%d) -> #%d:%s\n", use->id(),
use->op()->mnemonic(), edge.index(), node->id(),
node->op()->mnemonic()));
i.UpdateToAndIncrement(NULL);
} else {
++i;
edge.UpdateTo(NULL);
}
}
}
......@@ -473,18 +472,16 @@ class ControlReducerImpl {
// Replace IfTrue and IfFalse projections from this branch.
Node* control = NodeProperties::GetControlInput(node);
for (UseIter i = node->uses().begin(); i != node->uses().end();) {
Node* to = *i;
if (to->opcode() == IrOpcode::kIfTrue) {
TRACE((" IfTrue: #%d:%s\n", to->id(), to->op()->mnemonic()));
i.UpdateToAndIncrement(NULL);
ReplaceNode(to, (result == kTrue) ? control : dead());
} else if (to->opcode() == IrOpcode::kIfFalse) {
TRACE((" IfFalse: #%d:%s\n", to->id(), to->op()->mnemonic()));
i.UpdateToAndIncrement(NULL);
ReplaceNode(to, (result == kTrue) ? dead() : control);
} else {
++i;
for (Edge edge : node->use_edges()) {
Node* use = edge.from();
if (use->opcode() == IrOpcode::kIfTrue) {
TRACE((" IfTrue: #%d:%s\n", use->id(), use->op()->mnemonic()));
edge.UpdateTo(NULL);
ReplaceNode(use, (result == kTrue) ? control : dead());
} else if (use->opcode() == IrOpcode::kIfFalse) {
TRACE((" IfFalse: #%d:%s\n", use->id(), use->op()->mnemonic()));
edge.UpdateTo(NULL);
ReplaceNode(use, (result == kTrue) ? dead() : control);
}
}
return control;
......
......@@ -19,13 +19,13 @@ template <class N>
class NodeInputIterationTraits {
public:
typedef N Node;
typedef typename N::Inputs::iterator Iterator;
typedef typename N::InputEdges::iterator Iterator;
static Iterator begin(Node* node) { return node->inputs().begin(); }
static Iterator end(Node* node) { return node->inputs().end(); }
static Iterator begin(Node* node) { return node->input_edges().begin(); }
static Iterator end(Node* node) { return node->input_edges().end(); }
static int max_id(Graph* graph) { return graph->NodeCount(); }
static Node* to(Iterator iterator) { return *iterator; }
static Node* from(Iterator iterator) { return iterator.edge().from(); }
static Node* to(Iterator iterator) { return (*iterator).to(); }
static Node* from(Iterator iterator) { return (*iterator).from(); }
};
} // namespace compiler
......
......@@ -70,13 +70,13 @@ class GenericGraphVisit {
post_order_node = Traits::from(stack.top().first);
visit = true;
} else {
visitor->PreEdge(Traits::from(top.first), top.first.edge().index(),
visitor->PreEdge(Traits::from(top.first), (*top.first).index(),
Traits::to(top.first));
current = Traits::to(top.first);
if (!GetVisited(&visited, current->id())) break;
}
top = stack.top();
visitor->PostEdge(Traits::from(top.first), top.first.edge().index(),
visitor->PostEdge(Traits::from(top.first), (*top.first).index(),
Traits::to(top.first));
++stack.top().first;
}
......
......@@ -228,7 +228,7 @@ class GraphVisualizer {
void PrintNode(Node* node, bool gray);
private:
void PrintEdge(Node::Edge edge);
void PrintEdge(Edge edge);
AllNodes all_;
std::ostream& os_;
......@@ -285,26 +285,26 @@ void GraphVisualizer::PrintNode(Node* node, bool gray) {
label << *node->op();
os_ << " label=\"{{#" << SafeId(node) << ":" << Escaped(label);
InputIter i = node->inputs().begin();
auto i = node->input_edges().begin();
for (int j = node->op()->ValueInputCount(); j > 0; ++i, j--) {
os_ << "|<I" << i.index() << ">#" << SafeId(*i);
os_ << "|<I" << (*i).index() << ">#" << SafeId((*i).to());
}
for (int j = OperatorProperties::GetContextInputCount(node->op()); j > 0;
++i, j--) {
os_ << "|<I" << i.index() << ">X #" << SafeId(*i);
os_ << "|<I" << (*i).index() << ">X #" << SafeId((*i).to());
}
for (int j = OperatorProperties::GetFrameStateInputCount(node->op()); j > 0;
++i, j--) {
os_ << "|<I" << i.index() << ">F #" << SafeId(*i);
os_ << "|<I" << (*i).index() << ">F #" << SafeId((*i).to());
}
for (int j = node->op()->EffectInputCount(); j > 0; ++i, j--) {
os_ << "|<I" << i.index() << ">E #" << SafeId(*i);
os_ << "|<I" << (*i).index() << ">E #" << SafeId((*i).to());
}
if (OperatorProperties::IsBasicBlockBegin(node->op()) ||
GetControlCluster(node) == NULL) {
for (int j = node->op()->ControlInputCount(); j > 0; ++i, j--) {
os_ << "|<I" << i.index() << ">C #" << SafeId(*i);
os_ << "|<I" << (*i).index() << ">C #" << SafeId((*i).to());
}
}
os_ << "}";
......@@ -338,7 +338,7 @@ static bool IsLikelyBackEdge(Node* from, int index, Node* to) {
}
void GraphVisualizer::PrintEdge(Node::Edge edge) {
void GraphVisualizer::PrintEdge(Edge edge) {
Node* from = edge.from();
int index = edge.index();
Node* to = edge.to();
......@@ -382,8 +382,8 @@ void GraphVisualizer::Print() {
// With all the nodes written, add the edges.
for (Node* const node : all_.live) {
for (UseIter i = node->uses().begin(); i != node->uses().end(); ++i) {
PrintEdge(i.edge());
for (Edge edge : node->use_edges()) {
PrintEdge(edge);
}
}
os_ << "}\n";
......@@ -531,7 +531,7 @@ void GraphC1Visualizer::PrintInputs(InputIter* i, int count,
void GraphC1Visualizer::PrintInputs(Node* node) {
InputIter i = node->inputs().begin();
auto i = node->inputs().begin();
PrintInputs(&i, node->op()->ValueInputCount(), " ");
PrintInputs(&i, OperatorProperties::GetContextInputCount(node->op()),
" Ctx:");
......
......@@ -47,9 +47,8 @@ void InstructionSelector::SelectInstructions() {
if (phi->opcode() != IrOpcode::kPhi) continue;
// Mark all inputs as used.
Node::Inputs inputs = phi->inputs();
for (InputIter k = inputs.begin(); k != inputs.end(); ++k) {
MarkAsUsed(*k);
for (Node* const k : phi->inputs()) {
MarkAsUsed(k);
}
}
}
......@@ -409,11 +408,10 @@ void InstructionSelector::InitializeCallBuffer(Node* call, CallBuffer* buffer,
// arguments require an explicit push instruction before the call and do
// not appear as arguments to the call. Everything else ends up
// as an InstructionOperand argument to the call.
InputIter iter(call->inputs().begin());
auto iter(call->inputs().begin());
int pushed_count = 0;
for (size_t index = 0; index < input_count; ++iter, ++index) {
DCHECK(iter != call->inputs().end());
DCHECK(index == static_cast<size_t>(iter.index()));
DCHECK((*iter)->op()->opcode() != IrOpcode::kFrameState);
if (index == 0) continue; // The first argument (callee) is already done.
InstructionOperand* op =
......
......@@ -126,19 +126,17 @@ void Inlinee::UnifyReturn(JSGraph* jsgraph) {
NodeVector effects(jsgraph->zone());
// Iterate over all control flow predecessors,
// which must be return statements.
InputIter iter = final_merge->inputs().begin();
while (iter != final_merge->inputs().end()) {
Node* input = *iter;
for (Edge edge : final_merge->input_edges()) {
Node* input = edge.to();
switch (input->opcode()) {
case IrOpcode::kReturn:
values.push_back(NodeProperties::GetValueInput(input, 0));
effects.push_back(NodeProperties::GetEffectInput(input));
iter.UpdateToAndIncrement(NodeProperties::GetControlInput(input));
edge.UpdateTo(NodeProperties::GetControlInput(input));
input->RemoveAllInputs();
break;
default:
UNREACHABLE();
++iter;
break;
}
}
......@@ -167,9 +165,8 @@ class CopyVisitor : public NullNodeVisitor {
void Post(Node* original) {
NodeVector inputs(temp_zone_);
for (InputIter it = original->inputs().begin();
it != original->inputs().end(); ++it) {
inputs.push_back(GetCopy(*it));
for (Node* const node : original->inputs()) {
inputs.push_back(GetCopy(node));
}
// Reuse the operator in the copy. This assumes that op lives in a zone
......@@ -242,35 +239,33 @@ void Inlinee::InlineAtCall(JSGraph* jsgraph, Node* call) {
// context, effect, control.
int inliner_inputs = call->op()->ValueInputCount();
// Iterate over all uses of the start node.
UseIter iter = start_->uses().begin();
while (iter != start_->uses().end()) {
Node* use = *iter;
for (Edge edge : start_->use_edges()) {
Node* use = edge.from();
switch (use->opcode()) {
case IrOpcode::kParameter: {
int index = 1 + OpParameter<int>(use->op());
if (index < inliner_inputs && index < inlinee_context_index) {
// There is an input from the call, and the index is a value
// projection but not the context, so rewire the input.
NodeProperties::ReplaceWithValue(*iter, call->InputAt(index));
NodeProperties::ReplaceWithValue(use, call->InputAt(index));
} else if (index == inlinee_context_index) {
// This is the context projection, rewire it to the context from the
// JSFunction object.
NodeProperties::ReplaceWithValue(*iter, context);
NodeProperties::ReplaceWithValue(use, context);
} else if (index < inlinee_context_index) {
// Call has fewer arguments than required, fill with undefined.
NodeProperties::ReplaceWithValue(*iter, jsgraph->UndefinedConstant());
NodeProperties::ReplaceWithValue(use, jsgraph->UndefinedConstant());
} else {
// We got too many arguments, discard for now.
// TODO(sigurds): Fix to treat arguments array correctly.
}
++iter;
break;
}
default:
if (NodeProperties::IsEffectEdge(iter.edge())) {
iter.UpdateToAndIncrement(context);
} else if (NodeProperties::IsControlEdge(iter.edge())) {
iter.UpdateToAndIncrement(control);
if (NodeProperties::IsEffectEdge(edge)) {
edge.UpdateTo(context);
} else if (NodeProperties::IsControlEdge(edge)) {
edge.UpdateTo(control);
} else {
UNREACHABLE();
}
......@@ -455,9 +450,8 @@ class JSCallRuntimeAccessor {
NodeVector inputs(Zone* zone) const {
NodeVector inputs(zone);
for (InputIter it = call_->inputs().begin(); it != call_->inputs().end();
++it) {
inputs.push_back(*it);
for (Node* const node : call_->inputs()) {
inputs.push_back(node);
}
return inputs;
}
......
......@@ -101,7 +101,7 @@ inline int NodeProperties::GetFrameStateIndex(Node* node) {
// -----------------------------------------------------------------------------
// Edge kinds.
inline bool NodeProperties::IsInputRange(Node::Edge edge, int first, int num) {
inline bool NodeProperties::IsInputRange(Edge edge, int first, int num) {
// TODO(titzer): edge.index() is linear time;
// edges maybe need to be marked as value/effect/control.
if (num == 0) return false;
......@@ -109,25 +109,25 @@ inline bool NodeProperties::IsInputRange(Node::Edge edge, int first, int num) {
return first <= index && index < first + num;
}
inline bool NodeProperties::IsValueEdge(Node::Edge edge) {
inline bool NodeProperties::IsValueEdge(Edge edge) {
Node* node = edge.from();
return IsInputRange(edge, FirstValueIndex(node),
node->op()->ValueInputCount());
}
inline bool NodeProperties::IsContextEdge(Node::Edge edge) {
inline bool NodeProperties::IsContextEdge(Edge edge) {
Node* node = edge.from();
return IsInputRange(edge, FirstContextIndex(node),
OperatorProperties::GetContextInputCount(node->op()));
}
inline bool NodeProperties::IsEffectEdge(Node::Edge edge) {
inline bool NodeProperties::IsEffectEdge(Edge edge) {
Node* node = edge.from();
return IsInputRange(edge, FirstEffectIndex(node),
node->op()->EffectInputCount());
}
inline bool NodeProperties::IsControlEdge(Node::Edge edge) {
inline bool NodeProperties::IsControlEdge(Edge edge) {
Node* node = edge.from();
return IsInputRange(edge, FirstControlIndex(node),
node->op()->ControlInputCount());
......@@ -176,13 +176,12 @@ inline void NodeProperties::ReplaceWithValue(Node* node, Node* value,
}
// Requires distinguishing between value and effect edges.
UseIter iter = node->uses().begin();
while (iter != node->uses().end()) {
if (NodeProperties::IsEffectEdge(iter.edge())) {
for (Edge edge : node->use_edges()) {
if (NodeProperties::IsEffectEdge(edge)) {
DCHECK_NE(NULL, effect);
iter = iter.UpdateToAndIncrement(effect);
edge.UpdateTo(effect);
} else {
iter = iter.UpdateToAndIncrement(value);
edge.UpdateTo(value);
}
}
}
......
......@@ -25,10 +25,10 @@ class NodeProperties {
static inline int GetFrameStateIndex(Node* node);
static inline bool IsValueEdge(Node::Edge edge);
static inline bool IsContextEdge(Node::Edge edge);
static inline bool IsEffectEdge(Node::Edge edge);
static inline bool IsControlEdge(Node::Edge edge);
static inline bool IsValueEdge(Edge edge);
static inline bool IsContextEdge(Edge edge);
static inline bool IsEffectEdge(Edge edge);
static inline bool IsControlEdge(Edge edge);
static inline bool IsControl(Node* node);
......@@ -56,7 +56,7 @@ class NodeProperties {
static inline int PastEffectIndex(Node* node);
static inline int PastControlIndex(Node* node);
static inline bool IsInputRange(Node::Edge edge, int first, int count);
static inline bool IsInputRange(Edge edge, int first, int count);
};
} // namespace compiler
......
This diff is collapsed.
......@@ -147,8 +147,8 @@ void Scheduler::UpdatePlacement(Node* node, Placement placement) {
// Reduce the use count of the node's inputs to potentially make them
// schedulable. If all the uses of a node have been scheduled, then the node
// itself can be scheduled.
for (InputIter i = node->inputs().begin(); i != node->inputs().end(); ++i) {
DecrementUnscheduledUseCount(*i, i.index(), i.edge().from());
for (Edge const edge : node->input_edges()) {
DecrementUnscheduledUseCount(edge.to(), edge.index(), edge.from());
}
}
data->placement_ = placement;
......@@ -455,9 +455,8 @@ class CFGBuilder : public ZoneObject {
DCHECK(block != NULL);
// For all of the merge's control inputs, add a goto at the end to the
// merge's basic block.
for (InputIter j = merge->inputs().begin(); j != merge->inputs().end();
++j) {
BasicBlock* predecessor_block = schedule_->block(*j);
for (Node* const j : merge->inputs()) {
BasicBlock* predecessor_block = schedule_->block(j);
TraceConnect(merge, predecessor_block, block);
schedule_->AddGoto(predecessor_block, block);
}
......@@ -1250,9 +1249,7 @@ class ScheduleLateNodeVisitor {
private:
void ProcessQueue(Node* root) {
ZoneQueue<Node*>* queue = &(scheduler_->schedule_queue_);
for (InputIter i = root->inputs().begin(); i != root->inputs().end(); ++i) {
Node* node = *i;
for (Node* node : root->inputs()) {
// Don't schedule coupled nodes on their own.
if (scheduler_->GetPlacement(node) == Scheduler::kCoupled) {
node = NodeProperties::GetControlInput(node);
......@@ -1325,9 +1322,8 @@ class ScheduleLateNodeVisitor {
BasicBlock* GetCommonDominatorOfUses(Node* node) {
BasicBlock* block = NULL;
Node::Uses uses = node->uses();
for (Node::Uses::iterator i = uses.begin(); i != uses.end(); ++i) {
BasicBlock* use_block = GetBlockForUse(i.edge());
for (Edge edge : node->use_edges()) {
BasicBlock* use_block = GetBlockForUse(edge);
block = block == NULL ? use_block : use_block == NULL
? block
: scheduler_->GetCommonDominator(
......@@ -1336,7 +1332,7 @@ class ScheduleLateNodeVisitor {
return block;
}
BasicBlock* GetBlockForUse(Node::Edge edge) {
BasicBlock* GetBlockForUse(Edge edge) {
Node* use = edge.from();
IrOpcode::Value opcode = use->opcode();
if (opcode == IrOpcode::kPhi || opcode == IrOpcode::kEffectPhi) {
......
......@@ -237,19 +237,19 @@ class RepresentationSelector {
// context, effect, and control inputs, assuming that value inputs should have
// {kRepTagged} representation and can observe all output values {kTypeAny}.
void VisitInputs(Node* node) {
InputIter i = node->inputs().begin();
auto i = node->input_edges().begin();
for (int j = node->op()->ValueInputCount(); j > 0; ++i, j--) {
ProcessInput(node, i.index(), kMachAnyTagged); // Value inputs
ProcessInput(node, (*i).index(), kMachAnyTagged); // Value inputs
}
for (int j = OperatorProperties::GetContextInputCount(node->op()); j > 0;
++i, j--) {
ProcessInput(node, i.index(), kMachAnyTagged); // Context inputs
ProcessInput(node, (*i).index(), kMachAnyTagged); // Context inputs
}
for (int j = node->op()->EffectInputCount(); j > 0; ++i, j--) {
Enqueue(*i); // Effect inputs: just visit
Enqueue((*i).to()); // Effect inputs: just visit
}
for (int j = node->op()->ControlInputCount(); j > 0; ++i, j--) {
Enqueue(*i); // Control inputs: just visit
Enqueue((*i).to()); // Control inputs: just visit
}
SetOutput(node, kMachAnyTagged);
}
......@@ -379,21 +379,19 @@ class RepresentationSelector {
}
// Convert inputs to the output representation of this phi.
Node::Inputs inputs = node->inputs();
for (Node::Inputs::iterator iter(inputs.begin()); iter != inputs.end();
++iter, --values) {
for (Edge const edge : node->input_edges()) {
// TODO(titzer): it'd be nice to have distinguished edge kinds here.
ProcessInput(node, iter.index(), values > 0 ? output_type : 0);
ProcessInput(node, edge.index(), values > 0 ? output_type : 0);
values--;
}
} else {
// Propagate {use} of the phi to value inputs, and 0 to control.
Node::Inputs inputs = node->inputs();
MachineType use_type =
static_cast<MachineType>((use & kTypeMask) | output);
for (Node::Inputs::iterator iter(inputs.begin()); iter != inputs.end();
++iter, --values) {
for (Edge const edge : node->input_edges()) {
// TODO(titzer): it'd be nice to have distinguished edge kinds here.
ProcessInput(node, iter.index(), values > 0 ? use_type : 0);
ProcessInput(node, edge.index(), values > 0 ? use_type : 0);
values--;
}
}
}
......
......@@ -176,11 +176,11 @@ void Verifier::Visitor::Pre(Node* node) {
// Verify all successors are projections if multiple value outputs exist.
if (node->op()->ValueOutputCount() > 1) {
Node::Uses uses = node->uses();
for (Node::Uses::iterator it = uses.begin(); it != uses.end(); ++it) {
CHECK(!NodeProperties::IsValueEdge(it.edge()) ||
(*it)->opcode() == IrOpcode::kProjection ||
(*it)->opcode() == IrOpcode::kParameter);
for (Edge edge : node->use_edges()) {
Node* use = edge.from();
CHECK(!NodeProperties::IsValueEdge(edge) ||
use->opcode() == IrOpcode::kProjection ||
use->opcode() == IrOpcode::kParameter);
}
}
......
......@@ -130,11 +130,8 @@ class ControlReducerTester : HandleAndZoneScope {
}
Node* SetSelfReferences(Node* node) {
Node::Inputs inputs = node->inputs();
for (Node::Inputs::iterator iter(inputs.begin()); iter != inputs.end();
++iter) {
Node* input = *iter;
if (input == self) node->ReplaceInput(iter.index(), node);
for (Edge edge : node->input_edges()) {
if (edge.to() == self) node->ReplaceInput(edge.index(), node);
}
return node;
}
......
......@@ -92,10 +92,8 @@ TEST(NodeInputIteratorOne) {
TEST(NodeUseIteratorEmpty) {
GraphTester graph;
Node* n1 = graph.NewNode(&dummy_operator);
Node::Uses::iterator i(n1->uses().begin());
int use_count = 0;
for (; i != n1->uses().end(); ++i) {
Node::Edge edge(i.edge());
for (Edge const edge : n1->use_edges()) {
USE(edge);
use_count++;
}
......@@ -365,31 +363,31 @@ TEST(AppendInputsAndIterator) {
Node* n1 = graph.NewNode(&dummy_operator, n0);
Node* n2 = graph.NewNode(&dummy_operator, n0, n1);
Node::Inputs inputs(n2->inputs());
Node::Inputs::iterator current = inputs.begin();
Node::InputEdges inputs(n2->input_edges());
Node::InputEdges::iterator current = inputs.begin();
CHECK(current != inputs.end());
CHECK(*current == n0);
CHECK((*current).to() == n0);
++current;
CHECK(current != inputs.end());
CHECK(*current == n1);
CHECK((*current).to() == n1);
++current;
CHECK(current == inputs.end());
Node* n3 = graph.NewNode(&dummy_operator);
n2->AppendInput(graph.zone(), n3);
inputs = n2->inputs();
inputs = n2->input_edges();
current = inputs.begin();
CHECK(current != inputs.end());
CHECK(*current == n0);
CHECK_EQ(0, current.index());
CHECK((*current).to() == n0);
CHECK_EQ(0, (*current).index());
++current;
CHECK(current != inputs.end());
CHECK(*current == n1);
CHECK_EQ(1, current.index());
CHECK((*current).to() == n1);
CHECK_EQ(1, (*current).index());
++current;
CHECK(current != inputs.end());
CHECK(*current == n3);
CHECK_EQ(2, current.index());
CHECK((*current).to() == n3);
CHECK_EQ(2, (*current).index());
++current;
CHECK(current == inputs.end());
}
......
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