当前指令旁边的 RIP 相关加载会发生什么情况?缓存命中?

What happens for a RIP-relative load next to the current instruction? Cache hit?

我正在阅读 Agner Fog 关于 x86 汇编的书。我想知道 RIP 相对寻址在这种情况下是如何工作的。具体来说,假设我的 RIP 偏移量是 +1。这表明我要读取的数据就在内存中这条指令的旁边。

这条数据很可能已经被提取到 L1 指令缓存中。假设这个数据不在L1d中,那么在CPU上究竟会发生什么?

我们假设它是相对较新的 Intel 架构,例如 Kaby Lake。

是的,它在 L1i 缓存和 uop 缓存中可能很热。该页面在 L1iTLB 中也很热门。但所有这些都与数据加载无关。

由于指令获取,它在 L2 中可能很热,但它可能从那时起就被驱逐了(L2 是 NINE wrt。L1 缓存)。 所以最好的情况是在 L2 中命中

L1iTLB 和 L1dTLB 是分开的,因此如果这是从该页面加载的第一个数据,它将在 L1dTLB 中丢失。如果统一的二级 TLB 是受害者缓存,它可能会错过那里,甚至触发页面遍历,尽管在 L1iTLB 中很热,但是 。不过,这是有道理的;同一页面中的代码和数据通常很少见。 (尽管比同一 中的代码和数据更少见。)

另请参阅 了解一些详细信息和讨论。但请注意,这是一个错误的说法,编译器 不要 在 x86 上这样做,因为它对性能有帮助(浪费 TLB 覆盖足迹,浪费缓存容量),这与 ARM 不同,后者是常量函数之间的池是正常的,因为 PC 相对寻址的范围非常有限。只有一些混淆器可能会这样做。


Specifically, assume my RIP offset is +1. This suggests the data I want to read is right next to this instruction in memory

rel32是相对于当前指令的end。所以不,不在右边旁边;那将是一个 1 字节的间隙。

例如像这样:

              movzx eax, byte [rip + 1]  
              ret
                            ; could be a page boundary here
load_target:  int3        ; db 0xcc

请注意,如果指令在页面边界的 0 或 1 字节内结束,[RIP+1] 可能与使用该寻址模式的指令位于不同的缓存行甚至页面中。

那个 1 字节甚至可以是一个 ret,所以这条指令可能已经在执行,而前端还没有(或曾经)从其他行或页面中获取,就像它会否则。我认为您对从包含当前指令的同一行中获取的情况更感兴趣。不妨说 mov eax, [RIP - 4] 从当前指令的机器代码中获取 -4 rel32 本身。

加载不会触发自修改代码管道核弹,只会触发存储,所以没关系。