From 7e9a34dfa561f6fa3e91848212f1a0cf15094799 Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Tue, 20 May 2014 17:12:51 +0000 Subject: [PATCH] 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 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@209217 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/Attr.td | 6 ++++++ include/clang/Basic/AttrDocs.td | 8 ++++++++ lib/CodeGen/CGCall.cpp | 6 ++++++ lib/Sema/SemaDeclAttr.cpp | 3 +++ test/CodeGen/flatten.c | 19 ++++++++++++++++++ test/CodeGenCXX/flatten.cpp | 10 ++++++++++ test/SemaCXX/attr-flatten.cpp | 34 +++++++++++++++++++++++++++++++++ 7 files changed, 86 insertions(+) create mode 100644 test/CodeGen/flatten.c create mode 100644 test/CodeGenCXX/flatten.cpp create mode 100644 test/SemaCXX/attr-flatten.cpp diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index e054d6a8fb..1b011b0686 100644 --- a/include/clang/Basic/Attr.td +++ b/include/clang/Basic/Attr.td @@ -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">, diff --git a/include/clang/Basic/AttrDocs.td b/include/clang/Basic/AttrDocs.td index a0c2028512..9694e21090 100644 --- a/include/clang/Basic/AttrDocs.td +++ b/include/clang/Basic/AttrDocs.td @@ -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 = [{ diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index e477a54c67..31665f8851 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -2935,6 +2935,12 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, if (callOrInvoke) *callOrInvoke = CS.getInstruction(); + if (CurCodeDecl && CurCodeDecl->hasAttr() && + !CS.hasFnAttr(llvm::Attribute::NoInline)) + Attrs = + Attrs.addAttribute(getLLVMContext(), llvm::AttributeSet::FunctionIndex, + llvm::Attribute::AlwaysInline); + CS.setAttributes(Attrs); CS.setCallingConv(static_cast(CallingConv)); diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index b7c1d5d15b..9775c58639 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -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(S, D, Attr); + break; case AttributeList::AT_Format: handleFormatAttr(S, D, Attr); break; diff --git a/test/CodeGen/flatten.c b/test/CodeGen/flatten.c new file mode 100644 index 0000000000..d766d543e0 --- /dev/null +++ b/test/CodeGen/flatten.c @@ -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(); +} diff --git a/test/CodeGenCXX/flatten.cpp b/test/CodeGenCXX/flatten.cpp new file mode 100644 index 0000000000..9e0f67f789 --- /dev/null +++ b/test/CodeGenCXX/flatten.cpp @@ -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(); +} diff --git a/test/SemaCXX/attr-flatten.cpp b/test/SemaCXX/attr-flatten.cpp new file mode 100644 index 0000000000..afcba72b64 --- /dev/null +++ b/test/SemaCXX/attr-flatten.cpp @@ -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 +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 +[[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(); +}; -- 2.40.0