c - __restrict vis-a-vis 流行编译器的函数优化行为

标签 c gcc visual-c++ clang restrict

考虑以下函数:

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

我们是否需要从 x 中读取两次,因为调用了 g()?或者 __restriction 是否足以保证 g() 的调用不会访问/不会更改地址 x 处的值?

this link我们看到最流行的编译器对此有看法(GodBolt;语言标准 C99,平台 AMD64):

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

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

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

最佳答案

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

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

1 Let D be a declaration of an ordinary identifier that provides a means of designating an object P as a restrict-qualified pointer to type T.

2 If D appears inside a block and does not have storage class extern, let B denote the block. If D appears in the list of parameter declarations of a function definition, let B denote the associated block. Otherwise, let B denote the block of main (or the block of whatever function is called at program startup in a freestanding environment).

3 In what follows, a pointer expression E is said to be based on object P if (at some sequence point in the execution of B prior to the evaluation of E) modifying P to point to a copy of the array object into which it formerly pointed would change the value of E.137) Note that ''based'' is defined only for expressions with pointer types.

4 During each execution of B, let L be any lvalue that has &L based on P. If L is used to access the value of the object X that it designates, and X is also modified (by any means), then the following requirements apply: T shall not be const-qualified. Every other lvalue used to access the value of X shall also have its address based on P. Every access that modifies X shall be considered also to modify P, for the purposes of this subclause. If P is assigned the value of a pointer expression E that is based on another restricted pointer object P2, associated with block B2, then either the execution of B2 shall begin before the execution of B, or the execution of B2 shall end prior to the assignment. If these requirements are not met, then the behavior is undefined.

5 Here an execution of B means that portion of the execution of the program that would correspond to the lifetime of an object with scalar type and automatic storage duration associated with B.

按照我的理解,g() 的执行属于 bar block 的执行,所以 g() 不允许修改 *x 并且 clang 优化第二个负载的权利(IOW,如果 *x 指的是一个非常量全局变量,g() 不能修改那个全局变量。

关于c - __restrict vis-a-vis 流行编译器的函数优化行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54847052/

相关文章:

c - 从 C 中的函数返回一个 const 字符串

gcc - 使用gnueabihf为ARMv6构建

c++ - 为什么比较 double 和 float 会导致意想不到的结果?

c++ - 为什么在启用浮点异常后我得到多个陷阱错误

c - 在 C 中撤消,复制结构

Python3和C不同的数学除法结果

c - 为什么全局变量总是初始化为 '0' ,而不是局部变量?

c - 将外部库的头文件包含在另一个头文件中

c++ - usr/bin/ld : cannot find -lncurses

c++ - Microsoft Visual C++ 的两阶段模板实例化的 "broken"到底是什么?