AVR-GCC 4.9.2 optimizations
Posted: Thu Aug 06, 2015 5:24 pm
I finally installed avr-gcc 4.9.2 to see how it compares to my old 4.3.3. Well, so far I'm perplexed. Consider this code for instance:
In avr-gcc 4.3.3 it generates the following assembly which is pretty much what I would expect:
But 4.9.2 generates the following:
Notice the track->flags bits where it recomputes the whole adress each time instead of using Z with displacement!? I could understand the first time since it calculate the pointer. But the second time?? It's like it has changed scope in the if statement and forgot about it.
One good thing it does is using a JMP to reach TriggerCommon instead of a call to save push/pops.
Code: Select all
void TriggerNote(unsigned char channel,unsigned char patch,unsigned char note,unsigned char volume){
struct TrackStruct* track=&tracks[channel];
if((track->flags&TRACK_FLAGS_PLAYING)==0 || (track->flags&TRACK_FLAGS_PRIORITY)==0)
{
track->flags&=(~TRACK_FLAGS_HOLD_ENV);//patchEnvelopeHold=false;
track->patchCurrDeltaTime=0;
track->envelopeStep=0;
TriggerCommon(channel,patch,volume,note);
}
}
Code: Select all
void TriggerNote(unsigned char channel,unsigned char patch,unsigned char note,unsigned char volume){
39e8: 98 2f mov r25, r24
39ea: 34 2f mov r19, r20
struct TrackStruct* track=&tracks[channel];
39ec: 86 e1 ldi r24, 0x16 ; 22
39ee: 98 9f mul r25, r24
39f0: f0 01 movw r30, r0
39f2: 11 24 eor r1, r1
39f4: e1 51 subi r30, 0x11 ; 17
39f6: f5 4f sbci r31, 0xF5 ; 245
//allow only other music notes
if((track->flags&TRACK_FLAGS_PLAYING)==0 || (track->flags&TRACK_FLAGS_PRIORITY)==0){
39f8: 80 81 ld r24, Z
39fa: 85 ff sbrs r24, 5
39fc: 02 c0 rjmp .+4 ; 0x3a02 <TriggerNote+0x1a>
39fe: 87 fd sbrc r24, 7
3a00: 09 c0 rjmp .+18 ; 0x3a14 <TriggerNote+0x2c>
track->flags&=(~TRACK_FLAGS_HOLD_ENV);//patchEnvelopeHold=false;
3a02: 8f 7b andi r24, 0xBF ; 191
3a04: 80 83 st Z, r24
track->patchCurrDeltaTime=0;
3a06: 12 8a std Z+18, r1 ; 0x12
track->envelopeStep=0;
3a08: 15 86 std Z+13, r1 ; 0x0d
TriggerCommon(channel,patch,volume,note);
3a0a: 89 2f mov r24, r25
3a0c: 42 2f mov r20, r18
3a0e: 23 2f mov r18, r19
3a10: 0e 94 1f 1c call 0x383e ; 0x383e <TriggerCommon>
3a14: 08 95 ret
Code: Select all
void TriggerNote(unsigned char channel,unsigned char patch,unsigned char note,unsigned char volume){
3a16: 32 2f mov r19, r18
struct TrackStruct* track=&tracks[channel];
//allow only other music notes
if((track->flags&TRACK_FLAGS_PLAYING)==0 || (track->flags&TRACK_FLAGS_PRIORITY)==0){
3a18: a8 2f mov r26, r24
3a1a: b0 e0 ldi r27, 0x00 ; 0
3a1c: 96 e1 ldi r25, 0x16 ; 22
3a1e: 89 9f mul r24, r25
3a20: f0 01 movw r30, r0
3a22: 11 24 eor r1, r1
3a24: e1 51 subi r30, 0x11 ; 17
3a26: f5 4f sbci r31, 0xF5 ; 245
3a28: 90 81 ld r25, Z
3a2a: 95 ff sbrs r25, 5
3a2c: 02 c0 rjmp .+4 ; 0x3a32 <TriggerNote+0x1c>
3a2e: 97 fd sbrc r25, 7
3a30: 10 c0 rjmp .+32 ; 0x3a52 <TriggerNote+0x3c>
track->flags&=(~TRACK_FLAGS_HOLD_ENV);//patchEnvelopeHold=false;
3a32: 26 e1 ldi r18, 0x16 ; 22
3a34: 2a 9f mul r18, r26
3a36: f0 01 movw r30, r0
3a38: 2b 9f mul r18, r27
3a3a: f0 0d add r31, r0
3a3c: 11 24 eor r1, r1
3a3e: e1 51 subi r30, 0x11 ; 17
3a40: f5 4f sbci r31, 0xF5 ; 245
3a42: 9f 7b andi r25, 0xBF ; 191
3a44: 90 83 st Z, r25
track->patchCurrDeltaTime=0;
3a46: 12 8a std Z+18, r1 ; 0x12
track->envelopeStep=0;
3a48: 15 86 std Z+13, r1 ; 0x0d
TriggerCommon(channel,patch,volume,note);
3a4a: 24 2f mov r18, r20
3a4c: 43 2f mov r20, r19
3a4e: 0c 94 1f 1c jmp 0x383e ; 0x383e <TriggerCommon>
3a52: 08 95 ret
One good thing it does is using a JMP to reach TriggerCommon instead of a call to save push/pops.