xref: /llvm-project/llvm/test/Transforms/ConstraintElimination/reproducer-remarks.ll (revision 2d69827c5c754f0eca98e497ecf0e52ed54b4fd3)
1; RUN: opt -passes=constraint-elimination -constraint-elimination-dump-reproducers -pass-remarks=constraint-elimination %s 2>&1 | FileCheck %s
2
3target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
4
5declare void @use(i1)
6
7declare void @llvm.assume(i1)
8
9define i1 @test_no_known_facts(ptr %dst) {
10; CHECK: remark: <unknown>:0:0: module; ModuleID = 'test_no_known_facts'
11; CHECK-LABEL: define i1 @"{{.+}}test_no_known_factsrepro"(ptr %dst)
12; CHECK-NEXT:  entry:
13; CHECK-NEXT:    %dst.0 = getelementptr inbounds ptr, ptr %dst, i64 0
14; CHECK-NEXT:    %upper = getelementptr inbounds ptr, ptr %dst, i64 2
15; CHECK-NEXT:    %c = icmp ult ptr %dst.0, %upper
16; CHECK-NEXT:    ret i1 %c
17; CHECK-NEXT:  }
18;
19entry:
20  %dst.0 = getelementptr inbounds ptr, ptr %dst, i64 0
21  %upper = getelementptr inbounds ptr, ptr %dst, i64 2
22  %c = icmp ult ptr %dst.0, %upper
23  ret i1 %c
24}
25
26define void @test_one_known_fact_true_branch(i8 %start, i8 %high) {
27; CHECK: remark: <unknown>:0:0: module; ModuleID = 'test_one_known_fact_true_branch'
28
29; CHECK-LABEL: define i1 @"{{.*}}test_one_known_fact_true_branchrepro"(i8 %high, i8 %start) {
30; CHECK-NEXT: entry:
31; CHECK-NEXT:   %add.ptr.i = add nuw i8 %start, 3
32; CHECK-NEXT:   %0 = icmp ult i8 %add.ptr.i, %high
33; CHECK-NEXT:   call void @llvm.assume(i1 %0)
34; CHECK-NEXT:   %t.0 = icmp ult i8 %start, %high
35; CHECK-NEXT:   ret i1 %t.0
36; CHECK-NEXT: }
37;
38entry:
39  %add.ptr.i = add nuw i8 %start, 3
40  %c.1 = icmp ult i8 %add.ptr.i, %high
41  br i1 %c.1, label %if.then, label %if.end
42
43if.then:
44  %t.0 = icmp ult i8 %start, %high
45  call void @use(i1 %t.0)
46  ret void
47
48if.end:
49  ret void
50}
51
52define void @test_one_known_fact_false_branch(i8 %start, i8 %high) {
53; CHECK: remark: <unknown>:0:0: module; ModuleID = 'test_one_known_fact_false_branch'
54;
55; CHECK-LABEL:define i1 @"{{.*}}test_one_known_fact_false_branchrepro"(i8 %high, i8 %start) {
56; CHECK-NEXT: entry:
57; CHECK-NEXT:   %add.ptr.i = add nuw i8 %start, 3
58; CHECK-NEXT:   %0 = icmp ult i8 %add.ptr.i, %high
59; CHECK-NEXT:   call void @llvm.assume(i1 %0)
60; CHECK-NEXT:   %t.0 = icmp ult i8 %start, %high
61; CHECK-NEXT:   ret i1 %t.0
62; CHECK-NEXT: }
63;
64entry:
65  %add.ptr.i = add nuw i8 %start, 3
66  %c.1 = icmp uge i8 %add.ptr.i, %high
67  br i1 %c.1, label %if.then, label %if.end
68
69if.then:
70  ret void
71
72if.end:
73  %t.0 = icmp ult i8 %start, %high
74  call void @use(i1 %t.0)
75  ret void
76}
77
78define void @test_multiple_known_facts_branches_1(i8 %a, i8 %b) {
79; CHECK: remark: <unknown>:0:0: module; ModuleID = 'test_multiple_known_facts_branches_1'
80
81; CHECK-LABEL: define i1 @"{{.*}}test_multiple_known_facts_branches_1repro"(i8 %a, i8 %b) {
82; CHECK-NEXT: entry:
83; CHECK-NEXT:   %0 = icmp ugt i8 %a, 10
84; CHECK-NEXT:   call void @llvm.assume(i1 %0)
85; CHECK-NEXT:   %1 = icmp ugt i8 %b, 10
86; CHECK-NEXT:   call void @llvm.assume(i1 %1)
87; CHECK-NEXT:   %add = add nuw i8 %a, %b
88; CHECK-NEXT:   %t.0 = icmp ugt i8 %add, 20
89; CHECK-NEXT:   ret i1 %t.0
90; CHECK-NEXT: }
91;
92entry:
93  %c.1 = icmp ugt i8 %a, 10
94  br i1 %c.1, label %then.1, label %else.1
95
96then.1:
97  %c.2 = icmp ugt i8 %b, 10
98  br i1 %c.2, label %then.2, label %else.1
99
100then.2:
101  %add = add nuw i8 %a, %b
102  %t.0 = icmp ugt i8 %add, 20
103  call void @use(i1 %t.0)
104  ret void
105
106else.1:
107  ret void
108}
109
110define void @test_multiple_known_facts_branches_2(i8 %a, i8 %b) {
111; CHECK: remark: <unknown>:0:0: module; ModuleID = 'test_multiple_known_facts_branches_2'
112;
113; CHECK-LABEL: define i1 @"{{.*}}test_multiple_known_facts_branches_2repro"(i8 %a, i8 %b) {
114; CHECK-NEXT: entry:
115; CHECK-NEXT:   %0 = icmp ugt i8 %a, 10
116; CHECK-NEXT:   call void @llvm.assume(i1 %0)
117; CHECK-NEXT:   %1 = icmp ugt i8 %b, 10
118; CHECK-NEXT:   call void @llvm.assume(i1 %1)
119; CHECK-NEXT:   %add = add nuw i8 %a, %b
120; CHECK-NEXT:   %t.0 = icmp ugt i8 %add, 20
121; CHECK-NEXT:   ret i1 %t.0
122; CHECK-NEXT: }
123;
124entry:
125  %c.1 = icmp ugt i8 %a, 10
126  br i1 %c.1, label %then.1, label %exit
127
128then.1:
129  %c.2 = icmp ule i8 %b, 10
130  br i1 %c.2, label %exit, label %else.2
131
132else.2:
133  %add = add nuw i8 %a, %b
134  %t.0 = icmp ugt i8 %add, 20
135  call void @use(i1 %t.0)
136  ret void
137
138exit:
139  ret void
140}
141
142define void @test_assumes(i8 %a, i8 %b) {
143; CHECK-LABEL: define i1 @"{{.*}}test_assumesrepro.2"(i8 %a, i8 %b) {
144; CHECK-NEXT: entry:
145; CHECK-NEXT:   %0 = icmp ugt i8 %a, 10
146; CHECK-NEXT:   call void @llvm.assume(i1 %0)
147; CHECK-NEXT:   %1 = icmp ugt i8 %b, 10
148; CHECK-NEXT:   call void @llvm.assume(i1 %1)
149; CHECK-NEXT:   %add = add nuw i8 %a, %b
150; CHECK-NEXT:   %t.0 = icmp ult i8 %add, 20
151; CHECK-NEXT:   ret i1 %t.0
152; CHECK-NEXT: }
153;
154entry:
155  %c.1 = icmp ugt i8 %a, 10
156  call void @llvm.assume(i1 %c.1)
157  %c.2 = icmp ugt i8 %b, 10
158  call void @llvm.assume(i1 %c.2)
159  %add = add nuw i8 %a, %b
160  %t.0 = icmp ult i8 %add, 20
161  call void @use(i1 %t.0)
162  ret void
163}
164
165declare void @noundef(ptr noundef)
166
167; Currently this fails decomposition. No reproducer should be generated.
168define i1 @test_inbounds_precondition(ptr %src, i32 %n, i32 %idx) {
169; CHECK-NOT: test_inbounds_precondition
170entry:
171  %upper = getelementptr inbounds i32, ptr %src, i64 5
172  %src.idx.4 = getelementptr i32, ptr %src, i64 4
173  %cmp.upper.4 = icmp ule ptr %src.idx.4, %upper
174  br i1 %cmp.upper.4, label %then, label %else
175
176then:
177  ret i1 true
178
179else:
180  ret i1 false
181}
182
183define i32 @test_branch(i32 %a) {
184; CHECK-LABEL: define i1 @"{{.+}}test_branchrepro"(i32 %a) {
185; CHECK-NEXT: entry:
186; CHECK-NEXT:   %0 = icmp ult i32 %a, 4
187; CHECK-NEXT:   call void @llvm.assume(i1 %0)
188; CHECK-NEXT:   %c.2 = icmp ugt i32 0, 0
189; CHECK-NEXT:   ret i1 %c.2
190; CHECK-NEXT: }
191;
192entry:
193  %c.1 = icmp ult i32 %a, 4
194  br i1 %c.1, label %then, label %exit
195
196then:
197  %c.2 = icmp ugt i32 0, 0
198  call void @use(i1 %c.2)
199  br label %exit
200
201exit:
202  ret i32 0
203}
204
205define i32 @test_invoke(i32 %a) personality ptr null {
206; CHECK-LABEL: define i1 @"{{.+}}test_invokerepro"(i32 %l, i32 %a) {
207; CHECK-NEXT: entry:
208; CHECK-NEXT:  %0 = icmp slt i32 %a, %l
209; CHECK-NEXT:  call void @llvm.assume(i1 %0)
210; CHECK-NEXT:  %c.2 = icmp eq i32 0, 0
211; CHECK-NEXT:  ret i1 %c.2
212; CHECK-NEXT:}
213;
214entry:
215  %call = invoke ptr null(i64 0)
216          to label %cont unwind label %lpad
217
218cont:
219  %l = load i32, ptr %call, align 4
220  %c.1 = icmp slt i32 %a, %l
221  br i1 %c.1, label %then, label %exit
222
223lpad:
224  %lp = landingpad { ptr, i32 }
225          catch ptr null
226          catch ptr null
227  ret i32 0
228
229then:
230  %c.2 = icmp eq i32 0, 0
231  call void @use(i1 %c.2)
232  br label %exit
233
234exit:
235  ret i32 0
236}
237
238define <2 x i1> @vector_cmp(<2 x ptr> %vec) {
239; CHECK-LABEL: define <2 x i1> @"{{.+}}vector_cmprepro"(<2 x ptr> %vec) {
240; CHECK-NEXT: entry:
241; CHECK-NEXT:   %gep.1 = getelementptr inbounds i32, <2 x ptr> %vec, i64 1
242; CHECK-NEXT:   %t.1 = icmp ult <2 x ptr> %vec, %gep.1
243; CHECK-NEXT:   ret <2 x i1> %t.1
244; CHECK-NEXT: }
245;
246  %gep.1 = getelementptr inbounds i32, <2 x ptr> %vec, i64 1
247  %t.1 = icmp ult <2 x ptr> %vec, %gep.1
248  ret <2 x i1> %t.1
249}
250
251define i1 @shared_operand() {
252; CHECK-LABEL: define i1 @"{{.+}}shared_operandrepro"() {
253; CHECK-NEXT: entry:
254; CHECK-NEXT:   %sub = sub i8 0, 0
255; CHECK-NEXT:   %sub.2 = sub nuw i8 %sub, 0
256; CHECK-NEXT:   %c.5 = icmp ult i8 %sub.2, %sub
257; CHECK-NEXT:   ret i1 %c.5
258; CHECK-NEXT: }
259;
260entry:
261  %sub = sub i8 0, 0
262  %sub.2 = sub nuw i8 %sub, 0
263  %c.5 = icmp ult i8 %sub.2, %sub
264  ret i1 %c.5
265}
266
267@glob = external global i32
268
269define i1 @load_global() {
270; CHECK-LABEL: define i1 @"{{.*}}load_globalrepro"(i32 %l) {
271; CHECK-NEXT: entry:
272; CHECK-NEXT:  %c = icmp ugt i32 %l, %l
273; CHECK-NEXT:  ret i1 %c
274; CHECK-NEXT:}
275;
276entry:
277  %l = load i32, ptr @glob, align 8
278  %c = icmp ugt i32 %l, %l
279  ret i1 %c
280}
281
282define i1 @test_ptr_null_constant(ptr %a) {
283; CHECK-LABEL: define i1 @"{{.+}}test_ptr_null_constantrepro"(ptr %a) {
284; CHECK-NEXT: entry:
285; CHECK-NEXT:   %0 = icmp eq ptr %a, null
286; CHECK-NEXT:   call void @llvm.assume(i1 %0)
287; CHECK-NEXT:   %c.2 = icmp eq ptr %a, null
288; CHECK-NEXT:   ret i1 %c.2
289; CHECK-NEXT: }
290;
291entry:
292  %c.1 = icmp eq ptr %a, null
293  br i1 %c.1, label %then, label %else
294
295then:
296  %c.2 = icmp eq ptr %a, null
297  ret i1 %c.2
298
299else:
300  ret i1 false
301}
302
303define i1 @test_both_signed_and_unsigned_conds_needed_in_reproducer(ptr %src, ptr %lower, ptr %upper, i16 %N) {
304; CHECK-LABEL: define i1 @"{{.+}}test_both_signed_and_unsigned_conds_needed_in_reproducerrepro"(i16 %N, ptr %src) {
305; CHECK-NEXT: entry:
306; CHECK-NEXT:   %0 = icmp sge i16 %N, 0
307; CHECK-NEXT:   call void @llvm.assume(i1 %0)
308; CHECK-NEXT:   %src.end = getelementptr inbounds i8, ptr %src, i16 %N
309; CHECK-NEXT:   %cmp.src.start = icmp ule ptr %src, %src.end
310; CHECK-NEXT:   ret i1 %cmp.src.start
311; CHECK-NEXT: }
312;
313entry:
314  %N.pos = icmp sge i16 %N, 0
315  br i1 %N.pos, label %then, label %else
316
317then:
318  %src.end = getelementptr inbounds i8, ptr %src, i16 %N
319  %cmp.src.start = icmp ule ptr %src, %src.end
320  ret i1 %cmp.src.start
321
322else:
323  ret i1 false
324}
325