1; RUN: llc -march=amdgcn -mcpu=tahiti -verify-machineinstrs < %s | FileCheck -check-prefixes=GCN,GFX6,GFX6_8_9,MAD %s
2; RUN: llc -march=amdgcn -mcpu=tonga -verify-machineinstrs < %s | FileCheck -check-prefixes=GCN,GFX8,GFX6_8_9,GFX8_9,GFX8_9_10,MAD %s
3; RUN: llc -march=amdgcn -mcpu=gfx900 -verify-machineinstrs  -amdgpu-enable-global-sgpr-addr < %s | FileCheck -check-prefixes=GCN,GFX9,GFX6_8_9,GFX8_9,GFX8_9_10,MAD %s
4; RUN: llc -march=amdgcn -mcpu=gfx1010 -verify-machineinstrs -amdgpu-enable-global-sgpr-addr < %s | FileCheck -check-prefixes=GCN,GFX10,GFX8_9_10,GFX10-MAD %s
5; RUN: llc -march=amdgcn -mcpu=gfx1010 -verify-machineinstrs -fp-contract=fast -amdgpu-enable-global-sgpr-addr < %s | FileCheck -check-prefixes=GCN,GFX10,GFX8_9_10,FMA %s
6
7declare i32 @llvm.amdgcn.workitem.id.x() nounwind readnone
8declare float @llvm.fabs.f32(float) nounwind readnone
9
10; GCN-LABEL: {{^}}madak_f32:
11; GFX6:   buffer_load_dword [[VA:v[0-9]+]]
12; GFX6:   buffer_load_dword [[VB:v[0-9]+]]
13; GFX8: {{flat|global}}_load_dword [[VA:v[0-9]+]]
14; GFX8: {{flat|global}}_load_dword [[VB:v[0-9]+]]
15; GFX9: {{flat|global}}_load_dword [[VA:v[0-9]+]]
16; GFX9: {{flat|global}}_load_dword [[VB:v[0-9]+]]
17; GFX10: {{flat|global}}_load_dword [[VA:v[0-9]+]]
18; GFX10: {{flat|global}}_load_dword [[VB:v[0-9]+]]
19; MAD:   v_madak_f32 {{v[0-9]+}}, [[VA]], [[VB]], 0x41200000
20; GFX10-MAD:   v_madak_f32 {{v[0-9]+}}, [[VA]], [[VB]], 0x41200000
21; FMA:   v_fmaak_f32 {{v[0-9]+}}, [[VA]], [[VB]], 0x41200000
22define amdgpu_kernel void @madak_f32(float addrspace(1)* noalias %out, float addrspace(1)* noalias %in.a, float addrspace(1)* noalias %in.b) #0 {
23  %tid = tail call i32 @llvm.amdgcn.workitem.id.x() nounwind readnone
24  %in.a.gep = getelementptr float, float addrspace(1)* %in.a, i32 %tid
25  %in.b.gep = getelementptr float, float addrspace(1)* %in.b, i32 %tid
26  %out.gep = getelementptr float, float addrspace(1)* %out, i32 %tid
27
28  %a = load float, float addrspace(1)* %in.a.gep, align 4
29  %b = load float, float addrspace(1)* %in.b.gep, align 4
30
31  %mul = fmul float %a, %b
32  %madak = fadd float %mul, 10.0
33  store float %madak, float addrspace(1)* %out.gep, align 4
34  ret void
35}
36
37; Make sure this is only folded with one use. This is a code size
38; optimization and if we fold the immediate multiple times, we'll undo
39; it.
40
41; GCN-LABEL: {{^}}madak_2_use_f32:
42; GFX8_9_10:    v_mov_b32_e32 [[VK:v[0-9]+]], 0x41200000
43; GFX6-DAG:     buffer_load_dword [[VA:v[0-9]+]], {{v\[[0-9]+:[0-9]+\]}}, {{s\[[0-9]+:[0-9]+\]}}, 0 addr64{{$}}
44; GFX6-DAG:     buffer_load_dword [[VB:v[0-9]+]], {{v\[[0-9]+:[0-9]+\]}}, {{s\[[0-9]+:[0-9]+\]}}, 0 addr64 offset:4
45; GFX6-DAG:     buffer_load_dword [[VC:v[0-9]+]], {{v\[[0-9]+:[0-9]+\]}}, {{s\[[0-9]+:[0-9]+\]}}, 0 addr64 offset:8
46; GFX8_9_10:    {{flat|global}}_load_dword [[VA:v[0-9]+]], {{v\[[0-9]+:[0-9]+\]}}
47; GFX8_9_10:    {{flat|global}}_load_dword [[VB:v[0-9]+]], {{v\[[0-9]+:[0-9]+\]}}
48; GFX8_9_10:    {{flat|global}}_load_dword [[VC:v[0-9]+]], {{v\[[0-9]+:[0-9]+\]}}
49; GFX6-DAG:     v_mov_b32_e32 [[VK:v[0-9]+]], 0x41200000
50; GFX6_8_9-DAG: v_madak_f32 {{v[0-9]+}}, [[VA]], [[VB]], 0x41200000
51; GFX10-MAD-DAG:v_madak_f32 {{v[0-9]+}}, [[VA]], [[VB]], 0x41200000
52; FMA-DAG:      v_fmaak_f32 {{v[0-9]+}}, [[VA]], [[VB]], 0x41200000
53; MAD-DAG:      v_mac_f32_e32 [[VK]], [[VA]], [[VC]]
54; FMA-DAG:      v_fmac_f32_e32 [[VK]], [[VA]], [[VC]]
55; GCN:          s_endpgm
56define amdgpu_kernel void @madak_2_use_f32(float addrspace(1)* noalias %out, float addrspace(1)* noalias %in) #0 {
57  %tid = tail call i32 @llvm.amdgcn.workitem.id.x() nounwind readnone
58
59  %in.gep.0 = getelementptr float, float addrspace(1)* %in, i32 %tid
60  %in.gep.1 = getelementptr float, float addrspace(1)* %in.gep.0, i32 1
61  %in.gep.2 = getelementptr float, float addrspace(1)* %in.gep.0, i32 2
62
63  %out.gep.0 = getelementptr float, float addrspace(1)* %out, i32 %tid
64  %out.gep.1 = getelementptr float, float addrspace(1)* %in.gep.0, i32 1
65
66  %a = load volatile float, float addrspace(1)* %in.gep.0, align 4
67  %b = load volatile float, float addrspace(1)* %in.gep.1, align 4
68  %c = load volatile float, float addrspace(1)* %in.gep.2, align 4
69
70  %mul0 = fmul float %a, %b
71  %mul1 = fmul float %a, %c
72  %madak0 = fadd float %mul0, 10.0
73  %madak1 = fadd float %mul1, 10.0
74
75  store volatile float %madak0, float addrspace(1)* %out.gep.0, align 4
76  store volatile float %madak1, float addrspace(1)* %out.gep.1, align 4
77  ret void
78}
79
80; GCN-LABEL: {{^}}madak_m_inline_imm_f32:
81; GCN: {{buffer|flat|global}}_load_dword [[VA:v[0-9]+]]
82; MAD: v_madak_f32 {{v[0-9]+}}, 4.0, [[VA]], 0x41200000
83; GFX10-MAD: v_madak_f32 {{v[0-9]+}}, 4.0, [[VA]], 0x41200000
84; FMA: v_fmaak_f32 {{v[0-9]+}}, 4.0, [[VA]], 0x41200000
85define amdgpu_kernel void @madak_m_inline_imm_f32(float addrspace(1)* noalias %out, float addrspace(1)* noalias %in.a) #0 {
86  %tid = tail call i32 @llvm.amdgcn.workitem.id.x() nounwind readnone
87  %in.a.gep = getelementptr float, float addrspace(1)* %in.a, i32 %tid
88  %out.gep = getelementptr float, float addrspace(1)* %out, i32 %tid
89
90  %a = load float, float addrspace(1)* %in.a.gep, align 4
91
92  %mul = fmul float 4.0, %a
93  %madak = fadd float %mul, 10.0
94  store float %madak, float addrspace(1)* %out.gep, align 4
95  ret void
96}
97
98; Make sure nothing weird happens with a value that is also allowed as
99; an inline immediate.
100
101; GCN-LABEL: {{^}}madak_inline_imm_f32:
102; GFX6:   buffer_load_dword [[VA:v[0-9]+]]
103; GFX6:   buffer_load_dword [[VB:v[0-9]+]]
104; GFX8: {{flat|global}}_load_dword [[VA:v[0-9]+]]
105; GFX8: {{flat|global}}_load_dword [[VB:v[0-9]+]]
106; GFX9: {{flat|global}}_load_dword [[VA:v[0-9]+]]
107; GFX9: {{flat|global}}_load_dword [[VB:v[0-9]+]]
108; GFX10: {{flat|global}}_load_dword [[VA:v[0-9]+]]
109; GFX10: {{flat|global}}_load_dword [[VB:v[0-9]+]]
110; MAD:   v_mad_f32 {{v[0-9]+}}, [[VA]], [[VB]], 4.0
111; GFX10-MAD:   v_mad_f32 {{v[0-9]+}}, [[VA]], [[VB]], 4.0
112; FMA:   v_fma_f32 {{v[0-9]+}}, [[VA]], [[VB]], 4.0
113define amdgpu_kernel void @madak_inline_imm_f32(float addrspace(1)* noalias %out, float addrspace(1)* noalias %in.a, float addrspace(1)* noalias %in.b) #0 {
114  %tid = tail call i32 @llvm.amdgcn.workitem.id.x() nounwind readnone
115  %in.a.gep = getelementptr float, float addrspace(1)* %in.a, i32 %tid
116  %in.b.gep = getelementptr float, float addrspace(1)* %in.b, i32 %tid
117  %out.gep = getelementptr float, float addrspace(1)* %out, i32 %tid
118
119  %a = load float, float addrspace(1)* %in.a.gep, align 4
120  %b = load float, float addrspace(1)* %in.b.gep, align 4
121
122  %mul = fmul float %a, %b
123  %madak = fadd float %mul, 4.0
124  store float %madak, float addrspace(1)* %out.gep, align 4
125  ret void
126}
127
128; We can't use an SGPR when forming madak
129; GCN-LABEL: {{^}}s_v_madak_f32:
130; GCN-DAG:      s_load_dword [[SB:s[0-9]+]]
131; GFX6_8_9-DAG: v_mov_b32_e32 [[VK:v[0-9]+]], 0x41200000
132; GCN-DAG:      {{buffer|flat|global}}_load_dword{{(_addtid)?}} [[VA:v[0-9]+]]
133; GCN-NOT:      v_madak_f32
134; GFX6_8_9:     v_mac_f32_e32 [[VK]], [[SB]], [[VA]]
135; GFX10-MAD:    v_mad_f32 v{{[0-9]+}}, [[VA]], [[SB]], 0x41200000
136; FMA:          v_fma_f32 v{{[0-9]+}}, [[VA]], [[SB]], 0x41200000
137define amdgpu_kernel void @s_v_madak_f32(float addrspace(1)* noalias %out, float addrspace(1)* noalias %in.a, float %b) #0 {
138  %tid = tail call i32 @llvm.amdgcn.workitem.id.x() nounwind readnone
139  %in.a.gep = getelementptr float, float addrspace(1)* %in.a, i32 %tid
140  %out.gep = getelementptr float, float addrspace(1)* %out, i32 %tid
141
142  %a = load float, float addrspace(1)* %in.a.gep, align 4
143
144  %mul = fmul float %a, %b
145  %madak = fadd float %mul, 10.0
146  store float %madak, float addrspace(1)* %out.gep, align 4
147  ret void
148}
149
150; GCN-LABEL: @v_s_madak_f32
151; GCN-DAG:       s_load_dword [[SB:s[0-9]+]]
152; GFX6_8_9-DAG:  v_mov_b32_e32 [[VK:v[0-9]+]], 0x41200000
153; GCN-DAG:       {{buffer|flat|global}}_load_dword{{(_addtid)?}} [[VA:v[0-9]+]]
154; GFX6_8_9-NOT:  v_madak_f32
155; GFX6_8_9:      v_mac_f32_e32 [[VK]], [[SB]], [[VA]]
156; GFX10-MAD:     v_madak_f32 v{{[0-9]+}}, [[SB]], [[VA]], 0x41200000
157; FMA:           v_fmaak_f32 v{{[0-9]+}}, [[SB]], [[VA]], 0x41200000
158define amdgpu_kernel void @v_s_madak_f32(float addrspace(1)* noalias %out, float %a, float addrspace(1)* noalias %in.b) #0 {
159  %tid = tail call i32 @llvm.amdgcn.workitem.id.x() nounwind readnone
160  %in.b.gep = getelementptr float, float addrspace(1)* %in.b, i32 %tid
161  %out.gep = getelementptr float, float addrspace(1)* %out, i32 %tid
162
163  %b = load float, float addrspace(1)* %in.b.gep, align 4
164
165  %mul = fmul float %a, %b
166  %madak = fadd float %mul, 10.0
167  store float %madak, float addrspace(1)* %out.gep, align 4
168  ret void
169}
170
171; GCN-LABEL: {{^}}s_s_madak_f32:
172; GCN-NOT: v_madak_f32
173; GFX8_9:  v_mac_f32_e32 {{v[0-9]+}}, {{s[0-9]+}}, {{v[0-9]+}}
174; GFX10-MAD: v_mac_f32_e64 {{v[0-9]+}}, {{s[0-9]+}}, {{s[0-9]+}}
175; FMA:       v_fmac_f32_e64 {{v[0-9]+}}, {{s[0-9]+}}, {{s[0-9]+}}
176define amdgpu_kernel void @s_s_madak_f32(float addrspace(1)* %out, float %a, float %b) #0 {
177  %mul = fmul float %a, %b
178  %madak = fadd float %mul, 10.0
179  store float %madak, float addrspace(1)* %out, align 4
180  ret void
181}
182
183; GCN-LABEL: {{^}}no_madak_src0_modifier_f32:
184; GFX6:      buffer_load_dword [[VA:v[0-9]+]]
185; GFX6:      buffer_load_dword [[VB:v[0-9]+]]
186; GFX8_9_10: {{flat|global}}_load_dword [[VB:v[0-9]+]]
187; GFX8_9_10: {{flat|global}}_load_dword [[VA:v[0-9]+]]
188; GFX6_8_9:  v_mad_f32 {{v[0-9]+}}, |{{v[0-9]+}}|, {{v[0-9]+}}, {{[sv][0-9]+}}
189; GFX10-MAD: v_mad_f32 {{v[0-9]+}}, |{{v[0-9]+}}|, {{v[0-9]+}}, 0x41200000
190; FMA:       v_fma_f32 {{v[0-9]+}}, |{{v[0-9]+}}|, {{v[0-9]+}}, 0x41200000
191; GCN:       s_endpgm
192define amdgpu_kernel void @no_madak_src0_modifier_f32(float addrspace(1)* noalias %out, float addrspace(1)* noalias %in.a, float addrspace(1)* noalias %in.b) #0 {
193  %tid = tail call i32 @llvm.amdgcn.workitem.id.x() nounwind readnone
194  %in.a.gep = getelementptr float, float addrspace(1)* %in.a, i32 %tid
195  %in.b.gep = getelementptr float, float addrspace(1)* %in.b, i32 %tid
196  %out.gep = getelementptr float, float addrspace(1)* %out, i32 %tid
197
198  %a = load float, float addrspace(1)* %in.a.gep, align 4
199  %b = load float, float addrspace(1)* %in.b.gep, align 4
200
201  %a.fabs = call float @llvm.fabs.f32(float %a) nounwind readnone
202
203  %mul = fmul float %a.fabs, %b
204  %madak = fadd float %mul, 10.0
205  store float %madak, float addrspace(1)* %out.gep, align 4
206  ret void
207}
208
209; GCN-LABEL: {{^}}no_madak_src1_modifier_f32:
210; GFX6:      buffer_load_dword [[VA:v[0-9]+]]
211; GFX6:      buffer_load_dword [[VB:v[0-9]+]]
212; GFX8_9_10: {{flat|global}}_load_dword [[VB:v[0-9]+]]
213; GFX8_9_10: {{flat|global}}_load_dword [[VA:v[0-9]+]]
214; GFX6_8_9:  v_mad_f32 {{v[0-9]+}}, {{v[0-9]+}}, |{{v[0-9]+}}|, {{[sv][0-9]+}}
215; GFX10-MAD: v_mad_f32 {{v[0-9]+}}, {{v[0-9]+}}, |{{v[0-9]+}}|, 0x41200000
216; FMA:       v_fma_f32 {{v[0-9]+}}, {{v[0-9]+}}, |{{v[0-9]+}}|, 0x41200000
217; GCN:       s_endpgm
218define amdgpu_kernel void @no_madak_src1_modifier_f32(float addrspace(1)* noalias %out, float addrspace(1)* noalias %in.a, float addrspace(1)* noalias %in.b) #0 {
219  %tid = tail call i32 @llvm.amdgcn.workitem.id.x() nounwind readnone
220  %in.a.gep = getelementptr float, float addrspace(1)* %in.a, i32 %tid
221  %in.b.gep = getelementptr float, float addrspace(1)* %in.b, i32 %tid
222  %out.gep = getelementptr float, float addrspace(1)* %out, i32 %tid
223
224  %a = load float, float addrspace(1)* %in.a.gep, align 4
225  %b = load float, float addrspace(1)* %in.b.gep, align 4
226
227  %b.fabs = call float @llvm.fabs.f32(float %b) nounwind readnone
228
229  %mul = fmul float %a, %b.fabs
230  %madak = fadd float %mul, 10.0
231  store float %madak, float addrspace(1)* %out.gep, align 4
232  ret void
233}
234
235; SIFoldOperands should not fold the SGPR copy into the instruction before GFX10
236; because the implicit immediate already uses the constant bus.
237; On GFX10+ we can use two scalar operands.
238; GCN-LABEL: {{^}}madak_constant_bus_violation:
239; GCN:       s_load_dword [[SGPR0:s[0-9]+]], s{{\[[0-9]+:[0-9]+\]}}, {{0x12|0x48}}
240
241; GCN:       {{buffer|flat|global}}_load_dword [[VGPR:v[0-9]+]]
242; MAD:       v_mov_b32_e32 [[MADAK:v[0-9]+]], 0x42280000
243; MAD:       v_mac_f32_e64 [[MADAK]], [[SGPR0]], 0.5
244; GFX10:     v_mov_b32_e32 [[SGPR0_VCOPY:v[0-9]+]], [[SGPR0]]
245; GFX10-MAD: v_madak_f32 [[MADAK:v[0-9]+]], 0.5, [[SGPR0_VCOPY]], 0x42280000
246; FMA:       v_fmaak_f32 [[MADAK:v[0-9]+]], 0.5, [[SGPR0_VCOPY]], 0x42280000
247; GCN:       v_mul_f32_e32 [[MUL:v[0-9]+]], [[MADAK]], [[VGPR]]
248; GFX6:      buffer_store_dword [[MUL]]
249; GFX8_9_10: {{flat|global}}_store_dword v[{{[0-9:]+}}], [[MUL]]
250define amdgpu_kernel void @madak_constant_bus_violation(i32 %arg1, [8 x i32], float %sgpr0, float %sgpr1) #0 {
251bb:
252  %tmp = icmp eq i32 %arg1, 0
253  br i1 %tmp, label %bb3, label %bb4
254
255bb3:
256  store volatile float 0.0, float addrspace(1)* undef
257  br label %bb4
258
259bb4:
260  %vgpr = load volatile float, float addrspace(1)* undef
261  %tmp0 = fmul float %sgpr0, 0.5
262  %tmp1 = fadd float %tmp0, 42.0
263  %tmp2 = fmul float %tmp1, %vgpr
264  store volatile float %tmp2, float addrspace(1)* undef, align 4
265  ret void
266}
267
268attributes #0 = { nounwind "denormal-fp-math-f32"="preserve-sign,preserve-sign" }
269