forked from OSchip/llvm-project
Implemented support for "pragma clang optimize on/off", based on attribute 'optnone'.
This patch implements support for selectively disabling optimizations on a range of function definitions through a pragma. The implementation is that all function definitions in the range are decorated with attribute 'optnone'. #pragma clang optimize off // All function definitions in here are decorated with 'optnone'. #pragma clang optimize on // Compilation resumes as normal. llvm-svn: 209510
This commit is contained in:
parent
e1e9a4e2ec
commit
13a0a38fe0
|
@ -843,6 +843,14 @@ def err_pragma_detect_mismatch_malformed : Error<
|
||||||
def err_pragma_pointers_to_members_unknown_kind : Error<
|
def err_pragma_pointers_to_members_unknown_kind : Error<
|
||||||
"unexpected %0, expected to see one of %select{|'best_case', 'full_generality', }1"
|
"unexpected %0, expected to see one of %select{|'best_case', 'full_generality', }1"
|
||||||
"'single_inheritance', 'multiple_inheritance', or 'virtual_inheritance'">;
|
"'single_inheritance', 'multiple_inheritance', or 'virtual_inheritance'">;
|
||||||
|
// - #pragma clang optimize on/off
|
||||||
|
def err_pragma_optimize_missing_argument : Error<
|
||||||
|
"missing argument to '#pragma clang optimize'; expected 'on' or 'off'">;
|
||||||
|
def err_pragma_optimize_invalid_argument : Error<
|
||||||
|
"unexpected argument '%0' to '#pragma clang optimize'; "
|
||||||
|
"expected 'on' or 'off'">;
|
||||||
|
def err_pragma_optimize_extra_argument : Error<
|
||||||
|
"unexpected extra argument '%0' to '#pragma clang optimize'">;
|
||||||
|
|
||||||
// OpenCL Section 6.8.g
|
// OpenCL Section 6.8.g
|
||||||
def err_not_opencl_storage_class_specifier : Error<
|
def err_not_opencl_storage_class_specifier : Error<
|
||||||
|
|
|
@ -160,6 +160,7 @@ class Parser : public CodeCompletionHandler {
|
||||||
std::unique_ptr<PragmaHandler> MSConstSeg;
|
std::unique_ptr<PragmaHandler> MSConstSeg;
|
||||||
std::unique_ptr<PragmaHandler> MSCodeSeg;
|
std::unique_ptr<PragmaHandler> MSCodeSeg;
|
||||||
std::unique_ptr<PragmaHandler> MSSection;
|
std::unique_ptr<PragmaHandler> MSSection;
|
||||||
|
std::unique_ptr<PragmaHandler> OptimizeHandler;
|
||||||
|
|
||||||
std::unique_ptr<CommentHandler> CommentSemaHandler;
|
std::unique_ptr<CommentHandler> CommentSemaHandler;
|
||||||
|
|
||||||
|
|
|
@ -333,6 +333,11 @@ public:
|
||||||
/// VisContext - Manages the stack for \#pragma GCC visibility.
|
/// VisContext - Manages the stack for \#pragma GCC visibility.
|
||||||
void *VisContext; // Really a "PragmaVisStack*"
|
void *VisContext; // Really a "PragmaVisStack*"
|
||||||
|
|
||||||
|
/// \brief This represents the last location of a "#pragma clang optimize off"
|
||||||
|
/// directive if such a directive has not been closed by an "on" yet. If
|
||||||
|
/// optimizations are currently "on", this is set to an invalid location.
|
||||||
|
SourceLocation OptimizeOffPragmaLocation;
|
||||||
|
|
||||||
/// \brief Flag indicating if Sema is building a recovery call expression.
|
/// \brief Flag indicating if Sema is building a recovery call expression.
|
||||||
///
|
///
|
||||||
/// This flag is used to avoid building recovery call expressions
|
/// This flag is used to avoid building recovery call expressions
|
||||||
|
@ -7231,6 +7236,25 @@ public:
|
||||||
/// the appropriate attribute.
|
/// the appropriate attribute.
|
||||||
void AddCFAuditedAttribute(Decl *D);
|
void AddCFAuditedAttribute(Decl *D);
|
||||||
|
|
||||||
|
/// \brief Called on well formed \#pragma clang optimize.
|
||||||
|
void ActOnPragmaOptimize(bool On, SourceLocation PragmaLoc);
|
||||||
|
|
||||||
|
/// \brief Get the location for the currently active "\#pragma clang optimize
|
||||||
|
/// off". If this location is invalid, then the state of the pragma is "on".
|
||||||
|
SourceLocation getOptimizeOffPragmaLocation() const {
|
||||||
|
return OptimizeOffPragmaLocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Only called on function definitions; if there is a pragma in scope
|
||||||
|
/// with the effect of a range-based optnone, consider marking the function
|
||||||
|
/// with attribute optnone.
|
||||||
|
void AddRangeBasedOptnone(FunctionDecl *FD);
|
||||||
|
|
||||||
|
/// \brief Adds the 'optnone' attribute to the function declaration if there
|
||||||
|
/// are no conflicts; Loc represents the location causing the 'optnone'
|
||||||
|
/// attribute to be added (usually because of a pragma).
|
||||||
|
void AddOptnoneAttributeIfNoConflicts(FunctionDecl *FD, SourceLocation Loc);
|
||||||
|
|
||||||
/// AddAlignedAttr - Adds an aligned attribute to a particular declaration.
|
/// AddAlignedAttr - Adds an aligned attribute to a particular declaration.
|
||||||
void AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E,
|
void AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E,
|
||||||
unsigned SpellingListIndex, bool IsPackExpansion);
|
unsigned SpellingListIndex, bool IsPackExpansion);
|
||||||
|
|
|
@ -542,7 +542,10 @@ namespace clang {
|
||||||
UNDEFINED_BUT_USED = 49,
|
UNDEFINED_BUT_USED = 49,
|
||||||
|
|
||||||
/// \brief Record code for late parsed template functions.
|
/// \brief Record code for late parsed template functions.
|
||||||
LATE_PARSED_TEMPLATE = 50
|
LATE_PARSED_TEMPLATE = 50,
|
||||||
|
|
||||||
|
/// \brief Record code for \#pragma optimize options.
|
||||||
|
OPTIMIZE_PRAGMA_OPTIONS = 51
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief Record types used within a source manager block.
|
/// \brief Record types used within a source manager block.
|
||||||
|
|
|
@ -768,6 +768,9 @@ private:
|
||||||
/// \brief The floating point pragma option settings.
|
/// \brief The floating point pragma option settings.
|
||||||
SmallVector<uint64_t, 1> FPPragmaOptions;
|
SmallVector<uint64_t, 1> FPPragmaOptions;
|
||||||
|
|
||||||
|
/// \brief The pragma clang optimize location (if the pragma state is "off").
|
||||||
|
SourceLocation OptimizeOffPragmaLocation;
|
||||||
|
|
||||||
/// \brief The OpenCL extension settings.
|
/// \brief The OpenCL extension settings.
|
||||||
SmallVector<uint64_t, 1> OpenCLExtensions;
|
SmallVector<uint64_t, 1> OpenCLExtensions;
|
||||||
|
|
||||||
|
|
|
@ -488,6 +488,7 @@ private:
|
||||||
void WriteRedeclarations();
|
void WriteRedeclarations();
|
||||||
void WriteMergedDecls();
|
void WriteMergedDecls();
|
||||||
void WriteLateParsedTemplates(Sema &SemaRef);
|
void WriteLateParsedTemplates(Sema &SemaRef);
|
||||||
|
void WriteOptimizePragmaOptions(Sema &SemaRef);
|
||||||
|
|
||||||
unsigned DeclParmVarAbbrev;
|
unsigned DeclParmVarAbbrev;
|
||||||
unsigned DeclContextLexicalAbbrev;
|
unsigned DeclContextLexicalAbbrev;
|
||||||
|
|
|
@ -131,6 +131,16 @@ struct PragmaMSPragma : public PragmaHandler {
|
||||||
Token &FirstToken) override;
|
Token &FirstToken) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// PragmaOptimizeHandler - "\#pragma clang optimize on/off".
|
||||||
|
struct PragmaOptimizeHandler : public PragmaHandler {
|
||||||
|
PragmaOptimizeHandler(Sema &S)
|
||||||
|
: PragmaHandler("optimize"), Actions(S) {}
|
||||||
|
void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
|
||||||
|
Token &FirstToken) override;
|
||||||
|
private:
|
||||||
|
Sema &Actions;
|
||||||
|
};
|
||||||
|
|
||||||
} // end namespace
|
} // end namespace
|
||||||
|
|
||||||
void Parser::initializePragmaHandlers() {
|
void Parser::initializePragmaHandlers() {
|
||||||
|
@ -195,6 +205,9 @@ void Parser::initializePragmaHandlers() {
|
||||||
MSSection.reset(new PragmaMSPragma("section"));
|
MSSection.reset(new PragmaMSPragma("section"));
|
||||||
PP.AddPragmaHandler(MSSection.get());
|
PP.AddPragmaHandler(MSSection.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OptimizeHandler.reset(new PragmaOptimizeHandler(Actions));
|
||||||
|
PP.AddPragmaHandler("clang", OptimizeHandler.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Parser::resetPragmaHandlers() {
|
void Parser::resetPragmaHandlers() {
|
||||||
|
@ -249,6 +262,9 @@ void Parser::resetPragmaHandlers() {
|
||||||
|
|
||||||
PP.RemovePragmaHandler("STDC", FPContractHandler.get());
|
PP.RemovePragmaHandler("STDC", FPContractHandler.get());
|
||||||
FPContractHandler.reset();
|
FPContractHandler.reset();
|
||||||
|
|
||||||
|
PP.RemovePragmaHandler("clang", OptimizeHandler.get());
|
||||||
|
OptimizeHandler.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Handle the annotation token produced for #pragma unused(...)
|
/// \brief Handle the annotation token produced for #pragma unused(...)
|
||||||
|
@ -1531,3 +1547,40 @@ void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
|
||||||
|
|
||||||
Actions.ActOnPragmaMSComment(Kind, ArgumentString);
|
Actions.ActOnPragmaMSComment(Kind, ArgumentString);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #pragma clang optimize off
|
||||||
|
// #pragma clang optimize on
|
||||||
|
void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP,
|
||||||
|
PragmaIntroducerKind Introducer,
|
||||||
|
Token &FirstToken) {
|
||||||
|
Token Tok;
|
||||||
|
PP.Lex(Tok);
|
||||||
|
if (Tok.is(tok::eod)) {
|
||||||
|
PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_missing_argument);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (Tok.isNot(tok::identifier)) {
|
||||||
|
PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
|
||||||
|
<< PP.getSpelling(Tok);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const IdentifierInfo *II = Tok.getIdentifierInfo();
|
||||||
|
// The only accepted values are 'on' or 'off'.
|
||||||
|
bool IsOn = false;
|
||||||
|
if (II->isStr("on")) {
|
||||||
|
IsOn = true;
|
||||||
|
} else if (!II->isStr("off")) {
|
||||||
|
PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
|
||||||
|
<< PP.getSpelling(Tok);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
PP.Lex(Tok);
|
||||||
|
|
||||||
|
if (Tok.isNot(tok::eod)) {
|
||||||
|
PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_extra_argument)
|
||||||
|
<< PP.getSpelling(Tok);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Actions.ActOnPragmaOptimize(IsOn, FirstToken.getLocation());
|
||||||
|
}
|
||||||
|
|
|
@ -470,6 +470,34 @@ void Sema::AddCFAuditedAttribute(Decl *D) {
|
||||||
D->addAttr(CFAuditedTransferAttr::CreateImplicit(Context, Loc));
|
D->addAttr(CFAuditedTransferAttr::CreateImplicit(Context, Loc));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Sema::ActOnPragmaOptimize(bool On, SourceLocation PragmaLoc) {
|
||||||
|
if(On)
|
||||||
|
OptimizeOffPragmaLocation = SourceLocation();
|
||||||
|
else
|
||||||
|
OptimizeOffPragmaLocation = PragmaLoc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sema::AddRangeBasedOptnone(FunctionDecl *FD) {
|
||||||
|
// In the future, check other pragmas if they're implemented (e.g. pragma
|
||||||
|
// optimize 0 will probably map to this functionality too).
|
||||||
|
if(OptimizeOffPragmaLocation.isValid())
|
||||||
|
AddOptnoneAttributeIfNoConflicts(FD, OptimizeOffPragmaLocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sema::AddOptnoneAttributeIfNoConflicts(FunctionDecl *FD,
|
||||||
|
SourceLocation Loc) {
|
||||||
|
// Don't add a conflicting attribute. No diagnostic is needed.
|
||||||
|
if (FD->hasAttr<MinSizeAttr>() || FD->hasAttr<AlwaysInlineAttr>())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Add attributes only if required. Optnone requires noinline as well, but if
|
||||||
|
// either is already present then don't bother adding them.
|
||||||
|
if (!FD->hasAttr<OptimizeNoneAttr>())
|
||||||
|
FD->addAttr(OptimizeNoneAttr::CreateImplicit(Context, Loc));
|
||||||
|
if (!FD->hasAttr<NoInlineAttr>())
|
||||||
|
FD->addAttr(NoInlineAttr::CreateImplicit(Context, Loc));
|
||||||
|
}
|
||||||
|
|
||||||
typedef std::vector<std::pair<unsigned, SourceLocation> > VisStack;
|
typedef std::vector<std::pair<unsigned, SourceLocation> > VisStack;
|
||||||
enum : unsigned { NoVisibility = ~0U };
|
enum : unsigned { NoVisibility = ~0U };
|
||||||
|
|
||||||
|
|
|
@ -7373,6 +7373,11 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
||||||
// marking the function.
|
// marking the function.
|
||||||
AddCFAuditedAttribute(NewFD);
|
AddCFAuditedAttribute(NewFD);
|
||||||
|
|
||||||
|
// If this is a function definition, check if we have to apply optnone due to
|
||||||
|
// a pragma.
|
||||||
|
if(D.isFunctionDefinition())
|
||||||
|
AddRangeBasedOptnone(NewFD);
|
||||||
|
|
||||||
// If this is the first declaration of an extern C variable, update
|
// If this is the first declaration of an extern C variable, update
|
||||||
// the map of such variables.
|
// the map of such variables.
|
||||||
if (NewFD->isFirstDecl() && !NewFD->isInvalidDecl() &&
|
if (NewFD->isFirstDecl() && !NewFD->isInvalidDecl() &&
|
||||||
|
|
|
@ -3281,6 +3281,14 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
|
||||||
LateParsedTemplates.append(Record.begin(), Record.end());
|
LateParsedTemplates.append(Record.begin(), Record.end());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case OPTIMIZE_PRAGMA_OPTIONS:
|
||||||
|
if (Record.size() != 1) {
|
||||||
|
Error("invalid pragma optimize record");
|
||||||
|
return Failure;
|
||||||
|
}
|
||||||
|
OptimizeOffPragmaLocation = ReadSourceLocation(F, Record[0]);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6808,6 +6816,11 @@ void ASTReader::UpdateSema() {
|
||||||
}
|
}
|
||||||
SemaDeclRefs.clear();
|
SemaDeclRefs.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update the state of 'pragma clang optimize'. Use the same API as if we had
|
||||||
|
// encountered the pragma in the source.
|
||||||
|
if(OptimizeOffPragmaLocation.isValid())
|
||||||
|
SemaObj->ActOnPragmaOptimize(/* IsOn = */ false, OptimizeOffPragmaLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
IdentifierInfo* ASTReader::get(const char *NameStart, const char *NameEnd) {
|
IdentifierInfo* ASTReader::get(const char *NameStart, const char *NameEnd) {
|
||||||
|
|
|
@ -866,6 +866,7 @@ void ASTWriter::WriteBlockInfoBlock() {
|
||||||
RECORD(MACRO_OFFSET);
|
RECORD(MACRO_OFFSET);
|
||||||
RECORD(MACRO_TABLE);
|
RECORD(MACRO_TABLE);
|
||||||
RECORD(LATE_PARSED_TEMPLATE);
|
RECORD(LATE_PARSED_TEMPLATE);
|
||||||
|
RECORD(OPTIMIZE_PRAGMA_OPTIONS);
|
||||||
|
|
||||||
// SourceManager Block.
|
// SourceManager Block.
|
||||||
BLOCK(SOURCE_MANAGER_BLOCK);
|
BLOCK(SOURCE_MANAGER_BLOCK);
|
||||||
|
@ -3850,6 +3851,14 @@ void ASTWriter::WriteLateParsedTemplates(Sema &SemaRef) {
|
||||||
Stream.EmitRecord(LATE_PARSED_TEMPLATE, Record);
|
Stream.EmitRecord(LATE_PARSED_TEMPLATE, Record);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief Write the state of 'pragma clang optimize' at the end of the module.
|
||||||
|
void ASTWriter::WriteOptimizePragmaOptions(Sema &SemaRef) {
|
||||||
|
RecordData Record;
|
||||||
|
SourceLocation PragmaLoc = SemaRef.getOptimizeOffPragmaLocation();
|
||||||
|
AddSourceLocation(PragmaLoc, Record);
|
||||||
|
Stream.EmitRecord(OPTIMIZE_PRAGMA_OPTIONS, Record);
|
||||||
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// General Serialization Routines
|
// General Serialization Routines
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
@ -4466,6 +4475,8 @@ void ASTWriter::WriteASTCore(Sema &SemaRef,
|
||||||
WriteMergedDecls();
|
WriteMergedDecls();
|
||||||
WriteObjCCategories();
|
WriteObjCCategories();
|
||||||
WriteLateParsedTemplates(SemaRef);
|
WriteLateParsedTemplates(SemaRef);
|
||||||
|
if(!WritingModule)
|
||||||
|
WriteOptimizePragmaOptions(SemaRef);
|
||||||
|
|
||||||
// Some simple statistics
|
// Some simple statistics
|
||||||
Record.clear();
|
Record.clear();
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
// Test this without pch.
|
||||||
|
// RUN: %clang_cc1 %s -include %s -verify -fsyntax-only
|
||||||
|
|
||||||
|
// Test with pch.
|
||||||
|
// RUN: %clang_cc1 %s -emit-pch -o %t
|
||||||
|
// RUN: %clang_cc1 %s -emit-llvm -include-pch %t -o - | FileCheck %s
|
||||||
|
|
||||||
|
// expected-no-diagnostics
|
||||||
|
|
||||||
|
#ifndef HEADER
|
||||||
|
#define HEADER
|
||||||
|
#pragma clang optimize off
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
int a;
|
||||||
|
|
||||||
|
void f() {
|
||||||
|
a = 12345;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that the function is decorated with optnone
|
||||||
|
|
||||||
|
// CHECK-DAG: @f() [[ATTRF:#[0-9]+]]
|
||||||
|
// CHECK-DAG: attributes [[ATTRF]] = { {{.*}}noinline{{.*}}optnone{{.*}} }
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,28 @@
|
||||||
|
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
||||||
|
|
||||||
|
#pragma clang optimize off
|
||||||
|
|
||||||
|
#pragma clang optimize on
|
||||||
|
|
||||||
|
// Extra arguments
|
||||||
|
#pragma clang optimize on top of spaghetti // expected-error {{unexpected extra argument 'top' to '#pragma clang optimize'}}
|
||||||
|
|
||||||
|
// Wrong argument
|
||||||
|
#pragma clang optimize something_wrong // expected-error {{unexpected argument 'something_wrong' to '#pragma clang optimize'; expected 'on' or 'off'}}
|
||||||
|
|
||||||
|
// No argument
|
||||||
|
#pragma clang optimize // expected-error {{missing argument to '#pragma clang optimize'; expected 'on' or 'off'}}
|
||||||
|
|
||||||
|
// Check that macros can be used in the pragma
|
||||||
|
#define OFF off
|
||||||
|
#define ON on
|
||||||
|
#pragma clang optimize OFF
|
||||||
|
#pragma clang optimize ON
|
||||||
|
|
||||||
|
// Check that _Pragma can also be used to address the use case where users want
|
||||||
|
// to define optimization control macros to abstract out which compiler they are
|
||||||
|
// using.
|
||||||
|
#define OPT_OFF _Pragma("clang optimize off")
|
||||||
|
#define OPT_ON _Pragma("clang optimize on")
|
||||||
|
OPT_OFF
|
||||||
|
OPT_ON
|
|
@ -0,0 +1,113 @@
|
||||||
|
// RUN: %clang_cc1 -x c++ -std=c++11 -emit-llvm -O2 < %s | FileCheck %s
|
||||||
|
|
||||||
|
#pragma clang optimize off
|
||||||
|
|
||||||
|
// This is a macro definition and therefore its text is not present after
|
||||||
|
// preprocessing. The pragma has no effect here.
|
||||||
|
#define CREATE_FUNC(name) \
|
||||||
|
int name (int param) { \
|
||||||
|
return param; \
|
||||||
|
} \
|
||||||
|
|
||||||
|
// This is a declaration and therefore it is not decorated with `optnone`.
|
||||||
|
extern int foo(int a, int b);
|
||||||
|
// CHECK-DAG: @_Z3fooii{{.*}} [[ATTRFOO:#[0-9]+]]
|
||||||
|
|
||||||
|
// This is a definition and therefore it will be decorated with `optnone`.
|
||||||
|
int bar(int x, int y) {
|
||||||
|
for(int i = 0; i < x; ++i)
|
||||||
|
y += x;
|
||||||
|
return y + foo(x, y);
|
||||||
|
}
|
||||||
|
// CHECK-DAG: @_Z3barii{{.*}} [[ATTRBAR:#[0-9]+]]
|
||||||
|
|
||||||
|
// The function "int created (int param)" created by the macro invocation
|
||||||
|
// is also decorated with the `optnone` attribute because it is within a
|
||||||
|
// region of code affected by the functionality (not because of the position
|
||||||
|
// of the macro definition).
|
||||||
|
CREATE_FUNC (created)
|
||||||
|
// CHECK-DAG: @_Z7createdi{{.*}} [[ATTRCREATED:#[0-9]+]]
|
||||||
|
|
||||||
|
class MyClass {
|
||||||
|
public:
|
||||||
|
// The declaration of the method is not decorated with `optnone`.
|
||||||
|
int method(int blah);
|
||||||
|
};
|
||||||
|
|
||||||
|
// The definition of the method instead is decorated with `optnone`.
|
||||||
|
int MyClass::method(int blah) {
|
||||||
|
return blah + 1;
|
||||||
|
}
|
||||||
|
// CHECK-DAG: @_ZN7MyClass6methodEi{{.*}} [[ATTRMETHOD:#[0-9]+]]
|
||||||
|
|
||||||
|
// A template declaration will not be decorated with `optnone`.
|
||||||
|
template <typename T> T twice (T param);
|
||||||
|
|
||||||
|
// The template definition will be decorated with the attribute `optnone`.
|
||||||
|
template <typename T> T thrice (T param) {
|
||||||
|
return 3 * param;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function definition will not be decorated with `optnone` because the
|
||||||
|
// attribute would conflict with `always_inline`.
|
||||||
|
int __attribute__((always_inline)) baz(int z) {
|
||||||
|
return foo(z, 2);
|
||||||
|
}
|
||||||
|
// CHECK-DAG: @_Z3bazi{{.*}} [[ATTRBAZ:#[0-9]+]]
|
||||||
|
|
||||||
|
#pragma clang optimize on
|
||||||
|
|
||||||
|
// The function "int wombat(int param)" created by the macro is not
|
||||||
|
// decorated with `optnone`, because the pragma applies its effects only
|
||||||
|
// after preprocessing. The position of the macro definition is not
|
||||||
|
// relevant.
|
||||||
|
CREATE_FUNC (wombat)
|
||||||
|
// CHECK-DAG: @_Z6wombati{{.*}} [[ATTRWOMBAT:#[0-9]+]]
|
||||||
|
|
||||||
|
// This instantiation of the "twice" template function with a "float" type
|
||||||
|
// will not have an `optnone` attribute because the template declaration was
|
||||||
|
// not affected by the pragma.
|
||||||
|
float container (float par) {
|
||||||
|
return twice(par);
|
||||||
|
}
|
||||||
|
// CHECK-DAG: @_Z9containerf{{.*}} [[ATTRCONTAINER:#[0-9]+]]
|
||||||
|
// CHECK-DAG: @_Z5twiceIfET_S0_{{.*}} [[ATTRTWICE:#[0-9]+]]
|
||||||
|
|
||||||
|
// This instantiation of the "thrice" template function with a "float" type
|
||||||
|
// will have an `optnone` attribute because the template definition was
|
||||||
|
// affected by the pragma.
|
||||||
|
float container2 (float par) {
|
||||||
|
return thrice(par);
|
||||||
|
}
|
||||||
|
// CHECK-DAG: @_Z10container2f{{.*}} [[ATTRCONTAINER2:#[0-9]+]]
|
||||||
|
// CHECK-DAG: @_Z6thriceIfET_S0_{{.*}} [[ATTRTHRICEFLOAT:#[0-9]+]]
|
||||||
|
|
||||||
|
|
||||||
|
// A template specialization is a new definition and it will not be
|
||||||
|
// decorated with an `optnone` attribute because it is now outside of the
|
||||||
|
// affected region.
|
||||||
|
template<> int thrice(int par) {
|
||||||
|
return (par << 1) + par;
|
||||||
|
}
|
||||||
|
int container3 (int par) {
|
||||||
|
return thrice(par);
|
||||||
|
}
|
||||||
|
// CHECK-DAG: @_Z10container3i{{.*}} [[ATTRCONTAINER3:#[0-9]+]]
|
||||||
|
// CHECK-DAG: @_Z6thriceIiET_S0_{{.*}} [[ATTRTHRICEINT:#[0-9]+]]
|
||||||
|
|
||||||
|
|
||||||
|
// Check for both noinline and optnone on each function that should have them.
|
||||||
|
// CHECK-DAG: attributes [[ATTRBAR]] = { {{.*}}noinline{{.*}}optnone{{.*}} }
|
||||||
|
// CHECK-DAG: attributes [[ATTRCREATED]] = { {{.*}}noinline{{.*}}optnone{{.*}} }
|
||||||
|
// CHECK-DAG: attributes [[ATTRMETHOD]] = { {{.*}}noinline{{.*}}optnone{{.*}} }
|
||||||
|
// CHECK-DAG: attributes [[ATTRTHRICEFLOAT]] = { {{.*}}noinline{{.*}}optnone{{.*}} }
|
||||||
|
|
||||||
|
// Check that the other functions do NOT have optnone.
|
||||||
|
// CHECK-DAG-NOT: attributes [[ATTRFOO]] = { {{.*}}optnone{{.*}} }
|
||||||
|
// CHECK-DAG-NOT: attributes [[ATTRBAZ]] = { {{.*}}optnone{{.*}} }
|
||||||
|
// CHECK-DAG-NOT: attributes [[ATTRWOMBAT]] = { {{.*}}optnone{{.*}} }
|
||||||
|
// CHECK-DAG-NOT: attributes [[ATTRCONTAINER]] = { {{.*}}optnone{{.*}} }
|
||||||
|
// CHECK-DAG-NOT: attributes [[ATTRTWICE]] = { {{.*}}optnone{{.*}} }
|
||||||
|
// CHECK-DAG-NOT: attributes [[ATTRCONTAINER2]] = { {{.*}}optnone{{.*}} }
|
||||||
|
// CHECK-DAG-NOT: attributes [[ATTRCONTAINER3]] = { {{.*}}optnone{{.*}} }
|
||||||
|
// CHECK-DAG-NOT: attributes [[ATTRTHRICEINT]] = { {{.*}}optnone{{.*}} }
|
Loading…
Reference in New Issue