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
Assignee Loading
Time tracking Loading