From: Nuno Lopes Date: Tue, 3 Jul 2012 17:30:18 +0000 (+0000) Subject: BoundsChecking: optimize out the check for offset < 0 if size is known to be >=... X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=42d80c7a5b369285c10c0dc4b2e025f7a65d635e;p=oota-llvm.git 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 --- diff --git a/lib/Transforms/Scalar/BoundsChecking.cpp b/lib/Transforms/Scalar/BoundsChecking.cpp index 0690d76e7b5..ef2f39d8583 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(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 6c42ec815a9..86b59222707 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