diff --git a/llvm/include/llvm/Analysis/Loads.h b/llvm/include/llvm/Analysis/Loads.h --- a/llvm/include/llvm/Analysis/Loads.h +++ b/llvm/include/llvm/Analysis/Loads.h @@ -155,6 +155,14 @@ BasicBlock::iterator &ScanFrom, unsigned MaxInstsToScan, AAResults *AA, bool *IsLoadCSE, unsigned *NumScanedInst); + +/// Returns true if a pointer value \p A can be replace with another pointer +/// value \B if they are deemed equal through some means (e.g. information from +/// conditions). +// NOTE: the current implementations is incomplete and unsound. It does not +// reject all invalid cases yet, but will be made stricter in the future. +bool canReplacePointersIfEqual(Value *A, Value *B, const DataLayout &DL, + Instruction *CtxI); } #endif diff --git a/llvm/lib/Analysis/Loads.cpp b/llvm/lib/Analysis/Loads.cpp --- a/llvm/lib/Analysis/Loads.cpp +++ b/llvm/lib/Analysis/Loads.cpp @@ -503,3 +503,23 @@ // block. return nullptr; } + +bool llvm::canReplacePointersIfEqual(Value *A, Value *B, const DataLayout &DL, + Instruction *CtxI) { + Type *Ty = A->getType(); + assert(Ty == B->getType() && Ty->isPointerTy() && + "values must have matching pointer types"); + + // NOTE: The checks in the function are incomplete and currently miss illegal + // cases! The current implementation is a starting point and the + // implementation should be made stricter over time. + if (auto *C = dyn_cast(B)) { + // Do not allow replacing a pointer with a constant pointer, unless it is + // either null or at least one byte is dereferenceable. + APInt OneByte(DL.getPointerTypeSizeInBits(A->getType()), 1); + return C->isNullValue() || + isDereferenceableAndAlignedPointer(B, Align(1), OneByte, DL, CtxI); + } + + return true; +}