On Thu, May 16, 2013 at 10:13 AM, Chris Lattner <span dir="ltr"><<a href="mailto:clattner@apple.com" target="_blank">clattner@apple.com</a>></span> wrote:<br><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div style="word-wrap:break-word"><div class="im"><div><div>On May 15, 2013, at 10:32 PM, Richard Smith <<a href="mailto:richard@metafoo.co.uk" target="_blank">richard@metafoo.co.uk</a>> wrote:</div><blockquote type="cite">
<div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><div><div><blockquote type="cite"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<div style="word-wrap:break-word"><div><div><blockquote type="cite"><div class="gmail_quote"><div>Initially, I'm just concerned about keeping the optimizations we already perform, such as globalopt lowering a new/delete pair into a global, while disabling the non-conforming variations of those optimizations. But we're also permitted to merge multiple allocations into one if they have sufficiently similar lifetimes.</div>



</div>
</blockquote></div><br></div><div>So your proposal is for Clang to slap the attribute on explicit calls to ::operator new, but any other use of the symbol (e.g. from C code or something else weird) can be optimized?</div>


</div></blockquote><div><br></div><div>No, because Clang cannot statically detect which indirect calls might call ::operator new. Instead, my proposal is to add a 'builtin' attribute to LLVM, and then for clang to add that attribute to the calls which can be optimized.</div>

</div></blockquote><div><br></div></div><div>Ugh.  Having two different ways to represent "the same" thing is deeply unfortunate.  I don't understand the full issue here though, how can you get an indirect call to ::operator new?  Can you take its address in C++?</div>

</div></div></blockquote><div><br></div><div>Yes. operator new is an ordinary function that happens to have a funny name, and can have its address taken.</div></div></blockquote><br></div></div><div>To be clear, I'm only objecting because I don't want to add complexity to the IR for such a weird corner case.</div>
<div><br></div><div>Just brainstorming here, and yes, this is somewhat horrible, but would it be possible to handle this by having IRGen introduce a "thunk" function in the case when ::operator new has its address taken?</div>
<div><br></div><div>For example, you could have this pseudo code:</div><div><br></div><div><br></div><div><span style="white-space:pre-wrap">   </span>auto FP = & ::operator new;  // I have no idea how to actually spell this in C++</div>
<div><br></div><div>IRGen into the equivalent of:</div><div><br></div><div><span style="white-space:pre-wrap">    </span>static void *thunk(size_t NumBytes) {</div><div><span style="white-space:pre-wrap">    </span>  return ::operator new(NumBytes);   // Direct call, with nobuiltin attribute set.</div>
<div><span style="white-space:pre-wrap">  </span>}</div><div><br></div><div><span style="white-space:pre-wrap">       </span>auto FP = thunk;</div><div><br></div><div>That way the pain of this corner case is hoisted into clang, instead of subjecting all consumers of LLVM IR to a complexity increase.</div>
</div></blockquote><div><br></div><div>That would violate the ABI. Another TU, built by another compiler, could do something like this:</div><div><br></div><div>extern void *(*FP)(size_t); </div><div>void f() {</div><div>
  assert(FP == (void*(*)(size_t))&::operator new);</div><div>}</div><div><br></div><div>That assert is not permitted to fire.</div><div><br></div><div>Since it would probably help to quantify the complexity increase, I've implemented my more recent suggestion (patch attached). This patch allows 'nobuiltin' on a function declaration or definition, and adds a 'builtin' attribute which can only be present on a call site for a direct call to a function declared with the 'nobuiltin' attribute. The 'builtin' attribute has the effect of canceling out the 'nobuiltin' attribute on the declaration.</div>
<div><br></div><div>This (incidentally) also exactly matches what we want for another Clang feature: we want a -fno-builtin-foo which makes 'foo' not be a builtin (but we still want __builtin_foo to have the builtin behavior). This, again, is not possible with the existing 'nobuiltin' attribute, due to the function pointer problem. Instead, Clang currently just provides -fno-builtin, and even *that* only provides a broken half-implementation -- it calls TargetLibraryInfo::disableAllFunctions, whose effect is not preserved across "clang -fno-builtin -emit-llvm | opt", nor across LTO.</div>
</div>