[MemoryBuiltins] Add getReallocatedOperand() function (NFC)

Replace the value-accepting isReallocLikeFn() overload with a
getReallocatedOperand() function, which returns which operand is
the one being reallocated. Currently, this is always the first one,
but once allockind(realloc) is respected, the reallocated operand
will be determined by the allocptr parameter attribute.
This commit is contained in:
Nikita Popov 2022-07-21 14:54:16 +02:00
parent 46e6dd84b7
commit 1f69503107
3 changed files with 17 additions and 17 deletions

View File

@ -65,14 +65,13 @@ bool isMallocOrCallocLikeFn(const Value *V, const TargetLibraryInfo *TLI);
/// allocates memory (either malloc, calloc, or strdup like).
bool isAllocLikeFn(const Value *V, const TargetLibraryInfo *TLI);
/// Tests if a value is a call or invoke to a library function that
/// reallocates memory (e.g., realloc).
bool isReallocLikeFn(const Value *V, const TargetLibraryInfo *TLI);
/// Tests if a function is a call or invoke to a library function that
/// reallocates memory (e.g., realloc).
bool isReallocLikeFn(const Function *F, const TargetLibraryInfo *TLI);
/// If this is a call to a realloc function, return the reallocated operand.
Value *getReallocatedOperand(const CallBase *CB, const TargetLibraryInfo *TLI);
//===----------------------------------------------------------------------===//
// free Call Utility Functions.
//

View File

@ -312,18 +312,21 @@ bool llvm::isAllocLikeFn(const Value *V, const TargetLibraryInfo *TLI) {
return getAllocationData(V, AllocLike, TLI).has_value();
}
/// Tests if a value is a call or invoke to a library function that
/// reallocates memory (e.g., realloc).
bool llvm::isReallocLikeFn(const Value *V, const TargetLibraryInfo *TLI) {
return getAllocationData(V, ReallocLike, TLI).has_value();
}
/// Tests if a functions is a call or invoke to a library function that
/// reallocates memory (e.g., realloc).
bool llvm::isReallocLikeFn(const Function *F, const TargetLibraryInfo *TLI) {
return getAllocationDataForFunction(F, ReallocLike, TLI).has_value();
}
Value *llvm::getReallocatedOperand(const CallBase *CB,
const TargetLibraryInfo *TLI) {
if (getAllocationData(CB, ReallocLike, TLI).has_value()) {
// All currently supported realloc functions reallocate the first argument.
return CB->getArgOperand(0);
}
return nullptr;
}
bool llvm::isRemovableAlloc(const CallBase *CB, const TargetLibraryInfo *TLI) {
// Note: Removability is highly dependent on the source language. For
// example, recent C++ requires direct calls to the global allocation

View File

@ -2808,7 +2808,7 @@ static bool isAllocSiteRemovable(Instruction *AI,
continue;
}
if (isReallocLikeFn(I, &TLI) &&
if (getReallocatedOperand(cast<CallBase>(I), &TLI) == PI &&
getAllocationFamily(I, &TLI) == Family) {
assert(Family);
Users.emplace_back(I);
@ -3050,12 +3050,10 @@ Instruction *InstCombinerImpl::visitFree(CallInst &FI, Value *Op) {
// If we had free(realloc(...)) with no intervening uses, then eliminate the
// realloc() entirely.
if (CallInst *CI = dyn_cast<CallInst>(Op)) {
if (CI->hasOneUse() && isReallocLikeFn(CI, &TLI)) {
return eraseInstFromFunction(
*replaceInstUsesWith(*CI, CI->getOperand(0)));
}
}
CallInst *CI = dyn_cast<CallInst>(Op);
if (CI && CI->hasOneUse())
if (Value *ReallocatedOp = getReallocatedOperand(CI, &TLI))
return eraseInstFromFunction(*replaceInstUsesWith(*CI, ReallocatedOp));
// If we optimize for code size, try to move the call to free before the null
// test so that simplify cfg can remove the empty block and dead code