steplong updated this revision to Diff 436551.
steplong added a comment.

- Remove -Og, and all non-zero optimization levels
- Fix up docs
- Modified tests to reflect -Og and non-zero opt level change


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D126984/new/

https://reviews.llvm.org/D126984

Files:
  clang/docs/ReleaseNotes.rst
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/AttrDocs.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/Misc/pragma-attribute-supported-attributes-list.test
  clang/test/Sema/attr-optimize.c

Index: clang/test/Sema/attr-optimize.c
===================================================================
--- /dev/null
+++ clang/test/Sema/attr-optimize.c
@@ -0,0 +1,52 @@
+// 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-warning {{invalid optimization level 'Og' specified; only '-O0', '-Os', '-Oz', and '-Ofast' are supported; attribute ignored}}
+void
+f4() {}
+
+__attribute__((optimize("O-1"))) // expected-warning {{invalid optimization level 'O-1' specified; only '-O0', '-Os', '-Oz', and '-Ofast' are supported; attribute ignored}}
+void
+f5() {}
+
+__attribute__((optimize("O+1"))) // expected-warning {{invalid optimization level 'O+1' specified; only '-O0', '-Os', '-Oz', and '-Ofast' are supported; attribute ignored}}
+void
+f6() {}
+
+__attribute__((optimize("O0"))) // expected-no-error
+void
+f7() {}
+
+__attribute__((optimize("Os"))) // expected-no-error
+void
+f8() {}
+
+__attribute__((optimize("O44"))) // expected-warning {{invalid optimization level 'O44' specified; only '-O0', '-Os', '-Oz', and '-Ofast' are supported; attribute ignored}}
+void
+f9() {}
+
+__attribute__((optimize("Oz"))) // expected-no-error
+void
+f10() {}
+
+__attribute__((optimize("Ofast"))) // expected-no-error
+void
+f11() {}
+
+__attribute__((optimize("O"))) // expected-no-error
+void
+f12() {}
+
+__attribute__((optimize("O0"))) // expected-error {{expected identifier or '('}}
Index: clang/test/Misc/pragma-attribute-supported-attributes-list.test
===================================================================
--- clang/test/Misc/pragma-attribute-supported-attributes-list.test
+++ clang/test/Misc/pragma-attribute-supported-attributes-list.test
@@ -142,6 +142,7 @@
 // CHECK-NEXT: ObjCSubclassingRestricted (SubjectMatchRule_objc_interface)
 // CHECK-NEXT: OpenCLIntelReqdSubGroupSize (SubjectMatchRule_function)
 // CHECK-NEXT: OpenCLNoSVM (SubjectMatchRule_variable)
+// CHECK-NEXT: Optimize (SubjectMatchRule_function)
 // CHECK-NEXT: OptimizeNone (SubjectMatchRule_function, SubjectMatchRule_objc_method)
 // CHECK-NEXT: Overloadable (SubjectMatchRule_function)
 // CHECK-NEXT: Owner (SubjectMatchRule_record_not_is_union)
Index: clang/test/CodeGen/attr-optimize.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/attr-optimize.c
@@ -0,0 +1,25 @@
+// 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{{.*}}[[ATTR_OPTNONE:#[0-9]+]]
+// O0: @f1{{.*}}[[ATTR_OPTNONE:#[0-9]+]]
+
+__attribute__((optimize("Os"))) void f2(void) {}
+// O2: @f2{{.*}}[[ATTR_OPTSIZE:#[0-9]+]]
+// O0: @f2{{.*}}[[ATTR_OPTNONE]]
+
+__attribute__((optimize("Oz"))) void f4(void) {}
+// O2: @f4{{.*}}[[ATTR_MINSIZE:#[0-9]+]]
+// O0: @f4{{.*}}[[ATTR_OPTNONE]]
+
+__attribute__((optimize("Ofast"))) void f5(void) {}
+// O2: @f5{{.*}}[[ATTR_OPTSIZE]]
+// O0: @f5{{.*}}[[ATTR_OPTNONE]]
+
+// O2: attributes [[ATTR_OPTNONE]] = { {{.*}}optnone{{.*}} }
+// O2: attributes [[ATTR_OPTSIZE]] = { {{.*}}optsize{{.*}} }
+// O2: attributes [[ATTR_MINSIZE]] = { {{.*}}minsize{{.*}}optsize{{.*}} }
+
+// Check that O0 overrides the attribute
+// O0: attributes [[ATTR_OPTNONE]] = { {{.*}}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::warn_invalid_optimize_attr_level) << Arg;
+
+  llvm::StringMap<OptimizeAttr::OptLevelKind> StrToKind = {
+      {"", OptimizeAttr::NoOpts},   {"s", OptimizeAttr::OptSize},
+      {"fast", OptimizeAttr::Fast}, {"z", OptimizeAttr::MinSize},
+      {"0", OptimizeAttr::NoOpts},
+  };
+
+  auto It = StrToKind.find(Level.str());
+  if (It != StrToKind.end()) {
+    D->addAttr(::new (S.Context) OptimizeAttr(S.Context, AL, Arg, It->second));
+    return;
+  }
+
+  llvm::APInt Num;
+  if (!Level.getAsInteger(10, Num) && Num.isZero()) {
+    // We only support -O0
+    D->addAttr(::new (S.Context)
+                   OptimizeAttr(S.Context, AL, Arg, OptimizeAttr::NoOpts));
+    return;
+  }
+
+  S.Diag(AL.getLoc(), diag::warn_invalid_optimize_attr_level) << Arg;
+}
+
 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,6 +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 HasOptsize, bool HasMinsize,
                                     bool AttrOnCallSite,
                                     llvm::AttrBuilder &FuncAttrs);
 
