On Fri, Aug 3, 2012 at 8:40 AM, Uros Bizjak <ubiz...@gmail.com> wrote:
> We can implement atomic_fetch_sub with atomic_fetch_add and inverted > operand 2. However, we have to prevent overflows with negation, so > only const_int operand 2 is allowed in the expander. > > 2012-08-02 Uros Bizjak <ubiz...@gmail.com> > > PR target/54087 > * config/i386/sync.md (atomic_fetch_sub<mode>): New expander. > > Tested on x86_64-pc-linux-gnu {,-m32}. > > I will wait for a day for possible comments. Patch attached again, this time with a testcase. 2012-08-02 Uros Bizjak <ubiz...@gmail.com> PR target/54087 * gcc.target/i386/pr54087.c: New test. Uros.
Index: config/i386/sync.md =================================================================== --- config/i386/sync.md (revision 190111) +++ config/i386/sync.md (working copy) @@ -520,6 +520,31 @@ return "lock{%;} add{<imodesuffix>}\t{%1, %0|%0, %1}"; }) +;; We can use atomic_fetch_add with negated operand 2 to implement +;; atomic_fetch_sub. We have to prevent overflows with negation, so +;; only const_int operand 2 is allowed. +(define_expand "atomic_fetch_sub<mode>" + [(set (match_operand:SWI 0 "register_operand") + (unspec_volatile:SWI + [(match_operand:SWI 1 "memory_operand") + (match_operand:SI 3 "const_int_operand")] ;; model + UNSPECV_XCHG)) + (set (match_dup 1) + (minus:SWI (match_dup 1) + (match_operand:SWI 2 "const_int_operand"))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_XADD" +{ + /* Avoid overflows. */ + if (mode_signbit_p (<MODE>mode, operands[2])) + FAIL; + + emit_insn (gen_atomic_fetch_add<mode> (operands[0], operands[1], + negate_rtx (<MODE>mode, operands[2]), + operands[3])); + DONE; +}) + ;; Recall that xchg implicitly sets LOCK#, so adding it again wastes space. ;; In addition, it is always a full barrier, so we can ignore the memory model. (define_insn "atomic_exchange<mode>" Index: testsuite/gcc.target/i386/pr54087.c =================================================================== --- testsuite/gcc.target/i386/pr54087.c (revision 0) +++ testsuite/gcc.target/i386/pr54087.c (revision 0) @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ +/* { dg-additional-options "-march=i486" { target ia32 } } */ + +int v; + +int foo (void) +{ + return __atomic_sub_fetch (&v, 5, __ATOMIC_SEQ_CST); +} + +/* { dg-final { scan-assembler "xadd" } } */ +/* { dg-final { scan-assembler-not "cmpxchg" } } */