jle*_*ahy 62 c gcc inline-assembly
在实现无锁数据结构和时序代码时,通常需要抑制编译器的优化.通常人们在clobber列表中使用asm volatilewith memory,但你有时会看到asm volatile或只是一个简单的asm破坏性记忆.
这些不同的陈述对代码生成有什么影响(特别是在GCC中,因为它不太可能是可移植的)?
仅供参考,这些是有趣的变化:
asm (""); // presumably this has no effect on code generation
asm volatile ("");
asm ("" ::: "memory");
asm volatile ("" ::: "memory");
Run Code Online (Sandbox Code Playgroud)
Mat*_*ery 57
您可以
asm通过在volatile后面写入关键字来阻止删除指令asm.[...]volatile关键字表示该指令具有重要的副作用.volatile如果可以访问,GCC将不会删除asm.
和
asm没有任何输出操作数的指令将被视为与易失性asm指令相同.
您的示例都没有指定输出操作数,因此asm和asm volatile表单的行为相同:它们在代码中创建一个可能不会被删除的点(除非它被证明是无法访问的).
这与什么都不做完全不一样.请参阅此问题以获取asm更改代码生成的虚拟示例- 在该示例中,围绕循环1000次的代码被矢量化为代码,该代码一次计算循环的16次迭代; 但是asm循环内部的存在会抑制优化(asm必须达到1000次).
所述"memory"撞使得GCC假定任何存储器可以被任意地读取或写入asm块,所以会防止编译器通过它重新排序加载或存储:
这将导致GCC不保持跨汇编指令缓存在寄存器中的内存值,而不是优化存储器或加载到该内存.
(但这并不妨碍CPU相对于另一个CPU重新排序加载和存储;您需要真正的内存屏障指令.)
asm ("") 什么都不做(或者至少,它不应该做任何事情.
asm volatile ("") 也什么也没做.
asm ("" ::: "memory") 是一个简单的编译器围栏.
asm volatile ("" ::: "memory")AFAIK与之前相同.该volatile关键字告诉编译器不允许移动此程序集块.例如,如果编译器确定每次调用中的输入值相同,则可以将其从循环中提升.我不确定在什么条件下编译器会决定它对程序集的了解程度足以尝试优化其位置,但volatile关键字完全抑制了这一点.也就是说,如果编译器试图移动asm没有声明输入或输出的语句,我会感到非常惊讶.
顺便提一下,volatile如果它确定输出值未被使用,也会阻止编译器删除表达式.这只有在有输出值时才会发生,所以它不适用于asm ("" ::: "memory").
| 归档时间: |
|
| 查看次数: |
44582 次 |
| 最近记录: |