Skip to content

Commit 5e9e43c

Browse files
mrutland-armctmarinas
authored andcommitted
arm64: atomics: lse: define ANDs in terms of ANDNOTs
The FEAT_LSE atomic instructions include atomic bit-clear instructions (`ldclr*` and `stclr*`) which can be used to directly implement ANDNOT operations. Each AND op is implemented as a copy of the corresponding ANDNOT op with a leading `mvn` instruction to apply a bitwise NOT to the `i` argument. As the compiler has no visibility of the `mvn`, this leads to less than optimal code generation when generating `i` into a register. For example, __lse_atomic_fetch_and(0xf, v) can be compiled to: mov w1, #0xf mvn w1, w1 ldclral w1, w1, [x2] This patch improves this by replacing the `mvn` with NOT in C before the inline assembly block, e.g. i = ~i; This allows the compiler to generate `i` into a register more optimally, e.g. mov w1, #0xfffffff0 ldclral w1, w1, [x2] With this change the assembly for each AND op is identical to the corresponding ANDNOT op (including barriers and clobbers), so I've removed the inline assembly and rewritten each AND op in terms of the corresponding ANDNOT op, e.g. | static inline void __lse_atomic_and(int i, atomic_t *v) | { | return __lse_atomic_andnot(~i, v); | } This is intended as an optimization and cleanup. There should be no functional change as a result of this patch. Signed-off-by: Mark Rutland <[email protected]> Cc: Boqun Feng <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Will Deacon <[email protected]> Acked-by: Will Deacon <[email protected]> Acked-by: Peter Zijlstra (Intel) <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Catalin Marinas <[email protected]>
1 parent ef53245 commit 5e9e43c

File tree

1 file changed

+4
-30
lines changed

1 file changed

+4
-30
lines changed

arch/arm64/include/asm/atomic_lse.h

Lines changed: 4 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -102,26 +102,13 @@ ATOMIC_OP_ADD_SUB_RETURN( , al, "memory")
102102

103103
static inline void __lse_atomic_and(int i, atomic_t *v)
104104
{
105-
asm volatile(
106-
__LSE_PREAMBLE
107-
" mvn %w[i], %w[i]\n"
108-
" stclr %w[i], %[v]"
109-
: [i] "+&r" (i), [v] "+Q" (v->counter)
110-
: "r" (v));
105+
return __lse_atomic_andnot(~i, v);
111106
}
112107

113108
#define ATOMIC_FETCH_OP_AND(name, mb, cl...) \
114109
static inline int __lse_atomic_fetch_and##name(int i, atomic_t *v) \
115110
{ \
116-
asm volatile( \
117-
__LSE_PREAMBLE \
118-
" mvn %w[i], %w[i]\n" \
119-
" ldclr" #mb " %w[i], %w[i], %[v]" \
120-
: [i] "+&r" (i), [v] "+Q" (v->counter) \
121-
: "r" (v) \
122-
: cl); \
123-
\
124-
return i; \
111+
return __lse_atomic_fetch_andnot##name(~i, v); \
125112
}
126113

127114
ATOMIC_FETCH_OP_AND(_relaxed, )
@@ -223,26 +210,13 @@ ATOMIC64_OP_ADD_SUB_RETURN( , al, "memory")
223210

224211
static inline void __lse_atomic64_and(s64 i, atomic64_t *v)
225212
{
226-
asm volatile(
227-
__LSE_PREAMBLE
228-
" mvn %[i], %[i]\n"
229-
" stclr %[i], %[v]"
230-
: [i] "+&r" (i), [v] "+Q" (v->counter)
231-
: "r" (v));
213+
return __lse_atomic64_andnot(~i, v);
232214
}
233215

234216
#define ATOMIC64_FETCH_OP_AND(name, mb, cl...) \
235217
static inline long __lse_atomic64_fetch_and##name(s64 i, atomic64_t *v) \
236218
{ \
237-
asm volatile( \
238-
__LSE_PREAMBLE \
239-
" mvn %[i], %[i]\n" \
240-
" ldclr" #mb " %[i], %[i], %[v]" \
241-
: [i] "+&r" (i), [v] "+Q" (v->counter) \
242-
: "r" (v) \
243-
: cl); \
244-
\
245-
return i; \
219+
return __lse_atomic64_fetch_andnot##name(~i, v); \
246220
}
247221

248222
ATOMIC64_FETCH_OP_AND(_relaxed, )

0 commit comments

Comments
 (0)