Если вы не возражаете против небольшой встроенной сборки x86 (синтаксис GNU C), вы можете воспользоваться предложением суперкатера использовать rotate-with-carry после добавления, чтобы поставить старшие 32 бита полный 33-битный результат в регистр.
Конечно, вы обычно должны возражать против использования inline-asm, потому что это побеждает некоторые оптимизации (https://gcc.gnu.org/wiki/DontUseInlineAsm). Но мы все равно пойдем:
// works for 64-bit long as well on x86-64, and doesn't depend on calling convention
unsigned average(unsigned x, unsigned y)
{
unsigned result;
asm("add %[x], %[res]\n\t"
"rcr %[res]"
: [res] "=r" (result) // output
: [y] "%0"(y), // input: in the same reg as results output. Commutative with next operand
[x] "rme"(x) // input: reg, mem, or immediate
: // no clobbers. ("cc" is implicit on x86)
);
return result;
}
Модификатор %
, указывающий компилятору, что аргументы являются коммутативными, на самом деле не помогает улучшить asm в моем случае, вызывая функцию с y, являющимся константой или указателем с разыменованием (память операнд). Вероятно, использование соответствия для выходного операнда побеждает это, поскольку вы не можете использовать его с операндами чтения-записи.
Как вы можете видеть в проводнике компилятора Godbolt , он компилируется правильно, как и версия, в которой мы меняем операнды на unsigned long
, с тем же встроенным asm. Однако clang3.9 все испортил и решил использовать опцию "m"
для ограничения "rme"
, поэтому он сохраняет в памяти и использует операнд памяти.
RCR-by-one не слишком медленный, но на Skylake он все еще 3 мопа с задержкой в 2 цикла. Это замечательно для процессоров AMD, где RCR имеет задержку одного цикла. (Источник: Таблицы инструкций Агнера Фога , см. Также вики-тег x86 для ссылок на производительность x86). Это все же лучше, чем версия @ Sellibitze, но хуже, чем версия, зависящая от порядка @ Sheldon. (См. Код на Godbolt)
Но помните, что inline-asm побеждает оптимизацию как постоянное распространение, поэтому любая версия на чистом C ++ будет лучше в этом случае.