LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 1390|回复: 11

好像发现一个gcc 4.1的bug!

[复制链接]
发表于 2006-5-8 11:33:03 | 显示全部楼层 |阅读模式
gentoo 2006.0 gcc 4.1 amd64下:
以下求最无符号数的最左边的1是哪一位的程序,没想到不同的编译参数给出不同的结果;这是gcc 4.1的bug吗?因为今天我用gcc 3.4.6编译发现没有错误了。请大家帮忙测试。

另外用gcc4.1的兄弟,有没有觉得其实gcc4.1编译性能还没有gcc 3.4好呢?一个大点的软件编译时间通常比gcc3.4慢10多分钟。64位系统是不是比32位系统要慢呢?

filename: highbits.c

  1. #include<stdio.h>

  2. int highbits(unsigned int j);

  3. int main()
  4. {
  5.         int ii,n;
  6.         unsigned int i = 0x45000000;
  7.         for(ii=0; ii < 100000000; ii++)
  8.                 n = highbits(i);      
  9.         printf("%d\n",n);
  10.       
  11. }


  12. int highbits(unsigned int j){
  13.         float f = j;
  14.         unsigned int* p = (unsigned int*)(&f);
  15.         int offset = ( ( *p & 0x7f800000) >> 23 ) - 127;
  16.         return offset;
  17. }
复制代码

用不同的优化参数编译得到的结果让人费解:
方法1:

  1. ifree@MMMIX ~/test $ gcc highbits.c -o highbits
  2. ifree@MMMIX ~/test $ time ./highbits
  3. 30

  4. real    0m1.505s
  5. user    0m1.504s
  6. sys     0m0.000s
复制代码

方法2:

  1. ifree@MMMIX ~/test $ gcc -O1 highbits.c -o highbitsO1
  2. ifree@MMMIX ~/test $ time ./highbitsO1
  3. 30

  4. real    0m0.002s
  5. user    0m0.000s
  6. sys     0m0.004s
  7. 速度快了何止万倍????
复制代码


方法3:

  1. ifree@MMMIX ~/test $ time ./highbitsO2
  2. -127

  3. real    0m0.002s
  4. user    0m0.000s
  5. sys     0m0.004s
复制代码

竟然得到错误的结果

方法4:


  1. ifree@MMMIX ~/test $ gcc -O3 highbits.c -o highbitsO3
  2. ifree@MMMIX ~/test $ time ./highbitsO3
  3. -127
复制代码


real    0m0.109s
user    0m0.104s
sys     0m0.004s
速度不快反慢
发表于 2006-5-8 11:50:12 | 显示全部楼层
以为这个正常吧

编译器不保证浮点数的表示的, 它可能选择认为快或者安全的表示.

或者说, 上面的用法在C语言里可以说是无定义的结果.
回复 支持 反对

使用道具 举报

发表于 2006-5-8 12:31:53 | 显示全部楼层
其实你那个循环:
  1.      for(ii=0; ii < 100000000; ii++)
  2.                 n = highbits(i);      
复制代码
其中n = highbits(i);   就是一个循环不变式,优化时自动提到循环外了,然后循环作为无用表达式被删除,所以优化后速度自然很快。

不同的优化,不同的结果。
  1. ~/coding/test $  gcc --version
  2. gcc (GCC) 4.1.0 (Gentoo 4.1.0)
  3. Copyright (C) 2006 Free Software Foundation, Inc.
  4. This is free software; see the source for copying conditions.  There is NO
  5. warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  6. ~/coding/test $  gcc a2.c -O1
  7. ~/coding/test $  time ./a.out
  8. 30
  9. real        0m0.001s
  10. user        0m0.000s
  11. sys        0m0.001s
  12. ~/coding/test $  gcc a2.c -O2
  13. ~/coding/test $  time ./a.out
  14. -16
  15. real        0m0.001s
  16. user        0m0.000s
  17. sys        0m0.001s
  18. ~/coding/test $  gcc a2.c -O3
  19. ~/coding/test $  time ./a.out
  20. -16
  21. real        0m0.148s
  22. user        0m0.145s
  23. sys        0m0.002s
复制代码
回复 支持 反对

使用道具 举报

发表于 2006-5-8 12:35:56 | 显示全部楼层
再用gcc3.4.6编译,发现结果正确。
貌似的确是gcc4.10的bug
  1. ~/coding/test $  gcc --version
  2. gcc (GCC) 3.4.6 (Gentoo 3.4.6, ssp-3.4.5-1.0, pie-8.7.9)
  3. Copyright (C) 2006 Free Software Foundation, Inc.
  4. This is free software; see the source for copying conditions.  There is NO
  5. warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  6. ~/coding/test $  gcc a2.c -O1
  7. ~/coding/test $  time ./a.out
  8. 30
  9. real        0m2.541s
  10. user        0m2.529s
  11. sys        0m0.012s
  12. ~/coding/test $  gcc a2.c -O2
  13. ~/coding/test $  time ./a.out
  14. 30
  15. real        0m0.149s
  16. user        0m0.145s
  17. sys        0m0.004s
  18. ~/coding/test $  gcc a2.c -O3
  19. ~/coding/test $  time ./a.out
  20. 30
  21. real        0m0.147s
  22. user        0m0.146s
  23. sys        0m0.001s
复制代码
回复 支持 反对

使用道具 举报

 楼主| 发表于 2006-5-8 12:50:36 | 显示全部楼层
Post by pointer
以为这个正常吧

编译器不保证浮点数的表示的, 它可能选择认为快或者安全的表示.

或者说, 上面的用法在C语言里可以说是无定义的结果.

你这样说有根据吗?浮点数的表示不是有个什么IEEE标准吗?
难道C语言还会用其他非标准的表现形式?
回复 支持 反对

使用道具 举报

发表于 2006-5-8 14:42:05 | 显示全部楼层
一方面是优化选项,一方面是精度选项,-O -O2什么的都是这些选项的不同组合,图方便而已。真的要编译软件一定是根据要求指定cflag的,尤其是是涉及浮点数。
回复 支持 反对

使用道具 举报

发表于 2006-5-9 11:13:42 | 显示全部楼层
If optimization level is >= 2 in gcc-4.1, strict-aliasing is used, and this could cause probelms when a pointer is referencing to a different type of object and the object is refered thereafter  by using this pointer.  That is the case in this example. So you should force the compiler to not use strict-aliasing by a argument "-fno-strict-aliasing" if you want to use "-O2" or "-O3".
回复 支持 反对

使用道具 举报

发表于 2006-5-9 12:00:33 | 显示全部楼层
受教了,谢谢zyx
回复 支持 反对

使用道具 举报

发表于 2006-5-9 12:07:30 | 显示全部楼层
在例子中,若是no-strict-aliasing,*p的值应和使用strict-aliasing时的*p值不同。问题是例子中float和unsigned int在物理表示上是不同的,用一指针处理与其不同类型的物理表示,如何处理编译器有自己规则,而编程中应尽量避免,否则就要清楚编译器的行为。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2006-5-9 18:48:36 | 显示全部楼层
多谢zyx的解释了。意思是说这个一个特性,不是bug。
那么,我那样的写法在C标准中,结果是不是属于没有定义的呢?
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表