RE: FW: RE: x86_64 port

2005-03-08 Thread Simon Marlow
On 07 March 2005 18:01, Kurt Roeckx wrote:

 On Mon, Mar 07, 2005 at 11:47:31AM -, Simon Marlow wrote:
 
 $ cat bug.c
 register void * R1 __asm__(%r13);
 
 extern void g(void);
 static void f(void) {
  R1 = g;
  goto *R1;
 }
 $ gcc -S -O bug.c
 $
 
 And take a look at the generated assembly for the function f:
 
 f:
 .LFB2:
 movl$g, %eax
 jmp *%rax
 
 I get the same with both gcc-3.3 and gcc-3.4.  They generate
 identical code.
 
 Note that the assignment to the global variable R1 has been lost.  It
 works fine on x86 though: change the register variable to %esi and
 try it.
 
 It looks to me like it's using eax/rax instead of r13 to me.
 It's probably doing some optimizing it shouldn't, but on the
 other hand isn't wrong.
... 
 Anyway, as summary:
 - It's using a movl where it should use a movq
 - It's probably doing some optimizations it shouldn't, but
   they're not wrong in this testcase and probably can't be
   avoided because of the way gcc works.
   Those happen on both i386 and amd64.

The question of whether this behaviour is wrong or not is interesting.
On the face of it, the generated code is incorrect because it doesn't
implement the semantics of the original program.

However, we have to be clear about what the semantics of the original
program *is*.  The register annotation is just an annotation, and
therefore doesn't affect the semantics.  But the gcc manual has this to
say about computed goto:

  You may not use this mechanism to jump to code in a different
  function.

So, perhaps the example program relies on undefined behaviour.  But, you
can change the example program so that gcc has no idea where it's
jumping to, and gcc will still generate incorrect code.  So in fact it
has nothing to do with the jump destination being outside the current
function.

It's a bug.

Cheers,
Simon
___
Glasgow-haskell-users mailing list
Glasgow-haskell-users@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users


Re: FW: RE: x86_64 port

2005-03-07 Thread Kurt Roeckx
On Fri, Mar 04, 2005 at 11:13:28AM -0600, John Goerzen wrote:
 Do any of you know if this is a known problem?
 
 - Forwarded message from Simon Marlow [EMAIL PROTECTED] -
 
 From: Simon Marlow [EMAIL PROTECTED]
 Date: Fri, 4 Mar 2005 17:03:31 -
 To: John Goerzen [EMAIL PROTECTED]
 Cc: glasgow-haskell-users@haskell.org
 Subject: RE: x86_64 port
 
 On 04 March 2005 16:59, John Goerzen wrote:
 
  On Fri, Mar 04, 2005 at 04:57:04PM -, Simon Marlow wrote:
  On 04 March 2005 14:04, John Goerzen wrote:
  My amd64 hardware arrived yesterday, shouldn't be too long before
  we have a registerised port of GHC, and possibly a native code
  generator...
  
  burns excellent /burns
  
  Don't hold your breath, I have some bad news.  It seems that gcc is
  still generating incorrect code for register variables (or maybe it's
  broken again?).
  
  Which version of gcc?
 
 gcc (GCC) 3.4.2 20041017 (Red Hat 3.4.2-6.fc3)

I have no idea what ghc has too do with gcc, or what the problem
exactly is.  We have very little problems with gcc for the debian
amd64 port.  Our default compiler is still 3.3.  This builds
almost everything without problems, however we build a few
mozilla packages with gcc-3.4.

All I can tell is that ghc6 seems to be working on debian amd64.
It can build itself and things like that.

Can someone please give a test case (and show what to do) to see
what is wrong?

Out current default compiler in debian is:
gcc version 3.3.5 (Debian 1:3.3.5-8)

The gcc 3.4 version is:
gcc version 3.4.4 20050203 (prerelease) (Debian 3.4.3-9)

And ghc6 is at version 6.2.2-3.


