The 'optnone' attribute means don't inline anything into this function
authorPaul Robinson <paul_robinson@playstation.sony.com>
Mon, 18 Nov 2013 21:44:03 +0000 (21:44 +0000)
committerPaul Robinson <paul_robinson@playstation.sony.com>
Mon, 18 Nov 2013 21:44:03 +0000 (21:44 +0000)
(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

docs/LangRef.rst
lib/Analysis/IPA/InlineCost.cpp
lib/IR/Verifier.cpp
test/Bitcode/attributes.ll
test/Feature/optnone.ll
test/Transforms/Inline/inline-optnone.ll [new file with mode: 0644]

index f7914f864fb88080a743298cdd469ebae6e61a0c..18d2c9cfb52211d1840ca9ee02ba539a288ae19e 100644 (file)
@@ -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,
index 89dcd819ee2cedeaffdcc2d0e18f6bdeba1f1b5c..013691b668b22b6de4bc6556d635fe6fba3b28e3 100644 (file)
@@ -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.
index 0bcb118ecad6fbad102f631b8d3ccf043718d1a8..da6b573a0c3cb5118cc725cb13d1824f9e5e7ed4 100644 (file)
@@ -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),
index 2ff87d68ebcbaf0798c148af9ad3203767d5b8e2..1789878e9f50c088e9dc4a652823884bfcd95e17 100644 (file)
@@ -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 }
 
index ec1d7232b363d939c3656cce8d01cb0bb78b5149..7d8afd4b773eff7726bc9f2766acb59fc5d7aeb6 100644 (file)
@@ -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 (file)
index 0000000..9b99c45
--- /dev/null
@@ -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 }