istvan@hhb.UUCP (Istvan Mohos) (05/06/90)
main() { /* prog1, compile with: /bin/cc -O prog1.c -o reg */ static unsigned char buf[4096]; register unsigned char *p; for (p = buf + 4096; --p >= buf;) for (; *p < 255; ++*p); } main() { /* prog2, compile with: /bin/cc -O prog2.c -o nonreg */ static unsigned char buf[4096]; unsigned char *p; for (p = buf + 4096; --p >= buf;) for (; *p < 255; ++*p); } Prog1 and prog2 are identical except that prog1 requests the assignment of the auto variable p to a hardware register. I mistakenly assumed that by using the -O flag, the compiler would optimize prog2, and generate identical objects from prog1 and prog2. Of the systems I tried this on, the Pyramid90X, the Sparcstation1, and a SystemV 6300+ PC, proved this to be true. A VAX Ultrix and a Sun3 proved me wrong. Here are some execution times for the reg and nonreg objects, gotten on quiescent systems using /bin/time ./[non]reg >& [non]regtime Ultrix: regtime 15.8 real 3.1 user 0.9 sys nonregtime 21.6 real 3.7 user 1.2 sys 6300+: 7.9 real 7.8 user 0.1 sys Pyramid: 4.8 real 4.6 user 0.1 sys Sun3: regtime 1.7 real 1.6 user 0.0 sys nonregtime 2.2 real 2.2 user 0.0 sys Sparcstation1: 0.9 real 0.8 user 0.0 sys Is the automatic allocation of a few variables into registers too much to ask from an optimizing compiler? -- Istvan Mohos ...uunet!pyrdc!pyrnj!hhb!istvan RACAL-REDAC/HHB 1000 Wyckoff Ave. Mahwah NJ 07430 201-848-8000 ======================================================================
guy@auspex.auspex.com (Guy Harris) (05/07/90)
The answer to the question "why doesn't -O assign things to register automatically" is "-O means different things on different systems". Prior to SunOS 4.0, Sun didn't have an optimizing compiler for C on the 68K that would assign variables to registers for you; 4.0 has such a compiler, but you have to say "-O2" or higher to get that level of optimization; "-O" is equivalent to "-O1". The SPARC compiler gives you "-O2" when you say "-O". (In SunOS 4.1, "-O" means "-O2" on both 68K and SPARC.) Presumably, for the other machines where "p" wasn't put into a register automatically, either the compiler won't do that for you, or you have to ask for it with more than just "-O".
p554mve@mpirbn.UUCP (Michael van Elst) (05/07/90)
In article <512@hhb.UUCP> istvan@hhb.UUCP (Istvan Mohos) writes: >Prog1 and prog2 are identical except that prog1 requests the >assignment of the auto variable p to a hardware register. >I mistakenly assumed that by using the -O flag, the compiler >would optimize prog2, and generate identical objects from >prog1 and prog2. Of the systems I tried this on, the Pyramid90X, >the Sparcstation1, and a SystemV 6300+ PC, proved this to be true. >A VAX Ultrix and a Sun3 proved me wrong. Here are some execution I've simply checked this by looking at the cc -S output. The Sun C compiler does not allocate registers when run with optimizer level 1 but it does so with level 2. The -O option just invokes a peephole optimizer. The difference between Sparc and Sun-3 systems is that the Sparc compiler will run -O2 if invoked with just -O while the Sun-3 defaults to -O1. Under SunOS 4.1, both systems will use -O2. -- Michael van Elst UUCP: universe!local-cluster!milky-way!sol!earth!uunet!unido!mpirbn!p554mve Internet: p554mve@mpirbn.mpifr-bonn.mpg.de "A potential Snark may lurk in every tree."
leo@atcmp.nl (Leo Willems) (05/08/90)
From article <512@hhb.UUCP>, by istvan@hhb.UUCP (Istvan Mohos): > > program deleted > > Prog1 and prog2 are identical except that prog1 requests the > assignment of the auto variable p to a hardware register. and prog2 not. > I mistakenly assumed that by using the -O flag, the compiler > would optimize prog2, and generate identical objects from etc. > > Is the automatic allocation of a few variables into registers > too much to ask from an optimizing compiler? Sorry for the rude deletion of text. Our compiler with -O is putting automatic variables in registers. (3b2 SV 3.1) But I have a question on this subject: Should an optimizer put autovar's in a register anyway? If you use setjmp/longjmp, on the return from setjmp via longjmp, automatic variables can not be trusted any more! If they are not in a register everything is fine, but else the reg-var's are overwritten with registervalues which were there at the time of the longjmp call. This is in conflict with the manual page of setjmp/longjmp. (I realise the setjmp/longjmp implementation is not very portable, but their behaviour should be) Is there an answer to this problem? (besides of not using setjmp/longjmp:-( ) Thanks Leo Willems Internet: leo@atcmp.nl AT Computing UUCP: mcvax!hp4nl!kunivv1!atcmpe!leo P. O. Box 1428 6501 BK Nijmegen Phone: +31-80-566880 The Netherlands Fax: +31-80-555887
gwyn@smoke.BRL.MIL (Doug Gwyn) (05/08/90)
In article <512@hhb.UUCP> istvan@hhb.UUCP (Istvan Mohos) writes: >Is the automatic allocation of a few variables into registers >too much to ask from an optimizing compiler? Use of the cc -O flag does not magically transform the compiler into an "optimizing compiler". In fact, for older (PCC-based) compilers, it merely invokes a peephole optimizer on the resulting assembly code. Naturally, it is too late to reassign registers at that point.
meissner@osf.org (Michael Meissner) (05/08/90)
In article <596@atcmpe.atcmp.nl> leo@atcmp.nl (Leo Willems) writes: | But I have a question on this subject: | | Should an optimizer put autovar's in a register anyway? If you use | setjmp/longjmp, on the return from setjmp via longjmp, automatic | variables can not be trusted any more! If they are not in a register | everything is fine, but else the reg-var's are overwritten with registervalues | which were there at the time of the longjmp call. ANSI says that all local variables whether register or not, that do not have the volatile qualifier, can be trashed by setjmp/longjmp. Implementors don't seem willing to have longjmp 'do the right thing' (ie, completely unwind the stack, restoring registers -- for machines with well defined frames, this is rather trivial -- for the two RISC machines I'm familar with [MIPS, 88k], there is a lookaside table that tells for each function, which registers are saved where, and what register to use as the virtual frame pointer). | This is in conflict with the manual page of setjmp/longjmp. | (I realise the setjmp/longjmp implementation is not very portable, but their | behaviour should be) | | Is there an answer to this problem? (besides of not using setjmp/longjmp:-( ) Don't assume that any local variable has a meaningful value after setjmp (and of course longjmp going through setjmp) returns. No ifs, ands, or buts. GCC -Wall -O options will warn of live variables across setjmp calls. -- Michael Meissner email: meissner@osf.org phone: 617-621-8861 Open Software Foundation, 11 Cambridge Center, Cambridge, MA Catproof is an oxymoron, Childproof is nearly so
guy@auspex.auspex.com (Guy Harris) (05/09/90)
>Should an optimizer put autovar's in a register anyway? Yes, it should. >If you use setjmp/longjmp, on the return from setjmp via longjmp, automatic >variables can not be trusted any more! If they are not in a register >everything is fine, but else the reg-var's are overwritten with registervalues >which were there at the time of the longjmp call. ANSI C says that unless you declare the automatic variables "volatile", there's no guarantee that "setjmp"/"longjmp" will preserve them. Sun's C compiler includes a #pragma "makes_regs_inconsistent", and on the 68K-based Suns includes this #pragma when you include <setjmp.h>; that #pragma suppresses the automatic register allocation in routines that call the routines listed in the #pragma, and in the version used when you include <setjmp.h>, "sigsetjmp", "setjmp", and "_setjmp" are listed.
richard@aiai.ed.ac.uk (Richard Tobin) (05/09/90)
In article <596@atcmpe.atcmp.nl> leo@atcmp.nl (Leo Willems) writes: >Should an optimizer put autovar's in a register anyway? If you use >setjmp/longjmp, on the return from setjmp via longjmp, automatic >variables can not be trusted any more! This is often true. >This is in conflict with the manual page of setjmp/longjmp. This depends on your manual. >Is there an answer to this problem? Yes, there are several. (1) In Ansi C, auto variables that have changed since the setjmp() have unpredictable values (ie, the registers may be restored to the values saved by setjmp()). You can avoid this by declaring the variable as "volatile", which will prevent it from being stored in a register. (2) In some implementations, longjmp() "unwinds" the stack so that all variables in registers are restored to the correct values. (3) In some implementations, only variables declared as "register" will be assigned to registers. (4) In some implementations, any routine that calls setjmp() will not be optimised - all auto variables will go on the stack :-( (5) In some implementations, in a routine that calls setjmp() only variables declared as "register" will be assigned to registers. I suppose it would also be possible to use registers, but always store them on the stack before calling a routine which might call longjmp(), but I don't know of any implementation that does this. So what do you do? Choose from the following: - if your compiler supports it, use "volatile" - if your compiler respects it, use (or rather don't use) "register" - don't optimise the relvant routines. In some cases, it may be possible to move the setjmp() down into a separate procedure with fewer auto variables. In such cases it must be that you don't modify the variables in the outer procedure between setjmp() and longjmp(), so this will only help in case (4). -- Richard -- Richard Tobin, JANET: R.Tobin@uk.ac.ed AI Applications Institute, ARPA: R.Tobin%uk.ac.ed@nsfnet-relay.ac.uk Edinburgh University. UUCP: ...!ukc!ed.ac.uk!R.Tobin