Message ID | 20190918015817.24408-6-richard.henderson@linaro.org |
---|---|
State | New |
Headers | show |
Series | LSE atomics out-of-line | expand |
On 9/18/19 2:58 AM, Richard Henderson wrote: > * config/aarch64/aarch64.opt (-moutline-atomics): New. > * config/aarch64/aarch64.c (aarch64_atomic_ool_func): New. > (aarch64_ool_cas_names, aarch64_ool_swp_names): New. > (aarch64_ool_ldadd_names, aarch64_ool_ldset_names): New. > (aarch64_ool_ldclr_names, aarch64_ool_ldeor_names): New. > (aarch64_expand_compare_and_swap): Honor TARGET_OUTLINE_ATOMICS. > * config/aarch64/atomics.md (atomic_exchange<ALLI>): Likewise. > (atomic_<atomic_op><ALLI>): Likewise. > (atomic_fetch_<atomic_op><ALLI>): Likewise. > (atomic_<atomic_op>_fetch<ALLI>): Likewise. > testsuite/ > * gcc.target/aarch64/atomic-op-acq_rel.c: Use -mno-outline-atomics. > * gcc.target/aarch64/atomic-comp-swap-release-acquire.c: Likewise. > * gcc.target/aarch64/atomic-op-acquire.c: Likewise. > * gcc.target/aarch64/atomic-op-char.c: Likewise. > * gcc.target/aarch64/atomic-op-consume.c: Likewise. > * gcc.target/aarch64/atomic-op-imm.c: Likewise. > * gcc.target/aarch64/atomic-op-int.c: Likewise. > * gcc.target/aarch64/atomic-op-long.c: Likewise. > * gcc.target/aarch64/atomic-op-relaxed.c: Likewise. > * gcc.target/aarch64/atomic-op-release.c: Likewise. > * gcc.target/aarch64/atomic-op-seq_cst.c: Likewise. > * gcc.target/aarch64/atomic-op-short.c: Likewise. > * gcc.target/aarch64/atomic_cmp_exchange_zero_reg_1.c: Likewise. > * gcc.target/aarch64/atomic_cmp_exchange_zero_strong_1.c: Likewise. > * gcc.target/aarch64/sync-comp-swap.c: Likewise. > * gcc.target/aarch64/sync-op-acquire.c: Likewise. > * gcc.target/aarch64/sync-op-full.c: Likewise. > --- > gcc/config/aarch64/aarch64-protos.h | 13 +++ > gcc/config/aarch64/aarch64.c | 87 +++++++++++++++++ > .../atomic-comp-swap-release-acquire.c | 2 +- > .../gcc.target/aarch64/atomic-op-acq_rel.c | 2 +- > .../gcc.target/aarch64/atomic-op-acquire.c | 2 +- > .../gcc.target/aarch64/atomic-op-char.c | 2 +- > .../gcc.target/aarch64/atomic-op-consume.c | 2 +- > .../gcc.target/aarch64/atomic-op-imm.c | 2 +- > .../gcc.target/aarch64/atomic-op-int.c | 2 +- > .../gcc.target/aarch64/atomic-op-long.c | 2 +- > .../gcc.target/aarch64/atomic-op-relaxed.c | 2 +- > .../gcc.target/aarch64/atomic-op-release.c | 2 +- > .../gcc.target/aarch64/atomic-op-seq_cst.c | 2 +- > .../gcc.target/aarch64/atomic-op-short.c | 2 +- > .../aarch64/atomic_cmp_exchange_zero_reg_1.c | 2 +- > .../atomic_cmp_exchange_zero_strong_1.c | 2 +- > .../gcc.target/aarch64/sync-comp-swap.c | 2 +- > .../gcc.target/aarch64/sync-op-acquire.c | 2 +- > .../gcc.target/aarch64/sync-op-full.c | 2 +- > gcc/config/aarch64/aarch64.opt | 3 + > gcc/config/aarch64/atomics.md | 94 +++++++++++++++++-- > gcc/doc/invoke.texi | 16 +++- > 22 files changed, 221 insertions(+), 26 deletions(-) > > diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h > index c4b73d26df6..1c1aac7201a 100644 > --- a/gcc/config/aarch64/aarch64-protos.h > +++ b/gcc/config/aarch64/aarch64-protos.h > @@ -696,4 +696,17 @@ poly_uint64 aarch64_regmode_natural_size (machine_mode); > > bool aarch64_high_bits_all_ones_p (HOST_WIDE_INT); > > +struct atomic_ool_names > +{ > + const char *str[5][4]; > +}; > + > +rtx aarch64_atomic_ool_func(machine_mode mode, rtx model_rtx, > + const atomic_ool_names *names); > +extern const atomic_ool_names aarch64_ool_swp_names; > +extern const atomic_ool_names aarch64_ool_ldadd_names; > +extern const atomic_ool_names aarch64_ool_ldset_names; > +extern const atomic_ool_names aarch64_ool_ldclr_names; > +extern const atomic_ool_names aarch64_ool_ldeor_names; > + > #endif /* GCC_AARCH64_PROTOS_H */ > diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c > index b937514e6f8..56a4a47db73 100644 > --- a/gcc/config/aarch64/aarch64.c > +++ b/gcc/config/aarch64/aarch64.c > @@ -16867,6 +16867,82 @@ aarch64_emit_unlikely_jump (rtx insn) > add_reg_br_prob_note (jump, profile_probability::very_unlikely ()); > } > > +/* We store the names of the various atomic helpers in a 5x4 array. > + Return the libcall function given MODE, MODEL and NAMES. */ > + > +rtx > +aarch64_atomic_ool_func(machine_mode mode, rtx model_rtx, > + const atomic_ool_names *names) > +{ > + memmodel model = memmodel_base (INTVAL (model_rtx)); > + int mode_idx, model_idx; > + > + switch (mode) > + { > + case E_QImode: > + mode_idx = 0; > + break; > + case E_HImode: > + mode_idx = 1; > + break; > + case E_SImode: > + mode_idx = 2; > + break; > + case E_DImode: > + mode_idx = 3; > + break; > + case E_TImode: > + mode_idx = 4; > + break; > + default: > + gcc_unreachable (); > + } > + > + switch (model) > + { > + case MEMMODEL_RELAXED: > + model_idx = 0; > + break; > + case MEMMODEL_CONSUME: > + case MEMMODEL_ACQUIRE: > + model_idx = 1; > + break; > + case MEMMODEL_RELEASE: > + model_idx = 2; > + break; > + case MEMMODEL_ACQ_REL: > + case MEMMODEL_SEQ_CST: > + model_idx = 3; > + break; > + default: > + gcc_unreachable (); > + } > + > + return init_one_libfunc_visibility (names->str[mode_idx][model_idx], > + VISIBILITY_HIDDEN); > +} > + > +#define DEF0(B, N) \ > + { "__aarch64_" #B #N "_relax", \ > + "__aarch64_" #B #N "_acq", \ > + "__aarch64_" #B #N "_rel", \ > + "__aarch64_" #B #N "_acq_rel" } > + > +#define DEF4(B) DEF0(B, 1), DEF0(B, 2), DEF0(B, 4), DEF0(B, 8), \ > + { NULL, NULL, NULL, NULL } > +#define DEF5(B) DEF0(B, 1), DEF0(B, 2), DEF0(B, 4), DEF0(B, 8), DEF0(B, 16) > + > +static const atomic_ool_names aarch64_ool_cas_names = { { DEF5(cas) } }; > +const atomic_ool_names aarch64_ool_swp_names = { { DEF4(swp) } }; > +const atomic_ool_names aarch64_ool_ldadd_names = { { DEF4(ldadd) } }; > +const atomic_ool_names aarch64_ool_ldset_names = { { DEF4(ldset) } }; > +const atomic_ool_names aarch64_ool_ldclr_names = { { DEF4(ldclr) } }; > +const atomic_ool_names aarch64_ool_ldeor_names = { { DEF4(ldeor) } }; > + > +#undef DEF0 > +#undef DEF4 > +#undef DEF5 > + > /* Expand a compare and swap pattern. */ > > void > @@ -16913,6 +16989,17 @@ aarch64_expand_compare_and_swap (rtx operands[]) > newval, mod_s)); > cc_reg = aarch64_gen_compare_reg_maybe_ze (NE, rval, oldval, mode); > } > + else if (TARGET_OUTLINE_ATOMICS) > + { > + /* Oldval must satisfy compare afterward. */ > + if (!aarch64_plus_operand (oldval, mode)) > + oldval = force_reg (mode, oldval); > + rtx func = aarch64_atomic_ool_func (mode, mod_s, &aarch64_ool_cas_names); > + rval = emit_library_call_value (func, NULL_RTX, LCT_NORMAL, r_mode, > + oldval, mode, newval, mode, > + XEXP (mem, 0), Pmode); > + cc_reg = aarch64_gen_compare_reg_maybe_ze (NE, rval, oldval, mode); > + } > else > { > /* The oldval predicate varies by mode. Test it and force to reg. */ > diff --git a/gcc/testsuite/gcc.target/aarch64/atomic-comp-swap-release-acquire.c b/gcc/testsuite/gcc.target/aarch64/atomic-comp-swap-release-acquire.c > index 49ca5d0d09c..a828a72aa75 100644 > --- a/gcc/testsuite/gcc.target/aarch64/atomic-comp-swap-release-acquire.c > +++ b/gcc/testsuite/gcc.target/aarch64/atomic-comp-swap-release-acquire.c > @@ -1,5 +1,5 @@ > /* { dg-do compile } */ > -/* { dg-options "-march=armv8-a+nolse -O2 -fno-ipa-icf" } */ > +/* { dg-options "-march=armv8-a+nolse -O2 -fno-ipa-icf -mno-outline-atomics" } */ > > #include "atomic-comp-swap-release-acquire.x" > > diff --git a/gcc/testsuite/gcc.target/aarch64/atomic-op-acq_rel.c b/gcc/testsuite/gcc.target/aarch64/atomic-op-acq_rel.c > index 74f26348e42..6823ce381b2 100644 > --- a/gcc/testsuite/gcc.target/aarch64/atomic-op-acq_rel.c > +++ b/gcc/testsuite/gcc.target/aarch64/atomic-op-acq_rel.c > @@ -1,5 +1,5 @@ > /* { dg-do compile } */ > -/* { dg-options "-march=armv8-a+nolse -O2" } */ > +/* { dg-options "-march=armv8-a+nolse -O2 -mno-outline-atomics" } */ > > #include "atomic-op-acq_rel.x" > > diff --git a/gcc/testsuite/gcc.target/aarch64/atomic-op-acquire.c b/gcc/testsuite/gcc.target/aarch64/atomic-op-acquire.c > index 66c1b1efe20..87937de378a 100644 > --- a/gcc/testsuite/gcc.target/aarch64/atomic-op-acquire.c > +++ b/gcc/testsuite/gcc.target/aarch64/atomic-op-acquire.c > @@ -1,5 +1,5 @@ > /* { dg-do compile } */ > -/* { dg-options "-march=armv8-a+nolse -O2" } */ > +/* { dg-options "-march=armv8-a+nolse -O2 -mno-outline-atomics" } */ > > #include "atomic-op-acquire.x" > > diff --git a/gcc/testsuite/gcc.target/aarch64/atomic-op-char.c b/gcc/testsuite/gcc.target/aarch64/atomic-op-char.c > index c09d0434ecf..60955e57da3 100644 > --- a/gcc/testsuite/gcc.target/aarch64/atomic-op-char.c > +++ b/gcc/testsuite/gcc.target/aarch64/atomic-op-char.c > @@ -1,5 +1,5 @@ > /* { dg-do compile } */ > -/* { dg-options "-march=armv8-a+nolse -O2" } */ > +/* { dg-options "-march=armv8-a+nolse -O2 -mno-outline-atomics" } */ > > #include "atomic-op-char.x" > > diff --git a/gcc/testsuite/gcc.target/aarch64/atomic-op-consume.c b/gcc/testsuite/gcc.target/aarch64/atomic-op-consume.c > index 5783ab84f5c..16cb11aeeaf 100644 > --- a/gcc/testsuite/gcc.target/aarch64/atomic-op-consume.c > +++ b/gcc/testsuite/gcc.target/aarch64/atomic-op-consume.c > @@ -1,5 +1,5 @@ > /* { dg-do compile } */ > -/* { dg-options "-march=armv8-a+nolse -O2" } */ > +/* { dg-options "-march=armv8-a+nolse -O2 -mno-outline-atomics" } */ > > #include "atomic-op-consume.x" > > diff --git a/gcc/testsuite/gcc.target/aarch64/atomic-op-imm.c b/gcc/testsuite/gcc.target/aarch64/atomic-op-imm.c > index 18b8f0b04e9..bcab4e481e3 100644 > --- a/gcc/testsuite/gcc.target/aarch64/atomic-op-imm.c > +++ b/gcc/testsuite/gcc.target/aarch64/atomic-op-imm.c > @@ -1,5 +1,5 @@ > /* { dg-do compile } */ > -/* { dg-options "-march=armv8-a+nolse -O2" } */ > +/* { dg-options "-march=armv8-a+nolse -O2 -mno-outline-atomics" } */ > > int v = 0; > > diff --git a/gcc/testsuite/gcc.target/aarch64/atomic-op-int.c b/gcc/testsuite/gcc.target/aarch64/atomic-op-int.c > index 8520f0839ba..040e4a8d168 100644 > --- a/gcc/testsuite/gcc.target/aarch64/atomic-op-int.c > +++ b/gcc/testsuite/gcc.target/aarch64/atomic-op-int.c > @@ -1,5 +1,5 @@ > /* { dg-do compile } */ > -/* { dg-options "-march=armv8-a+nolse -O2" } */ > +/* { dg-options "-march=armv8-a+nolse -O2 -mno-outline-atomics" } */ > > #include "atomic-op-int.x" > > diff --git a/gcc/testsuite/gcc.target/aarch64/atomic-op-long.c b/gcc/testsuite/gcc.target/aarch64/atomic-op-long.c > index d011f8c5ce2..fc88b92cd3e 100644 > --- a/gcc/testsuite/gcc.target/aarch64/atomic-op-long.c > +++ b/gcc/testsuite/gcc.target/aarch64/atomic-op-long.c > @@ -1,5 +1,5 @@ > /* { dg-do compile } */ > -/* { dg-options "-march=armv8-a+nolse -O2" } */ > +/* { dg-options "-march=armv8-a+nolse -O2 -mno-outline-atomics" } */ > > long v = 0; > > diff --git a/gcc/testsuite/gcc.target/aarch64/atomic-op-relaxed.c b/gcc/testsuite/gcc.target/aarch64/atomic-op-relaxed.c > index ed96bfdb978..503d62b0280 100644 > --- a/gcc/testsuite/gcc.target/aarch64/atomic-op-relaxed.c > +++ b/gcc/testsuite/gcc.target/aarch64/atomic-op-relaxed.c > @@ -1,5 +1,5 @@ > /* { dg-do compile } */ > -/* { dg-options "-march=armv8-a+nolse -O2" } */ > +/* { dg-options "-march=armv8-a+nolse -O2 -mno-outline-atomics" } */ > > #include "atomic-op-relaxed.x" > > diff --git a/gcc/testsuite/gcc.target/aarch64/atomic-op-release.c b/gcc/testsuite/gcc.target/aarch64/atomic-op-release.c > index fc4be17de89..efe14aea7e4 100644 > --- a/gcc/testsuite/gcc.target/aarch64/atomic-op-release.c > +++ b/gcc/testsuite/gcc.target/aarch64/atomic-op-release.c > @@ -1,5 +1,5 @@ > /* { dg-do compile } */ > -/* { dg-options "-march=armv8-a+nolse -O2" } */ > +/* { dg-options "-march=armv8-a+nolse -O2 -mno-outline-atomics" } */ > > #include "atomic-op-release.x" > > diff --git a/gcc/testsuite/gcc.target/aarch64/atomic-op-seq_cst.c b/gcc/testsuite/gcc.target/aarch64/atomic-op-seq_cst.c > index 613000fe490..09973bf82ba 100644 > --- a/gcc/testsuite/gcc.target/aarch64/atomic-op-seq_cst.c > +++ b/gcc/testsuite/gcc.target/aarch64/atomic-op-seq_cst.c > @@ -1,5 +1,5 @@ > /* { dg-do compile } */ > -/* { dg-options "-march=armv8-a+nolse -O2" } */ > +/* { dg-options "-march=armv8-a+nolse -O2 -mno-outline-atomics" } */ > > #include "atomic-op-seq_cst.x" > > diff --git a/gcc/testsuite/gcc.target/aarch64/atomic-op-short.c b/gcc/testsuite/gcc.target/aarch64/atomic-op-short.c > index e82c8118ece..e1dcebb0f89 100644 > --- a/gcc/testsuite/gcc.target/aarch64/atomic-op-short.c > +++ b/gcc/testsuite/gcc.target/aarch64/atomic-op-short.c > @@ -1,5 +1,5 @@ > /* { dg-do compile } */ > -/* { dg-options "-march=armv8-a+nolse -O2" } */ > +/* { dg-options "-march=armv8-a+nolse -O2 -mno-outline-atomics" } */ > > #include "atomic-op-short.x" > > diff --git a/gcc/testsuite/gcc.target/aarch64/atomic_cmp_exchange_zero_reg_1.c b/gcc/testsuite/gcc.target/aarch64/atomic_cmp_exchange_zero_reg_1.c > index f2a21ddf2e1..29246979bfb 100644 > --- a/gcc/testsuite/gcc.target/aarch64/atomic_cmp_exchange_zero_reg_1.c > +++ b/gcc/testsuite/gcc.target/aarch64/atomic_cmp_exchange_zero_reg_1.c > @@ -1,5 +1,5 @@ > /* { dg-do compile } */ > -/* { dg-options "-O2 -march=armv8-a+nolse" } */ > +/* { dg-options "-O2 -march=armv8-a+nolse -mno-outline-atomics" } */ > /* { dg-skip-if "" { *-*-* } { "-mcpu=*" } { "" } } */ > > int > diff --git a/gcc/testsuite/gcc.target/aarch64/atomic_cmp_exchange_zero_strong_1.c b/gcc/testsuite/gcc.target/aarch64/atomic_cmp_exchange_zero_strong_1.c > index 8d2ae67dfbe..6daf9b08f5a 100644 > --- a/gcc/testsuite/gcc.target/aarch64/atomic_cmp_exchange_zero_strong_1.c > +++ b/gcc/testsuite/gcc.target/aarch64/atomic_cmp_exchange_zero_strong_1.c > @@ -1,5 +1,5 @@ > /* { dg-do compile } */ > -/* { dg-options "-O2 -march=armv8-a+nolse" } */ > +/* { dg-options "-O2 -march=armv8-a+nolse -mno-outline-atomics" } */ > /* { dg-skip-if "" { *-*-* } { "-mcpu=*" } { "" } } */ > > int > diff --git a/gcc/testsuite/gcc.target/aarch64/sync-comp-swap.c b/gcc/testsuite/gcc.target/aarch64/sync-comp-swap.c > index e571b2f13b3..f56415f3354 100644 > --- a/gcc/testsuite/gcc.target/aarch64/sync-comp-swap.c > +++ b/gcc/testsuite/gcc.target/aarch64/sync-comp-swap.c > @@ -1,5 +1,5 @@ > /* { dg-do compile } */ > -/* { dg-options "-march=armv8-a+nolse -O2 -fno-ipa-icf" } */ > +/* { dg-options "-march=armv8-a+nolse -O2 -fno-ipa-icf -mno-outline-atomics" } */ > > #include "sync-comp-swap.x" > > diff --git a/gcc/testsuite/gcc.target/aarch64/sync-op-acquire.c b/gcc/testsuite/gcc.target/aarch64/sync-op-acquire.c > index 357bf1be3b2..39b3144aa36 100644 > --- a/gcc/testsuite/gcc.target/aarch64/sync-op-acquire.c > +++ b/gcc/testsuite/gcc.target/aarch64/sync-op-acquire.c > @@ -1,5 +1,5 @@ > /* { dg-do compile } */ > -/* { dg-options "-march=armv8-a+nolse -O2" } */ > +/* { dg-options "-march=armv8-a+nolse -O2 -mno-outline-atomics" } */ > > #include "sync-op-acquire.x" > > diff --git a/gcc/testsuite/gcc.target/aarch64/sync-op-full.c b/gcc/testsuite/gcc.target/aarch64/sync-op-full.c > index c6ba1629965..6b8b2043f40 100644 > --- a/gcc/testsuite/gcc.target/aarch64/sync-op-full.c > +++ b/gcc/testsuite/gcc.target/aarch64/sync-op-full.c > @@ -1,5 +1,5 @@ > /* { dg-do compile } */ > -/* { dg-options "-march=armv8-a+nolse -O2" } */ > +/* { dg-options "-march=armv8-a+nolse -O2 -mno-outline-atomics" } */ > > #include "sync-op-full.x" > > diff --git a/gcc/config/aarch64/aarch64.opt b/gcc/config/aarch64/aarch64.opt > index 55d466068b8..865b6a6d8ca 100644 > --- a/gcc/config/aarch64/aarch64.opt > +++ b/gcc/config/aarch64/aarch64.opt > @@ -255,3 +255,6 @@ user-land code. > TargetVariable > long aarch64_stack_protector_guard_offset = 0 > > +moutline-atomics > +Target Report Mask(OUTLINE_ATOMICS) Save > +Generate local calls to out-of-line atomic operations. > diff --git a/gcc/config/aarch64/atomics.md b/gcc/config/aarch64/atomics.md > index f8bdd048b37..2e59b868420 100644 > --- a/gcc/config/aarch64/atomics.md > +++ b/gcc/config/aarch64/atomics.md > @@ -186,16 +186,27 @@ > (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; > + { > + emit_insn (gen_aarch64_atomic_exchange<mode>_lse > + (operands[0], operands[1], operands[2], operands[3])); > + } > + else if (TARGET_OUTLINE_ATOMICS) > + { > + machine_mode mode = <MODE>mode; > + rtx func = aarch64_atomic_ool_func (mode, operands[3], > + &aarch64_ool_swp_names); > + rtx rval = emit_library_call_value (func, operands[0], LCT_NORMAL, > + mode, operands[2], mode, > + XEXP (operands[1], 0), Pmode); > + emit_move_insn (operands[0], rval); > + } > else > - gen = gen_aarch64_atomic_exchange<mode>; > - > - emit_insn (gen (operands[0], operands[1], operands[2], operands[3])); > - > + { > + emit_insn (gen_aarch64_atomic_exchange<mode> > + (operands[0], operands[1], operands[2], operands[3])); > + } > DONE; > } > ) > @@ -280,6 +291,39 @@ > } > operands[1] = force_reg (<MODE>mode, operands[1]); > } > + else if (TARGET_OUTLINE_ATOMICS) > + { > + const atomic_ool_names *names; > + switch (<CODE>) > + { > + case MINUS: > + operands[1] = expand_simple_unop (<MODE>mode, NEG, operands[1], > + NULL, 1); > + /* fallthru */ > + case PLUS: > + names = &aarch64_ool_ldadd_names; > + break; > + case IOR: > + names = &aarch64_ool_ldset_names; > + break; > + case XOR: > + names = &aarch64_ool_ldeor_names; > + break; > + case AND: > + operands[1] = expand_simple_unop (<MODE>mode, NOT, operands[1], > + NULL, 1); > + names = &aarch64_ool_ldclr_names; > + break; > + default: > + gcc_unreachable (); > + } > + machine_mode mode = <MODE>mode; > + rtx func = aarch64_atomic_ool_func (mode, operands[2], names); > + emit_library_call_value (func, NULL_RTX, LCT_NORMAL, mode, > + operands[1], mode, > + XEXP (operands[0], 0), Pmode); > + DONE; > + } > else > gen = gen_aarch64_atomic_<atomic_optab><mode>; > > @@ -405,6 +449,40 @@ > } > operands[2] = force_reg (<MODE>mode, operands[2]); > } > + else if (TARGET_OUTLINE_ATOMICS) > + { > + const atomic_ool_names *names; > + switch (<CODE>) > + { > + case MINUS: > + operands[2] = expand_simple_unop (<MODE>mode, NEG, operands[2], > + NULL, 1); > + /* fallthru */ > + case PLUS: > + names = &aarch64_ool_ldadd_names; > + break; > + case IOR: > + names = &aarch64_ool_ldset_names; > + break; > + case XOR: > + names = &aarch64_ool_ldeor_names; > + break; > + case AND: > + operands[2] = expand_simple_unop (<MODE>mode, NOT, operands[2], > + NULL, 1); > + names = &aarch64_ool_ldclr_names; > + break; > + default: > + gcc_unreachable (); > + } > + machine_mode mode = <MODE>mode; > + rtx func = aarch64_atomic_ool_func (mode, operands[3], names); > + rtx rval = emit_library_call_value (func, operands[0], LCT_NORMAL, mode, > + operands[2], mode, > + XEXP (operands[1], 0), Pmode); > + emit_move_insn (operands[0], rval); > + DONE; > + } > else > gen = gen_aarch64_atomic_fetch_<atomic_optab><mode>; > > @@ -494,7 +572,7 @@ > { > /* 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) > + if (TARGET_LSE || TARGET_OUTLINE_ATOMICS) > { > rtx tmp = gen_reg_rtx (<MODE>mode); > operands[2] = force_reg (<MODE>mode, operands[2]); > diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi > index 0e3693598e7..900fda1efb2 100644 > --- a/gcc/doc/invoke.texi > +++ b/gcc/doc/invoke.texi > @@ -643,7 +643,8 @@ Objective-C and Objective-C++ Dialects}. > -march=@var{name} -mcpu=@var{name} -mtune=@var{name} @gol > -moverride=@var{string} -mverbose-cost-dump @gol > -mstack-protector-guard=@var{guard} -mstack-protector-guard-reg=@var{sysreg} @gol > --mstack-protector-guard-offset=@var{offset} -mtrack-speculation } > +-mstack-protector-guard-offset=@var{offset} -mtrack-speculation @gol > +-moutline-atomics } > > @emph{Adapteva Epiphany Options} > @gccoptlist{-mhalf-reg-file -mprefer-short-insn-regs @gol > @@ -15874,6 +15875,19 @@ be used by the compiler when expanding calls to > @code{__builtin_speculation_safe_copy} to permit a more efficient code > sequence to be generated. > > +@item -moutline-atomics > +@itemx -mno-outline-atomics > +Enable or disable calls to out-of-line helpers to implement atomic operations. > +These helpers will, at runtime, determine if ARMv8.1-Atomics instructions > +should be used; if not, they will use the load/store-exclusive instructions > +that are present in the base ARMv8.0 ISA. Let's call them "LSE instructions from Armv8.1-A", rather than ARMv8.1-Atomics. > + > +This option is only applicable when compiling for the base ARMv8.0 > +instruction set. If using a later revision, e.g. @option{-march=armv8.1-a} > +or @option{-march=armv8-a+lse}, the ARMv8.1-Atomics instructions will be > +used directly. The same applies when using @option{-mcpu=} when the > +selected cpu supports the @samp{lse} feature. > + This needs a corresponding ChangeLog entry. Thanks, Kyril > @item -march=@var{name} > @opindex march > Specify the name of the target architecture and, optionally, one or
diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h index c4b73d26df6..1c1aac7201a 100644 --- a/gcc/config/aarch64/aarch64-protos.h +++ b/gcc/config/aarch64/aarch64-protos.h @@ -696,4 +696,17 @@ poly_uint64 aarch64_regmode_natural_size (machine_mode); bool aarch64_high_bits_all_ones_p (HOST_WIDE_INT); +struct atomic_ool_names +{ + const char *str[5][4]; +}; + +rtx aarch64_atomic_ool_func(machine_mode mode, rtx model_rtx, + const atomic_ool_names *names); +extern const atomic_ool_names aarch64_ool_swp_names; +extern const atomic_ool_names aarch64_ool_ldadd_names; +extern const atomic_ool_names aarch64_ool_ldset_names; +extern const atomic_ool_names aarch64_ool_ldclr_names; +extern const atomic_ool_names aarch64_ool_ldeor_names; + #endif /* GCC_AARCH64_PROTOS_H */ diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index b937514e6f8..56a4a47db73 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -16867,6 +16867,82 @@ aarch64_emit_unlikely_jump (rtx insn) add_reg_br_prob_note (jump, profile_probability::very_unlikely ()); } +/* We store the names of the various atomic helpers in a 5x4 array. + Return the libcall function given MODE, MODEL and NAMES. */ + +rtx +aarch64_atomic_ool_func(machine_mode mode, rtx model_rtx, + const atomic_ool_names *names) +{ + memmodel model = memmodel_base (INTVAL (model_rtx)); + int mode_idx, model_idx; + + switch (mode) + { + case E_QImode: + mode_idx = 0; + break; + case E_HImode: + mode_idx = 1; + break; + case E_SImode: + mode_idx = 2; + break; + case E_DImode: + mode_idx = 3; + break; + case E_TImode: + mode_idx = 4; + break; + default: + gcc_unreachable (); + } + + switch (model) + { + case MEMMODEL_RELAXED: + model_idx = 0; + break; + case MEMMODEL_CONSUME: + case MEMMODEL_ACQUIRE: + model_idx = 1; + break; + case MEMMODEL_RELEASE: + model_idx = 2; + break; + case MEMMODEL_ACQ_REL: + case MEMMODEL_SEQ_CST: + model_idx = 3; + break; + default: + gcc_unreachable (); + } + + return init_one_libfunc_visibility (names->str[mode_idx][model_idx], + VISIBILITY_HIDDEN); +} + +#define DEF0(B, N) \ + { "__aarch64_" #B #N "_relax", \ + "__aarch64_" #B #N "_acq", \ + "__aarch64_" #B #N "_rel", \ + "__aarch64_" #B #N "_acq_rel" } + +#define DEF4(B) DEF0(B, 1), DEF0(B, 2), DEF0(B, 4), DEF0(B, 8), \ + { NULL, NULL, NULL, NULL } +#define DEF5(B) DEF0(B, 1), DEF0(B, 2), DEF0(B, 4), DEF0(B, 8), DEF0(B, 16) + +static const atomic_ool_names aarch64_ool_cas_names = { { DEF5(cas) } }; +const atomic_ool_names aarch64_ool_swp_names = { { DEF4(swp) } }; +const atomic_ool_names aarch64_ool_ldadd_names = { { DEF4(ldadd) } }; +const atomic_ool_names aarch64_ool_ldset_names = { { DEF4(ldset) } }; +const atomic_ool_names aarch64_ool_ldclr_names = { { DEF4(ldclr) } }; +const atomic_ool_names aarch64_ool_ldeor_names = { { DEF4(ldeor) } }; + +#undef DEF0 +#undef DEF4 +#undef DEF5 + /* Expand a compare and swap pattern. */ void @@ -16913,6 +16989,17 @@ aarch64_expand_compare_and_swap (rtx operands[]) newval, mod_s)); cc_reg = aarch64_gen_compare_reg_maybe_ze (NE, rval, oldval, mode); } + else if (TARGET_OUTLINE_ATOMICS) + { + /* Oldval must satisfy compare afterward. */ + if (!aarch64_plus_operand (oldval, mode)) + oldval = force_reg (mode, oldval); + rtx func = aarch64_atomic_ool_func (mode, mod_s, &aarch64_ool_cas_names); + rval = emit_library_call_value (func, NULL_RTX, LCT_NORMAL, r_mode, + oldval, mode, newval, mode, + XEXP (mem, 0), Pmode); + cc_reg = aarch64_gen_compare_reg_maybe_ze (NE, rval, oldval, mode); + } else { /* The oldval predicate varies by mode. Test it and force to reg. */ diff --git a/gcc/testsuite/gcc.target/aarch64/atomic-comp-swap-release-acquire.c b/gcc/testsuite/gcc.target/aarch64/atomic-comp-swap-release-acquire.c index 49ca5d0d09c..a828a72aa75 100644 --- a/gcc/testsuite/gcc.target/aarch64/atomic-comp-swap-release-acquire.c +++ b/gcc/testsuite/gcc.target/aarch64/atomic-comp-swap-release-acquire.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-march=armv8-a+nolse -O2 -fno-ipa-icf" } */ +/* { dg-options "-march=armv8-a+nolse -O2 -fno-ipa-icf -mno-outline-atomics" } */ #include "atomic-comp-swap-release-acquire.x" diff --git a/gcc/testsuite/gcc.target/aarch64/atomic-op-acq_rel.c b/gcc/testsuite/gcc.target/aarch64/atomic-op-acq_rel.c index 74f26348e42..6823ce381b2 100644 --- a/gcc/testsuite/gcc.target/aarch64/atomic-op-acq_rel.c +++ b/gcc/testsuite/gcc.target/aarch64/atomic-op-acq_rel.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-march=armv8-a+nolse -O2" } */ +/* { dg-options "-march=armv8-a+nolse -O2 -mno-outline-atomics" } */ #include "atomic-op-acq_rel.x" diff --git a/gcc/testsuite/gcc.target/aarch64/atomic-op-acquire.c b/gcc/testsuite/gcc.target/aarch64/atomic-op-acquire.c index 66c1b1efe20..87937de378a 100644 --- a/gcc/testsuite/gcc.target/aarch64/atomic-op-acquire.c +++ b/gcc/testsuite/gcc.target/aarch64/atomic-op-acquire.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-march=armv8-a+nolse -O2" } */ +/* { dg-options "-march=armv8-a+nolse -O2 -mno-outline-atomics" } */ #include "atomic-op-acquire.x" diff --git a/gcc/testsuite/gcc.target/aarch64/atomic-op-char.c b/gcc/testsuite/gcc.target/aarch64/atomic-op-char.c index c09d0434ecf..60955e57da3 100644 --- a/gcc/testsuite/gcc.target/aarch64/atomic-op-char.c +++ b/gcc/testsuite/gcc.target/aarch64/atomic-op-char.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-march=armv8-a+nolse -O2" } */ +/* { dg-options "-march=armv8-a+nolse -O2 -mno-outline-atomics" } */ #include "atomic-op-char.x" diff --git a/gcc/testsuite/gcc.target/aarch64/atomic-op-consume.c b/gcc/testsuite/gcc.target/aarch64/atomic-op-consume.c index 5783ab84f5c..16cb11aeeaf 100644 --- a/gcc/testsuite/gcc.target/aarch64/atomic-op-consume.c +++ b/gcc/testsuite/gcc.target/aarch64/atomic-op-consume.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-march=armv8-a+nolse -O2" } */ +/* { dg-options "-march=armv8-a+nolse -O2 -mno-outline-atomics" } */ #include "atomic-op-consume.x" diff --git a/gcc/testsuite/gcc.target/aarch64/atomic-op-imm.c b/gcc/testsuite/gcc.target/aarch64/atomic-op-imm.c index 18b8f0b04e9..bcab4e481e3 100644 --- a/gcc/testsuite/gcc.target/aarch64/atomic-op-imm.c +++ b/gcc/testsuite/gcc.target/aarch64/atomic-op-imm.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-march=armv8-a+nolse -O2" } */ +/* { dg-options "-march=armv8-a+nolse -O2 -mno-outline-atomics" } */ int v = 0; diff --git a/gcc/testsuite/gcc.target/aarch64/atomic-op-int.c b/gcc/testsuite/gcc.target/aarch64/atomic-op-int.c index 8520f0839ba..040e4a8d168 100644 --- a/gcc/testsuite/gcc.target/aarch64/atomic-op-int.c +++ b/gcc/testsuite/gcc.target/aarch64/atomic-op-int.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-march=armv8-a+nolse -O2" } */ +/* { dg-options "-march=armv8-a+nolse -O2 -mno-outline-atomics" } */ #include "atomic-op-int.x" diff --git a/gcc/testsuite/gcc.target/aarch64/atomic-op-long.c b/gcc/testsuite/gcc.target/aarch64/atomic-op-long.c index d011f8c5ce2..fc88b92cd3e 100644 --- a/gcc/testsuite/gcc.target/aarch64/atomic-op-long.c +++ b/gcc/testsuite/gcc.target/aarch64/atomic-op-long.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-march=armv8-a+nolse -O2" } */ +/* { dg-options "-march=armv8-a+nolse -O2 -mno-outline-atomics" } */ long v = 0; diff --git a/gcc/testsuite/gcc.target/aarch64/atomic-op-relaxed.c b/gcc/testsuite/gcc.target/aarch64/atomic-op-relaxed.c index ed96bfdb978..503d62b0280 100644 --- a/gcc/testsuite/gcc.target/aarch64/atomic-op-relaxed.c +++ b/gcc/testsuite/gcc.target/aarch64/atomic-op-relaxed.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-march=armv8-a+nolse -O2" } */ +/* { dg-options "-march=armv8-a+nolse -O2 -mno-outline-atomics" } */ #include "atomic-op-relaxed.x" diff --git a/gcc/testsuite/gcc.target/aarch64/atomic-op-release.c b/gcc/testsuite/gcc.target/aarch64/atomic-op-release.c index fc4be17de89..efe14aea7e4 100644 --- a/gcc/testsuite/gcc.target/aarch64/atomic-op-release.c +++ b/gcc/testsuite/gcc.target/aarch64/atomic-op-release.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-march=armv8-a+nolse -O2" } */ +/* { dg-options "-march=armv8-a+nolse -O2 -mno-outline-atomics" } */ #include "atomic-op-release.x" diff --git a/gcc/testsuite/gcc.target/aarch64/atomic-op-seq_cst.c b/gcc/testsuite/gcc.target/aarch64/atomic-op-seq_cst.c index 613000fe490..09973bf82ba 100644 --- a/gcc/testsuite/gcc.target/aarch64/atomic-op-seq_cst.c +++ b/gcc/testsuite/gcc.target/aarch64/atomic-op-seq_cst.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-march=armv8-a+nolse -O2" } */ +/* { dg-options "-march=armv8-a+nolse -O2 -mno-outline-atomics" } */ #include "atomic-op-seq_cst.x" diff --git a/gcc/testsuite/gcc.target/aarch64/atomic-op-short.c b/gcc/testsuite/gcc.target/aarch64/atomic-op-short.c index e82c8118ece..e1dcebb0f89 100644 --- a/gcc/testsuite/gcc.target/aarch64/atomic-op-short.c +++ b/gcc/testsuite/gcc.target/aarch64/atomic-op-short.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-march=armv8-a+nolse -O2" } */ +/* { dg-options "-march=armv8-a+nolse -O2 -mno-outline-atomics" } */ #include "atomic-op-short.x" diff --git a/gcc/testsuite/gcc.target/aarch64/atomic_cmp_exchange_zero_reg_1.c b/gcc/testsuite/gcc.target/aarch64/atomic_cmp_exchange_zero_reg_1.c index f2a21ddf2e1..29246979bfb 100644 --- a/gcc/testsuite/gcc.target/aarch64/atomic_cmp_exchange_zero_reg_1.c +++ b/gcc/testsuite/gcc.target/aarch64/atomic_cmp_exchange_zero_reg_1.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -march=armv8-a+nolse" } */ +/* { dg-options "-O2 -march=armv8-a+nolse -mno-outline-atomics" } */ /* { dg-skip-if "" { *-*-* } { "-mcpu=*" } { "" } } */ int diff --git a/gcc/testsuite/gcc.target/aarch64/atomic_cmp_exchange_zero_strong_1.c b/gcc/testsuite/gcc.target/aarch64/atomic_cmp_exchange_zero_strong_1.c index 8d2ae67dfbe..6daf9b08f5a 100644 --- a/gcc/testsuite/gcc.target/aarch64/atomic_cmp_exchange_zero_strong_1.c +++ b/gcc/testsuite/gcc.target/aarch64/atomic_cmp_exchange_zero_strong_1.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -march=armv8-a+nolse" } */ +/* { dg-options "-O2 -march=armv8-a+nolse -mno-outline-atomics" } */ /* { dg-skip-if "" { *-*-* } { "-mcpu=*" } { "" } } */ int diff --git a/gcc/testsuite/gcc.target/aarch64/sync-comp-swap.c b/gcc/testsuite/gcc.target/aarch64/sync-comp-swap.c index e571b2f13b3..f56415f3354 100644 --- a/gcc/testsuite/gcc.target/aarch64/sync-comp-swap.c +++ b/gcc/testsuite/gcc.target/aarch64/sync-comp-swap.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-march=armv8-a+nolse -O2 -fno-ipa-icf" } */ +/* { dg-options "-march=armv8-a+nolse -O2 -fno-ipa-icf -mno-outline-atomics" } */ #include "sync-comp-swap.x" diff --git a/gcc/testsuite/gcc.target/aarch64/sync-op-acquire.c b/gcc/testsuite/gcc.target/aarch64/sync-op-acquire.c index 357bf1be3b2..39b3144aa36 100644 --- a/gcc/testsuite/gcc.target/aarch64/sync-op-acquire.c +++ b/gcc/testsuite/gcc.target/aarch64/sync-op-acquire.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-march=armv8-a+nolse -O2" } */ +/* { dg-options "-march=armv8-a+nolse -O2 -mno-outline-atomics" } */ #include "sync-op-acquire.x" diff --git a/gcc/testsuite/gcc.target/aarch64/sync-op-full.c b/gcc/testsuite/gcc.target/aarch64/sync-op-full.c index c6ba1629965..6b8b2043f40 100644 --- a/gcc/testsuite/gcc.target/aarch64/sync-op-full.c +++ b/gcc/testsuite/gcc.target/aarch64/sync-op-full.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-march=armv8-a+nolse -O2" } */ +/* { dg-options "-march=armv8-a+nolse -O2 -mno-outline-atomics" } */ #include "sync-op-full.x" diff --git a/gcc/config/aarch64/aarch64.opt b/gcc/config/aarch64/aarch64.opt index 55d466068b8..865b6a6d8ca 100644 --- a/gcc/config/aarch64/aarch64.opt +++ b/gcc/config/aarch64/aarch64.opt @@ -255,3 +255,6 @@ user-land code. TargetVariable long aarch64_stack_protector_guard_offset = 0 +moutline-atomics +Target Report Mask(OUTLINE_ATOMICS) Save +Generate local calls to out-of-line atomic operations. diff --git a/gcc/config/aarch64/atomics.md b/gcc/config/aarch64/atomics.md index f8bdd048b37..2e59b868420 100644 --- a/gcc/config/aarch64/atomics.md +++ b/gcc/config/aarch64/atomics.md @@ -186,16 +186,27 @@ (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; + { + emit_insn (gen_aarch64_atomic_exchange<mode>_lse + (operands[0], operands[1], operands[2], operands[3])); + } + else if (TARGET_OUTLINE_ATOMICS) + { + machine_mode mode = <MODE>mode; + rtx func = aarch64_atomic_ool_func (mode, operands[3], + &aarch64_ool_swp_names); + rtx rval = emit_library_call_value (func, operands[0], LCT_NORMAL, + mode, operands[2], mode, + XEXP (operands[1], 0), Pmode); + emit_move_insn (operands[0], rval); + } else - gen = gen_aarch64_atomic_exchange<mode>; - - emit_insn (gen (operands[0], operands[1], operands[2], operands[3])); - + { + emit_insn (gen_aarch64_atomic_exchange<mode> + (operands[0], operands[1], operands[2], operands[3])); + } DONE; } ) @@ -280,6 +291,39 @@ } operands[1] = force_reg (<MODE>mode, operands[1]); } + else if (TARGET_OUTLINE_ATOMICS) + { + const atomic_ool_names *names; + switch (<CODE>) + { + case MINUS: + operands[1] = expand_simple_unop (<MODE>mode, NEG, operands[1], + NULL, 1); + /* fallthru */ + case PLUS: + names = &aarch64_ool_ldadd_names; + break; + case IOR: + names = &aarch64_ool_ldset_names; + break; + case XOR: + names = &aarch64_ool_ldeor_names; + break; + case AND: + operands[1] = expand_simple_unop (<MODE>mode, NOT, operands[1], + NULL, 1); + names = &aarch64_ool_ldclr_names; + break; + default: + gcc_unreachable (); + } + machine_mode mode = <MODE>mode; + rtx func = aarch64_atomic_ool_func (mode, operands[2], names); + emit_library_call_value (func, NULL_RTX, LCT_NORMAL, mode, + operands[1], mode, + XEXP (operands[0], 0), Pmode); + DONE; + } else gen = gen_aarch64_atomic_<atomic_optab><mode>; @@ -405,6 +449,40 @@ } operands[2] = force_reg (<MODE>mode, operands[2]); } + else if (TARGET_OUTLINE_ATOMICS) + { + const atomic_ool_names *names; + switch (<CODE>) + { + case MINUS: + operands[2] = expand_simple_unop (<MODE>mode, NEG, operands[2], + NULL, 1); + /* fallthru */ + case PLUS: + names = &aarch64_ool_ldadd_names; + break; + case IOR: + names = &aarch64_ool_ldset_names; + break; + case XOR: + names = &aarch64_ool_ldeor_names; + break; + case AND: + operands[2] = expand_simple_unop (<MODE>mode, NOT, operands[2], + NULL, 1); + names = &aarch64_ool_ldclr_names; + break; + default: + gcc_unreachable (); + } + machine_mode mode = <MODE>mode; + rtx func = aarch64_atomic_ool_func (mode, operands[3], names); + rtx rval = emit_library_call_value (func, operands[0], LCT_NORMAL, mode, + operands[2], mode, + XEXP (operands[1], 0), Pmode); + emit_move_insn (operands[0], rval); + DONE; + } else gen = gen_aarch64_atomic_fetch_<atomic_optab><mode>; @@ -494,7 +572,7 @@ { /* 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) + if (TARGET_LSE || TARGET_OUTLINE_ATOMICS) { rtx tmp = gen_reg_rtx (<MODE>mode); operands[2] = force_reg (<MODE>mode, operands[2]); diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 0e3693598e7..900fda1efb2 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -643,7 +643,8 @@ Objective-C and Objective-C++ Dialects}. -march=@var{name} -mcpu=@var{name} -mtune=@var{name} @gol -moverride=@var{string} -mverbose-cost-dump @gol -mstack-protector-guard=@var{guard} -mstack-protector-guard-reg=@var{sysreg} @gol --mstack-protector-guard-offset=@var{offset} -mtrack-speculation } +-mstack-protector-guard-offset=@var{offset} -mtrack-speculation @gol +-moutline-atomics } @emph{Adapteva Epiphany Options} @gccoptlist{-mhalf-reg-file -mprefer-short-insn-regs @gol @@ -15874,6 +15875,19 @@ be used by the compiler when expanding calls to @code{__builtin_speculation_safe_copy} to permit a more efficient code sequence to be generated. +@item -moutline-atomics +@itemx -mno-outline-atomics +Enable or disable calls to out-of-line helpers to implement atomic operations. +These helpers will, at runtime, determine if ARMv8.1-Atomics instructions +should be used; if not, they will use the load/store-exclusive instructions +that are present in the base ARMv8.0 ISA. + +This option is only applicable when compiling for the base ARMv8.0 +instruction set. If using a later revision, e.g. @option{-march=armv8.1-a} +or @option{-march=armv8-a+lse}, the ARMv8.1-Atomics instructions will be +used directly. The same applies when using @option{-mcpu=} when the +selected cpu supports the @samp{lse} feature. + @item -march=@var{name} @opindex march Specify the name of the target architecture and, optionally, one or