如果我有
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 |
答案 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可能不是吞吐量瓶颈,也许一个或另一个输入已经准备好了一个周期。
但是,如果x
或y
是不变的,那么只需2条指令就可以更便宜地计算新的(x+y) * (x-y)
,CSEing不会改变的方格。
这会破坏两个输入,因此如果您在此之后需要x或y,则需要mov
。另一个版本会保留y
(在edx
中)并将x-y
留在注册表中。