• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature
2; RUN: opt -ipsccp -S %s | FileCheck %s
3
4%t1 = type opaque
5
6@e = common global i32 0, align 4
7
8; Test that we a skip unknown values depending on a unknown tracked call, until the call gets resolved. The @test1 and @test2 variants are very similar, they just check 2 different kinds of users (icmp and zext)
9
10define i32 @test1_m(i32 %h) {
11; CHECK-LABEL: define {{[^@]+}}@test1_m
12; CHECK-SAME: (i32 [[H:%.*]])
13; CHECK-NEXT:  entry:
14; CHECK-NEXT:    [[CONV:%.*]] = trunc i32 [[H]] to i8
15; CHECK-NEXT:    [[CALL:%.*]] = call i32 @test1_k(i8 [[CONV]], i32 0)
16; CHECK-NEXT:    [[CONV1:%.*]] = sext i32 [[H]] to i64
17; CHECK-NEXT:    [[TMP0:%.*]] = inttoptr i64 [[CONV1]] to %t1*
18; CHECK-NEXT:    [[CALL2:%.*]] = call i1 @test1_g(%t1* [[TMP0]], i32 1)
19; CHECK-NEXT:    ret i32 undef
20;
21entry:
22  %conv = trunc i32 %h to i8
23  %call = call i32 @test1_k(i8 %conv, i32 0)
24  %conv1 = sext i32 %h to i64
25  %0 = inttoptr i64 %conv1 to %t1*
26  %call2 = call i1 @test1_g(%t1* %0, i32 1)
27  ret i32 undef
28
29; uselistorder directives
30  uselistorder i32 %h, { 1, 0 }
31}
32
33declare void @use.1(i1)
34
35define internal i32 @test1_k(i8 %h, i32 %i) {
36; CHECK-LABEL: define {{[^@]+}}@test1_k
37; CHECK-SAME: (i8 [[H:%.*]], i32 [[I:%.*]])
38; CHECK-NEXT:  entry:
39; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* @e, align 4
40; CHECK-NEXT:    [[CONV:%.*]] = sext i32 [[TMP0]] to i64
41; CHECK-NEXT:    [[TMP1:%.*]] = inttoptr i64 [[CONV]] to %t1*
42; CHECK-NEXT:    [[CALL:%.*]] = call i1 @test1_g(%t1* [[TMP1]], i32 0)
43; CHECK-NEXT:    call void @use.1(i1 false)
44; CHECK-NEXT:    ret i32 undef
45;
46entry:
47  %0 = load i32, i32* @e, align 4
48  %conv = sext i32 %0 to i64
49  %1 = inttoptr i64 %conv to %t1*
50  %call = call i1 @test1_g(%t1* %1, i32 %i)
51  %frombool.1 = zext i1 %call to i8
52  %tobool.1 = trunc i8 %frombool.1 to i1
53  call void @use.1(i1 %tobool.1)
54  ret i32 undef
55}
56
57define internal i1 @test1_g(%t1* %h, i32 %i) #0 {
58; CHECK-LABEL: define {{[^@]+}}@test1_g
59; CHECK-SAME: (%t1* [[H:%.*]], i32 [[I:%.*]])
60; CHECK-NEXT:  entry:
61; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp ne i32 [[I]], 0
62; CHECK-NEXT:    br i1 [[TOBOOL]], label [[LAND_RHS:%.*]], label [[LAND_END:%.*]]
63; CHECK:       land.rhs:
64; CHECK-NEXT:    [[CALL:%.*]] = call i32 (...) @test1_j()
65; CHECK-NEXT:    [[TOBOOL1:%.*]] = icmp ne i32 [[CALL]], 0
66; CHECK-NEXT:    br label [[LAND_END]]
67; CHECK:       land.end:
68; CHECK-NEXT:    [[TMP0:%.*]] = phi i1 [ false, [[ENTRY:%.*]] ], [ [[TOBOOL1]], [[LAND_RHS]] ]
69; CHECK-NEXT:    ret i1 undef
70;
71entry:
72  %tobool = icmp ne i32 %i, 0
73  br i1 %tobool, label %land.rhs, label %land.end
74
75land.rhs:                                         ; preds = %entry
76  %call = call i32 (...) @test1_j()
77  %tobool1 = icmp ne i32 %call, 0
78  br label %land.end
79
80land.end:                                         ; preds = %land.rhs, %entry
81  %0 = phi i1 [ false, %entry ], [ %tobool1, %land.rhs ]
82  ret i1 false
83}
84
85declare i32 @test1_j(...)
86
87define i32 @test2_m(i32 %h) #0 {
88; CHECK-LABEL: define {{[^@]+}}@test2_m
89; CHECK-SAME: (i32 [[H:%.*]])
90; CHECK-NEXT:  entry:
91; CHECK-NEXT:    [[CONV:%.*]] = trunc i32 [[H]] to i8
92; CHECK-NEXT:    [[CALL:%.*]] = call i32 @test2_k(i8 [[CONV]], i32 0)
93; CHECK-NEXT:    [[CONV1:%.*]] = sext i32 [[H]] to i64
94; CHECK-NEXT:    [[TMP0:%.*]] = inttoptr i64 [[CONV1]] to %t1*
95; CHECK-NEXT:    [[CALL2:%.*]] = call i1 @test2_g(%t1* [[TMP0]], i32 1)
96; CHECK-NEXT:    ret i32 undef
97;
98entry:
99  %conv = trunc i32 %h to i8
100  %call = call i32 @test2_k(i8 %conv, i32 0)
101  %conv1 = sext i32 %h to i64
102  %0 = inttoptr i64 %conv1 to %t1*
103  %call2 = call i1 @test2_g(%t1* %0, i32 1)
104  ret i32 undef
105
106; uselistorder directives
107  uselistorder i32 %h, { 1, 0 }
108}
109
110; TODO: We could do better for the return value of call i1 @test3_g, if we
111;       resolve the unknown values there first.
112define internal i32 @test2_k(i8 %h, i32 %i) {
113; CHECK-LABEL: define {{[^@]+}}@test2_k
114; CHECK-SAME: (i8 [[H:%.*]], i32 [[I:%.*]])
115; CHECK-NEXT:  entry:
116; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* @e, align 4
117; CHECK-NEXT:    [[CONV:%.*]] = sext i32 [[TMP0]] to i64
118; CHECK-NEXT:    [[TMP1:%.*]] = inttoptr i64 [[CONV]] to %t1*
119; CHECK-NEXT:    [[CALL:%.*]] = call i1 @test3_g(%t1* [[TMP1]], i32 0)
120; CHECK-NEXT:    call void @use.1(i1 false)
121; CHECK-NEXT:    ret i32 undef
122;
123entry:
124  %0 = load i32, i32* @e, align 4
125  %conv = sext i32 %0 to i64
126  %1 = inttoptr i64 %conv to %t1*
127  %call = call i1 @test3_g(%t1* %1, i32 %i)
128  %frombool = icmp slt i1 %call, 1
129  %add = add i1 %frombool, %frombool
130  call void @use.1(i1 %frombool)
131  ret i32 undef
132
133}
134
135define internal i1 @test2_g(%t1* %h, i32 %i) {
136; CHECK-LABEL: define {{[^@]+}}@test2_g
137; CHECK-SAME: (%t1* [[H:%.*]], i32 [[I:%.*]])
138; CHECK-NEXT:  entry:
139; CHECK-NEXT:    br label [[LAND_RHS:%.*]]
140; CHECK:       land.rhs:
141; CHECK-NEXT:    [[CALL:%.*]] = call i32 (...) @test2_j()
142; CHECK-NEXT:    [[TOBOOL1:%.*]] = icmp ne i32 [[CALL]], 0
143; CHECK-NEXT:    br label [[LAND_END:%.*]]
144; CHECK:       land.end:
145; CHECK-NEXT:    ret i1 undef
146;
147entry:
148  %tobool = icmp ne i32 %i, 0
149  br i1 %tobool, label %land.rhs, label %land.end
150
151land.rhs:                                         ; preds = %entry
152  %call = call i32 (...) @test2_j()
153  %tobool1 = icmp ne i32 %call, 0
154  br label %land.end
155
156land.end:                                         ; preds = %land.rhs, %entry
157  %0 = phi i1 [ false, %entry ], [ %tobool1, %land.rhs ]
158  ret i1 false
159}
160
161declare i32 @test2_j(...)
162
163
164
165; Same as test_2*, but with a PHI node depending on a tracked  call result.
166define i32 @test3_m(i32 %h) #0 {
167; CHECK-LABEL: define {{[^@]+}}@test3_m
168; CHECK-SAME: (i32 [[H:%.*]])
169; CHECK-NEXT:  entry:
170; CHECK-NEXT:    [[CONV:%.*]] = trunc i32 [[H]] to i8
171; CHECK-NEXT:    [[CALL:%.*]] = call i32 @test3_k(i8 [[CONV]], i32 0)
172; CHECK-NEXT:    [[CONV1:%.*]] = sext i32 [[H]] to i64
173; CHECK-NEXT:    [[TMP0:%.*]] = inttoptr i64 [[CONV1]] to %t1*
174; CHECK-NEXT:    [[CALL2:%.*]] = call i1 @test3_g(%t1* [[TMP0]], i32 1)
175; CHECK-NEXT:    ret i32 undef
176;
177entry:
178  %conv = trunc i32 %h to i8
179  %call = call i32 @test3_k(i8 %conv, i32 0)
180  %conv1 = sext i32 %h to i64
181  %0 = inttoptr i64 %conv1 to %t1*
182  %call2 = call i1 @test3_g(%t1* %0, i32 1)
183  ret i32 undef
184
185; uselistorder directives
186  uselistorder i32 %h, { 1, 0 }
187}
188
189define internal i32 @test3_k(i8 %h, i32 %i) {
190; CHECK-LABEL: define {{[^@]+}}@test3_k
191; CHECK-SAME: (i8 [[H:%.*]], i32 [[I:%.*]])
192; CHECK-NEXT:  entry:
193; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* @e, align 4
194; CHECK-NEXT:    [[CONV:%.*]] = sext i32 [[TMP0]] to i64
195; CHECK-NEXT:    [[TMP1:%.*]] = inttoptr i64 [[CONV]] to %t1*
196; CHECK-NEXT:    br label [[LOOP:%.*]]
197; CHECK:       loop:
198; CHECK-NEXT:    [[CALL:%.*]] = call i1 @test3_g(%t1* [[TMP1]], i32 0)
199; CHECK-NEXT:    call void @use.1(i1 false)
200; CHECK-NEXT:    br label [[EXIT:%.*]]
201; CHECK:       exit:
202; CHECK-NEXT:    ret i32 undef
203;
204entry:
205  %0 = load i32, i32* @e, align 4
206  %conv = sext i32 %0 to i64
207  %1 = inttoptr i64 %conv to %t1*
208  br label %loop
209
210loop:
211  %phi = phi i1 [ undef, %entry], [ %call, %loop ]
212  %call = call i1 @test3_g(%t1* %1, i32 %i)
213  %frombool = icmp slt i1 %call, 1
214  %add = add i1 %frombool, %frombool
215  call void @use.1(i1 %frombool)
216  br i1 %call, label %loop, label %exit
217
218exit:
219  ret i32 undef
220}
221
222define internal i1 @test3_g(%t1* %h, i32 %i) {
223; CHECK-LABEL: define {{[^@]+}}@test3_g
224; CHECK-SAME: (%t1* [[H:%.*]], i32 [[I:%.*]])
225; CHECK-NEXT:  entry:
226; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp ne i32 [[I]], 0
227; CHECK-NEXT:    br i1 [[TOBOOL]], label [[LAND_RHS:%.*]], label [[LAND_END:%.*]]
228; CHECK:       land.rhs:
229; CHECK-NEXT:    [[CALL:%.*]] = call i32 (...) @test3_j()
230; CHECK-NEXT:    [[TOBOOL1:%.*]] = icmp ne i32 [[CALL]], 0
231; CHECK-NEXT:    br label [[LAND_END]]
232; CHECK:       land.end:
233; CHECK-NEXT:    [[TMP0:%.*]] = phi i1 [ false, [[ENTRY:%.*]] ], [ [[TOBOOL1]], [[LAND_RHS]] ]
234; CHECK-NEXT:    ret i1 undef
235;
236entry:
237  %tobool = icmp ne i32 %i, 0
238  br i1 %tobool, label %land.rhs, label %land.end
239
240land.rhs:                                         ; preds = %entry
241  %call = call i32 (...) @test3_j()
242  %tobool1 = icmp ne i32 %call, 0
243  br label %land.end
244
245land.end:                                         ; preds = %land.rhs, %entry
246  %0 = phi i1 [ false, %entry ], [ %tobool1, %land.rhs ]
247  ret i1 false
248}
249
250declare i32 @test3_j(...)
251
252
253; TODO: We can eliminate the bitcast, if we resolve the unknown argument of
254;       @test4_b first.
255
256declare void @use.16(i16*)
257declare void @use.8(i8*)
258
259define void @test4_a() {
260; CHECK-LABEL: define {{[^@]+}}@test4_a()
261; CHECK-NEXT:  bb:
262; CHECK-NEXT:    [[TMP:%.*]] = call i8* @test4_c(i8* null)
263; CHECK-NEXT:    call void @test4_b(i8* null)
264; CHECK-NEXT:    ret void
265;
266bb:
267  %tmp = call i8* @test4_c(i8* null)
268  call void @test4_b(i8* %tmp)
269  ret void
270}
271
272define internal void @test4_b(i8* %arg) {
273; CHECK-LABEL: define {{[^@]+}}@test4_b
274; CHECK-SAME: (i8* [[ARG:%.*]])
275; CHECK-NEXT:  bb:
276; CHECK-NEXT:    [[TMP:%.*]] = bitcast i8* null to i16*
277; CHECK-NEXT:    [[SEL:%.*]] = select i1 false, i8* null, i8* null
278; CHECK-NEXT:    call void @use.16(i16* [[TMP]])
279; CHECK-NEXT:    call void @use.8(i8* [[SEL]])
280; CHECK-NEXT:    ret void
281;
282bb:
283  %tmp = bitcast i8* %arg to i16*
284  %sel = select i1 false, i8* %arg, i8* %arg
285  call void @use.16(i16* %tmp)
286  call void @use.8(i8* %sel)
287  ret void
288}
289
290define internal i8* @test4_c(i8* %arg) {
291; CHECK-LABEL: define {{[^@]+}}@test4_c
292; CHECK-SAME: (i8* [[ARG:%.*]])
293; CHECK-NEXT:  bb1:
294; CHECK-NEXT:    [[TMP:%.*]] = and i1 undef, undef
295; CHECK-NEXT:    br i1 [[TMP]], label [[BB3:%.*]], label [[BB2:%.*]]
296; CHECK:       bb2:
297; CHECK-NEXT:    unreachable
298; CHECK:       bb3:
299; CHECK-NEXT:    ret i8* undef
300;
301bb1:                                              ; preds = %bb
302  %tmp = and i1 undef, undef
303  br i1 %tmp, label %bb3, label %bb2
304
305bb2:                                              ; preds = %bb1
306  unreachable
307
308bb3:                                              ; preds = %bb1
309  ret i8* null
310}
311
312; TODO: Same as test4, but with a select instead of a bitcast.
313
314define void @test5_a() {
315; CHECK-LABEL: define {{[^@]+}}@test5_a()
316; CHECK-NEXT:  bb:
317; CHECK-NEXT:    [[TMP:%.*]] = call i8* @test5_c(i8* null)
318; CHECK-NEXT:    call void @test5_b(i8* null)
319; CHECK-NEXT:    ret void
320;
321bb:
322  %tmp = call i8* @test5_c(i8* null)
323  call void @test5_b(i8* %tmp)
324  ret void
325}
326
327define internal void @test5_b(i8* %arg) {
328; CHECK-LABEL: define {{[^@]+}}@test5_b
329; CHECK-SAME: (i8* [[ARG:%.*]])
330; CHECK-NEXT:  bb:
331; CHECK-NEXT:    [[SEL:%.*]] = select i1 false, i8* null, i8* null
332; CHECK-NEXT:    call void @use.8(i8* [[SEL]])
333; CHECK-NEXT:    ret void
334;
335bb:
336  %sel = select i1 false, i8* %arg, i8* %arg
337  call void @use.8(i8* %sel)
338  ret void
339}
340
341define internal i8* @test5_c(i8* %arg) {
342; CHECK-LABEL: define {{[^@]+}}@test5_c
343; CHECK-SAME: (i8* [[ARG:%.*]])
344; CHECK-NEXT:  bb1:
345; CHECK-NEXT:    [[TMP:%.*]] = and i1 undef, undef
346; CHECK-NEXT:    br i1 [[TMP]], label [[BB3:%.*]], label [[BB2:%.*]]
347; CHECK:       bb2:
348; CHECK-NEXT:    unreachable
349; CHECK:       bb3:
350; CHECK-NEXT:    ret i8* undef
351;
352bb1:                                              ; preds = %bb
353  %tmp = and i1 undef, undef
354  br i1 %tmp, label %bb3, label %bb2
355
356bb2:                                              ; preds = %bb1
357  unreachable
358
359bb3:                                              ; preds = %bb1
360  ret i8* null
361}
362
363
364
365@contextsize = external dso_local local_unnamed_addr global i32, align 4
366@pcount = internal local_unnamed_addr global i32 0, align 4
367@maxposslen = external dso_local local_unnamed_addr global i32, align 4
368
369define void @test3() {
370; CHECK-LABEL: define {{[^@]+}}@test3()
371; CHECK-NEXT:  entry:
372; CHECK-NEXT:    br label [[IF_END16:%.*]]
373; CHECK:       if.end16:
374; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* @contextsize, align 4
375; CHECK-NEXT:    [[SUB18:%.*]] = sub i32 undef, [[TMP0]]
376; CHECK-NEXT:    [[SUB19:%.*]] = sub i32 [[SUB18]], undef
377; CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* @maxposslen, align 4
378; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[TMP1]], 8
379; CHECK-NEXT:    [[DIV:%.*]] = sdiv i32 undef, [[ADD]]
380; CHECK-NEXT:    [[TMP2:%.*]] = load i32, i32* @pcount, align 4
381; CHECK-NEXT:    [[MUL:%.*]] = mul nsw i32 [[DIV]], [[SUB19]]
382; CHECK-NEXT:    [[CMP20:%.*]] = icmp sgt i32 [[TMP2]], [[MUL]]
383; CHECK-NEXT:    br i1 [[CMP20]], label [[IF_THEN22:%.*]], label [[IF_END24:%.*]]
384; CHECK:       if.then22:
385; CHECK-NEXT:    store i32 [[MUL]], i32* @pcount, align 4
386; CHECK-NEXT:    ret void
387; CHECK:       if.end24:
388; CHECK-NEXT:    [[CMP25474:%.*]] = icmp sgt i32 [[TMP2]], 0
389; CHECK-NEXT:    br i1 [[CMP25474]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]]
390; CHECK:       for.body:
391; CHECK-NEXT:    ret void
392; CHECK:       for.end:
393; CHECK-NEXT:    ret void
394;
395entry:
396  br label %if.end16
397
398if.end16:                                         ; preds = %entry
399  %0 = load i32, i32* @contextsize, align 4
400  %sub18 = sub i32 undef, %0
401  %sub19 = sub i32 %sub18, undef
402  %1 = load i32, i32* @maxposslen, align 4
403  %add = add nsw i32 %1, 8
404  %div = sdiv i32 undef, %add
405  %2 = load i32, i32* @pcount, align 4
406  %mul = mul nsw i32 %div, %sub19
407  %cmp20 = icmp sgt i32 %2, %mul
408  br i1 %cmp20, label %if.then22, label %if.end24
409
410if.then22:                                        ; preds = %if.end16
411  store i32 %mul, i32* @pcount, align 4
412  ret void
413
414if.end24:                                         ; preds = %if.end16
415  %cmp25474 = icmp sgt i32 %2, 0
416  br i1 %cmp25474, label %for.body, label %for.end
417
418for.body:                                         ; preds = %if.end24
419  %3 = trunc i64 0 to i32
420  %div30 = sdiv i32 %3, %sub19
421  ret void
422
423for.end:                                          ; preds = %if.end24
424  ret void
425}
426