Open
Description
Here is a test C program that where MSAN reports false positives when compiled with -O2 -fsanitize=memory -march=skylake-avx512
with Clang 17.0.6:
#include <immintrin.h>
#include <inttypes.h>
#include <stdalign.h>
#include <stdint.h>
#include <stdio.h>
#include <time.h>
static inline uint64_t SplitMix64(uint64_t z) {
z = (z ^ (z >> 30)) * UINT64_C(0xBF58476D1CE4E5B9);
z = (z ^ (z >> 27)) * UINT64_C(0x94D049BB133111EB);
return z ^ (z >> 31);
}
static inline void RandomSeed(uint64_t* s0, uint64_t* s1) {
uint64_t seed =
SplitMix64((uint64_t)time(NULL) + UINT64_C(0x123456789) +
(uint64_t)((uintptr_t)s0) + (uint64_t)((uintptr_t)s1));
*s0 = seed;
*s1 = SplitMix64(seed);
}
static inline uint64_t RandomValue(uint64_t* s0, uint64_t* s1) {
uint64_t next_s1 = *s0;
const uint64_t next_s0 = *s1;
const uint64_t bits = next_s0 + next_s1;
*s0 = next_s0;
next_s1 ^= next_s1 << 23;
next_s1 ^= next_s0 ^ (next_s1 >> 18) ^ (next_s0 >> 5);
*s1 = next_s1;
return bits;
}
static inline __m128i DemoteM512I32ToI8(__m512i vect) {
vect = _mm512_packs_epi32(vect, vect);
vect = _mm512_packs_epi16(vect, vect);
return _mm512_castsi512_si128(_mm512_permutexvar_epi32(
_mm512_setr_epi32(0, 4, 8, 12, 0, 4, 8, 12, 0, 4, 8, 12, 0, 4, 8, 12),
vect));
}
static __attribute__((__noinline__)) void PrintInputAndResultValues(
const int32_t* input_values, const int8_t* result_values) {
printf("Input values:\n%" PRId32 ", %" PRId32 ", %" PRId32 ", %" PRId32
", %" PRId32 ", %" PRId32 ",\n%" PRId32 ", %" PRId32 ", %" PRId32
", %" PRId32 ", %" PRId32 ", %" PRId32 ",\n%" PRId32 ", %" PRId32
", %" PRId32 ", %" PRId32 "\n",
input_values[0], input_values[1], input_values[2], input_values[3],
input_values[4], input_values[5], input_values[6], input_values[7],
input_values[8], input_values[9], input_values[10], input_values[11],
input_values[12], input_values[13], input_values[14],
input_values[15]);
printf("Result values:\n%" PRId8 ", %" PRId8 ", %" PRId8 ", %" PRId8
", %" PRId8 ", %" PRId8 ", %" PRId8 ", %" PRId8 ", %" PRId8 ", %" PRId8
", %" PRId8 ", %" PRId8 ", %" PRId8 ",\n%" PRId8 ", %" PRId8
", %" PRId8 "\n",
result_values[0], result_values[1], result_values[2], result_values[3],
result_values[4], result_values[5], result_values[6], result_values[7],
result_values[8], result_values[9], result_values[10],
result_values[11], result_values[12], result_values[13],
result_values[14], result_values[15]);
}
int main(int argc, char** argv) {
(void)argc;
(void)argv;
uint64_t s0, s1;
RandomSeed(&s0, &s1);
alignas(64) int32_t input_values[16];
alignas(16) int8_t result_values[16];
for (size_t i = 0; i < 16; i++) {
uint32_t bits = (uint32_t)RandomValue(&s0, &s1);
int bit_len = (int)(RandomValue(&s0, &s1) % 31u) + 2;
uint32_t msb = (uint32_t)(UINT32_C(1) << (bit_len - 1));
input_values[i] = (int32_t)(((bits & (msb | (msb - 1))) ^ msb) - msb);
}
__m512i input_vect = _mm512_load_si512(input_values);
__m128i result_vect = DemoteM512I32ToI8(input_vect);
_mm_store_si128((__m128i*)result_values, result_vect);
PrintInputAndResultValues(input_values, result_values);
return 0;
}
Here is the error that MSAN reports when the above program is compiled with Clang 17.0.6:
==6170==WARNING: MemorySanitizer: use-of-uninitialized-value
#0 0x56295a24d229 in main (/home/testuser/programming/avx512_demote_u32_to_i8_rand_vals_010524_clang_msan+0xc0229) (BuildId: 71568913205c15c4c114d9cedfd2ea9142f359b0)
#1 0x7efc50829d8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#2 0x7efc50829e3f in __libc_start_main csu/../csu/libc-start.c:392:3
#3 0x56295a1be294 in _start (/home/testuser/programming/avx512_demote_u32_to_i8_rand_vals_010524_clang_msan+0x31294) (BuildId: 71568913205c15c4c114d9cedfd2ea9142f359b0)
SUMMARY: MemorySanitizer: use-of-uninitialized-value (/home/testuser/programming/avx512_demote_u32_to_i8_rand_vals_010524_clang_msan+0xc0229) (BuildId: 71568913205c15c4c114d9cedfd2ea9142f359b0) in main
Exiting
Here is the function that causes the false MSAN positive when compiled with -O2 -fsanitize=memory -march=skylake-avx512
:
static inline __m128i DemoteM512I32ToI8(__m512i vect) {
vect = _mm512_packs_epi32(vect, vect);
vect = _mm512_packs_epi16(vect, vect);
return _mm512_castsi512_si128(_mm512_permutexvar_epi32(
_mm512_setr_epi32(0, 4, 8, 12, 0, 4, 8, 12, 0, 4, 8, 12, 0, 4, 8, 12),
vect));
}