Никогда. Это нарушит цель встроенной сборки, которая должна получить именно то, о чем вы просите.
Если вы хотите использовать полную мощность инструкции целевого процессора установить таким образом, что компилятор может понять и оптимизировать, вы должны использовать встроенные функции, а не встроенный ассемблер.
например. вместо inline asm для popcnt
, используйте int count = __builtin_popcount(x);
(в GNU C, составленном с -mpopcnt
). Inline-asm также специфичен для компилятора, поэтому, если что-либо внутреннее устройство более переносимо, особенно если вы используете встроенные функции Intel x86, которые поддерживаются всеми основными компиляторами, которые могут ориентироваться на x86. Используйте #include <x86intrin.h>
, и вы можете использовать int _popcnt32 (int a)
, чтобы надежно получить инструкцию popcnt
x86. См. , а также другие ссылки в теге x86.
int count(){
int total = 0;
for(int i=0 ; i<4 ; ++i)
total += popc(i);
return total;
}
Собран с #define popc _popcnt32
по gcc6.3:
mov eax, 4
ret
clang 3.9 with an inline-asm definition of popc
, on the Godbolt compiler explorer:
xor eax, eax
popcnt eax, eax
mov ecx, 1
popcnt ecx, ecx
add ecx, eax
mov edx, 2
popcnt edx, edx
add edx, ecx
mov eax, 3
popcnt eax, eax
add eax, edx
ret
Это классический пример встроенного ассемблере побеждая постоянная распространение, и почему вы не должны Не используйте его для повышения производительности, если его можно избежать: https://gcc.gnu.org/wiki/DontUseInlineAsm.
Это определение рядный ASM я использовал для этого теста:
int popc_asm(int x) {
// force use of the same register because popcnt has a false dependency on its output, on Intel hardware
// this is just a toy example, though, and also demonstrates how non-optimal constraints can lead to worse code
asm("popcnt %0,%0" : "+r"(x));
return x;
}
Если вы не знаете, что popcnt
has a false dependency on its output register on Intel hardware, это еще одна причина, вы должны оставить его в компилятор, когда это возможно.
Используя специальные инструкции, которые компилятор не знает о том, один вариант использования для встроенного ассемблере, но если компилятор не знает об этом, конечно же, не может оптимизировать его. Прежде чем компиляторы были хороши в оптимизации встроенных функций (например, для SIMD-инструкций), inline asm для такого рода вещей был более распространенным. Но мы уже много лет отстаем от этого, и компиляторы в целом хороши с внутренними особенностями даже для архитектур без архитектуры x86, таких как ARM.
Это может быть сделано при запросе глобальной оптимизации. Оба g ++ и MSVC поддерживают глобальную оптимизацию. –
Надеюсь, что никогда! Если вы заботитесь о том, чтобы сделать встроенную сборку, вы, вероятно, не хотите, чтобы она была запутана. Как компилятор знает, что кажущаяся бесполезная запись в 0xbeefface не важна для какого-либо встроенного устройства? – John3136
Когда вы используете встроенную сборку, вы в основном говорите компилятору, что знаете, что делаете, и это будет лучше, чем то, что он может сделать. Зачем компилятор пытается его оптимизировать? Если вы хотите, чтобы компилятор оптимизировал ваш код, вы должны писать на реальном языке, для которого предназначен компилятор, IMO. –