X86:如何将xmm0的下半部分设置为0,而不影响上半部分?

Posted

技术标签:

【中文标题】X86:如何将xmm0的下半部分设置为0,而不影响上半部分?【英文标题】:X86: How to set lower half of xmm0 to 0, without affecting the upper half? 【发布时间】:2019-12-25 17:58:53 【问题描述】:

我使用 xmm0 具有 128 位的系统。 我想将 [63...0] 设置为零,而不影响 [127...64]。 我用:

MOV RAX, 0xFFFFFFFFFFFFFFFF
MOVQ xmm2, RAX
PSHUFD xmm2, xmm2, 0b00001111
PAND xmm1, xmm2

有没有更快的方法?

【问题讨论】:

【参考方案1】:

您可以通过

更有效地创建常量
pcmpeqd xmm2,xmm2       ; xmm2 = all-ones.  Needs any ALU port
pslldq  xmm2, 8         ; left shift by 8 bytes.  Needs the shuffle port

PAND    xmm1, xmm2

(另见Agner Fog's optimization guide;他有一节介绍动态创建常量。另见What are the best instruction sequences to generate vector constants on the fly?)

或者正如@RossRidge 所建议的那样,如果您经常需要它以在缓存中保持热状态,但不能只是将其提升出循环并将其保存在寄存器中,那么对常量使用内存源操作数可能是最有效的.


或混入新的低 8 字节零

pxor   xmm2, xmm2       ; xmm2=0; very efficient on Intel CPUs; no back-end uop

movsd  xmm1, xmm2       ; runs on port5 only on Intel CPUs, like shuffles.

(作为从内存中加载,movsd 零扩展。但是对于 reg-reg 移动它并且movss 保持目标上部不变。)

其他混合方式更有效,但比 SSE2 需要更多:

SSE4.1:pblendw xmm1, xmm2, 0b00001111 - 一切都更糟(或速度相同但代码大小更差)。仍然只在 Intel 的 port5 上运行。 Ryzen 在比pblendw 更多的端口上运行movsd xmm,xmm。低功耗 Atom/Silvermont 在比 pblendw 更多的端口上运行 movsd,但 Goldmont 和 KNL 对此和 movsd 有 2 个/时钟的吞吐量。所以它仍然永远不会比 movsd 更好。 SSE4.1 blendpd xmm1, xmm2, 0b01(或blendps) - 与 vpblendd 一样高效,但如果在整数指令之间使用会产生绕过转发延迟。如果您在吞吐量方面遇到瓶颈,这可能没问题,尤其是在您必须避免后端压力的情况下。 AVX2:vpblendd xmm1, xmm1, xmm2, 0b0011 - 在任何 AVX2 CPU 的任何 ALU 端口上运行。

某些 CPU 可能还会在整数指令之间对 movsd 进行旁路延迟,但 Sandybridge 系列对随机播放非常宽容。

在某些 CPU 上与 movsd 一样高效,只需要 SSE1:

movhlps xmm1, xmm2 - 将 xmm1 的低 qword 替换为 xmm2 的高 qword(也为零)。在 Ryzen 或 Silvermont 上效率较低。

同样,shufpdshufps 可以将xmm1 的上半部分复制到零寄存器的上半部分。 (如果您不想破坏原始注册,则很有用)。但是您可以使用movsd 轻松高效地做到这一点。


也可能:movlps xmm, [mem] 加载零,可能是您刚刚存储到堆栈中。它不允许注册源操作数,并且需要 Intel 上的 port5 uop(shuffle / uncommon blend)。它可以微融合到一个融合域微指令中,但它比带有内存源的pand 差很多,因为它可以在更少的端口上运行。

【讨论】:

以上是关于X86:如何将xmm0的下半部分设置为0,而不影响上半部分?的主要内容,如果未能解决你的问题,请参考以下文章

css 已经定义上面一部分 下半部分想使高度占下半区域100%怎么办

Android XML切断了布局的下半部分

如何将半透明的“图片/图像”设置为黑白,而不影响子元素和背景颜色? [复制]

我应该使用啥约束来让图像视图方面填充其父视图的下半部分?

在 UITableView 上为 layoutIfNeeded 设置动画而不为 UITableViewCells 设置动画

X86 操作码将 xmm 寄存器移动到通用寄存器