[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 
      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 
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 

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:


Kind regards


More information about the fpc-pascal mailing list