[InstCombine] Signed saturation patterns
[llvm-core.git] / test / CodeGen / X86 / addcarry2.ll
blob2fef838e57cfc391d432391f0af6a93e9424f389
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=X32
3 ; RUN: llc < %s -mtriple=x86_64-unknown       --show-mc-encoding | FileCheck %s --check-prefix=X64
5 define void @adc_load_store_64_15(i64* inreg %x, i64* inreg %x2, i64 inreg %y) nounwind {
6 ; X32-LABEL: adc_load_store_64_15:
7 ; X32:       # %bb.0:
8 ; X32-NEXT:    pushl %esi # encoding: [0x56]
9 ; X32-NEXT:    movl {{[0-9]+}}(%esp), %esi # encoding: [0x8b,0x74,0x24,0x08]
10 ; X32-NEXT:    addl $1, %ecx # encoding: [0x83,0xc1,0x01]
11 ; X32-NEXT:    adcl $0, %esi # encoding: [0x83,0xd6,0x00]
12 ; X32-NEXT:    adcl $15, (%eax) # encoding: [0x83,0x10,0x0f]
13 ; X32-NEXT:    adcl $0, 4(%eax) # encoding: [0x83,0x50,0x04,0x00]
14 ; X32-NEXT:    setb %al # encoding: [0x0f,0x92,0xc0]
15 ; X32-NEXT:    movzbl %al, %eax # encoding: [0x0f,0xb6,0xc0]
16 ; X32-NEXT:    movl %eax, (%edx) # encoding: [0x89,0x02]
17 ; X32-NEXT:    movl $0, 4(%edx) # encoding: [0xc7,0x42,0x04,0x00,0x00,0x00,0x00]
18 ; X32-NEXT:    popl %esi # encoding: [0x5e]
19 ; X32-NEXT:    retl # encoding: [0xc3]
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, i64* %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, i64* %x
38   %ssum2 = lshr i192 %zsum, 128
39   %val2 = trunc i192 %ssum2 to i64
40   store i64 %val2, i64* %x2
41   ret void
44 define void @adc_load_store_64_0x1000F(i64* inreg %x, i64* inreg %x2, i64 inreg %y) nounwind {
45 ; X32-LABEL: adc_load_store_64_0x1000F:
46 ; X32:       # %bb.0:
47 ; X32-NEXT:    pushl %esi # encoding: [0x56]
48 ; X32-NEXT:    movl {{[0-9]+}}(%esp), %esi # encoding: [0x8b,0x74,0x24,0x08]
49 ; X32-NEXT:    addl $1, %ecx # encoding: [0x83,0xc1,0x01]
50 ; X32-NEXT:    adcl $0, %esi # encoding: [0x83,0xd6,0x00]
51 ; X32-NEXT:    adcl $65551, (%eax) # encoding: [0x81,0x10,0x0f,0x00,0x01,0x00]
52 ; X32-NEXT:    # imm = 0x1000F
53 ; X32-NEXT:    adcl $0, 4(%eax) # encoding: [0x83,0x50,0x04,0x00]
54 ; X32-NEXT:    setb %al # encoding: [0x0f,0x92,0xc0]
55 ; X32-NEXT:    movzbl %al, %eax # encoding: [0x0f,0xb6,0xc0]
56 ; X32-NEXT:    movl %eax, (%edx) # encoding: [0x89,0x02]
57 ; X32-NEXT:    movl $0, 4(%edx) # encoding: [0xc7,0x42,0x04,0x00,0x00,0x00,0x00]
58 ; X32-NEXT:    popl %esi # encoding: [0x5e]
59 ; X32-NEXT:    retl # encoding: [0xc3]
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, i64* %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, i64* %x
79   %ssum2 = lshr i192 %zsum, 128
80   %val2 = trunc i192 %ssum2 to i64
81   store i64 %val2, i64* %x2
82   ret void
85 define void @adc_load_store_64_0x100001000F(i64* inreg %x, i64* inreg %x2, i64 inreg %y) nounwind {
86 ; X32-LABEL: adc_load_store_64_0x100001000F:
87 ; X32:       # %bb.0:
88 ; X32-NEXT:    pushl %esi # encoding: [0x56]
89 ; X32-NEXT:    movl {{[0-9]+}}(%esp), %esi # encoding: [0x8b,0x74,0x24,0x08]
90 ; X32-NEXT:    addl $1, %ecx # encoding: [0x83,0xc1,0x01]
91 ; X32-NEXT:    adcl $0, %esi # encoding: [0x83,0xd6,0x00]
92 ; X32-NEXT:    adcl $15, (%eax) # encoding: [0x83,0x10,0x0f]
93 ; X32-NEXT:    adcl $16, 4(%eax) # encoding: [0x83,0x50,0x04,0x10]
94 ; X32-NEXT:    setb %al # encoding: [0x0f,0x92,0xc0]
95 ; X32-NEXT:    movzbl %al, %eax # encoding: [0x0f,0xb6,0xc0]
96 ; X32-NEXT:    movl %eax, (%edx) # encoding: [0x89,0x02]
97 ; X32-NEXT:    movl $0, 4(%edx) # encoding: [0xc7,0x42,0x04,0x00,0x00,0x00,0x00]
98 ; X32-NEXT:    popl %esi # encoding: [0x5e]
99 ; X32-NEXT:    retl # encoding: [0xc3]
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, i64* %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, i64* %x
120   %ssum2 = lshr i192 %zsum, 128
121   %val2 = trunc i192 %ssum2 to i64
122   store i64 %val2, i64* %x2
123   ret void
126 define void @adc_load_store_32_127(i32* inreg %x, i32* inreg %x2, i32 inreg %y) nounwind {
127 ; X32-LABEL: adc_load_store_32_127:
128 ; X32:       # %bb.0:
129 ; X32-NEXT:    addl $1, %ecx # encoding: [0x83,0xc1,0x01]
130 ; X32-NEXT:    adcl $127, (%eax) # encoding: [0x83,0x10,0x7f]
131 ; X32-NEXT:    setb %al # encoding: [0x0f,0x92,0xc0]
132 ; X32-NEXT:    movzbl %al, %eax # encoding: [0x0f,0xb6,0xc0]
133 ; X32-NEXT:    movl %eax, (%edx) # encoding: [0x89,0x02]
134 ; X32-NEXT:    retl # encoding: [0xc3]
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, i32* %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, i32* %x
160   %ssum2 = lshr i96 %zsum, 64
161   %val2 = trunc i96 %ssum2 to i32
162   store i32 %val2, i32* %x2
163   ret void
166 define void @adc_load_store_32_128(i32* inreg %x, i32* inreg %x2, i32 inreg %y) nounwind {
167 ; X32-LABEL: adc_load_store_32_128:
168 ; X32:       # %bb.0:
169 ; X32-NEXT:    addl $1, %ecx # encoding: [0x83,0xc1,0x01]
170 ; X32-NEXT:    adcl $128, (%eax) # encoding: [0x81,0x10,0x80,0x00,0x00,0x00]
171 ; X32-NEXT:    setb %al # encoding: [0x0f,0x92,0xc0]
172 ; X32-NEXT:    movzbl %al, %eax # encoding: [0x0f,0xb6,0xc0]
173 ; X32-NEXT:    movl %eax, (%edx) # encoding: [0x89,0x02]
174 ; X32-NEXT:    retl # encoding: [0xc3]
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, i32* %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, i32* %x
200   %ssum2 = lshr i96 %zsum, 64
201   %val2 = trunc i96 %ssum2 to i32
202   store i32 %val2, i32* %x2
203   ret void
206 ; These tests all verify the load-op-store fusion does not generate
207 ; larger instructions than mainline DAG Instruction selection.
209 define void @adc_load_store_8_15(i64 inreg %ca, i64 inreg %cb, i8* inreg %x) nounwind {
210 ; X32-LABEL: adc_load_store_8_15:
211 ; X32:       # %bb.0:
212 ; X32-NEXT:    pushl %esi # encoding: [0x56]
213 ; X32-NEXT:    movl {{[0-9]+}}(%esp), %esi # encoding: [0x8b,0x74,0x24,0x0c]
214 ; X32-NEXT:    addl %ecx, %eax # encoding: [0x01,0xc8]
215 ; X32-NEXT:    adcl {{[0-9]+}}(%esp), %edx # encoding: [0x13,0x54,0x24,0x08]
216 ; X32-NEXT:    adcb $15, (%esi) # encoding: [0x80,0x16,0x0f]
217 ; X32-NEXT:    popl %esi # encoding: [0x5e]
218 ; X32-NEXT:    retl # encoding: [0xc3]
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, i8* %x
232   %cc_off = add i8 15, %cc
233   %vsum = add i8 %vx, %cc_off
234   store i8 %vsum, i8* %x
235   ret void
238 define void @adc_load_store_16_15(i64 inreg %ca, i64 inreg %cb, i16* inreg %x) nounwind {
239 ; X32-LABEL: adc_load_store_16_15:
240 ; X32:       # %bb.0:
241 ; X32-NEXT:    pushl %esi # encoding: [0x56]
242 ; X32-NEXT:    movl {{[0-9]+}}(%esp), %esi # encoding: [0x8b,0x74,0x24,0x0c]
243 ; X32-NEXT:    addl %ecx, %eax # encoding: [0x01,0xc8]
244 ; X32-NEXT:    adcl {{[0-9]+}}(%esp), %edx # encoding: [0x13,0x54,0x24,0x08]
245 ; X32-NEXT:    adcw $15, (%esi) # encoding: [0x66,0x83,0x16,0x0f]
246 ; X32-NEXT:    popl %esi # encoding: [0x5e]
247 ; X32-NEXT:    retl # encoding: [0xc3]
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, i16* %x
261   %cc_off = add i16 15, %cc
262   %vsum = add i16 %vx, %cc_off
263   store i16 %vsum, i16* %x
264   ret void
267 define void @adc_load_store_16_256(i64 inreg %ca, i64 inreg %cb, i16* inreg %x) nounwind {
268 ; X32-LABEL: adc_load_store_16_256:
269 ; X32:       # %bb.0:
270 ; X32-NEXT:    pushl %esi # encoding: [0x56]
271 ; X32-NEXT:    movl {{[0-9]+}}(%esp), %esi # encoding: [0x8b,0x74,0x24,0x0c]
272 ; X32-NEXT:    addl %ecx, %eax # encoding: [0x01,0xc8]
273 ; X32-NEXT:    adcl {{[0-9]+}}(%esp), %edx # encoding: [0x13,0x54,0x24,0x08]
274 ; X32-NEXT:    adcw $256, (%esi) # encoding: [0x66,0x81,0x16,0x00,0x01]
275 ; X32-NEXT:    # imm = 0x100
276 ; X32-NEXT:    popl %esi # encoding: [0x5e]
277 ; X32-NEXT:    retl # encoding: [0xc3]
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, i16* %x
292   %cc_off = add i16 256, %cc
293   %vsum = add i16 %vx, %cc_off
294   store i16 %vsum, i16* %x
295   ret void