Index: lib/Transforms/IPO/SampleProfile.cpp =================================================================== --- lib/Transforms/IPO/SampleProfile.cpp +++ lib/Transforms/IPO/SampleProfile.cpp @@ -28,9 +28,11 @@ #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/StringRef.h" #include "llvm/Analysis/AssumptionCache.h" +#include "llvm/Analysis/InlineCost.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/OptimizationDiagnosticInfo.h" #include "llvm/Analysis/PostDominators.h" +#include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DebugInfo.h" #include "llvm/IR/DiagnosticInfo.h" @@ -81,9 +83,14 @@ cl::desc("Emit a warning if less than N% of samples in the input profile " "are matched to the IR.")); static cl::opt SampleProfileHotThreshold( - "sample-profile-inline-hot-threshold", cl::init(0.1), cl::value_desc("N"), + "sample-profile-hot-threshold", cl::init(0.1), cl::value_desc("N"), cl::desc("Inlined functions that account for more than N% of all samples " "collected in the parent function, will be inlined again.")); +static cl::opt SampleProfileInlineHotThreshold( + "sample-profile-inline-hot-threshold", cl::init(100000), + cl::value_desc("N"), + cl::desc("Inline line threshold for hot functions that has been inlined in " + "the profiling binary.")); namespace { typedef DenseMap BlockWeightMap; @@ -148,10 +155,12 @@ public: SampleProfileLoader( StringRef Name, - std::function GetAssumptionCache) + std::function GetAssumptionCache, + std::function GetTargetTransformInfo) : DT(nullptr), PDT(nullptr), LI(nullptr), GetAC(GetAssumptionCache), - Reader(), Samples(nullptr), Filename(Name), ProfileIsValid(false), - TotalCollectedSamples(0), ORE(nullptr) {} + GetTTI(GetTargetTransformInfo), Reader(), Samples(nullptr), + Filename(Name), ProfileIsValid(false), TotalCollectedSamples(0), + ORE(nullptr) {} bool doInitialization(Module &M); bool runOnModule(Module &M, ModuleAnalysisManager *AM); @@ -225,6 +234,7 @@ std::unique_ptr LI; std::function GetAC; + std::function GetTTI; /// \brief Predecessors for each basic block in the CFG. BlockEdgeMap Predecessors; @@ -265,8 +275,11 @@ : ModulePass(ID), SampleLoader(Name, [&](Function &F) -> AssumptionCache & { return ACT->getAssumptionCache(F); + }, + [&](Function &F) -> TargetTransformInfo & { + return TTIWP->getTTI(F); }), - ACT(nullptr) { + ACT(nullptr), TTIWP(nullptr) { initializeSampleProfileLoaderLegacyPassPass( *PassRegistry::getPassRegistry()); } @@ -281,11 +294,13 @@ void getAnalysisUsage(AnalysisUsage &AU) const override { AU.addRequired(); + AU.addRequired(); } private: SampleProfileLoader SampleLoader; AssumptionCacheTracker *ACT; + TargetTransformInfoWrapperPass *TTIWP; }; /// Return true if the given callsite is hot wrt to its caller. @@ -747,9 +762,14 @@ Samples->getTotalSamples() * SampleProfileHotThreshold / 100); continue; } + CallSite CS(DI); + if (!getInlineCost(CS, getInlineParams(SampleProfileInlineHotThreshold), + GetTTI(*CalledFunction), GetAC, None, nullptr, + nullptr)) + continue; DebugLoc DLoc = I->getDebugLoc(); BasicBlock *BB = I->getParent(); - if (InlineFunction(CallSite(DI), IFI)) { + if (InlineFunction(CS, IFI)) { LocalChanged = true; // The call to InlineFunction erases DI, so we can't pass it here. ORE->emit(OptimizationRemark(DEBUG_TYPE, "HotInline", DLoc, BB) @@ -1418,6 +1438,7 @@ INITIALIZE_PASS_BEGIN(SampleProfileLoaderLegacyPass, "sample-profile", "Sample Profile loader", false, false) INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker) +INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass) INITIALIZE_PASS_END(SampleProfileLoaderLegacyPass, "sample-profile", "Sample Profile loader", false, false) @@ -1483,6 +1504,7 @@ bool SampleProfileLoaderLegacyPass::runOnModule(Module &M) { ACT = &getAnalysis(); + TTIWP = &getAnalysis(); return SampleLoader.runOnModule(M, nullptr); } @@ -1512,10 +1534,13 @@ auto GetAssumptionCache = [&](Function &F) -> AssumptionCache & { return FAM.getResult(F); }; + auto GetTTI = [&](Function &F) -> TargetTransformInfo & { + return FAM.getResult(F); + }; SampleProfileLoader SampleLoader(ProfileFileName.empty() ? SampleProfileFile : ProfileFileName, - GetAssumptionCache); + GetAssumptionCache, GetTTI); SampleLoader.doInitialization(M); Index: test/Transforms/SampleProfile/Inputs/einline.prof =================================================================== --- test/Transforms/SampleProfile/Inputs/einline.prof +++ test/Transforms/SampleProfile/Inputs/einline.prof @@ -1,5 +1,6 @@ _Z3foov:200:100 1: _Z3barv:0 + 2: no_inline:100 3: _Z3barv:100 recursive:200:100 1: recursive:100 Index: test/Transforms/SampleProfile/early-inline.ll =================================================================== --- test/Transforms/SampleProfile/early-inline.ll +++ test/Transforms/SampleProfile/early-inline.ll @@ -12,6 +12,8 @@ %1 = alloca i8* %2 = alloca i32 %3 = alloca i32, align 4 +; CHECK: call void @no_inline + call void @no_inline(), !dbg !16 ; CHECK-NOT: call call void @_ZL3barv(), !dbg !9 ; CHECK-NOT: invoke @@ -45,8 +47,16 @@ ret void } +; The callee has mismatch attributes to the caller, it should not be inlined +define void @no_inline() #1 !dbg !17 { + ret void +} + declare i32 @__gxx_personality_v0(...) +attributes #0 = {"target-features"="+sse4.1"} +attributes #1 = {"target-features"="+sse4.2"} + !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!3, !4} @@ -62,3 +72,5 @@ !13 = distinct !DISubprogram(linkageName: "recursive", scope: !1, file: !1, line: 20, scopeLine: 20, unit: !0) !14 = !DILocation(line: 21, column: 3, scope: !13) !15 = !DILocation(line: 22, column: 3, scope: !13) +!16 = !DILocation(line: 7, column: 3, scope: !6) +!17 = distinct !DISubprogram(linkageName: "no_inline", scope: !1, file: !1, line: 20, scopeLine: 20, unit: !0)