1; RUN: llc -march=amdgcn -mcpu=fiji -denormal-fp-math=preserve-sign -denormal-fp-math-f32=ieee -fp-contract=on -verify-machineinstrs < %s | FileCheck -enable-var-scope -check-prefixes=GCN,GCN-STRICT,VI-FLUSH,VI %s
2; RUN: llc -march=amdgcn -mcpu=fiji -denormal-fp-math=preserve-sign -denormal-fp-math-f32=ieee -fp-contract=fast -verify-machineinstrs < %s | FileCheck -enable-var-scope -check-prefixes=GCN,GCN-CONTRACT,VI-FLUSH,VI %s
3
4; RUN: llc -march=amdgcn -mcpu=fiji -denormal-fp-math=ieee -denormal-fp-math-f32=ieee -fp-contract=on -verify-machineinstrs < %s | FileCheck -enable-var-scope -check-prefixes=GCN,GCN-STRICT,GCN-DENORM,GCN-DENORM-STRICT,VI-DENORM-STRICT,VI-DENORM,VI %s
5; RUN: llc -march=amdgcn -mcpu=fiji -denormal-fp-math=ieee -denormal-fp-math-f32=ieee -fp-contract=fast -verify-machineinstrs < %s | FileCheck -enable-var-scope -check-prefixes=GCN,GCN-CONTRACT,GCN-DENORM,GCN-DENORM-CONTRACT,VI-DENORM-CONTRACT,VI-DENORM,VI %s
6
7; RUN: llc -march=amdgcn -mcpu=gfx1010 -denormal-fp-math=preserve-sign -denormal-fp-math-f32=ieee -fp-contract=on -verify-machineinstrs < %s | FileCheck -enable-var-scope -check-prefixes=GCN,GCN-STRICT,GFX10-FLUSH,GFX10 %s
8; RUN: llc -march=amdgcn -mcpu=gfx1010 -denormal-fp-math=preserve-sign -denormal-fp-math-f32=ieee -fp-contract=fast -verify-machineinstrs < %s | FileCheck -enable-var-scope -check-prefixes=GCN,GCN-CONTRACT,GFX10-FLUSH,GFX10 %s
9; RUN: llc -march=amdgcn -mcpu=gfx1010 -denormal-fp-math=ieee -denormal-fp-math-f32=ieee -fp-contract=on -verify-machineinstrs < %s | FileCheck -enable-var-scope -check-prefixes=GCN,GCN-STRICT,GCN-DENORM,GCN-DENORM-STRICT,GFX10-DENORM-STRICT,GFX10-DENORM,GFX10 %s
10; RUN: llc -march=amdgcn -mcpu=gfx1010 -denormal-fp-math=ieee -denormal-fp-math-f32=ieee -fp-contract=fast -verify-machineinstrs < %s | FileCheck -enable-var-scope -check-prefixes=GCN,GCN-CONTRACT,GCN-DENORM,GCN-DENORM-CONTRACT,GFX10-DENORM-CONTRACT,GFX10-DENORM,GFX10 %s
11
12declare i32 @llvm.amdgcn.workitem.id.x() #1
13declare half @llvm.fmuladd.f16(half, half, half) #1
14declare half @llvm.fabs.f16(half) #1
15
16; GCN-LABEL: {{^}}fmuladd_f16:
17; VI-FLUSH: v_mac_f16_e32 {{v[0-9]+, v[0-9]+, v[0-9]+}}
18
19; VI-DENORM: v_fma_f16 {{v[0-9]+, v[0-9]+, v[0-9]+}}
20
21; GFX10-FLUSH:  v_mul_f16_e32
22; GFX10-FLUSH:  v_add_f16_e32
23; GFX10-DENORM: v_fmac_f16_e32 {{v[0-9]+, v[0-9]+, v[0-9]+}}
24
25define amdgpu_kernel void @fmuladd_f16(half addrspace(1)* %out, half addrspace(1)* %in1,
26                         half addrspace(1)* %in2, half addrspace(1)* %in3) #0 {
27  %r0 = load half, half addrspace(1)* %in1
28  %r1 = load half, half addrspace(1)* %in2
29  %r2 = load half, half addrspace(1)* %in3
30  %r3 = tail call half @llvm.fmuladd.f16(half %r0, half %r1, half %r2)
31  store half %r3, half addrspace(1)* %out
32  ret void
33}
34
35; GCN-LABEL: {{^}}fmuladd_2.0_a_b_f16
36; GCN: {{buffer|flat|global}}_load_ushort [[R1:v[0-9]+]],
37; GCN: {{buffer|flat|global}}_load_ushort [[R2:v[0-9]+]],
38; VI-FLUSH: v_mac_f16_e32 [[R2]], 2.0, [[R1]]
39; VI-FLUSH: flat_store_short v{{\[[0-9]+:[0-9]+\]}}, [[R2]]
40
41; VI-DENORM:    v_fma_f16 [[RESULT:v[0-9]+]], [[R1]], 2.0, [[R2]]
42; GFX10-DENORM: v_fmac_f16_e32 [[R2:v[0-9]+]], 2.0, [[R1]]
43
44; GFX10-FLUSH:  v_add_f16_e32 [[MUL2:v[0-9]+]], [[R1]], [[R1]]
45; GFX10-FLUSH:  v_add_f16_e32 [[RESULT:v[0-9]+]], [[MUL2]], [[R2]]
46
47; VI-DENORM:    flat_store_short v{{\[[0-9]+:[0-9]+\]}}, [[RESULT]]
48; GFX10-DENORM: global_store_short v{{\[[0-9]+:[0-9]+\]}}, [[R2]]
49; GFX10-FLUSH:  global_store_short v{{\[[0-9]+:[0-9]+\]}}, [[RESULT]]
50
51define amdgpu_kernel void @fmuladd_2.0_a_b_f16(half addrspace(1)* %out, half addrspace(1)* %in) #0 {
52  %tid = call i32 @llvm.amdgcn.workitem.id.x()
53  %gep.0 = getelementptr half, half addrspace(1)* %out, i32 %tid
54  %gep.1 = getelementptr half, half addrspace(1)* %gep.0, i32 1
55  %gep.out = getelementptr half, half addrspace(1)* %out, i32 %tid
56
57  %r1 = load volatile half, half addrspace(1)* %gep.0
58  %r2 = load volatile half, half addrspace(1)* %gep.1
59
60  %r3 = tail call half @llvm.fmuladd.f16(half 2.0, half %r1, half %r2)
61  store half %r3, half addrspace(1)* %gep.out
62  ret void
63}
64
65; GCN-LABEL: {{^}}fmuladd_a_2.0_b_f16
66; GCN: {{buffer|flat|global}}_load_ushort [[R1:v[0-9]+]],
67; GCN: {{buffer|flat|global}}_load_ushort [[R2:v[0-9]+]],
68; VI-FLUSH: v_mac_f16_e32 [[R2]], 2.0, [[R1]]
69; VI-FLUSH: flat_store_short v{{\[[0-9]+:[0-9]+\]}}, [[R2]]
70
71; VI-DENORM:    v_fma_f16 [[RESULT:v[0-9]+]], [[R1]], 2.0, [[R2]]
72; GFX10-DENORM: v_fmac_f16_e32 [[R2]], 2.0, [[R1]]
73
74; GFX10-FLUSH:  v_add_f16_e32 [[MUL2:v[0-9]+]], [[R1]], [[R1]]
75; GFX10-FLUSH:  v_add_f16_e32 [[RESULT:v[0-9]+]], [[MUL2]], [[R2]]
76
77; VI-DENORM: flat_store_short v{{\[[0-9]+:[0-9]+\]}}, [[RESULT]]
78; GFX10-DENORM: global_store_short v{{\[[0-9]+:[0-9]+\]}}, [[R2]]
79; GFX10-FLUSH:  global_store_short v{{\[[0-9]+:[0-9]+\]}}, [[RESULT]]
80
81define amdgpu_kernel void @fmuladd_a_2.0_b_f16(half addrspace(1)* %out, half addrspace(1)* %in) #0 {
82  %tid = call i32 @llvm.amdgcn.workitem.id.x()
83  %gep.0 = getelementptr half, half addrspace(1)* %out, i32 %tid
84  %gep.1 = getelementptr half, half addrspace(1)* %gep.0, i32 1
85  %gep.out = getelementptr half, half addrspace(1)* %out, i32 %tid
86
87  %r1 = load volatile half, half addrspace(1)* %gep.0
88  %r2 = load volatile half, half addrspace(1)* %gep.1
89
90  %r3 = tail call half @llvm.fmuladd.f16(half %r1, half 2.0, half %r2)
91  store half %r3, half addrspace(1)* %gep.out
92  ret void
93}
94
95; GCN-LABEL: {{^}}fadd_a_a_b_f16:
96; GCN: {{buffer|flat|global}}_load_ushort [[R1:v[0-9]+]],
97; GCN: {{buffer|flat|global}}_load_ushort [[R2:v[0-9]+]],
98; VI-FLUSH: v_mac_f16_e32 [[R2]], 2.0, [[R1]]
99; VI-FLUSH: flat_store_short v{{\[[0-9]+:[0-9]+\]}}, [[R2]]
100
101; VI-DENORM-CONTRACT:    v_fma_f16 [[RESULT:v[0-9]+]], [[R1]], 2.0, [[R2]]
102; GFX10-DENORM-CONTRACT: v_fmac_f16_e32 [[R2]], 2.0, [[R1]]
103
104; GCN-DENORM-STRICT: v_add_f16_e32 [[TMP:v[0-9]+]], [[R1]], [[R1]]
105; GCN-DENORM-STRICT: v_add_f16_e32 [[RESULT:v[0-9]+]], [[TMP]], [[R2]]
106
107; VI-DENORM: flat_store_short v{{\[[0-9]+:[0-9]+\]}}, [[RESULT]]
108
109; GFX10-FLUSH:           v_add_f16_e32 [[MUL2:v[0-9]+]], [[R1]], [[R1]]
110; GFX10-FLUSH:           v_add_f16_e32 [[RESULT:v[0-9]+]], [[MUL2]], [[R2]]
111; GFX10-FLUSH:           global_store_short v{{\[[0-9]+:[0-9]+\]}}, [[RESULT]]
112; GFX10-DENORM-STRICT:   global_store_short v{{\[[0-9]+:[0-9]+\]}}, [[RESULT]]
113; GFX10-DENORM-CONTRACT: global_store_short v{{\[[0-9]+:[0-9]+\]}}, [[R2]]
114
115define amdgpu_kernel void @fadd_a_a_b_f16(half addrspace(1)* %out,
116                            half addrspace(1)* %in1,
117                            half addrspace(1)* %in2) #0 {
118  %tid = call i32 @llvm.amdgcn.workitem.id.x()
119  %gep.0 = getelementptr half, half addrspace(1)* %out, i32 %tid
120  %gep.1 = getelementptr half, half addrspace(1)* %gep.0, i32 1
121  %gep.out = getelementptr half, half addrspace(1)* %out, i32 %tid
122
123  %r0 = load volatile half, half addrspace(1)* %gep.0
124  %r1 = load volatile half, half addrspace(1)* %gep.1
125
126  %add.0 = fadd half %r0, %r0
127  %add.1 = fadd half %add.0, %r1
128  store half %add.1, half addrspace(1)* %gep.out
129  ret void
130}
131
132; GCN-LABEL: {{^}}fadd_b_a_a_f16:
133; GCN: {{buffer|flat|global}}_load_ushort [[R1:v[0-9]+]],
134; GCN: {{buffer|flat|global}}_load_ushort [[R2:v[0-9]+]],
135; VI-FLUSH: v_mac_f16_e32 [[R2]], 2.0, [[R1]]
136; VI-FLUSH: flat_store_short v{{\[[0-9]+:[0-9]+\]}}, [[R2]]
137
138; VI-DENORM-CONTRACT:    v_fma_f16 [[RESULT:v[0-9]+]], [[R1]], 2.0, [[R2]]
139; GFX10-DENORM-CONTRACT: v_fmac_f16_e32 [[R2]], 2.0, [[R1]]
140
141; GCN-DENORM-STRICT: v_add_f16_e32 [[TMP:v[0-9]+]], [[R1]], [[R1]]
142; GCN-DENORM-STRICT: v_add_f16_e32 [[RESULT:v[0-9]+]],  [[R2]], [[TMP]]
143
144; VI-DENORM: flat_store_short v{{\[[0-9]+:[0-9]+\]}}, [[RESULT]]
145
146; GFX10-FLUSH: v_add_f16_e32 [[MUL2:v[0-9]+]], [[R1]], [[R1]]
147; GFX10-FLUSH: v_add_f16_e32 [[RESULT:v[0-9]+]], [[R2]], [[MUL2]]
148; GFX10-FLUSH: global_store_short v{{\[[0-9]+:[0-9]+\]}}, [[RESULT]]
149; GFX10-DENORM-STRICT:   global_store_short v{{\[[0-9]+:[0-9]+\]}}, [[RESULT]]
150; GFX10-DENORM-CONTRACT: global_store_short v{{\[[0-9]+:[0-9]+\]}}, [[R2]]
151
152define amdgpu_kernel void @fadd_b_a_a_f16(half addrspace(1)* %out,
153                            half addrspace(1)* %in1,
154                            half addrspace(1)* %in2) #0 {
155  %tid = call i32 @llvm.amdgcn.workitem.id.x()
156  %gep.0 = getelementptr half, half addrspace(1)* %out, i32 %tid
157  %gep.1 = getelementptr half, half addrspace(1)* %gep.0, i32 1
158  %gep.out = getelementptr half, half addrspace(1)* %out, i32 %tid
159
160  %r0 = load volatile half, half addrspace(1)* %gep.0
161  %r1 = load volatile half, half addrspace(1)* %gep.1
162
163  %add.0 = fadd half %r0, %r0
164  %add.1 = fadd half %r1, %add.0
165  store half %add.1, half addrspace(1)* %gep.out
166  ret void
167}
168
169; GCN-LABEL: {{^}}fmuladd_neg_2.0_a_b_f16
170; GCN: {{buffer|flat|global}}_load_ushort [[R1:v[0-9]+]],
171; GCN: {{buffer|flat|global}}_load_ushort [[R2:v[0-9]+]],
172; VI-FLUSH:     v_mac_f16_e32 [[R2]], -2.0, [[R1]]
173; VI-DENORM:    v_fma_f16 [[RESULT:v[0-9]+]], [[R1]], -2.0, [[R2]]
174; GFX10-DENORM: v_fmac_f16_e32 [[R2]], -2.0, [[R1]]
175; VI-FLUSH:  flat_store_short v{{\[[0-9]+:[0-9]+\]}}, [[R2]]
176; VI-DENORM: flat_store_short v{{\[[0-9]+:[0-9]+\]}}, [[RESULT]]
177; GFX10-FLUSH: v_add_f16_e32 [[MUL2:v[0-9]+]], [[R1]], [[R1]]
178; GFX10-FLUSH: v_sub_f16_e32 [[RESULT:v[0-9]+]], [[R2]], [[MUL2]]
179; GFX10-FLUSH:  global_store_short v{{\[[0-9]+:[0-9]+\]}}, [[RESULT]]
180; GFX10-DENORM: global_store_short v{{\[[0-9]+:[0-9]+\]}}, [[R2]]
181define amdgpu_kernel void @fmuladd_neg_2.0_a_b_f16(half addrspace(1)* %out, half addrspace(1)* %in) #0 {
182  %tid = call i32 @llvm.amdgcn.workitem.id.x()
183  %gep.0 = getelementptr half, half addrspace(1)* %out, i32 %tid
184  %gep.1 = getelementptr half, half addrspace(1)* %gep.0, i32 1
185  %gep.out = getelementptr half, half addrspace(1)* %out, i32 %tid
186
187  %r1 = load volatile half, half addrspace(1)* %gep.0
188  %r2 = load volatile half, half addrspace(1)* %gep.1
189
190  %r3 = tail call half @llvm.fmuladd.f16(half -2.0, half %r1, half %r2)
191  store half %r3, half addrspace(1)* %gep.out
192  ret void
193}
194
195; GCN-LABEL: {{^}}fmuladd_neg_2.0_neg_a_b_f16
196; GCN: {{buffer|flat|global}}_load_ushort [[R1:v[0-9]+]],
197; GCN: {{buffer|flat|global}}_load_ushort [[R2:v[0-9]+]],
198; VI-FLUSH: v_mac_f16_e32 [[R2]], 2.0, [[R1]]
199; VI-FLUSH: flat_store_short v{{\[[0-9]+:[0-9]+\]}}, [[R2]]
200
201; VI-DENORM:    v_fma_f16 [[RESULT:v[0-9]+]], [[R1]], 2.0, [[R2]]
202; VI-DENORM:  flat_store_short v{{\[[0-9]+:[0-9]+\]}}, [[RESULT]]
203
204; GFX10-FLUSH: v_add_f16_e32 [[MUL2:v[0-9]+]], [[R1]], [[R1]]
205; GFX10-FLUSH: v_add_f16_e32 [[RESULT:v[0-9]+]], [[R2]], [[MUL2]]
206; GFX10-FLUSH:  global_store_short v{{\[[0-9]+:[0-9]+\]}}, [[RESULT]]
207
208; GFX10-DENORM: v_fmac_f16_e32 [[R2]], 2.0, [[R1]]
209; GFX10-DENORM: global_store_short v{{\[[0-9]+:[0-9]+\]}}, [[R2]]
210define amdgpu_kernel void @fmuladd_neg_2.0_neg_a_b_f16(half addrspace(1)* %out, half addrspace(1)* %in) #0 {
211  %tid = call i32 @llvm.amdgcn.workitem.id.x()
212  %gep.0 = getelementptr half, half addrspace(1)* %out, i32 %tid
213  %gep.1 = getelementptr half, half addrspace(1)* %gep.0, i32 1
214  %gep.out = getelementptr half, half addrspace(1)* %out, i32 %tid
215
216  %r1 = load volatile half, half addrspace(1)* %gep.0
217  %r2 = load volatile half, half addrspace(1)* %gep.1
218
219  %r1.fneg = fsub half -0.000000e+00, %r1
220
221  %r3 = tail call half @llvm.fmuladd.f16(half -2.0, half %r1.fneg, half %r2)
222  store half %r3, half addrspace(1)* %gep.out
223  ret void
224}
225
226; GCN-LABEL: {{^}}fmuladd_2.0_neg_a_b_f16
227; GCN: {{buffer|flat|global}}_load_ushort [[R1:v[0-9]+]],
228; GCN: {{buffer|flat|global}}_load_ushort [[R2:v[0-9]+]],
229; VI-FLUSH: v_mac_f16_e32 [[R2]], -2.0, [[R1]]
230; VI-FLUSH: flat_store_short v{{\[[0-9]+:[0-9]+\]}}, [[R2]]
231
232; VI-DENORM: v_fma_f16 [[RESULT:v[0-9]+]], [[R1]], -2.0, [[R2]]
233; VI-DENORM:  flat_store_short v{{\[[0-9]+:[0-9]+\]}}, [[RESULT]]
234
235; GFX10-FLUSH: v_add_f16_e32 [[MUL2:v[0-9]+]], [[R1]], [[R1]]
236; GFX10-FLUSH: v_sub_f16_e32 [[RESULT:v[0-9]+]], [[R2]], [[MUL2]]
237; GFX10-FLUSH: global_store_short v{{\[[0-9]+:[0-9]+\]}}, [[RESULT]]
238
239; GFX10-DENORM: v_fmac_f16_e32 [[R2]], -2.0, [[R1]]
240; GFX10-DENORM: global_store_short v{{\[[0-9]+:[0-9]+\]}}, [[R2]]
241define amdgpu_kernel void @fmuladd_2.0_neg_a_b_f16(half addrspace(1)* %out, half addrspace(1)* %in) #0 {
242  %tid = call i32 @llvm.amdgcn.workitem.id.x()
243  %gep.0 = getelementptr half, half addrspace(1)* %out, i32 %tid
244  %gep.1 = getelementptr half, half addrspace(1)* %gep.0, i32 1
245  %gep.out = getelementptr half, half addrspace(1)* %out, i32 %tid
246
247  %r1 = load volatile half, half addrspace(1)* %gep.0
248  %r2 = load volatile half, half addrspace(1)* %gep.1
249
250  %r1.fneg = fsub half -0.000000e+00, %r1
251
252  %r3 = tail call half @llvm.fmuladd.f16(half 2.0, half %r1.fneg, half %r2)
253  store half %r3, half addrspace(1)* %gep.out
254  ret void
255}
256
257; GCN-LABEL: {{^}}fmuladd_2.0_a_neg_b_f16
258; GCN: {{buffer|flat|global}}_load_ushort [[R1:v[0-9]+]],
259; GCN: {{buffer|flat|global}}_load_ushort [[R2:v[0-9]+]],
260; VI-FLUSH:   v_mad_f16 [[RESULT:v[0-9]+]], [[R1]], 2.0, -[[R2]]
261; GCN-DENORM: v_fma_f16 [[RESULT:v[0-9]+]], [[R1]], 2.0, -[[R2]]
262; VI: flat_store_short v{{\[[0-9]+:[0-9]+\]}}, [[RESULT]]
263; GFX10-FLUSH: v_add_f16_e32 [[MUL2:v[0-9]+]], [[R1]], [[R1]]
264; GFX10-FLUSH: v_sub_f16_e32 [[RESULT:v[0-9]+]], [[MUL2]], [[R2]]
265; GFX10:       global_store_short v{{\[[0-9]+:[0-9]+\]}}, [[RESULT]]
266define amdgpu_kernel void @fmuladd_2.0_a_neg_b_f16(half addrspace(1)* %out, half addrspace(1)* %in) #0 {
267  %tid = call i32 @llvm.amdgcn.workitem.id.x()
268  %gep.0 = getelementptr half, half addrspace(1)* %out, i32 %tid
269  %gep.1 = getelementptr half, half addrspace(1)* %gep.0, i32 1
270  %gep.out = getelementptr half, half addrspace(1)* %out, i32 %tid
271
272  %r1 = load volatile half, half addrspace(1)* %gep.0
273  %r2 = load volatile half, half addrspace(1)* %gep.1
274
275  %r2.fneg = fsub half -0.000000e+00, %r2
276
277  %r3 = tail call half @llvm.fmuladd.f16(half 2.0, half %r1, half %r2.fneg)
278  store half %r3, half addrspace(1)* %gep.out
279  ret void
280}
281
282; GCN-LABEL: {{^}}mad_sub_f16:
283; GCN: {{buffer|flat|global}}_load_ushort [[REGA:v[0-9]+]]
284; GCN: {{buffer|flat|global}}_load_ushort [[REGB:v[0-9]+]]
285; GCN: {{buffer|flat|global}}_load_ushort [[REGC:v[0-9]+]]
286
287; VI-FLUSH: v_mad_f16 [[RESULT:v[0-9]+]], [[REGA]], [[REGB]], -[[REGC]]
288
289; GCN-DENORM-CONTRACT: v_fma_f16 [[RESULT:v[0-9]+]], [[REGA]], [[REGB]], -[[REGC]]
290
291; GCN-DENORM-STRICT: v_mul_f16_e32 [[TMP:v[0-9]+]], [[REGA]], [[REGB]]
292; GCN-DENORM-STRICT: v_sub_f16_e32 [[RESULT:v[0-9]+]], [[TMP]], [[REGC]]
293
294; VI: flat_store_short v{{\[[0-9]+:[0-9]+\]}}, [[RESULT]]
295
296; GFX10-FLUSH: v_mul_f16_e32 [[TMP:v[0-9]+]], [[REGA]], [[REGB]]
297; GFX10-FLUSH: v_sub_f16_e32 [[RESULT:v[0-9]+]], [[TMP]], [[REGC]]
298; GFX10:       global_store_short v{{\[[0-9]+:[0-9]+\]}}, [[RESULT]]
299define amdgpu_kernel void @mad_sub_f16(half addrspace(1)* noalias nocapture %out, half addrspace(1)* noalias nocapture readonly %ptr) #1 {
300  %tid = tail call i32 @llvm.amdgcn.workitem.id.x() #0
301  %tid.ext = sext i32 %tid to i64
302  %gep0 = getelementptr half, half addrspace(1)* %ptr, i64 %tid.ext
303  %add1 = add i64 %tid.ext, 1
304  %gep1 = getelementptr half, half addrspace(1)* %ptr, i64 %add1
305  %add2 = add i64 %tid.ext, 2
306  %gep2 = getelementptr half, half addrspace(1)* %ptr, i64 %add2
307  %outgep = getelementptr half, half addrspace(1)* %out, i64 %tid.ext
308  %a = load volatile half, half addrspace(1)* %gep0, align 2
309  %b = load volatile half, half addrspace(1)* %gep1, align 2
310  %c = load volatile half, half addrspace(1)* %gep2, align 2
311  %mul = fmul half %a, %b
312  %sub = fsub half %mul, %c
313  store half %sub, half addrspace(1)* %outgep, align 2
314  ret void
315}
316
317; GCN-LABEL: {{^}}mad_sub_inv_f16:
318; GCN: {{buffer|flat|global}}_load_ushort [[REGA:v[0-9]+]]
319; GCN: {{buffer|flat|global}}_load_ushort [[REGB:v[0-9]+]]
320; GCN: {{buffer|flat|global}}_load_ushort [[REGC:v[0-9]+]]
321; VI-FLUSH: v_mad_f16 [[RESULT:v[0-9]+]], -[[REGA]], [[REGB]], [[REGC]]
322
323; VI-DENORM-CONTRACT:    v_fma_f16 [[RESULT:v[0-9]+]], -[[REGA]], [[REGB]], [[REGC]]
324; GFX10-DENORM-CONTRACT: v_fmac_f16_e64 [[REGC]], -[[REGA]], [[REGB]]
325
326; GCN-DENORM-STRICT: v_mul_f16_e32 [[TMP:v[0-9]+]], [[REGA]], [[REGB]]
327; GCN-DENORM-STRICT: v_sub_f16_e32 [[RESULT:v[0-9]+]], [[REGC]], [[TMP]]
328
329; VI: flat_store_short v{{\[[0-9]+:[0-9]+\]}}, [[RESULT]]
330
331; GFX10-FLUSH: v_mul_f16_e32 [[TMP:v[0-9]+]], [[REGA]], [[REGB]]
332; GFX10-FLUSH: v_sub_f16_e32 [[RESULT:v[0-9]+]], [[REGC]], [[TMP]]
333; GFX10-FLUSH:  global_store_short v{{\[[0-9]+:[0-9]+\]}}, [[RESULT]]
334; GFX10-DENORM-STRICT: global_store_short v{{\[[0-9]+:[0-9]+\]}}, [[RESULT]]
335; GFX10-DENORM-CONTRACT: global_store_short v{{\[[0-9]+:[0-9]+\]}}, [[REGC]]
336define amdgpu_kernel void @mad_sub_inv_f16(half addrspace(1)* noalias nocapture %out, half addrspace(1)* noalias nocapture readonly %ptr) #1 {
337  %tid = tail call i32 @llvm.amdgcn.workitem.id.x() #0
338  %tid.ext = sext i32 %tid to i64
339  %gep0 = getelementptr half, half addrspace(1)* %ptr, i64 %tid.ext
340  %add1 = add i64 %tid.ext, 1
341  %gep1 = getelementptr half, half addrspace(1)* %ptr, i64 %add1
342  %add2 = add i64 %tid.ext, 2
343  %gep2 = getelementptr half, half addrspace(1)* %ptr, i64 %add2
344  %outgep = getelementptr half, half addrspace(1)* %out, i64 %tid.ext
345  %a = load volatile half, half addrspace(1)* %gep0, align 2
346  %b = load volatile half, half addrspace(1)* %gep1, align 2
347  %c = load volatile half, half addrspace(1)* %gep2, align 2
348  %mul = fmul half %a, %b
349  %sub = fsub half %c, %mul
350  store half %sub, half addrspace(1)* %outgep, align 2
351  ret void
352}
353
354; GCN-LABEL: {{^}}mad_sub_fabs_f16:
355; GCN: {{buffer|flat|global}}_load_ushort [[REGA:v[0-9]+]]
356; GCN: {{buffer|flat|global}}_load_ushort [[REGB:v[0-9]+]]
357; GCN: {{buffer|flat|global}}_load_ushort [[REGC:v[0-9]+]]
358; VI-FLUSH: v_mad_f16 [[RESULT:v[0-9]+]], [[REGA]], [[REGB]], -|[[REGC]]|
359
360; GCN-DENORM-CONTRACT: v_fma_f16 [[RESULT:v[0-9]+]], [[REGA]], [[REGB]], -|[[REGC]]|
361
362; GCN-DENORM-STRICT: v_mul_f16_e32 [[TMP:v[0-9]+]], [[REGA]], [[REGB]]
363; GCN-DENORM-STRICT: v_sub_f16_e64 [[RESULT:v[0-9]+]], [[TMP]], |[[REGC]]|
364
365; VI: flat_store_short v{{\[[0-9]+:[0-9]+\]}}, [[RESULT]]
366
367; GFX10-FLUSH: v_mul_f16_e32 [[TMP:v[0-9]+]], [[REGA]], [[REGB]]
368; GFX10-FLUSH: v_sub_f16_e64 [[RESULT:v[0-9]+]], [[TMP]], |[[REGC]]|
369; GFX10:       global_store_short v{{\[[0-9]+:[0-9]+\]}}, [[RESULT]]
370define amdgpu_kernel void @mad_sub_fabs_f16(half addrspace(1)* noalias nocapture %out, half addrspace(1)* noalias nocapture readonly %ptr) #1 {
371  %tid = tail call i32 @llvm.amdgcn.workitem.id.x() #0
372  %tid.ext = sext i32 %tid to i64
373  %gep0 = getelementptr half, half addrspace(1)* %ptr, i64 %tid.ext
374  %add1 = add i64 %tid.ext, 1
375  %gep1 = getelementptr half, half addrspace(1)* %ptr, i64 %add1
376  %add2 = add i64 %tid.ext, 2
377  %gep2 = getelementptr half, half addrspace(1)* %ptr, i64 %add2
378  %outgep = getelementptr half, half addrspace(1)* %out, i64 %tid.ext
379  %a = load volatile half, half addrspace(1)* %gep0, align 2
380  %b = load volatile half, half addrspace(1)* %gep1, align 2
381  %c = load volatile half, half addrspace(1)* %gep2, align 2
382  %c.abs = call half @llvm.fabs.f16(half %c) #0
383  %mul = fmul half %a, %b
384  %sub = fsub half %mul, %c.abs
385  store half %sub, half addrspace(1)* %outgep, align 2
386  ret void
387}
388
389; GCN-LABEL: {{^}}mad_sub_fabs_inv_f16:
390; GCN: {{buffer|flat|global}}_load_ushort [[REGA:v[0-9]+]]
391; GCN: {{buffer|flat|global}}_load_ushort [[REGB:v[0-9]+]]
392; GCN: {{buffer|flat|global}}_load_ushort [[REGC:v[0-9]+]]
393
394; VI-FLUSH: v_mad_f16 [[RESULT:v[0-9]+]], -[[REGA]], [[REGB]], |[[REGC]]|
395
396; GCN-DENORM-CONTRACT: v_fma_f16 [[RESULT:v[0-9]+]], -[[REGA]], [[REGB]], |[[REGC]]|
397
398; GCN-DENORM-STRICT: v_mul_f16_e32 [[TMP:v[0-9]+]], [[REGA]], [[REGB]]
399; GCN-DENORM-STRICT: v_sub_f16_e64 [[RESULT:v[0-9]+]], |[[REGC]]|, [[TMP]]
400
401; VI: flat_store_short v{{\[[0-9]+:[0-9]+\]}}, [[RESULT]]
402
403; GFX10-FLUSH: v_mul_f16_e32 [[TMP:v[0-9]+]], [[REGA]], [[REGB]]
404; GFX10-FLUSH: v_sub_f16_e64 [[RESULT:v[0-9]+]], |[[REGC]]|, [[TMP]]
405; GFX10:       global_store_short v{{\[[0-9]+:[0-9]+\]}}, [[RESULT]]
406define amdgpu_kernel void @mad_sub_fabs_inv_f16(half addrspace(1)* noalias nocapture %out, half addrspace(1)* noalias nocapture readonly %ptr) #1 {
407  %tid = tail call i32 @llvm.amdgcn.workitem.id.x() #0
408  %tid.ext = sext i32 %tid to i64
409  %gep0 = getelementptr half, half addrspace(1)* %ptr, i64 %tid.ext
410  %add1 = add i64 %tid.ext, 1
411  %gep1 = getelementptr half, half addrspace(1)* %ptr, i64 %add1
412  %add2 = add i64 %tid.ext, 2
413  %gep2 = getelementptr half, half addrspace(1)* %ptr, i64 %add2
414  %outgep = getelementptr half, half addrspace(1)* %out, i64 %tid.ext
415  %a = load volatile half, half addrspace(1)* %gep0, align 2
416  %b = load volatile half, half addrspace(1)* %gep1, align 2
417  %c = load volatile half, half addrspace(1)* %gep2, align 2
418  %c.abs = call half @llvm.fabs.f16(half %c) #0
419  %mul = fmul half %a, %b
420  %sub = fsub half %c.abs, %mul
421  store half %sub, half addrspace(1)* %outgep, align 2
422  ret void
423}
424
425; GCN-LABEL: {{^}}neg_neg_mad_f16:
426; GCN: {{buffer|flat|global}}_load_ushort [[REGA:v[0-9]+]]
427; GCN: {{buffer|flat|global}}_load_ushort [[REGB:v[0-9]+]]
428; GCN: {{buffer|flat|global}}_load_ushort [[REGC:v[0-9]+]]
429
430; VI-FLUSH: v_mac_f16_e32 [[REGC]], [[REGA]], [[REGB]]
431; VI-FLUSH: flat_store_short v{{\[[0-9]+:[0-9]+\]}}, [[REGC]]
432
433; VI-DENORM-CONTRACT:    v_fma_f16 [[RESULT:v[0-9]+]], [[REGA]], [[REGB]], [[REGC]]
434; GFX10-DENORM-CONTRACT: v_fmac_f16_e32 [[REGC]], [[REGA]], [[REGB]]
435
436; GCN-DENORM-STRICT: v_mul_f16_e32 [[TMP:v[0-9]+]], [[REGA]], [[REGB]]
437; GCN-DENORM-STRICT: v_add_f16_e32 [[RESULT:v[0-9]+]], [[REGC]], [[TMP]]
438; VI-DENORM: flat_store_short v{{\[[0-9]+:[0-9]+\]}}, [[RESULT]]
439
440; GFX10-FLUSH: v_mul_f16_e32 [[TMP:v[0-9]+]], [[REGA]], [[REGB]]
441; GFX10-FLUSH: v_add_f16_e32 [[RESULT:v[0-9]+]], [[REGC]], [[TMP]]
442; GFX10-FLUSH:  global_store_short v{{\[[0-9]+:[0-9]+\]}}, [[RESULT]]
443; GFX10-DENORM-STRICT: global_store_short v{{\[[0-9]+:[0-9]+\]}}, [[RESULT]]
444; GFX10-DENORM-CONTRACT: global_store_short v{{\[[0-9]+:[0-9]+\]}}, [[REGC]]
445define amdgpu_kernel void @neg_neg_mad_f16(half addrspace(1)* noalias nocapture %out, half addrspace(1)* noalias nocapture readonly %ptr) #1 {
446  %tid = tail call i32 @llvm.amdgcn.workitem.id.x() #0
447  %tid.ext = sext i32 %tid to i64
448  %gep0 = getelementptr half, half addrspace(1)* %ptr, i64 %tid.ext
449  %add1 = add i64 %tid.ext, 1
450  %gep1 = getelementptr half, half addrspace(1)* %ptr, i64 %add1
451  %add2 = add i64 %tid.ext, 2
452  %gep2 = getelementptr half, half addrspace(1)* %ptr, i64 %add2
453  %outgep = getelementptr half, half addrspace(1)* %out, i64 %tid.ext
454  %a = load volatile half, half addrspace(1)* %gep0, align 2
455  %b = load volatile half, half addrspace(1)* %gep1, align 2
456  %c = load volatile half, half addrspace(1)* %gep2, align 2
457  %nega = fsub half -0.000000e+00, %a
458  %negb = fsub half -0.000000e+00, %b
459  %mul = fmul half %nega, %negb
460  %sub = fadd half %mul, %c
461  store half %sub, half addrspace(1)* %outgep, align 2
462  ret void
463}
464
465; GCN-LABEL: {{^}}mad_fabs_sub_f16:
466; GCN: {{buffer|flat|global}}_load_ushort [[REGA:v[0-9]+]]
467; GCN: {{buffer|flat|global}}_load_ushort [[REGB:v[0-9]+]]
468; GCN: {{buffer|flat|global}}_load_ushort [[REGC:v[0-9]+]]
469
470; VI-FLUSH: v_mad_f16 [[RESULT:v[0-9]+]], [[REGA]], |[[REGB]]|, -[[REGC]]
471
472; GCN-DENORM-CONTRACT: v_fma_f16 [[RESULT:v[0-9]+]], [[REGA]], |[[REGB]]|, -[[REGC]]
473
474; GCN-DENORM-STRICT: v_mul_f16_e64 [[TMP:v[0-9]+]], [[REGA]], |[[REGB]]|
475; GCN-DENORM-STRICT: v_sub_f16_e32 [[RESULT:v[0-9]+]], [[TMP]], [[REGC]]
476
477; VI: flat_store_short v{{\[[0-9]+:[0-9]+\]}}, [[RESULT]]
478
479; GFX10-FLUSH: v_mul_f16_e64 [[TMP:v[0-9]+]], [[REGA]], |[[REGB]]|
480; GFX10-FLUSH: v_sub_f16_e32 [[RESULT:v[0-9]+]], [[TMP]], [[REGC]]
481; GFX10:       global_store_short v{{\[[0-9]+:[0-9]+\]}}, [[RESULT]]
482define amdgpu_kernel void @mad_fabs_sub_f16(half addrspace(1)* noalias nocapture %out, half addrspace(1)* noalias nocapture readonly %ptr) #1 {
483  %tid = tail call i32 @llvm.amdgcn.workitem.id.x() #0
484  %tid.ext = sext i32 %tid to i64
485  %gep0 = getelementptr half, half addrspace(1)* %ptr, i64 %tid.ext
486  %add1 = add i64 %tid.ext, 1
487  %gep1 = getelementptr half, half addrspace(1)* %ptr, i64 %add1
488  %add2 = add i64 %tid.ext, 2
489  %gep2 = getelementptr half, half addrspace(1)* %ptr, i64 %add2
490  %outgep = getelementptr half, half addrspace(1)* %out, i64 %tid.ext
491  %a = load volatile half, half addrspace(1)* %gep0, align 2
492  %b = load volatile half, half addrspace(1)* %gep1, align 2
493  %c = load volatile half, half addrspace(1)* %gep2, align 2
494  %b.abs = call half @llvm.fabs.f16(half %b) #0
495  %mul = fmul half %a, %b.abs
496  %sub = fsub half %mul, %c
497  store half %sub, half addrspace(1)* %outgep, align 2
498  ret void
499}
500
501; GCN-LABEL: {{^}}fsub_c_fadd_a_a_f16:
502; GCN: {{buffer|flat|global}}_load_ushort [[R1:v[0-9]+]],
503; GCN: {{buffer|flat|global}}_load_ushort [[R2:v[0-9]+]],
504; VI-FLUSH: v_mac_f16_e32 [[R2]], -2.0, [[R1]]
505; VI-FLUSH: flat_store_short v{{\[[0-9]+:[0-9]+\]}}, [[R2]]
506
507; VI-DENORM-CONTRACT:    v_fma_f16 [[RESULT:v[0-9]+]], [[R1]], -2.0, [[R2]]
508; GFX10-DENORM-CONTRACT: v_fmac_f16_e32 [[R2]], -2.0, [[R1]]
509
510; GCN-DENORM-STRICT: v_add_f16_e32 [[TMP:v[0-9]+]], [[R1]], [[R1]]
511; GCN-DENORM-STRICT: v_sub_f16_e32 [[RESULT:v[0-9]+]], [[R2]], [[TMP]]
512
513; VI-DENORM: flat_store_short v{{\[[0-9]+:[0-9]+\]}}, [[RESULT]]
514
515; GFX10-FLUSH: v_add_f16_e32 [[TMP:v[0-9]+]], [[R1]], [[R1]]
516; GFX10-FLUSH: v_sub_f16_e32 [[RESULT:v[0-9]+]], [[R2]], [[TMP]]
517; GFX10-FLUSH:  global_store_short v{{\[[0-9]+:[0-9]+\]}}, [[RESULT]]
518; GFX10-DENORM-STRICT:   global_store_short v{{\[[0-9]+:[0-9]+\]}}, [[RESULT]]
519; GFX10-DENORM-CONTRACT: global_store_short v{{\[[0-9]+:[0-9]+\]}}, [[R2]]
520define amdgpu_kernel void @fsub_c_fadd_a_a_f16(half addrspace(1)* %out, half addrspace(1)* %in) {
521  %tid = call i32 @llvm.amdgcn.workitem.id.x()
522  %gep.0 = getelementptr half, half addrspace(1)* %out, i32 %tid
523  %gep.1 = getelementptr half, half addrspace(1)* %gep.0, i32 1
524  %gep.out = getelementptr half, half addrspace(1)* %out, i32 %tid
525
526  %r1 = load volatile half, half addrspace(1)* %gep.0
527  %r2 = load volatile half, half addrspace(1)* %gep.1
528
529  %add = fadd half %r1, %r1
530  %r3 = fsub half %r2, %add
531
532  store half %r3, half addrspace(1)* %gep.out
533  ret void
534}
535
536; GCN-LABEL: {{^}}fsub_fadd_a_a_c_f16:
537; GCN: {{buffer|flat|global}}_load_ushort [[R1:v[0-9]+]],
538; GCN: {{buffer|flat|global}}_load_ushort [[R2:v[0-9]+]],
539
540; VI-FLUSH: v_mad_f16 [[RESULT:v[0-9]+]], [[R1]], 2.0, -[[R2]]
541
542; GCN-DENORM-CONTRACT: v_fma_f16 [[RESULT:v[0-9]+]], [[R1]], 2.0, -[[R2]]
543
544; GCN-DENORM-STRICT: v_add_f16_e32 [[TMP:v[0-9]+]], [[R1]], [[R1]]
545; GCN-DENORM-STRICT: v_sub_f16_e32 [[RESULT:v[0-9]+]], [[TMP]], [[R2]]
546
547; VI: flat_store_short v{{\[[0-9]+:[0-9]+\]}}, [[RESULT]]
548
549; GFX10-FLUSH: v_add_f16_e32 [[TMP:v[0-9]+]], [[R1]], [[R1]]
550; GFX10-FLUSH: v_sub_f16_e32 [[RESULT:v[0-9]+]], [[TMP]], [[R2]]
551; GFX10:       global_store_short v{{\[[0-9]+:[0-9]+\]}}, [[RESULT]]
552define amdgpu_kernel void @fsub_fadd_a_a_c_f16(half addrspace(1)* %out, half addrspace(1)* %in) {
553  %tid = call i32 @llvm.amdgcn.workitem.id.x()
554  %gep.0 = getelementptr half, half addrspace(1)* %out, i32 %tid
555  %gep.1 = getelementptr half, half addrspace(1)* %gep.0, i32 1
556  %gep.out = getelementptr half, half addrspace(1)* %out, i32 %tid
557
558  %r1 = load volatile half, half addrspace(1)* %gep.0
559  %r2 = load volatile half, half addrspace(1)* %gep.1
560
561  %add = fadd half %r1, %r1
562  %r3 = fsub half %add, %r2
563
564  store half %r3, half addrspace(1)* %gep.out
565  ret void
566}
567
568attributes #0 = { nounwind }
569attributes #1 = { nounwind readnone }
570