<div dir="auto">Can I chime in way after the fact? I <i>think</i> the move = bitcopies (P1029R3 by Niall Douglas) might help a lot with simplifying this problem, by allowing for a much simpler lifetime analysis when the smart pointer is moved around via std::move explicitly or when it's otherwise moved around implicitly (return values, etc).<div dir="auto"><br></div><div dir="auto">If you read the proposal, he mentions the trivial_abi attribute, and explicitly mentions unique_ptr. He's a smart guy.</div><div dir="auto"><br></div><div dir="auto">Obviously, that's a language solution, not a clang solution, but it seems more worthy of someone's time to implement the general solution than to implement a use-specific optimization pass.</div><div dir="auto"><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, Jun 5, 2020, 2:46 PM Zoe Carver via cfe-dev <<a href="mailto:cfe-dev@lists.llvm.org">cfe-dev@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div dir="ltr"><p style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Helvetica;min-height:17px">Hello all,<br><span style="font-variant-ligatures:no-common-ligatures"></span></p>
<p style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Helvetica;min-height:17px"><span style="font-variant-ligatures:no-common-ligatures"></span><br></p>
<p style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Helvetica"><span style="font-variant-ligatures:no-common-ligatures">I'm planning to do some work to add lifetime optimization passes for smart pointers and reference-counted objects. I'll use this email as a sort of proposal for what I hope to do. </span></p><p style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Helvetica"><span style="font-variant-ligatures:no-common-ligatures"><br></span></p>
<p style="margin:0px;font-stretch:normal;font-size:18px;line-height:normal;font-family:Helvetica"><b>Scope</b></p>
<p style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Helvetica;min-height:17px"><span style="font-variant-ligatures:no-common-ligatures"></span><br></p>
<p style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Helvetica"><span style="font-variant-ligatures:no-common-ligatures">As I'm developing the pass, I'm trying to keep it general and create utilities that could work across multiple smart pointers. But, right now, I'm focussing on</span><span style="letter-spacing:3.2px;font-variant-ligatures:no-common-ligatures"> </span><span style="font-stretch:normal;line-height:normal;font-family:Courier;font-variant-ligatures:no-common-ligatures">unique_pt</span><span style="font-stretch:normal;line-height:normal;font-family:Courier;letter-spacing:3.2px;font-variant-ligatures:no-common-ligatures">r</span><span style="font-variant-ligatures:no-common-ligatures"> and applying specific ownership optimizations to</span><span style="letter-spacing:3.2px;font-variant-ligatures:no-common-ligatures"> </span><span style="font-stretch:normal;line-height:normal;font-family:Courier;font-variant-ligatures:no-common-ligatures">unique_pt</span><span style="font-stretch:normal;line-height:normal;font-family:Courier;letter-spacing:3.2px;font-variant-ligatures:no-common-ligatures">r</span><span style="font-variant-ligatures:no-common-ligatures"> only. </span></p>
<p style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Helvetica;min-height:17px"><span style="font-variant-ligatures:no-common-ligatures"></span><br></p>
<p style="margin:0px;font-stretch:normal;font-size:18px;line-height:normal;font-family:Helvetica"><b>unique_ptr Optimzations</b></p>
<p style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Helvetica;min-height:17px"><span style="font-variant-ligatures:no-common-ligatures"></span><br></p>
<p style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Helvetica"><span style="font-variant-ligatures:no-common-ligatures">The pass I'm currently developing adds a single, simple, optimization: constant fold the destructor based on ownership information.</span><span style="letter-spacing:3.2px;font-variant-ligatures:no-common-ligatures"> </span><span style="font-stretch:normal;line-height:normal;font-family:Courier;font-variant-ligatures:no-common-ligatures">unique_pt</span><span style="font-stretch:normal;line-height:normal;font-family:Courier;letter-spacing:3.2px;font-variant-ligatures:no-common-ligatures">r</span><span style="font-variant-ligatures:no-common-ligatures"> has a lot of ownership information communicated with reference semantics. When a</span><span style="letter-spacing:3.2px;font-variant-ligatures:no-common-ligatures"> </span><span style="font-stretch:normal;line-height:normal;font-family:Courier;font-variant-ligatures:no-common-ligatures">unique_pt</span><span style="font-stretch:normal;line-height:normal;font-family:Courier;letter-spacing:3.2px;font-variant-ligatures:no-common-ligatures">r</span><span style="font-variant-ligatures:no-common-ligatures"> is moved into another function, that function takes over ownership of the</span><span style="letter-spacing:3.2px;font-variant-ligatures:no-common-ligatures"> </span><span style="font-stretch:normal;line-height:normal;font-family:Courier;font-variant-ligatures:no-common-ligatures">unique_pt</span><span style="font-stretch:normal;line-height:normal;font-family:Courier;letter-spacing:3.2px;font-variant-ligatures:no-common-ligatures">r</span><span style="font-variant-ligatures:no-common-ligatures">, and subsequent destructors can be eliminated (because they will be no-ops). Otherwise, branchless functions are often complicated after inlining</span><span style="letter-spacing:3.2px;font-variant-ligatures:no-common-ligatures"> </span><span style="font-stretch:normal;line-height:normal;font-family:Courier;font-variant-ligatures:no-common-ligatures">unique_pt</span><span style="font-stretch:normal;line-height:normal;font-family:Courier;letter-spacing:3.2px;font-variant-ligatures:no-common-ligatures">r</span><span style="font-variant-ligatures:no-common-ligatures">'s destructor so, this optimization should be fairly beneficial.</span></p>
<p style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Helvetica;min-height:17px"><span style="letter-spacing:3.2px;font-variant-ligatures:no-common-ligatures"></span><br></p>
<p style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Helvetica"><span style="font-stretch:normal;line-height:normal;font-family:Courier;font-variant-ligatures:no-common-ligatures">unique_pt</span><span style="font-stretch:normal;line-height:normal;font-family:Courier;letter-spacing:3.2px;font-variant-ligatures:no-common-ligatures">r</span><span style="font-variant-ligatures:no-common-ligatures">'s reset and release methods both complicate this optimization a bit. Because they are also able to transfer and remove ownership, all unknown instructions must be ignored. However, in the future, knowledge of those methods might be able to make the pass more robust. </span></p>
<p style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Helvetica;min-height:17px"><span style="font-variant-ligatures:no-common-ligatures"></span><br></p>
<p style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Helvetica"><span style="font-variant-ligatures:no-common-ligatures">With</span><span style="letter-spacing:3.2px;font-variant-ligatures:no-common-ligatures"> </span><span style="font-stretch:normal;line-height:normal;font-family:Courier;font-variant-ligatures:no-common-ligatures">unique_pt</span><span style="font-stretch:normal;line-height:normal;font-family:Courier;letter-spacing:3.2px;font-variant-ligatures:no-common-ligatures">r</span><span style="font-variant-ligatures:no-common-ligatures">, it's difficult to prove liveness. So, it is hard to constant fold the destructor call to always be there. Maybe in the future, this would be possible, though (with sufficient analysis). </span></p>
<p style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Helvetica;min-height:17px"><span style="font-variant-ligatures:no-common-ligatures"></span><br></p>
<p style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Helvetica"><span style="font-variant-ligatures:no-common-ligatures">Last, an optimization that I hope to do is lowering the</span><span style="letter-spacing:3.2px;font-variant-ligatures:no-common-ligatures"> </span><span style="font-stretch:normal;line-height:normal;font-family:Courier;font-variant-ligatures:no-common-ligatures">unique_pt</span><span style="font-stretch:normal;line-height:normal;font-family:Courier;letter-spacing:3.2px;font-variant-ligatures:no-common-ligatures">r</span><span style="font-variant-ligatures:no-common-ligatures"> to a raw pointer if all lifetime paths are known. I think removing this layer of abstraction would make it easier for other optimization passes to be successful. Eventually, we may even be able to specialize functions that used to take a</span><span style="letter-spacing:3.2px;font-variant-ligatures:no-common-ligatures"> </span><span style="font-stretch:normal;line-height:normal;font-family:Courier;font-variant-ligatures:no-common-ligatures">unique_pt</span><span style="font-stretch:normal;line-height:normal;font-family:Courier;letter-spacing:3.2px;font-variant-ligatures:no-common-ligatures">r</span><span style="font-variant-ligatures:no-common-ligatures"> to now take a raw pointer, if the argument's lifetime was also able to be fully analyzed. </span></p><p style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Helvetica"><span style="font-variant-ligatures:no-common-ligatures"><br></span></p>
<p style="margin:0px;font-stretch:normal;font-size:18px;line-height:normal;font-family:Helvetica"><b>Lifetime Annotations</b></p>
<p style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Helvetica;min-height:17px"><span style="font-variant-ligatures:no-common-ligatures"></span><br></p>
<p style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Helvetica"><span style="font-variant-ligatures:no-common-ligatures">Right now, the pass relies on (pre-inlined) function calls to generate ownership information. Another approach would be to add ownership annotations, such as the lifetime intrinsics (i.e.</span><span style="letter-spacing:3.2px;font-variant-ligatures:no-common-ligatures"> </span><span style="font-stretch:normal;line-height:normal;font-family:Courier;font-variant-ligatures:no-common-ligatures">llvm.lifetime.star</span><span style="font-stretch:normal;line-height:normal;font-family:Courier;letter-spacing:3.2px;font-variant-ligatures:no-common-ligatures">t</span><span style="font-variant-ligatures:no-common-ligatures">). </span></p>
<p style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Helvetica;min-height:17px"><span style="font-variant-ligatures:no-common-ligatures"></span><br></p>
<p style="margin:0px;font-stretch:normal;font-size:18px;line-height:normal;font-family:Helvetica"><b>ARC Optimizations</b></p>
<p style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Helvetica;min-height:17px"><span style="font-variant-ligatures:no-common-ligatures"></span><br></p>
<p style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Helvetica"><span style="font-variant-ligatures:no-common-ligatures">There are a huge number of large and small ARC optimizations already in LLVM. For</span><span style="letter-spacing:3.2px;font-variant-ligatures:no-common-ligatures"> </span><span style="font-stretch:normal;line-height:normal;font-family:Courier;font-variant-ligatures:no-common-ligatures">unique_pt</span><span style="font-stretch:normal;line-height:normal;font-family:Courier;letter-spacing:3.2px;font-variant-ligatures:no-common-ligatures">r</span><span style="font-variant-ligatures:no-common-ligatures"> specifically, I'm not sure these are of any benefit because</span><span style="letter-spacing:3.2px;font-variant-ligatures:no-common-ligatures"> </span><span style="font-stretch:normal;line-height:normal;font-family:Courier;font-variant-ligatures:no-common-ligatures">unique_pt</span><span style="font-stretch:normal;line-height:normal;font-family:Courier;letter-spacing:3.2px;font-variant-ligatures:no-common-ligatures">r</span><span style="font-variant-ligatures:no-common-ligatures"> doesn't actually do any reference counting. But, later on, when I start working on generalizing this pass to support more smart pointers (specifically</span><span style="letter-spacing:3.2px;font-variant-ligatures:no-common-ligatures"> </span><span style="font-stretch:normal;line-height:normal;font-family:Courier;font-variant-ligatures:no-common-ligatures">shared_pt</span><span style="font-stretch:normal;line-height:normal;font-family:Courier;letter-spacing:3.2px;font-variant-ligatures:no-common-ligatures">r</span><span style="font-variant-ligatures:no-common-ligatures">) I think the ARC optimization pass, and especially the utilities it contains, could be very beneficial. If anyone has experience with ARC optimizations, I'd love to hear your thoughts on extending them to other reference counted objects. </span></p>
<p style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Helvetica;min-height:17px"><span style="font-variant-ligatures:no-common-ligatures"></span><br></p>
<p style="margin:0px;font-stretch:normal;font-size:18px;line-height:normal;font-family:Helvetica"><b>trivial_abi and Hidden References</b></p>
<p style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Helvetica;min-height:17px"><span style="font-variant-ligatures:no-common-ligatures"></span><br></p>
<p style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Helvetica"><span style="font-variant-ligatures:no-common-ligatures">Arthur O'Dwyer made a good point, which is that a lot of these optimizations can be applied when with the</span><span style="letter-spacing:3.2px;font-variant-ligatures:no-common-ligatures"> </span><span style="font-stretch:normal;line-height:normal;font-family:Courier;font-variant-ligatures:no-common-ligatures">trivial_ab</span><span style="font-stretch:normal;line-height:normal;font-family:Courier;letter-spacing:3.2px;font-variant-ligatures:no-common-ligatures">i</span><span style="font-variant-ligatures:no-common-ligatures"> attribute. However, given that's not a standard attribute and these optimizations only <i>happen</i> to work with</span><span style="letter-spacing:3.2px;font-variant-ligatures:no-common-ligatures"> </span><span style="font-stretch:normal;line-height:normal;font-family:Courier;font-variant-ligatures:no-common-ligatures">trivial_ab</span><span style="font-stretch:normal;line-height:normal;font-family:Courier;letter-spacing:3.2px;font-variant-ligatures:no-common-ligatures">i</span><span style="font-variant-ligatures:no-common-ligatures"> (i.e., in a more complicated program, they may not continue to work). I think lifetime utilities and specific lifetime optimization passes are still beneficial (especially if they can be applied to other smart pointers in the future). </span></p>
<p style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Helvetica;min-height:17px"><span style="font-variant-ligatures:no-common-ligatures"></span><br></p>
<p style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Helvetica"><span style="font-variant-ligatures:no-common-ligatures">Because all smart pointers have non-trivial destructors, they are always passed by hidden references. With</span><span style="letter-spacing:3.2px;font-variant-ligatures:no-common-ligatures"> </span><span style="font-stretch:normal;line-height:normal;font-family:Courier;font-variant-ligatures:no-common-ligatures">unique_pt</span><span style="font-stretch:normal;line-height:normal;font-family:Courier;letter-spacing:3.2px;font-variant-ligatures:no-common-ligatures">r</span><span style="font-variant-ligatures:no-common-ligatures">, this is as simple as bit-casting the pointer member to</span><span style="letter-spacing:3.2px;font-variant-ligatures:no-common-ligatures"> </span><span style="font-stretch:normal;line-height:normal;font-family:Courier;font-variant-ligatures:no-common-ligatures">unique_pt</span><span style="font-stretch:normal;line-height:normal;font-family:Courier;letter-spacing:3.2px;font-variant-ligatures:no-common-ligatures">r</span><span style="font-variant-ligatures:no-common-ligatures">, which would allow for it to be lowered to a single raw pointer instead of a stack-allocated object. Even without the</span><span style="letter-spacing:3.2px;font-variant-ligatures:no-common-ligatures"> </span><span style="font-stretch:normal;line-height:normal;font-family:Courier;font-variant-ligatures:no-common-ligatures">trival_ab</span><span style="font-stretch:normal;line-height:normal;font-family:Courier;letter-spacing:3.2px;font-variant-ligatures:no-common-ligatures">i</span><span style="font-variant-ligatures:no-common-ligatures"> attribute, I think this is an optimization that could be done.</span></p>
<p style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Helvetica;min-height:17px"><span style="font-variant-ligatures:no-common-ligatures"></span><br></p>
<p style="margin:0px;font-stretch:normal;font-size:18px;line-height:normal;font-family:Helvetica"><b>Results</b></p>
<p style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Helvetica;min-height:17px"><span style="font-variant-ligatures:no-common-ligatures"></span><br></p>
<p style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Helvetica"><span style="font-variant-ligatures:no-common-ligatures">Here's the</span><span style="letter-spacing:3.2px;font-variant-ligatures:no-common-ligatures"> </span><span style="font-stretch:normal;line-height:normal;font-family:Courier;font-variant-ligatures:no-common-ligatures">unique_pt</span><span style="font-stretch:normal;line-height:normal;font-family:Courier;letter-spacing:3.2px;font-variant-ligatures:no-common-ligatures">r</span><span style="font-variant-ligatures:no-common-ligatures"> pass I've been talking about: <a href="https://reviews.llvm.org/D81288" target="_blank" rel="noreferrer">⚙ D81288 Opt Smart pointer lifetime optimizations pass<span style="letter-spacing:1.3px;font-variant-ligatures:no-common-ligatures">.</span></a></span></p>
<p style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Helvetica"><span style="font-variant-ligatures:no-common-ligatures">For reference, here are the before and after results:</span></p>
<p style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Helvetica"><span style="font-variant-ligatures:no-common-ligatures">Clang trunk (four branches): <a href="https://godbolt.org/z/bsJFty" target="_blank" rel="noreferrer">Compiler Explore<span style="letter-spacing:1.3px;font-variant-ligatures:no-common-ligatures">r</span></a></span></p>
<p style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Helvetica"><span style="font-variant-ligatures:no-common-ligatures">With optimizations (branchless): <a href="https://pastebin.com/raw/mQ2r6pru" target="_blank" rel="noreferrer">https://pastebin.com/raw/mQ2r6pru</a></span></p>
<p style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Helvetica;min-height:17px"><span style="font-variant-ligatures:no-common-ligatures"></span><br></p>
<p style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Helvetica"><span style="font-variant-ligatures:no-common-ligatures">Best,</span></p>
<p style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Helvetica"><span style="font-variant-ligatures:no-common-ligatures">Zoe</span></p></div></div>
_______________________________________________<br>
cfe-dev mailing list<br>
<a href="mailto:cfe-dev@lists.llvm.org" target="_blank" rel="noreferrer">cfe-dev@lists.llvm.org</a><br>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" rel="noreferrer noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev</a><br>
</blockquote></div>