efriedma added inline comments.
Herald added subscribers: bd1976llvm, jplehr.


================
Comment at: clang/lib/CodeGen/CGDeclCXX.cpp:520
+      getOpenMPRuntime().emitDeclareTargetVarDefinition(D, Addr, PerformInit))
+    return;
+
----------------
efriedma wrote:
> I don't really like the copy-pasted bits here.
It would be nice it we could to unify EmitCXXCtorInit with 
EmitCXXGlobalVarDeclInitFunc a bit more.


================
Comment at: clang/lib/CodeGen/CodeGenModule.cpp:5006
+    if (NeedsGlobalCtor || NeedsGlobalDtor)
+      DelayedCXXInitPosition[D] = ~0U;
+  } else {
----------------
zahiraam wrote:
> efriedma wrote:
> > zahiraam wrote:
> > > efriedma wrote:
> > > > zahiraam wrote:
> > > > > efriedma wrote:
> > > > > > zahiraam wrote:
> > > > > > > efriedma wrote:
> > > > > > > > zahiraam wrote:
> > > > > > > > > Do you agree this should be done only when one of those flags 
> > > > > > > > > is on?
> > > > > > > > Yes, that's fine; I wasn't really paying close attention to the 
> > > > > > > > exact code.  Just wanted to make the point about the structure 
> > > > > > > > of the if statements, and code was the easiest way to explain 
> > > > > > > > it.
> > > > > > > > 
> > > > > > > > Maybe the outer if statement should actually be `if 
> > > > > > > > (isStaticInit(D, getLangOpts()) && NeedsGlobalCtor) {`.
> > > > > > > > 
> > > > > > > > On a related note, we might want to avoid the name "ctor", in 
> > > > > > > > case that accidentally conflicts with some user code; an 
> > > > > > > > "__"-prefixed name would be appropriate.
> > > > > > > >> Maybe the outer if statement should actually be if 
> > > > > > > >> (isStaticInit(D, getLangOpts()) && NeedsGlobalCtor) {
> > > > > > > Not sure about that! There are cases where (isStaticInit(D, 
> > > > > > > getLangOpts())) = true and NeedsGlobalCtor=false, but 
> > > > > > > NeedsGlobalDtor=true. In which case a __dtor needs to be emitted, 
> > > > > > > no?
> > > > > > > 
> > > > > > > Writing the condition as you are proposing would actually not get 
> > > > > > > me into the body to emit the __dtor. Is that what we want?
> > > > > > EmitCXXGlobalVarDeclInitFunc should be able to handle that case.
> > > > > > 
> > > > > > Looking again, I'm a little concerned that in the isStaticInit() 
> > > > > > case, we're skipping a bunch of the logic in 
> > > > > > EmitCXXGlobalVarDeclInitFunc. EmitCXXCtorInit handles the basic 
> > > > > > cases correctly, but there are a lot of special cases in 
> > > > > > EmitCXXGlobalVarDeclInitFunc.
> > > > > I have left the condition as it was to make sure no cases are left. 
> > > > > What other cases are you thinking of? 
> > > > > 
> > > > EmitCXXGlobalVarDeclInitFunc has special cases for CUDA, OpenMP, 
> > > > thread-local variables, the InitSeg attribute, and inline variables.
> > > Let me know if this works? I have added one additional LIT test. I 
> > > referred to 
> > > https://learn.microsoft.com/en-us/cpp/cpp/storage-classes-cpp?view=msvc-170#thread_local
> > >  for thread_local. 
> > > For the inline variables, I couldn't find much information about 
> > > initialization of inline variables. I tried to find a case that wouldn't 
> > > pass by the new code and wouldn't pass by EmitCXXGlobalVarDeclInitFunc, 
> > > but no success.
> > Inline variable example:
> > 
> > ```
> > __declspec(dllimport) extern int x;
> > inline int *y = &x;
> > int **z = &y;
> > ```
> > 
> > This should trigger your new codepath, I think?
> Yes. And the IR looks like this:
> 
>   @"?y@@3PEAHEA" = linkonce_odr dso_local global ptr null, comdat, align 8
>   @"?z@@3PEAPEAHEA" = dso_local global ptr @"?y@@3PEAHEA", align 8
>   @"?x@@3HA" = external dllimport global i32, align 4
>   @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, 
> ptr } { i32 201, ptr @__ctor, ptr null }]
> 
>   ; Function Attrs: noinline nounwind
>   define linkonce_odr dso_local void @__ctor() #0 comdat {
>   entry:
>     store ptr @"?x@@3HA", ptr @"?y@@3PEAHEA", align 8
>     ret void
>   }
> 
> I think this is correct. 
> Adding it to the LIT testing.
Without your patch, the IR looks significantly different; the constructor 
function is named ??__Ey@@YAXXZ, and there's a reference to the variable in 
llvm.global_ctors.  This is necessary to ensure we only construct the variable 
once.

