// icc -msse -O2 -Wall -c icc_register_pressure_bug.c -o bug.o // icc -v: icc version 13.0.1 (gcc version 4.7.0 compatibility) // multiple bugs for ICC under heaver register pressure // gcc 4.7.2 and clang 3.2 both work correctly #include #define XMM_MOVE(xmm_src, xmm_dst) \ __asm volatile("movdqa %1, %0" : \ /* writes %0 */ "=x" (xmm_dst) : \ /* reads %1 */ "x" (xmm_src)) // function with 14 specified registers works as expected __m128 using_14_xmm_registers_works() { register __m128 X0 asm("%xmm0") = {0, 1}; register __m128 X1 asm("%xmm1") = {1, 2}; register __m128 X2 asm("%xmm2") = {2, 3}; register __m128 X3 asm("%xmm3"); register __m128 X4 asm("%xmm4"); register __m128 X5 asm("%xmm5"); register __m128 X6 asm("%xmm6"); register __m128 X7 asm("%xmm7"); register __m128 X8 asm("%xmm8"); register __m128 X9 asm("%xmm9"); register __m128 X10 asm("%xmm10"); register __m128 X11 asm("%xmm11"); register __m128 X12 asm("%xmm12"); register __m128 X13 asm("%xmm13"); XMM_MOVE(X0, X1); XMM_MOVE(X1, X2); XMM_MOVE(X2, X3); XMM_MOVE(X3, X4); XMM_MOVE(X4, X5); XMM_MOVE(X5, X6); XMM_MOVE(X6, X7); XMM_MOVE(X7, X8); XMM_MOVE(X8, X9); XMM_MOVE(X9, X10); XMM_MOVE(X10, X11); XMM_MOVE(X11, X12); XMM_MOVE(X12, X13); return X13; } // function with 15 specified XMM registers is silently wrong // look at asm: unitialized value of %xmm14 is returned __m128 using_15_xmm_registers_is_silently_wrong() { register __m128 X0 asm("%xmm0") = {0, 1}; register __m128 X1 asm("%xmm1") = {1, 2}; register __m128 X2 asm("%xmm2") = {2, 3}; register __m128 X3 asm("%xmm3"); register __m128 X4 asm("%xmm4"); register __m128 X5 asm("%xmm5"); register __m128 X6 asm("%xmm6"); register __m128 X7 asm("%xmm7"); register __m128 X8 asm("%xmm8"); register __m128 X9 asm("%xmm9"); register __m128 X10 asm("%xmm10"); register __m128 X11 asm("%xmm11"); register __m128 X12 asm("%xmm12"); register __m128 X13 asm("%xmm13"); register __m128 X14 asm("%xmm14"); XMM_MOVE(X0, X1); XMM_MOVE(X1, X2); XMM_MOVE(X2, X3); XMM_MOVE(X3, X4); XMM_MOVE(X4, X5); XMM_MOVE(X5, X6); XMM_MOVE(X6, X7); XMM_MOVE(X7, X8); XMM_MOVE(X8, X9); XMM_MOVE(X9, X10); XMM_MOVE(X10, X11); XMM_MOVE(X11, X12); XMM_MOVE(X12, X13); XMM_MOVE(X13, X14); return X14; } // add -DCATASTROPHIC_ERROR to see bug for 16 specified XMM registers // $ icc -DCATASTROPHIC_ERROR -msse -O2 -Wall -c icc_register_pressure_bug.c // icc_register_pressure_bug.c(103): catastrophic error: // Cannot match asm operand constraint #ifdef CATASTROPHIC_ERROR __m128 using_16_xmm_registers_errors_out() { register __m128 X0 asm("%xmm0") = {0, 1}; register __m128 X1 asm("%xmm1") = {1, 2}; register __m128 X2 asm("%xmm2") = {2, 3}; register __m128 X3 asm("%xmm3"); register __m128 X4 asm("%xmm4"); register __m128 X5 asm("%xmm5"); register __m128 X6 asm("%xmm6"); register __m128 X7 asm("%xmm7"); register __m128 X8 asm("%xmm8"); register __m128 X9 asm("%xmm9"); register __m128 X10 asm("%xmm10"); register __m128 X11 asm("%xmm11"); register __m128 X12 asm("%xmm12"); register __m128 X13 asm("%xmm13"); register __m128 X14 asm("%xmm14"); register __m128 X15 asm("%xmm15"); XMM_MOVE(X0, X1); XMM_MOVE(X1, X2); XMM_MOVE(X2, X3); XMM_MOVE(X3, X4); XMM_MOVE(X4, X5); XMM_MOVE(X5, X6); XMM_MOVE(X6, X7); XMM_MOVE(X7, X8); XMM_MOVE(X8, X9); XMM_MOVE(X9, X10); XMM_MOVE(X10, X11); XMM_MOVE(X11, X12); XMM_MOVE(X12, X13); XMM_MOVE(X13, X14); XMM_MOVE(X14, X15); return X15; } #endif // CATASTROPHIC_ERROR