#Optimizer Useless!?
20-Jul-93 20:29:43
Sb: #7227-#Optimizer Useless!?
Fm: Ken Broomfield 70650,523
To: Kevin Irlen 76666,2005
Here is a short program which illustrates the problem with optimization not
occurring in functions containing toolbox calls:
class CBase
{
public:
short a, b, c;
inline CBase () { a = 1; b = 2; c = 3; }
inline void foobar () { a = b + c * 8 + b * 7; }
inline void btoc () { b = c; }
inline void nothing () { }
};
class CSub: public CBase
{
public:
inline CSub () { }
inline void foobar () { inherited::foobar (); }
inline void btoc () { if (0) foobar (); inherited::btoc (); }
};
void takebase (CBase &b) { }
void localSysBeep (short s) { }
void main (void)
{
CSub s;
s.foobar ();
s.btoc ();
s.nothing ();
takebase (s); // This call is needed so that the optimizer
won't
// remove the above member function calls as
dead code
localSysBeep (1); // Change this to "SysBeep (1);" and the code
will
// suddenly experience the _Oprah Effect_,
growing
// by from 74 to 114 bytes, an increase of 54%.
// The code should actually SHRINK by two bytes
// owing to the change from a JSR instruction
to
// a toolbox trap.
}
If you're wondering about all the various parts of this source code that
should generate no object code, they do have an effect regarding this
problem, though they don't account for all of it. I ran into this problem
while developing classes for fixed point numbers (to allow the use of standard
arithmetic operators with the Mac fixed point types) which required defining
many small inline functions which did little or no actual work (such as
converting
from one type to another when the representation was internally the same).
I noticed that the code which contained calls to FixMul() and FixDiv(), etc.,
contained a lot of useless busy-work. Then I discovered that ANY toolbox call
had the same effect.
Another unrelated problem I've noticed in the disassemblies below is that
this compiler LOVES to allocate stack frames that are WAY TOO LARGE for
what it needs. The first version allocates 44 bytes and uses 6 of them.
The second version allocates 36 bytes and uses 22, mostly for unneeded
store instructions.
I'm running with these options:
C++ Compiler:
– Use global optimizer: on. All optimization options are on.
Optimize for space selected
– All debugging options are off except for Generate optimizer warnings
– Generate 68020 instructions: on
– Align to 2 byte boundaries
– Relaxed ANSI conformance enabled
TPM:
– Optimize monomorphic methods: on
Here is the disassembly of main() from the version that calls localSysBeep()
(i.e., no toolbox calls are made). The code looks clean:
main:
00000000: 4E56 FFD4 LINK A6,#$FFD4
00000004: 48E7 1800 MOVEM.L D3/D4,-(A7)
00000008: 7601 MOVEQ #$01,D3
0000000A: 3D43 FFD4 MOVE.W D3,$FFD4(A6)
0000000E: 7002 MOVEQ #$02,D0
00000010: 3D40 FFD6 MOVE.W D0,$FFD6(A6)
00000014: 7003 MOVEQ #$03,D0
00000016: 3D40 FFD8 MOVE.W D0,$FFD8(A6)
0000001A: 382E FFD6 MOVE.W $FFD6(A6),D4
0000001E: C9FC 0007 MULS.W #$0007,D4
00000022: 7018 MOVEQ #$18,D0
00000024: D840 ADD.W D0,D4
00000026: D86E FFD6 ADD.W $FFD6(A6),D4
0000002A: 3D44 FFD4 MOVE.W D4,$FFD4(A6)
[continued in the reply]