diff options
author | Matthew Wahab <matthew.wahab@arm.com> | 2015-08-13 11:28:42 +0000 |
---|---|---|
committer | Matthew Wahab <mwahab@gcc.gnu.org> | 2015-08-13 11:28:42 +0000 |
commit | b0770c0f18133105bddbc841f435a7cb5ccf9747 (patch) | |
tree | 3bc09bb15618e9177907e536179a7f1bbec4a466 /gcc/config/aarch64/atomics.md | |
parent | 045c2d32d9f8c0338cfffb0152088447acaced5e (diff) | |
download | gcc-b0770c0f18133105bddbc841f435a7cb5ccf9747.zip gcc-b0770c0f18133105bddbc841f435a7cb5ccf9747.tar.gz gcc-b0770c0f18133105bddbc841f435a7cb5ccf9747.tar.bz2 |
* config/aarch64/aarch64-protos.h
(aarch64_gen_atomic_cas): Declare.
* config/aarch64/aarch64.c (aarch64_expand_compare_and_swap):
Choose appropriate instruction pattern for the target.
(aarch64_gen_atomic_cas): New.
* config/aarch64/atomics.md (UNSPECV_ATOMIC_CAS): New.
(atomic_compare_and_swap<mode>_1): Rename to
aarch64_compare_and_swap<mode>. Fix some indentation.
(aarch64_compare_and_swap<mode>_lse): New.
(aarch64_atomic_cas<mode>): New.
From-SVN: r226858
Diffstat (limited to 'gcc/config/aarch64/atomics.md')
-rw-r--r-- | gcc/config/aarch64/atomics.md | 117 |
1 files changed, 110 insertions, 7 deletions
diff --git a/gcc/config/aarch64/atomics.md b/gcc/config/aarch64/atomics.md index 1a38ac0..7082f61 100644 --- a/gcc/config/aarch64/atomics.md +++ b/gcc/config/aarch64/atomics.md @@ -26,6 +26,7 @@ UNSPECV_STL ; Represent an atomic store or store-release. UNSPECV_ATOMIC_CMPSW ; Represent an atomic compare swap. UNSPECV_ATOMIC_EXCHG ; Represent an atomic exchange. + UNSPECV_ATOMIC_CAS ; Represent an atomic CAS. UNSPECV_ATOMIC_OP ; Represent an atomic operation. ]) @@ -45,10 +46,10 @@ } ) -(define_insn_and_split "atomic_compare_and_swap<mode>_1" +(define_insn_and_split "aarch64_compare_and_swap<mode>" [(set (reg:CC CC_REGNUM) ;; bool out (unspec_volatile:CC [(const_int 0)] UNSPECV_ATOMIC_CMPSW)) - (set (match_operand:SI 0 "register_operand" "=&r") ;; val out + (set (match_operand:SI 0 "register_operand" "=&r") ;; val out (zero_extend:SI (match_operand:SHORT 1 "aarch64_sync_memory_operand" "+Q"))) ;; memory (set (match_dup 1) @@ -57,7 +58,7 @@ (match_operand:SHORT 3 "register_operand" "r") ;; desired (match_operand:SI 4 "const_int_operand") ;; is_weak (match_operand:SI 5 "const_int_operand") ;; mod_s - (match_operand:SI 6 "const_int_operand")] ;; mod_f + (match_operand:SI 6 "const_int_operand")] ;; mod_f UNSPECV_ATOMIC_CMPSW)) (clobber (match_scratch:SI 7 "=&r"))] "" @@ -70,17 +71,17 @@ } ) -(define_insn_and_split "atomic_compare_and_swap<mode>_1" +(define_insn_and_split "aarch64_compare_and_swap<mode>" [(set (reg:CC CC_REGNUM) ;; bool out (unspec_volatile:CC [(const_int 0)] UNSPECV_ATOMIC_CMPSW)) (set (match_operand:GPI 0 "register_operand" "=&r") ;; val out - (match_operand:GPI 1 "aarch64_sync_memory_operand" "+Q")) ;; memory + (match_operand:GPI 1 "aarch64_sync_memory_operand" "+Q")) ;; memory (set (match_dup 1) (unspec_volatile:GPI [(match_operand:GPI 2 "aarch64_plus_operand" "rI") ;; expect (match_operand:GPI 3 "register_operand" "r") ;; desired - (match_operand:SI 4 "const_int_operand") ;; is_weak - (match_operand:SI 5 "const_int_operand") ;; mod_s + (match_operand:SI 4 "const_int_operand") ;; is_weak + (match_operand:SI 5 "const_int_operand") ;; mod_s (match_operand:SI 6 "const_int_operand")] ;; mod_f UNSPECV_ATOMIC_CMPSW)) (clobber (match_scratch:SI 7 "=&r"))] @@ -94,6 +95,57 @@ } ) +(define_insn_and_split "aarch64_compare_and_swap<mode>_lse" + [(set (reg:CC CC_REGNUM) ;; bool out + (unspec_volatile:CC [(const_int 0)] UNSPECV_ATOMIC_CMPSW)) + (set (match_operand:SI 0 "register_operand" "=&r") ;; val out + (zero_extend:SI + (match_operand:SHORT 1 "aarch64_sync_memory_operand" "+Q"))) ;; memory + (set (match_dup 1) + (unspec_volatile:SHORT + [(match_operand:SI 2 "aarch64_plus_operand" "rI") ;; expected + (match_operand:SHORT 3 "register_operand" "r") ;; desired + (match_operand:SI 4 "const_int_operand") ;; is_weak + (match_operand:SI 5 "const_int_operand") ;; mod_s + (match_operand:SI 6 "const_int_operand")] ;; mod_f + UNSPECV_ATOMIC_CMPSW))] + "TARGET_LSE" + "#" + "&& reload_completed" + [(const_int 0)] + { + aarch64_gen_atomic_cas (operands[0], operands[1], + operands[2], operands[3], + operands[5]); + DONE; + } +) + +(define_insn_and_split "aarch64_compare_and_swap<mode>_lse" + [(set (reg:CC CC_REGNUM) ;; bool out + (unspec_volatile:CC [(const_int 0)] UNSPECV_ATOMIC_CMPSW)) + (set (match_operand:GPI 0 "register_operand" "=&r") ;; val out + (match_operand:GPI 1 "aarch64_sync_memory_operand" "+Q")) ;; memory + (set (match_dup 1) + (unspec_volatile:GPI + [(match_operand:GPI 2 "aarch64_plus_operand" "rI") ;; expect + (match_operand:GPI 3 "register_operand" "r") ;; desired + (match_operand:SI 4 "const_int_operand") ;; is_weak + (match_operand:SI 5 "const_int_operand") ;; mod_s + (match_operand:SI 6 "const_int_operand")] ;; mod_f + UNSPECV_ATOMIC_CMPSW))] + "TARGET_LSE " + "#" + "&& reload_completed" + [(const_int 0)] + { + aarch64_gen_atomic_cas (operands[0], operands[1], + operands[2], operands[3], + operands[5]); + DONE; + } +) + (define_insn_and_split "atomic_exchange<mode>" [(set (match_operand:ALLI 0 "register_operand" "=&r") ;; output (match_operand:ALLI 1 "aarch64_sync_memory_operand" "+Q")) ;; memory @@ -370,3 +422,54 @@ return "dmb\\tish"; } ) + +;; ARMv8.1 LSE instructions. + +;; Atomic compare-and-swap: HI and smaller modes. + +(define_insn "aarch64_atomic_cas<mode>" + [(set (match_operand:SI 0 "register_operand" "+&r") ;; out + (zero_extend:SI + (match_operand:SHORT 1 "aarch64_sync_memory_operand" "+Q"))) ;; memory. + (set (match_dup 1) + (unspec_volatile:SHORT + [(match_dup 0) + (match_operand:SHORT 2 "register_operand" "r") ;; value. + (match_operand:SI 3 "const_int_operand" "")] ;; model. + UNSPECV_ATOMIC_CAS))] + "TARGET_LSE && reload_completed" +{ + enum memmodel model = memmodel_from_int (INTVAL (operands[3])); + if (is_mm_relaxed (model)) + return "cas<atomic_sfx>\t%<w>0, %<w>2, %1"; + else if (is_mm_acquire (model) || is_mm_consume (model)) + return "casa<atomic_sfx>\t%<w>0, %<w>2, %1"; + else if (is_mm_release (model)) + return "casl<atomic_sfx>\t%<w>0, %<w>2, %1"; + else + return "casal<atomic_sfx>\t%<w>0, %<w>2, %1"; +}) + +;; Atomic compare-and-swap: SI and larger modes. + +(define_insn "aarch64_atomic_cas<mode>" + [(set (match_operand:GPI 0 "register_operand" "+&r") ;; out + (match_operand:GPI 1 "aarch64_sync_memory_operand" "+Q")) ;; memory. + (set (match_dup 1) + (unspec_volatile:GPI + [(match_dup 0) + (match_operand:GPI 2 "register_operand" "r") ;; value. + (match_operand:SI 3 "const_int_operand" "")] ;; model. + UNSPECV_ATOMIC_CAS))] + "TARGET_LSE && reload_completed" +{ + enum memmodel model = memmodel_from_int (INTVAL (operands[3])); + if (is_mm_relaxed (model)) + return "cas<atomic_sfx>\t%<w>0, %<w>2, %1"; + else if (is_mm_acquire (model) || is_mm_consume (model)) + return "casa<atomic_sfx>\t%<w>0, %<w>2, %1"; + else if (is_mm_release (model)) + return "casl<atomic_sfx>\t%<w>0, %<w>2, %1"; + else + return "casal<atomic_sfx>\t%<w>0, %<w>2, %1"; +}) |