summaryrefslogtreecommitdiff
path: root/compiler/optimizing/nodes.cc
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/optimizing/nodes.cc')
-rw-r--r--compiler/optimizing/nodes.cc66
1 files changed, 55 insertions, 11 deletions
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc
index a6390af1f2..881f9ec117 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -189,15 +189,20 @@ void HGraph::TransformToSsa() {
ssa_builder.BuildSsa();
}
-void HGraph::SplitCriticalEdge(HBasicBlock* block, HBasicBlock* successor) {
- // Insert a new node between `block` and `successor` to split the
- // critical edge.
+HBasicBlock* HGraph::SplitEdge(HBasicBlock* block, HBasicBlock* successor) {
HBasicBlock* new_block = new (arena_) HBasicBlock(this, successor->GetDexPc());
AddBlock(new_block);
- new_block->AddInstruction(new (arena_) HGoto());
// Use `InsertBetween` to ensure the predecessor index and successor index of
// `block` and `successor` are preserved.
new_block->InsertBetween(block, successor);
+ return new_block;
+}
+
+void HGraph::SplitCriticalEdge(HBasicBlock* block, HBasicBlock* successor) {
+ // Insert a new node between `block` and `successor` to split the
+ // critical edge.
+ HBasicBlock* new_block = SplitEdge(block, successor);
+ new_block->AddInstruction(new (arena_) HGoto());
if (successor->IsLoopHeader()) {
// If we split at a back edge boundary, make the new block the back edge.
HLoopInformation* info = successor->GetLoopInformation();
@@ -1019,6 +1024,35 @@ void HInstruction::MoveBefore(HInstruction* cursor) {
}
}
+HBasicBlock* HBasicBlock::SplitBefore(HInstruction* cursor) {
+ DCHECK(!graph_->IsInSsaForm()) << "Support for SSA form not implemented";
+ DCHECK_EQ(cursor->GetBlock(), this);
+
+ HBasicBlock* new_block = new (GetGraph()->GetArena()) HBasicBlock(GetGraph(), GetDexPc());
+ new_block->instructions_.first_instruction_ = cursor;
+ new_block->instructions_.last_instruction_ = instructions_.last_instruction_;
+ instructions_.last_instruction_ = cursor->previous_;
+ if (cursor->previous_ == nullptr) {
+ instructions_.first_instruction_ = nullptr;
+ } else {
+ cursor->previous_->next_ = nullptr;
+ cursor->previous_ = nullptr;
+ }
+
+ new_block->instructions_.SetBlockOfInstructions(new_block);
+ AddInstruction(new (GetGraph()->GetArena()) HGoto());
+
+ for (size_t i = 0, e = GetSuccessors().Size(); i < e; ++i) {
+ HBasicBlock* successor = GetSuccessors().Get(i);
+ new_block->successors_.Add(successor);
+ successor->predecessors_.Put(successor->GetPredecessorIndexOf(this), new_block);
+ }
+ successors_.Reset();
+ AddSuccessor(new_block);
+
+ return new_block;
+}
+
HBasicBlock* HBasicBlock::SplitAfter(HInstruction* cursor) {
DCHECK(!cursor->IsControlFlow());
DCHECK_NE(instructions_.last_instruction_, cursor);
@@ -1048,14 +1082,24 @@ HBasicBlock* HBasicBlock::SplitAfter(HInstruction* cursor) {
return new_block;
}
+bool HBasicBlock::IsExceptionalSuccessor(size_t idx) const {
+ return !GetInstructions().IsEmpty()
+ && GetLastInstruction()->IsTryBoundary()
+ && GetLastInstruction()->AsTryBoundary()->IsExceptionalSuccessor(idx);
+}
+
+static bool HasOnlyOneInstruction(const HBasicBlock& block) {
+ return block.GetPhis().IsEmpty()
+ && !block.GetInstructions().IsEmpty()
+ && block.GetFirstInstruction() == block.GetLastInstruction();
+}
+
bool HBasicBlock::IsSingleGoto() const {
- HLoopInformation* loop_info = GetLoopInformation();
- DCHECK(EndsWithControlFlowInstruction());
- return GetPhis().IsEmpty()
- && GetFirstInstruction() == GetLastInstruction()
- && GetLastInstruction()->IsGoto()
- // Back edges generate the suspend check.
- && (loop_info == nullptr || !loop_info->IsBackEdge(*this));
+ return HasOnlyOneInstruction(*this) && GetLastInstruction()->IsGoto();
+}
+
+bool HBasicBlock::IsSingleTryBoundary() const {
+ return HasOnlyOneInstruction(*this) && GetLastInstruction()->IsTryBoundary();
}
bool HBasicBlock::EndsWithControlFlowInstruction() const {