This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]