Hi,

I encountered the problem that the avx2 code crashes with segfault.
This happens if the cygwin gcc or cygwin mingw gcc compiler is used.

To reproduce the problem, compile the following test case with:
gcc -O0 avx2test.c -mavx2 -o avx2test
or
x86_64-w64-mingw32-gcc -O0 avx2test.c -mavx2 -o avx2test
then, run avx2test.exe.

I looked into this problem a bit, and noticed that vmovdqa/vmovaps is
used for misaligned operands. If run
gcc -S -O0 avx2test.c -mavx2
and replase all vmovdqa/vmovaps with vmovdqu/vmovups in avx2test.s,
then run
gcc avx2test.s -o avx2test
the test case runs correctly.

This does not happen with gcc in Linux, mingw gcc in linux and MSYS2.
Only the cygwin gcc (v11.4, 12.3, 13.2) causes this problem.

Any idea?


/* avx2test.c */
#include <stdio.h>
#include <immintrin.h>
#include <stdint.h>

__m256i __m256i_div_epi32(const __m256i *a, const __m256i *b)
{
        __m256 a1 = _mm256_cvtepi32_ps(*a);
        __m256 b1 = _mm256_cvtepi32_ps(*b);
        __m256 c = _mm256_div_ps(a1, b1);
        __m256 d = _mm256_floor_ps(c);
        __m256i e = _mm256_cvtps_epi32(d);
        return e;
}

__m256i load_32bit_to_16bit_w16_avx2(const int32_t *a)
{
        __m256i a_low = _mm256_lddqu_si256((const __m256i *) a);
        __m256i a_high = _mm256_lddqu_si256((const __m256i *) (a + 8));
        __m256i b = _mm256_packs_epi32(a_low, a_high);
        return _mm256_permute4x64_epi64(b, 0xD8);
}

int main()
{
        __attribute__ ((aligned (32))) int64_t a64[4] =
                {0x447b400045754, 0x447b4000447b4, 0x447b4000443cc, 
0x44b9c000447b4};
        __attribute__ ((aligned (32))) int64_t b64[4] =
                {0x426800004268, 0x426800004268, 0x426800004268, 
0x426800004268};
        __attribute__ ((aligned (32))) int32_t c32[16] =
                {0x7fe, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};

        __m256i d = __m256i_div_epi32((__m256i*)a64, (__m256i*)b64);
        int64_t *d64 = (int64_t *)&d;
        printf("%lx, %lx, %lx, %lx\n", d64[0], d64[1], d64[2], d64[3]);

        __m256i e = load_32bit_to_16bit_w16_avx2(c32);
        int64_t *e64 = (int64_t *)&e;
        printf("%lx, %lx, %lx, %lx\n", e64[0], e64[1], e64[2], e64[3]);

        return 0;
}

-- 
Takashi Yano <takashi.y...@nifty.ne.jp>

-- 
Problem reports:      https://cygwin.com/problems.html
FAQ:                  https://cygwin.com/faq/
Documentation:        https://cygwin.com/docs.html
Unsubscribe info:     https://cygwin.com/ml/#unsubscribe-simple

Reply via email to