https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93418
Bug ID: 93418
Summary: GCC incorrectly constant propagates _mm_sllv/srlv/srav
Product: gcc
Version: 10.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: regression
Assignee: unassigned at gcc dot gnu.org
Reporter: husseydevin at gmail dot com
Target Milestone: ---
Regression starting in GCC 9
Currently, GCC constant propagates the AVX2 _mm_sllv family with constant
amounts to only shift by the first element instead of all elements
individually.
#include <immintrin.h>
#include <stdio.h>
// force -O0
__attribute__((__optimize__("-O0")))
void unoptimized() {
__m128i vals = _mm_set1_epi32(0xffffffff);
__m128i shifts = _mm_setr_epi32(16, 31, -34, 3);
__m128i shifted = _mm_sllv_epi32(vals, shifts);
printf("%08x %08x %08x %08x\n", _mm_extract_epi32(shifted, 0),
_mm_extract_epi32(shifted, 1), _mm_extract_epi32(shifted, 2),
_mm_extract_epi32(shifted, 3));
}
// force -O3
__attribute__((__optimize__("-O3")))
void optimized() {
__m128i vals = _mm_set1_epi32(0xffffffff);
__m128i shifts = _mm_setr_epi32(16, 31, -34, 3);
__m128i shifted = _mm_sllv_epi32(vals, shifts);
printf("%08x %08x %08x %08x\n", _mm_extract_epi32(shifted, 0),
_mm_extract_epi32(shifted, 1), _mm_extract_epi32(shifted, 2),
_mm_extract_epi32(shifted, 3));
}
int main() {
printf("Without optimizations (correct result):\t");
unoptimized();
printf("With optimizations (incorrect result):\t");
optimized();
}
I would expect this code to emit the following:
Without optimizations (correct result): ffff0000 80000000 00000000 fffffff8
With optimizations (incorrect result): ffff0000 80000000 00000000 fffffff8
Clang and GCC < 9 exhibit the first output, but 9.1 and later
However, I get this output on GCC 9 and later:
Without optimizations (correct result): ffff0000 80000000 00000000 fffffff8
With optimizations (incorrect result): ffff0000 ffff0000 ffff0000 ffff0000
Godbolt link: https://gcc.godbolt.org/z/oC3Psp