This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
block reordering problem
- To: gcc-bugs at gcc dot gnu dot org
- Subject: block reordering problem
- From: Ulrich Drepper <drepper at redhat dot com>
- Date: 09 Sep 2000 23:15:48 -0700
- Cc: rth at cygnus dot com
- Reply-To: drepper at cygnus dot com (Ulrich Drepper)
glibc ones more does not compile with the current mainline gcc on x86.
I haven't tried it for quite some time so I cannot say when the
problem got introduced.
I managed to get a reduced testcase which I append below. Compile it
with
-O3 -march=i686 -freorder-blocks
The interesting case is the fail branch of the ?: operator in foo.
Due to block reordering and the NULL pointer comparison this code is
ouf ot line. The code I get for the function is this:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
const char *
foo (const char *n, const char *m)
30: 55 push %ebp
31: 89 e5 mov %esp,%ebp
33: 53 push %ebx
34: 83 ec 14 sub $0x14,%esp
37: 8b 4d 08 mov 0x8(%ebp),%ecx
3a: 8b 5d 0c mov 0xc(%ebp),%ebx
{
3d: 85 db test %ebx,%ebx
3f: 74 20 je 61 <foo+0x31>
41: 83 ec 08 sub $0x8,%esp
44: 51 push %ecx
45: 53 push %ebx
46: e8 fc ff ff ff call 47 <foo+0x17>
47: R_386_PC32 bar
4b: 83 c4 10 add $0x10,%esp
const char *r = m ? bar (m, n) : local_strdup (n);
4e: 83 ec 0c sub $0xc,%esp
51: 50 push %eax
52: e8 fc ff ff ff call 53 <foo+0x23>
53: R_386_PC32 baz
return baz (r);
57: 8b 5d fc mov 0xfffffffc(%ebp),%ebx
5a: 83 c4 10 add $0x10,%esp
5d: 89 ec mov %ebp,%esp
5f: 5d pop %ebp
60: c3 ret
61: 89 c8 mov %ecx,%eax
63: 83 ec 0c sub $0xc,%esp
66: 8a 10 mov (%eax),%dl
68: 8d 40 01 lea 0x1(%eax),%eax
6b: 84 d2 test %dl,%dl
6d: 75 f7 jne 66 <foo+0x36>
6f: 29 c8 sub %ecx,%eax
71: 50 push %eax
72: e8 fc ff ff ff call 73 <foo+0x43>
73: R_386_PC32 malloc
77: 83 c4 10 add $0x10,%esp
7a: 85 c0 test %eax,%eax
7c: 0f 44 c3 cmove %ebx,%eax
7f: eb cd jmp 4e <foo+0x1e>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The test at offset 0x3d is the test in the ?: operator. At offset
0x61 you'll see the inlined strlen() call and then the malloc() call.
So far so good. At offset 0x7a the memcpy() part of the
local_strdup() function should be but there is just the test with a
senseless conditional move. At offset 0x4e there is just the call of
baz(). This means the memcpy() call (or the inlining) was optimized
out.
It tried making this into a runnable program but failed because -O3
wants to inline a lot and this makes the problem go away.
--
---------------. ,-. 1325 Chesapeake Terrace
Ulrich Drepper \ ,-------------------' \ Sunnyvale, CA 94089 USA
Red Hat `--' drepper at redhat.com `------------------------
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#include <stddef.h>
extern void *malloc (size_t) __attribute__ ((__malloc__));
size_t
strlen (__const char *__str)
{
register char __dummy;
register __const char *__tmp = __str;
__asm__ __volatile__
("1:\n\t"
"movb (%0),%b1\n\t"
"leal 1(%0),%0\n\t"
"testb %b1,%b1\n\t"
"jne 1b"
: "=r" (__tmp), "=&q" (__dummy)
: "0" (__str)
: "memory", "cc" );
return __tmp - __str - 1;
}
void *
memcpy (void *__dest, __const void *__src, size_t __n)
{
register unsigned long int __d0, __d1, __d2;
register void *__tmp = __dest;
__asm__ __volatile__
("cld\n\t"
"shrl $1,%%ecx\n\t"
"jnc 1f\n\t"
"movsb\n"
"1:\n\t"
"shrl $1,%%ecx\n\t"
"jnc 2f\n\t"
"movsw\n"
"2:\n\t"
"rep; movsl"
: "=&c" (__d0), "=&D" (__d1), "=&S" (__d2)
: "0" (__n), "1" (__tmp), "2" (__src)
: "memory", "cc");
return __dest;
}
static inline char *
local_strdup (const char *s)
{
size_t len = strlen (s) + 1;
void *new = malloc (len);
if (new == NULL)
return NULL;
return (char *) memcpy (new, s, len);
}
extern const char *bar (const char *, const char *);
extern const char *baz (const char *);
const char *
foo (const char *n, const char *m)
{
const char *r = m ? bar (m, n) : local_strdup (n);
return baz (r);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~