blob: 52dfe1c8792b25b7d065d643aa49deda3e9b5f3b [file] [log] [blame]
Simon Pilgrimf6d7cfe2019-01-27 14:04:45 +00001; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc < %s -mtriple=x86_64-unknown | FileCheck %s
3
4; PR31754
5;
6; #include <x86intrin.h>
7; using u64 = unsigned long long;
8;
9; template<u64 K>
10; void test(u64& alo, u64& ahi)
11; {
12; u64 blo = K;
13; u64 bhi = 0;
14; bool cf = (alo += blo) < blo;
15; _addcarry_u64(cf, ahi, bhi, &ahi);
16; }
17;
18; template void test<0ull>(u64&, u64&);
19; template void test<1ull>(u64&, u64&);
20; template void test<2ull>(u64&, u64&);
21; template void test<3ull>(u64&, u64&);
22; template void test<4ull>(u64&, u64&);
23; template void test<0x7fffffffffffffffull>(u64&, u64&);
24; template void test<0x8000000000000000ull>(u64&, u64&);
25; template void test<0x8000000000000001ull>(u64&, u64&);
26; template void test<0xffffffff80000000ull>(u64&, u64&);
27; template void test<0xfffffffffffffffdull>(u64&, u64&);
28; template void test<0xfffffffffffffffeull>(u64&, u64&);
29; template void test<0xffffffffffffffffull>(u64&, u64&);
30
31define void @test_0(i64*, i64*) {
32; CHECK-LABEL: test_0:
33; CHECK: # %bb.0:
34; CHECK-NEXT: retq
35 %3 = load i64, i64* %1, align 8
36 %4 = tail call { i8, i64 } @llvm.x86.addcarry.64(i8 0, i64 %3, i64 0)
37 %5 = extractvalue { i8, i64 } %4, 1
38 store i64 %5, i64* %1, align 8
39 ret void
40}
41
42define void @test_1(i64*, i64*) {
43; CHECK-LABEL: test_1:
44; CHECK: # %bb.0:
45; CHECK-NEXT: incq (%rdi)
46; CHECK-NEXT: sete %al
47; CHECK-NEXT: addb $-1, %al
48; CHECK-NEXT: adcq $0, (%rsi)
49; CHECK-NEXT: retq
50 %3 = load i64, i64* %0, align 8
51 %4 = add i64 %3, 1
52 store i64 %4, i64* %0, align 8
53 %5 = icmp eq i64 %4, 0
54 %6 = zext i1 %5 to i8
55 %7 = load i64, i64* %1, align 8
56 %8 = tail call { i8, i64 } @llvm.x86.addcarry.64(i8 %6, i64 %7, i64 0)
57 %9 = extractvalue { i8, i64 } %8, 1
58 store i64 %9, i64* %1, align 8
59 ret void
60}
61
62define void @test_2(i64*, i64*) {
63; CHECK-LABEL: test_2:
64; CHECK: # %bb.0:
65; CHECK-NEXT: addq $2, (%rdi)
66; CHECK-NEXT: adcq $0, (%rsi)
67; CHECK-NEXT: retq
68 %3 = load i64, i64* %0, align 8
69 %4 = add i64 %3, 2
70 store i64 %4, i64* %0, align 8
71 %5 = icmp ult i64 %4, 2
72 %6 = zext i1 %5 to i8
73 %7 = load i64, i64* %1, align 8
74 %8 = tail call { i8, i64 } @llvm.x86.addcarry.64(i8 %6, i64 %7, i64 0)
75 %9 = extractvalue { i8, i64 } %8, 1
76 store i64 %9, i64* %1, align 8
77 ret void
78}
79
80define void @test_3(i64*, i64*) {
81; CHECK-LABEL: test_3:
82; CHECK: # %bb.0:
83; CHECK-NEXT: addq $3, (%rdi)
84; CHECK-NEXT: adcq $0, (%rsi)
85; CHECK-NEXT: retq
86 %3 = load i64, i64* %0, align 8
87 %4 = add i64 %3, 3
88 store i64 %4, i64* %0, align 8
89 %5 = icmp ult i64 %4, 3
90 %6 = zext i1 %5 to i8
91 %7 = load i64, i64* %1, align 8
92 %8 = tail call { i8, i64 } @llvm.x86.addcarry.64(i8 %6, i64 %7, i64 0)
93 %9 = extractvalue { i8, i64 } %8, 1
94 store i64 %9, i64* %1, align 8
95 ret void
96}
97
98define void @test_4(i64*, i64*) {
99; CHECK-LABEL: test_4:
100; CHECK: # %bb.0:
101; CHECK-NEXT: addq $4, (%rdi)
102; CHECK-NEXT: adcq $0, (%rsi)
103; CHECK-NEXT: retq
104 %3 = load i64, i64* %0, align 8
105 %4 = add i64 %3, 4
106 store i64 %4, i64* %0, align 8
107 %5 = icmp ult i64 %4, 4
108 %6 = zext i1 %5 to i8
109 %7 = load i64, i64* %1, align 8
110 %8 = tail call { i8, i64 } @llvm.x86.addcarry.64(i8 %6, i64 %7, i64 0)
111 %9 = extractvalue { i8, i64 } %8, 1
112 store i64 %9, i64* %1, align 8
113 ret void
114}
115
116define void @test_9223372036854775807(i64*, i64*) {
117; CHECK-LABEL: test_9223372036854775807:
118; CHECK: # %bb.0:
119; CHECK-NEXT: movabsq $9223372036854775807, %rax # imm = 0x7FFFFFFFFFFFFFFF
120; CHECK-NEXT: addq %rax, (%rdi)
121; CHECK-NEXT: adcq $0, (%rsi)
122; CHECK-NEXT: retq
123 %3 = load i64, i64* %0, align 8
124 %4 = add i64 %3, 9223372036854775807
125 store i64 %4, i64* %0, align 8
126 %5 = icmp ult i64 %4, 9223372036854775807
127 %6 = zext i1 %5 to i8
128 %7 = load i64, i64* %1, align 8
129 %8 = tail call { i8, i64 } @llvm.x86.addcarry.64(i8 %6, i64 %7, i64 0)
130 %9 = extractvalue { i8, i64 } %8, 1
131 store i64 %9, i64* %1, align 8
132 ret void
133}
134
135define void @test_9223372036854775808(i64*, i64*) {
136; CHECK-LABEL: test_9223372036854775808:
137; CHECK: # %bb.0:
138; CHECK-NEXT: movq (%rdi), %rax
139; CHECK-NEXT: movabsq $-9223372036854775808, %rcx # imm = 0x8000000000000000
140; CHECK-NEXT: xorq %rax, %rcx
141; CHECK-NEXT: movq %rcx, (%rdi)
142; CHECK-NEXT: shrq $63, %rax
143; CHECK-NEXT: addb $-1, %al
144; CHECK-NEXT: adcq $0, (%rsi)
145; CHECK-NEXT: retq
146 %3 = load i64, i64* %0, align 8
147 %4 = xor i64 %3, -9223372036854775808
148 store i64 %4, i64* %0, align 8
149 %5 = lshr i64 %3, 63
150 %6 = trunc i64 %5 to i8
151 %7 = load i64, i64* %1, align 8
152 %8 = tail call { i8, i64 } @llvm.x86.addcarry.64(i8 %6, i64 %7, i64 0)
153 %9 = extractvalue { i8, i64 } %8, 1
154 store i64 %9, i64* %1, align 8
155 ret void
156}
157
158define void @test_9223372036854775809(i64*, i64*) {
159; CHECK-LABEL: test_9223372036854775809:
160; CHECK: # %bb.0:
161; CHECK-NEXT: movabsq $-9223372036854775807, %rax # imm = 0x8000000000000001
162; CHECK-NEXT: addq %rax, (%rdi)
163; CHECK-NEXT: adcq $0, (%rsi)
164; CHECK-NEXT: retq
165 %3 = load i64, i64* %0, align 8
166 %4 = add i64 %3, -9223372036854775807
167 store i64 %4, i64* %0, align 8
168 %5 = icmp ult i64 %4, -9223372036854775807
169 %6 = zext i1 %5 to i8
170 %7 = load i64, i64* %1, align 8
171 %8 = tail call { i8, i64 } @llvm.x86.addcarry.64(i8 %6, i64 %7, i64 0)
172 %9 = extractvalue { i8, i64 } %8, 1
173 store i64 %9, i64* %1, align 8
174 ret void
175}
176
177define void @test_18446744071562067968(i64*, i64*) {
178; CHECK-LABEL: test_18446744071562067968:
179; CHECK: # %bb.0:
180; CHECK-NEXT: addq $-2147483648, (%rdi) # imm = 0x80000000
181; CHECK-NEXT: adcq $0, (%rsi)
182; CHECK-NEXT: retq
183 %3 = load i64, i64* %0, align 8
184 %4 = add i64 %3, -2147483648
185 store i64 %4, i64* %0, align 8
186 %5 = icmp ult i64 %4, -2147483648
187 %6 = zext i1 %5 to i8
188 %7 = load i64, i64* %1, align 8
189 %8 = tail call { i8, i64 } @llvm.x86.addcarry.64(i8 %6, i64 %7, i64 0)
190 %9 = extractvalue { i8, i64 } %8, 1
191 store i64 %9, i64* %1, align 8
192 ret void
193}
194
195define void @test_18446744073709551613(i64*, i64*) {
196; CHECK-LABEL: test_18446744073709551613:
197; CHECK: # %bb.0:
198; CHECK-NEXT: addq $-3, (%rdi)
199; CHECK-NEXT: adcq $0, (%rsi)
200; CHECK-NEXT: retq
201 %3 = load i64, i64* %0, align 8
202 %4 = add i64 %3, -3
203 store i64 %4, i64* %0, align 8
204 %5 = icmp ult i64 %4, -3
205 %6 = zext i1 %5 to i8
206 %7 = load i64, i64* %1, align 8
207 %8 = tail call { i8, i64 } @llvm.x86.addcarry.64(i8 %6, i64 %7, i64 0)
208 %9 = extractvalue { i8, i64 } %8, 1
209 store i64 %9, i64* %1, align 8
210 ret void
211}
212
213define void @test_18446744073709551614(i64*, i64*) {
214; CHECK-LABEL: test_18446744073709551614:
215; CHECK: # %bb.0:
216; CHECK-NEXT: addq $-2, (%rdi)
217; CHECK-NEXT: adcq $0, (%rsi)
218; CHECK-NEXT: retq
219 %3 = load i64, i64* %0, align 8
220 %4 = add i64 %3, -2
221 store i64 %4, i64* %0, align 8
222 %5 = icmp ult i64 %4, -2
223 %6 = zext i1 %5 to i8
224 %7 = load i64, i64* %1, align 8
225 %8 = tail call { i8, i64 } @llvm.x86.addcarry.64(i8 %6, i64 %7, i64 0)
226 %9 = extractvalue { i8, i64 } %8, 1
227 store i64 %9, i64* %1, align 8
228 ret void
229}
230
231define void @test_18446744073709551615(i64*, i64*) {
232; CHECK-LABEL: test_18446744073709551615:
233; CHECK: # %bb.0:
234; CHECK-NEXT: movq (%rdi), %rax
235; CHECK-NEXT: leaq -1(%rax), %rcx
236; CHECK-NEXT: movq %rcx, (%rdi)
237; CHECK-NEXT: testq %rax, %rax
238; CHECK-NEXT: setne %al
239; CHECK-NEXT: addb $-1, %al
240; CHECK-NEXT: adcq $0, (%rsi)
241; CHECK-NEXT: retq
242 %3 = load i64, i64* %0, align 8
243 %4 = add i64 %3, -1
244 store i64 %4, i64* %0, align 8
245 %5 = icmp ne i64 %3, 0
246 %6 = zext i1 %5 to i8
247 %7 = load i64, i64* %1, align 8
248 %8 = tail call { i8, i64 } @llvm.x86.addcarry.64(i8 %6, i64 %7, i64 0)
249 %9 = extractvalue { i8, i64 } %8, 1
250 store i64 %9, i64* %1, align 8
251 ret void
252}
253
254declare { i8, i64 } @llvm.x86.addcarry.64(i8, i64, i64)