aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/LangRef.rst5
-rw-r--r--lib/Analysis/IPA/InlineCost.cpp4
-rw-r--r--lib/IR/Verifier.cpp6
-rw-r--r--test/Bitcode/attributes.ll4
-rw-r--r--test/Feature/optnone.ll6
-rw-r--r--test/Transforms/Inline/inline-optnone.ll52
6 files changed, 67 insertions, 10 deletions
diff --git a/docs/LangRef.rst b/docs/LangRef.rst
index f7914f8..18d2c9c 100644
--- a/docs/LangRef.rst
+++ b/docs/LangRef.rst
@@ -941,9 +941,10 @@ example:
attribute; this attribute is also incompatible
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
- candidates for inlining inside the body of this function.
+ candidates for inlining into the body of this function.
``optsize``
This attribute suggests that optimization passes and code generator
passes make choices that keep the code size of this function low,
diff --git a/lib/Analysis/IPA/InlineCost.cpp b/lib/Analysis/IPA/InlineCost.cpp
index 89dcd81..013691b 100644
--- a/lib/Analysis/IPA/InlineCost.cpp
+++ b/lib/Analysis/IPA/InlineCost.cpp
@@ -1206,6 +1206,10 @@ InlineCost InlineCostAnalysis::getInlineCost(CallSite CS, Function *Callee,
if (!functionsHaveCompatibleAttributes(CS.getCaller(), Callee))
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
// something else. Don't inline functions marked noinline or call sites
// marked noinline.
diff --git a/lib/IR/Verifier.cpp b/lib/IR/Verifier.cpp
index 0bcb118..da6b573 100644
--- a/lib/IR/Verifier.cpp
+++ b/lib/IR/Verifier.cpp
@@ -927,9 +927,9 @@ void Verifier::VerifyFunctionAttrs(FunctionType *FT, AttributeSet Attrs,
if (Attrs.hasAttribute(AttributeSet::FunctionIndex,
Attribute::OptimizeNone)) {
- Assert1(!Attrs.hasAttribute(AttributeSet::FunctionIndex,
- Attribute::AlwaysInline),
- "Attributes 'alwaysinline and optnone' are incompatible!", V);
+ Assert1(Attrs.hasAttribute(AttributeSet::FunctionIndex,
+ Attribute::NoInline),
+ "Attribute 'optnone' requires 'noinline'!", V);
Assert1(!Attrs.hasAttribute(AttributeSet::FunctionIndex,
Attribute::OptimizeForSize),
diff --git a/test/Bitcode/attributes.ll b/test/Bitcode/attributes.ll
index 2ff87d6..1789878 100644
--- a/test/Bitcode/attributes.ll
+++ b/test/Bitcode/attributes.ll
@@ -207,7 +207,7 @@ define void @f34()
ret void;
}
-define void @f35() optnone
+define void @f35() optnone noinline
; CHECK: define void @f35() #23
{
ret void;
@@ -236,6 +236,6 @@ define void @f35() optnone
; CHECK: attributes #20 = { "cpu"="cortex-a8" }
; CHECK: attributes #21 = { sspstrong }
; CHECK: attributes #22 = { minsize }
-; CHECK: attributes #23 = { optnone }
+; CHECK: attributes #23 = { noinline optnone }
; CHECK: attributes #24 = { nobuiltin }
diff --git a/test/Feature/optnone.ll b/test/Feature/optnone.ll
index ec1d723..7d8afd4 100644
--- a/test/Feature/optnone.ll
+++ b/test/Feature/optnone.ll
@@ -1,12 +1,12 @@
; 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
define void @foo() #0 {
ret void
}
-; CHECK: attributes #0 = { optnone }
-attributes #0 = { optnone }
+; CHECK: attributes #0 = { noinline optnone }
+attributes #0 = { optnone noinline }
diff --git a/test/Transforms/Inline/inline-optnone.ll b/test/Transforms/Inline/inline-optnone.ll
new file mode 100644
index 0000000..9b99c45
--- /dev/null
+++ b/test/Transforms/Inline/inline-optnone.ll
@@ -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 }