为什么这个程序没有被优化掉?

时间:2015-06-10 08:28:29

标签: c++ optimization strength-reduction

考虑以下简单程序(改编自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.1gcc 5.3icc 13.0.1似乎无法进行此类优化,即使使用-Ofast也是如此。 (请注意编译器之间生成的程序集如何大不相同!)。但是,从等式中删除mul2x2时,clang即使使用-O2也可以执行类似的优化。

是什么阻止了两个编译器将第一个程序优化到第二个程序?

2 个答案:

答案 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。没有什么能阻止他们进行优化,除非它对于那些编译器的当前版本来说太复杂了。