iains updated this revision to Diff 462689.
iains marked 3 inline comments as done.
iains edited the summary of this revision.
iains added a comment.

address review comments, minor amendments to description.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D134589

Files:
  clang/lib/CodeGen/CGDeclCXX.cpp
  clang/test/CodeGenCXX/module-initializer-guard-elision.cpp

Index: clang/test/CodeGenCXX/module-initializer-guard-elision.cpp
===================================================================
--- /dev/null
+++ clang/test/CodeGenCXX/module-initializer-guard-elision.cpp
@@ -0,0 +1,68 @@
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+// RUN: cd %t
+
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 O.cpp \
+// RUN:    -emit-module-interface -o O.pcm
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 O.pcm -S -emit-llvm \
+// RUN:  -o - | FileCheck %s --check-prefix=CHECK-O
+
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 P.cpp \
+// RUN:    -emit-module-interface -fmodule-file=O.pcm -o P.pcm
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 P.pcm -S -emit-llvm \
+// RUN:  -o - | FileCheck %s --check-prefix=CHECK-P
+
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 Q.cpp \
+// RUN:    -emit-module-interface -fmodule-file=O.pcm -o Q.pcm
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 Q.pcm -S -emit-llvm \
+// RUN:  -o - | FileCheck %s --check-prefix=CHECK-Q
+
+// Testing cases where we can elide the module initializer guard variable.
+
+// This module has no global inits and does not import any other module
+//--- O.cpp
+
+export module O;
+
+export int foo ();
+
+// CHECK-O: define void @_ZGIW1O
+// CHECK-O-LABEL: entry
+// CHECK-O-NEXT: ret void
+// CHECK-O-NOT: @_ZGIW1O__in_chrg
+
+// This has no global inits but imports a module.
+//--- P.cpp
+
+export module P;
+
+export import O;
+export int bar ();
+
+// CHECK-P: define void @_ZGIW1P
+// CHECK-P-LABEL: entry
+// CHECK-P-NEXT: call void @_ZGIW1O()
+// CHECK-P-NEXT: ret void
+// CHECK-P-NOT: @_ZGIW1P__in_chrg
+
+// This imports a module and has global inits, so needs a guard.
+//--- Q.cpp
+
+export module Q;
+export import O;
+
+export struct Quack {
+  Quack(){};
+};
+
+export Quack Duck;
+
+export int baz ();
+
+// CHECK-Q: define internal void @__cxx_global_var_init
+// CHECK-Q: call {{.*}} @_ZNW1Q5QuackC1Ev
+// CHECK-Q: define void @_ZGIW1Q
+// CHECK-Q: store i8 1, ptr @_ZGIW1Q__in_chrg
+// CHECK-Q: call void @_ZGIW1O()
+// CHECK-Q: call void @__cxx_global_var_init
+
Index: clang/lib/CodeGen/CGDeclCXX.cpp
===================================================================
--- clang/lib/CodeGen/CGDeclCXX.cpp
+++ clang/lib/CodeGen/CGDeclCXX.cpp
@@ -703,13 +703,11 @@
       for (; I < PrioE; ++I)
         ModuleInits.push_back(I->second);
     }
-    PrioritizedCXXGlobalInits.clear();
   }
 
   // Now append the ones without specified priority.
   for (auto *F : CXXGlobalInits)
     ModuleInits.push_back(F);
-  CXXGlobalInits.clear();
 
   llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);
   const CGFunctionInfo &FI = getTypes().arrangeNullaryFunction();
@@ -719,7 +717,6 @@
   // each init is run just once (even though a module might be imported
   // multiple times via nested use).
   llvm::Function *Fn;
-  llvm::GlobalVariable *Guard = nullptr;
   {
     SmallString<256> InitFnName;
     llvm::raw_svector_ostream Out(InitFnName);
@@ -729,17 +726,26 @@
         FTy, llvm::Twine(InitFnName), FI, SourceLocation(), false,
         llvm::GlobalVariable::ExternalLinkage);
 
-    Guard = new llvm::GlobalVariable(getModule(), Int8Ty, /*isConstant=*/false,
-                                     llvm::GlobalVariable::InternalLinkage,
-                                     llvm::ConstantInt::get(Int8Ty, 0),
-                                     InitFnName.str() + "__in_chrg");
+    // If we have an empty initializer then we do not want to create a guard
+    // var.  'Empty' excludes calls to imported module initializers since
+    // those will contain local guards as needed (and might themselves
+    // be empty).
+    ConstantAddress GuardAddr = ConstantAddress::invalid();
+    if (!PrioritizedCXXGlobalInits.empty() || !CXXGlobalInits.empty()) {
+      // Create the guard var.
+      llvm::GlobalVariable *Guard = new llvm::GlobalVariable(
+          getModule(), Int8Ty, /*isConstant=*/false,
+          llvm::GlobalVariable::InternalLinkage,
+          llvm::ConstantInt::get(Int8Ty, 0), InitFnName.str() + "__in_chrg");
+      CharUnits GuardAlign = CharUnits::One();
+      Guard->setAlignment(GuardAlign.getAsAlign());
+      GuardAddr = ConstantAddress(Guard, Int8Ty, GuardAlign);
+    }
+    CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn, ModuleInits,
+                                                     GuardAddr);
   }
-  CharUnits GuardAlign = CharUnits::One();
-  Guard->setAlignment(GuardAlign.getAsAlign());
 
-  CodeGenFunction(*this).GenerateCXXGlobalInitFunc(
-      Fn, ModuleInits, ConstantAddress(Guard, Int8Ty, GuardAlign));
-  // We allow for the case that a module object is added to  a linked binary
+  // We allow for the case that a module object is added to a linked binary
   // without a specific call to the the initializer.  This also ensure that
   // implementation partition initializers are called when the partition
   // is not imported as an interface.
@@ -759,6 +765,9 @@
     Fn->addFnAttr("device-init");
   }
 
+  // We are done with the inits.
+  PrioritizedCXXGlobalInits.clear();
+  CXXGlobalInits.clear();
   ModuleInits.clear();
 }
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to