Optimize Low and High for Integer
## Summary Looking for a weird slowness in a code, I think I find a weird problem in optimizer. ## System Information Lazarus 2.3.0 (rev main-2_3-1804-g43e385a90b) FPC 3.3.1 x86_64-win64-win32/win64 ## Example Project ```pascal program project1; uses SysUtils; function Check1Integer(Index: Integer; const Value: TCharArray; const A: TCharArray): Integer; inline; var I, J: Integer; begin for I := Index to High(Value) do for J := Low(A) to High(A) do if Value[I] = A[J] then Exit(I); Result := -1; end; function Check2Integer(Index: Integer; const Value: TCharArray; const A: TCharArray): Integer; inline; var I, J, L, H: Integer; begin L := Low(A); H := High(A); for I := Index to High(Value) do for J := L to H do if Value[I] = A[J] then Exit(I); Result := -1; end; function Test1Check1Integer(const Value: TCharArray; const A: TCharArray): Integer; var I: Integer; begin Result := 0; I := 0; repeat I := Check1Integer(I, Value, A); I += 1; Result += 1; until I = 0; Result -= 1; end; function Test1Check2Integer(const Value: TCharArray; const A: TCharArray): Integer; var I: Integer; begin Result := 0; I := 0; repeat I := Check2Integer(I, Value, A); I += 1; Result += 1; until I = 0; Result -= 1; end; procedure Test2Check1Integer(const Value: TCharArray; const A: TCharArray); var I: Integer; begin I := 0; repeat I := Check1Integer(I, Value, A); I += 1; until I = 0; end; procedure Test2Check2Integer(const Value: TCharArray; const A: TCharArray); var I: Integer; begin I := 0; repeat I := Check2Integer(I, Value, A); I += 1; until I = 0; end; procedure Test3Check1Integer(const Value: TCharArray; const A: TCharArray); var I: Integer; begin for I := 0 to High(Value) do Check1Integer(I, Value, A); end; procedure Test3Check2Integer(const Value: TCharArray; const A: TCharArray); var I: Integer; begin for I := 0 to High(Value) do Check2Integer(I, Value, A); end; function Check1Int64(Index: Int64; const Value: TCharArray; const A: TCharArray): Int64; inline; var I, J: Int64; begin for I := Index to High(Value) do for J := Low(A) to High(A) do if Value[I] = A[J] then Exit(I); Result := -1; end; function Check2Int64(Index: Int64; const Value: TCharArray; const A: TCharArray): Int64; inline; var I, J, L, H: Int64; begin L := Low(A); H := High(A); for I := Index to High(Value) do for J := L to H do if Value[I] = A[J] then Exit(I); Result := -1; end; function Test1Check1Int64(const Value: TCharArray; const A: TCharArray): Int64; var I: Int64; begin Result := 0; I := 0; repeat I := Check1Int64(I, Value, A); I += 1; Result += 1; until I = 0; Result -= 1; end; function Test1Check2Int64(const Value: TCharArray; const A: TCharArray): Int64; var I: Int64; begin Result := 0; I := 0; repeat I := Check2Int64(I, Value, A); I += 1; Result += 1; until I = 0; Result -= 1; end; procedure Test2Check1Int64(const Value: TCharArray; const A: TCharArray); var I: Int64; begin I := 0; repeat I := Check1Int64(I, Value, A); I += 1; until I = 0; end; procedure Test2Check2Int64(const Value: TCharArray; const A: TCharArray); var I: Int64; begin I := 0; repeat I := Check2Int64(I, Value, A); I += 1; until I = 0; end; procedure Test3Check1Int64(const Value: TCharArray; const A: TCharArray); var I: Int64; begin for I := 0 to High(Value) do Check1Int64(I, Value, A); end; procedure Test3Check2Int64(const Value: TCharArray; const A: TCharArray); var I: Int64; begin for I := 0 to High(Value) do Check2Int64(I, Value, A); end; var A: TCharArray = (#0); Tick: QWord; Value: TCharArray; begin SetLength(Value, 1000000000); Tick := GetTickCount64; Test1Check1Integer(Value, A); WriteLn('Test1Check1Integer: ', GetTickCount64 - Tick); Tick := GetTickCount64; Test1Check2Integer(Value, A); WriteLn('Test1Check2Integer: ', GetTickCount64 - Tick); Tick := GetTickCount64; Test2Check1Integer(Value, A); WriteLn('Test2Check1Integer: ', GetTickCount64 - Tick); Tick := GetTickCount64; Test2Check2Integer(Value, A); WriteLn('Test2Check2Integer: ', GetTickCount64 - Tick); Tick := GetTickCount64; Test3Check1Integer(Value, A); WriteLn('Test3Check1Integer: ', GetTickCount64 - Tick); Tick := GetTickCount64; Test3Check2Integer(Value, A); WriteLn('Test3Check2Integer: ', GetTickCount64 - Tick); Tick := GetTickCount64; Test1Check1Int64(Value, A); WriteLn('Test1Check1Int64: ', GetTickCount64 - Tick); Tick := GetTickCount64; Test1Check2Int64(Value, A); WriteLn('Test1Check2Int64: ', GetTickCount64 - Tick); Tick := GetTickCount64; Test2Check1Int64(Value, A); WriteLn('Test2Check1Int64: ', GetTickCount64 - Tick); Tick := GetTickCount64; Test2Check2Int64(Value, A); WriteLn('Test2Check2Int64: ', GetTickCount64 - Tick); Tick := GetTickCount64; Test3Check1Int64(Value, A); WriteLn('Test3Check1Int64: ', GetTickCount64 - Tick); Tick := GetTickCount64; Test3Check2Int64(Value, A); WriteLn('Test3Check2Int64: ', GetTickCount64 - Tick); ReadLn; end. ``` ## What is the current bug behavior? These are the times, In all cases the Check1 and Check2 versions should take the same time or Check2 be slower. But it is not the case and even different results for Integer and Int64. This issue happen for three cases I marked in this log. ``` Test1Check1Integer: 1750[1] Test1Check2Integer: 1406[1] Test2Check1Integer: 1953 Test2Check2Integer: 1953 Test3Check1Integer: 1735[2] Test3Check2Integer: 1515[2] Test1Check1Int64: 1297 Test1Check2Int64: 1734 Test2Check1Int64: 1938[3] Test2Check2Int64: 1734[3] Test3Check1Int64: 1313 Test3Check2Int64: 1297 ``` Here is the assembly output: [project1.s](/uploads/4b6e91e3d42c07494bc5718a4daecf06/project1.s)
issue