ARM程序调用标准是否允许与C标准相矛盾的易失性优化?
根据ARM体系结构的程序调用标准(§7.1.5): 编译器可能会忽略自动代码的易失性限定 除非函数调用,否则永远不会获取其地址的变量 setjmp() 这是否意味着在以下代码中:ARM程序调用标准是否允许与C标准相矛盾的易失性优化?,c,arm,language-lawyer,volatile,abi,C,Arm,Language Lawyer,Volatile,Abi,根据ARM体系结构的程序调用标准(§7.1.5): 编译器可能会忽略自动代码的易失性限定 除非函数调用,否则永远不会获取其地址的变量 setjmp() 这是否意味着在以下代码中: volatile int x = 8; if (x == 1) { printf("can be optimised away??"); } 整个if范围是否可以优化 这与标准正好相反,首先,易失性访问是可观察行为的一部分,必须按照抽象机器代码执行: §5.1.2.3: 一致性实施的最低要求是: 对易失性对象
volatile int x = 8;
if (x == 1)
{
printf("can be optimised away??");
}
整个if
范围是否可以优化
这与标准正好相反,首先,易失性访问是可观察行为的一部分,必须按照抽象机器代码执行:
§5.1.2.3:
一致性实施的最低要求是:
对易失性对象的访问严格按照
抽象机器的规则
以及§6.7.3:
具有volatile限定类型的对象可以通过以下方式进行修改
实施未知或有其他未知的副作用。
因此,任何涉及此类对象的表达式应
严格按照抽象机器的规则进行评估
有矛盾吗?如果是这样,PC与C标准冲突的合法性如何?因此我联系了ARM toolchain的支持小组,根据他们的说法,ARM PC标准是一个独立的标准,不受C标准的约束,因此编译器可以选择遵守其中一个或两个标准。用他们自己的话来说: 在某种程度上,这并不是一个真正的矛盾
- APCS允许编译器尊重或忽略本地易失性
- C标准要求编译器尊重本地易失性
总之,实现ARM PC的ARM体系结构的C兼容编译器永远不会执行此优化。为什么它与标准相矛盾?如果没有人通过指针观察到
x
,那么为什么它仍然需要被视为易失性
?C标准说“在序列点,易失性对象是稳定的,因为之前的访问已经完成,后续的访问尚未发生。”考虑到PCS设置的约束条件,这看起来是可以满足的。一致性实现的最低要求是:对易失性对象的访问严格按照抽象机器的规则进行评估…
它能比这更简单吗?另外,具有volatile限定类型的对象可能会以实现未知的方式进行修改,或者具有其他未知的副作用。因此,任何引用此类对象的表达式都应严格按照抽象机器的规则进行计算,
我在godbolt中找不到任何优化它的编译器。示例-,如何以编译器未知的方式修改x?
我认为关键在于“对易失性对象的访问严格按照抽象机器的规则进行评估”。ARM过程调用标准不适用于任何抽象机器,只要ARM抽象机器就可以优化代码,因为它知道x
在其抽象机器的世界中是无法访问的。那么,为易失性合格的自动对象提供了什么保证呢?ARM ABI什么都不承诺。如果编译器符合C标准,则必须遵循C标准保证。ABI允许忽略非C标准编译器可以执行的自动volatile限定符。