ymm0 寄存器(不是内存)中单个浮点数的位表示是什么?

What is the bit representation of a single float number inside ymm0 register (not memory)?

内存中的一个浮点数需要 4 个字节,但是单个 ymm0 有空间容纳 8 个浮点数,那么 ymm0 中的所有位在加载一个浮点值后如何处理?在执行浮点运算时,我仍然每个寄存器只加载 1 个数字。

寄存器中剩余的space在什么情况下使用?

我知道如何使用 float 和 unsigned int 的联合从内存中读取位 hex。我把寄存器想象成一个只有一个地址的小内存,寄存器中的浮点数位是如何组织的?

向量 reg 的低 32 位中的位模式与内存匹配:IEEE binary32 single-precision floating point。您可以使用 SIMD 整数来操作它,例如 psrld xmm0, 23 将指数字段移动到双字的底部。 (像这样的东西在实践中用于为标量或 SIMD 实现 exp/log)。

背景:最初有 Pentium III 的 SSE1(又名 SSE),它只有 128 位/16 字节 XMM 寄存器并且只有单精度 float(不是 double 或整数 SIMD)。 AVX1 将 XMM regs 扩展为 256 位 YMM,并为 128 位指令添加了不同的 (VEX) 编码,零扩展以清除低 128 位 XMM 部分之外的部分。 (vaddps xmm,xmm,xmmss 而不是 addps xmm,xmmss)。 AVX512 扩展到 512 位 ZMM(并添加掩码作为第一个 class 操作,可以作为任何其他指令的一部分)。

就标量 FP 数学而言,YMM 寄存器的高字节是 "don't care"。 但是每条 asm 指令对于它对完整寄存器的操作都有明确定义的语义:加载零扩展,ALU 操作合并到旧值(包括movss xmm,xmm)合并一个新的低元素到现有目的地。

对于包括 sqrtss xmm, xmmsqrtss xmm, [mem]cvtsi2ss xmm0, eax 的单源操作,目标将是只写的,因此这会产生错误的依赖性。

英特尔针对 SSE1 的短视设计产生了编译器必须解决的输出依赖性,尤其是在 int->FP 转换中。 (Pentium III 将 128 位操作分成 64 位的一半,因此零扩展会花费额外的 uop。)

A vmovss xmm0, [mem] 从内存零扩展到完整的 XMM/YMM/ZMM 寄存器 。根据操作部分 in the Intel manual:

  VMOVSS (VEX.128.F3.0F 10 /r when the source operand is memory and the destination is an XMM register) ¶
DEST[31:0] ←SRC[31:0]
DEST[MAXVL-1:32] ←0

指令 (movss xmm0, [mem]) 的旧版 SSE 编码零扩展到 XMM 元素,但 YMM/ZMM 的上层元素未修改。 (引入性能问题的可能性,如果 CPU 不知道它们为零,因此它可以避免实际合并:

幸运的是,英特尔避免了使用 SSE1(和 SSE2)加载的虚假依赖合并到目标错误,即使他们对 cvtsi2ss xmm0, eaxsqrtss xmm0, xmm1.[=39 这样的东西这样做了=]

vmovss xmm0, xmm1, xmm2 将xmm2合并到xmm1,并将结果写入xmm0。 (当然,零扩展为 ymm/zmm0)。 https://felixcloutier.com/x86/movss。使用 vmovaps 通过复制整个 XMM 寄存器来正常复制标量浮点数。

Under what circumstances is the remaining space in the register used?

最明显的是,当您想使用 ...ps 压缩单 SIMD 指令而不是 ...ss 单标量指令同时执行 8 个 FP 操作时

SIMD 是向量寄存器首先很宽的原因。

您还可以在向量寄存器的高位元素中有 leftover 垃圾,例如经过一些 shuffle/add 得到水平总和下降到 1 个标量 float 后,具有非零高元素是正常的。

即使跨越函数调用边界,ABI 也保证上层元素为零;您的调用者可能已经在向量寄存器的底部计算了一个标量并将其传递给您的 float 函数。

如果您想严格遵循 FP 异常语义,则需要确保在高位元素中存在 NaN 或其他垃圾时,您不会进行引发异常的计算。为了性能,对那些未知的位模式进行操作可能会产生不正常的结果。 (或者它们可能是次正规输入)。因此,如果您不小心使用 addps 而不是 addss.

,您最终可能会使用 > 100 周期的微码帮助来解决这个问题