[Oberon] Oberon performance (long)
Vasile Rotaru
vrotaru at seznam.cz
Thu Apr 17 23:37:56 CEST 2003
Hi
> This is correct. A few instructions could be removed.
> There are basically two approaches: finding a small local optimization
> which achieves this (e.g. the register allocator could remember the
> last value loaded in a register and propose the same register instead
> of loading it again), or implementing CSE (common subexpression
> elimination) in the compiler.
>
> The compiler first emits the code in an intermediate representation (LIR)
> (defined
> in PCLIR). Then the installed backend (PCG386 + PCO for i386) will
> translate the LIR to i386 after a small optimization step to reconstruct the
> complex addressing modes instead (and at the same time remove a few
> instructions).
>
Well, it was the first thing I was thinking about, and may be I'll go this way (or both woys). But just now
a small modification in PCC.Field has compiled my toy example rather well, and I'm interested to see if
it could be done at the level of intermediate code generation. Here are the relevant bits.
PROCEDURE Field*(code: Code; VAR x: Item; fld: PCT.Field);
BEGIN
(* new code *)
IF (lastLoad.level = x.level) & (lastLoad.offs = x.offs) THEN
x := lastLoad;
ELSE
LoadAdr(code, x);
lastLoad := x;
END; (* if *)
(* old code
LoadAdr(code, x);
*)
x.mode := RegRel; x.offs := fld.adr(PCBT.Variable).offset; x.type := fld.type;
x.deref := FALSE
END Field;
Of course, ``lastLoad'' is new variable of type ``Item'', and it is initialazed like this
lastLoad.level := -1;
As for the results:
MODULE Simple;
TYPE
Simple = OBJECT
VAR
x, y, z: LONGINT;
PROCEDURE &Init;
BEGIN
x := 1; y := 2; z := 3;
END Init;
PROCEDURE Sum () : LONGINT;
BEGIN
RETURN x + y + z
END Sum;
END Simple;
END Simple.
Decoder.Decode Simple.Obx ~
PROCEDURE Simple.Init
0007H: 55 PUSH EBP
0008H: 8B EC MOV EBP,ESP
000AH: 8B 5D 08 MOV EBX,8[EBP]
000DH: C7 03 01 00 00 00 MOV 0[EBX],1
0013H: C7 43 04 02 00 00 00 MOV 4[EBX],2
001AH: C7 43 08 03 00 00 00 MOV 8[EBX],3
0021H: 8B E5 MOV ESP,EBP
0023H: 5D POP EBP
0024H: C2 04 00 RET 4
PROCEDURE Simple.Sum
0027H: 55 PUSH EBP
0028H: 8B EC MOV EBP,ESP
002AH: 8B 5D 08 MOV EBX,8[EBP]
002DH: 8B 03 MOV EAX,0[EBX]
002FH: 03 43 04 ADD EAX,4[EBX]
0032H: 03 43 08 ADD EAX,8[EBX]
0035H: 8B E5 MOV ESP,EBP
0037H: 5D POP EBP
0038H: C2 04 00 RET 4
003BH: 6A 03 PUSH 3
003DH: CC INT 3
(Of course it fails, on any real-world programs.)
I have tried to generalize this scheme, but I didn't succeed very much. In fact at all.
There is one more question. Is the code generation done concurrently?
And how can I know which data belongs to which process? Using AosActive.ActiveObject() ?
May this be a problem if I choose to modify the register allocator in x86 backend?
Any way, I will have to look deeply into the code. But this is a nice intelectual challenge and I like it.
Regards
--
How apt the poor are to be proud.
-- William Shakespeare, "Twelfth-Night"
More information about the Oberon
mailing list