aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/aarch64/atomics.md
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2018-10-31 09:58:48 +0000
committerRichard Henderson <rth@gcc.gnu.org>2018-10-31 02:58:48 -0700
commit7803ec5ee2a547043fb6708a08ddb1361ba91202 (patch)
treedcf5f28df3603081cc04cbce0864e469f2e8d39c /gcc/config/aarch64/atomics.md
parent8f5603d363a4e0453d2c38c7103aeb0bdca85c4e (diff)
downloadgcc-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.md197
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";
- })