[llvm] r239299 - Minor refactoring of GEP handling in isDereferenceablePointer
Artur Pilipenko
apilipenko at azulsystems.com
Mon Jun 8 04:58:14 PDT 2015
Author: apilipenko
Date: Mon Jun 8 06:58:13 2015
New Revision: 239299
URL: http://llvm.org/viewvc/llvm-project?rev=239299&view=rev
Log:
Minor refactoring of GEP handling in isDereferenceablePointer
For GEP instructions isDereferenceablePointer checks that all indices are constant and within bounds. Replace this index calculation logic to a call to accumulateConstantOffset. Separated from the http://reviews.llvm.org/D9791
Reviewed By: sanjoy
Differential Revision: http://reviews.llvm.org/D9874
Modified:
llvm/trunk/lib/Analysis/ValueTracking.cpp
llvm/trunk/test/Analysis/ValueTracking/memory-dereferenceable.ll
Modified: llvm/trunk/lib/Analysis/ValueTracking.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ValueTracking.cpp?rev=239299&r1=239298&r2=239299&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/ValueTracking.cpp (original)
+++ llvm/trunk/lib/Analysis/ValueTracking.cpp Mon Jun 8 06:58:13 2015
@@ -2967,38 +2967,25 @@ static bool isDereferenceablePointer(con
// For GEPs, determine if the indexing lands within the allocated object.
if (const GEPOperator *GEP = dyn_cast<GEPOperator>(V)) {
+ Type *VTy = GEP->getType();
+ Type *Ty = VTy->getPointerElementType();
+ const Value *Base = GEP->getPointerOperand();
+
// Conservatively require that the base pointer be fully dereferenceable.
- if (!Visited.insert(GEP->getOperand(0)).second)
+ if (!Visited.insert(Base).second)
return false;
- if (!isDereferenceablePointer(GEP->getOperand(0), DL, CtxI,
+ if (!isDereferenceablePointer(Base, DL, CtxI,
DT, TLI, Visited))
return false;
- // Check the indices.
- gep_type_iterator GTI = gep_type_begin(GEP);
- for (User::const_op_iterator I = GEP->op_begin()+1,
- E = GEP->op_end(); I != E; ++I) {
- Value *Index = *I;
- Type *Ty = *GTI++;
- // Struct indices can't be out of bounds.
- if (isa<StructType>(Ty))
- continue;
- ConstantInt *CI = dyn_cast<ConstantInt>(Index);
- if (!CI)
- return false;
- // Zero is always ok.
- if (CI->isZero())
- continue;
- // Check to see that it's within the bounds of an array.
- ArrayType *ATy = dyn_cast<ArrayType>(Ty);
- if (!ATy)
- return false;
- if (CI->getValue().getActiveBits() > 64)
- return false;
- if (CI->getZExtValue() >= ATy->getNumElements())
- return false;
- }
- // Indices check out; this is dereferenceable.
- return true;
+
+ APInt Offset(DL.getPointerTypeSizeInBits(VTy), 0);
+ if (!GEP->accumulateConstantOffset(DL, Offset))
+ return false;
+
+ // Check if the load is within the bounds of the underlying object.
+ uint64_t LoadSize = DL.getTypeStoreSize(Ty);
+ Type *BaseType = Base->getType()->getPointerElementType();
+ return (Offset + LoadSize).ule(DL.getTypeAllocSize(BaseType));
}
// For gc.relocate, look through relocations
Modified: llvm/trunk/test/Analysis/ValueTracking/memory-dereferenceable.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/ValueTracking/memory-dereferenceable.ll?rev=239299&r1=239298&r2=239299&view=diff
==============================================================================
--- llvm/trunk/test/Analysis/ValueTracking/memory-dereferenceable.ll (original)
+++ llvm/trunk/test/Analysis/ValueTracking/memory-dereferenceable.ll Mon Jun 8 06:58:13 2015
@@ -10,6 +10,9 @@ declare zeroext i1 @return_i1()
@globalstr = global [6 x i8] c"hello\00"
@globali32ptr = external global i32*
+%struct.A = type { [8 x i8], [5 x i8] }
+ at globalstruct = external global %struct.A
+
define void @test(i32 addrspace(1)* dereferenceable(8) %dparam) gc "statepoint-example" {
; CHECK: The following are dereferenceable:
; CHECK: %globalptr
@@ -22,6 +25,8 @@ define void @test(i32 addrspace(1)* dere
; CHECK-NOT: %d2_load
; CHECK-NOT: %d_or_null_load
; CHECK: %d_or_null_non_null_load
+; CHECK: %within_allocation
+; CHECK-NOT: %outside_allocation
entry:
%globalptr = getelementptr inbounds [6 x i8], [6 x i8]* @globalstr, i32 0, i32 0
%load1 = load i8, i8* %globalptr
@@ -54,6 +59,14 @@ entry:
%d_or_null_non_null_load = load i32*, i32** @globali32ptr, !nonnull !2, !dereferenceable_or_null !0
%load10 = load i32, i32* %d_or_null_non_null_load
+ ; It's OK to overrun static array size as long as we stay within underlying object size
+ %within_allocation = getelementptr inbounds %struct.A, %struct.A* @globalstruct, i64 0, i32 0, i64 10
+ %load11 = load i8, i8* %within_allocation
+
+ ; GEP is outside the underlying object size
+ %outside_allocation = getelementptr inbounds %struct.A, %struct.A* @globalstruct, i64 0, i32 1, i64 10
+ %load12 = load i8, i8* %outside_allocation
+
ret void
}
More information about the llvm-commits
mailing list