http://blog.csdn.net/shuimuniao/article/details/8017971

将流水线引入cpu,可以提高cpu的效率。更简单的说,让cpu可以预先取出下一条指令,可以提供cpu的效率。如下图所示:
+--------------------------------
|取指令 | 执行指令 | 输出结果
+--------------------------------
|             | 取指令     | 执行
+--------------------------------
可见,cpu流水钱可以减少cpu等待取指令的耗时,从而提高cpu的效率。
       
如果存在跳转指令,那么预先取出的指令就无用了。cpu在执行当前指令时,从内存中取出了当前指令的下一条指令。执行完当前指令后,cpu发现不是要执行
下一条指令,而是执行offset偏移处的指令。cpu只能重新从内存中取出offset偏移处的指令。因此,跳转指令会降低流水线的效率,也就是降低
cpu的效率。
        综上,在写程序时应该尽量避免跳转语句。那么如何避免跳转语句呢?答案就是使用__builtin_expect。
       
这个指令是gcc引入的,作用是"允许程序员将最有可能执行的分支告诉编译器"。这个指令的写法为:__builtin_expect(EXP,
N)。意思是:EXP==N的概率很大。一般的使用方法是将__builtin_expect指令封装为LIKELY和UNLIKELY宏。这两个宏的写
法如下。
        #define LIKELY(x) __builtin_expect(!!(x), 1) //x很可能为真
        #define UNLIKELY(x) __builtin_expect(!!(x), 0) //x很可能为假

如下是一个实际的例子。

  1. //test_builtin_expect.c
  2. #define LIKELY(x) __builtin_expect(!!(x), 1)
  3. #define UNLIKELY(x) __builtin_expect(!!(x), 0)
  4. int test_likely(int x)
  5. {
  6. if(LIKELY(x))
  7. {
  8. x = 5;
  9. }
  10. else
  11. {
  12. x = 6;
  13. }
  14. return x;
  15. }
  16. int test_unlikely(int x)
  17. {
  18. if(UNLIKELY(x))
  19. {
  20. x = 5;
  21. }
  22. else
  23. {
  24. x = 6;
  25. }
  26. return x;
  27. }

运行如下命令:
        gcc -fprofile-arcs -O2 -c test_builtin_expect.c
        objdump -d test_builtin_expect.o
输出的汇编码为:

  1. <test_likely>:
  2. 00    push     %ebp
  3. 01    mov      %esp,%ebp
  4. 03    mov      0x8(%ebp),%eax
  5. 06    addl     $0x1,0x38
  6. 0d    adcl     $0x0,0x3c
  7. 14    test     %eax,%eax
  8. 16    jz       2d <test_likely+0x2d>//主要看这里。此处的效果是eax不为零时,不需要跳转。即x为真是不跳转。
  9. 18    addl     $0x1,0x40
  10. 1f    mov      $0x5,%eax
  11. 24    adcl     $0x0,0x44
  12. 2b    pop      %ebp
  13. 2c    ret
  14. 2d    addl     $0x1,0x48
  15. 34    mov      $0x6,%eax
  16. 39    adcl     $0x0,0x4c
  17. 40    pop      %ebp
  18. 41    ret
  19. 42    lea      0x0(%esi,%eiz,1),%esi
  20. 49    lea      0x0(%edi,%eiz,1),%edi
  21. <test_unlikely>:
  22. 50    push     %ebp
  23. 51    mov      %esp,%ebp
  24. 53    mov      0x8(%ebp),%edx
  25. 56    addl     $0x1,0x20
  26. 5d    adcl     $0x0,0x24
  27. 64    test     %edx,%edx
  28. 66    jne      7d <test_unlikely+0x2d>//主要看这里。此处的效果是edx为零时,不需跳转。即x为假时不跳转。
  29. 68    addl     $0x1,0x30
  30. 6f    mov      $0x6,%eax
  31. 74    adcl     $0x0,0x34
  32. 7b    pop      %ebp
  33. 7c    ret
  34. 7d    addl     $0x1,0x28
  35. 84    mov      $0x5,%eax
  36. 89    adcl     $0x0,0x2c
  37. 90    pop      %ebp
  38. 91    ret
  39. 92    lea      0x0(%esi,%eiz,1),%esi
  40. 99    lea      0x0(%edi,%eiz,1),%edi

可见,编译器利用程序员作出的判断,生成了高效的汇编码。即,跳转语句不生效的概率很大。

参考资料:http://hi.baidu.com/uu_dou/item/e9f6f41d570d817b7a5f25c7

