From f85aa24ad0f75a4a32c03ea62503d4cf2901ac2c Mon Sep 17 00:00:00 2001 From: "J. Gareth \"Curious Kit\" Moreton" Date: Tue, 25 Feb 2025 23:56:27 +0000 Subject: [PATCH] * x86: Refactoring register update code in "OptPass2ADD" and "OptPass2SUB" --- compiler/x86/aoptx86.pas | 127 +++++++++++++++++++++------------------ 1 file changed, 69 insertions(+), 58 deletions(-) diff --git a/compiler/x86/aoptx86.pas b/compiler/x86/aoptx86.pas index 0de1c307fb..3de49d5f50 100644 --- a/compiler/x86/aoptx86.pas +++ b/compiler/x86/aoptx86.pas @@ -15564,6 +15564,7 @@ unit aoptx86; NewRef: TReference; Distance: Cardinal; TempTracking: TAllUsedRegs; + DoAddMov2Lea: Boolean; { This entire nested function is used in an if-statement below, but we want to avoid all the used reg transfers and GetNextInstruction calls @@ -15573,10 +15574,11 @@ unit aoptx86; hp2: tai; begin TransferUsedRegs(TmpUsedRegs); - hp2 := p; - repeat - UpdateUsedRegs(TmpUsedRegs, tai(hp2.Next)); - until not (cs_opt_level3 in current_settings.optimizerswitches) or not GetNextInstruction(hp2, hp2) or (hp2 = hp1); + if (cs_opt_level3 in current_settings.optimizerswitches) then + UpdateUsedRegsBetween(TmpUsedRegs, p, hp1) + else + { p and hp1 will be adjacent } + UpdateUsedRegs(TmpUsedRegs, tai(p.Next)); Result := not RegUsedAfterInstruction(taicpu(p).oper[1]^.reg, hp1, TmpUsedRegs); end; @@ -15625,11 +15627,13 @@ unit aoptx86; begin { Update the register tracking to the MOV instruction } CopyUsedRegs(TempTracking); - hp2 := p; - repeat - UpdateUsedRegs(tai(hp2.Next)); - until not (cs_opt_level3 in current_settings.optimizerswitches) or not GetNextInstruction(hp2, hp2) or (hp2 = hp1); + if (cs_opt_level3 in current_settings.optimizerswitches) then + UpdateUsedRegsBetween(UsedRegs, p, hp1) + else + { p and hp1 will be adjacent } + UpdateUsedRegs(UsedRegs, tai(p.Next)); + hp2 := hp1; { if hp1 <> hp2 after the call, then hp1 got removed, so let OptPass2ADD get called again } if OptPass2MOV(hp1) and (hp1 <> hp2) then @@ -15750,18 +15754,22 @@ unit aoptx86; ) then begin TransferUsedRegs(TmpUsedRegs); - hp2 := p; - repeat - UpdateUsedRegs(TmpUsedRegs, tai(hp2.Next)); - until not (cs_opt_level3 in current_settings.optimizerswitches) or not GetNextInstruction(hp2, hp2) or (hp2 = hp1); + if (cs_opt_level3 in current_settings.optimizerswitches) then + UpdateUsedRegsBetween(TmpUsedRegs, p, hp1) + else + { p and hp1 will be adjacent } + UpdateUsedRegs(TmpUsedRegs, tai(p.Next)); if ( + SetAndTest( + ( + not RegUsedAfterInstruction(taicpu(p).oper[1]^.reg, hp1, TmpUsedRegs) and + not RegUsedAfterInstruction(NR_DEFAULTFLAGS, hp1, TmpUsedRegs) + ), + DoAddMov2Lea + ) or { Don't do AddMov2LeaAdd under -Os, but do allow AddMov2Lea } - not (cs_opt_size in current_settings.optimizerswitches) or - ( - not RegUsedAfterInstruction(taicpu(p).oper[1]^.reg, hp1, TmpUsedRegs) and - not RegUsedAfterInstruction(NR_DEFAULTFLAGS, hp1, TmpUsedRegs) - ) + not (cs_opt_size in current_settings.optimizerswitches) ) then begin { Change the MOV instruction to a LEA instruction, and update the @@ -15775,8 +15783,18 @@ unit aoptx86; taicpu(hp1).opcode := A_LEA; taicpu(hp1).loadref(0, NewRef); - if RegUsedAfterInstruction(NewRef.base, hp1, TmpUsedRegs) or - RegUsedAfterInstruction(NR_DEFAULTFLAGS, hp1, TmpUsedRegs) then + if DoAddMov2Lea then + begin + { Since %reg1 or the flags aren't used afterwards, we can delete p completely } + DebugMsg(SPeepholeOptimization + 'AddMov2Lea', hp1); + + if (cs_opt_level3 in current_settings.optimizerswitches) then + { hp1 may not be the immediate next instruction under -O3 } + RemoveCurrentp(p) + else + RemoveCurrentp(p, hp1); + end + else begin hp2 := tai(hp1.Next); { for the benefit of AllocRegBetween } @@ -15787,17 +15805,6 @@ unit aoptx86; DebugMsg(SPeepholeOptimization + 'AddMov2LeaAdd', p); p := hp1; - end - else - begin - { Since %reg1 or the flags aren't used afterwards, we can delete p completely } - DebugMsg(SPeepholeOptimization + 'AddMov2Lea', hp1); - - if (cs_opt_level3 in current_settings.optimizerswitches) then - { hp1 may not be the immediate next instruction under -O3 } - RemoveCurrentp(p) - else - RemoveCurrentp(p, hp1); end; Result := True; @@ -15923,6 +15930,7 @@ unit aoptx86; NewRef: TReference; Distance: Cardinal; TempTracking: TAllUsedRegs; + DoSubMov2Lea: Boolean; begin Result := False; @@ -15968,11 +15976,13 @@ unit aoptx86; begin { Update the register tracking to the MOV instruction } CopyUsedRegs(TempTracking); - hp2 := p; - repeat - UpdateUsedRegs(tai(hp2.Next)); - until not (cs_opt_level3 in current_settings.optimizerswitches) or not GetNextInstruction(hp2, hp2) or (hp2 = hp1); + if (cs_opt_level3 in current_settings.optimizerswitches) then + UpdateUsedRegsBetween(UsedRegs, p, hp1) + else + { p and hp1 will be adjacent } + UpdateUsedRegs(UsedRegs, tai(p.Next)); + hp2 := hp1; { if hp1 <> hp2 after the call, then hp1 got removed, so let OptPass2SUB get called again } if OptPass2MOV(hp1) and (hp1 <> hp2) then @@ -16023,18 +16033,22 @@ unit aoptx86; ) then begin TransferUsedRegs(TmpUsedRegs); - hp2 := p; - repeat - UpdateUsedRegs(TmpUsedRegs, tai(hp2.Next)); - until not (cs_opt_level3 in current_settings.optimizerswitches) or not GetNextInstruction(hp2, hp2) or (hp2 = hp1); + if (cs_opt_level3 in current_settings.optimizerswitches) then + UpdateUsedRegsBetween(TmpUsedRegs, p, hp1) + else + { p and hp1 will be adjacent } + UpdateUsedRegs(TmpUsedRegs, tai(p.Next)); if ( + SetAndTest( + ( + not RegUsedAfterInstruction(taicpu(p).oper[1]^.reg, hp1, TmpUsedRegs) and + not RegUsedAfterInstruction(NR_DEFAULTFLAGS, hp1, TmpUsedRegs) + ), + DoSubMov2Lea + ) or { Don't do SubMov2LeaSub under -Os, but do allow SubMov2Lea } - not (cs_opt_size in current_settings.optimizerswitches) or - ( - not RegUsedAfterInstruction(taicpu(p).oper[1]^.reg, hp1, TmpUsedRegs) and - not RegUsedAfterInstruction(NR_DEFAULTFLAGS, hp1, TmpUsedRegs) - ) + not (cs_opt_size in current_settings.optimizerswitches) ) then begin { Change the MOV instruction to a LEA instruction, and update the @@ -16047,10 +16061,18 @@ unit aoptx86; taicpu(hp1).opcode := A_LEA; taicpu(hp1).loadref(0, NewRef); - TransferUsedRegs(TmpUsedRegs); - UpdateUsedRegs(TmpUsedRegs, tai(p.Next)); - if RegUsedAfterInstruction(NewRef.base, hp1, TmpUsedRegs) or - RegUsedAfterInstruction(NR_DEFAULTFLAGS, hp1, TmpUsedRegs) then + if DoSubMov2Lea then + begin + { Since %reg1 or the flags aren't used afterwards, we can delete p completely } + DebugMsg(SPeepholeOptimization + 'SubMov2Lea', hp1); + + if (cs_opt_level3 in current_settings.optimizerswitches) then + { hp1 may not be the immediate next instruction under -O3 } + RemoveCurrentp(p) + else + RemoveCurrentp(p, hp1); + end + else begin hp2 := tai(hp1.Next); { for the benefit of AllocRegBetween } @@ -16061,17 +16083,6 @@ unit aoptx86; DebugMsg(SPeepholeOptimization + 'SubMov2LeaSub', p); p := hp1; - end - else - begin - { Since %reg1 or the flags aren't used afterwards, we can delete p completely } - DebugMsg(SPeepholeOptimization + 'SubMov2Lea', hp1); - - if (cs_opt_level3 in current_settings.optimizerswitches) then - { hp1 may not be the immediate next instruction under -O3 } - RemoveCurrentp(p) - else - RemoveCurrentp(p, hp1); end; Result := True;