1# RUN: llc -run-pass=machine-combiner -o - -simplify-mir -mtriple=arm64-apple-iphoneos %s | FileCheck %s
2
3# Can create FMADD, because both the fmul and fadd have all fast-math flags.
4#
5# CHECK-LABEL: name: scalar_fmadd_fast
6# CHECK:        [[C:%.*]]:fpr32 = COPY $s2
7# CHECK-NEXT:   [[B:%.*]]:fpr32 = COPY $s1
8# CHECK-NEXT:   [[A:%.*]]:fpr32 = COPY $s0
9# CHECK-NEXT:   :fpr32 = FMADDSrrr [[B]], [[A]], [[C]]
10---
11name:            scalar_fmadd_fast
12alignment:       4
13tracksRegLiveness: true
14registers:
15  - { id: 0, class: fpr32 }
16  - { id: 1, class: fpr32 }
17  - { id: 2, class: fpr32 }
18  - { id: 3, class: fpr32 }
19  - { id: 4, class: fpr32 }
20liveins:
21  - { reg: '$s0', virtual-reg: '%0' }
22  - { reg: '$s1', virtual-reg: '%1' }
23  - { reg: '$s2', virtual-reg: '%2' }
24frameInfo:
25  maxAlignment:    1
26  maxCallFrameSize: 0
27machineFunctionInfo: {}
28body:             |
29  bb.0.entry:
30    liveins: $s0, $s1, $s2
31
32    %2:fpr32 = COPY $s2
33    %1:fpr32 = COPY $s1
34    %0:fpr32 = COPY $s0
35    %3:fpr32 = nnan ninf nsz arcp contract afn reassoc FMULSrr %1, %0
36    %4:fpr32 = nnan ninf nsz arcp contract afn reassoc FADDSrr killed %3, %2
37    $s0 = COPY %4
38    RET_ReallyLR implicit $s0
39
40...
41
42# Can create FMADD, because both the fmul and fadd have the contract fast-math flag.
43#
44# CHECK-LABEL: name: scalar_fmadd_contract
45# CHECK:        [[C:%.*]]:fpr32 = COPY $s2
46# CHECK-NEXT:   [[B:%.*]]:fpr32 = COPY $s1
47# CHECK-NEXT:   [[A:%.*]]:fpr32 = COPY $s0
48# CHECK-NEXT:   :fpr32 = FMADDSrrr [[B]], [[A]], [[C]]
49
50---
51name:            scalar_fmadd_contract
52alignment:       4
53tracksRegLiveness: true
54registers:
55  - { id: 0, class: fpr32 }
56  - { id: 1, class: fpr32 }
57  - { id: 2, class: fpr32 }
58  - { id: 3, class: fpr32 }
59  - { id: 4, class: fpr32 }
60liveins:
61  - { reg: '$s0', virtual-reg: '%0' }
62  - { reg: '$s1', virtual-reg: '%1' }
63  - { reg: '$s2', virtual-reg: '%2' }
64frameInfo:
65  maxAlignment:    1
66  maxCallFrameSize: 0
67machineFunctionInfo: {}
68body:             |
69  bb.0.entry:
70    liveins: $s0, $s1, $s2
71
72    %2:fpr32 = COPY $s2
73    %1:fpr32 = COPY $s1
74    %0:fpr32 = COPY $s0
75    %3:fpr32 = contract FMULSrr %1, %0
76    %4:fpr32 = contract FADDSrr killed %3, %2
77    $s0 = COPY %4
78    RET_ReallyLR implicit $s0
79
80...
81
82# Do not create FMADD, because we don't have the contract flag on the FADD.
83
84# CHECK-LABEL: name: scalar_fmadd_contract_op0
85# CHECK:        [[C:%.*]]:fpr32 = COPY $s2
86# CHECK-NEXT:   [[B:%.*]]:fpr32 = COPY $s1
87# CHECK-NEXT:   [[A:%.*]]:fpr32 = COPY $s0
88# CHECK-NEXT:   [[MUL:%.*]]:fpr32 = contract FMULSrr [[B]], [[A]]
89# CHECK-NEXT:   fpr32 = FADDSrr killed [[MUL]], [[C]]
90---
91name:            scalar_fmadd_contract_op0
92alignment:       4
93tracksRegLiveness: true
94registers:
95  - { id: 0, class: fpr32 }
96  - { id: 1, class: fpr32 }
97  - { id: 2, class: fpr32 }
98  - { id: 3, class: fpr32 }
99  - { id: 4, class: fpr32 }
100liveins:
101  - { reg: '$s0', virtual-reg: '%0' }
102  - { reg: '$s1', virtual-reg: '%1' }
103  - { reg: '$s2', virtual-reg: '%2' }
104frameInfo:
105  maxAlignment:    1
106  maxCallFrameSize: 0
107machineFunctionInfo: {}
108body:             |
109  bb.0.entry:
110    liveins: $s0, $s1, $s2
111
112    %2:fpr32 = COPY $s2
113    %1:fpr32 = COPY $s1
114    %0:fpr32 = COPY $s0
115    %3:fpr32 = contract FMULSrr %1, %0
116    %4:fpr32 = FADDSrr killed %3, %2
117    $s0 = COPY %4
118    RET_ReallyLR implicit $s0
119
120...
121
122# Do create FMADD, because we have the contract flag on the FADD.
123#
124# CHECK-LABEL: name: scalar_fmadd_contract_op1
125# CHECK:        [[C:%.*]]:fpr32 = COPY $s2
126# CHECK-NEXT:   [[B:%.*]]:fpr32 = COPY $s1
127# CHECK-NEXT:   [[A:%.*]]:fpr32 = COPY $s0
128# CHECK-NEXT:   :fpr32 = FMADDSrrr [[B]], [[A]], [[C]]
129
130---
131name:            scalar_fmadd_contract_op1
132alignment:       4
133tracksRegLiveness: true
134registers:
135  - { id: 0, class: fpr32 }
136  - { id: 1, class: fpr32 }
137  - { id: 2, class: fpr32 }
138  - { id: 3, class: fpr32 }
139  - { id: 4, class: fpr32 }
140liveins:
141  - { reg: '$s0', virtual-reg: '%0' }
142  - { reg: '$s1', virtual-reg: '%1' }
143  - { reg: '$s2', virtual-reg: '%2' }
144frameInfo:
145  maxAlignment:    1
146  maxCallFrameSize: 0
147machineFunctionInfo: {}
148body:             |
149  bb.0.entry:
150    liveins: $s0, $s1, $s2
151
152    %2:fpr32 = COPY $s2
153    %1:fpr32 = COPY $s1
154    %0:fpr32 = COPY $s0
155    %3:fpr32 = FMULSrr %1, %0
156    %4:fpr32 = contract FADDSrr killed %3, %2
157    $s0 = COPY %4
158    RET_ReallyLR implicit $s0
159
160...
161
162# Do not create FMADD, as nsz flag does not allow it.
163#
164# CHECK-LABEL: name: scalar_fmadd_nsz
165# CHECK:        [[C:%.*]]:fpr32 = COPY $s2
166# CHECK-NEXT:   [[B:%.*]]:fpr32 = COPY $s1
167# CHECK-NEXT:   [[A:%.*]]:fpr32 = COPY $s0
168# CHECK-NEXT:   [[MUL:%.*]]:fpr32 = nsz FMULSrr [[B]], [[A]]
169# CHECK-NEXT:   fpr32 = nsz FADDSrr killed [[MUL]], [[C]]
170
171---
172name:            scalar_fmadd_nsz
173alignment:       4
174tracksRegLiveness: true
175registers:
176  - { id: 0, class: fpr32 }
177  - { id: 1, class: fpr32 }
178  - { id: 2, class: fpr32 }
179  - { id: 3, class: fpr32 }
180  - { id: 4, class: fpr32 }
181liveins:
182  - { reg: '$s0', virtual-reg: '%0' }
183  - { reg: '$s1', virtual-reg: '%1' }
184  - { reg: '$s2', virtual-reg: '%2' }
185frameInfo:
186  maxAlignment:    1
187  maxCallFrameSize: 0
188machineFunctionInfo: {}
189body:             |
190  bb.0.entry:
191    liveins: $s0, $s1, $s2
192
193    %2:fpr32 = COPY $s2
194    %1:fpr32 = COPY $s1
195    %0:fpr32 = COPY $s0
196    %3:fpr32 = nsz FMULSrr %1, %0
197    %4:fpr32 = nsz FADDSrr killed %3, %2
198    $s0 = COPY %4
199    RET_ReallyLR implicit $s0
200
201...
202
203# Can create FMLA, because both the fmul and fadd have all fast-math flags.
204#
205# CHECK-LABEL: name: vector_fmadd_fast
206# CHECK:       [[C:%.*]]:fpr128 = COPY $q2
207# CHECK-NEXT:  [[B:%.*]]:fpr128 = COPY $q1
208# CHECK-NEXT:  [[A:%.*]]:fpr128 = COPY $q0
209# CHECK-NEXT:  fpr128 = FMLAv2f64 [[C]], [[B]], [[A]]
210---
211name:            vector_fmadd_fast
212alignment:       4
213tracksRegLiveness: true
214registers:
215  - { id: 0, class: fpr128 }
216  - { id: 1, class: fpr128 }
217  - { id: 2, class: fpr128 }
218  - { id: 3, class: fpr128 }
219  - { id: 4, class: fpr128 }
220liveins:
221  - { reg: '$q0', virtual-reg: '%0' }
222  - { reg: '$q1', virtual-reg: '%1' }
223  - { reg: '$q2', virtual-reg: '%2' }
224frameInfo:
225  maxAlignment:    1
226  maxCallFrameSize: 0
227machineFunctionInfo: {}
228body:             |
229  bb.0.entry:
230    liveins: $q0, $q1, $q2
231
232    %2:fpr128 = COPY $q2
233    %1:fpr128 = COPY $q1
234    %0:fpr128 = COPY $q0
235    %3:fpr128 = nnan ninf nsz arcp contract afn reassoc FMULv2f64 %1, %0
236    %4:fpr128 = nnan ninf nsz arcp contract afn reassoc FADDv2f64 killed %3, %2
237    $q0 = COPY %4
238    RET_ReallyLR implicit $q0
239
240...
241
242# Can create FMLA, because both the fmul and fadd have the contract fast-math flag.
243#
244# CHECK-LABEL: name: vector_fmadd_contract
245# CHECK:       [[C:%.*]]:fpr128 = COPY $q2
246# CHECK-NEXT:  [[B:%.*]]:fpr128 = COPY $q1
247# CHECK-NEXT:  [[A:%.*]]:fpr128 = COPY $q0
248# CHECK-NEXT:  fpr128 = FMLAv2f64 [[C]], [[B]], [[A]]
249---
250name:            vector_fmadd_contract
251alignment:       4
252tracksRegLiveness: true
253registers:
254  - { id: 0, class: fpr128 }
255  - { id: 1, class: fpr128 }
256  - { id: 2, class: fpr128 }
257  - { id: 3, class: fpr128 }
258  - { id: 4, class: fpr128 }
259liveins:
260  - { reg: '$q0', virtual-reg: '%0' }
261  - { reg: '$q1', virtual-reg: '%1' }
262  - { reg: '$q2', virtual-reg: '%2' }
263frameInfo:
264  maxAlignment:    1
265  maxCallFrameSize: 0
266machineFunctionInfo: {}
267body:             |
268  bb.0.entry:
269    liveins: $q0, $q1, $q2
270
271    %2:fpr128 = COPY $q2
272    %1:fpr128 = COPY $q1
273    %0:fpr128 = COPY $q0
274    %3:fpr128 = contract FMULv2f64 %1, %0
275    %4:fpr128 = contract FADDv2f64 killed %3, %2
276    $q0 = COPY %4
277    RET_ReallyLR implicit $q0
278
279...
280
281# Do not create FMLA, because we don't have the contract flag on the FADD.
282#
283# CHECK-LABEL: name: vector_fmadd_contract_op0
284# CHECK:       [[C:%.*]]:fpr128 = COPY $q2
285# CHECK-NEXT:  [[B:%.*]]:fpr128 = COPY $q1
286# CHECK-NEXT:  [[A:%.*]]:fpr128 = COPY $q0
287# CHECK-NEXT:  [[MUL:%.*]]:fpr128 = contract FMULv2f64 [[B]], [[A]]
288# CHECK-NEXT:  fpr128 = FADDv2f64 killed [[MUL]], [[C]]
289---
290name:            vector_fmadd_contract_op0
291alignment:       4
292tracksRegLiveness: true
293registers:
294  - { id: 0, class: fpr128 }
295  - { id: 1, class: fpr128 }
296  - { id: 2, class: fpr128 }
297  - { id: 3, class: fpr128 }
298  - { id: 4, class: fpr128 }
299liveins:
300  - { reg: '$q0', virtual-reg: '%0' }
301  - { reg: '$q1', virtual-reg: '%1' }
302  - { reg: '$q2', virtual-reg: '%2' }
303frameInfo:
304  maxAlignment:    1
305  maxCallFrameSize: 0
306machineFunctionInfo: {}
307body:             |
308  bb.0.entry:
309    liveins: $q0, $q1, $q2
310
311    %2:fpr128 = COPY $q2
312    %1:fpr128 = COPY $q1
313    %0:fpr128 = COPY $q0
314    %3:fpr128 = contract FMULv2f64 %1, %0
315    %4:fpr128 = FADDv2f64 killed %3, %2
316    $q0 = COPY %4
317    RET_ReallyLR implicit $q0
318
319...
320
321# Do create FMLA, because we have the contract flag on the FADD.
322#
323# CHECK-LABEL: name: vector_fmadd_contract_op1
324# CHECK:       [[C:%.*]]:fpr128 = COPY $q2
325# CHECK-NEXT:  [[B:%.*]]:fpr128 = COPY $q1
326# CHECK-NEXT:  [[A:%.*]]:fpr128 = COPY $q0
327# CHECK-NEXT:  fpr128 = FMLAv2f64 [[C]], [[B]], [[A]]
328
329---
330name:            vector_fmadd_contract_op1
331alignment:       4
332tracksRegLiveness: true
333registers:
334  - { id: 0, class: fpr128 }
335  - { id: 1, class: fpr128 }
336  - { id: 2, class: fpr128 }
337  - { id: 3, class: fpr128 }
338  - { id: 4, class: fpr128 }
339liveins:
340  - { reg: '$q0', virtual-reg: '%0' }
341  - { reg: '$q1', virtual-reg: '%1' }
342  - { reg: '$q2', virtual-reg: '%2' }
343frameInfo:
344  maxAlignment:    1
345  maxCallFrameSize: 0
346machineFunctionInfo: {}
347body:             |
348  bb.0.entry:
349    liveins: $q0, $q1, $q2
350
351    %2:fpr128 = COPY $q2
352    %1:fpr128 = COPY $q1
353    %0:fpr128 = COPY $q0
354    %3:fpr128 = FMULv2f64 %1, %0
355    %4:fpr128 = contract FADDv2f64 killed %3, %2
356    $q0 = COPY %4
357    RET_ReallyLR implicit $q0
358
359...
360
361# Do not create FMLA, as nsz flag does not allow it.
362#
363# CHECK-LABEL: name: vector_fmadd_nsz
364# CHECK:       [[C:%.*]]:fpr128 = COPY $q2
365# CHECK-NEXT:  [[B:%.*]]:fpr128 = COPY $q1
366# CHECK-NEXT:  [[A:%.*]]:fpr128 = COPY $q0
367# CHECK-NEXT:  [[MUL:%.*]]:fpr128 = nsz FMULv2f64 [[B]], [[A]]
368# CHECK-NEXT:  fpr128 = nsz FADDv2f64 killed [[MUL]], [[C]]
369---
370name:            vector_fmadd_nsz
371alignment:       4
372tracksRegLiveness: true
373registers:
374  - { id: 0, class: fpr128 }
375  - { id: 1, class: fpr128 }
376  - { id: 2, class: fpr128 }
377  - { id: 3, class: fpr128 }
378  - { id: 4, class: fpr128 }
379liveins:
380  - { reg: '$q0', virtual-reg: '%0' }
381  - { reg: '$q1', virtual-reg: '%1' }
382  - { reg: '$q2', virtual-reg: '%2' }
383frameInfo:
384  maxAlignment:    1
385  maxCallFrameSize: 0
386machineFunctionInfo: {}
387body:             |
388  bb.0.entry:
389    liveins: $q0, $q1, $q2
390
391    %2:fpr128 = COPY $q2
392    %1:fpr128 = COPY $q1
393    %0:fpr128 = COPY $q0
394    %3:fpr128 = nsz FMULv2f64 %1, %0
395    %4:fpr128 = nsz FADDv2f64 killed %3, %2
396    $q0 = COPY %4
397    RET_ReallyLR implicit $q0
398
399...
400