diff options
author | Eli Friedman <eli.friedman@gmail.com> | 2012-02-27 20:46:07 +0000 |
---|---|---|
committer | Eli Friedman <eli.friedman@gmail.com> | 2012-02-27 20:46:07 +0000 |
commit | 1680a24e534f3066f99fa6b8a618e71373e2920c (patch) | |
tree | 54e6a31e1ecefc7047b50ebea1b5d652eb3a2b9c /lib/Analysis | |
parent | 9e2a79c2878afb4fd20a6ab05952b5f71cf580e9 (diff) |
Teach BasicAA about the LLVM IR rules that allow reading past the end of an object given sufficient alignment. Fixes PR12098.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@151553 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis')
-rw-r--r-- | lib/Analysis/BasicAliasAnalysis.cpp | 35 |
1 files changed, 26 insertions, 9 deletions
diff --git a/lib/Analysis/BasicAliasAnalysis.cpp b/lib/Analysis/BasicAliasAnalysis.cpp index 4a55c219cb..23b89ddf75 100644 --- a/lib/Analysis/BasicAliasAnalysis.cpp +++ b/lib/Analysis/BasicAliasAnalysis.cpp @@ -84,42 +84,59 @@ static bool isEscapeSource(const Value *V) { /// getObjectSize - Return the size of the object specified by V, or /// UnknownSize if unknown. -static uint64_t getObjectSize(const Value *V, const TargetData &TD) { +static uint64_t getObjectSize(const Value *V, const TargetData &TD, + bool RoundToAlign = false) { Type *AccessTy; + unsigned Align; if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(V)) { if (!GV->hasDefinitiveInitializer()) return AliasAnalysis::UnknownSize; AccessTy = GV->getType()->getElementType(); + Align = GV->getAlignment(); } else if (const AllocaInst *AI = dyn_cast<AllocaInst>(V)) { if (!AI->isArrayAllocation()) AccessTy = AI->getType()->getElementType(); else return AliasAnalysis::UnknownSize; + Align = AI->getAlignment(); } else if (const CallInst* CI = extractMallocCall(V)) { - if (!isArrayMalloc(V, &TD)) + if (!RoundToAlign && !isArrayMalloc(V, &TD)) // The size is the argument to the malloc call. if (const ConstantInt* C = dyn_cast<ConstantInt>(CI->getArgOperand(0))) return C->getZExtValue(); return AliasAnalysis::UnknownSize; } else if (const Argument *A = dyn_cast<Argument>(V)) { - if (A->hasByValAttr()) + if (A->hasByValAttr()) { AccessTy = cast<PointerType>(A->getType())->getElementType(); - else + Align = A->getParamAlignment(); + } else { return AliasAnalysis::UnknownSize; + } } else { return AliasAnalysis::UnknownSize; } - - if (AccessTy->isSized()) - return TD.getTypeAllocSize(AccessTy); - return AliasAnalysis::UnknownSize; + + if (!AccessTy->isSized()) + return AliasAnalysis::UnknownSize; + + uint64_t Size = TD.getTypeAllocSize(AccessTy); + if (RoundToAlign) { + if (!Align) + return AliasAnalysis::UnknownSize; + Size = RoundUpToAlignment(Size, Align); + } + + return Size; } /// isObjectSmallerThan - Return true if we can prove that the object specified /// by V is smaller than Size. static bool isObjectSmallerThan(const Value *V, uint64_t Size, const TargetData &TD) { - uint64_t ObjectSize = getObjectSize(V, TD); + // This function needs to use the aligned object size because we allow + // reads a bit past the end given sufficient alignment. + uint64_t ObjectSize = getObjectSize(V, TD, /*RoundToAlign*/true); + return ObjectSize != AliasAnalysis::UnknownSize && ObjectSize < Size; } |