3.3.1 generates wrong asm (intel 64bit) / wrong register
3.3.1 6a7d42bb with patch (below) similar to disable from #41422 (comment 2791138239)
Compile the testcase from martin_frb/lazarus@d38d998c with build mode "O2 riot Sa -gt NO gh"
Line 1700
procedure TGenLazRoundList.MoveRowsUp(const AFromIndex, AToIndex, ACount: Cardinal);
var
Cnt, Cap, CapBytes, c, Diff: Cardinal;
MPtr: TLazListClassesInternalMem.PMemRecord;
begin
assert((AToIndex>AFromIndex) and (AToIndex+ACount<=Count), 'TGenLazRoundList._MoveRowsUp: (AToIndex>AFromIndex) and (AToIndex+ACount<=Count)');
MPtr := FMem.FMem;
Cnt := MPtr^.Count;
Cap := FCapacityAccessor.ReadCapacity(MPtr);
generates this asm
lazlistclasses.pas:1710 MPtr := FMem.FMem;
00000001000535B6 488B45E0 mov rax,[rbp-$20]
00000001000535BA 488B18 mov rbx,[rax]
lazlistclasses.pas:1711 Cnt := MPtr^.Count;
00000001000535BD 817A04FFFFFF7F cmp [rdx+$04],$7FFFFFFF
00000001000535C4 7605 jbe +$05 # $00000001000535CB MOVEROWSUP+251 lazlistclasses.pas:1711
00000001000535C6 E8A5BCFBFF call -$0004435B # $000000010000F270 FPC_RANGEERROR
00000001000535CB 8B4304 mov eax,[rbx+$04]
00000001000535CE 8945FC mov [rbp-$04],eax
lazlistclasses.pas:1712 Cap := FCapacityAccessor.ReadCapacity(MPtr);
The range check test uses rdx. But the pointer is in rbx
Click to expand / patch 331
diff --git a/compiler/x86/aoptx86.pas b/compiler/x86/aoptx86.pas
index c0812b1a28..da4b239a7e 100644
--- a/compiler/x86/aoptx86.pas
+++ b/compiler/x86/aoptx86.pas
@@ -4220,44 +4220,47 @@ TJumpTrackingItem = class(TLinkedListItem)
mov mem, %reg"
}
- if not RegUsedBetween(taicpu(hp1).oper[1]^.reg, p, hp1) then
- begin
-{$ifdef x86_64}
- { If zero extending from 32-bit to 64-bit,
- we have to make sure the replaced
- register is the right size }
- taicpu(p).loadreg(1, newreg(R_INTREGISTER,getsupreg(taicpu(hp1).oper[1]^.reg),getsubreg(p_TargetReg)));
-{$else}
- taicpu(p).loadreg(1, taicpu(hp1).oper[1]^.reg);
-{$endif x86_64}
- DebugMsg(SPeepholeOptimization + 'MovMov2Mov 3a done', p);
- AllocRegBetween(taicpu(hp1).oper[1]^.reg, p, hp1, UsedRegs);
- RemoveInstruction(hp1);
- Result := True;
- Exit;
- end
- else if
- { Make sure that if a reference is used, its
- registers are not modified in between }
- not RefModifiedBetween(taicpu(p).oper[0]^.ref^, topsize2memsize[taicpu(p).opsize] shr 3, p, hp1) then
- begin
- if (taicpu(p).oper[0]^.ref^.base <> NR_NO){$ifdef x86_64} and (taicpu(p).oper[0]^.ref^.base <> NR_RIP){$endif x86_64} then
- AllocRegBetween(taicpu(p).oper[0]^.ref^.base, p, hp1, UsedRegs);
- if (taicpu(p).oper[0]^.ref^.index <> NR_NO) and (taicpu(p).oper[0]^.ref^.index <> taicpu(p).oper[0]^.ref^.base) then
- AllocRegBetween(taicpu(p).oper[0]^.ref^.index, p, hp1, UsedRegs);
-
- taicpu(hp1).loadref(0, taicpu(p).oper[0]^.ref^);
-
- if Assigned(taicpu(p).oper[0]^.ref^.symbol) then
- taicpu(p).oper[0]^.ref^.symbol.decrefs;
- if Assigned(taicpu(p).oper[0]^.ref^.relsymbol) then
- taicpu(p).oper[0]^.ref^.relsymbol.decrefs;
-
- DebugMsg(SPeepholeOptimization + 'MovMov2Mov 3 done', hp1);
- RemoveCurrentP(p);
- Result := True;
- Exit;
- end;
+;
+//if false then begin
+// if not RegUsedBetween(taicpu(hp1).oper[1]^.reg, p, hp1) then
+// begin
+//{$ifdef x86_64}
+// { If zero extending from 32-bit to 64-bit,
+// we have to make sure the replaced
+// register is the right size }
+// taicpu(p).loadreg(1, newreg(R_INTREGISTER,getsupreg(taicpu(hp1).oper[1]^.reg),getsubreg(p_TargetReg)));
+//{$else}
+// taicpu(p).loadreg(1, taicpu(hp1).oper[1]^.reg);
+//{$endif x86_64}
+// DebugMsg(SPeepholeOptimization + 'MovMov2Mov 3a done', p);
+// AllocRegBetween(taicpu(hp1).oper[1]^.reg, p, hp1, UsedRegs);
+// RemoveInstruction(hp1);
+// Result := True;
+// Exit;
+// end
+// else if
+// { Make sure that if a reference is used, its
+// registers are not modified in between }
+// not RefModifiedBetween(taicpu(p).oper[0]^.ref^, topsize2memsize[taicpu(p).opsize] shr 3, p, hp1) then
+// begin
+// if (taicpu(p).oper[0]^.ref^.base <> NR_NO){$ifdef x86_64} and (taicpu(p).oper[0]^.ref^.base <> NR_RIP){$endif x86_64} then
+// AllocRegBetween(taicpu(p).oper[0]^.ref^.base, p, hp1, UsedRegs);
+// if (taicpu(p).oper[0]^.ref^.index <> NR_NO) and (taicpu(p).oper[0]^.ref^.index <> taicpu(p).oper[0]^.ref^.base) then
+// AllocRegBetween(taicpu(p).oper[0]^.ref^.index, p, hp1, UsedRegs);
+//
+// taicpu(hp1).loadref(0, taicpu(p).oper[0]^.ref^);
+//
+// if Assigned(taicpu(p).oper[0]^.ref^.symbol) then
+// taicpu(p).oper[0]^.ref^.symbol.decrefs;
+// if Assigned(taicpu(p).oper[0]^.ref^.relsymbol) then
+// taicpu(p).oper[0]^.ref^.relsymbol.decrefs;
+//
+// DebugMsg(SPeepholeOptimization + 'MovMov2Mov 3 done', hp1);
+// RemoveCurrentP(p);
+// Result := True;
+// Exit;
+// end;
+//end;
top_ref:
if not RegInRef(p_TargetReg, taicpu(p).oper[0]^.ref^) then
begin