MIPS(好奇心)更快的清除寄存器的方法?
在 MIPS 汇编中清除寄存器 (=0) 的最快方法是什么?
一些例子:
xor $t0, $t0, $t0
and $t0, $t0, $0
move $t0, $0
li $t0, 0
add $t0, $0, $0
哪个最有效?
What is the fastest way of clearing a register (=0) in MIPS assembly?
Some examples:
xor $t0, $t0, $t0
and $t0, $t0, $0
move $t0, $0
li $t0, 0
add $t0, $0, $0
Which is the most efficient?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
在许多 MIPS 实现中,这些操作都将编译为相同的指令,因为通常“mov $a, $b”是
or $a, $b, $0
和li $ 的习惯用法r, x
是ori $r, $0, x
的简写:这些都将发生在同一个管道上,在架构上是等效的:
并且在我曾经工作过的每个 RISC 实现中with, add 与 xor/and/nor/etc 在同一管道上。
基本上,这都是特定芯片的实现所特有的,但它们都应该是单时钟。如果芯片出现故障,
li
或和 x, $0, $0
可能 是最快的,因为它们最大限度地减少了对其他寄存器的错误依赖。In many MIPS implementations, these ops will both compile to the same instruction, because typically 'mov $a, $b' is an idiom for
or $a, $b, $0
andli $r, x
is shorthand forori $r, $0, x
:and these will both take place on the same pipeline, being architecturally equivalent:
and in every RISC implementation I've ever worked with, add is on the same pipe as xor/and/nor/etc.
Basically, this is all particular to the implementation of a particular chip, but they all ought to be single clock. If the chip is out of order,
li
orand x, $0, $0
might be fastest because they minimize false dependencies on other registers.我似乎记得 $0 是专门为这种情况创建的,所以我希望
move $t0 $0
应该是清除寄存器的推荐方法。但我已经快10年没有做过MIPS了……I seem to remember that $0 was creted specifically for this case, so I would expect that
move $t0 $0
should be the recommended way to clear a register. But I have not done MIPS for almost 10 years ...鉴于所有这些指令都需要一个管道周期,因此它们之间应该没有太大区别。
如果有的话,我希望 xor $t0, $t0, $t0 的速度最好,因为它不使用任何其他寄存器,从而使它们可以自由用于其他值并可能减少寄存器文件争用。
异或方法在某些处理器上也被视为特定的习惯用法,这使得它可以使用更少的资源(例如不需要执行异或 ALU 操作)。
Given that all of those instructions take a single pipeline cycle, there shouldn't be much difference between them.
If any, I'd expect the
xor $t0, $t0, $t0
to be best for speed because it doesn't use any other registers, thus keeping them free for other values and potentially reducing register file contention.The xor method is also treated as a specific idiom on some processors, which allow it to use even less resources (e.g. not needing to do the XOR ALU operation.
在 MIPS 架构的大多数实现中,所有这些都应提供相同的性能。然而,人们可以设想一种超标量系统,它可以同时执行多个指令,只要它们使用不同的内部单元。我没有像这样工作的 MIPS 系统的实际示例,但这就是它在 PowerPC 系统上发生的情况。当
移动$t0时,
不会使用该单位;从概念上讲,后者可以与另一个执行整数计算的操作码并行执行。xor $t0, $t0, $t0
操作码将在“整数计算”单元上执行(因为它是一个xor
), $0简而言之,如果您发现一个系统,您列出的所有方法的效率并不相同,那么我希望
移动 $t0, $0
方法是最有效的。On most implementations of the MIPS architecture, all of these should offer the same performance. However, one can envision a superscalar system which could execute several instructions simultaneously, as long as they use distinct internal units. I have no actual example of a MIPS system which works like that, but that is how it happens on PowerPC systems. A
xor $t0, $t0, $t0
opcode would be executed on the "integer computations" unit (because it is axor
) whilemove $t0, $0
would not use that unit; conceptually, the latter could be executed in parallel with another opcode which perform integer computations.In brief, if you find a system where all the ways you list are not equally efficient, then I would expect the
move $t0, $0
method to be the most efficient.这可能取决于同时在管道中的其他指令:上次使用寄存器的时间、下次使用寄存器的时间以及当前正在使用哪些内部单元。
我不熟悉任何特定 MIPS 处理器的管道结构,但您的编译器应该熟悉,并且我希望它选择给定代码序列中最快的一个。
It probably depends on what other instructions will be in the pipeline at the same time: when the register was last used, when it will next be used and which internal units are currently in use.
I'm not familiar with the pipeline structure of any particular MIPS processor, but your compiler should be and I would expect it to choose whichever would be the fastest in a given code sequence.
您可以简单地使用 $zero 寄存器作为参考,并将其值(0 或 0b00000000)写入要清除的寄存器中。
如果您使用浮点型或双精度型,您只需在 .data 中将浮点型和/或双精度型变量声明为 0.0,然后将其写入您想要随时清除的寄存器中。
例子:
You can simply use the $zero register as a reference and write its value, which is 0 or 0b00000000, into the register you want to clear up.
If you're working with floats or doubles you can simply declare a float and or double variable in .data as 0.0 and write it into the register you want to clear up whenever you want.
Example: