[fpc-pascal] Can FPC optimize: if (s[i]='a') or ...
Bernd Oppolzer
bernd.oppolzer at t-online.de
Sun Apr 14 15:37:29 CEST 2019
Am 13.04.2019 um 21:55 schrieb Ralf Quint:
> On 4/13/2019 12:30 PM, Alexey Tor. wrote:
>> E.g. i have a loop which test each s[i] char for several cases: 'a',
>> 'b', 'c'.
>>
>> for i:= 1 to length(s) do
>>
>> if (s[i]='a') or (s[i]='b') or (s[i]='c') then ...
>>
>> Can FPC optimize it so it only reads s[i] once (to register), not 3
>> times?
>>
> How about writing it in Pascal, something like
>
> if s[i] in ['a'..'c'] then
>
> or in case of no-sequential characters/values
>
> if s[i] in ['a', 'b', 'c'] then...
>
>
> Ralf
>
I'd like to second that ... the benefit that the optimizer may get
when IN is used ...
I would like to show you what my New Stanford Pascal compiler does;
it does not eliminate the common expressions s[i], but evaluates
them 3 times, given the original coding. But when the IN expression is used
(this coding: if s[i] in ['a', 'b', 'c'] then...)
it does a very good job. Because the three constants in the set are a
close range without holes in it, it checks in fact the range.
This is how it looks in IBM 370 ASSEMBLY language:
@@ 01AE: SR 3,3 -- clear register 3
@@ 01B0: IC 3,404(13,2) -- insert character s[i] into
register 3 (register 2 has index i, 404/13 is the address of s)
@@ 01B4: AH 3,=H'-97' -- subtract constant 'a' - should be
EBCDIC 'a', but is ASCII 'a', because I tested on the PC :-)
@@ 01B8: CL 3,=F'2' -- check, if register 3 is between 0 and 2
@@ 01BC: BC 2,L12 -- branch, if not
This is the result after the second step of the translation;
the first step is the translation to P-Code. The P-Code looks like this
(the Index I is on top of the stack at the beginning, the address of
S at the second position):
01AE: DEC I,1 -- dec top of stack
01AE: IXA 1 -- use top of stack as index for
address at second position
01AE: IND C,0 -- replace top of stack (= address)
with content of type char
01AE: ORD -- convert to integer (does nothing)
01B4: LCA S,C32'abc' -- load character set constant
01B4: SLD 32,432 -- convert to binary set
representation
01B4: INN -- implement IN on elements on stack
01BC: FJP L12 -- jump false
On the IBM mainframe, this P-Code is translated to what you see above.
On the other platforms (Windows, Linux, ...), the P-Code is interpreted -
a version of the compiler which generates native code on these platforms
has still to be done. But anyway: the language is fully portable, the
results
are the same. (The P-Code is portable, the 370 implementation is of course
NOT portable - hence the problem when testing the 370 translation on the
PC).
The optimization (implementing IN as a range check in this case) is
in fact done in stage 2, that is: in the P-Code to 370 translator.
The credits for this very fine compiler technology (which is about
40 years old) does not belong to me, but to many other people who
worked on this in the 1975 to 1990 era. I only did some extensions
to it in the last few years and ported the compiler to Windows and
Linux etc.
More information:
http://bernd-oppolzer.de/job9.htm
https://www.facebook.com/StanfordPascal
Kind regards
Bernd
More information about the fpc-pascal
mailing list