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

Reply via email to