@@ -2027,15 +2027,45 @@ struct DSEState {
2027
2027
auto *InnerCallee = Malloc->getCalledFunction ();
2028
2028
if (!InnerCallee)
2029
2029
return false ;
2030
- LibFunc Func;
2030
+ LibFunc Func = NotLibFunc ;
2031
2031
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
+ }
2034
2036
// Gracefully handle malloc with unexpected memory attributes.
2035
2037
auto *MallocDef = dyn_cast_or_null<MemoryDef>(MSSA.getMemoryAccess (Malloc));
2036
2038
if (!MallocDef)
2037
2039
return false ;
2038
2040
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
+
2039
2069
auto shouldCreateCalloc = [](CallInst *Malloc, CallInst *Memset) {
2040
2070
// Check for br(icmp ptr, null), truebb, falsebb) pattern at the end
2041
2071
// of malloc block
@@ -2054,6 +2084,18 @@ struct DSEState {
2054
2084
return false ;
2055
2085
return true ;
2056
2086
};
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
+ };
2057
2099
2058
2100
if (Malloc->getOperand (0 ) != MemSet->getLength ())
2059
2101
return false ;
@@ -2062,10 +2104,19 @@ struct DSEState {
2062
2104
!memoryIsNotModifiedBetween (Malloc, MemSet, BatchAA, DL, &DT))
2063
2105
return false ;
2064
2106
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
+ }
2069
2120
if (!Calloc)
2070
2121
return false ;
2071
2122
0 commit comments