内联 C 函数时,优化编译器取消引用指针的次数是否可以超过源代码中显式写入的次数?

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

考虑以下代码:

int y = 1;
int* p = &y;

inline int f(int x) {
  return x + x;
}

int g(void) {
  return f(*p);
}

在此代码中,有一个显式取消引用。

C 编译器允许编译/优化此代码,大致如下:

int g(void) {
  return *p + *p;
}

也就是说,在内联 f 时,编译器是否可以执行并使用对目标内存的两次单独访问,而不是实际写入的单个访问? C 规范中是否有特定部分允许或禁止这种行为? 请注意,在示例中,p 不是易失性的,“优化”代码至少在功能上是正确的。

(请注意,问题不是“编译器会这样做”或“编译器应该这样做”,而是,根据 C 规范,编译器可以这样做。假设寄存器溢出使第二次解引用更多高效,或类似的东西)。

参考 C99 规范,我看到了一些关于所需参数处理的可能提示。 我想知道“每个参数都分配了相应参数的值”(6.5.2.2)或“其[参数的]标识符是左值”(6.9.1)是否可能会阻止这种情况,但这种解释似乎与某些不兼容我见过的常见参数优化。

c gcc compilation compiler-construction c99
1个回答
0
投票

在内联 C 函数时,优化编译器取消引用指针的次数是否可以超过源代码中显式写入的次数?

是的,前提是它不是指向

volatile
类型的指针。

也就是说,在内联f的同时,编译器是否可以执行并使用两个 对目标内存的单独访问,而不是单个访问 访问实际写入的内容?

是的,尽管这很少会构成改进,所以我不希望任何编译器真正做到这一点。

C 中有特定部分吗? 允许或禁止这种行为的规范?

是的。

作为上下文,C17 5.1.2.3/1:

本国际标准中的语义描述描述了 抽象机的行为,其中优化问题是 无关紧要。

允许优化的主要规定是C17 5.1.2.3/6:

符合实施的最低要求是:

  • 对易失性对象的访问严格按照抽象机的规则进行评估。

  • 程序终止时,写入文件的所有数据应与程序按照指令执行的结果相同 就会产生抽象语义。

  • 交互设备的输入和输出动态应按照 7.21.3 的规定进行。这些要求的目的是 无缓冲或行缓冲输出尽快出现,以 确保提示消息实际上出现在程序之前 等待输入。

这是程序的可观察的行为

这些是最低要求意味着只要实现满足这些要求,它就可以通过它选择的任何方式来实现。 这就是实现优化的原因。

参考C99规范,

C99 早已过时,尽管该版本的结论是相同的。 从那时起,就有了 C11 和当前的规格 C17。 C2X 正处于批准的最后阶段。

我看到一些可能的提示 需要处理参数。我想知道是否“每个 参数被赋予相应参数的值” (6.5.2.2) 或“其[参数的]标识符是左值”(6.9.1) 可能会阻止这种情况发生,但这种解释似乎 与我的一些常见参数优化不兼容 见过。

这些细节描述了抽象机的行为。 只要它们产生正确的可观察行为,实现就不必遵守它们。

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