Рассмотрим следующий код:
__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;
}
Там не должно быть никакой разницы, верно?Параметры (разумеется, что касается сборки) - это два целых числа;а второй не используется.Так что я ожидаю увидеть тот же код сборки.Пока что ... нет.И clang, и gcc инициализируют оба поля ti
перед вызовом foo2()
.
Оба фрагмента кода с gcc & clang (GodBolt.org)
Итак, что-нибудь обязывает компиляторы инициализировать оба поля или это упущенная возможность оптимизации?