r205255 - Implement the 'optnone' attribute, which suppresses most optimizations

Paul Robinson paul_robinson at playstation.sony.com
Mon Mar 31 15:29:16 PDT 2014


Author: probinson
Date: Mon Mar 31 17:29:15 2014
New Revision: 205255

URL: http://llvm.org/viewvc/llvm-project?rev=205255&view=rev
Log:
Implement the 'optnone' attribute, which suppresses most optimizations
on a function.

Added:
    cfe/trunk/test/CodeGen/attr-optnone.c
    cfe/trunk/test/SemaCXX/attr-optnone.cpp
Modified:
    cfe/trunk/include/clang/Basic/Attr.td
    cfe/trunk/include/clang/Basic/AttrDocs.td
    cfe/trunk/lib/CodeGen/CodeGenModule.cpp
    cfe/trunk/lib/Sema/SemaDeclAttr.cpp
    cfe/trunk/test/SemaObjC/method-attributes.m

Modified: cfe/trunk/include/clang/Basic/Attr.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=205255&r1=205254&r2=205255&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Attr.td (original)
+++ cfe/trunk/include/clang/Basic/Attr.td Mon Mar 31 17:29:15 2014
@@ -975,6 +975,12 @@ def ObjCDesignatedInitializer : Attr {
   let Documentation = [Undocumented];
 }
 
+def OptimizeNone : InheritableAttr {
+  let Spellings = [GNU<"optnone">, CXX11<"clang", "optnone">];
+  let Subjects = SubjectList<[Function, ObjCMethod]>;
+  let Documentation = [OptnoneDocs];
+}
+
 def Overloadable : Attr {
   let Spellings = [GNU<"overloadable">];
   let Subjects = SubjectList<[Function], ErrorDiag>;

Modified: cfe/trunk/include/clang/Basic/AttrDocs.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/AttrDocs.td?rev=205255&r1=205254&r2=205255&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/AttrDocs.td (original)
+++ cfe/trunk/include/clang/Basic/AttrDocs.td Mon Mar 31 17:29:15 2014
@@ -952,3 +952,19 @@ an error:
   struct S {};
 }];
 }
+
+def OptnoneDocs : Documentation {
+  let Category = DocCatFunction;
+  let Content = [{
+The ``optnone`` attribute suppresses essentially all optimizations
+on a function or method, regardless of the optimization level applied to
+the compilation unit as a whole.  This is particularly useful when you
+need to debug a particular function, but it is infeasible to build the
+entire application without optimization.  Avoiding optimization on the
+specified function can improve the quality of the debugging information
+for that function.
+
+This attribute is incompatible with the ``always_inline`` attribute.
+  }];
+}
+

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=205255&r1=205254&r2=205255&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Mon Mar 31 17:29:15 2014
@@ -660,6 +660,10 @@ void CodeGenModule::SetLLVMFunctionAttri
     // Naked implies noinline: we should not be inlining such functions.
     B.addAttribute(llvm::Attribute::Naked);
     B.addAttribute(llvm::Attribute::NoInline);
+  } else if (D->hasAttr<OptimizeNoneAttr>()) {
+    // OptimizeNone implies noinline; we should not be inlining such functions.
+    B.addAttribute(llvm::Attribute::OptimizeNone);
+    B.addAttribute(llvm::Attribute::NoInline);
   } else if (D->hasAttr<NoDuplicateAttr>()) {
     B.addAttribute(llvm::Attribute::NoDuplicate);
   } else if (D->hasAttr<NoInlineAttr>()) {
@@ -679,6 +683,12 @@ void CodeGenModule::SetLLVMFunctionAttri
   if (D->hasAttr<MinSizeAttr>())
     B.addAttribute(llvm::Attribute::MinSize);
 
+  if (D->hasAttr<OptimizeNoneAttr>()) {
+    // OptimizeNone wins over OptimizeForSize and MinSize.
+    B.removeAttribute(llvm::Attribute::OptimizeForSize);
+    B.removeAttribute(llvm::Attribute::MinSize);
+  }
+
   if (LangOpts.getStackProtector() == LangOptions::SSPOn)
     B.addAttribute(llvm::Attribute::StackProtect);
   else if (LangOpts.getStackProtector() == LangOptions::SSPStrong)

Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=205255&r1=205254&r2=205255&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Mon Mar 31 17:29:15 2014
@@ -2972,6 +2972,26 @@ static void handleNoDebugAttr(Sema &S, D
                          Attr.getAttributeSpellingListIndex()));
 }
 
