nightmares with biased stack pointers

David S. Miller davem@jenolan.rutgers.edu
Sat Sep 13 03:26:00 GMT 1997


The sparc64 target presents an interesting state of affairs for gcc,
especially with respect to allocate_dynamic_stack_space().  I only
learned the problems caused when I finally hacked up and finally
bootstrapped a native 64-bit sparc64-linux compiler.  I had been using
a 32-->64 bit cross compiler up to this point, and as many of you know
gcc won't even attempt a lot of optimizations when the native word
size is smaller than the targets.

The problem is that sparc64 is the only target which has whats called
a 'biased' stack pointer.  %sp really doesn't point to the stack, it
points to the stack minus 2,047 bytes.  Why the weird number and why
the bias at all?  With 64-bit, stack frames get larger, the bias
allows you to access 2k more from the frame pointer than you otherwise
would be able to.  Think about it, you care not whats below the stack
pointer (when stack grows downward) but you do care a lot about whats
on both sides of the frame pointer.  This produces more chances that
the immediate offset in a load address can allow you to get to the
frame pointer relative stack slot in one instruction.

Anyways, consider allocate_dynamic_stack_space() being called to emit
code for an alloca() expression.  As an example, here is what I got
sort of looked like:

	unsigned long *p = alloca(16);

	foo(p);

produced

	sub	%sp, 16, %sp
	add	%sp, STACK_BIAS + FIRST_PARM_OFFSET, %o0
	add	%o0, 15, %o1
	srlx	%o1, 4, %o2
	sllx	%o2, 4, %o3
	mov	%o3, %o0
	call	foo
	 nop

(STACK_BIAS is the aforementioned 2047 byte bias %sp has,
 FIRST_PARM_OFFSET is a known aligned offset from that frame)

That code is correct and unoptimized.  If I turn on any optimizations,
the combiner looks at that and determines something along these lines:

1) Hey, I know how %sp must be aligned
2) Hey look, two redundant addition instructions, combine 'em
3) Hey look, taking into account the known alignment of the stack
   frame and the "add sp, const, reg; srlx 4; sllx 4;" sequence,
   I can determine that this is really an alignment of the 'constant'
   so I can merge this into a constant operation and blow the two
   shifts away.

I'm left with:

	sub	%sp, 16, %sp
	add	%sp, CONST_ALIGN_16(STACK_BIAS + FIRST_PARM_OFFSET + 15), %o0
	call	foo
	 nop

and a crash.

Any suggestions?

Later,
David "Sparc" Miller
davem@caip.rutgers.edu



More information about the Gcc mailing list