Skip to content

Commit f94c92c

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

File tree

3 files changed

+58
-8
lines changed

3 files changed

+58
-8
lines changed

llvm/docs/LangRef.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1954,6 +1954,10 @@ For example:
19541954
The first three options are mutually exclusive, and the remaining options
19551955
describe more details of how the function behaves. The remaining options
19561956
are invalid for "free"-type functions.
1957+
``"alloc-variant-zeroed"="FUNCTION"``
1958+
This attribute indicates that another function is equivalent to an allocator function,
1959+
but returns zeroed memory. The function must have "zeroed" allocation behavior,
1960+
the same ``alloc-family``, and take exactly the same arguments.
19571961
``allocsize(<EltSizeParam>[, <NumEltsParam>])``
19581962
This attribute indicates that the annotated function will always return at
19591963
least a given number of bytes (or null). Its arguments are zero-indexed

llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2028,9 +2028,19 @@ struct DSEState {
20282028
if (!InnerCallee)
20292029
return false;
20302030
LibFunc Func;
2031+
std::optional<StringRef> ZeroedVariantName = std::nullopt;
20312032
if (!TLI.getLibFunc(*InnerCallee, Func) || !TLI.has(Func) ||
2032-
Func != LibFunc_malloc)
2033-
return false;
2033+
Func != LibFunc_malloc) {
2034+
if (!Malloc->hasFnAttr("alloc-variant-zeroed") ||
2035+
Malloc->getFnAttr("alloc-variant-zeroed")
2036+
.getValueAsString()
2037+
.empty()) {
2038+
return false;
2039+
}
2040+
ZeroedVariantName =
2041+
Malloc->getFnAttr("alloc-variant-zeroed").getValueAsString();
2042+
}
2043+
20342044
// Gracefully handle malloc with unexpected memory attributes.
20352045
auto *MallocDef = dyn_cast_or_null<MemoryDef>(MSSA.getMemoryAccess(Malloc));
20362046
if (!MallocDef)
@@ -2057,15 +2067,38 @@ struct DSEState {
20572067

20582068
if (Malloc->getOperand(0) != MemSet->getLength())
20592069
return false;
2060-
if (!shouldCreateCalloc(Malloc, MemSet) ||
2061-
!DT.dominates(Malloc, MemSet) ||
2070+
if (!shouldCreateCalloc(Malloc, MemSet) || !DT.dominates(Malloc, MemSet) ||
20622071
!memoryIsNotModifiedBetween(Malloc, MemSet, BatchAA, DL, &DT))
20632072
return false;
20642073
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());
2074+
assert(Func == LibFunc_malloc || ZeroedVariantName.has_value());
2075+
Value *Calloc = nullptr;
2076+
if (ZeroedVariantName.has_value()) {
2077+
auto *ZeroedVariant =
2078+
Malloc->getModule()->getFunction(*ZeroedVariantName);
2079+
if (!ZeroedVariant)
2080+
return false;
2081+
auto Attributes = ZeroedVariant->getAttributes();
2082+
auto MallocFamily = getAllocationFamily(Malloc, &TLI);
2083+
if (MallocFamily &&
2084+
*MallocFamily !=
2085+
Attributes.getFnAttr("alloc-family").getValueAsString())
2086+
return false;
2087+
if (!Attributes.hasFnAttr(Attribute::AllocKind) ||
2088+
(Attributes.getAllocKind() & AllocFnKind::Zeroed) ==
2089+
AllocFnKind::Unknown)
2090+
return false;
2091+
2092+
SmallVector<Value *, 3> Args;
2093+
for (unsigned I = 0; I < Malloc->arg_size(); I++)
2094+
Args.push_back(Malloc->getArgOperand(I));
2095+
Calloc = IRB.CreateCall(ZeroedVariant, Args, *ZeroedVariantName);
2096+
} else {
2097+
Type *SizeTTy = Malloc->getArgOperand(0)->getType();
2098+
Calloc =
2099+
emitCalloc(ConstantInt::get(SizeTTy, 1), Malloc->getArgOperand(0),
2100+
IRB, TLI, Malloc->getType()->getPointerAddressSpace());
2101+
}
20692102
if (!Calloc)
20702103
return false;
20712104

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" "alloc-variant-zeroed"="customalloc_zeroed"
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)