考虑以下简单程序(改编自this question):
#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
也可以执行类似的优化。
是什么阻止了两个编译器将第一个程序优化到第二个程序?
答案 0 :(得分:4)
即使是铿锵声,完整的表达也太复杂了。如果你拆分它,那么一切都会再次优化:
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);
答案 1 :(得分:2)
我不是编译程序员,所以这只能是猜测。恕我直言,答案是@dlask的答案中的一部分,并且当你从表达式中删除mul2
和<img id="product-collection-image-<?php echo $_product->getId(); ?>"
src="<?php echo $this->helper('catalog/image')->init($_product, 'small_image')->resize(236,193); ?>"
alt="<?php echo $this->stripTags($this->getImageLabel($_product, 'small_image'), null, true) ?>" />
时,clang会对优化进行评论。
编译器可能优化它可以做的所有事情。但我也认为优化编译器已经是庞大而复杂的程序,其中错误会产生很大的后果,因为它们几乎是其他所有东西的基础(Python最新的解释器是用...编写的)
因此,优化器的效率与其复杂性之间必须保持平衡,而且我认为这个示例程序超出了gcc的范围,而且只是针对clang。没有什么能阻止他们进行优化,除非它对于那些编译器的当前版本来说太复杂了。