llvm.org GIT mirror llvm / 716786c
[PoisonCheker] Support for out of bounds operands on shifts + insert/extractelement These are sources of poison which don't come from flags, but are clearly documented in the LangRef. Left off support for scalable vectors for the moment, but should be easy to add if anyone is interested. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@365543 91177308-0d34-0410-b5e6-96231b3b80d8 Philip Reames 3 months ago
2 changed file(s) with 162 addition(s) and 1 deletion(s). Raw diff Collapse all Expand all
168168 }
169169 break;
170170 }
171 case Instruction::AShr:
172 case Instruction::LShr:
173 case Instruction::Shl: {
174 Value *ShiftCheck =
175 B.CreateICmp(ICmpInst::ICMP_UGE, RHS,
176 ConstantInt::get(RHS->getType(),
177 LHS->getType()->getScalarSizeInBits()));
178 Checks.push_back(ShiftCheck);
179 break;
180 }
171181 };
172182 }
173183
174184 static Value* generatePoisonChecks(Instruction &I) {
175185 IRBuilder<> B(&I);
176186 SmallVector Checks;
177 if (isa(I))
187 if (isa(I) && !I.getType()->isVectorTy())
178188 generatePoisonChecksForBinOp(I, Checks);
189
190 // Handle non-binops seperately
191 switch (I.getOpcode()) {
192 default:
193 break;
194 case Instruction::ExtractElement: {
195 Value *Vec = I.getOperand(0);
196 if (Vec->getType()->getVectorIsScalable())
197 break;
198 Value *Idx = I.getOperand(1);
199 unsigned NumElts = Vec->getType()->getVectorNumElements();
200 Value *Check =
201 B.CreateICmp(ICmpInst::ICMP_UGE, Idx,
202 ConstantInt::get(Idx->getType(), NumElts));
203 Checks.push_back(Check);
204 break;
205 }
206 case Instruction::InsertElement: {
207 Value *Vec = I.getOperand(0);
208 if (Vec->getType()->getVectorIsScalable())
209 break;
210 Value *Idx = I.getOperand(2);
211 unsigned NumElts = Vec->getType()->getVectorNumElements();
212 Value *Check =
213 B.CreateICmp(ICmpInst::ICMP_UGE, Idx,
214 ConstantInt::get(Idx->getType(), NumElts));
215 Checks.push_back(Check);
216 break;
217 }
218 };
179219 return buildOrChain(B, Checks);
180220 }
181221
198198 %res = udiv exact i32 %a, %b
199199 ret i32 %res
200200 }
201
202 define i32 @ashr_noflags(i32 %a, i32 %b) {
203 ; CHECK-LABEL: @ashr_noflags(
204 ; CHECK-NEXT: [[TMP1:%.*]] = icmp uge i32 [[B:%.*]], 32
205 ; CHECK-NEXT: [[RES:%.*]] = ashr i32 [[A:%.*]], [[B]]
206 ; CHECK-NEXT: [[TMP2:%.*]] = xor i1 [[TMP1]], true
207 ; CHECK-NEXT: call void @__poison_checker_assert(i1 [[TMP2]])
208 ; CHECK-NEXT: ret i32 [[RES]]
209 ;
210 %res = ashr i32 %a, %b
211 ret i32 %res
212 }
213
214 define i32 @ashr_exact(i32 %a, i32 %b) {
215 ; CHECK-LABEL: @ashr_exact(
216 ; CHECK-NEXT: [[TMP1:%.*]] = icmp uge i32 [[B:%.*]], 32
217 ; CHECK-NEXT: [[RES:%.*]] = ashr exact i32 [[A:%.*]], [[B]]
218 ; CHECK-NEXT: [[TMP2:%.*]] = xor i1 [[TMP1]], true
219 ; CHECK-NEXT: call void @__poison_checker_assert(i1 [[TMP2]])
220 ; CHECK-NEXT: ret i32 [[RES]]
221 ;
222 %res = ashr exact i32 %a, %b
223 ret i32 %res
224 }
225
226 define i32 @lshr_noflags(i32 %a, i32 %b) {
227 ; CHECK-LABEL: @lshr_noflags(
228 ; CHECK-NEXT: [[TMP1:%.*]] = icmp uge i32 [[B:%.*]], 32
229 ; CHECK-NEXT: [[RES:%.*]] = lshr i32 [[A:%.*]], [[B]]
230 ; CHECK-NEXT: [[TMP2:%.*]] = xor i1 [[TMP1]], true
231 ; CHECK-NEXT: call void @__poison_checker_assert(i1 [[TMP2]])
232 ; CHECK-NEXT: ret i32 [[RES]]
233 ;
234 %res = lshr i32 %a, %b
235 ret i32 %res
236 }
237
238 define i32 @lshr_exact(i32 %a, i32 %b) {
239 ; CHECK-LABEL: @lshr_exact(
240 ; CHECK-NEXT: [[TMP1:%.*]] = icmp uge i32 [[B:%.*]], 32
241 ; CHECK-NEXT: [[RES:%.*]] = lshr exact i32 [[A:%.*]], [[B]]
242 ; CHECK-NEXT: [[TMP2:%.*]] = xor i1 [[TMP1]], true
243 ; CHECK-NEXT: call void @__poison_checker_assert(i1 [[TMP2]])
244 ; CHECK-NEXT: ret i32 [[RES]]
245 ;
246 %res = lshr exact i32 %a, %b
247 ret i32 %res
248 }
249
250 define i32 @shl_noflags(i32 %a, i32 %b) {
251 ; CHECK-LABEL: @shl_noflags(
252 ; CHECK-NEXT: [[TMP1:%.*]] = icmp uge i32 [[B:%.*]], 32
253 ; CHECK-NEXT: [[RES:%.*]] = shl i32 [[A:%.*]], [[B]]
254 ; CHECK-NEXT: [[TMP2:%.*]] = xor i1 [[TMP1]], true
255 ; CHECK-NEXT: call void @__poison_checker_assert(i1 [[TMP2]])
256 ; CHECK-NEXT: ret i32 [[RES]]
257 ;
258 %res = shl i32 %a, %b
259 ret i32 %res
260 }
261
262 define i32 @shl_nsw(i32 %a, i32 %b) {
263 ; CHECK-LABEL: @shl_nsw(
264 ; CHECK-NEXT: [[TMP1:%.*]] = icmp uge i32 [[B:%.*]], 32
265 ; CHECK-NEXT: [[RES:%.*]] = shl nsw i32 [[A:%.*]], [[B]]
266 ; CHECK-NEXT: [[TMP2:%.*]] = xor i1 [[TMP1]], true
267 ; CHECK-NEXT: call void @__poison_checker_assert(i1 [[TMP2]])
268 ; CHECK-NEXT: ret i32 [[RES]]
269 ;
270 %res = shl nsw i32 %a, %b
271 ret i32 %res
272 }
273
274 define i32 @shl_nuw(i32 %a, i32 %b) {
275 ; CHECK-LABEL: @shl_nuw(
276 ; CHECK-NEXT: [[TMP1:%.*]] = icmp uge i32 [[B:%.*]], 32
277 ; CHECK-NEXT: [[RES:%.*]] = shl nuw i32 [[A:%.*]], [[B]]
278 ; CHECK-NEXT: [[TMP2:%.*]] = xor i1 [[TMP1]], true
279 ; CHECK-NEXT: call void @__poison_checker_assert(i1 [[TMP2]])
280 ; CHECK-NEXT: ret i32 [[RES]]
281 ;
282 %res = shl nuw i32 %a, %b
283 ret i32 %res
284 }
285
286 define i32 @shl_nsw_nuw(i32 %a, i32 %b) {
287 ; CHECK-LABEL: @shl_nsw_nuw(
288 ; CHECK-NEXT: [[TMP1:%.*]] = icmp uge i32 [[B:%.*]], 32
289 ; CHECK-NEXT: [[RES:%.*]] = shl nuw nsw i32 [[A:%.*]], [[B]]
290 ; CHECK-NEXT: [[TMP2:%.*]] = xor i1 [[TMP1]], true
291 ; CHECK-NEXT: call void @__poison_checker_assert(i1 [[TMP2]])
292 ; CHECK-NEXT: ret i32 [[RES]]
293 ;
294 %res = shl nsw nuw i32 %a, %b
295 ret i32 %res
296 }
297
298 define i32 @extractelement(<4 x i32> %v, i32 %idx) {
299 ; CHECK-LABEL: @extractelement(
300 ; CHECK-NEXT: [[TMP1:%.*]] = icmp uge i32 [[IDX:%.*]], 4
301 ; CHECK-NEXT: [[RES:%.*]] = extractelement <4 x i32> [[V:%.*]], i32 [[IDX]]
302 ; CHECK-NEXT: [[TMP2:%.*]] = xor i1 [[TMP1]], true
303 ; CHECK-NEXT: call void @__poison_checker_assert(i1 [[TMP2]])
304 ; CHECK-NEXT: ret i32 [[RES]]
305 ;
306 %res = extractelement <4 x i32> %v, i32 %idx
307 ret i32 %res
308 }
309
310 define <4 x i32> @insertelement(<4 x i32> %v, i32 %idx, i32 %val) {
311 ; CHECK-LABEL: @insertelement(
312 ; CHECK-NEXT: [[TMP1:%.*]] = icmp uge i32 [[IDX:%.*]], 4
313 ; CHECK-NEXT: [[RES:%.*]] = insertelement <4 x i32> [[V:%.*]], i32 [[VAL:%.*]], i32 [[IDX]]
314 ; CHECK-NEXT: [[TMP2:%.*]] = xor i1 [[TMP1]], true
315 ; CHECK-NEXT: call void @__poison_checker_assert(i1 [[TMP2]])
316 ; CHECK-NEXT: ret <4 x i32> [[RES]]
317 ;
318 %res = insertelement <4 x i32> %v, i32 %val, i32 %idx
319 ret <4 x i32> %res
320 }
321