JonChesterfield updated this revision to Diff 247652.
JonChesterfield marked 2 inline comments as done.
JonChesterfield added a comment.

- Address review comments, more test coverage


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D74361

Files:
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/AttrDocs.td
  clang/lib/AST/DeclBase.cpp
  clang/lib/CodeGen/CGDecl.cpp
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/lib/Sema/SemaDeclAttr.cpp
  clang/test/CodeGen/attr-loader-uninitialized.c
  clang/test/CodeGenCXX/attr-loader-uninitialized.cpp
  clang/test/Misc/pragma-attribute-supported-attributes-list.test
  clang/test/Sema/attr-loader-uninitialized.cpp

Index: clang/test/Sema/attr-loader-uninitialized.cpp
===================================================================
--- /dev/null
+++ clang/test/Sema/attr-loader-uninitialized.cpp
@@ -0,0 +1,36 @@
+// RUN: %clang_cc1 %s -verify -fsyntax-only
+
+int good __attribute__((loader_uninitialized));
+const int still_cant_be_const __attribute__((loader_uninitialized)); // expected-error {{default initialization of an object of const type}}
+extern int external __attribute__((loader_uninitialized));
+
+int noargs __attribute__((loader_uninitialized(0))); // expected-error {{'loader_uninitialized' attribute takes no arguments}} 
+
+void func() __attribute__((loader_uninitialized)) // expected-warning {{'loader_uninitialized' attribute only applies to global variables}}
+{
+  int local __attribute__((loader_uninitialized)); // expected-warning {{'loader_uninitialized' attribute only applies to global variables}}
+
+  static int sl __attribute__((loader_uninitialized));
+}
+
+struct s {
+  __attribute__((loader_uninitialized)) int field; // expected-warning {{'loader_uninitialized' attribute only applies to global variables}}
+
+  static __attribute__((loader_uninitialized)) int sfield;
+
+} __attribute__((loader_uninitialized)); // expected-warning {{'loader_uninitialized' attribute only applies to global variables}}
+
+int redef_attr_first __attribute__((loader_uninitialized));
+int redef_attr_first;
+// expected-error@-1 {{redefinition of 'redef_attr_first'}}
+// expected-note@-3 {{previous definition is here}}
+
+int redef_attr_second; 
+int redef_attr_second __attribute__((loader_uninitialized)); 
+// expected-warning@-1 {{attribute declaration must precede definition}}
+// expected-note@-3 {{previous definition is here}}
+// expected-error@-3 {{redefinition of 'redef_attr_second'}}
+// expected-note@-5 {{previous definition is here}}
+
+// Would like sema to reject this, but that is not yet implemented
+int multiple_definitions __attribute__((loader_uninitialized)) = 42;
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
@@ -65,6 +65,7 @@
 // CHECK-NEXT: InitPriority (SubjectMatchRule_variable)
 // CHECK-NEXT: InternalLinkage (SubjectMatchRule_variable, SubjectMatchRule_function, SubjectMatchRule_record)
 // CHECK-NEXT: LTOVisibilityPublic (SubjectMatchRule_record)
+// CHECK-NEXT: LoaderUninitialized (SubjectMatchRule_variable_is_global)
 // CHECK-NEXT: Lockable (SubjectMatchRule_record)
 // CHECK-NEXT: MIGServerRoutine (SubjectMatchRule_function, SubjectMatchRule_objc_method, SubjectMatchRule_block)
 // CHECK-NEXT: MSStruct (SubjectMatchRule_record)
Index: clang/test/CodeGenCXX/attr-loader-uninitialized.cpp
===================================================================
--- /dev/null
+++ clang/test/CodeGenCXX/attr-loader-uninitialized.cpp
@@ -0,0 +1,47 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -std=c++11 -emit-llvm -o - %s | FileCheck %s
+
+// CHECK: @_ZZ4funcvE4data = internal global i32 undef
+int* func(void)
+{
+  static int data [[clang::loader_uninitialized]];
+  return &data;
+}
+
+// No code emitted
+extern int extern_unhelpful_but_harmless [[clang::loader_uninitialized]];
+
+// CHECK: @defn = global i32 undef
+int defn  [[clang::loader_uninitialized]];
+
+// CHECK: @_ZL11defn_static = internal global i32 undef
+static int defn_static [[clang::loader_uninitialized]] __attribute__((used));
+
+// CHECK: @nominally_zero_init = global i32 undef
+int nominally_zero_init  [[clang::loader_uninitialized]] = 0;
+
+// CHECK: @nominally_value_init = global i32 undef
+int nominally_value_init  [[clang::loader_uninitialized]] = 4;
+
+class trivial
+{
+  float x;
+};
+
+// CHECK: @ut = global %class.trivial undef
+trivial ut [[clang::loader_uninitialized]];
+
+struct nontrivial
+{
+  nontrivial() : x(3.14) {}
+  double x;
+};
+
+// CHECK: @unt = global %struct.nontrivial undef
+nontrivial unt [[clang::loader_uninitialized]];
+
+// CHECK: @arr = global [32 x double] undef, align 16
+double arr[32] __attribute__((loader_uninitialized));
+
+// Defining as arr2[] [[clang..]] raises the error: attribute cannot be applied to types
+// CHECK: @arr2 = global [4 x double] undef, align 16
+double arr2 [[clang::loader_uninitialized]] [4];
Index: clang/test/CodeGen/attr-loader-uninitialized.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/attr-loader-uninitialized.c
@@ -0,0 +1,29 @@
+// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s
+
+// CHECK: @tentative_attr_first = weak global i32 undef, align 4
+int tentative_attr_first __attribute__((loader_uninitialized));
+int tentative_attr_first;
+
+// CHECK: @tentative_attr_second = weak global i32 undef, align 4
+int tentative_attr_second;
+int tentative_attr_second __attribute__((loader_uninitialized));
+
+// CHECK: @attr_both_uninit_wins = global i32 undef, align 4
+int attr_both_uninit_wins __attribute__((loader_uninitialized)) = 42;
+
+// CHECK: @array = weak global [16 x float] undef, align 16
+float array[16] __attribute__((loader_uninitialized));
+
+typedef struct
+{
+  int x;
+  float y;
+} s;
+
+// CHECK: @i = weak global %struct.s undef, align 4
+s i __attribute__((loader_uninitialized));
+
+// This is caused by missing sema - should be an error, actually resolves to 4
+// CHECK: @tentative_attr_sema_fail = global i32 4, align 4
+int tentative_attr_sema_fail = 4;
+int tentative_attr_sema_fail __attribute__((loader_uninitialized));
Index: clang/lib/Sema/SemaDeclAttr.cpp
===================================================================
--- clang/lib/Sema/SemaDeclAttr.cpp
+++ clang/lib/Sema/SemaDeclAttr.cpp
@@ -6505,6 +6505,11 @@
   D->addAttr(::new (S.Context) UninitializedAttr(S.Context, AL));
 }
 
