ahatanak created this revision. ahatanak added a reviewer: aaron.ballman. ahatanak added a subscriber: cfe-commits.
This patch adds support for a new function attribute "notail". The attribute is used to disable tail call optimization on calls to functions marked with the attribute. This is different from the attribute proposed in D12547, which disables tail call optimizations on call sites within the marked function. http://reviews.llvm.org/D12547 http://reviews.llvm.org/D12922 Files: include/clang/Basic/Attr.td include/clang/Basic/AttrDocs.td lib/CodeGen/CGCall.cpp lib/Sema/SemaDeclAttr.cpp test/CodeGen/attr-no-tail.c Index: test/CodeGen/attr-no-tail.c =================================================================== --- /dev/null +++ test/CodeGen/attr-no-tail.c @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.7.0 %s -emit-llvm -o - | FileCheck %s + +// CHECK: define i32 @callee0(i32 %a) [[ATTRNOTAIL0:#[0-9]+]] { +// CHECK: declare i32 @callee1(i32) [[ATTRNOTAIL1:#[0-9]+]] +// CHECK: declare i32 @callee2(i32) [[ATTRTAIL0:#[0-9]+]] + +int callee0(int a) __attribute__((notail)) { + return a + 1; +} + +int callee1(int) __attribute__((notail)); + +int callee2(int); + +int caller0(int a) { + if (a > 0) + return callee0(a); + if (a < 0) + return callee1(a); + return callee2(a); +} + +// CHECK: attributes [[ATTRNOTAIL0]] = { {{.*}}notail{{.*}} } +// CHECK: attributes [[ATTRNOTAIL1]] = { {{.*}}notail{{.*}} } +// CHECK-NOT: attributes [[ATTRTAIL0]] = { {{.*}}notail{{.*}} } Index: lib/Sema/SemaDeclAttr.cpp =================================================================== --- lib/Sema/SemaDeclAttr.cpp +++ lib/Sema/SemaDeclAttr.cpp @@ -4878,6 +4878,9 @@ case AttributeList::AT_ReturnsTwice: handleSimpleAttribute<ReturnsTwiceAttr>(S, D, Attr); break; + case AttributeList::AT_NoTail: + handleSimpleAttribute<NoTailAttr>(S, D, Attr); + break; case AttributeList::AT_Used: handleUsedAttr(S, D, Attr); break; Index: lib/CodeGen/CGCall.cpp =================================================================== --- lib/CodeGen/CGCall.cpp +++ lib/CodeGen/CGCall.cpp @@ -1414,6 +1414,8 @@ FuncAttrs.addAttribute(llvm::Attribute::NoReturn); if (TargetDecl->hasAttr<NoDuplicateAttr>()) FuncAttrs.addAttribute(llvm::Attribute::NoDuplicate); + if (TargetDecl->hasAttr<NoTailAttr>()) + FuncAttrs.addAttribute(llvm::Attribute::NoTail); if (const FunctionDecl *Fn = dyn_cast<FunctionDecl>(TargetDecl)) { const FunctionProtoType *FPT = Fn->getType()->getAs<FunctionProtoType>(); Index: include/clang/Basic/AttrDocs.td =================================================================== --- include/clang/Basic/AttrDocs.td +++ include/clang/Basic/AttrDocs.td @@ -1612,3 +1612,10 @@ arguments, with arbitrary offsets. }]; } + +def NoTailDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +Tail call optimization is not performed on calls to a function marked ``notail``. + }]; +} Index: include/clang/Basic/Attr.td =================================================================== --- include/clang/Basic/Attr.td +++ include/clang/Basic/Attr.td @@ -1020,6 +1020,12 @@ let Documentation = [Undocumented]; } +def NoTail : InheritableAttr { + let Spellings = [GNU<"notail">, CXX11<"clang", "notail">]; + let Subjects = SubjectList<[Function, ObjCMethod]>; + let Documentation = [NoTailDocs]; +} + def NoThrow : InheritableAttr { let Spellings = [GCC<"nothrow">, Declspec<"nothrow">]; let Documentation = [Undocumented];
Index: test/CodeGen/attr-no-tail.c =================================================================== --- /dev/null +++ test/CodeGen/attr-no-tail.c @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.7.0 %s -emit-llvm -o - | FileCheck %s + +// CHECK: define i32 @callee0(i32 %a) [[ATTRNOTAIL0:#[0-9]+]] { +// CHECK: declare i32 @callee1(i32) [[ATTRNOTAIL1:#[0-9]+]] +// CHECK: declare i32 @callee2(i32) [[ATTRTAIL0:#[0-9]+]] + +int callee0(int a) __attribute__((notail)) { + return a + 1; +} + +int callee1(int) __attribute__((notail)); + +int callee2(int); + +int caller0(int a) { + if (a > 0) + return callee0(a); + if (a < 0) + return callee1(a); + return callee2(a); +} + +// CHECK: attributes [[ATTRNOTAIL0]] = { {{.*}}notail{{.*}} } +// CHECK: attributes [[ATTRNOTAIL1]] = { {{.*}}notail{{.*}} } +// CHECK-NOT: attributes [[ATTRTAIL0]] = { {{.*}}notail{{.*}} } Index: lib/Sema/SemaDeclAttr.cpp =================================================================== --- lib/Sema/SemaDeclAttr.cpp +++ lib/Sema/SemaDeclAttr.cpp @@ -4878,6 +4878,9 @@ case AttributeList::AT_ReturnsTwice: handleSimpleAttribute<ReturnsTwiceAttr>(S, D, Attr); break; + case AttributeList::AT_NoTail: + handleSimpleAttribute<NoTailAttr>(S, D, Attr); + break; case AttributeList::AT_Used: handleUsedAttr(S, D, Attr); break; Index: lib/CodeGen/CGCall.cpp =================================================================== --- lib/CodeGen/CGCall.cpp +++ lib/CodeGen/CGCall.cpp @@ -1414,6 +1414,8 @@ FuncAttrs.addAttribute(llvm::Attribute::NoReturn); if (TargetDecl->hasAttr<NoDuplicateAttr>()) FuncAttrs.addAttribute(llvm::Attribute::NoDuplicate); + if (TargetDecl->hasAttr<NoTailAttr>()) + FuncAttrs.addAttribute(llvm::Attribute::NoTail); if (const FunctionDecl *Fn = dyn_cast<FunctionDecl>(TargetDecl)) { const FunctionProtoType *FPT = Fn->getType()->getAs<FunctionProtoType>(); Index: include/clang/Basic/AttrDocs.td =================================================================== --- include/clang/Basic/AttrDocs.td +++ include/clang/Basic/AttrDocs.td @@ -1612,3 +1612,10 @@ arguments, with arbitrary offsets. }]; } + +def NoTailDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +Tail call optimization is not performed on calls to a function marked ``notail``. + }]; +} Index: include/clang/Basic/Attr.td =================================================================== --- include/clang/Basic/Attr.td +++ include/clang/Basic/Attr.td @@ -1020,6 +1020,12 @@ let Documentation = [Undocumented]; } +def NoTail : InheritableAttr { + let Spellings = [GNU<"notail">, CXX11<"clang", "notail">]; + let Subjects = SubjectList<[Function, ObjCMethod]>; + let Documentation = [NoTailDocs]; +} + def NoThrow : InheritableAttr { let Spellings = [GCC<"nothrow">, Declspec<"nothrow">]; let Documentation = [Undocumented];
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits