<p dir="ltr">Hi,</p>
<p dir="ltr">Thanks a lot for the detailed explanation!</p>
<p dir="ltr">I did not pay attention to the difference between signed and unsigned less-than. Indeed the unsigned check is necessary because the index could be negative (and hence out of bound).</p>
<p dir="ltr">This shows me that I need to be more careful when making assumptions about code... I hope I'll learn the lesson. Thanks again.</p>
<p dir="ltr">- Jonas</p>
<div class="gmail_quote">On Apr 8, 2014 7:02 PM, "Will Dietz" <<a href="mailto:willdtz@gmail.com">willdtz@gmail.com</a>> wrote:<br type="attribution"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
In the future please be a bit more specific about which blocks<br>
correspond to your unexpected behavior, it'd help folks understand<br>
your issue :).<br>
<br>
Anyway, looking at the IR for a bit I think I see what might be<br>
confusing (other than sanitizers making control flow extra fun :)):<br>
<br>
There are two comparisons similar to the outer loop condition:<br>
<br>
%0 = icmp ult i32 %i.042, 32, !dbg !20<br>
<br>
And:<br>
<br>
%cmp = icmp slt i32 %26, 32, !dbg !19<br>
<br>
The first check, if it fails, branches to a block that necessarily<br>
calls one of two sanitizer abort functions.<br>
<br>
Observations:<br>
<br>
1) The first check is an ULT, stronger than the SLT used later and<br>
specified in your source as the outer loop condition. This is<br>
significant, and helps explain why when the check fails the program<br>
will necessarily call one of two abort functions as it's not a loop<br>
condition check but rather a bounds check:<br>
<br>
2)If the ULT fails (somehow 'i' is larger than 32 when interpreted as<br>
unsigned!), if the code makes it to the array access it will be an<br>
out-of-bounds access. However, if the code encounters a float-to-int<br>
error before this happens, the float abort handler will be called<br>
instead. This explains the resulting control-flow that is followed<br>
should the first check fail.<br>
<br>
3)This code is certainly sub-optimal, unfortunately. It seems LLVM is<br>
unable to reason about the loops effectively when instrumented by the<br>
sanitizers, likely at least partially due to the increment<br>
instructions being replaced with overflow-checking intrinsics.<br>
There's more to it, however, since it seems building with only<br>
-sanitize=bound LLVM is able to optimize away the check on 'i', but<br>
not the check for 'j'.<br>
<br>
Anyway, AFAICT nothing is 'dead' and the code is correct if a bit<br>
more complicated than one might like :).<br>
Let me know if anything was unclear or you have any further questions.<br>
<br>
Hope this helps,<br>
~Will<br>
<br>
On Mon, Apr 7, 2014 at 11:24 AM, Jonas Wagner <<a href="mailto:jonas.wagner@epfl.ch">jonas.wagner@epfl.ch</a>> wrote:<br>
> Hi,<br>
><br>
> I'm surprised by the result of compiling the following lines of code:<br>
><br>
> for (int i = 0; i < RANDOM_CHUNKS; i++) {<br>
> for (int j = 0; j < RANDOM_CHUNK_SIZE; j++) {<br>
> random_text[i][j] = (int)(ran()*256);<br>
> }<br>
> }<br>
><br>
> The problem happens when -fsanitize=undefined, -fno-sanitize-recover and -O3<br>
> are enabled. In this case, UndefinedBehaviorSanitizer inserts check for<br>
> array index out of bounds, and for cast-to-int overflow. The loop<br>
> unswitching pass presumably tries to move these out of the loops. Thereby,<br>
> the loop condition of the outer loop gets duplicated, and one of the copies<br>
> branches to a dead block.<br>
><br>
> This is a problem at the interplay between multiple optimization passes.<br>
> Maybe there isn't an easy solution. But I thought I'd post it here since<br>
> people might be interested.<br>
><br>
> Attached are a complete C file reproducing the problem, as well as the<br>
> resulting Bitcode. Compilation was done using clang -Wall -g -flto -O3<br>
> -fsanitize=undefined -fno-sanitize-recover -c weird_loop.c<br>
><br>
> Cheers,<br>
> Jonas<br>
><br>
><br>
> _______________________________________________<br>
> LLVM Developers mailing list<br>
> <a href="mailto:LLVMdev@cs.uiuc.edu">LLVMdev@cs.uiuc.edu</a> <a href="http://llvm.cs.uiuc.edu" target="_blank">http://llvm.cs.uiuc.edu</a><br>
> <a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev</a><br>
><br>
</blockquote></div>