苏黎 搜索开发工程师

gcc 特性学习

2018-03-31
suli
   

gcc优化特性学习

1. C类型发现

typeof字段可以识别变量类型,实现泛型,下面是一个泛型的例子。

#define min(x, y) ({                \
    typeof(x) _min1 = (x);          \
    typeof(y) _min2 = (y);          \
    (void) (&_min1 == &_min2);      \
    _min1 < _min2 ? _min1 : _min2; })

2. 范围扩展

gcc可以使用范围,比如在数组初始化的时候会出现一些简单的递增的数据,可以直接使用…来使用gcc推测功能。在switch语句中case中如果范围。

static int sd_major(int major_idx)
{
    switch (major_idx) {
    case 0:
        return SCSI_DISK0_MAJOR;
    case 1 ... 7:
        return SCSI_DISK1_MAJOR + major_idx - 1;
    case 8 ... 15:
        return SCSI_DISK8_MAJOR + major_idx - 8;
    default:
        BUG();
        return 0;   /* shut up gcc */
    }
}

数组的范围拓展

int abc[] = {[0 ... 9] = 0};
int widths[] = { [0 ... 9] = 1, [10 ... 99] = 2, [100] = 3 };

3. 判断调用地址

gcc允许调用到函数在堆栈中的返回地址,gcc提供一下函数用来返回函数地址

void * __builtin_return_address( unsigned int level );

level如果是0的话就返回当前函数地址,1的话就返回上层栈帧的地址。

4. 常量检测

gcc提供了用来检测数据是否是常量

int __builtin_constant_p( exp )

5. 函数属性

gcc提供了很多函数的优化。

# define __inline__     __inline__      __attribute__((always_inline))
# define __deprecated           __attribute__((deprecated))
# define __attribute_used__     __attribute__((__used__))
# define __attribute_const__     __attribute__((__const__))
# define __must_check            __attribute__((warn_unused_result))

  1. always_inline gcc内联处理指定的函数,无论是否启用了优化。
  2. deprecated 指出函数已经被废弃,不应该再使用。如果试图使用已经废弃的函数,就会收到警告。还可以对类型和变量应用这个属性,促使开发人员尽可能少使用它们。
  3. __used__ 告诉编译器无论 GCC 是否发现这个函数的调用实例,都要使用这个函数。这对于从汇编代码中调用 C 函数有帮助。
  4. __const__ 告诉编译器某个函数是无状态的(也就是说,它使用传递给它的参数生成要返回的结果)。
  5. warn_unused_result 让编译器检查所有调用者是否都检查函数的结果。这确保调用者适当地检验函数结果,从而能够适当地处理错误。

实例代码

int __deprecated __check_region(struct resource 
    *parent, unsigned long start, unsigned long n)
 
static enum unw_register_index __attribute_const__ 
    decode_abreg(unsigned char abreg, int memory)

6. 分支预测提示

gcc中__builtin_expect中使用了两个宏likely 和 unlikely。

#define likely(x)   __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)

7. 预抓取

gcc提供了将数据缓存到一级或者二级缓存,gcc提供__builtin_prefetch函数来:

  • 数据的地址
  • rw 参数,使用它指明预抓取数据是为了执行读操作,还是执行写操作
  • locality 参数,使用它指定在使用数据之后数据应该留在缓存中,还是应该清除
void __builtin_prefetch( const void *addr, int rw, int locality );

预抓取函数

#ifndef ARCH_HAS_PREFETCH
#define prefetch(x) __builtin_prefetch(x)
#endif
 
static inline void prefetch_range(void *addr, size_t len)
{
#ifdef ARCH_HAS_PREFETCH
    char *cp;
    char *end = addr + len;
 
    for (cp = addr; cp < end; cp += PREFETCH_STRIDE)
        prefetch(cp);
#endif
}

8. 变量属性

gcc提供对变量属性的指定,其中一个aligned属性就很重要,专门用来对齐字节。

char __nosavedata swsusp_pg_dir[PAGE_SIZE]
    __attribute__ ((aligned (PAGE_SIZE)));

packed 属性是打包一个结构尽可能减少内存

static struct swsusp_header {
        char reserved[PAGE_SIZE - 20 - sizeof(swp_entry_t)];
        swp_entry_t image;
        char    orig_sig[10];
        char    sig[10];
} __attribute__((packed, aligned(PAGE_SIZE))) swsusp_header;

总结

本文主要总结几个常见的gcc特性,用来优化编译结果。


Similar Posts

Comments