diff options
author | Nikita Popov <npopov@redhat.com> | 2024-08-09 14:54:59 +0200 |
---|---|---|
committer | Nikita Popov <npopov@redhat.com> | 2024-08-09 15:22:54 +0200 |
commit | 195362929cd79c0202f73bcbab9a09b8a1a3beaa (patch) | |
tree | 8c9cf2646a0cc3b6d86b2bcbaa50e39687e62313 /llvm/lib/Analysis/MemoryBuiltins.cpp | |
parent | fff78a51ee1413676c1aa772532c925dcf313527 (diff) | |
download | llvm-195362929cd79c0202f73bcbab9a09b8a1a3beaa.zip llvm-195362929cd79c0202f73bcbab9a09b8a1a3beaa.tar.gz llvm-195362929cd79c0202f73bcbab9a09b8a1a3beaa.tar.bz2 |
[MemoryBuiltins] Handle allocator attributes on call-site
We should handle allocator attributes not only on function
declarations, but also on the call-site. That way we can e.g.
also optimize cases where the allocator function is a virtual
function call.
This was already supported in some of the MemoryBuiltins helpers,
but not all of them. This adds support for allocsize, alloc-family
and allockind("free").
Diffstat (limited to 'llvm/lib/Analysis/MemoryBuiltins.cpp')
-rw-r--r-- | llvm/lib/Analysis/MemoryBuiltins.cpp | 59 |
1 files changed, 28 insertions, 31 deletions
diff --git a/llvm/lib/Analysis/MemoryBuiltins.cpp b/llvm/lib/Analysis/MemoryBuiltins.cpp index 1edc51e..6fbdda1 100644 --- a/llvm/lib/Analysis/MemoryBuiltins.cpp +++ b/llvm/lib/Analysis/MemoryBuiltins.cpp @@ -240,21 +240,18 @@ getAllocationData(const Value *V, AllocType AllocTy, } static std::optional<AllocFnsTy> -getAllocationSize(const Value *V, const TargetLibraryInfo *TLI) { +getAllocationSize(const CallBase *CB, const TargetLibraryInfo *TLI) { bool IsNoBuiltinCall; - const Function *Callee = - getCalledFunction(V, IsNoBuiltinCall); - if (!Callee) - return std::nullopt; - - // Prefer to use existing information over allocsize. This will give us an - // accurate AllocTy. - if (!IsNoBuiltinCall) + const Function *Callee = getCalledFunction(CB, IsNoBuiltinCall); + if (Callee && !IsNoBuiltinCall) { + // Prefer to use existing information over allocsize. This will give us an + // accurate AllocTy. if (std::optional<AllocFnsTy> Data = getAllocationDataForFunction(Callee, AnyAlloc, TLI)) return Data; + } - Attribute Attr = Callee->getFnAttribute(Attribute::AllocSize); + Attribute Attr = CB->getFnAttr(Attribute::AllocSize); if (Attr == Attribute()) return std::nullopt; @@ -264,7 +261,7 @@ getAllocationSize(const Value *V, const TargetLibraryInfo *TLI) { // Because allocsize only tells us how many bytes are allocated, we're not // really allowed to assume anything, so we use MallocLike. Result.AllocTy = MallocLike; - Result.NumParams = Callee->getNumOperands(); + Result.NumParams = CB->arg_size(); Result.FstParam = Args.first; Result.SndParam = Args.second.value_or(-1); // Allocsize has no way to specify an alignment argument @@ -512,19 +509,20 @@ std::optional<StringRef> llvm::getAllocationFamily(const Value *I, const TargetLibraryInfo *TLI) { bool IsNoBuiltin; const Function *Callee = getCalledFunction(I, IsNoBuiltin); - if (Callee == nullptr || IsNoBuiltin) - return std::nullopt; - LibFunc TLIFn; - - if (TLI && TLI->getLibFunc(*Callee, TLIFn) && TLI->has(TLIFn)) { - // Callee is some known library function. - const auto AllocData = getAllocationDataForFunction(Callee, AnyAlloc, TLI); - if (AllocData) - return mangledNameForMallocFamily(AllocData->Family); - const auto FreeData = getFreeFunctionDataForFunction(Callee, TLIFn); - if (FreeData) - return mangledNameForMallocFamily(FreeData->Family); + if (Callee && !IsNoBuiltin) { + LibFunc TLIFn; + if (TLI && TLI->getLibFunc(*Callee, TLIFn) && TLI->has(TLIFn)) { + // Callee is some known library function. + const auto AllocData = + getAllocationDataForFunction(Callee, AnyAlloc, TLI); + if (AllocData) + return mangledNameForMallocFamily(AllocData->Family); + const auto FreeData = getFreeFunctionDataForFunction(Callee, TLIFn); + if (FreeData) + return mangledNameForMallocFamily(FreeData->Family); + } } + // Callee isn't a known library function, still check attributes. if (checkFnAllocKind(I, AllocFnKind::Free | AllocFnKind::Alloc | AllocFnKind::Realloc)) { @@ -558,14 +556,13 @@ bool llvm::isLibFreeFunction(const Function *F, const LibFunc TLIFn) { Value *llvm::getFreedOperand(const CallBase *CB, const TargetLibraryInfo *TLI) { bool IsNoBuiltinCall; const Function *Callee = getCalledFunction(CB, IsNoBuiltinCall); - if (Callee == nullptr || IsNoBuiltinCall) - return nullptr; - - LibFunc TLIFn; - if (TLI && TLI->getLibFunc(*Callee, TLIFn) && TLI->has(TLIFn) && - isLibFreeFunction(Callee, TLIFn)) { - // All currently supported free functions free the first argument. - return CB->getArgOperand(0); + if (Callee && !IsNoBuiltinCall) { + LibFunc TLIFn; + if (TLI && TLI->getLibFunc(*Callee, TLIFn) && TLI->has(TLIFn) && + isLibFreeFunction(Callee, TLIFn)) { + // All currently supported free functions free the first argument. + return CB->getArgOperand(0); + } } if (checkFnAllocKind(CB, AllocFnKind::Free)) |