diff --git a/llvm/include/llvm/Analysis/MLInlineAdvisor.h b/llvm/include/llvm/Analysis/MLInlineAdvisor.h --- a/llvm/include/llvm/Analysis/MLInlineAdvisor.h +++ b/llvm/include/llvm/Analysis/MLInlineAdvisor.h @@ -65,7 +65,8 @@ private: int64_t getModuleIRSize() const; - + std::unique_ptr + getSkipAdviceIfUnreachableCallsite(CallBase &CB); void print(raw_ostream &OS) const override; mutable DenseMap FPICache; diff --git a/llvm/lib/Analysis/MLInlineAdvisor.cpp b/llvm/lib/Analysis/MLInlineAdvisor.cpp --- a/llvm/lib/Analysis/MLInlineAdvisor.cpp +++ b/llvm/lib/Analysis/MLInlineAdvisor.cpp @@ -277,6 +277,9 @@ } std::unique_ptr MLInlineAdvisor::getAdviceImpl(CallBase &CB) { + if (auto Skip = getSkipAdviceIfUnreachableCallsite(CB)) + return Skip; + auto &Caller = *CB.getCaller(); auto &Callee = *CB.getCalledFunction(); @@ -376,9 +379,19 @@ this, CB, ORE, static_cast(ModelRunner->evaluate())); } +std::unique_ptr +MLInlineAdvisor::getSkipAdviceIfUnreachableCallsite(CallBase &CB) { + if (!FAM.getResult(*CB.getCaller()) + .isReachableFromEntry(CB.getParent())) + return std::make_unique(this, CB, getCallerORE(CB), false); + return nullptr; +} + std::unique_ptr 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 --- /dev/null +++ b/llvm/test/Transforms/Inline/ML/skip-unreachable.ll @@ -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