This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
inline asm constraints for conditions
- From: David Howells <dhowells at redhat dot com>
- To: gcc at gcc dot gnu dot org
- Date: Fri, 26 Sep 2003 19:07:12 +0100
- Subject: inline asm constraints for conditions
Would it be possible to get a new type of inline asm constraint added, such
that a "condition" can be an output? This would be useful in the Linux kernel
as there are a number of places where we have to write a value into a register
inside the asm statement and then test that value later.
Take something like the x86 test-and-set bit function for instance:
static __inline__ int test_and_set_bit(int nr, volatile void * addr)
{
int oldbit;
__asm__ __volatile__( LOCK_PREFIX
"btsl %2,%1\n\tsbbl %0,%0"
:"=r" (oldbit),"=m" (ADDR)
:"Ir" (nr) : "memory");
return oldbit;
}
Most of the time, all we want to do with the result is test it, eg:
if (test_and_set_bit(9, &wibble->flags)) {
...
}
However, this incurs unnecessary extra instructions:
lock bts %eax,(%edx)
sbb %eax,%eax <---
test %eax,%eax <---
jne 1c <x+0x1c>
What if, instead, it was possible to specify a special output-only constaint
of the form:
"=?<true-cond>/<false-cond>"
Where <true-cond> and <false-cond> are the condition parts of a branch, set or
move instruction mnemonic appropriate to the CPU. <true-cond> would be used to
test if the condition is true, and <false-cond> to test if it is false.
For example, the bit-test-and-set above could then be rewritten thus:
static __inline__ int test_and_set_bit(int nr, volatile void * addr)
{
int oldbit;
__asm__ __volatile__( LOCK_PREFIX
"btsl %2,%1"
:"=?c/nc" (oldbit),"=m" (ADDR)
:"Ir" (nr) : "memory");
return oldbit;
}
If the statement that uses it is an if-statement or a conditional operator,
this would be rendered into assembly using a jump or a conditional
instruction:
lock bts %eax,(%edx)
jnc 1c <x+0x1c>
Or:
lock bts %eax,(%edx)
cmovc $20,%ebx
Anyone trying to access the value directly would cause it to be turned into
zero if the condition was false, non-zero otherwise:
lock bts %eax,(%edx)
setc %eax
movzx %al,%eax
Possibly the compiler could detect c/nc and do the following as a special
case:
lock bts %eax,(%edx)
sbb %eax,%eax
As for non-x86 CPUs, on something like the SH where, IIRC, you have a single
flag (T), the following would then be possible:
"=?t/f" or "=?f/t"
And on the IA64 where predicate registers are available:
"=?p4/p7"
David