diff options
author | mkuvyrkov <mkuvyrkov@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-06-20 00:57:23 +0000 |
---|---|---|
committer | mkuvyrkov <mkuvyrkov@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-06-20 00:57:23 +0000 |
commit | 39a8c5eaded1e5771a941c56a49ca0a5e9c5eca0 (patch) | |
tree | cc80416977299664a93d282bbcace60a7d765062 /gcc/config/mips/sync.md | |
parent | d0c24bc90505bf4409fed3622482b24d23dfc596 (diff) | |
download | gcc-39a8c5eaded1e5771a941c56a49ca0a5e9c5eca0.tar.gz |
2012-06-19 Tom de Vries <vries@codesourcery.com>
Maxim Kuvyrkov <maxim@codesourcery.com>
* config/mips/mips.c (mips_emit_pre_atomic_barrier_p,)
(mips_emit_post_atomic_barrier_p): New static functions.
(mips_process_sync_loop): Use them. Emit sync memory barriers in
accordance with memory model semantics. Add return of CMP result for
compare_and_swap.
* config/mips/mips.md: Update comment.
(sync_cmp): New attribute.
(sync_memmodel): New attribute replacing sync_release_barrier.
* config/mips/sync.md (UNSPEC_ATOMIC_COMPARE_AND_SWAP,)
(UNSPEC_ATOMIC_EXCHANGE, UNSPEC_ATOMIC_FETCH_OP): New constants.
(sync_lock_test_and_set, test_and_set_12): Update.
(atomic_compare_and_swap, atomic_exchange, atomic_exchange_llsc,)
(atomic_fetch_add, atomic_fetch_add_llsc): New patterns.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@188803 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/mips/sync.md')
-rw-r--r-- | gcc/config/mips/sync.md | 107 |
1 files changed, 105 insertions, 2 deletions
diff --git a/gcc/config/mips/sync.md b/gcc/config/mips/sync.md index 1b4097ec225..604aefa3d0e 100644 --- a/gcc/config/mips/sync.md +++ b/gcc/config/mips/sync.md @@ -29,6 +29,9 @@ UNSPEC_SYNC_EXCHANGE UNSPEC_SYNC_EXCHANGE_12 UNSPEC_MEMORY_BARRIER + UNSPEC_ATOMIC_COMPARE_AND_SWAP + UNSPEC_ATOMIC_EXCHANGE + UNSPEC_ATOMIC_FETCH_OP ]) ;; Atomic fetch bitwise operations. @@ -54,6 +57,7 @@ "GENERATE_SYNC" { return mips_output_sync (); }) +;; Can be removed in favor of atomic_compare_and_swap below. (define_insn "sync_compare_and_swap<mode>" [(set (match_operand:GPR 0 "register_operand" "=&d,&d") (match_operand:GPR 1 "memory_operand" "+R,R")) @@ -368,6 +372,7 @@ (set_attr "sync_mem" "0") (set_attr "sync_insn1_op2" "1")]) +;; Can be removed in favor of atomic_fetch_add below. (define_insn "sync_old_add<mode>" [(set (match_operand:GPR 0 "register_operand" "=&d,&d") (match_operand:GPR 1 "memory_operand" "+R,R")) @@ -521,7 +526,7 @@ UNSPEC_SYNC_EXCHANGE))] "GENERATE_LL_SC" { return mips_output_sync_loop (insn, operands); } - [(set_attr "sync_release_barrier" "no") + [(set_attr "sync_memmodel" "11") (set_attr "sync_insn1" "li,move") (set_attr "sync_oldval" "0") (set_attr "sync_mem" "1") @@ -550,7 +555,7 @@ UNSPEC_SYNC_EXCHANGE_12))] "GENERATE_LL_SC" { return mips_output_sync_loop (insn, operands); } - [(set_attr "sync_release_barrier" "no") + [(set_attr "sync_memmodel" "11") (set_attr "sync_oldval" "0") (set_attr "sync_mem" "1") ;; Unused, but needed to give the number of operands expected by @@ -558,3 +563,101 @@ (set_attr "sync_inclusive_mask" "2") (set_attr "sync_exclusive_mask" "3") (set_attr "sync_insn1_op2" "4")]) + +(define_insn "atomic_compare_and_swap<mode>" + [(set (match_operand:GPR 0 "register_operand" "=&d,&d") + ;; Logically this unspec is an "eq" operator, but we need to obscure + ;; reads and writes from/to memory with an unspec to prevent + ;; optimizations on shared memory locations. Otherwise, comparison in + ;; { mem = 2; if (atomic_cmp_swap(mem,...) == 2) ...; } + ;; would be optimized away. In addition to that we need to use + ;; unspec_volatile, not just plain unspec -- for the sake of other + ;; threads -- to make sure we don't remove the entirety of the pattern + ;; just because current thread doesn't observe any effect from it. + ;; TODO: the obscuring unspec can be relaxed for permissive memory + ;; models. + ;; Same applies to other atomic_* patterns. + (unspec_volatile:GPR [(match_operand:GPR 2 "memory_operand" "+R,R") + (match_operand:GPR 3 "reg_or_0_operand" "dJ,dJ")] + UNSPEC_ATOMIC_COMPARE_AND_SWAP)) + (set (match_operand:GPR 1 "register_operand" "=&d,&d") + (unspec_volatile:GPR [(match_dup 2)] + UNSPEC_ATOMIC_COMPARE_AND_SWAP)) + (set (match_dup 2) + (unspec_volatile:GPR [(match_dup 2) + (match_dup 3) + (match_operand:GPR 4 "arith_operand" "I,d")] + UNSPEC_ATOMIC_COMPARE_AND_SWAP)) + (unspec_volatile:GPR [(match_operand:SI 5 "const_int_operand") + (match_operand:SI 6 "const_int_operand") + (match_operand:SI 7 "const_int_operand")] + UNSPEC_ATOMIC_COMPARE_AND_SWAP)] + "GENERATE_LL_SC" + { return mips_output_sync_loop (insn, operands); } + [(set_attr "sync_insn1" "li,move") + (set_attr "sync_oldval" "1") + (set_attr "sync_cmp" "0") + (set_attr "sync_mem" "2") + (set_attr "sync_required_oldval" "3") + (set_attr "sync_insn1_op2" "4") + (set_attr "sync_memmodel" "6")]) + +(define_expand "atomic_exchange<mode>" + [(match_operand:GPR 0 "register_operand") + (match_operand:GPR 1 "memory_operand") + (match_operand:GPR 2 "arith_operand") + (match_operand:SI 3 "const_int_operand")] + "GENERATE_LL_SC" +{ + emit_insn (gen_atomic_exchange<mode>_llsc (operands[0], operands[1], + operands[2], operands[3])); + DONE; +}) + +(define_insn "atomic_exchange<mode>_llsc" + [(set (match_operand:GPR 0 "register_operand" "=&d,&d") + (unspec_volatile:GPR [(match_operand:GPR 1 "memory_operand" "+R,R")] + UNSPEC_ATOMIC_EXCHANGE)) + (set (match_dup 1) + (unspec_volatile:GPR [(match_operand:GPR 2 "arith_operand" "I,d")] + UNSPEC_ATOMIC_EXCHANGE)) + (unspec_volatile:GPR [(match_operand:SI 3 "const_int_operand")] + UNSPEC_ATOMIC_EXCHANGE)] + "GENERATE_LL_SC" + { return mips_output_sync_loop (insn, operands); } + [(set_attr "sync_insn1" "li,move") + (set_attr "sync_oldval" "0") + (set_attr "sync_mem" "1") + (set_attr "sync_insn1_op2" "2") + (set_attr "sync_memmodel" "3")]) + +(define_expand "atomic_fetch_add<mode>" + [(match_operand:GPR 0 "register_operand") + (match_operand:GPR 1 "memory_operand") + (match_operand:GPR 2 "arith_operand") + (match_operand:SI 3 "const_int_operand")] + "GENERATE_LL_SC" +{ + emit_insn (gen_atomic_fetch_add<mode>_llsc (operands[0], operands[1], + operands[2], operands[3])); + DONE; +}) + +(define_insn "atomic_fetch_add<mode>_llsc" + [(set (match_operand:GPR 0 "register_operand" "=&d,&d") + (unspec_volatile:GPR [(match_operand:GPR 1 "memory_operand" "+R,R")] + UNSPEC_ATOMIC_FETCH_OP)) + (set (match_dup 1) + (unspec_volatile:GPR + [(plus:GPR (match_dup 1) + (match_operand:GPR 2 "arith_operand" "I,d"))] + UNSPEC_ATOMIC_FETCH_OP)) + (unspec_volatile:GPR [(match_operand:SI 3 "const_int_operand")] + UNSPEC_ATOMIC_FETCH_OP)] + "GENERATE_LL_SC" + { return mips_output_sync_loop (insn, operands); } + [(set_attr "sync_insn1" "addiu,addu") + (set_attr "sync_oldval" "0") + (set_attr "sync_mem" "1") + (set_attr "sync_insn1_op2" "2") + (set_attr "sync_memmodel" "3")]) |