AVR-GCC 4.9.2 optimizations

Topics on software tools like TileStudio, comments on documentation and tutorials (or the lack of) should go here.
Post Reply
User avatar
uze6666
Site Admin
Posts: 4778
Joined: Tue Aug 12, 2008 9:13 pm
Location: Montreal, Canada
Contact:

AVR-GCC 4.9.2 optimizations

Post by uze6666 »

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:

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);	
	}
}
In avr-gcc 4.3.3 it generates the following assembly which is pretty much what I would expect:

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
But 4.9.2 generates the following:

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
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.
User avatar
D3thAdd3r
Posts: 3175
Joined: Wed Apr 29, 2009 10:00 am
Location: Minneapolis, United States

Re: AVR-GCC 4.9.2 optimizations

Post by D3thAdd3r »

Have you noticed significant size differences recompiling games? I've only set up prebuilt WinAVR following some tutorial long ago, but if there is some complete idiot's guide to getting 4.9.2 in AVRS 4.19 it would be lovely.
User avatar
uze6666
Site Admin
Posts: 4778
Joined: Tue Aug 12, 2008 9:13 pm
Location: Montreal, Canada
Contact:

Re: AVR-GCC 4.9.2 optimizations

Post by uze6666 »

D3thAdd3r wrote:Have you noticed significant size differences recompiling games? I've only set up prebuilt WinAVR following some tutorial long ago, but if there is some complete idiot's guide to getting 4.9.2 in AVRS 4.19 it would be lovely.
On -Os the generated code is a few hundeds bytes smaller the on the projects I have tested so far.

On Windows it's a no brainer. Here's complete idiot's guide to setting up 4.9.2:
  • Download the prebuilt package zip from: http://andybrown.me.uk/wk/2015/03/08/avr-gcc-492/
  • Unzip to disk, ex: c:\avrgcc492
  • Update your PATH environment variable and replace "C:\WinAVR-20100110\bin" with "c:\avrgcc492\bin"
  • Copy WinAVR\bin\avr-size.exe to c:\avrgcc492\bin\. This is required since the base binutils version does not support the -C flag.
That's it!
CunningFellow
Posts: 1445
Joined: Mon Feb 11, 2013 8:08 am
Location: Brisbane, Australia

Re: AVR-GCC 4.9.2 optimizations

Post by CunningFellow »

That optimization seems woeful.

I've seen 4.9.2 do some things soo much better than 4.3.x but that's bad.
User avatar
uze6666
Site Admin
Posts: 4778
Joined: Tue Aug 12, 2008 9:13 pm
Location: Montreal, Canada
Contact:

Re: AVR-GCC 4.9.2 optimizations

Post by uze6666 »

CunningFellow wrote:That optimization seems woeful.

I've seen 4.9.2 do some things soo much better than 4.3.x but that's bad.
Yeah well, this sucks. I will rewrite these calls in assembler eventually.
CunningFellow
Posts: 1445
Joined: Mon Feb 11, 2013 8:08 am
Location: Brisbane, Australia

Re: AVR-GCC 4.9.2 optimizations

Post by CunningFellow »

I will (or you can) ask on AVRfreaks if there is something else that should be done to help in C.
User avatar
D3thAdd3r
Posts: 3175
Joined: Wed Apr 29, 2009 10:00 am
Location: Minneapolis, United States

Re: AVR-GCC 4.9.2 optimizations

Post by D3thAdd3r »

Perfect I think I can handle that install!
User avatar
uze6666
Site Admin
Posts: 4778
Joined: Tue Aug 12, 2008 9:13 pm
Location: Montreal, Canada
Contact:

Re: AVR-GCC 4.9.2 optimizations

Post by uze6666 »

Until I can resolve to optimization aberrations, personally I'll keep both gcc versions side-by-side. That will allow to compare which is best at least for size. Performance wise, uzem should eventually be able to come to the rescue to time sections of code. 8-)

Just got an idea. Uzem could profile code in two way. Profiling would be triggered by writing to a reserved ports. One would count all cpu cycles elapsed. An another port could count only cycles elapsed while the global interrupt flag is enabled, in other words timing only the user code. Another port could count only kernel cycles.
Post Reply