• [转] GCC __builtin_expect的作用


    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.   
    5. int test_likely(int x)  
    6. {  
    7.     if(LIKELY(x))  
    8.     {  
    9.         x = 5;  
    10.     }  
    11.     else  
    12.     {  
    13.         x = 6;  
    14.     }  
    15.   
    16.     return x;  
    17. }  
    18.   
    19. int test_unlikely(int x)  
    20. {  
    21.     if(UNLIKELY(x))  
    22.     {  
    23.         x = 5;  
    24.     }  
    25.     else  
    26.     {  
    27.         x = 6;  
    28.     }  
    29.   
    30.     return x;  
    31. }  


    运行如下命令:
            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.   
    22. <test_unlikely>:  
    23. 50    push     %ebp  
    24. 51    mov      %esp,%ebp  
    25. 53    mov      0x8(%ebp),%edx  
    26. 56    addl     $0x1,0x20  
    27. 5d    adcl     $0x0,0x24  
    28. 64    test     %edx,%edx  
    29. 66    jne      7d <test_unlikely+0x2d>//主要看这里。此处的效果是edx为零时,不需跳转。即x为假时不跳转。  
    30. 68    addl     $0x1,0x30  
    31. 6f    mov      $0x6,%eax  
    32. 74    adcl     $0x0,0x34  
    33. 7b    pop      %ebp  
    34. 7c    ret  
    35. 7d    addl     $0x1,0x28  
    36. 84    mov      $0x5,%eax  
    37. 89    adcl     $0x0,0x2c  
    38. 90    pop      %ebp  
    39. 91    ret  
    40. 92    lea      0x0(%esi,%eiz,1),%esi  
    41. 99    lea      0x0(%edi,%eiz,1),%edi   


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


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

  • 相关阅读:
    c# 类型转换符的重载
    C# 串口读写
    STM32 Keil C++编写单片机程序
    C# 静态构造函数的使用
    MvvMlight 学习之 SimpleIoc
    STM32 之 DMA
    STM32 之 SysTick
    突然发现用PHP做多条件模糊查询很简单
    discuz代码转为html代码
    Discuz!开发之HTML转Discuz代码(bbcode)函数html2bbcode()
  • 原文地址:https://www.cnblogs.com/qiangxia/p/4290583.html
Copyright © 2020-2023  润新知