@@ -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
0 commit comments