1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -constraint-elimination -S %s | FileCheck %s
5 define void @checks_in_loops_removable(i8* %ptr, i8* %lower, i8* %upper, i32 %n) {
6 ; CHECK-LABEL: @checks_in_loops_removable(
8 ; CHECK-NEXT: [[CMP_PTR_LOWER:%.*]] = icmp ult i8* [[PTR:%.*]], [[LOWER:%.*]]
9 ; CHECK-NEXT: br i1 [[CMP_PTR_LOWER]], label [[TRAP:%.*]], label [[PRE_1:%.*]]
11 ; CHECK-NEXT: [[IDX_EXT:%.*]] = zext i32 [[N:%.*]] to i64
12 ; CHECK-NEXT: [[PTR_N:%.*]] = getelementptr inbounds i8, i8* [[PTR]], i64 [[IDX_EXT]]
13 ; CHECK-NEXT: [[CMP_PTR_N_UPPER:%.*]] = icmp ult i8* [[PTR_N]], [[UPPER:%.*]]
14 ; CHECK-NEXT: br i1 [[CMP_PTR_N_UPPER]], label [[PRE_2:%.*]], label [[TRAP]]
16 ; CHECK-NEXT: [[CMP_N_NOT_ZERO:%.*]] = icmp eq i32 [[N]], 0
17 ; CHECK-NEXT: br i1 [[CMP_N_NOT_ZERO]], label [[EXIT:%.*]], label [[LOOP_HEADER:%.*]]
19 ; CHECK-NEXT: ret void
21 ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[PRE_2]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
22 ; CHECK-NEXT: [[PTR_IV:%.*]] = getelementptr inbounds i8, i8* [[PTR]], i64 [[IV]]
23 ; CHECK-NEXT: [[CMP_PTR_IV_LOWER:%.*]] = icmp ugt i8* [[LOWER]], [[PTR_IV]]
24 ; CHECK-NEXT: [[CMP_PTR_IV_UPPER:%.*]] = icmp ule i8* [[UPPER]], [[PTR_IV]]
25 ; CHECK-NEXT: [[OR:%.*]] = or i1 [[CMP_PTR_IV_LOWER]], [[CMP_PTR_IV_UPPER]]
26 ; CHECK-NEXT: br i1 [[OR]], label [[TRAP]], label [[LOOP_LATCH]]
28 ; CHECK-NEXT: store i8 0, i8* [[PTR_IV]], align 4
29 ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
30 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[IV_NEXT]], [[IDX_EXT]]
31 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP_HEADER]], label [[EXIT]]
33 ; CHECK-NEXT: ret void
36 %cmp.ptr.lower = icmp ult i8* %ptr, %lower
37 br i1 %cmp.ptr.lower, label %trap, label %pre.1
40 %idx.ext = zext i32 %n to i64
41 %ptr.n = getelementptr inbounds i8, i8* %ptr, i64 %idx.ext
42 %cmp.ptr.n.upper = icmp ult i8* %ptr.n, %upper
43 br i1 %cmp.ptr.n.upper, label %pre.2, label %trap
46 %cmp.n.not.zero = icmp eq i32 %n, 0
47 br i1 %cmp.n.not.zero, label %exit, label %loop.header
53 %iv = phi i64 [ 0, %pre.2 ], [ %iv.next, %loop.latch ]
54 %ptr.iv = getelementptr inbounds i8, i8* %ptr, i64 %iv
55 %cmp.ptr.iv.lower = icmp ugt i8* %lower, %ptr.iv
56 %cmp.ptr.iv.upper = icmp ule i8* %upper, %ptr.iv
57 %or = or i1 %cmp.ptr.iv.lower, %cmp.ptr.iv.upper
58 br i1 %or, label %trap, label %loop.latch
61 store i8 0, i8* %ptr.iv, align 4
62 %iv.next = add nuw nsw i64 %iv, 1
63 %exitcond = icmp ne i64 %iv.next, %idx.ext
64 br i1 %exitcond, label %loop.header, label %exit
70 define void @some_checks_in_loops_removable(i8* %ptr, i8* %lower, i8* %upper, i32 %n) {
71 ; CHECK-LABEL: @some_checks_in_loops_removable(
73 ; CHECK-NEXT: [[CMP_PTR_LOWER:%.*]] = icmp ult i8* [[PTR:%.*]], [[LOWER:%.*]]
74 ; CHECK-NEXT: br i1 [[CMP_PTR_LOWER]], label [[TRAP:%.*]], label [[PRE_1:%.*]]
76 ; CHECK-NEXT: [[IDX_EXT:%.*]] = zext i32 [[N:%.*]] to i64
77 ; CHECK-NEXT: [[PTR_N:%.*]] = getelementptr inbounds i8, i8* [[PTR]], i64 [[IDX_EXT]]
78 ; CHECK-NEXT: [[CMP_PTR_N_UPPER:%.*]] = icmp ult i8* [[PTR_N]], [[UPPER:%.*]]
79 ; CHECK-NEXT: br i1 [[CMP_PTR_N_UPPER]], label [[PRE_2:%.*]], label [[TRAP]]
81 ; CHECK-NEXT: [[CMP_N_NOT_ZERO:%.*]] = icmp eq i32 [[N]], 0
82 ; CHECK-NEXT: br i1 [[CMP_N_NOT_ZERO]], label [[EXIT:%.*]], label [[LOOP_HEADER:%.*]]
84 ; CHECK-NEXT: ret void
86 ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[PRE_2]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
87 ; CHECK-NEXT: [[PTR_IV:%.*]] = getelementptr inbounds i8, i8* [[PTR]], i64 [[IV]]
88 ; CHECK-NEXT: [[CMP_PTR_IV_LOWER:%.*]] = icmp ugt i8* [[LOWER]], [[PTR_IV]]
89 ; CHECK-NEXT: [[CMP_PTR_IV_UPPER:%.*]] = icmp ule i8* [[UPPER]], [[PTR_IV]]
90 ; CHECK-NEXT: [[OR:%.*]] = or i1 [[CMP_PTR_IV_LOWER]], [[CMP_PTR_IV_UPPER]]
91 ; CHECK-NEXT: br i1 [[OR]], label [[TRAP]], label [[LOOP_BODY:%.*]]
93 ; CHECK-NEXT: [[IV_1:%.*]] = add nuw nsw i64 [[IV]], 1
94 ; CHECK-NEXT: [[PTR_IV_1:%.*]] = getelementptr inbounds i8, i8* [[PTR]], i64 [[IV_1]]
95 ; CHECK-NEXT: [[CMP_PTR_IV_1_LOWER:%.*]] = icmp ugt i8* [[LOWER]], [[PTR_IV_1]]
96 ; CHECK-NEXT: [[CMP_PTR_IV_1_UPPER:%.*]] = icmp ule i8* [[UPPER]], [[PTR_IV_1]]
97 ; CHECK-NEXT: [[OR_1:%.*]] = or i1 false, [[CMP_PTR_IV_1_UPPER]]
98 ; CHECK-NEXT: br i1 [[OR]], label [[TRAP]], label [[LOOP_LATCH]]
100 ; CHECK-NEXT: store i8 0, i8* [[PTR_IV]], align 4
101 ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
102 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[IV_NEXT]], [[IDX_EXT]]
103 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP_HEADER]], label [[EXIT]]
105 ; CHECK-NEXT: ret void
108 %cmp.ptr.lower = icmp ult i8* %ptr, %lower
109 br i1 %cmp.ptr.lower, label %trap, label %pre.1
112 %idx.ext = zext i32 %n to i64
113 %ptr.n = getelementptr inbounds i8, i8* %ptr, i64 %idx.ext
114 %cmp.ptr.n.upper = icmp ult i8* %ptr.n, %upper
115 br i1 %cmp.ptr.n.upper, label %pre.2, label %trap
118 %cmp.n.not.zero = icmp eq i32 %n, 0
119 br i1 %cmp.n.not.zero, label %exit, label %loop.header
125 %iv = phi i64 [ 0, %pre.2 ], [ %iv.next, %loop.latch ]
126 %ptr.iv = getelementptr inbounds i8, i8* %ptr, i64 %iv
127 %cmp.ptr.iv.lower = icmp ugt i8* %lower, %ptr.iv
128 %cmp.ptr.iv.upper = icmp ule i8* %upper, %ptr.iv
129 %or = or i1 %cmp.ptr.iv.lower, %cmp.ptr.iv.upper
130 br i1 %or, label %trap, label %loop.body
133 %iv.1 = add nuw nsw i64 %iv, 1
134 %ptr.iv.1 = getelementptr inbounds i8, i8* %ptr, i64 %iv.1
135 %cmp.ptr.iv.1.lower = icmp ugt i8* %lower, %ptr.iv.1
136 %cmp.ptr.iv.1.upper = icmp ule i8* %upper, %ptr.iv.1
137 %or.1 = or i1 %cmp.ptr.iv.1.lower, %cmp.ptr.iv.1.upper
138 br i1 %or, label %trap, label %loop.latch
141 store i8 0, i8* %ptr.iv, align 4
142 %iv.next = add nuw nsw i64 %iv, 1
143 %exitcond = icmp ne i64 %iv.next, %idx.ext
144 br i1 %exitcond, label %loop.header, label %exit
151 ; N might be zero, cannot remove upper checks.
152 define void @no_checks_in_loops_removable(i8* %ptr, i8* %lower, i8* %upper, i32 %n) {
153 ; CHECK-LABEL: @no_checks_in_loops_removable(
155 ; CHECK-NEXT: [[CMP_PTR_LOWER:%.*]] = icmp ult i8* [[PTR:%.*]], [[LOWER:%.*]]
156 ; CHECK-NEXT: br i1 [[CMP_PTR_LOWER]], label [[TRAP:%.*]], label [[PRE_1:%.*]]
158 ; CHECK-NEXT: [[IDX_EXT:%.*]] = zext i32 [[N:%.*]] to i64
159 ; CHECK-NEXT: [[PTR_N:%.*]] = getelementptr inbounds i8, i8* [[PTR]], i64 [[IDX_EXT]]
160 ; CHECK-NEXT: [[CMP_PTR_N_UPPER:%.*]] = icmp ult i8* [[PTR_N]], [[UPPER:%.*]]
161 ; CHECK-NEXT: br i1 [[CMP_PTR_N_UPPER]], label [[LOOP_HEADER:%.*]], label [[TRAP]]
163 ; CHECK-NEXT: ret void
164 ; CHECK: loop.header:
165 ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[PRE_1]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
166 ; CHECK-NEXT: [[PTR_IV:%.*]] = getelementptr inbounds i8, i8* [[PTR]], i64 [[IV]]
167 ; CHECK-NEXT: [[CMP_PTR_IV_LOWER:%.*]] = icmp ugt i8* [[LOWER]], [[PTR_IV]]
168 ; CHECK-NEXT: [[CMP_PTR_IV_UPPER:%.*]] = icmp ule i8* [[UPPER]], [[PTR_IV]]
169 ; CHECK-NEXT: [[OR:%.*]] = or i1 [[CMP_PTR_IV_LOWER]], [[CMP_PTR_IV_UPPER]]
170 ; CHECK-NEXT: br i1 [[OR]], label [[TRAP]], label [[LOOP_BODY:%.*]]
172 ; CHECK-NEXT: [[IV_1:%.*]] = add nuw nsw i64 [[IV]], 1
173 ; CHECK-NEXT: [[PTR_IV_1:%.*]] = getelementptr inbounds i8, i8* [[PTR]], i64 [[IV_1]]
174 ; CHECK-NEXT: [[CMP_PTR_IV_1_LOWER:%.*]] = icmp ugt i8* [[LOWER]], [[PTR_IV_1]]
175 ; CHECK-NEXT: [[CMP_PTR_IV_1_UPPER:%.*]] = icmp ule i8* [[UPPER]], [[PTR_IV_1]]
176 ; CHECK-NEXT: [[OR_1:%.*]] = or i1 false, [[CMP_PTR_IV_1_UPPER]]
177 ; CHECK-NEXT: br i1 [[OR]], label [[TRAP]], label [[LOOP_LATCH]]
179 ; CHECK-NEXT: store i8 0, i8* [[PTR_IV]], align 4
180 ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
181 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[IV_NEXT]], [[IDX_EXT]]
182 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP_HEADER]], label [[EXIT:%.*]]
184 ; CHECK-NEXT: ret void
187 %cmp.ptr.lower = icmp ult i8* %ptr, %lower
188 br i1 %cmp.ptr.lower, label %trap, label %pre.1
191 %idx.ext = zext i32 %n to i64
192 %ptr.n = getelementptr inbounds i8, i8* %ptr, i64 %idx.ext
193 %cmp.ptr.n.upper = icmp ult i8* %ptr.n, %upper
194 br i1 %cmp.ptr.n.upper, label %loop.header, label %trap
200 %iv = phi i64 [ 0, %pre.1 ], [ %iv.next, %loop.latch ]
201 %ptr.iv = getelementptr inbounds i8, i8* %ptr, i64 %iv
202 %cmp.ptr.iv.lower = icmp ugt i8* %lower, %ptr.iv
203 %cmp.ptr.iv.upper = icmp ule i8* %upper, %ptr.iv
204 %or = or i1 %cmp.ptr.iv.lower, %cmp.ptr.iv.upper
205 br i1 %or, label %trap, label %loop.body
208 %iv.1 = add nuw nsw i64 %iv, 1
209 %ptr.iv.1 = getelementptr inbounds i8, i8* %ptr, i64 %iv.1
210 %cmp.ptr.iv.1.lower = icmp ugt i8* %lower, %ptr.iv.1
211 %cmp.ptr.iv.1.upper = icmp ule i8* %upper, %ptr.iv.1
212 %or.1 = or i1 %cmp.ptr.iv.1.lower, %cmp.ptr.iv.1.upper
213 br i1 %or, label %trap, label %loop.latch
216 store i8 0, i8* %ptr.iv, align 4
217 %iv.next = add nuw nsw i64 %iv, 1
218 %exitcond = icmp ne i64 %iv.next, %idx.ext
219 br i1 %exitcond, label %loop.header, label %exit