gcc和clang不愿意懒散地初始化部分使用的结构
考虑以下代码:gcc和clang不愿意懒散地初始化部分使用的结构,c,gcc,clang,compiler-optimization,compiler-bug,C,Gcc,Clang,Compiler Optimization,Compiler Bug,考虑以下代码: __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(),以便只从内存中读取第一个参数的值 现在假设我们
__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;
}
应该没什么区别吧?参数(当然就组件而言)是两个整数;第二个是不使用的。所以我希望看到相同的汇编代码。然而我不。在调用foo2()
之前,clang和gcc都会初始化ti
的两个字段
(GodBolt.org)
那么,编译器是否有义务初始化这两个字段,或者这是一个错过的优化机会?编译器可以分析
foo1
,并决定在调用函数的任何地方抑制第二个参数。但在第二种情况下,编译器需要分析整个程序,然后才能安全地抑制第二个初始值设定项。foo2
不使用membery
这一事实并不能告诉编译器是否需要ti.y
。@user3386109:这不是真的。编译器不需要全局抑制第二个初始值设定项。它只需要在foo2()
中抑制它。我被以下语句误导了:“在调用foo2()
之前,clang和gcc都初始化ti
的两个字段。”。似乎您实际上关心的是s
的初始化,它是传递给foo2
@user3386109的ti
的副本:ti
被省略在foo2()的输入参数中。只有一个结构。编译器可以分析foo1
,并决定在调用函数的任何地方抑制第二个参数。但在第二种情况下,编译器需要分析整个程序,然后才能安全地抑制第二个初始值设定项。foo2
不使用membery
这一事实并不能告诉编译器是否需要ti.y
。@user3386109:这不是真的。编译器不需要全局抑制第二个初始值设定项。它只需要在foo2()
中抑制它。我被以下语句误导了:“在调用foo2()
之前,clang和gcc都初始化ti
的两个字段。”。似乎您实际上关心的是s
的初始化,它是传递给foo2
@user3386109的ti
的副本:ti
被省略在foo2()的输入参数中。只有一个结构。