Рассмотрим следующую простую программу (адаптированную из этот вопрос):
#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;
}
И все еще лязг 3.7.1, gcc 5.3 а также ICC 13.0.1 кажется, не в состоянии сделать такую оптимизацию, даже с -Ofast
, (Заметьте, кстати, как сгенерированная сборка сильно отличается между компиляторами!). Однако при удалении mul2
а также x2
из уравнения, лязг способен выполнить аналогичную оптимизацию даже при -O2
,
Что мешает обоим компиляторам оптимизировать первую программу во вторую?
Полное выражение слишком сложно даже для лязга. Если вы разделите его, все снова будет оптимизировано:
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);
Я не программист, поэтому это только предположение. ИМХО, ответ является частью ответа @ dlask и замечанием, что clang выполняет оптимизацию при удалении x2
а также mul2
из выражения.
Компилятор может оптимизировать все, что он может сделать. Но я также думаю, что оптимизирующие компиляторы — это уже огромные и сложные программы, в которых ошибки могут иметь серьезные последствия, потому что они лежат в основе почти всего остального (самый современный интерпретатор Python написан на … C)
Таким образом, должен быть баланс между эффективностью оптимизатора и его сложностью, и я думаю, что этот пример программы выходит за рамки gcc, и только для clang. Ничто не мешает им выполнить эту оптимизацию, за исключением того, что она слишком сложна для текущей версии этих компиляторов.