Sparc `long long' incorrect code generation

Zack Weinberg zack@rabi.phys.columbia.edu
Mon Oct 20 19:22:00 GMT 1997


Solaris has a special trap to read the `high resolution timer' which
is useful for timing inner loops.  It's exposed as a library call,
gethrtime(), the disassembly of which is:

gethrvtime:
	ta 0x24
	retl
	nop

The trap returns a 64 bit value in o0:o1 (hi:lo).  You can write a
version of this with gcc's inline asms:

unsigned long long
timer(void)
{
    register unsigned long long val asm("%o0");
    asm("ta 0x24" : "=r" (val));
    return val;
}

gcc 2.7.2 translates this to
timer:
        save %sp,-112,%sp
        ta 0x24
        mov %o0,%i0
        mov %o1,%i1
        ret
        restore

which is correct, although it should be optimized to a leaf.  egcs
971016, on the other hand, generates:

timer:
        save %sp,-112,%sp
        ta 0x24
        ret
        restore

which, if I understand Sparc register windows correctly, is wrong:
the results of the trap will be shifted away and the caller will not
see them.

Interestingly, if you make this an inline function and refer to it
elsewhere, say like so:

extern void foo(unsigned long long);
int
main(void)
{
    foo(timer());
    return 0;
}

both compilers generate the same code:

main:
        save %sp,-112,%sp
        ta 0x24
        call foo,0
        mov 0,%i0
        ret
        restore

which is correct and optimal.

Also, it would be nice if the docs said that you could allocate a
32-bit register pair to a 64-bit integer by putting the high register
in the asm("reg") phrase.  I found that out by trial and error.

zw



More information about the Gcc mailing list