1; RUN: llc -march=amdgcn -mcpu=gfx801 -verify-machineinstrs -denormal-fp-math-f32=preserve-sign < %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=+fp-exceptions -denormal-fp-math-f32=preserve-sign < %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 -denormal-fp-math-f32=ieee < %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 -denormal-fp-math-f32=ieee < %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 -denormal-fp-math-f32=preserve-sign < %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: v_mov_b32_e32 [[V:v[0-9]+]], 0x41700000
141; GCN: v_mac_f32_e32 [[V]], v{{[0-9]+}}, v{{[0-9]+$}}
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_f16_e32 [[V0:v[0-9]+]], v{{[0-9]+}}
414; GCN-NOT: v_mul
415; GCN-NOT: v_max
416; GCN: {{flat|global}}_store_short v[{{[0-9:]+}}], [[V0]]
417define amdgpu_kernel void @test_fold_canonicalize_sin_value_f16(half addrspace(1)* %arg) {
418  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
419  %gep = getelementptr inbounds half, half addrspace(1)* %arg, i32 %id
420  %load = load half, half addrspace(1)* %gep, align 2
421  %v = tail call half @llvm.sin.f16(half %load)
422  %canonicalized = tail call half @llvm.canonicalize.f16(half %v)
423  store half %canonicalized, half addrspace(1)* %gep, align 2
424  ret void
425}
426
427; GCN-LABEL: test_fold_canonicalize_cos_value_f16:
428; GCN: v_cos_f16_e32 [[V0:v[0-9]+]], v{{[0-9]+}}
429; GCN-NOT: v_mul
430; GCN-NOT: v_max
431; GCN: {{flat|global}}_store_short v[{{[0-9:]+}}], [[V0]]
432define amdgpu_kernel void @test_fold_canonicalize_cos_value_f16(half addrspace(1)* %arg) {
433  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
434  %gep = getelementptr inbounds half, half addrspace(1)* %arg, i32 %id
435  %load = load half, half addrspace(1)* %gep, align 2
436  %v = tail call half @llvm.cos.f16(half %load)
437  %canonicalized = tail call half @llvm.canonicalize.f16(half %v)
438  store half %canonicalized, half addrspace(1)* %gep, align 2
439  ret void
440}
441
442; GCN-LABEL: test_fold_canonicalize_qNaN_value_f32:
443; GCN: v_mov_b32_e32 [[V:v[0-9]+]], 0x7fc00000
444; GCN-NOT: v_mul
445; GCN-NOT: v_max
446; GCN: {{flat|global}}_store_dword v[{{[0-9:]+}}], [[V]]
447define amdgpu_kernel void @test_fold_canonicalize_qNaN_value_f32(float addrspace(1)* %arg) {
448  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
449  %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id
450  %canonicalized = tail call float @llvm.canonicalize.f32(float 0x7FF8000000000000)
451  store float %canonicalized, float addrspace(1)* %gep, align 4
452  ret void
453}
454
455; GCN-LABEL: test_fold_canonicalize_minnum_value_from_load_f32_ieee_mode:
456; GCN: {{flat|global}}_load_dword [[VAL:v[0-9]+]]
457; GCN-FLUSH: v_mul_f32_e32 [[QUIET:v[0-9]+]], 1.0, [[VAL]]
458; GCN-DENORM: v_max_f32_e32 [[QUIET:v[0-9]+]], [[VAL]], [[VAL]]
459; GCN: v_min_f32_e32 [[V:v[0-9]+]], 0, [[QUIET]]
460
461; GCN-NOT: v_max
462; GCN-NOT: v_mul
463
464; GFX9: {{flat|global}}_store_dword v[{{[0-9:]+}}], [[V]]
465define amdgpu_kernel void @test_fold_canonicalize_minnum_value_from_load_f32_ieee_mode(float addrspace(1)* %arg) {
466  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
467  %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id
468  %load = load float, float addrspace(1)* %gep, align 4
469  %v = tail call float @llvm.minnum.f32(float %load, float 0.0)
470  %canonicalized = tail call float @llvm.canonicalize.f32(float %v)
471  store float %canonicalized, float addrspace(1)* %gep, align 4
472  ret void
473}
474
475; GCN-LABEL: test_fold_canonicalize_minnum_value_from_load_f32_nnan_ieee_mode:
476; VI-FLUSH: v_mul_f32_e32 v{{[0-9]+}}, 1.0, v{{[0-9]+}}
477; GCN-DENORM-NOT: v_max
478; GCN-DENORM-NOT: v_mul
479
480; GCN: v_min_f32_e32 v{{[0-9]+}}, 0, v{{[0-9]+}}
481; GCN-DENORM-NOT: v_max
482; GCN-DENORM-NOT: v_mul
483
484; GFX9: {{flat|global}}_store_dword v[{{[0-9:]+}}]
485define amdgpu_kernel void @test_fold_canonicalize_minnum_value_from_load_f32_nnan_ieee_mode(float addrspace(1)* %arg) #1 {
486  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
487  %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id
488  %load = load float, float addrspace(1)* %gep, align 4
489  %v = tail call float @llvm.minnum.f32(float %load, float 0.0)
490  %canonicalized = tail call float @llvm.canonicalize.f32(float %v)
491  store float %canonicalized, float addrspace(1)* %gep, align 4
492  ret void
493}
494
495; GCN-LABEL: test_fold_canonicalize_minnum_value_f32:
496; GCN: v_min_f32_e32 [[V:v[0-9]+]], 0, v{{[0-9]+}}
497; GCN-NOT: v_mul
498; GCN-NOT: v_max
499; GCN: {{flat|global}}_store_dword v[{{[0-9:]+}}], [[V]]
500define amdgpu_kernel void @test_fold_canonicalize_minnum_value_f32(float addrspace(1)* %arg) {
501  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
502  %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id
503  %load = load float, float addrspace(1)* %gep, align 4
504  %v0 = fadd float %load, 0.0
505  %v = tail call float @llvm.minnum.f32(float %v0, float 0.0)
506  %canonicalized = tail call float @llvm.canonicalize.f32(float %v)
507  store float %canonicalized, float addrspace(1)* %gep, align 4
508  ret void
509}
510
511; FIXME: Should there be more checks here? minnum with NaN operand is simplified away.
512
513; GCN-LABEL: test_fold_canonicalize_sNaN_value_f32:
514; GCN: {{flat|global}}_load_dword [[LOAD:v[0-9]+]]
515; GCN-FLUSH: v_mul_f32_e32 v{{[0-9]+}}, 1.0, [[LOAD]]
516; GCN-DENORM: v_max_f32_e32 v{{[0-9]+}}, [[LOAD]], [[LOAD]]
517define amdgpu_kernel void @test_fold_canonicalize_sNaN_value_f32(float addrspace(1)* %arg) {
518  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
519  %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id
520  %load = load float, float addrspace(1)* %gep, align 4
521  %v = tail call float @llvm.minnum.f32(float %load, float bitcast (i32 2139095041 to float))
522  %canonicalized = tail call float @llvm.canonicalize.f32(float %v)
523  store float %canonicalized, float addrspace(1)* %gep, align 4
524  ret void
525}
526
527; GCN-LABEL: test_fold_canonicalize_denorm_value_f32:
528; GCN: {{flat|global}}_load_dword [[VAL:v[0-9]+]]
529
530; GFX9-DENORM: v_max_f32_e32 [[QUIET:v[0-9]+]], [[VAL]], [[VAL]]
531; GFX9-DENORM: v_min_f32_e32 [[RESULT:v[0-9]+]], 0x7fffff, [[QUIET]]
532
533; GFX9-FLUSH: v_mul_f32_e32 [[QUIET:v[0-9]+]], 1.0, [[VAL]]
534; GFX9-FLUSH: v_min_f32_e32 [[RESULT:v[0-9]+]], 0, [[QUIET]]
535
536
537; VI-FLUSH: v_mul_f32_e32 [[QUIET_V0:v[0-9]+]], 1.0, [[VAL]]
538; VI-FLUSH: v_min_f32_e32 [[RESULT:v[0-9]+]], 0, [[QUIET_V0]]
539
540; VI-DENORM: v_min_f32_e32 [[RESULT:v[0-9]+]], 0x7fffff, [[VAL]]
541
542; GCN-NOT: v_mul
543; GCN-NOT: v_max
544; GCN:   {{flat|global}}_store_dword v[{{[0-9:]+}}], [[RESULT]]
545define amdgpu_kernel void @test_fold_canonicalize_denorm_value_f32(float addrspace(1)* %arg) {
546  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
547  %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id
548  %load = load float, float addrspace(1)* %gep, align 4
549  %v = tail call float @llvm.minnum.f32(float %load, float bitcast (i32 8388607 to float))
550  %canonicalized = tail call float @llvm.canonicalize.f32(float %v)
551  store float %canonicalized, float addrspace(1)* %gep, align 4
552  ret void
553}
554
555; GCN-LABEL: test_fold_canonicalize_maxnum_value_from_load_f32_ieee_mode:
556; GCN: {{flat|global}}_load_dword [[VAL:v[0-9]+]]
557
558; GFX9:  v_max_f32_e32 [[RESULT:v[0-9]+]], 0, [[VAL]]
559
560; VI-FLUSH:    v_mul_f32_e32 [[QUIET:v[0-9]+]], 1.0, [[VAL]]
561; VI-FLUSH:    v_max_f32_e32 [[RESULT:v[0-9]+]], 0, [[QUIET]]
562
563; VI-DENORM: v_max_f32_e32 [[RESULT:v[0-9]+]], 0, [[VAL]]
564
565; GCN-NOT: v_mul
566; GCN-NOT: v_max
567; GCN:  {{flat|global}}_store_dword v[{{[0-9:]+}}], [[RESULT]]
568define amdgpu_kernel void @test_fold_canonicalize_maxnum_value_from_load_f32_ieee_mode(float addrspace(1)* %arg) {
569  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
570  %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id
571  %load = load float, float addrspace(1)* %gep, align 4
572  %v = tail call float @llvm.maxnum.f32(float %load, float 0.0)
573  %canonicalized = tail call float @llvm.canonicalize.f32(float %v)
574  store float %canonicalized, float addrspace(1)* %gep, align 4
575  ret void
576}
577
578; GCN-LABEL: test_fold_canonicalize_maxnum_value_f32:
579; GCN: v_max_f32_e32 [[V:v[0-9]+]], 0, v{{[0-9]+}}
580; GCN-NOT: v_max
581; GCN-NOT: v_mul
582; GCN: {{flat|global}}_store_dword v[{{[0-9:]+}}], [[V]]
583define amdgpu_kernel void @test_fold_canonicalize_maxnum_value_f32(float addrspace(1)* %arg) {
584  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
585  %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id
586  %load = load float, float addrspace(1)* %gep, align 4
587  %v0 = fadd float %load, 0.0
588  %v = tail call float @llvm.maxnum.f32(float %v0, float 0.0)
589  %canonicalized = tail call float @llvm.canonicalize.f32(float %v)
590  store float %canonicalized, float addrspace(1)* %gep, align 4
591  ret void
592}
593
594; GCN-LABEL: test_fold_canonicalize_maxnum_value_f64:
595; GCN: v_max_f64 [[V:v\[[0-9]+:[0-9]+\]]], v[{{[0-9:]+}}], 0
596; GCN-NOT: v_mul
597; GCN-NOT: v_max
598; GCN: {{flat|global}}_store_dwordx2 v[{{[0-9:]+}}], [[V]]
599define amdgpu_kernel void @test_fold_canonicalize_maxnum_value_f64(double addrspace(1)* %arg) {
600  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
601  %gep = getelementptr inbounds double, double addrspace(1)* %arg, i32 %id
602  %load = load double, double addrspace(1)* %gep, align 8
603  %v0 = fadd double %load, 0.0
604  %v = tail call double @llvm.maxnum.f64(double %v0, double 0.0)
605  %canonicalized = tail call double @llvm.canonicalize.f64(double %v)
606  store double %canonicalized, double addrspace(1)* %gep, align 8
607  ret void
608}
609
610; GCN-LABEL: test_fold_canonicalize_fmul_value_f32_no_ieee:
611; GCN: v_mul_f32_e32 [[V:v[0-9]+]], 0x41700000, v{{[0-9]+}}
612; GCN-NOT: v_mul
613; GCN-NOT: v_max
614; GCN-NEXT: ; return
615define amdgpu_ps float @test_fold_canonicalize_fmul_value_f32_no_ieee(float %arg) {
616entry:
617  %v = fmul float %arg, 15.0
618  %canonicalized = tail call float @llvm.canonicalize.f32(float %v)
619  ret float %canonicalized
620}
621
622; GCN-LABEL: test_fold_canonicalize_fmul_nnan_value_f32_no_ieee:
623; GCN: v_mul_f32_e32 [[V:v[0-9]+]], 0x41700000, v{{[0-9]+}}
624; GCN-NOT: v_mul
625; GCN-NOT: v_max
626; GCN-NEXT: ; return
627define amdgpu_ps float @test_fold_canonicalize_fmul_nnan_value_f32_no_ieee(float %arg) {
628entry:
629  %v = fmul nnan float %arg, 15.0
630  %canonicalized = tail call float @llvm.canonicalize.f32(float %v)
631  ret float %canonicalized
632}
633
634; GCN-LABEL: {{^}}test_fold_canonicalize_fdiv_value_f32_no_ieee:
635; GCN: v_div_fixup_f32
636; GCN-NOT: v_max
637; GCN-NOT: v_mul
638; GCN: ; return
639define amdgpu_ps float @test_fold_canonicalize_fdiv_value_f32_no_ieee(float %arg0) {
640entry:
641  %v = fdiv float 15.0, %arg0
642  %canonicalized = tail call float @llvm.canonicalize.f32(float %v)
643  ret float %canonicalized
644}
645
646; GCN-LABEL: {{^}}test_fold_canonicalize_load_nnan_value_f32
647; GFX9-DENORM: global_load_dword [[V:v[0-9]+]],
648; GFX9-DENORM: global_store_dword v[{{[0-9:]+}}], [[V]]
649; GFX9-DENORM-NOT: 1.0
650; GCN-FLUSH: v_mul_f32_e32 v{{[0-9]+}}, 1.0, v{{[0-9]+}}
651define amdgpu_kernel void @test_fold_canonicalize_load_nnan_value_f32(float addrspace(1)* %arg, float addrspace(1)* %out) #1 {
652  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
653  %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id
654  %v = load float, float addrspace(1)* %gep, align 4
655  %canonicalized = tail call float @llvm.canonicalize.f32(float %v)
656  %gep2 = getelementptr inbounds float, float addrspace(1)* %out, i32 %id
657  store float %canonicalized, float addrspace(1)* %gep2, align 4
658  ret void
659}
660
661; GCN-LABEL: {{^}}test_fold_canonicalize_load_nnan_value_f64
662; GCN: {{flat|global}}_load_dwordx2 [[V:v\[[0-9:]+\]]],
663; GCN: {{flat|global}}_store_dwordx2 v[{{[0-9:]+}}], [[V]]
664; GCN-NOT: v_mul_
665; GCN-NOT: v_max_
666define amdgpu_kernel void @test_fold_canonicalize_load_nnan_value_f64(double addrspace(1)* %arg, double addrspace(1)* %out) #1 {
667  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
668  %gep = getelementptr inbounds double, double addrspace(1)* %arg, i32 %id
669  %v = load double, double addrspace(1)* %gep, align 8
670  %canonicalized = tail call double @llvm.canonicalize.f64(double %v)
671  %gep2 = getelementptr inbounds double, double addrspace(1)* %out, i32 %id
672  store double %canonicalized, double addrspace(1)* %gep2, align 8
673  ret void
674}
675
676; GCN-LABEL: {{^}}test_fold_canonicalize_load_nnan_value_f16
677; GCN: {{flat|global}}_load_ushort [[V:v[0-9]+]],
678; GCN-NOT: v_mul
679; GCN-NOT: v_max
680; GCN: {{flat|global}}_store_short v{{\[[0-9]+:[0-9]+\]}}, [[V]]
681define amdgpu_kernel void @test_fold_canonicalize_load_nnan_value_f16(half addrspace(1)* %arg, half addrspace(1)* %out) #1 {
682  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
683  %gep = getelementptr inbounds half, half addrspace(1)* %arg, i32 %id
684  %v = load half, half addrspace(1)* %gep, align 2
685  %canonicalized = tail call half @llvm.canonicalize.f16(half %v)
686  %gep2 = getelementptr inbounds half, half addrspace(1)* %out, i32 %id
687  store half %canonicalized, half addrspace(1)* %gep2, align 2
688  ret void
689}
690
691; GCN-LABEL: {{^}}test_fold_canonicalize_select_value_f32:
692; GCN: v_add_f32
693; GCN: v_add_f32
694; GCN: v_cndmask_b32
695; GCN-NOT: v_mul_
696; GCN-NOT: v_max_
697define amdgpu_kernel void @test_fold_canonicalize_select_value_f32(float addrspace(1)* %arg) {
698  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
699  %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id
700  %load0 = load volatile float, float addrspace(1)* %gep, align 4
701  %load1 = load volatile float, float addrspace(1)* %gep, align 4
702  %load2 = load volatile i32, i32 addrspace(1)* undef, align 4
703  %v0 = fadd float %load0, 15.0
704  %v1 = fadd float %load1, 32.0
705  %cond = icmp eq i32 %load2, 0
706  %select = select i1 %cond, float %v0, float %v1
707  %canonicalized = tail call float @llvm.canonicalize.f32(float %select)
708  store float %canonicalized, float addrspace(1)* %gep, align 4
709  ret void
710}
711
712; Need to quiet the nan with a separate instruction since it will be
713; passed through the minnum.
714; FIXME: canonicalize doens't work correctly without ieee_mode
715
716; GCN-LABEL: {{^}}test_fold_canonicalize_minnum_value_no_ieee_mode:
717; GFX9-NOT: v0
718; GFX9-NOT: v1
719; GFX9: v_min_f32_e32 v0, v0, v1
720; GFX9-NEXT: ; return to shader
721
722; VI-FLUSH: v_min_f32_e32 v0, v0, v1
723; VI-FLUSH-NEXT: v_mul_f32_e32 v0, 1.0, v0
724; VI-FLUSH-NEXT: ; return
725
726; VI-DENORM-NOT: v0
727; VI-DENORM: v_min_f32_e32 v0, v0, v1
728; VI-DENORM-NEXT: ; return
729define amdgpu_ps float @test_fold_canonicalize_minnum_value_no_ieee_mode(float %arg0, float %arg1) {
730  %v = tail call float @llvm.minnum.f32(float %arg0, float %arg1)
731  %canonicalized = tail call float @llvm.canonicalize.f32(float %v)
732  ret float %canonicalized
733}
734
735; GCN-LABEL: {{^}}test_fold_canonicalize_minnum_value_ieee_mode:
736; GFX9: v_min_f32_e32 v0, v0, v1
737; GFX9-NEXT: s_setpc_b64
738
739; VI-FLUSH-DAG: v_mul_f32_e32 v0, 1.0, v0
740; VI-FLUSH-DAG: v_mul_f32_e32 v1, 1.0, v1
741; VI-FLUSH: v_min_f32_e32 v0, v0, v1
742
743; VI-DENORM-DAG: v_max_f32_e32 v0, v0, v0
744; VI-DENORM-DAG: v_max_f32_e32 v1, v1, v1
745; VI-DENORM: v_min_f32_e32 v0, v0, v1
746
747; VI-NEXT: s_setpc_b64
748define float @test_fold_canonicalize_minnum_value_ieee_mode(float %arg0, float %arg1) {
749  %v = tail call float @llvm.minnum.f32(float %arg0, float %arg1)
750  %canonicalized = tail call float @llvm.canonicalize.f32(float %v)
751  ret float %canonicalized
752}
753
754; Canonicalizing flush necessary pre-gfx9
755; GCN-LABEL: {{^}}test_fold_canonicalize_minnum_value_no_ieee_mode_nnan:
756; GCN: v_min_f32_e32 v0, v0, v1
757; VI-FLUSH-NEXT: v_mul_f32_e32 v0, 1.0, v0
758; GCN-NEXT: ; return
759define amdgpu_ps float @test_fold_canonicalize_minnum_value_no_ieee_mode_nnan(float %arg0, float %arg1) #1 {
760  %v = tail call float @llvm.minnum.f32(float %arg0, float %arg1)
761  %canonicalized = tail call float @llvm.canonicalize.f32(float %v)
762  ret float %canonicalized
763}
764
765; GCN-LABEL: {{^}}v_test_canonicalize_build_vector_v2f16:
766; GFX9-DAG: v_add_f16_e32
767; GFX9-DAG: v_mul_f16_e32
768; GFX9-NOT: v_max
769; GFX9-NOT: v_pk_max
770define <2 x half> @v_test_canonicalize_build_vector_v2f16(<2 x half> %vec) {
771  %lo = extractelement <2 x half> %vec, i32 0
772  %hi = extractelement <2 x half> %vec, i32 1
773  %lo.op = fadd half %lo, 1.0
774  %hi.op = fmul half %lo, 4.0
775  %ins0 = insertelement <2 x half> undef, half %lo.op, i32 0
776  %ins1 = insertelement <2 x half> %ins0, half %hi.op, i32 1
777  %canonicalized = call <2 x half> @llvm.canonicalize.v2f16(<2 x half> %ins1)
778  ret <2 x half> %canonicalized
779}
780
781; GCN-LABEL: {{^}}v_test_canonicalize_build_vector_noncanon1_v2f16:
782; GFX9: v_add_f16_e32
783; GFX9: v_pk_max
784define <2 x half> @v_test_canonicalize_build_vector_noncanon1_v2f16(<2 x half> %vec) {
785  %lo = extractelement <2 x half> %vec, i32 0
786  %lo.op = fadd half %lo, 1.0
787  %ins = insertelement <2 x half> %vec, half %lo.op, i32 0
788  %canonicalized = call <2 x half> @llvm.canonicalize.v2f16(<2 x half> %ins)
789  ret <2 x half> %canonicalized
790}
791
792; GCN-LABEL: {{^}}v_test_canonicalize_build_vector_noncanon0_v2f16:
793; GFX9: v_add_f16_sdwa
794; GFX9: v_pk_max
795define <2 x half> @v_test_canonicalize_build_vector_noncanon0_v2f16(<2 x half> %vec) {
796  %hi = extractelement <2 x half> %vec, i32 1
797  %hi.op = fadd half %hi, 1.0
798  %ins = insertelement <2 x half> %vec, half %hi.op, i32 1
799  %canonicalized = call <2 x half> @llvm.canonicalize.v2f16(<2 x half> %ins)
800  ret <2 x half> %canonicalized
801}
802
803; GCN-LABEL: {{^}}v_test_canonicalize_extract_element_v2f16:
804; GFX9: s_waitcnt
805; GFX9-NEXT: v_mul_f16_e32 v0, 4.0, v0
806; GFX9-NEXT: s_setpc_b64
807define half @v_test_canonicalize_extract_element_v2f16(<2 x half> %vec) {
808  %vec.op = fmul <2 x half> %vec, <half 4.0, half 4.0>
809  %elt = extractelement <2 x half> %vec.op, i32 0
810  %canonicalized = call half @llvm.canonicalize.f16(half %elt)
811  ret half %canonicalized
812}
813
814; GCN-LABEL: {{^}}v_test_canonicalize_insertelement_v2f16:
815; GFX9: v_mul_f16_e32
816; GFX9: v_pk_mul_f16
817; GFX9-NOT: v_max
818; GFX9-NOT: v_pk_max
819define <2 x half> @v_test_canonicalize_insertelement_v2f16(<2 x half> %vec, half %val, i32 %idx) {
820  %vec.op = fmul <2 x half> %vec, <half 4.0, half 4.0>
821  %ins.op = fmul half %val, 8.0
822  %ins = insertelement <2 x half> %vec.op, half %ins.op, i32 %idx
823  %canonicalized = call <2 x half> @llvm.canonicalize.v2f16(<2 x half> %ins)
824  ret <2 x half> %canonicalized
825}
826
827; GCN-LABEL: {{^}}v_test_canonicalize_insertelement_noncanon_vec_v2f16:
828; GFX9: v_mul_f16
829; GFX9: v_pk_max_f16 v0, v0, v0
830; GFX9-NEXT: s_setpc_b64
831define <2 x half> @v_test_canonicalize_insertelement_noncanon_vec_v2f16(<2 x half> %vec, half %val, i32 %idx) {
832  %ins.op = fmul half %val, 8.0
833  %ins = insertelement <2 x half> %vec, half %ins.op, i32 %idx
834  %canonicalized = call <2 x half> @llvm.canonicalize.v2f16(<2 x half> %ins)
835  ret <2 x half> %canonicalized
836}
837
838; GCN-LABEL: {{^}}v_test_canonicalize_insertelement_noncanon_insval_v2f16:
839; GFX9: v_pk_mul_f16
840; GFX9: v_pk_max_f16 v0, v0, v0
841; GFX9-NEXT: s_setpc_b64
842define <2 x half> @v_test_canonicalize_insertelement_noncanon_insval_v2f16(<2 x half> %vec, half %val, i32 %idx) {
843  %vec.op = fmul <2 x half> %vec, <half 4.0, half 4.0>
844  %ins = insertelement <2 x half> %vec.op, half %val, i32 %idx
845  %canonicalized = call <2 x half> @llvm.canonicalize.v2f16(<2 x half> %ins)
846  ret <2 x half> %canonicalized
847}
848
849; GCN-LABEL: {{^}}v_test_canonicalize_cvt_pkrtz:
850; GCN: s_waitcnt
851; GCN-NEXT: v_cvt_pkrtz_f16_f32 v0, v0, v1
852; GCN-NEXT: s_setpc_b64
853define <2 x half> @v_test_canonicalize_cvt_pkrtz(float %a, float %b) {
854  %cvt = call <2 x half> @llvm.amdgcn.cvt.pkrtz(float %a, float %b)
855  %canonicalized = call <2 x half> @llvm.canonicalize.v2f16(<2 x half> %cvt)
856  ret <2 x half> %canonicalized
857}
858
859; GCN-LABEL: {{^}}v_test_canonicalize_cubeid:
860; GCN: s_waitcnt
861; GCN-NEXT: v_cubeid_f32 v0, v0, v1, v2
862; GCN-NEXT: s_setpc_b64
863define float @v_test_canonicalize_cubeid(float %a, float %b, float %c) {
864  %cvt = call float @llvm.amdgcn.cubeid(float %a, float %b, float %c)
865  %canonicalized = call float @llvm.canonicalize.f32(float %cvt)
866  ret float %canonicalized
867}
868
869; GCN-LABEL: {{^}}v_test_canonicalize_frexp_mant:
870; GCN: s_waitcnt
871; GCN-NEXT: v_frexp_mant_f32_e32 v0, v0
872; GCN-NEXT: s_setpc_b64
873define float @v_test_canonicalize_frexp_mant(float %a) {
874  %cvt = call float @llvm.amdgcn.frexp.mant.f32(float %a)
875  %canonicalized = call float @llvm.canonicalize.f32(float %cvt)
876  ret float %canonicalized
877}
878
879; Avoid failing the test on FreeBSD11.0 which will match the GCN-NOT: 1.0
880; in the .amd_amdgpu_isa "amdgcn-unknown-freebsd11.0--gfx802" directive
881; GCN: .amd_amdgpu_isa
882
883declare float @llvm.canonicalize.f32(float) #0
884declare float @llvm.copysign.f32(float, float) #0
885declare float @llvm.amdgcn.fmul.legacy(float, float) #0
886declare float @llvm.amdgcn.fmad.ftz.f32(float, float, float) #0
887declare double @llvm.canonicalize.f64(double) #0
888declare half @llvm.canonicalize.f16(half) #0
889declare <2 x half> @llvm.canonicalize.v2f16(<2 x half>) #0
890declare i32 @llvm.amdgcn.workitem.id.x() #0
891declare float @llvm.sqrt.f32(float) #0
892declare float @llvm.ceil.f32(float) #0
893declare float @llvm.floor.f32(float) #0
894declare float @llvm.fma.f32(float, float, float) #0
895declare float @llvm.fmuladd.f32(float, float, float) #0
896declare float @llvm.fabs.f32(float) #0
897declare float @llvm.sin.f32(float) #0
898declare float @llvm.cos.f32(float) #0
899declare half @llvm.sin.f16(half) #0
900declare half @llvm.cos.f16(half) #0
901declare float @llvm.minnum.f32(float, float) #0
902declare float @llvm.maxnum.f32(float, float) #0
903declare double @llvm.maxnum.f64(double, double) #0
904declare <2 x half> @llvm.amdgcn.cvt.pkrtz(float, float) #0
905declare float @llvm.amdgcn.cubeid(float, float, float) #0
906declare float @llvm.amdgcn.frexp.mant.f32(float) #0
907
908attributes #0 = { nounwind readnone }
909attributes #1 = { "no-nans-fp-math"="true" }
910attributes #2 = { "denormal-fp-math"="preserve-sign,preserve-sign" "denormal-fp-math-f32"="ieee,ieee" }
911