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