Compiler emits 16bit compares for switch(byte)?

Go To Last Post
9 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am using WinAVR with the ATmega128, with a code segment like:

switch( *pBytePtr ) {
	case 29:
		dosomestuff();
		break;
	case 77:
		dosomestuff2();
		break;
	//
	// Three more cases, all values<256, and default
	//
}

With -O2 optimization the compiler is emitting 16 bit compares for each case value:

Quote:
clr r17
cpi r16,29
cpc r17,__zero_reg__
brne .+2
rjmp .L67

I am just wondering why the second compare is there. Seems like the optimizer could easily omit it.

GCC is version 3.4.3.

Jim

C: i = "told you so";

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It is C standard to promote all byte values to 'int's. If you want to make it do single byte compares, you will have to do explicate casts. This can be a real pain sometimes.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I've tried casting *pBytePtr and the case constant values to (unsigned char) but the 16 bit compare is still used.

Jim

C: i = "told you so";

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Can you try the latest WinAVR version which contains GCC 3.4.6? See if it's any better...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think that you will need to cast the case values as well, as constants will default to 'int's.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Very good point Steve (Koshchi), you're right. The C language standard treats all plain integer constants as type int which is 16-bits on the AVR.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I tried the latest WinAVR (GCC 3.4.6); it still emits 16 bit compares.

My test code now looks like:

	switch((unsigned char)PORTC) {
		case (unsigned char)0xA0:
			PORTB=0x1;
			break;
		case (unsigned char)0x10:
			PORTB=0x21;
			break;
		case (unsigned char)0xE0:
			PORTB=0x22;
			break;
	}

Emitted:

	clr r25
	cpi r24,160
	cpc r25,__zero_reg__
	breq .L199
.LM292:
	...

C: i = "told you so";

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I tried it too. It looks like it won't work with a switch statement. However with if ... else it works just fine.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ICCAVR does the same :( I use a if-elseif-elseif... construction then. Saves a lot of code and execution time.