Ожидайте высочайшую компетентность от вашего оптимизатора
Это, конечно, полностью зависит от реализации.Но, как правило, можно ожидать, что оптимизирующий компилятор будет генерировать аналогично оптимизированный код в обоих случаях.
Почему?Потому что, в основном, на многих целевых ЦП работа с битовыми полями требует только нескольких двоичных операций (смещение вправо и влево) с исходным значением.Затем оптимизатор может оптимизировать эти выражения (например, оптимизируя избыточные подвыражения), как и любые другие операции в выражении.
Практический эксперимент:
Возьмем последовательность:
x=S.f0*S.f0;
y=S.f0*S.f1;
(соответствующая часть) код, сгенерированный с помощью GCC 8.3:
1) movzx eax, BYTE PTR S[rip] ; load 8 bit of data data and make it 16 bits
2) sal eax, 2 ; get rid of the 2 bytes to keep only the 6
3) sar al, 2
4) movsx edx, al ; clone the value in second register
5) mov eax, edx
6) imul eax, edx
7) mov DWORD PTR x[rip], eax
8) movzx eax, WORD PTR S[rip] ; load 16 bits
9) sal eax, 4 ; get rid of 4 bits (so remain 12)
10) sar ax, 10 ; get rid of 10 bits on other side (so remain 6 next)
11) movsx eax, al
12) imul eax, edx ; reuse register previously loaded
13) mov DWORD PTR y[rip], eax
Теперь для другой альтернативы:
const int f0=S.f0,f1=S.f1;
x=f0*f0;
y=f0*f1;
вы получите следующий код :
1) movzx eax, BYTE PTR S[rip]
8) movzx edx, WORD PTR S[rip] ; but in another register
2) sal eax, 2
9) sal edx, 4 ; but other register
3) sar al, 2
10) sar dx, 10 ; but other register
4) movsx eax, al
11) movsx edx, dl ; but other register
5) mov ecx, eax ; but other register
6) imul ecx, eax ; but other register
12) imul eax, edx
7) mov DWORD PTR x[rip], ecx ; but other register
13) mov DWORD PTR y[rip], eax
Дополнительные эксперименты показывают, что этоТо же самое для оптимизации цикла: компилятор может извлечь код доступа к битовому полю из цикла и повторно использовать извлеченные значения несколько раз.
Подсказка: ради тестов, учитывая возможности оптимизатора, вам нужно немного обмануть, чтобы ваш тестовый код не работалОптимизировать.Для этого я сделал x и y volatiles (чтобы они записывались в событие, если значение никогда не используется).Я также инициализировал структуру с несуществующей внешней функцией, чтобы компилятор не мог выполнять постоянное распространение.
Конечно, это верно только в том случае, если компилятор уверен, что S не меняется между последовательными выражениями.Если компилятор не может предположить, что (например, вы вызываете функцию, используя ссылку или указатель на S), ему придется каждый раз перезагружать S.fx, делая его медленнее, чем первоначальная загрузка, в константное значение.