The 'optnone' attribute means don't inline anything into this function

(except functions marked always_inline).
Functions with 'optnone' must also have 'noinline' so they don't get
inlined into any other function.

Based on work by Andrea Di Biagio.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@195046 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Paul Robinson 2013-11-18 21:44:03 +00:00
parent 3560dd2dcd
commit fe45fd084d
6 changed files with 67 additions and 10 deletions

View File

@ -941,9 +941,10 @@ example:
attribute; this attribute is also incompatible attribute; this attribute is also incompatible
with the ``minsize`` attribute and the ``optsize`` attribute. with the ``minsize`` attribute and the ``optsize`` attribute.
The inliner should never inline this function in any situation. This attribute requires the ``noinline`` attribute to be specified on
the function as well, so the function is never inlined into any caller.
Only functions with the ``alwaysinline`` attribute are valid Only functions with the ``alwaysinline`` attribute are valid
candidates for inlining inside the body of this function. candidates for inlining into the body of this function.
``optsize`` ``optsize``
This attribute suggests that optimization passes and code generator This attribute suggests that optimization passes and code generator
passes make choices that keep the code size of this function low, passes make choices that keep the code size of this function low,

View File

@ -1206,6 +1206,10 @@ InlineCost InlineCostAnalysis::getInlineCost(CallSite CS, Function *Callee,
if (!functionsHaveCompatibleAttributes(CS.getCaller(), Callee)) if (!functionsHaveCompatibleAttributes(CS.getCaller(), Callee))
return llvm::InlineCost::getNever(); return llvm::InlineCost::getNever();
// Don't inline this call if the caller has the optnone attribute.
if (CS.getCaller()->hasFnAttribute(Attribute::OptimizeNone))
return llvm::InlineCost::getNever();
// Don't inline functions which can be redefined at link-time to mean // Don't inline functions which can be redefined at link-time to mean
// something else. Don't inline functions marked noinline or call sites // something else. Don't inline functions marked noinline or call sites
// marked noinline. // marked noinline.

View File

@ -927,9 +927,9 @@ void Verifier::VerifyFunctionAttrs(FunctionType *FT, AttributeSet Attrs,
if (Attrs.hasAttribute(AttributeSet::FunctionIndex, if (Attrs.hasAttribute(AttributeSet::FunctionIndex,
Attribute::OptimizeNone)) { Attribute::OptimizeNone)) {
Assert1(!Attrs.hasAttribute(AttributeSet::FunctionIndex, Assert1(Attrs.hasAttribute(AttributeSet::FunctionIndex,
Attribute::AlwaysInline), Attribute::NoInline),
"Attributes 'alwaysinline and optnone' are incompatible!", V); "Attribute 'optnone' requires 'noinline'!", V);
Assert1(!Attrs.hasAttribute(AttributeSet::FunctionIndex, Assert1(!Attrs.hasAttribute(AttributeSet::FunctionIndex,
Attribute::OptimizeForSize), Attribute::OptimizeForSize),

View File

@ -207,7 +207,7 @@ define void @f34()
ret void; ret void;
} }
define void @f35() optnone define void @f35() optnone noinline
; CHECK: define void @f35() #23 ; CHECK: define void @f35() #23
{ {
ret void; ret void;
@ -236,6 +236,6 @@ define void @f35() optnone
; CHECK: attributes #20 = { "cpu"="cortex-a8" } ; CHECK: attributes #20 = { "cpu"="cortex-a8" }
; CHECK: attributes #21 = { sspstrong } ; CHECK: attributes #21 = { sspstrong }
; CHECK: attributes #22 = { minsize } ; CHECK: attributes #22 = { minsize }
; CHECK: attributes #23 = { optnone } ; CHECK: attributes #23 = { noinline optnone }
; CHECK: attributes #24 = { nobuiltin } ; CHECK: attributes #24 = { nobuiltin }

View File

@ -1,12 +1,12 @@
; RUN: llvm-as < %s | llvm-dis | FileCheck %s ; RUN: llvm-as < %s | llvm-dis | FileCheck %s
; Check for the presence of attribute noopt in the disassembly. ; Check for the presence of attribute optnone in the disassembly.
; CHECK: @foo() #0 ; CHECK: @foo() #0
define void @foo() #0 { define void @foo() #0 {
ret void ret void
} }
; CHECK: attributes #0 = { optnone } ; CHECK: attributes #0 = { noinline optnone }
attributes #0 = { optnone } attributes #0 = { optnone noinline }

View File

@ -0,0 +1,52 @@
; RUN: opt < %s -inline -S | FileCheck %s
; Test that functions with attribute optnone are not inlined.
; Also test that only functions with attribute alwaysinline are
; valid candidates for inlining if the caller has the optnone attribute.
; Function Attrs: alwaysinline nounwind readnone uwtable
define i32 @alwaysInlineFunction(i32 %a) #0 {
entry:
%mul = mul i32 %a, %a
ret i32 %mul
}
; Function Attrs: nounwind readnone uwtable
define i32 @simpleFunction(i32 %a) #1 {
entry:
%add = add i32 %a, %a
ret i32 %add
}
; Function Attrs: nounwind noinline optnone readnone uwtable
define i32 @OptnoneFunction(i32 %a) #2 {
entry:
%0 = tail call i32 @alwaysInlineFunction(i32 %a)
%1 = tail call i32 @simpleFunction(i32 %a)
%add = add i32 %0, %1
ret i32 %add
}
; CHECK-LABEL: @OptnoneFunction
; CHECK-NOT: call i32 @alwaysInlineFunction(i32 %a)
; CHECK: call i32 @simpleFunction(i32 %a)
; CHECK: ret
; Function Attrs: nounwind readnone uwtable
define i32 @bar(i32 %a) #1 {
entry:
%0 = tail call i32 @OptnoneFunction(i32 5)
%1 = tail call i32 @simpleFunction(i32 6)
%add = add i32 %0, %1
ret i32 %add
}
; CHECK-LABEL: @bar
; CHECK: call i32 @OptnoneFunction(i32 5)
; CHECK-NOT: call i32 @simpleFunction(i32 6)
; CHECK: ret
attributes #0 = { alwaysinline nounwind readnone uwtable }
attributes #1 = { nounwind readnone uwtable }
attributes #2 = { nounwind noinline optnone readnone uwtable }