Add irreducible loop check in CanInlineBody

In aosp/2335809 we moved splitting the critical edge (aka adding
the extra goto) from the builder to InlineInto. We need to
also move the irreducible loop check from there to inliner.cc.

Bug: 262725735
Fixes: 262725735
Test: dex2oat compiling the apps in the bug
Test: art/test/testrunner/testrunner.py --host --64 --optimizing -b
Change-Id: I94eebfb21cd94b1199ba996d458b897b7917840e
diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc
index 2645cf1..3992ff4 100644
--- a/compiler/optimizing/inliner.cc
+++ b/compiler/optimizing/inliner.cc
@@ -1896,11 +1896,25 @@
   bool has_one_return = false;
   for (HBasicBlock* predecessor : exit_block->GetPredecessors()) {
     const HInstruction* last_instruction = predecessor->GetLastInstruction();
-    // On inlinees, we can have Throw -> TryBoundary -> Exit. To check for the actual last
-    // instruction, we have to skip it.
+    // On inlinees, we can have Return/ReturnVoid/Throw -> TryBoundary -> Exit. To check for the
+    // actual last instruction, we have to skip the TryBoundary instruction.
     if (last_instruction->IsTryBoundary()) {
       predecessor = predecessor->GetSinglePredecessor();
       last_instruction = predecessor->GetLastInstruction();
+
+      // If the last instruction chain is Return/ReturnVoid -> TryBoundary -> Exit we will have to
+      // split a critical edge in InlineInto and might recompute loop information, which is
+      // unsupported for irreducible loops.
+      if (!last_instruction->IsThrow() && graph_->HasIrreducibleLoops()) {
+        DCHECK(last_instruction->IsReturn() || last_instruction->IsReturnVoid());
+        // TODO(ngeoffray): Support re-computing loop information to graphs with
+        // irreducible loops?
+        LOG_FAIL(stats_, MethodCompilationStat::kNotInlinedIrreducibleLoopCaller)
+            << "Method " << resolved_method->PrettyMethod()
+            << " could not be inlined because we will have to recompute the loop information and"
+            << " the caller has irreducible loops";
+        return false;
+      }
     }
 
     if (last_instruction->IsThrow()) {
@@ -1914,9 +1928,10 @@
       } else if (graph_->HasIrreducibleLoops()) {
         // TODO(ngeoffray): Support re-computing loop information to graphs with
         // irreducible loops?
-        VLOG(compiler) << "Method " << resolved_method->PrettyMethod()
-                       << " could not be inlined because one branch always throws and"
-                       << " caller has irreducible loops";
+        LOG_FAIL(stats_, MethodCompilationStat::kNotInlinedIrreducibleLoopCaller)
+            << "Method " << resolved_method->PrettyMethod()
+            << " could not be inlined because one branch always throws and"
+            << " the caller has irreducible loops";
         return false;
       }
     } else {
@@ -1952,7 +1967,7 @@
       if (block->GetLoopInformation()->IsIrreducible()) {
         // Don't inline methods with irreducible loops, they could prevent some
         // optimizations to run.
-        LOG_FAIL(stats_, MethodCompilationStat::kNotInlinedIrreducibleLoop)
+        LOG_FAIL(stats_, MethodCompilationStat::kNotInlinedIrreducibleLoopCallee)
             << "Method " << resolved_method->PrettyMethod()
             << " could not be inlined because it contains an irreducible loop";
         return false;
diff --git a/compiler/optimizing/optimizing_compiler_stats.h b/compiler/optimizing/optimizing_compiler_stats.h
index c741b02..100441a 100644
--- a/compiler/optimizing/optimizing_compiler_stats.h
+++ b/compiler/optimizing/optimizing_compiler_stats.h
@@ -92,7 +92,8 @@
   kNotInlinedEnvironmentBudget,
   kNotInlinedInstructionBudget,
   kNotInlinedLoopWithoutExit,
-  kNotInlinedIrreducibleLoop,
+  kNotInlinedIrreducibleLoopCallee,
+  kNotInlinedIrreducibleLoopCaller,
   kNotInlinedAlwaysThrows,
   kNotInlinedInfiniteLoop,
   kNotInlinedTryCatchCallee,