Оптимизирует ли GCC std :: tie, используемый только для удобства чтения?

Предположим, у меня есть std::tuple:

std::tuple<int,int,int,int> t = {1,2,3,4};

и я хочу использовать std::tie просто для удобства чтения:

int a, b, c, d; // in real context these names would be meaningful
std::tie(a, b, c, d) = t;

против просто использования t.get<int>(0), так далее.

Будет ли GCC оптимизировать использование памяти этого кортежа или выделит дополнительное пространство для a, b, c, d переменные?

6

Решение

В этом случае я не вижу причин, почему нет, под как будто правило компилятор должен только эмулировать наблюдаемое поведение программы. Быстрый эксперимент используя Godbolt:

#include <tuple>
#include <cstdio>

void func( int x1, int x2,int  x3, int x4)
{
std::tuple<int,int,int,int> t{x1,x2,x3,x4};

int a, b, c, d; // in real context these names would be meaningful
std::tie(a, b, c, d) = t;

printf( "%d %d %d %d\n", a, b, c, d ) ;
}

показывает, что gcc действительно оптимизирует его:

func(int, int, int, int):
movl    %ecx, %r8d
xorl    %eax, %eax
movl    %edx, %ecx
movl    %esi, %edx
movl    %edi, %esi
movl    $.LC0, %edi
jmp printf

С другой стороны, если вы использовали адрес t и распечатали его, теперь мы имеем наблюдаемое поведение, которое опирается на t существующий (увидеть это в прямом эфире):

printf( "%p\n", static_cast<void*>(&t) );

и мы можем видеть, что GCC больше не оптимизирует от t:

movl    %esi, 12(%rsp)
leaq    16(%rsp), %rsi
movd    12(%rsp), %xmm1
movl    %edi, 12(%rsp)
movl    $.LC0, %edi
movd    12(%rsp), %xmm2
movl    %ecx, 12(%rsp)
movd    12(%rsp), %xmm0
movl    %edx, 12(%rsp)
movd    12(%rsp), %xmm3
punpckldq   %xmm2, %xmm1
punpckldq   %xmm3, %xmm0
punpcklqdq  %xmm1, %xmm0

В конце дня вам нужно посмотреть, что генерирует компилятор, и профилировать ваш код, в более сложных случаях это может вас удивить. То, что компилятору разрешено выполнять определенные оптимизации, еще не значит, что так будет. Я посмотрел на более сложные случаи, когда компилятор не делает то, что я ожидал бы с std::tuple, Godbolt — очень полезный инструмент здесь, я не могу сосчитать, сколько оптимизационных предположений я имел, которые были опровергнуты, добавив простые примеры в Godbolt.

Обратите внимание, я обычно использую printf в этих примерах, потому что iostreams генерирует много кода, который мешает примеру.

7

Другие решения


По вопросам рекламы [email protected]