diff --git a/compiler/x86/aoptx86.pas b/compiler/x86/aoptx86.pas index 89f359565f..f901964b90 100644 --- a/compiler/x86/aoptx86.pas +++ b/compiler/x86/aoptx86.pas @@ -180,6 +180,7 @@ unit aoptx86; globals, cpuinfo, procinfo, + paramgr, aasmbase, aoptbase,aoptutils, symconst,symsym, @@ -4723,6 +4724,8 @@ unit aoptx86; l : Longint; condition : TAsmCond; symbol: TAsmSymbol; + reg: tsuperregister; + regavailable: Boolean; begin result:=false; symbol:=nil; @@ -4748,7 +4751,7 @@ unit aoptx86; @@1: } begin carryadd_opcode:=A_NONE; - if Taicpu(p).condition in [C_NAE,C_B] then + if Taicpu(p).condition in [C_NAE,C_B,C_C] then begin if (Taicpu(hp1).opcode=A_INC) or ((Taicpu(hp1).opcode=A_ADD) and @@ -4781,7 +4784,7 @@ unit aoptx86; exit; end; end - else if Taicpu(p).condition in [C_AE,C_NB] then + else if Taicpu(p).condition in [C_AE,C_NB,C_NC] then begin if (Taicpu(hp1).opcode=A_INC) or ((Taicpu(hp1).opcode=A_ADD) and @@ -4810,6 +4813,77 @@ unit aoptx86; result:=true; exit; end; + end + { + jcc @@1 setcc tmpreg + inc/dec/add/sub operand -> (movzx tmpreg) + @@1: add/sub tmpreg,operand + + While this increases code size slightly, it makes the code much faster if the + jump is unpredictable + } + else if not(cs_opt_size in current_settings.optimizerswitches) and + ((((Taicpu(hp1).opcode=A_ADD) or (Taicpu(hp1).opcode=A_SUB)) and + (Taicpu(hp1).oper[0]^.typ=top_const) and + (Taicpu(hp1).oper[1]^.typ=top_reg) and + (Taicpu(hp1).oper[0]^.val=1)) or + ((Taicpu(hp1).opcode=A_INC) or (Taicpu(hp1).opcode=A_DEC)) + ) then + begin + TransferUsedRegs(TmpUsedRegs); + UpdateUsedRegs(TmpUsedRegs, tai(p.next)); + + { search for an available register which is volatile } + regavailable:=false; + for reg in tcpuregisterset do + begin + if (reg in paramanager.get_volatile_registers_int(current_procinfo.procdef.proccalloption)) and + not(reg in TmpUsedRegs[R_INTREGISTER].GetUsedRegs) and + not(RegInInstruction(newreg(R_INTREGISTER,reg,R_SUBL),hp1)) +{$ifdef i386} + and (reg in [RS_EAX,RS_EBX,RS_ECX,RS_EDX]) +{$endif i386} + then + begin + regavailable:=true; + break; + end; + end; + + if regavailable then + begin + Taicpu(p).clearop(0); + Taicpu(p).ops:=1; + Taicpu(p).is_jmp:=false; + Taicpu(p).opcode:=A_SETcc; + DebugMsg(SPeepholeOptimization+'JccAdd2SetccAdd',p); + Taicpu(p).condition:=inverse_cond(Taicpu(p).condition); + Taicpu(p).loadreg(0,newreg(R_INTREGISTER,reg,R_SUBL)); + + if getsubreg(Taicpu(hp1).oper[1]^.reg)<>R_SUBL then + begin + case getsubreg(Taicpu(hp1).oper[1]^.reg) of + R_SUBW: + hp2:=Taicpu.op_reg_reg(A_MOVZX,S_BW,newreg(R_INTREGISTER,reg,R_SUBL), + newreg(R_INTREGISTER,reg,R_SUBW)); + R_SUBD, + R_SUBQ: + hp2:=Taicpu.op_reg_reg(A_MOVZX,S_BL,newreg(R_INTREGISTER,reg,R_SUBL), + newreg(R_INTREGISTER,reg,R_SUBD)); + else + Internalerror(2020030601); + end; + taicpu(hp2).fileinfo:=taicpu(hp1).fileinfo; + asml.InsertAfter(hp2,p); + end; + if (Taicpu(hp1).opcode=A_INC) or (Taicpu(hp1).opcode=A_DEC) then + begin + Taicpu(hp1).ops:=2; + Taicpu(hp1).loadoper(1,Taicpu(hp1).oper[0]^) + end; + Taicpu(hp1).loadreg(0,newreg(R_INTREGISTER,reg,getsubreg(Taicpu(hp1).oper[1]^.reg))); + AllocRegBetween(newreg(R_INTREGISTER,reg,getsubreg(Taicpu(hp1).oper[1]^.reg)),p,hp1,UsedRegs); + end; end; end;