assembly x86-64地址计算mov,即mov i(r,r,i),r在端口1上执行吗?还是p0156?

mwyxok5s  于 2024-01-08  发布在  其他
关注(0)|答案(1)|浏览(208)

我问是否mov指令,需要计算该地址,即(在at&t语法
mov i(r, r, i), regmov reg, i(r, reg, i)
必须在端口1上执行,因为它们实际上是具有3个操作数+ MOV的莱亚,或者它们可以在端口0156上自由执行。
如果它们确实在端口1上执行莱亚部分,那么一旦地址计算完成,端口1将被解除阻塞,还是整个存储器加载需要首先完成。
在ICL上似乎p7可以做索引地址模式?

  1. #include <stdint.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #define BENCH_ATTR __attribute__((noinline, noclone, aligned(4096)))
  5. #define TERMS 3
  6. void BENCH_ATTR
  7. test_store_port() {
  8. const uint32_t N = (1 << 29);
  9. uint64_t dst, loop_cnt;
  10. uint64_t src[16] __attribute__((aligned(64)));
  11. asm volatile(
  12. "movl %[N], %k[loop_cnt]\n\t"
  13. ".p2align 5\n\t"
  14. "1:\n\t"
  15. "movl %k[loop_cnt], %k[dst]\n\t"
  16. "andl $15, %k[dst]\n\t"
  17. #if TERMS == 3
  18. "movl %k[dst], (%[src], %[dst], 4)\n\t"
  19. #else
  20. "movl %k[dst], (%[src])\n\t"
  21. #endif
  22. "decl %k[loop_cnt]\n\t"
  23. "jnz 1b\n\t"
  24. : [ dst ] "+r"(dst), [ loop_cnt ] "+r"(loop_cnt)
  25. : [ N ] "i"(N), [ src ] "r"(src), "m"(*((const uint32_t(*)[16])src))
  26. : "cc");
  27. }
  28. int
  29. main(int argc, char ** argv) {
  30. test_store_port();
  31. }

字符串
使用#define TERMS 3的结果:

  1. perf stat -e uops_dispatched.port_2_3 -e uops_dispatched.port_7_8 -e uops_issued.any -e cpu-cycles ./bsf_dep
  2. Performance counter stats for './bsf_dep':
  3. 297,191 uops_dispatched.port_2_3
  4. 537,039,830 uops_dispatched.port_7_8
  5. 2,149,098,661 uops_issued.any
  6. 761,661,276 cpu-cycles
  7. 0.210463841 seconds time elapsed
  8. 0.210366000 seconds user
  9. 0.000000000 seconds sys


关于#define TERMS 1

  1. perf stat -e uops_dispatched.port_2_3 -e uops_dispatched.port_7_8 -e uops_issued.any -e cpu-cycles ./bsf_dep
  2. Performance counter stats for './bsf_dep':
  3. 291,370 uops_dispatched.port_2_3
  4. 537,040,822 uops_dispatched.port_7_8
  5. 2,148,947,408 uops_issued.any
  6. 761,476,510 cpu-cycles
  7. 0.202235307 seconds time elapsed
  8. 0.202209000 seconds user
  9. 0.000000000 seconds sys

3zwtqj6y

3zwtqj6y1#

所有CPU都在加载或存储地址端口的AGU上为加载/存储uop进行地址生成,而不是在ALU端口上。只有莱亚使用ALU执行端口进行移位和加法运算。
如果复杂寻址模式需要端口1,https://uops.info/和/或https://agner.org/optimize/会在它们的指令表中这样说,但它们不需要:加载只需要p23,存储地址只需要p237,存储数据只需要p4。
https://www.realworldtech.com/haswell-cpu/5/在端口2和3上显示了load/AGU执行单元,在端口7上显示了store-AGU。
实际上只有p23用于索引存储;端口7上的简单存储地址AGU(Haswell到Skylake)只能处理reg+常量,这意味着如果您在代码中使用索引寻址模式,则地址生成可能是一个瓶颈,否则每个时钟可以支持2次加载+ 1次存储。
(早期的Sandybridge-family,SnB和IvB,甚至会取消层压索引商店,所以也有前端成本。

Ice Lake改变了这一点,在端口7和8上有2个专用的存储AGU。存储地址uops不能再借用加载AGU,因此存储AGU必须是全功能的。https://uops.info/html-tp/ICL/MOV_M32_R32-Measurements.html确认具有索引寻址模式的存储在ICL上以2/时钟运行,因此两个存储AGU都是全功能的。例如mov [r14+r13*1+0x4],r8d。(uops.info没有测试比例因子> 1,但我假设两个store-AGU是相同的,在这种情况下,它们都会处理它。

不幸的是,HSW/SKL对于调优来说并不重要,因为英特尔仍在销售Skylake衍生的微架构,因此它们将成为桌面软件安装基础的很大一部分。

相关问题