complex support on alpha

Kamil Iskra kamil@dwd.interkom.pl
Sat Oct 4 14:33:00 GMT 1997


On Thu, 2 Oct 1997, Jim Wilson wrote:

> It has been broken ever since the initial implementation.  There is a general
> problem that __complex__ X fails if X is half the word size or smaller.
> For instance, __complex__ short will fail on any 32 bit machine in the same
> way that __complex__ float fails on the alpha.  It would be nice to see this
> fixed.

Could you please explain how things are *supposed* to work?

Richard Henderson says that on Alpha the real and imaginary parts should
be passed as two completely separate arguments. Is this how it should work
on any other target?

For example, see what I get on m68k-amigaos, for __complex__ char:

#include <stdio.h>

void f(__complex__ char cc)
{
	printf("cc: (%d, %d)\n", __real__ cc, __imag__ cc);
}

int main(void)
{
	__complex__ char cc;
	__real__ cc=1;
	__imag__ cc=2;
	f(cc);
}

#NO_APP
gcc2_compiled.:
___gnu_compiled_c:
.text
LC0:
	.ascii "cc: (%d, %d)\12\0"
	.even
.globl _f
_f:
	link a5,#0
	moveb a5@(11),d0 ;# 26 movqi+1/1
	extw d0 ;# 7 extendqihi2
	movew d0,a0 ;# 8 extendhisi2/2
	movel a0,sp@- ;# 10 movsi+1/1
	moveb a5@(10),d0 ;# 28 movqi+1/1
	extw d0 ;# 11 extendqihi2
	movew d0,a0 ;# 12 extendhisi2/2
	movel a0,sp@- ;# 14 movsi+1/1
	pea LC0 ;# 16 movsi+1/1
	jbsr _printf ;# 18 call_value+1
	lea sp@(12),sp ;# 19 *addsi3_internal/2
L5:
	unlk a5
	rts
	.even
.globl _main
_main:
	link a5,#-4
	jbsr ___main ;# 6 call+1
	moveb #1,a5@(-2) ;# 10 movqi+1/3
	moveb #2,a5@(-1) ;# 12 movqi+1/3
	subql #2,sp ;# 14 movqi+1/3
	moveb a5@(-1),sp@(1)
	subql #2,sp ;# 15 movqi+1/3
	moveb a5@(-2),sp@(1)
	subql #2,sp ;# 16 *addsi3_internal/2
	jbsr _f ;# 18 call+1
	addql #4,sp ;# 19 *addsi3_internal/2
	moveq #0,d0 ;# 23 movsi_const0
	jra L6 ;# 25 jump
	.even
L6:
	unlk a5
	rts

In f(), the stack is referenced as if there was a single, two-byte
__complex__ char variable on it. However, that's not the way main() 
arranges things: it puts a padding inbetween (insns 14 and 15), since the
m68k stack has to be 16-bit aligned. "Who" is right - main() or f()?

Actually, there's yet another problem, with a completely bogus insn 16.
The compiler pushes 6 bytes, but pops only 4 (insn 19). That's because
PARM_BOUNDARY is 32, and in calls.c:store_one_arg the compiler decides
that it will need to adjust stack for 2 bytes, but it doesn't yet know
that this won't be needed since it's not going to push one 2-byte object,
but two 1-byte ones, with PUSH_ROUNDING alignment for each of them.

Not surprisingly, the above code works fine if char is changed to short.

And one more thing. If I change the "cc" definition in main() to:

	register __complex__ char cc __asm__("d2");

I get the following main():

_main:
	link a5,#0
	movel d2,sp@-
	jbsr ___main ;# 6 call+1
	moveq #1,d2 ;# 10 movqi+1/1
	moveq #2,d2 ;# 12 movqi+1/1
	subql #2,sp ;# 14 movqi+1/3
	moveb d2,sp@(1)
	subql #2,sp ;# 15 movqi+1/3
	moveb d2,sp@(1)
	subql #2,sp ;# 16 *addsi3_internal/2
	jbsr _f ;# 18 call+1
	addql #4,sp ;# 19 *addsi3_internal/2
	moveq #0,d0 ;# 24 movsi_const0
	jra L6 ;# 26 jump
	.even
L6:
	movel a5@(-4),d2
	unlk a5
	rts

The compiler is clearly unaware that it needs to apply more logic for
stores/loads or real and imaginary parts when they are in the same
register. How is such a case supposed to work? Should two separate
registers be allocated (d2 and d3 in this case), or should more
sophisticated store/load code be generated?

/ Kamil Iskra - AMIGA 1200, 68030 50MHz, HDD 1.6 GB, 18 MB RAM \
| iskra@student.uci.agh.edu.pl  kiskra@ernie.icslab.agh.edu.pl |
| http://student.uci.agh.edu.pl/~iskra                         |
\ PGP public key available via Finger or WWW                   /




More information about the Gcc mailing list