+static void handleAlwaysInlineAttr(Sema &S, Decl *D,
+                                   const AttributeList &Attr) {
+  if (checkAttrMutualExclusion<OptimizeNoneAttr>(S, D, Attr))
+    return;
+
+  D->addAttr(::new (S.Context)
+             AlwaysInlineAttr(Attr.getRange(), S.Context,
+                              Attr.getAttributeSpellingListIndex()));
+}
+
+static void handleOptimizeNoneAttr(Sema &S, Decl *D,
+                                   const AttributeList &Attr) {
+  if (checkAttrMutualExclusion<AlwaysInlineAttr>(S, D, Attr))
+    return;
+
+  D->addAttr(::new (S.Context)
+             OptimizeNoneAttr(Attr.getRange(), S.Context,
+                              Attr.getAttributeSpellingListIndex()));
+}
+
 static void handleGlobalAttr(Sema &S, Decl *D, const AttributeList &Attr) {
   FunctionDecl *FD = cast<FunctionDecl>(D);
   if (!FD->getReturnType()->isVoidType()) {
@@ -4042,7 +4062,7 @@ static void ProcessDeclAttribute(Sema &S
     handleAlignedAttr(S, D, Attr);
     break;
   case AttributeList::AT_AlwaysInline:
-    handleSimpleAttribute<AlwaysInlineAttr>(S, D, Attr);
+    handleAlwaysInlineAttr(S, D, Attr);
     break;
   case AttributeList::AT_AnalyzerNoReturn:
     handleAnalyzerNoReturnAttr(S, D, Attr);
@@ -4086,6 +4106,9 @@ static void ProcessDeclAttribute(Sema &S
   case AttributeList::AT_MinSize:
     handleSimpleAttribute<MinSizeAttr>(S, D, Attr);
     break;
+  case AttributeList::AT_OptimizeNone:
+    handleOptimizeNoneAttr(S, D, Attr);
+    break;
   case AttributeList::AT_Format:
     handleFormatAttr(S, D, Attr);
     break;

Added: cfe/trunk/test/CodeGen/attr-optnone.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/attr-optnone.c?rev=205255&view=auto
==============================================================================
--- cfe/trunk/test/CodeGen/attr-optnone.c (added)
+++ cfe/trunk/test/CodeGen/attr-optnone.c Mon Mar 31 17:29:15 2014
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -emit-llvm < %s > %t
+// RUN: FileCheck %s --check-prefix=PRESENT < %t
+// RUN: FileCheck %s --check-prefix=ABSENT  < %t
+
+__attribute__((always_inline))
+int test2() { return 0; }
+// PRESENT-DAG: @test2{{.*}}[[ATTR2:#[0-9]+]]
+
+__attribute__((optnone)) __attribute__((minsize))
+int test3() { return 0; }
+// PRESENT-DAG: @test3{{.*}}[[ATTR3:#[0-9]+]]
+
+__attribute__((optnone)) __attribute__((cold))
+int test4() { return test2(); }
+// PRESENT-DAG: @test4{{.*}}[[ATTR4:#[0-9]+]]
+// Also check that test2 is inlined into test4 (always_inline still works).
+// PRESENT-DAG-NOT: call i32 @test2
+
+// Check for both noinline and optnone on each optnone function.
+// PRESENT-DAG: attributes [[ATTR3]] = { {{.*}}noinline{{.*}}optnone{{.*}} }
+// PRESENT-DAG: attributes [[ATTR4]] = { {{.*}}noinline{{.*}}optnone{{.*}} }
+
+// Check that no 'optsize' or 'minsize' attributes appear.
+// ABSENT-NOT: optsize
+// ABSENT-NOT: minsize

Added: cfe/trunk/test/SemaCXX/attr-optnone.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/attr-optnone.cpp?rev=205255&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/attr-optnone.cpp (added)
+++ cfe/trunk/test/SemaCXX/attr-optnone.cpp Mon Mar 31 17:29:15 2014
@@ -0,0 +1,47 @@
+// RUN: %clang_cc1 -std=c++11 -fms-compatibility -fsyntax-only -verify %s
+
+int foo() __attribute__((optnone));
+int bar() __attribute__((optnone)) __attribute__((noinline));
+
+int baz() __attribute__((always_inline)) __attribute__((optnone)); // expected-error{{'always_inline' and 'optnone' attributes are not compatible}}
+int quz() __attribute__((optnone)) __attribute__((always_inline)); // expected-error{{'optnone' and 'always_inline' attributes are not compatible}}
+
+__forceinline __attribute__((optnone)) int bax(); // expected-error{{'__forceinline' and 'optnone' attributes are not compatible}}
+__attribute__((optnone)) __forceinline int qux(); // expected-error{{'optnone' and '__forceinline' attributes are not compatible}}
+
+int globalVar __attribute__((optnone)); // expected-warning{{'optnone' attribute only applies to functions}}
+
+int fubar(int __attribute__((optnone)), int); // expected-warning{{'optnone' attribute only applies to functions}}
+
+struct A {
+  int aField __attribute__((optnone));  // expected-warning{{'optnone' attribute only applies to functions}}
+};
+
+struct B {
+  void foo() __attribute__((optnone));
+  static void bar() __attribute__((optnone));
+};
+
+// Verify that we can specify the [[clang::optnone]] syntax as well.
+
+[[clang::optnone]]
+int foo2();
+[[clang::optnone]]
+int bar2() __attribute__((noinline));
+
+[[clang::optnone]]
+int baz2() __attribute__((always_inline)); // expected-error{{'always_inline' and 'optnone' attributes are not compatible}}
+
+[[clang::optnone]] int globalVar2; //expected-warning{{'optnone' attribute only applies to functions}}
+
+struct A2 {
+  [[clang::optnone]] int aField; // expected-warning{{'optnone' attribute only applies to functions}}
+};
+
+struct B2 {
+  [[clang::optnone]]
+  void foo();
+  [[clang::optnone]]
+  static void bar();
+};
+

Modified: cfe/trunk/test/SemaObjC/method-attributes.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/method-attributes.m?rev=205255&r1=205254&r2=205255&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/method-attributes.m (original)
+++ cfe/trunk/test/SemaObjC/method-attributes.m Mon Mar 31 17:29:15 2014
@@ -8,6 +8,7 @@
 -(void) m0 __attribute__((noreturn));
 -(void) m1 __attribute__((unused));
 -(void) m2 __attribute__((stdcall));
+-(void) m3 __attribute__((optnone));
 @end
 
 





More information about the cfe-commits mailing list