【发布时间】:2012-02-07 16:25:54
【问题描述】:
在 gcc 中使用不同优化级别编译此代码时,我看到了我不期望的行为。
函数测试应该用 1 填充 64 位无符号整数,将它们向左移动 shift_size 位,并将低 32 位作为 32 位无符号整数返回。
当我使用 -O0 编译时,我得到了我期望的结果。
当我使用 -O2 编译时,如果我尝试移动 32 位或更多位,我不会这样做。
事实上,如果我在 x86 上通过大于或等于位宽的移位来移位 32 位整数,我得到的结果正是我所期望的,这是仅使用移位大小的 5 个低位的移位。
但是我正在移动一个 64 位数字,所以移动
我认为这是我理解中的错误,而不是编译器中的错误,但我无法弄清楚。
我的机器: gcc (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5 i686-linux-gnu
#include <stdint.h>
#include <stdio.h>
#include <inttypes.h>
uint32_t test(unsigned int shift_size) {
uint64_t res = 0;
res = ~res;
res = res << shift_size; //Shift size < uint64_t width so this should work
return res; //Implicit cast to uint32_t
}
int main(int argc, char *argv[])
{
int dst;
sscanf(argv[1], "%d", &dst); //Get arg from outside so optimizer doesn't eat everything
printf("%" PRIu32 "l\n", test(dst));
return 0;
}
用法:
$ gcc -Wall -O0 test.c
$ ./a.out 32
0l
$ gcc -Wall -O2 test.c
$ ./a.out 32
4294967295l
【问题讨论】:
-
你能把你的编译器生成的汇编代码的相关部分也贴出来吗? (
-S用于 gcc) -
FWIW 它使用 gcc 4.2.1 在从
-O0到-O3的所有优化级别上为我提供了正确的结果 (0l),所以我怀疑你可能 发现了一个 gcc 错误。 -
嗯,我的代码在两个优化级别都可以正常工作...(gcc 版本 4.5.0 20100604,openSUSE 11.3 (x86_64))
-
@Alex:如果您尝试使用带有 -O2 -m32 的 non-LLVM gcc 4.2.1,那么您应该会看到它(这就是我正在使用的)
-
这是一个已确认的错误:gcc.gnu.org/bugzilla/show_bug.cgi?id=51821
标签: c optimization gcc bit-manipulation shift