mirror of https://github.com/microsoft/clang.git
Implement the 'optnone' attribute, which suppresses most optimizations
on a function. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@205255 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
b1f71ddfcf
commit
8c03089bda
|
@ -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>;
|
||||
|
|
|
@ -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.
|
||||
}];
|
||||
}
|
||||
|
||||
|
|
|
@ -660,6 +660,10 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
|
|||
// 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::SetLLVMFunctionAttributesForDefinition(const Decl *D,
|
|||
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)
|
||||
|
|
|
@ -2972,6 +2972,26 @@ static void handleNoDebugAttr(Sema &S, Decl *D, const AttributeList &Attr) {
|
|||
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, Scope *scope, Decl *D,
|
|||
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, Scope *scope, Decl *D,
|
|||
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;
|
||||
|
|
|
@ -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
|
|
@ -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();
|
||||
};
|
||||
|
|
@ -8,6 +8,7 @@
|
|||
-(void) m0 __attribute__((noreturn));
|
||||
-(void) m1 __attribute__((unused));
|
||||
-(void) m2 __attribute__((stdcall));
|
||||
-(void) m3 __attribute__((optnone));
|
||||
@end
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue