xref: /llvm-project/llvm/test/CodeGen/X86/sink-addsub-of-const.ll (revision 4318b033bddc64d5654f3e368fddde859ff4d02e)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc < %s -mtriple=i686-unknown-unknown -mattr=+slow-lea,+slow-3ops-lea,+sse,+sse2   | FileCheck %s --check-prefixes=ALL,X32
3; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+slow-lea,+slow-3ops-lea,+sse,+sse2 | FileCheck %s --check-prefixes=ALL,X64
4
5; Scalar tests. Trying to avoid LEA here, so the output is actually readable..
6
7; add (add %x, C), %y
8; Outer 'add' is commutative - 2 variants.
9
10define i32 @sink_add_of_const_to_add0(i32 %a, i32 %b) {
11; X32-LABEL: sink_add_of_const_to_add0:
12; X32:       # %bb.0:
13; X32-NEXT:    movl {{[0-9]+}}(%esp), %eax
14; X32-NEXT:    movl {{[0-9]+}}(%esp), %ecx
15; X32-NEXT:    addl %ecx, %eax
16; X32-NEXT:    addl $32, %eax
17; X32-NEXT:    retl
18;
19; X64-LABEL: sink_add_of_const_to_add0:
20; X64:       # %bb.0:
21; X64-NEXT:    # kill: def $esi killed $esi def $rsi
22; X64-NEXT:    # kill: def $edi killed $edi def $rdi
23; X64-NEXT:    leal 32(%rdi,%rsi), %eax
24; X64-NEXT:    retq
25  %t0 = add i32 %a, 32 ; constant always on RHS
26  %r = add i32 %t0, %b
27  ret i32 %r
28}
29define i32 @sink_add_of_const_to_add1(i32 %a, i32 %b) {
30; X32-LABEL: sink_add_of_const_to_add1:
31; X32:       # %bb.0:
32; X32-NEXT:    movl {{[0-9]+}}(%esp), %eax
33; X32-NEXT:    movl {{[0-9]+}}(%esp), %ecx
34; X32-NEXT:    addl %ecx, %eax
35; X32-NEXT:    addl $32, %eax
36; X32-NEXT:    retl
37;
38; X64-LABEL: sink_add_of_const_to_add1:
39; X64:       # %bb.0:
40; X64-NEXT:    # kill: def $esi killed $esi def $rsi
41; X64-NEXT:    # kill: def $edi killed $edi def $rdi
42; X64-NEXT:    leal 32(%rdi,%rsi), %eax
43; X64-NEXT:    retq
44  %t0 = add i32 %a, 32 ; constant always on RHS
45  %r = add i32 %b, %t0
46  ret i32 %r
47}
48
49; add (sub %x, C), %y
50; Outer 'add' is commutative - 2 variants.
51
52define i32 @sink_sub_of_const_to_add0(i32 %a, i32 %b) {
53; X32-LABEL: sink_sub_of_const_to_add0:
54; X32:       # %bb.0:
55; X32-NEXT:    movl {{[0-9]+}}(%esp), %eax
56; X32-NEXT:    movl {{[0-9]+}}(%esp), %ecx
57; X32-NEXT:    addl %ecx, %eax
58; X32-NEXT:    addl $-32, %eax
59; X32-NEXT:    retl
60;
61; X64-LABEL: sink_sub_of_const_to_add0:
62; X64:       # %bb.0:
63; X64-NEXT:    # kill: def $esi killed $esi def $rsi
64; X64-NEXT:    # kill: def $edi killed $edi def $rdi
65; X64-NEXT:    leal -32(%rdi,%rsi), %eax
66; X64-NEXT:    retq
67  %t0 = sub i32 %a, 32
68  %r = add i32 %t0, %b
69  ret i32 %r
70}
71define i32 @sink_sub_of_const_to_add1(i32 %a, i32 %b) {
72; X32-LABEL: sink_sub_of_const_to_add1:
73; X32:       # %bb.0:
74; X32-NEXT:    movl {{[0-9]+}}(%esp), %eax
75; X32-NEXT:    movl {{[0-9]+}}(%esp), %ecx
76; X32-NEXT:    addl %ecx, %eax
77; X32-NEXT:    addl $-32, %eax
78; X32-NEXT:    retl
79;
80; X64-LABEL: sink_sub_of_const_to_add1:
81; X64:       # %bb.0:
82; X64-NEXT:    # kill: def $esi killed $esi def $rsi
83; X64-NEXT:    # kill: def $edi killed $edi def $rdi
84; X64-NEXT:    leal -32(%rdi,%rsi), %eax
85; X64-NEXT:    retq
86  %t0 = sub i32 %a, 32
87  %r = add i32 %b, %t0
88  ret i32 %r
89}
90
91; add (sub C, %x), %y
92; Outer 'add' is commutative - 2 variants.
93
94define i32 @sink_sub_from_const_to_add0(i32 %a, i32 %b) {
95; X32-LABEL: sink_sub_from_const_to_add0:
96; X32:       # %bb.0:
97; X32-NEXT:    movl {{[0-9]+}}(%esp), %eax
98; X32-NEXT:    subl {{[0-9]+}}(%esp), %eax
99; X32-NEXT:    addl $32, %eax
100; X32-NEXT:    retl
101;
102; X64-LABEL: sink_sub_from_const_to_add0:
103; X64:       # %bb.0:
104; X64-NEXT:    # kill: def $esi killed $esi def $rsi
105; X64-NEXT:    subl %edi, %esi
106; X64-NEXT:    leal 32(%rsi), %eax
107; X64-NEXT:    retq
108  %t0 = sub i32 32, %a
109  %r = add i32 %t0, %b
110  ret i32 %r
111}
112define i32 @sink_sub_from_const_to_add1(i32 %a, i32 %b) {
113; X32-LABEL: sink_sub_from_const_to_add1:
114; X32:       # %bb.0:
115; X32-NEXT:    movl {{[0-9]+}}(%esp), %eax
116; X32-NEXT:    subl {{[0-9]+}}(%esp), %eax
117; X32-NEXT:    addl $32, %eax
118; X32-NEXT:    retl
119;
120; X64-LABEL: sink_sub_from_const_to_add1:
121; X64:       # %bb.0:
122; X64-NEXT:    # kill: def $esi killed $esi def $rsi
123; X64-NEXT:    subl %edi, %esi
124; X64-NEXT:    leal 32(%rsi), %eax
125; X64-NEXT:    retq
126  %t0 = sub i32 32, %a
127  %r = add i32 %b, %t0
128  ret i32 %r
129}
130
131; sub (add %x, C), %y
132; sub %y, (add %x, C)
133
134define i32 @sink_add_of_const_to_sub(i32 %a, i32 %b) {
135; X32-LABEL: sink_add_of_const_to_sub:
136; X32:       # %bb.0:
137; X32-NEXT:    movl {{[0-9]+}}(%esp), %eax
138; X32-NEXT:    subl {{[0-9]+}}(%esp), %eax
139; X32-NEXT:    addl $32, %eax
140; X32-NEXT:    retl
141;
142; X64-LABEL: sink_add_of_const_to_sub:
143; X64:       # %bb.0:
144; X64-NEXT:    # kill: def $edi killed $edi def $rdi
145; X64-NEXT:    subl %esi, %edi
146; X64-NEXT:    leal 32(%rdi), %eax
147; X64-NEXT:    retq
148  %t0 = add i32 %a, 32 ; constant always on RHS
149  %r = sub i32 %t0, %b
150  ret i32 %r
151}
152define i32 @sink_add_of_const_to_sub2(i32 %a, i32 %b) {
153; X32-LABEL: sink_add_of_const_to_sub2:
154; X32:       # %bb.0:
155; X32-NEXT:    movl {{[0-9]+}}(%esp), %eax
156; X32-NEXT:    subl {{[0-9]+}}(%esp), %eax
157; X32-NEXT:    addl $-32, %eax
158; X32-NEXT:    retl
159;
160; X64-LABEL: sink_add_of_const_to_sub2:
161; X64:       # %bb.0:
162; X64-NEXT:    # kill: def $esi killed $esi def $rsi
163; X64-NEXT:    subl %edi, %esi
164; X64-NEXT:    leal -32(%rsi), %eax
165; X64-NEXT:    retq
166  %t0 = add i32 %a, 32 ; constant always on RHS
167  %r = sub i32 %b, %t0
168  ret i32 %r
169}
170
171; sub (sub %x, C), %y
172; sub %y, (sub %x, C)
173
174define i32 @sink_sub_of_const_to_sub(i32 %a, i32 %b) {
175; X32-LABEL: sink_sub_of_const_to_sub:
176; X32:       # %bb.0:
177; X32-NEXT:    movl {{[0-9]+}}(%esp), %eax
178; X32-NEXT:    subl {{[0-9]+}}(%esp), %eax
179; X32-NEXT:    addl $-32, %eax
180; X32-NEXT:    retl
181;
182; X64-LABEL: sink_sub_of_const_to_sub:
183; X64:       # %bb.0:
184; X64-NEXT:    # kill: def $edi killed $edi def $rdi
185; X64-NEXT:    subl %esi, %edi
186; X64-NEXT:    leal -32(%rdi), %eax
187; X64-NEXT:    retq
188  %t0 = sub i32 %a, 32
189  %r = sub i32 %t0, %b
190  ret i32 %r
191}
192define i32 @sink_sub_of_const_to_sub2(i32 %a, i32 %b) {
193; X32-LABEL: sink_sub_of_const_to_sub2:
194; X32:       # %bb.0:
195; X32-NEXT:    movl {{[0-9]+}}(%esp), %eax
196; X32-NEXT:    subl {{[0-9]+}}(%esp), %eax
197; X32-NEXT:    addl $32, %eax
198; X32-NEXT:    retl
199;
200; X64-LABEL: sink_sub_of_const_to_sub2:
201; X64:       # %bb.0:
202; X64-NEXT:    # kill: def $esi killed $esi def $rsi
203; X64-NEXT:    subl %edi, %esi
204; X64-NEXT:    leal 32(%rsi), %eax
205; X64-NEXT:    retq
206  %t0 = sub i32 %a, 32
207  %r = sub i32 %b, %t0
208  ret i32 %r
209}
210
211; sub (sub C, %x), %y
212; sub %y, (sub C, %x)
213
214define i32 @sink_sub_from_const_to_sub(i32 %a, i32 %b) {
215; X32-LABEL: sink_sub_from_const_to_sub:
216; X32:       # %bb.0:
217; X32-NEXT:    movl {{[0-9]+}}(%esp), %ecx
218; X32-NEXT:    addl {{[0-9]+}}(%esp), %ecx
219; X32-NEXT:    movl $32, %eax
220; X32-NEXT:    subl %ecx, %eax
221; X32-NEXT:    retl
222;
223; X64-LABEL: sink_sub_from_const_to_sub:
224; X64:       # %bb.0:
225; X64-NEXT:    addl %esi, %edi
226; X64-NEXT:    movl $32, %eax
227; X64-NEXT:    subl %edi, %eax
228; X64-NEXT:    retq
229  %t0 = sub i32 32, %a
230  %r = sub i32 %t0, %b
231  ret i32 %r
232}
233define i32 @sink_sub_from_const_to_sub2(i32 %a, i32 %b) {
234; X32-LABEL: sink_sub_from_const_to_sub2:
235; X32:       # %bb.0:
236; X32-NEXT:    movl {{[0-9]+}}(%esp), %eax
237; X32-NEXT:    movl {{[0-9]+}}(%esp), %ecx
238; X32-NEXT:    addl %ecx, %eax
239; X32-NEXT:    addl $-32, %eax
240; X32-NEXT:    retl
241;
242; X64-LABEL: sink_sub_from_const_to_sub2:
243; X64:       # %bb.0:
244; X64-NEXT:    # kill: def $esi killed $esi def $rsi
245; X64-NEXT:    # kill: def $edi killed $edi def $rdi
246; X64-NEXT:    leal -32(%rdi,%rsi), %eax
247; X64-NEXT:    retq
248  %t0 = sub i32 32, %a
249  %r = sub i32 %b, %t0
250  ret i32 %r
251}
252
253;------------------------------------------------------------------------------;
254; Basic vector tests. Here it is easier to see where the constant operand is.
255;------------------------------------------------------------------------------;
256
257; add (add %x, C), %y
258; Outer 'add' is commutative - 2 variants.
259
260define <4 x i32> @vec_sink_add_of_const_to_add0(<4 x i32> %a, <4 x i32> %b) {
261; X32-LABEL: vec_sink_add_of_const_to_add0:
262; X32:       # %bb.0:
263; X32-NEXT:    paddd %xmm1, %xmm0
264; X32-NEXT:    paddd {{\.?LCPI[0-9]+_[0-9]+}}, %xmm0
265; X32-NEXT:    retl
266;
267; X64-LABEL: vec_sink_add_of_const_to_add0:
268; X64:       # %bb.0:
269; X64-NEXT:    paddd %xmm1, %xmm0
270; X64-NEXT:    paddd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
271; X64-NEXT:    retq
272  %t0 = add <4 x i32> %a, <i32 42, i32 24, i32 undef, i32 46> ; constant always on RHS
273  %r = add <4 x i32> %t0, %b
274  ret <4 x i32> %r
275}
276define <4 x i32> @vec_sink_add_of_const_to_add1(<4 x i32> %a, <4 x i32> %b) {
277; X32-LABEL: vec_sink_add_of_const_to_add1:
278; X32:       # %bb.0:
279; X32-NEXT:    paddd %xmm1, %xmm0
280; X32-NEXT:    paddd {{\.?LCPI[0-9]+_[0-9]+}}, %xmm0
281; X32-NEXT:    retl
282;
283; X64-LABEL: vec_sink_add_of_const_to_add1:
284; X64:       # %bb.0:
285; X64-NEXT:    paddd %xmm1, %xmm0
286; X64-NEXT:    paddd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
287; X64-NEXT:    retq
288  %t0 = add <4 x i32> %a, <i32 42, i32 24, i32 undef, i32 46> ; constant always on RHS
289  %r = add <4 x i32> %b, %t0
290  ret <4 x i32> %r
291}
292
293; add (sub %x, C), %y
294; Outer 'add' is commutative - 2 variants.
295
296define <4 x i32> @vec_sink_sub_of_const_to_add0(<4 x i32> %a, <4 x i32> %b) {
297; X32-LABEL: vec_sink_sub_of_const_to_add0:
298; X32:       # %bb.0:
299; X32-NEXT:    paddd %xmm1, %xmm0
300; X32-NEXT:    psubd {{\.?LCPI[0-9]+_[0-9]+}}, %xmm0
301; X32-NEXT:    retl
302;
303; X64-LABEL: vec_sink_sub_of_const_to_add0:
304; X64:       # %bb.0:
305; X64-NEXT:    paddd %xmm1, %xmm0
306; X64-NEXT:    psubd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
307; X64-NEXT:    retq
308  %t0 = sub <4 x i32> %a, <i32 42, i32 24, i32 undef, i32 46>
309  %r = add <4 x i32> %t0, %b
310  ret <4 x i32> %r
311}
312define <4 x i32> @vec_sink_sub_of_const_to_add1(<4 x i32> %a, <4 x i32> %b) {
313; X32-LABEL: vec_sink_sub_of_const_to_add1:
314; X32:       # %bb.0:
315; X32-NEXT:    paddd %xmm1, %xmm0
316; X32-NEXT:    psubd {{\.?LCPI[0-9]+_[0-9]+}}, %xmm0
317; X32-NEXT:    retl
318;
319; X64-LABEL: vec_sink_sub_of_const_to_add1:
320; X64:       # %bb.0:
321; X64-NEXT:    paddd %xmm1, %xmm0
322; X64-NEXT:    psubd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
323; X64-NEXT:    retq
324  %t0 = sub <4 x i32> %a, <i32 42, i32 24, i32 undef, i32 46>
325  %r = add <4 x i32> %b, %t0
326  ret <4 x i32> %r
327}
328
329; add (sub C, %x), %y
330; Outer 'add' is commutative - 2 variants.
331
332define <4 x i32> @vec_sink_sub_from_const_to_add0(<4 x i32> %a, <4 x i32> %b) {
333; X32-LABEL: vec_sink_sub_from_const_to_add0:
334; X32:       # %bb.0:
335; X32-NEXT:    psubd %xmm0, %xmm1
336; X32-NEXT:    paddd {{\.?LCPI[0-9]+_[0-9]+}}, %xmm1
337; X32-NEXT:    movdqa %xmm1, %xmm0
338; X32-NEXT:    retl
339;
340; X64-LABEL: vec_sink_sub_from_const_to_add0:
341; X64:       # %bb.0:
342; X64-NEXT:    psubd %xmm0, %xmm1
343; X64-NEXT:    paddd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1
344; X64-NEXT:    movdqa %xmm1, %xmm0
345; X64-NEXT:    retq
346  %t0 = sub <4 x i32> <i32 42, i32 24, i32 undef, i32 46>, %a
347  %r = add <4 x i32> %t0, %b
348  ret <4 x i32> %r
349}
350define <4 x i32> @vec_sink_sub_from_const_to_add1(<4 x i32> %a, <4 x i32> %b) {
351; X32-LABEL: vec_sink_sub_from_const_to_add1:
352; X32:       # %bb.0:
353; X32-NEXT:    psubd %xmm0, %xmm1
354; X32-NEXT:    paddd {{\.?LCPI[0-9]+_[0-9]+}}, %xmm1
355; X32-NEXT:    movdqa %xmm1, %xmm0
356; X32-NEXT:    retl
357;
358; X64-LABEL: vec_sink_sub_from_const_to_add1:
359; X64:       # %bb.0:
360; X64-NEXT:    psubd %xmm0, %xmm1
361; X64-NEXT:    paddd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1
362; X64-NEXT:    movdqa %xmm1, %xmm0
363; X64-NEXT:    retq
364  %t0 = sub <4 x i32> <i32 42, i32 24, i32 undef, i32 46>, %a
365  %r = add <4 x i32> %b, %t0
366  ret <4 x i32> %r
367}
368
369; sub (add %x, C), %y
370; sub %y, (add %x, C)
371
372define <4 x i32> @vec_sink_add_of_const_to_sub(<4 x i32> %a, <4 x i32> %b) {
373; X32-LABEL: vec_sink_add_of_const_to_sub:
374; X32:       # %bb.0:
375; X32-NEXT:    psubd %xmm1, %xmm0
376; X32-NEXT:    paddd {{\.?LCPI[0-9]+_[0-9]+}}, %xmm0
377; X32-NEXT:    retl
378;
379; X64-LABEL: vec_sink_add_of_const_to_sub:
380; X64:       # %bb.0:
381; X64-NEXT:    psubd %xmm1, %xmm0
382; X64-NEXT:    paddd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
383; X64-NEXT:    retq
384  %t0 = add <4 x i32> %a, <i32 42, i32 24, i32 undef, i32 46> ; constant always on RHS
385  %r = sub <4 x i32> %t0, %b
386  ret <4 x i32> %r
387}
388define <4 x i32> @vec_sink_add_of_const_to_sub2(<4 x i32> %a, <4 x i32> %b) {
389; X32-LABEL: vec_sink_add_of_const_to_sub2:
390; X32:       # %bb.0:
391; X32-NEXT:    psubd %xmm0, %xmm1
392; X32-NEXT:    psubd {{\.?LCPI[0-9]+_[0-9]+}}, %xmm1
393; X32-NEXT:    movdqa %xmm1, %xmm0
394; X32-NEXT:    retl
395;
396; X64-LABEL: vec_sink_add_of_const_to_sub2:
397; X64:       # %bb.0:
398; X64-NEXT:    psubd %xmm0, %xmm1
399; X64-NEXT:    psubd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1
400; X64-NEXT:    movdqa %xmm1, %xmm0
401; X64-NEXT:    retq
402  %t0 = add <4 x i32> %a, <i32 42, i32 24, i32 undef, i32 46> ; constant always on RHS
403  %r = sub <4 x i32> %b, %t0
404  ret <4 x i32> %r
405}
406
407; sub (sub %x, C), %y
408; sub %y, (sub %x, C)
409
410define <4 x i32> @vec_sink_sub_of_const_to_sub(<4 x i32> %a, <4 x i32> %b) {
411; X32-LABEL: vec_sink_sub_of_const_to_sub:
412; X32:       # %bb.0:
413; X32-NEXT:    psubd %xmm1, %xmm0
414; X32-NEXT:    psubd {{\.?LCPI[0-9]+_[0-9]+}}, %xmm0
415; X32-NEXT:    retl
416;
417; X64-LABEL: vec_sink_sub_of_const_to_sub:
418; X64:       # %bb.0:
419; X64-NEXT:    psubd %xmm1, %xmm0
420; X64-NEXT:    psubd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
421; X64-NEXT:    retq
422  %t0 = sub <4 x i32> %a, <i32 42, i32 24, i32 undef, i32 46>
423  %r = sub <4 x i32> %t0, %b
424  ret <4 x i32> %r
425}
426define <4 x i32> @vec_sink_sub_of_const_to_sub2(<4 x i32> %a, <4 x i32> %b) {
427; X32-LABEL: vec_sink_sub_of_const_to_sub2:
428; X32:       # %bb.0:
429; X32-NEXT:    psubd %xmm0, %xmm1
430; X32-NEXT:    paddd {{\.?LCPI[0-9]+_[0-9]+}}, %xmm1
431; X32-NEXT:    movdqa %xmm1, %xmm0
432; X32-NEXT:    retl
433;
434; X64-LABEL: vec_sink_sub_of_const_to_sub2:
435; X64:       # %bb.0:
436; X64-NEXT:    psubd %xmm0, %xmm1
437; X64-NEXT:    paddd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1
438; X64-NEXT:    movdqa %xmm1, %xmm0
439; X64-NEXT:    retq
440  %t0 = sub <4 x i32> %a, <i32 42, i32 24, i32 undef, i32 46>
441  %r = sub <4 x i32> %b, %t0
442  ret <4 x i32> %r
443}
444
445; sub (sub C, %x), %y
446; sub %y, (sub C, %x)
447
448define <4 x i32> @vec_sink_sub_from_const_to_sub(<4 x i32> %a, <4 x i32> %b) {
449; ALL-LABEL: vec_sink_sub_from_const_to_sub:
450; ALL:       # %bb.0:
451; ALL-NEXT:    movdqa {{.*#+}} xmm2 = [42,24,u,46]
452; ALL-NEXT:    paddd %xmm1, %xmm0
453; ALL-NEXT:    psubd %xmm0, %xmm2
454; ALL-NEXT:    movdqa %xmm2, %xmm0
455; ALL-NEXT:    ret{{[l|q]}}
456  %t0 = sub <4 x i32> <i32 42, i32 24, i32 undef, i32 46>, %a
457  %r = sub <4 x i32> %t0, %b
458  ret <4 x i32> %r
459}
460define <4 x i32> @vec_sink_sub_from_const_to_sub2(<4 x i32> %a, <4 x i32> %b) {
461; X32-LABEL: vec_sink_sub_from_const_to_sub2:
462; X32:       # %bb.0:
463; X32-NEXT:    paddd %xmm1, %xmm0
464; X32-NEXT:    psubd {{\.?LCPI[0-9]+_[0-9]+}}, %xmm0
465; X32-NEXT:    retl
466;
467; X64-LABEL: vec_sink_sub_from_const_to_sub2:
468; X64:       # %bb.0:
469; X64-NEXT:    paddd %xmm1, %xmm0
470; X64-NEXT:    psubd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
471; X64-NEXT:    retq
472  %t0 = sub <4 x i32> <i32 42, i32 24, i32 undef, i32 46>, %a
473  %r = sub <4 x i32> %b, %t0
474  ret <4 x i32> %r
475}
476