<div dir="ltr"><div><div><div><div><div>In the situation where a partial word is tested, lets say >0, by shifting left to get the sign bit into the msb and testing llvm is inserting a spurious right shift instruction.<br>
<br></div>For example this IR:<br>...<br> %0 = load i64* %a.addr, align 8<br> %shl = shl i64 %0, 28<br> %cmp = icmp sgt i64 %shl, 0<br>...<br></div>results in<br>...<br> shlq $28, %rdi<br> sarq $28, %rdi ; <<< spurious shift<br>
testq %rdi, %rdi<br><br></div>gcc doesnt have this problem. It just emits the shift and test.<br><br></div>The reason appears to be that the instruction combining pass decides that the shift and test is equivalent to a test on the partial word, in this case an I36. <br>
<br></div>From the -debug log:<br><br><p><font face="tahoma">From the -debug log:</font></p>
<p><font face="tahoma">....</font></p>
<p><font face="tahoma"><font face="tahoma"><font face="tahoma">INSTCOMBINE ITERATION
#0 on testit<br>IC: ADDING: 10 instrs to worklist<br>IC: Visiting: %shl = shl
i64 %a, 28<br>IC: Visiting: %cmp = icmp sgt i64 %shl, 0<br>IC: ADD: %0 =
trunc i64 %a to i36<br>IC: Old = %cmp = icmp sgt i64 %shl, 0<br> New =
<badref> = icmp sgt i36 %0, 0<br>IC: ADD: %cmp = icmp sgt i36 %0,
0<br>IC: ERASE %1 = icmp sgt i64 %shl, 0<br>IC: ADD: %shl = shl i64 %a,
28<br>IC: DCE: %shl = shl i64 %a, 28</font></font></font></p><p><font face="tahoma"><font face="tahoma"><font face="tahoma">--- etc</font></font></font></p><p>So apparently the extra shift is inserted to restore the I36, although it is never referenced again.</p>
<p><br></p><p>Here is a little C test program, try it at -O3 in both gcc and clang and you will see the problem:</p><p>#include <stdint.h><br><br>uint8_t testit(uint64_t a) {<br> return ((int64_t) (a << 28) > 0) ;<br>
}<br><br><br></p><p><br></p><p><font face="tahoma"><font face="tahoma"><font face="tahoma"><br></font></font></font></p><br><div><br><div><br><div><br><div><div><div><div><div style id="__af745f8f43-e961-4b88-8424-80b67790c964__">
</div></div></div></div></div></div></div></div></div>