GCC之编译暗示语句
GCC暗示语句,不生成任何代码,仅仅给GCC编译器提供编译上的功能需求提示。
barrier
#define barrier() __asm__ __volatile__("":::"memory")
barrier()告诉GCC编译器,在这之后使用的内存变量全部要重新从内存单元获取,而不能从临时寄存器获取。
一般说来,GCC编译后的函数汇编代码实现是:某个内存变量首先被读取到寄存器中,然后对该寄存器进行访问从而实现对该变量的读取和修改操作,直到函数退出前需要将该变量保存到内存单元中。
当程序插入barrier()语句:
- 那么在该语句之前,某个内存变量数据在临时寄存器中发生改变,就会将其写会到内存单元,无论barrier()之后是否还会被访问,如果该内存变量在临时寄存器中并没有被修改,就不需要写回内存单元。
- 在该barrier()之后语句之后,任何内存变量数据都要重新从内存单元获取。
likely和unlikely
# define likely(x) __builtin_expect(!!(x), 1)
# define unlikely(x) __builtin_expect(!!(x), 0)
上面两个宏likely和unlikely是根据GCC内建函数__builtin_expect定义的。
主要用于条件判断语句,程序员本人对条件成立的概率有一个初步判断,如果条件成立的概率相当大或者相当小,最好用likely或unlikely来告诉GCC;GCC就会对条件跳转过程进行优化。
if(likely(condition)) { ... }
if(unlikely(condition)) { ... }
GCC优化的基本策略:
- 大概率运行分支代码尽可能不通过跳转就可以运行;
- 大概率运行分支代码如果可能实现函数返回,就直接实现函数返回;
注意:很多时候,我们把likely/unlikely和处理器分支预测混淆。一个是编译器层面,一个是处理器层面的。