xref: /llvm-project/llvm/test/Transforms/AtomicExpand/SPARC/partword.ll (revision 31af5e9001508dd2e58d2232e900adba01896736)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -S %s -passes=atomic-expand | FileCheck %s
3
4;; Verify the cmpxchg and atomicrmw expansions where sub-word-size
5;; instructions are not available.
6
7;;; NOTE: this test is mostly target-independent -- any target which
8;;; doesn't support cmpxchg of sub-word sizes would do.
9target datalayout = "E-m:e-i64:64-n32:64-S128"
10target triple = "sparcv9-unknown-unknown"
11
12define i8 @test_cmpxchg_i8(ptr %arg, i8 %old, i8 %new) {
13; CHECK-LABEL: @test_cmpxchg_i8(
14; CHECK-NEXT:  entry:
15; CHECK-NEXT:    fence seq_cst
16; CHECK-NEXT:    [[ALIGNEDADDR:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[ARG:%.*]], i64 -4)
17; CHECK-NEXT:    [[TMP0:%.*]] = ptrtoint ptr [[ARG]] to i64
18; CHECK-NEXT:    [[PTRLSB:%.*]] = and i64 [[TMP0]], 3
19; CHECK-NEXT:    [[TMP1:%.*]] = xor i64 [[PTRLSB]], 3
20; CHECK-NEXT:    [[TMP2:%.*]] = shl i64 [[TMP1]], 3
21; CHECK-NEXT:    [[SHIFTAMT:%.*]] = trunc i64 [[TMP2]] to i32
22; CHECK-NEXT:    [[MASK:%.*]] = shl i32 255, [[SHIFTAMT]]
23; CHECK-NEXT:    [[INV_MASK:%.*]] = xor i32 [[MASK]], -1
24; CHECK-NEXT:    [[TMP3:%.*]] = zext i8 [[NEW:%.*]] to i32
25; CHECK-NEXT:    [[TMP4:%.*]] = shl i32 [[TMP3]], [[SHIFTAMT]]
26; CHECK-NEXT:    [[TMP5:%.*]] = zext i8 [[OLD:%.*]] to i32
27; CHECK-NEXT:    [[TMP6:%.*]] = shl i32 [[TMP5]], [[SHIFTAMT]]
28; CHECK-NEXT:    [[TMP7:%.*]] = load i32, ptr [[ALIGNEDADDR]], align 4
29; CHECK-NEXT:    [[TMP8:%.*]] = and i32 [[TMP7]], [[INV_MASK]]
30; CHECK-NEXT:    br label [[PARTWORD_CMPXCHG_LOOP:%.*]]
31; CHECK:       partword.cmpxchg.loop:
32; CHECK-NEXT:    [[TMP9:%.*]] = phi i32 [ [[TMP8]], [[ENTRY:%.*]] ], [ [[TMP15:%.*]], [[PARTWORD_CMPXCHG_FAILURE:%.*]] ]
33; CHECK-NEXT:    [[TMP10:%.*]] = or i32 [[TMP9]], [[TMP4]]
34; CHECK-NEXT:    [[TMP11:%.*]] = or i32 [[TMP9]], [[TMP6]]
35; CHECK-NEXT:    [[TMP12:%.*]] = cmpxchg ptr [[ALIGNEDADDR]], i32 [[TMP11]], i32 [[TMP10]] monotonic monotonic, align 4
36; CHECK-NEXT:    [[TMP13:%.*]] = extractvalue { i32, i1 } [[TMP12]], 0
37; CHECK-NEXT:    [[TMP14:%.*]] = extractvalue { i32, i1 } [[TMP12]], 1
38; CHECK-NEXT:    br i1 [[TMP14]], label [[PARTWORD_CMPXCHG_END:%.*]], label [[PARTWORD_CMPXCHG_FAILURE]]
39; CHECK:       partword.cmpxchg.failure:
40; CHECK-NEXT:    [[TMP15]] = and i32 [[TMP13]], [[INV_MASK]]
41; CHECK-NEXT:    [[TMP16:%.*]] = icmp ne i32 [[TMP9]], [[TMP15]]
42; CHECK-NEXT:    br i1 [[TMP16]], label [[PARTWORD_CMPXCHG_LOOP]], label [[PARTWORD_CMPXCHG_END]]
43; CHECK:       partword.cmpxchg.end:
44; CHECK-NEXT:    [[SHIFTED:%.*]] = lshr i32 [[TMP13]], [[SHIFTAMT]]
45; CHECK-NEXT:    [[EXTRACTED:%.*]] = trunc i32 [[SHIFTED]] to i8
46; CHECK-NEXT:    [[TMP17:%.*]] = insertvalue { i8, i1 } poison, i8 [[EXTRACTED]], 0
47; CHECK-NEXT:    [[TMP18:%.*]] = insertvalue { i8, i1 } [[TMP17]], i1 [[TMP14]], 1
48; CHECK-NEXT:    fence seq_cst
49; CHECK-NEXT:    [[RET:%.*]] = extractvalue { i8, i1 } [[TMP18]], 0
50; CHECK-NEXT:    ret i8 [[RET]]
51;
52entry:
53  %ret_succ = cmpxchg ptr %arg, i8 %old, i8 %new seq_cst monotonic
54  %ret = extractvalue { i8, i1 } %ret_succ, 0
55  ret i8 %ret
56}
57
58define i16 @test_cmpxchg_i16(ptr %arg, i16 %old, i16 %new) {
59; CHECK-LABEL: @test_cmpxchg_i16(
60; CHECK-NEXT:  entry:
61; CHECK-NEXT:    fence seq_cst
62; CHECK-NEXT:    [[ALIGNEDADDR:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[ARG:%.*]], i64 -4)
63; CHECK-NEXT:    [[TMP0:%.*]] = ptrtoint ptr [[ARG]] to i64
64; CHECK-NEXT:    [[PTRLSB:%.*]] = and i64 [[TMP0]], 3
65; CHECK-NEXT:    [[TMP1:%.*]] = xor i64 [[PTRLSB]], 2
66; CHECK-NEXT:    [[TMP2:%.*]] = shl i64 [[TMP1]], 3
67; CHECK-NEXT:    [[SHIFTAMT:%.*]] = trunc i64 [[TMP2]] to i32
68; CHECK-NEXT:    [[MASK:%.*]] = shl i32 65535, [[SHIFTAMT]]
69; CHECK-NEXT:    [[INV_MASK:%.*]] = xor i32 [[MASK]], -1
70; CHECK-NEXT:    [[TMP3:%.*]] = zext i16 [[NEW:%.*]] to i32
71; CHECK-NEXT:    [[TMP4:%.*]] = shl i32 [[TMP3]], [[SHIFTAMT]]
72; CHECK-NEXT:    [[TMP5:%.*]] = zext i16 [[OLD:%.*]] to i32
73; CHECK-NEXT:    [[TMP6:%.*]] = shl i32 [[TMP5]], [[SHIFTAMT]]
74; CHECK-NEXT:    [[TMP7:%.*]] = load i32, ptr [[ALIGNEDADDR]], align 4
75; CHECK-NEXT:    [[TMP8:%.*]] = and i32 [[TMP7]], [[INV_MASK]]
76; CHECK-NEXT:    br label [[PARTWORD_CMPXCHG_LOOP:%.*]]
77; CHECK:       partword.cmpxchg.loop:
78; CHECK-NEXT:    [[TMP9:%.*]] = phi i32 [ [[TMP8]], [[ENTRY:%.*]] ], [ [[TMP15:%.*]], [[PARTWORD_CMPXCHG_FAILURE:%.*]] ]
79; CHECK-NEXT:    [[TMP10:%.*]] = or i32 [[TMP9]], [[TMP4]]
80; CHECK-NEXT:    [[TMP11:%.*]] = or i32 [[TMP9]], [[TMP6]]
81; CHECK-NEXT:    [[TMP12:%.*]] = cmpxchg ptr [[ALIGNEDADDR]], i32 [[TMP11]], i32 [[TMP10]] monotonic monotonic, align 4
82; CHECK-NEXT:    [[TMP13:%.*]] = extractvalue { i32, i1 } [[TMP12]], 0
83; CHECK-NEXT:    [[TMP14:%.*]] = extractvalue { i32, i1 } [[TMP12]], 1
84; CHECK-NEXT:    br i1 [[TMP14]], label [[PARTWORD_CMPXCHG_END:%.*]], label [[PARTWORD_CMPXCHG_FAILURE]]
85; CHECK:       partword.cmpxchg.failure:
86; CHECK-NEXT:    [[TMP15]] = and i32 [[TMP13]], [[INV_MASK]]
87; CHECK-NEXT:    [[TMP16:%.*]] = icmp ne i32 [[TMP9]], [[TMP15]]
88; CHECK-NEXT:    br i1 [[TMP16]], label [[PARTWORD_CMPXCHG_LOOP]], label [[PARTWORD_CMPXCHG_END]]
89; CHECK:       partword.cmpxchg.end:
90; CHECK-NEXT:    [[SHIFTED:%.*]] = lshr i32 [[TMP13]], [[SHIFTAMT]]
91; CHECK-NEXT:    [[EXTRACTED:%.*]] = trunc i32 [[SHIFTED]] to i16
92; CHECK-NEXT:    [[TMP17:%.*]] = insertvalue { i16, i1 } poison, i16 [[EXTRACTED]], 0
93; CHECK-NEXT:    [[TMP18:%.*]] = insertvalue { i16, i1 } [[TMP17]], i1 [[TMP14]], 1
94; CHECK-NEXT:    fence seq_cst
95; CHECK-NEXT:    [[RET:%.*]] = extractvalue { i16, i1 } [[TMP18]], 0
96; CHECK-NEXT:    ret i16 [[RET]]
97;
98entry:
99  %ret_succ = cmpxchg ptr %arg, i16 %old, i16 %new seq_cst monotonic
100  %ret = extractvalue { i16, i1 } %ret_succ, 0
101  ret i16 %ret
102}
103
104define i16 @test_add_i16(ptr %arg, i16 %val) {
105; CHECK-LABEL: @test_add_i16(
106; CHECK-NEXT:  entry:
107; CHECK-NEXT:    fence seq_cst
108; CHECK-NEXT:    [[ALIGNEDADDR:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[ARG:%.*]], i64 -4)
109; CHECK-NEXT:    [[TMP0:%.*]] = ptrtoint ptr [[ARG]] to i64
110; CHECK-NEXT:    [[PTRLSB:%.*]] = and i64 [[TMP0]], 3
111; CHECK-NEXT:    [[TMP1:%.*]] = xor i64 [[PTRLSB]], 2
112; CHECK-NEXT:    [[TMP2:%.*]] = shl i64 [[TMP1]], 3
113; CHECK-NEXT:    [[SHIFTAMT:%.*]] = trunc i64 [[TMP2]] to i32
114; CHECK-NEXT:    [[MASK:%.*]] = shl i32 65535, [[SHIFTAMT]]
115; CHECK-NEXT:    [[INV_MASK:%.*]] = xor i32 [[MASK]], -1
116; CHECK-NEXT:    [[TMP3:%.*]] = zext i16 [[VAL:%.*]] to i32
117; CHECK-NEXT:    [[VALOPERAND_SHIFTED:%.*]] = shl i32 [[TMP3]], [[SHIFTAMT]]
118; CHECK-NEXT:    [[TMP4:%.*]] = load i32, ptr [[ALIGNEDADDR]], align 4
119; CHECK-NEXT:    br label [[ATOMICRMW_START:%.*]]
120; CHECK:       atomicrmw.start:
121; CHECK-NEXT:    [[LOADED:%.*]] = phi i32 [ [[TMP4]], [[ENTRY:%.*]] ], [ [[NEWLOADED:%.*]], [[ATOMICRMW_START]] ]
122; CHECK-NEXT:    [[NEW:%.*]] = add i32 [[LOADED]], [[VALOPERAND_SHIFTED]]
123; CHECK-NEXT:    [[TMP5:%.*]] = and i32 [[NEW]], [[MASK]]
124; CHECK-NEXT:    [[TMP6:%.*]] = and i32 [[LOADED]], [[INV_MASK]]
125; CHECK-NEXT:    [[TMP7:%.*]] = or i32 [[TMP6]], [[TMP5]]
126; CHECK-NEXT:    [[TMP8:%.*]] = cmpxchg ptr [[ALIGNEDADDR]], i32 [[LOADED]], i32 [[TMP7]] monotonic monotonic, align 4
127; CHECK-NEXT:    [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP8]], 1
128; CHECK-NEXT:    [[NEWLOADED]] = extractvalue { i32, i1 } [[TMP8]], 0
129; CHECK-NEXT:    br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]]
130; CHECK:       atomicrmw.end:
131; CHECK-NEXT:    [[SHIFTED:%.*]] = lshr i32 [[NEWLOADED]], [[SHIFTAMT]]
132; CHECK-NEXT:    [[EXTRACTED:%.*]] = trunc i32 [[SHIFTED]] to i16
133; CHECK-NEXT:    fence seq_cst
134; CHECK-NEXT:    ret i16 [[EXTRACTED]]
135;
136entry:
137  %ret = atomicrmw add ptr %arg, i16 %val seq_cst
138  ret i16 %ret
139}
140
141define i16 @test_xor_i16(ptr %arg, i16 %val) {
142; CHECK-LABEL: @test_xor_i16(
143; CHECK-NEXT:  entry:
144; CHECK-NEXT:    fence seq_cst
145; CHECK-NEXT:    [[ALIGNEDADDR:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[ARG:%.*]], i64 -4)
146; CHECK-NEXT:    [[TMP0:%.*]] = ptrtoint ptr [[ARG]] to i64
147; CHECK-NEXT:    [[PTRLSB:%.*]] = and i64 [[TMP0]], 3
148; CHECK-NEXT:    [[TMP1:%.*]] = xor i64 [[PTRLSB]], 2
149; CHECK-NEXT:    [[TMP2:%.*]] = shl i64 [[TMP1]], 3
150; CHECK-NEXT:    [[SHIFTAMT:%.*]] = trunc i64 [[TMP2]] to i32
151; CHECK-NEXT:    [[MASK:%.*]] = shl i32 65535, [[SHIFTAMT]]
152; CHECK-NEXT:    [[INV_MASK:%.*]] = xor i32 [[MASK]], -1
153; CHECK-NEXT:    [[TMP3:%.*]] = zext i16 [[VAL:%.*]] to i32
154; CHECK-NEXT:    [[VALOPERAND_SHIFTED:%.*]] = shl i32 [[TMP3]], [[SHIFTAMT]]
155; CHECK-NEXT:    [[TMP4:%.*]] = load i32, ptr [[ALIGNEDADDR]], align 4
156; CHECK-NEXT:    br label [[ATOMICRMW_START:%.*]]
157; CHECK:       atomicrmw.start:
158; CHECK-NEXT:    [[LOADED:%.*]] = phi i32 [ [[TMP4]], [[ENTRY:%.*]] ], [ [[NEWLOADED:%.*]], [[ATOMICRMW_START]] ]
159; CHECK-NEXT:    [[NEW:%.*]] = xor i32 [[LOADED]], [[VALOPERAND_SHIFTED]]
160; CHECK-NEXT:    [[TMP5:%.*]] = cmpxchg ptr [[ALIGNEDADDR]], i32 [[LOADED]], i32 [[NEW]] monotonic monotonic, align 4
161; CHECK-NEXT:    [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1
162; CHECK-NEXT:    [[NEWLOADED]] = extractvalue { i32, i1 } [[TMP5]], 0
163; CHECK-NEXT:    br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]]
164; CHECK:       atomicrmw.end:
165; CHECK-NEXT:    [[SHIFTED:%.*]] = lshr i32 [[NEWLOADED]], [[SHIFTAMT]]
166; CHECK-NEXT:    [[EXTRACTED:%.*]] = trunc i32 [[SHIFTED]] to i16
167; CHECK-NEXT:    fence seq_cst
168; CHECK-NEXT:    ret i16 [[EXTRACTED]]
169;
170entry:
171  %ret = atomicrmw xor ptr %arg, i16 %val seq_cst
172  ret i16 %ret
173}
174
175define i16 @test_or_i16(ptr %arg, i16 %val) {
176; CHECK-LABEL: @test_or_i16(
177; CHECK-NEXT:  entry:
178; CHECK-NEXT:    fence seq_cst
179; CHECK-NEXT:    [[ALIGNEDADDR:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[ARG:%.*]], i64 -4)
180; CHECK-NEXT:    [[TMP0:%.*]] = ptrtoint ptr [[ARG]] to i64
181; CHECK-NEXT:    [[PTRLSB:%.*]] = and i64 [[TMP0]], 3
182; CHECK-NEXT:    [[TMP1:%.*]] = xor i64 [[PTRLSB]], 2
183; CHECK-NEXT:    [[TMP2:%.*]] = shl i64 [[TMP1]], 3
184; CHECK-NEXT:    [[SHIFTAMT:%.*]] = trunc i64 [[TMP2]] to i32
185; CHECK-NEXT:    [[MASK:%.*]] = shl i32 65535, [[SHIFTAMT]]
186; CHECK-NEXT:    [[INV_MASK:%.*]] = xor i32 [[MASK]], -1
187; CHECK-NEXT:    [[TMP3:%.*]] = zext i16 [[VAL:%.*]] to i32
188; CHECK-NEXT:    [[VALOPERAND_SHIFTED:%.*]] = shl i32 [[TMP3]], [[SHIFTAMT]]
189; CHECK-NEXT:    [[TMP4:%.*]] = load i32, ptr [[ALIGNEDADDR]], align 4
190; CHECK-NEXT:    br label [[ATOMICRMW_START:%.*]]
191; CHECK:       atomicrmw.start:
192; CHECK-NEXT:    [[LOADED:%.*]] = phi i32 [ [[TMP4]], [[ENTRY:%.*]] ], [ [[NEWLOADED:%.*]], [[ATOMICRMW_START]] ]
193; CHECK-NEXT:    [[NEW:%.*]] = or i32 [[LOADED]], [[VALOPERAND_SHIFTED]]
194; CHECK-NEXT:    [[TMP5:%.*]] = cmpxchg ptr [[ALIGNEDADDR]], i32 [[LOADED]], i32 [[NEW]] monotonic monotonic, align 4
195; CHECK-NEXT:    [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1
196; CHECK-NEXT:    [[NEWLOADED]] = extractvalue { i32, i1 } [[TMP5]], 0
197; CHECK-NEXT:    br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]]
198; CHECK:       atomicrmw.end:
199; CHECK-NEXT:    [[SHIFTED:%.*]] = lshr i32 [[NEWLOADED]], [[SHIFTAMT]]
200; CHECK-NEXT:    [[EXTRACTED:%.*]] = trunc i32 [[SHIFTED]] to i16
201; CHECK-NEXT:    fence seq_cst
202; CHECK-NEXT:    ret i16 [[EXTRACTED]]
203;
204entry:
205  %ret = atomicrmw or ptr %arg, i16 %val seq_cst
206  ret i16 %ret
207}
208
209define i16 @test_and_i16(ptr %arg, i16 %val) {
210; CHECK-LABEL: @test_and_i16(
211; CHECK-NEXT:  entry:
212; CHECK-NEXT:    fence seq_cst
213; CHECK-NEXT:    [[ALIGNEDADDR:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[ARG:%.*]], i64 -4)
214; CHECK-NEXT:    [[TMP0:%.*]] = ptrtoint ptr [[ARG]] to i64
215; CHECK-NEXT:    [[PTRLSB:%.*]] = and i64 [[TMP0]], 3
216; CHECK-NEXT:    [[TMP1:%.*]] = xor i64 [[PTRLSB]], 2
217; CHECK-NEXT:    [[TMP2:%.*]] = shl i64 [[TMP1]], 3
218; CHECK-NEXT:    [[SHIFTAMT:%.*]] = trunc i64 [[TMP2]] to i32
219; CHECK-NEXT:    [[MASK:%.*]] = shl i32 65535, [[SHIFTAMT]]
220; CHECK-NEXT:    [[INV_MASK:%.*]] = xor i32 [[MASK]], -1
221; CHECK-NEXT:    [[TMP3:%.*]] = zext i16 [[VAL:%.*]] to i32
222; CHECK-NEXT:    [[VALOPERAND_SHIFTED:%.*]] = shl i32 [[TMP3]], [[SHIFTAMT]]
223; CHECK-NEXT:    [[ANDOPERAND:%.*]] = or i32 [[VALOPERAND_SHIFTED]], [[INV_MASK]]
224; CHECK-NEXT:    [[TMP4:%.*]] = load i32, ptr [[ALIGNEDADDR]], align 4
225; CHECK-NEXT:    br label [[ATOMICRMW_START:%.*]]
226; CHECK:       atomicrmw.start:
227; CHECK-NEXT:    [[LOADED:%.*]] = phi i32 [ [[TMP4]], [[ENTRY:%.*]] ], [ [[NEWLOADED:%.*]], [[ATOMICRMW_START]] ]
228; CHECK-NEXT:    [[NEW:%.*]] = and i32 [[LOADED]], [[ANDOPERAND]]
229; CHECK-NEXT:    [[TMP5:%.*]] = cmpxchg ptr [[ALIGNEDADDR]], i32 [[LOADED]], i32 [[NEW]] monotonic monotonic, align 4
230; CHECK-NEXT:    [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1
231; CHECK-NEXT:    [[NEWLOADED]] = extractvalue { i32, i1 } [[TMP5]], 0
232; CHECK-NEXT:    br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]]
233; CHECK:       atomicrmw.end:
234; CHECK-NEXT:    [[SHIFTED:%.*]] = lshr i32 [[NEWLOADED]], [[SHIFTAMT]]
235; CHECK-NEXT:    [[EXTRACTED:%.*]] = trunc i32 [[SHIFTED]] to i16
236; CHECK-NEXT:    fence seq_cst
237; CHECK-NEXT:    ret i16 [[EXTRACTED]]
238;
239entry:
240  %ret = atomicrmw and ptr %arg, i16 %val seq_cst
241  ret i16 %ret
242}
243
244define i16 @test_min_i16(ptr %arg, i16 %val) {
245; CHECK-LABEL: @test_min_i16(
246; CHECK-NEXT:  entry:
247; CHECK-NEXT:    fence seq_cst
248; CHECK-NEXT:    [[ALIGNEDADDR:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[ARG:%.*]], i64 -4)
249; CHECK-NEXT:    [[TMP0:%.*]] = ptrtoint ptr [[ARG]] to i64
250; CHECK-NEXT:    [[PTRLSB:%.*]] = and i64 [[TMP0]], 3
251; CHECK-NEXT:    [[TMP1:%.*]] = xor i64 [[PTRLSB]], 2
252; CHECK-NEXT:    [[TMP2:%.*]] = shl i64 [[TMP1]], 3
253; CHECK-NEXT:    [[SHIFTAMT:%.*]] = trunc i64 [[TMP2]] to i32
254; CHECK-NEXT:    [[MASK:%.*]] = shl i32 65535, [[SHIFTAMT]]
255; CHECK-NEXT:    [[INV_MASK:%.*]] = xor i32 [[MASK]], -1
256; CHECK-NEXT:    [[TMP3:%.*]] = load i32, ptr [[ALIGNEDADDR]], align 4
257; CHECK-NEXT:    br label [[ATOMICRMW_START:%.*]]
258; CHECK:       atomicrmw.start:
259; CHECK-NEXT:    [[LOADED:%.*]] = phi i32 [ [[TMP3]], [[ENTRY:%.*]] ], [ [[NEWLOADED:%.*]], [[ATOMICRMW_START]] ]
260; CHECK-NEXT:    [[SHIFTED:%.*]] = lshr i32 [[LOADED]], [[SHIFTAMT]]
261; CHECK-NEXT:    [[EXTRACTED:%.*]] = trunc i32 [[SHIFTED]] to i16
262; CHECK-NEXT:    [[TMP4:%.*]] = icmp sle i16 [[EXTRACTED]], [[VAL:%.*]]
263; CHECK-NEXT:    [[NEW:%.*]] = select i1 [[TMP4]], i16 [[EXTRACTED]], i16 [[VAL]]
264; CHECK-NEXT:    [[EXTENDED:%.*]] = zext i16 [[NEW]] to i32
265; CHECK-NEXT:    [[SHIFTED1:%.*]] = shl nuw i32 [[EXTENDED]], [[SHIFTAMT]]
266; CHECK-NEXT:    [[UNMASKED:%.*]] = and i32 [[LOADED]], [[INV_MASK]]
267; CHECK-NEXT:    [[INSERTED:%.*]] = or i32 [[UNMASKED]], [[SHIFTED1]]
268; CHECK-NEXT:    [[TMP5:%.*]] = cmpxchg ptr [[ALIGNEDADDR]], i32 [[LOADED]], i32 [[INSERTED]] monotonic monotonic, align 4
269; CHECK-NEXT:    [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1
270; CHECK-NEXT:    [[NEWLOADED]] = extractvalue { i32, i1 } [[TMP5]], 0
271; CHECK-NEXT:    br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]]
272; CHECK:       atomicrmw.end:
273; CHECK-NEXT:    [[SHIFTED2:%.*]] = lshr i32 [[NEWLOADED]], [[SHIFTAMT]]
274; CHECK-NEXT:    [[EXTRACTED3:%.*]] = trunc i32 [[SHIFTED2]] to i16
275; CHECK-NEXT:    fence seq_cst
276; CHECK-NEXT:    ret i16 [[EXTRACTED3]]
277;
278entry:
279  %ret = atomicrmw min ptr %arg, i16 %val seq_cst
280  ret i16 %ret
281}
282
283define half @test_atomicrmw_fadd_f16(ptr %ptr, half %value) {
284; CHECK-LABEL: @test_atomicrmw_fadd_f16(
285; CHECK-NEXT:    fence seq_cst
286; CHECK-NEXT:    [[ALIGNEDADDR:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[PTR:%.*]], i64 -4)
287; CHECK-NEXT:    [[TMP1:%.*]] = ptrtoint ptr [[PTR]] to i64
288; CHECK-NEXT:    [[PTRLSB:%.*]] = and i64 [[TMP1]], 3
289; CHECK-NEXT:    [[TMP2:%.*]] = xor i64 [[PTRLSB]], 2
290; CHECK-NEXT:    [[TMP3:%.*]] = shl i64 [[TMP2]], 3
291; CHECK-NEXT:    [[SHIFTAMT:%.*]] = trunc i64 [[TMP3]] to i32
292; CHECK-NEXT:    [[MASK:%.*]] = shl i32 65535, [[SHIFTAMT]]
293; CHECK-NEXT:    [[INV_MASK:%.*]] = xor i32 [[MASK]], -1
294; CHECK-NEXT:    [[TMP4:%.*]] = load i32, ptr [[ALIGNEDADDR]], align 4
295; CHECK-NEXT:    br label [[ATOMICRMW_START:%.*]]
296; CHECK:       atomicrmw.start:
297; CHECK-NEXT:    [[LOADED:%.*]] = phi i32 [ [[TMP4]], [[TMP0:%.*]] ], [ [[NEWLOADED:%.*]], [[ATOMICRMW_START]] ]
298; CHECK-NEXT:    [[SHIFTED:%.*]] = lshr i32 [[LOADED]], [[SHIFTAMT]]
299; CHECK-NEXT:    [[EXTRACTED:%.*]] = trunc i32 [[SHIFTED]] to i16
300; CHECK-NEXT:    [[TMP5:%.*]] = bitcast i16 [[EXTRACTED]] to half
301; CHECK-NEXT:    [[NEW:%.*]] = fadd half [[TMP5]], [[VALUE:%.*]]
302; CHECK-NEXT:    [[TMP6:%.*]] = bitcast half [[NEW]] to i16
303; CHECK-NEXT:    [[EXTENDED:%.*]] = zext i16 [[TMP6]] to i32
304; CHECK-NEXT:    [[SHIFTED1:%.*]] = shl nuw i32 [[EXTENDED]], [[SHIFTAMT]]
305; CHECK-NEXT:    [[UNMASKED:%.*]] = and i32 [[LOADED]], [[INV_MASK]]
306; CHECK-NEXT:    [[INSERTED:%.*]] = or i32 [[UNMASKED]], [[SHIFTED1]]
307; CHECK-NEXT:    [[TMP7:%.*]] = cmpxchg ptr [[ALIGNEDADDR]], i32 [[LOADED]], i32 [[INSERTED]] monotonic monotonic, align 4
308; CHECK-NEXT:    [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP7]], 1
309; CHECK-NEXT:    [[NEWLOADED]] = extractvalue { i32, i1 } [[TMP7]], 0
310; CHECK-NEXT:    br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]]
311; CHECK:       atomicrmw.end:
312; CHECK-NEXT:    [[SHIFTED2:%.*]] = lshr i32 [[NEWLOADED]], [[SHIFTAMT]]
313; CHECK-NEXT:    [[EXTRACTED3:%.*]] = trunc i32 [[SHIFTED2]] to i16
314; CHECK-NEXT:    [[TMP8:%.*]] = bitcast i16 [[EXTRACTED3]] to half
315; CHECK-NEXT:    fence seq_cst
316; CHECK-NEXT:    ret half [[TMP8]]
317;
318  %res = atomicrmw fadd ptr %ptr, half %value seq_cst
319  ret half %res
320}
321