In this particular case, I guess the harm of constructing the variable multiple 
times would be relatively minor, but it's still not a great idea.  And we 
definitely can't emit a linkonce_odr function and just name it "__ctor".


================
Comment at: clang/test/CodeGenCXX/constant-init.cpp:17
+
+// CHECK: define internal void @"??__Ft2@@YAXXZ"() #0 {
+// CHECK: entry:
----------------
zahiraam wrote:
> efriedma wrote:
> > This doesn't look like your new codepath is triggering?  If your code is 
> > working correctly, it should, I think?
> That's right. In all cases where 
> 
>   llvm::Constant *Initializer = emitter->tryEmitForInitializer(*InitDecl);
> 
> is returning an initializer (with NeedsGlobalCtor=false and 
> NeedsGlobalDtor=true) the control path is following the old path (no call to 
> EmitCXXCtorInit), i.e. call to  EmitCXXGlobalVarDeclInitFunc.
> 
> Unless we want to change the value of NeedsGlobaCtor in this case?
> 
> With:
>   diff --git a/clang/lib/CodeGen/CodeGenModule.cpp 
> b/clang/lib/CodeGen/CodeGenModule.cpp
>   index f7add1350238..106ac355d356 100644
>   --- a/clang/lib/CodeGen/CodeGenModule.cpp
>  +++ b/clang/lib/CodeGen/CodeGenModule.cpp
>   @@ -4898,6 +4898,8 @@ void CodeGenModule::EmitGlobalVarDefinition(const 
> VarDecl *D,
>        // also don't need to register a destructor.
>        if (getLangOpts().CPlusPlus && !NeedsGlobalDtor)
>          DelayedCXXInitPosition.erase(D);
>   +      if (isStaticInit(D, getLangOpts()) && !NeedsGlobalCtor)
>   +        NeedsGlobalCtor = true;
> 
>    #ifndef NDEBUG
>         CharUnits VarSize = getContext().getTypeSizeInChars(ASTTy) +
> 
> In which case for:
> 
>   struct Test1 {
>   constexpr Test1(int) {}
>   ~Test1() {}
>   };
>   inline constinit Test1 t2 = 2;
> 
> We would get this IR?
> 
> @llvm.global_ctors = appending global [2 x { i32, ptr, ptr }] [{ i32, ptr, 
> ptr } { i32 201, ptr @__ctor, ptr null }, { i32, ptr, ptr } { i32 65535, ptr 
> @__dtor, ptr null }]
> 
> ; Function Attrs: noinline nounwind
> define linkonce_odr dso_local void @__ctor() #0 comdat {
> entry:
>   %call = call noundef ptr @"??0Test1@@QEAA@H@Z"(ptr noundef nonnull align 1 
> dereferenceable(1) @"?t2@@3UTest1@@A", i32 noundef 2)
>   %0 = call i32 @atexit(ptr @"??__Ft2@@YAXXZ") #2
>   ret void
> }
> 
> define internal void @"??__Ft2@@YAXXZ"() #0 {
> entry:
>   call void @"??1Test1@@QEAA@XZ"(ptr @"?t2@@3UTest1@@A")
>   ret void
> }
> 
> define linkonce_odr dso_local void @__dtor() #0 comdat {
> entry:
>   %0 = call i32 @atexit(ptr @"??__Ft2@@YAXXZ.1") #2
>   ret void
> }
> 
Reading this again, not sure what I was asking for here.

We should not be calling atexit() from a priority 201 constructor; we should 
always register it with the normal registration priority, so stuff is destroyed 
in the right order.


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

https://reviews.llvm.org/D137107

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to