x86-64地址计算中的mov指令,例如mov i(r, r, i), r,在端口1上执行还是在p0156上执行?

4

我想问一下需要计算地址的mov指令,即(在at&t语法中)

mov i(r, r, i), regmov reg, i(r, reg, i)

是否必须在端口1上执行,因为它们实际上是带有3个操作数+ MOV的LEA,或者它们可以在端口0156上自由执行。

如果它们确实在端口1上执行LEA部分,那么一旦地址计算完成,端口1是否会解除阻塞,还是整个内存加载需要先完成。

在ICL上,似乎p7可以执行索引地址模式?

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>


#define BENCH_ATTR __attribute__((noinline, noclone, aligned(4096)))


#define TERMS 3

void BENCH_ATTR
test_store_port() {
    const uint32_t N = (1 << 29);

    uint64_t dst, loop_cnt;
    uint64_t src[16] __attribute__((aligned(64)));

    asm volatile(
        "movl %[N], %k[loop_cnt]\n\t"
        ".p2align 5\n\t"
        "1:\n\t"

        "movl %k[loop_cnt], %k[dst]\n\t"
        "andl $15, %k[dst]\n\t"
#if TERMS == 3
        "movl %k[dst], (%[src], %[dst], 4)\n\t"
#else
        "movl %k[dst], (%[src])\n\t"
#endif


        "decl %k[loop_cnt]\n\t"
        "jnz 1b\n\t"
        : [ dst ] "+r"(dst), [ loop_cnt ] "+r"(loop_cnt)
        : [ N ] "i"(N), [ src ] "r"(src), "m"(*((const uint32_t(*)[16])src))
        : "cc");
}

int
main(int argc, char ** argv) {
    test_store_port();
}

#define TERMS 3的结果:

perf stat -e uops_dispatched.port_2_3 -e uops_dispatched.port_7_8 -e uops_issued.any -e cpu-cycles ./bsf_dep

 Performance counter stats for './bsf_dep':

           297,191      uops_dispatched.port_2_3                                    
       537,039,830      uops_dispatched.port_7_8                                    
     2,149,098,661      uops_issued.any                                             
       761,661,276      cpu-cycles                                                  

       0.210463841 seconds time elapsed

       0.210366000 seconds user
       0.000000000 seconds sys

#define TERMS 1的结果:

perf stat -e uops_dispatched.port_2_3 -e uops_dispatched.port_7_8 -e uops_issued.any -e cpu-cycles ./bsf_dep

 Performance counter stats for './bsf_dep':

           291,370      uops_dispatched.port_2_3                                    
       537,040,822      uops_dispatched.port_7_8                                    
     2,148,947,408      uops_issued.any                                             
       761,476,510      cpu-cycles                                                  

       0.202235307 seconds time elapsed

       0.202209000 seconds user
       0.000000000 seconds sys
1个回答

2
所有的CPU都会在加载或存储地址端口上的AGU上进行地址生成,而不是在ALU端口上。只有LEA会使用ALU执行端口进行移位和加法运算。
如果复杂的寻址模式需要端口1,则https://uops.info/和/或https://agner.org/optimize/会在其指令表中说明。但是它们并没有这样做:加载只需要p23,存储只需要p237用于存储地址+ p4用于存储数据。
实际上,对于索引存储来说只有p23;Haswell至Skylake上的简单存储地址AGU(端口7)只能处理reg+constant,这意味着如果在代码中使用索引寻址模式,地址生成可能成为瓶颈,否则每个时钟周期可以支持2次加载和1次存储。
(早期的Sandybridge系列,SnB和IvB,甚至会将索引存储“un-laminate”,所以也存在前端成本。)
"Ice Lake改变了这一点,具有7号和8号端口上的2个专用存储器AGU。存储地址uops不能再借用加载AGU,因此存储器AGU必须具备完整的功能。 https://uops.info/html-tp/ICL/MOV_M32_R32-Measurements.html确认使用索引寻址模式的存储在ICL上以2/clock运行,因此两个存储器AGU都是完整功能的。例如,mov [r14+r13*1+0x4],r8d。(uops.info没有测试比1更大的比例因子,但我假设两个存储AGU是相同的,因此它们都可以处理它。)不幸的是,在调优方面,HSW/SKL仍然很重要,因为英特尔仍在销售基于Skylake的微架构,因此它们将成为桌面软件的重要组成部分多年。"

1
你能看一下那个例子吗?除非你发现有什么问题,否则似乎在icelake端口7也可以进行索引地址计算。(我知道这超出了最初的问题范围)。我试图回答的更大的问题(并且我相信我已经回答了)是假设没有地址生成的端口争用问题,选择简单地址模式而不是索引地址模式是否有任何理由(除了代码大小):没有。 - undefined
1
@Noah: 是的,冰湖改变了这一点。存储地址操作单元(uops)不能再借用加载地址生成单元(AGUs),所以存储地址生成单元必须具备完整功能。(或者至少其中一个需要;你测试过它是否能够支持每个时钟周期2个索引存储(比64字节窄),以避免存储数据成为瓶颈吗?我希望是的,但Haswell / SKL选择在其第7端口存储地址生成单元中省略了这一功能,原因不明,肯定会限制优化。)当然,如果你关心你的代码能够在大量已安装的旧CPU上运行,你仍然需要相应地进行优化。 - undefined
1
@Noah: 没关系,https://www.uops.info/html-tp/ICL/MOV_M32_R32-Measurements.html 已经测量过了。向下滚动查看索引寻址模式:这样的存储在ICL上以2个时钟运行。例如 mov [r14+r13*1+0x4],r8d。他们显然没有测试缩放索引,但我希望它是相同的。特别是如果端口7和端口8没有单独的计数器,希望它们是相同的。 - undefined
1
@Noah: 那些5c的延迟是负载使用延迟(用于指针追踪,如迭代链表或树)。我不知道如何测量存储地址延迟;很难将其作为依赖链的一部分。但是是的,除了[reg + 0..2047]这种特殊情况当reg本身是另一个加载操作的结果时,一切都是始终5c的总负载使用延迟。(或者在Ice Lake上,似乎已经取消了这种特殊情况,现在始终是5c。)但即使在ICL之前,CPU只在指针追踪时尝试乐观地跳过关键路径上的AGU加法器,这是加载延迟最关键的情况。 - undefined
1
@Noah:关于标签比较器:是的,你会获取一组中所有路径的标签和数据,并且任何对地址的标签部分进行==比较的命中都会导致将相应的数据混合到输出中。https://courses.cs.washington.edu/courses/cse378/09wi/lectures/lec16.pdf#page=19 上有一个示例图表。 - undefined
显示剩余11条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接