Skip to content

Commit 12d29cd

Browse files
author
Thorsten Schütt
committed
test overflow intrinsics
1 parent 1f6a347 commit 12d29cd

File tree

1 file changed

+242
-0
lines changed

1 file changed

+242
-0
lines changed

llvm/test/CodeGen/AArch64/overflow.ll

Lines changed: 242 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,242 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2+
; RUN: llc < %s -mtriple=arm64-eabi -verify-machineinstrs | FileCheck %s --check-prefixes=CHECK,SDAG
3+
; RUN: llc < %s -mtriple=arm64-eabi -global-isel -global-isel-abort=2 -verify-machineinstrs | FileCheck %s --check-prefixes=CHECK,GISEL
4+
5+
6+
define zeroext i1 @saddo1.i32.unused(i32 %v1, i32 %v2, ptr %res) {
7+
; CHECK-LABEL: saddo1.i32.unused:
8+
; CHECK: // %bb.0: // %entry
9+
; CHECK-NEXT: add w8, w0, w1
10+
; CHECK-NEXT: mov w0, #1 // =0x1
11+
; CHECK-NEXT: str w8, [x2]
12+
; CHECK-NEXT: ret
13+
entry:
14+
%t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %v1, i32 %v2)
15+
%obit = extractvalue {i32, i1} %t, 1
16+
%val = extractvalue {i32, i1} %t, 0
17+
store i32 %val, ptr %res
18+
ret i1 1
19+
}
20+
21+
define zeroext i1 @saddo1.i32.fold(i32 %v1, i32 %v2, ptr %res) {
22+
; SDAG-LABEL: saddo1.i32.fold:
23+
; SDAG: // %bb.0: // %entry
24+
; SDAG-NEXT: mov w8, #20 // =0x14
25+
; SDAG-NEXT: mov w0, wzr
26+
; SDAG-NEXT: str w8, [x2]
27+
; SDAG-NEXT: ret
28+
;
29+
; GISEL-LABEL: saddo1.i32.fold:
30+
; GISEL: // %bb.0: // %entry
31+
; GISEL-NEXT: mov w8, #9 // =0x9
32+
; GISEL-NEXT: adds w8, w8, #11
33+
; GISEL-NEXT: cset w0, vs
34+
; GISEL-NEXT: str w8, [x2]
35+
; GISEL-NEXT: ret
36+
entry:
37+
%t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 9, i32 11)
38+
%val = extractvalue {i32, i1} %t, 0
39+
%obit = extractvalue {i32, i1} %t, 1
40+
store i32 %val, ptr %res
41+
ret i1 %obit
42+
}
43+
44+
define zeroext i1 @saddo1.i32.addzero(i32 %v1, i32 %v2, ptr %res) {
45+
; CHECK-LABEL: saddo1.i32.addzero:
46+
; CHECK: // %bb.0: // %entry
47+
; CHECK-NEXT: mov w8, w0
48+
; CHECK-NEXT: mov w0, wzr
49+
; CHECK-NEXT: str w8, [x2]
50+
; CHECK-NEXT: ret
51+
entry:
52+
%t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %v1, i32 0)
53+
%val = extractvalue {i32, i1} %t, 0
54+
%obit = extractvalue {i32, i1} %t, 1
55+
store i32 %val, ptr %res
56+
ret i1 %obit
57+
}
58+
59+
define zeroext i1 @uaddo1.i32.addzero(i32 %v1, i32 %v2, ptr %res) {
60+
; CHECK-LABEL: uaddo1.i32.addzero:
61+
; CHECK: // %bb.0: // %entry
62+
; CHECK-NEXT: mov w8, w0
63+
; CHECK-NEXT: mov w0, wzr
64+
; CHECK-NEXT: str w8, [x2]
65+
; CHECK-NEXT: ret
66+
entry:
67+
%t = call {i32, i1} @llvm.uadd.with.overflow.i32(i32 %v1, i32 0)
68+
%val = extractvalue {i32, i1} %t, 0
69+
%obit = extractvalue {i32, i1} %t, 1
70+
store i32 %val, ptr %res
71+
ret i1 %obit
72+
}
73+
74+
define i32 @saddo.select.i64(i32 %v1, i32 %v2, i1 %v3, i64 %v4, i64 %v5) {
75+
; SDAG-LABEL: saddo.select.i64:
76+
; SDAG: // %bb.0: // %entry
77+
; SDAG-NEXT: mov w0, w1
78+
; SDAG-NEXT: ret
79+
;
80+
; GISEL-LABEL: saddo.select.i64:
81+
; GISEL: // %bb.0: // %entry
82+
; GISEL-NEXT: mov w8, #13 // =0xd
83+
; GISEL-NEXT: and x9, x3, #0xc
84+
; GISEL-NEXT: and x8, x4, x8
85+
; GISEL-NEXT: cmn x9, x8
86+
; GISEL-NEXT: cset w8, vs
87+
; GISEL-NEXT: tst w8, #0x1
88+
; GISEL-NEXT: csel w0, w0, w1, ne
89+
; GISEL-NEXT: ret
90+
entry:
91+
%lhs = and i64 %v4, 12
92+
%rhs = and i64 %v5, 13
93+
%t = call {i64, i1} @llvm.sadd.with.overflow.64(i64 %lhs, i64 %rhs)
94+
%obit = extractvalue {i64, i1} %t, 1
95+
%ret = select i1 %obit, i32 %v1, i32 %v2
96+
ret i32 %ret
97+
}
98+
99+
define i32 @uaddo.select.i64(i32 %v1, i32 %v2, i1 %v3, i64 %v4, i64 %v5) {
100+
; SDAG-LABEL: uaddo.select.i64:
101+
; SDAG: // %bb.0: // %entry
102+
; SDAG-NEXT: mov w0, w1
103+
; SDAG-NEXT: ret
104+
;
105+
; GISEL-LABEL: uaddo.select.i64:
106+
; GISEL: // %bb.0: // %entry
107+
; GISEL-NEXT: mov w8, #9 // =0x9
108+
; GISEL-NEXT: mov w9, #10 // =0xa
109+
; GISEL-NEXT: and x8, x3, x8
110+
; GISEL-NEXT: and x9, x4, x9
111+
; GISEL-NEXT: cmn x8, x9
112+
; GISEL-NEXT: cset w8, hs
113+
; GISEL-NEXT: tst w8, #0x1
114+
; GISEL-NEXT: csel w0, w0, w1, ne
115+
; GISEL-NEXT: ret
116+
entry:
117+
%lhs = and i64 %v4, 9
118+
%rhs = and i64 %v5, 10
119+
%t = call {i64, i1} @llvm.uadd.with.overflow.64(i64 %lhs, i64 %rhs)
120+
%obit = extractvalue {i64, i1} %t, 1
121+
%ret = select i1 %obit, i32 %v1, i32 %v2
122+
ret i32 %ret
123+
}
124+
125+
define zeroext i1 @saddo.canon.i32(i32 %v1, i32 %v2, i32 %v3, i32 %v4, i32 %v5, ptr %res) {
126+
; SDAG-LABEL: saddo.canon.i32:
127+
; SDAG: // %bb.0: // %entry
128+
; SDAG-NEXT: mov w0, wzr
129+
; SDAG-NEXT: str w4, [x5]
130+
; SDAG-NEXT: ret
131+
;
132+
; GISEL-LABEL: saddo.canon.i32:
133+
; GISEL: // %bb.0: // %entry
134+
; GISEL-NEXT: adds w8, wzr, w4
135+
; GISEL-NEXT: cset w0, vs
136+
; GISEL-NEXT: str w8, [x5]
137+
; GISEL-NEXT: ret
138+
entry:
139+
%t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 0, i32 %v5)
140+
%val = extractvalue {i32, i1} %t, 0
141+
%obit = extractvalue {i32, i1} %t, 1
142+
store i32 %val, ptr %res
143+
ret i1 %obit
144+
}
145+
define zeroext i1 @saddo.add.i32(i32 %v1, i32 %v2, i32 %v3, i32 %v4, i32 %v5, ptr %res) {
146+
; CHECK-LABEL: saddo.add.i32:
147+
; CHECK: // %bb.0: // %entry
148+
; CHECK-NEXT: add w8, w4, #100
149+
; CHECK-NEXT: subs w8, w8, #100
150+
; CHECK-NEXT: cset w0, vs
151+
; CHECK-NEXT: str w8, [x5]
152+
; CHECK-NEXT: ret
153+
entry:
154+
%lhs = add nsw i32 %v5, 100
155+
%t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %lhs, i32 -100)
156+
%val = extractvalue {i32, i1} %t, 0
157+
%obit = extractvalue {i32, i1} %t, 1
158+
store i32 %val, ptr %res
159+
ret i1 %obit
160+
}
161+
162+
define zeroext i1 @uaddo.add.i32(i32 %v1, i32 %v2, i32 %v3, i32 %v4, i32 %v5, ptr %res) {
163+
; CHECK-LABEL: uaddo.add.i32:
164+
; CHECK: // %bb.0: // %entry
165+
; CHECK-NEXT: add w8, w4, #5
166+
; CHECK-NEXT: adds w8, w8, #5
167+
; CHECK-NEXT: cset w0, hs
168+
; CHECK-NEXT: str w8, [x5]
169+
; CHECK-NEXT: ret
170+
entry:
171+
%lhs = add nuw i32 %v5, 5
172+
%t = call {i32, i1} @llvm.uadd.with.overflow.i32(i32 %lhs, i32 5)
173+
%val = extractvalue {i32, i1} %t, 0
174+
%obit = extractvalue {i32, i1} %t, 1
175+
store i32 %val, ptr %res
176+
ret i1 %obit
177+
}
178+
179+
define zeroext i1 @uaddo.negative.i32(i32 %v1, i32 %v2, i32 %v3, i32 %v4, i32 %v5, ptr %res) {
180+
; CHECK-LABEL: uaddo.negative.i32:
181+
; CHECK: // %bb.0: // %entry
182+
; CHECK-NEXT: adds w8, w3, #5
183+
; CHECK-NEXT: cset w0, hs
184+
; CHECK-NEXT: str w8, [x5]
185+
; CHECK-NEXT: ret
186+
entry:
187+
%t = call {i32, i1} @llvm.uadd.with.overflow.i32(i32 %v4, i32 5)
188+
%val = extractvalue {i32, i1} %t, 0
189+
%obit = extractvalue {i32, i1} %t, 1
190+
store i32 %val, ptr %res
191+
ret i1 %obit
192+
}
193+
194+
define i32 @saddo.always.i8(i32 %v1, i32 %v2, i32 %v3, i32 %v4, i32 %v5, ptr %res) {
195+
; CHECK-LABEL: saddo.always.i8:
196+
; CHECK: // %bb.0: // %entry
197+
; CHECK-NEXT: mov w0, w1
198+
; CHECK-NEXT: ret
199+
entry:
200+
%t = call {i8, i1} @llvm.sadd.with.overflow.i8(i8 255, i8 254)
201+
%obit = extractvalue {i8, i1} %t, 1
202+
%ret = select i1 %obit, i32 %v1, i32 %v2
203+
ret i32 %ret
204+
}
205+
206+
define i32 @uaddo.never.i8(i32 %v1, i32 %v2, i32 %v3, i32 %v4, i32 %v5, ptr %res) {
207+
; CHECK-LABEL: uaddo.never.i8:
208+
; CHECK: // %bb.0: // %entry
209+
; CHECK-NEXT: mov w0, w1
210+
; CHECK-NEXT: ret
211+
entry:
212+
%t = call {i8, i1} @llvm.uadd.with.overflow.i8(i8 2, i8 1)
213+
%obit = extractvalue {i8, i1} %t, 1
214+
%ret = select i1 %obit, i32 %v1, i32 %v2
215+
ret i32 %ret
216+
}
217+
218+
219+
declare {i8, i1} @llvm.sadd.with.overflow.i8(i8, i8) nounwind readnone
220+
declare {i16, i1} @llvm.sadd.with.overflow.i16(i16, i16) nounwind readnone
221+
declare {i32, i1} @llvm.sadd.with.overflow.i32(i32, i32) nounwind readnone
222+
declare {i64, i1} @llvm.sadd.with.overflow.i64(i64, i64) nounwind readnone
223+
declare {i8, i1} @llvm.uadd.with.overflow.i8(i8, i8) nounwind readnone
224+
declare {i16, i1} @llvm.uadd.with.overflow.i16(i16, i16) nounwind readnone
225+
declare {i32, i1} @llvm.uadd.with.overflow.i32(i32, i32) nounwind readnone
226+
declare {i64, i1} @llvm.uadd.with.overflow.i64(i64, i64) nounwind readnone
227+
declare {i8, i1} @llvm.ssub.with.overflow.i8(i8, i8) nounwind readnone
228+
declare {i16, i1} @llvm.ssub.with.overflow.i16(i16, i16) nounwind readnone
229+
declare {i32, i1} @llvm.ssub.with.overflow.i32(i32, i32) nounwind readnone
230+
declare {i64, i1} @llvm.ssub.with.overflow.i64(i64, i64) nounwind readnone
231+
declare {i8, i1} @llvm.usub.with.overflow.i8(i8, i8) nounwind readnone
232+
declare {i16, i1} @llvm.usub.with.overflow.i16(i16, i16) nounwind readnone
233+
declare {i32, i1} @llvm.usub.with.overflow.i32(i32, i32) nounwind readnone
234+
declare {i64, i1} @llvm.usub.with.overflow.i64(i64, i64) nounwind readnone
235+
declare {i8, i1} @llvm.smul.with.overflow.i8(i8, i8) nounwind readnone
236+
declare {i16, i1} @llvm.smul.with.overflow.i16(i16, i16) nounwind readnone
237+
declare {i32, i1} @llvm.smul.with.overflow.i32(i32, i32) nounwind readnone
238+
declare {i64, i1} @llvm.smul.with.overflow.i64(i64, i64) nounwind readnone
239+
declare {i8, i1} @llvm.umul.with.overflow.i8(i8, i8) nounwind readnone
240+
declare {i16, i1} @llvm.umul.with.overflow.i16(i16, i16) nounwind readnone
241+
declare {i32, i1} @llvm.umul.with.overflow.i32(i32, i32) nounwind readnone
242+
declare {i64, i1} @llvm.umul.with.overflow.i64(i64, i64) nounwind readnone

0 commit comments

Comments
 (0)