https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106470
Bug ID: 106470 Summary: Subscribed access to __m256i casted to (uint16_t *) produces garbage or a warning Product: gcc Version: 12.1.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: vt at altlinux dot org Target Milestone: --- It's appeared in liboqs in code imported from PQClean[1]. There is minimized reproducer: 1. ``` $ cat test1.c #include <immintrin.h> #include <stdio.h> #include <stdint.h> #include <string.h> int main(void) { __m256i tmp = _mm256_set_epi16(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); for (size_t i = 0; i < 16; i++) { printf(" %04x", ((uint16_t *)&tmp)[i]); } printf("\n"); return 0; } $ gcc -O2 -Wall -mavx2 -o a test1.c $ ./a c040 69a1 558e 0000 68da b7f6 7fb1 0000 87d0 b7f6 7fb1 0000 0000 0000 0001 0000 ``` This should been printing: 0010 000f 000e 000d 000c 000b 000a 0009 0008 0007 0006 0005 0004 0003 0002 0001 2. If we add `#pragma GCC unroll 16` it compiles with the warning, still printing incorrect values. ``` $ cat test2.c #include <immintrin.h> #include <stdio.h> #include <stdint.h> #include <string.h> int main(void) { __m256i tmp = _mm256_set_epi16(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); #pragma GCC unroll 16 for (size_t i = 0; i < 16; i++) { printf(" %04x", ((uint16_t *)&tmp)[i]); } printf("\n"); return 0; } $ gcc -O2 -Wall -mavx2 -o b test2.c test2.c: In function ‘main’: test2.c:10:51: warning: ‘tmp’ is used uninitialized [-Wuninitialized] 10 | printf(" %04x", ((uint16_t *)&tmp)[i]); | ~~~~~~~~~~~~~~~~~~^~~ test2.c:7:17: note: ‘tmp’ was declared here 7 | __m256i tmp = _mm256_set_epi16(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); | ^~~ $ ./b 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 ``` In comparison, clang produces correct output. [1] https://github.com/open-quantum-safe/liboqs/issues/1244