Это ошибка оптимизации ag cc -O2 (отличается от -O1)? - PullRequest
2 голосов
/ 22 апреля 2020

Я пишу очень простую программу, она ведет себя нормально без -O2:

#include <stdio.h>
#include <stdint.h>

int main()
{
    uint32_t A[4] = { 1, 2, 3, 4 };
    float B[4] = { 0, 0, 0, 0 };
    float C[4] = { 5, 6, 7, 8 };
    int i;

    // convert integer A to float B
    for (i = 0; i < 4; i++) 
        B[i] = (float)A[i];

    // memory copy from B to C
    uint32_t *src = (uint32_t*)(B);
    uint32_t *dst = (uint32_t*)(C);
    dst[0] = src[0];
    dst[1] = src[1];
    dst[2] = src[2];
    dst[3] = src[3];

#if 0
    // open this to correct the error
    __asm__("":::"memory");
#endif

    // print C, C should be [1.0, 2.0, 3.0, 4.0]
    for (i = 0; i < 4; i++) 
        printf("%f\n", C[i]);

    return 0;
}

Компилируется без -O2:

$ gcc error.c -o error
$ ./error
1.0000
2.0000
3.0000
4.0000

Работает как положено. Но если я добавил -O2:

$ gcc -O2 error.c -o error
$ ./error
-6169930235904.000000
0.000000
-6169804406784.000000
0.000000

Кроме того, если вы переключите #if 0 на #if 1, он снова будет работать правильно. asm ("":::"memory") должен быть ненужным в том же потоке.

Это ошибка -O2 оптимизации ??

Есть ли что-то, что я могу сказать компилятору, чтобы позаботиться об этом ?? У меня есть функция для сохранения регистра xmm в (void *) указатель, например:

inline void StoreRegister(void *ptr, const __m128& reg)
{
#if DONT_HAVE_SSE
    const uint32_t *src = reinterpret_cast<const uint32_t*>(&reg);
    uint32_t *dst = reinterpret_cast<uint32_t*>(ptr);
    dst[0] = src[0];
    dst[1] = src[1];
    dst[2] = src[2];
    dst[3] = src[3];
#else
    _mm_storeu_si128(reinterpret_cast<__m128*>(ptr), _mm_castps_si128(reg));
#endif
}

dst - это C в приведенном выше коде, любой способ исправить это без изменения подпись функции.

1 Ответ

9 голосов
/ 22 апреля 2020

Нет, это не проявление ошибки компилятора.

Скорее поведение вашего кода undefined из-за использования вами результата приведения (uint32_t*)(B) & c , Это нарушение строгого псевдонима .

Компиляторы - особенно g cc - становятся все более агрессивными, когда дело доходит до обработки неопределенных конструкций. Согласно стандарту они допускают, что неопределенное поведение не происходит, и могут удалить любую ветвь, которая его содержит.

...