【发布时间】:2020-02-04 21:06:04
【问题描述】:
英特尔软件开发人员手册将 VCVTTPD2QQ 描述为:
Convert eight packed double-precision floating-point values
from zmm2/m512 to eight packed quadword integers in zmm1
using truncation with writemask k1.
我正在使用VCVTTPD2QQ将8个双精度64位浮点数加载到zmm1中,编码如下:
mov rax,18446744073709551615
KMOVQ k1,rax
EVEX.512.66.0F.W1 VCVTTPD2QQ zmm1 {k1}{z},[r11+r15]
我用全 1 填充 k1 以指示移动所有 8 个数字。
如果我这样编码,我仍然会得到相同的结果:
VCVTTPD2QQ zmm1 {k1}{z},[r11+r15]
英特尔手册通过寄存器名称区分三种可能的编码;如果名字是一个zmm寄存器,那么它应该移动8。
为什么我只有 4 个而不是 8 个数据点加载到 zmm1 中?
编辑:
我消除了写掩码,正如 Peter Cordes 在下面所说的那样,这里没有区别。我还创建了一个内存数组并将其访问为:
test_array: dq 24.0, 93.0, 43.0, 28.0, 86.0, 143.0, 17.0, 129.0, 33.0, 67.0, 55.0
mov rdi,test_array
EVEX.512.66.0F.W1 VCVTTPD2QQ zmm1,[rdi]
调试器显示的内容与访问从外部文件(4 个元素,而不是 8 个)读取的数组相同。这是 gdb 输出:
(gdb) i r zmm1
zmm1 {v16_float = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v8_double = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0}, v64_int8 = {0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5d, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x1c, 0x0 <repeats 39 times>}, v32_int16 = {0x18, 0x0, 0x0, 0x0, 0x5d,
0x0, 0x0, 0x0, 0x2b, 0x0, 0x0, 0x0, 0x1c, 0x0 <repeats 19 times>}, v16_int32 = {0x18, 0x0, 0x5d, 0x0, 0x2b, 0x0, 0x1c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v8_int64 = {0x18, 0x5d, 0x2b, 0x1c, 0x0, 0x0, 0x0,
0x0}, v4_int128 = {0x5d0000000000000018, 0x1c000000000000002b, 0x0, 0x0}}
在 v8_int64 部分中,我们看到前四个值(正确),但后四个为零且输入数据不为零。
【问题讨论】:
-
包含一个可以重现此问题的最小、完整且可验证的示例:stackoverflow.com/help/minimal-reproducible-example
-
你为什么要使用遮罩?如果您想要全部 8 个,只需使用未屏蔽的。另外,你为什么要用十进制写你的常数,而不是像普通人那样写
-1或0xffffffffffffffff?或者更好,kxnorw k1, k0, k0如果您出于某种原因确实想要一个全为掩码(而不是根本不使用掩码)。并不是说这些都会改变结果,只是你把它复杂化了。显示调试器输出,您在 ZMM 寄存器中看到“只有 4 个”值,即使指向的内存有 8 个非零doubles。 -
而MCVE可以像
.rodata中的arr: times 4 dq 3.0, 2.0一样简单,并且这条指令带有内存源。 -
嗯。 GDB 在这里可能有问题。尝试将 ZMM1 存储到内存并检查内存。顺便说一句,您可以
p $zmm1.v8_int64仅显示矢量注册的视图。为什么在你的 asm 源代码中包含EVEX.512.66.0F.W1?不过,这不是问题。我从VCVTTPD2QQ zmm1,[rdi]获得的机器代码与使用该覆盖时相同。 -
你有任何证据表明它真的只加载 32 字节吗?例如如果您在未映射的页面之前加载最后 32 个字节,这不会出错吗? (这极不可能;更有可能这是一个 GDB 错误,将向量的高 256 位打印为 0,而不是指令实际上执行错误。)因此,更好的标题可能是将前 4 个元素归零。
标签: assembly gdb x86-64 nasm avx512