Skip to content

Commit

Permalink
[MemoryBuiltins] Add getReallocatedOperand() function (NFC)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
nikic committed Jul 21, 2022
1 parent 46e6dd8 commit 1f69503
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 17 deletions.
7 changes: 3 additions & 4 deletions llvm/include/llvm/Analysis/MemoryBuiltins.h
Expand Up @@ -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.
//
Expand Down
15 changes: 9 additions & 6 deletions llvm/lib/Analysis/MemoryBuiltins.cpp
Expand Up @@ -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
Expand Down
12 changes: 5 additions & 7 deletions llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
Expand Up @@ -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);
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 1f69503

Please sign in to comment.