+static void handleLoaderUninitializedAttr(Sema &S, Decl *D,
+                                          const ParsedAttr &AL) {
+  D->addAttr(::new (S.Context) LoaderUninitializedAttr(S.Context, AL));
+}
+
 static bool tryMakeVariablePseudoStrong(Sema &S, VarDecl *VD,
                                         bool DiagnoseFailure) {
   QualType Ty = VD->getType();
@@ -7427,6 +7432,10 @@
     handleUninitializedAttr(S, D, AL);
     break;
 
+  case ParsedAttr::AT_LoaderUninitialized:
+    handleLoaderUninitializedAttr(S, D, AL);
+    break;
+
   case ParsedAttr::AT_ObjCExternallyRetained:
     handleObjCExternallyRetainedAttr(S, D, AL);
     break;
Index: clang/lib/CodeGen/CodeGenModule.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenModule.cpp
+++ clang/lib/CodeGen/CodeGenModule.cpp
@@ -3942,6 +3942,8 @@
   if (getLangOpts().CUDA &&
       (IsCUDASharedVar || IsCUDAShadowVar || IsHIPPinnedShadowVar))
     Init = llvm::UndefValue::get(getTypes().ConvertType(ASTTy));
+  else if (D->hasAttr<LoaderUninitializedAttr>())
+    Init = llvm::UndefValue::get(getTypes().ConvertType(ASTTy));
   else if (!InitExpr) {
     // This is a tentative definition; tentative definitions are
     // implicitly initialized with { 0 }.
Index: clang/lib/CodeGen/CGDecl.cpp
===================================================================
--- clang/lib/CodeGen/CGDecl.cpp
+++ clang/lib/CodeGen/CGDecl.cpp
@@ -249,7 +249,7 @@
   // variables cannot have an initializer.
   llvm::Constant *Init = nullptr;
   if (Ty.getAddressSpace() == LangAS::opencl_local ||
-      D.hasAttr<CUDASharedAttr>())
+      D.hasAttr<CUDASharedAttr>() || D.hasAttr<LoaderUninitializedAttr>())
     Init = llvm::UndefValue::get(LTy);
   else
     Init = EmitNullConstant(Ty);
Index: clang/lib/AST/DeclBase.cpp
===================================================================
--- clang/lib/AST/DeclBase.cpp
+++ clang/lib/AST/DeclBase.cpp
@@ -454,7 +454,8 @@
 }
 
 bool Decl::hasDefiningAttr() const {
-  return hasAttr<AliasAttr>() || hasAttr<IFuncAttr>();
+  return hasAttr<AliasAttr>() || hasAttr<IFuncAttr>() ||
+         hasAttr<LoaderUninitializedAttr>();
 }
 
 const Attr *Decl::getDefiningAttr() const {
@@ -462,6 +463,8 @@
     return AA;
   if (auto *IFA = getAttr<IFuncAttr>())
     return IFA;
+  if (auto *NZA = getAttr<LoaderUninitializedAttr>())
+    return NZA;  
   return nullptr;
 }
 
Index: clang/include/clang/Basic/AttrDocs.td
===================================================================
--- clang/include/clang/Basic/AttrDocs.td
+++ clang/include/clang/Basic/AttrDocs.td
@@ -4358,6 +4358,16 @@
   }];
 }
 
+def LoaderUninitializedDocs : Documentation {
+  let Category = DocCatVariable;
+  let Content = [{
+The ``loader_uninitialized`` attribute can be placed on global variables to
+indicate that the variable does not need to be zero initialized by the loader.
+This is useful for variables that are always written to before use where the
+default zero initialization provided by the toolchain loader is expensive.
+  }];
+}
+
 def CallbackDocs : Documentation {
   let Category = DocCatFunction;
   let Content = [{
Index: clang/include/clang/Basic/Attr.td
===================================================================
--- clang/include/clang/Basic/Attr.td
+++ clang/include/clang/Basic/Attr.td
@@ -3430,6 +3430,12 @@
   let Documentation = [UninitializedDocs];
 }
 
+def LoaderUninitialized : InheritableAttr {
+  let Spellings = [Clang<"loader_uninitialized">];
+  let Subjects = SubjectList<[GlobalVar]>;
+  let Documentation = [LoaderUninitializedDocs];
+}
+  
 def ObjCExternallyRetained : InheritableAttr {
   let LangOpts = [ObjCAutoRefCount];
   let Spellings = [Clang<"objc_externally_retained">];
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to