<div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote">On Tue, Nov 12, 2013 at 10:36 AM, Rafael Espíndola <span dir="ltr"><<a href="mailto:rafael.espindola@gmail.com" target="_blank">rafael.espindola@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="im">On 12 November 2013 13:21, David Blaikie <<a href="mailto:dblaikie@gmail.com">dblaikie@gmail.com</a>> wrote:<br>

> Talked with Chandler a bit (just for a pseudo-random (weighted by<br>
> convenience) C++ programmer perspective) about how problematic/surprising<br>
> this would be during debugging.<br>
><br>
> Had a couple of thoughts:<br>
><br>
> 1) In the case of a local "derived" object, we could possibly use inlining<br>
> debug info to describe the base dtor call to be an inlined instance of the<br>
> derived dtor. On further consideration I'm not sure this works generally<br>
> because the choice of aliasing/inlining could be made from another TU (does<br>
> this optimization fire for an out of line "= default" definition of a<br>
> special member?).<br>
><br>
> Tested the out-of-line = default case, this optimization doesn't seem to<br>
> fire and I still see the derived dtor on the stack.<br>
<br>
</div>What do you mean by "out-of-line = default"?<br></blockquote><div><br></div><div>struct derived: base {</div><div>  ~derived();<br>};<br><br>derived::~derived() = default;</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

<div class="im"><br>
> 2) In the case of virtual destruction, I assume this optimization doesn't<br>
> fire due to the derived dtor needing to do vtable changes? Maybe? On<br>
> experimentation this seems to be the case, though narrowly so.<br>
><br>
> Given:<br>
> struct base { virtual ~base() { f(); } };<br>
> struct derived: base { };<br>
><br>
> This:<br>
> derived d;<br>
> derived *p = new derived();<br>
> delete p;<br>
><br>
> Shows the base dtor run without the derived dtor in the call stack, but<br>
> this:<br>
><br>
> base *b = new derived();<br>
> delete b;<br>
><br>
> does show the derived dtor in the call stack. So that seems OK.<br>
<br>
</div>Yes, that is what should happen. The code has:<br>
<br>
 // If we need to manipulate a VTT parameter, give up.<br>
  if (Class->getNumVBases()) {<br></blockquote><div><br></div><div>Yet when I wrote this:<br><br>struct base {</div><div>  virtual ~base() { func(); }</div><div>};<br><br>struct derived : base {<br>};<br><br>int main() {</div>
<div>  derived d;<br>}<br><br>the call stack at "func()" did not include a derived dtor - perhaps this is an existing optimization not related to your change, then?</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

<div class="im"><br>
><br>
> So... what's the benefit of this optimization compared to letting the<br>
> backend inline the known-trivial dtors? Then we'd get the inlining debug<br>
> info for free in (1) (and the non-polymorphic cases of (2)) rather than<br>
> having to implement a special-case inlining in Clang. Does this fire in<br>
> other cases where LLVM cannot do this? Is there measurable overhead in<br>
> emitting trivial derived dtors that simply call their base dtor?<br>
<br>
</div>It fires in cases we don't have the body of the destructor we will be<br>
calling. For example:<br>
<br>
class foo {<br>
  ~foo();<br>
};<br>
<br>
class bar : public foo {<br>
};<br>
<br>
LLVM also does'n implement replacing the pointers in the vtables.</blockquote><div><br></div><div>But it doesn't look like your optimization was happening with vtables either, at least not in my tests. When the destruction is actually virtual (delete base_ptr_to_derived_obj) I see both base and derived dtors on the stack.</div>
<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"> We<br>
probably could (and should) implement an optimization in llvm so that<br>
a trivial unnamed_addr function that just calls another is replaced<br>
with an alias or replaced with the callee.<br></blockquote><div><br>Probably, but I'm not sure that's what I'm asking about.<br><br>I'm asking about the simple cases of known-derived object destruction skipping the derived dtor (such as the example above with "derived d;" in main). But as I said - maybe that's a different optimization that's not related to your change?<br>
 </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
It is probably still a good idea to keep the special case in clang, at<br>
the very least until llvm can cover this cases. It is also not clear<br>
exactly where we should put such optimization in llvm. It should<br>
happen fairly early to avoid one being inlinned into the other. We<br>
also need some logic like this for the Base/Complete destructors where<br>
msvc only outputs one if they would be identical.<br>
<br>
Cheers,<br>
Rafael<br>
</blockquote></div><br></div><div class="gmail_extra"><br></div><div class="gmail_extra"><br></div></div>