On Fri, Aug 3, 2012 at 8:40 AM, Uros Bizjak <[email protected]> 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 <[email protected]>
>
> 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 <[email protected]>
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" } } */