Implement the flatten attribute.

This is a GNU attribute that causes calls within the attributed function
to be inlined where possible. It is implemented by giving such calls the
alwaysinline attribute.

Differential Revision: http://reviews.llvm.org/D3816

llvm-svn: 209217
This commit is contained in:
Peter Collingbourne 2014-05-20 17:12:51 +00:00
parent 650c8f2a06
commit 41af7c2fdc
7 changed files with 86 additions and 0 deletions
clang
include/clang/Basic
lib
test
CodeGen
CodeGenCXX
SemaCXX

View File

@ -668,6 +668,12 @@ def MinSize : InheritableAttr {
let Documentation = [Undocumented];
}
def Flatten : InheritableAttr {
let Spellings = [GCC<"flatten">];
let Subjects = SubjectList<[Function], ErrorDiag>;
let Documentation = [FlattenDocs];
}
def Format : InheritableAttr {
let Spellings = [GCC<"format">];
let Args = [IdentifierArgument<"Type">, IntArgument<"FormatIdx">,

View File

@ -877,6 +877,14 @@ expression is compared to the type tag. There are two supported flags:
}];
}
def FlattenDocs : Documentation {
let Category = DocCatFunction;
let Content = [{
The ``flatten`` attribute causes calls within the attributed function to be
inlined if possible.
}];
}
def FormatDocs : Documentation {
let Category = DocCatFunction;
let Content = [{

View File

@ -2935,6 +2935,12 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
if (callOrInvoke)
*callOrInvoke = CS.getInstruction();
if (CurCodeDecl && CurCodeDecl->hasAttr<FlattenAttr>() &&
!CS.hasFnAttr(llvm::Attribute::NoInline))
Attrs =
Attrs.addAttribute(getLLVMContext(), llvm::AttributeSet::FunctionIndex,
llvm::Attribute::AlwaysInline);
CS.setAttributes(Attrs);
CS.setCallingConv(static_cast<llvm::CallingConv::ID>(CallingConv));

View File

@ -4147,6 +4147,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case AttributeList::AT_OptimizeNone:
handleOptimizeNoneAttr(S, D, Attr);
break;
case AttributeList::AT_Flatten:
handleSimpleAttribute<FlattenAttr>(S, D, Attr);
break;
case AttributeList::AT_Format:
handleFormatAttr(S, D, Attr);
break;

View File

@ -0,0 +1,19 @@
// RUN: %clang_cc1 -triple=x86_64-linux-gnu %s -emit-llvm -o - | FileCheck %s
void f(void) {}
__attribute__((noinline)) void ni(void) {}
__attribute__((flatten))
// CHECK: define void @g()
void g(void) {
// CHECK-NOT: call {{.*}} @f
f();
// CHECK: call {{.*}} @ni
ni();
}
void h(void) {
// CHECK: call {{.*}} @f
f();
}

View File

@ -0,0 +1,10 @@
// RUN: %clang_cc1 -triple=x86_64-linux-gnu -std=c++11 %s -emit-llvm -o - | FileCheck %s
void f(void) {}
[[gnu::flatten]]
// CHECK: define void @_Z1gv()
void g(void) {
// CHECK-NOT: call {{.*}} @_Z1fv
f();
}

View File

@ -0,0 +1,34 @@
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
int i __attribute__((flatten)); // expected-error {{'flatten' attribute only applies to functions}}
void f1() __attribute__((flatten));
void f2() __attribute__((flatten(1))); // expected-error {{'flatten' attribute takes no arguments}}
template <typename T>
void tf1() __attribute__((flatten));
int f3(int __attribute__((flatten)), int); // expected-error{{'flatten' attribute only applies to functions}}
struct A {
int f __attribute__((flatten)); // expected-error{{'flatten' attribute only applies to functions}}
void mf1() __attribute__((flatten));
static void mf2() __attribute__((flatten));
};
int ci [[gnu::flatten]]; // expected-error {{'flatten' attribute only applies to functions}}
[[gnu::flatten]] void cf1();
[[gnu::flatten(1)]] void cf2(); // expected-error {{'flatten' attribute takes no arguments}}
template <typename T>
[[gnu::flatten]]
void ctf1();
int cf3(int c[[gnu::flatten]], int); // expected-error{{'flatten' attribute only applies to functions}}
struct CA {
int f [[gnu::flatten]]; // expected-error{{'flatten' attribute only applies to functions}}
[[gnu::flatten]] void mf1();
[[gnu::flatten]] static void mf2();
};