2017-05-11 22 views
1

如何告诉GCC编译器应该生成串行(即没有跳转)的代码。如何告诉GCC编译器应该生成的代码是串行的,即没有跳转

我正在研究将内联汇编嵌入C源代码(或LLVM IR)的项目。

我的实现取决于将内联汇编写入可执行文件的代码。

更正式地说,假设我有索里的代码(C或LLVM IR):

.label_start: (inserted as inline assembly) 
inline_assembly0 
source_code0 
source_code1 
inline_assembly1 
... 
.label_end: (inserted as inline assembly) 
... 

现在,这不应该被编译为:

.jmp_target: 
source_code1 
inline_assembly1 
... 
.label_end: (inserted as inline assembly) 
... 

.label_start: (inserted as inline assembly) 
inline_assembly0 
source_code0 
jmp jmp_target 

即代码应留在标签之间,不要跳转.label_start.label_end

有什么办法告诉GCC两个内联汇编标签之间的所有内容都应该保持“完好无损”而不必重新排序?我的实现取决于此。

+0

这段代码是否恰好在循环中? –

+0

你为什么需要这个?在任何情况下,你是否有一个不符合乱序执行的CPU。 –

+0

通常,代码可以位于循环@BenVoigt中。 – Shuzheng

回答

4

如果我理解你的问题,GCC manual对此有几句话(强调增加)。

请注意,编译器可以将相对于其他代码(包括跨越跳转指令)的指令移动到甚至不稳定的asm指令。例如,在许多目标上有一个系统寄存器,用于控制浮点操作的舍入模式。如下面的PowerPC例子那样,使用易失性asm进行设置,不能可靠地工作。

asm volatile("mtfsf 255, %0" : : "f" (fpenv)); 
sum = x + y; 

编译器可能会在不稳定的asm之前移回加回。 要使其工作如预期,在随后的代码引用变量添加人工的依赖于asm,例如:

asm volatile("mtfsf 255,%1" : "=X" (sum) : "f" (fpenv)); 
sum = x + y; 

基本上,你需要一个“虚用”,以防止重新排序。

我们也使用这种单中的事情,延长在低级别的GC码参考的活跃度,以确保如果GC中断例行它不会被过早释放:

static inline void dummy_use (void *v) 
    __asm__ volatile ("" : "=r"(v) : "r"(v)); 
} 
+1

这涉及执行的顺序,但问题是讨论内存布局 –

+0

谢谢,这是非常丰富的!但它确保内存布局吗? – Shuzheng

+2

@Shuzheng:不像Ben Voigt说的那样,它只能让你确保代码以特定顺序执行。例如,一个冷分支可能仍然被排除在外。总的来说,我猜你需要做一些类似'#pragma GCC push_options','#pragma GCC optimize(“O0”)','#pragma GCC pop_options'来在本地禁用所有优化。 ('-fno-reorder-blocks'可能就足够了。)如果这对你是可行的,你也可以使用内联汇编来处理这些块中的所有内容。 –

相关问题