[LLVMdev] Optimization bug - spurious shift in partial word test

Rafael EspĂ­ndola rafael.espindola at gmail.com
Fri Nov 1 14:40:33 PDT 2013


Could you report a bug in llvm.org/bug?

On 30 October 2013 17:05, Maurice Marks <maurice.marks at gmail.com> wrote:
> 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.
>
> For example this IR:
> ...
>   %0 = load i64* %a.addr, align 8
>   %shl = shl i64 %0, 28
>   %cmp = icmp sgt i64 %shl, 0
> ...
> results in
> ...
>         shlq    $28, %rdi
>         sarq    $28, %rdi ; <<< spurious shift
>         testq   %rdi, %rdi
>
> gcc doesnt have this problem. It just emits the shift and test.
>
> 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.
>
> From the -debug log:
>
> From the -debug log:
>
> ....
>
> INSTCOMBINE ITERATION #0 on testit
> IC: ADDING: 10 instrs to worklist
> IC: Visiting: %shl = shl i64 %a, 28
> IC: Visiting: %cmp = icmp sgt i64 %shl, 0
> IC: ADD: %0 = trunc i64 %a to i36
> IC: Old = %cmp = icmp sgt i64 %shl, 0
> New = <badref> = icmp sgt i36 %0, 0
> IC: ADD: %cmp = icmp sgt i36 %0, 0
> IC: ERASE %1 = icmp sgt i64 %shl, 0
> IC: ADD: %shl = shl i64 %a, 28
> IC: DCE: %shl = shl i64 %a, 28
>
> --- etc
>
> So apparently the extra shift is inserted to restore the I36, although it is
> never referenced again.
>
>
> Here is a little C test program, try it at -O3 in both gcc and clang and you
> will see the problem:
>
> #include <stdint.h>
>
> uint8_t testit(uint64_t a) {
>         return ((int64_t) (a << 28) > 0) ;
>         }
>
>
>
>
>
>
>
>
>
> _______________________________________________
> LLVM Developers mailing list
> LLVMdev at cs.uiuc.edu         http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
>



More information about the llvm-dev mailing list