无用的测试指令?

33

我为我的Java程序进行JIT编译时得到了下面的汇编列表结果。

mov    0x14(%rsp),%r10d
inc    %r10d              

mov    0x1c(%rsp),%r8d
inc    %r8d               

test   %eax,(%r11)         ; <--- this instruction

mov    (%rsp),%r9
mov    0x40(%rsp),%r14d
mov    0x18(%rsp),%r11d
mov    %ebp,%r13d
mov    0x8(%rsp),%rbx
mov    0x20(%rsp),%rbp
mov    0x10(%rsp),%ecx
mov    0x28(%rsp),%rax    

movzbl 0x18(%r9),%edi     
movslq %r8d,%rsi          

cmp    0x30(%rsp),%rsi
jge    0x00007fd3d27c4f17 

我理解这里test指令是无用的,因为测试的主要思想是

SF、ZF、PF标志位被修改,而AND的结果被丢弃。

在这里我们不使用这些结果标志位。

这是JIT中的一个错误吗?还是我忽略了什么?如果是错误,请问报告错误的最佳位置在哪里?谢谢!


2
这条指令似乎确实没有用。 - fuz
6
就我所知,这段话隐含地检查了r11是否包含有效的指针,如果不是则会引发异常。这是有意为之吗?不确定,缺乏上下文信息。 - user10762593
3
现在我们知道答案了,如果JVM有更多时间来分析周围的代码,它就可以使用 mov (%r11), %r9d,因为另一条指令即将写入 r9。 MOV 的代码字节数相同,但它是一个纯载入指令,没有 ALU 微操作。这是一个次要的优化,因为 ALU 端口压力几乎肯定不是问题,而现代的 x86 CPU 将负载微融合到单个微操作中,并通过大部分流水线与 ALU 指令一起运行,因此它不会影响前端吞吐量。 - Peter Cordes
@liliscent:我不应该说SnB 和之前的。我认为这篇论文只是声称SnB与IvB有所不同,并没有提到SnB之前的版本。(而且也没有提供任何关于他们如何得出这个结论的信息,所以我并不完全信任它,但除此之外,这篇论文看起来很好。) 是的,我认为P6系列有一个融合域ROB。SnB简化了内部uop格式(因此取消了索引地址模式的分层),因此尝试使用未融合的ROB是可行的,然后在找到方法或发现不值得权衡之后,再回到IvB的融合域ROB。 - Peter Cordes
@PeterCordes 我认为你是正确的,特别是在阅读了您链接的答案之后。SnB 必须有一些变化。Anger Fog 对微型融合的描述对于后来的描述来说过于模糊,它们似乎仅声称 SnB - SKL 与 PM 完全相同,但没有提供太多细节。 - llllllllll
显示剩余4条评论
1个回答

46

那一定是 本地线程握手轮询。看看哪里读取了%r11。如果它是从%r15(线程本地存储)的某个偏移处读取的,那就是它了。在这里可以看到示例:

  0.31%  ↗  ...70: movzbl 0x94(%r9),%r10d    
  0.19%  │  ...78: mov    0x108(%r15),%r11  ; read the thread-local page addr
 25.62%  │  ...7f: add    $0x1,%rbp          
 35.10%  │  ...83: test   %eax,(%r11)       ; thread-local handshake poll
 34.91%  │  ...86: test   %r10d,%r10d
         ╰  ...89: je     ...70

它不是无用的,一旦保护页被标记为非可读,它将导致SEGV,这将转移控制权给JVM的SEGV处理程序。这是JVM安全点Java线程的机制的一部分,例如垃圾收集。

更新:希望在此处了解更多细节。


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