1; RUN:  llc -amdgpu-scalarize-global-loads=false  -march=amdgcn -mcpu=tahiti -verify-machineinstrs -fp-contract=fast < %s | FileCheck -check-prefix=SI-NOFMA -check-prefix=SI-SAFE -check-prefix=SI -check-prefix=FUNC %s
2; RUN:  llc -amdgpu-scalarize-global-loads=false  -march=amdgcn -mcpu=verde -verify-machineinstrs -fp-contract=fast < %s | FileCheck -check-prefix=SI-NOFMA -check-prefix=SI-SAFE -check-prefix=SI -check-prefix=FUNC %s
3; RUN:  llc -amdgpu-scalarize-global-loads=false  -march=amdgcn -mcpu=tahiti -verify-machineinstrs -fp-contract=fast -enable-no-infs-fp-math -enable-unsafe-fp-math -mattr=+fp32-denormals < %s | FileCheck -check-prefix=SI-FMA -check-prefix=SI-UNSAFE -check-prefix=SI -check-prefix=FUNC %s
4
5; Note: The SI-FMA conversions of type x * (y + 1) --> x * y + x would be
6; beneficial even without fp32 denormals, but they do require no-infs-fp-math
7; for correctness.
8
9declare i32 @llvm.amdgcn.workitem.id.x() #0
10declare double @llvm.fabs.f64(double) #0
11declare double @llvm.fma.f64(double, double, double) #0
12declare float @llvm.fma.f32(float, float, float) #0
13
14; (fadd (fmul x, y), z) -> (fma x, y, z)
15; FUNC-LABEL: {{^}}combine_to_fma_f64_0:
16; SI-DAG: buffer_load_dwordx2 [[A:v\[[0-9]+:[0-9]+\]]], v{{\[[0-9]+:[0-9]+\]}}, s{{\[[0-9]+:[0-9]+\]}}, 0 addr64{{$}}
17; SI-DAG: buffer_load_dwordx2 [[B:v\[[0-9]+:[0-9]+\]]], v{{\[[0-9]+:[0-9]+\]}}, s{{\[[0-9]+:[0-9]+\]}}, 0 addr64 offset:8{{$}}
18; SI-DAG: buffer_load_dwordx2 [[C:v\[[0-9]+:[0-9]+\]]], v{{\[[0-9]+:[0-9]+\]}}, s{{\[[0-9]+:[0-9]+\]}}, 0 addr64 offset:16{{$}}
19; SI: v_fma_f64 [[RESULT:v\[[0-9]+:[0-9]+\]]], [[A]], [[B]], [[C]]
20; SI: buffer_store_dwordx2 [[RESULT]]
21define amdgpu_kernel void @combine_to_fma_f64_0(double addrspace(1)* noalias %out, double addrspace(1)* noalias %in) #1 {
22  %tid = tail call i32 @llvm.amdgcn.workitem.id.x() #0
23  %gep.0 = getelementptr double, double addrspace(1)* %in, i32 %tid
24  %gep.1 = getelementptr double, double addrspace(1)* %gep.0, i32 1
25  %gep.2 = getelementptr double, double addrspace(1)* %gep.0, i32 2
26  %gep.out = getelementptr double, double addrspace(1)* %out, i32 %tid
27
28  %a = load volatile double, double addrspace(1)* %gep.0
29  %b = load volatile double, double addrspace(1)* %gep.1
30  %c = load volatile double, double addrspace(1)* %gep.2
31
32  %mul = fmul double %a, %b
33  %fma = fadd double %mul, %c
34  store double %fma, double addrspace(1)* %gep.out
35  ret void
36}
37
38; (fadd (fmul x, y), z) -> (fma x, y, z)
39; FUNC-LABEL: {{^}}combine_to_fma_f64_0_2use:
40; SI-DAG: buffer_load_dwordx2 [[A:v\[[0-9]+:[0-9]+\]]], v{{\[[0-9]+:[0-9]+\]}}, s{{\[[0-9]+:[0-9]+\]}}, 0 addr64{{$}}
41; SI-DAG: buffer_load_dwordx2 [[B:v\[[0-9]+:[0-9]+\]]], v{{\[[0-9]+:[0-9]+\]}}, s{{\[[0-9]+:[0-9]+\]}}, 0 addr64 offset:8{{$}}
42; SI-DAG: buffer_load_dwordx2 [[C:v\[[0-9]+:[0-9]+\]]], v{{\[[0-9]+:[0-9]+\]}}, s{{\[[0-9]+:[0-9]+\]}}, 0 addr64 offset:16{{$}}
43; SI-DAG: buffer_load_dwordx2 [[D:v\[[0-9]+:[0-9]+\]]], v{{\[[0-9]+:[0-9]+\]}}, s{{\[[0-9]+:[0-9]+\]}}, 0 addr64 offset:24{{$}}
44; SI-DAG: v_fma_f64 [[RESULT0:v\[[0-9]+:[0-9]+\]]], [[A]], [[B]], [[C]]
45; SI-DAG: v_fma_f64 [[RESULT1:v\[[0-9]+:[0-9]+\]]], [[A]], [[B]], [[D]]
46; SI-DAG: buffer_store_dwordx2 [[RESULT0]], v{{\[[0-9]+:[0-9]+\]}}, s{{\[[0-9]+:[0-9]+\]}}, 0 addr64{{$}}
47; SI-DAG: buffer_store_dwordx2 [[RESULT1]], v{{\[[0-9]+:[0-9]+\]}}, s{{\[[0-9]+:[0-9]+\]}}, 0 addr64 offset:8{{$}}
48; SI: s_endpgm
49define amdgpu_kernel void @combine_to_fma_f64_0_2use(double addrspace(1)* noalias %out, double addrspace(1)* noalias %in) #1 {
50  %tid = tail call i32 @llvm.amdgcn.workitem.id.x() #0
51  %gep.0 = getelementptr double, double addrspace(1)* %in, i32 %tid
52  %gep.1 = getelementptr double, double addrspace(1)* %gep.0, i32 1
53  %gep.2 = getelementptr double, double addrspace(1)* %gep.0, i32 2
54  %gep.3 = getelementptr double, double addrspace(1)* %gep.0, i32 3
55  %gep.out.0 = getelementptr double, double addrspace(1)* %out, i32 %tid
56  %gep.out.1 = getelementptr double, double addrspace(1)* %gep.out.0, i32 1
57
58  %a = load volatile double, double addrspace(1)* %gep.0
59  %b = load volatile double, double addrspace(1)* %gep.1
60  %c = load volatile double, double addrspace(1)* %gep.2
61  %d = load volatile double, double addrspace(1)* %gep.3
62
63  %mul = fmul double %a, %b
64  %fma0 = fadd double %mul, %c
65  %fma1 = fadd double %mul, %d
66  store volatile double %fma0, double addrspace(1)* %gep.out.0
67  store volatile double %fma1, double addrspace(1)* %gep.out.1
68  ret void
69}
70
71; (fadd x, (fmul y, z)) -> (fma y, z, x)
72; FUNC-LABEL: {{^}}combine_to_fma_f64_1:
73; SI-DAG: buffer_load_dwordx2 [[A:v\[[0-9]+:[0-9]+\]]], v{{\[[0-9]+:[0-9]+\]}}, s{{\[[0-9]+:[0-9]+\]}}, 0 addr64{{$}}
74; SI-DAG: buffer_load_dwordx2 [[B:v\[[0-9]+:[0-9]+\]]], v{{\[[0-9]+:[0-9]+\]}}, s{{\[[0-9]+:[0-9]+\]}}, 0 addr64 offset:8{{$}}
75; SI-DAG: buffer_load_dwordx2 [[C:v\[[0-9]+:[0-9]+\]]], v{{\[[0-9]+:[0-9]+\]}}, s{{\[[0-9]+:[0-9]+\]}}, 0 addr64 offset:16{{$}}
76; SI: v_fma_f64 [[RESULT:v\[[0-9]+:[0-9]+\]]], [[A]], [[B]], [[C]]
77; SI: buffer_store_dwordx2 [[RESULT]]
78define amdgpu_kernel void @combine_to_fma_f64_1(double addrspace(1)* noalias %out, double addrspace(1)* noalias %in) #1 {
79  %tid = tail call i32 @llvm.amdgcn.workitem.id.x() #0
80  %gep.0 = getelementptr double, double addrspace(1)* %in, i32 %tid
81  %gep.1 = getelementptr double, double addrspace(1)* %gep.0, i32 1
82  %gep.2 = getelementptr double, double addrspace(1)* %gep.0, i32 2
83  %gep.out = getelementptr double, double addrspace(1)* %out, i32 %tid
84
85  %a = load volatile double, double addrspace(1)* %gep.0
86  %b = load volatile double, double addrspace(1)* %gep.1
87  %c = load volatile double, double addrspace(1)* %gep.2
88
89  %mul = fmul double %a, %b
90  %fma = fadd double %c, %mul
91  store double %fma, double addrspace(1)* %gep.out
92  ret void
93}
94
95; (fsub (fmul x, y), z) -> (fma x, y, (fneg z))
96; FUNC-LABEL: {{^}}combine_to_fma_fsub_0_f64:
97; SI-DAG: buffer_load_dwordx2 [[A:v\[[0-9]+:[0-9]+\]]], v{{\[[0-9]+:[0-9]+\]}}, s{{\[[0-9]+:[0-9]+\]}}, 0 addr64{{$}}
98; SI-DAG: buffer_load_dwordx2 [[B:v\[[0-9]+:[0-9]+\]]], v{{\[[0-9]+:[0-9]+\]}}, s{{\[[0-9]+:[0-9]+\]}}, 0 addr64 offset:8{{$}}
99; SI-DAG: buffer_load_dwordx2 [[C:v\[[0-9]+:[0-9]+\]]], v{{\[[0-9]+:[0-9]+\]}}, s{{\[[0-9]+:[0-9]+\]}}, 0 addr64 offset:16{{$}}
100; SI: v_fma_f64 [[RESULT:v\[[0-9]+:[0-9]+\]]], [[A]], [[B]], -[[C]]
101; SI: buffer_store_dwordx2 [[RESULT]]
102define amdgpu_kernel void @combine_to_fma_fsub_0_f64(double addrspace(1)* noalias %out, double addrspace(1)* noalias %in) #1 {
103  %tid = tail call i32 @llvm.amdgcn.workitem.id.x() #0
104  %gep.0 = getelementptr double, double addrspace(1)* %in, i32 %tid
105  %gep.1 = getelementptr double, double addrspace(1)* %gep.0, i32 1
106  %gep.2 = getelementptr double, double addrspace(1)* %gep.0, i32 2
107  %gep.out = getelementptr double, double addrspace(1)* %out, i32 %tid
108
109  %a = load volatile double, double addrspace(1)* %gep.0
110  %b = load volatile double, double addrspace(1)* %gep.1
111  %c = load volatile double, double addrspace(1)* %gep.2
112
113  %mul = fmul double %a, %b
114  %fma = fsub double %mul, %c
115  store double %fma, double addrspace(1)* %gep.out
116  ret void
117}
118
119; (fsub (fmul x, y), z) -> (fma x, y, (fneg z))
120; FUNC-LABEL: {{^}}combine_to_fma_fsub_f64_0_2use:
121; SI-DAG: buffer_load_dwordx2 [[A:v\[[0-9]+:[0-9]+\]]], v{{\[[0-9]+:[0-9]+\]}}, s{{\[[0-9]+:[0-9]+\]}}, 0 addr64{{$}}
122; SI-DAG: buffer_load_dwordx2 [[B:v\[[0-9]+:[0-9]+\]]], v{{\[[0-9]+:[0-9]+\]}}, s{{\[[0-9]+:[0-9]+\]}}, 0 addr64 offset:8{{$}}
123; SI-DAG: buffer_load_dwordx2 [[C:v\[[0-9]+:[0-9]+\]]], v{{\[[0-9]+:[0-9]+\]}}, s{{\[[0-9]+:[0-9]+\]}}, 0 addr64 offset:16{{$}}
124; SI-DAG: buffer_load_dwordx2 [[D:v\[[0-9]+:[0-9]+\]]], v{{\[[0-9]+:[0-9]+\]}}, s{{\[[0-9]+:[0-9]+\]}}, 0 addr64 offset:24{{$}}
125; SI-DAG: v_fma_f64 [[RESULT0:v\[[0-9]+:[0-9]+\]]], [[A]], [[B]], -[[C]]
126; SI-DAG: v_fma_f64 [[RESULT1:v\[[0-9]+:[0-9]+\]]], [[A]], [[B]], -[[D]]
127; SI-DAG: buffer_store_dwordx2 [[RESULT0]], v{{\[[0-9]+:[0-9]+\]}}, s{{\[[0-9]+:[0-9]+\]}}, 0 addr64{{$}}
128; SI-DAG: buffer_store_dwordx2 [[RESULT1]], v{{\[[0-9]+:[0-9]+\]}}, s{{\[[0-9]+:[0-9]+\]}}, 0 addr64 offset:8{{$}}
129; SI: s_endpgm
130define amdgpu_kernel void @combine_to_fma_fsub_f64_0_2use(double addrspace(1)* noalias %out, double addrspace(1)* noalias %in) #1 {
131  %tid = tail call i32 @llvm.amdgcn.workitem.id.x() #0
132  %gep.0 = getelementptr double, double addrspace(1)* %in, i32 %tid
133  %gep.1 = getelementptr double, double addrspace(1)* %gep.0, i32 1
134  %gep.2 = getelementptr double, double addrspace(1)* %gep.0, i32 2
135  %gep.3 = getelementptr double, double addrspace(1)* %gep.0, i32 3
136  %gep.out.0 = getelementptr double, double addrspace(1)* %out, i32 %tid
137  %gep.out.1 = getelementptr double, double addrspace(1)* %gep.out.0, i32 1
138
139  %a = load volatile double, double addrspace(1)* %gep.0
140  %b = load volatile double, double addrspace(1)* %gep.1
141  %c = load volatile double, double addrspace(1)* %gep.2
142  %d = load volatile double, double addrspace(1)* %gep.3
143
144  %mul = fmul double %a, %b
145  %fma0 = fsub double %mul, %c
146  %fma1 = fsub double %mul, %d
147  store volatile double %fma0, double addrspace(1)* %gep.out.0
148  store volatile double %fma1, double addrspace(1)* %gep.out.1
149  ret void
150}
151
152; (fsub x, (fmul y, z)) -> (fma (fneg y), z, x)
153; FUNC-LABEL: {{^}}combine_to_fma_fsub_1_f64:
154; SI-DAG: buffer_load_dwordx2 [[A:v\[[0-9]+:[0-9]+\]]], v{{\[[0-9]+:[0-9]+\]}}, s{{\[[0-9]+:[0-9]+\]}}, 0 addr64{{$}}
155; SI-DAG: buffer_load_dwordx2 [[B:v\[[0-9]+:[0-9]+\]]], v{{\[[0-9]+:[0-9]+\]}}, s{{\[[0-9]+:[0-9]+\]}}, 0 addr64 offset:8{{$}}
156; SI-DAG: buffer_load_dwordx2 [[C:v\[[0-9]+:[0-9]+\]]], v{{\[[0-9]+:[0-9]+\]}}, s{{\[[0-9]+:[0-9]+\]}}, 0 addr64 offset:16{{$}}
157; SI: v_fma_f64 [[RESULT:v\[[0-9]+:[0-9]+\]]], -[[A]], [[B]], [[C]]
158; SI: buffer_store_dwordx2 [[RESULT]]
159define amdgpu_kernel void @combine_to_fma_fsub_1_f64(double addrspace(1)* noalias %out, double addrspace(1)* noalias %in) #1 {
160  %tid = tail call i32 @llvm.amdgcn.workitem.id.x() #0
161  %gep.0 = getelementptr double, double addrspace(1)* %in, i32 %tid
162  %gep.1 = getelementptr double, double addrspace(1)* %gep.0, i32 1
163  %gep.2 = getelementptr double, double addrspace(1)* %gep.0, i32 2
164  %gep.out = getelementptr double, double addrspace(1)* %out, i32 %tid
165
166  %a = load volatile double, double addrspace(1)* %gep.0
167  %b = load volatile double, double addrspace(1)* %gep.1
168  %c = load volatile double, double addrspace(1)* %gep.2
169
170  %mul = fmul double %a, %b
171  %fma = fsub double %c, %mul
172  store double %fma, double addrspace(1)* %gep.out
173  ret void
174}
175
176; (fsub x, (fmul y, z)) -> (fma (fneg y), z, x)
177; FUNC-LABEL: {{^}}combine_to_fma_fsub_1_f64_2use:
178; SI-DAG: buffer_load_dwordx2 [[A:v\[[0-9]+:[0-9]+\]]], v{{\[[0-9]+:[0-9]+\]}}, s{{\[[0-9]+:[0-9]+\]}}, 0 addr64{{$}}
179; SI-DAG: buffer_load_dwordx2 [[B:v\[[0-9]+:[0-9]+\]]], v{{\[[0-9]+:[0-9]+\]}}, s{{\[[0-9]+:[0-9]+\]}}, 0 addr64 offset:8{{$}}
180; SI-DAG: buffer_load_dwordx2 [[C:v\[[0-9]+:[0-9]+\]]], v{{\[[0-9]+:[0-9]+\]}}, s{{\[[0-9]+:[0-9]+\]}}, 0 addr64 offset:16{{$}}
181; SI-DAG: buffer_load_dwordx2 [[D:v\[[0-9]+:[0-9]+\]]], v{{\[[0-9]+:[0-9]+\]}}, s{{\[[0-9]+:[0-9]+\]}}, 0 addr64 offset:24{{$}}
182; SI-DAG: v_fma_f64 [[RESULT0:v\[[0-9]+:[0-9]+\]]], -[[A]], [[B]], [[C]]
183; SI-DAG: v_fma_f64 [[RESULT1:v\[[0-9]+:[0-9]+\]]], -[[A]], [[B]], [[D]]
184; SI-DAG: buffer_store_dwordx2 [[RESULT0]], v{{\[[0-9]+:[0-9]+\]}}, s{{\[[0-9]+:[0-9]+\]}}, 0 addr64{{$}}
185; SI-DAG: buffer_store_dwordx2 [[RESULT1]], v{{\[[0-9]+:[0-9]+\]}}, s{{\[[0-9]+:[0-9]+\]}}, 0 addr64 offset:8{{$}}
186; SI: s_endpgm
187define amdgpu_kernel void @combine_to_fma_fsub_1_f64_2use(double addrspace(1)* noalias %out, double addrspace(1)* noalias %in) #1 {
188  %tid = tail call i32 @llvm.amdgcn.workitem.id.x() #0
189  %gep.0 = getelementptr double, double addrspace(1)* %in, i32 %tid
190  %gep.1 = getelementptr double, double addrspace(1)* %gep.0, i32 1
191  %gep.2 = getelementptr double, double addrspace(1)* %gep.0, i32 2
192  %gep.3 = getelementptr double, double addrspace(1)* %gep.0, i32 3
193  %gep.out.0 = getelementptr double, double addrspace(1)* %out, i32 %tid
194  %gep.out.1 = getelementptr double, double addrspace(1)* %gep.out.0, i32 1
195
196  %a = load volatile double, double addrspace(1)* %gep.0
197  %b = load volatile double, double addrspace(1)* %gep.1
198  %c = load volatile double, double addrspace(1)* %gep.2
199  %d = load volatile double, double addrspace(1)* %gep.3
200
201  %mul = fmul double %a, %b
202  %fma0 = fsub double %c, %mul
203  %fma1 = fsub double %d, %mul
204  store volatile double %fma0, double addrspace(1)* %gep.out.0
205  store volatile double %fma1, double addrspace(1)* %gep.out.1
206  ret void
207}
208
209; (fsub (fneg (fmul x, y)), z) -> (fma (fneg x), y, (fneg z))
210; FUNC-LABEL: {{^}}combine_to_fma_fsub_2_f64:
211; SI-DAG: buffer_load_dwordx2 [[A:v\[[0-9]+:[0-9]+\]]], v{{\[[0-9]+:[0-9]+\]}}, s{{\[[0-9]+:[0-9]+\]}}, 0 addr64{{$}}
212; SI-DAG: buffer_load_dwordx2 [[B:v\[[0-9]+:[0-9]+\]]], v{{\[[0-9]+:[0-9]+\]}}, s{{\[[0-9]+:[0-9]+\]}}, 0 addr64 offset:8{{$}}
213; SI-DAG: buffer_load_dwordx2 [[C:v\[[0-9]+:[0-9]+\]]], v{{\[[0-9]+:[0-9]+\]}}, s{{\[[0-9]+:[0-9]+\]}}, 0 addr64 offset:16{{$}}
214; SI: v_fma_f64 [[RESULT:v\[[0-9]+:[0-9]+\]]], -[[A]], [[B]], -[[C]]
215; SI: buffer_store_dwordx2 [[RESULT]]
216define amdgpu_kernel void @combine_to_fma_fsub_2_f64(double addrspace(1)* noalias %out, double addrspace(1)* noalias %in) #1 {
217  %tid = tail call i32 @llvm.amdgcn.workitem.id.x() #0
218  %gep.0 = getelementptr double, double addrspace(1)* %in, i32 %tid
219  %gep.1 = getelementptr double, double addrspace(1)* %gep.0, i32 1
220  %gep.2 = getelementptr double, double addrspace(1)* %gep.0, i32 2
221  %gep.out = getelementptr double, double addrspace(1)* %out, i32 %tid
222
223  %a = load volatile double, double addrspace(1)* %gep.0
224  %b = load volatile double, double addrspace(1)* %gep.1
225  %c = load volatile double, double addrspace(1)* %gep.2
226
227  %mul = fmul double %a, %b
228  %mul.neg = fsub double -0.0, %mul
229  %fma = fsub double %mul.neg, %c
230
231  store double %fma, double addrspace(1)* %gep.out
232  ret void
233}
234
235; (fsub (fneg (fmul x, y)), z) -> (fma (fneg x), y, (fneg z))
236; FUNC-LABEL: {{^}}combine_to_fma_fsub_2_f64_2uses_neg:
237; SI-DAG: buffer_load_dwordx2 [[A:v\[[0-9]+:[0-9]+\]]], v{{\[[0-9]+:[0-9]+\]}}, s{{\[[0-9]+:[0-9]+\]}}, 0 addr64{{$}}
238; SI-DAG: buffer_load_dwordx2 [[B:v\[[0-9]+:[0-9]+\]]], v{{\[[0-9]+:[0-9]+\]}}, s{{\[[0-9]+:[0-9]+\]}}, 0 addr64 offset:8{{$}}
239; SI-DAG: buffer_load_dwordx2 [[C:v\[[0-9]+:[0-9]+\]]], v{{\[[0-9]+:[0-9]+\]}}, s{{\[[0-9]+:[0-9]+\]}}, 0 addr64 offset:16{{$}}
240; SI-DAG: v_fma_f64 [[RESULT0:v\[[0-9]+:[0-9]+\]]], -[[A]], [[B]], -[[C]]
241; SI-DAG: v_fma_f64 [[RESULT1:v\[[0-9]+:[0-9]+\]]], -[[A]], [[B]], -[[D]]
242; SI-DAG: buffer_store_dwordx2 [[RESULT0]], v{{\[[0-9]+:[0-9]+\]}}, s{{\[[0-9]+:[0-9]+\]}}, 0 addr64{{$}}
243; SI-DAG: buffer_store_dwordx2 [[RESULT1]], v{{\[[0-9]+:[0-9]+\]}}, s{{\[[0-9]+:[0-9]+\]}}, 0 addr64 offset:8{{$}}
244; SI: s_endpgm
245define amdgpu_kernel void @combine_to_fma_fsub_2_f64_2uses_neg(double addrspace(1)* noalias %out, double addrspace(1)* noalias %in) #1 {
246  %tid = tail call i32 @llvm.amdgcn.workitem.id.x() #0
247  %gep.0 = getelementptr double, double addrspace(1)* %in, i32 %tid
248  %gep.1 = getelementptr double, double addrspace(1)* %gep.0, i32 1
249  %gep.2 = getelementptr double, double addrspace(1)* %gep.0, i32 2
250  %gep.3 = getelementptr double, double addrspace(1)* %gep.0, i32 3
251  %gep.out.0 = getelementptr double, double addrspace(1)* %out, i32 %tid
252  %gep.out.1 = getelementptr double, double addrspace(1)* %gep.out.0, i32 1
253
254  %a = load volatile double, double addrspace(1)* %gep.0
255  %b = load volatile double, double addrspace(1)* %gep.1
256  %c = load volatile double, double addrspace(1)* %gep.2
257  %d = load volatile double, double addrspace(1)* %gep.3
258
259  %mul = fmul double %a, %b
260  %mul.neg = fsub double -0.0, %mul
261  %fma0 = fsub double %mul.neg, %c
262  %fma1 = fsub double %mul.neg, %d
263
264  store volatile double %fma0, double addrspace(1)* %gep.out.0
265  store volatile double %fma1, double addrspace(1)* %gep.out.1
266  ret void
267}
268
269; (fsub (fneg (fmul x, y)), z) -> (fma (fneg x), y, (fneg z))
270; FUNC-LABEL: {{^}}combine_to_fma_fsub_2_f64_2uses_mul:
271; SI-DAG: buffer_load_dwordx2 [[A:v\[[0-9]+:[0-9]+\]]], v{{\[[0-9]+:[0-9]+\]}}, s{{\[[0-9]+:[0-9]+\]}}, 0 addr64{{$}}
272; SI-DAG: buffer_load_dwordx2 [[B:v\[[0-9]+:[0-9]+\]]], v{{\[[0-9]+:[0-9]+\]}}, s{{\[[0-9]+:[0-9]+\]}}, 0 addr64 offset:8{{$}}
273; SI-DAG: buffer_load_dwordx2 [[C:v\[[0-9]+:[0-9]+\]]], v{{\[[0-9]+:[0-9]+\]}}, s{{\[[0-9]+:[0-9]+\]}}, 0 addr64 offset:16{{$}}
274; SI-DAG: v_fma_f64 [[RESULT0:v\[[0-9]+:[0-9]+\]]], -[[A]], [[B]], -[[C]]
275; SI-DAG: v_fma_f64 [[RESULT1:v\[[0-9]+:[0-9]+\]]], [[A]], [[B]], -[[D]]
276; SI-DAG: buffer_store_dwordx2 [[RESULT0]], v{{\[[0-9]+:[0-9]+\]}}, s{{\[[0-9]+:[0-9]+\]}}, 0 addr64{{$}}
277; SI-DAG: buffer_store_dwordx2 [[RESULT1]], v{{\[[0-9]+:[0-9]+\]}}, s{{\[[0-9]+:[0-9]+\]}}, 0 addr64 offset:8{{$}}
278; SI: s_endpgm
279define amdgpu_kernel void @combine_to_fma_fsub_2_f64_2uses_mul(double addrspace(1)* noalias %out, double addrspace(1)* noalias %in) #1 {
280  %tid = tail call i32 @llvm.amdgcn.workitem.id.x() #0
281  %gep.0 = getelementptr double, double addrspace(1)* %in, i32 %tid
282  %gep.1 = getelementptr double, double addrspace(1)* %gep.0, i32 1
283  %gep.2 = getelementptr double, double addrspace(1)* %gep.0, i32 2
284  %gep.3 = getelementptr double, double addrspace(1)* %gep.0, i32 3
285  %gep.out.0 = getelementptr double, double addrspace(1)* %out, i32 %tid
286  %gep.out.1 = getelementptr double, double addrspace(1)* %gep.out.0, i32 1
287
288  %a = load volatile double, double addrspace(1)* %gep.0
289  %b = load volatile double, double addrspace(1)* %gep.1
290  %c = load volatile double, double addrspace(1)* %gep.2
291  %d = load volatile double, double addrspace(1)* %gep.3
292
293  %mul = fmul double %a, %b
294  %mul.neg = fsub double -0.0, %mul
295  %fma0 = fsub double %mul.neg, %c
296  %fma1 = fsub double %mul, %d
297
298  store volatile double %fma0, double addrspace(1)* %gep.out.0
299  store volatile double %fma1, double addrspace(1)* %gep.out.1
300  ret void
301}
302
303; fold (fsub (fma x, y, (fmul u, v)), z) -> (fma x, y (fma u, v, (fneg z)))
304
305; FUNC-LABEL: {{^}}aggressive_combine_to_fma_fsub_0_f64:
306; SI-DAG: buffer_load_dwordx2 [[X:v\[[0-9]+:[0-9]+\]]], v{{\[[0-9]+:[0-9]+\]}}, s{{\[[0-9]+:[0-9]+\]}}, 0 addr64{{$}}
307; SI-DAG: buffer_load_dwordx2 [[Y:v\[[0-9]+:[0-9]+\]]], v{{\[[0-9]+:[0-9]+\]}}, s{{\[[0-9]+:[0-9]+\]}}, 0 addr64 offset:8{{$}}
308; SI-DAG: buffer_load_dwordx2 [[Z:v\[[0-9]+:[0-9]+\]]], v{{\[[0-9]+:[0-9]+\]}}, s{{\[[0-9]+:[0-9]+\]}}, 0 addr64 offset:16{{$}}
309; SI-DAG: buffer_load_dwordx2 [[U:v\[[0-9]+:[0-9]+\]]], v{{\[[0-9]+:[0-9]+\]}}, s{{\[[0-9]+:[0-9]+\]}}, 0 addr64 offset:24{{$}}
310; SI-DAG: buffer_load_dwordx2 [[V:v\[[0-9]+:[0-9]+\]]], v{{\[[0-9]+:[0-9]+\]}}, s{{\[[0-9]+:[0-9]+\]}}, 0 addr64 offset:32{{$}}
311
312; SI-SAFE: v_mul_f64 [[TMP0:v\[[0-9]+:[0-9]+\]]], [[U]], [[V]]
313; SI-SAFE: v_fma_f64 [[TMP1:v\[[0-9]+:[0-9]+\]]], [[X]], [[Y]], [[TMP0]]
314; SI-SAFE: v_add_f64 [[RESULT:v\[[0-9]+:[0-9]+\]]], [[TMP1]], -[[Z]]
315
316; SI-UNSAFE: v_fma_f64 [[FMA0:v\[[0-9]+:[0-9]+\]]], [[U]], [[V]], -[[Z]]
317; SI-UNSAFE: v_fma_f64 [[RESULT:v\[[0-9]+:[0-9]+\]]], [[X]], [[Y]], [[FMA0]]
318
319; SI: buffer_store_dwordx2 [[RESULT]]
320define amdgpu_kernel void @aggressive_combine_to_fma_fsub_0_f64(double addrspace(1)* noalias %out, double addrspace(1)* noalias %in) #1 {
321  %tid = tail call i32 @llvm.amdgcn.workitem.id.x() #0
322  %gep.0 = getelementptr double, double addrspace(1)* %in, i32 %tid
323  %gep.1 = getelementptr double, double addrspace(1)* %gep.0, i32 1
324  %gep.2 = getelementptr double, double addrspace(1)* %gep.0, i32 2
325  %gep.3 = getelementptr double, double addrspace(1)* %gep.0, i32 3
326  %gep.4 = getelementptr double, double addrspace(1)* %gep.0, i32 4
327  %gep.out = getelementptr double, double addrspace(1)* %out, i32 %tid
328
329  %x = load volatile double, double addrspace(1)* %gep.0
330  %y = load volatile double, double addrspace(1)* %gep.1
331  %z = load volatile double, double addrspace(1)* %gep.2
332  %u = load volatile double, double addrspace(1)* %gep.3
333  %v = load volatile double, double addrspace(1)* %gep.4
334
335  %tmp0 = fmul double %u, %v
336  %tmp1 = call double @llvm.fma.f64(double %x, double %y, double %tmp0) #0
337  %tmp2 = fsub double %tmp1, %z
338
339  store double %tmp2, double addrspace(1)* %gep.out
340  ret void
341}
342
343; fold (fsub x, (fma y, z, (fmul u, v)))
344;   -> (fma (fneg y), z, (fma (fneg u), v, x))
345
346; FUNC-LABEL: {{^}}aggressive_combine_to_fma_fsub_1_f64:
347; SI-DAG: buffer_load_dwordx2 [[X:v\[[0-9]+:[0-9]+\]]], v{{\[[0-9]+:[0-9]+\]}}, s{{\[[0-9]+:[0-9]+\]}}, 0 addr64{{$}}
348; SI-DAG: buffer_load_dwordx2 [[Y:v\[[0-9]+:[0-9]+\]]], v{{\[[0-9]+:[0-9]+\]}}, s{{\[[0-9]+:[0-9]+\]}}, 0 addr64 offset:8{{$}}
349; SI-DAG: buffer_load_dwordx2 [[Z:v\[[0-9]+:[0-9]+\]]], v{{\[[0-9]+:[0-9]+\]}}, s{{\[[0-9]+:[0-9]+\]}}, 0 addr64 offset:16{{$}}
350; SI-DAG: buffer_load_dwordx2 [[U:v\[[0-9]+:[0-9]+\]]], v{{\[[0-9]+:[0-9]+\]}}, s{{\[[0-9]+:[0-9]+\]}}, 0 addr64 offset:24{{$}}
351; SI-DAG: buffer_load_dwordx2 [[V:v\[[0-9]+:[0-9]+\]]], v{{\[[0-9]+:[0-9]+\]}}, s{{\[[0-9]+:[0-9]+\]}}, 0 addr64 offset:32{{$}}
352
353; SI-SAFE: v_mul_f64 [[TMP0:v\[[0-9]+:[0-9]+\]]], [[U]], [[V]]
354; SI-SAFE: v_fma_f64 [[TMP1:v\[[0-9]+:[0-9]+\]]], [[Y]], [[Z]], [[TMP0]]
355; SI-SAFE: v_add_f64 [[RESULT:v\[[0-9]+:[0-9]+\]]], [[X]], -[[TMP1]]
356
357; SI-UNSAFE: v_fma_f64 [[FMA0:v\[[0-9]+:[0-9]+\]]], -[[U]], [[V]], [[X]]
358; SI-UNSAFE: v_fma_f64 [[RESULT:v\[[0-9]+:[0-9]+\]]], -[[Y]], [[Z]], [[FMA0]]
359
360; SI: buffer_store_dwordx2 [[RESULT]]
361define amdgpu_kernel void @aggressive_combine_to_fma_fsub_1_f64(double addrspace(1)* noalias %out, double addrspace(1)* noalias %in) #1 {
362  %tid = tail call i32 @llvm.amdgcn.workitem.id.x() #0
363  %gep.0 = getelementptr double, double addrspace(1)* %in, i32 %tid
364  %gep.1 = getelementptr double, double addrspace(1)* %gep.0, i32 1
365  %gep.2 = getelementptr double, double addrspace(1)* %gep.0, i32 2
366  %gep.3 = getelementptr double, double addrspace(1)* %gep.0, i32 3
367  %gep.4 = getelementptr double, double addrspace(1)* %gep.0, i32 4
368  %gep.out = getelementptr double, double addrspace(1)* %out, i32 %tid
369
370  %x = load volatile double, double addrspace(1)* %gep.0
371  %y = load volatile double, double addrspace(1)* %gep.1
372  %z = load volatile double, double addrspace(1)* %gep.2
373  %u = load volatile double, double addrspace(1)* %gep.3
374  %v = load volatile double, double addrspace(1)* %gep.4
375
376  %tmp0 = fmul double %u, %v
377  %tmp1 = call double @llvm.fma.f64(double %y, double %z, double %tmp0) #0
378  %tmp2 = fsub double %x, %tmp1
379
380  store double %tmp2, double addrspace(1)* %gep.out
381  ret void
382}
383
384;
385; Patterns (+ fneg variants): mul(add(1.0,x),y), mul(sub(1.0,x),y), mul(sub(x,1.0),y)
386;
387
388; FUNC-LABEL: {{^}}test_f32_mul_add_x_one_y:
389; SI-NOFMA: v_add_f32_e32 [[VS:v[0-9]]], 1.0, [[VX:v[0-9]]]
390; SI-NOFMA: v_mul_f32_e32 {{v[0-9]}}, [[VS]], [[VY:v[0-9]]]
391;
392; SI-FMA: v_fma_f32 {{v[0-9]}}, [[VX:v[0-9]]], [[VY:v[0-9]]], [[VY:v[0-9]]]
393define amdgpu_kernel void @test_f32_mul_add_x_one_y(float addrspace(1)* %out,
394                                        float addrspace(1)* %in1,
395                                        float addrspace(1)* %in2) {
396  %x = load volatile float, float addrspace(1)* %in1
397  %y = load volatile float, float addrspace(1)* %in2
398  %a = fadd float %x, 1.0
399  %m = fmul float %a, %y
400  store float %m, float addrspace(1)* %out
401  ret void
402}
403
404; FUNC-LABEL: {{^}}test_f32_mul_y_add_x_one:
405; SI-NOFMA: v_add_f32_e32 [[VS:v[0-9]]], 1.0, [[VX:v[0-9]]]
406; SI-NOFMA: v_mul_f32_e32 {{v[0-9]}}, [[VY:v[0-9]]], [[VS]]
407;
408; SI-FMA: v_fma_f32 {{v[0-9]}}, [[VX:v[0-9]]], [[VY:v[0-9]]], [[VY:v[0-9]]]
409define amdgpu_kernel void @test_f32_mul_y_add_x_one(float addrspace(1)* %out,
410                                        float addrspace(1)* %in1,
411                                        float addrspace(1)* %in2) {
412  %x = load volatile float, float addrspace(1)* %in1
413  %y = load volatile float, float addrspace(1)* %in2
414  %a = fadd float %x, 1.0
415  %m = fmul float %y, %a
416  store float %m, float addrspace(1)* %out
417  ret void
418}
419
420; FUNC-LABEL: {{^}}test_f32_mul_add_x_negone_y:
421; SI-NOFMA: v_add_f32_e32 [[VS:v[0-9]]], -1.0, [[VX:v[0-9]]]
422; SI-NOFMA: v_mul_f32_e32 {{v[0-9]}}, [[VS]], [[VY:v[0-9]]]
423;
424; SI-FMA: v_fma_f32 {{v[0-9]}}, [[VX:v[0-9]]], [[VY:v[0-9]]], -[[VY:v[0-9]]]
425define amdgpu_kernel void @test_f32_mul_add_x_negone_y(float addrspace(1)* %out,
426                                           float addrspace(1)* %in1,
427                                           float addrspace(1)* %in2) {
428  %x = load float, float addrspace(1)* %in1
429  %y = load float, float addrspace(1)* %in2
430  %a = fadd float %x, -1.0
431  %m = fmul float %a, %y
432  store float %m, float addrspace(1)* %out
433  ret void
434}
435
436; FUNC-LABEL: {{^}}test_f32_mul_y_add_x_negone:
437; SI-NOFMA: v_add_f32_e32 [[VS:v[0-9]]], -1.0, [[VX:v[0-9]]]
438; SI-NOFMA: v_mul_f32_e32 {{v[0-9]}}, [[VY:v[0-9]]], [[VS]]
439;
440; SI-FMA: v_fma_f32 {{v[0-9]}}, [[VX:v[0-9]]], [[VY:v[0-9]]], -[[VY:v[0-9]]]
441define amdgpu_kernel void @test_f32_mul_y_add_x_negone(float addrspace(1)* %out,
442                                           float addrspace(1)* %in1,
443                                           float addrspace(1)* %in2) {
444  %x = load float, float addrspace(1)* %in1
445  %y = load float, float addrspace(1)* %in2
446  %a = fadd float %x, -1.0
447  %m = fmul float %y, %a
448  store float %m, float addrspace(1)* %out
449  ret void
450}
451
452; FUNC-LABEL: {{^}}test_f32_mul_sub_one_x_y:
453; SI-NOFMA: v_sub_f32_e32 [[VS:v[0-9]]], 1.0, [[VX:v[0-9]]]
454; SI-NOFMA: v_mul_f32_e32 {{v[0-9]}}, [[VS]], [[VY:v[0-9]]]
455;
456; SI-FMA: v_fma_f32 {{v[0-9]}}, -[[VX:v[0-9]]], [[VY:v[0-9]]], [[VY:v[0-9]]]
457define amdgpu_kernel void @test_f32_mul_sub_one_x_y(float addrspace(1)* %out,
458                                        float addrspace(1)* %in1,
459                                        float addrspace(1)* %in2) {
460  %x = load float, float addrspace(1)* %in1
461  %y = load float, float addrspace(1)* %in2
462  %s = fsub float 1.0, %x
463  %m = fmul float %s, %y
464  store float %m, float addrspace(1)* %out
465  ret void
466}
467
468; FUNC-LABEL: {{^}}test_f32_mul_y_sub_one_x:
469; SI-NOFMA: v_sub_f32_e32 [[VS:v[0-9]]], 1.0, [[VX:v[0-9]]]
470; SI-NOFMA: v_mul_f32_e32 {{v[0-9]}}, [[VY:v[0-9]]], [[VS]]
471;
472; SI-FMA: v_fma_f32 {{v[0-9]}}, -[[VX:v[0-9]]], [[VY:v[0-9]]], [[VY:v[0-9]]]
473define amdgpu_kernel void @test_f32_mul_y_sub_one_x(float addrspace(1)* %out,
474                                        float addrspace(1)* %in1,
475                                        float addrspace(1)* %in2) {
476  %x = load float, float addrspace(1)* %in1
477  %y = load float, float addrspace(1)* %in2
478  %s = fsub float 1.0, %x
479  %m = fmul float %y, %s
480  store float %m, float addrspace(1)* %out
481  ret void
482}
483
484; FUNC-LABEL: {{^}}test_f32_mul_sub_negone_x_y:
485; SI-NOFMA: v_sub_f32_e32 [[VS:v[0-9]]], -1.0, [[VX:v[0-9]]]
486; SI-NOFMA: v_mul_f32_e32 {{v[0-9]}}, [[VS]], [[VY:v[0-9]]]
487;
488; SI-FMA: v_fma_f32 {{v[0-9]}}, -[[VX:v[0-9]]], [[VY:v[0-9]]], -[[VY:v[0-9]]]
489define amdgpu_kernel void @test_f32_mul_sub_negone_x_y(float addrspace(1)* %out,
490                                           float addrspace(1)* %in1,
491                                           float addrspace(1)* %in2) {
492  %x = load float, float addrspace(1)* %in1
493  %y = load float, float addrspace(1)* %in2
494  %s = fsub float -1.0, %x
495  %m = fmul float %s, %y
496  store float %m, float addrspace(1)* %out
497  ret void
498}
499
500; FUNC-LABEL: {{^}}test_f32_mul_y_sub_negone_x:
501; SI-NOFMA: v_sub_f32_e32 [[VS:v[0-9]]], -1.0, [[VX:v[0-9]]]
502; SI-NOFMA: v_mul_f32_e32 {{v[0-9]}}, [[VY:v[0-9]]], [[VS]]
503;
504; SI-FMA: v_fma_f32 {{v[0-9]}}, -[[VX:v[0-9]]], [[VY:v[0-9]]], -[[VY:v[0-9]]]
505define amdgpu_kernel void @test_f32_mul_y_sub_negone_x(float addrspace(1)* %out,
506                                         float addrspace(1)* %in1,
507                                         float addrspace(1)* %in2) {
508  %x = load float, float addrspace(1)* %in1
509  %y = load float, float addrspace(1)* %in2
510  %s = fsub float -1.0, %x
511  %m = fmul float %y, %s
512  store float %m, float addrspace(1)* %out
513  ret void
514}
515
516; FUNC-LABEL: {{^}}test_f32_mul_sub_x_one_y:
517; SI-NOFMA: v_add_f32_e32 [[VS:v[0-9]]], -1.0, [[VX:v[0-9]]]
518; SI-NOFMA: v_mul_f32_e32 {{v[0-9]}}, [[VS]], [[VY:v[0-9]]]
519;
520; SI-FMA: v_fma_f32 {{v[0-9]}}, [[VX:v[0-9]]], [[VY:v[0-9]]], -[[VY:v[0-9]]]
521define amdgpu_kernel void @test_f32_mul_sub_x_one_y(float addrspace(1)* %out,
522                                        float addrspace(1)* %in1,
523                                        float addrspace(1)* %in2) {
524  %x = load float, float addrspace(1)* %in1
525  %y = load float, float addrspace(1)* %in2
526  %s = fsub float %x, 1.0
527  %m = fmul float %s, %y
528  store float %m, float addrspace(1)* %out
529  ret void
530}
531
532; FUNC-LABEL: {{^}}test_f32_mul_y_sub_x_one:
533; SI-NOFMA: v_add_f32_e32 [[VS:v[0-9]]], -1.0, [[VX:v[0-9]]]
534; SI-NOFMA: v_mul_f32_e32 {{v[0-9]}}, [[VY:v[0-9]]], [[VS]]
535;
536; SI-FMA: v_fma_f32 {{v[0-9]}}, [[VX:v[0-9]]], [[VY:v[0-9]]], -[[VY:v[0-9]]]
537define amdgpu_kernel void @test_f32_mul_y_sub_x_one(float addrspace(1)* %out,
538                                      float addrspace(1)* %in1,
539                                      float addrspace(1)* %in2) {
540  %x = load float, float addrspace(1)* %in1
541  %y = load float, float addrspace(1)* %in2
542  %s = fsub float %x, 1.0
543  %m = fmul float %y, %s
544  store float %m, float addrspace(1)* %out
545  ret void
546}
547
548; FUNC-LABEL: {{^}}test_f32_mul_sub_x_negone_y:
549; SI-NOFMA: v_add_f32_e32 [[VS:v[0-9]]], 1.0, [[VX:v[0-9]]]
550; SI-NOFMA: v_mul_f32_e32 {{v[0-9]}}, [[VS]], [[VY:v[0-9]]]
551;
552; SI-FMA: v_fma_f32 {{v[0-9]}}, [[VX:v[0-9]]], [[VY:v[0-9]]], [[VY:v[0-9]]]
553define amdgpu_kernel void @test_f32_mul_sub_x_negone_y(float addrspace(1)* %out,
554                                         float addrspace(1)* %in1,
555                                         float addrspace(1)* %in2) {
556  %x = load float, float addrspace(1)* %in1
557  %y = load float, float addrspace(1)* %in2
558  %s = fsub float %x, -1.0
559  %m = fmul float %s, %y
560  store float %m, float addrspace(1)* %out
561  ret void
562}
563
564; FUNC-LABEL: {{^}}test_f32_mul_y_sub_x_negone:
565; SI-NOFMA: v_add_f32_e32 [[VS:v[0-9]]], 1.0, [[VX:v[0-9]]]
566; SI-NOFMA: v_mul_f32_e32 {{v[0-9]}}, [[VY:v[0-9]]], [[VS]]
567;
568; SI-FMA: v_fma_f32 {{v[0-9]}}, [[VX:v[0-9]]], [[VY:v[0-9]]], [[VY:v[0-9]]]
569define amdgpu_kernel void @test_f32_mul_y_sub_x_negone(float addrspace(1)* %out,
570                                         float addrspace(1)* %in1,
571                                         float addrspace(1)* %in2) {
572  %x = load float, float addrspace(1)* %in1
573  %y = load float, float addrspace(1)* %in2
574  %s = fsub float %x, -1.0
575  %m = fmul float %y, %s
576  store float %m, float addrspace(1)* %out
577  ret void
578}
579
580;
581; Interpolation Patterns: add(mul(x,t),mul(sub(1.0,t),y))
582;
583
584; FUNC-LABEL: {{^}}test_f32_interp:
585; SI-NOFMA: v_sub_f32_e32 [[VT1:v[0-9]]], 1.0, [[VT:v[0-9]]]
586; SI-NOFMA: v_mul_f32_e32 [[VTY:v[0-9]]], [[VY:v[0-9]]], [[VT1]]
587; SI-NOFMA: v_mac_f32_e32 [[VTY]], [[VX:v[0-9]]], [[VT]]
588;
589; SI-FMA: v_fma_f32 [[VR:v[0-9]]], -[[VT:v[0-9]]], [[VY:v[0-9]]], [[VY]]
590; SI-FMA: v_fma_f32 {{v[0-9]}}, [[VX:v[0-9]]], [[VT]], [[VR]]
591define amdgpu_kernel void @test_f32_interp(float addrspace(1)* %out,
592                             float addrspace(1)* %in1,
593                             float addrspace(1)* %in2,
594                             float addrspace(1)* %in3) {
595  %x = load float, float addrspace(1)* %in1
596  %y = load float, float addrspace(1)* %in2
597  %t = load float, float addrspace(1)* %in3
598  %t1 = fsub float 1.0, %t
599  %tx = fmul float %x, %t
600  %ty = fmul float %y, %t1
601  %r = fadd float %tx, %ty
602  store float %r, float addrspace(1)* %out
603  ret void
604}
605
606; FUNC-LABEL: {{^}}test_f64_interp:
607; SI-NOFMA: v_add_f64 [[VT1:v\[[0-9]+:[0-9]+\]]], -[[VT:v\[[0-9]+:[0-9]+\]]], 1.0
608; SI-NOFMA: v_mul_f64 [[VTY:v\[[0-9]+:[0-9]+\]]], [[VY:v\[[0-9]+:[0-9]+\]]], [[VT1]]
609; SI-NOFMA: v_fma_f64 v{{\[[0-9]+:[0-9]+\]}}, [[VX:v\[[0-9]+:[0-9]+\]]], [[VT]], [[VTY]]
610;
611; SI-FMA: v_fma_f64 [[VR:v\[[0-9]+:[0-9]+\]]], -[[VT:v\[[0-9]+:[0-9]+\]]], [[VY:v\[[0-9]+:[0-9]+\]]], [[VY]]
612; SI-FMA: v_fma_f64 v{{\[[0-9]+:[0-9]+\]}}, [[VX:v\[[0-9]+:[0-9]+\]]], [[VT]], [[VR]]
613define amdgpu_kernel void @test_f64_interp(double addrspace(1)* %out,
614                             double addrspace(1)* %in1,
615                             double addrspace(1)* %in2,
616                             double addrspace(1)* %in3) {
617  %x = load double, double addrspace(1)* %in1
618  %y = load double, double addrspace(1)* %in2
619  %t = load double, double addrspace(1)* %in3
620  %t1 = fsub double 1.0, %t
621  %tx = fmul double %x, %t
622  %ty = fmul double %y, %t1
623  %r = fadd double %tx, %ty
624  store double %r, double addrspace(1)* %out
625  ret void
626}
627
628; Make sure negative constant cancels out fneg
629; GCN-LABEL: {{^}}fma_neg_2.0_neg_a_b_f32:
630; GCN: {{buffer|flat|global}}_load_dword [[A:v[0-9]+]]
631; GCN: {{buffer|flat|global}}_load_dword [[B:v[0-9]+]]
632; GCN-NOT: [[A]]
633; GCN-NOT: [[B]]
634; GCN: v_fma_f32 v{{[0-9]+}}, [[A]], 2.0, [[B]]
635define amdgpu_kernel void @fma_neg_2.0_neg_a_b_f32(float addrspace(1)* %out, float addrspace(1)* %in) #0 {
636  %tid = call i32 @llvm.amdgcn.workitem.id.x()
637  %gep.0 = getelementptr float, float addrspace(1)* %out, i32 %tid
638  %gep.1 = getelementptr float, float addrspace(1)* %gep.0, i32 1
639  %gep.out = getelementptr float, float addrspace(1)* %out, i32 %tid
640
641  %r1 = load volatile float, float addrspace(1)* %gep.0
642  %r2 = load volatile float, float addrspace(1)* %gep.1
643
644  %r1.fneg = fsub float -0.000000e+00, %r1
645
646  %r3 = tail call float @llvm.fma.f32(float -2.0, float %r1.fneg, float %r2)
647  store float %r3, float addrspace(1)* %gep.out
648  ret void
649}
650
651; GCN-LABEL: {{^}}fma_2.0_neg_a_b_f32:
652; GCN: {{buffer|flat|global}}_load_dword [[A:v[0-9]+]]
653; GCN: {{buffer|flat|global}}_load_dword [[B:v[0-9]+]]
654; GCN-NOT: [[A]]
655; GCN-NOT: [[B]]
656; GCN: v_fma_f32 v{{[0-9]+}}, [[A]], -2.0, [[B]]
657define amdgpu_kernel void @fma_2.0_neg_a_b_f32(float addrspace(1)* %out, float addrspace(1)* %in) #0 {
658  %tid = call i32 @llvm.amdgcn.workitem.id.x()
659  %gep.0 = getelementptr float, float addrspace(1)* %out, i32 %tid
660  %gep.1 = getelementptr float, float addrspace(1)* %gep.0, i32 1
661  %gep.out = getelementptr float, float addrspace(1)* %out, i32 %tid
662
663  %r1 = load volatile float, float addrspace(1)* %gep.0
664  %r2 = load volatile float, float addrspace(1)* %gep.1
665
666  %r1.fneg = fsub float -0.000000e+00, %r1
667
668  %r3 = tail call float @llvm.fma.f32(float 2.0, float %r1.fneg, float %r2)
669  store float %r3, float addrspace(1)* %gep.out
670  ret void
671}
672
673attributes #0 = { nounwind readnone }
674attributes #1 = { nounwind }
675
676