diff options
author | Nuno Lopes <nunoplopes@sapo.pt> | 2012-07-03 17:30:18 +0000 |
---|---|---|
committer | Nuno Lopes <nunoplopes@sapo.pt> | 2012-07-03 17:30:18 +0000 |
commit | 42d80c7a5b369285c10c0dc4b2e025f7a65d635e (patch) | |
tree | e220c91a009529fa7d2192da7e6d959c1c135dea | |
parent | 0dff532fce434c3e9fdf9695aed8efeb5f752ed5 (diff) | |
download | external_llvm-42d80c7a5b369285c10c0dc4b2e025f7a65d635e.zip external_llvm-42d80c7a5b369285c10c0dc4b2e025f7a65d635e.tar.gz external_llvm-42d80c7a5b369285c10c0dc4b2e025f7a65d635e.tar.bz2 |
BoundsChecking: optimize out the check for offset < 0 if size is known to be >= 0 (signed).
(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
-rw-r--r-- | lib/Transforms/Scalar/BoundsChecking.cpp | 17 | ||||
-rw-r--r-- | test/Transforms/BoundsChecking/phi.ll | 8 |
2 files changed, 16 insertions, 9 deletions
diff --git a/lib/Transforms/Scalar/BoundsChecking.cpp b/lib/Transforms/Scalar/BoundsChecking.cpp index 0690d76..ef2f39d 100644 --- a/lib/Transforms/Scalar/BoundsChecking.cpp +++ b/lib/Transforms/Scalar/BoundsChecking.cpp @@ -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; diff --git a/test/Transforms/BoundsChecking/phi.ll b/test/Transforms/BoundsChecking/phi.ll index 6c42ec8..86b5922 100644 --- a/test/Transforms/BoundsChecking/phi.ll +++ b/test/Transforms/BoundsChecking/phi.ll @@ -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 |