[MLInliner] Don't inline call sites in unreachable basic blocks
authorMircea Trofin <mtrofin@google.com>
Wed, 15 Jun 2022 14:32:55 +0000 (07:32 -0700)
committerMircea Trofin <mtrofin@google.com>
Thu, 16 Jun 2022 16:14:22 +0000 (09:14 -0700)
This requires DominatorTree be updated, which we do in the ml inliner
case, but not in the default case, and the cost of doing so is
noticeable to compile time for the latter[1]. So the patch only affects
the ML inliner.

[1] https://llvm-compile-time-tracker.com/compare.php?from=9fc0aa45e3312944431ba7e1ca0cec99c613992b&to=7af461b1ce0d9138211ef5f883f35d5b9ddf47be&stat=wall-time

Differential Revision: https://reviews.llvm.org/D127899

llvm/include/llvm/Analysis/MLInlineAdvisor.h
llvm/lib/Analysis/MLInlineAdvisor.cpp
llvm/test/Transforms/Inline/ML/skip-unreachable.ll [new file with mode: 0644]

index 290726e..00e8d7d 100644 (file)
@@ -65,7 +65,8 @@ protected:
 
 private:
   int64_t getModuleIRSize() const;
-
+  std::unique_ptr<InlineAdvice>
+  getSkipAdviceIfUnreachableCallsite(CallBase &CB);
   void print(raw_ostream &OS) const override;
 
   mutable DenseMap<const Function *, FunctionPropertiesInfo> FPICache;
index edc8eac..1a7cdc3 100644 (file)
@@ -277,6 +277,9 @@ FunctionPropertiesInfo &MLInlineAdvisor::getCachedFPI(Function &F) const {
 }
 
 std::unique_ptr<InlineAdvice> MLInlineAdvisor::getAdviceImpl(CallBase &CB) {
+  if (auto Skip = getSkipAdviceIfUnreachableCallsite(CB))
+    return Skip;
+
   auto &Caller = *CB.getCaller();
   auto &Callee = *CB.getCalledFunction();
 
@@ -376,9 +379,19 @@ MLInlineAdvisor::getAdviceFromModel(CallBase &CB,
       this, CB, ORE, static_cast<bool>(ModelRunner->evaluate<int64_t>()));
 }
 
+std::unique_ptr<InlineAdvice>
+MLInlineAdvisor::getSkipAdviceIfUnreachableCallsite(CallBase &CB) {
+  if (!FAM.getResult<DominatorTreeAnalysis>(*CB.getCaller())
+           .isReachableFromEntry(CB.getParent()))
+    return std::make_unique<InlineAdvice>(this, CB, getCallerORE(CB), false);
+  return nullptr;
+}
+
 std::unique_ptr<InlineAdvice> MLInlineAdvisor::getMandatoryAdvice(CallBase &CB,
                                                                   bool Advice) {
   // Make sure we track inlinings in all cases - mandatory or not.
+  if (auto Skip = getSkipAdviceIfUnreachableCallsite(CB))
+    return Skip;
   if (Advice && !ForceStop)
     return getMandatoryAdviceImpl(CB);
 
diff --git a/llvm/test/Transforms/Inline/ML/skip-unreachable.ll b/llvm/test/Transforms/Inline/ML/skip-unreachable.ll
new file mode 100644 (file)
index 0000000..47a75c3
--- /dev/null
@@ -0,0 +1,46 @@
+; Test skipping inlining when the callsite is unreachable (for both mandatory
+; and non-mandatory cases)
+; REQUIRES: llvm_inliner_model_autogenerated
+; RUN: opt -passes=inliner-ml-advisor-release -S < %s | FileCheck %s --check-prefix=CHECK
+
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-grtev4-linux-gnu"
+
+; Mandatory case
+define i32 @f1() {
+entry:
+  br label %exit
+some_bb:  ; unreachable - has no predecessors
+  %r = call i32 @f2()
+  br label %exit
+exit:
+  ret i32 1
+}
+
+define i32 @f2() #0 {
+  ret i32 2
+}
+
+; Non-mandatory case
+define i32 @f3() {
+entry:
+  br label %exit
+some_bb:  ; unreachable - has no predecessors
+  %r = call i32 @f4()
+  br label %exit
+exit:
+  ret i32 1
+}
+
+define i32 @f4() {
+  ret i32 2
+}
+
+attributes #0 = { alwaysinline }
+
+; CHECK-LABEL: @f1
+; CHECK-LABEL: some_bb
+; CHECK-NEXT: call i32 @f2
+; CHECK-LABEL: @f3
+; CHECK-LABEL: some_bb
+; CHECK-NEXT: call i32 @f4