可以mul r1,r1?

时间:2017-11-03 18:43:43

标签: assembly mips x86-64 isa

如果我有

movmr x,r1

有可能吗?

mul r1,r1 

(x*x)一样。我正在努力有效地做到这一点以节省字节,但这是我能想到的最好的解决方案到目前为止,似乎无法找到它是否允许。

整个等式为(x+y)(x-y),因此我将其缩减为x^2 - y^2

此外,如果您想知道,f + d / exe基于每个字节。

OPC = 8位,x / y = 20位,reg = 3位。所以movmr x,r1是4f + d和4 exe

编辑:我们正在使用基于Linux的系统

OPC | DST,SRC,XX | < = | 1byte | 1byte |

1 个答案:

答案 0 :(得分:1)

大多数国际检索单位都没有这种限制,任何相关的都会记录下来。

通常,指令在写入任何输出操作数之前会读取所有输入操作数,因此如果它们重叠则会很好。任何限制将始终记录在ISA手册/指令集参考中。

您通常只能找到写入多个寄存器的指令的限制,在这种情况下,当您为两个输出提供相同的寄存器时,不可预测的行为或非法指令异常是正常的。例如,AVX512 vpgatherqq

  

如果目标向量zmm1与索引向量VINDEX相同,则指令将为#UD错误。

AVX2版本在ISA参考手册中没有提到这一点,但我忘了在其他任何地方是否有针对它的规则。

一个非法的案例是ARM:MUL Rd, Rm, Rs执行Rd := Rm × Rs

在ARM早期版本(?)中,如果Rd和Rm是相同的寄存器,则行为是不可预测的。 (ARM wiki和某些版本的official ARM docs)。也许早期的微体系结构进行了某种多步骤微编码计算,并将结果累积到目标寄存器中。

MUL     r1,r1,r6    ; incorrect: Rd cannot be the same as Rm
MUL     r1,r6,r1    ; correct:  r1 *= r6

A later version of ARM documentation没有提到这个限制,所以我猜不适用于以后的架构?或谷歌没有找到好的ISA文档。这些似乎是ARM的汇编程序的文档。以后的ARM架构版本肯定不会有限制,但IDK为什么以后的文档在删除限制时没有提及。

davespace says它的Rs和Rm(两个源操作数)不能相同。这与任何其他文档的说法都不匹配,并且在微体系结构上没那么正确,所以我认为这是错误的。

还有对ARM 32x32 => 64 bit full-multiply umull Rhi, Rlo, Rm, Rs的限制:Rhi,Rlo和Rm都必须是不同的寄存器。

UMULL  r1, r0, r0, r0     ; unpredictable, Rlo and Rm are the same. 
UMULL  r2, r1, r0, r0     ; r2:r1  =  r0*r0
  

整个等式为(x+y)(x-y),因此我将其缩减为x^2 - y^2

在没有任何周围代码的情况下,这种转变使它变得更加昂贵,而不是更少。 add / sub比乘法更便宜:更好的吞吐量和更低的延迟。在x86上,给定寄存器中的x和y,你可以

; x=eax
; y=edx

lea  ecx, [rax + rdx]     ; x+y
sub  eax, edx             ; x-y
imul ecx, eax             ; (x+y) * (x-y)

Intel SnB系列上的4个周期延迟。 (3个周期imul,lea / sub可以并行运行。http://agner.org/optimize/)。 VS

imul  eax, eax
imul  edx, edx
sub   eax, edx

如果eax和edx同时就绪,则会有5个周期延迟。现有的x86 CPU没有超过1个标量乘法执行单元,因此存在资源冲突:第二个imul必须等待一个循环才能执行。根据周围的代码,port1可能不是吞吐量瓶颈,也许一个或另一个输入已经准备好了一个周期。

但是,如果xy是不变的,那么只需2条指令就可以更便宜地计算新的(x+y) * (x-y),CSEing不会改变的方格。

这会破坏两个输入,因此如果您在此之后需要x或y,则需要mov。另一个版本会保留y(在edx中)并将x-y留在注册表中。