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

Maurice Marks maurice.marks at gmail.com
Wed Oct 30 14:05:18 PDT 2013


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) ;
        }
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20131030/29e3dde8/attachment.html>


More information about the llvm-dev mailing list