Analysis: Reorder code in isDereferenceableAndAlignedPointer

GEPs should be the most common and basic case, so try that first.
This commit is contained in:
Matt Arsenault 2022-09-19 14:04:12 -04:00
parent ff2b60bbcb
commit 4f2f7e84ff
1 changed files with 66 additions and 64 deletions

View File

@ -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<SelectInst>(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<BitCastOperator>(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<GEPOperator>(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<GCRelocateInst>(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<BitCastOperator>(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<AddrSpaceCastOperator>(V))
return isDereferenceableAndAlignedPointer(ASC->getOperand(0), Alignment,
// Recurse into both hands of select.
if (const SelectInst *Sel = dyn_cast<SelectInst>(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<CallBase>(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<GCRelocateInst>(V))
return isDereferenceableAndAlignedPointer(RelocateInst->getDerivedPtr(),
Alignment, Size, DL, CtxI, AC, DT,
TLI, Visited, MaxDepth);
if (const AddrSpaceCastOperator *ASC = dyn_cast<AddrSpaceCastOperator>(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;
}