[llvm] r365543 - [PoisonCheker] Support for out of bounds operands on shifts + insert/extractelement

Philip Reames via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 9 12:26:12 PDT 2019


Author: reames
Date: Tue Jul  9 12:26:12 2019
New Revision: 365543

URL: http://llvm.org/viewvc/llvm-project?rev=365543&view=rev
Log:
[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.  


Modified:
    llvm/trunk/lib/Transforms/Instrumentation/PoisonChecking.cpp
    llvm/trunk/test/Instrumentation/PoisonChecking/basic-flag-validation.ll

Modified: llvm/trunk/lib/Transforms/Instrumentation/PoisonChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Instrumentation/PoisonChecking.cpp?rev=365543&r1=365542&r2=365543&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Instrumentation/PoisonChecking.cpp (original)
+++ llvm/trunk/lib/Transforms/Instrumentation/PoisonChecking.cpp Tue Jul  9 12:26:12 2019
@@ -169,14 +169,54 @@ static void generatePoisonChecksForBinOp
     }
     break;
   }
+  case Instruction::AShr:
+  case Instruction::LShr:
+  case Instruction::Shl: {
+    Value *ShiftCheck =
+      B.CreateICmp(ICmpInst::ICMP_UGE, RHS,
+                   ConstantInt::get(RHS->getType(),
+                                    LHS->getType()->getScalarSizeInBits()));
+    Checks.push_back(ShiftCheck);
+    break;
+  }
   };
 }
 
 static Value* generatePoisonChecks(Instruction &I) {
   IRBuilder<> B(&I);
   SmallVector<Value*, 2> Checks;
-  if (isa<BinaryOperator>(I))
+  if (isa<BinaryOperator>(I) && !I.getType()->isVectorTy())
     generatePoisonChecksForBinOp(I, Checks);
+
+  // Handle non-binops seperately
+  switch (I.getOpcode()) {
+  default:
+    break;
+  case Instruction::ExtractElement: {
+    Value *Vec = I.getOperand(0);
+    if (Vec->getType()->getVectorIsScalable())
+      break;
+    Value *Idx = I.getOperand(1);
+    unsigned NumElts = Vec->getType()->getVectorNumElements();
+    Value *Check =
+      B.CreateICmp(ICmpInst::ICMP_UGE, Idx,
+                   ConstantInt::get(Idx->getType(), NumElts));
+    Checks.push_back(Check);
+    break;
+  }
+  case Instruction::InsertElement: {
+    Value *Vec = I.getOperand(0);
+    if (Vec->getType()->getVectorIsScalable())
+      break;
+    Value *Idx = I.getOperand(2);
+    unsigned NumElts = Vec->getType()->getVectorNumElements();
+    Value *Check =
+      B.CreateICmp(ICmpInst::ICMP_UGE, Idx,
+                   ConstantInt::get(Idx->getType(), NumElts));
+    Checks.push_back(Check);
+    break;
+  }
+  };
   return buildOrChain(B, Checks);
 }
 

Modified: llvm/trunk/test/Instrumentation/PoisonChecking/basic-flag-validation.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Instrumentation/PoisonChecking/basic-flag-validation.ll?rev=365543&r1=365542&r2=365543&view=diff
==============================================================================
--- llvm/trunk/test/Instrumentation/PoisonChecking/basic-flag-validation.ll (original)
+++ llvm/trunk/test/Instrumentation/PoisonChecking/basic-flag-validation.ll Tue Jul  9 12:26:12 2019
@@ -199,3 +199,124 @@ define i32 @udiv_exact(i32 %a, i32 %b) {
   %res = udiv exact i32 %a, %b
   ret i32 %res
 }
