r252986 - Add support for function attribute 'disable_tail_calls'.

Akira Hatanaka via cfe-commits cfe-commits at lists.llvm.org
Thu Nov 12 16:42:22 PST 2015


Author: ahatanak
Date: Thu Nov 12 18:42:21 2015
New Revision: 252986

URL: http://llvm.org/viewvc/llvm-project?rev=252986&view=rev
Log:
Add support for function attribute 'disable_tail_calls'.

The ``disable_tail_calls`` attribute instructs the backend to not
perform tail call optimization inside the marked function.

For example, 

int callee(int);

int foo(int a) __attribute__((disable_tail_calls)) {
  return callee(a); // This call is not tail-call optimized.
}

Note that this attribute is different from 'not_tail_called', which
prevents tail-call optimization to the marked function.

rdar://problem/8973573

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

Added:
    cfe/trunk/test/CodeGenCXX/attr-disable-tail-calls.cpp
    cfe/trunk/test/Sema/attr-disable-tail-calls.c
    cfe/trunk/test/SemaCXX/attr-disable-tail-calls.cpp
Modified:
    cfe/trunk/include/clang/Basic/Attr.td
    cfe/trunk/include/clang/Basic/AttrDocs.td
    cfe/trunk/lib/CodeGen/CGCall.cpp
    cfe/trunk/lib/Sema/SemaDeclAttr.cpp
    cfe/trunk/test/CodeGen/attr-disable-tail-calls.c

Modified: cfe/trunk/include/clang/Basic/Attr.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=252986&r1=252985&r2=252986&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Attr.td (original)
+++ cfe/trunk/include/clang/Basic/Attr.td Thu Nov 12 18:42:21 2015
@@ -890,6 +890,13 @@ def ReturnsTwice : InheritableAttr {
   let Documentation = [Undocumented];
 }
 
+def DisableTailCalls : InheritableAttr {
+  let Spellings = [GNU<"disable_tail_calls">,
+                   CXX11<"clang", "disable_tail_calls">];
+  let Subjects = SubjectList<[Function, ObjCMethod]>;
+  let Documentation = [DisableTailCallsDocs];
+}
+
 def NoAlias : InheritableAttr {
   let Spellings = [Declspec<"noalias">];
   let Subjects = SubjectList<[Function]>;

Modified: cfe/trunk/include/clang/Basic/AttrDocs.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/AttrDocs.td?rev=252986&r1=252985&r2=252986&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/AttrDocs.td (original)
+++ cfe/trunk/include/clang/Basic/AttrDocs.td Thu Nov 12 18:42:21 2015
@@ -1684,3 +1684,41 @@ this attribute affects all methods and s
 This can be used to contain the ABI of a C++ library by excluding unwanted class methods from the export tables.
   }];
 }
+
+def DisableTailCallsDocs : Documentation {
+  let Category = DocCatFunction;
+  let Content = [{
+The ``disable_tail_calls`` attribute instructs the backend to not perform tail call optimization inside the marked function.
+
+For example:
+
+  .. code-block:: c
+
+    int callee(int);
+
+    int foo(int a) __attribute__((disable_tail_calls)) {
+      return callee(a); // This call is not tail-call optimized.
+    }
+
+Marking virtual functions as ``disable_tail_calls`` is legal.
+
+  .. code-block: c++
+
+    int callee(int);
+
+    class Base {
+    public:
+      [[clang::disable_tail_calls]] virtual int foo1() {
+        return callee(); // This call is not tail-call optimized.
+      }
+    };
+
+    class Derived1 : public Base {
+    public:
+      int foo1() override {
+        return callee(); // This call is tail-call optimized.
+      }
+    };
+
+  }];
+}

Modified: cfe/trunk/lib/CodeGen/CGCall.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCall.cpp?rev=252986&r1=252985&r2=252986&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCall.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCall.cpp Thu Nov 12 18:42:21 2015
@@ -1481,8 +1481,12 @@ void CodeGenModule::ConstructAttributeLi
       FuncAttrs.addAttribute("no-frame-pointer-elim-non-leaf");
     }
 
