1 ; RUN: llc -mtriple=x86_64-unknown-unknown < %s | FileCheck %s -check-prefix=DAG
2 ; RUN: llc -mtriple=x86_64-unknown-unknown -fast-isel -fast-isel-abort < %s | FileCheck %s --check-prefix=FAST
5 ; Get the actual value of the overflow bit.
8 define zeroext i1 @saddo.i8(i8 signext %v1, i8 signext %v2, i8* %res) {
11 ; DAG: addb %sil, %dil
13 ; FAST-LABEL: saddo.i8
14 ; FAST: addb %sil, %dil
16 %t = call {i8, i1} @llvm.sadd.with.overflow.i8(i8 %v1, i8 %v2)
17 %val = extractvalue {i8, i1} %t, 0
18 %obit = extractvalue {i8, i1} %t, 1
19 store i8 %val, i8* %res
23 define zeroext i1 @saddo.i16(i16 %v1, i16 %v2, i16* %res) {
25 ; DAG-LABEL: saddo.i16
28 ; FAST-LABEL: saddo.i16
31 %t = call {i16, i1} @llvm.sadd.with.overflow.i16(i16 %v1, i16 %v2)
32 %val = extractvalue {i16, i1} %t, 0
33 %obit = extractvalue {i16, i1} %t, 1
34 store i16 %val, i16* %res
38 define zeroext i1 @saddo.i32(i32 %v1, i32 %v2, i32* %res) {
40 ; DAG-LABEL: saddo.i32
41 ; DAG: addl %esi, %edi
43 ; FAST-LABEL: saddo.i32
44 ; FAST: addl %esi, %edi
46 %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %v1, i32 %v2)
47 %val = extractvalue {i32, i1} %t, 0
48 %obit = extractvalue {i32, i1} %t, 1
49 store i32 %val, i32* %res
53 define zeroext i1 @saddo.i64(i64 %v1, i64 %v2, i64* %res) {
55 ; DAG-LABEL: saddo.i64
56 ; DAG: addq %rsi, %rdi
58 ; FAST-LABEL: saddo.i64
59 ; FAST: addq %rsi, %rdi
61 %t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %v1, i64 %v2)
62 %val = extractvalue {i64, i1} %t, 0
63 %obit = extractvalue {i64, i1} %t, 1
64 store i64 %val, i64* %res
68 ; SADDO reg, imm | imm, reg
69 ; FIXME: INC isn't supported in FastISel yet
70 define zeroext i1 @saddo.i64imm1(i64 %v1, i64* %res) {
72 ; DAG-LABEL: saddo.i64imm1
75 ; FAST-LABEL: saddo.i64imm1
78 %t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %v1, i64 1)
79 %val = extractvalue {i64, i1} %t, 0
80 %obit = extractvalue {i64, i1} %t, 1
81 store i64 %val, i64* %res
85 ; FIXME: DAG doesn't optimize immediates on the LHS.
86 define zeroext i1 @saddo.i64imm2(i64 %v1, i64* %res) {
88 ; DAG-LABEL: saddo.i64imm2
92 ; FAST-LABEL: saddo.i64imm2
95 %t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 1, i64 %v1)
96 %val = extractvalue {i64, i1} %t, 0
97 %obit = extractvalue {i64, i1} %t, 1
98 store i64 %val, i64* %res
102 ; Check boundary conditions for large immediates.
103 define zeroext i1 @saddo.i64imm3(i64 %v1, i64* %res) {
105 ; DAG-LABEL: saddo.i64imm3
106 ; DAG: addq $-2147483648, %rdi
108 ; FAST-LABEL: saddo.i64imm3
109 ; FAST: addq $-2147483648, %rdi
110 ; FAST-NEXT: seto %al
111 %t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %v1, i64 -2147483648)
112 %val = extractvalue {i64, i1} %t, 0
113 %obit = extractvalue {i64, i1} %t, 1
114 store i64 %val, i64* %res
118 define zeroext i1 @saddo.i64imm4(i64 %v1, i64* %res) {
120 ; DAG-LABEL: saddo.i64imm4
121 ; DAG: movabsq $-21474836489, %[[REG:[a-z]+]]
122 ; DAG-NEXT: addq %rdi, %[[REG]]
124 ; FAST-LABEL: saddo.i64imm4
125 ; FAST: movabsq $-21474836489, %[[REG:[a-z]+]]
126 ; FAST-NEXT: addq %rdi, %[[REG]]
128 %t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %v1, i64 -21474836489)
129 %val = extractvalue {i64, i1} %t, 0
130 %obit = extractvalue {i64, i1} %t, 1
131 store i64 %val, i64* %res
135 define zeroext i1 @saddo.i64imm5(i64 %v1, i64* %res) {
137 ; DAG-LABEL: saddo.i64imm5
138 ; DAG: addq $2147483647, %rdi
140 ; FAST-LABEL: saddo.i64imm5
141 ; FAST: addq $2147483647, %rdi
143 %t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %v1, i64 2147483647)
144 %val = extractvalue {i64, i1} %t, 0
145 %obit = extractvalue {i64, i1} %t, 1
146 store i64 %val, i64* %res
150 ; TODO: FastISel shouldn't use movabsq.
151 define zeroext i1 @saddo.i64imm6(i64 %v1, i64* %res) {
153 ; DAG-LABEL: saddo.i64imm6
154 ; DAG: movl $2147483648, %ecx
155 ; DAG: addq %rdi, %rcx
157 ; FAST-LABEL: saddo.i64imm6
158 ; FAST: movabsq $2147483648, %[[REG:[a-z]+]]
159 ; FAST: addq %rdi, %[[REG]]
161 %t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %v1, i64 2147483648)
162 %val = extractvalue {i64, i1} %t, 0
163 %obit = extractvalue {i64, i1} %t, 1
164 store i64 %val, i64* %res
169 define zeroext i1 @uaddo.i32(i32 %v1, i32 %v2, i32* %res) {
171 ; DAG-LABEL: uaddo.i32
172 ; DAG: addl %esi, %edi
174 ; FAST-LABEL: uaddo.i32
175 ; FAST: addl %esi, %edi
176 ; FAST-NEXT: setb %al
177 %t = call {i32, i1} @llvm.uadd.with.overflow.i32(i32 %v1, i32 %v2)
178 %val = extractvalue {i32, i1} %t, 0
179 %obit = extractvalue {i32, i1} %t, 1
180 store i32 %val, i32* %res
184 define zeroext i1 @uaddo.i64(i64 %v1, i64 %v2, i64* %res) {
186 ; DAG-LABEL: uaddo.i64
187 ; DAG: addq %rsi, %rdi
189 ; FAST-LABEL: uaddo.i64
190 ; FAST: addq %rsi, %rdi
191 ; FAST-NEXT: setb %al
192 %t = call {i64, i1} @llvm.uadd.with.overflow.i64(i64 %v1, i64 %v2)
193 %val = extractvalue {i64, i1} %t, 0
194 %obit = extractvalue {i64, i1} %t, 1
195 store i64 %val, i64* %res
200 define zeroext i1 @ssubo.i32(i32 %v1, i32 %v2, i32* %res) {
202 ; DAG-LABEL: ssubo.i32
203 ; DAG: subl %esi, %edi
205 ; FAST-LABEL: ssubo.i32
206 ; FAST: subl %esi, %edi
207 ; FAST-NEXT: seto %al
208 %t = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %v1, i32 %v2)
209 %val = extractvalue {i32, i1} %t, 0
210 %obit = extractvalue {i32, i1} %t, 1
211 store i32 %val, i32* %res
215 define zeroext i1 @ssubo.i64(i64 %v1, i64 %v2, i64* %res) {
217 ; DAG-LABEL: ssubo.i64
218 ; DAG: subq %rsi, %rdi
220 ; FAST-LABEL: ssubo.i64
221 ; FAST: subq %rsi, %rdi
222 ; FAST-NEXT: seto %al
223 %t = call {i64, i1} @llvm.ssub.with.overflow.i64(i64 %v1, i64 %v2)
224 %val = extractvalue {i64, i1} %t, 0
225 %obit = extractvalue {i64, i1} %t, 1
226 store i64 %val, i64* %res
231 define zeroext i1 @usubo.i32(i32 %v1, i32 %v2, i32* %res) {
233 ; DAG-LABEL: usubo.i32
234 ; DAG: subl %esi, %edi
236 ; FAST-LABEL: usubo.i32
237 ; FAST: subl %esi, %edi
238 ; FAST-NEXT: setb %al
239 %t = call {i32, i1} @llvm.usub.with.overflow.i32(i32 %v1, i32 %v2)
240 %val = extractvalue {i32, i1} %t, 0
241 %obit = extractvalue {i32, i1} %t, 1
242 store i32 %val, i32* %res
246 define zeroext i1 @usubo.i64(i64 %v1, i64 %v2, i64* %res) {
248 ; DAG-LABEL: usubo.i64
249 ; DAG: subq %rsi, %rdi
251 ; FAST-LABEL: usubo.i64
252 ; FAST: subq %rsi, %rdi
253 ; FAST-NEXT: setb %al
254 %t = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %v1, i64 %v2)
255 %val = extractvalue {i64, i1} %t, 0
256 %obit = extractvalue {i64, i1} %t, 1
257 store i64 %val, i64* %res
262 define zeroext i1 @smulo.i32(i32 %v1, i32 %v2, i32* %res) {
264 ; DAG-LABEL: smulo.i32
265 ; DAG: imull %esi, %edi
267 ; FAST-LABEL: smulo.i32
268 ; FAST: imull %esi, %edi
269 ; FAST-NEXT: seto %al
270 %t = call {i32, i1} @llvm.smul.with.overflow.i32(i32 %v1, i32 %v2)
271 %val = extractvalue {i32, i1} %t, 0
272 %obit = extractvalue {i32, i1} %t, 1
273 store i32 %val, i32* %res
277 define zeroext i1 @smulo.i64(i64 %v1, i64 %v2, i64* %res) {
279 ; DAG-LABEL: smulo.i64
280 ; DAG: imulq %rsi, %rdi
282 ; FAST-LABEL: smulo.i64
283 ; FAST: imulq %rsi, %rdi
284 ; FAST-NEXT: seto %al
285 %t = call {i64, i1} @llvm.smul.with.overflow.i64(i64 %v1, i64 %v2)
286 %val = extractvalue {i64, i1} %t, 0
287 %obit = extractvalue {i64, i1} %t, 1
288 store i64 %val, i64* %res
293 define zeroext i1 @umulo.i32(i32 %v1, i32 %v2, i32* %res) {
295 ; DAG-LABEL: umulo.i32
298 ; FAST-LABEL: umulo.i32
301 %t = call {i32, i1} @llvm.umul.with.overflow.i32(i32 %v1, i32 %v2)
302 %val = extractvalue {i32, i1} %t, 0
303 %obit = extractvalue {i32, i1} %t, 1
304 store i32 %val, i32* %res
308 define zeroext i1 @umulo.i64(i64 %v1, i64 %v2, i64* %res) {
310 ; DAG-LABEL: umulo.i64
313 ; FAST-LABEL: umulo.i64
316 %t = call {i64, i1} @llvm.umul.with.overflow.i64(i64 %v1, i64 %v2)
317 %val = extractvalue {i64, i1} %t, 0
318 %obit = extractvalue {i64, i1} %t, 1
319 store i64 %val, i64* %res
323 declare {i8, i1} @llvm.sadd.with.overflow.i8(i8, i8) nounwind readnone
324 declare {i16, i1} @llvm.sadd.with.overflow.i16(i16, i16) nounwind readnone
325 declare {i32, i1} @llvm.sadd.with.overflow.i32(i32, i32) nounwind readnone
326 declare {i64, i1} @llvm.sadd.with.overflow.i64(i64, i64) nounwind readnone
327 declare {i32, i1} @llvm.uadd.with.overflow.i32(i32, i32) nounwind readnone
328 declare {i64, i1} @llvm.uadd.with.overflow.i64(i64, i64) nounwind readnone
329 declare {i32, i1} @llvm.ssub.with.overflow.i32(i32, i32) nounwind readnone
330 declare {i64, i1} @llvm.ssub.with.overflow.i64(i64, i64) nounwind readnone
331 declare {i32, i1} @llvm.usub.with.overflow.i32(i32, i32) nounwind readnone
332 declare {i64, i1} @llvm.usub.with.overflow.i64(i64, i64) nounwind readnone
333 declare {i32, i1} @llvm.smul.with.overflow.i32(i32, i32) nounwind readnone
334 declare {i64, i1} @llvm.smul.with.overflow.i64(i64, i64) nounwind readnone
335 declare {i32, i1} @llvm.umul.with.overflow.i32(i32, i32) nounwind readnone
336 declare {i64, i1} @llvm.umul.with.overflow.i64(i64, i64) nounwind readnone