aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Analysis/MemoryBuiltins.cpp
diff options
context:
space:
mode:
authorNikita Popov <npopov@redhat.com>2024-08-09 14:54:59 +0200
committerNikita Popov <npopov@redhat.com>2024-08-09 15:22:54 +0200
commit195362929cd79c0202f73bcbab9a09b8a1a3beaa (patch)
tree8c9cf2646a0cc3b6d86b2bcbaa50e39687e62313 /llvm/lib/Analysis/MemoryBuiltins.cpp
parentfff78a51ee1413676c1aa772532c925dcf313527 (diff)
downloadllvm-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.cpp59
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))