xref: /llvm-project/llvm/test/CodeGen/AArch64/sink-addsub-of-const.ll (revision cc82f1290a1e2157a6c0530d78d8cc84d2b8553d)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc < %s -mtriple=aarch64-unknown-unknown | FileCheck %s
3
4; Scalar tests.
5
6; add (add %x, C), %y
7; Outer 'add' is commutative - 2 variants.
8
9define i32 @sink_add_of_const_to_add0(i32 %a, i32 %b) {
10; CHECK-LABEL: sink_add_of_const_to_add0:
11; CHECK:       // %bb.0:
12; CHECK-NEXT:    add w8, w0, w1
13; CHECK-NEXT:    add w0, w8, #32
14; CHECK-NEXT:    ret
15  %t0 = add i32 %a, 32 ; constant always on RHS
16  %r = add i32 %t0, %b
17  ret i32 %r
18}
19define i32 @sink_add_of_const_to_add1(i32 %a, i32 %b) {
20; CHECK-LABEL: sink_add_of_const_to_add1:
21; CHECK:       // %bb.0:
22; CHECK-NEXT:    add w8, w0, w1
23; CHECK-NEXT:    add w0, w8, #32
24; CHECK-NEXT:    ret
25  %t0 = add i32 %a, 32 ; constant always on RHS
26  %r = add i32 %b, %t0
27  ret i32 %r
28}
29
30; add (sub %x, C), %y
31; Outer 'add' is commutative - 2 variants.
32
33define i32 @sink_sub_of_const_to_add0(i32 %a, i32 %b) {
34; CHECK-LABEL: sink_sub_of_const_to_add0:
35; CHECK:       // %bb.0:
36; CHECK-NEXT:    add w8, w0, w1
37; CHECK-NEXT:    sub w0, w8, #32
38; CHECK-NEXT:    ret
39  %t0 = sub i32 %a, 32
40  %r = add i32 %t0, %b
41  ret i32 %r
42}
43define i32 @sink_sub_of_const_to_add1(i32 %a, i32 %b) {
44; CHECK-LABEL: sink_sub_of_const_to_add1:
45; CHECK:       // %bb.0:
46; CHECK-NEXT:    add w8, w0, w1
47; CHECK-NEXT:    sub w0, w8, #32
48; CHECK-NEXT:    ret
49  %t0 = sub i32 %a, 32
50  %r = add i32 %b, %t0
51  ret i32 %r
52}
53
54; add (sub C, %x), %y
55; Outer 'add' is commutative - 2 variants.
56
57define i32 @sink_sub_from_const_to_add0(i32 %a, i32 %b) {
58; CHECK-LABEL: sink_sub_from_const_to_add0:
59; CHECK:       // %bb.0:
60; CHECK-NEXT:    sub w8, w1, w0
61; CHECK-NEXT:    add w0, w8, #32
62; CHECK-NEXT:    ret
63  %t0 = sub i32 32, %a
64  %r = add i32 %t0, %b
65  ret i32 %r
66}
67define i32 @sink_sub_from_const_to_add1(i32 %a, i32 %b) {
68; CHECK-LABEL: sink_sub_from_const_to_add1:
69; CHECK:       // %bb.0:
70; CHECK-NEXT:    sub w8, w1, w0
71; CHECK-NEXT:    add w0, w8, #32
72; CHECK-NEXT:    ret
73  %t0 = sub i32 32, %a
74  %r = add i32 %b, %t0
75  ret i32 %r
76}
77
78; sub (add %x, C), %y
79; sub %y, (add %x, C)
80
81define i32 @sink_add_of_const_to_sub(i32 %a, i32 %b) {
82; CHECK-LABEL: sink_add_of_const_to_sub:
83; CHECK:       // %bb.0:
84; CHECK-NEXT:    sub w8, w0, w1
85; CHECK-NEXT:    add w0, w8, #32
86; CHECK-NEXT:    ret
87  %t0 = add i32 %a, 32 ; constant always on RHS
88  %r = sub i32 %t0, %b
89  ret i32 %r
90}
91define i32 @sink_add_of_const_to_sub2(i32 %a, i32 %b) {
92; CHECK-LABEL: sink_add_of_const_to_sub2:
93; CHECK:       // %bb.0:
94; CHECK-NEXT:    sub w8, w1, w0
95; CHECK-NEXT:    sub w0, w8, #32
96; CHECK-NEXT:    ret
97  %t0 = add i32 %a, 32 ; constant always on RHS
98  %r = sub i32 %b, %t0
99  ret i32 %r
100}
101
102; sub (sub %x, C), %y
103; sub %y, (sub %x, C)
104
105define i32 @sink_sub_of_const_to_sub(i32 %a, i32 %b) {
106; CHECK-LABEL: sink_sub_of_const_to_sub:
107; CHECK:       // %bb.0:
108; CHECK-NEXT:    sub w8, w0, w1
109; CHECK-NEXT:    sub w0, w8, #32
110; CHECK-NEXT:    ret
111  %t0 = sub i32 %a, 32
112  %r = sub i32 %t0, %b
113  ret i32 %r
114}
115define i32 @sink_sub_of_const_to_sub2(i32 %a, i32 %b) {
116; CHECK-LABEL: sink_sub_of_const_to_sub2:
117; CHECK:       // %bb.0:
118; CHECK-NEXT:    sub w8, w1, w0
119; CHECK-NEXT:    add w0, w8, #32
120; CHECK-NEXT:    ret
121  %t0 = sub i32 %a, 32
122  %r = sub i32 %b, %t0
123  ret i32 %r
124}
125
126; sub (sub C, %x), %y
127; sub %y, (sub C, %x)
128
129define i32 @sink_sub_from_const_to_sub(i32 %a, i32 %b) {
130; CHECK-LABEL: sink_sub_from_const_to_sub:
131; CHECK:       // %bb.0:
132; CHECK-NEXT:    mov w8, #32 // =0x20
133; CHECK-NEXT:    add w9, w0, w1
134; CHECK-NEXT:    sub w0, w8, w9
135; CHECK-NEXT:    ret
136  %t0 = sub i32 32, %a
137  %r = sub i32 %t0, %b
138  ret i32 %r
139}
140define i32 @sink_sub_from_const_to_sub2(i32 %a, i32 %b) {
141; CHECK-LABEL: sink_sub_from_const_to_sub2:
142; CHECK:       // %bb.0:
143; CHECK-NEXT:    add w8, w0, w1
144; CHECK-NEXT:    sub w0, w8, #32
145; CHECK-NEXT:    ret
146  %t0 = sub i32 32, %a
147  %r = sub i32 %b, %t0
148  ret i32 %r
149}
150
151;------------------------------------------------------------------------------;
152; Basic vector tests. Here it is easier to see where the constant operand is.
153;------------------------------------------------------------------------------;
154
155; add (add %x, C), %y
156; Outer 'add' is commutative - 2 variants.
157
158define <4 x i32> @vec_sink_add_of_const_to_add0(<4 x i32> %a, <4 x i32> %b) {
159; CHECK-LABEL: vec_sink_add_of_const_to_add0:
160; CHECK:       // %bb.0:
161; CHECK-NEXT:    adrp x8, .LCPI12_0
162; CHECK-NEXT:    add v0.4s, v0.4s, v1.4s
163; CHECK-NEXT:    ldr q1, [x8, :lo12:.LCPI12_0]
164; CHECK-NEXT:    add v0.4s, v0.4s, v1.4s
165; CHECK-NEXT:    ret
166  %t0 = add <4 x i32> %a, <i32 42, i32 24, i32 undef, i32 46> ; constant always on RHS
167  %r = add <4 x i32> %t0, %b
168  ret <4 x i32> %r
169}
170define <4 x i32> @vec_sink_add_of_const_to_add1(<4 x i32> %a, <4 x i32> %b) {
171; CHECK-LABEL: vec_sink_add_of_const_to_add1:
172; CHECK:       // %bb.0:
173; CHECK-NEXT:    adrp x8, .LCPI13_0
174; CHECK-NEXT:    add v0.4s, v0.4s, v1.4s
175; CHECK-NEXT:    ldr q1, [x8, :lo12:.LCPI13_0]
176; CHECK-NEXT:    add v0.4s, v0.4s, v1.4s
177; CHECK-NEXT:    ret
178  %t0 = add <4 x i32> %a, <i32 42, i32 24, i32 undef, i32 46> ; constant always on RHS
179  %r = add <4 x i32> %b, %t0
180  ret <4 x i32> %r
181}
182
183; add (sub %x, C), %y
184; Outer 'add' is commutative - 2 variants.
185
186define <4 x i32> @vec_sink_sub_of_const_to_add0(<4 x i32> %a, <4 x i32> %b) {
187; CHECK-LABEL: vec_sink_sub_of_const_to_add0:
188; CHECK:       // %bb.0:
189; CHECK-NEXT:    adrp x8, .LCPI14_0
190; CHECK-NEXT:    add v0.4s, v0.4s, v1.4s
191; CHECK-NEXT:    ldr q1, [x8, :lo12:.LCPI14_0]
192; CHECK-NEXT:    sub v0.4s, v0.4s, v1.4s
193; CHECK-NEXT:    ret
194  %t0 = sub <4 x i32> %a, <i32 42, i32 24, i32 undef, i32 46>
195  %r = add <4 x i32> %t0, %b
196  ret <4 x i32> %r
197}
198define <4 x i32> @vec_sink_sub_of_const_to_add1(<4 x i32> %a, <4 x i32> %b) {
199; CHECK-LABEL: vec_sink_sub_of_const_to_add1:
200; CHECK:       // %bb.0:
201; CHECK-NEXT:    adrp x8, .LCPI15_0
202; CHECK-NEXT:    add v0.4s, v0.4s, v1.4s
203; CHECK-NEXT:    ldr q1, [x8, :lo12:.LCPI15_0]
204; CHECK-NEXT:    sub v0.4s, v0.4s, v1.4s
205; CHECK-NEXT:    ret
206  %t0 = sub <4 x i32> %a, <i32 42, i32 24, i32 undef, i32 46>
207  %r = add <4 x i32> %b, %t0
208  ret <4 x i32> %r
209}
210
211; add (sub C, %x), %y
212; Outer 'add' is commutative - 2 variants.
213
214define <4 x i32> @vec_sink_sub_from_const_to_add0(<4 x i32> %a, <4 x i32> %b) {
215; CHECK-LABEL: vec_sink_sub_from_const_to_add0:
216; CHECK:       // %bb.0:
217; CHECK-NEXT:    adrp x8, .LCPI16_0
218; CHECK-NEXT:    sub v0.4s, v1.4s, v0.4s
219; CHECK-NEXT:    ldr q1, [x8, :lo12:.LCPI16_0]
220; CHECK-NEXT:    add v0.4s, v0.4s, v1.4s
221; CHECK-NEXT:    ret
222  %t0 = sub <4 x i32> <i32 42, i32 24, i32 undef, i32 46>, %a
223  %r = add <4 x i32> %t0, %b
224  ret <4 x i32> %r
225}
226define <4 x i32> @vec_sink_sub_from_const_to_add1(<4 x i32> %a, <4 x i32> %b) {
227; CHECK-LABEL: vec_sink_sub_from_const_to_add1:
228; CHECK:       // %bb.0:
229; CHECK-NEXT:    adrp x8, .LCPI17_0
230; CHECK-NEXT:    sub v0.4s, v1.4s, v0.4s
231; CHECK-NEXT:    ldr q1, [x8, :lo12:.LCPI17_0]
232; CHECK-NEXT:    add v0.4s, v0.4s, v1.4s
233; CHECK-NEXT:    ret
234  %t0 = sub <4 x i32> <i32 42, i32 24, i32 undef, i32 46>, %a
235  %r = add <4 x i32> %b, %t0
236  ret <4 x i32> %r
237}
238
239; sub (add %x, C), %y
240; sub %y, (add %x, C)
241
242define <4 x i32> @vec_sink_add_of_const_to_sub(<4 x i32> %a, <4 x i32> %b) {
243; CHECK-LABEL: vec_sink_add_of_const_to_sub:
244; CHECK:       // %bb.0:
245; CHECK-NEXT:    adrp x8, .LCPI18_0
246; CHECK-NEXT:    sub v0.4s, v0.4s, v1.4s
247; CHECK-NEXT:    ldr q1, [x8, :lo12:.LCPI18_0]
248; CHECK-NEXT:    add v0.4s, v0.4s, v1.4s
249; CHECK-NEXT:    ret
250  %t0 = add <4 x i32> %a, <i32 42, i32 24, i32 undef, i32 46> ; constant always on RHS
251  %r = sub <4 x i32> %t0, %b
252  ret <4 x i32> %r
253}
254define <4 x i32> @vec_sink_add_of_const_to_sub2(<4 x i32> %a, <4 x i32> %b) {
255; CHECK-LABEL: vec_sink_add_of_const_to_sub2:
256; CHECK:       // %bb.0:
257; CHECK-NEXT:    adrp x8, .LCPI19_0
258; CHECK-NEXT:    sub v0.4s, v1.4s, v0.4s
259; CHECK-NEXT:    ldr q1, [x8, :lo12:.LCPI19_0]
260; CHECK-NEXT:    sub v0.4s, v0.4s, v1.4s
261; CHECK-NEXT:    ret
262  %t0 = add <4 x i32> %a, <i32 42, i32 24, i32 undef, i32 46> ; constant always on RHS
263  %r = sub <4 x i32> %b, %t0
264  ret <4 x i32> %r
265}
266
267; sub (sub %x, C), %y
268; sub %y, (sub %x, C)
269
270define <4 x i32> @vec_sink_sub_of_const_to_sub(<4 x i32> %a, <4 x i32> %b) {
271; CHECK-LABEL: vec_sink_sub_of_const_to_sub:
272; CHECK:       // %bb.0:
273; CHECK-NEXT:    adrp x8, .LCPI20_0
274; CHECK-NEXT:    sub v0.4s, v0.4s, v1.4s
275; CHECK-NEXT:    ldr q1, [x8, :lo12:.LCPI20_0]
276; CHECK-NEXT:    sub v0.4s, v0.4s, v1.4s
277; CHECK-NEXT:    ret
278  %t0 = sub <4 x i32> %a, <i32 42, i32 24, i32 undef, i32 46>
279  %r = sub <4 x i32> %t0, %b
280  ret <4 x i32> %r
281}
282define <4 x i32> @vec_sink_sub_of_const_to_sub2(<4 x i32> %a, <4 x i32> %b) {
283; CHECK-LABEL: vec_sink_sub_of_const_to_sub2:
284; CHECK:       // %bb.0:
285; CHECK-NEXT:    adrp x8, .LCPI21_0
286; CHECK-NEXT:    sub v0.4s, v1.4s, v0.4s
287; CHECK-NEXT:    ldr q1, [x8, :lo12:.LCPI21_0]
288; CHECK-NEXT:    add v0.4s, v0.4s, v1.4s
289; CHECK-NEXT:    ret
290  %t0 = sub <4 x i32> %a, <i32 42, i32 24, i32 undef, i32 46>
291  %r = sub <4 x i32> %b, %t0
292  ret <4 x i32> %r
293}
294
295; sub (sub C, %x), %y
296; sub %y, (sub C, %x)
297
298define <4 x i32> @vec_sink_sub_from_const_to_sub(<4 x i32> %a, <4 x i32> %b) {
299; CHECK-LABEL: vec_sink_sub_from_const_to_sub:
300; CHECK:       // %bb.0:
301; CHECK-NEXT:    adrp x8, .LCPI22_0
302; CHECK-NEXT:    add v0.4s, v0.4s, v1.4s
303; CHECK-NEXT:    ldr q1, [x8, :lo12:.LCPI22_0]
304; CHECK-NEXT:    sub v0.4s, v1.4s, v0.4s
305; CHECK-NEXT:    ret
306  %t0 = sub <4 x i32> <i32 42, i32 24, i32 undef, i32 46>, %a
307  %r = sub <4 x i32> %t0, %b
308  ret <4 x i32> %r
309}
310define <4 x i32> @vec_sink_sub_from_const_to_sub2(<4 x i32> %a, <4 x i32> %b) {
311; CHECK-LABEL: vec_sink_sub_from_const_to_sub2:
312; CHECK:       // %bb.0:
313; CHECK-NEXT:    adrp x8, .LCPI23_0
314; CHECK-NEXT:    add v0.4s, v0.4s, v1.4s
315; CHECK-NEXT:    ldr q1, [x8, :lo12:.LCPI23_0]
316; CHECK-NEXT:    sub v0.4s, v0.4s, v1.4s
317; CHECK-NEXT:    ret
318  %t0 = sub <4 x i32> <i32 42, i32 24, i32 undef, i32 46>, %a
319  %r = sub <4 x i32> %b, %t0
320  ret <4 x i32> %r
321}
322