[转] GCC __builtin_expect的作用的更多相关文章

  1. GCC __builtin_expect的作用

    https://blog.csdn.net/shuimuniao/article/details/8017971 #define LIKELY(x) __builtin_expect(!!(x), 1 ...

  2. gcc -ldl 选项作用

    如果你的程序中使用dlopen.dlsym.dlclose.dlerror 显示加载动态库,需要设置链接选项 -ldl 加载动态链接库,首先为共享库分配物理内存,然后在进程对应的页表项中建立虚拟页和物 ...

  3. Clang比 gcc/g++更人性化代码出错提示的C/C++编译器

    编译器方面的几个命令 gcc/g++ 一. 常用编译命令选项 常用用法 gcc -Wall test.c -o test gcc编译过程 .c ->(-E)-> .i[中间文件] -> ...

  4. linux下gcc编译多个源文件、gdb的使用方法

    一. gcc常用编译命令选项 假设源程序文件名为test.c. 1. 无选项编译链接 用法:#gcc test.c 作用:将test.c预处理.汇编.编译并链接形成可执行文件.这里未指定输出文件,默认 ...

  5. gcc编译代码报错及编译方式

    一.error: 'for' loop initial declarations are only allowed in C99 mode 前段时间写了一个小C程序,放在linux下用gcc编译出错, ...

  6. GCC 编译命令

    今天突然被同事问道一个GCC编译命令为的问题,感觉对相应内容生疏了,赶紧整理下相关内容,梳理下相关知识. GCC命令提供了非常多的命令选项,但并不是所有都要熟悉,初学时掌握几个常用的就可以了,到后面再 ...

  7. Ubuntu下GCC的安装以及版本控制

    在Ubuntu下安装GCC和其他一些Linux系统有点不一样. 方法一: 该方法超简单:sudo apt-get  build-depgcc 就上面这条命令就可以搞定 方法二:sudo apt-get ...

  8. gcc总结【基本用法】【选项】【动静态库】(转)

    1.////////////////////////////////////////////////////////////////////////////////////////////////// ...

  9. gcc常用命令集

    引用:http://developer.51cto.com/art/200609/32317_1.htm 对于GUN编译器来说,程序的编译要经历预处理.编译.汇编.连接四个阶段 假设源程序文件名为te ...

随机推荐

  1. Java环境配置出现的问题及解决办法

    我使用的安装文件,从博客园一个童鞋那里找到的,连接是http://www.cnblogs.com/SelectError/p/3205582.html#commentform 开发基础环境,版本为Ja ...

  2. thinkphp 中js 实现刷新

    <input name="Button5" value="返回" id="Button5" style="width:56p ...

  3. jQuery 树形结构

    强大的jquery.ztree树形菜单插件支持多种树形菜单导航 http://www.17sucai.com/pins/2259.html 演示: http://www.17sucai.com/pin ...

  4. yum版本新增包的一般步骤

    在Jekins的自动构建环境中,有时会有在构建出的ISO中添加新应用app需求,对于采用rpm包源代码管理方式的构建环境来说,基本步骤如下: 1.下载app的src.rpm包 2.解压src.rpm包 ...

  5. 《C和指针》章节后编程练习解答参考——6.1

    <C和指针>——6.1 6.1 题目: 编写一个函数,在一个字符串中进行搜索,查找另一子字符串中出现的字符. 函数原型如下: char *find_char(char const *sou ...

  6. 01:A+B问题

    总时间限制:  1000ms 内存限制:  65536kB 描述 在大部分的在线题库中,都会将A+B问题作为第一题,以帮助新手熟悉平台的使用方法. A+B问题的题目描述如下:给定两个整数A和B,输出A ...

  7. 优秀开源项目的svn地址

    很多优秀的开源项目已经提供SVN源码签出了,无论是解疑还是学习,都是一大幸福之事啊! Apache的SVN库,强烈推荐! http://svn.apache.org/repos/asf/ 里面不但有S ...

  8. BZOJ 1043 下落的圆盘

    Description 有n个圆盘从天而降,后面落下的可以盖住前面的.求最后形成的封闭区域的周长.看下面这副图, 所有的红色线条的总长度即为所求.  Input n ri xi y1 ... rn x ...

  9. DOMContentLoaded vs onload

    http://ie.microsoft.com/testdrive/HTML5/DOMContentLoaded/Default.html The DOMContentLoaded event fir ...

  10. 宏中"#"和"##"的用法

    一.一般用法 我们使用#把宏参数变为一个字符串,用##把两个宏参数贴合在一起. 用法: #include<cstdio> #include<climits> using nam ...