[英]Possible to mul r1,r1?
如果我有
movmr x,r1
有可能吗?
mul r1,r1
如(x*x)
。 我正在尝试有效地执行此操作以节省字节,但这是迄今为止我能想到的最好的解决方案,并且似乎无法找到是否允许这样做。
整个方程为(x+y)(xy)
,因此我将其简化为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 |
大多数ISA都没有这种限制,任何有限制的都可以记录下来。
通常,指令在写入任何输出操作数之前先读取其所有输入操作数,因此,如果它们重叠,就可以了。 任何限制都将始终记录在ISA手册/指令集参考中。
通常,您只会发现对写入多个寄存器的指令的限制,在这种情况下,当您为两个输出提供相同的寄存器时,异常行为或非法指令异常是正常的。 例如, AVX512 vpgatherqq
:
如果目标向量zmm1与索引向量VINDEX相同,则该指令将#UD错误。
AVX2版本在ISA参考手册中没有提及这一点,但我忘记了在其他任何地方是否有反对它的规则。
一种非法的情况是ARM: MUL Rd, Rm, Rs
确实Rd := Rm × Rs
在早期的ARM版本(?)中,如果Rd和Rm是同一寄存器,则该行为是不可预测的。 ( ARM Wiki和一些正式的ARM文档版本)。 也许早期的微体系结构进行了一些多步微编码计算,并将结果累加到目标寄存器中。
MUL r1,r1,r6 ; incorrect: Rd cannot be the same as Rm
MUL r1,r6,r1 ; correct: r1 *= r6
更高版本的ARM文档没有提及此限制,因此我想它不适用于更高的体系结构吗? 否则,谷歌找不到合适的ISA文档。 这些似乎是ARM汇编程序的文档。 以后的ARM体系结构版本肯定没有此限制,但是IDK为什么后来的文档没有提到取消限制的时间。
davespace表示 Rs和Rm(两个源操作数)不能相同。 这与任何其他文档所说的都不匹配,并且从微体系结构的角度讲意义不大,所以我认为这是错误的。
ARM的32x32 => 64位全乘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)(xy)
,因此我将其简化为x^2 - y^2
。
在没有任何周围代码的情况下,这种转换使它变得更加昂贵,而不是更少。 添加/订阅比乘法便宜:更好的吞吐量和更低的延迟。 在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 /子可以并行运行。 http://agner.org/optimize/ )。 与
imul eax, eax
imul edx, edx
sub eax, edx
如果eax和edx同时准备就绪,则有5个周期的延迟。 没有现有的x86 CPU具有超过1个标量乘法执行单元,因此存在资源冲突:第二个imul
必须等待一个周期才能执行。 取决于周围的代码,端口1可能不是吞吐量瓶颈,也许其中一个输入或另一个输入都可以提前一个周期准备好。
但是,如果x
或y
是不变的,则只需2条指令,您就可以通过这种方式便宜地计算出新的(x+y) * (xy)
,CSE处理不变的平方。
这会破坏两个输入,因此如果之后需要x或y,则需要mov
。 另一个版本保留y
(在edx
)并将xy
保留在寄存器中。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.