<html><head><meta http-equiv="Content-Type" content="text/html charset=windows-1252"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;">Thanks Martin.<div><br></div><div>I’ll have a look when I get a chance.</div><div><br></div><div>-Quentin</div><div><br><div style=""><div>On Oct 14, 2014, at 1:36 AM, martin krastev <<a href="mailto:blu.dark@gmail.com">blu.dark@gmail.com</a>> wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div dir="ltr">Hi Quentin,<div><br></div><div>Thank you for the directions. Here is the bug ticket: <a href="http://llvm.org/bugs/show_bug.cgi?id=21269">http://llvm.org/bugs/show_bug.cgi?id=21269</a></div><div><br></div><div><br></div><div>Best regards,</div><div>Martin</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Oct 13, 2014 at 8:03 PM, Quentin Colombet <span dir="ltr"><<a href="mailto:qcolombet@apple.com" target="_blank">qcolombet@apple.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi Martin,<br>
<br>
I haven’t checked what is going on here, but if you believe some spill can be avoided, this is worth filing a PR (<a href="http://www.llvm.org/bugs" target="_blank">www.llvm.org/bugs</a>) to libraries -> Register Allocator.<br>
Please attach the IR to reproduce the problem (-emit-llvm from clang).<br>
<br>
Thanks,<br>
-Quentin<br>
<div><div class="h5"><br>
On Oct 13, 2014, at 9:13 AM, martin krastev <<a href="mailto:blu.dark@gmail.com">blu.dark@gmail.com</a>> wrote:<br>
<br>
> Hello,<br>
><br>
> Depending on how I extract integer lanes from an x86_64 xmm register, the backend may spill that register in order to load scalars. The effect was observed on two targets: corei7-avx and btver1 (I haven't checked other targets).<br>
><br>
> Here's a test case with spilling/no-spilling code put on conditional compile:<br>
><br>
> #if __SSE4_1__ != 0<br>
>       #include <smmintrin.h><br>
> #else<br>
>       #include <emmintrin.h><br>
> #endif<br>
> #include <stdint.h><br>
> #include <assert.h><br>
><br>
> #if SPILLING_ENSUES == 1<br>
> static int32_t geti(const __m128i v, const size_t i)<br>
> {<br>
>       switch (i) {<br>
>       case 0:<br>
>               return _mm_cvtsi128_si32(v);<br>
>       case 1:<br>
>               return _mm_cvtsi128_si32(_mm_shuffle_epi32(v, 0xe5));<br>
>       case 2:<br>
>               return _mm_cvtsi128_si32(_mm_shuffle_epi32(v, 0xe6));<br>
>       case 3:<br>
>               return _mm_cvtsi128_si32(_mm_shuffle_epi32(v, 0xe7));<br>
>       }<br>
><br>
>       assert(0);<br>
>       return -1;<br>
> }<br>
><br>
> #else<br>
> static int32_t geti(const __m128i v, const size_t i)<br>
> {<br>
>       switch (i) {<br>
>       case 0:<br>
>               return int32_t(v[0] >> 0);<br>
>       case 1:<br>
>               return int32_t(v[0] >> 32);<br>
>       case 2:<br>
>               return int32_t(v[1] >> 0);<br>
>       case 3:<br>
>               return int32_t(v[1] >> 32);<br>
>       }<br>
><br>
>       assert(0);<br>
>       return -1;<br>
> }<br>
> #endif<br>
><br>
> __m128 x[] = { (__m128){ .123f, .999f, .123f, .999f } };<br>
> __m128 r[1];<br>
><br>
> static const float table[3] = {<br>
>       1.0,<br>
>       2.0,<br>
>       4.0,<br>
> };<br>
><br>
> static __m128 testee(<br>
>       const __m128 x)<br>
> {<br>
>       const __m128i iexp = _mm_sub_epi32(_mm_srli_epi32(_mm_castps_si128(x), 23), _mm_set1_epi32(127));<br>
>       const __m128 s = _mm_or_ps(<br>
>               _mm_andnot_ps(_mm_castsi128_ps(_mm_set1_epi32(0xff << 23)), x),<br>
>                             _mm_castsi128_ps(_mm_set1_epi32(0x7f << 23)));<br>
><br>
>       const __m128 exp = _mm_cvtepi32_ps(iexp);<br>
>       const __m128i quot = _mm_cvttps_epi32(_mm_div_ps(exp, _mm_set1_ps(3.f)));<br>
>       const __m128i rem  = _mm_sub_epi32(iexp, _mm_mullo_epi16(quot, _mm_set1_epi32(0x10003)));<br>
><br>
>       const __m128 entry = _mm_setr_ps( // 'rem' gets spilled depending on version of lane extractor used<br>
>               table[geti(rem, 0)],<br>
>               table[geti(rem, 1)],<br>
>               table[geti(rem, 2)],<br>
>               table[geti(rem, 3)]);<br>
><br>
>       return _mm_set1_ps(.5f) * entry;<br>
> }<br>
><br>
> int main(int argc, char** argv)<br>
> {<br>
>       r[0] = testee(x[0]);<br>
>       return 0;<br>
> }<br>
><br>
><br>
> In the above function 'testee' (duly inlined in the disassembly below), local var 'rem' gets spilled and read back as scalars, depending on which version of the integer lane accessor was used.<br>
><br>
> Output from clang 3.4 for target corei7-avx:<br>
><br>
> $ clang++ test.cpp -O3 -fstrict-aliasing -funroll-loops -ffast-math -march=native -mtune=native -DSPILLING_ENSUES=0   /* no spilling */<br>
> $ objdump -dC --no-show-raw-insn ./a.out<br>
> ...<br>
> 00000000004004f0 <main>:<br>
>   4004f0:   vmovdqa 0x2004c8(%rip),%xmm0        # 6009c0 <x><br>
>   4004f8:   vpsrld $0x17,%xmm0,%xmm0<br>
>   4004fd:   vpaddd 0x17b(%rip),%xmm0,%xmm0        # 400680 <__dso_handle+0x8><br>
>   400505:   vcvtdq2ps %xmm0,%xmm1<br>
>   400509:   vdivps 0x17f(%rip),%xmm1,%xmm1        # 400690 <__dso_handle+0x18><br>
>   400511:   vcvttps2dq %xmm1,%xmm1<br>
>   400515:   vpmullw 0x183(%rip),%xmm1,%xmm1        # 4006a0 <__dso_handle+0x28><br>
>   40051d:   vpsubd %xmm1,%xmm0,%xmm0<br>
>   400521:   vmovq  %xmm0,%rax<br>
>   400526:   movslq %eax,%rcx<br>
>   400529:   sar    $0x20,%rax<br>
>   40052d:   vpextrq $0x1,%xmm0,%rdx<br>
>   400533:   movslq %edx,%rsi<br>
>   400536:   sar    $0x20,%rdx<br>
>   40053a:   vmovss 0x4006c0(,%rcx,4),%xmm0<br>
>   400543:   vinsertps $0x10,0x4006c0(,%rax,4),%xmm0,%xmm0<br>
>   40054e:   vinsertps $0x20,0x4006c0(,%rsi,4),%xmm0,%xmm0<br>
>   400559:   vinsertps $0x30,0x4006c0(,%rdx,4),%xmm0,%xmm0<br>
>   400564:   vmulps 0x144(%rip),%xmm0,%xmm0        # 4006b0 <__dso_handle+0x38><br>
>   40056c:   vmovaps %xmm0,0x20046c(%rip)        # 6009e0 <r><br>
>   400574:   xor    %eax,%eax<br>
>   400576:   retq<br>
><br>
> $ clang++ test.cpp -O3 -fstrict-aliasing -funroll-loops -ffast-math -march=native -mtune=native -DSPILLING_ENSUES=1    /* spilling */<br>
> $ objdump -dC --no-show-raw-insn ./a.out<br>
> ...<br>
> 00000000004004f0 <main>:<br>
>   4004f0:   vmovdqa 0x2004c8(%rip),%xmm0        # 6009c0 <x><br>
>   4004f8:   vpsrld $0x17,%xmm0,%xmm0<br>
>   4004fd:   vpaddd 0x17b(%rip),%xmm0,%xmm0        # 400680 <__dso_handle+0x8><br>
>   400505:   vcvtdq2ps %xmm0,%xmm1<br>
>   400509:   vdivps 0x17f(%rip),%xmm1,%xmm1        # 400690 <__dso_handle+0x18><br>
>   400511:   vcvttps2dq %xmm1,%xmm1<br>
>   400515:   vpmullw 0x183(%rip),%xmm1,%xmm1        # 4006a0 <__dso_handle+0x28><br>
>   40051d:   vpsubd %xmm1,%xmm0,%xmm0<br>
>   400521:   vmovdqa %xmm0,-0x18(%rsp)<br>
>   400527:   movslq -0x18(%rsp),%rax<br>
>   40052c:   movslq -0x14(%rsp),%rcx<br>
>   400531:   movslq -0x10(%rsp),%rdx<br>
>   400536:   movslq -0xc(%rsp),%rsi<br>
>   40053b:   vmovss 0x4006c0(,%rax,4),%xmm0<br>
>   400544:   vinsertps $0x10,0x4006c0(,%rcx,4),%xmm0,%xmm0<br>
>   40054f:   vinsertps $0x20,0x4006c0(,%rdx,4),%xmm0,%xmm0<br>
>   40055a:   vinsertps $0x30,0x4006c0(,%rsi,4),%xmm0,%xmm0<br>
>   400565:   vmulps 0x143(%rip),%xmm0,%xmm0        # 4006b0 <__dso_handle+0x38><br>
>   40056d:   vmovaps %xmm0,0x20046b(%rip)        # 6009e0 <r><br>
>   400575:   xor    %eax,%eax<br>
>   400577:   retq<br>
><br>
><br>
> Output from clang pre-release 3.5 trunk for target btver1:<br>
><br>
> $ clang++ test.cpp -O3 -fstrict-aliasing -funroll-loops -ffast-math -march=native -mtune=native -DSPILLING_ENSUES=0   /* no spilling */<br>
> $ objdump -dC --no-show-raw-insn ./a.out<br>
> ...<br>
> 00000000004005c0 <main>:<br>
>   4005c0:     movdqa 0x1a58(%rip),%xmm0        # 402020 <x><br>
>   4005c8:     psrld  $0x17,%xmm0<br>
>   4005cd:     paddd  0x12b(%rip),%xmm0        # 400700 <.LCPI0_0><br>
>   4005d5:     cvtdq2ps %xmm0,%xmm1<br>
>   4005d8:     divps  0x131(%rip),%xmm1        # 400710 <.LCPI0_1><br>
>   4005df:     cvttps2dq %xmm1,%xmm1<br>
>   4005e3:     pmullw 0x135(%rip),%xmm1        # 400720 <.LCPI0_2><br>
>   4005eb:     psubd  %xmm1,%xmm0<br>
>   4005ef:     movq   %xmm0,%rax<br>
>   4005f4:     movslq %eax,%rcx<br>
>   4005f7:     sar    $0x20,%rax<br>
>   4005fb:     punpckhqdq %xmm0,%xmm0<br>
>   4005ff:     movq   %xmm0,%rdx<br>
>   400604:     movslq %edx,%rsi<br>
>   400607:     sar    $0x20,%rdx<br>
>   40060b:     movss  0x400740(,%rax,4),%xmm0<br>
>   400614:     movss  0x400740(,%rdx,4),%xmm1<br>
>   40061d:     unpcklps %xmm1,%xmm0<br>
>   400620:     movss  0x400740(,%rcx,4),%xmm1<br>
>   400629:     movss  0x400740(,%rsi,4),%xmm2<br>
>   400632:     unpcklps %xmm2,%xmm1<br>
>   400635:     unpcklps %xmm0,%xmm1<br>
>   400638:     mulps  0xf1(%rip),%xmm1        # 400730 <.LCPI0_3><br>
>   40063f:     movaps %xmm1,0x1a1a(%rip)        # 402060 <r><br>
>   400646:     xor    %eax,%eax<br>
>   400648:     retq<br>
><br>
> $ clang++ test.cpp -O3 -fstrict-aliasing -funroll-loops -ffast-math -march=native -mtune=native -DSPILLING_ENSUES=1    /* spilling */<br>
> $ objdump -dC --no-show-raw-insn ./a.out<br>
> ...<br>
> 00000000004005c0 <main>:<br>
>   4005c0:     movdqa 0x1a58(%rip),%xmm0        # 402020 <x><br>
>   4005c8:     psrld  $0x17,%xmm0<br>
>   4005cd:     paddd  0x12b(%rip),%xmm0        # 400700 <.LCPI0_0><br>
>   4005d5:     cvtdq2ps %xmm0,%xmm1<br>
>   4005d8:     divps  0x131(%rip),%xmm1        # 400710 <.LCPI0_1><br>
>   4005df:     cvttps2dq %xmm1,%xmm1<br>
>   4005e3:     pmullw 0x135(%rip),%xmm1        # 400720 <.LCPI0_2><br>
>   4005eb:     psubd  %xmm1,%xmm0<br>
>   4005ef:     movdqa %xmm0,-0x18(%rsp)<br>
>   4005f5:     movslq -0x18(%rsp),%rax<br>
>   4005fa:     movslq -0x14(%rsp),%rcx<br>
>   4005ff:     movslq -0x10(%rsp),%rdx<br>
>   400604:     movslq -0xc(%rsp),%rsi<br>
>   400609:     movss  0x400740(,%rsi,4),%xmm0<br>
>   400612:     movss  0x400740(,%rcx,4),%xmm1<br>
>   40061b:     unpcklps %xmm0,%xmm1<br>
>   40061e:     movss  0x400740(,%rdx,4),%xmm0<br>
>   400627:     movss  0x400740(,%rax,4),%xmm2<br>
>   400630:     unpcklps %xmm0,%xmm2<br>
>   400633:     unpcklps %xmm1,%xmm2<br>
>   400636:     mulps  0xf3(%rip),%xmm2        # 400730 <.LCPI0_3><br>
>   40063d:     movaps %xmm2,0x1a1c(%rip)        # 402060 <r><br>
>   400644:     xor    %eax,%eax<br>
>   400646:     retq<br>
><br>
><br>
> Is that behavior expected? Because I find it odd.<br>
><br>
> Best regards,<br>
> Martin<br>
</div></div>> _______________________________________________<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><br></div>
</blockquote></div><br></div></body></html>