r222683 - Correctly remove OptimizeForSize from functions marked OptimizeNone.

Paul Robinson paul_robinson at playstation.sony.com
Mon Nov 24 12:51:42 PST 2014


Author: probinson
Date: Mon Nov 24 14:51:42 2014
New Revision: 222683

URL: http://llvm.org/viewvc/llvm-project?rev=222683&view=rev
Log:
Correctly remove OptimizeForSize from functions marked OptimizeNone.
This allows using __attribute__((optnone)) and the -Os/-Oz options.
Fixes PR21604.

Added:
    cfe/trunk/test/CodeGenCXX/optnone-def-decl.cpp
Modified:
    cfe/trunk/lib/CodeGen/CodeGenModule.cpp
    cfe/trunk/test/CodeGen/attr-optnone.c

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=222683&r1=222682&r2=222683&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Mon Nov 24 14:51:42 2014
@@ -715,10 +715,6 @@ 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>()) {
@@ -738,12 +734,6 @@ 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)
@@ -772,6 +762,21 @@ void CodeGenModule::SetLLVMFunctionAttri
                    llvm::AttributeSet::get(
                        F->getContext(), llvm::AttributeSet::FunctionIndex, B));
 
+  if (D->hasAttr<OptimizeNoneAttr>()) {
+    // OptimizeNone implies noinline; we should not be inlining such functions.
+    F->addFnAttr(llvm::Attribute::OptimizeNone);
+    F->addFnAttr(llvm::Attribute::NoInline);
+
+    // OptimizeNone wins over OptimizeForSize, MinSize, AlwaysInline.
+    F->removeFnAttr(llvm::Attribute::OptimizeForSize);
+    F->removeFnAttr(llvm::Attribute::MinSize);
+    F->removeFnAttr(llvm::Attribute::AlwaysInline);
+
+    // Attribute 'inlinehint' has no effect on 'optnone' functions.
+    // Explicitly remove it from the set of function attributes.
+    F->removeFnAttr(llvm::Attribute::InlineHint);
+  }
+
   if (isa<CXXConstructorDecl>(D) || isa<CXXDestructorDecl>(D))
     F->setUnnamedAddr(true);
   else if (const auto *MD = dyn_cast<CXXMethodDecl>(D))

Modified: cfe/trunk/test/CodeGen/attr-optnone.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/attr-optnone.c?rev=222683&r1=222682&r2=222683&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/attr-optnone.c (original)
+++ cfe/trunk/test/CodeGen/attr-optnone.c Mon Nov 24 14:51:42 2014
@@ -1,10 +1,13 @@
 // RUN: %clang_cc1 -emit-llvm < %s > %t
 // RUN: FileCheck %s --check-prefix=PRESENT < %t
 // RUN: FileCheck %s --check-prefix=ABSENT  < %t
+// RUN: %clang_cc1 -emit-llvm -Os < %s > %t
+// RUN: FileCheck %s --check-prefix=PRESENT < %t
+// RUN: FileCheck %s --check-prefix=OPTSIZE < %t
 
 __attribute__((always_inline))
 int test2() { return 0; }
-// PRESENT-DAG: @test2{{.*}}[[ATTR2:#[0-9]+]]
+// OPTSIZE: @test2{{.*}}[[ATTR2:#[0-9]+]]
 
 __attribute__((optnone)) __attribute__((minsize))
 int test3() { return 0; }
@@ -23,3 +26,8 @@ int test4() { return test2(); }
 // Check that no 'optsize' or 'minsize' attributes appear.
 // ABSENT-NOT: optsize
 // ABSENT-NOT: minsize
+
+// With -Os, check that 'optsize' appears only on test2.
+// OPTSIZE-NOT: optsize
+// OPTSIZE: attributes [[ATTR2]] = { {{.*}}optsize{{.*}} }
+// OPTSIZE-NOT: optsize

Added: cfe/trunk/test/CodeGenCXX/optnone-def-decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/optnone-def-decl.cpp?rev=222683&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/optnone-def-decl.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/optnone-def-decl.cpp Mon Nov 24 14:51:42 2014
@@ -0,0 +1,94 @@
+// RUN: %clang_cc1 %s -triple %itanium_abi_triple -fms-extensions -emit-llvm -o - | FileCheck %s
+
+// Test optnone on both function declarations and function definitions.
+// Verify also that we don't generate invalid IR functions with
+// both alwaysinline and noinline. (optnone implies noinline and wins
+// over alwaysinline, in all cases.)
+
+// Test optnone on extern declaration only.
+extern int decl_only(int a) __attribute__((optnone));
+
+// This function should be marked 'optnone'.
+int decl_only(int a) {
+  return a + a + a + a;
+}
+
+// CHECK: define i32 @_Z9decl_onlyi(i32 %a) [[OPTNONE:#[0-9]+]]
+
+// Test optnone on definition but not extern declaration.
+extern int def_only(int a);
+
+__attribute__((optnone))
+int def_only(int a) {
+  return a + a + a + a;
+}
+
+// Function def_only is a optnone function and therefore it should not be
+// inlined inside 'user_of_def_only'.
+int user_of_def_only() {
+  return def_only(5);
+}
+
+// CHECK: define i32 @_Z8def_onlyi(i32 %a) [[OPTNONE]]
+// CHECK: define i32 @_Z16user_of_def_onlyv() [[NORMAL:#[0-9]+]]
+
+// Test optnone on both definition and declaration.
+extern int def_and_decl(int a) __attribute__((optnone));
+
+__attribute__((optnone))
+int def_and_decl(int a) {
+  return a + a + a + a;
+}
+
+// CHECK: define i32 @_Z12def_and_decli(i32 %a) [[OPTNONE]]
+
+// Check that optnone wins over always_inline.
+
+// Test optnone on definition and always_inline on declaration.
+extern int always_inline_function(int a) __attribute__((always_inline));
+
+__attribute__((optnone))
+extern int always_inline_function(int a) {
+  return a + a + a + a;
+}
+// CHECK: define i32 @_Z22always_inline_functioni(i32 %a) [[OPTNONE]]
+
+int user_of_always_inline_function() {
+  return always_inline_function(4);
+}
+
+// CHECK: define i32 @_Z30user_of_always_inline_functionv() [[NORMAL]]
+
+// Test optnone on declaration and always_inline on definition.
+extern int optnone_function(int a) __attribute__((optnone));
+
+__attribute__((always_inline))
+int optnone_function(int a) {
+  return a + a + a + a;
+}
+// CHECK: define i32 @_Z16optnone_functioni(i32 %a) [[OPTNONE]]
+
+int user_of_optnone_function() {
+  return optnone_function(4);
+}
+
+// CHECK: define i32 @_Z24user_of_optnone_functionv() [[NORMAL]]
+
+// Test the combination of optnone with forceinline (optnone wins).
+extern __forceinline int forceinline_optnone_function(int a, int b);
+
+__attribute__((optnone))
+extern int forceinline_optnone_function(int a, int b) {
+    return a + b;
+}
+
+int user_of_forceinline_optnone_function() {
+    return forceinline_optnone_function(4,5);
+}
+
+// CHECK: @_Z36user_of_forceinline_optnone_functionv() [[NORMAL]]
+// CHECK: @_Z28forceinline_optnone_functionii(i32 %a, i32 %b) [[OPTNONE]]
+
+// CHECK: attributes [[OPTNONE]] = { noinline nounwind optnone {{.*}} }
+// CHECK: attributes [[NORMAL]] = { nounwind {{.*}} }
+





More information about the cfe-commits mailing list