diff --git a/compiler/i386/aoptcpu.pas b/compiler/i386/aoptcpu.pas index 8e9becd234..c0b721cbff 100644 --- a/compiler/i386/aoptcpu.pas +++ b/compiler/i386/aoptcpu.pas @@ -525,51 +525,6 @@ var GetFinalDestination := true; end; - function DoSubAddOpt(var p: tai): Boolean; - begin - DoSubAddOpt := False; - if GetLastInstruction(p, hp1) and - (hp1.typ = ait_instruction) and - (taicpu(hp1).opsize = taicpu(p).opsize) then - case taicpu(hp1).opcode Of - A_DEC: - if (taicpu(hp1).oper[0]^.typ = top_reg) and - (taicpu(hp1).oper[0]^.reg = taicpu(p).oper[1]^.reg) then - begin - taicpu(p).loadConst(0,taicpu(p).oper[0]^.val+1); - asml.remove(hp1); - hp1.free; - end; - A_SUB: - if (taicpu(hp1).oper[0]^.typ = top_const) and - (taicpu(hp1).oper[1]^.typ = top_reg) and - (taicpu(hp1).oper[1]^.reg = taicpu(p).oper[1]^.reg) then - begin - taicpu(p).loadConst(0,taicpu(p).oper[0]^.val+taicpu(hp1).oper[0]^.val); - asml.remove(hp1); - hp1.free; - end; - A_ADD: - if (taicpu(hp1).oper[0]^.typ = top_const) and - (taicpu(hp1).oper[1]^.typ = top_reg) and - (taicpu(hp1).oper[1]^.reg = taicpu(p).oper[1]^.reg) then - begin - taicpu(p).loadConst(0,taicpu(p).oper[0]^.val-taicpu(hp1).oper[0]^.val); - asml.remove(hp1); - hp1.free; - if (taicpu(p).oper[0]^.val = 0) then - begin - hp1 := tai(p.next); - asml.remove(p); - p.free; - if not GetLastInstruction(hp1, p) then - p := hp1; - DoSubAddOpt := True; - end - end; - end; - end; - begin p := BlockStart; ClearUsedRegs; @@ -1116,50 +1071,8 @@ begin end end; A_SUB: - { * change "subl $2, %esp; pushw x" to "pushl x"} - { * change "sub/add const1, reg" or "dec reg" followed by - "sub const2, reg" to one "sub ..., reg" } - begin - if (taicpu(p).oper[0]^.typ = top_const) and - (taicpu(p).oper[1]^.typ = top_reg) then - if (taicpu(p).oper[0]^.val = 2) and - (taicpu(p).oper[1]^.reg = NR_ESP) and - { Don't do the sub/push optimization if the sub } - { comes from setting up the stack frame (JM) } - (not getLastInstruction(p,hp1) or - (hp1.typ <> ait_instruction) or - (taicpu(hp1).opcode <> A_MOV) or - (taicpu(hp1).oper[0]^.typ <> top_reg) or - (taicpu(hp1).oper[0]^.reg <> NR_ESP) or - (taicpu(hp1).oper[1]^.typ <> top_reg) or - (taicpu(hp1).oper[1]^.reg <> NR_EBP)) then - begin - hp1 := tai(p.next); - while Assigned(hp1) and - (tai(hp1).typ in [ait_instruction]+SkipInstr) and - not RegReadByInstruction(NR_ESP,hp1) and - not RegModifiedByInstruction(NR_ESP,hp1) do - hp1 := tai(hp1.next); - if Assigned(hp1) and - (tai(hp1).typ = ait_instruction) and - (taicpu(hp1).opcode = A_PUSH) and - (taicpu(hp1).opsize = S_W) then - begin - taicpu(hp1).changeopsize(S_L); - if taicpu(hp1).oper[0]^.typ=top_reg then - setsubreg(taicpu(hp1).oper[0]^.reg,R_SUBWHOLE); - hp1 := tai(p.next); - asml.remove(p); - p.free; - p := hp1; - continue - end; - if DoSubAddOpt(p) then - continue; - end - else if DoSubAddOpt(p) then - continue - end; + if OptPass1Sub(p) then + continue; A_VMOVAPS, A_VMOVAPD: if OptPass1VMOVAP(p) then diff --git a/compiler/i8086/aoptcpu.pas b/compiler/i8086/aoptcpu.pas index 544c2c5746..62cd5a3e56 100644 --- a/compiler/i8086/aoptcpu.pas +++ b/compiler/i8086/aoptcpu.pas @@ -109,7 +109,9 @@ unit aoptcpu; result:=true; end; end; - end + A_SUB: + result:=OptPass1Sub(p); + end; end end; end; diff --git a/compiler/x86/aoptx86.pas b/compiler/x86/aoptx86.pas index e2072fdf7e..a39dbb0761 100644 --- a/compiler/x86/aoptx86.pas +++ b/compiler/x86/aoptx86.pas @@ -55,6 +55,8 @@ unit aoptx86; class function isFoldableArithOp(hp1 : taicpu; reg : tregister) : boolean; procedure RemoveLastDeallocForFuncRes(p : tai); + function DoSubAddOpt(var p : tai) : Boolean; + function PrePeepholeOptSxx(var p : tai) : boolean; function OptPass1AND(var p : tai) : boolean; @@ -66,6 +68,7 @@ unit aoptx86; function OptPass1MOVXX(var p : tai) : boolean; function OptPass1OP(const p : tai) : boolean; function OptPass1LEA(var p : tai) : boolean; + function OptPass1Sub(var p : tai) : boolean; function OptPass2MOV(var p : tai) : boolean; function OptPass2Imul(var p : tai) : boolean; @@ -1875,6 +1878,99 @@ unit aoptx86; end; + function TX86AsmOptimizer.DoSubAddOpt(var p: tai): Boolean; + var + hp1 : tai; + begin + DoSubAddOpt := False; + if GetLastInstruction(p, hp1) and + (hp1.typ = ait_instruction) and + (taicpu(hp1).opsize = taicpu(p).opsize) then + case taicpu(hp1).opcode Of + A_DEC: + if (taicpu(hp1).oper[0]^.typ = top_reg) and + MatchOperand(taicpu(hp1).oper[1]^,taicpu(p).oper[1]^) then + begin + taicpu(p).loadConst(0,taicpu(p).oper[0]^.val+1); + asml.remove(hp1); + hp1.free; + end; + A_SUB: + if MatchOpType(taicpu(hp1),top_const,top_reg) and + MatchOperand(taicpu(hp1).oper[1]^,taicpu(p).oper[1]^) then + begin + taicpu(p).loadConst(0,taicpu(p).oper[0]^.val+taicpu(hp1).oper[0]^.val); + asml.remove(hp1); + hp1.free; + end; + A_ADD: + if MatchOpType(taicpu(hp1),top_const,top_reg) and + MatchOperand(taicpu(hp1).oper[1]^,taicpu(p).oper[1]^) then + begin + taicpu(p).loadConst(0,taicpu(p).oper[0]^.val-taicpu(hp1).oper[0]^.val); + asml.remove(hp1); + hp1.free; + if (taicpu(p).oper[0]^.val = 0) then + begin + hp1 := tai(p.next); + asml.remove(p); + p.free; + if not GetLastInstruction(hp1, p) then + p := hp1; + DoSubAddOpt := True; + end + end; + end; + end; + + + function TX86AsmOptimizer.OptPass1Sub(var p : tai) : boolean; + var + hp1 : tai; + begin + Result:=false; + { * change "subl $2, %esp; pushw x" to "pushl x"} + { * change "sub/add const1, reg" or "dec reg" followed by + "sub const2, reg" to one "sub ..., reg" } + if MatchOpType(taicpu(p),top_const,top_reg) then + begin +{$ifdef i386} + if (taicpu(p).oper[0]^.val = 2) and + (taicpu(p).oper[1]^.reg = NR_ESP) and + { Don't do the sub/push optimization if the sub } + { comes from setting up the stack frame (JM) } + (not(GetLastInstruction(p,hp1)) or + not(MatchInstruction(hp1,A_MOV,[S_L]) and + MatchOperand(taicpu(hp1).oper[0]^,NR_ESP) and + MatchOperand(taicpu(hp1).oper[0]^,NR_EBP))) then + begin + hp1 := tai(p.next); + while Assigned(hp1) and + (tai(hp1).typ in [ait_instruction]+SkipInstr) and + not RegReadByInstruction(NR_ESP,hp1) and + not RegModifiedByInstruction(NR_ESP,hp1) do + hp1 := tai(hp1.next); + if Assigned(hp1) and + MatchInstruction(hp1,A_PUSH,[S_W]) then + begin + taicpu(hp1).changeopsize(S_L); + if taicpu(hp1).oper[0]^.typ=top_reg then + setsubreg(taicpu(hp1).oper[0]^.reg,R_SUBWHOLE); + hp1 := tai(p.next); + asml.remove(p); + p.free; + p := hp1; + Result:=true; + exit; + end; + end; +{$endif i386} + if DoSubAddOpt(p) then + Result:=true; + end; + end; + + function TX86AsmOptimizer.OptPass2MOV(var p : tai) : boolean; var TmpUsedRegs : TAllUsedRegs; diff --git a/compiler/x86_64/aoptcpu.pas b/compiler/x86_64/aoptcpu.pas index 23491af1d7..3155e20113 100644 --- a/compiler/x86_64/aoptcpu.pas +++ b/compiler/x86_64/aoptcpu.pas @@ -106,6 +106,8 @@ uses result:=OptPass1MOVXX(p); A_LEA: result:=OptPass1LEA(p); + A_SUB: + result:=OptPass1Sub(p); end; end; end;