K
Kevin Bracey
In message <[email protected]>
Ours definitely would add in a null case. The code would come out like:
; a1 = direction
SUB a1,a1,#'1' ; reduce a1 to 0-3,5-8 for our cases
CMP a1,#8
ADDLS pc,pc,a1,LSL #2 ; jump into branch table if <= 8
B endofswitch
B case1
B case2
B case3
B case4
B endofswitch
B case6
B case7
B case8
BL move_upper_right ; case 9
endofswitch
; ... following code here
; somewhere else
case1
BL move_lower_left
B endofswitch
case2
BL move_down
B endofswitch
; ... then other cases
Typically it will tend to use a branch table if there are 5 or more cases
and they cover at least half the range of values. They can also be used for
dense parts of an otherwise sparse switch.
I think this sort of behaviour is probably pretty typical among compilers.
I really wouldn't worry about adding fake cases just to create a contiguous
range. But if you are switching on some arbitrary internal constants (enums
or whatever), it is probably best to make those constants small and
contiguous, rather than large and irregular.
Other stunts that may or may not occur might be to spot things like:
switch (x)
{
case 0x100: ...
case 0x200: ...
case 0x300: ...
case 0x400: ...
}
which though sparse, can be reduced to a branch table with a little shifting.
Our compiler does this, but I'm not sure I've ever seen any code it actually
helps
I'm currently looking at how best to implement switches on long long
expressions (ie ones bigger than a machine word size). C99 requires this, and
it's a bit of a pain. But I suppose the precedent was already set in that you
could switch on a "long", which may have been bigger than a word in some
architectures.
Thomas Matthews said:True, but I was specifically interested in the switch
statement. I didn't know if the compiler's intelligence
would add in a null case to the switch statement to provide
better optimization.
How do you handle it in your compiler?
Ours definitely would add in a null case. The code would come out like:
; a1 = direction
SUB a1,a1,#'1' ; reduce a1 to 0-3,5-8 for our cases
CMP a1,#8
ADDLS pc,pc,a1,LSL #2 ; jump into branch table if <= 8
B endofswitch
B case1
B case2
B case3
B case4
B endofswitch
B case6
B case7
B case8
BL move_upper_right ; case 9
endofswitch
; ... following code here
; somewhere else
case1
BL move_lower_left
B endofswitch
case2
BL move_down
B endofswitch
; ... then other cases
Typically it will tend to use a branch table if there are 5 or more cases
and they cover at least half the range of values. They can also be used for
dense parts of an otherwise sparse switch.
I think this sort of behaviour is probably pretty typical among compilers.
I really wouldn't worry about adding fake cases just to create a contiguous
range. But if you are switching on some arbitrary internal constants (enums
or whatever), it is probably best to make those constants small and
contiguous, rather than large and irregular.
Other stunts that may or may not occur might be to spot things like:
switch (x)
{
case 0x100: ...
case 0x200: ...
case 0x300: ...
case 0x400: ...
}
which though sparse, can be reduced to a branch table with a little shifting.
Our compiler does this, but I'm not sure I've ever seen any code it actually
helps
I'm currently looking at how best to implement switches on long long
expressions (ie ones bigger than a machine word size). C99 requires this, and
it's a bit of a pain. But I suppose the precedent was already set in that you
could switch on a "long", which may have been bigger than a word in some
architectures.