首页 文章

什么时候可以完全优化易失性变量?

提问于
浏览
6

考虑以下代码示例:

int main(void)
{
  volatile int a;
  static volatile int b;

  volatile int c;
  c = 20;
  static volatile int d;
  d = 30;

  volatile int e = 40;
  static volatile int f = 50;

  return 0;
}

如果没有 volatile ,编译器可以优化掉所有变量,因为它们永远不会被读取 .

我认为 ab 可以被优化掉,因为它们完全未使用,请参阅unused volatile variable .

我认为 cd 无法被删除,因为它们被写入,并且必须实际发生对volatile变量的写入 . e 应相当于 c .

GCC不会优化 f ,但它也不会发出任何写入指令 . 在数据部分中设置50 . LLVM(clang)完全删除 f .

这些陈述是真的吗?

  • 如果永远不会访问volatile变量,则可以对其进行优化 .

  • 静态或全局变量的初始化不计为访问 .

2 回答

  • 4

    写入volatile变量(甚至是自动变量)算作可观察行为 .

    C11(N1570)5.1.2.3/6:

    对符合实现的最低要求是: - 严格根据抽象机器的规则评估对易失性对象的访问 . - 在程序终止时,写入文件的所有数据应与根据抽象语义产生的程序执行结果相同 . - 交互设备的输入和输出动态应按照7.21.3的规定进行 . 这些要求的目的是尽快出现无缓冲或行缓冲输出,以确保在程序等待输入之前实际出现提示消息 . 这是该程序的可观察行为 .

    问题是:初始化( ef )算作"access"吗?正如Sander de Dycker所指出的那样,6.7.3说:

    什么构成对具有volatile限定类型的对象的访问是实现定义的 .

    这意味着由编译器决定是否可以优化 ef - 但这必须记录在案!

  • 8

    严格地说,根据C标准,无法优化访问(读取或写入)的任何易失性变量 . 标准说,访问易失性对象可能具有未知的副作用,并且对volatile对象的访问必须遵循C抽象机器的规则(其中所有表达式按其语义指定进行评估) .

    从强大的标准(强调我的):

    (C11,6.7.3p7)“具有挥发性限定类型的对象可能以实现未知的方式进行修改或具有其他未知的副作用 . 因此,任何涉及此类对象的表达应严格按照规则进行评估 . 摘要机器,如5.1.2.3所述 . “

    接下来,即使简单的变量初始化也应被视为访问 . 请记住 static 说明符也会导致对象被初始化(到 0 )并因此被访问 .

    现在已知编译器对volatile限定符的行为有所不同,我猜他们中的很多只会优化示例程序的大多数volatile对象,除了那些具有显式赋值( = )的对象 .

相关问题