Почему эта программа не оптимизирована?

Рассмотрим следующую, простую программу (адаптированную из этого вопроса):

#include <cstdlib>

int main(int argc, char** argv) {
    int mul1[10] = { 4, 1, 8, 6, 3, 2, 5, 8, 6, 7 }; // sum = 50
    int mul2[10] = { 4, 1, 8, 6, 7, 9, 5, 1, 2, 3 }; // sum = 46

    int x1 = std::atoi(argv[1]);
    int x2 = std::atoi(argv[2]);

    int result = 0;

    // For each element in mul1/mul2, accumulate the product with x1/x2 in result
    for (int i = 0; i < 10; ++i) {
        result += x1 * mul1[i] + x2 * mul2[i];
    }

    return result;
}

Я считаю, что он функционально эквивалентен следующему:

#include <cstdlib>

int main(int argc, char** argv) {
    int x1 = std::atoi(argv[1]);
    int x2 = std::atoi(argv[2]);

    return x1 * 50 + x2 * 46;
}

И все же clang 3.7.1, gcc 5.3 и icc 13.0.1, похоже, не могут выполнить такую ​​оптимизацию даже при -Ofast. (Обратите внимание на то, как сгенерированная сборка сильно отличается от компиляторов!). Однако при удалении из уравнения mul2 и x2 clang может выполнять аналогичную оптимизацию даже при -O2.

Что мешает обоим компиляторам оптимизировать первую программу во второй?

Ответ 1

Полное выражение слишком сложно даже для clang. Если вы разделите его, все снова будет оптимизировано:

int result1 = 0;
int result2 = 0;

for (int i = 0; i < 10; ++i) {
    result1 += x1 * mul1[i];
    result2 += x2 * mul2[i];
}

std::cout << (result1 + result2);

Ответ 2

Я не программист, поэтому это может быть только предположение. IMHO, ответ является частью ответа @dlask и частью замечания, что clang делает оптимизацию, когда вы удаляете x2 и mul2 из выражения.

Компилятор может оптимизировать все, что он может сделать. Но я также думаю, что оптимизация компиляторов - это уже огромные и сложные программы, в которых ошибки могут иметь высокие последствия, потому что они лежат в основе почти всего остального (самый интерпретатор Python написан в... C)

Таким образом, должен быть баланс между эффективностью оптимизатора и его сложностью, и я думаю, что этот пример программы находится за его пределами для gcc и просто для clang. Ничто не мешает им делать эту оптимизацию, кроме того, что она слишком сложна для текущей версии этих компиляторов.