我正在查看MIPS平台的一些编译器输出,并努力了解函数如何返回以及允许的内容。
这是一个简单的例子:
int two_x_squared(int x)
{
return 2*x*x;
}
如果我compile it with Compiler Explorer看到
two_x_squared(int):
sll $2,$4,1
mult $2,$4
mflo $2
j $31
nop
好的,在这里没什么大不了的,我猜想j $31
会跳转到返回地址,而nop
可能是防止管道中的推测性执行所必需的。
但是随后我在-O2
下使用XC32进行编译,我得到了
two_x_squared:
mul $4,$4,$4
j $31
sll $2,$4,1
那么... j $31
之后的行在跳转之后的 之后执行了!!
答案 0 :(得分:6)
这称为branch delay slot。是的,分支实际执行的指令比您期望的要晚,并且编译器应该用一些有用的东西填充延迟槽—通过将在分支之前逻辑地完成的操作移入该槽,或者通过将在分支之后发生的事情移动插入该插槽。
它被引入到原始的MIPS架构(以及HP PA RISC等)中,以帮助流水线处理器,因为它们必须排空并重新填充已采用分支上的流水线,这浪费了指令周期。
此功能已在更高版本的MIPS处理器以及开源RISC V硬件中的后续版本中删除。更现代的硬件使用其他方法来减轻与管道重新填充相关的浪费周期,包括分支预测,一些乱序执行,推测,在管道中更早执行分支。