<div dir="ltr">Hello,<div><br></div><div>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).</div><div><br></div><div>Here's a test case with spilling/no-spilling code put on conditional compile:</div><div><br></div><div><div>#if __SSE4_1__ != 0</div><div><span class="" style="white-space:pre">        </span>#include <smmintrin.h></div><div>#else</div><div><span class="" style="white-space:pre">   </span>#include <emmintrin.h></div><div>#endif</div><div>#include <stdint.h></div><div>#include <assert.h></div><div><br></div><div>#if SPILLING_ENSUES == 1</div><div>static int32_t geti(const __m128i v, const size_t i)</div><div>{</div><div><span class="" style="white-space:pre">      </span>switch (i) {</div><div><span class="" style="white-space:pre">       </span>case 0:</div><div><span class="" style="white-space:pre">            </span>return _mm_cvtsi128_si32(v);</div><div><span class="" style="white-space:pre">       </span>case 1:</div><div><span class="" style="white-space:pre">            </span>return _mm_cvtsi128_si32(_mm_shuffle_epi32(v, 0xe5));</div><div><span class="" style="white-space:pre">      </span>case 2:</div><div><span class="" style="white-space:pre">            </span>return _mm_cvtsi128_si32(_mm_shuffle_epi32(v, 0xe6));</div><div><span class="" style="white-space:pre">      </span>case 3:</div><div><span class="" style="white-space:pre">            </span>return _mm_cvtsi128_si32(_mm_shuffle_epi32(v, 0xe7));</div><div><span class="" style="white-space:pre">      </span>}</div><div><br></div><div><span class="" style="white-space:pre"> </span>assert(0);</div><div><span class="" style="white-space:pre"> </span>return -1;</div><div>}</div><div><br></div><div>#else</div><div>static int32_t geti(const __m128i v, const size_t i)</div><div>{</div><div><span class="" style="white-space:pre">        </span>switch (i) {</div><div><span class="" style="white-space:pre">       </span>case 0:</div><div><span class="" style="white-space:pre">            </span>return int32_t(v[0] >> 0);</div><div><span class="" style="white-space:pre">   </span>case 1:</div><div><span class="" style="white-space:pre">            </span>return int32_t(v[0] >> 32);</div><div><span class="" style="white-space:pre">  </span>case 2:</div><div><span class="" style="white-space:pre">            </span>return int32_t(v[1] >> 0);</div><div><span class="" style="white-space:pre">   </span>case 3:</div><div><span class="" style="white-space:pre">            </span>return int32_t(v[1] >> 32);</div><div><span class="" style="white-space:pre">  </span>}</div><div><br></div><div><span class="" style="white-space:pre"> </span>assert(0);</div><div><span class="" style="white-space:pre"> </span>return -1;</div><div>}</div><div>#endif</div><div><br></div><div>__m128 x[] = { (__m128){ .123f, .999f, .123f, .999f } };</div><div>__m128 r[1];</div><div><br></div><div>static const float table[3] = {</div><div><span class="" style="white-space:pre">  </span>1.0,</div><div><span class="" style="white-space:pre">       </span>2.0,</div><div><span class="" style="white-space:pre">       </span>4.0,</div><div>};</div><div><br></div><div>static __m128 testee(</div><div><span class="" style="white-space:pre"> </span>const __m128 x)</div><div>{</div><div><span class="" style="white-space:pre">    </span>const __m128i iexp = _mm_sub_epi32(_mm_srli_epi32(_mm_castps_si128(x), 23), _mm_set1_epi32(127));</div><div><span class="" style="white-space:pre">  </span>const __m128 s = _mm_or_ps(</div><div><span class="" style="white-space:pre">                </span>_mm_andnot_ps(_mm_castsi128_ps(_mm_set1_epi32(0xff << 23)), x),</div><div><span class="" style="white-space:pre">              </span>              _mm_castsi128_ps(_mm_set1_epi32(0x7f << 23)));</div><div><br></div><div><span class="" style="white-space:pre"> </span>const __m128 exp = _mm_cvtepi32_ps(iexp);</div><div><span class="" style="white-space:pre">  </span>const __m128i quot = _mm_cvttps_epi32(_mm_div_ps(exp, _mm_set1_ps(3.f)));</div><div><span class="" style="white-space:pre">  </span>const __m128i rem  = _mm_sub_epi32(iexp, _mm_mullo_epi16(quot, _mm_set1_epi32(0x10003)));</div><div><br></div><div><span class="" style="white-space:pre">        </span>const __m128 entry = _mm_setr_ps( // 'rem' gets spilled depending on version of lane extractor used</div><div><span class="" style="white-space:pre">                </span>table[geti(rem, 0)],</div><div><span class="" style="white-space:pre">               </span>table[geti(rem, 1)],</div><div><span class="" style="white-space:pre">               </span>table[geti(rem, 2)],</div><div><span class="" style="white-space:pre">               </span>table[geti(rem, 3)]);</div><div><br></div><div><span class="" style="white-space:pre">     </span>return _mm_set1_ps(.5f) * entry;</div><div>}</div><div><br></div><div>int main(int argc, char** argv)</div><div>{</div><div><span class="" style="white-space:pre">    </span>r[0] = testee(x[0]);</div><div><span class="" style="white-space:pre">       </span>return 0;<br></div><div>}</div></div><div><br></div><div><br></div><div>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.</div><div><br></div><div>Output from clang 3.4 for target corei7-avx:</div><div><br></div><div>$ clang++ test.cpp -O3 -fstrict-aliasing -funroll-loops -ffast-math -march=native -mtune=native -DSPILLING_ENSUES=0   /* no spilling */</div><div>$ objdump -dC --no-show-raw-insn ./a.out</div><div>...<br></div><div><div>00000000004004f0 <main>:</div><div>  4004f0:   vmovdqa 0x2004c8(%rip),%xmm0        # 6009c0 <x></div><div>  4004f8:   vpsrld $0x17,%xmm0,%xmm0</div><div>  4004fd:   vpaddd 0x17b(%rip),%xmm0,%xmm0        # 400680 <__dso_handle+0x8></div><div>  400505:   vcvtdq2ps %xmm0,%xmm1</div><div>  400509:   vdivps 0x17f(%rip),%xmm1,%xmm1        # 400690 <__dso_handle+0x18></div><div>  400511:   vcvttps2dq %xmm1,%xmm1</div><div>  400515:   vpmullw 0x183(%rip),%xmm1,%xmm1        # 4006a0 <__dso_handle+0x28></div><div>  40051d:   vpsubd %xmm1,%xmm0,%xmm0</div><div>  400521:   vmovq  %xmm0,%rax</div><div>  400526:   movslq %eax,%rcx</div><div>  400529:   sar    $0x20,%rax</div><div>  40052d:   vpextrq $0x1,%xmm0,%rdx</div><div>  400533:   movslq %edx,%rsi</div><div>  400536:   sar    $0x20,%rdx</div><div>  40053a:   vmovss 0x4006c0(,%rcx,4),%xmm0</div><div>  400543:   vinsertps $0x10,0x4006c0(,%rax,4),%xmm0,%xmm0</div><div>  40054e:   vinsertps $0x20,0x4006c0(,%rsi,4),%xmm0,%xmm0</div><div>  400559:   vinsertps $0x30,0x4006c0(,%rdx,4),%xmm0,%xmm0</div><div>  400564:   vmulps 0x144(%rip),%xmm0,%xmm0        # 4006b0 <__dso_handle+0x38></div><div>  40056c:   vmovaps %xmm0,0x20046c(%rip)        # 6009e0 <r></div><div>  400574:   xor    %eax,%eax</div><div>  400576:   retq</div></div><div><br></div><div>$ clang++ test.cpp -O3 -fstrict-aliasing -funroll-loops -ffast-math -march=native -mtune=native -DSPILLING_ENSUES=1    /* spilling */</div><div>$ objdump -dC --no-show-raw-insn ./a.out</div><div>...</div><div><div>00000000004004f0 <main>:</div><div>  4004f0:   vmovdqa 0x2004c8(%rip),%xmm0        # 6009c0 <x></div><div>  4004f8:   vpsrld $0x17,%xmm0,%xmm0</div><div>  4004fd:   vpaddd 0x17b(%rip),%xmm0,%xmm0        # 400680 <__dso_handle+0x8></div><div>  400505:   vcvtdq2ps %xmm0,%xmm1</div><div>  400509:   vdivps 0x17f(%rip),%xmm1,%xmm1        # 400690 <__dso_handle+0x18></div><div>  400511:   vcvttps2dq %xmm1,%xmm1</div><div>  400515:   vpmullw 0x183(%rip),%xmm1,%xmm1        # 4006a0 <__dso_handle+0x28></div><div>  40051d:   vpsubd %xmm1,%xmm0,%xmm0</div><div>  400521:   vmovdqa %xmm0,-0x18(%rsp)</div><div>  400527:   movslq -0x18(%rsp),%rax</div><div>  40052c:   movslq -0x14(%rsp),%rcx</div><div>  400531:   movslq -0x10(%rsp),%rdx</div><div>  400536:   movslq -0xc(%rsp),%rsi</div><div>  40053b:   vmovss 0x4006c0(,%rax,4),%xmm0</div><div>  400544:   vinsertps $0x10,0x4006c0(,%rcx,4),%xmm0,%xmm0</div><div>  40054f:   vinsertps $0x20,0x4006c0(,%rdx,4),%xmm0,%xmm0</div><div>  40055a:   vinsertps $0x30,0x4006c0(,%rsi,4),%xmm0,%xmm0</div><div>  400565:   vmulps 0x143(%rip),%xmm0,%xmm0        # 4006b0 <__dso_handle+0x38></div><div>  40056d:   vmovaps %xmm0,0x20046b(%rip)        # 6009e0 <r></div><div>  400575:   xor    %eax,%eax</div><div>  400577:   retq</div></div><div><br></div><div><div><br></div><div>Output from clang pre-release 3.5 trunk for target btver1:</div><div><br></div></div><div><div>$ clang++ test.cpp -O3 -fstrict-aliasing -funroll-loops -ffast-math -march=native -mtune=native -DSPILLING_ENSUES=0   /* no spilling */</div><div>$ objdump -dC --no-show-raw-insn ./a.out</div><div>...<br></div><div></div><div>00000000004005c0 <main>:</div><div>  4005c0:<span class="" style="white-space:pre">      </span>movdqa 0x1a58(%rip),%xmm0        # 402020 <x></div><div>  4005c8:<span class="" style="white-space:pre">  </span>psrld  $0x17,%xmm0<br></div><div>  4005cd:<span class="" style="white-space:pre">    </span>paddd  0x12b(%rip),%xmm0        # 400700 <.LCPI0_0></div><div>  4005d5:<span class="" style="white-space:pre">   </span>cvtdq2ps %xmm0,%xmm1<br></div><div>  4005d8:<span class="" style="white-space:pre">   </span>divps  0x131(%rip),%xmm1        # 400710 <.LCPI0_1></div><div>  4005df:<span class="" style="white-space:pre">   </span>cvttps2dq %xmm1,%xmm1</div><div>  4005e3:<span class="" style="white-space:pre">    </span>pmullw 0x135(%rip),%xmm1        # 400720 <.LCPI0_2></div><div>  4005eb:<span class="" style="white-space:pre">    </span>psubd  %xmm1,%xmm0<br></div><div>  4005ef:<span class="" style="white-space:pre">    </span>movq   %xmm0,%rax</div><div>  4005f4:<span class="" style="white-space:pre">       </span>movslq %eax,%rcx</div><div>  4005f7:<span class="" style="white-space:pre"> </span>sar    $0x20,%rax</div><div>  4005fb:<span class="" style="white-space:pre">      </span>punpckhqdq %xmm0,%xmm0</div><div>  4005ff:<span class="" style="white-space:pre">   </span>movq   %xmm0,%rdx</div><div>  400604:<span class="" style="white-space:pre">       </span>movslq %edx,%rsi</div><div>  400607:<span class="" style="white-space:pre"> </span>sar    $0x20,%rdx</div><div>  40060b:<span class="" style="white-space:pre">      </span>movss  0x400740(,%rax,4),%xmm0</div><div>  400614:<span class="" style="white-space:pre">  </span>movss  0x400740(,%rdx,4),%xmm1<br></div><div>  40061d:<span class="" style="white-space:pre">        </span>unpcklps %xmm1,%xmm0<br></div><div>  400620:<span class="" style="white-space:pre">   </span>movss  0x400740(,%rcx,4),%xmm1</div><div>  400629:<span class="" style="white-space:pre">  </span>movss  0x400740(,%rsi,4),%xmm2<br></div><div>  400632:<span class="" style="white-space:pre">        </span>unpcklps %xmm2,%xmm1<br></div><div>  400635:<span class="" style="white-space:pre">   </span>unpcklps %xmm0,%xmm1</div><div>  400638:<span class="" style="white-space:pre">     </span>mulps  0xf1(%rip),%xmm1        # 400730 <.LCPI0_3></div><div>  40063f:<span class="" style="white-space:pre">    </span>movaps %xmm1,0x1a1a(%rip)        # 402060 <r></div><div>  400646:<span class="" style="white-space:pre">  </span>xor    %eax,%eax</div><div>  400648:<span class="" style="white-space:pre">       </span>retq</div></div><div><br></div><div><div>$ clang++ test.cpp -O3 -fstrict-aliasing -funroll-loops -ffast-math -march=native -mtune=native -DSPILLING_ENSUES=1    /* spilling */</div><div>$ objdump -dC --no-show-raw-insn ./a.out</div><div>...</div><div><div>00000000004005c0 <main>:</div><div>  4005c0:<span class="" style="white-space:pre">      </span>movdqa 0x1a58(%rip),%xmm0        # 402020 <x></div><div>  4005c8:<span class="" style="white-space:pre">  </span>psrld  $0x17,%xmm0</div><div>  4005cd:<span class="" style="white-space:pre">      </span>paddd  0x12b(%rip),%xmm0        # 400700 <.LCPI0_0></div><div>  4005d5:<span class="" style="white-space:pre">   </span>cvtdq2ps %xmm0,%xmm1</div><div>  4005d8:<span class="" style="white-space:pre">     </span>divps  0x131(%rip),%xmm1        # 400710 <.LCPI0_1></div><div>  4005df:<span class="" style="white-space:pre">   </span>cvttps2dq %xmm1,%xmm1</div><div>  4005e3:<span class="" style="white-space:pre">    </span>pmullw 0x135(%rip),%xmm1        # 400720 <.LCPI0_2></div><div>  4005eb:<span class="" style="white-space:pre">    </span>psubd  %xmm1,%xmm0</div><div>  4005ef:<span class="" style="white-space:pre">      </span>movdqa %xmm0,-0x18(%rsp)</div><div>  4005f5:<span class="" style="white-space:pre"> </span>movslq -0x18(%rsp),%rax</div><div>  4005fa:<span class="" style="white-space:pre">  </span>movslq -0x14(%rsp),%rcx</div><div>  4005ff:<span class="" style="white-space:pre">  </span>movslq -0x10(%rsp),%rdx</div><div>  400604:<span class="" style="white-space:pre">  </span>movslq -0xc(%rsp),%rsi</div><div>  400609:<span class="" style="white-space:pre">   </span>movss  0x400740(,%rsi,4),%xmm0</div><div>  400612:<span class="" style="white-space:pre">  </span>movss  0x400740(,%rcx,4),%xmm1</div><div>  40061b:<span class="" style="white-space:pre">  </span>unpcklps %xmm0,%xmm1</div><div>  40061e:<span class="" style="white-space:pre">     </span>movss  0x400740(,%rdx,4),%xmm0</div><div>  400627:<span class="" style="white-space:pre">  </span>movss  0x400740(,%rax,4),%xmm2</div><div>  400630:<span class="" style="white-space:pre">  </span>unpcklps %xmm0,%xmm2</div><div>  400633:<span class="" style="white-space:pre">     </span>unpcklps %xmm1,%xmm2</div><div>  400636:<span class="" style="white-space:pre">     </span>mulps  0xf3(%rip),%xmm2        # 400730 <.LCPI0_3></div><div>  40063d:<span class="" style="white-space:pre">    </span>movaps %xmm2,0x1a1c(%rip)        # 402060 <r></div><div>  400644:<span class="" style="white-space:pre">  </span>xor    %eax,%eax</div><div>  400646:<span class="" style="white-space:pre">       </span>retq</div></div><div><br></div><div><br></div><div>Is that behavior expected? Because I find it odd.</div><div><br></div><div>Best regards,</div><div>Martin</div><div></div></div></div>