GCC优化对比特操作的有效性

Dum*_*Guy 13 c optimization x86 assembly

以下是在x86-64上设置C中的单个位的两种方法:

inline void SetBitC(long *array, int bit) {
   //Pure C version
   *array |= 1<<bit;
}

inline void SetBitASM(long *array, int bit) {
   // Using inline x86 assembly
   asm("bts %1,%0" : "+r" (*array) : "g" (bit));
}
Run Code Online (Sandbox Code Playgroud)

使用带有-O3 -march=core2选项的GCC 4.3,与常量一起使用时,C版本需要大约90%的时间bit.(两个版本编译为完全相同的汇编代码,但C版本使用or [1<<num],%rax指令而不是bts [num],%rax指令)

与变量一起使用时bit,C版本表现更好,但仍然明显慢于内联汇编.

重置,切换和检查位具有类似的结果.

为什么GCC对这种常见操作的优化程度如此之差?我是否在使用C版本做错了什么?

编辑:对不起,等待漫长的等待,这是我用来进行基准测试的代码.它实际上是一个简单的编程问题...

int main() {
    // Get the sum of all integers from 1 to 2^28 with bit 11 always set
    unsigned long i,j,c=0;
    for (i=1; i<(1<<28); i++) {
        j = i;
        SetBit(&j, 10);
        c += j;
    }
    printf("Result: %lu\n", c);
    return 0;
}

gcc -O3 -march=core2 -pg test.c
./a.out
gprof
with ASM: 101.12      0.08     0.08                             main
with C:   101.12      0.16     0.16                             main
Run Code Online (Sandbox Code Playgroud)

time ./a.out 也给出了类似的结果.

Nor*_*sey 13

为什么GCC对这种常见操作的优化程度如此之差?

序言:自20世纪80年代后期以来,对编译器优化的关注已经从专注于单个操作的微基准测试转向专注于人们关注速度的应用程序的宏基准测试.目前,大多数编译器编写者都专注于宏基准测试,开发好的基准测试套件是值得认真对待的.

:关于海合会没有人使用的基准的区别在哪里orbts事项一个真正的程序的执行时间.如果你可以制作这样的节目,你可能会得到gcc-land中人们的关注.

我是否在使用C版本做错了什么?

不,这是非常好的标准C.事实上,非常可读和惯用.


Set*_*eth 0

我认为您对优化器的要求很高。

您可以通过执行“register long z = 1L << bit;”,然后将其与您的数组进行或运算来帮助它。

但是,我假设多出 90% 的时间,您的意思是 C 版本需要 10 个周期,而 asm 版本需要 5 个周期,对吧?-O2 或 -O1 下的性能比较如何?