On Thu, May 16, 2013 at 10:13 AM, Chris Lattner <clattner at apple.com>
wrote:
> On May 15, 2013, at 10:32 PM, Richard Smith <richard at
metafoo.co.uk> wrote:
>
> 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.
>>>
>>>
>>> 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?
>>>
>>
>> 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.
>>
>>
>> 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++?
>>
>
> Yes. operator new is an ordinary function that happens to have a funny
> name, and can have its address taken.
>
>
> To be clear, I'm only objecting because I don't want to add
complexity to
> the IR for such a weird corner case.
>
> 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?
>
> For example, you could have this pseudo code:
>
>
> auto FP = & ::operator new; // I have no idea how to actually spell
this
> in C++
>
> IRGen into the equivalent of:
>
> static void *thunk(size_t NumBytes) {
> return ::operator new(NumBytes); // Direct call, with nobuiltin
> attribute set.
> }
>
> auto FP = thunk;
>
> That way the pain of this corner case is hoisted into clang, instead of
> subjecting all consumers of LLVM IR to a complexity increase.
>
That would violate the ABI. Another TU, built by another compiler, could do
something like this:
extern void *(*FP)(size_t);
void f() {
assert(FP == (void*(*)(size_t))&::operator new);
}
That assert is not permitted to fire.
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.
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.
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://lists.llvm.org/pipermail/llvm-dev/attachments/20130516/cf7faa57/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: builtin-nobuiltin.diff
Type: application/octet-stream
Size: 13412 bytes
Desc: not available
URL:
<http://lists.llvm.org/pipermail/llvm-dev/attachments/20130516/cf7faa57/attachment.obj>