Commit c56ffe13 authored by Tobias Tebbi's avatar Tobias Tebbi Committed by Commit Bot

[csa][torque] eliminate unnecessary phi nodes in the CSA pipeline

This removes the burden from Torque not to emit unnecessary phis.
This is factored out from the Torque IR CL (https://crrev.com/c/1245766).

Change-Id: I302714250e9ea6367f37613c09caa522d56c151c
Reviewed-on: https://chromium-review.googlesource.com/1254121Reviewed-by: 's avatarDaniel Clifford <danno@chromium.org>
Commit-Queue: Tobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#56312}
parent 0503f195
...@@ -42,48 +42,36 @@ bool BasicBlock::LoopContains(BasicBlock* block) const { ...@@ -42,48 +42,36 @@ bool BasicBlock::LoopContains(BasicBlock* block) const {
block->rpo_number_ < loop_end_->rpo_number_; block->rpo_number_ < loop_end_->rpo_number_;
} }
void BasicBlock::AddSuccessor(BasicBlock* successor) { void BasicBlock::AddSuccessor(BasicBlock* successor) {
successors_.push_back(successor); successors_.push_back(successor);
} }
void BasicBlock::AddPredecessor(BasicBlock* predecessor) { void BasicBlock::AddPredecessor(BasicBlock* predecessor) {
predecessors_.push_back(predecessor); predecessors_.push_back(predecessor);
} }
void BasicBlock::AddNode(Node* node) { nodes_.push_back(node); } void BasicBlock::AddNode(Node* node) { nodes_.push_back(node); }
void BasicBlock::set_control(Control control) { control_ = control; }
void BasicBlock::set_control(Control control) {
control_ = control;
}
void BasicBlock::set_control_input(Node* control_input) { void BasicBlock::set_control_input(Node* control_input) {
control_input_ = control_input; control_input_ = control_input;
} }
void BasicBlock::set_loop_depth(int32_t loop_depth) { void BasicBlock::set_loop_depth(int32_t loop_depth) {
loop_depth_ = loop_depth; loop_depth_ = loop_depth;
} }
void BasicBlock::set_rpo_number(int32_t rpo_number) { void BasicBlock::set_rpo_number(int32_t rpo_number) {
rpo_number_ = rpo_number; rpo_number_ = rpo_number;
} }
void BasicBlock::set_loop_end(BasicBlock* loop_end) { loop_end_ = loop_end; } void BasicBlock::set_loop_end(BasicBlock* loop_end) { loop_end_ = loop_end; }
void BasicBlock::set_loop_header(BasicBlock* loop_header) { void BasicBlock::set_loop_header(BasicBlock* loop_header) {
loop_header_ = loop_header; loop_header_ = loop_header;
} }
// static // static
BasicBlock* BasicBlock::GetCommonDominator(BasicBlock* b1, BasicBlock* b2) { BasicBlock* BasicBlock::GetCommonDominator(BasicBlock* b1, BasicBlock* b2) {
while (b1 != b2) { while (b1 != b2) {
...@@ -141,12 +129,10 @@ std::ostream& operator<<(std::ostream& os, const BasicBlock::Control& c) { ...@@ -141,12 +129,10 @@ std::ostream& operator<<(std::ostream& os, const BasicBlock::Control& c) {
UNREACHABLE(); UNREACHABLE();
} }
std::ostream& operator<<(std::ostream& os, const BasicBlock::Id& id) { std::ostream& operator<<(std::ostream& os, const BasicBlock::Id& id) {
return os << id.ToSize(); return os << id.ToSize();
} }
Schedule::Schedule(Zone* zone, size_t node_count_hint) Schedule::Schedule(Zone* zone, size_t node_count_hint)
: zone_(zone), : zone_(zone),
all_blocks_(zone), all_blocks_(zone),
...@@ -157,7 +143,6 @@ Schedule::Schedule(Zone* zone, size_t node_count_hint) ...@@ -157,7 +143,6 @@ Schedule::Schedule(Zone* zone, size_t node_count_hint)
nodeid_to_block_.reserve(node_count_hint); nodeid_to_block_.reserve(node_count_hint);
} }
BasicBlock* Schedule::block(Node* node) const { BasicBlock* Schedule::block(Node* node) const {
if (node->id() < static_cast<NodeId>(nodeid_to_block_.size())) { if (node->id() < static_cast<NodeId>(nodeid_to_block_.size())) {
return nodeid_to_block_[node->id()]; return nodeid_to_block_[node->id()];
...@@ -165,25 +150,21 @@ BasicBlock* Schedule::block(Node* node) const { ...@@ -165,25 +150,21 @@ BasicBlock* Schedule::block(Node* node) const {
return nullptr; return nullptr;
} }
bool Schedule::IsScheduled(Node* node) { bool Schedule::IsScheduled(Node* node) {
if (node->id() >= nodeid_to_block_.size()) return false; if (node->id() >= nodeid_to_block_.size()) return false;
return nodeid_to_block_[node->id()] != nullptr; return nodeid_to_block_[node->id()] != nullptr;
} }
BasicBlock* Schedule::GetBlockById(BasicBlock::Id block_id) { BasicBlock* Schedule::GetBlockById(BasicBlock::Id block_id) {
DCHECK(block_id.ToSize() < all_blocks_.size()); DCHECK(block_id.ToSize() < all_blocks_.size());
return all_blocks_[block_id.ToSize()]; return all_blocks_[block_id.ToSize()];
} }
bool Schedule::SameBasicBlock(Node* a, Node* b) const { bool Schedule::SameBasicBlock(Node* a, Node* b) const {
BasicBlock* block = this->block(a); BasicBlock* block = this->block(a);
return block != nullptr && block == this->block(b); return block != nullptr && block == this->block(b);
} }
BasicBlock* Schedule::NewBasicBlock() { BasicBlock* Schedule::NewBasicBlock() {
BasicBlock* block = new (zone_) BasicBlock* block = new (zone_)
BasicBlock(zone_, BasicBlock::Id::FromSize(all_blocks_.size())); BasicBlock(zone_, BasicBlock::Id::FromSize(all_blocks_.size()));
...@@ -191,7 +172,6 @@ BasicBlock* Schedule::NewBasicBlock() { ...@@ -191,7 +172,6 @@ BasicBlock* Schedule::NewBasicBlock() {
return block; return block;
} }
void Schedule::PlanNode(BasicBlock* block, Node* node) { void Schedule::PlanNode(BasicBlock* block, Node* node) {
if (FLAG_trace_turbo_scheduler) { if (FLAG_trace_turbo_scheduler) {
StdoutStream{} << "Planning #" << node->id() << ":" StdoutStream{} << "Planning #" << node->id() << ":"
...@@ -202,7 +182,6 @@ void Schedule::PlanNode(BasicBlock* block, Node* node) { ...@@ -202,7 +182,6 @@ void Schedule::PlanNode(BasicBlock* block, Node* node) {
SetBlockForNode(block, node); SetBlockForNode(block, node);
} }
void Schedule::AddNode(BasicBlock* block, Node* node) { void Schedule::AddNode(BasicBlock* block, Node* node) {
if (FLAG_trace_turbo_scheduler) { if (FLAG_trace_turbo_scheduler) {
StdoutStream{} << "Adding #" << node->id() << ":" << node->op()->mnemonic() StdoutStream{} << "Adding #" << node->id() << ":" << node->op()->mnemonic()
...@@ -213,7 +192,6 @@ void Schedule::AddNode(BasicBlock* block, Node* node) { ...@@ -213,7 +192,6 @@ void Schedule::AddNode(BasicBlock* block, Node* node) {
SetBlockForNode(block, node); SetBlockForNode(block, node);
} }
void Schedule::AddGoto(BasicBlock* block, BasicBlock* succ) { void Schedule::AddGoto(BasicBlock* block, BasicBlock* succ) {
DCHECK_EQ(BasicBlock::kNone, block->control()); DCHECK_EQ(BasicBlock::kNone, block->control());
block->set_control(BasicBlock::kGoto); block->set_control(BasicBlock::kGoto);
...@@ -249,7 +227,6 @@ void Schedule::AddCall(BasicBlock* block, Node* call, BasicBlock* success_block, ...@@ -249,7 +227,6 @@ void Schedule::AddCall(BasicBlock* block, Node* call, BasicBlock* success_block,
SetControlInput(block, call); SetControlInput(block, call);
} }
void Schedule::AddBranch(BasicBlock* block, Node* branch, BasicBlock* tblock, void Schedule::AddBranch(BasicBlock* block, Node* branch, BasicBlock* tblock,
BasicBlock* fblock) { BasicBlock* fblock) {
DCHECK_EQ(BasicBlock::kNone, block->control()); DCHECK_EQ(BasicBlock::kNone, block->control());
...@@ -260,7 +237,6 @@ void Schedule::AddBranch(BasicBlock* block, Node* branch, BasicBlock* tblock, ...@@ -260,7 +237,6 @@ void Schedule::AddBranch(BasicBlock* block, Node* branch, BasicBlock* tblock,
SetControlInput(block, branch); SetControlInput(block, branch);
} }
void Schedule::AddSwitch(BasicBlock* block, Node* sw, BasicBlock** succ_blocks, void Schedule::AddSwitch(BasicBlock* block, Node* sw, BasicBlock** succ_blocks,
size_t succ_count) { size_t succ_count) {
DCHECK_EQ(BasicBlock::kNone, block->control()); DCHECK_EQ(BasicBlock::kNone, block->control());
...@@ -272,7 +248,6 @@ void Schedule::AddSwitch(BasicBlock* block, Node* sw, BasicBlock** succ_blocks, ...@@ -272,7 +248,6 @@ void Schedule::AddSwitch(BasicBlock* block, Node* sw, BasicBlock** succ_blocks,
SetControlInput(block, sw); SetControlInput(block, sw);
} }
void Schedule::AddTailCall(BasicBlock* block, Node* input) { void Schedule::AddTailCall(BasicBlock* block, Node* input) {
DCHECK_EQ(BasicBlock::kNone, block->control()); DCHECK_EQ(BasicBlock::kNone, block->control());
block->set_control(BasicBlock::kTailCall); block->set_control(BasicBlock::kTailCall);
...@@ -280,7 +255,6 @@ void Schedule::AddTailCall(BasicBlock* block, Node* input) { ...@@ -280,7 +255,6 @@ void Schedule::AddTailCall(BasicBlock* block, Node* input) {
if (block != end()) AddSuccessor(block, end()); if (block != end()) AddSuccessor(block, end());
} }
void Schedule::AddReturn(BasicBlock* block, Node* input) { void Schedule::AddReturn(BasicBlock* block, Node* input) {
DCHECK_EQ(BasicBlock::kNone, block->control()); DCHECK_EQ(BasicBlock::kNone, block->control());
block->set_control(BasicBlock::kReturn); block->set_control(BasicBlock::kReturn);
...@@ -288,7 +262,6 @@ void Schedule::AddReturn(BasicBlock* block, Node* input) { ...@@ -288,7 +262,6 @@ void Schedule::AddReturn(BasicBlock* block, Node* input) {
if (block != end()) AddSuccessor(block, end()); if (block != end()) AddSuccessor(block, end());
} }
void Schedule::AddDeoptimize(BasicBlock* block, Node* input) { void Schedule::AddDeoptimize(BasicBlock* block, Node* input) {
DCHECK_EQ(BasicBlock::kNone, block->control()); DCHECK_EQ(BasicBlock::kNone, block->control());
block->set_control(BasicBlock::kDeoptimize); block->set_control(BasicBlock::kDeoptimize);
...@@ -296,7 +269,6 @@ void Schedule::AddDeoptimize(BasicBlock* block, Node* input) { ...@@ -296,7 +269,6 @@ void Schedule::AddDeoptimize(BasicBlock* block, Node* input) {
if (block != end()) AddSuccessor(block, end()); if (block != end()) AddSuccessor(block, end());
} }
void Schedule::AddThrow(BasicBlock* block, Node* input) { void Schedule::AddThrow(BasicBlock* block, Node* input) {
DCHECK_EQ(BasicBlock::kNone, block->control()); DCHECK_EQ(BasicBlock::kNone, block->control());
block->set_control(BasicBlock::kThrow); block->set_control(BasicBlock::kThrow);
...@@ -304,7 +276,6 @@ void Schedule::AddThrow(BasicBlock* block, Node* input) { ...@@ -304,7 +276,6 @@ void Schedule::AddThrow(BasicBlock* block, Node* input) {
if (block != end()) AddSuccessor(block, end()); if (block != end()) AddSuccessor(block, end());
} }
void Schedule::InsertBranch(BasicBlock* block, BasicBlock* end, Node* branch, void Schedule::InsertBranch(BasicBlock* block, BasicBlock* end, Node* branch,
BasicBlock* tblock, BasicBlock* fblock) { BasicBlock* tblock, BasicBlock* fblock) {
DCHECK_NE(BasicBlock::kNone, block->control()); DCHECK_NE(BasicBlock::kNone, block->control());
...@@ -320,7 +291,6 @@ void Schedule::InsertBranch(BasicBlock* block, BasicBlock* end, Node* branch, ...@@ -320,7 +291,6 @@ void Schedule::InsertBranch(BasicBlock* block, BasicBlock* end, Node* branch,
SetControlInput(block, branch); SetControlInput(block, branch);
} }
void Schedule::InsertSwitch(BasicBlock* block, BasicBlock* end, Node* sw, void Schedule::InsertSwitch(BasicBlock* block, BasicBlock* end, Node* sw,
BasicBlock** succ_blocks, size_t succ_count) { BasicBlock** succ_blocks, size_t succ_count) {
DCHECK_NE(BasicBlock::kNone, block->control()); DCHECK_NE(BasicBlock::kNone, block->control());
...@@ -343,7 +313,7 @@ void Schedule::EnsureCFGWellFormedness() { ...@@ -343,7 +313,7 @@ void Schedule::EnsureCFGWellFormedness() {
BasicBlockVector all_blocks_copy(all_blocks_); BasicBlockVector all_blocks_copy(all_blocks_);
// Insert missing split edge blocks. // Insert missing split edge blocks.
for (auto block : all_blocks_copy) { for (BasicBlock* block : all_blocks_copy) {
if (block->PredecessorCount() > 1) { if (block->PredecessorCount() > 1) {
if (block != end_) { if (block != end_) {
EnsureSplitEdgeForm(block); EnsureSplitEdgeForm(block);
...@@ -351,24 +321,36 @@ void Schedule::EnsureCFGWellFormedness() { ...@@ -351,24 +321,36 @@ void Schedule::EnsureCFGWellFormedness() {
if (block->deferred()) { if (block->deferred()) {
EnsureDeferredCodeSingleEntryPoint(block); EnsureDeferredCodeSingleEntryPoint(block);
} }
} else {
EliminateNoopPhiNodes(block);
} }
} }
}
void Schedule::EliminateNoopPhiNodes(BasicBlock* block) { EliminateNoopPhiNodes();
// Ensure that useless phi nodes in blocks that only have a single predecessor }
// -- which can happen with the automatically generated code in the CSA and
// torque -- are pruned. void Schedule::EliminateNoopPhiNodes() {
if (block->PredecessorCount() == 1) { bool reached_fixed_point = false;
for (size_t i = 0; i < block->NodeCount();) { while (!reached_fixed_point) {
Node* node = block->NodeAt(i); reached_fixed_point = true;
if (node->opcode() == IrOpcode::kPhi) { for (BasicBlock* block : all_blocks_) {
node->ReplaceUses(node->InputAt(0)); int predecessor_count = static_cast<int>(block->PredecessorCount());
block->RemoveNode(block->begin() + i); for (size_t node_pos = 0; node_pos < block->NodeCount(); ++node_pos) {
} else { Node* node = block->NodeAt(node_pos);
++i; if (node->opcode() == IrOpcode::kPhi) {
Node* first_input = node->InputAt(0);
bool inputs_equal = true;
for (int i = 1; i < predecessor_count; ++i) {
Node* input = node->InputAt(i);
if (input != first_input && input != node) {
inputs_equal = false;
break;
}
}
if (!inputs_equal) continue;
node->ReplaceUses(first_input);
block->RemoveNode(block->begin() + node_pos);
--node_pos;
reached_fixed_point = false;
}
} }
} }
} }
...@@ -481,7 +463,6 @@ void Schedule::AddSuccessor(BasicBlock* block, BasicBlock* succ) { ...@@ -481,7 +463,6 @@ void Schedule::AddSuccessor(BasicBlock* block, BasicBlock* succ) {
succ->AddPredecessor(block); succ->AddPredecessor(block);
} }
void Schedule::MoveSuccessors(BasicBlock* from, BasicBlock* to) { void Schedule::MoveSuccessors(BasicBlock* from, BasicBlock* to) {
for (BasicBlock* const successor : from->successors()) { for (BasicBlock* const successor : from->successors()) {
to->AddSuccessor(successor); to->AddSuccessor(successor);
...@@ -492,13 +473,11 @@ void Schedule::MoveSuccessors(BasicBlock* from, BasicBlock* to) { ...@@ -492,13 +473,11 @@ void Schedule::MoveSuccessors(BasicBlock* from, BasicBlock* to) {
from->ClearSuccessors(); from->ClearSuccessors();
} }
void Schedule::SetControlInput(BasicBlock* block, Node* node) { void Schedule::SetControlInput(BasicBlock* block, Node* node) {
block->set_control_input(node); block->set_control_input(node);
SetBlockForNode(block, node); SetBlockForNode(block, node);
} }
void Schedule::SetBlockForNode(BasicBlock* block, Node* node) { void Schedule::SetBlockForNode(BasicBlock* block, Node* node) {
if (node->id() >= nodeid_to_block_.size()) { if (node->id() >= nodeid_to_block_.size()) {
nodeid_to_block_.resize(node->id() + 1); nodeid_to_block_.resize(node->id() + 1);
...@@ -506,7 +485,6 @@ void Schedule::SetBlockForNode(BasicBlock* block, Node* node) { ...@@ -506,7 +485,6 @@ void Schedule::SetBlockForNode(BasicBlock* block, Node* node) {
nodeid_to_block_[node->id()] = block; nodeid_to_block_[node->id()] = block;
} }
std::ostream& operator<<(std::ostream& os, const Schedule& s) { std::ostream& operator<<(std::ostream& os, const Schedule& s) {
for (BasicBlock* block : for (BasicBlock* block :
((s.RpoBlockCount() == 0) ? *s.all_blocks() : *s.rpo_order())) { ((s.RpoBlockCount() == 0) ? *s.all_blocks() : *s.rpo_order())) {
......
...@@ -166,12 +166,12 @@ class V8_EXPORT_PRIVATE BasicBlock final ...@@ -166,12 +166,12 @@ class V8_EXPORT_PRIVATE BasicBlock final
BasicBlock* loop_header_; // Pointer to dominating loop header basic block, BasicBlock* loop_header_; // Pointer to dominating loop header basic block,
// nullptr if none. For loop headers, this points to // nullptr if none. For loop headers, this points to
// enclosing loop header. // enclosing loop header.
BasicBlock* loop_end_; // end of the loop, if this block is a loop header. BasicBlock* loop_end_; // end of the loop, if this block is a loop header.
int32_t loop_depth_; // loop nesting, 0 is top-level int32_t loop_depth_; // loop nesting, 0 is top-level
Control control_; // Control at the end of the block. Control control_; // Control at the end of the block.
Node* control_input_; // Input value for control. Node* control_input_; // Input value for control.
NodeVector nodes_; // nodes of this block in forward order. NodeVector nodes_; // nodes of this block in forward order.
BasicBlockVector successors_; BasicBlockVector successors_;
BasicBlockVector predecessors_; BasicBlockVector predecessors_;
...@@ -187,7 +187,6 @@ std::ostream& operator<<(std::ostream&, const BasicBlock&); ...@@ -187,7 +187,6 @@ std::ostream& operator<<(std::ostream&, const BasicBlock&);
std::ostream& operator<<(std::ostream&, const BasicBlock::Control&); std::ostream& operator<<(std::ostream&, const BasicBlock::Control&);
std::ostream& operator<<(std::ostream&, const BasicBlock::Id&); std::ostream& operator<<(std::ostream&, const BasicBlock::Id&);
// A schedule represents the result of assigning nodes to basic blocks // A schedule represents the result of assigning nodes to basic blocks
// and ordering them within basic blocks. Prior to computing a schedule, // and ordering them within basic blocks. Prior to computing a schedule,
// a graph has no notion of control flow ordering other than that induced // a graph has no notion of control flow ordering other than that induced
...@@ -272,12 +271,13 @@ class V8_EXPORT_PRIVATE Schedule final : public NON_EXPORTED_BASE(ZoneObject) { ...@@ -272,12 +271,13 @@ class V8_EXPORT_PRIVATE Schedule final : public NON_EXPORTED_BASE(ZoneObject) {
friend class BasicBlockInstrumentor; friend class BasicBlockInstrumentor;
friend class RawMachineAssembler; friend class RawMachineAssembler;
// Ensure properties of the CFG assumed by further stages. // For CSA/Torque: Ensure properties of the CFG assumed by further stages.
void EnsureCFGWellFormedness(); void EnsureCFGWellFormedness();
// Eliminates no-op phi nodes added for blocks that only have a single // For CSA/Torque: Eliminates unnecessary phi nodes, including phis with a
// predecessor. This ensures the property required for SSA deconstruction that // single input. The latter is necessary to ensure the property required for
// the target block of a control flow split has no phis. // SSA deconstruction that the target block of a control flow split has no
void EliminateNoopPhiNodes(BasicBlock* block); // phis.
void EliminateNoopPhiNodes();
// Ensure split-edge form for a hand-assembled schedule. // Ensure split-edge form for a hand-assembled schedule.
void EnsureSplitEdgeForm(BasicBlock* block); void EnsureSplitEdgeForm(BasicBlock* block);
// Ensure entry into a deferred block happens from a single hot block. // Ensure entry into a deferred block happens from a single hot block.
...@@ -294,9 +294,9 @@ class V8_EXPORT_PRIVATE Schedule final : public NON_EXPORTED_BASE(ZoneObject) { ...@@ -294,9 +294,9 @@ class V8_EXPORT_PRIVATE Schedule final : public NON_EXPORTED_BASE(ZoneObject) {
void SetBlockForNode(BasicBlock* block, Node* node); void SetBlockForNode(BasicBlock* block, Node* node);
Zone* zone_; Zone* zone_;
BasicBlockVector all_blocks_; // All basic blocks in the schedule. BasicBlockVector all_blocks_; // All basic blocks in the schedule.
BasicBlockVector nodeid_to_block_; // Map from node to containing block. BasicBlockVector nodeid_to_block_; // Map from node to containing block.
BasicBlockVector rpo_order_; // Reverse-post-order block list. BasicBlockVector rpo_order_; // Reverse-post-order block list.
BasicBlock* start_; BasicBlock* start_;
BasicBlock* end_; BasicBlock* 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