我注意到我的一个数字运算程序中的一些无辜查找if语句会显着降低执行速度(JRE 1.8.25,64位Hotspot build 25.25-b02,Intel 64位CPU)。
我检查了JIT编译器生成的代码,看起来有点奇怪。这是一个简单的函数来说明问题:
private float test(float a,float b) {
float c=a+b;
if(c<0) {
return -1;
}
return 0;
}
这是生成代码的有趣部分:
...
0x2bd17ae: vaddss xmm0,xmm0,xmm1
0x2bd17b2: vxorps xmm1,xmm1,xmm1
0x2bd17b6: vucomiss xmm0,xmm1
0x2bd17ba: mov esi,1h
0x2bd17bf: jp 2bd17d8h
0x2bd17c5: jnbe 2bd17d8h
0x2bd17cb: mov esi,0h
0x2bd17d0: je 2bd17d8h
0x2bd17d6: dec esi ;*fcmpg
0x2bd17d8: cmp esi,0h
0x2bd17db: mov rsi,57448760h ; {metadata(method data for {method} ...}
0x2bd17e5: mov rdi,108h
0x2bd17ef: jnl 2bd17ffh
0x2bd17f5: mov rdi,118h
0x2bd17ff: mov rbx,qword ptr [rsi+rdi]
0x2bd1803: lea rbx,[rbx+1h]
0x2bd1807: mov qword ptr [rsi+rdi],rbx
0x2bd180b: jnl 2bd1c1fh ;*ifge
...
// straightforward code for "return -1f" and "return 0f" follows
...
从0x2bd17ba到0x2bd1807的代码对我来说没有多大意义。为什么会这样?知道它的作用吗?
编辑:考虑一下,它可能是JIT编译器添加的一些代码来收集运行时统计信息(只是猜测因为元数据&#39;注释)。但问题是:为什么会这样?我已经将该方法调用了数百万次,因此我认为代码应该已达到最终的优化形式。
答案 0 :(得分:1)
(v)ucomiss
设置标志如下:
unordered zf,pf,cf = 111
greater zf,pf,cf = 000
less than zf,pf,cf = 001
equal zf,pf,cf = 100
所以这段代码:
mov esi,1h
jp label ; if unordered, or
jnbe label ; if greater than, keep it at 1
mov esi,0h
je label ; if equal, make 0
dec esi ; otherwise -1
label:
制作esi = 1
(如果无序或更高),esi = 0
(如果相等),esi = -1
(如果更小)
然后它将esi
与0进行比较,标记为&#34; ifge&#34;确实检查&#34;如果大于或等于&#34; (通过检查esi
不小于0来排序,也包括无序的情况),所以&#34;否则&#34;分支的一部分。
从0x2bd17db到0x2bd1807的部分有条件地增加两个计数器,一个或另一个,具体取决于分支采用的方式。所以它是某种形式的分析。也许以后会用于优化,但我不知道(不过你还会用它做什么)。
他们可以做到:
vaddss xmm0,xmm0,xmm1
vxorps xmm1,xmm1,xmm1
vcmpss xmm0,xmm1,1
vandps xmm0,xmm0,[rel negative_one]
ret
没有分析,但是没有分支,所以无需分析。