gcc是否以代数方式优化c ++代码,如果可以,优化程度如何?

问题描述 投票:1回答:2

考虑下面的代码显示一些简单的算术运算

    int result = 0;

    result = c * (a + b) + d * (a + b) + e;

要在cpu上方的表达式中获得结果,将需要执行两个整数乘法和三个整数加法。但是从代数上讲,上述表达式可以简化为以下代码。

 result = (c + d) * (a + b) + e

这两个表达式在代数上是相同的,但是第二个表达式仅包含一个乘法和三个加法。 gcc(或与此相关的其他编译器)是否能够自行进行此简单的优化。

现在假设编译器足够智能,可以进行此简单的优化,它将能够优化更复杂的内容,例如Trapezoidal rule(用于数值积分)。下面的示例以pi / 4的步长(为简单起见较小)来近似sin(x)下的区域,其中0 <= x <= pi。请假定所有文字都是运行时变量。

#include <math.h>

// Please assume all literals are runtime variables. Have done it this way to 
// simplify the code.
double integral = 0.5 * ((sin(0) + sin(M_PI/4) * (M_PI/4 - 0) + (sin(M_PI/4) + 
    sin(M_PI/2)) * (M_PI/2 - M_PI/4) + (sin(M_PI/2) + sin(3 * M_PI/4)) * 
    (3 * M_PI/4 - M_PI/2) + (sin(3 * M_PI/4) + sin(M_PI)) * (M_PI - 3 * M_PI/4));

现在,可以使用梯形法则简化上述函数。这大大减少了获得相同答案所需的乘法/除法次数。

integral = 0.5 * (1 / no_steps /* 4 in th case above*/) * 
    (M_PI - 0 /* Upper and lower limit*/) * (sin(0) + 2 * (sin(M_PI/4) +
    sin(3 * M_PI/4)) + sin(M_PI));
c++ c gcc g++
2个回答
7
投票

[GCC(和大多数C ++编译器,就此而言)不重构代数表达式。

这主要是因为就GCC和通用软件算法而言,行

double x = 0.5 * (4.6 + 6.7);
double y = 0.5 * 4.6 + 0.5 * 6.7;

assert(x == y); //Will probably fail!

不保证将其评估为完全相同的数字。没有这种保证,海湾合作委员会就无法优化这些结构。

此外,操作顺序可能很重要。例如:

int x = y;
int z = (y / 16) * 16;

assert(x == z); //Will only be true if y is a whole multiple of 16

从代数上讲,这两行应该相等,对吗?但是,如果yint,则实际上将使x等于“ y舍入为16的整数倍”。有时,这是预期的行为(例如,如果您要进行字节对齐)。其他时候,这是一个错误。重要的是,两者都是有效的计算机代码,并且都可以根据情况使用,并且如果GCC围绕这些结构进行了优化,则将阻止程序员对其代码进行代理。


1
投票

是的,包括gcc在内的优化程序,都进行了这种类型的优化。不一定是您精确引用的表达式或其他任意复杂的表达式。但是更简单的表达方式是,例如(a + a) - a可能会优化为a。可能的优化的另一个示例是a*a*a*atemp = a*a; (temp)*(temp)

© www.soinside.com 2019 - 2024. All rights reserved.