https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114039
Bug ID: 114039 Summary: Unroll loops with SSE/AVX intrinsic where an immediate argument is a loop var Product: gcc Version: 13.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: daniil.iaitskov at soostone dot com Target Milestone: --- Lots of SSE/AVX intrinsic functions can accept only literal constants in arguments. Current workaround is turning a variable with a small cardinality into a switch wrapped with a macro. I think extending unrolling semantic to this case should help a lot with reducing code boilerplate. Program expected to pass compilation: ``` #include <stdio.h> #include <immintrin.h> inline __m128i testUnrollSse(__m128i x, __m128i d, int n) { for (int i = n; i <= n; ++i) { // loop does always just a single iteration return _mm_srli_si128(x, i); } return d; } __m128i foo(int i, __m128i x, __m128i d) { if (i < 16) { return testUnrollSse(x, d, i); } return d; } ``` Compiler options: gcc -mavx2 -O3 ``` Output of x86-64 gcc 13.2 (Compiler #1) In file included from /opt/compiler-explorer/gcc-13.2.0/lib/gcc/x86_64-linux-gnu/13.2.0/include/xmmintrin.h:1322, from /opt/compiler-explorer/gcc-13.2.0/lib/gcc/x86_64-linux-gnu/13.2.0/include/immintrin.h:31, from <source>:2: In function '_mm_srli_si128', inlined from 'testUnrollSse' at <source>:6:12, inlined from 'foo' at <source>:13:16: /opt/compiler-explorer/gcc-13.2.0/lib/gcc/x86_64-linux-gnu/13.2.0/include/emmintrin.h:1229:19: error: the last argument must be an 8-bit immediate 1229 | return (__m128i)__builtin_ia32_psrldqi128 (__A, __N * 8); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Compiler returned: 1 ``` Expected code: ``` switch(i) { case 1: return _mm_srli_si128(x, 1); case 2: return _mm_srli_si128(x, 2); // ... case 16: return _mm_srli_si128(x, 16); defaut: fprintf(stderr, "Panic ....", __FILE__, __LINE__, i); exit(-1); ```