RE: FW: RE: x86_64 port
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
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
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
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
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
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
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
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
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
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
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