Wrong offsets in array of strings of size 5 or 11 when peephole optimizer enabled for 80386 CPU
## Summary When accessing elements in an array of string[5] or string[11], byte offsets from the base pointer of the array are calculated wrong. ## System Information - **Operating system:** Go32v2 and 32-bit Windows. - **Processor architecture:** x86 - **Compiler version:** 3.x - **Device:** Computer ## Steps to reproduce Compile the example project. For Go32v2: ``` fpc -Tgo32v2 -O1 -Op80386 -Oopeephole test.pas ``` For 32-bit Windows: ``` fpc -Twin32 -O1 -Op80386 -Oopeephole test.pas ``` It is important to enable peephole optimization and set CPU to 80386. ## Example project ``` const StrLen = 11 {5 or 11}; Str: array [0..15] of string[StrLen] = ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15'); var I: Integer; S: ^string; begin WriteLn('@Str=', HexStr(PtrUInt(@Str), 8)); for I := Low(Str) to High(Str) div 4 do begin {$IFDEF CPU16} asm jmp @1; nop; int3; @1: end; {$ELSE} asm jmp .L1; nop; int3; .L1: end; {$ENDIF} S := @Str[I]; WriteLn('Str[', I, ']=@', HexStr(PtrUInt(S), 8), '=@Str+', PtrUInt(S) - PtrUInt(@Str), '=''', S^, ''''); end; end. ``` ## What is the current bug behavior? For string[5] (array element size of 6 bytes), index is multiplied by 10 to get offset. For string[11] (12 bytes), index is multiplied by 36. ## What is the expected (correct) behavior? Index should be multipled by element size to get byte offset. Behavior is correct in FPC 2.6.4; also in FPC 3.x for i8086. ## Relevant logs and/or screenshots For string[5]: ``` @Str=004090D0 Str[0]=@004090D0=@Str+0='0' Str[1]=@004090DA=@Str+10=' 2 3 4 5 6 ' Str[2]=@004090E4=@Str+20='' Str[3]=@004090EE=@Str+30='5' ``` For string[11]: ``` @Str=004090D0 Str[0]=@004090D0=@Str+0='0' Str[1]=@004090F4=@Str+36='3' Str[2]=@00409118=@Str+72='6' Str[3]=@0040913C=@Str+108='9' ``` Look for bytes 0x90 0xCC in the compiled code to see what happens. Multiplication of eax by 6 is converted to: ``` 8D 04 00 lea eax,[eax][eax] 8D 04 80 lea eax,[eax][eax]*4 ``` which is actually multiplication by 10. Multiplication of eax by 12 becomes: ``` 8D 04 85 00 00 00 00 lea eax,[eax]*4[0] 8D 04 C0 lea eax,[eax][eax]*8 ``` that is, multiplication by 36. In FPC 2.6.4, these compiled correctly to: ``` 8D 04 40 lea eax,[eax][eax]*2 01 C0 add eax,eax ``` and ``` 8D 04 40 lea eax,[eax][eax]*2 8D 04 85 00 00 00 00 lea eax,[eax]*4[0] ``` ## Possible fixes Probably, the peephole optimizer optimizes multiplications by 6 and 12 incorrectly. In file \fpc-3.2.2\compiler\i386\aoptcpu.pas of the source, the replacement seems to be correct; the multiplication of an integer variable by a constant of 6 or 12 is also correct. Maybe, array offset calculation is using another code path?
issue