[comp.unix.wizards] Should optimizing compilers automatically assign registers?

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