akhuang added inline comments.

================
Comment at: clang/lib/CodeGen/CGDebugInfo.cpp:2292-2300
+  bool hasCtor = false;
+  for (const auto *Ctor : RD->ctors()) {
     if (Ctor->isTrivial() && !Ctor->isCopyOrMoveConstructor())
       return false;
+    if (!Ctor->isCopyOrMoveConstructor())
+      hasCtor = true;
+  }
----------------
rsmith wrote:
> dblaikie wrote:
> > rsmith wrote:
> > > This looks pretty similar to:
> > > 
> > > ```
> > > return RD->hasUserDeclaredConstructor() && 
> > > !RD->hasTrivialDefaultConstructor();
> > > ```
> > > 
> > > (other than its treatment of user-declared copy or move constructors), 
> > > but I have to admit I don't really understand what the "at least one 
> > > constructor and no trivial or constexpr constructors" rule aims to 
> > > achieve, so it's hard to know if this is the right interpretation. The 
> > > rule as written in the comment above is presumably not exactly right -- 
> > > all classes have at least one constructor, and we're not excluding 
> > > classes with trivial copy or move constructors, only those with trivial 
> > > default constructors.
> > > 
> > > I wonder if the intent would be better captured by "at least one 
> > > non-inline constructor" (that is, assuming all declared functions are 
> > > defined, there is at least one translation unit in which a constructor is 
> > > defined that can be used as a home for the class info).
> > So the general goal is to detect any type where the construction of that 
> > type somewhere must invoke a constructor that will be IR-generated.
> > 
> > Move and copy constructors are ignored because the assumption is they must 
> > be moving/copying from some other object, which must've been constructed, 
> > ultimately, by a non-move/copy constructor.
> > 
> > Ideally this would be usable even for inline ctors - even if the ctor calls 
> > get optimized away later[^1], they'd still allow us to reduce the number of 
> > places the type is emitted to only those places that call the ctor.
> > 
> > 
> > 
> > [^1] actually, the way that should work doesn't seem to be working right 
> > now (eg:
> > type.cpp
> > ```
> > struct t1 { t1() { } };
> > void f1(void*);
> > int main() {
> >   f1(new t1());
> > }
> > ```
> > type2.cpp
> > ```
> > struct t1 { t1() { } };
> > void f1(void* v) {
> >   delete (t1*)v;
> > }
> > ```
> > build: `clang++ type.cpp -g -Xclang -fuse-ctor-homing type2.cpp && 
> > llvm-dwarfdump a.out`
> > -> definition of "t1" in the DWARF
> > build with optimizations: `clang++ -O3 type.cpp -g -Xclang 
> > -fuse-ctor-homing type2.cpp && llvm-dwarfdump a.out`
> > -> missing definition of "t1"
> > `type.cpp` is chosen as a home for `t1` because it calls a user-defined 
> > ctor, but then that ctor gets optimized away and there's no other mention 
> > of `t1` in `type.cpp` so the type is dropped entirely. This could happen 
> > even with a non-inline definition - under LTO the ctor could get optimized 
> > away (though this would be safe in FullLTO - the other references to `t1` 
> > would be made to refer to the definition and keep it alive - but in ThinLTO 
> > the TU defining the ctor might be imported and nothing else - leaving the 
> > type unused/dropped)
> > To fix this we should put 'homed' types in the retained types list so they 
> > are preserved even if all other code/references to the type are dropped. I 
> > think I implemented this homed type pinning for explicit template 
> > specialization definitions, because they have no code attachment point, so 
> > similar logic could be used for ctor homing. (vtable homing /might/ benefit 
> > from this with aggressive/whole program devirtualization? Not sure - harder 
> > to actually optimize away all the references to a type, but possible maybe?)
> Oh, I see, that's clever and very neat.
> 
> So the intent is to identify types for which we know that either no instances 
> are ever created, or some constructor must be actually emitted in some 
> translation unit (prior to optimizations running). And that's why we want to 
> ignore copy and move constructors [and could in fact ignore any constructor 
> taking the class type by value or reference, directly or indirectly] (they 
> cannot be the only place that creates an object) and also why we don't want 
> to do this if there's a constexpr constructor or trivial default constructor 
> (we might not generate code for them). And the "no constructors" check seems 
> to effectively be checking whether aggregate initialization could be 
> performed.
> 
> I think we can replace the loop with `return !RD->isAggregate() && 
> !RD->hasTrivialDefaultConstructor();`.
> 
> (Minor aside, it is possible to create an instance of a type if its only 
> constructor is a copy constructor, eg with `struct A { A(const A&) {} } a = 
> a;`, but I doubt that's a practical concern for your purposes.)
> So the intent is to identify types for which we know that either no instances 
> are ever created, or some constructor must be actually emitted in some 
> translation unit (prior to optimizations running). And that's why we want to 
> ignore copy and move constructors [and could in fact ignore any constructor 
> taking the class type by value or reference, directly or indirectly] (they 
> cannot be the only place that creates an object) and also why we don't want 
> to do this if there's a constexpr constructor or trivial default constructor 
> (we might not generate code for them). And the "no constructors" check seems 
> to effectively be checking whether aggregate initialization could be 
> performed.

> I think we can replace the loop with return !RD->isAggregate() && 
> !RD->hasTrivialDefaultConstructor();.
Ok, I think that makes sense - I guess the loop was sort of attempting to do 
what `RD->hasTrivialDefaultConstructor()`does. 

> To fix this we should put 'homed' types in the retained types list so they 
> are preserved even if all other code/references to the type are dropped.
Yeah, think you mentioned this before and then I never added it--I'll make a 
separate patch for it. 


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D87808

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

Reply via email to