summaryrefslogtreecommitdiff
path: root/compiler/optimizing/graph_checker.cc
diff options
context:
space:
mode:
authorDavid Brazdil <dbrazdil@google.com>2016-02-16 09:26:07 +0000
committerDavid Brazdil <dbrazdil@google.com>2016-04-04 11:21:20 +0100
commit86ea7eeabe30c98bbe1651a51d03cb89776724e7 (patch)
tree01702f6df5c39925b354a3152dd04289e7d97062 /compiler/optimizing/graph_checker.cc
parent0cb5c86b7021e70cbf584c1455aad1ef383af786 (diff)
Build dominator tree before generating HInstructions
Second CL in the series of merging HGraphBuilder and SsaBuilder. This patch refactors the builders so that dominator tree can be built before any HInstructions are generated. This puts the SsaBuilder removal of HLoadLocals/HStoreLocals straight after HGraphBuilder's HInstruction generation phase. Next CL will therefore be able to merge them. This patch also adds util classes for iterating bytecode and switch tables which allowed to simplify the code. Bug: 27894376 Change-Id: Ic425d298b2e6e7980481ed697230b1a0b7904526
Diffstat (limited to 'compiler/optimizing/graph_checker.cc')
-rw-r--r--compiler/optimizing/graph_checker.cc69
1 files changed, 37 insertions, 32 deletions
diff --git a/compiler/optimizing/graph_checker.cc b/compiler/optimizing/graph_checker.cc
index c790d013b5..9ea4b2dab4 100644
--- a/compiler/optimizing/graph_checker.cc
+++ b/compiler/optimizing/graph_checker.cc
@@ -27,6 +27,21 @@
namespace art {
+static bool IsAllowedToJumpToExitBlock(HInstruction* instruction) {
+ return instruction->IsThrow() || instruction->IsReturn() || instruction->IsReturnVoid();
+}
+
+static bool IsExitTryBoundaryIntoExitBlock(HBasicBlock* block) {
+ if (!block->IsSingleTryBoundary()) {
+ return false;
+ }
+
+ HTryBoundary* boundary = block->GetLastInstruction()->AsTryBoundary();
+ return block->GetPredecessors().size() == 1u &&
+ boundary->GetNormalFlowSuccessor()->IsExitBlock() &&
+ !boundary->IsEntry();
+}
+
void GraphChecker::VisitBasicBlock(HBasicBlock* block) {
current_block_ = block;
@@ -85,28 +100,17 @@ void GraphChecker::VisitBasicBlock(HBasicBlock* block) {
block->GetBlockId()));
}
- // Ensure that only Return(Void) and Throw jump to Exit. An exiting
- // TryBoundary may be between a Throw and the Exit if the Throw is in a try.
+ // Ensure that only Return(Void) and Throw jump to Exit. An exiting TryBoundary
+ // may be between the instructions if the Throw/Return(Void) is in a try block.
if (block->IsExitBlock()) {
for (HBasicBlock* predecessor : block->GetPredecessors()) {
- if (predecessor->IsSingleTryBoundary()
- && !predecessor->GetLastInstruction()->AsTryBoundary()->IsEntry()) {
- HBasicBlock* real_predecessor = predecessor->GetSinglePredecessor();
- HInstruction* last_instruction = real_predecessor->GetLastInstruction();
- if (!last_instruction->IsThrow()) {
- AddError(StringPrintf("Unexpected TryBoundary between %s:%d and Exit.",
- last_instruction->DebugName(),
- last_instruction->GetId()));
- }
- } else {
- HInstruction* last_instruction = predecessor->GetLastInstruction();
- if (!last_instruction->IsReturn()
- && !last_instruction->IsReturnVoid()
- && !last_instruction->IsThrow()) {
- AddError(StringPrintf("Unexpected instruction %s:%d jumps into the exit block.",
- last_instruction->DebugName(),
- last_instruction->GetId()));
- }
+ HInstruction* last_instruction = IsExitTryBoundaryIntoExitBlock(predecessor) ?
+ predecessor->GetSinglePredecessor()->GetLastInstruction() :
+ predecessor->GetLastInstruction();
+ if (!IsAllowedToJumpToExitBlock(last_instruction)) {
+ AddError(StringPrintf("Unexpected instruction %s:%d jumps into the exit block.",
+ last_instruction->DebugName(),
+ last_instruction->GetId()));
}
}
}
@@ -176,16 +180,15 @@ void GraphChecker::VisitBasicBlock(HBasicBlock* block) {
// predecessors). Exceptional edges are synthesized and hence
// not accounted for.
if (block->GetSuccessors().size() > 1) {
- for (HBasicBlock* successor : block->GetNormalSuccessors()) {
- if (successor->IsExitBlock() &&
- block->IsSingleTryBoundary() &&
- block->GetPredecessors().size() == 1u &&
- block->GetSinglePredecessor()->GetLastInstruction()->IsThrow()) {
- // Allowed critical edge Throw->TryBoundary->Exit.
- } else if (successor->GetPredecessors().size() > 1) {
- AddError(StringPrintf("Critical edge between blocks %d and %d.",
- block->GetBlockId(),
- successor->GetBlockId()));
+ if (IsExitTryBoundaryIntoExitBlock(block)) {
+ // Allowed critical edge (Throw/Return/ReturnVoid)->TryBoundary->Exit.
+ } else {
+ for (HBasicBlock* successor : block->GetNormalSuccessors()) {
+ if (successor->GetPredecessors().size() > 1) {
+ AddError(StringPrintf("Critical edge between blocks %d and %d.",
+ block->GetBlockId(),
+ successor->GetBlockId()));
+ }
}
}
}
@@ -505,7 +508,8 @@ void GraphChecker::VisitInvokeStaticOrDirect(HInvokeStaticOrDirect* invoke) {
void GraphChecker::VisitReturn(HReturn* ret) {
VisitInstruction(ret);
- if (!ret->GetBlock()->GetSingleSuccessor()->IsExitBlock()) {
+ HBasicBlock* successor = ret->GetBlock()->GetSingleSuccessor();
+ if (!successor->IsExitBlock() && !IsExitTryBoundaryIntoExitBlock(successor)) {
AddError(StringPrintf("%s:%d does not jump to the exit block.",
ret->DebugName(),
ret->GetId()));
@@ -514,7 +518,8 @@ void GraphChecker::VisitReturn(HReturn* ret) {
void GraphChecker::VisitReturnVoid(HReturnVoid* ret) {
VisitInstruction(ret);
- if (!ret->GetBlock()->GetSingleSuccessor()->IsExitBlock()) {
+ HBasicBlock* successor = ret->GetBlock()->GetSingleSuccessor();
+ if (!successor->IsExitBlock() && !IsExitTryBoundaryIntoExitBlock(successor)) {
AddError(StringPrintf("%s:%d does not jump to the exit block.",
ret->DebugName(),
ret->GetId()));