Kurt

___
Glasgow-haskell-users mailing list
Glasgow-haskell-users@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users


RE: FW: RE: x86_64 port

2005-03-07 Thread Simon Marlow
On 04 March 2005 17:32, Kurt Roeckx wrote:

 I have no idea what ghc has too do with gcc,

A bit of background: GHC uses gcc as a backend compiler.  GHC generates
C code that is compiled using gcc (we also have a native code generator
for some platforms; but not for x86_64 yet).

 or what the problem exactly is.

The problem is that gcc generates incorrect code for C code that uses
global register variables.  You won't have noticed this, because most
programs don't use global register variables.  GHC uses global register
variables to speed up the generated code.

 We have very little problems with gcc for the debian
 amd64 port.  Our default compiler is still 3.3.  This builds
 almost everything without problems, however we build a few
 mozilla packages with gcc-3.4.
 
 All I can tell is that ghc6 seems to be working on debian amd64.
 It can build itself and things like that.

That build of ghc6 is what we call unregisterised: it doesn't make use
of register variables to speed up the generated code.  IOW, it generates
plain ANSI C code, which gcc compiles fine.

 Can someone please give a test case (and show what to do) to see
 what is wrong?

Ok, here's a really simple example:

$ cat bug.c
register void * R1 __asm__(%r13);

extern void g(void);
static void f(void) {
 R1 = g;
 goto *R1;
}
$ gcc -S -O bug.c
$

And take a look at the generated assembly for the function f:

f:
.LFB2:
movl$g, %eax
jmp *%rax

Note that the assignment to the global variable R1 has been lost.  It
works fine on x86 though: change the register variable to %esi and try
it.

 Out current default compiler in debian is:
 gcc version 3.3.5 (Debian 1:3.3.5-8)
 
 The gcc 3.4 version is:
 gcc version 3.4.4 20050203 (prerelease) (Debian 3.4.3-9)
 
 And ghc6 is at version 6.2.2-3.

I'm going to try with different versions of gcc.  I've just submitted
this bug report to the gcc guys.

Cheers,
Simon
___
Glasgow-haskell-users mailing list
Glasgow-haskell-users@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users


Re: FW: RE: x86_64 port

2005-03-07 Thread David Brown
On Mon, Mar 07, 2005 at 11:47:31AM -, Simon Marlow wrote:

 $ cat bug.c
 register void * R1 __asm__(%r13);
 
 extern void g(void);
 static void f(void) {
  R1 = g;
  goto *R1;
 }
 $ gcc -S -O bug.c
 $
 
 And take a look at the generated assembly for the function f:
 
 f:
 .LFB2:
 movl$g, %eax
 jmp *%rax
 
 Note that the assignment to the global variable R1 has been lost.  It
 works fine on x86 though: change the register variable to %esi and try
 it.

Hmm.  On gcc 3.3.5 that I have, it discards the assignment on x86 as well.

Dave
___
Glasgow-haskell-users mailing list
Glasgow-haskell-users@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users


RE: FW: RE: x86_64 port

2005-03-07 Thread Simon Marlow
On 07 March 2005 16:18, David Brown wrote:

 On Mon, Mar 07, 2005 at 11:47:31AM -, Simon Marlow wrote:
 
 $ cat bug.c
 register void * R1 __asm__(%r13);
 
 extern void g(void);
 static void f(void) {
  R1 = g;
  goto *R1;
 }
 $ gcc -S -O bug.c
 $
 
 And take a look at the generated assembly for the function f:
 
 f:
 .LFB2:
 movl$g, %eax
 jmp *%rax
 
 Note that the assignment to the global variable R1 has been lost.  It
 works fine on x86 though: change the register variable to %esi and
 try it.
 
 Hmm.  On gcc 3.3.5 that I have, it discards the assignment on x86 as
 well. 

Yes, looks like it fails with 3.4.1 and 3.4.3 I have here, but 3.2.2
works.

