第91章 编译器的智能短板

Intel C++ 10.1(在Linux x86平台上编译Oracle RDBMS 11.2的编译器)有时候会生成两个连续的JZ指令。实际上第二条JZ指令不会被执行、没有实际意义。

指令清单91.1 kdli.o from libserver11.a

.text:08114CF1                     loc_8114CF1: ; CODE XREF: __PGOSF539_kdlimemSer+89A
.text:08114CF1                                  ; __PGOSF539_kdlimemSer+3994
.text:08114CF1 8B 45 08                mov     eax, [ebp+arg_0]
.text:08114CF4 0F B6 50 14             movzx   edx, byte ptr [eax+14h]
.text:08114CF8 F6 C2 01                test    dl, 1
.text:08114CFB 0F 85 17 08 00 00       jnz     loc_8115518
.text:08114D01 85 C9                   test    ecx, ecx
.text:08114D03 0F 84 8A 00 00 00       jz      loc_8114D93
.text:08114D09 0F 84 09 08 00 00       jz      loc_8115518
.text:08114D0F 8B 53 08                mov     edx, [ebx+8]
.text:08114D12 89 55 FC                mov     [ebp+var_4], edx
.text:08114D15 31 C0                   xor     eax, eax
.text:08114D17 89 45 F4                mov     [ebp+var_C], eax
.text:08114D1A 50                      push    eax
.text:08114D1B 52                      push    edx
.text:08114D1C E8 03 54 00 00          call    esp, 8
.text:08114D21 83 C4 08                add     esp, 8

上述文件中,另有一处也存在这种问题。

指令清单91.2 from the same code

.text:0811A2A5                     loc_811A2A5: ; CODE XREF: kdliSerLengths+11C
.text:0811A2A5                                  ; kdliSerLengths+1C1
.text:0811A2A5 8B 7D 08                mov     edi, [ebp+arg_0]
.text:0811A2A8 8B 7F 10                mov     edi, [edi+10h]
.text:0811A2AB 0F B6 57 14             movzx   edx, byte ptr [edi+14h]
.text:0811A2AF F6 C2 01                test    dl, 1
.text:0811A2B2 75 3E                   jnz     short loc_811A2F2
.text:0811A2B4 83 E0 01                and     eax, 1
.text:0811A2B7 74 1F                   jz      short loc_811A2D8
.text:0811A2B9 74 37                   jz      short loc_811A2F2
.text:0811A2BB 6A 00                   push    0
.text:0811A2BD FF 71 08                push    dwordptr [ecx+8]
.text:0811A2C0 E8 5F FE FF FF          call    len2nbytes

这些问题可能属于编译器的bug。但是它们生成的程序不会受到该bug的影响,所以可能被测试人员遗漏了下来。本书的19.2.4节、39.3节、47.7节、18.7节、12.4.1节、19.5.2节中都演示了这种问题。

本文演示了这些编译器问题,以证明编译器确实可能出现匪夷所思的奇怪行为。如果遇到了这种现象,读者不必绞尽脑汁地去琢磨“编译器为什么生成这种诡异代码”。