Index: clang/lib/CodeGen/CodeGenModule.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenModule.cpp
+++ clang/lib/CodeGen/CodeGenModule.cpp
@@ -1928,6 +1928,10 @@
   ShouldAddOptNone &= !D->hasAttr<MinSizeAttr>();
   ShouldAddOptNone &= !D->hasAttr<AlwaysInlineAttr>();
 
+  if (const auto *OA = D->getAttr<OptimizeAttr>())
+    ShouldAddOptNone =
+        ShouldAddOptNone || (OA->getOptLevel() == OptimizeAttr::NoOpts);
+
   // Add optnone, but do so only if the function isn't always_inline.
   if ((ShouldAddOptNone || D->hasAttr<OptimizeNoneAttr>()) &&
       !F->hasFnAttribute(llvm::Attribute::AlwaysInline)) {
@@ -1950,7 +1954,8 @@
     B.addAttribute(llvm::Attribute::NoInline);
   } else if (D->hasAttr<NoDuplicateAttr>()) {
     B.addAttribute(llvm::Attribute::NoDuplicate);
-  } else if (D->hasAttr<NoInlineAttr>() && !F->hasFnAttribute(llvm::Attribute::AlwaysInline)) {
+  } else if (D->hasAttr<NoInlineAttr>() &&
+             !F->hasFnAttribute(llvm::Attribute::AlwaysInline)) {
     // Add noinline if the function isn't always_inline.
     B.addAttribute(llvm::Attribute::NoInline);
   } else if (D->hasAttr<AlwaysInlineAttr>() &&
Index: clang/lib/CodeGen/CGCall.cpp
===================================================================
--- clang/lib/CodeGen/CGCall.cpp
+++ clang/lib/CodeGen/CGCall.cpp
@@ -1792,15 +1792,14 @@
   return ReturnType.isTriviallyCopyableType(Context);
 }
 
-void CodeGenModule::getDefaultFunctionAttributes(StringRef Name,
-                                                 bool HasOptnone,
-                                                 bool AttrOnCallSite,
-                                               llvm::AttrBuilder &FuncAttrs) {
+void CodeGenModule::getDefaultFunctionAttributes(
+    StringRef Name, bool HasOptnone, bool HasOptsize, bool HasMinsize,
+    bool AttrOnCallSite, 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)
+    if (CodeGenOpts.OptimizeSize == 2 || HasMinsize)
       FuncAttrs.addAttribute(llvm::Attribute::MinSize);
   }
 
