diff options
author | Richard Henderson <richard.henderson@linaro.org> | 2018-10-31 09:58:48 +0000 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 2018-10-31 02:58:48 -0700 |
commit | 7803ec5ee2a547043fb6708a08ddb1361ba91202 (patch) | |
tree | dcf5f28df3603081cc04cbce0864e469f2e8d39c /gcc/config/aarch64/atomics.md | |
parent | 8f5603d363a4e0453d2c38c7103aeb0bdca85c4e (diff) | |
download | gcc-7803ec5ee2a547043fb6708a08ddb1361ba91202.zip gcc-7803ec5ee2a547043fb6708a08ddb1361ba91202.tar.gz gcc-7803ec5ee2a547043fb6708a08ddb1361ba91202.tar.bz2 |
aarch64: Improve atomic-op lse generation
Fix constraints; avoid unnecessary split. Drop the use of the atomic_op
iterator in favor of the ATOMIC_LDOP iterator; this is simplier and more
logical for ldclr aka bic.
* config/aarch64/aarch64.c (aarch64_emit_bic): Remove.
(aarch64_atomic_ldop_supported_p): Remove.
(aarch64_gen_atomic_ldop): Remove.
* config/aarch64/atomic.md (atomic_<atomic_optab><ALLI>):
Fully expand LSE operations here.
(atomic_fetch_<atomic_optab><ALLI>): Likewise.
(atomic_<atomic_optab>_fetch<ALLI>): Likewise.
(aarch64_atomic_<ATOMIC_LDOP><ALLI>_lse): Drop atomic_op iterator
and use ATOMIC_LDOP instead; use register_operand for the input;
drop the split and emit insns directly.
(aarch64_atomic_fetch_<ATOMIC_LDOP><ALLI>_lse): Likewise.
(aarch64_atomic_<atomic_op>_fetch<ALLI>_lse): Remove.
(@aarch64_atomic_load<ATOMIC_LDOP><ALLI>): Remove.
From-SVN: r265660
Diffstat (limited to 'gcc/config/aarch64/atomics.md')
-rw-r--r-- | gcc/config/aarch64/atomics.md | 197 |
1 files changed, 104 insertions, 93 deletions
diff --git a/gcc/config/aarch64/atomics.md b/gcc/config/aarch64/atomics.md index bc9e396..2198649 100644 --- a/gcc/config/aarch64/atomics.md +++ b/gcc/config/aarch64/atomics.md @@ -207,13 +207,37 @@ rtx (*gen) (rtx, rtx, rtx); /* Use an atomic load-operate instruction when possible. */ - if (aarch64_atomic_ldop_supported_p (<CODE>)) - gen = gen_aarch64_atomic_<atomic_optab><mode>_lse; + if (TARGET_LSE) + { + switch (<CODE>) + { + case MINUS: + operands[1] = expand_simple_unop (<MODE>mode, NEG, operands[1], + NULL, 1); + /* fallthru */ + case PLUS: + gen = gen_aarch64_atomic_add<mode>_lse; + break; + case IOR: + gen = gen_aarch64_atomic_ior<mode>_lse; + break; + case XOR: + gen = gen_aarch64_atomic_xor<mode>_lse; + break; + case AND: + operands[1] = expand_simple_unop (<MODE>mode, NOT, operands[1], + NULL, 1); + gen = gen_aarch64_atomic_bic<mode>_lse; + break; + default: + gcc_unreachable (); + } + operands[1] = force_reg (<MODE>mode, operands[1]); + } else gen = gen_aarch64_atomic_<atomic_optab><mode>; emit_insn (gen (operands[0], operands[1], operands[2])); - DONE; } ) @@ -239,22 +263,25 @@ } ) -(define_insn_and_split "aarch64_atomic_<atomic_optab><mode>_lse" +(define_insn "aarch64_atomic_<atomic_ldoptab><mode>_lse" [(set (match_operand:ALLI 0 "aarch64_sync_memory_operand" "+Q") - (unspec_volatile:ALLI - [(atomic_op:ALLI (match_dup 0) - (match_operand:ALLI 1 "<atomic_op_operand>" "r<const_atomic>")) - (match_operand:SI 2 "const_int_operand")] - UNSPECV_ATOMIC_OP)) + (unspec_volatile:ALLI + [(match_dup 0) + (match_operand:ALLI 1 "register_operand" "r") + (match_operand:SI 2 "const_int_operand")] + ATOMIC_LDOP)) (clobber (match_scratch:ALLI 3 "=&r"))] "TARGET_LSE" - "#" - "&& reload_completed" - [(const_int 0)] { - aarch64_gen_atomic_ldop (<CODE>, operands[3], NULL, operands[0], - operands[1], operands[2]); - DONE; + enum memmodel model = memmodel_from_int (INTVAL (operands[2])); + if (is_mm_relaxed (model)) + return "ld<atomic_ldop><atomic_sfx>\t%<w>1, %<w>3, %0"; + else if (is_mm_release (model)) + return "ld<atomic_ldop>l<atomic_sfx>\t%<w>1, %<w>3, %0"; + else if (is_mm_acquire (model) || is_mm_consume (model)) + return "ld<atomic_ldop>a<atomic_sfx>\t%<w>1, %<w>3, %0"; + else + return "ld<atomic_ldop>al<atomic_sfx>\t%<w>1, %<w>3, %0"; } ) @@ -280,7 +307,7 @@ } ) -;; Load-operate-store, returning the updated memory data. +;; Load-operate-store, returning the original memory data. (define_expand "atomic_fetch_<atomic_optab><mode>" [(match_operand:ALLI 0 "register_operand" "") @@ -293,13 +320,37 @@ rtx (*gen) (rtx, rtx, rtx, rtx); /* Use an atomic load-operate instruction when possible. */ - if (aarch64_atomic_ldop_supported_p (<CODE>)) - gen = gen_aarch64_atomic_fetch_<atomic_optab><mode>_lse; + if (TARGET_LSE) + { + switch (<CODE>) + { + case MINUS: + operands[2] = expand_simple_unop (<MODE>mode, NEG, operands[2], + NULL, 1); + /* fallthru */ + case PLUS: + gen = gen_aarch64_atomic_fetch_add<mode>_lse; + break; + case IOR: + gen = gen_aarch64_atomic_fetch_ior<mode>_lse; + break; + case XOR: + gen = gen_aarch64_atomic_fetch_xor<mode>_lse; + break; + case AND: + operands[2] = expand_simple_unop (<MODE>mode, NOT, operands[2], + NULL, 1); + gen = gen_aarch64_atomic_fetch_bic<mode>_lse; + break; + default: + gcc_unreachable (); + } + operands[2] = force_reg (<MODE>mode, operands[2]); + } else gen = gen_aarch64_atomic_fetch_<atomic_optab><mode>; emit_insn (gen (operands[0], operands[1], operands[2], operands[3])); - DONE; }) @@ -326,23 +377,26 @@ } ) -(define_insn_and_split "aarch64_atomic_fetch_<atomic_optab><mode>_lse" - [(set (match_operand:ALLI 0 "register_operand" "=&r") - (match_operand:ALLI 1 "aarch64_sync_memory_operand" "+Q")) +(define_insn "aarch64_atomic_fetch_<atomic_ldoptab><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 - [(atomic_op:ALLI (match_dup 1) - (match_operand:ALLI 2 "<atomic_op_operand>" "r<const_atomic>")) - (match_operand:SI 3 "const_int_operand")] - UNSPECV_ATOMIC_LDOP))] + (unspec_volatile:ALLI + [(match_dup 1) + (match_operand:ALLI 2 "register_operand" "r") + (match_operand:SI 3 "const_int_operand")] + ATOMIC_LDOP))] "TARGET_LSE" - "#" - "&& reload_completed" - [(const_int 0)] { - aarch64_gen_atomic_ldop (<CODE>, operands[0], NULL, operands[1], - operands[2], operands[3]); - DONE; + enum memmodel model = memmodel_from_int (INTVAL (operands[3])); + if (is_mm_relaxed (model)) + return "ld<atomic_ldop><atomic_sfx>\t%<w>2, %<w>0, %1"; + else if (is_mm_acquire (model) || is_mm_consume (model)) + return "ld<atomic_ldop>a<atomic_sfx>\t%<w>2, %<w>0, %1"; + else if (is_mm_release (model)) + return "ld<atomic_ldop>l<atomic_sfx>\t%<w>2, %<w>0, %1"; + else + return "ld<atomic_ldop>al<atomic_sfx>\t%<w>2, %<w>0, %1"; } ) @@ -370,7 +424,7 @@ } ) -;; Load-operate-store, returning the original memory data. +;; Load-operate-store, returning the updated memory data. (define_expand "atomic_<atomic_optab>_fetch<mode>" [(match_operand:ALLI 0 "register_operand" "") @@ -380,17 +434,23 @@ (match_operand:SI 3 "const_int_operand")] "" { - rtx (*gen) (rtx, rtx, rtx, rtx); - rtx value = operands[2]; - - /* Use an atomic load-operate instruction when possible. */ - if (aarch64_atomic_ldop_supported_p (<CODE>)) - gen = gen_aarch64_atomic_<atomic_optab>_fetch<mode>_lse; + /* Use an atomic load-operate instruction when possible. In this case + we will re-compute the result from the original mem value. */ + if (TARGET_LSE) + { + rtx tmp = gen_reg_rtx (<MODE>mode); + operands[2] = force_reg (<MODE>mode, operands[2]); + emit_insn (gen_atomic_fetch_<atomic_optab><mode> + (tmp, operands[1], operands[2], operands[3])); + tmp = expand_simple_binop (<MODE>mode, <CODE>, tmp, operands[2], + operands[0], 1, OPTAB_WIDEN); + emit_move_insn (operands[0], tmp); + } else - gen = gen_aarch64_atomic_<atomic_optab>_fetch<mode>; - - emit_insn (gen (operands[0], operands[1], value, operands[3])); - + { + emit_insn (gen_aarch64_atomic_<atomic_optab>_fetch<mode> + (operands[0], operands[1], operands[2], operands[3])); + } DONE; }) @@ -417,29 +477,6 @@ } ) -(define_insn_and_split "aarch64_atomic_<atomic_optab>_fetch<mode>_lse" - [(set (match_operand:ALLI 0 "register_operand" "=&r") - (atomic_op:ALLI - (match_operand:ALLI 1 "aarch64_sync_memory_operand" "+Q") - (match_operand:ALLI 2 "<atomic_op_operand>" "r<const_atomic>"))) - (set (match_dup 1) - (unspec_volatile:ALLI - [(match_dup 1) - (match_dup 2) - (match_operand:SI 3 "const_int_operand")] - UNSPECV_ATOMIC_LDOP)) - (clobber (match_scratch:ALLI 4 "=&r"))] - "TARGET_LSE" - "#" - "&& reload_completed" - [(const_int 0)] - { - aarch64_gen_atomic_ldop (<CODE>, operands[4], operands[0], operands[1], - operands[2], operands[3]); - DONE; - } -) - (define_insn_and_split "atomic_nand_fetch<mode>" [(set (match_operand:ALLI 0 "register_operand" "=&r") (not:ALLI @@ -585,29 +622,3 @@ return "dmb\\tish"; } ) - -;; ARMv8.1-A LSE instructions. - -;; Atomic load-op: Load data, operate, store result, keep data. - -(define_insn "@aarch64_atomic_load<atomic_ldop><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_dup 1) - (match_operand:ALLI 2 "register_operand") - (match_operand:SI 3 "const_int_operand")] - ATOMIC_LDOP))] - "TARGET_LSE && reload_completed" - { - enum memmodel model = memmodel_from_int (INTVAL (operands[3])); - if (is_mm_relaxed (model)) - return "ld<atomic_ldop><atomic_sfx>\t%<w>2, %<w>0, %1"; - else if (is_mm_acquire (model) || is_mm_consume (model)) - return "ld<atomic_ldop>a<atomic_sfx>\t%<w>2, %<w>0, %1"; - else if (is_mm_release (model)) - return "ld<atomic_ldop>l<atomic_sfx>\t%<w>2, %<w>0, %1"; - else - return "ld<atomic_ldop>al<atomic_sfx>\t%<w>2, %<w>0, %1"; - }) |