__builtin_expect, __builtin_unreachable和__builtin_prefetch

__builtin_expect

该指令是gcc引入的,就是允许代码编写者把最有可能执行的分支告诉编译器,标准写法是__bultin_expect(exp, n),意思是exp==n的概率很大,这样编译器可以对代码进行优化,减少指令跳转带来的性能下降,对应通常有两个宏定义:

#define likely(x) __builtin_expect(!!(x), 1) // x为真的可能性更大
#define unlikely(x) __builtin_expect(!!(x), 0) // x为假的可能性更大

需要注意一点,!!(x)似乎是没有意义的,但其实是有意义的,首先__buildin_expect(x, a)意味着很可能x==a,然而x==2时,x也是true,但x!=1,所以!!(x)可以保证x==true时,!!(x)==1。

__builtin_unreachable

__builtin_unreachable函数是用来通知编译器这一行在CPU运行时永远不会到达,这样可以提前防止编译中的很多麻烦。我们来看一个例子:

# define ATHCONTAINERS_ASSUME(x) do { if (!(x)) __builtin_unreachable(); } while(0)


inline
void*
AuxVectorData::Cache::getDataArray (SG::auxid_t auxid,
                                    AuxVectorData& parent)
{
  // This function is important for performance.
  // Be careful when changing it.

  void* ptr = cachePtr (auxid);
  if (ATHCONTAINERS_UNLIKELY (ptr == 0)) {
    // We don't have the variable cached.
    // Call the out-of-line routine to get it cached.
    ptr = parent.getDataOol (auxid, false);

    // These inform the compiler of what the previous call did.
    // They tell the optimizer that it can now assume that this cache
    // entry is valid.
    ATHCONTAINERS_ASSUME (ptr != 0); 
    ATHCONTAINERS_ASSUME (cachePtr (auxid) != 0); 
    ATHCONTAINERS_ASSUME (cachePtr (auxid) == ptr);
  }
  return ptr;
}

宏定义ATHCONTAINERS_ASSUME告诉编译器参数x不能为false。这使编译器不必生成任何代码来适应x为假的可能。例如,当编译器看到ATHCONTAINERS_ASSUME (ptr != 0)时,它可以假设ptr不为空,并且任何与该假设相矛盾的代码都可以被优化掉,因为它将是未定义的行为。由于getDataArray()是内联的,编译器可以在每个调用点知道返回的指针永远不会为空。

__builtin_prefetch

用于预取数据到CPU的缓存中,以便提高程序的执行效率:

__builtin_prefetch (const void *addr, int rw, int locality)

addr是一个指向要预取数据的地址的指针,rw是一个表示读写属性的整数,locality是一个表示预取数据的局部性的整数。__builtin_prefetch的返回值是void类型,它只是告诉CPU预取数据到缓存中,而不会等待数据被加载到缓存中。

你可能感兴趣的:(C++编程,c++)