[AMDGPU] Add True16 register classes.
[llvm-project.git] / llvm / test / CodeGen / AMDGPU / v_mac.ll
blob3df7f3c26aad82eb251775210b5d06b18ea54224
1 ; RUN:  llc -amdgpu-scalarize-global-loads=false -march=amdgcn -mattr=+mad-mac-f32-insts -denormal-fp-math-f32=preserve-sign -verify-machineinstrs < %s | FileCheck --check-prefixes=SI,GCN %s
2 ; RUN:  llc -amdgpu-scalarize-global-loads=false -march=amdgcn -mcpu=tonga -denormal-fp-math=preserve-sign -denormal-fp-math-f32=preserve-sign -mattr=-flat-for-global -verify-machineinstrs < %s | FileCheck --check-prefixes=VI-FLUSH,GCN %s
3 ; RUN:  llc -amdgpu-scalarize-global-loads=false -march=amdgcn -mcpu=tonga -denormal-fp-math=ieee -denormal-fp-math-f32=preserve-sign -mattr=-flat-for-global -verify-machineinstrs < %s | FileCheck -check-prefix=GCN %s
5 ; GCN-LABEL: {{^}}mac_vvv:
6 ; GCN: buffer_load_dword [[A:v[0-9]+]], off, s[{{[0-9]+:[0-9]+}}], 0 glc{{$}}
7 ; GCN: buffer_load_dword [[B:v[0-9]+]], off, s[{{[0-9]+:[0-9]+}}], 0 offset:4
8 ; GCN: buffer_load_dword [[C:v[0-9]+]], off, s[{{[0-9]+:[0-9]+}}], 0 offset:8
9 ; GCN: v_mac_f32_e32 [[C]], [[A]], [[B]]
10 ; GCN: buffer_store_dword [[C]]
11 define amdgpu_kernel void @mac_vvv(ptr addrspace(1) %out, ptr addrspace(1) %in) #0 {
12 entry:
13   %b_ptr = getelementptr float, ptr addrspace(1) %in, i32 1
14   %c_ptr = getelementptr float, ptr addrspace(1) %in, i32 2
16   %a = load volatile float, ptr addrspace(1) %in
17   %b = load volatile float, ptr addrspace(1) %b_ptr
18   %c = load volatile float, ptr addrspace(1) %c_ptr
20   %tmp0 = fmul float %a, %b
21   %tmp1 = fadd float %tmp0, %c
22   store float %tmp1, ptr addrspace(1) %out
23   ret void
26 ; GCN-LABEL: {{^}}mad_inline_sgpr_inline:
27 ; GCN-NOT: v_mac_f32
28 ; GCN: v_mad_f32 v{{[0-9]}}, s{{[0-9]+}}, 0.5, 0.5
29 define amdgpu_kernel void @mad_inline_sgpr_inline(ptr addrspace(1) %out, float %in) #0 {
30 entry:
31   %tmp0 = fmul float 0.5, %in
32   %tmp1 = fadd float %tmp0, 0.5
33   store float %tmp1, ptr addrspace(1) %out
34   ret void
37 ; GCN-LABEL: {{^}}mad_vvs:
38 ; GCN-NOT: v_mac_f32
39 ; GCN: v_mad_f32 v{{[0-9]+}}, v{{[0-9]+}}, v{{[0-9]+}}, s{{[0-9]+}}
40 define amdgpu_kernel void @mad_vvs(ptr addrspace(1) %out, ptr addrspace(1) %in, float %c) #0 {
41 entry:
42   %b_ptr = getelementptr float, ptr addrspace(1) %in, i32 1
44   %a = load float, ptr addrspace(1) %in
45   %b = load float, ptr addrspace(1) %b_ptr
47   %tmp0 = fmul float %a, %b
48   %tmp1 = fadd float %tmp0, %c
49   store float %tmp1, ptr addrspace(1) %out
50   ret void
53 ; GCN-LABEL: {{^}}mac_ssv:
54 ; GCN: v_mac_f32_e64 v{{[0-9]+}}, s{{[0-9]+}}, s{{[0-9]+}}
55 define amdgpu_kernel void @mac_ssv(ptr addrspace(1) %out, ptr addrspace(1) %in, float %a) #0 {
56 entry:
57   %c = load float, ptr addrspace(1) %in
59   %tmp0 = fmul float %a, %a
60   %tmp1 = fadd float %tmp0, %c
61   store float %tmp1, ptr addrspace(1) %out
62   ret void
65 ; GCN-LABEL: {{^}}mac_mad_same_add:
66 ; GCN: v_mad_f32 v{{[0-9]}}, v{{[0-9]+}}, v{{[0-9]+}}, [[ADD:v[0-9]+]]
67 ; GCN: v_mac_f32_e32 [[ADD]], v{{[0-9]+}}, v{{[0-9]+}}
68 define amdgpu_kernel void @mac_mad_same_add(ptr addrspace(1) %out, ptr addrspace(1) %in) #0 {
69 entry:
70   %b_ptr = getelementptr float, ptr addrspace(1) %in, i32 1
71   %c_ptr = getelementptr float, ptr addrspace(1) %in, i32 2
72   %d_ptr = getelementptr float, ptr addrspace(1) %in, i32 3
73   %e_ptr = getelementptr float, ptr addrspace(1) %in, i32 4
75   %a = load volatile float, ptr addrspace(1) %in
76   %b = load volatile float, ptr addrspace(1) %b_ptr
77   %c = load volatile float, ptr addrspace(1) %c_ptr
78   %d = load volatile float, ptr addrspace(1) %d_ptr
79   %e = load volatile float, ptr addrspace(1) %e_ptr
81   %tmp0 = fmul float %a, %b
82   %tmp1 = fadd float %tmp0, %c
84   %tmp2 = fmul float %d, %e
85   %tmp3 = fadd float %tmp2, %c
87   %out1 = getelementptr float, ptr addrspace(1) %out, i32 1
88   store float %tmp1, ptr addrspace(1) %out
89   store float %tmp3, ptr addrspace(1) %out1
90   ret void
93 ; There is no advantage to using v_mac when one of the operands is negated
94 ; and v_mad accepts more operand types.
96 ; GCN-LABEL: {{^}}mad_neg_src0:
97 ; GCN-NOT: v_mac_f32
98 ; GCN: v_mad_f32 v{{[0-9]+}}, -v{{[0-9]+}}, v{{[0-9]+}}, v{{[-0-9]}}
99 define amdgpu_kernel void @mad_neg_src0(ptr addrspace(1) %out, ptr addrspace(1) %in) #0 {
100 entry:
101   %b_ptr = getelementptr float, ptr addrspace(1) %in, i32 1
102   %c_ptr = getelementptr float, ptr addrspace(1) %in, i32 2
104   %a = load float, ptr addrspace(1) %in
105   %b = load float, ptr addrspace(1) %b_ptr
106   %c = load float, ptr addrspace(1) %c_ptr
108   %neg_a = fneg float %a
109   %tmp0 = fmul float %neg_a, %b
110   %tmp1 = fadd float %tmp0, %c
112   store float %tmp1, ptr addrspace(1) %out
113   ret void
116 ; GCN-LABEL: {{^}}nsz_mad_sub0_src0:
117 ; GCN-NOT: v_mac_f32
118 ; GCN: v_mad_f32 v{{[0-9]+}}, -v{{[0-9]+}}, v{{[0-9]+}}, v{{[-0-9]}}
119 define amdgpu_kernel void @nsz_mad_sub0_src0(ptr addrspace(1) %out, ptr addrspace(1) %in) #1 {
120 entry:
121   %b_ptr = getelementptr float, ptr addrspace(1) %in, i32 1
122   %c_ptr = getelementptr float, ptr addrspace(1) %in, i32 2
124   %a = load float, ptr addrspace(1) %in
125   %b = load float, ptr addrspace(1) %b_ptr
126   %c = load float, ptr addrspace(1) %c_ptr
128   %neg_a = fsub float 0.0, %a
129   %tmp0 = fmul float %neg_a, %b
130   %tmp1 = fadd float %tmp0, %c
132   store float %tmp1, ptr addrspace(1) %out
133   ret void
136 ; GCN-LABEL: {{^}}safe_mad_sub0_src0:
137 ; GCN: v_sub_f32_e32 [[SUB0:v[0-9]+]], 0,
138 ; GCN: v_ma{{[cd]}}_f32{{[_e32]*}} v{{[0-9]+}}, [[SUB0]], v{{[0-9]+}}
139 define amdgpu_kernel void @safe_mad_sub0_src0(ptr addrspace(1) %out, ptr addrspace(1) %in) #0 {
140 entry:
141   %b_ptr = getelementptr float, ptr addrspace(1) %in, i32 1
142   %c_ptr = getelementptr float, ptr addrspace(1) %in, i32 2
144   %a = load float, ptr addrspace(1) %in
145   %b = load float, ptr addrspace(1) %b_ptr
146   %c = load float, ptr addrspace(1) %c_ptr
148   %neg_a = fsub float 0.0, %a
149   %tmp0 = fmul float %neg_a, %b
150   %tmp1 = fadd float %tmp0, %c
152   store float %tmp1, ptr addrspace(1) %out
153   ret void
156 ; GCN-LABEL: {{^}}mad_neg_src1:
157 ; GCN-NOT: v_mac_f32
158 ; GCN: v_mad_f32 v{{[0-9]+}}, -v{{[0-9]+}}, v{{[0-9]+}}, v{{[-0-9]}}
159 define amdgpu_kernel void @mad_neg_src1(ptr addrspace(1) %out, ptr addrspace(1) %in) #0 {
160 entry:
161   %b_ptr = getelementptr float, ptr addrspace(1) %in, i32 1
162   %c_ptr = getelementptr float, ptr addrspace(1) %in, i32 2
164   %a = load float, ptr addrspace(1) %in
165   %b = load float, ptr addrspace(1) %b_ptr
166   %c = load float, ptr addrspace(1) %c_ptr
168   %neg_b = fneg float %b
169   %tmp0 = fmul float %a, %neg_b
170   %tmp1 = fadd float %tmp0, %c
172   store float %tmp1, ptr addrspace(1) %out
173   ret void
176 ; GCN-LABEL: {{^}}nsz_mad_sub0_src1:
177 ; GCN-NOT: v_mac_f32
178 ; GCN: v_mad_f32 v{{[0-9]+}}, -v{{[0-9]+}}, v{{[0-9]+}}, v{{[-0-9]}}
179 define amdgpu_kernel void @nsz_mad_sub0_src1(ptr addrspace(1) %out, ptr addrspace(1) %in) #1 {
180 entry:
181   %b_ptr = getelementptr float, ptr addrspace(1) %in, i32 1
182   %c_ptr = getelementptr float, ptr addrspace(1) %in, i32 2
184   %a = load float, ptr addrspace(1) %in
185   %b = load float, ptr addrspace(1) %b_ptr
186   %c = load float, ptr addrspace(1) %c_ptr
188   %neg_b = fsub float 0.0, %b
189   %tmp0 = fmul float %a, %neg_b
190   %tmp1 = fadd float %tmp0, %c
192   store float %tmp1, ptr addrspace(1) %out
193   ret void
196 ; GCN-LABEL: {{^}}mad_neg_src2:
197 ; GCN-NOT: v_mac
198 ; GCN: v_mad_f32 v{{[0-9]+}}, v{{[0-9]+}}, v{{[0-9]+}}, -v{{[-0-9]}}
199 define amdgpu_kernel void @mad_neg_src2(ptr addrspace(1) %out, ptr addrspace(1) %in) #0 {
200 entry:
201   %b_ptr = getelementptr float, ptr addrspace(1) %in, i32 1
202   %c_ptr = getelementptr float, ptr addrspace(1) %in, i32 2
204   %a = load float, ptr addrspace(1) %in
205   %b = load float, ptr addrspace(1) %b_ptr
206   %c = load float, ptr addrspace(1) %c_ptr
208   %neg_c = fneg float %c
209   %tmp0 = fmul float %a, %b
210   %tmp1 = fadd float %tmp0, %neg_c
212   store float %tmp1, ptr addrspace(1) %out
213   ret void
216 ; Without special casing the inline constant check for v_mac_f32's
217 ; src2, this fails to fold the 1.0 into a mad.
219 ; GCN-LABEL: {{^}}fold_inline_imm_into_mac_src2_f32:
220 ; GCN: {{buffer|flat}}_load_dword [[A:v[0-9]+]]
221 ; GCN: {{buffer|flat}}_load_dword [[B:v[0-9]+]]
223 ; GCN: v_add_f32_e32 [[TMP2:v[0-9]+]], [[A]], [[A]]
224 ; GCN: v_mad_f32 v{{[0-9]+}}, [[TMP2]], -4.0, 1.0
225 define amdgpu_kernel void @fold_inline_imm_into_mac_src2_f32(ptr addrspace(1) %out, ptr addrspace(1) %a, ptr addrspace(1) %b) #3 {
227   %tid = call i32 @llvm.amdgcn.workitem.id.x()
228   %tid.ext = sext i32 %tid to i64
229   %gep.a = getelementptr inbounds float, ptr addrspace(1) %a, i64 %tid.ext
230   %gep.b = getelementptr inbounds float, ptr addrspace(1) %b, i64 %tid.ext
231   %gep.out = getelementptr inbounds float, ptr addrspace(1) %out, i64 %tid.ext
232   %tmp = load volatile float, ptr addrspace(1) %gep.a
233   %tmp1 = load volatile float, ptr addrspace(1) %gep.b
234   %tmp2 = fadd float %tmp, %tmp
235   %tmp3 = fmul float %tmp2, 4.0
236   %tmp4 = fsub float 1.0, %tmp3
237   %tmp5 = fadd float %tmp4, %tmp1
238   %tmp6 = fadd float %tmp1, %tmp1
239   %tmp7 = fmul float %tmp6, %tmp
240   %tmp8 = fsub float 1.0, %tmp7
241   %tmp9 = fmul float %tmp8, 8.0
242   %tmp10 = fadd float %tmp5, %tmp9
243   store float %tmp10, ptr addrspace(1) %gep.out
244   ret void
247 ; GCN-LABEL: {{^}}fold_inline_imm_into_mac_src2_f16:
248 ; GCN: {{buffer|flat}}_load_ushort [[A:v[0-9]+]]
249 ; GCN: {{buffer|flat}}_load_ushort [[B:v[0-9]+]]
251 ; SI-DAG: v_cvt_f32_f16_e32 [[CVT_A:v[0-9]+]], [[A]]
252 ; SI-DAG: v_cvt_f32_f16_e32 [[CVT_B:v[0-9]+]], [[B]]
254 ; SI: v_add_f32_e32 [[TMP2:v[0-9]+]], [[CVT_A]], [[CVT_A]]
255 ; SI: v_mad_f32 v{{[0-9]+}}, [[TMP2]], -4.0, 1.0
256 ; SI: v_mac_f32_e32 v{{[0-9]+}}, 0x41000000, v{{[0-9]+}}
258 ; VI-FLUSH: v_add_f16_e32 [[TMP2:v[0-9]+]], [[A]], [[A]]
259 ; VI-FLUSH: v_mad_f16 v{{[0-9]+}}, [[TMP2]], -4.0, 1.0
260 define amdgpu_kernel void @fold_inline_imm_into_mac_src2_f16(ptr addrspace(1) %out, ptr addrspace(1) %a, ptr addrspace(1) %b) #3 {
262   %tid = call i32 @llvm.amdgcn.workitem.id.x()
263   %tid.ext = sext i32 %tid to i64
264   %gep.a = getelementptr inbounds half, ptr addrspace(1) %a, i64 %tid.ext
265   %gep.b = getelementptr inbounds half, ptr addrspace(1) %b, i64 %tid.ext
266   %gep.out = getelementptr inbounds half, ptr addrspace(1) %out, i64 %tid.ext
267   %tmp = load volatile half, ptr addrspace(1) %gep.a
268   %tmp1 = load volatile half, ptr addrspace(1) %gep.b
269   %tmp2 = fadd half %tmp, %tmp
270   %tmp3 = fmul half %tmp2, 4.0
271   %tmp4 = fsub half 1.0, %tmp3
272   %tmp5 = fadd half %tmp4, %tmp1
273   %tmp6 = fadd half %tmp1, %tmp1
274   %tmp7 = fmul half %tmp6, %tmp
275   %tmp8 = fsub half 1.0, %tmp7
276   %tmp9 = fmul half %tmp8, 8.0
277   %tmp10 = fadd half %tmp5, %tmp9
278   store half %tmp10, ptr addrspace(1) %gep.out
279   ret void
282 ; Need to assume denormal handling is needed for dynamic denormal mode
283 ; GCN-LABEL: {{^}}v_mac_f32_dynamic:
284 ; GCN: v_mul_f32
285 ; GCN: v_add_f32
286 define float @v_mac_f32_dynamic(float %a, float %b, float %c) "denormal-fp-math-f32"="dynamic,dynamic" {
287   %mul = fmul float %a, %b
288   %mad = fadd float %mul, %c
289   ret float %mad
292 ; GCN-LABEL: {{^}}v_mac_f32_dynamic_daz:
293 ; GCN: v_mul_f32
294 ; GCN: v_add_f32
295 define float @v_mac_f32_dynamic_daz(float %a, float %b, float %c) "denormal-fp-math-f32"="preserve-sign,dynamic" {
296   %mul = fmul float %a, %b
297   %mad = fadd float %mul, %c
298   ret float %mad
301 ; GCN-LABEL: {{^}}v_mac_f32_dynamic_ftz:
302 ; GCN: v_mul_f32
303 ; GCN: v_add_f32
304 define float @v_mac_f32_dynamic_ftz(float %a, float %b, float %c) "denormal-fp-math-f32"="dynamic,preserve-sign" {
305   %mul = fmul float %a, %b
306   %mad = fadd float %mul, %c
307   ret float %mad
310 declare i32 @llvm.amdgcn.workitem.id.x() #2
312 attributes #0 = { nounwind "no-signed-zeros-fp-math"="false" }
313 attributes #1 = { nounwind "no-signed-zeros-fp-math"="true" }
314 attributes #2 = { nounwind readnone }
315 attributes #3 = { nounwind }