[FastISel][X86] Extend support for {s|u}{add|sub|mul}.with.overflow intrinsics.
[oota-llvm.git] / test / CodeGen / X86 / xaluo.ll
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
3
4 ;
5 ; Get the actual value of the overflow bit.
6 ;
7 ; SADDO reg, reg
8 define zeroext i1 @saddo.i8(i8 signext %v1, i8 signext %v2, i8* %res) {
9 entry:
10 ; DAG-LABEL:    saddo.i8
11 ; DAG:          addb %sil, %dil
12 ; DAG-NEXT:     seto %al
13 ; FAST-LABEL:   saddo.i8
14 ; FAST:         addb %sil, %dil
15 ; FAST-NEXT:    seto %al
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
20   ret i1 %obit
21 }
22
23 define zeroext i1 @saddo.i16(i16 %v1, i16 %v2, i16* %res) {
24 entry:
25 ; DAG-LABEL:    saddo.i16
26 ; DAG:          addw %si, %di
27 ; DAG-NEXT:     seto %al
28 ; FAST-LABEL:   saddo.i16
29 ; FAST:         addw %si, %di
30 ; FAST-NEXT:    seto %al
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
35   ret i1 %obit
36 }
37
38 define zeroext i1 @saddo.i32(i32 %v1, i32 %v2, i32* %res) {
39 entry:
40 ; DAG-LABEL:    saddo.i32
41 ; DAG:          addl %esi, %edi
42 ; DAG-NEXT:     seto %al
43 ; FAST-LABEL:   saddo.i32
44 ; FAST:         addl %esi, %edi
45 ; FAST-NEXT:    seto %al
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
50   ret i1 %obit
51 }
52
53 define zeroext i1 @saddo.i64(i64 %v1, i64 %v2, i64* %res) {
54 entry:
55 ; DAG-LABEL:    saddo.i64
56 ; DAG:          addq %rsi, %rdi
57 ; DAG-NEXT:     seto %al
58 ; FAST-LABEL:   saddo.i64
59 ; FAST:         addq %rsi, %rdi
60 ; FAST-NEXT:    seto %al
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
65   ret i1 %obit
66 }
67
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) {
71 entry:
72 ; DAG-LABEL:    saddo.i64imm1
73 ; DAG:          incq %rdi
74 ; DAG-NEXT:     seto %al
75 ; FAST-LABEL:   saddo.i64imm1
76 ; FAST:         addq $1, %rdi
77 ; FAST-NEXT:    seto %al
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
82   ret i1 %obit
83 }
84
85 ; FIXME: DAG doesn't optimize immediates on the LHS.
86 define zeroext i1 @saddo.i64imm2(i64 %v1, i64* %res) {
87 entry:
88 ; DAG-LABEL:    saddo.i64imm2
89 ; DAG:          mov
90 ; DAG-NEXT:     addq
91 ; DAG-NEXT:     seto
92 ; FAST-LABEL:   saddo.i64imm2
93 ; FAST:         addq $1, %rdi
94 ; FAST-NEXT:    seto %al
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
99   ret i1 %obit
100 }
101
102 ; Check boundary conditions for large immediates.
103 define zeroext i1 @saddo.i64imm3(i64 %v1, i64* %res) {
104 entry:
105 ; DAG-LABEL:    saddo.i64imm3
106 ; DAG:          addq $-2147483648, %rdi
107 ; DAG-NEXT:     seto %al
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
115   ret i1 %obit
116 }
117
118 define zeroext i1 @saddo.i64imm4(i64 %v1, i64* %res) {
119 entry:
120 ; DAG-LABEL:    saddo.i64imm4
121 ; DAG:          movabsq $-21474836489, %[[REG:[a-z]+]]
122 ; DAG-NEXT:     addq %rdi, %[[REG]]
123 ; DAG-NEXT:     seto
124 ; FAST-LABEL:   saddo.i64imm4
125 ; FAST:         movabsq $-21474836489, %[[REG:[a-z]+]]
126 ; FAST-NEXT:    addq %rdi, %[[REG]]
127 ; FAST-NEXT:    seto
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
132   ret i1 %obit
133 }
134
135 define zeroext i1 @saddo.i64imm5(i64 %v1, i64* %res) {
136 entry:
137 ; DAG-LABEL:    saddo.i64imm5
138 ; DAG:          addq $2147483647, %rdi
139 ; DAG-NEXT:     seto
140 ; FAST-LABEL:   saddo.i64imm5
141 ; FAST:         addq $2147483647, %rdi
142 ; FAST-NEXT:    seto
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
147   ret i1 %obit
148 }
149
150 ; TODO: FastISel shouldn't use movabsq.
151 define zeroext i1 @saddo.i64imm6(i64 %v1, i64* %res) {
152 entry:
153 ; DAG-LABEL:    saddo.i64imm6
154 ; DAG:          movl $2147483648, %ecx
155 ; DAG:          addq %rdi, %rcx
156 ; DAG-NEXT:     seto
157 ; FAST-LABEL:   saddo.i64imm6
158 ; FAST:         movabsq $2147483648, %[[REG:[a-z]+]]
159 ; FAST:         addq %rdi, %[[REG]]
160 ; FAST-NEXT:     seto
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
165   ret i1 %obit
166 }
167
168 ; UADDO
169 define zeroext i1 @uaddo.i32(i32 %v1, i32 %v2, i32* %res) {
170 entry:
171 ; DAG-LABEL:    uaddo.i32
172 ; DAG:          addl %esi, %edi
173 ; DAG-NEXT:     setb %al
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
181   ret i1 %obit
182 }
183
184 define zeroext i1 @uaddo.i64(i64 %v1, i64 %v2, i64* %res) {
185 entry:
186 ; DAG-LABEL:    uaddo.i64
187 ; DAG:          addq %rsi, %rdi
188 ; DAG-NEXT:     setb %al
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
196   ret i1 %obit
197 }
198
199 ; SSUBO
200 define zeroext i1 @ssubo.i32(i32 %v1, i32 %v2, i32* %res) {
201 entry:
202 ; DAG-LABEL:    ssubo.i32
203 ; DAG:          subl %esi, %edi
204 ; DAG-NEXT:     seto %al
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
212   ret i1 %obit
213 }
214
215 define zeroext i1 @ssubo.i64(i64 %v1, i64 %v2, i64* %res) {
216 entry:
217 ; DAG-LABEL:    ssubo.i64
218 ; DAG:          subq %rsi, %rdi
219 ; DAG-NEXT:     seto %al
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
227   ret i1 %obit
228 }
229
230 ; USUBO
231 define zeroext i1 @usubo.i32(i32 %v1, i32 %v2, i32* %res) {
232 entry:
233 ; DAG-LABEL:    usubo.i32
234 ; DAG:          subl %esi, %edi
235 ; DAG-NEXT:     setb %al
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
243   ret i1 %obit
244 }
245
246 define zeroext i1 @usubo.i64(i64 %v1, i64 %v2, i64* %res) {
247 entry:
248 ; DAG-LABEL:    usubo.i64
249 ; DAG:          subq %rsi, %rdi
250 ; DAG-NEXT:     setb %al
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
258   ret i1 %obit
259 }
260
261 ; SMULO
262 define zeroext i1 @smulo.i32(i32 %v1, i32 %v2, i32* %res) {
263 entry:
264 ; DAG-LABEL:    smulo.i32
265 ; DAG:          imull %esi, %edi
266 ; DAG-NEXT:     seto %al
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
274   ret i1 %obit
275 }
276
277 define zeroext i1 @smulo.i64(i64 %v1, i64 %v2, i64* %res) {
278 entry:
279 ; DAG-LABEL:    smulo.i64
280 ; DAG:          imulq %rsi, %rdi
281 ; DAG-NEXT:     seto %al
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
289   ret i1 %obit
290 }
291
292 ; UMULO
293 define zeroext i1 @umulo.i32(i32 %v1, i32 %v2, i32* %res) {
294 entry:
295 ; DAG-LABEL:    umulo.i32
296 ; DAG:          mull %esi
297 ; DAG-NEXT:     seto
298 ; FAST-LABEL:   umulo.i32
299 ; FAST:         mull %esi
300 ; FAST-NEXT:    seto
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
305   ret i1 %obit
306 }
307
308 define zeroext i1 @umulo.i64(i64 %v1, i64 %v2, i64* %res) {
309 entry:
310 ; DAG-LABEL:    umulo.i64
311 ; DAG:          mulq %rsi
312 ; DAG-NEXT:     seto
313 ; FAST-LABEL:   umulo.i64
314 ; FAST:         mulq %rsi
315 ; FAST-NEXT:    seto
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
320   ret i1 %obit
321 }
322
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
337