Skip to content
This repository has been archived by the owner on Jan 9, 2021. It is now read-only.

Commit

Permalink
BoundsChecking: optimize out the check for offset < 0 if size is know…
Browse files Browse the repository at this point in the history
…n 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
  • Loading branch information
nunoplopes committed Jul 3, 2012
1 parent 0dff532 commit 42d80c7
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 9 deletions.
17 changes: 10 additions & 7 deletions lib/Transforms/Scalar/BoundsChecking.cpp
Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand All @@ -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;
Expand Down
8 changes: 6 additions & 2 deletions test/Transforms/BoundsChecking/phi.ll
Expand Up @@ -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
Expand Down

0 comments on commit 42d80c7

Please sign in to comment.