diff --git a/compiler/x86/aoptx86.pas b/compiler/x86/aoptx86.pas index 0a46f3963d..5794eba0a9 100644 --- a/compiler/x86/aoptx86.pas +++ b/compiler/x86/aoptx86.pas @@ -3108,6 +3108,59 @@ unit aoptx86; DebugMsg(SPeepholeOptimization + 'MovAndTest2Test done',p); taicpu(hp1).loadoper(1,taicpu(p).oper[0]^); taicpu(hp1).opcode:=A_TEST; + + { Shrink the TEST instruction down to the smallest possible size } + case taicpu(hp1).oper[0]^.val of + 0..255: + if (taicpu(hp1).opsize <> S_B) +{$ifndef x86_64} + and ( + (taicpu(hp1).oper[1]^.typ <> top_reg) or + { Cannot encode byte-sized ESI, EDI, EBP or ESP under i386 } + (GetSupReg(taicpu(hp1).oper[1]^.reg) in [RS_EAX, RS_EBX, RS_ECX, RS_EDX]) + ) +{$endif x86_64} + then + begin + if taicpu(hp1).opsize <> taicpu(hp2).opsize then + { Only print debug message if the TEST instruction + is a different size before and after } + DebugMsg(SPeepholeOptimization + 'test' + debug_opsize2str(taicpu(hp1).opsize) + ' -> testb to reduce instruction size (Test2Test 1a)' , p); + + taicpu(hp1).opsize := S_B; + if (taicpu(hp1).oper[1]^.typ = top_reg) then + setsubreg(taicpu(hp1).oper[1]^.reg, R_SUBL); + end; + 256..65535: + if (taicpu(hp1).opsize <> S_W) then + begin + if taicpu(hp1).opsize <> taicpu(hp2).opsize then + { Only print debug message if the TEST instruction + is a different size before and after } + DebugMsg(SPeepholeOptimization + 'test' + debug_opsize2str(taicpu(hp1).opsize) + ' -> testw to reduce instruction size (Test2Test 1b)' , p); + + taicpu(hp1).opsize := S_W; + if (taicpu(hp1).oper[1]^.typ = top_reg) then + setsubreg(taicpu(hp1).oper[1]^.reg, R_SUBW); + end; +{$ifdef x86_64} + 65536..$7FFFFFFF: + if (taicpu(hp1).opsize <> S_L) then + begin + if taicpu(hp1).opsize <> taicpu(hp2).opsize then + { Only print debug message if the TEST instruction + is a different size before and after } + DebugMsg(SPeepholeOptimization + 'test' + debug_opsize2str(taicpu(hp1).opsize) + ' -> testl to reduce instruction size (Test2Test 1c)' , p); + + taicpu(hp1).opsize := S_L; + if (taicpu(hp1).oper[1]^.typ = top_reg) then + setsubreg(taicpu(hp1).oper[1]^.reg, R_SUBD); + end; +{$endif x86_64} + else + ; + end; + RemoveInstruction(hp2); RemoveCurrentP(p, hp1); Result:=true;