[LLVMdev] SIMD for sdiv <2 x i64>

Benjamin Kramer
Fri, 24 Jul 2015 10:42:49 -0000

> On 24.07.2015, at 08:06, zhi chen <zchenhn at gmail.com> wrote:
>
> It seems that that it's hard to vectorize int64 in LLVM. For example,
LLVM 3.4 generates very complicated code for the following IR. I am running on a
Haswell processor. Is it because there is no alternative AVX/2 instructions for
int64? The same thing also happens to zext <2 x i32> -> <2 x i64>
and trunc <2 x i64> -> <2 x i32>. Any ideas to optimize these
instructions? Thanks.
>
> %sub.ptr.sub.i6.i.i.i.i = sub <2 x i64> %sub.ptr.lhs.cast.i4.i.i.i.i,
%sub.ptr.rhs.cast.i5.i.i.i.i
> %sub.ptr.div.i7.i.i.i.i = sdiv <2 x i64> %sub.ptr.sub.i6.i.i.i.i,
<i64 24, i64 24>
>
> Assembly:
>     vpsubq  %xmm6, %xmm5, %xmm5
>     vmovq   %xmm5, %rax
>     movabsq $3074457345618258603, %rbx # imm = 0x2AAAAAAAAAAAAAAB
>     imulq   %rbx
>     movq    %rdx, %rcx
>     movq    %rcx, %rax
>     shrq    $63, %rax
>     shrq    $2, %rcx
>     addl    %eax, %ecx
>     vpextrq $1, %xmm5, %rax
>     imulq   %rbx
>     movq    %rdx, %rax
>     shrq    $63, %rax
>     shrq    $2, %rdx
>     addl    %eax, %edx
>     movslq  %edx, %rax
>     vmovq   %rax, %xmm5
>     movslq  %ecx, %rax
>     vmovq   %rax, %xmm6
>     vpunpcklqdq %xmm5, %xmm6, %xmm5 # xmm5 = xmm6[0],xmm5[0]

AVX2 doesn't have integer vector division instructions and LLVM lowers
divides by constants into (128 bit) multiplies. However, AVX2 doesn't have a
way to get to the upper 64 bits of a 64x64->128 bit multiply either, so LLVM
uses the scalar imulq instruction to do that. There's not much room to
optimize here given the limitations of AVX2.

You seem to be subtracting pointers though, so if you can guarantee that the
pointers are aligned you could set the exact bit on your 'sdiv'
instruction. That should give better code.

- Ben