<div dir="ltr">At runtime, without the hoisting, the undef value will never be referenced, but the speculative hoisting of the comparison introduces the real undef reference.  Another workaround is to disable such speculative LICM in the first place.  If it is hoisted, it should really be like:<div><br></div><div>if (some_cond)</div><div>   t1 = (a == i)</div><div>else</div><div>   t2 = undef</div><div>t = phi(t1, t2)</div><div><br></div><div>In this case, the condition is loop variant, so it is not possible.</div><div><br></div><div>David</div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Jul 17, 2017 at 5:11 PM, Wei Mi <span dir="ltr"><<a href="mailto:wmi@google.com" target="_blank">wmi@google.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">On Mon, Jul 17, 2017 at 2:09 PM, Sanjoy Das<br>
<<a href="mailto:sanjoy@playingwithpointers.com">sanjoy@playingwithpointers.<wbr>com</a>> wrote:<br>
> Hi,<br>
><br>
> On Mon, Jul 17, 2017 at 1:56 PM, Daniel Berlin via llvm-dev<br>
> <<a href="mailto:llvm-dev@lists.llvm.org">llvm-dev@lists.llvm.org</a>> wrote:<br>
>><br>
>><br>
>> On Mon, Jul 17, 2017 at 1:53 PM, Wei Mi <<a href="mailto:wmi@google.com">wmi@google.com</a>> wrote:<br>
>>><br>
>>> It seems MemorySSA.cpp is the only real code where we found the<br>
>>> problem happening.<br>
>><br>
>><br>
>> This is doubtful, ¸FWIW :)<br>
>><br>
>>><br>
>>> Is it possible to change the source of<br>
>>> MemorySSA.cpp to hide the problem and buy some time for now? Now we<br>
>>> use an empty generic_def_path_iterator with Optional<ListIndex> N<br>
>>> being initialized by None as the end of range. Can we initialize the<br>
>>> Optional var with a special value instead of None?<br>
>>><br>
>>>   iterator_range<def_path_<wbr>iterator> def_path(ListIndex From) {<br>
>>>     return make_range(def_path_iterator(<wbr>this, From), def_path_iterator());<br>
>>>   }<br>
>>><br>
>><br>
>> Why does this work?<br>
><br>
> Fwiw, I don't think this is a good idea.  If it can happen in<br>
> MemorySSA it can happen in other organic C++ source code too - think<br>
> about what you're going to tell other folks who run into this issue,<br>
> where such a workaround may be difficult to achieve or explain.<br>
><br>
> -- Sanjoy<br>
<br>
</span>Talked with David offline and he suggested a simple workaround<br>
solution. For the case in MemorySSA.cpp, we have "if (a == b)" with b<br>
being defined by a phi, and the phi has an undef operand. We can<br>
recognize the simple pattern and give up loop unswitch for it. The<br>
idea is not to use isGuaranteedNotToBeUndefOrPois<wbr>on to prove<br>
correctness, but just to rule out some patterns where such error may<br>
appear.<br>
<br>
I admit the solution is far from ideal, but at least it is very simple<br>
to implement, and serves to mitigate the immediate correctness issue<br>
while avoiding performance regression. What do you think?<br>
<br>
Thanks,<br>
Wei.<br>
<div class="HOEnZb"><div class="h5"><br>
><br>
>><br>
>>><br>
>>><br>
>>> On Mon, Jul 17, 2017 at 1:37 PM, Daniel Berlin <<a href="mailto:dberlin@dberlin.org">dberlin@dberlin.org</a>><br>
>>> wrote:<br>
>>> > I think everyone agrees pretty much everything short of "Fix undef" will<br>
>>> > not<br>
>>> > fix the problem for good.<br>
>>> > I think we are more trying to hide it well enough that we get the months<br>
>>> > we<br>
>>> > need for various folks to work on the larger proposals.<br>
>>> > Which sucks, but not sure we have a better answer, because i don't think<br>
>>> > we<br>
>>> > are going to commit the freeze/etc patches tomorrow.<br>
>>> ><br>
>>> ><br>
>>> > On Mon, Jul 17, 2017 at 1:34 PM, Juneyoung Lee<br>
>>> > <<a href="mailto:juneyoung.lee@sf.snu.ac.kr">juneyoung.lee@sf.snu.ac.kr</a>><br>
>>> > wrote:<br>
>>> >><br>
>>> >> Hello, some of the patches had conflicts with LLVM head, so I updated<br>
>>> >> them. If you experienced patch failure before then you can try it<br>
>>> >> again.<br>
>>> >><br>
>>> >> I compiled your code (1.c) with LLVM r308173 with the 5 patches<br>
>>> >> applied,<br>
>>> >> and it generated assembly like this. Now it contains store to c(%rip).<br>
>>> >> It tries to store a(%rip) + b(%rip) to c(%rip). I wish this translation<br>
>>> >> is<br>
>>> >> now correct.<br>
>>> >><br>
>>> >> ```<br>
>>> >> 73   .globl  hoo                     # -- Begin function hoo<br>
>>> >> 74   .p2align  4, 0x90<br>
>>> >> 75   .type hoo,@function<br>
>>> >> 76 hoo:                                    # @hoo<br>
>>> >> 77   .cfi_startproc<br>
>>> >> 78 # BB#0:<br>
>>> >> 79   movq  a(%rip), %rax<br>
>>> >> 80   movq  cnt(%rip), %rcx<br>
>>> >> 81   cmpq  $0, i_hasval(%rip)<br>
>>> >> 82   sete  %sil<br>
>>> >> 83   xorl  %edx, %edx<br>
>>> >> 84   .p2align  4, 0x90<br>
>>> >> 85 .LBB1_1:                                # =>This Inner Loop Header:<br>
>>> >> Depth=1<br>
>>> >> 86   testb $1, %sil<br>
>>> >> 87   je  .LBB1_3<br>
>>> >> 88 # BB#2:                                 #   in Loop: Header=BB1_1<br>
>>> >> Depth=1<br>
>>> >> 89   movq  b(%rip), %rsi<br>
>>> >> 90   addq  %rax, %rsi<br>
>>> >> 91   movq  %rsi, c(%rip)<br>
>>> >> 92   movq  $3, i_hasval(%rip)<br>
>>> >> 93   incq  %rdx<br>
>>> >> 94   xorl  %esi, %esi<br>
>>> >> 95   cmpq  %rcx, %rdx<br>
>>> >> 96   jl  .LBB1_1<br>
>>> >> 97 .LBB1_3:<br>
>>> >> 98   retq<br>
>>> >> ```<br>
>>> >><br>
>>> >> IMHO, enhancing `<wbr>isGuaranteedNotToBeUndefOrPois<wbr>on` and using it as a<br>
>>> >> precondition in loop unswitching is<br>
>>> >> not enough. undef (and poison) value can be stored into memory, and<br>
>>> >> also<br>
>>> >> be passed by a function argument.<br>
>>> >> `<wbr>isGuaranteedNotToBeUndefOrPois<wbr>on` will virtually return `false` for<br>
>>> >> all<br>
>>> >> cases except the value is<br>
>>> >> some integer constant. Sanjoy's suggestion might be helpful (if I<br>
>>> >> understood correctly), but I'm<br>
>>> >> not sure how much it will be.<br>
>>> >><br>
>>> >> Best Regards,<br>
>>> >> Juneyoung Lee<br>
>>> >><br>
>>> >> On Tue, Jul 18, 2017 at 3:43 AM, Sanjoy Das via llvm-dev<br>
>>> >> <<a href="mailto:llvm-dev@lists.llvm.org">llvm-dev@lists.llvm.org</a>> wrote:<br>
>>> >>><br>
>>> >>> On Mon, Jul 17, 2017 at 11:21 AM, Daniel Berlin <<a href="mailto:dberlin@dberlin.org">dberlin@dberlin.org</a>><br>
>>> >>> wrote:<br>
>>> >>> >> On Mon, Jul 17, 2017 at 10:32 AM, Xinliang David Li<br>
>>> >>> >> <<a href="mailto:davidxl@google.com">davidxl@google.com</a>><br>
>>> >>> >> wrote:<br>
>>> >>> >> > The issue blocks another optimization patch and Wei has spent<br>
>>> >>> >> > huge<br>
>>> >>> >> > amount of<br>
>>> >>> >> > effort isolating the the bootstrap failure to this same problem.<br>
>>> >>> >> > I<br>
>>> >>> >> > agree<br>
>>> >>> >> > with Wei that other developers may also get hit by the same issue<br>
>>> >>> >> > and<br>
>>> >>> >> > the<br>
>>> >>> >> > cost of leaving this issue open for long can be very high to the<br>
>>> >>> >> > community.<br>
>>> >>> >><br>
>>> >>> >> I can't speak for others, but I am fine with adding a workaround<br>
>>> >>> >> for<br>
>>> >>> >> this.  However, I suspect isGuaranteedNotToBeUndefOrPois<wbr>on in<br>
>>> >>> >> LoopUnswitch may regress other benchmarks.<br>
>>> >>> ><br>
>>> >>> > Any other thoughts on a more minimal fix?<br>
>>> >>><br>
>>> >>> I can't think of any good answers here.<br>
>>> >>><br>
>>> >>> The semantic we want is "branching on poison or undef is undefined<br>
>>> >>> behavior" (which lets us do propagateEquality).  Given that, we could<br>
>>> >>> be clever about implementing isGuaranteedNotToBeUndefOrPois<wbr>on; for<br>
>>> >>> instance if we have:<br>
>>> >>><br>
>>> >>> do {<br>
>>> >>>   if (a != b) {<br>
>>> >>>     ...<br>
>>> >>>   }<br>
>>> >>> } while (...);<br>
>>> >>><br>
>>> >>> then we can use post-domination to prove that "a != b" is not undef<br>
>>> >>> (otherwise the loop is guaranteed to have undefined behavior).<br>
>>> >>><br>
>>> >>> (I hate to say this), a more aggressive fix is to introduce a "freeze"<br>
>>> >>> intrinsic that freezes only an i1.  LoopUnswitch would wrap the loop<br>
>>> >>> invariant condition in this after hoisting the branch.  This would be<br>
>>> >>> a poor man's version of the more invasive patches Juneyoung already<br>
>>> >>> has developed.<br>
>>> >>><br>
>>> >>> -- Sanjoy<br>
>>> >>> ______________________________<wbr>_________________<br>
>>> >>> LLVM Developers mailing list<br>
>>> >>> <a href="mailto:llvm-dev@lists.llvm.org">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/<wbr>mailman/listinfo/llvm-dev</a><br>
>>> >><br>
>>> >><br>
>>> >><br>
>>> >><br>
>>> >> --<br>
>>> >><br>
>>> >> Juneyoung Lee<br>
>>> >> Software Foundation Lab, Seoul National University<br>
>>> ><br>
>>> ><br>
>><br>
>><br>
>><br>
>> ______________________________<wbr>_________________<br>
>> LLVM Developers mailing list<br>
>> <a href="mailto:llvm-dev@lists.llvm.org">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/<wbr>mailman/listinfo/llvm-dev</a><br>
>><br>
</div></div></blockquote></div><br></div>