我有一个类似的简单函数:
int foo(const Data& a, int pos)
{
Big_obj x= (pos==1?a.x : a.y);//I just use x for reading
return x.elem*x.elem;
}
(假设我忘记通过引用const Big_obj& x=...
存储对象)
今天编译器可以将其优化为以下代码吗? :
int foo(const Data& a, int pos)
{
if (pos == 1)
return a.x.elem * a.x.elem;
else
return a.y.elem * a.y.elem;
}
答案 0 :(得分:3)
使用GCC有一个非常有用的编译器开关:-fdump-tree-optimized
,它将在执行优化后显示代码。
您可以发现这一切都取决于Big_obj
。
E.g。
struct Big_obj
{
int elem;
int vect[1000];
};
struct Data { Big_obj x, y; };
和g++ -Wall -O3 -fdump-tree-optimized
将生成 .165t.optimized 文件,其中包含:
int foo(const Data&, int) (const struct Data & a, int pos)
{
int x$elem;
const struct Big_obj * iftmp.4;
int _8;
<bb 2>:
if (pos_2(D) == 1)
goto <bb 3>;
else
goto <bb 4>;
<bb 3>:
iftmp.4_4 = &a_3(D)->x;
goto <bb 5>;
<bb 4>:
iftmp.4_5 = &a_3(D)->y;
<bb 5>:
# iftmp.4_1 = PHI <iftmp.4_4(3), iftmp.4_5(4)>
x$elem_7 = MEM[(const struct Big_obj &)iftmp.4_1];
_8 = x$elem_7 * x$elem_7;
return _8;
}
这正是您发布的优化代码。但是,如果您更改Big_obj
(vect
类型已从数组更改为std::vector
):
struct Big_obj
{
int elem;
std::vector<int> vect;
};
优化不再执行(即foo()
也会为x.vect
分配/取消分配内存。
在该示例中,原因是必须根据as-if rule实现优化:只允许不改变程序的可观察行为的代码转换。
operator new
可以有一个自定义实现,计算它被调用的次数(这很难检测)。但即使没有自定义operator new
,也存在其他问题(请参阅Does allocating memory and then releasing constitute a side effect in a C++ program?)。
使用其他编译器,您必须研究汇编代码(例如clang++ -S
开关),但同样如此。