1 # RUN: llc -mtriple=aarch64-linux-gnu -run-pass machine-combiner -verify-machineinstrs -o - %s | FileCheck %s
3 # The test cases in this file check following transformation if the right form
5 # A - (B + C) ==> (A - B) - C
10 # CHECK-LABEL: name: test1
11 # CHECK: [[TMP:%[0-9]+]]:gpr32 = SUBWrr killed %3, %4
12 # CHECK-NEXT: %7:gpr32 = SUBWrr killed [[TMP]], %5
16 - { id: 0, class: gpr32common }
17 - { id: 1, class: gpr32 }
18 - { id: 2, class: gpr32 }
19 - { id: 3, class: gpr32common }
20 - { id: 4, class: gpr32common }
21 - { id: 5, class: gpr32 }
22 - { id: 6, class: gpr32 }
23 - { id: 7, class: gpr32 }
24 - { id: 8, class: gpr32 }
29 %0:gpr32common = COPY $w0
30 %3:gpr32common = ORRWri %2:gpr32, 1600
31 %4:gpr32common = ADDWri %0:gpr32common, 100, 0
32 %5:gpr32 = EORWrs %1:gpr32, %4:gpr32common, 8
33 %6:gpr32 = ADDWrr %5:gpr32, %4:gpr32common
34 %7:gpr32 = SUBWrr killed %3:gpr32common, killed %6:gpr32
35 %8:gpr32 = EORWrs killed %7:gpr32, %5:gpr32, 141
37 RET_ReallyLR implicit $w0
43 # CHECK-LABEL: name: test2
44 # CHECK: [[TMP:%[0-9]+]]:gpr64 = SUBXrr killed %3, %4
45 # CHECK-NEXT: %7:gpr64 = SUBXrr killed [[TMP]], %5
49 - { id: 0, class: gpr64common }
50 - { id: 1, class: gpr64 }
51 - { id: 2, class: gpr64 }
52 - { id: 3, class: gpr64common }
53 - { id: 4, class: gpr64common }
54 - { id: 5, class: gpr64 }
55 - { id: 6, class: gpr64 }
56 - { id: 7, class: gpr64 }
57 - { id: 8, class: gpr64 }
62 %0:gpr64common = COPY $x0
63 %3:gpr64common = ORRXri %2:gpr64, 1600
64 %4:gpr64common = ADDXri %0:gpr64common, 100, 0
65 %5:gpr64 = EORXrs %1:gpr64, %4:gpr64common, 8
66 %6:gpr64 = ADDXrr %5:gpr64, %4:gpr64common
67 %7:gpr64 = SUBXrr killed %3:gpr64common, killed %6:gpr64
68 %8:gpr64 = EORXrs killed %7:gpr64, %5:gpr64, 141
70 RET_ReallyLR implicit $x0
74 # Negative test. The right form can't reduce latency.
76 # CHECK-LABEL: name: test3
77 # CHECK: %6:gpr32 = ADDWrr killed %3, %4
78 # CHECK-NEXT: %7:gpr32 = SUBWrr %5, killed %6
82 - { id: 0, class: gpr32common }
83 - { id: 1, class: gpr32 }
84 - { id: 2, class: gpr32 }
85 - { id: 3, class: gpr32common }
86 - { id: 4, class: gpr32common }
87 - { id: 5, class: gpr32 }
88 - { id: 6, class: gpr32 }
89 - { id: 7, class: gpr32 }
90 - { id: 8, class: gpr32 }
95 %0:gpr32common = COPY $w0
96 %3:gpr32common = ORRWri %2:gpr32, 1600
97 %4:gpr32common = ADDWri %0:gpr32common, 100, 0
98 %5:gpr32 = EORWrs %1:gpr32, %4:gpr32common, 8
99 %6:gpr32 = ADDWrr killed %3:gpr32common, %4:gpr32common
100 %7:gpr32 = SUBWrr %5:gpr32, killed %6:gpr32
101 %8:gpr32 = EORWrs killed %7:gpr32, %5:gpr32, 141
103 RET_ReallyLR implicit $w0
107 # Dead define of flag registers should not block transformation.
109 # CHECK-LABEL: name: test4
110 # CHECK: [[TMP:%[0-9]+]]:gpr64 = SUBXrr killed %3, %4
111 # CHECK-NEXT: %7:gpr64 = SUBXrr killed [[TMP]], %5
115 - { id: 0, class: gpr64common }
116 - { id: 1, class: gpr64 }
117 - { id: 2, class: gpr64 }
118 - { id: 3, class: gpr64common }
119 - { id: 4, class: gpr64common }
120 - { id: 5, class: gpr64 }
121 - { id: 6, class: gpr64 }
122 - { id: 7, class: gpr64 }
123 - { id: 8, class: gpr64 }
128 %0:gpr64common = COPY $x0
129 %3:gpr64common = ORRXri %2:gpr64, 1600
130 %4:gpr64common = ADDXri %0:gpr64common, 100, 0
131 %5:gpr64 = EORXrs %1:gpr64, %4:gpr64common, 8
132 %6:gpr64 = ADDSXrr %5:gpr64, %4:gpr64common, implicit-def dead $nzcv
133 %7:gpr64 = SUBSXrr killed %3:gpr64common, killed %6:gpr64, implicit-def dead $nzcv
134 %8:gpr64 = EORXrs killed %7:gpr64, %5:gpr64, 141
136 RET_ReallyLR implicit $x0
140 # Non dead define of flag register in SUB can block the transformation.
142 # CHECK-LABEL: name: test5
143 # CHECK: %6:gpr32 = ADDWrr %5, %4
144 # CHECK-NEXT: %7:gpr32 = SUBSWrr killed %3, killed %6, implicit-def $nzcv
148 - { id: 0, class: gpr32common }
149 - { id: 1, class: gpr32 }
150 - { id: 2, class: gpr32 }
151 - { id: 3, class: gpr32common }
152 - { id: 4, class: gpr32common }
153 - { id: 5, class: gpr32 }
154 - { id: 6, class: gpr32 }
155 - { id: 7, class: gpr32 }
156 - { id: 8, class: gpr32 }
161 %0:gpr32common = COPY $w0
162 %3:gpr32common = ORRWri %2:gpr32, 1600
163 %4:gpr32common = ADDWri %0:gpr32common, 100, 0
164 %5:gpr32 = EORWrs %1:gpr32, %4:gpr32common, 8
165 %6:gpr32 = ADDWrr %5:gpr32, %4:gpr32common
166 %7:gpr32 = SUBSWrr killed %3:gpr32common, killed %6:gpr32, implicit-def $nzcv
167 %8:gpr32 = EORWrs killed %7:gpr32, %5:gpr32, 141
169 RET_ReallyLR implicit $w0
173 # Non dead define of flag register in ADD can block the transformation.
175 # CHECK-LABEL: name: test6
176 # CHECK: %6:gpr64 = ADDSXrr %5, %4, implicit-def $nzcv
177 # CHECK-NEXT: %7:gpr64 = SUBXrr killed %3, killed %6
181 - { id: 0, class: gpr64common }
182 - { id: 1, class: gpr64 }
183 - { id: 2, class: gpr64 }
184 - { id: 3, class: gpr64common }
185 - { id: 4, class: gpr64common }
186 - { id: 5, class: gpr64 }
187 - { id: 6, class: gpr64 }
188 - { id: 7, class: gpr64 }
189 - { id: 8, class: gpr64 }
194 %0:gpr64common = COPY $x0
195 %3:gpr64common = ORRXri %2:gpr64, 1600
196 %4:gpr64common = ADDXri %0:gpr64common, 100, 0
197 %5:gpr64 = EORXrs %1:gpr64, %4:gpr64common, 8
198 %6:gpr64 = ADDSXrr %5:gpr64, %4:gpr64common, implicit-def $nzcv
199 %7:gpr64 = SUBXrr killed %3:gpr64common, killed %6:gpr64
200 %8:gpr64 = EORXrs killed %7:gpr64, %5:gpr64, 141
202 RET_ReallyLR implicit $x0
206 # ADD has multiple uses, so it is always required, we should not transform it.
208 # CHECK-LABEL: name: test7
209 # CHECK: %6:gpr32 = ADDWrr %5, %4
210 # CHECK-NEXT: %7:gpr32 = SUBWrr killed %3, %6
214 - { id: 0, class: gpr32common }
215 - { id: 1, class: gpr32 }
216 - { id: 2, class: gpr32 }
217 - { id: 3, class: gpr32common }
218 - { id: 4, class: gpr32common }
219 - { id: 5, class: gpr32 }
220 - { id: 6, class: gpr32 }
221 - { id: 7, class: gpr32 }
222 - { id: 8, class: gpr32 }
223 - { id: 9, class: gpr32 }
228 %0:gpr32common = COPY $w0
229 %3:gpr32common = ORRWri %2:gpr32, 1600
230 %4:gpr32common = ADDWri %0:gpr32common, 100, 0
231 %5:gpr32 = EORWrs %1:gpr32, %4:gpr32common, 8
232 %6:gpr32 = ADDWrr %5:gpr32, %4:gpr32common
233 %7:gpr32 = SUBWrr killed %3:gpr32common, %6:gpr32
234 %8:gpr32 = EORWrs killed %7:gpr32, %5:gpr32, 141
235 %9:gpr32 = ADDWrr %8:gpr32, %6:gpr32
237 RET_ReallyLR implicit $w0
241 # Drop nowrap flags in SUB
243 # CHECK-LABEL: name: test8
244 # CHECK: [[SUBXrr:%[0-9]+]]:gpr64 = SUBXrr %1, %0
245 # CHECK-NEXT: %4:gpr64common = SUBXrr killed [[SUBXrr]], killed %2
249 - { id: 0, class: gpr64 }
250 - { id: 1, class: gpr64 }
251 - { id: 2, class: gpr64common }
252 - { id: 3, class: gpr64 }
253 - { id: 4, class: gpr64common }
254 - { id: 5, class: gpr64 }
259 %2:gpr64common = ORRXri %0:gpr64, 4096
260 %3:gpr64 = ADDXrr killed %2:gpr64common, %0:gpr64
261 %4:gpr64common = nsw SUBSXrr %1:gpr64, killed %3:gpr64, implicit-def dead $nzcv
262 %5:gpr64 = SUBSXri %4:gpr64common, 0, 0, implicit-def $nzcv
264 RET_ReallyLR implicit $x0
270 # CHECK-LABEL: name: wzr
271 # CHECK: [[TMP:%[0-9]+]]:gpr32 = SUBWrr killed $wzr, %4
272 # CHECK-NEXT: %7:gpr32 = SUBWrr killed [[TMP]], %5
276 - { id: 0, class: gpr32common }
277 - { id: 1, class: gpr32 }
278 - { id: 2, class: gpr32 }
279 - { id: 3, class: gpr32common }
280 - { id: 4, class: gpr32common }
281 - { id: 5, class: gpr32 }
282 - { id: 6, class: gpr32 }
283 - { id: 7, class: gpr32 }
284 - { id: 8, class: gpr32 }
289 %0:gpr32common = COPY $w0
290 %3:gpr32common = ORRWri %2:gpr32, 1600
291 %4:gpr32common = ADDWri %0:gpr32common, 100, 0
292 %5:gpr32 = EORWrs %1:gpr32, %4:gpr32common, 8
293 %6:gpr32 = ADDWrr %5:gpr32, %4:gpr32common
294 %7:gpr32 = SUBWrr killed $wzr, killed %6:gpr32
295 %8:gpr32 = EORWrs killed %7:gpr32, %5:gpr32, 141
297 RET_ReallyLR implicit $w0