Messages in this thread |  | | Subject | Re: i386 flags register clober in inline assembly | From | Momchil Velikov <> | Date | 17 Nov 2001 22:24:28 +0200 |
| |
>>>>> "Linus" == Linus Torvalds <torvalds@transmeta.com> writes:
Linus> (Example code:
Linus> atomic_sub_and_test: Linus> __asm__ __volatile__( Linus> LOCK "subl %2,%0; sete %1" Linus> :"=m" (v->counter), "=qm" (c) Linus> :"ir" (i), "m" (v->counter) : "memory");
Linus> Where we first get the value we _really_ want in ZF in eflags, then we Linus> use "sete" to move it to a register, and then gcc will end up generating Linus> code to test that register by hand, so the end result is usually Linus> something like:
Linus> #APP Linus> lock ; decl 20(%edi); sete %al Linus> #NO_APP Linus> testb %al, %al Linus> je .L1570
Linus> even though what we'd _want_ is really
Linus> lock ; decl 20(%edi) Linus> jne .L1570
Linus> which is not only smaller and faster, but is often _really_ faster Linus> because at least some Intel CPU's will forward the flags values to the Linus> branch prediction stuff, and going through a register dependency will Linus> add non-forwarded state and thus extra cycles.
Linus> So I would personally _really_ really like for some way to expose the Linus> internal gcc
Linus> "(set (cc0) ..asm..)"
Linus> construct, together with some way of setting the cc_status.flags.
Linux> From what I can tell, all the x86 machine description already uses "cc0" Linus> together with the notion of comparing it to zero (either signed or Linus> unsigned), so something like this _might_ just work
Linus> unsigned long result; Linus> asm volatile( Linus> LOCK "decl %m" Linus> :"+m" (v->counter), Linus> "=cc" (result) Linus> : :"memory"); Linus> if (result > 0) /* "jnb" */ Linus> ...
Linus> which would be wonderful, and would expand to
Linus> (set (cc0) ..asm..) Linus> (set (pc) Linus> (if_then_else (gtu (cc0) (const_int 0)) Linus> (label_ref (match_operand .. Linus> (pc))
Indeed, with pattern like: (define_insn "*ja" [(set (pc) (if_then_else (gtu (match_operand:CC 0 "" "") (const_int 0)) (label_ref (match_operand 1 "" "")) (pc)))] "" "ja ..." ...)
Linus> Which _should_ just automatically give us
Linus> lock ; decl .. Linus> ja ..
Linus> which is exactly what we want.
Regards, -velco - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
|  |