Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / llvm / test / CodeGen / AMDGPU / GlobalISel / fmed3-min-max-const-combine.ll
blobd6d36fe1acf35f7c17a7c6ef507a4cd5e71b3e89
1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc -global-isel -mtriple=amdgcn-amd-mesa3d -mcpu=gfx1010 -verify-machineinstrs < %s | FileCheck -check-prefix=GFX10 %s
3 ; RUN: llc -global-isel -mtriple=amdgcn-amd-mesa3d -mcpu=gfx803 -verify-machineinstrs < %s | FileCheck -check-prefix=GFX8 %s
5 define float @test_min_max_ValK0_K1_f32(float %a) #0 {
6 ; GFX10-LABEL: test_min_max_ValK0_K1_f32:
7 ; GFX10:       ; %bb.0:
8 ; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
9 ; GFX10-NEXT:    v_med3_f32 v0, v0, 2.0, 4.0
10 ; GFX10-NEXT:    s_setpc_b64 s[30:31]
12 ; GFX8-LABEL: test_min_max_ValK0_K1_f32:
13 ; GFX8:       ; %bb.0:
14 ; GFX8-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
15 ; GFX8-NEXT:    v_med3_f32 v0, v0, 2.0, 4.0
16 ; GFX8-NEXT:    s_setpc_b64 s[30:31]
17   %maxnum = call nnan float @llvm.maxnum.f32(float %a, float 2.0)
18   %fmed = call nnan float @llvm.minnum.f32(float %maxnum, float 4.0)
19   ret float %fmed
22 define float @test_min_max_K0Val_K1_f32(float %a) #1 {
23 ; GFX10-LABEL: test_min_max_K0Val_K1_f32:
24 ; GFX10:       ; %bb.0:
25 ; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
26 ; GFX10-NEXT:    v_med3_f32 v0, v0, 2.0, 4.0
27 ; GFX10-NEXT:    s_setpc_b64 s[30:31]
29 ; GFX8-LABEL: test_min_max_K0Val_K1_f32:
30 ; GFX8:       ; %bb.0:
31 ; GFX8-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
32 ; GFX8-NEXT:    v_med3_f32 v0, v0, 2.0, 4.0
33 ; GFX8-NEXT:    s_setpc_b64 s[30:31]
34   %maxnum = call nnan float @llvm.maxnum.f32(float 2.0, float %a)
35   %fmed = call nnan float @llvm.minnum.f32(float %maxnum, float 4.0)
36   ret float %fmed
39 ; min-max patterns for ieee=true do not have to check for NaNs
40 ; 'v_max_f16_e32 v0, v0, v0' is from fcanonicalize of the input to fmin/fmax with ieee=true
41 define half @test_min_K1max_ValK0_f16(half %a) #0 {
42 ; GFX10-LABEL: test_min_K1max_ValK0_f16:
43 ; GFX10:       ; %bb.0:
44 ; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
45 ; GFX10-NEXT:    v_max_f16_e32 v0, v0, v0
46 ; GFX10-NEXT:    v_med3_f16 v0, v0, 2.0, 4.0
47 ; GFX10-NEXT:    s_setpc_b64 s[30:31]
49 ; GFX8-LABEL: test_min_K1max_ValK0_f16:
50 ; GFX8:       ; %bb.0:
51 ; GFX8-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
52 ; GFX8-NEXT:    v_max_f16_e32 v0, v0, v0
53 ; GFX8-NEXT:    v_max_f16_e32 v0, 2.0, v0
54 ; GFX8-NEXT:    v_min_f16_e32 v0, 4.0, v0
55 ; GFX8-NEXT:    s_setpc_b64 s[30:31]
56   %maxnum = call half @llvm.maxnum.f16(half %a, half 2.0)
57   %fmed = call half @llvm.minnum.f16(half 4.0, half %maxnum)
58   ret half %fmed
61 define half @test_min_K1max_K0Val_f16(half %a) #1 {
62 ; GFX10-LABEL: test_min_K1max_K0Val_f16:
63 ; GFX10:       ; %bb.0:
64 ; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
65 ; GFX10-NEXT:    v_med3_f16 v0, v0, 2.0, 4.0
66 ; GFX10-NEXT:    s_setpc_b64 s[30:31]
68 ; GFX8-LABEL: test_min_K1max_K0Val_f16:
69 ; GFX8:       ; %bb.0:
70 ; GFX8-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
71 ; GFX8-NEXT:    v_max_f16_e32 v0, 2.0, v0
72 ; GFX8-NEXT:    v_min_f16_e32 v0, 4.0, v0
73 ; GFX8-NEXT:    s_setpc_b64 s[30:31]
74   %maxnum = call nnan half @llvm.maxnum.f16(half 2.0, half %a)
75   %fmed = call nnan half @llvm.minnum.f16(half 4.0, half %maxnum)
76   ret half %fmed
79 ; max-mix patterns work only for non-NaN inputs
80 define float @test_max_min_ValK1_K0_f32(float %a) #0 {
81 ; GFX10-LABEL: test_max_min_ValK1_K0_f32:
82 ; GFX10:       ; %bb.0:
83 ; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
84 ; GFX10-NEXT:    v_med3_f32 v0, v0, 2.0, 4.0
85 ; GFX10-NEXT:    s_setpc_b64 s[30:31]
87 ; GFX8-LABEL: test_max_min_ValK1_K0_f32:
88 ; GFX8:       ; %bb.0:
89 ; GFX8-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
90 ; GFX8-NEXT:    v_med3_f32 v0, v0, 2.0, 4.0
91 ; GFX8-NEXT:    s_setpc_b64 s[30:31]
92   %minnum = call nnan float @llvm.minnum.f32(float %a, float 4.0)
93   %fmed = call nnan float @llvm.maxnum.f32(float %minnum, float 2.0)
94   ret float %fmed
97 define float @test_max_min_K1Val_K0_f32(float %a) #1 {
98 ; GFX10-LABEL: test_max_min_K1Val_K0_f32:
99 ; GFX10:       ; %bb.0:
100 ; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
101 ; GFX10-NEXT:    v_med3_f32 v0, v0, 2.0, 4.0
102 ; GFX10-NEXT:    s_setpc_b64 s[30:31]
104 ; GFX8-LABEL: test_max_min_K1Val_K0_f32:
105 ; GFX8:       ; %bb.0:
106 ; GFX8-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
107 ; GFX8-NEXT:    v_med3_f32 v0, v0, 2.0, 4.0
108 ; GFX8-NEXT:    s_setpc_b64 s[30:31]
109   %minnum = call nnan float @llvm.minnum.f32(float 4.0, float %a)
110   %fmed = call nnan float @llvm.maxnum.f32(float %minnum, float 2.0)
111   ret float %fmed
114 define half @test_max_K0min_ValK1_f16(half %a) #0 {
115 ; GFX10-LABEL: test_max_K0min_ValK1_f16:
116 ; GFX10:       ; %bb.0:
117 ; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
118 ; GFX10-NEXT:    v_med3_f16 v0, v0, 2.0, 4.0
119 ; GFX10-NEXT:    s_setpc_b64 s[30:31]
121 ; GFX8-LABEL: test_max_K0min_ValK1_f16:
122 ; GFX8:       ; %bb.0:
123 ; GFX8-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
124 ; GFX8-NEXT:    v_min_f16_e32 v0, 4.0, v0
125 ; GFX8-NEXT:    v_max_f16_e32 v0, 2.0, v0
126 ; GFX8-NEXT:    s_setpc_b64 s[30:31]
127   %minnum = call nnan half @llvm.minnum.f16(half %a, half 4.0)
128   %fmed = call nnan half @llvm.maxnum.f16(half 2.0, half %minnum)
129   ret half %fmed
132 define half @test_max_K0min_K1Val_f16(half %a) #1 {
133 ; GFX10-LABEL: test_max_K0min_K1Val_f16:
134 ; GFX10:       ; %bb.0:
135 ; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
136 ; GFX10-NEXT:    v_med3_f16 v0, v0, 2.0, 4.0
137 ; GFX10-NEXT:    s_setpc_b64 s[30:31]
139 ; GFX8-LABEL: test_max_K0min_K1Val_f16:
140 ; GFX8:       ; %bb.0:
141 ; GFX8-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
142 ; GFX8-NEXT:    v_min_f16_e32 v0, 4.0, v0
143 ; GFX8-NEXT:    v_max_f16_e32 v0, 2.0, v0
144 ; GFX8-NEXT:    s_setpc_b64 s[30:31]
145   %minnum = call nnan half @llvm.minnum.f16(half 4.0, half %a)
146   %fmed = call nnan half @llvm.maxnum.f16(half 2.0, half %minnum)
147   ret half %fmed
150 ; global nnan function attribute always forces fmed3 combine
152 define float @test_min_max_global_nnan(float %a) #2 {
153 ; GFX10-LABEL: test_min_max_global_nnan:
154 ; GFX10:       ; %bb.0:
155 ; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
156 ; GFX10-NEXT:    v_med3_f32 v0, v0, 2.0, 4.0
157 ; GFX10-NEXT:    s_setpc_b64 s[30:31]
159 ; GFX8-LABEL: test_min_max_global_nnan:
160 ; GFX8:       ; %bb.0:
161 ; GFX8-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
162 ; GFX8-NEXT:    v_med3_f32 v0, v0, 2.0, 4.0
163 ; GFX8-NEXT:    s_setpc_b64 s[30:31]
164   %maxnum = call float @llvm.maxnum.f32(float %a, float 2.0)
165   %fmed = call float @llvm.minnum.f32(float %maxnum, float 4.0)
166   ret float %fmed
169 define float @test_max_min_global_nnan(float %a) #2 {
170 ; GFX10-LABEL: test_max_min_global_nnan:
171 ; GFX10:       ; %bb.0:
172 ; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
173 ; GFX10-NEXT:    v_med3_f32 v0, v0, 2.0, 4.0
174 ; GFX10-NEXT:    s_setpc_b64 s[30:31]
176 ; GFX8-LABEL: test_max_min_global_nnan:
177 ; GFX8:       ; %bb.0:
178 ; GFX8-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
179 ; GFX8-NEXT:    v_med3_f32 v0, v0, 2.0, 4.0
180 ; GFX8-NEXT:    s_setpc_b64 s[30:31]
181   %minnum = call float @llvm.minnum.f32(float %a, float 4.0)
182   %fmed = call float @llvm.maxnum.f32(float %minnum, float 2.0)
183   ret float %fmed
186 ; ------------------------------------------------------------------------------
187 ; Negative patterns
188 ; ------------------------------------------------------------------------------
190 ; min(max(Val, K0), K1) K0 > K1, should be K0<=K1
191 define float @test_min_max_K0_gt_K1(float %a) #0 {
192 ; GFX10-LABEL: test_min_max_K0_gt_K1:
193 ; GFX10:       ; %bb.0:
194 ; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
195 ; GFX10-NEXT:    v_max_f32_e32 v0, 4.0, v0
196 ; GFX10-NEXT:    v_min_f32_e32 v0, 2.0, v0
197 ; GFX10-NEXT:    s_setpc_b64 s[30:31]
199 ; GFX8-LABEL: test_min_max_K0_gt_K1:
200 ; GFX8:       ; %bb.0:
201 ; GFX8-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
202 ; GFX8-NEXT:    v_max_f32_e32 v0, 4.0, v0
203 ; GFX8-NEXT:    v_min_f32_e32 v0, 2.0, v0
204 ; GFX8-NEXT:    s_setpc_b64 s[30:31]
205   %maxnum = call nnan float @llvm.maxnum.f32(float %a, float 4.0)
206   %fmed = call nnan float @llvm.minnum.f32(float %maxnum, float 2.0)
207   ret float %fmed
210 ; max(min(Val, K1), K0) K0 > K1, should be K0<=K1
211 define float @test_max_min_K0_gt_K1(float %a) #0 {
212 ; GFX10-LABEL: test_max_min_K0_gt_K1:
213 ; GFX10:       ; %bb.0:
214 ; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
215 ; GFX10-NEXT:    v_min_f32_e32 v0, 2.0, v0
216 ; GFX10-NEXT:    v_max_f32_e32 v0, 4.0, v0
217 ; GFX10-NEXT:    s_setpc_b64 s[30:31]
219 ; GFX8-LABEL: test_max_min_K0_gt_K1:
220 ; GFX8:       ; %bb.0:
221 ; GFX8-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
222 ; GFX8-NEXT:    v_min_f32_e32 v0, 2.0, v0
223 ; GFX8-NEXT:    v_max_f32_e32 v0, 4.0, v0
224 ; GFX8-NEXT:    s_setpc_b64 s[30:31]
225   %minnum = call nnan float @llvm.minnum.f32(float %a, float 2.0)
226   %fmed = call nnan float @llvm.maxnum.f32(float %minnum, float 4.0)
227   ret float %fmed
230 ; non-inline constant
231 define float @test_min_max_non_inline_const(float %a) #0 {
232 ; GFX10-LABEL: test_min_max_non_inline_const:
233 ; GFX10:       ; %bb.0:
234 ; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
235 ; GFX10-NEXT:    v_max_f32_e32 v0, 2.0, v0
236 ; GFX10-NEXT:    v_min_f32_e32 v0, 0x41000000, v0
237 ; GFX10-NEXT:    s_setpc_b64 s[30:31]
239 ; GFX8-LABEL: test_min_max_non_inline_const:
240 ; GFX8:       ; %bb.0:
241 ; GFX8-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
242 ; GFX8-NEXT:    v_max_f32_e32 v0, 2.0, v0
243 ; GFX8-NEXT:    v_min_f32_e32 v0, 0x41000000, v0
244 ; GFX8-NEXT:    s_setpc_b64 s[30:31]
245   %maxnum = call nnan float @llvm.maxnum.f32(float %a, float 2.0)
246   %fmed = call nnan float @llvm.minnum.f32(float %maxnum, float 8.0)
247   ret float %fmed
250 ; there is no fmed3 for f64 or v2f16 types
252 define double @test_min_max_f64(double %a) #0 {
253 ; GFX10-LABEL: test_min_max_f64:
254 ; GFX10:       ; %bb.0:
255 ; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
256 ; GFX10-NEXT:    v_max_f64 v[0:1], v[0:1], 2.0
257 ; GFX10-NEXT:    v_min_f64 v[0:1], v[0:1], 4.0
258 ; GFX10-NEXT:    s_setpc_b64 s[30:31]
260 ; GFX8-LABEL: test_min_max_f64:
261 ; GFX8:       ; %bb.0:
262 ; GFX8-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
263 ; GFX8-NEXT:    v_max_f64 v[0:1], v[0:1], 2.0
264 ; GFX8-NEXT:    v_min_f64 v[0:1], v[0:1], 4.0
265 ; GFX8-NEXT:    s_setpc_b64 s[30:31]
266   %maxnum = call nnan double @llvm.maxnum.f64(double %a, double 2.0)
267   %fmed = call nnan double @llvm.minnum.f64(double %maxnum, double 4.0)
268   ret double %fmed
271 define <2 x half> @test_min_max_v2f16(<2 x half> %a) #0 {
272 ; GFX10-LABEL: test_min_max_v2f16:
273 ; GFX10:       ; %bb.0:
274 ; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
275 ; GFX10-NEXT:    v_pk_max_f16 v0, v0, 2.0 op_sel_hi:[1,0]
276 ; GFX10-NEXT:    v_pk_min_f16 v0, v0, 4.0 op_sel_hi:[1,0]
277 ; GFX10-NEXT:    s_setpc_b64 s[30:31]
279 ; GFX8-LABEL: test_min_max_v2f16:
280 ; GFX8:       ; %bb.0:
281 ; GFX8-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
282 ; GFX8-NEXT:    v_mov_b32_e32 v2, 0x4000
283 ; GFX8-NEXT:    v_max_f16_e32 v1, 2.0, v0
284 ; GFX8-NEXT:    v_max_f16_sdwa v0, v0, v2 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 src1_sel:DWORD
285 ; GFX8-NEXT:    v_mov_b32_e32 v2, 0x4400
286 ; GFX8-NEXT:    v_min_f16_e32 v1, 4.0, v1
287 ; GFX8-NEXT:    v_min_f16_sdwa v0, v0, v2 dst_sel:WORD_1 dst_unused:UNUSED_PAD src0_sel:DWORD src1_sel:DWORD
288 ; GFX8-NEXT:    v_or_b32_e32 v0, v1, v0
289 ; GFX8-NEXT:    s_setpc_b64 s[30:31]
290   %maxnum = call nnan <2 x half> @llvm.maxnum.v2f16(<2 x half> %a, <2 x half> <half 2.0, half 2.0>)
291   %fmed = call nnan <2 x half> @llvm.minnum.v2f16(<2 x half> %maxnum, <2 x half> <half 4.0, half 4.0>)
292   ret <2 x half> %fmed
295 ; input that can be NaN
297 ; min-max patterns for ieee=false require known non-NaN input
298 define float @test_min_max_maybe_NaN_input_ieee_false(float %a) #1 {
299 ; GFX10-LABEL: test_min_max_maybe_NaN_input_ieee_false:
300 ; GFX10:       ; %bb.0:
301 ; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
302 ; GFX10-NEXT:    v_max_f32_e32 v0, 2.0, v0
303 ; GFX10-NEXT:    v_min_f32_e32 v0, 4.0, v0
304 ; GFX10-NEXT:    s_setpc_b64 s[30:31]
306 ; GFX8-LABEL: test_min_max_maybe_NaN_input_ieee_false:
307 ; GFX8:       ; %bb.0:
308 ; GFX8-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
309 ; GFX8-NEXT:    v_max_f32_e32 v0, 2.0, v0
310 ; GFX8-NEXT:    v_min_f32_e32 v0, 4.0, v0
311 ; GFX8-NEXT:    s_setpc_b64 s[30:31]
312   %maxnum = call float @llvm.maxnum.f32(float %a, float 2.0)
313   %fmed = call float @llvm.minnum.f32(float %maxnum, float 4.0)
314   ret float %fmed
317 ; max-min patterns always require known non-NaN input
319 define float @test_max_min_maybe_NaN_input_ieee_false(float %a) #1 {
320 ; GFX10-LABEL: test_max_min_maybe_NaN_input_ieee_false:
321 ; GFX10:       ; %bb.0:
322 ; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
323 ; GFX10-NEXT:    v_min_f32_e32 v0, 4.0, v0
324 ; GFX10-NEXT:    v_max_f32_e32 v0, 2.0, v0
325 ; GFX10-NEXT:    s_setpc_b64 s[30:31]
327 ; GFX8-LABEL: test_max_min_maybe_NaN_input_ieee_false:
328 ; GFX8:       ; %bb.0:
329 ; GFX8-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
330 ; GFX8-NEXT:    v_min_f32_e32 v0, 4.0, v0
331 ; GFX8-NEXT:    v_max_f32_e32 v0, 2.0, v0
332 ; GFX8-NEXT:    s_setpc_b64 s[30:31]
333   %minnum = call float @llvm.minnum.f32(float %a, float 4.0)
334   %fmed = call float @llvm.maxnum.f32(float %minnum, float 2.0)
335   ret float %fmed
338 ; 'v_max_f32_e32 v0, v0, v0' is from fcanonicalize of the input to fmin/fmax with ieee=true
339 define float @test_max_min_maybe_NaN_input_ieee_true(float %a) #0 {
340 ; GFX10-LABEL: test_max_min_maybe_NaN_input_ieee_true:
341 ; GFX10:       ; %bb.0:
342 ; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
343 ; GFX10-NEXT:    v_max_f32_e32 v0, v0, v0
344 ; GFX10-NEXT:    v_min_f32_e32 v0, 4.0, v0
345 ; GFX10-NEXT:    v_max_f32_e32 v0, 2.0, v0
346 ; GFX10-NEXT:    s_setpc_b64 s[30:31]
348 ; GFX8-LABEL: test_max_min_maybe_NaN_input_ieee_true:
349 ; GFX8:       ; %bb.0:
350 ; GFX8-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
351 ; GFX8-NEXT:    v_mul_f32_e32 v0, 1.0, v0
352 ; GFX8-NEXT:    v_min_f32_e32 v0, 4.0, v0
353 ; GFX8-NEXT:    v_max_f32_e32 v0, 2.0, v0
354 ; GFX8-NEXT:    s_setpc_b64 s[30:31]
355   %minnum = call float @llvm.minnum.f32(float %a, float 4.0)
356   %fmed = call float @llvm.maxnum.f32(float %minnum, float 2.0)
357   ret float %fmed
360 declare half @llvm.minnum.f16(half, half)
361 declare half @llvm.maxnum.f16(half, half)
362 declare float @llvm.minnum.f32(float, float)
363 declare float @llvm.maxnum.f32(float, float)
364 declare double @llvm.minnum.f64(double, double)
365 declare double @llvm.maxnum.f64(double, double)
366 declare <2 x half> @llvm.minnum.v2f16(<2 x half>, <2 x half>)
367 declare <2 x half> @llvm.maxnum.v2f16(<2 x half>, <2 x half>)
368 attributes #0 = {"amdgpu-ieee"="true"}
369 attributes #1 = {"amdgpu-ieee"="false"}
370 attributes #2 = {"no-nans-fp-math"="true"}