Now I'm quite surpised that this hasn't affected us on x86.  Very
strange.

Cheers,
Simon
___
Glasgow-haskell-users mailing list
Glasgow-haskell-users@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users


RE: FW: RE: x86_64 port

2005-03-07 Thread Simon Marlow
On 07 March 2005 16:40, Simon Marlow wrote:

 On 07 March 2005 16:18, David Brown wrote:
 
 On Mon, Mar 07, 2005 at 11:47:31AM -, Simon Marlow wrote:
 
 $ cat bug.c
 register void * R1 __asm__(%r13);
 
 extern void g(void);
 static void f(void) {
  R1 = g;
  goto *R1;
 }
 $ gcc -S -O bug.c
 $
 
 And take a look at the generated assembly for the function f:
 
 f:
 .LFB2:
 movl$g, %eax
 jmp *%rax
 
 Note that the assignment to the global variable R1 has been lost. 
 It works fine on x86 though: change the register variable to %esi
 and try it.
 
 Hmm.  On gcc 3.3.5 that I have, it discards the assignment on x86 as
 well.
 
 Yes, looks like it fails with 3.4.1 and 3.4.3 I have here, but 3.2.2
 works.
 
 Now I'm quite surpised that this hasn't affected us on x86.  Very
 strange.

The mystery as to why this doesn't affect us on x86 is solved: on x86 we
generate slightly different C code, including a dummy function call:

extern void g(void);
static void f(void) {
  R1 = g;
  dummy();
  goto *R1;
}

the call to dummy() (which we filter out from the assembly later) is
enough to force gcc to emit the assignment to R1.  That dummy function
call has been there for ever, and the original reason for it has been
lost in the mists of time... comments in the source code seemed to
indicate that it was probably not necessary any more, so for x86_64 I
removed it.  It looks like I'll have to reinstate it to work around this
bug, though.

Cheers,
Simon
___
Glasgow-haskell-users mailing list
Glasgow-haskell-users@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users


Re: FW: RE: x86_64 port

2005-03-07 Thread David Brown
On Mon, Mar 07, 2005 at 04:59:38PM -, Simon Marlow wrote:

 The mystery as to why this doesn't affect us on x86 is solved: on x86 we
 generate slightly different C code, including a dummy function call:
 
 extern void g(void);
 static void f(void) {
   R1 = g;
   dummy();
   goto *R1;
 }
 
 the call to dummy() (which we filter out from the assembly later) is
 enough to force gcc to emit the assignment to R1.  That dummy function
 call has been there for ever, and the original reason for it has been
 lost in the mists of time... comments in the source code seemed to
 indicate that it was probably not necessary any more, so for x86_64 I
 removed it.  It looks like I'll have to reinstate it to work around this
 bug, though.

gcc 3.3.4 on AMD64 appears to generate correct code when the dummy call is
present.  Ick.

Dave
___
Glasgow-haskell-users mailing list
Glasgow-haskell-users@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users


Re: FW: RE: x86_64 port

2005-03-07 Thread Duncan Coutts
In message [EMAIL PROTECTED] David Brown
[EMAIL PROTECTED] writes:
 On Mon, Mar 07, 2005 at 04:59:38PM -, Simon Marlow wrote:
 
  The mystery as to why this doesn't affect us on x86 is solved: on x86 we
  generate slightly different C code, including a dummy function call:
  
  extern void g(void);
  static void f(void) {
R1 = g;
dummy();
goto *R1;
  }
  
  the call to dummy() (which we filter out from the assembly later) is
  enough to force gcc to emit the assignment to R1.  That dummy function
  call has been there for ever, and the original reason for it has been
  lost in the mists of time... comments in the source code seemed to
  indicate that it was probably not necessary any more, so for x86_64 I
  removed it.  It looks like I'll have to reinstate it to work around this
  bug, though.

This all appears to be the same for Sparc. With:

register void * R1 __asm__(%g7);

