public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* Register Allocation Bug?
@ 2009-03-25 10:55 Kasper Bonne
  2009-04-06 17:51 ` Segher Boessenkool
  0 siblings, 1 reply; 2+ messages in thread
From: Kasper Bonne @ 2009-03-25 10:55 UTC (permalink / raw)
  To: gcc-bugs

Hi List

I have a question (or possible compiler bug) regarding inline assembly
that I hope you can help me with.

I wanted a routine that would give me the value and address of a
memory location relative to the stack pointer. What I initially tried
was the following:

#define ESP(rel,value,addr)                                             \
    asm volatile ("mov (%%esp, %2, 4), %0\n\t"                          \
                  "lea (%%esp, %2, 4), %1\n\t"                          \
                  : "=r" (value), "=r" (addr)                           \
                  : "r" (rel));                                         \

It didn't work as expected so I looked at the assembler code generated
for the above:

 1:       b8 00 00 00 00          mov    $0x0,%eax
 2:       8b 04 84                mov    (%esp,%eax,4),%eax
 3:       8d 14 84                lea    (%esp,%eax,4),%edx
 4:       89 45 f8                mov    %eax,0xfffffff8(%ebp)
 5:       89 55 fc                mov    %edx,0xfffffffc(%ebp)


As it turns out, %eax is being used for both input and output in line
2, clobbering %eax, so of course line 3 does not give the expected
result... Is this a compiler error?  I thought the only way the same
register would be used for both input and output was if you use the
"0" constraint? I'm compiling with 'GCC 4.2.1 20070719'.

The best solution I found was to split the two assembler statements in
the following way:

#define ESP(rel,value,addr)                                             \
    asm volatile ("movl (%%esp, %1, 4), %0\n\t" :                       \
                  "=r" (value) : "r" (rel));                            \
    asm volatile ("lea  (%%esp, %1, 4), %0\n\t" :                       \
                  "=r" (addr) : "r" (rel));

The above compiles into six instructions instead of five (duplicating
mov $0x0,%eax) but is has the benefit of only using one register:

 1:       b8 00 00 00 00          mov    $0x0,%eax
 2:       8b 04 84                mov    (%esp,%eax,4),%eax
 3:       89 45 fc                mov    %eax,0xfffffffc(%ebp)
 4:       b8 00 00 00 00          mov    $0x0,%eax
 5:       8d 04 84                lea    (%esp,%eax,4),%eax
 6:       89 45 f0                mov    %eax,0xfffffff0(%ebp)

So, again, my question is this: Is the compiler doing what it's
supposed to when it's assigning the same register to both input and
output when the specified constraint is "r" and not "0"?

As far as I can tell this problem have been floating around for a
number of years. The following post from 2000 describes exactly the
same issue:

http://gcc.gnu.org/ml/gcc-bugs/2000-07/msg00456.html

Since it hasn't been fixed maybe it's a bu..*ahem*..feature?

Best
/Kasper


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: Register Allocation Bug?
  2009-03-25 10:55 Register Allocation Bug? Kasper Bonne
@ 2009-04-06 17:51 ` Segher Boessenkool
  0 siblings, 0 replies; 2+ messages in thread
From: Segher Boessenkool @ 2009-04-06 17:51 UTC (permalink / raw)
  To: Kasper Bonne; +Cc: gcc-bugs

> #define ESP 
> (rel,value,addr)                                             \
>     asm volatile ("mov (%%esp, %2, 4), %0\n 
> \t"                          \
>                   "lea (%%esp, %2, 4), %1\n 
> \t"                          \
>                   : "=r" (value),  
> "=r" (addr)                           \
>                   :  
> "r" (rel));                                         \
>
> It didn't work as expected so I looked at the assembler code generated
> for the above:
>
>  1:       b8 00 00 00 00          mov    $0x0,%eax
>  2:       8b 04 84                mov    (%esp,%eax,4),%eax
>  3:       8d 14 84                lea    (%esp,%eax,4),%edx
>  4:       89 45 f8                mov    %eax,0xfffffff8(%ebp)
>  5:       89 55 fc                mov    %edx,0xfffffffc(%ebp)
>
>
> As it turns out, %eax is being used for both input and output in line
> 2, clobbering %eax, so of course line 3 does not give the expected
> result... Is this a compiler error?

It's not a compiler bug: you need to use an "early clobber", namely
"=&r"(value) .  See the Fine Manual.


Segher


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2009-04-06 17:51 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-03-25 10:55 Register Allocation Bug? Kasper Bonne
2009-04-06 17:51 ` Segher Boessenkool

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).