CompuServe Messages

#Optimizer Useless!?

    20-Jul-93 20:29:43
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]