diff --git a/lib/Analysis/BasicAliasAnalysis.cpp b/lib/Analysis/BasicAliasAnalysis.cpp index 8e0637a49b5..f3695929d16 100644 --- a/lib/Analysis/BasicAliasAnalysis.cpp +++ b/lib/Analysis/BasicAliasAnalysis.cpp @@ -97,38 +97,53 @@ static bool isEscapeSource(const Value *V) { return false; } -/// 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) { +/// getObjectSize - Return the size of the object specified by V, or +/// UnknownSize if unknown. +static uint64_t getObjectSize(const Value *V, const TargetData &TD) { const Type *AccessTy; if (const GlobalVariable *GV = dyn_cast(V)) { if (!GV->hasDefinitiveInitializer()) - return false; + return AliasAnalysis::UnknownSize; AccessTy = GV->getType()->getElementType(); } else if (const AllocaInst *AI = dyn_cast(V)) { if (!AI->isArrayAllocation()) AccessTy = AI->getType()->getElementType(); else - return false; + return AliasAnalysis::UnknownSize; } else if (const CallInst* CI = extractMallocCall(V)) { if (!isArrayMalloc(V, &TD)) // The size is the argument to the malloc call. if (const ConstantInt* C = dyn_cast(CI->getArgOperand(0))) - return (C->getZExtValue() < Size); - return false; + return C->getZExtValue(); + return AliasAnalysis::UnknownSize; } else if (const Argument *A = dyn_cast(V)) { if (A->hasByValAttr()) AccessTy = cast(A->getType())->getElementType(); else - return false; + return AliasAnalysis::UnknownSize; } else { - return false; + return AliasAnalysis::UnknownSize; } if (AccessTy->isSized()) - return TD.getTypeAllocSize(AccessTy) < Size; - return false; + return TD.getTypeAllocSize(AccessTy); + return AliasAnalysis::UnknownSize; +} + +/// 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); + return ObjectSize != AliasAnalysis::UnknownSize && ObjectSize < Size; +} + +/// isObjectSize - Return true if we can prove that the object specified +/// by V has size Size. +static bool isObjectSize(const Value *V, uint64_t Size, + const TargetData &TD) { + uint64_t ObjectSize = getObjectSize(V, TD); + return ObjectSize != AliasAnalysis::UnknownSize && ObjectSize == Size; } //===----------------------------------------------------------------------===// @@ -1142,6 +1157,14 @@ BasicAliasAnalysis::aliasCheck(const Value *V1, uint64_t V1Size, if (Result != MayAlias) return Result; } + // If both pointers are pointing into the same object and one of them + // accesses is accessing the entire object, then the accesses must + // overlap in some way. + if (TD && O1 == O2) + if ((V1Size != UnknownSize && isObjectSize(O1, V1Size, *TD)) || + (V2Size != UnknownSize && isObjectSize(O2, V2Size, *TD))) + return PartialAlias; + return AliasAnalysis::alias(Location(V1, V1Size, V1TBAAInfo), Location(V2, V2Size, V2TBAAInfo)); } diff --git a/test/Analysis/BasicAA/full-store-partial-alias.ll b/test/Analysis/BasicAA/full-store-partial-alias.ll new file mode 100644 index 00000000000..f92c689516e --- /dev/null +++ b/test/Analysis/BasicAA/full-store-partial-alias.ll @@ -0,0 +1,33 @@ +; RUN: opt -S -tbaa -basicaa -gvn < %s | grep {ret i32 %} +; RUN: opt -S -tbaa -gvn < %s | grep {ret i32 0} +; rdar://8875631 + +; BasicAA should notice that the store stores to the entire %u object, +; so the %tmp5 load is PartialAlias with the store and suppress TBAA. +; Without BasicAA, TBAA should say that %tmp5 is NoAlias with the store. + +target datalayout = "e-p:64:64:64" + +%union.anon = type { double } + +@u = global %union.anon { double -2.500000e-01 }, align 8 +@endianness_test = global i64 1, align 8 + +define i32 @signbit(double %x) nounwind { +entry: + %u = alloca %union.anon, align 8 + %tmp9 = getelementptr inbounds %union.anon* %u, i64 0, i32 0 + store double %x, double* %tmp9, align 8, !tbaa !0 + %tmp2 = load i32* bitcast (i64* @endianness_test to i32*), align 8, !tbaa !3 + %idxprom = sext i32 %tmp2 to i64 + %tmp4 = bitcast %union.anon* %u to [2 x i32]* + %arrayidx = getelementptr inbounds [2 x i32]* %tmp4, i64 0, i64 %idxprom + %tmp5 = load i32* %arrayidx, align 4, !tbaa !3 + %tmp5.lobit = lshr i32 %tmp5, 31 + ret i32 %tmp5.lobit +} + +!0 = metadata !{metadata !"double", metadata !1} +!1 = metadata !{metadata !"omnipotent char", metadata !2} +!2 = metadata !{metadata !"Simple C/C++ TBAA", null} +!3 = metadata !{metadata !"int", metadata !1}