diff --git a/llvm/lib/Analysis/Loads.cpp b/llvm/lib/Analysis/Loads.cpp index bc16c00c5320..24c4cff8a8ec 100644 --- a/llvm/lib/Analysis/Loads.cpp +++ b/llvm/lib/Analysis/Loads.cpp @@ -54,63 +54,6 @@ static bool isDereferenceableAndAlignedPointer( // Note that it is not safe to speculate into a malloc'd region because // malloc may return null. - // Recurse into both hands of select. - if (const SelectInst *Sel = dyn_cast(V)) { - return isDereferenceableAndAlignedPointer(Sel->getTrueValue(), Alignment, - Size, DL, CtxI, AC, DT, TLI, - Visited, MaxDepth) && - isDereferenceableAndAlignedPointer(Sel->getFalseValue(), Alignment, - Size, DL, CtxI, AC, DT, TLI, - Visited, MaxDepth); - } - - // bitcast instructions are no-ops as far as dereferenceability is concerned. - if (const BitCastOperator *BC = dyn_cast(V)) { - if (BC->getSrcTy()->isPointerTy()) - return isDereferenceableAndAlignedPointer(BC->getOperand(0), Alignment, - Size, DL, CtxI, AC, DT, TLI, - Visited, MaxDepth); - } - - bool CheckForNonNull, CheckForFreed; - APInt KnownDerefBytes(Size.getBitWidth(), - V->getPointerDereferenceableBytes(DL, CheckForNonNull, - CheckForFreed)); - if (KnownDerefBytes.getBoolValue() && KnownDerefBytes.uge(Size) && - !CheckForFreed) - if (!CheckForNonNull || isKnownNonZero(V, DL, 0, AC, CtxI, DT)) { - // As we recursed through GEPs to get here, we've incrementally checked - // that each step advanced by a multiple of the alignment. If our base is - // properly aligned, then the original offset accessed must also be. - APInt Offset(DL.getTypeStoreSizeInBits(V->getType()), 0); - return isAligned(V, Offset, Alignment, DL); - } - - if (CtxI) { - /// Look through assumes to see if both dereferencability and alignment can - /// be provent by an assume - RetainedKnowledge AlignRK; - RetainedKnowledge DerefRK; - if (getKnowledgeForValue( - V, {Attribute::Dereferenceable, Attribute::Alignment}, AC, - [&](RetainedKnowledge RK, Instruction *Assume, auto) { - if (!isValidAssumeForContext(Assume, CtxI)) - return false; - if (RK.AttrKind == Attribute::Alignment) - AlignRK = std::max(AlignRK, RK); - if (RK.AttrKind == Attribute::Dereferenceable) - DerefRK = std::max(DerefRK, RK); - if (AlignRK && DerefRK && AlignRK.ArgValue >= Alignment.value() && - DerefRK.ArgValue >= Size.getZExtValue()) - return true; // We have found what we needed so we stop looking - return false; // Other assumes may have better information. so - // keep looking - })) - return true; - } - /// TODO refactor this function to be able to search independently for - /// Dereferencability and Alignment requirements. - // For GEPs, determine if the indexing lands within the allocated object. if (const GEPOperator *GEP = dyn_cast(V)) { const Value *Base = GEP->getPointerOperand(); @@ -134,16 +77,41 @@ static bool isDereferenceableAndAlignedPointer( CtxI, AC, DT, TLI, Visited, MaxDepth); } - // For gc.relocate, look through relocations - if (const GCRelocateInst *RelocateInst = dyn_cast(V)) - return isDereferenceableAndAlignedPointer(RelocateInst->getDerivedPtr(), - Alignment, Size, DL, CtxI, AC, DT, - TLI, Visited, MaxDepth); + // bitcast instructions are no-ops as far as dereferenceability is concerned. + if (const BitCastOperator *BC = dyn_cast(V)) { + if (BC->getSrcTy()->isPointerTy()) + return isDereferenceableAndAlignedPointer( + BC->getOperand(0), Alignment, Size, DL, CtxI, AC, DT, TLI, + Visited, MaxDepth); + } - if (const AddrSpaceCastOperator *ASC = dyn_cast(V)) - return isDereferenceableAndAlignedPointer(ASC->getOperand(0), Alignment, + // Recurse into both hands of select. + if (const SelectInst *Sel = dyn_cast(V)) { + return isDereferenceableAndAlignedPointer(Sel->getTrueValue(), Alignment, + Size, DL, CtxI, AC, DT, TLI, + Visited, MaxDepth) && + isDereferenceableAndAlignedPointer(Sel->getFalseValue(), Alignment, Size, DL, CtxI, AC, DT, TLI, Visited, MaxDepth); + } + + bool CheckForNonNull, CheckForFreed; + APInt KnownDerefBytes(Size.getBitWidth(), + V->getPointerDereferenceableBytes(DL, CheckForNonNull, + CheckForFreed)); + if (KnownDerefBytes.getBoolValue() && KnownDerefBytes.uge(Size) && + !CheckForFreed) + if (!CheckForNonNull || isKnownNonZero(V, DL, 0, AC, CtxI, DT)) { + // As we recursed through GEPs to get here, we've incrementally checked + // that each step advanced by a multiple of the alignment. If our base is + // properly aligned, then the original offset accessed must also be. + APInt Offset(DL.getTypeStoreSizeInBits(V->getType()), 0); + return isAligned(V, Offset, Alignment, DL); + } + + /// TODO refactor this function to be able to search independently for + /// Dereferencability and Alignment requirements. + if (const auto *Call = dyn_cast(V)) { if (auto *RP = getArgumentAliasingToReturnedPointer(Call, true)) @@ -178,6 +146,40 @@ static bool isDereferenceableAndAlignedPointer( } } + // For gc.relocate, look through relocations + if (const GCRelocateInst *RelocateInst = dyn_cast(V)) + return isDereferenceableAndAlignedPointer(RelocateInst->getDerivedPtr(), + Alignment, Size, DL, CtxI, AC, DT, + TLI, Visited, MaxDepth); + + if (const AddrSpaceCastOperator *ASC = dyn_cast(V)) + return isDereferenceableAndAlignedPointer(ASC->getOperand(0), Alignment, + Size, DL, CtxI, AC, DT, TLI, + Visited, MaxDepth); + + if (CtxI) { + /// Look through assumes to see if both dereferencability and alignment can + /// be provent by an assume + RetainedKnowledge AlignRK; + RetainedKnowledge DerefRK; + if (getKnowledgeForValue( + V, {Attribute::Dereferenceable, Attribute::Alignment}, AC, + [&](RetainedKnowledge RK, Instruction *Assume, auto) { + if (!isValidAssumeForContext(Assume, CtxI)) + return false; + if (RK.AttrKind == Attribute::Alignment) + AlignRK = std::max(AlignRK, RK); + if (RK.AttrKind == Attribute::Dereferenceable) + DerefRK = std::max(DerefRK, RK); + if (AlignRK && DerefRK && AlignRK.ArgValue >= Alignment.value() && + DerefRK.ArgValue >= Size.getZExtValue()) + return true; // We have found what we needed so we stop looking + return false; // Other assumes may have better information. so + // keep looking + })) + return true; + } + // If we don't know, assume the worst. return false; }