@@ -1945,7 +1944,8 @@
 
 void CodeGenModule::addDefaultFunctionDefinitionAttributes(llvm::Function &F) {
   llvm::AttrBuilder FuncAttrs(F.getContext());
-  getDefaultFunctionAttributes(F.getName(), F.hasOptNone(),
+  getDefaultFunctionAttributes(F.getName(), F.hasOptNone(), F.hasOptSize(),
+                               F.hasMinSize(),
                                /* AttrOnCallSite = */ false, FuncAttrs);
   // TODO: call GetCPUAndFeaturesAttributes?
   F.addFnAttrs(FuncAttrs);
@@ -1954,6 +1954,7 @@
 void CodeGenModule::addDefaultFunctionDefinitionAttributes(
                                                    llvm::AttrBuilder &attrs) {
   getDefaultFunctionAttributes(/*function name*/ "", /*optnone*/ false,
+                               /*optsize*/ false, /*minsize*/ false,
                                /*for call*/ false, attrs);
   GetCPUAndFeaturesAttributes(GlobalDecl(), attrs);
 }
@@ -2088,6 +2089,8 @@
   AddAttributesFromAssumes(FuncAttrs, TargetDecl);
 
   bool HasOptnone = false;
+  bool HasOptsize = false;
+  bool HasMinsize = false;
   // The NoBuiltinAttr attached to the target FunctionDecl.
   const NoBuiltinAttr *NBA = nullptr;
 
@@ -2164,6 +2167,13 @@
       FuncAttrs.addAttribute(llvm::Attribute::NoCallback);
 
     HasOptnone = TargetDecl->hasAttr<OptimizeNoneAttr>();
+    if (const auto *OA = TargetDecl->getAttr<OptimizeAttr>()) {
+      OptimizeAttr::OptLevelKind Kind = OA->getOptLevel();
+      HasOptnone = HasOptnone || (Kind == OptimizeAttr::NoOpts);
+      HasOptsize = Kind == OptimizeAttr::OptSize || OptimizeAttr::MinSize ||
+                   OptimizeAttr::Fast;
+      HasMinsize = Kind == OptimizeAttr::MinSize;
+    }
     if (auto *AllocSize = TargetDecl->getAttr<AllocSizeAttr>()) {
       Optional<unsigned> NumElemsParam;
       if (AllocSize->getNumElemsParam().isValid())
@@ -2197,7 +2207,8 @@
   addNoBuiltinAttributes(FuncAttrs, getLangOpts(), NBA);
 
   // Collect function IR attributes based on global settiings.
-  getDefaultFunctionAttributes(Name, HasOptnone, AttrOnCallSite, FuncAttrs);
+  getDefaultFunctionAttributes(Name, HasOptnone, HasOptsize, HasMinsize,
+                               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,10 @@
   "%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 warn_invalid_optimize_attr_level : Warning <
+   "invalid optimization level '%0' specified; only "
+   "'-O0', '-Os', '-Oz', and '-Ofast' are supported; attribute ignored">,
+   InGroup<IgnoredAttributes>;
 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/AttrDocs.td
===================================================================
--- clang/include/clang/Basic/AttrDocs.td
+++ clang/include/clang/Basic/AttrDocs.td
@@ -3456,6 +3456,22 @@
   }];
 }
 
+def OptimizeDocs : Documentation {
+  let Category = DocCatFunction;
+  let Content = [{
+The ``optimize`` attribute, when attached to a function, indicates that the
+function should be compiled with a different optimization level than specified
+on the command line. See the Function Attributes documentation on GCC's docs for
+more information. Currently, the attribute differs from GCC in that Clang only
+supports one argument, doesn't support ``-f`` arguments, and also doesn't
+support expressions or integers as arguments. Clang does not intend to fully
+support the GCC semantics. Optimization levels `-O1` through `-O4` are
+ignored. Only "-O0", "-Oz", "-Os", and "-Ofast" are supported.
+
+Refer to: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html
+  }];
+}
+
 def LoopHintDocs : Documentation {
   let Category = DocCatStmt;
   let Heading = "#pragma clang loop";
Index: clang/include/clang/Basic/Attr.td
===================================================================
--- clang/include/clang/Basic/Attr.td
+++ clang/include/clang/Basic/Attr.td
@@ -2260,6 +2260,17 @@
   let Documentation = [OptnoneDocs];
 }
 
+def Optimize : InheritableAttr {
+  let Spellings = [GCC<"optimize">];
+  let Args = [StringArgument<"Level">,
+              EnumArgument<"OptLevel", "OptLevelKind",
+                           ["Ofast", "Oz", "Os", "O0"],
+                           ["Fast", "MinSize", "OptSize", "NoOpts"],
+                           /*optional*/0, /*fake*/1>];
+  let Subjects = SubjectList<[Function]>;
+  let Documentation = [OptimizeDocs];
+}
+
 def Overloadable : Attr {
   let Spellings = [Clang<"overloadable">];
   let Subjects = SubjectList<[Function], ErrorDiag>;
Index: clang/docs/ReleaseNotes.rst
===================================================================
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -328,6 +328,12 @@
   builtins (corresponding to the specific names listed in the attribute) in the
   body of the function the attribute is on.
 
+- Added some support for GCC's attribute ``optimize``, which allows
+  functions to be compiled with different optimization options than what was
+  specified on the command line. Clang's support only adds certain function
+  attributes (depending on the optimization level passed to the attribute) and
+  is not intended to be like GCC's attribute.
+
 Windows Support
 ---------------
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to