在使用clang实现char8_t方面是否存在缺陷,或者该标准的某个暗角禁止优化?

Tob*_*obi 12 c++ clang compiler-optimization c++20

clang 8.0.0引入了对char8_t从c ++ 20开始的类型的支持。但是,我希望以下函数具有相同的编译器输出

#include <algorithm>

bool compare4(char const* pcha, char const* pchB, int n) {
    return std::equal(pcha, pcha+4, pchB);
}

bool compare4(char8_t const* pchA, char8_t const* pchB, int n) {
    return std::equal(pchA, pchA+4, pchB);
}
Run Code Online (Sandbox Code Playgroud)

然而,他们编译-std=c++2a -O2

compare4(char const*, char const*, int):   # @compare4(char const*, char const*, int)
        mov     eax, dword ptr [rdi]
        cmp     eax, dword ptr [rsi]
        sete    al
        ret
_Z8compare4PKDuS0_i:                       # @_Z8compare4PKDuS0_i
        mov     al, byte ptr [rdi]
        cmp     al, byte ptr [rsi]
        jne     .LBB1_4
        mov     al, byte ptr [rdi + 1]
        cmp     al, byte ptr [rsi + 1]
        jne     .LBB1_4
        mov     al, byte ptr [rdi + 2]
        cmp     al, byte ptr [rsi + 2]
        jne     .LBB1_4
        mov     al, byte ptr [rdi + 3]
        cmp     al, byte ptr [rsi + 3]
        sete    al
        ret
.LBB1_4:
        xor     eax, eax
        ret
Run Code Online (Sandbox Code Playgroud)

显然后者的优化程度较差。是否有原因(我在标准中找不到)或这是clang中的错误?

cpp*_*ner 4

  1. 在 libstdc++ 中,当它检测到参数是“简单”时std::equal调用,否则它使用朴素的 for 循环。__builtin_memcmp这里的“简单”是指指向相同整数或指针类型的指针(或指针周围的某些迭代器包装器)。(相关源代码

    • 类型是否为整型是通过内部__is_integerTrait 来检测的,但是 libstdc++ 8.2.0(godbolt.org 上使用的版本)并没有专门针对 的这个 Trait char8_t,所以后者不会被检测为整型。(相关源码
  2. Clang(使用此特定配置)在 for 循环情况下生成比在 for 循环情况下更详细的汇编__builtin_memcmp(但前者在性能方面不一定优化较差。请参阅Loop_unrolling。)

所以这种差异是有原因的,而且在我看来这不是 clang 的错误。