From 8efb1a62b67fd1e6866a4b7e465afc11770bb082 Mon Sep 17 00:00:00 2001 From: Santiago Aboy Solanes Date: Fri, 24 Jun 2022 11:16:35 +0100 Subject: Compiler implementation of try catch inlining Notable changes: 1) Wiring of the graph now allows for inlinees graph ending in TryBoundary, or Goto in some special cases. 2) Building a graph with try catch for inlining may add an extra Goto block. 3) Oat version bump. 4) Reduced kMaximumNumberOfCumulatedDexRegisters from 32 to 20. Bug: 227283224 Test: art/test/testrunner/testrunner.py --host --64 --optimizing -b Change-Id: Ic2fd956de24b72d1de29b4cd3d0b2a1ddab231d8 --- compiler/optimizing/builder.cc | 53 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 2 deletions(-) (limited to 'compiler/optimizing/builder.cc') diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc index e7826bbba3..b28c2d9592 100644 --- a/compiler/optimizing/builder.cc +++ b/compiler/optimizing/builder.cc @@ -96,7 +96,50 @@ bool HGraphBuilder::SkipCompilation(size_t number_of_branches) { return false; } -GraphAnalysisResult HGraphBuilder::BuildGraph() { +static bool NeedsExtraGotoBlock(HBasicBlock* block) { + if (!block->IsSingleTryBoundary()) { + return false; + } + + const HTryBoundary* boundary = block->GetLastInstruction()->AsTryBoundary(); + DCHECK(boundary->GetNormalFlowSuccessor()->IsExitBlock()); + DCHECK(!boundary->IsEntry()); + + const HInstruction* last_instruction = block->GetSinglePredecessor()->GetLastInstruction(); + DCHECK(last_instruction->IsReturn() || + last_instruction->IsReturnVoid() || + last_instruction->IsThrow()); + + return !last_instruction->IsThrow(); +} + +void HGraphBuilder::MaybeAddExtraGotoBlocks() { + if (graph_->GetExitBlock() == nullptr) return; + + bool added_block = false; + for (size_t pred = 0, size = graph_->GetExitBlock()->GetPredecessors().size(); pred < size; + ++pred) { + HBasicBlock* predecessor = graph_->GetExitBlock()->GetPredecessors()[pred]; + if (NeedsExtraGotoBlock(predecessor)) { + added_block = true; + graph_->SplitEdge(predecessor, graph_->GetExitBlock()) + ->AddInstruction(new (graph_->GetAllocator()) HGoto(predecessor->GetDexPc())); + } + } + + // TODO(solanes): Avoid recomputing the full dominator tree by manually updating the relevant + // information (loop information, dominance, try catch information). + if (added_block) { + DCHECK(!graph_->HasIrreducibleLoops()) + << "Recomputing loop information in graphs with irreducible loops " + << "is unsupported, as it could lead to loop header changes"; + graph_->ClearLoopInformation(); + graph_->ClearDominanceInformation(); + graph_->BuildDominatorTree(); + } +} + +GraphAnalysisResult HGraphBuilder::BuildGraph(bool build_for_inline) { DCHECK(code_item_accessor_.HasCodeItem()); DCHECK(graph_->GetBlocks().empty()); @@ -147,7 +190,13 @@ GraphAnalysisResult HGraphBuilder::BuildGraph() { return kAnalysisInvalidBytecode; } - // 5) Type the graph and eliminate dead/redundant phis. + // 5) When inlining, we want to add a Goto block if we have Return/ReturnVoid->TryBoundary->Exit + // since we will have Return/ReturnVoid->TryBoundary->`continue to normal execution` once inlined. + if (build_for_inline) { + MaybeAddExtraGotoBlocks(); + } + + // 6) Type the graph and eliminate dead/redundant phis. return ssa_builder.BuildSsa(); } -- cgit v1.2.3-59-g8ed1b