Index: include/llvm/Transforms/IPO.h =================================================================== --- include/llvm/Transforms/IPO.h +++ include/llvm/Transforms/IPO.h @@ -100,9 +100,16 @@ /// /// The -inline-threshold command line option takes precedence over the /// threshold given here. +/// +/// The OnlyHint flag allow to restrict inlining analysis to function with +/// InlineHint attribute. +/// +/// The inline-restrict-to-hint command line option takes precedence over the +/// flag given here. Pass *createFunctionInliningPass(); -Pass *createFunctionInliningPass(int Threshold); -Pass *createFunctionInliningPass(unsigned OptLevel, unsigned SizeOptLevel); +Pass *createFunctionInliningPass(int Threshold, bool OnlyHint = false); +Pass *createFunctionInliningPass(unsigned OptLevel, unsigned SizeOptLevel, + bool OnlyHint = false); //===----------------------------------------------------------------------===// /// createAlwaysInlinerPass - Return a new pass object that inlines only Index: lib/Transforms/IPO/InlineSimple.cpp =================================================================== --- lib/Transforms/IPO/InlineSimple.cpp +++ lib/Transforms/IPO/InlineSimple.cpp @@ -31,6 +31,10 @@ #define DEBUG_TYPE "inline" +static cl::opt RestrictInlineToHinted( + "inline-restrict-to-hint", cl::Hidden, cl::init(false), + cl::desc("Flag to restrict inlining to InlineHint functions only")); + namespace { /// \brief Actual inliner pass implementation. @@ -47,18 +51,23 @@ public: SimpleInliner() - : Inliner(ID), DefaultThreshold(llvm::getDefaultInlineThreshold()) { + : Inliner(ID), DefaultThreshold(llvm::getDefaultInlineThreshold()), + RestrictToHinted(RestrictInlineToHinted) { initializeSimpleInlinerPass(*PassRegistry::getPassRegistry()); } - explicit SimpleInliner(int Threshold) + explicit SimpleInliner(int Threshold, bool OnlyHint) : Inliner(ID), DefaultThreshold(Threshold) { + RestrictToHinted = RestrictInlineToHinted.getNumOccurrences() > 0 ? + RestrictInlineToHinted : OnlyHint; initializeSimpleInlinerPass(*PassRegistry::getPassRegistry()); } static char ID; // Pass identification, replacement for typeid InlineCost getInlineCost(CallSite CS) override { + if (RestrictToHinted && !CS.hasFnAttr(llvm::Attribute::InlineHint)) + return InlineCost::getNever(); Function *Callee = CS.getCalledFunction(); TargetTransformInfo &TTI = TTIWP->getTTI(*Callee); return llvm::getInlineCost(CS, DefaultThreshold, TTI, ACT, PSI); @@ -69,6 +78,7 @@ private: TargetTransformInfoWrapperPass *TTIWP; + bool RestrictToHinted; }; } // end anonymous namespace @@ -86,14 +96,14 @@ Pass *llvm::createFunctionInliningPass() { return new SimpleInliner(); } -Pass *llvm::createFunctionInliningPass(int Threshold) { - return new SimpleInliner(Threshold); +Pass *llvm::createFunctionInliningPass(int Threshold, bool OnlyHint) { + return new SimpleInliner(Threshold, OnlyHint); } Pass *llvm::createFunctionInliningPass(unsigned OptLevel, - unsigned SizeOptLevel) { + unsigned SizeOptLevel, bool OnlyHint) { return new SimpleInliner( - llvm::computeThresholdFromOptLevels(OptLevel, SizeOptLevel)); + llvm::computeThresholdFromOptLevels(OptLevel, SizeOptLevel), OnlyHint); } bool SimpleInliner::runOnSCC(CallGraphSCC &SCC) { Index: test/Transforms/Inline/inline-hint.ll =================================================================== --- test/Transforms/Inline/inline-hint.ll +++ test/Transforms/Inline/inline-hint.ll @@ -0,0 +1,37 @@ +; Test that -inline-restrict-to-hint correctly restrict to hinted functions +; RUN: opt < %s -inline -inline-restrict-to-hint=true -S | FileCheck %s -check-prefix=RESTRICT +; RUN: opt < %s -inline -S | FileCheck %s -check-prefix=INLINE + +; Function Attrs: nounwind readnone uwtable +define i32 @simpleFunction(i32 %a) #0 { +entry: + %add = add i32 %a, %a + ret i32 %add +} + +; Function Attrs: inlinehint nounwind readnone uwtable +define i32 @hintFunction(i32 %a) #1 { +entry: + %add = add i32 %a, %a + ret i32 %add +} + +; INLINE-LABEL: @bar +; RESTRICT-LABEL: @bar +; Function Attrs: nounwind readnone uwtable +define i32 @bar(i32 %a) #0 { +entry: +; INLINE-NOT: call i32 @simpleFunction +; RESTRICT: call i32 @simpleFunction(i32 5) + %0 = tail call i32 @simpleFunction(i32 5) +; INLINE-NOT: call i32 @hintFunction +; RESTRICT-NOT: call i32 @hintFunction + %1 = tail call i32 @hintFunction(i32 6) + %add = add i32 %0, %1 +; INLINE: ret +; RESTRICT: ret + ret i32 %add +} + +attributes #0 = { nounwind readnone uwtable } +attributes #1 = { inlinehint nounwind readnone uwtable }