BoundsChecking: optimize out the check for offset < 0 if size is known to be >=...
authorNuno Lopes <nunoplopes@sapo.pt>
Tue, 3 Jul 2012 17:30:18 +0000 (17:30 +0000)
committerNuno Lopes <nunoplopes@sapo.pt>
Tue, 3 Jul 2012 17:30:18 +0000 (17:30 +0000)
(LLVM optimizers cannot do this optimization by themselves)

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@159668 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/Scalar/BoundsChecking.cpp
test/Transforms/BoundsChecking/phi.ll

index 0690d76e7b59b6b92e98d729f597e9d816ca8848..ef2f39d8583ffa4a0e2a7820b2db93374a7f5730 100644 (file)
@@ -67,11 +67,8 @@ namespace {
 }
 
 char BoundsChecking::ID = 0;
-INITIALIZE_PASS_BEGIN(BoundsChecking, "bounds-checking",
-                      "Run-time bounds checking", false, false)
-INITIALIZE_PASS_DEPENDENCY(ScalarEvolution)
-INITIALIZE_PASS_END(BoundsChecking, "bounds-checking",
-                      "Run-time bounds checking", false, false)
+INITIALIZE_PASS(BoundsChecking, "bounds-checking", "Run-time bounds checking",
+                false, false)
 
 
 /// getTrapBB - create a basic block that traps. All overflowing conditions
@@ -141,6 +138,7 @@ bool BoundsChecking::instrument(Value *Ptr, Value *InstVal) {
 
   Value *Size   = SizeOffset.first;
   Value *Offset = SizeOffset.second;
+  ConstantInt *SizeCI = dyn_cast<ConstantInt>(Size);
 
   IntegerType *IntTy = TD->getIntPtrType(Inst->getContext());
   Value *NeededSizeVal = ConstantInt::get(IntTy, NeededSize);
@@ -149,12 +147,17 @@ bool BoundsChecking::instrument(Value *Ptr, Value *InstVal) {
   // . Offset >= 0  (since the offset is given from the base ptr)
   // . Size >= Offset  (unsigned)
   // . Size - Offset >= NeededSize  (unsigned)
+  //
+  // optimization: if Size >= 0 (signed), skip 1st check
   // FIXME: add NSW/NUW here?  -- we dont care if the subtraction overflows
   Value *ObjSize = Builder->CreateSub(Size, Offset);
-  Value *Cmp1 = Builder->CreateICmpSLT(Offset, ConstantInt::get(IntTy, 0));
   Value *Cmp2 = Builder->CreateICmpULT(Size, Offset);
   Value *Cmp3 = Builder->CreateICmpULT(ObjSize, NeededSizeVal);
-  Value *Or = Builder->CreateOr(Cmp1, Builder->CreateOr(Cmp2, Cmp3));
+  Value *Or = Builder->CreateOr(Cmp2, Cmp3);
+  if (!SizeCI || SizeCI->getValue().slt(0)) {
+    Value *Cmp1 = Builder->CreateICmpSLT(Offset, ConstantInt::get(IntTy, 0));
+    Or = Builder->CreateOr(Cmp1, Or);
+  }
   emitBranchToTrap(Or);
 
   ++ChecksAdded;
index 6c42ec815a9c7bc28237a125d99adb739b8625b4..86b59222707b81321dd8d4f713cd2d519ef783f4 100644 (file)
@@ -34,10 +34,14 @@ while.body.i.preheader:
 while.body.i:
 ; CHECK: phi
 ; CHECK-NEXT: phi
-; CHECK-NEXT: phi
-; CHECK: trap
+; CHECK-NOT: phi
   %c.addr.02.i = phi i8* [ %incdec.ptr.i, %while.body.i ], [ %addr, %while.body.i.preheader ]
   %incdec.ptr.i = getelementptr inbounds i8* %c.addr.02.i, i64 -1
+; CHECK: sub i64 10, %0
+; CHECK-NEXT: icmp ult i64 10, %0
+; CHECK-NEXT: icmp ult i64 {{.*}}, 1
+; CHECK-NEXT: or i1
+; CHECK-NEXT: br {{.*}}, label %trap
   store i8 100, i8* %c.addr.02.i, align 1
   %0 = load i8* %incdec.ptr.i, align 1
   %tobool.i = icmp eq i8 %0, 0