+    bool DisableTailCalls =
+        CodeGenOpts.DisableTailCalls ||
+        (TargetDecl && TargetDecl->hasAttr<DisableTailCallsAttr>());
     FuncAttrs.addAttribute("disable-tail-calls",
-                           llvm::toStringRef(CodeGenOpts.DisableTailCalls));
+                           llvm::toStringRef(DisableTailCalls));
+
     FuncAttrs.addAttribute("less-precise-fpmad",
                            llvm::toStringRef(CodeGenOpts.LessPreciseFPMAD));
     FuncAttrs.addAttribute("no-infs-fp-math",

Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=252986&r1=252985&r2=252986&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Thu Nov 12 18:42:21 2015
@@ -1583,6 +1583,15 @@ static void handleCommonAttr(Sema &S, De
     D->addAttr(CA);
 }
 
+static void handleNakedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+  if (checkAttrMutualExclusion<DisableTailCallsAttr>(S, D, Attr.getRange(),
+                                                     Attr.getName()))
+    return;
+
+  D->addAttr(::new (S.Context) NakedAttr(Attr.getRange(), S.Context,
+                                         Attr.getAttributeSpellingListIndex()));
+}
+
 static void handleNoReturnAttr(Sema &S, Decl *D, const AttributeList &attr) {
   if (hasDeclarator(D)) return;
 
@@ -1713,6 +1722,16 @@ static void handleNotTailCalledAttr(Sema
       Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
 }
 
+static void handleDisableTailCallsAttr(Sema &S, Decl *D,
+                                       const AttributeList &Attr) {
+  if (checkAttrMutualExclusion<NakedAttr>(S, D, Attr.getRange(),
+                                          Attr.getName()))
+    return;
+
+  D->addAttr(::new (S.Context) DisableTailCallsAttr(
+      Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
+}
+
 static void handleUsedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
   if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
     if (VD->hasLocalStorage()) {
@@ -4933,7 +4952,7 @@ static void ProcessDeclAttribute(Sema &S
     handleHotAttr(S, D, Attr);
     break;
   case AttributeList::AT_Naked:
-    handleSimpleAttribute<NakedAttr>(S, D, Attr);
+    handleNakedAttr(S, D, Attr);
     break;
   case AttributeList::AT_NoReturn:
     handleNoReturnAttr(S, D, Attr);
@@ -5056,6 +5075,9 @@ static void ProcessDeclAttribute(Sema &S
   case AttributeList::AT_NotTailCalled:
     handleNotTailCalledAttr(S, D, Attr);
     break;
+  case AttributeList::AT_DisableTailCalls:
+    handleDisableTailCallsAttr(S, D, Attr);
+    break;
   case AttributeList::AT_Used:
     handleUsedAttr(S, D, Attr);
     break;

Modified: cfe/trunk/test/CodeGen/attr-disable-tail-calls.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/attr-disable-tail-calls.c?rev=252986&r1=252985&r2=252986&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/attr-disable-tail-calls.c (original)
+++ cfe/trunk/test/CodeGen/attr-disable-tail-calls.c Thu Nov 12 18:42:21 2015
@@ -1,11 +1,19 @@
-// RUN: %clang_cc1 -triple x86_64-apple-macosx10.7.0 %s -emit-llvm -mdisable-tail-calls -o - | FileCheck %s -check-prefix=CHECK -check-prefix=DISABLE
-// RUN: %clang_cc1 -triple x86_64-apple-macosx10.7.0 %s -emit-llvm -o - | FileCheck %s -check-prefix=CHECK -check-prefix=ENABLE
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.7.0 %s -emit-llvm -mdisable-tail-calls -o - | FileCheck %s -check-prefix=DISABLE
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.7.0 %s -emit-llvm -o - | FileCheck %s -check-prefix=ENABLE
 
-// CHECK: define i32 @f1() [[ATTR:#[0-9]+]] {
+// DISABLE: define i32 @f1() [[ATTRTRUE:#[0-9]+]] {
+// DISABLE: define i32 @f2() [[ATTRTRUE]] {
+// ENABLE: define i32 @f1() [[ATTRFALSE:#[0-9]+]] {
+// ENABLE: define i32 @f2() [[ATTRTRUE:#[0-9]+]] {
 
 int f1() {
   return 0;
 }
 
-// DISABLE: attributes [[ATTR]] = { {{.*}} "disable-tail-calls"="true" {{.*}} }
-// ENABLE: attributes [[ATTR]] = { {{.*}} "disable-tail-calls"="false" {{.*}} }
+int f2() __attribute__((disable_tail_calls)) {
+  return 0;
+}
+
+// DISABLE: attributes [[ATTRTRUE]] = { {{.*}}"disable-tail-calls"="true"{{.*}} }
+// ENABLE: attributes [[ATTRFALSE]] = { {{.*}}"disable-tail-calls"="false"{{.*}} }
+// ENABLE: attributes [[ATTRTRUE]] = { {{.*}}"disable-tail-calls"="true"{{.*}} }

Added: cfe/trunk/test/CodeGenCXX/attr-disable-tail-calls.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/attr-disable-tail-calls.cpp?rev=252986&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/attr-disable-tail-calls.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/attr-disable-tail-calls.cpp Thu Nov 12 18:42:21 2015
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 -triple=x86_64-apple-darwin -std=c++11 -emit-llvm -o - %s | FileCheck %s
+
+class B {
+public:
+  [[clang::disable_tail_calls]] virtual int m1() { return 1; }
+  virtual int m2() { return 2; }
+  int m3() { return 3; }
+  [[clang::disable_tail_calls]] int m4();
+};
+
+class D : public B {
+public:
+  int m1() override { return 11; }
+  [[clang::disable_tail_calls]] int m2() override { return 22; }
+};
+
+int foo1() {
+  B *b = new B;
+  D *d = new D;
+  int t = 0;
+  t += b->m1() + b->m2() + b->m3() + b->m4();
+  t += d->m1() + d->m2();
+  return t;
+}
+
+// CHECK: define linkonce_odr i32 @_ZN1B2m3Ev(%class.B* %this) [[ATTRFALSE:#[0-9]+]]
+// CHECK: declare i32 @_ZN1B2m4Ev(%class.B*) [[ATTRTRUE0:#[0-9]+]]
+// CHECK: define linkonce_odr i32 @_ZN1B2m1Ev(%class.B* %this) unnamed_addr [[ATTRTRUE1:#[0-9]+]]
+// CHECK: define linkonce_odr i32 @_ZN1B2m2Ev(%class.B* %this) unnamed_addr [[ATTRFALSE:#[0-9]+]]
+// CHECK: define linkonce_odr i32 @_ZN1D2m1Ev(%class.D* %this) unnamed_addr [[ATTRFALSE:#[0-9]+]]
+// CHECK: define linkonce_odr i32 @_ZN1D2m2Ev(%class.D* %this) unnamed_addr [[ATTRTRUE1:#[0-9]+]]
+
+// CHECK: attributes [[ATTRFALSE]] = { {{.*}}"disable-tail-calls"="false"{{.*}} }
+// CHECK: attributes [[ATTRTRUE0]] = { {{.*}}"disable-tail-calls"="true"{{.*}} }
+// CHECK: attributes [[ATTRTRUE1]] = { {{.*}}"disable-tail-calls"="true"{{.*}} }

Added: cfe/trunk/test/Sema/attr-disable-tail-calls.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/attr-disable-tail-calls.c?rev=252986&view=auto
==============================================================================
--- cfe/trunk/test/Sema/attr-disable-tail-calls.c (added)
+++ cfe/trunk/test/Sema/attr-disable-tail-calls.c Thu Nov 12 18:42:21 2015
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+void __attribute__((disable_tail_calls,naked)) foo1(int a) { // expected-error {{'disable_tail_calls' and 'naked' attributes are not compatible}} expected-note {{conflicting attribute is here}}
+  __asm__("");
+}
+
+void __attribute__((naked,disable_tail_calls)) foo2(int a) { // expected-error {{'naked' and 'disable_tail_calls' attributes are not compatible}} expected-note {{conflicting attribute is here}}
+  __asm__("");
+}
+
+int g0 __attribute__((disable_tail_calls)); // expected-warning {{'disable_tail_calls' attribute only applies to functions and methods}}
+
+int foo3(int a) __attribute__((disable_tail_calls("abc"))); // expected-error {{'disable_tail_calls' attribute takes no arguments}}

Added: cfe/trunk/test/SemaCXX/attr-disable-tail-calls.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/attr-disable-tail-calls.cpp?rev=252986&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/attr-disable-tail-calls.cpp (added)
+++ cfe/trunk/test/SemaCXX/attr-disable-tail-calls.cpp Thu Nov 12 18:42:21 2015
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
+// expected-no-diagnostics
+
+class B {
+public:
+  [[clang::disable_tail_calls]] virtual int foo1() { return 1; }
+  [[clang::disable_tail_calls]] int foo2() { return 2; }
+};




More information about the cfe-commits mailing list