extern void g(void);
static void f(void) {
 R1 = g;
 goto *R1;
}

(BTW I have no idea if register g7 is a sensible choice here! So this test may
be meaningless!)

We get:

sethi   %hi(g), %g1
jmp %g1+%lo(g)
nop

While with the dummy() call inserted:

sethi   %hi(g), %g1
calldummy, 0
or  %g1, %lo(g), %g7
jmp %g7
nop

we actually get any mention of %g7 at all.

This is with gcc 3.3.5 on Sparc Linux (Gentoo).

Duncan
___
Glasgow-haskell-users mailing list
Glasgow-haskell-users@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users


Re: FW: RE: x86_64 port

2005-03-07 Thread Kurt Roeckx
On Mon, Mar 07, 2005 at 11:47:31AM -, Simon Marlow wrote:
 
 $ cat bug.c
 register void * R1 __asm__(%r13);
 
 extern void g(void);
 static void f(void) {
  R1 = g;
  goto *R1;
 }
 $ gcc -S -O bug.c
 $
 
 And take a look at the generated assembly for the function f:
 
 f:
 .LFB2:
 movl$g, %eax
 jmp *%rax

I get the same with both gcc-3.3 and gcc-3.4.  They generate
identical code.

 Note that the assignment to the global variable R1 has been lost.  It
 works fine on x86 though: change the register variable to %esi and try
 it.

It looks to me like it's using eax/rax instead of r13 to me.
It's probably doing some optimizing it shouldn't, but on the
other hand isn't wrong.
Also, it should be a movq $g, %rax instead of movl.

Without -O I get:
f:
pushq   %rbp
movq%rsp, %rbp
movl$g, %r13d
movq%r13, %rax
jmp *%rax

(Note that the first 2 instructions are now a stack frame,
disabled with -O)

It still is using an movl instead of a movq, which is wrong.

esi (or rsi) give the following warning:
bug.c:1: warning: call-clobbered register used for global register variable

And doesn't change a thing.  It's still the same code.

Using %ebp or %rbp with -O gives:

movl$g, %ebp
jmp *%rbp

Which gives the same movl/movq problem, but now got the right
register.


Doing the same on i386 generates this:
f:
pushl   %ebp
movl%esp, %ebp
movl$g, %eax
jmp *%eax

Using -fomit-frame-pointer you get:
f:
movl$g, %eax
jmp *%eax

Which seems to be exactly the same thing, except it got the size
right now.

The weird thing is that r13 doesn't exist on i386, and it didn't
complain about it.

Anyway, as summary:
- It's using a movl where it should use a movq
- It's probably doing some optimizations it shouldn't, but
  they're not wrong in this testcase and probably can't be
  avoided because of the way gcc works.
  Those happen on both i386 and amd64.


Kurt

___
Glasgow-haskell-users mailing list
Glasgow-haskell-users@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users


Re: FW: RE: x86_64 port

2005-03-07 Thread Kurt Roeckx
On Mon, Mar 07, 2005 at 09:15:01AM -0800, David Brown wrote:
 
 gcc 3.3.4 on AMD64 appears to generate correct code when the dummy call is
 present.  Ick.

It generates the following code here:

subq$8, %rsp
movl$g, %r13d
movl$0, %eax
calldummy
jmp *%r13

Which still has the movl vs movq problem.


Kurt

___
Glasgow-haskell-users mailing list
Glasgow-haskell-users@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users


Re: FW: RE: x86_64 port

2005-03-07 Thread David Brown
On Mon, Mar 07, 2005 at 07:01:16PM +0100, Kurt Roeckx wrote:

 Also, it should be a movq $g, %rax instead of movl.

The default x86_64 model on gcc is -mcmodel=small, which assumes that all
symbols are within the first 2GB.  If you compile it with -mcmodel=medium
it'll generate:

  movabsq  $g, %r13

Dave
___
Glasgow-haskell-users mailing list
Glasgow-haskell-users@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users