Skip to content

Commit 6e08081

Browse files
jamie-osecclubby789
authored andcommitted
Support non-malloc functions in malloc+memset->calloc fold
1 parent ee3610e commit 6e08081

File tree

2 files changed

+71
-7
lines changed

2 files changed

+71
-7
lines changed

llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp

Lines changed: 58 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2027,15 +2027,45 @@ struct DSEState {
20272027
auto *InnerCallee = Malloc->getCalledFunction();
20282028
if (!InnerCallee)
20292029
return false;
2030-
LibFunc Func;
2030+
LibFunc Func = NotLibFunc;
20312031
if (!TLI.getLibFunc(*InnerCallee, Func) || !TLI.has(Func) ||
2032-
Func != LibFunc_malloc)
2033-
return false;
2032+
Func != LibFunc_malloc) {
2033+
if (!isAllocLikeFn(Malloc, &TLI))
2034+
return false;
2035+
}
20342036
// Gracefully handle malloc with unexpected memory attributes.
20352037
auto *MallocDef = dyn_cast_or_null<MemoryDef>(MSSA.getMemoryAccess(Malloc));
20362038
if (!MallocDef)
20372039
return false;
20382040

2041+
// If the allocation is not a malloc, search for a matching zero-alloc
2042+
// function
2043+
Function *ZeroedAlloc = nullptr;
2044+
2045+
if (Func != LibFunc_malloc) {
2046+
auto OptFamily = getAllocationFamily(Malloc, &TLI);
2047+
if (!OptFamily)
2048+
return false;
2049+
auto &Family = *OptFamily;
2050+
auto *Module = InnerCallee->getParent();
2051+
for (auto &ModuleFunc : Module->functions()) {
2052+
auto Attributes = ModuleFunc.getAttributes();
2053+
if (!Attributes.hasFnAttr("alloc-family") ||
2054+
Attributes.getFnAttr("alloc-family").getValueAsString() != Family ||
2055+
!Attributes.hasFnAttr(llvm::Attribute::AllocKind) ||
2056+
(Attributes.getAllocKind() & AllocFnKind::Zeroed) ==
2057+
AllocFnKind::Unknown)
2058+
continue;
2059+
ZeroedAlloc = &ModuleFunc;
2060+
break;
2061+
}
2062+
if (!ZeroedAlloc)
2063+
return false;
2064+
}
2065+
2066+
assert((Func == LibFunc_malloc || ZeroedAlloc) &&
2067+
"didn't resolve allocation functions");
2068+
20392069
auto shouldCreateCalloc = [](CallInst *Malloc, CallInst *Memset) {
20402070
// Check for br(icmp ptr, null), truebb, falsebb) pattern at the end
20412071
// of malloc block
@@ -2054,6 +2084,18 @@ struct DSEState {
20542084
return false;
20552085
return true;
20562086
};
2087+
auto RemapArgs =
2088+
[&ZeroedAlloc](CallInst *Malloc) -> SmallVector<Value *, 3> {
2089+
// If the arg counts match, use the existing args
2090+
if (Malloc->arg_size() == ZeroedAlloc->arg_size()) {
2091+
SmallVector<Value *, 3> SV;
2092+
for (unsigned I = 0; I < Malloc->arg_size(); I++)
2093+
SV.push_back(Malloc->getArgOperand(I));
2094+
return SV;
2095+
};
2096+
// Unknown mapping
2097+
return {};
2098+
};
20572099

20582100
if (Malloc->getOperand(0) != MemSet->getLength())
20592101
return false;
@@ -2062,10 +2104,19 @@ struct DSEState {
20622104
!memoryIsNotModifiedBetween(Malloc, MemSet, BatchAA, DL, &DT))
20632105
return false;
20642106
IRBuilder<> IRB(Malloc);
2065-
Type *SizeTTy = Malloc->getArgOperand(0)->getType();
2066-
auto *Calloc =
2067-
emitCalloc(ConstantInt::get(SizeTTy, 1), Malloc->getArgOperand(0), IRB,
2068-
TLI, Malloc->getType()->getPointerAddressSpace());
2107+
Value *Calloc;
2108+
if (Func == LibFunc_malloc) {
2109+
Type *SizeTTy = Malloc->getArgOperand(0)->getType();
2110+
Calloc =
2111+
emitCalloc(ConstantInt::get(SizeTTy, 1), Malloc->getArgOperand(0),
2112+
IRB, TLI, Malloc->getType()->getPointerAddressSpace());
2113+
} else {
2114+
auto Args = RemapArgs(Malloc);
2115+
if (Args.empty())
2116+
return false;
2117+
Calloc = IRB.CreateCall(FunctionCallee(ZeroedAlloc), Args,
2118+
ZeroedAlloc->getName());
2119+
}
20692120
if (!Calloc)
20702121
return false;
20712122

llvm/test/Transforms/DeadStoreElimination/noop-stores.ll

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,19 @@ define ptr @notmalloc_memset(i64 %size, ptr %notmalloc) {
374374
ret ptr %call1
375375
}
376376

377+
; This should create a customalloc_zeroed
378+
define ptr @customalloc_memset(i64 %size, i64 %align) {
379+
; CHECK-LABEL: @customalloc_memset
380+
; CHECK-NEXT: [[CALL:%.*]] = call ptr @customalloc_zeroed(i64 [[SIZE:%.*]], i64 [[ALIGN:%.*]])
381+
; CHECK-NEXT: ret ptr [[CALL]]
382+
%call = call ptr @customalloc(i64 %size, i64 %align)
383+
call void @llvm.memset.p0.i64(ptr %call, i8 0, i64 %size, i1 false)
384+
ret ptr %call
385+
}
386+
387+
declare ptr @customalloc(i64, i64) allockind("alloc") "alloc-family"="customalloc"
388+
declare ptr @customalloc_zeroed(i64, i64) allockind("alloc,zeroed") "alloc-family"="customalloc"
389+
377390
; This should not create recursive call to calloc.
378391
define ptr @calloc(i64 %nmemb, i64 %size) inaccessiblememonly {
379392
; CHECK-LABEL: @calloc(

0 commit comments

Comments
 (0)