1; RUN: llc -march=amdgcn -mcpu=gfx801 -verify-machineinstrs -mattr=-fp32-denormals < %s | FileCheck -enable-var-scope -check-prefixes=GCN,VI,VI-FLUSH,GCN-FLUSH,GCN-NOEXCEPT %s
2; RUN: llc -march=amdgcn -mcpu=gfx801 -verify-machineinstrs -mattr=-fp32-denormals,+fp-exceptions < %s | FileCheck -enable-var-scope -check-prefixes=GCN,GCN-EXCEPT,VI,VI-FLUSH,GCN-FLUSH %s
3; RUN: llc -march=amdgcn -mcpu=gfx801 -verify-machineinstrs -mattr=+fp32-denormals < %s | FileCheck -enable-var-scope -check-prefixes=GCN,VI,VI-DENORM,GCN-DENORM,GCN-NOEXCEPT %s
4; RUN: llc -march=amdgcn -mcpu=gfx900 -verify-machineinstrs -mattr=+fp32-denormals < %s | FileCheck -enable-var-scope -check-prefixes=GCN,GFX9,GFX9-DENORM,GCN-DENORM,GCN-NOEXCEPT %s
5; RUN: llc -march=amdgcn -mcpu=gfx900 -verify-machineinstrs -mattr=-fp32-denormals < %s | FileCheck -enable-var-scope -check-prefixes=GCN,GFX9,GFX9-FLUSH,GCN-FLUSH,GCN-NOEXCEPT %s
6
7; GCN-LABEL: {{^}}test_no_fold_canonicalize_loaded_value_f32:
8; GCN-FLUSH:   v_mul_f32_e32 v{{[0-9]+}}, 1.0, v{{[0-9]+}}
9; GFX9-DENORM: v_max_f32_e32 v{{[0-9]+}}, v{{[0-9]+}}, v{{[0-9]+}}
10define amdgpu_kernel void @test_no_fold_canonicalize_loaded_value_f32(float addrspace(1)* %arg) {
11  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
12  %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id
13  %v = load float, float addrspace(1)* %gep, align 4
14  %canonicalized = tail call float @llvm.canonicalize.f32(float %v)
15  store float %canonicalized, float addrspace(1)* %gep, align 4
16  ret void
17}
18
19; GCN-LABEL: {{^}}test_fold_canonicalize_fmul_value_f32:
20; GCN: v_mul_f32_e32 [[V:v[0-9]+]], 0x41700000, v{{[0-9]+}}
21; GCN: {{flat|global}}_store_dword v[{{[0-9:]+}}], [[V]]
22; GCN-NOT: 1.0
23define amdgpu_kernel void @test_fold_canonicalize_fmul_value_f32(float addrspace(1)* %arg) {
24  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
25  %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id
26  %load = load float, float addrspace(1)* %gep, align 4
27  %v = fmul float %load, 15.0
28  %canonicalized = tail call float @llvm.canonicalize.f32(float %v)
29  store float %canonicalized, float addrspace(1)* %gep, align 4
30  ret void
31}
32
33; GCN-LABEL: {{^}}test_fold_canonicalize_fmul_legacy_value_f32:
34; GCN: v_mul_legacy_f32_e32 [[V:v[0-9]+]], 0x41700000, v{{[0-9]+}}
35; GCN-NOT: v_mul
36; GCN-NOT: v_max
37; GCN: {{flat|global}}_store_dword v[{{[0-9:]+}}], [[V]]
38define amdgpu_kernel void @test_fold_canonicalize_fmul_legacy_value_f32(float addrspace(1)* %arg) {
39  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
40  %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id
41  %load = load float, float addrspace(1)* %gep, align 4
42  %v = call float @llvm.amdgcn.fmul.legacy(float %load, float 15.0)
43  %canonicalized = tail call float @llvm.canonicalize.f32(float %v)
44  store float %canonicalized, float addrspace(1)* %gep, align 4
45  ret void
46}
47
48; GCN-LABEL: {{^}}test_fold_canonicalize_sub_value_f32:
49; GCN: v_sub_f32_e32 [[V:v[0-9]+]], 0x41700000, v{{[0-9]+}}
50; GCN-NOT: v_mul
51; GCN-NOT: v_max
52; GCN: {{flat|global}}_store_dword v[{{[0-9:]+}}], [[V]]
53define amdgpu_kernel void @test_fold_canonicalize_sub_value_f32(float addrspace(1)* %arg) {
54  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
55  %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id
56  %load = load float, float addrspace(1)* %gep, align 4
57  %v = fsub float 15.0, %load
58  %canonicalized = tail call float @llvm.canonicalize.f32(float %v)
59  store float %canonicalized, float addrspace(1)* %gep, align 4
60  ret void
61}
62
63; GCN-LABEL: {{^}}test_fold_canonicalize_add_value_f32:
64; GCN: v_add_f32_e32 [[V:v[0-9]+]], 0x41700000, v{{[0-9]+}}
65; GCN-NOT: v_mul
66; GCN-NOT: v_max
67; GCN: {{flat|global}}_store_dword v[{{[0-9:]+}}], [[V]]
68define amdgpu_kernel void @test_fold_canonicalize_add_value_f32(float addrspace(1)* %arg) {
69  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
70  %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id
71  %load = load float, float addrspace(1)* %gep, align 4
72  %v = fadd float %load, 15.0
73  %canonicalized = tail call float @llvm.canonicalize.f32(float %v)
74  store float %canonicalized, float addrspace(1)* %gep, align 4
75  ret void
76}
77
78; GCN-LABEL: {{^}}test_fold_canonicalize_sqrt_value_f32:
79; GCN: v_sqrt_f32_e32 [[V:v[0-9]+]], v{{[0-9]+}}
80; GCN-NOT: v_mul
81; GCN-NOT: v_max
82; GCN: {{flat|global}}_store_dword v[{{[0-9:]+}}], [[V]]
83define amdgpu_kernel void @test_fold_canonicalize_sqrt_value_f32(float addrspace(1)* %arg) {
84  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
85  %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id
86  %load = load float, float addrspace(1)* %gep, align 4
87  %v = call float @llvm.sqrt.f32(float %load)
88  %canonicalized = tail call float @llvm.canonicalize.f32(float %v)
89  store float %canonicalized, float addrspace(1)* %gep, align 4
90  ret void
91}
92
93; GCN-LABEL: test_fold_canonicalize_fceil_value_f32:
94; GCN: v_ceil_f32_e32 [[V:v[0-9]+]], v{{[0-9]+}}
95; GCN-NOT: v_mul
96; GCN-NOT: v_max
97; GCN: {{flat|global}}_store_dword v[{{[0-9:]+}}], [[V]]
98define amdgpu_kernel void @test_fold_canonicalize_fceil_value_f32(float addrspace(1)* %arg) {
99  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
100  %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id
101  %load = load float, float addrspace(1)* %gep, align 4
102  %v = call float @llvm.ceil.f32(float %load)
103  %canonicalized = tail call float @llvm.canonicalize.f32(float %v)
104  store float %canonicalized, float addrspace(1)* %gep, align 4
105  ret void
106}
107
108; GCN-LABEL: test_fold_canonicalize_floor_value_f32:
109; GCN: v_floor_f32_e32 [[V:v[0-9]+]], v{{[0-9]+}}
110; GCN-NOT: v_mul
111; GCN-NOT: v_max
112; GCN: {{flat|global}}_store_dword v[{{[0-9:]+}}], [[V]]
113define amdgpu_kernel void @test_fold_canonicalize_floor_value_f32(float addrspace(1)* %arg) {
114  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
115  %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id
116  %load = load float, float addrspace(1)* %gep, align 4
117  %v = call float @llvm.floor.f32(float %load)
118  %canonicalized = tail call float @llvm.canonicalize.f32(float %v)
119  store float %canonicalized, float addrspace(1)* %gep, align 4
120  ret void
121}
122
123; GCN-LABEL: test_fold_canonicalize_fma_value_f32:
124; GCN: s_mov_b32 [[SREG:s[0-9]+]], 0x41700000
125; GCN: v_fma_f32 [[V:v[0-9]+]], v{{[0-9]+}}, [[SREG]], [[SREG]]
126; GCN-NOT: v_mul
127; GCN-NOT: v_max
128; GCN: {{flat|global}}_store_dword v[{{[0-9:]+}}], [[V]]
129define amdgpu_kernel void @test_fold_canonicalize_fma_value_f32(float addrspace(1)* %arg) {
130  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
131  %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id
132  %load = load float, float addrspace(1)* %gep, align 4
133  %v = call float @llvm.fma.f32(float %load, float 15.0, float 15.0)
134  %canonicalized = tail call float @llvm.canonicalize.f32(float %v)
135  store float %canonicalized, float addrspace(1)* %gep, align 4
136  ret void
137}
138
139; GCN-LABEL: test_fold_canonicalize_fmad_ftz_value_f32:
140; GCN: s_mov_b32 [[SGPR:s[0-9]+]], 0x41700000
141; GCN: v_mad_f32 [[V:v[0-9]+]], v{{[0-9]+}}, [[SGPR]], [[SGPR]]
142; GCN-NOT: v_mul
143; GCN-NOT: v_max
144; GCN: {{flat|global}}_store_dword v[{{[0-9:]+}}], [[V]]
145define amdgpu_kernel void @test_fold_canonicalize_fmad_ftz_value_f32(float addrspace(1)* %arg) {
146  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
147  %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id
148  %load = load float, float addrspace(1)* %gep, align 4
149  %v = call float @llvm.amdgcn.fmad.ftz.f32(float %load, float 15.0, float 15.0)
150  %canonicalized = tail call float @llvm.canonicalize.f32(float %v)
151  store float %canonicalized, float addrspace(1)* %gep, align 4
152  ret void
153}
154
155; GCN-LABEL: test_fold_canonicalize_fmuladd_value_f32:
156; GCN-FLUSH: v_mac_f32_e32 [[V:v[0-9]+]], v{{[0-9]+}}, v{{[0-9]+}}
157; GCN-DENORM: s_mov_b32 [[SREG:s[0-9]+]], 0x41700000
158; GCN-DENORM: v_fma_f32 [[V:v[0-9]+]], v{{[0-9]+}}, [[SREG]], [[SREG]]
159; GCN-NOT: v_mul
160; GCN-NOT: v_max
161; GCN: {{flat|global}}_store_dword v[{{[0-9:]+}}], [[V]]
162; GCN-NOT: 1.0
163define amdgpu_kernel void @test_fold_canonicalize_fmuladd_value_f32(float addrspace(1)* %arg) {
164  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
165  %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id
166  %load = load float, float addrspace(1)* %gep, align 4
167  %v = call float @llvm.fmuladd.f32(float %load, float 15.0, float 15.0)
168  %canonicalized = tail call float @llvm.canonicalize.f32(float %v)
169  store float %canonicalized, float addrspace(1)* %gep, align 4
170  ret void
171}
172
173; GCN-LABEL: test_fold_canonicalize_canonicalize_value_f32:
174; GCN: {{flat|global}}_load_dword [[LOAD:v[0-9]+]],
175; GCN-FLUSH:  v_mul_f32_e32 [[V:v[0-9]+]], 1.0, [[LOAD]]
176; GCN-DENORM: v_max_f32_e32 [[V:v[0-9]+]], [[LOAD]], [[LOAD]]
177; GCN-NOT: v_mul
178; GCN-NOT: v_max
179; GCN: {{flat|global}}_store_dword v[{{[0-9:]+}}], [[V]]
180define amdgpu_kernel void @test_fold_canonicalize_canonicalize_value_f32(float addrspace(1)* %arg) {
181  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
182  %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id
183  %load = load float, float addrspace(1)* %gep, align 4
184  %v = call float @llvm.canonicalize.f32(float %load)
185  %canonicalized = tail call float @llvm.canonicalize.f32(float %v)
186  store float %canonicalized, float addrspace(1)* %gep, align 4
187  ret void
188}
189
190; GCN-LABEL: test_fold_canonicalize_fpextend_value_f64_f32:
191; GCN: v_cvt_f64_f32_e32 [[V:v\[[0-9]+:[0-9]+\]]], v{{[0-9]+}}
192; GCN-NOT: v_mul
193; GCN-NOT: v_max
194; GCN: {{flat|global}}_store_dwordx2 v[{{[0-9:]+}}], [[V]]
195define amdgpu_kernel void @test_fold_canonicalize_fpextend_value_f64_f32(float addrspace(1)* %arg, double addrspace(1)* %out) {
196  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
197  %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id
198  %load = load float, float addrspace(1)* %gep, align 4
199  %v = fpext float %load to double
200  %canonicalized = tail call double @llvm.canonicalize.f64(double %v)
201  %gep2 = getelementptr inbounds double, double addrspace(1)* %out, i32 %id
202  store double %canonicalized, double addrspace(1)* %gep2, align 8
203  ret void
204}
205
206; GCN-LABEL: test_fold_canonicalize_fpextend_value_f32_f16:
207; GCN: v_cvt_f32_f16_e32 [[V:v[0-9]+]], v{{[0-9]+}}
208; GCN-NOT: v_mul
209; GCN-NOT: v_max
210; GCN: {{flat|global}}_store_dword v[{{[0-9:]+}}], [[V]]
211define amdgpu_kernel void @test_fold_canonicalize_fpextend_value_f32_f16(half addrspace(1)* %arg, float addrspace(1)* %out) {
212  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
213  %gep = getelementptr inbounds half, half addrspace(1)* %arg, i32 %id
214  %load = load half, half addrspace(1)* %gep, align 2
215  %v = fpext half %load to float
216  %canonicalized = tail call float @llvm.canonicalize.f32(float %v)
217  %gep2 = getelementptr inbounds float, float addrspace(1)* %out, i32 %id
218  store float %canonicalized, float addrspace(1)* %gep2, align 4
219  ret void
220}
221
222; GCN-LABEL: test_fold_canonicalize_fpextend_value_f32_f16_flushf16:
223; GCN: v_cvt_f32_f16_e32 [[V:v[0-9]+]], v{{[0-9]+}}
224; GCN-NOT: v_mul
225; GCN-NOT: v_max
226; GCN: {{flat|global}}_store_dword v[{{[0-9:]+}}], [[V]]
227define amdgpu_kernel void @test_fold_canonicalize_fpextend_value_f32_f16_flushf16(half addrspace(1)* %arg, float addrspace(1)* %out) #2 {
228  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
229  %gep = getelementptr inbounds half, half addrspace(1)* %arg, i32 %id
230  %load = load half, half addrspace(1)* %gep, align 2
231  %v = fpext half %load to float
232  %canonicalized = tail call float @llvm.canonicalize.f32(float %v)
233  %gep2 = getelementptr inbounds float, float addrspace(1)* %out, i32 %id
234  store float %canonicalized, float addrspace(1)* %gep2, align 4
235  ret void
236}
237
238; GCN-LABEL: test_fold_canonicalize_fpround_value_f32_f64:
239; GCN: v_cvt_f32_f64_e32 [[V:v[0-9]+]], v[{{[0-9:]+}}]
240; GCN-NOT: v_mul
241; GCN-NOT: v_max
242; GCN: {{flat|global}}_store_dword v[{{[0-9:]+}}], [[V]]
243define amdgpu_kernel void @test_fold_canonicalize_fpround_value_f32_f64(double addrspace(1)* %arg, float addrspace(1)* %out) {
244  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
245  %gep = getelementptr inbounds double, double addrspace(1)* %arg, i32 %id
246  %load = load double, double addrspace(1)* %gep, align 8
247  %v = fptrunc double %load to float
248  %canonicalized = tail call float @llvm.canonicalize.f32(float %v)
249  %gep2 = getelementptr inbounds float, float addrspace(1)* %out, i32 %id
250  store float %canonicalized, float addrspace(1)* %gep2, align 4
251  ret void
252}
253
254; GCN-LABEL: test_fold_canonicalize_fpround_value_f16_f32:
255; GCN: v_cvt_f16_f32_e32 [[V:v[0-9]+]], v{{[0-9]+}}
256; GCN-NOT: v_max
257; GCN-NOT: v_mul
258; GCN: {{flat|global}}_store_short v[{{[0-9:]+}}], [[V]]
259define amdgpu_kernel void @test_fold_canonicalize_fpround_value_f16_f32(float addrspace(1)* %arg, half addrspace(1)* %out) {
260  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
261  %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id
262  %load = load float, float addrspace(1)* %gep, align 4
263  %v = fptrunc float %load to half
264  %canonicalized = tail call half @llvm.canonicalize.f16(half %v)
265  %gep2 = getelementptr inbounds half, half addrspace(1)* %out, i32 %id
266  store half %canonicalized, half addrspace(1)* %gep2, align 2
267  ret void
268}
269
270; GCN-LABEL: test_fold_canonicalize_fpround_value_f16_f32_flushf16:
271; GCN: v_cvt_f16_f32_e32 [[V:v[0-9]+]], v{{[0-9]+}}
272; GCN-NOT: v_max
273; GCN-NOT: v_mul
274; GCN: {{flat|global}}_store_short v[{{[0-9:]+}}], [[V]]
275define amdgpu_kernel void @test_fold_canonicalize_fpround_value_f16_f32_flushf16(float addrspace(1)* %arg, half addrspace(1)* %out) #2 {
276  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
277  %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id
278  %load = load float, float addrspace(1)* %gep, align 4
279  %v = fptrunc float %load to half
280  %canonicalized = tail call half @llvm.canonicalize.f16(half %v)
281  %gep2 = getelementptr inbounds half, half addrspace(1)* %out, i32 %id
282  store half %canonicalized, half addrspace(1)* %gep2, align 2
283  ret void
284}
285
286; GCN-LABEL: test_fold_canonicalize_fpround_value_v2f16_v2f32:
287; GCN-DAG: v_cvt_f16_f32_e32 [[V0:v[0-9]+]], v{{[0-9]+}}
288; VI-DAG: v_cvt_f16_f32_sdwa [[V1:v[0-9]+]], v{{[0-9]+}}
289; VI: v_or_b32_e32 [[V:v[0-9]+]], [[V0]], [[V1]]
290; GFX9: v_cvt_f16_f32_e32 [[V1:v[0-9]+]], v{{[0-9]+}}
291; GFX9: v_and_b32_e32 [[V0_16:v[0-9]+]], 0xffff, [[V0]]
292; GFX9: v_lshl_or_b32 [[V:v[0-9]+]], [[V1]], 16, [[V0_16]]
293; GCN-NOT: v_mul
294; GCN-NOT: v_max
295; GCN: {{flat|global}}_store_dword v[{{[0-9:]+}}], [[V]]
296define amdgpu_kernel void @test_fold_canonicalize_fpround_value_v2f16_v2f32(<2 x float> addrspace(1)* %arg, <2 x half> addrspace(1)* %out) {
297  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
298  %gep = getelementptr inbounds <2 x float>, <2 x float> addrspace(1)* %arg, i32 %id
299  %load = load <2 x float>, <2 x float> addrspace(1)* %gep, align 8
300  %v = fptrunc <2 x float> %load to <2 x half>
301  %canonicalized = tail call <2 x half> @llvm.canonicalize.v2f16(<2 x half> %v)
302  %gep2 = getelementptr inbounds <2 x half>, <2 x half> addrspace(1)* %out, i32 %id
303  store <2 x half> %canonicalized, <2 x half> addrspace(1)* %gep2, align 4
304  ret void
305}
306
307; GCN-LABEL: test_no_fold_canonicalize_fneg_value_f32:
308; GCN-FLUSH:  v_mul_f32_e32 v{{[0-9]+}}, -1.0, v{{[0-9]+}}
309; GCN-DENORM: v_max_f32_e64 v{{[0-9]+}}, -v{{[0-9]+}}, -v{{[0-9]+}}
310define amdgpu_kernel void @test_no_fold_canonicalize_fneg_value_f32(float addrspace(1)* %arg) {
311  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
312  %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id
313  %load = load float, float addrspace(1)* %gep, align 4
314  %v = fsub float -0.0, %load
315  %canonicalized = tail call float @llvm.canonicalize.f32(float %v)
316  store float %canonicalized, float addrspace(1)* %gep, align 4
317  ret void
318}
319
320; GCN-LABEL: test_fold_canonicalize_fneg_value_f32:
321; GCN: v_xor_b32_e32 [[V:v[0-9]+]], 0x80000000, v{{[0-9]+}}
322; GCN-NOT: v_mul
323; GCN-NOT: v_max
324; GCN: {{flat|global}}_store_dword v[{{[0-9:]+}}], [[V]]
325define amdgpu_kernel void @test_fold_canonicalize_fneg_value_f32(float addrspace(1)* %arg) {
326  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
327  %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id
328  %load = load float, float addrspace(1)* %gep, align 4
329  %v0 = fadd float %load, 0.0
330  %v = fsub float -0.0, %v0
331  %canonicalized = tail call float @llvm.canonicalize.f32(float %v)
332  store float %canonicalized, float addrspace(1)* %gep, align 4
333  ret void
334}
335
336; GCN-LABEL: test_no_fold_canonicalize_fabs_value_f32:
337; GCN-FLUSH:  v_mul_f32_e64 v{{[0-9]+}}, 1.0, |v{{[0-9]+}}|
338; GCN-DENORM: v_max_f32_e64 v{{[0-9]+}}, |v{{[0-9]+}}|, |v{{[0-9]+}}|
339define amdgpu_kernel void @test_no_fold_canonicalize_fabs_value_f32(float addrspace(1)* %arg) {
340  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
341  %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id
342  %load = load float, float addrspace(1)* %gep, align 4
343  %v = tail call float @llvm.fabs.f32(float %load)
344  %canonicalized = tail call float @llvm.canonicalize.f32(float %v)
345  store float %canonicalized, float addrspace(1)* %gep, align 4
346  ret void
347}
348
349; GCN-LABEL: test_no_fold_canonicalize_fcopysign_value_f32:
350; GCN-FLUSH:  v_mul_f32_e64 v{{[0-9]+}}, 1.0, |v{{[0-9]+}}|
351; GCN-DENORM: v_max_f32_e64 v{{[0-9]+}}, |v{{[0-9]+}}|, |v{{[0-9]+}}|
352; GCN-NOT: v_mul_
353; GCN-NOT: v_max_
354define amdgpu_kernel void @test_no_fold_canonicalize_fcopysign_value_f32(float addrspace(1)* %arg, float %sign) {
355  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
356  %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id
357  %load = load float, float addrspace(1)* %gep, align 4
358  %canon.load = tail call float @llvm.canonicalize.f32(float %load)
359  %copysign = call float @llvm.copysign.f32(float %canon.load, float %sign)
360  %v = tail call float @llvm.fabs.f32(float %load)
361  %canonicalized = tail call float @llvm.canonicalize.f32(float %v)
362  store float %canonicalized, float addrspace(1)* %gep, align 4
363  ret void
364}
365
366; GCN-LABEL: test_fold_canonicalize_fabs_value_f32:
367; GCN: v_and_b32_e32 [[V:v[0-9]+]], 0x7fffffff, v{{[0-9]+}}
368; GCN-NOT: v_mul
369; GCN-NOT: v_max
370; GCN: {{flat|global}}_store_dword v[{{[0-9:]+}}], [[V]]
371define amdgpu_kernel void @test_fold_canonicalize_fabs_value_f32(float addrspace(1)* %arg) {
372  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
373  %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id
374  %load = load float, float addrspace(1)* %gep, align 4
375  %v0 = fadd float %load, 0.0
376  %v = tail call float @llvm.fabs.f32(float %v0)
377  %canonicalized = tail call float @llvm.canonicalize.f32(float %v)
378  store float %canonicalized, float addrspace(1)* %gep, align 4
379  ret void
380}
381
382; GCN-LABEL: test_fold_canonicalize_sin_value_f32:
383; GCN: v_sin_f32_e32 [[V:v[0-9]+]], v{{[0-9]+}}
384; GCN-NOT: v_mul
385; GCN-NOT: v_max
386; GCN: {{flat|global}}_store_dword v[{{[0-9:]+}}], [[V]]
387define amdgpu_kernel void @test_fold_canonicalize_sin_value_f32(float addrspace(1)* %arg) {
388  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
389  %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id
390  %load = load float, float addrspace(1)* %gep, align 4
391  %v = tail call float @llvm.sin.f32(float %load)
392  %canonicalized = tail call float @llvm.canonicalize.f32(float %v)
393  store float %canonicalized, float addrspace(1)* %gep, align 4
394  ret void
395}
396
397; GCN-LABEL: test_fold_canonicalize_cos_value_f32:
398; GCN: v_cos_f32_e32 [[V:v[0-9]+]], v{{[0-9]+}}
399; GCN-NOT: v_mul
400; GCN-NOT: v_max
401; GCN: {{flat|global}}_store_dword v[{{[0-9:]+}}], [[V]]
402define amdgpu_kernel void @test_fold_canonicalize_cos_value_f32(float addrspace(1)* %arg) {
403  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
404  %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id
405  %load = load float, float addrspace(1)* %gep, align 4
406  %v = tail call float @llvm.cos.f32(float %load)
407  %canonicalized = tail call float @llvm.canonicalize.f32(float %v)
408  store float %canonicalized, float addrspace(1)* %gep, align 4
409  ret void
410}
411
412; GCN-LABEL: test_fold_canonicalize_sin_value_f16:
413; GCN: v_sin_f32_e32 [[V0:v[0-9]+]], v{{[0-9]+}}
414; GCN: v_cvt_f16_f32_e32 [[V:v[0-9]+]], [[V0]]
415; GCN-NOT: v_mul
416; GCN-NOT: v_max
417; GCN: {{flat|global}}_store_short v[{{[0-9:]+}}], [[V]]
418define amdgpu_kernel void @test_fold_canonicalize_sin_value_f16(half addrspace(1)* %arg) {
419  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
420  %gep = getelementptr inbounds half, half addrspace(1)* %arg, i32 %id
421  %load = load half, half addrspace(1)* %gep, align 2
422  %v = tail call half @llvm.sin.f16(half %load)
423  %canonicalized = tail call half @llvm.canonicalize.f16(half %v)
424  store half %canonicalized, half addrspace(1)* %gep, align 2
425  ret void
426}
427
428; GCN-LABEL: test_fold_canonicalize_cos_value_f16:
429; GCN: v_cos_f32_e32 [[V0:v[0-9]+]], v{{[0-9]+}}
430; GCN: v_cvt_f16_f32_e32 [[V:v[0-9]+]], [[V0]]
431; GCN-NOT: v_mul
432; GCN-NOT: v_max
433; GCN: {{flat|global}}_store_short v[{{[0-9:]+}}], [[V]]
434define amdgpu_kernel void @test_fold_canonicalize_cos_value_f16(half addrspace(1)* %arg) {
435  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
436  %gep = getelementptr inbounds half, half addrspace(1)* %arg, i32 %id
437  %load = load half, half addrspace(1)* %gep, align 2
438  %v = tail call half @llvm.cos.f16(half %load)
439  %canonicalized = tail call half @llvm.canonicalize.f16(half %v)
440  store half %canonicalized, half addrspace(1)* %gep, align 2
441  ret void
442}
443
444; GCN-LABEL: test_fold_canonicalize_qNaN_value_f32:
445; GCN: v_mov_b32_e32 [[V:v[0-9]+]], 0x7fc00000
446; GCN-NOT: v_mul
447; GCN-NOT: v_max
448; GCN: {{flat|global}}_store_dword v[{{[0-9:]+}}], [[V]]
449define amdgpu_kernel void @test_fold_canonicalize_qNaN_value_f32(float addrspace(1)* %arg) {
450  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
451  %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id
452  %canonicalized = tail call float @llvm.canonicalize.f32(float 0x7FF8000000000000)
453  store float %canonicalized, float addrspace(1)* %gep, align 4
454  ret void
455}
456
457; GCN-LABEL: test_fold_canonicalize_minnum_value_from_load_f32_ieee_mode:
458; GCN: {{flat|global}}_load_dword [[VAL:v[0-9]+]]
459; GCN-FLUSH: v_mul_f32_e32 [[QUIET:v[0-9]+]], 1.0, [[VAL]]
460; GCN-DENORM: v_max_f32_e32 [[QUIET:v[0-9]+]], [[VAL]], [[VAL]]
461; GCN: v_min_f32_e32 [[V:v[0-9]+]], 0, [[QUIET]]
462
463; GCN-NOT: v_max
464; GCN-NOT: v_mul
465
466; GFX9: {{flat|global}}_store_dword v[{{[0-9:]+}}], [[V]]
467define amdgpu_kernel void @test_fold_canonicalize_minnum_value_from_load_f32_ieee_mode(float addrspace(1)* %arg) {
468  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
469  %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id
470  %load = load float, float addrspace(1)* %gep, align 4
471  %v = tail call float @llvm.minnum.f32(float %load, float 0.0)
472  %canonicalized = tail call float @llvm.canonicalize.f32(float %v)
473  store float %canonicalized, float addrspace(1)* %gep, align 4
474  ret void
475}
476
477; GCN-LABEL: test_fold_canonicalize_minnum_value_from_load_f32_nnan_ieee_mode:
478; VI-FLUSH: v_mul_f32_e32 v{{[0-9]+}}, 1.0, v{{[0-9]+}}
479; GCN-DENORM-NOT: v_max
480; GCN-DENORM-NOT: v_mul
481
482; GCN: v_min_f32_e32 v{{[0-9]+}}, 0, v{{[0-9]+}}
483; GCN-DENORM-NOT: v_max
484; GCN-DENORM-NOT: v_mul
485
486; GFX9: {{flat|global}}_store_dword v[{{[0-9:]+}}]
487define amdgpu_kernel void @test_fold_canonicalize_minnum_value_from_load_f32_nnan_ieee_mode(float addrspace(1)* %arg) #1 {
488  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
489  %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id
490  %load = load float, float addrspace(1)* %gep, align 4
491  %v = tail call float @llvm.minnum.f32(float %load, float 0.0)
492  %canonicalized = tail call float @llvm.canonicalize.f32(float %v)
493  store float %canonicalized, float addrspace(1)* %gep, align 4
494  ret void
495}
496
497; GCN-LABEL: test_fold_canonicalize_minnum_value_f32:
498; GCN: v_min_f32_e32 [[V:v[0-9]+]], 0, v{{[0-9]+}}
499; GCN-NOT: v_mul
500; GCN-NOT: v_max
501; GCN: {{flat|global}}_store_dword v[{{[0-9:]+}}], [[V]]
502define amdgpu_kernel void @test_fold_canonicalize_minnum_value_f32(float addrspace(1)* %arg) {
503  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
504  %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id
505  %load = load float, float addrspace(1)* %gep, align 4
506  %v0 = fadd float %load, 0.0
507  %v = tail call float @llvm.minnum.f32(float %v0, float 0.0)
508  %canonicalized = tail call float @llvm.canonicalize.f32(float %v)
509  store float %canonicalized, float addrspace(1)* %gep, align 4
510  ret void
511}
512
513; FIXME: Should there be more checks here? minnum with NaN operand is simplified away.
514
515; GCN-LABEL: test_fold_canonicalize_sNaN_value_f32:
516; GCN: {{flat|global}}_load_dword [[LOAD:v[0-9]+]]
517; GCN-FLUSH: v_mul_f32_e32 v{{[0-9]+}}, 1.0, [[LOAD]]
518; GCN-DENORM: v_max_f32_e32 v{{[0-9]+}}, [[LOAD]], [[LOAD]]
519define amdgpu_kernel void @test_fold_canonicalize_sNaN_value_f32(float addrspace(1)* %arg) {
520  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
521  %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id
522  %load = load float, float addrspace(1)* %gep, align 4
523  %v = tail call float @llvm.minnum.f32(float %load, float bitcast (i32 2139095041 to float))
524  %canonicalized = tail call float @llvm.canonicalize.f32(float %v)
525  store float %canonicalized, float addrspace(1)* %gep, align 4
526  ret void
527}
528
529; GCN-LABEL: test_fold_canonicalize_denorm_value_f32:
530; GCN: {{flat|global}}_load_dword [[VAL:v[0-9]+]]
531
532; GFX9-DENORM: v_max_f32_e32 [[QUIET:v[0-9]+]], [[VAL]], [[VAL]]
533; GFX9-DENORM: v_min_f32_e32 [[RESULT:v[0-9]+]], 0x7fffff, [[QUIET]]
534
535; GFX9-FLUSH: v_mul_f32_e32 [[QUIET:v[0-9]+]], 1.0, [[VAL]]
536; GFX9-FLUSH: v_min_f32_e32 [[RESULT:v[0-9]+]], 0, [[QUIET]]
537
538
539; VI-FLUSH: v_mul_f32_e32 [[QUIET_V0:v[0-9]+]], 1.0, [[VAL]]
540; VI-FLUSH: v_min_f32_e32 [[RESULT:v[0-9]+]], 0, [[QUIET_V0]]
541
542; VI-DENORM: v_min_f32_e32 [[RESULT:v[0-9]+]], 0x7fffff, [[VAL]]
543
544; GCN-NOT: v_mul
545; GCN-NOT: v_max
546; GCN:   {{flat|global}}_store_dword v[{{[0-9:]+}}], [[RESULT]]
547define amdgpu_kernel void @test_fold_canonicalize_denorm_value_f32(float addrspace(1)* %arg) {
548  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
549  %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id
550  %load = load float, float addrspace(1)* %gep, align 4
551  %v = tail call float @llvm.minnum.f32(float %load, float bitcast (i32 8388607 to float))
552  %canonicalized = tail call float @llvm.canonicalize.f32(float %v)
553  store float %canonicalized, float addrspace(1)* %gep, align 4
554  ret void
555}
556
557; GCN-LABEL: test_fold_canonicalize_maxnum_value_from_load_f32_ieee_mode:
558; GCN: {{flat|global}}_load_dword [[VAL:v[0-9]+]]
559
560; GFX9:  v_max_f32_e32 [[RESULT:v[0-9]+]], 0, [[VAL]]
561
562; VI-FLUSH:    v_mul_f32_e32 [[QUIET:v[0-9]+]], 1.0, [[VAL]]
563; VI-FLUSH:    v_max_f32_e32 [[RESULT:v[0-9]+]], 0, [[QUIET]]
564
565; VI-DENORM: v_max_f32_e32 [[RESULT:v[0-9]+]], 0, [[VAL]]
566
567; GCN-NOT: v_mul
568; GCN-NOT: v_max
569; GCN:  {{flat|global}}_store_dword v[{{[0-9:]+}}], [[RESULT]]
570define amdgpu_kernel void @test_fold_canonicalize_maxnum_value_from_load_f32_ieee_mode(float addrspace(1)* %arg) {
571  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
572  %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id
573  %load = load float, float addrspace(1)* %gep, align 4
574  %v = tail call float @llvm.maxnum.f32(float %load, float 0.0)
575  %canonicalized = tail call float @llvm.canonicalize.f32(float %v)
576  store float %canonicalized, float addrspace(1)* %gep, align 4
577  ret void
578}
579
580; GCN-LABEL: test_fold_canonicalize_maxnum_value_f32:
581; GCN: v_max_f32_e32 [[V:v[0-9]+]], 0, v{{[0-9]+}}
582; GCN-NOT: v_max
583; GCN-NOT: v_mul
584; GCN: {{flat|global}}_store_dword v[{{[0-9:]+}}], [[V]]
585define amdgpu_kernel void @test_fold_canonicalize_maxnum_value_f32(float addrspace(1)* %arg) {
586  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
587  %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id
588  %load = load float, float addrspace(1)* %gep, align 4
589  %v0 = fadd float %load, 0.0
590  %v = tail call float @llvm.maxnum.f32(float %v0, float 0.0)
591  %canonicalized = tail call float @llvm.canonicalize.f32(float %v)
592  store float %canonicalized, float addrspace(1)* %gep, align 4
593  ret void
594}
595
596; GCN-LABEL: test_fold_canonicalize_maxnum_value_f64:
597; GCN: v_max_f64 [[V:v\[[0-9]+:[0-9]+\]]], v[{{[0-9:]+}}], 0
598; GCN-NOT: v_mul
599; GCN-NOT: v_max
600; GCN: {{flat|global}}_store_dwordx2 v[{{[0-9:]+}}], [[V]]
601define amdgpu_kernel void @test_fold_canonicalize_maxnum_value_f64(double addrspace(1)* %arg) {
602  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
603  %gep = getelementptr inbounds double, double addrspace(1)* %arg, i32 %id
604  %load = load double, double addrspace(1)* %gep, align 8
605  %v0 = fadd double %load, 0.0
606  %v = tail call double @llvm.maxnum.f64(double %v0, double 0.0)
607  %canonicalized = tail call double @llvm.canonicalize.f64(double %v)
608  store double %canonicalized, double addrspace(1)* %gep, align 8
609  ret void
610}
611
612; GCN-LABEL: test_fold_canonicalize_fmul_value_f32_no_ieee:
613; GCN: v_mul_f32_e32 [[V:v[0-9]+]], 0x41700000, v{{[0-9]+}}
614; GCN-NOT: v_mul
615; GCN-NOT: v_max
616; GCN-NEXT: ; return
617define amdgpu_ps float @test_fold_canonicalize_fmul_value_f32_no_ieee(float %arg) {
618entry:
619  %v = fmul float %arg, 15.0
620  %canonicalized = tail call float @llvm.canonicalize.f32(float %v)
621  ret float %canonicalized
622}
623
624; GCN-LABEL: test_fold_canonicalize_fmul_nnan_value_f32_no_ieee:
625; GCN: v_mul_f32_e32 [[V:v[0-9]+]], 0x41700000, v{{[0-9]+}}
626; GCN-NOT: v_mul
627; GCN-NOT: v_max
628; GCN-NEXT: ; return
629define amdgpu_ps float @test_fold_canonicalize_fmul_nnan_value_f32_no_ieee(float %arg) {
630entry:
631  %v = fmul nnan float %arg, 15.0
632  %canonicalized = tail call float @llvm.canonicalize.f32(float %v)
633  ret float %canonicalized
634}
635
636; GCN-LABEL: {{^}}test_fold_canonicalize_fdiv_value_f32_no_ieee:
637; GCN: v_div_fixup_f32
638; GCN-NOT: v_max
639; GCN-NOT: v_mul
640; GCN: ; return
641define amdgpu_ps float @test_fold_canonicalize_fdiv_value_f32_no_ieee(float %arg0) {
642entry:
643  %v = fdiv float 15.0, %arg0
644  %canonicalized = tail call float @llvm.canonicalize.f32(float %v)
645  ret float %canonicalized
646}
647
648; GCN-LABEL: {{^}}test_fold_canonicalize_load_nnan_value_f32
649; GFX9-DENORM: global_load_dword [[V:v[0-9]+]],
650; GFX9-DENORM: global_store_dword v[{{[0-9:]+}}], [[V]]
651; GFX9-DENORM-NOT: 1.0
652; GCN-FLUSH: v_mul_f32_e32 v{{[0-9]+}}, 1.0, v{{[0-9]+}}
653define amdgpu_kernel void @test_fold_canonicalize_load_nnan_value_f32(float addrspace(1)* %arg, float addrspace(1)* %out) #1 {
654  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
655  %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id
656  %v = load float, float addrspace(1)* %gep, align 4
657  %canonicalized = tail call float @llvm.canonicalize.f32(float %v)
658  %gep2 = getelementptr inbounds float, float addrspace(1)* %out, i32 %id
659  store float %canonicalized, float addrspace(1)* %gep2, align 4
660  ret void
661}
662
663; GCN-LABEL: {{^}}test_fold_canonicalize_load_nnan_value_f64
664; GCN: {{flat|global}}_load_dwordx2 [[V:v\[[0-9:]+\]]],
665; GCN: {{flat|global}}_store_dwordx2 v[{{[0-9:]+}}], [[V]]
666; GCN-NOT: v_mul_
667; GCN-NOT: v_max_
668define amdgpu_kernel void @test_fold_canonicalize_load_nnan_value_f64(double addrspace(1)* %arg, double addrspace(1)* %out) #1 {
669  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
670  %gep = getelementptr inbounds double, double addrspace(1)* %arg, i32 %id
671  %v = load double, double addrspace(1)* %gep, align 8
672  %canonicalized = tail call double @llvm.canonicalize.f64(double %v)
673  %gep2 = getelementptr inbounds double, double addrspace(1)* %out, i32 %id
674  store double %canonicalized, double addrspace(1)* %gep2, align 8
675  ret void
676}
677
678; GCN-LABEL: {{^}}test_fold_canonicalize_load_nnan_value_f16
679; GCN: {{flat|global}}_load_ushort [[V:v[0-9]+]],
680; GCN-NOT: v_mul
681; GCN-NOT: v_max
682; GCN: {{flat|global}}_store_short v{{\[[0-9]+:[0-9]+\]}}, [[V]]
683define amdgpu_kernel void @test_fold_canonicalize_load_nnan_value_f16(half addrspace(1)* %arg, half addrspace(1)* %out) #1 {
684  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
685  %gep = getelementptr inbounds half, half addrspace(1)* %arg, i32 %id
686  %v = load half, half addrspace(1)* %gep, align 2
687  %canonicalized = tail call half @llvm.canonicalize.f16(half %v)
688  %gep2 = getelementptr inbounds half, half addrspace(1)* %out, i32 %id
689  store half %canonicalized, half addrspace(1)* %gep2, align 2
690  ret void
691}
692
693; GCN-LABEL: {{^}}test_fold_canonicalize_select_value_f32:
694; GCN: v_add_f32
695; GCN: v_add_f32
696; GCN: v_cndmask_b32
697; GCN-NOT: v_mul_
698; GCN-NOT: v_max_
699define amdgpu_kernel void @test_fold_canonicalize_select_value_f32(float addrspace(1)* %arg) {
700  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
701  %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id
702  %load0 = load volatile float, float addrspace(1)* %gep, align 4
703  %load1 = load volatile float, float addrspace(1)* %gep, align 4
704  %load2 = load volatile i32, i32 addrspace(1)* undef, align 4
705  %v0 = fadd float %load0, 15.0
706  %v1 = fadd float %load1, 32.0
707  %cond = icmp eq i32 %load2, 0
708  %select = select i1 %cond, float %v0, float %v1
709  %canonicalized = tail call float @llvm.canonicalize.f32(float %select)
710  store float %canonicalized, float addrspace(1)* %gep, align 4
711  ret void
712}
713
714; Need to quiet the nan with a separate instruction since it will be
715; passed through the minnum.
716; FIXME: canonicalize doens't work correctly without ieee_mode
717
718; GCN-LABEL: {{^}}test_fold_canonicalize_minnum_value_no_ieee_mode:
719; GFX9-NOT: v0
720; GFX9-NOT: v1
721; GFX9: v_min_f32_e32 v0, v0, v1
722; GFX9-NEXT: ; return to shader
723
724; VI-FLUSH: v_min_f32_e32 v0, v0, v1
725; VI-FLUSH-NEXT: v_mul_f32_e32 v0, 1.0, v0
726; VI-FLUSH-NEXT: ; return
727
728; VI-DENORM-NOT: v0
729; VI-DENORM: v_min_f32_e32 v0, v0, v1
730; VI-DENORM-NEXT: ; return
731define amdgpu_ps float @test_fold_canonicalize_minnum_value_no_ieee_mode(float %arg0, float %arg1) {
732  %v = tail call float @llvm.minnum.f32(float %arg0, float %arg1)
733  %canonicalized = tail call float @llvm.canonicalize.f32(float %v)
734  ret float %canonicalized
735}
736
737; GCN-LABEL: {{^}}test_fold_canonicalize_minnum_value_ieee_mode:
738; GFX9: v_min_f32_e32 v0, v0, v1
739; GFX9-NEXT: s_setpc_b64
740
741; VI-FLUSH-DAG: v_mul_f32_e32 v0, 1.0, v0
742; VI-FLUSH-DAG: v_mul_f32_e32 v1, 1.0, v1
743; VI-FLUSH: v_min_f32_e32 v0, v0, v1
744
745; VI-DENORM-DAG: v_max_f32_e32 v0, v0, v0
746; VI-DENORM-DAG: v_max_f32_e32 v1, v1, v1
747; VI-DENORM: v_min_f32_e32 v0, v0, v1
748
749; VI-NEXT: s_setpc_b64
750define float @test_fold_canonicalize_minnum_value_ieee_mode(float %arg0, float %arg1) {
751  %v = tail call float @llvm.minnum.f32(float %arg0, float %arg1)
752  %canonicalized = tail call float @llvm.canonicalize.f32(float %v)
753  ret float %canonicalized
754}
755
756; Canonicalizing flush necessary pre-gfx9
757; GCN-LABEL: {{^}}test_fold_canonicalize_minnum_value_no_ieee_mode_nnan:
758; GCN: v_min_f32_e32 v0, v0, v1
759; VI-FLUSH-NEXT: v_mul_f32_e32 v0, 1.0, v0
760; GCN-NEXT: ; return
761define amdgpu_ps float @test_fold_canonicalize_minnum_value_no_ieee_mode_nnan(float %arg0, float %arg1) #1 {
762  %v = tail call float @llvm.minnum.f32(float %arg0, float %arg1)
763  %canonicalized = tail call float @llvm.canonicalize.f32(float %v)
764  ret float %canonicalized
765}
766
767; GCN-LABEL: {{^}}v_test_canonicalize_build_vector_v2f16:
768; GFX9-DAG: v_add_f16_e32
769; GFX9-DAG: v_mul_f16_e32
770; GFX9-NOT: v_max
771; GFX9-NOT: v_pk_max
772define <2 x half> @v_test_canonicalize_build_vector_v2f16(<2 x half> %vec) {
773  %lo = extractelement <2 x half> %vec, i32 0
774  %hi = extractelement <2 x half> %vec, i32 1
775  %lo.op = fadd half %lo, 1.0
776  %hi.op = fmul half %lo, 4.0
777  %ins0 = insertelement <2 x half> undef, half %lo.op, i32 0
778  %ins1 = insertelement <2 x half> %ins0, half %hi.op, i32 1
779  %canonicalized = call <2 x half> @llvm.canonicalize.v2f16(<2 x half> %ins1)
780  ret <2 x half> %canonicalized
781}
782
783; GCN-LABEL: {{^}}v_test_canonicalize_build_vector_noncanon1_v2f16:
784; GFX9: v_add_f16_e32
785; GFX9: v_pk_max
786define <2 x half> @v_test_canonicalize_build_vector_noncanon1_v2f16(<2 x half> %vec) {
787  %lo = extractelement <2 x half> %vec, i32 0
788  %lo.op = fadd half %lo, 1.0
789  %ins = insertelement <2 x half> %vec, half %lo.op, i32 0
790  %canonicalized = call <2 x half> @llvm.canonicalize.v2f16(<2 x half> %ins)
791  ret <2 x half> %canonicalized
792}
793
794; GCN-LABEL: {{^}}v_test_canonicalize_build_vector_noncanon0_v2f16:
795; GFX9: v_add_f16_sdwa
796; GFX9: v_pk_max
797define <2 x half> @v_test_canonicalize_build_vector_noncanon0_v2f16(<2 x half> %vec) {
798  %hi = extractelement <2 x half> %vec, i32 1
799  %hi.op = fadd half %hi, 1.0
800  %ins = insertelement <2 x half> %vec, half %hi.op, i32 1
801  %canonicalized = call <2 x half> @llvm.canonicalize.v2f16(<2 x half> %ins)
802  ret <2 x half> %canonicalized
803}
804
805; GCN-LABEL: {{^}}v_test_canonicalize_extract_element_v2f16:
806; GFX9: s_waitcnt
807; GFX9-NEXT: v_mul_f16_e32 v0, 4.0, v0
808; GFX9-NEXT: s_setpc_b64
809define half @v_test_canonicalize_extract_element_v2f16(<2 x half> %vec) {
810  %vec.op = fmul <2 x half> %vec, <half 4.0, half 4.0>
811  %elt = extractelement <2 x half> %vec.op, i32 0
812  %canonicalized = call half @llvm.canonicalize.f16(half %elt)
813  ret half %canonicalized
814}
815
816; GCN-LABEL: {{^}}v_test_canonicalize_insertelement_v2f16:
817; GFX9: v_pk_mul_f16
818; GFX9: v_mul_f16_e32
819; GFX9-NOT: v_max
820; GFX9-NOT: v_pk_max
821define <2 x half> @v_test_canonicalize_insertelement_v2f16(<2 x half> %vec, half %val, i32 %idx) {
822  %vec.op = fmul <2 x half> %vec, <half 4.0, half 4.0>
823  %ins.op = fmul half %val, 8.0
824  %ins = insertelement <2 x half> %vec.op, half %ins.op, i32 %idx
825  %canonicalized = call <2 x half> @llvm.canonicalize.v2f16(<2 x half> %ins)
826  ret <2 x half> %canonicalized
827}
828
829; GCN-LABEL: {{^}}v_test_canonicalize_insertelement_noncanon_vec_v2f16:
830; GFX9: v_mul_f16
831; GFX9: v_pk_max_f16 v0, v0, v0
832; GFX9-NEXT: s_setpc_b64
833define <2 x half> @v_test_canonicalize_insertelement_noncanon_vec_v2f16(<2 x half> %vec, half %val, i32 %idx) {
834  %ins.op = fmul half %val, 8.0
835  %ins = insertelement <2 x half> %vec, half %ins.op, i32 %idx
836  %canonicalized = call <2 x half> @llvm.canonicalize.v2f16(<2 x half> %ins)
837  ret <2 x half> %canonicalized
838}
839
840; GCN-LABEL: {{^}}v_test_canonicalize_insertelement_noncanon_insval_v2f16:
841; GFX9: v_pk_mul_f16
842; GFX9: v_pk_max_f16 v0, v0, v0
843; GFX9-NEXT: s_setpc_b64
844define <2 x half> @v_test_canonicalize_insertelement_noncanon_insval_v2f16(<2 x half> %vec, half %val, i32 %idx) {
845  %vec.op = fmul <2 x half> %vec, <half 4.0, half 4.0>
846  %ins = insertelement <2 x half> %vec.op, half %val, i32 %idx
847  %canonicalized = call <2 x half> @llvm.canonicalize.v2f16(<2 x half> %ins)
848  ret <2 x half> %canonicalized
849}
850
851; GCN-LABEL: {{^}}v_test_canonicalize_cvt_pkrtz:
852; GCN: s_waitcnt
853; GCN-NEXT: v_cvt_pkrtz_f16_f32 v0, v0, v1
854; GCN-NEXT: s_setpc_b64
855define <2 x half> @v_test_canonicalize_cvt_pkrtz(float %a, float %b) {
856  %cvt = call <2 x half> @llvm.amdgcn.cvt.pkrtz(float %a, float %b)
857  %canonicalized = call <2 x half> @llvm.canonicalize.v2f16(<2 x half> %cvt)
858  ret <2 x half> %canonicalized
859}
860
861; GCN-LABEL: {{^}}v_test_canonicalize_cubeid:
862; GCN: s_waitcnt
863; GCN-NEXT: v_cubeid_f32 v0, v0, v1, v2
864; GCN-NEXT: s_setpc_b64
865define float @v_test_canonicalize_cubeid(float %a, float %b, float %c) {
866  %cvt = call float @llvm.amdgcn.cubeid(float %a, float %b, float %c)
867  %canonicalized = call float @llvm.canonicalize.f32(float %cvt)
868  ret float %canonicalized
869}
870
871; GCN-LABEL: {{^}}v_test_canonicalize_frexp_mant:
872; GCN: s_waitcnt
873; GCN-NEXT: v_frexp_mant_f32_e32 v0, v0
874; GCN-NEXT: s_setpc_b64
875define float @v_test_canonicalize_frexp_mant(float %a) {
876  %cvt = call float @llvm.amdgcn.frexp.mant.f32(float %a)
877  %canonicalized = call float @llvm.canonicalize.f32(float %cvt)
878  ret float %canonicalized
879}
880
881; Avoid failing the test on FreeBSD11.0 which will match the GCN-NOT: 1.0
882; in the .amd_amdgpu_isa "amdgcn-unknown-freebsd11.0--gfx802" directive
883; CHECK: .amd_amdgpu_isa
884
885declare float @llvm.canonicalize.f32(float) #0
886declare float @llvm.copysign.f32(float, float) #0
887declare float @llvm.amdgcn.fmul.legacy(float, float) #0
888declare float @llvm.amdgcn.fmad.ftz.f32(float, float, float) #0
889declare double @llvm.canonicalize.f64(double) #0
890declare half @llvm.canonicalize.f16(half) #0
891declare <2 x half> @llvm.canonicalize.v2f16(<2 x half>) #0
892declare i32 @llvm.amdgcn.workitem.id.x() #0
893declare float @llvm.sqrt.f32(float) #0
894declare float @llvm.ceil.f32(float) #0
895declare float @llvm.floor.f32(float) #0
896declare float @llvm.fma.f32(float, float, float) #0
897declare float @llvm.fmuladd.f32(float, float, float) #0
898declare float @llvm.fabs.f32(float) #0
899declare float @llvm.sin.f32(float) #0
900declare float @llvm.cos.f32(float) #0
901declare half @llvm.sin.f16(half) #0
902declare half @llvm.cos.f16(half) #0
903declare float @llvm.minnum.f32(float, float) #0
904declare float @llvm.maxnum.f32(float, float) #0
905declare double @llvm.maxnum.f64(double, double) #0
906declare <2 x half> @llvm.amdgcn.cvt.pkrtz(float, float) #0
907declare float @llvm.amdgcn.cubeid(float, float, float) #0
908declare float @llvm.amdgcn.frexp.mant.f32(float) #0
909
910attributes #0 = { nounwind readnone }
911attributes #1 = { "no-nans-fp-math"="true" }
912attributes #2 = { "target-features"="-fp64-fp16-denormals" }
913