I add -Os -Wall flags to every avr-g++ command. During coding I've noticed g++ adds plenty of unnecessary assembly to output file. I'll try to check it with gcc 4.x but currently I fail to compile it.
Problem is related to static initialization of template class/struct variable. Following code snippet should explain the issue. I've tried to make it minimal. I'd be happy even with some work-around like __attribute__ but not with 'use macros instead' which I hear constantly... Hope this helps someone. /* Reading specs from /usr/lib/gcc/avr/3.4.6/specs Configured with: /var/tmp/cross/avr/portage/cross-avr/gcc-3.4.6/work/gcc-3.4.6/configure --prefix=/usr --bindir=/usr/x86_64-pc-linux-gnu/avr/gcc-bin/3.4.6 --includedir=/usr/lib/gcc/avr/3.4.6/include --datadir=/usr/share/gcc-data/avr/3.4.6 --mandir=/usr/share/gcc-data/avr/3.4.6/man --infodir=/usr/share/gcc-data/avr/3.4.6/info --with-gxx-include-dir=/usr/lib/gcc/avr/3.4.6/include/g++-v3 --host=x86_64-pc-linux-gnu --target=avr --build=x86_64-pc-linux-gnu --disable-altivec --enable-nls --without-included-gettext --with-system-zlib --disable-checking --disable-werror --enable-secureplt --disable-libunwind-exceptions --disable-libgcj --enable-languages=c,c++ --enable-shared --disable-threads Thread model: single gcc version 3.4.6 (Gentoo 3.4.6, ssp-3.4.5-1.0, pie-8.7.9) (Can't successfully build 4.x yet) i686 4.1.2 version also generates additional code in one case but the code is much smaller. */ /* Declaration of Real */ struct stub { float D; stub() {} stub(float A) : D(A) {} inline operator float&() { return D; } inline operator const float&() const { return D; } }; //typedef float Real; /* No problems if real is simply a float */ typedef stub Real; /*** Template using previously defined type ***/ #define OUTER 0 /* No problem if we use static variable not from the template */ #if OUTER == 1 static Real Result; #endif template<int Dummy> /* When there's no template code is ok */ struct Avg { #if OUTER == 0 static Real Result; #endif static const Real &Push(const Real Value) { Result *= Dummy; // Result *= 20 /* No problems if we won't touch dummy */ return Result; } }; #if OUTER == 0 template<int Dummy> Real Avg<Dummy>::Result; #endif int main() { Avg<20>::Push(1.0); return 0; } #if 0 Unnecessary code generated looks like this: .type _GLOBAL__I_main, @function _GLOBAL__I_main: /* prologue: frame size=0 */ push r2 push r3 push r4 push r5 push r6 push r7 push r8 push r9 push r10 push r11 push r12 push r13 push r14 push r15 push r16 push r17 /* prologue end (size=16) */ lds r18,_ZGVN3AvgILi20EE6ResultE lds r19,_ZGVN3AvgILi20EE6ResultE+1 lds r20,_ZGVN3AvgILi20EE6ResultE+2 lds r21,_ZGVN3AvgILi20EE6ResultE+3 lds r22,_ZGVN3AvgILi20EE6ResultE+4 lds r23,_ZGVN3AvgILi20EE6ResultE+5 lds r24,_ZGVN3AvgILi20EE6ResultE+6 lds r25,_ZGVN3AvgILi20EE6ResultE+7 ldi r30,lo8(1) mov r2,r30 clr r3 mov r4,r3 mov r5,r3 mov r6,r3 mov r7,r3 mov r8,r3 mov r9,r3 mov r10,r18 add r10,r2 mov r30,r2 cp r10,r18 brlo .L7 mov r30,r3 .L7: mov r11,r19 add r11,r3 ldi r26,lo8(1) cp r11,r19 brlo .L8 ldi r26,lo8(0) .L8: add r30,r11 ldi r31,lo8(1) cp r30,r11 brlo .L9 ldi r31,lo8(0) .L9: or r26,r31 mov r11,r30 mov r12,r20 add r12,r4 ldi r27,lo8(1) cp r12,r20 brlo .L10 ldi r27,lo8(0) .L10: mov r30,r26 add r30,r12 ldi r31,lo8(1) cp r30,r12 brlo .L11 ldi r31,lo8(0) .L11: or r27,r31 mov r12,r30 mov r13,r21 add r13,r5 ldi r26,lo8(1) cp r13,r21 brlo .L12 ldi r26,lo8(0) .L12: mov r30,r27 add r30,r13 ldi r31,lo8(1) cp r30,r13 brlo .L13 ldi r31,lo8(0) .L13: or r26,r31 mov r13,r30 mov r14,r22 add r14,r6 ldi r27,lo8(1) cp r14,r22 brlo .L14 ldi r27,lo8(0) .L14: mov r30,r26 add r30,r14 ldi r31,lo8(1) cp r30,r14 brlo .L15 ldi r31,lo8(0) .L15: or r27,r31 mov r14,r30 mov r15,r23 add r15,r7 ldi r26,lo8(1) cp r15,r23 brlo .L16 ldi r26,lo8(0) .L16: mov r30,r27 add r30,r15 ldi r31,lo8(1) cp r30,r15 brlo .L17 ldi r31,lo8(0) .L17: or r26,r31 mov r15,r30 mov r16,r24 add r16,r8 ldi r27,lo8(1) cp r16,r24 brlo .L18 ldi r27,lo8(0) .L18: mov r31,r26 add r31,r16 ldi r30,lo8(1) cp r31,r16 brlo .L19 ldi r30,lo8(0) .L19: or r30,r27 mov r17,r25 add r17,r9 add r30,r17 sts _ZGVN3AvgILi20EE6ResultE,r10 sts _ZGVN3AvgILi20EE6ResultE+1,r11 sts _ZGVN3AvgILi20EE6ResultE+2,r12 sts _ZGVN3AvgILi20EE6ResultE+3,r13 sts _ZGVN3AvgILi20EE6ResultE+4,r14 sts _ZGVN3AvgILi20EE6ResultE+5,r15 sts _ZGVN3AvgILi20EE6ResultE+6,r31 sts _ZGVN3AvgILi20EE6ResultE+7,r30 /* epilogue: frame size=0 */ pop r17 pop r16 pop r15 pop r14 pop r13 pop r12 pop r11 pop r10 pop r9 pop r8 pop r7 pop r6 pop r5 pop r4 pop r3 pop r2 ret #endif -- Summary: Lots of (possibly) unnecesary static initialization code generated. Product: gcc Version: 3.4.6 Status: UNCONFIRMED Severity: enhancement Priority: P3 Component: c++ AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: bla at thera dot be GCC build triplet: x86_64-pc-linux-gnu GCC host triplet: x86_64-pc-linux-gnu GCC target triplet: avr http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36310