Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!csd4.milw.wisc.edu!cs.utexas.edu!uunet!ksr!occam!johnm From: johnm@occam.ksr.com (John Martin) Newsgroups: comp.lang.c Subject: Re: Short code to determine compiler's number of registers Message-ID: <547@ksr.UUCP> Date: 20 Jul 89 01:36:13 GMT References: <396@uop.uop.EDU> <225800197@uxe.cso.uiuc.edu> <579@targon.UUCP> <18603@mimsy.UUCP> Sender: nobody@ksr.UUCP Reply-To: johnm@ksr.UUCP (John Martin) Organization: Kendall Square Research, Waltham, MA Lines: 108 In article <18603@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes: > >... the way to find out how many registers the compiler will >use on your code is to compile your code and count how many registers >were used. This is completely reliable, although not necessarily >repeatable. It is also likely to be a useless statistic. >-- >In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) >Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris All true. For amusement's sake though, here is a C program that finds out what register variables one can have by looking at their effect on execution time, which presumably is why one might want to know in the first place. The following example works with gcc and cc on Sun 3's and 4's running SunOS 3.5, and should work on most UNIX machines with little change. As is frequently noted, timing routines are not very portable across OS's; sorry about that. On the systems I've tried ( Sun 3/75, 3/60, 3/140, 4/280 ) the register-variable loops run about 2.2 - 2.5 times faster than the memory-variable loops. The SPARC is about twice as fast as a 3/75, achieving about 1 million Hz for register loops. For the curious the register counts are: gcc : 10 registers on MC68020, 14 on SPARC. Sun cc : 6 registers on MC68020, 14 on SPARC. Counting address registers, and finding whether address and integer registers are separate or part of the same general register set, or being used in a slick way by the compiler, are left as exercises to the reader. The answers will have some surprises -- for example, the gcc MC68020 result of 10 integer registers is interesting, since an MC68020 only has 8 data registers. As Chris Torek says, the only way to be sure what's happening is to look at the assembler. /* showregs.c How many registers will your compiler give you? * * On a UNIX system: * * % cc showregs.c * _or_ % gcc -traditional showregs.c * _or_ % gcc -ansi showregs.c * * ( one flag or the other is needed to make PRINTLINE expand correctly) * * % a.out > regs * % graph -b -a -y 0 -g 1 < regs | plot */ #include #include #ifdef __STDC__ #define PRINTLINE(xx) (void) printf( "%8u %s\n", xx, #xx) #else old-style macro substitution inside quotes #define PRINTLINE(xx) (void) printf( "%8u xx\n", xx) #endif /* Execute a simple unrolled loop for a fixed time & count iterations. */ #define LOOPS(var) \ var = 0; \ timing = 1; \ if ( setitimer( ITIMER_VIRTUAL, &itval, 0) ) \ perror( "Starting timer"); \ while (timing) { var--; var++; var--; var++; var++; } \ PRINTLINE(var) unsigned timing; int vtalrmhandler() { timing = 0; return 0; } int main() { register unsigned r01, r02, r03, r04, r05, r06, r07, r08, r09, r10, r11, r12, r13, r14, r15, r16, r17, r18, r19, r20; struct itimerval itval; /* Set up to use the UNIX virtual timer for 200 milliseconds * of process time. */ itval.it_value.tv_sec = 0; itval.it_value.tv_usec = 200*1000; itval.it_interval.tv_sec = itval.it_interval.tv_usec = 0; (void) signal( SIGVTALRM, vtalrmhandler); LOOPS(r01); LOOPS(r02); LOOPS(r03); LOOPS(r04); LOOPS(r05); LOOPS(r06); LOOPS(r07); LOOPS(r08); LOOPS(r09); LOOPS(r10); LOOPS(r11); LOOPS(r12); LOOPS(r13); LOOPS(r14); LOOPS(r15); LOOPS(r16); LOOPS(r17); LOOPS(r18); LOOPS(r19); LOOPS(r20); } /* end main */ /* EOF */ John H. Martin harvard!ksr!johnm Kendall Square Research Corporation johnm@ksr.com 170 Tracer Lane Waltham, MA 02154 "A creative economy is the fuel of magnificence." -- Emerson Disclaimer: My only organizationally-endorsed position is prone.