<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Sep 25, 2015 at 8:22 AM, David Majnemer <span dir="ltr"><<a href="mailto:david.majnemer@gmail.com" target="_blank">david.majnemer@gmail.com</a>></span> wrote:<br><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 dir="ltr">FWIW, consider the following:<div><div>$ cat t.c</div><div><div>extern "C"</div><div>int printf(const char *, ...);</div><div><br></div><div>struct S {</div><div> int x[];</div><div>};</div><div><br></div><div>void f(S a) {</div><div> S b;</div><div> printf("%p %p\n", &a, &b);</div><div>}</div><div><br></div><div>int main() {</div><div> S s;</div><div> f(s);</div><div>}</div></div></div><div><br></div><div>$ clang -O2 t.cpp -o t && ./t</div><div>0x7fff5e75a8e8 0x7fff5e75a8e8<br></div><div><br></div><div>Perhaps Dan was concerned about zero sized objects?</div></div></blockquote><div><br></div><div>This case is a red herring, we CSE'd the stack allocations for 'a' and 's' which left us with 'call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([7 x i8]* @.str, i64 0, i64 0), %struct.S* %b.i, %struct.S* %b.i)'</div><div> </div><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 dir="ltr"><div><br></div></div><div class=""><div class="h5"><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Sep 24, 2015 at 6:04 PM, Hans Wennborg via llvm-dev <span dir="ltr"><<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a>></span> wrote:<br><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">I tried your patch on a Clang build to see if it would fire. It<br>
reduced the size of a bootstrap with 8500 bytes. Not huge, but it<br>
seems like a nice improvement. And maybe it could be made more<br>
powerful: not just checking if the address is a param or alloca, but<br>
an address based on such values.<br>
<div><div><br>
On Thu, Sep 24, 2015 at 2:55 PM, Philip Reames<br>
<<a href="mailto:listmail@philipreames.com" target="_blank">listmail@philipreames.com</a>> wrote:<br>
> I threw together a patch which implements this (attached.) If we decide<br>
> that this is actually a legal transform, I'm happy to post this for review.<br>
><br>
> In addition to the version proposed here, I also implemented a case where a<br>
> trivially escaped alloca's address is not equal to any other value. I<br>
> believe both are valid, but we should confirm.<br>
><br>
> Philip<br>
><br>
><br>
> On 09/24/2015 02:34 PM, Aaron Ballman via llvm-dev wrote:<br>
>><br>
>> On Thu, Sep 24, 2015 at 5:15 PM, Hans Wennborg <<a href="mailto:hans@chromium.org" target="_blank">hans@chromium.org</a>> wrote:<br>
>>><br>
>>> On Thu, Sep 24, 2015 at 12:06 PM, Aaron Ballman <<a href="mailto:aaron@aaronballman.com" target="_blank">aaron@aaronballman.com</a>><br>
>>> wrote:<br>
>>>><br>
>>>> On Thu, Sep 24, 2015 at 2:42 PM, Hans Wennborg <<a href="mailto:hans@chromium.org" target="_blank">hans@chromium.org</a>><br>
>>>> wrote:<br>
>>>>><br>
>>>>> I was wondering why LLVM cannot optimize this code (which GCC does<br>
>>>>> optimize):<br>
>>>>><br>
>>>>> int f(int *p) { int x; return p == &x; }<br>
>>>>><br>
>>>>> it would seem that this must always return 0. (This occurs as a<br>
>>>>> self-assignment check in the code I was looking at; I was hoping we<br>
>>>>> could fold that check away.)<br>
>>>><br>
>>>> This is different than a self-assignment check, is it not?<br>
>>>><br>
>>>> blah& operator=(const blah &b) {<br>
>>>> if (&b == this) {}<br>
>>>> // ...<br>
>>>> }<br>
>>>><br>
>>>> (Because it gets the pointer from the parameter and compares against a<br>
>>>> "local" pointer?)<br>
>>>><br>
>>>> I just want to make sure that you're not suggesting we should optimize<br>
>>>> away self-assignment checks in the general case.<br>
>>><br>
>>> Right, I'm not suggesting that :-)<br>
>>><br>
>>> The code I looked at went something like this:<br>
>>><br>
>>> struct S {<br>
>>> S& operator=(const S& other) {<br>
>>> if (&other != this)<br>
>>> val = other.val;<br>
>>> return *this;<br>
>>> }<br>
>>> void foo();<br>
>>> int val;<br>
>>> };<br>
>>> void S::foo() {<br>
>>> S tmp;<br>
>>> tmp.val = 42;<br>
>>> *this = tmp; // operator= gets inlined; we should know(?) that &tmp<br>
>>> != this<br>
>>> }<br>
>>><br>
>>> This is of course a silly example, but with GCC we get:<br>
>>><br>
>>> movl $42, (%rdi)<br>
>>> ret<br>
>>><br>
>>> whereas Clang generates:<br>
>>><br>
>>> movl $42, -8(%rsp)<br>
>>> leaq -8(%rsp), %rax<br>
>>> cmpq %rdi, %rax<br>
>>> je .LBB0_2<br>
>>> movl $42, (%rdi)<br>
>>> .LBB0_2:<br>
>>> retq<br>
>>><br>
>>> which made me sad.<br>
>><br>
>> Ah, yes, this makes perfect sense to me. Thank you for the explanation!<br>
>><br>
>> ~Aaron<br>
>><br>
>>><br>
>>>>> I'd be interested to hear what those with a stronger understanding of<br>
>>>>> the standard than myself think about this, and also if there is any<br>
>>>>> example of something that could break because of this optimization. If<br>
>>>>> not, I'd like us to optimize it :-)<br>
>>>>><br>
>>>>><br>
>>>>> On Thu, Jan 31, 2013 at 4:49 PM, Dan Gohman <<a href="mailto:dan433584@gmail.com" target="_blank">dan433584@gmail.com</a>><br>
>>>>> wrote:<br>
>>>>>><br>
>>>>>> Author: djg<br>
>>>>>> Date: Thu Jan 31 18:49:06 2013<br>
>>>>>> New Revision: 174131<br>
>>>>>><br>
>>>>>> URL: <a href="http://llvm.org/viewvc/llvm-project?rev=174131&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=174131&view=rev</a><br>
>>>>>> Log:<br>
>>>>>> Add a comment explaining an unavailable optimization.<br>
>>>>>><br>
>>>>>> Modified:<br>
>>>>>> llvm/trunk/lib/Analysis/InstructionSimplify.cpp<br>
>>>>>><br>
>>>>>> Modified: llvm/trunk/lib/Analysis/InstructionSimplify.cpp<br>
>>>>>> URL:<br>
>>>>>> <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/InstructionSimplify.cpp?rev=174131&r1=174130&r2=174131&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/InstructionSimplify.cpp?rev=174131&r1=174130&r2=174131&view=diff</a><br>
>>>>>><br>
>>>>>> ==============================================================================<br>
>>>>>> --- llvm/trunk/lib/Analysis/InstructionSimplify.cpp (original)<br>
>>>>>> +++ llvm/trunk/lib/Analysis/InstructionSimplify.cpp Thu Jan 31<br>
>>>>>> 18:49:06 2013<br>
>>>>>> @@ -1688,6 +1688,34 @@ static Value *ExtractEquivalentCondition<br>
>>>>>> return 0;<br>
>>>>>> }<br>
>>>>>><br>
>>>>>> +// A significant optimization not implemented here is assuming that<br>
>>>>>> alloca<br>
>>>>>> +// addresses are not equal to incoming argument values. They don't<br>
>>>>>> *alias*,<br>
>>>>>> +// as we say, but that doesn't mean they aren't equal, so we take a<br>
>>>>>> +// conservative approach.<br>
>>>>>> +//<br>
>>>>>> +// This is inspired in part by C++11 5.10p1:<br>
>>>>>> +// "Two pointers of the same type compare equal if and only if they<br>
>>>>>> are both<br>
>>>>>> +// null, both point to the same function, or both represent the<br>
>>>>>> same<br>
>>>>>> +// address."<br>
>>>>>> +//<br>
>>>>>> +// This is pretty permissive.<br>
>>>>><br>
>>>>> Indeed :-/<br>
>>>>><br>
>>>>>> +// It's also partly due to C11 6.5.9p6:<br>
>>>>>> +// "Two pointers compare equal if and only if both are null<br>
>>>>>> pointers, both are<br>
>>>>>> +// pointers to the same object (including a pointer to an object<br>
>>>>>> and a<br>
>>>>>> +// subobject at its beginning) or function, both are pointers to<br>
>>>>>> one past the<br>
>>>>>> +// last element of the same array object, or one is a pointer to<br>
>>>>>> one past the<br>
>>>>>> +// end of one array object and the other is a pointer to the start<br>
>>>>>> of a<br>
>>>>>> +// different array object that happens to immediately follow the<br>
>>>>>> ï¬ rst array<br>
>>>>>> +// object in the address space.)<br>
>>>>>> +//<br>
>>>>>> +// C11's version is more restrictive, however there's no reason why<br>
>>>>>> an argument<br>
>>>>>> +// couldn't be a one-past-the-end value for a stack object in the<br>
>>>>>> caller and be<br>
>>>>>> +// equal to the beginning of a stack object in the callee.<br>
>>>>><br>
>>>>> This is interesting.<br>
>>>>><br>
>>>>> For the one-past-the-end pointer to point into the callee, the stack<br>
>>>>> would have to be growing upwards. So this won't happen on X86. Can we<br>
>>>>> turn this optimization on for downward-growing-stack targets?<br>
>>>>><br>
>>>>> Second, if the stack grows upward, and the function argument does<br>
>>>>> point into the callee stack frame, "p" and "&x" could have the same<br>
>>>>> contents. So per the "represent the same address" part above, they<br>
>>>>> should compare equal? But they're noalias? Are we allowed to write<br>
>>>>> through p? It wasn't a pointer to a valid object when we made the<br>
>>>>> call, but it became valid in the callee? This is all terrifying.<br>
>>>>><br>
>>>>> I suppose one could store the value of &x though, and then use it<br>
>>>>> again later, i.e.:<br>
>>>>><br>
>>>>> int *global;<br>
>>>>> int f(int *p) {<br>
>>>>> int x;<br>
>>>>> global = &x;<br>
>>>>> return p == &x;<br>
>>>>> }<br>
>>>>> int g() {<br>
>>>>> f(0);<br>
>>>>> return f(global);<br>
>>>>> }<br>
>>>>><br>
>>>>> Is g() guaranteed to return 1 here? Maybe we could claim it's<br>
>>>>> implementation dependent? GCC does not seem fold p==&x to 0 here. I<br>
>>>>> suppose we could make sure to check whether &x escapes the function?<br>
>>>>><br>
>>>>> - Hans<br>
>><br>
>> _______________________________________________<br>
>> LLVM Developers mailing list<br>
>> <a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a><br>
>> <a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev</a><br>
><br>
><br>
_______________________________________________<br>
LLVM Developers mailing list<br>
<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev</a><br>
</div></div></blockquote></div><br></div>
</div></div></blockquote></div><br></div></div>