xref: /llvm-project/llvm/test/Transforms/AtomicExpand/AMDGPU/expand-atomic-rmw-fmax.ll (revision 9cc298108a7bb34d0126028a529ecdcb0ade9baf)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=hawaii -passes=atomic-expand %s | FileCheck -check-prefixes=GCN,GFX7 %s
3; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 -passes=atomic-expand %s | FileCheck -check-prefixes=GCN,GFX9 %s
4
5define float @test_atomicrmw_fmax_f32_flat(ptr %ptr, float %value) {
6; GCN-LABEL: @test_atomicrmw_fmax_f32_flat(
7; GCN-NEXT:    [[TMP1:%.*]] = load float, ptr [[PTR:%.*]], align 4
8; GCN-NEXT:    br label [[ATOMICRMW_START:%.*]]
9; GCN:       atomicrmw.start:
10; GCN-NEXT:    [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP6:%.*]], [[ATOMICRMW_START]] ]
11; GCN-NEXT:    [[TMP2:%.*]] = call float @llvm.maxnum.f32(float [[LOADED]], float [[VALUE:%.*]])
12; GCN-NEXT:    [[TMP3:%.*]] = bitcast float [[TMP2]] to i32
13; GCN-NEXT:    [[TMP4:%.*]] = bitcast float [[LOADED]] to i32
14; GCN-NEXT:    [[TMP5:%.*]] = cmpxchg ptr [[PTR]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst, align 4
15; GCN-NEXT:    [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1
16; GCN-NEXT:    [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0
17; GCN-NEXT:    [[TMP6]] = bitcast i32 [[NEWLOADED]] to float
18; GCN-NEXT:    br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]]
19; GCN:       atomicrmw.end:
20; GCN-NEXT:    ret float [[TMP6]]
21;
22  %res = atomicrmw fmax ptr %ptr, float %value seq_cst
23  ret float %res
24}
25
26define float @test_atomicrmw_fmax_f32_global(ptr addrspace(1) %ptr, float %value) {
27; GCN-LABEL: @test_atomicrmw_fmax_f32_global(
28; GCN-NEXT:    [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR:%.*]], align 4
29; GCN-NEXT:    br label [[ATOMICRMW_START:%.*]]
30; GCN:       atomicrmw.start:
31; GCN-NEXT:    [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP6:%.*]], [[ATOMICRMW_START]] ]
32; GCN-NEXT:    [[TMP2:%.*]] = call float @llvm.maxnum.f32(float [[LOADED]], float [[VALUE:%.*]])
33; GCN-NEXT:    [[TMP3:%.*]] = bitcast float [[TMP2]] to i32
34; GCN-NEXT:    [[TMP4:%.*]] = bitcast float [[LOADED]] to i32
35; GCN-NEXT:    [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst, align 4
36; GCN-NEXT:    [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1
37; GCN-NEXT:    [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0
38; GCN-NEXT:    [[TMP6]] = bitcast i32 [[NEWLOADED]] to float
39; GCN-NEXT:    br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]]
40; GCN:       atomicrmw.end:
41; GCN-NEXT:    ret float [[TMP6]]
42;
43  %res = atomicrmw fmax ptr addrspace(1) %ptr, float %value seq_cst
44  ret float %res
45}
46
47define float @test_atomicrmw_fmax_f32_local(ptr addrspace(3) %ptr, float %value) {
48; GCN-LABEL: @test_atomicrmw_fmax_f32_local(
49; GCN-NEXT:    [[RES:%.*]] = atomicrmw fmax ptr addrspace(3) [[PTR:%.*]], float [[VALUE:%.*]] seq_cst, align 4
50; GCN-NEXT:    ret float [[RES]]
51;
52  %res = atomicrmw fmax ptr addrspace(3) %ptr, float %value seq_cst
53  ret float %res
54}
55
56define half @test_atomicrmw_fmax_f16_flat(ptr %ptr, half %value) {
57; GCN-LABEL: @test_atomicrmw_fmax_f16_flat(
58; GCN-NEXT:    [[ALIGNEDADDR:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[PTR:%.*]], i64 -4)
59; GCN-NEXT:    [[TMP1:%.*]] = ptrtoint ptr [[PTR]] to i64
60; GCN-NEXT:    [[PTRLSB:%.*]] = and i64 [[TMP1]], 3
61; GCN-NEXT:    [[TMP2:%.*]] = shl i64 [[PTRLSB]], 3
62; GCN-NEXT:    [[SHIFTAMT:%.*]] = trunc i64 [[TMP2]] to i32
63; GCN-NEXT:    [[MASK:%.*]] = shl i32 65535, [[SHIFTAMT]]
64; GCN-NEXT:    [[INV_MASK:%.*]] = xor i32 [[MASK]], -1
65; GCN-NEXT:    [[TMP3:%.*]] = load i32, ptr [[ALIGNEDADDR]], align 4
66; GCN-NEXT:    br label [[ATOMICRMW_START:%.*]]
67; GCN:       atomicrmw.start:
68; GCN-NEXT:    [[LOADED:%.*]] = phi i32 [ [[TMP3]], [[TMP0:%.*]] ], [ [[NEWLOADED:%.*]], [[ATOMICRMW_START]] ]
69; GCN-NEXT:    [[SHIFTED:%.*]] = lshr i32 [[LOADED]], [[SHIFTAMT]]
70; GCN-NEXT:    [[EXTRACTED:%.*]] = trunc i32 [[SHIFTED]] to i16
71; GCN-NEXT:    [[TMP4:%.*]] = bitcast i16 [[EXTRACTED]] to half
72; GCN-NEXT:    [[TMP5:%.*]] = call half @llvm.maxnum.f16(half [[TMP4]], half [[VALUE:%.*]])
73; GCN-NEXT:    [[TMP6:%.*]] = bitcast half [[TMP5]] to i16
74; GCN-NEXT:    [[EXTENDED:%.*]] = zext i16 [[TMP6]] to i32
75; GCN-NEXT:    [[SHIFTED1:%.*]] = shl nuw i32 [[EXTENDED]], [[SHIFTAMT]]
76; GCN-NEXT:    [[UNMASKED:%.*]] = and i32 [[LOADED]], [[INV_MASK]]
77; GCN-NEXT:    [[INSERTED:%.*]] = or i32 [[UNMASKED]], [[SHIFTED1]]
78; GCN-NEXT:    [[TMP7:%.*]] = cmpxchg ptr [[ALIGNEDADDR]], i32 [[LOADED]], i32 [[INSERTED]] seq_cst seq_cst, align 4
79; GCN-NEXT:    [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP7]], 1
80; GCN-NEXT:    [[NEWLOADED]] = extractvalue { i32, i1 } [[TMP7]], 0
81; GCN-NEXT:    br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]]
82; GCN:       atomicrmw.end:
83; GCN-NEXT:    [[SHIFTED2:%.*]] = lshr i32 [[NEWLOADED]], [[SHIFTAMT]]
84; GCN-NEXT:    [[EXTRACTED3:%.*]] = trunc i32 [[SHIFTED2]] to i16
85; GCN-NEXT:    [[TMP8:%.*]] = bitcast i16 [[EXTRACTED3]] to half
86; GCN-NEXT:    ret half [[TMP8]]
87;
88  %res = atomicrmw fmax ptr %ptr, half %value seq_cst
89  ret half %res
90}
91
92define half @test_atomicrmw_fmax_f16_global(ptr addrspace(1) %ptr, half %value) {
93; GCN-LABEL: @test_atomicrmw_fmax_f16_global(
94; GCN-NEXT:    [[ALIGNEDADDR:%.*]] = call ptr addrspace(1) @llvm.ptrmask.p1.i64(ptr addrspace(1) [[PTR:%.*]], i64 -4)
95; GCN-NEXT:    [[TMP1:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64
96; GCN-NEXT:    [[PTRLSB:%.*]] = and i64 [[TMP1]], 3
97; GCN-NEXT:    [[TMP2:%.*]] = shl i64 [[PTRLSB]], 3
98; GCN-NEXT:    [[SHIFTAMT:%.*]] = trunc i64 [[TMP2]] to i32
99; GCN-NEXT:    [[MASK:%.*]] = shl i32 65535, [[SHIFTAMT]]
100; GCN-NEXT:    [[INV_MASK:%.*]] = xor i32 [[MASK]], -1
101; GCN-NEXT:    [[TMP3:%.*]] = load i32, ptr addrspace(1) [[ALIGNEDADDR]], align 4
102; GCN-NEXT:    br label [[ATOMICRMW_START:%.*]]
103; GCN:       atomicrmw.start:
104; GCN-NEXT:    [[LOADED:%.*]] = phi i32 [ [[TMP3]], [[TMP0:%.*]] ], [ [[NEWLOADED:%.*]], [[ATOMICRMW_START]] ]
105; GCN-NEXT:    [[SHIFTED:%.*]] = lshr i32 [[LOADED]], [[SHIFTAMT]]
106; GCN-NEXT:    [[EXTRACTED:%.*]] = trunc i32 [[SHIFTED]] to i16
107; GCN-NEXT:    [[TMP4:%.*]] = bitcast i16 [[EXTRACTED]] to half
108; GCN-NEXT:    [[TMP5:%.*]] = call half @llvm.maxnum.f16(half [[TMP4]], half [[VALUE:%.*]])
109; GCN-NEXT:    [[TMP6:%.*]] = bitcast half [[TMP5]] to i16
110; GCN-NEXT:    [[EXTENDED:%.*]] = zext i16 [[TMP6]] to i32
111; GCN-NEXT:    [[SHIFTED1:%.*]] = shl nuw i32 [[EXTENDED]], [[SHIFTAMT]]
112; GCN-NEXT:    [[UNMASKED:%.*]] = and i32 [[LOADED]], [[INV_MASK]]
113; GCN-NEXT:    [[INSERTED:%.*]] = or i32 [[UNMASKED]], [[SHIFTED1]]
114; GCN-NEXT:    [[TMP7:%.*]] = cmpxchg ptr addrspace(1) [[ALIGNEDADDR]], i32 [[LOADED]], i32 [[INSERTED]] seq_cst seq_cst, align 4
115; GCN-NEXT:    [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP7]], 1
116; GCN-NEXT:    [[NEWLOADED]] = extractvalue { i32, i1 } [[TMP7]], 0
117; GCN-NEXT:    br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]]
118; GCN:       atomicrmw.end:
119; GCN-NEXT:    [[SHIFTED2:%.*]] = lshr i32 [[NEWLOADED]], [[SHIFTAMT]]
120; GCN-NEXT:    [[EXTRACTED3:%.*]] = trunc i32 [[SHIFTED2]] to i16
121; GCN-NEXT:    [[TMP8:%.*]] = bitcast i16 [[EXTRACTED3]] to half
122; GCN-NEXT:    ret half [[TMP8]]
123;
124  %res = atomicrmw fmax ptr addrspace(1) %ptr, half %value seq_cst
125  ret half %res
126}
127
128define half @test_atomicrmw_fmax_f16_global_align4(ptr addrspace(1) %ptr, half %value) {
129; GCN-LABEL: @test_atomicrmw_fmax_f16_global_align4(
130; GCN-NEXT:    [[TMP1:%.*]] = load i32, ptr addrspace(1) [[PTR:%.*]], align 4
131; GCN-NEXT:    br label [[ATOMICRMW_START:%.*]]
132; GCN:       atomicrmw.start:
133; GCN-NEXT:    [[LOADED:%.*]] = phi i32 [ [[TMP1]], [[TMP0:%.*]] ], [ [[NEWLOADED:%.*]], [[ATOMICRMW_START]] ]
134; GCN-NEXT:    [[EXTRACTED:%.*]] = trunc i32 [[LOADED]] to i16
135; GCN-NEXT:    [[TMP2:%.*]] = bitcast i16 [[EXTRACTED]] to half
136; GCN-NEXT:    [[TMP3:%.*]] = call half @llvm.maxnum.f16(half [[TMP2]], half [[VALUE:%.*]])
137; GCN-NEXT:    [[TMP4:%.*]] = bitcast half [[TMP3]] to i16
138; GCN-NEXT:    [[EXTENDED:%.*]] = zext i16 [[TMP4]] to i32
139; GCN-NEXT:    [[UNMASKED:%.*]] = and i32 [[LOADED]], -65536
140; GCN-NEXT:    [[INSERTED:%.*]] = or i32 [[UNMASKED]], [[EXTENDED]]
141; GCN-NEXT:    [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[LOADED]], i32 [[INSERTED]] seq_cst seq_cst, align 4
142; GCN-NEXT:    [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1
143; GCN-NEXT:    [[NEWLOADED]] = extractvalue { i32, i1 } [[TMP5]], 0
144; GCN-NEXT:    br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]]
145; GCN:       atomicrmw.end:
146; GCN-NEXT:    [[EXTRACTED1:%.*]] = trunc i32 [[NEWLOADED]] to i16
147; GCN-NEXT:    [[TMP6:%.*]] = bitcast i16 [[EXTRACTED1]] to half
148; GCN-NEXT:    ret half [[TMP6]]
149;
150  %res = atomicrmw fmax ptr addrspace(1) %ptr, half %value seq_cst, align 4
151  ret half %res
152}
153
154define half @test_atomicrmw_fmax_f16_local(ptr addrspace(3) %ptr, half %value) {
155; GCN-LABEL: @test_atomicrmw_fmax_f16_local(
156; GCN-NEXT:    [[ALIGNEDADDR:%.*]] = call ptr addrspace(3) @llvm.ptrmask.p3.i32(ptr addrspace(3) [[PTR:%.*]], i32 -4)
157; GCN-NEXT:    [[TMP1:%.*]] = ptrtoint ptr addrspace(3) [[PTR]] to i32
158; GCN-NEXT:    [[PTRLSB:%.*]] = and i32 [[TMP1]], 3
159; GCN-NEXT:    [[TMP2:%.*]] = shl i32 [[PTRLSB]], 3
160; GCN-NEXT:    [[MASK:%.*]] = shl i32 65535, [[TMP2]]
161; GCN-NEXT:    [[INV_MASK:%.*]] = xor i32 [[MASK]], -1
162; GCN-NEXT:    [[TMP3:%.*]] = load i32, ptr addrspace(3) [[ALIGNEDADDR]], align 4
163; GCN-NEXT:    br label [[ATOMICRMW_START:%.*]]
164; GCN:       atomicrmw.start:
165; GCN-NEXT:    [[LOADED:%.*]] = phi i32 [ [[TMP3]], [[TMP0:%.*]] ], [ [[NEWLOADED:%.*]], [[ATOMICRMW_START]] ]
166; GCN-NEXT:    [[SHIFTED:%.*]] = lshr i32 [[LOADED]], [[TMP2]]
167; GCN-NEXT:    [[EXTRACTED:%.*]] = trunc i32 [[SHIFTED]] to i16
168; GCN-NEXT:    [[TMP4:%.*]] = bitcast i16 [[EXTRACTED]] to half
169; GCN-NEXT:    [[TMP5:%.*]] = call half @llvm.maxnum.f16(half [[TMP4]], half [[VALUE:%.*]])
170; GCN-NEXT:    [[TMP6:%.*]] = bitcast half [[TMP5]] to i16
171; GCN-NEXT:    [[EXTENDED:%.*]] = zext i16 [[TMP6]] to i32
172; GCN-NEXT:    [[SHIFTED1:%.*]] = shl nuw i32 [[EXTENDED]], [[TMP2]]
173; GCN-NEXT:    [[UNMASKED:%.*]] = and i32 [[LOADED]], [[INV_MASK]]
174; GCN-NEXT:    [[INSERTED:%.*]] = or i32 [[UNMASKED]], [[SHIFTED1]]
175; GCN-NEXT:    [[TMP7:%.*]] = cmpxchg ptr addrspace(3) [[ALIGNEDADDR]], i32 [[LOADED]], i32 [[INSERTED]] seq_cst seq_cst, align 4
176; GCN-NEXT:    [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP7]], 1
177; GCN-NEXT:    [[NEWLOADED]] = extractvalue { i32, i1 } [[TMP7]], 0
178; GCN-NEXT:    br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]]
179; GCN:       atomicrmw.end:
180; GCN-NEXT:    [[SHIFTED2:%.*]] = lshr i32 [[NEWLOADED]], [[TMP2]]
181; GCN-NEXT:    [[EXTRACTED3:%.*]] = trunc i32 [[SHIFTED2]] to i16
182; GCN-NEXT:    [[TMP8:%.*]] = bitcast i16 [[EXTRACTED3]] to half
183; GCN-NEXT:    ret half [[TMP8]]
184;
185  %res = atomicrmw fmax ptr addrspace(3) %ptr, half %value seq_cst
186  ret half %res
187}
188
189define double @test_atomicrmw_fmax_f64_flat(ptr %ptr, double %value) {
190; GCN-LABEL: @test_atomicrmw_fmax_f64_flat(
191; GCN-NEXT:    [[IS_PRIVATE:%.*]] = call i1 @llvm.amdgcn.is.private(ptr [[PTR:%.*]])
192; GCN-NEXT:    br i1 [[IS_PRIVATE]], label [[ATOMICRMW_PRIVATE:%.*]], label [[ATOMICRMW_GLOBAL:%.*]]
193; GCN:       atomicrmw.private:
194; GCN-NEXT:    [[TMP1:%.*]] = addrspacecast ptr [[PTR]] to ptr addrspace(5)
195; GCN-NEXT:    [[LOADED_PRIVATE:%.*]] = load double, ptr addrspace(5) [[TMP1]], align 8
196; GCN-NEXT:    [[TMP2:%.*]] = call double @llvm.maxnum.f64(double [[LOADED_PRIVATE]], double [[VALUE:%.*]])
197; GCN-NEXT:    store double [[TMP2]], ptr addrspace(5) [[TMP1]], align 8
198; GCN-NEXT:    br label [[ATOMICRMW_PHI:%.*]]
199; GCN:       atomicrmw.global:
200; GCN-NEXT:    [[TMP3:%.*]] = load double, ptr [[PTR]], align 8
201; GCN-NEXT:    br label [[ATOMICRMW_START:%.*]]
202; GCN:       atomicrmw.start:
203; GCN-NEXT:    [[LOADED:%.*]] = phi double [ [[TMP3]], [[ATOMICRMW_GLOBAL]] ], [ [[TMP8:%.*]], [[ATOMICRMW_START]] ]
204; GCN-NEXT:    [[TMP4:%.*]] = call double @llvm.maxnum.f64(double [[LOADED]], double [[VALUE]])
205; GCN-NEXT:    [[TMP5:%.*]] = bitcast double [[TMP4]] to i64
206; GCN-NEXT:    [[TMP6:%.*]] = bitcast double [[LOADED]] to i64
207; GCN-NEXT:    [[TMP7:%.*]] = cmpxchg ptr [[PTR]], i64 [[TMP6]], i64 [[TMP5]] seq_cst seq_cst, align 8, !noalias.addrspace [[META0:![0-9]+]]
208; GCN-NEXT:    [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP7]], 1
209; GCN-NEXT:    [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP7]], 0
210; GCN-NEXT:    [[TMP8]] = bitcast i64 [[NEWLOADED]] to double
211; GCN-NEXT:    br i1 [[SUCCESS]], label [[ATOMICRMW_END1:%.*]], label [[ATOMICRMW_START]]
212; GCN:       atomicrmw.end1:
213; GCN-NEXT:    br label [[ATOMICRMW_PHI]]
214; GCN:       atomicrmw.phi:
215; GCN-NEXT:    [[RES:%.*]] = phi double [ [[LOADED_PRIVATE]], [[ATOMICRMW_PRIVATE]] ], [ [[TMP8]], [[ATOMICRMW_END1]] ]
216; GCN-NEXT:    br label [[ATOMICRMW_END:%.*]]
217; GCN:       atomicrmw.end:
218; GCN-NEXT:    ret double [[RES]]
219;
220  %res = atomicrmw fmax ptr %ptr, double %value seq_cst
221  ret double %res
222}
223
224define double @test_atomicrmw_fmax_f64_flat__noprivate(ptr %ptr, double %value) {
225; GCN-LABEL: @test_atomicrmw_fmax_f64_flat__noprivate(
226; GCN-NEXT:    [[TMP1:%.*]] = load double, ptr [[PTR:%.*]], align 8
227; GCN-NEXT:    br label [[ATOMICRMW_START:%.*]]
228; GCN:       atomicrmw.start:
229; GCN-NEXT:    [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP6:%.*]], [[ATOMICRMW_START]] ]
230; GCN-NEXT:    [[TMP2:%.*]] = call double @llvm.maxnum.f64(double [[LOADED]], double [[VALUE:%.*]])
231; GCN-NEXT:    [[TMP3:%.*]] = bitcast double [[TMP2]] to i64
232; GCN-NEXT:    [[TMP4:%.*]] = bitcast double [[LOADED]] to i64
233; GCN-NEXT:    [[TMP5:%.*]] = cmpxchg ptr [[PTR]], i64 [[TMP4]], i64 [[TMP3]] seq_cst seq_cst, align 8, !noalias.addrspace [[META0]]
234; GCN-NEXT:    [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP5]], 1
235; GCN-NEXT:    [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP5]], 0
236; GCN-NEXT:    [[TMP6]] = bitcast i64 [[NEWLOADED]] to double
237; GCN-NEXT:    br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]]
238; GCN:       atomicrmw.end:
239; GCN-NEXT:    ret double [[TMP6]]
240;
241  %res = atomicrmw fmax ptr %ptr, double %value seq_cst, !noalias.addrspace !0
242  ret double %res
243}
244
245define double @test_atomicrmw_fmax_f64_global(ptr addrspace(1) %ptr, double %value) {
246; GCN-LABEL: @test_atomicrmw_fmax_f64_global(
247; GCN-NEXT:    [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR:%.*]], align 8
248; GCN-NEXT:    br label [[ATOMICRMW_START:%.*]]
249; GCN:       atomicrmw.start:
250; GCN-NEXT:    [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP6:%.*]], [[ATOMICRMW_START]] ]
251; GCN-NEXT:    [[TMP2:%.*]] = call double @llvm.maxnum.f64(double [[LOADED]], double [[VALUE:%.*]])
252; GCN-NEXT:    [[TMP3:%.*]] = bitcast double [[TMP2]] to i64
253; GCN-NEXT:    [[TMP4:%.*]] = bitcast double [[LOADED]] to i64
254; GCN-NEXT:    [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP4]], i64 [[TMP3]] seq_cst seq_cst, align 8
255; GCN-NEXT:    [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP5]], 1
256; GCN-NEXT:    [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP5]], 0
257; GCN-NEXT:    [[TMP6]] = bitcast i64 [[NEWLOADED]] to double
258; GCN-NEXT:    br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]]
259; GCN:       atomicrmw.end:
260; GCN-NEXT:    ret double [[TMP6]]
261;
262  %res = atomicrmw fmax ptr addrspace(1) %ptr, double %value seq_cst
263  ret double %res
264}
265
266define double @test_atomicrmw_fmax_f64_local(ptr addrspace(3) %ptr, double %value) {
267; GCN-LABEL: @test_atomicrmw_fmax_f64_local(
268; GCN-NEXT:    [[RES:%.*]] = atomicrmw fmax ptr addrspace(3) [[PTR:%.*]], double [[VALUE:%.*]] seq_cst, align 8
269; GCN-NEXT:    ret double [[RES]]
270;
271  %res = atomicrmw fmax ptr addrspace(3) %ptr, double %value seq_cst
272  ret double %res
273}
274
275define double @test_atomicrmw_fmax_f64_global_strictfp(ptr addrspace(1) %ptr, double %value) strictfp {
276; GCN-LABEL: @test_atomicrmw_fmax_f64_global_strictfp(
277; GCN-NEXT:    [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR:%.*]], align 8
278; GCN-NEXT:    br label [[ATOMICRMW_START:%.*]]
279; GCN:       atomicrmw.start:
280; GCN-NEXT:    [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP6:%.*]], [[ATOMICRMW_START]] ]
281; GCN-NEXT:    [[TMP2:%.*]] = call double @llvm.experimental.constrained.maxnum.f64(double [[LOADED]], double [[VALUE:%.*]], metadata !"fpexcept.strict") #[[ATTR4:[0-9]+]]
282; GCN-NEXT:    [[TMP3:%.*]] = bitcast double [[TMP2]] to i64
283; GCN-NEXT:    [[TMP4:%.*]] = bitcast double [[LOADED]] to i64
284; GCN-NEXT:    [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP4]], i64 [[TMP3]] seq_cst seq_cst, align 8
285; GCN-NEXT:    [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP5]], 1
286; GCN-NEXT:    [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP5]], 0
287; GCN-NEXT:    [[TMP6]] = bitcast i64 [[NEWLOADED]] to double
288; GCN-NEXT:    br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]]
289; GCN:       atomicrmw.end:
290; GCN-NEXT:    ret double [[TMP6]]
291;
292  %res = atomicrmw fmax ptr addrspace(1) %ptr, double %value seq_cst
293  ret double %res
294}
295
296!0 = !{i32 5, i32 6}
297
298;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
299; GFX7: {{.*}}
300; GFX9: {{.*}}
301