关键字restrict

要理解 restrict,先要知道什么是 Pointer aliasing。
Pointer aliasing 是指两个或以上的指针指向同一数据,例如

  int i = 0;
  int *a = &i;
  int *b = &i; 

这样会有什么问题呢?
如果编译器采用最安全的假设,即不理会两个指针会否指向同一数据,那么通过指针读写数据是很直观的。
然而,这种假设会令编译器无法优化,例如:

  int foo(int *a, int *b) 
  {     
  *a = 5;    
   *b = 6;     
   return *a + *b; 
   // 不一定是 11!
  }

如果 a 和 b 都指向同一数据,*b = 6 会导致 *a = 6,返回12。所以编译器在做 *a + *b 的时候,需要重新读取 *a 指向的数据:

   foo:     movl    $5, (%rdi)    # 存储 5 至 *a   
     movl    $6, (%rsi)    # 存储 6 至 *b     
     movl    (%rdi), %eax  # 重新读取 *a (因为有可能被上一行指令造成改变)     
     addl    $6, %eax      # 加上 6    
     ret 

如果我们确保两个指针不指向同一数据,就可以用 restrict 修饰指针类型:

  int rfoo(int *restrict a, int *restrict b)
   {    
    *a = 5;     
    *b = 6;    
     return *a + *b;
   }  

编译器就可以根据这个信息,做出优化:

   rfoo:    
    movl      $11, %eax   # 在编译期已计算出 11     
    movl      $5, (%rdi)  # 存储 5 至 *a     
    movl      $6, (%rsi)  # 存储 6 至 *b    
    ret  

但如果用了 restrict 去修饰两个指针,而它们在作用域内又指向同一地址,那么是未定义行为。
总之,restrict 是为了告诉编译器额外信息(两个指针不指向同一数据),从而生成更优化的机器码。注意,编译器是无法自行在编译期检测两个指针是否 alias。如使用 restrict,程序员也要遵守契约才能得出正确的代码(指针不能指向相同数据)。 以个人经验而言,编写代码时通常会忽略 pointer aliasing 的问题。更常见是在性能剖测时,通过反编译看到很多冗余的读取指令,才会想到加入 restrict 关键字来提升性能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值