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/