diff --git a/compiler/x86/aoptx86.pas b/compiler/x86/aoptx86.pas index f07f8d7e93..a70f110de5 100644 --- a/compiler/x86/aoptx86.pas +++ b/compiler/x86/aoptx86.pas @@ -2292,6 +2292,8 @@ unit aoptx86; var hp1, hp2, hp3: tai; l : ASizeInt; + ref: Integer; + saveref: treference; begin Result:=false; { removes seg register prefixes from LEA operations, as they @@ -2318,11 +2320,8 @@ unit aoptx86; end else if (taicpu(p).oper[0]^.ref^.offset = 0) then begin - hp1:=taicpu(p.Next); DebugMsg(SPeepholeOptimization + 'Lea2Nop done',p); - asml.remove(p); - p.free; - p:=hp1; + RemoveCurrentP(p); Result:=true; exit; end @@ -2407,10 +2406,76 @@ unit aoptx86; DebugMsg(SPeepholeOptimization + 'LeaLea2Lea done',p); inc(taicpu(hp1).oper[0]^.ref^.offset,taicpu(p).oper[0]^.ref^.offset); taicpu(hp1).oper[0]^.ref^.base:=taicpu(p).oper[0]^.ref^.base; - asml.Remove(p); - p.Free; - p:=hp1; + RemoveCurrentP(p); result:=true; + exit; + end; + { changes + lea , reg1 + ...,,... + to + ...,,... } + if (taicpu(p).oper[1]^.reg<>current_procinfo.framepointer) and + (taicpu(p).oper[1]^.reg<>NR_STACK_POINTER_REG) and + GetNextInstruction(p,hp1) and + (hp1.typ=ait_instruction) and + not(MatchInstruction(hp1,A_LEA,[])) then + begin + if (taicpu(hp1).ops>=1) and (taicpu(hp1).oper[0]^.typ=top_ref) and RegInOp(taicpu(p).oper[1]^.reg,taicpu(hp1).oper[0]^) then + ref:=0 + else if (taicpu(hp1).ops>=2) and (taicpu(hp1).oper[1]^.typ=top_ref) and RegInOp(taicpu(p).oper[1]^.reg,taicpu(hp1).oper[1]^) then + ref:=1 + else + ref:=-1; + if (ref<>-1) and + ((taicpu(hp1).oper[ref]^.ref^.base=taicpu(p).oper[1]^.reg) xor (taicpu(hp1).oper[ref]^.ref^.index=taicpu(p).oper[1]^.reg)) then + begin + saveref:=taicpu(hp1).oper[ref]^.ref^; + if taicpu(hp1).oper[ref]^.ref^.base=taicpu(p).oper[1]^.reg then + taicpu(hp1).oper[ref]^.ref^.base:=NR_NO + else if taicpu(hp1).oper[ref]^.ref^.index=taicpu(p).oper[1]^.reg then + taicpu(hp1).oper[ref]^.ref^.index:=NR_NO + else + Internalerror(2019111201); + if ((taicpu(hp1).oper[ref]^.ref^.base=taicpu(p).oper[1]^.reg) or (taicpu(hp1).oper[ref]^.ref^.scalefactor in [0,1])) and + ((taicpu(p).oper[0]^.ref^.base=NR_NO) or (taicpu(hp1).oper[ref]^.ref^.base=NR_NO)) and + ((taicpu(p).oper[0]^.ref^.index=NR_NO) or (taicpu(hp1).oper[ref]^.ref^.index=NR_NO)) and + ((taicpu(p).oper[0]^.ref^.symbol=nil) or (taicpu(hp1).oper[ref]^.ref^.symbol=nil)) and + ((taicpu(p).oper[0]^.ref^.relsymbol=nil) or (taicpu(hp1).oper[ref]^.ref^.relsymbol=nil)) and + ((taicpu(p).oper[0]^.ref^.scalefactor in [0,1]) or (taicpu(hp1).oper[ref]^.ref^.scalefactor in [0,1])) and + (taicpu(p).oper[0]^.ref^.segment=NR_NO) and (taicpu(hp1).oper[ref]^.ref^.segment=NR_NO) +{$ifdef x86_64} + and (abs(taicpu(hp1).oper[ref]^.ref^.offset+taicpu(p).oper[0]^.ref^.offset)<=$7fffffff) +{$endif x86_64} + then + begin + if not(RegInInstruction(taicpu(p).oper[1]^.reg,taicpu(hp1))) then + begin + TransferUsedRegs(TmpUsedRegs); + UpdateUsedRegs(TmpUsedRegs, tai(p.next)); + if not(RegUsedAfterInstruction(taicpu(p).oper[1]^.reg,hp1,TmpUsedRegs)) then + begin + DebugMsg(SPeepholeOptimization + 'LeaOp2Op done',p); + if taicpu(p).oper[0]^.ref^.base<>NR_NO then + taicpu(hp1).oper[ref]^.ref^.base:=taicpu(p).oper[0]^.ref^.base; + if taicpu(p).oper[0]^.ref^.index<>NR_NO then + taicpu(hp1).oper[ref]^.ref^.index:=taicpu(p).oper[0]^.ref^.index; + if taicpu(p).oper[0]^.ref^.symbol<>nil then + taicpu(hp1).oper[ref]^.ref^.symbol:=taicpu(p).oper[0]^.ref^.symbol; + if taicpu(p).oper[0]^.ref^.relsymbol<>nil then + taicpu(hp1).oper[ref]^.ref^.relsymbol:=taicpu(p).oper[0]^.ref^.relsymbol; + if not(taicpu(p).oper[0]^.ref^.scalefactor in [0,1]) then + taicpu(hp1).oper[ref]^.ref^.scalefactor:=taicpu(p).oper[0]^.ref^.scalefactor; + inc(taicpu(hp1).oper[ref]^.ref^.offset,taicpu(p).oper[0]^.ref^.offset); + RemoveCurrentP(p); + result:=true; + exit; + end + end; + end; + { recover } + taicpu(hp1).oper[ref]^.ref^:=saveref; + end; end; { replace lea x(stackpointer),stackpointer