ktb*_*ktb 5 c assembly gcc micro-optimization
在解释器循环(或其他有限状态机)中,有几种方法可以分派操作(或基于下一个输入的跳转状态)。C 中显而易见的方法是在循环中使用 switch 语句。但是,在循环内使用 switch 存在性能问题。在最坏的情况下,开关可以被编码为一个分支序列,如果操作编码不连续(或者编译器无法推断它是连续的),就会发生这种情况。即使在编译器生成跳转表的乐观情况下,仍然有多余的跳转回调度程序(我还没有看到编译器在看到循环中的开关时内联调度)。此外,调度程序中通常有一个冗余的边界检查。
GCC 团队通过引入 Computed Goto 解决了这个问题。这是一种语言扩展,允许引用标签,稍后可以跳转到goto
标签指针上使用。这生成了理想的汇编代码:一个操作码索引的跳转表,在每次操作后都带有内联调度。
有没有办法使用 ISO C 生成类似的汇编代码?
我能做到的最接近的方法是将每个操作编写为一个函数,将函数指针放在一个表中,并利用尾调用优化来生成跳转而不是调用。这个问题很明显:它依赖于可能存在也可能不存在的优化。如果没有优化,生成的代码将消耗堆栈并最终使应用程序崩溃。
我试图生成的理想汇编代码(GAS .intel_syntax,类似于 NASM 语法)
.intel_syntax noprefix
.section .rodata
optable:
.quad nop
.quad add
# more ops here
.section .text
## interpreter loop entry here
nop:
call nextinput # return value = table index in rax
jmp [optable + rax]
add:
# add stuff here
call nextinput
jmp [optable + rax]
Run Code Online (Sandbox Code Playgroud)