Avoid code duplication in the g++ ABI
The C++ ABI implemented by gcc and other compilers performs some often unnecessary code duplication on constructors/destructors leading to code bloat which is undesirable especially on platforms with low memory footprints such as the Cell SPUs.
Code bloat caused by not-in-charge method definitions
The following example code defines a base and a derived struct. Each of them declares a constructor which is defined outside the struct definition to force the compiler to generate the definition of the function in the object file.
struct base { base(); }; struct derived:base { derived(); }; base::base(){} derived::derived(){} //just 2 function definitions, right? Wrong!
We would expect that only two function definitions end up in the object file but the compiler generates four function definitions as can be seen in the following assembly generated by gcc (g++-4 version 4.3.4. on Cygwin)
00000000 <__ZN4baseC2Ev>: 0: 55 push %ebp 1: 89 e5 mov %esp,%ebp 3: 5d pop %ebp 4: c3 ret 5: 90 nop 00000006 <__ZN4baseC1Ev>: 6: 55 push %ebp 7: 89 e5 mov %esp,%ebp 9: 5d pop %ebp a: c3 ret b: 90 nop 0000000c <__ZN7derivedC2Ev>: c: 55 push %ebp d: 89 e5 mov %esp,%ebp f: 83 ec 04 sub $0x4,%esp 12: 8b 45 08 mov 0x8(%ebp),%eax 15: 89 04 24 mov %eax,(%esp) 18: e8 e3 ff ff ff call 0 <__ZN4baseC2Ev> 1d: c9 leave 1e: c3 ret 1f: 90 nop 00000020 <__ZN7derivedC1Ev>: 20: 55 push %ebp 21: 89 e5 mov %esp,%ebp 23: 83 ec 04 sub $0x4,%esp 26: 8b 45 08 mov 0x8(%ebp),%eax 29: 89 04 24 mov %eax,(%esp) 2c: e8 cf ff ff ff call 0 <__ZN4baseC2Ev> 31: c9 leave 32: c3 ret 33: 90 nop
The reason for the four functions (with the mangled function names: __ZN4baseC1Ev, __ZN4baseC2Ev, __ZN7derivedC1Ev, __ZN7derivedC2Ev) in the assembly instead of the expected two functions is that the gcc ABI duplicates constructor and destructor definitions to create not-in-charge constructors (C2 in the mangled function name) and destructors (D2 in mangled name, not shown in this example). These not-in-charge constructors/destructors are called only by derived constructors/destructors and perform the construction/destruction of the object without constructing/destructing virtual bases. However, for struct definitions that do not have virtual bases (like in the code above) the in-charge constructor (for example __ZN4baseC1Ev) is identical to the not-in-charge constructor (__ZN4baseC2Ev). This can lead to significant code bloat especially if the constructors/destructor definitions are large and emitted in the object file (i.e. not inlined).
Avoiding the code bloat
Codeplay's compilers (including Offload™) provide a command line option -noredundantgccmethods to disable this code duplication and generate not-in-charge functions (C2 or D2 in the mangled name) only where needed (i.e. where virtual bases are present). Using that option the Codeplay Vectorc compiler generates only two function definitions (in-charge functions with C1 in the mangled name) on the example above. Using that option calls to not-in-charge functions are replaced by calls to in-charge functions, for example in the following unoptimised assembly the in-charge constructor __ZN7derivedC1Ev now calls the in-charge base constructor __ZN4baseC1Ev.
00000000 <__ZN4baseC1Ev>: 0: c3 ret 1: 8d 84 20 00 00 00 00 lea 0x0(%eax,%eiz,1),%eax 8: 8d 84 20 00 00 00 00 lea 0x0(%eax,%eiz,1),%eax f: 90 nop 00000010 <__ZN7derivedC1Ev>: 10: 8b 44 24 04 mov 0x4(%esp),%eax 14: 50 push %eax 15: e8 e6 ff ff ff call 0 <__ZN4baseC1Ev> 1a: 83 c4 04 add $0x4,%esp 1d: c3 ret
The compiler suppresses the definition of not-in-charge methods on those structures (that don't have virtual bases) and calls the in-charge methods instead to initialise the base. Since using that option the not-in-charge are not emitted in the object file, any usage of those functions from code compiled without that option (including from gcc- compiled code), may result in a link error.