-fno将严格别名作为函数属性

-fno-strict-aliasing as function attribute

本文关键字:函数 属性 别名 -fno      更新时间:2023-10-16

我有一个函数,出于性能原因,我在其中键入punning。基本上,我有一个32乘32位的数组,存储为32 uint32s:的数组

struct Tile {
    uint32_t d[32];
};

然后,我想计算32×32瓷砖的28×28"内部"的总体("1"的数量)。naive方法将对机器的popcnt指令进行28次调用,每行一次。但是,由于popcnt可以采用64位参数,因此可以将其减少为14个popcnt调用:

int countPopulation(Tile* sqt) __attribute__((optimize("-fno-strict-aliasing"))) {
    int pop = 0;
    for (int i = 2; i < 30; i += 2) {
        const uint64_t v = *reinterpret_cast<const uint64_t*>(sqt->d + i);
        pop += __builtin_popcountll(v & 0x3ffffffc3ffffffcull);
    }
    return pop;
}

如果我不包括属性:

__attribute__((optimize("-fno-strict-aliasing")))

那么g++会一直抱怨我的双关语类型,原因很明显:

warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
         const uint64_t v = *reinterpret_cast<const uint64_t*>(sqt->d + i);

另一方面,如果我确实包含了属性,某些版本的g++会抱怨,而其他版本则不会。在我尝试过的机器中,我得到了:

  • g++(Ubuntu 4.8.4-2ubuntu114.04.1)4.8.4抱怨
  • g++-4.6.real(Ubuntu/Linaro 4.6.3-1ubuntu5)4.6.3没有抱怨
  • g++(Debian 5.3.1-5)5.3.1 20160101没有抱怨

g++4.8.4的Ubuntu风格有什么问题?

不要键入双关语。这是没有理由的。相反,请正确使用memcpy()int64_t参数进行复制。优化器将完成其余工作。