From: Nikita Popov Date: Thu, 21 Jul 2022 12:54:16 +0000 (+0200) Subject: [MemoryBuiltins] Add getReallocatedOperand() function (NFC) X-Git-Tag: upstream/15.0.7~970 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=1f69503107f2103106b8f7561d4fe7a7efa51b9f;p=platform%2Fupstream%2Fllvm.git [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. --- diff --git a/llvm/include/llvm/Analysis/MemoryBuiltins.h b/llvm/include/llvm/Analysis/MemoryBuiltins.h index 29b0cea..422f63d 100644 --- a/llvm/include/llvm/Analysis/MemoryBuiltins.h +++ b/llvm/include/llvm/Analysis/MemoryBuiltins.h @@ -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. // diff --git a/llvm/lib/Analysis/MemoryBuiltins.cpp b/llvm/lib/Analysis/MemoryBuiltins.cpp index b9e73c2..e91873f 100644 --- a/llvm/lib/Analysis/MemoryBuiltins.cpp +++ b/llvm/lib/Analysis/MemoryBuiltins.cpp @@ -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 diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp index f401a1e..71c763de 100644 --- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -2808,7 +2808,7 @@ static bool isAllocSiteRemovable(Instruction *AI, continue; } - if (isReallocLikeFn(I, &TLI) && + if (getReallocatedOperand(cast(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(Op)) { - if (CI->hasOneUse() && isReallocLikeFn(CI, &TLI)) { - return eraseInstFromFunction( - *replaceInstUsesWith(*CI, CI->getOperand(0))); - } - } + CallInst *CI = dyn_cast(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