xref: /llvm-project/llvm/test/CodeGen/X86/addcarry2.ll (revision 2f448bf509432c1a19ec46ab8cbc7353c03c6280)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc < %s -mtriple=i686-unknown-unknown --show-mc-encoding | FileCheck %s --check-prefix=X86
3; RUN: llc < %s -mtriple=x86_64-unknown       --show-mc-encoding | FileCheck %s --check-prefix=X64
4
5define void @adc_load_store_64_15(ptr inreg %x, ptr inreg %x2, i64 inreg %y) nounwind {
6; X86-LABEL: adc_load_store_64_15:
7; X86:       # %bb.0:
8; X86-NEXT:    pushl %esi # encoding: [0x56]
9; X86-NEXT:    movl {{[0-9]+}}(%esp), %esi # encoding: [0x8b,0x74,0x24,0x08]
10; X86-NEXT:    addl $1, %ecx # encoding: [0x83,0xc1,0x01]
11; X86-NEXT:    adcl $0, %esi # encoding: [0x83,0xd6,0x00]
12; X86-NEXT:    adcl $15, (%eax) # encoding: [0x83,0x10,0x0f]
13; X86-NEXT:    adcl $0, 4(%eax) # encoding: [0x83,0x50,0x04,0x00]
14; X86-NEXT:    setb %al # encoding: [0x0f,0x92,0xc0]
15; X86-NEXT:    movzbl %al, %eax # encoding: [0x0f,0xb6,0xc0]
16; X86-NEXT:    movl %eax, (%edx) # encoding: [0x89,0x02]
17; X86-NEXT:    movl $0, 4(%edx) # encoding: [0xc7,0x42,0x04,0x00,0x00,0x00,0x00]
18; X86-NEXT:    popl %esi # encoding: [0x5e]
19; X86-NEXT:    retl # encoding: [0xc3]
20;
21; X64-LABEL: adc_load_store_64_15:
22; X64:       # %bb.0:
23; X64-NEXT:    addq $1, %rdx # encoding: [0x48,0x83,0xc2,0x01]
24; X64-NEXT:    adcq $15, (%rdi) # encoding: [0x48,0x83,0x17,0x0f]
25; X64-NEXT:    setb %al # encoding: [0x0f,0x92,0xc0]
26; X64-NEXT:    movzbl %al, %eax # encoding: [0x0f,0xb6,0xc0]
27; X64-NEXT:    movq %rax, (%rsi) # encoding: [0x48,0x89,0x06]
28; X64-NEXT:    retq # encoding: [0xc3]
29  %vx   = load i64, ptr %x
30  %zvx  = zext i64 %vx to i192
31  %szvx = shl i192 %zvx, 64
32  %zy   = zext i64 %y to i192
33  %op   = or i192 %szvx, %zy
34  %zsum = add i192 %op, 276701161105643274241 ; 0x0000_0000_0000_0000__0000_0000_0000_000F__0000_0000_0000_0001
35  %ssum = lshr i192 %zsum, 64
36  %val = trunc i192 %ssum to i64
37  store i64 %val, ptr %x
38  %ssum2 = lshr i192 %zsum, 128
39  %val2 = trunc i192 %ssum2 to i64
40  store i64 %val2, ptr %x2
41  ret void
42}
43
44define void @adc_load_store_64_0x1000F(ptr inreg %x, ptr inreg %x2, i64 inreg %y) nounwind {
45; X86-LABEL: adc_load_store_64_0x1000F:
46; X86:       # %bb.0:
47; X86-NEXT:    pushl %esi # encoding: [0x56]
48; X86-NEXT:    movl {{[0-9]+}}(%esp), %esi # encoding: [0x8b,0x74,0x24,0x08]
49; X86-NEXT:    addl $1, %ecx # encoding: [0x83,0xc1,0x01]
50; X86-NEXT:    adcl $0, %esi # encoding: [0x83,0xd6,0x00]
51; X86-NEXT:    adcl $65551, (%eax) # encoding: [0x81,0x10,0x0f,0x00,0x01,0x00]
52; X86-NEXT:    # imm = 0x1000F
53; X86-NEXT:    adcl $0, 4(%eax) # encoding: [0x83,0x50,0x04,0x00]
54; X86-NEXT:    setb %al # encoding: [0x0f,0x92,0xc0]
55; X86-NEXT:    movzbl %al, %eax # encoding: [0x0f,0xb6,0xc0]
56; X86-NEXT:    movl %eax, (%edx) # encoding: [0x89,0x02]
57; X86-NEXT:    movl $0, 4(%edx) # encoding: [0xc7,0x42,0x04,0x00,0x00,0x00,0x00]
58; X86-NEXT:    popl %esi # encoding: [0x5e]
59; X86-NEXT:    retl # encoding: [0xc3]
60;
61; X64-LABEL: adc_load_store_64_0x1000F:
62; X64:       # %bb.0:
63; X64-NEXT:    addq $1, %rdx # encoding: [0x48,0x83,0xc2,0x01]
64; X64-NEXT:    adcq $65551, (%rdi) # encoding: [0x48,0x81,0x17,0x0f,0x00,0x01,0x00]
65; X64-NEXT:    # imm = 0x1000F
66; X64-NEXT:    setb %al # encoding: [0x0f,0x92,0xc0]
67; X64-NEXT:    movzbl %al, %eax # encoding: [0x0f,0xb6,0xc0]
68; X64-NEXT:    movq %rax, (%rsi) # encoding: [0x48,0x89,0x06]
69; X64-NEXT:    retq # encoding: [0xc3]
70  %vx   = load i64, ptr %x
71  %zvx  = zext i64 %vx to i192
72  %szvx = shl i192 %zvx, 64
73  %zy   = zext i64 %y to i192
74  %op   = or i192 %szvx, %zy
75  %zsum = add i192 %op, 1209202520775734817980417 ; 0x0000_0000_0000_0000__0000_0000_0001_000F__0000_0000_0000_0001
76  %ssum = lshr i192 %zsum, 64
77  %val = trunc i192 %ssum to i64
78  store i64 %val, ptr %x
79  %ssum2 = lshr i192 %zsum, 128
80  %val2 = trunc i192 %ssum2 to i64
81  store i64 %val2, ptr %x2
82  ret void
83}
84
85define void @adc_load_store_64_0x100001000F(ptr inreg %x, ptr inreg %x2, i64 inreg %y) nounwind {
86; X86-LABEL: adc_load_store_64_0x100001000F:
87; X86:       # %bb.0:
88; X86-NEXT:    pushl %esi # encoding: [0x56]
89; X86-NEXT:    movl {{[0-9]+}}(%esp), %esi # encoding: [0x8b,0x74,0x24,0x08]
90; X86-NEXT:    addl $1, %ecx # encoding: [0x83,0xc1,0x01]
91; X86-NEXT:    adcl $0, %esi # encoding: [0x83,0xd6,0x00]
92; X86-NEXT:    adcl $15, (%eax) # encoding: [0x83,0x10,0x0f]
93; X86-NEXT:    adcl $16, 4(%eax) # encoding: [0x83,0x50,0x04,0x10]
94; X86-NEXT:    setb %al # encoding: [0x0f,0x92,0xc0]
95; X86-NEXT:    movzbl %al, %eax # encoding: [0x0f,0xb6,0xc0]
96; X86-NEXT:    movl %eax, (%edx) # encoding: [0x89,0x02]
97; X86-NEXT:    movl $0, 4(%edx) # encoding: [0xc7,0x42,0x04,0x00,0x00,0x00,0x00]
98; X86-NEXT:    popl %esi # encoding: [0x5e]
99; X86-NEXT:    retl # encoding: [0xc3]
100;
101; X64-LABEL: adc_load_store_64_0x100001000F:
102; X64:       # %bb.0:
103; X64-NEXT:    addq $1, %rdx # encoding: [0x48,0x83,0xc2,0x01]
104; X64-NEXT:    movabsq $68719476751, %rax # encoding: [0x48,0xb8,0x0f,0x00,0x00,0x00,0x10,0x00,0x00,0x00]
105; X64-NEXT:    # imm = 0x100000000F
106; X64-NEXT:    adcq %rax, (%rdi) # encoding: [0x48,0x11,0x07]
107; X64-NEXT:    setb %al # encoding: [0x0f,0x92,0xc0]
108; X64-NEXT:    movzbl %al, %eax # encoding: [0x0f,0xb6,0xc0]
109; X64-NEXT:    movq %rax, (%rsi) # encoding: [0x48,0x89,0x06]
110; X64-NEXT:    retq # encoding: [0xc3]
111  %vx   = load i64, ptr %x
112  %zvx  = zext i64 %vx to i192
113  %szvx = shl i192 %zvx, 64
114  %zy   = zext i64 %y to i192
115  %op   = or i192 %szvx, %zy
116  %zsum = add i192 %op, 1267650600504930562602346479617 ; 0x0000_0000_0000_0000__0000_0010_0000_000F__0000_0000_0000_0001
117  %ssum = lshr i192 %zsum, 64
118  %val = trunc i192 %ssum to i64
119  store i64 %val, ptr %x
120  %ssum2 = lshr i192 %zsum, 128
121  %val2 = trunc i192 %ssum2 to i64
122  store i64 %val2, ptr %x2
123  ret void
124}
125
126define void @adc_load_store_32_127(ptr inreg %x, ptr inreg %x2, i32 inreg %y) nounwind {
127; X86-LABEL: adc_load_store_32_127:
128; X86:       # %bb.0:
129; X86-NEXT:    addl $1, %ecx # encoding: [0x83,0xc1,0x01]
130; X86-NEXT:    adcl $127, (%eax) # encoding: [0x83,0x10,0x7f]
131; X86-NEXT:    setb %al # encoding: [0x0f,0x92,0xc0]
132; X86-NEXT:    movzbl %al, %eax # encoding: [0x0f,0xb6,0xc0]
133; X86-NEXT:    movl %eax, (%edx) # encoding: [0x89,0x02]
134; X86-NEXT:    retl # encoding: [0xc3]
135;
136; X64-LABEL: adc_load_store_32_127:
137; X64:       # %bb.0:
138; X64-NEXT:    movl (%rdi), %eax # encoding: [0x8b,0x07]
139; X64-NEXT:    shlq $32, %rax # encoding: [0x48,0xc1,0xe0,0x20]
140; X64-NEXT:    movl %edx, %ecx # encoding: [0x89,0xd1]
141; X64-NEXT:    orq %rax, %rcx # encoding: [0x48,0x09,0xc1]
142; X64-NEXT:    movabsq $545460846593, %rax # encoding: [0x48,0xb8,0x01,0x00,0x00,0x00,0x7f,0x00,0x00,0x00]
143; X64-NEXT:    # imm = 0x7F00000001
144; X64-NEXT:    xorl %edx, %edx # encoding: [0x31,0xd2]
145; X64-NEXT:    addq %rcx, %rax # encoding: [0x48,0x01,0xc8]
146; X64-NEXT:    setb %dl # encoding: [0x0f,0x92,0xc2]
147; X64-NEXT:    shrq $32, %rax # encoding: [0x48,0xc1,0xe8,0x20]
148; X64-NEXT:    movl %eax, (%rdi) # encoding: [0x89,0x07]
149; X64-NEXT:    movl %edx, (%rsi) # encoding: [0x89,0x16]
150; X64-NEXT:    retq # encoding: [0xc3]
151  %vx   = load i32, ptr %x
152  %zvx  = zext i32 %vx to i96
153  %szvx = shl i96 %zvx, 32
154  %zy   = zext i32 %y to i96
155  %op   = or i96 %szvx, %zy
156  %zsum = add i96 %op, 545460846593 ; 0x0000_0000__0000_007F__0000_0001
157  %ssum = lshr i96 %zsum, 32
158  %val = trunc i96 %ssum to i32
159  store i32 %val, ptr %x
160  %ssum2 = lshr i96 %zsum, 64
161  %val2 = trunc i96 %ssum2 to i32
162  store i32 %val2, ptr %x2
163  ret void
164}
165
166define void @adc_load_store_32_128(ptr inreg %x, ptr inreg %x2, i32 inreg %y) nounwind {
167; X86-LABEL: adc_load_store_32_128:
168; X86:       # %bb.0:
169; X86-NEXT:    addl $1, %ecx # encoding: [0x83,0xc1,0x01]
170; X86-NEXT:    adcl $128, (%eax) # encoding: [0x81,0x10,0x80,0x00,0x00,0x00]
171; X86-NEXT:    setb %al # encoding: [0x0f,0x92,0xc0]
172; X86-NEXT:    movzbl %al, %eax # encoding: [0x0f,0xb6,0xc0]
173; X86-NEXT:    movl %eax, (%edx) # encoding: [0x89,0x02]
174; X86-NEXT:    retl # encoding: [0xc3]
175;
176; X64-LABEL: adc_load_store_32_128:
177; X64:       # %bb.0:
178; X64-NEXT:    movl (%rdi), %eax # encoding: [0x8b,0x07]
179; X64-NEXT:    shlq $32, %rax # encoding: [0x48,0xc1,0xe0,0x20]
180; X64-NEXT:    movl %edx, %ecx # encoding: [0x89,0xd1]
181; X64-NEXT:    orq %rax, %rcx # encoding: [0x48,0x09,0xc1]
182; X64-NEXT:    movabsq $549755813889, %rax # encoding: [0x48,0xb8,0x01,0x00,0x00,0x00,0x80,0x00,0x00,0x00]
183; X64-NEXT:    # imm = 0x8000000001
184; X64-NEXT:    xorl %edx, %edx # encoding: [0x31,0xd2]
185; X64-NEXT:    addq %rcx, %rax # encoding: [0x48,0x01,0xc8]
186; X64-NEXT:    setb %dl # encoding: [0x0f,0x92,0xc2]
187; X64-NEXT:    shrq $32, %rax # encoding: [0x48,0xc1,0xe8,0x20]
188; X64-NEXT:    movl %eax, (%rdi) # encoding: [0x89,0x07]
189; X64-NEXT:    movl %edx, (%rsi) # encoding: [0x89,0x16]
190; X64-NEXT:    retq # encoding: [0xc3]
191  %vx   = load i32, ptr %x
192  %zvx  = zext i32 %vx to i96
193  %szvx = shl i96 %zvx, 32
194  %zy   = zext i32 %y to i96
195  %op   = or i96 %szvx, %zy
196  %zsum = add i96 %op, 549755813889 ; 0x0000_0000__0000_0080__0000_0001
197  %ssum = lshr i96 %zsum, 32
198  %val = trunc i96 %ssum to i32
199  store i32 %val, ptr %x
200  %ssum2 = lshr i96 %zsum, 64
201  %val2 = trunc i96 %ssum2 to i32
202  store i32 %val2, ptr %x2
203  ret void
204}
205
206; These tests all verify the load-op-store fusion does not generate
207; larger instructions than mainline DAG Instruction selection.
208
209define void @adc_load_store_8_15(i64 inreg %ca, i64 inreg %cb, ptr inreg %x) nounwind {
210; X86-LABEL: adc_load_store_8_15:
211; X86:       # %bb.0:
212; X86-NEXT:    pushl %esi # encoding: [0x56]
213; X86-NEXT:    movl {{[0-9]+}}(%esp), %esi # encoding: [0x8b,0x74,0x24,0x0c]
214; X86-NEXT:    addl %ecx, %eax # encoding: [0x01,0xc8]
215; X86-NEXT:    adcl {{[0-9]+}}(%esp), %edx # encoding: [0x13,0x54,0x24,0x08]
216; X86-NEXT:    adcb $15, (%esi) # encoding: [0x80,0x16,0x0f]
217; X86-NEXT:    popl %esi # encoding: [0x5e]
218; X86-NEXT:    retl # encoding: [0xc3]
219;
220; X64-LABEL: adc_load_store_8_15:
221; X64:       # %bb.0:
222; X64-NEXT:    addq %rsi, %rdi # encoding: [0x48,0x01,0xf7]
223; X64-NEXT:    adcb $15, (%rdx) # encoding: [0x80,0x12,0x0f]
224; X64-NEXT:    retq # encoding: [0xc3]
225  %zca = zext i64 %ca to i65
226  %zcb = zext i64 %cb to i65
227  %zc = add i65 %zca, %zcb
228  %ec = lshr i65 %zc, 64
229  %c = trunc i65 %ec to i1
230  %cc = zext i1 %c to i8
231  %vx = load i8, ptr %x
232  %cc_off = add i8 15, %cc
233  %vsum = add i8 %vx, %cc_off
234  store i8 %vsum, ptr %x
235  ret void
236}
237
238define void @adc_load_store_16_15(i64 inreg %ca, i64 inreg %cb, ptr inreg %x) nounwind {
239; X86-LABEL: adc_load_store_16_15:
240; X86:       # %bb.0:
241; X86-NEXT:    pushl %esi # encoding: [0x56]
242; X86-NEXT:    movl {{[0-9]+}}(%esp), %esi # encoding: [0x8b,0x74,0x24,0x0c]
243; X86-NEXT:    addl %ecx, %eax # encoding: [0x01,0xc8]
244; X86-NEXT:    adcl {{[0-9]+}}(%esp), %edx # encoding: [0x13,0x54,0x24,0x08]
245; X86-NEXT:    adcw $15, (%esi) # encoding: [0x66,0x83,0x16,0x0f]
246; X86-NEXT:    popl %esi # encoding: [0x5e]
247; X86-NEXT:    retl # encoding: [0xc3]
248;
249; X64-LABEL: adc_load_store_16_15:
250; X64:       # %bb.0:
251; X64-NEXT:    addq %rsi, %rdi # encoding: [0x48,0x01,0xf7]
252; X64-NEXT:    adcw $15, (%rdx) # encoding: [0x66,0x83,0x12,0x0f]
253; X64-NEXT:    retq # encoding: [0xc3]
254  %zca = zext i64 %ca to i65
255  %zcb = zext i64 %cb to i65
256  %zc = add i65 %zca, %zcb
257  %ec = lshr i65 %zc, 64
258  %c = trunc i65 %ec to i1
259  %cc = zext i1 %c to i16
260  %vx = load i16, ptr %x
261  %cc_off = add i16 15, %cc
262  %vsum = add i16 %vx, %cc_off
263  store i16 %vsum, ptr %x
264  ret void
265}
266
267define void @adc_load_store_16_256(i64 inreg %ca, i64 inreg %cb, ptr inreg %x) nounwind {
268; X86-LABEL: adc_load_store_16_256:
269; X86:       # %bb.0:
270; X86-NEXT:    pushl %esi # encoding: [0x56]
271; X86-NEXT:    movl {{[0-9]+}}(%esp), %esi # encoding: [0x8b,0x74,0x24,0x0c]
272; X86-NEXT:    addl %ecx, %eax # encoding: [0x01,0xc8]
273; X86-NEXT:    adcl {{[0-9]+}}(%esp), %edx # encoding: [0x13,0x54,0x24,0x08]
274; X86-NEXT:    adcw $256, (%esi) # encoding: [0x66,0x81,0x16,0x00,0x01]
275; X86-NEXT:    # imm = 0x100
276; X86-NEXT:    popl %esi # encoding: [0x5e]
277; X86-NEXT:    retl # encoding: [0xc3]
278;
279; X64-LABEL: adc_load_store_16_256:
280; X64:       # %bb.0:
281; X64-NEXT:    addq %rsi, %rdi # encoding: [0x48,0x01,0xf7]
282; X64-NEXT:    adcw $256, (%rdx) # encoding: [0x66,0x81,0x12,0x00,0x01]
283; X64-NEXT:    # imm = 0x100
284; X64-NEXT:    retq # encoding: [0xc3]
285  %zca = zext i64 %ca to i65
286  %zcb = zext i64 %cb to i65
287  %zc = add i65 %zca, %zcb
288  %ec = lshr i65 %zc, 64
289  %c = trunc i65 %ec to i1
290  %cc = zext i1 %c to i16
291  %vx = load i16, ptr %x
292  %cc_off = add i16 256, %cc
293  %vsum = add i16 %vx, %cc_off
294  store i16 %vsum, ptr %x
295  ret void
296}
297