1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -passes=poison-checking -S -poison-checking-function-local < %s | FileCheck %s
3
4; This file contains tests to exercise the custom flag validation rules
5
6define i32 @add_noflags(i32 %a, i32 %b) {
7; CHECK-LABEL: @add_noflags(
8; CHECK-NEXT:    [[RES:%.*]] = add i32 [[A:%.*]], [[B:%.*]]
9; CHECK-NEXT:    ret i32 [[RES]]
10;
11  %res = add i32 %a, %b
12  ret i32 %res
13}
14
15define i32 @add_nsw(i32 %a, i32 %b) {
16; CHECK-LABEL: @add_nsw(
17; CHECK-NEXT:    [[TMP1:%.*]] = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 [[A:%.*]], i32 [[B:%.*]])
18; CHECK-NEXT:    [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1
19; CHECK-NEXT:    [[RES:%.*]] = add nsw i32 [[A]], [[B]]
20; CHECK-NEXT:    [[TMP3:%.*]] = xor i1 [[TMP2]], true
21; CHECK-NEXT:    call void @__poison_checker_assert(i1 [[TMP3]])
22; CHECK-NEXT:    ret i32 [[RES]]
23;
24  %res = add nsw i32 %a, %b
25  ret i32 %res
26}
27
28define i32 @add_nuw(i32 %a, i32 %b) {
29; CHECK-LABEL: @add_nuw(
30; CHECK-NEXT:    [[TMP1:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[A:%.*]], i32 [[B:%.*]])
31; CHECK-NEXT:    [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1
32; CHECK-NEXT:    [[RES:%.*]] = add nuw i32 [[A]], [[B]]
33; CHECK-NEXT:    [[TMP3:%.*]] = xor i1 [[TMP2]], true
34; CHECK-NEXT:    call void @__poison_checker_assert(i1 [[TMP3]])
35; CHECK-NEXT:    ret i32 [[RES]]
36;
37  %res = add nuw i32 %a, %b
38  ret i32 %res
39}
40
41define i32 @add_nsw_nuw(i32 %a, i32 %b) {
42; CHECK-LABEL: @add_nsw_nuw(
43; CHECK-NEXT:    [[TMP1:%.*]] = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 [[A:%.*]], i32 [[B:%.*]])
44; CHECK-NEXT:    [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1
45; CHECK-NEXT:    [[TMP3:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[A]], i32 [[B]])
46; CHECK-NEXT:    [[TMP4:%.*]] = extractvalue { i32, i1 } [[TMP3]], 1
47; CHECK-NEXT:    [[TMP5:%.*]] = or i1 [[TMP2]], [[TMP4]]
48; CHECK-NEXT:    [[RES:%.*]] = add nuw nsw i32 [[A]], [[B]]
49; CHECK-NEXT:    [[TMP6:%.*]] = xor i1 [[TMP5]], true
50; CHECK-NEXT:    call void @__poison_checker_assert(i1 [[TMP6]])
51; CHECK-NEXT:    ret i32 [[RES]]
52;
53  %res = add nsw nuw i32 %a, %b
54  ret i32 %res
55}
56
57define i32 @sub_noflags(i32 %a, i32 %b) {
58; CHECK-LABEL: @sub_noflags(
59; CHECK-NEXT:    [[RES:%.*]] = sub i32 [[A:%.*]], [[B:%.*]]
60; CHECK-NEXT:    ret i32 [[RES]]
61;
62  %res = sub i32 %a, %b
63  ret i32 %res
64}
65
66define i32 @sub_nsw(i32 %a, i32 %b) {
67; CHECK-LABEL: @sub_nsw(
68; CHECK-NEXT:    [[TMP1:%.*]] = call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 [[A:%.*]], i32 [[B:%.*]])
69; CHECK-NEXT:    [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1
70; CHECK-NEXT:    [[RES:%.*]] = sub nsw i32 [[A]], [[B]]
71; CHECK-NEXT:    [[TMP3:%.*]] = xor i1 [[TMP2]], true
72; CHECK-NEXT:    call void @__poison_checker_assert(i1 [[TMP3]])
73; CHECK-NEXT:    ret i32 [[RES]]
74;
75  %res = sub nsw i32 %a, %b
76  ret i32 %res
77}
78
79define i32 @sub_nuw(i32 %a, i32 %b) {
80; CHECK-LABEL: @sub_nuw(
81; CHECK-NEXT:    [[TMP1:%.*]] = call { i32, i1 } @llvm.usub.with.overflow.i32(i32 [[A:%.*]], i32 [[B:%.*]])
82; CHECK-NEXT:    [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1
83; CHECK-NEXT:    [[RES:%.*]] = sub nuw i32 [[A]], [[B]]
84; CHECK-NEXT:    [[TMP3:%.*]] = xor i1 [[TMP2]], true
85; CHECK-NEXT:    call void @__poison_checker_assert(i1 [[TMP3]])
86; CHECK-NEXT:    ret i32 [[RES]]
87;
88  %res = sub nuw i32 %a, %b
89  ret i32 %res
90}
91
92define i32 @sub_nsw_nuw(i32 %a, i32 %b) {
93; CHECK-LABEL: @sub_nsw_nuw(
94; CHECK-NEXT:    [[TMP1:%.*]] = call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 [[A:%.*]], i32 [[B:%.*]])
95; CHECK-NEXT:    [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1
96; CHECK-NEXT:    [[TMP3:%.*]] = call { i32, i1 } @llvm.usub.with.overflow.i32(i32 [[A]], i32 [[B]])
97; CHECK-NEXT:    [[TMP4:%.*]] = extractvalue { i32, i1 } [[TMP3]], 1
98; CHECK-NEXT:    [[TMP5:%.*]] = or i1 [[TMP2]], [[TMP4]]
99; CHECK-NEXT:    [[RES:%.*]] = sub nuw nsw i32 [[A]], [[B]]
100; CHECK-NEXT:    [[TMP6:%.*]] = xor i1 [[TMP5]], true
101; CHECK-NEXT:    call void @__poison_checker_assert(i1 [[TMP6]])
102; CHECK-NEXT:    ret i32 [[RES]]
103;
104  %res = sub nsw nuw i32 %a, %b
105  ret i32 %res
106}
107
108define i32 @mul_noflags(i32 %a, i32 %b) {
109; CHECK-LABEL: @mul_noflags(
110; CHECK-NEXT:    [[RES:%.*]] = mul i32 [[A:%.*]], [[B:%.*]]
111; CHECK-NEXT:    ret i32 [[RES]]
112;
113  %res = mul i32 %a, %b
114  ret i32 %res
115}
116
117define i32 @mul_nsw(i32 %a, i32 %b) {
118; CHECK-LABEL: @mul_nsw(
119; CHECK-NEXT:    [[TMP1:%.*]] = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 [[A:%.*]], i32 [[B:%.*]])
120; CHECK-NEXT:    [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1
121; CHECK-NEXT:    [[RES:%.*]] = mul nsw i32 [[A]], [[B]]
122; CHECK-NEXT:    [[TMP3:%.*]] = xor i1 [[TMP2]], true
123; CHECK-NEXT:    call void @__poison_checker_assert(i1 [[TMP3]])
124; CHECK-NEXT:    ret i32 [[RES]]
125;
126  %res = mul nsw i32 %a, %b
127  ret i32 %res
128}
129
130define i32 @mul_nuw(i32 %a, i32 %b) {
131; CHECK-LABEL: @mul_nuw(
132; CHECK-NEXT:    [[TMP1:%.*]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 [[A:%.*]], i32 [[B:%.*]])
133; CHECK-NEXT:    [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1
134; CHECK-NEXT:    [[RES:%.*]] = mul nuw i32 [[A]], [[B]]
135; CHECK-NEXT:    [[TMP3:%.*]] = xor i1 [[TMP2]], true
136; CHECK-NEXT:    call void @__poison_checker_assert(i1 [[TMP3]])
137; CHECK-NEXT:    ret i32 [[RES]]
138;
139  %res = mul nuw i32 %a, %b
140  ret i32 %res
141}
142
143define i32 @mul_nsw_nuw(i32 %a, i32 %b) {
144; CHECK-LABEL: @mul_nsw_nuw(
145; CHECK-NEXT:    [[TMP1:%.*]] = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 [[A:%.*]], i32 [[B:%.*]])
146; CHECK-NEXT:    [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1
147; CHECK-NEXT:    [[TMP3:%.*]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 [[A]], i32 [[B]])
148; CHECK-NEXT:    [[TMP4:%.*]] = extractvalue { i32, i1 } [[TMP3]], 1
149; CHECK-NEXT:    [[TMP5:%.*]] = or i1 [[TMP2]], [[TMP4]]
150; CHECK-NEXT:    [[RES:%.*]] = mul nuw nsw i32 [[A]], [[B]]
151; CHECK-NEXT:    [[TMP6:%.*]] = xor i1 [[TMP5]], true
152; CHECK-NEXT:    call void @__poison_checker_assert(i1 [[TMP6]])
153; CHECK-NEXT:    ret i32 [[RES]]
154;
155  %res = mul nsw nuw i32 %a, %b
156  ret i32 %res
157}
158
159define i32 @sdiv_noflags(i32 %a, i32 %b) {
160; CHECK-LABEL: @sdiv_noflags(
161; CHECK-NEXT:    [[RES:%.*]] = sdiv i32 [[A:%.*]], [[B:%.*]]
162; CHECK-NEXT:    ret i32 [[RES]]
163;
164  %res = sdiv i32 %a, %b
165  ret i32 %res
166}
167
168define i32 @sdiv_exact(i32 %a, i32 %b) {
169; CHECK-LABEL: @sdiv_exact(
170; CHECK-NEXT:    [[TMP1:%.*]] = srem i32 [[A:%.*]], [[B:%.*]]
171; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne i32 [[TMP1]], 0
172; CHECK-NEXT:    [[RES:%.*]] = sdiv exact i32 [[A]], [[B]]
173; CHECK-NEXT:    [[TMP3:%.*]] = xor i1 [[TMP2]], true
174; CHECK-NEXT:    call void @__poison_checker_assert(i1 [[TMP3]])
175; CHECK-NEXT:    ret i32 [[RES]]
176;
177  %res = sdiv exact i32 %a, %b
178  ret i32 %res
179}
180
181define i32 @udiv_noflags(i32 %a, i32 %b) {
182; CHECK-LABEL: @udiv_noflags(
183; CHECK-NEXT:    [[RES:%.*]] = udiv i32 [[A:%.*]], [[B:%.*]]
184; CHECK-NEXT:    ret i32 [[RES]]
185;
186  %res = udiv i32 %a, %b
187  ret i32 %res
188}
189
190define i32 @udiv_exact(i32 %a, i32 %b) {
191; CHECK-LABEL: @udiv_exact(
192; CHECK-NEXT:    [[TMP1:%.*]] = urem i32 [[A:%.*]], [[B:%.*]]
193; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne i32 [[TMP1]], 0
194; CHECK-NEXT:    [[RES:%.*]] = udiv exact i32 [[A]], [[B]]
195; CHECK-NEXT:    [[TMP3:%.*]] = xor i1 [[TMP2]], true
196; CHECK-NEXT:    call void @__poison_checker_assert(i1 [[TMP3]])
197; CHECK-NEXT:    ret i32 [[RES]]
198;
199  %res = udiv exact i32 %a, %b
200  ret i32 %res
201}
202
203define i32 @ashr_noflags(i32 %a, i32 %b) {
204; CHECK-LABEL: @ashr_noflags(
205; CHECK-NEXT:    [[TMP1:%.*]] = icmp uge i32 [[B:%.*]], 32
206; CHECK-NEXT:    [[RES:%.*]] = ashr i32 [[A:%.*]], [[B]]
207; CHECK-NEXT:    [[TMP2:%.*]] = xor i1 [[TMP1]], true
208; CHECK-NEXT:    call void @__poison_checker_assert(i1 [[TMP2]])
209; CHECK-NEXT:    ret i32 [[RES]]
210;
211  %res = ashr i32 %a, %b
212  ret i32 %res
213}
214
215define i32 @ashr_exact(i32 %a, i32 %b) {
216; CHECK-LABEL: @ashr_exact(
217; CHECK-NEXT:    [[TMP1:%.*]] = icmp uge i32 [[B:%.*]], 32
218; CHECK-NEXT:    [[RES:%.*]] = ashr exact i32 [[A:%.*]], [[B]]
219; CHECK-NEXT:    [[TMP2:%.*]] = xor i1 [[TMP1]], true
220; CHECK-NEXT:    call void @__poison_checker_assert(i1 [[TMP2]])
221; CHECK-NEXT:    ret i32 [[RES]]
222;
223  %res = ashr exact i32 %a, %b
224  ret i32 %res
225}
226
227define i32 @lshr_noflags(i32 %a, i32 %b) {
228; CHECK-LABEL: @lshr_noflags(
229; CHECK-NEXT:    [[TMP1:%.*]] = icmp uge i32 [[B:%.*]], 32
230; CHECK-NEXT:    [[RES:%.*]] = lshr i32 [[A:%.*]], [[B]]
231; CHECK-NEXT:    [[TMP2:%.*]] = xor i1 [[TMP1]], true
232; CHECK-NEXT:    call void @__poison_checker_assert(i1 [[TMP2]])
233; CHECK-NEXT:    ret i32 [[RES]]
234;
235  %res = lshr i32 %a, %b
236  ret i32 %res
237}
238
239define i32 @lshr_exact(i32 %a, i32 %b) {
240; CHECK-LABEL: @lshr_exact(
241; CHECK-NEXT:    [[TMP1:%.*]] = icmp uge i32 [[B:%.*]], 32
242; CHECK-NEXT:    [[RES:%.*]] = lshr exact i32 [[A:%.*]], [[B]]
243; CHECK-NEXT:    [[TMP2:%.*]] = xor i1 [[TMP1]], true
244; CHECK-NEXT:    call void @__poison_checker_assert(i1 [[TMP2]])
245; CHECK-NEXT:    ret i32 [[RES]]
246;
247  %res = lshr exact i32 %a, %b
248  ret i32 %res
249}
250
251define i32 @shl_noflags(i32 %a, i32 %b) {
252; CHECK-LABEL: @shl_noflags(
253; CHECK-NEXT:    [[TMP1:%.*]] = icmp uge i32 [[B:%.*]], 32
254; CHECK-NEXT:    [[RES:%.*]] = shl i32 [[A:%.*]], [[B]]
255; CHECK-NEXT:    [[TMP2:%.*]] = xor i1 [[TMP1]], true
256; CHECK-NEXT:    call void @__poison_checker_assert(i1 [[TMP2]])
257; CHECK-NEXT:    ret i32 [[RES]]
258;
259  %res = shl i32 %a, %b
260  ret i32 %res
261}
262
263define i32 @shl_nsw(i32 %a, i32 %b) {
264; CHECK-LABEL: @shl_nsw(
265; CHECK-NEXT:    [[TMP1:%.*]] = icmp uge i32 [[B:%.*]], 32
266; CHECK-NEXT:    [[RES:%.*]] = shl nsw i32 [[A:%.*]], [[B]]
267; CHECK-NEXT:    [[TMP2:%.*]] = xor i1 [[TMP1]], true
268; CHECK-NEXT:    call void @__poison_checker_assert(i1 [[TMP2]])
269; CHECK-NEXT:    ret i32 [[RES]]
270;
271  %res = shl nsw i32 %a, %b
272  ret i32 %res
273}
274
275define i32 @shl_nuw(i32 %a, i32 %b) {
276; CHECK-LABEL: @shl_nuw(
277; CHECK-NEXT:    [[TMP1:%.*]] = icmp uge i32 [[B:%.*]], 32
278; CHECK-NEXT:    [[RES:%.*]] = shl nuw i32 [[A:%.*]], [[B]]
279; CHECK-NEXT:    [[TMP2:%.*]] = xor i1 [[TMP1]], true
280; CHECK-NEXT:    call void @__poison_checker_assert(i1 [[TMP2]])
281; CHECK-NEXT:    ret i32 [[RES]]
282;
283  %res = shl nuw i32 %a, %b
284  ret i32 %res
285}
286
287define i32 @shl_nsw_nuw(i32 %a, i32 %b) {
288; CHECK-LABEL: @shl_nsw_nuw(
289; CHECK-NEXT:    [[TMP1:%.*]] = icmp uge i32 [[B:%.*]], 32
290; CHECK-NEXT:    [[RES:%.*]] = shl nuw nsw i32 [[A:%.*]], [[B]]
291; CHECK-NEXT:    [[TMP2:%.*]] = xor i1 [[TMP1]], true
292; CHECK-NEXT:    call void @__poison_checker_assert(i1 [[TMP2]])
293; CHECK-NEXT:    ret i32 [[RES]]
294;
295  %res = shl nsw nuw i32 %a, %b
296  ret i32 %res
297}
298
299define i32 @extractelement(<4 x i32> %v, i32 %idx) {
300; CHECK-LABEL: @extractelement(
301; CHECK-NEXT:    [[TMP1:%.*]] = icmp uge i32 [[IDX:%.*]], 4
302; CHECK-NEXT:    [[RES:%.*]] = extractelement <4 x i32> [[V:%.*]], i32 [[IDX]]
303; CHECK-NEXT:    [[TMP2:%.*]] = xor i1 [[TMP1]], true
304; CHECK-NEXT:    call void @__poison_checker_assert(i1 [[TMP2]])
305; CHECK-NEXT:    ret i32 [[RES]]
306;
307  %res = extractelement <4 x i32> %v, i32 %idx
308  ret i32 %res
309}
310
311define <4 x i32> @insertelement(<4 x i32> %v, i32 %idx, i32 %val) {
312; CHECK-LABEL: @insertelement(
313; CHECK-NEXT:    [[TMP1:%.*]] = icmp uge i32 [[IDX:%.*]], 4
314; CHECK-NEXT:    [[RES:%.*]] = insertelement <4 x i32> [[V:%.*]], i32 [[VAL:%.*]], i32 [[IDX]]
315; CHECK-NEXT:    [[TMP2:%.*]] = xor i1 [[TMP1]], true
316; CHECK-NEXT:    call void @__poison_checker_assert(i1 [[TMP2]])
317; CHECK-NEXT:    ret <4 x i32> [[RES]]
318;
319  %res = insertelement <4 x i32> %v, i32 %val, i32 %idx
320  ret <4 x i32> %res
321}
322
323