Skip to content

Commit 876816f

Browse files
authored
[AArch64] Set MaxAtomicSizeInBitsSupported. (#74385)
This will result in larger atomic operations getting expanded to `__atomic_*` libcalls via AtomicExpandPass, which matches what Clang already does in the frontend. Additionally, adjust some comments, and remove partial code dealing with larger-than-128bit atomics, as it's now unreachable. AArch64 always supports 128-bit atomics, so there's no conditionals needed here. (Though: we really ought to require that a 128-bit load is available, not just a cmpxchg, which would mean conditioning on LSE2. But that's future work.) The arm64-irtranslator.ll test was adjusted as it was using an i258 type as a hack to avoid IR atomic lowering to test GlobalISel behavior. Pass -mattr=+lse and use i32, instead, to accomplish that goal in a way that continues to work.
1 parent a37fa2a commit 876816f

File tree

3 files changed

+83
-108
lines changed

3 files changed

+83
-108
lines changed

llvm/lib/Target/AArch64/AArch64ISelLowering.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1651,6 +1651,7 @@ AArch64TargetLowering::AArch64TargetLowering(const TargetMachine &TM,
16511651
PredictableSelectIsExpensive = Subtarget->predictableSelectIsExpensive();
16521652

16531653
IsStrictFPEnabled = true;
1654+
setMaxAtomicSizeInBitsSupported(128);
16541655
}
16551656

16561657
void AArch64TargetLowering::addTypeForNEON(MVT VT) {
@@ -24909,15 +24910,21 @@ AArch64TargetLowering::shouldExpandAtomicLoadInIR(LoadInst *LI) const {
2490924910
: AtomicExpansionKind::LLSC;
2491024911
}
2491124912

24912-
// For the real atomic operations, we have ldxr/stxr up to 128 bits,
24913+
// The "default" for integer RMW operations is to expand to an LL/SC loop.
24914+
// However, with the LSE instructions (or outline-atomics mode, which provides
24915+
// library routines in place of the LSE-instructions), we can directly emit many
24916+
// operations instead.
24917+
//
24918+
// Floating-point operations are always emitted to a cmpxchg loop, because they
24919+
// may trigger a trap which aborts an LLSC sequence.
2491324920
TargetLowering::AtomicExpansionKind
2491424921
AArch64TargetLowering::shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const {
24922+
unsigned Size = AI->getType()->getPrimitiveSizeInBits();
24923+
assert(Size <= 128 && "AtomicExpandPass should've handled larger sizes.");
24924+
2491524925
if (AI->isFloatingPointOperation())
2491624926
return AtomicExpansionKind::CmpXChg;
2491724927

24918-
unsigned Size = AI->getType()->getPrimitiveSizeInBits();
24919-
if (Size > 128) return AtomicExpansionKind::None;
24920-
2492124928
bool CanUseLSE128 = Subtarget->hasLSE128() && Size == 128 &&
2492224929
(AI->getOperation() == AtomicRMWInst::Xchg ||
2492324930
AI->getOperation() == AtomicRMWInst::Or ||

llvm/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll

Lines changed: 61 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
; RUN: llc -O0 -aarch64-enable-atomic-cfg-tidy=0 -stop-after=irtranslator -global-isel -verify-machineinstrs %s -o - 2>&1 | FileCheck %s
2-
; RUN: llc -O3 -aarch64-enable-atomic-cfg-tidy=0 -stop-after=irtranslator -global-isel -verify-machineinstrs %s -o - 2>&1 | FileCheck %s --check-prefix=O3
1+
; RUN: llc -O0 -aarch64-enable-atomic-cfg-tidy=0 -mattr=+lse -stop-after=irtranslator -global-isel -verify-machineinstrs %s -o - 2>&1 | FileCheck %s
2+
; RUN: llc -O3 -aarch64-enable-atomic-cfg-tidy=0 -mattr=+lse -stop-after=irtranslator -global-isel -verify-machineinstrs %s -o - 2>&1 | FileCheck %s --check-prefix=O3
33

44
; This file checks that the translation from llvm IR to generic MachineInstr
55
; is correct.
@@ -2077,190 +2077,147 @@ done:
20772077
}
20782078

20792079
; Try a monotonic atomicrmw xchg
2080-
; AArch64 will expand some atomicrmw's at the LLVM-IR level so we use a wide type to avoid this.
20812080
define i32 @test_atomicrmw_xchg(ptr %addr) {
20822081
; CHECK-LABEL: name: test_atomicrmw_xchg
20832082
; CHECK: bb.1 (%ir-block.{{[0-9]+}}):
20842083
; CHECK-NEXT: liveins: $x0
20852084
; CHECK: [[ADDR:%[0-9]+]]:_(p0) = COPY $x0
2086-
; CHECK-NEXT: [[VAL:%[0-9]+]]:_(s256) = G_CONSTANT i256 1
2087-
; CHECK-NEXT: [[OLDVALRES:%[0-9]+]]:_(s256) = G_ATOMICRMW_XCHG [[ADDR]](p0), [[VAL]] :: (load store monotonic (s256) on %ir.addr)
2088-
; CHECK-NEXT: [[RES:%[0-9]+]]:_(s32) = G_TRUNC [[OLDVALRES]]
2089-
%oldval = atomicrmw xchg ptr %addr, i256 1 monotonic
2090-
; FIXME: We currently can't lower 'ret i256' and it's not the purpose of this
2091-
; test so work around it by truncating to i32 for now.
2092-
%oldval.trunc = trunc i256 %oldval to i32
2093-
ret i32 %oldval.trunc
2085+
; CHECK-NEXT: [[VAL:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
2086+
; CHECK-NEXT: [[OLDVALRES:%[0-9]+]]:_(s32) = G_ATOMICRMW_XCHG [[ADDR]](p0), [[VAL]] :: (load store monotonic (s32) on %ir.addr)
2087+
%oldval = atomicrmw xchg ptr %addr, i32 1 monotonic
2088+
ret i32 %oldval
20942089
}
20952090

20962091
; Try an acquire atomicrmw add
2097-
; AArch64 will expand some atomicrmw's at the LLVM-IR level so we use a wide type to avoid this.
20982092
define i32 @test_atomicrmw_add(ptr %addr) {
20992093
; CHECK-LABEL: name: test_atomicrmw_add
21002094
; CHECK: bb.1 (%ir-block.{{[0-9]+}}):
21012095
; CHECK-NEXT: liveins: $x0
21022096
; CHECK: [[ADDR:%[0-9]+]]:_(p0) = COPY $x0
2103-
; CHECK-NEXT: [[VAL:%[0-9]+]]:_(s256) = G_CONSTANT i256 1
2104-
; CHECK-NEXT: [[OLDVALRES:%[0-9]+]]:_(s256) = G_ATOMICRMW_ADD [[ADDR]](p0), [[VAL]] :: (load store acquire (s256) on %ir.addr)
2105-
; CHECK-NEXT: [[RES:%[0-9]+]]:_(s32) = G_TRUNC [[OLDVALRES]]
2106-
%oldval = atomicrmw add ptr %addr, i256 1 acquire
2107-
; FIXME: We currently can't lower 'ret i256' and it's not the purpose of this
2108-
; test so work around it by truncating to i32 for now.
2109-
%oldval.trunc = trunc i256 %oldval to i32
2110-
ret i32 %oldval.trunc
2097+
; CHECK-NEXT: [[VAL:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
2098+
; CHECK-NEXT: [[OLDVALRES:%[0-9]+]]:_(s32) = G_ATOMICRMW_ADD [[ADDR]](p0), [[VAL]] :: (load store acquire (s32) on %ir.addr)
2099+
%oldval = atomicrmw add ptr %addr, i32 1 acquire
2100+
ret i32 %oldval
21112101
}
21122102

21132103
; Try a release atomicrmw sub
2114-
; AArch64 will expand some atomicrmw's at the LLVM-IR level so we use a wide type to avoid this.
21152104
define i32 @test_atomicrmw_sub(ptr %addr) {
21162105
; CHECK-LABEL: name: test_atomicrmw_sub
21172106
; CHECK: bb.1 (%ir-block.{{[0-9]+}}):
21182107
; CHECK-NEXT: liveins: $x0
21192108
; CHECK: [[ADDR:%[0-9]+]]:_(p0) = COPY $x0
2120-
; CHECK-NEXT: [[VAL:%[0-9]+]]:_(s256) = G_CONSTANT i256 1
2121-
; CHECK-NEXT: [[OLDVALRES:%[0-9]+]]:_(s256) = G_ATOMICRMW_SUB [[ADDR]](p0), [[VAL]] :: (load store release (s256) on %ir.addr)
2122-
; CHECK-NEXT: [[RES:%[0-9]+]]:_(s32) = G_TRUNC [[OLDVALRES]]
2123-
%oldval = atomicrmw sub ptr %addr, i256 1 release
2124-
; FIXME: We currently can't lower 'ret i256' and it's not the purpose of this
2125-
; test so work around it by truncating to i32 for now.
2126-
%oldval.trunc = trunc i256 %oldval to i32
2127-
ret i32 %oldval.trunc
2109+
; CHECK-NEXT: [[VAL:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
2110+
; CHECK-NEXT: [[OLDVALRES:%[0-9]+]]:_(s32) = G_ATOMICRMW_SUB [[ADDR]](p0), [[VAL]] :: (load store release (s32) on %ir.addr)
2111+
%oldval = atomicrmw sub ptr %addr, i32 1 release
2112+
ret i32 %oldval
21282113
}
21292114

21302115
; Try an acq_rel atomicrmw and
2131-
; AArch64 will expand some atomicrmw's at the LLVM-IR level so we use a wide type to avoid this.
21322116
define i32 @test_atomicrmw_and(ptr %addr) {
21332117
; CHECK-LABEL: name: test_atomicrmw_and
21342118
; CHECK: bb.1 (%ir-block.{{[0-9]+}}):
21352119
; CHECK-NEXT: liveins: $x0
21362120
; CHECK: [[ADDR:%[0-9]+]]:_(p0) = COPY $x0
2137-
; CHECK-NEXT: [[VAL:%[0-9]+]]:_(s256) = G_CONSTANT i256 1
2138-
; CHECK-NEXT: [[OLDVALRES:%[0-9]+]]:_(s256) = G_ATOMICRMW_AND [[ADDR]](p0), [[VAL]] :: (load store acq_rel (s256) on %ir.addr)
2139-
; CHECK-NEXT: [[RES:%[0-9]+]]:_(s32) = G_TRUNC [[OLDVALRES]]
2140-
%oldval = atomicrmw and ptr %addr, i256 1 acq_rel
2141-
; FIXME: We currently can't lower 'ret i256' and it's not the purpose of this
2142-
; test so work around it by truncating to i32 for now.
2143-
%oldval.trunc = trunc i256 %oldval to i32
2144-
ret i32 %oldval.trunc
2145-
}
2146-
2147-
; Try an seq_cst atomicrmw nand
2148-
; AArch64 will expand some atomicrmw's at the LLVM-IR level so we use a wide type to avoid this.
2121+
; CHECK-NEXT: [[VAL:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
2122+
; CHECK-NEXT: [[OLDVALRES:%[0-9]+]]:_(s32) = G_ATOMICRMW_AND [[ADDR]](p0), [[VAL]] :: (load store acq_rel (s32) on %ir.addr)
2123+
%oldval = atomicrmw and ptr %addr, i32 1 acq_rel
2124+
ret i32 %oldval
2125+
}
2126+
2127+
; Try an seq_cst atomicrmw nand. NAND isn't supported by LSE, so it
2128+
; expands to G_ATOMIC_CMPXCHG_WITH_SUCCESS.
21492129
define i32 @test_atomicrmw_nand(ptr %addr) {
21502130
; CHECK-LABEL: name: test_atomicrmw_nand
21512131
; CHECK: bb.1 (%ir-block.{{[0-9]+}}):
2132+
; CHECK-NEXT: successors: %bb.2(0x80000000)
21522133
; CHECK-NEXT: liveins: $x0
21532134
; CHECK: [[ADDR:%[0-9]+]]:_(p0) = COPY $x0
2154-
; CHECK-NEXT: [[VAL:%[0-9]+]]:_(s256) = G_CONSTANT i256 1
2155-
; CHECK-NEXT: [[OLDVALRES:%[0-9]+]]:_(s256) = G_ATOMICRMW_NAND [[ADDR]](p0), [[VAL]] :: (load store seq_cst (s256) on %ir.addr)
2156-
; CHECK-NEXT: [[RES:%[0-9]+]]:_(s32) = G_TRUNC [[OLDVALRES]]
2157-
%oldval = atomicrmw nand ptr %addr, i256 1 seq_cst
2158-
; FIXME: We currently can't lower 'ret i256' and it's not the purpose of this
2159-
; test so work around it by truncating to i32 for now.
2160-
%oldval.trunc = trunc i256 %oldval to i32
2161-
ret i32 %oldval.trunc
2135+
; CHECK-NEXT: [[VAL:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
2136+
; CHECK-NEXT: [[NEG1:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1
2137+
; CHECK-NEXT: [[OLDVALSTART:%[0-9]+]]:_(s32) = G_LOAD [[ADDR]](p0) :: (load (s32) from %ir.addr)
2138+
; CHECK: bb.2.atomicrmw.start:
2139+
; CHECK-NEXT: successors: %bb.3({{[^)]+}}), %bb.2({{[^)]+}})
2140+
; CHECK: [[OLDVAL:%[0-9]+]]:_(s32) = G_PHI [[OLDVALSTART]](s32), %bb.1, [[OLDVALRES:%[0-9]+]](s32), %bb.2
2141+
; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[OLDVAL]], [[VAL]]
2142+
; CHECK-NEXT: [[NEWVAL:%[0-9]+]]:_(s32) = G_XOR [[AND]], [[NEG1]]
2143+
; CHECK: [[OLDVALRES]]:_(s32), [[SUCCESS:%[0-9]+]]:_(s1) = G_ATOMIC_CMPXCHG_WITH_SUCCESS [[ADDR]](p0), [[OLDVAL]], [[NEWVAL]] :: (load store seq_cst seq_cst (s32) on %ir.addr)
2144+
; CHECK-NEXT: G_BRCOND [[SUCCESS]](s1), %bb.3
2145+
; CHECK-NEXT: G_BR %bb.2
2146+
; CHECK: bb.3.atomicrmw.end:
2147+
%oldval = atomicrmw nand ptr %addr, i32 1 seq_cst
2148+
ret i32 %oldval
21622149
}
21632150

21642151
; Try an seq_cst atomicrmw or
2165-
; AArch64 will expand some atomicrmw's at the LLVM-IR level so we use a wide type to avoid this.
21662152
define i32 @test_atomicrmw_or(ptr %addr) {
21672153
; CHECK-LABEL: name: test_atomicrmw_or
21682154
; CHECK: bb.1 (%ir-block.{{[0-9]+}}):
21692155
; CHECK-NEXT: liveins: $x0
21702156
; CHECK: [[ADDR:%[0-9]+]]:_(p0) = COPY $x0
2171-
; CHECK-NEXT: [[VAL:%[0-9]+]]:_(s256) = G_CONSTANT i256 1
2172-
; CHECK-NEXT: [[OLDVALRES:%[0-9]+]]:_(s256) = G_ATOMICRMW_OR [[ADDR]](p0), [[VAL]] :: (load store seq_cst (s256) on %ir.addr)
2173-
; CHECK-NEXT: [[RES:%[0-9]+]]:_(s32) = G_TRUNC [[OLDVALRES]]
2174-
%oldval = atomicrmw or ptr %addr, i256 1 seq_cst
2175-
; FIXME: We currently can't lower 'ret i256' and it's not the purpose of this
2176-
; test so work around it by truncating to i32 for now.
2177-
%oldval.trunc = trunc i256 %oldval to i32
2178-
ret i32 %oldval.trunc
2157+
; CHECK-NEXT: [[VAL:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
2158+
; CHECK-NEXT: [[OLDVALRES:%[0-9]+]]:_(s32) = G_ATOMICRMW_OR [[ADDR]](p0), [[VAL]] :: (load store seq_cst (s32) on %ir.addr)
2159+
%oldval = atomicrmw or ptr %addr, i32 1 seq_cst
2160+
ret i32 %oldval
21792161
}
21802162

21812163
; Try an seq_cst atomicrmw xor
2182-
; AArch64 will expand some atomicrmw's at the LLVM-IR level so we use a wide type to avoid this.
21832164
define i32 @test_atomicrmw_xor(ptr %addr) {
21842165
; CHECK-LABEL: name: test_atomicrmw_xor
21852166
; CHECK: bb.1 (%ir-block.{{[0-9]+}}):
21862167
; CHECK-NEXT: liveins: $x0
21872168
; CHECK: [[ADDR:%[0-9]+]]:_(p0) = COPY $x0
2188-
; CHECK-NEXT: [[VAL:%[0-9]+]]:_(s256) = G_CONSTANT i256 1
2189-
; CHECK-NEXT: [[OLDVALRES:%[0-9]+]]:_(s256) = G_ATOMICRMW_XOR [[ADDR]](p0), [[VAL]] :: (load store seq_cst (s256) on %ir.addr)
2190-
; CHECK-NEXT: [[RES:%[0-9]+]]:_(s32) = G_TRUNC [[OLDVALRES]]
2191-
%oldval = atomicrmw xor ptr %addr, i256 1 seq_cst
2192-
; FIXME: We currently can't lower 'ret i256' and it's not the purpose of this
2193-
; test so work around it by truncating to i32 for now.
2194-
%oldval.trunc = trunc i256 %oldval to i32
2195-
ret i32 %oldval.trunc
2169+
; CHECK-NEXT: [[VAL:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
2170+
; CHECK-NEXT: [[OLDVALRES:%[0-9]+]]:_(s32) = G_ATOMICRMW_XOR [[ADDR]](p0), [[VAL]] :: (load store seq_cst (s32) on %ir.addr)
2171+
%oldval = atomicrmw xor ptr %addr, i32 1 seq_cst
2172+
ret i32 %oldval
21962173
}
21972174

21982175
; Try an seq_cst atomicrmw min
2199-
; AArch64 will expand some atomicrmw's at the LLVM-IR level so we use a wide type to avoid this.
22002176
define i32 @test_atomicrmw_min(ptr %addr) {
22012177
; CHECK-LABEL: name: test_atomicrmw_min
22022178
; CHECK: bb.1 (%ir-block.{{[0-9]+}}):
22032179
; CHECK-NEXT: liveins: $x0
22042180
; CHECK: [[ADDR:%[0-9]+]]:_(p0) = COPY $x0
2205-
; CHECK-NEXT: [[VAL:%[0-9]+]]:_(s256) = G_CONSTANT i256 1
2206-
; CHECK-NEXT: [[OLDVALRES:%[0-9]+]]:_(s256) = G_ATOMICRMW_MIN [[ADDR]](p0), [[VAL]] :: (load store seq_cst (s256) on %ir.addr)
2207-
; CHECK-NEXT: [[RES:%[0-9]+]]:_(s32) = G_TRUNC [[OLDVALRES]]
2208-
%oldval = atomicrmw min ptr %addr, i256 1 seq_cst
2209-
; FIXME: We currently can't lower 'ret i256' and it's not the purpose of this
2210-
; test so work around it by truncating to i32 for now.
2211-
%oldval.trunc = trunc i256 %oldval to i32
2212-
ret i32 %oldval.trunc
2181+
; CHECK-NEXT: [[VAL:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
2182+
; CHECK-NEXT: [[OLDVALRES:%[0-9]+]]:_(s32) = G_ATOMICRMW_MIN [[ADDR]](p0), [[VAL]] :: (load store seq_cst (s32) on %ir.addr)
2183+
%oldval = atomicrmw min ptr %addr, i32 1 seq_cst
2184+
ret i32 %oldval
22132185
}
22142186

22152187
; Try an seq_cst atomicrmw max
2216-
; AArch64 will expand some atomicrmw's at the LLVM-IR level so we use a wide type to avoid this.
22172188
define i32 @test_atomicrmw_max(ptr %addr) {
22182189
; CHECK-LABEL: name: test_atomicrmw_max
22192190
; CHECK: bb.1 (%ir-block.{{[0-9]+}}):
22202191
; CHECK-NEXT: liveins: $x0
22212192
; CHECK: [[ADDR:%[0-9]+]]:_(p0) = COPY $x0
2222-
; CHECK-NEXT: [[VAL:%[0-9]+]]:_(s256) = G_CONSTANT i256 1
2223-
; CHECK-NEXT: [[OLDVALRES:%[0-9]+]]:_(s256) = G_ATOMICRMW_MAX [[ADDR]](p0), [[VAL]] :: (load store seq_cst (s256) on %ir.addr)
2224-
; CHECK-NEXT: [[RES:%[0-9]+]]:_(s32) = G_TRUNC [[OLDVALRES]]
2225-
%oldval = atomicrmw max ptr %addr, i256 1 seq_cst
2226-
; FIXME: We currently can't lower 'ret i256' and it's not the purpose of this
2227-
; test so work around it by truncating to i32 for now.
2228-
%oldval.trunc = trunc i256 %oldval to i32
2229-
ret i32 %oldval.trunc
2193+
; CHECK-NEXT: [[VAL:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
2194+
; CHECK-NEXT: [[OLDVALRES:%[0-9]+]]:_(s32) = G_ATOMICRMW_MAX [[ADDR]](p0), [[VAL]] :: (load store seq_cst (s32) on %ir.addr)
2195+
%oldval = atomicrmw max ptr %addr, i32 1 seq_cst
2196+
ret i32 %oldval
22302197
}
22312198

22322199
; Try an seq_cst atomicrmw unsigned min
2233-
; AArch64 will expand some atomicrmw's at the LLVM-IR level so we use a wide type to avoid this.
22342200
define i32 @test_atomicrmw_umin(ptr %addr) {
22352201
; CHECK-LABEL: name: test_atomicrmw_umin
22362202
; CHECK: bb.1 (%ir-block.{{[0-9]+}}):
22372203
; CHECK-NEXT: liveins: $x0
22382204
; CHECK: [[ADDR:%[0-9]+]]:_(p0) = COPY $x0
2239-
; CHECK-NEXT: [[VAL:%[0-9]+]]:_(s256) = G_CONSTANT i256 1
2240-
; CHECK-NEXT: [[OLDVALRES:%[0-9]+]]:_(s256) = G_ATOMICRMW_UMIN [[ADDR]](p0), [[VAL]] :: (load store seq_cst (s256) on %ir.addr)
2241-
; CHECK-NEXT: [[RES:%[0-9]+]]:_(s32) = G_TRUNC [[OLDVALRES]]
2242-
%oldval = atomicrmw umin ptr %addr, i256 1 seq_cst
2243-
; FIXME: We currently can't lower 'ret i256' and it's not the purpose of this
2244-
; test so work around it by truncating to i32 for now.
2245-
%oldval.trunc = trunc i256 %oldval to i32
2246-
ret i32 %oldval.trunc
2205+
; CHECK-NEXT: [[VAL:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
2206+
; CHECK-NEXT: [[OLDVALRES:%[0-9]+]]:_(s32) = G_ATOMICRMW_UMIN [[ADDR]](p0), [[VAL]] :: (load store seq_cst (s32) on %ir.addr)
2207+
%oldval = atomicrmw umin ptr %addr, i32 1 seq_cst
2208+
ret i32 %oldval
22472209
}
22482210

22492211
; Try an seq_cst atomicrmw unsigned max
2250-
; AArch64 will expand some atomicrmw's at the LLVM-IR level so we use a wide type to avoid this.
22512212
define i32 @test_atomicrmw_umax(ptr %addr) {
22522213
; CHECK-LABEL: name: test_atomicrmw_umax
22532214
; CHECK: bb.1 (%ir-block.{{[0-9]+}}):
22542215
; CHECK-NEXT: liveins: $x0
22552216
; CHECK: [[ADDR:%[0-9]+]]:_(p0) = COPY $x0
2256-
; CHECK-NEXT: [[VAL:%[0-9]+]]:_(s256) = G_CONSTANT i256 1
2257-
; CHECK-NEXT: [[OLDVALRES:%[0-9]+]]:_(s256) = G_ATOMICRMW_UMAX [[ADDR]](p0), [[VAL]] :: (load store seq_cst (s256) on %ir.addr)
2258-
; CHECK-NEXT: [[RES:%[0-9]+]]:_(s32) = G_TRUNC [[OLDVALRES]]
2259-
%oldval = atomicrmw umax ptr %addr, i256 1 seq_cst
2260-
; FIXME: We currently can't lower 'ret i256' and it's not the purpose of this
2261-
; test so work around it by truncating to i32 for now.
2262-
%oldval.trunc = trunc i256 %oldval to i32
2263-
ret i32 %oldval.trunc
2217+
; CHECK-NEXT: [[VAL:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
2218+
; CHECK-NEXT: [[OLDVALRES:%[0-9]+]]:_(s32) = G_ATOMICRMW_UMAX [[ADDR]](p0), [[VAL]] :: (load store seq_cst (s32) on %ir.addr)
2219+
%oldval = atomicrmw umax ptr %addr, i32 1 seq_cst
2220+
ret i32 %oldval
22642221
}
22652222

22662223
@addr = global ptr null
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
; RUN: llc -march=aarch64 < %s | FileCheck %s
2+
3+
; Atomics larger than 128-bit are unsupported, and emit libcalls.
4+
define void @test(ptr %a) nounwind {
5+
; CHECK-LABEL: test:
6+
; CHECK: bl __atomic_load
7+
; CHECK: bl __atomic_store
8+
%1 = load atomic i256, ptr %a seq_cst, align 32
9+
store atomic i256 %1, ptr %a seq_cst, align 32
10+
ret void
11+
}

0 commit comments

Comments
 (0)