aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/aarch64/atomics.md
diff options
context:
space:
mode:
authorMatthew Wahab <matthew.wahab@arm.com>2015-09-22 09:19:55 +0000
committerMatthew Wahab <mwahab@gcc.gnu.org>2015-09-22 09:19:55 +0000
commit9cd7b72071d5b1101de6b726391e8ba71a61638f (patch)
tree86873c021fe60c2fffb4d16ae53a756647797d52 /gcc/config/aarch64/atomics.md
parent9915b1c916b1e6aa0fb7aa738dcc217f5f69b8ef (diff)
downloadgcc-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.md71
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>"