相对于流行编译器的函数优化行为__restrict

时间:2019-02-23 22:51:22

标签: c gcc visual-c++ clang restrict

考虑以下功能:

int bar(const int* __restrict x, void g())
{
    int result = *x;
    g();
    result += *x;
    return result;
}

由于调用了x,我们是否需要从g()读取两次?还是__restrict足以保证对g()的调用不会访问/不会更改地址x上的值?

this link,我们看到最流行的编译器不得不对此发表评论(GodBolt;语言标准C99,平台AMD64):

  • clang 7.0:遵守限制。
  • GCC 8.3:无限制。
  • MSVC 19.16:无限制。

clang是否正确地优化了秒读,不是吗?我在这里同时要求C和C ++,因为行为是相同的(感谢@PSkocik)。

相关信息和一些注意事项:

1 个答案:

答案 0 :(得分:0)

我认为这实际上是一个C问题,因为C实际上是带有restrict并附带正式规范的语言。

控制restrict使用的C标准部分为6.7.3.1

  

1设D为提供一个   将对象P指定为限制限定的指针的方法   输入T。

     

2如果D出现在块内并且没有存储类extern,   令B代表方块。如果D出现在参数列表中   函数定义的声明,让B表示关联的   块。否则,让B代表main的区块(或   独立运行程序时调用的任何功能   环境)。

     

3接下来,将指针表达式E称为基于   对象P如果(在执行B之前的某个顺序点   E)的评估,修改P以指向数组对象的副本   它先前指向的位置会更改E.137的值)   只能为具有指针类型的表达式定义“基于”。

     

4在每次执行B期间,令L为具有&L的任何左值。   P。如果使用L来访问对象X的值,则表示它   指定,并且X也被修改(通过任何方式),则以下内容   适用要求:T不得为const限定的。每隔一个左值   用于访问X值的地址也应基于P。   每次修改X的访问也应被视为修改P,因为   本节的目的。如果为P分配了a的值   基于另一个受限指针的指针表达式E   与块B2关联的对象P2,然后执行B2   应在执行B之前开始,或者B2的执行应开始   在分配之前结束。如果不满足这些要求,那么   行为是不确定的。

     

5此处执行B表示执行B的那一部分   与标量对象的生存期相对应的程序   B的类型和自动存储期限。

按照我的理解,g()的执行属于bar块的执行,因此不允许g()修改*x和{{ 1}} 来优化第二个负载的权利(IOW,如果clang引用非常量全局变量,*x不得修改该全局变量。)