微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > linux内核中的likely和unlikely

linux内核中的likely和unlikely

时间:11-22 来源:互联网 点击:

  1. ,r3,r1
  2. 88f4:e0a44002adcr4,r4,r2
  3. 88f8:e88c0018stmiaip,{r3,r4}
  4. 88fc:e8bd8010ldmiasp!,{r4,pc}
  5. 8900:e89e0006ldmialr,{r1,r2}
  6. 8904:e3a04000movr4,#0;0x0
  7. 8908:e3a03001movr3,#1;0x1
  8. 890c:e0911003addsr1,r1,r3
  9. 8910:e0a22004adcr2,r2,r4
  10. 8914:e3a00006movr0,#6;0x6
  11. 8918:e88e0006stmialr,{r1,r2}
  12. 891c:e8bd8010ldmiasp!,{r4,pc}
  13. 8920:000121e0andeqr2,r1,r0,ror#3
  14. 8924:000121e8andeqr2,r1,r8,ror#3
  15. 00008928:
  16. 8928:e3500000cmpr0,#0;0x0
  17. 892c:e92d4010stmdbsp!,{r4,lr}
  18. 8930:e59fc044ldrip,[pc,#68];897c<.text+0x1a4>
  19. 8934:e59fe044ldrlr,[pc,#68];8980<.text+0x1a8>
  20. 8938:e3a00005movr0,#5;0x5
  21. 893c:1a000007bne8960//前面通过cmp将r0和0进行比较,因为x=0的概率很大,优先执行等于0的分支
  22. 8940:e89c0018ldmiaip,{r3,r4}
  23. 8944:e3a02000movr2,#0;0x0
  24. 8948:e3a01001movr1,#1;0x1
  25. 894c:e0933001addsr3,r3,r1
  26. 8950:e0a44002adcr4,r4,r2
  27. 8954:e3a00006movr0,#6;0x6
  28. 8958:e88c0018stmiaip,{r3,r4}
  29. 895c:e8bd8010ldmiasp!,{r4,pc}
  30. 8960:e89e0006ldmialr,{r1,r2}
  31. 8964:e3a04000movr4,#0;0x0
  32. 8968:e3a03001movr3,#1;0x1
  33. 896c:e0911003addsr1,r1,r3
  34. 8970:e0a22004adcr2,r2,r4
  35. 8974:e88e0006stmialr,{r1,r2}
  36. 8978:e8bd8010ldmiasp!,{r4,pc}
  37. 897c:000121f8streqdr2,[r1],-r8
  38. 8980:000121f0streqdr2,[r1],-r0

如果我们将代码修改一下,不用这两个宏结果会怎样呢?

[plain]view plaincopyprint?

  1. //test_builtin_expect.c
  2. inttest_likely(intx)
  3. {
  4. if(x)
  5. x=5;
  6. else
  7. x=6;
  8. returnx;
  9. }
  10. inttest_unlikely(intx)
  11. {
  12. if(x)
  13. x=5;
  14. else
  15. x=6;
  16. returnx;
  17. }

反汇编代码如下:

[plain]view plaincopyprint?

  1. 00008460:
  2. 8460:e3500000cmpr0,#0;0x0
  3. 8464:03a00006moveqr0,#6;0x6
  4. 8468:13a00005movner0,#5;0x5
  5. 846c:e1a0f00emovpc,lr
  6. 00008470:
  7. 8470:e3500000cmpr0,#0;0x0
  8. 8474:03a00006moveqr0,#6;0x6
  9. 8478:13a00005movner0,#5;0x5
  10. 847c:e1a0f00emovpc,lr

如上述例子分析所示,两个函数编译生成的汇编语句所使用到的跳转指令不一样,仔细分析下会发现__builtin_expect实际上是为了满足在大多数情况不执行跳转指令,__builtin_expect仅仅是告诉编译器优化,并没有改变其对真值的判断。宏likely和宏unlikely唯一的作用就是选择”将if分支还是else分支放在跳转指令之后,从而优化程序的执行效率”。 因为likely(EXP)代表条件表达式EXP很可能成立,而unlikely(EXP)代表条件表达式EXP很可能不成立,当程序员清楚EXP表达式 多数情况成立(不成立)时,就可使用likely(unlikely),使if分支(else分支)紧跟跳转指令其后,从而在大多数情况下不用执行跳转指令,避开跳转指令所带来的开销,从而达到优化的目的。

还有一点需要注意的是,在生成汇编时用的是arm-linux-gcc -fprofile-arcs -O2 -c test_builtin_expect.c,而不是arm-linux-gcc-O2 -c test_builtin_expect.c。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top