限制限定符可以用来提示编译器外部函数不会修改你的内存吗?

问题描述 投票:0回答:1

作为我之前的问题的后续,请考虑以下代码:

int f(int *p);

static inline int g0(int *p) {
  *p=0;
  f(NULL); // might modify *p
  return *p==0;
}
int caller0(int *q) { return g0(q); }

在上面,调用

f
后,编译器必须获取
*p
并执行与 0 的比较,因为
p
可能会别名内存也可用于
f
。然而:

static inline int g1(int *restrict p) {
  *p=0;
  f(NULL); // cannot modify *p
  return *p==0;
}
int caller1(int *q) { return g1(q); }

因为

restrict
,编译器可以推断出
f
修改
*p
是非法的,因此它可以只返回1,从而优化了获取和比较。 Clang 17 做了这个优化。然而:

int caller2(int *q) {
  { int *restrict p=q;
    *p=0;
    f(NULL);
    return *p==0;
  }
}

这个

caller2
在我看来相当于
caller1
,只是手动内联。同一个 Clang 编译器没有对此进行优化(它发出获取和比较)。

第一个问题:编译器允许优化吗

caller2

进一步:

int caller3(int *q) {
  ... // many lines of code
  { int *restrict p=q;
    *p=0;
    ... // do something useful
    f(q);
    if (*p==0) { ... } // do something useful
  }
  ... // many lines of code
}

现在这是我真正关心的部分。如果允许编译器优化

caller2
,那么是否允许优化
caller3

根据我对标准的阅读,

q
在这里并不是“基于”
p
,并且
*p
是通过限制限定指针修改的,因此编译器可以假设
f
不会修改
*p 
(进一步;
f
甚至不允许读取
*q
,因此编译器甚至可以在调用
*p=0
之后对赋值
f
重新排序(尽管
f
可以合法地读/写
q[1]
))。

这是正确的吗?如果是,则表明即使在函数体内也可以创造性地使用

restrict
来向编译器提供有关别名的各种提示。

c language-lawyer compiler-optimization restrict-qualifier
1个回答
0
投票

因为

restrict
,编译器可以推断出
f
修改
*p
是非法的,因此它可以只返回1,从而优化了获取和比较。

“非法”不是正确的术语。该规范并不禁止此类行为。如果

f
确实修改了
*p
,它只会放弃这种情况。在这种情况下,对
g0()
的特定调用以及程序的整个执行都具有未定义的行为。因此(现代的解释是)编译器可以生成一个程序,其行为就好像
f
没有修改
*p
一样,无论实际情况如何。

编译器允许优化caller2吗?

如果我们接受编译器可以按照描述优化

caller1()
,那么是的,可以对
caller2()
执行类似的优化。但它没有义务这样做。

如果允许编译器优化

caller2
,是否允许优化
caller3

是的,如果我们接受允许对

caller2
进行优化的论点,那么同样的论点允许对
caller3
进行类似的优化。

正如您所观察到的,

q
并不是“基于”
p
。由于
p
没有链接,并且其地址和基于
p
的值的另一个对象的地址都不会被获取,因此编译器可以得出结论,
f()
无法访问基于
restrict
限定的任何指针
p
,因此,如果
f(q)
的评估修改了
*p
,则程序的行为是未定义的。

如果是,则表明

restrict
甚至可以在函数内部创造性地使用,以向编译器提供有关别名的各种提示。

我想你可以这样描述它。我更倾向于说“

restrict
可以在函数内部使用来邀请编译器为它们发出损坏的代码”。

在示例中,如果您想让编译器基于

f
不会修改其参数指向的数据的假设进行优化,那么将其参数声明为指向
const 的指针会更干净、更清晰
数据:

int f(const int *p);

如果你做不到这一点,那么你想要允许的非混叠假设可能不安全。

总的来说,

restrict
对于自动变量的使用并没有真正的意义。编译器不需要您的帮助来查看涉及这些的别名机会,并且建议它根据这些更有限的视图做出决策是自找麻烦。

© www.soinside.com 2019 - 2024. All rights reserved.