gcc内联asm未编译

gcc内联asm未编译,c,gcc,inline-assembly,C,Gcc,Inline Assembly,我目前正试图使用内置的popcnt来计算无符号字符数组中的1数 我的函数与常规的\uuu内置的\uu popcount一起工作,但由于一些更严格的速度要求,我决定采用内联asm方法 size_t popcnt_manual( unsigned char *bytes, size_t len ) { size_t i, cnt = 0; for( i = 0; i < len; i++ ) { __asm__( "popcnt

我目前正试图使用内置的
popcnt
来计算
无符号字符数组中的1数

我的函数与常规的
\uuu内置的\uu popcount
一起工作,但由于一些更严格的速度要求,我决定采用内联asm方法

size_t popcnt_manual( unsigned char *bytes, size_t len ) {
    size_t i, cnt = 0;
    for( i = 0; i < len; i++ ) {
        __asm__(
                 "popcnt %0, %0    \n\t"
                 "add    %0, %1    \n\t"
                 : "+r" (cnt)
                 : "r"  (bytes[i]));
    }

    return cnt;
}
size\u t popcnt\u手册(无符号字符*字节,size\t len){
尺寸i,cnt=0;
对于(i=0;i
编译器一直在说

后缀或操作数对于add无效


除了代码中的语法错误(
“r”
->
:“r”
)之外,您的问题是参数不匹配

查看-S的输出:

 add    rax, r8b
由于
cnt
是大小\u t,
bytes[i]
是一个字节,这是您所期望的。Add要求它们的大小相同

我还可以建议使用内置而不是内联asm吗?它可以避免类似这样的问题(以及许多其他问题)


有没有办法在不先将popcnt的结果存储在寄存器中的情况下将其相加

嗯。这实际上是一个完全不同的问题。您所问的错误是由于在单个
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];
}

它“将其存储在寄存器中”“你指的是什么?

忘了提我一开始是用内置的,但我想要更快的。有没有办法在不先将popcnt的结果存储在寄存器中的情况下将其相加?你是从“谢谢你的回答”那里得到这个主意的吗?我一定是被这篇博文想说的话弄糊涂了。以下是你的因果报应:)博客上没有日期,但它是用4.8.2写的。那是很久以前的事了,所以事情可能已经改变了。这是我建议使用内置而不是内联的另一个原因。内置可以随着时间的推移而改进,但如果您内联编写,您只能得到您所编写的内容。顺便说一句,如果性能至关重要,那么使用64位popcnt(可能)比重复使用8位快。您需要检查透镜和处理奇数尺寸,但我会尝试并计时。明白。谢谢你的意见
.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