+
+define i32 @ashr_noflags(i32 %a, i32 %b) {
+; CHECK-LABEL: @ashr_noflags(
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp uge i32 [[B:%.*]], 32
+; CHECK-NEXT:    [[RES:%.*]] = ashr i32 [[A:%.*]], [[B]]
+; CHECK-NEXT:    [[TMP2:%.*]] = xor i1 [[TMP1]], true
+; CHECK-NEXT:    call void @__poison_checker_assert(i1 [[TMP2]])
+; CHECK-NEXT:    ret i32 [[RES]]
+;
+  %res = ashr i32 %a, %b
+  ret i32 %res
+}
+
+define i32 @ashr_exact(i32 %a, i32 %b) {
+; CHECK-LABEL: @ashr_exact(
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp uge i32 [[B:%.*]], 32
+; CHECK-NEXT:    [[RES:%.*]] = ashr exact i32 [[A:%.*]], [[B]]
+; CHECK-NEXT:    [[TMP2:%.*]] = xor i1 [[TMP1]], true
+; CHECK-NEXT:    call void @__poison_checker_assert(i1 [[TMP2]])
+; CHECK-NEXT:    ret i32 [[RES]]
+;
+  %res = ashr exact i32 %a, %b
+  ret i32 %res
+}
+
+define i32 @lshr_noflags(i32 %a, i32 %b) {
+; CHECK-LABEL: @lshr_noflags(
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp uge i32 [[B:%.*]], 32
+; CHECK-NEXT:    [[RES:%.*]] = lshr i32 [[A:%.*]], [[B]]
+; CHECK-NEXT:    [[TMP2:%.*]] = xor i1 [[TMP1]], true
+; CHECK-NEXT:    call void @__poison_checker_assert(i1 [[TMP2]])
+; CHECK-NEXT:    ret i32 [[RES]]
+;
+  %res = lshr i32 %a, %b
+  ret i32 %res
+}
+
+define i32 @lshr_exact(i32 %a, i32 %b) {
+; CHECK-LABEL: @lshr_exact(
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp uge i32 [[B:%.*]], 32
+; CHECK-NEXT:    [[RES:%.*]] = lshr exact i32 [[A:%.*]], [[B]]
+; CHECK-NEXT:    [[TMP2:%.*]] = xor i1 [[TMP1]], true
+; CHECK-NEXT:    call void @__poison_checker_assert(i1 [[TMP2]])
+; CHECK-NEXT:    ret i32 [[RES]]
+;
+  %res = lshr exact i32 %a, %b
+  ret i32 %res
+}
+
+define i32 @shl_noflags(i32 %a, i32 %b) {
+; CHECK-LABEL: @shl_noflags(
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp uge i32 [[B:%.*]], 32
+; CHECK-NEXT:    [[RES:%.*]] = shl i32 [[A:%.*]], [[B]]
+; CHECK-NEXT:    [[TMP2:%.*]] = xor i1 [[TMP1]], true
+; CHECK-NEXT:    call void @__poison_checker_assert(i1 [[TMP2]])
+; CHECK-NEXT:    ret i32 [[RES]]
+;
+  %res = shl i32 %a, %b
+  ret i32 %res
+}
+
+define i32 @shl_nsw(i32 %a, i32 %b) {
+; CHECK-LABEL: @shl_nsw(
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp uge i32 [[B:%.*]], 32
+; CHECK-NEXT:    [[RES:%.*]] = shl nsw i32 [[A:%.*]], [[B]]
+; CHECK-NEXT:    [[TMP2:%.*]] = xor i1 [[TMP1]], true
+; CHECK-NEXT:    call void @__poison_checker_assert(i1 [[TMP2]])
+; CHECK-NEXT:    ret i32 [[RES]]
+;
+  %res = shl nsw i32 %a, %b
+  ret i32 %res
+}
+
+define i32 @shl_nuw(i32 %a, i32 %b) {
+; CHECK-LABEL: @shl_nuw(
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp uge i32 [[B:%.*]], 32
+; CHECK-NEXT:    [[RES:%.*]] = shl nuw i32 [[A:%.*]], [[B]]
+; CHECK-NEXT:    [[TMP2:%.*]] = xor i1 [[TMP1]], true
+; CHECK-NEXT:    call void @__poison_checker_assert(i1 [[TMP2]])
+; CHECK-NEXT:    ret i32 [[RES]]
+;
+  %res = shl nuw i32 %a, %b
+  ret i32 %res
+}
+
+define i32 @shl_nsw_nuw(i32 %a, i32 %b) {
+; CHECK-LABEL: @shl_nsw_nuw(
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp uge i32 [[B:%.*]], 32
+; CHECK-NEXT:    [[RES:%.*]] = shl nuw nsw i32 [[A:%.*]], [[B]]
+; CHECK-NEXT:    [[TMP2:%.*]] = xor i1 [[TMP1]], true
+; CHECK-NEXT:    call void @__poison_checker_assert(i1 [[TMP2]])
+; CHECK-NEXT:    ret i32 [[RES]]
+;
+  %res = shl nsw nuw i32 %a, %b
+  ret i32 %res
+}
+
+define i32 @extractelement(<4 x i32> %v, i32 %idx) {
+; CHECK-LABEL: @extractelement(
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp uge i32 [[IDX:%.*]], 4
+; CHECK-NEXT:    [[RES:%.*]] = extractelement <4 x i32> [[V:%.*]], i32 [[IDX]]
+; CHECK-NEXT:    [[TMP2:%.*]] = xor i1 [[TMP1]], true
+; CHECK-NEXT:    call void @__poison_checker_assert(i1 [[TMP2]])
+; CHECK-NEXT:    ret i32 [[RES]]
+;
+  %res = extractelement <4 x i32> %v, i32 %idx
+  ret i32 %res
+}
+
+define <4 x i32> @insertelement(<4 x i32> %v, i32 %idx, i32 %val) {
+; CHECK-LABEL: @insertelement(
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp uge i32 [[IDX:%.*]], 4
+; CHECK-NEXT:    [[RES:%.*]] = insertelement <4 x i32> [[V:%.*]], i32 [[VAL:%.*]], i32 [[IDX]]
+; CHECK-NEXT:    [[TMP2:%.*]] = xor i1 [[TMP1]], true
+; CHECK-NEXT:    call void @__poison_checker_assert(i1 [[TMP2]])
+; CHECK-NEXT:    ret <4 x i32> [[RES]]
+;
+  %res = insertelement <4 x i32> %v, i32 %val, i32 %idx
+  ret <4 x i32> %res
+}
+




More information about the llvm-commits mailing list