Generating code for the switch statement
Chris Torek
chris at umcp-cs.UUCP
Fri Aug 8 07:22:52 AEST 1986
>In article <610 at hropus.UUCP> ka at hropus.UUCP (Kenneth Almquist) writes:
>>If the cases are not consecutive, the branch table must be filled with
>>entries for the "missing" cases, making the table larger [; eventually
>>this becomes a waste of space and the compiler uses a different approach].
In article <1171 at umd5> zben at umd5.umd.edu (Ben Cranston) writes:
>... In one of an innumerable number of Impress-understanding
>programs I converted an IF nest into a switch statement, and was
>chagrined when the program didn't show a vast efficiency improvement.
>After peeking at the (BSD4.x) C compiler code generator we found
>the 1/3 fudge factor, and that the Impress codes were only two
>short of being dense enough to compile into a jump table.
[... followed by speculation on the effects of adding two cases.]
One can force a consecutive sequence in another, less compiler
dependent, way. Write a compressing array:
char input_class[256] = {
/* classes for 0-127 */
is_char, is_char, ..., is_char,
/* classes for 128 on up */
is_obj1, is_obj2, is_obj2, is_badobj, is_obj1, ...
};
Then use
switch (input_class[input]) {
case is_char:
...
case is_obj1:
...
}
Those who are familiar with Knuth's TeX system may have seen some
of the code supplied to convert TeX .DVI files to device-dependent
data (a la Imagen's imPress language). In these, someone---Knuth
himself most likely---has written code of the form
/* translated to C for this newsgroup */
#define two_cases(base) \
base: case base+1
#define four_cases(base) \
two_cases(base): case two_cases(base+2)
#define eight_cases(base) \
four_cases(base): case four_cases(base+4)
#define thirty_two_cases(base) \
eight_cases(base): case eight_cases(base+8): \
case eight_cases(base+16): case eight_cases(base+24)
#define sixty_four_cases(base) \
thirty_two_cases(base): case thirty_two_cases(base+32)
then, later in the program, used these as (e.g.)
#define w0 147
...
#define fntnum0 171
...
case four_cases(w0):
w = p;
x += w;
break;
...
case sixty_four_cases(fntnum0):
font = p;
break;
...
I originally used rather similar code in my own Imagen and Versatec
DVI conversion programs. For some reason I decided one day to try
a compressing array like the one above. To my surprise, the code
was not only clearer to me, but also ran rather faster. I verified
that the generated code indeed used a vax `casel' instruction in
both versions. My guess is that the speedup came entirely from
fitting more of the main loop into the cache.
--
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 1516)
UUCP: seismo!umcp-cs!chris
CSNet: chris at umcp-cs ARPA: chris at mimsy.umd.edu
More information about the Comp.lang.c
mailing list