steplong created this revision. Herald added a reviewer: aaron.ballman. Herald added a project: All. steplong requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
At the moment, it only supports a string argument that refers to the optimization level. "-f" arguments aren't supported. The argument must begin with "O" or "-O". Also, only non-negative optimization levels and "-Os" are accepted. Only "-Os" and "-O0" currently affect codegen. i.e. __attribute__((optimize("O0"))) Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D126984 Files: clang/include/clang/Basic/Attr.td clang/include/clang/Basic/DiagnosticSemaKinds.td clang/lib/CodeGen/CGCall.cpp clang/lib/CodeGen/CodeGenModule.cpp clang/lib/CodeGen/CodeGenModule.h clang/lib/Sema/SemaDeclAttr.cpp clang/test/CodeGen/attr-optimize.c clang/test/Sema/attr-optimize.c
Index: clang/test/Sema/attr-optimize.c =================================================================== --- /dev/null +++ clang/test/Sema/attr-optimize.c @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 -verify -fsyntax-only %s + +__attribute__((optimize(a))) // expected-error {{use of undeclared identifier 'a'}} +void f1() {} + +int b = 1; +__attribute__((optimize(b))) // expected-error {{'optimize' attribute requires a string}} +void f2() {} + +__attribute__((optimize("O0", "O1"))) // expected-error {{'optimize' attribute takes one argument}} +void f3() {} + +__attribute__((optimize("Og"))) // expected-error {{argument to '-O' should be non-negative integer or 's'}} +void f4() {} + +__attribute__((optimize("O-1"))) // expected-error {{argument to '-O' should be non-negative integer or 's'}} +void f5() {} + +__attribute__((optimize("O+1"))) // expected-error {{argument to '-O' should be non-negative integer or 's'}} +void f6() {} + +__attribute__((optimize("O0"))) // expected-no-error +void f7() {} + +__attribute__((optimize("Os"))) // expected-no-error +void f8() {} + +__attribute__((optimize("O44"))) // expected-no-error +void f9() {} + +__attribute__((optimize("O0"))) // expected-error {{expected identifier or '('}} Index: clang/test/CodeGen/attr-optimize.c =================================================================== --- /dev/null +++ clang/test/CodeGen/attr-optimize.c @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -O2 -S -emit-llvm %s -o - | FileCheck %s --check-prefix=O2 +// RUN: %clang_cc1 -O0 -S -emit-llvm %s -o - | FileCheck %s --check-prefix=O0 + +__attribute__((optimize("O0"))) void f1(void) {} +// O2: @f1{{.*}}[[ATTR1:#[0-9]+]] +// O0: @f1{{.*}}[[ATTR1:#[0-9]+]] + +__attribute__((optimize("Os"))) void f2(void) {} +// O2: @f2{{.*}}[[ATTR2:#[0-9]+]] +// O0: @f2{{.*}}[[ATTR1]] + +// O2: attributes [[ATTR1]] = { {{.*}}optnone{{.*}} } +// O2: attributes [[ATTR2]] = { {{.*}}optsize{{.*}} } + +// Check that O0 overrides the attribute +// O0: attributes [[ATTR1]] = { {{.*}}optnone{{.*}} } Index: clang/lib/Sema/SemaDeclAttr.cpp =================================================================== --- clang/lib/Sema/SemaDeclAttr.cpp +++ clang/lib/Sema/SemaDeclAttr.cpp @@ -4833,6 +4833,43 @@ D->addAttr(Optnone); } +static void handleOptimizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { + StringRef Arg; + if (!S.checkStringLiteralArgumentAttr(AL, 0, Arg)) + return; + + StringRef Level; + // Check if argument is prefixed with "-O" or "O" + if (Arg.str().rfind("-O", 0) == 0) + Level = Arg.substr(2); + else if (Arg.str().rfind("O", 0) == 0) + Level = Arg.substr(1); + else + S.Diag(AL.getLoc(), diag::err_attribute_only_allowed_with_argument) + << "-O" + << "non-negative integer or 's'"; + + llvm::APInt Num; + bool IsNum = !Level.getAsInteger(10, Num); + + if (Level == "" || (IsNum && Num == 0)) { + D->addAttr(::new (S.Context) OptimizeAttr(S.Context, AL, "0")); + return; + } else if (Level == "s") { + D->addAttr(::new (S.Context) OptimizeAttr(S.Context, AL, "s")); + return; + } else if (IsNum) { + // Limit level to -O3 if higher + std::string Level = std::to_string(Num.getLimitedValue(3)); + D->addAttr(::new (S.Context) OptimizeAttr(S.Context, AL, Level)); + return; + } + + S.Diag(AL.getLoc(), diag::err_attribute_only_allowed_with_argument) + << "-O" + << "non-negative integer or 's'"; +} + static void handleConstantAttr(Sema &S, Decl *D, const ParsedAttr &AL) { const auto *VD = cast<VarDecl>(D); if (VD->hasLocalStorage()) { @@ -8525,6 +8562,9 @@ case ParsedAttr::AT_OptimizeNone: handleOptimizeNoneAttr(S, D, AL); break; + case ParsedAttr::AT_Optimize: + handleOptimizeAttr(S, D, AL); + break; case ParsedAttr::AT_EnumExtensibility: handleEnumExtensibilityAttr(S, D, AL); break; Index: clang/lib/CodeGen/CodeGenModule.h =================================================================== --- clang/lib/CodeGen/CodeGenModule.h +++ clang/lib/CodeGen/CodeGenModule.h @@ -1654,7 +1654,7 @@ /// addDefaultFunctionDefinitionAttributes. Builds a set of function /// attributes to add to a function with the given properties. void getDefaultFunctionAttributes(StringRef Name, bool HasOptnone, - bool AttrOnCallSite, + bool HasOptsize, bool AttrOnCallSite, llvm::AttrBuilder &FuncAttrs); llvm::Metadata *CreateMetadataIdentifierImpl(QualType T, MetadataTypeMap &Map, Index: clang/lib/CodeGen/CodeGenModule.cpp =================================================================== --- clang/lib/CodeGen/CodeGenModule.cpp +++ clang/lib/CodeGen/CodeGenModule.cpp @@ -1929,7 +1929,9 @@ ShouldAddOptNone &= !D->hasAttr<AlwaysInlineAttr>(); // Add optnone, but do so only if the function isn't always_inline. - if ((ShouldAddOptNone || D->hasAttr<OptimizeNoneAttr>()) && + if ((ShouldAddOptNone || D->hasAttr<OptimizeNoneAttr>() || + (D->hasAttr<OptimizeAttr>() && + D->getAttr<OptimizeAttr>()->getLevel() == "0")) && !F->hasFnAttribute(llvm::Attribute::AlwaysInline)) { B.addAttribute(llvm::Attribute::OptimizeNone); Index: clang/lib/CodeGen/CGCall.cpp =================================================================== --- clang/lib/CodeGen/CGCall.cpp +++ clang/lib/CodeGen/CGCall.cpp @@ -1794,11 +1794,12 @@ void CodeGenModule::getDefaultFunctionAttributes(StringRef Name, bool HasOptnone, + bool HasOptsize, bool AttrOnCallSite, - llvm::AttrBuilder &FuncAttrs) { + llvm::AttrBuilder &FuncAttrs) { // OptimizeNoneAttr takes precedence over -Os or -Oz. No warning needed. if (!HasOptnone) { - if (CodeGenOpts.OptimizeSize) + if (CodeGenOpts.OptimizeSize || HasOptsize) FuncAttrs.addAttribute(llvm::Attribute::OptimizeForSize); if (CodeGenOpts.OptimizeSize == 2) FuncAttrs.addAttribute(llvm::Attribute::MinSize); @@ -1945,7 +1946,7 @@ void CodeGenModule::addDefaultFunctionDefinitionAttributes(llvm::Function &F) { llvm::AttrBuilder FuncAttrs(F.getContext()); - getDefaultFunctionAttributes(F.getName(), F.hasOptNone(), + getDefaultFunctionAttributes(F.getName(), F.hasOptNone(), F.hasOptSize(), /* AttrOnCallSite = */ false, FuncAttrs); // TODO: call GetCPUAndFeaturesAttributes? F.addFnAttrs(FuncAttrs); @@ -1954,7 +1955,7 @@ void CodeGenModule::addDefaultFunctionDefinitionAttributes( llvm::AttrBuilder &attrs) { getDefaultFunctionAttributes(/*function name*/ "", /*optnone*/ false, - /*for call*/ false, attrs); + /*optsize*/ false, /*for call*/ false, attrs); GetCPUAndFeaturesAttributes(GlobalDecl(), attrs); } @@ -2088,6 +2089,7 @@ AddAttributesFromAssumes(FuncAttrs, TargetDecl); bool HasOptnone = false; + bool HasOptsize = false; // The NoBuiltinAttr attached to the target FunctionDecl. const NoBuiltinAttr *NBA = nullptr; @@ -2163,7 +2165,11 @@ if (TargetDecl->hasAttr<LeafAttr>()) FuncAttrs.addAttribute(llvm::Attribute::NoCallback); - HasOptnone = TargetDecl->hasAttr<OptimizeNoneAttr>(); + HasOptnone = TargetDecl->hasAttr<OptimizeNoneAttr>() || + (TargetDecl->hasAttr<OptimizeAttr>() && + TargetDecl->getAttr<OptimizeAttr>()->getLevel() == "0"); + HasOptsize = TargetDecl->hasAttr<OptimizeAttr>() && + TargetDecl->getAttr<OptimizeAttr>()->getLevel() == "s"; if (auto *AllocSize = TargetDecl->getAttr<AllocSizeAttr>()) { Optional<unsigned> NumElemsParam; if (AllocSize->getNumElemsParam().isValid()) @@ -2197,7 +2203,8 @@ addNoBuiltinAttributes(FuncAttrs, getLangOpts(), NBA); // Collect function IR attributes based on global settiings. - getDefaultFunctionAttributes(Name, HasOptnone, AttrOnCallSite, FuncAttrs); + getDefaultFunctionAttributes(Name, HasOptnone, HasOptsize, AttrOnCallSite, + FuncAttrs); // Override some default IR attributes based on declaration-specific // information. Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3016,6 +3016,8 @@ "%0 attribute takes no more than %1 argument%s1">; def err_attribute_too_few_arguments : Error< "%0 attribute takes at least %1 argument%s1">; +def err_attribute_only_allowed_with_argument : Error < + "argument to '%0' should be %1">; def err_attribute_invalid_vector_type : Error<"invalid vector element type %0">; def err_attribute_invalid_matrix_type : Error<"invalid matrix element type %0">; def err_attribute_bad_neon_vector_size : Error< Index: clang/include/clang/Basic/Attr.td =================================================================== --- clang/include/clang/Basic/Attr.td +++ clang/include/clang/Basic/Attr.td @@ -2260,6 +2260,13 @@ let Documentation = [OptnoneDocs]; } +def Optimize : InheritableAttr { + let Spellings = [GCC<"optimize">]; + let Args = [StringArgument<"Level">]; + let Subjects = SubjectList<[Function]>; + let Documentation = [Undocumented]; +} + def Overloadable : Attr { let Spellings = [Clang<"overloadable">]; let Subjects = SubjectList<[Function], ErrorDiag>;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits