Почему G CC не оптимизирует записи в память в этом суммировании l oop? - PullRequest
3 голосов
/ 08 июля 2020

Учитывая следующий код C, почему G CC (версия 10.1, x86-64, -O3) записывает в память внутри l oop вместо того, чтобы просто использовать два регистра во время суммирования и записывать результат в память только в конце?

void sum(unsigned int l, int *as, int *r) {
    r[0] = 0;
    r[1] = 0;
    for (int i = 0; i < l; i++) {
        r[0] += as[2 * i];
        r[1] += as[2 * i + 1];
    }
}

Сгенерированные инструкции здесь .

Я предполагаю, что это поведение связано с G CC, имеющим «в виду» параллелизм . У вас может быть другой поток, например, чтение из памяти по тому же адресу, пока выполняется суммирование. Это настоящая (и единственная) причина? Возможно, это вообще определено стандартом C?

1 Ответ

7 голосов
/ 09 июля 2020

Компилятор не знает, указывают ли as и r на один и тот же массив, поэтому он не знает, что r[0] += as[2 * i]; не изменяет значение as[2 * i + 1], которое необходимо в r[1] += as[2 * i + 1];, и аналогично для других взаимодействий между r[0], r[1] и различными элементами as.

Вы можете сообщить компилятору, что элементы, указанные через as и r, не перекрываются, изменив объявление функции в void sum(unsigned int l, int * restrict as, int * restrict r).

...