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

Reply via email to