Помимо синтаксической ошибки в коде (" "r"
->: "r"
), ваша проблема несоответствующие параметры ,
Глядя на выходе из -S:
add rax, r8b
Поскольку cnt
является size_t и bytes[i]
является байт, это то, что вы ожидали бы. Добавить требует, чтобы они были одного размера.
Могу ли я также использовать встроенные функции вместо встроенного asm? Он избегает таких проблем (как и многие другие).
Есть ли способ, чтобы сложить результат с POPCNT без сохранения его в регистр в первую очередь?
Umm. На самом деле это совсем другой вопрос. Ошибка, о которой вы спрашивали, связана с смешением байта и size_t в одной инструкции add
. Она может быть решена, выполнив:
__asm__(
"popcnt %0, %0 \n\t"
"add %0, %1 \n\t"
: "+r" (cnt)
: "r" ((size_t)bytes[i]));
Я не призываю вас продолжать добавлять новые вопросы (? Как я могу получить мои очки кармы), но глядя на этом сайте, код кажется, он баловаться с это:
uint32_t builtin_popcnt_unrolled_errata(const uint64_t* buf, int len) {
assert(len % 4 == 0);
int cnt[4];
for (int i = 0; i < 4; ++i) {
cnt[i] = 0;
}
for (int i = 0; i < len; i+=4) {
cnt[0] += __builtin_popcountll(buf[i]);
cnt[1] += __builtin_popcountll(buf[i+1]);
cnt[2] += __builtin_popcountll(buf[i+2]);
cnt[3] += __builtin_popcountll(buf[i+3]);
}
return cnt[0] + cnt[1] + cnt[2] + cnt[3];
}
Он явно с помощью CNT [х] в попытке избежать «ложной» зависимостей проблемы POPCNT.
Использование GCC 6.1 и компиляции с -m64 -O3 -march=native -mtune=native
, я вижу это как выход:
.L14:
popcnt r11, QWORD PTR [rcx]
add rcx, 32
add edx, r11d
popcnt r11, QWORD PTR -24[rcx]
add eax, r11d
popcnt r11, QWORD PTR -16[rcx]
add r10d, r11d
popcnt r11, QWORD PTR -8[rcx]
add r9d, r11d
cmp rcx, r8
jne .L14
Какой «хранить его в регистре» вы имеете в виду?
забыл упомянуть, что я начал со встроенных функций, но хотел что-то быстрее. Есть ли способ добавить результат из popcnt, не сохраняя его сначала в регистре? Получил идею от https://danluu.com/assembly-intrinsics/ –
спасибо за ответ? Я, должно быть, был просто смущен тем, что пытался сказать блог. Вот ваши точки кармы :) –
В блоге нет даты, но она была написана с использованием 4.8.2. Это было давно, поэтому все могло измениться. Это еще одна причина, по которой я рекомендую использовать встроенные функции вместо встроенных. встроенные функции могут улучшиться с течением времени, но если вы напишете inline, вы получите только то, что вы пишете. BTW, если производительность критическая, использование 64-битного popcnt (вероятно) быстрее, чем повторение 8 бит. Вам нужно будет проверить len и обрабатывать нечетные размеры, но я бы попробовал и время. –