考虑以下代码:
__attribute__((noinline)) int foo1(int x, int y)
{
return x;
}
int bar1(int* a)
{
int b = foo1(a[5], a[10]);
return b * b;
}
即使没有foo1
的内联,编译器也可以很容易地告诉其参数之一未使用;因此实际上不必费心初始化它。确实,GCC 8.2和clang 7.0都编译bar1()
以便仅从内存中读取第一个参数的值。
现在假设我们将这两个int参数放入一个结构中:
struct two_ints { int x, y; };
__attribute__((noinline)) int foo2(struct two_ints s)
{
return s.x;
}
int bar2(int* a)
{
struct two_ints ti = { a[5], a[10] };
int b = foo2(ti);
return b * b;
}
应该没有什么区别吧?参数(就组件而言,肯定是两个)是整数。第二个不使用。因此,我希望看到相同的汇编代码。但是...我没有。在调用ti
之前,clang和gcc都初始化foo2()
的 both 字段。
Both code fragments with gcc & clang(GodBolt.org)
那么,有什么义务让编译器初始化两个字段,或者这是错过的优化机会吗?