1; RUN: llc < %s -mtriple=arm64-linux-gnu | FileCheck %s
2
3%0 = type { i64, i64 }
4
5define i128 @f0(i8* %p) nounwind readonly {
6; CHECK-LABEL: f0:
7; CHECK: ldxp {{x[0-9]+}}, {{x[0-9]+}}, [x0]
8entry:
9  %ldrexd = tail call %0 @llvm.aarch64.ldxp(i8* %p)
10  %0 = extractvalue %0 %ldrexd, 1
11  %1 = extractvalue %0 %ldrexd, 0
12  %2 = zext i64 %0 to i128
13  %3 = zext i64 %1 to i128
14  %shl = shl nuw i128 %2, 64
15  %4 = or i128 %shl, %3
16  ret i128 %4
17}
18
19define i32 @f1(i8* %ptr, i128 %val) nounwind {
20; CHECK-LABEL: f1:
21; CHECK: stxp {{w[0-9]+}}, {{x[0-9]+}}, {{x[0-9]+}}, [x0]
22entry:
23  %tmp4 = trunc i128 %val to i64
24  %tmp6 = lshr i128 %val, 64
25  %tmp7 = trunc i128 %tmp6 to i64
26  %strexd = tail call i32 @llvm.aarch64.stxp(i64 %tmp4, i64 %tmp7, i8* %ptr)
27  ret i32 %strexd
28}
29
30declare %0 @llvm.aarch64.ldxp(i8*) nounwind
31declare i32 @llvm.aarch64.stxp(i64, i64, i8*) nounwind
32
33@var = global i64 0, align 8
34
35define void @test_load_i8(i8* %addr) {
36; CHECK-LABEL: test_load_i8:
37; CHECK: ldxrb w[[LOADVAL:[0-9]+]], [x0]
38; CHECK-NOT: uxtb
39; CHECK-NOT: and
40; CHECK: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var]
41
42  %val = call i64 @llvm.aarch64.ldxr.p0i8(i8* %addr)
43  %shortval = trunc i64 %val to i8
44  %extval = zext i8 %shortval to i64
45  store i64 %extval, i64* @var, align 8
46  ret void
47}
48
49define void @test_load_i16(i16* %addr) {
50; CHECK-LABEL: test_load_i16:
51; CHECK: ldxrh w[[LOADVAL:[0-9]+]], [x0]
52; CHECK-NOT: uxth
53; CHECK-NOT: and
54; CHECK: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var]
55
56  %val = call i64 @llvm.aarch64.ldxr.p0i16(i16* %addr)
57  %shortval = trunc i64 %val to i16
58  %extval = zext i16 %shortval to i64
59  store i64 %extval, i64* @var, align 8
60  ret void
61}
62
63define void @test_load_i32(i32* %addr) {
64; CHECK-LABEL: test_load_i32:
65; CHECK: ldxr w[[LOADVAL:[0-9]+]], [x0]
66; CHECK-NOT: uxtw
67; CHECK-NOT: and
68; CHECK: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var]
69
70  %val = call i64 @llvm.aarch64.ldxr.p0i32(i32* %addr)
71  %shortval = trunc i64 %val to i32
72  %extval = zext i32 %shortval to i64
73  store i64 %extval, i64* @var, align 8
74  ret void
75}
76
77define void @test_load_i64(i64* %addr) {
78; CHECK-LABEL: test_load_i64:
79; CHECK: ldxr x[[LOADVAL:[0-9]+]], [x0]
80; CHECK: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var]
81
82  %val = call i64 @llvm.aarch64.ldxr.p0i64(i64* %addr)
83  store i64 %val, i64* @var, align 8
84  ret void
85}
86
87
88declare i64 @llvm.aarch64.ldxr.p0i8(i8*) nounwind
89declare i64 @llvm.aarch64.ldxr.p0i16(i16*) nounwind
90declare i64 @llvm.aarch64.ldxr.p0i32(i32*) nounwind
91declare i64 @llvm.aarch64.ldxr.p0i64(i64*) nounwind
92
93define i32 @test_store_i8(i32, i8 %val, i8* %addr) {
94; CHECK-LABEL: test_store_i8:
95; CHECK-NOT: uxtb
96; CHECK-NOT: and
97; CHECK: stxrb w0, w1, [x2]
98  %extval = zext i8 %val to i64
99  %res = call i32 @llvm.aarch64.stxr.p0i8(i64 %extval, i8* %addr)
100  ret i32 %res
101}
102
103define i32 @test_store_i16(i32, i16 %val, i16* %addr) {
104; CHECK-LABEL: test_store_i16:
105; CHECK-NOT: uxth
106; CHECK-NOT: and
107; CHECK: stxrh w0, w1, [x2]
108  %extval = zext i16 %val to i64
109  %res = call i32 @llvm.aarch64.stxr.p0i16(i64 %extval, i16* %addr)
110  ret i32 %res
111}
112
113define i32 @test_store_i32(i32, i32 %val, i32* %addr) {
114; CHECK-LABEL: test_store_i32:
115; CHECK-NOT: uxtw
116; CHECK-NOT: and
117; CHECK: stxr w0, w1, [x2]
118  %extval = zext i32 %val to i64
119  %res = call i32 @llvm.aarch64.stxr.p0i32(i64 %extval, i32* %addr)
120  ret i32 %res
121}
122
123define i32 @test_store_i64(i32, i64 %val, i64* %addr) {
124; CHECK-LABEL: test_store_i64:
125; CHECK: stxr w0, x1, [x2]
126  %res = call i32 @llvm.aarch64.stxr.p0i64(i64 %val, i64* %addr)
127  ret i32 %res
128}
129
130declare i32 @llvm.aarch64.stxr.p0i8(i64, i8*) nounwind
131declare i32 @llvm.aarch64.stxr.p0i16(i64, i16*) nounwind
132declare i32 @llvm.aarch64.stxr.p0i32(i64, i32*) nounwind
133declare i32 @llvm.aarch64.stxr.p0i64(i64, i64*) nounwind
134
135; CHECK: test_clear:
136; CHECK: clrex
137define void @test_clear() {
138  call void @llvm.aarch64.clrex()
139  ret void
140}
141
142declare void @llvm.aarch64.clrex() nounwind
143
144define i128 @test_load_acquire_i128(i8* %p) nounwind readonly {
145; CHECK-LABEL: test_load_acquire_i128:
146; CHECK: ldaxp {{x[0-9]+}}, {{x[0-9]+}}, [x0]
147entry:
148  %ldrexd = tail call %0 @llvm.aarch64.ldaxp(i8* %p)
149  %0 = extractvalue %0 %ldrexd, 1
150  %1 = extractvalue %0 %ldrexd, 0
151  %2 = zext i64 %0 to i128
152  %3 = zext i64 %1 to i128
153  %shl = shl nuw i128 %2, 64
154  %4 = or i128 %shl, %3
155  ret i128 %4
156}
157
158define i32 @test_store_release_i128(i8* %ptr, i128 %val) nounwind {
159; CHECK-LABEL: test_store_release_i128:
160; CHECK: stlxp {{w[0-9]+}}, {{x[0-9]+}}, {{x[0-9]+}}, [x0]
161entry:
162  %tmp4 = trunc i128 %val to i64
163  %tmp6 = lshr i128 %val, 64
164  %tmp7 = trunc i128 %tmp6 to i64
165  %strexd = tail call i32 @llvm.aarch64.stlxp(i64 %tmp4, i64 %tmp7, i8* %ptr)
166  ret i32 %strexd
167}
168
169declare %0 @llvm.aarch64.ldaxp(i8*) nounwind
170declare i32 @llvm.aarch64.stlxp(i64, i64, i8*) nounwind
171
172define void @test_load_acquire_i8(i8* %addr) {
173; CHECK-LABEL: test_load_acquire_i8:
174; CHECK: ldaxrb w[[LOADVAL:[0-9]+]], [x0]
175; CHECK-NOT: uxtb
176; CHECK-NOT: and
177; CHECK: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var]
178
179  %val = call i64 @llvm.aarch64.ldaxr.p0i8(i8* %addr)
180  %shortval = trunc i64 %val to i8
181  %extval = zext i8 %shortval to i64
182  store i64 %extval, i64* @var, align 8
183  ret void
184}
185
186define void @test_load_acquire_i16(i16* %addr) {
187; CHECK-LABEL: test_load_acquire_i16:
188; CHECK: ldaxrh w[[LOADVAL:[0-9]+]], [x0]
189; CHECK-NOT: uxth
190; CHECK-NOT: and
191; CHECK: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var]
192
193  %val = call i64 @llvm.aarch64.ldaxr.p0i16(i16* %addr)
194  %shortval = trunc i64 %val to i16
195  %extval = zext i16 %shortval to i64
196  store i64 %extval, i64* @var, align 8
197  ret void
198}
199
200define void @test_load_acquire_i32(i32* %addr) {
201; CHECK-LABEL: test_load_acquire_i32:
202; CHECK: ldaxr w[[LOADVAL:[0-9]+]], [x0]
203; CHECK-NOT: uxtw
204; CHECK-NOT: and
205; CHECK: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var]
206
207  %val = call i64 @llvm.aarch64.ldaxr.p0i32(i32* %addr)
208  %shortval = trunc i64 %val to i32
209  %extval = zext i32 %shortval to i64
210  store i64 %extval, i64* @var, align 8
211  ret void
212}
213
214define void @test_load_acquire_i64(i64* %addr) {
215; CHECK-LABEL: test_load_acquire_i64:
216; CHECK: ldaxr x[[LOADVAL:[0-9]+]], [x0]
217; CHECK: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var]
218
219  %val = call i64 @llvm.aarch64.ldaxr.p0i64(i64* %addr)
220  store i64 %val, i64* @var, align 8
221  ret void
222}
223
224
225declare i64 @llvm.aarch64.ldaxr.p0i8(i8*) nounwind
226declare i64 @llvm.aarch64.ldaxr.p0i16(i16*) nounwind
227declare i64 @llvm.aarch64.ldaxr.p0i32(i32*) nounwind
228declare i64 @llvm.aarch64.ldaxr.p0i64(i64*) nounwind
229
230define i32 @test_store_release_i8(i32, i8 %val, i8* %addr) {
231; CHECK-LABEL: test_store_release_i8:
232; CHECK-NOT: uxtb
233; CHECK-NOT: and
234; CHECK: stlxrb w0, w1, [x2]
235  %extval = zext i8 %val to i64
236  %res = call i32 @llvm.aarch64.stlxr.p0i8(i64 %extval, i8* %addr)
237  ret i32 %res
238}
239
240define i32 @test_store_release_i16(i32, i16 %val, i16* %addr) {
241; CHECK-LABEL: test_store_release_i16:
242; CHECK-NOT: uxth
243; CHECK-NOT: and
244; CHECK: stlxrh w0, w1, [x2]
245  %extval = zext i16 %val to i64
246  %res = call i32 @llvm.aarch64.stlxr.p0i16(i64 %extval, i16* %addr)
247  ret i32 %res
248}
249
250define i32 @test_store_release_i32(i32, i32 %val, i32* %addr) {
251; CHECK-LABEL: test_store_release_i32:
252; CHECK-NOT: uxtw
253; CHECK-NOT: and
254; CHECK: stlxr w0, w1, [x2]
255  %extval = zext i32 %val to i64
256  %res = call i32 @llvm.aarch64.stlxr.p0i32(i64 %extval, i32* %addr)
257  ret i32 %res
258}
259
260define i32 @test_store_release_i64(i32, i64 %val, i64* %addr) {
261; CHECK-LABEL: test_store_release_i64:
262; CHECK: stlxr w0, x1, [x2]
263  %res = call i32 @llvm.aarch64.stlxr.p0i64(i64 %val, i64* %addr)
264  ret i32 %res
265}
266
267declare i32 @llvm.aarch64.stlxr.p0i8(i64, i8*) nounwind
268declare i32 @llvm.aarch64.stlxr.p0i16(i64, i16*) nounwind
269declare i32 @llvm.aarch64.stlxr.p0i32(i64, i32*) nounwind
270declare i32 @llvm.aarch64.stlxr.p0i64(i64, i64*) nounwind
271