diff options
author | Matthew Wahab <matthew.wahab@arm.com> | 2015-09-22 09:19:55 +0000 |
---|---|---|
committer | Matthew Wahab <mwahab@gcc.gnu.org> | 2015-09-22 09:19:55 +0000 |
commit | 9cd7b72071d5b1101de6b726391e8ba71a61638f (patch) | |
tree | 86873c021fe60c2fffb4d16ae53a756647797d52 /gcc/config/aarch64/atomics.md | |
parent | 9915b1c916b1e6aa0fb7aa738dcc217f5f69b8ef (diff) | |
download | gcc-9cd7b72071d5b1101de6b726391e8ba71a61638f.zip gcc-9cd7b72071d5b1101de6b726391e8ba71a61638f.tar.gz gcc-9cd7b72071d5b1101de6b726391e8ba71a61638f.tar.bz2 |
[AArch64] Use atomic instructions for swap and fetch-update operations.
gcc/
2015-09-22 Matthew Wahab <matthew.wahab@arm.com>
* config/aarch64/aarch64-protos.h (aarch64_gen_atomic_ldop):
Declare.
* config/aarch64/aarch64.c (aarch64_emit_atomic_swap): New.
(aarch64_gen_atomic_ldop): New.
(aarch64_split_atomic_op): Fix whitespace and add a comment.
* config/aarch64/atomics.md (UNSPECV_ATOMIC_SWP): New.
(aarch64_compare_and_swap<mode>_lse): Fix some whitespace.
(atomic_exchange<mode>): Replace with an expander.
(aarch64_atomic_exchange<mode>): New.
(aarch64_atomic_exchange<mode>_lse): New.
(aarch64_atomic_<atomic_optab><mode>): Fix some whitespace.
(aarch64_atomic_swp<mode>): New.
gcc/testsuite/
2015-09-22 Matthew Wahab <matthew.wahab@arm.com>
* gcc.target/aarch64/atomic-inst-ops.inc: (TEST_MODEL): New.
(TEST_ONE): New.
* gcc.target/aarch64/atomic-inst-swap.c: New.
From-SVN: r227998
Diffstat (limited to 'gcc/config/aarch64/atomics.md')
-rw-r--r-- | gcc/config/aarch64/atomics.md | 71 |
1 files changed, 67 insertions, 4 deletions
diff --git a/gcc/config/aarch64/atomics.md b/gcc/config/aarch64/atomics.md index 65d2cc9..cb80539 100644 --- a/gcc/config/aarch64/atomics.md +++ b/gcc/config/aarch64/atomics.md @@ -27,6 +27,7 @@ UNSPECV_ATOMIC_CMPSW ; Represent an atomic compare swap. UNSPECV_ATOMIC_EXCHG ; Represent an atomic exchange. UNSPECV_ATOMIC_CAS ; Represent an atomic CAS. + UNSPECV_ATOMIC_SWP ; Represent an atomic SWP. UNSPECV_ATOMIC_OP ; Represent an atomic operation. ]) @@ -134,7 +135,7 @@ (match_operand:SI 5 "const_int_operand") ;; mod_s (match_operand:SI 6 "const_int_operand")] ;; mod_f UNSPECV_ATOMIC_CMPSW))] - "TARGET_LSE " + "TARGET_LSE" "#" "&& reload_completed" [(const_int 0)] @@ -146,7 +147,28 @@ } ) -(define_insn_and_split "atomic_exchange<mode>" +(define_expand "atomic_exchange<mode>" + [(match_operand:ALLI 0 "register_operand" "") + (match_operand:ALLI 1 "aarch64_sync_memory_operand" "") + (match_operand:ALLI 2 "register_operand" "") + (match_operand:SI 3 "const_int_operand" "")] + "" + { + rtx (*gen) (rtx, rtx, rtx, rtx); + + /* Use an atomic SWP when available. */ + if (TARGET_LSE) + gen = gen_aarch64_atomic_exchange<mode>_lse; + else + gen = gen_aarch64_atomic_exchange<mode>; + + emit_insn (gen (operands[0], operands[1], operands[2], operands[3])); + + DONE; + } +) + +(define_insn_and_split "aarch64_atomic_exchange<mode>" [(set (match_operand:ALLI 0 "register_operand" "=&r") ;; output (match_operand:ALLI 1 "aarch64_sync_memory_operand" "+Q")) ;; memory (set (match_dup 1) @@ -162,7 +184,26 @@ [(const_int 0)] { aarch64_split_atomic_op (SET, operands[0], NULL, operands[1], - operands[2], operands[3], operands[4]); + operands[2], operands[3], operands[4]); + DONE; + } +) + +(define_insn_and_split "aarch64_atomic_exchange<mode>_lse" + [(set (match_operand:ALLI 0 "register_operand" "=&r") + (match_operand:ALLI 1 "aarch64_sync_memory_operand" "+Q")) + (set (match_dup 1) + (unspec_volatile:ALLI + [(match_operand:ALLI 2 "register_operand" "r") + (match_operand:SI 3 "const_int_operand" "")] + UNSPECV_ATOMIC_EXCHG))] + "TARGET_LSE" + "#" + "&& reload_completed" + [(const_int 0)] + { + aarch64_gen_atomic_ldop (SET, operands[0], operands[1], + operands[2], operands[3]); DONE; } ) @@ -183,7 +224,7 @@ [(const_int 0)] { aarch64_split_atomic_op (<CODE>, NULL, operands[3], operands[0], - operands[1], operands[2], operands[4]); + operands[1], operands[2], operands[4]); DONE; } ) @@ -425,6 +466,28 @@ ;; ARMv8.1 LSE instructions. +;; Atomic swap with memory. +(define_insn "aarch64_atomic_swp<mode>" + [(set (match_operand:ALLI 0 "register_operand" "+&r") + (match_operand:ALLI 1 "aarch64_sync_memory_operand" "+Q")) + (set (match_dup 1) + (unspec_volatile:ALLI + [(match_operand:ALLI 2 "register_operand" "r") + (match_operand:SI 3 "const_int_operand" "")] + UNSPECV_ATOMIC_SWP))] + "TARGET_LSE && reload_completed" + { + enum memmodel model = memmodel_from_int (INTVAL (operands[3])); + if (is_mm_relaxed (model)) + return "swp<atomic_sfx>\t%<w>2, %<w>0, %1"; + else if (is_mm_acquire (model) || is_mm_consume (model)) + return "swpa<atomic_sfx>\t%<w>2, %<w>0, %1"; + else if (is_mm_release (model)) + return "swpl<atomic_sfx>\t%<w>2, %<w>0, %1"; + else + return "swpal<atomic_sfx>\t%<w>2, %<w>0, %1"; + }) + ;; Atomic compare-and-swap: HI and smaller modes. (define_insn "aarch64_atomic_cas<mode>" |