Lines Matching +full:compute +full:- +full:cb
1 //===- MemoryBuiltins.cpp - Identify calls to memory builtins -------------===//
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
12 //===----------------------------------------------------------------------===//
52 #define DEBUG_TYPE "memory-builtins"
55 "object-size-offset-visitor-max-visit-instructions",
108 // First and Second size parameters (or -1 if unused)
116 // clang-format off
120 …{LibFunc_Znwj, {OpNewLike, 1, 0, -1, -1, MallocFamily::CPPNew…
121 …{LibFunc_ZnwjRKSt9nothrow_t, {MallocLike, 2, 0, -1, -1, MallocFamily::CPPNew…
122 …{LibFunc_ZnwjSt11align_val_t, {OpNewLike, 2, 0, -1, 1, MallocFamily::CPPNew…
123 …{LibFunc_ZnwjSt11align_val_tRKSt9nothrow_t, {MallocLike, 3, 0, -1, 1, MallocFamily::CPPNew…
124 …{LibFunc_Znwm, {OpNewLike, 1, 0, -1, -1, MallocFamily::CPPNew…
125 …{LibFunc_Znwm12__hot_cold_t, {OpNewLike, 2, 0, -1, -1, MallocFamily::CPPN…
126 …{LibFunc_ZnwmRKSt9nothrow_t, {MallocLike, 2, 0, -1, -1, MallocFamily::CPPNew…
127 …{LibFunc_ZnwmRKSt9nothrow_t12__hot_cold_t, {MallocLike, 3, 0, -1, -1, MallocFamily::CP…
128 …{LibFunc_ZnwmSt11align_val_t, {OpNewLike, 2, 0, -1, 1, MallocFamily::CPPNew…
129 …{LibFunc_ZnwmSt11align_val_t12__hot_cold_t, {OpNewLike, 3, 0, -1, 1, MallocFamily::CPPNe…
130 …{LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t, {MallocLike, 3, 0, -1, 1, MallocFamily::CPPNew…
131 …{LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t12__hot_cold_t, {MallocLike, 4, 0, -1, 1, MallocFamily…
132 …{LibFunc_Znaj, {OpNewLike, 1, 0, -1, -1, MallocFamily::CPPNew…
133 …{LibFunc_ZnajRKSt9nothrow_t, {MallocLike, 2, 0, -1, -1, MallocFamily::CPPNew…
134 …{LibFunc_ZnajSt11align_val_t, {OpNewLike, 2, 0, -1, 1, MallocFamily::CPPNew…
135 …{LibFunc_ZnajSt11align_val_tRKSt9nothrow_t, {MallocLike, 3, 0, -1, 1, MallocFamily::CPPNew…
136 …{LibFunc_Znam, {OpNewLike, 1, 0, -1, -1, MallocFamily::CPPNew…
137 …{LibFunc_Znam12__hot_cold_t, {OpNewLike, 2, 0, -1, -1, MallocFamily::CPPN…
138 …{LibFunc_ZnamRKSt9nothrow_t, {MallocLike, 2, 0, -1, -1, MallocFamily::CPPNew…
139 …{LibFunc_ZnamRKSt9nothrow_t12__hot_cold_t, {MallocLike, 3, 0, -1, -1, MallocFamily::CP…
140 …{LibFunc_ZnamSt11align_val_t, {OpNewLike, 2, 0, -1, 1, MallocFamily::CPPNew…
141 …{LibFunc_ZnamSt11align_val_t12__hot_cold_t, {OpNewLike, 3, 0, -1, 1, MallocFamily::CPPNe…
142 …{LibFunc_ZnamSt11align_val_tRKSt9nothrow_t, {MallocLike, 3, 0, -1, 1, MallocFamily::CPPNew…
143 …{LibFunc_ZnamSt11align_val_tRKSt9nothrow_t12__hot_cold_t, {MallocLike, 4, 0, -1, 1, MallocFamily…
144 …{LibFunc_msvc_new_int, {OpNewLike, 1, 0, -1, -1, MallocFamily::MSVCNe…
145 …{LibFunc_msvc_new_int_nothrow, {MallocLike, 2, 0, -1, -1, MallocFamily::MSVCNe…
146 …{LibFunc_msvc_new_longlong, {OpNewLike, 1, 0, -1, -1, MallocFamily::MSVCNe…
147 …{LibFunc_msvc_new_longlong_nothrow, {MallocLike, 2, 0, -1, -1, MallocFamily::MSVCNe…
148 …{LibFunc_msvc_new_array_int, {OpNewLike, 1, 0, -1, -1, MallocFamily::MSVCAr…
149 …{LibFunc_msvc_new_array_int_nothrow, {MallocLike, 2, 0, -1, -1, MallocFamily::MSVCAr…
150 …{LibFunc_msvc_new_array_longlong, {OpNewLike, 1, 0, -1, -1, MallocFamily::MSVCAr…
151 …{LibFunc_msvc_new_array_longlong_nothrow, {MallocLike, 2, 0, -1, -1, MallocFamily::MSVCAr…
152 …{LibFunc_strdup, {StrDupLike, 1, -1, -1, -1, MallocFamily::Malloc…
153 …{LibFunc_dunder_strdup, {StrDupLike, 1, -1, -1, -1, MallocFamily::Malloc…
154 …{LibFunc_strndup, {StrDupLike, 2, 1, -1, -1, MallocFamily::Malloc…
155 …{LibFunc_dunder_strndup, {StrDupLike, 2, 1, -1, -1, MallocFamily::Malloc…
156 …{LibFunc___kmpc_alloc_shared, {MallocLike, 1, 0, -1, -1, MallocFamily::KmpcAl…
158 // clang-format on
166 const auto *CB = dyn_cast<CallBase>(V); in getCalledFunction() local
167 if (!CB) in getCalledFunction()
170 IsNoBuiltin = CB->isNoBuiltin(); in getCalledFunction()
172 if (const Function *Callee = CB->getCalledFunction()) in getCalledFunction()
184 if (!Callee->getReturnType()->isPointerTy()) in getAllocationDataForFunction()
189 if (!TLI || !TLI->getLibFunc(*Callee, TLIFn) || !TLI->has(TLIFn)) in getAllocationDataForFunction()
200 const AllocFnsTy *FnData = &Iter->second; in getAllocationDataForFunction()
201 if ((FnData->AllocTy & AllocTy) != FnData->AllocTy) in getAllocationDataForFunction()
205 int FstParam = FnData->FstParam; in getAllocationDataForFunction()
206 int SndParam = FnData->SndParam; in getAllocationDataForFunction()
207 FunctionType *FTy = Callee->getFunctionType(); in getAllocationDataForFunction()
209 if (FTy->getReturnType()->isPointerTy() && in getAllocationDataForFunction()
210 FTy->getNumParams() == FnData->NumParams && in getAllocationDataForFunction()
212 (FTy->getParamType(FstParam)->isIntegerTy(32) || in getAllocationDataForFunction()
213 FTy->getParamType(FstParam)->isIntegerTy(64))) && in getAllocationDataForFunction()
215 FTy->getParamType(SndParam)->isIntegerTy(32) || in getAllocationDataForFunction()
216 FTy->getParamType(SndParam)->isIntegerTy(64))) in getAllocationDataForFunction()
257 Attribute Attr = Callee->getFnAttribute(Attribute::AllocSize); in getAllocationSize()
267 Result.NumParams = Callee->getNumOperands(); in getAllocationSize()
269 Result.SndParam = Args.second.value_or(-1); in getAllocationSize()
271 Result.AlignParam = -1; in getAllocationSize()
276 if (const auto *CB = dyn_cast<CallBase>(V)) { in getAllocFnKind() local
277 Attribute Attr = CB->getFnAttr(Attribute::AllocKind); in getAllocFnKind()
285 return F->getAttributes().getAllocKind(); in getAllocFnKind()
336 Value *llvm::getReallocatedOperand(const CallBase *CB) { in getReallocatedOperand() argument
337 if (checkFnAllocKind(CB, AllocFnKind::Realloc)) in getReallocatedOperand()
338 return CB->getArgOperandWithAttribute(Attribute::AllocatedPointer); in getReallocatedOperand()
342 bool llvm::isRemovableAlloc(const CallBase *CB, const TargetLibraryInfo *TLI) { in isRemovableAlloc() argument
350 return isAllocLikeFn(CB, TLI); in isRemovableAlloc()
356 if (FnData && FnData->AlignParam >= 0) { in getAllocAlignment()
357 return V->getOperand(FnData->AlignParam); in getAllocAlignment()
359 return V->getArgOperandWithAttribute(Attribute::AllocAlign); in getAllocAlignment()
362 /// When we're compiling N-bit code, and the user uses parameters that are
363 /// greater than N bits (e.g. uint64_t on a 32-bit build), we can run into
379 llvm::getAllocSize(const CallBase *CB, const TargetLibraryInfo *TLI, in getAllocSize() argument
383 std::optional<AllocFnsTy> FnData = getAllocationSize(CB, TLI); in getAllocSize()
389 auto &DL = CB->getDataLayout(); in getAllocSize()
390 const unsigned IntTyBits = DL.getIndexTypeSizeInBits(CB->getType()); in getAllocSize()
392 // Handle strdup-like functions separately. in getAllocSize()
393 if (FnData->AllocTy == StrDupLike) { in getAllocSize()
394 APInt Size(IntTyBits, GetStringLength(Mapper(CB->getArgOperand(0)))); in getAllocSize()
399 if (FnData->FstParam > 0) { in getAllocSize()
401 dyn_cast<ConstantInt>(Mapper(CB->getArgOperand(FnData->FstParam))); in getAllocSize()
405 APInt MaxSize = Arg->getValue().zext(IntTyBits); in getAllocSize()
413 dyn_cast<ConstantInt>(Mapper(CB->getArgOperand(FnData->FstParam))); in getAllocSize()
417 APInt Size = Arg->getValue(); in getAllocSize()
422 if (FnData->SndParam < 0) in getAllocSize()
425 Arg = dyn_cast<ConstantInt>(Mapper(CB->getArgOperand(FnData->SndParam))); in getAllocSize()
429 APInt NumElems = Arg->getValue(); in getAllocSize()
466 // clang-format off
498 // clang-format on
508 return Iter->second; in getFreeFunctionDataForFunction()
519 if (TLI && TLI->getLibFunc(*Callee, TLIFn) && TLI->has(TLIFn)) { in getAllocationFamily()
523 return mangledNameForMallocFamily(AllocData->Family); in getAllocationFamily()
526 return mangledNameForMallocFamily(FreeData->Family); in getAllocationFamily()
531 Attribute Attr = cast<CallBase>(I)->getFnAttr("alloc-family"); in getAllocationFamily()
538 /// isLibFreeFunction - Returns true if the function is a builtin free()
547 FunctionType *FTy = F->getFunctionType(); in isLibFreeFunction()
548 if (!FTy->getReturnType()->isVoidTy()) in isLibFreeFunction()
550 if (FTy->getNumParams() != FnData->NumParams) in isLibFreeFunction()
552 if (!FTy->getParamType(0)->isPointerTy()) in isLibFreeFunction()
558 Value *llvm::getFreedOperand(const CallBase *CB, const TargetLibraryInfo *TLI) { in getFreedOperand() argument
560 const Function *Callee = getCalledFunction(CB, IsNoBuiltinCall); in getFreedOperand()
565 if (TLI && TLI->getLibFunc(*Callee, TLIFn) && TLI->has(TLIFn) && in getFreedOperand()
568 return CB->getArgOperand(0); in getFreedOperand()
571 if (checkFnAllocKind(CB, AllocFnKind::Free)) in getFreedOperand()
572 return CB->getArgOperandWithAttribute(Attribute::AllocatedPointer); in getFreedOperand()
577 //===----------------------------------------------------------------------===//
578 // Utility functions to compute size of objects.
585 return Size - Offset; in getSizeWithOverflow()
588 /// Compute the size of the object pointed by Ptr. Returns true and the
594 ObjectSizeOffsetVisitor Visitor(DL, TLI, Ptr->getContext(), Opts); in getObjectSize()
595 SizeOffsetAPInt Data = Visitor.compute(const_cast<Value *>(Ptr)); in getObjectSize()
615 assert(ObjectSize->getIntrinsicID() == Intrinsic::objectsize && in lowerObjectSizeCall()
618 bool MaxVal = cast<ConstantInt>(ObjectSize->getArgOperand(1))->isZero(); in lowerObjectSizeCall()
631 cast<ConstantInt>(ObjectSize->getArgOperand(2))->isOne(); in lowerObjectSizeCall()
633 auto *ResultType = cast<IntegerType>(ObjectSize->getType()); in lowerObjectSizeCall()
634 bool StaticOnly = cast<ConstantInt>(ObjectSize->getArgOperand(3))->isZero(); in lowerObjectSizeCall()
639 if (getObjectSize(ObjectSize->getArgOperand(0), Size, DL, TLI, EvalOptions) && in lowerObjectSizeCall()
640 isUIntN(ResultType->getBitWidth(), Size)) in lowerObjectSizeCall()
643 LLVMContext &Ctx = ObjectSize->getFunction()->getContext(); in lowerObjectSizeCall()
645 SizeOffsetValue SizeOffsetPair = Eval.compute(ObjectSize->getArgOperand(0)); in lowerObjectSizeCall()
651 InsertedInstructions->push_back(I); in lowerObjectSizeCall()
666 // The non-constant size expression cannot evaluate to -1. in lowerObjectSizeCall()
669 Builder.CreateICmpNE(Ret, ConstantInt::get(ResultType, -1))); in lowerObjectSizeCall()
678 return ConstantInt::get(ResultType, MaxVal ? -1ULL : 0); in lowerObjectSizeCall()
701 SizeOffsetAPInt ObjectSizeOffsetVisitor::compute(Value *V) { in compute() function in ObjectSizeOffsetVisitor
707 unsigned InitialIntTyBits = DL.getIndexTypeSizeInBits(V->getType()); in computeImpl()
715 V = V->stripAndAccumulateConstantOffsets( in computeImpl()
720 IntTyBits = DL.getIndexTypeSizeInBits(V->getType()); in computeImpl()
750 return P.first->second; in computeValue()
771 LLVM_DEBUG(dbgs() << "ObjectSizeOffsetVisitor::compute() unhandled value: " in computeValue()
790 APInt NumElems = C->getValue(); in visitAllocaInst()
805 if (!MemoryTy|| !MemoryTy->isSized()) { in visitArgument()
814 SizeOffsetAPInt ObjectSizeOffsetVisitor::visitCallBase(CallBase &CB) { in visitCallBase() argument
815 if (std::optional<APInt> Size = getAllocSize(&CB, TLI)) in visitCallBase()
822 // If null is unknown, there's nothing we can do. Additionally, non-zero in visitConstantPointerNull()
828 // addrspace(1) gets casted to addrspace(0) (or vice-versa). in visitConstantPointerNull()
829 if (Options.NullIsUnknownSize || CPN.getType()->getAddressSpace()) in visitConstantPointerNull()
853 if (!GV.getValueType()->isSized() || GV.hasExternalWeakLinkage() || in visitGlobalVariable()
875 return Where->second; in findLoadSizeOffset()
898 Options.AA->alias(SI->getPointerOperand(), Load.getPointerOperand()); in findLoadSizeOffset()
903 if (SI->getValueOperand()->getType()->isPointerTy()) in findLoadSizeOffset()
904 return Known(computeImpl(SI->getValueOperand())); in findLoadSizeOffset()
906 return Unknown(); // No handling of non-pointer values by `compute`. in findLoadSizeOffset()
912 if (auto *CB = dyn_cast<CallBase>(&I)) { in findLoadSizeOffset() local
913 Function *Callee = CB->getCalledFunction(); in findLoadSizeOffset()
919 if (!TLI || !TLI->getLibFunc(*CB->getCalledFunction(), TLIFn) || in findLoadSizeOffset()
920 !TLI->has(TLIFn)) in findLoadSizeOffset()
928 Options.AA->alias(CB->getOperand(0), Load.getPointerOperand()); in findLoadSizeOffset()
942 ICmpInst::ICMP_EQ, CB, ConstantInt::get(CB->getType(), 0), &Load, DL); in findLoadSizeOffset()
946 Value *Size = CB->getOperand(2); in findLoadSizeOffset()
951 return Known({C->getValue(), APInt(C->getValue().getBitWidth(), 0)}); in findLoadSizeOffset()
955 } while (From-- != BB.begin()); in findLoadSizeOffset()
960 Load, *PredBB, BasicBlock::iterator(PredBB->getTerminator()), in findLoadSizeOffset()
1052 // IntTy and Zero must be set for each compute() since the address space may
1056 SizeOffsetValue ObjectSizeOffsetEvaluator::compute(Value *V) { in compute() function in ObjectSizeOffsetEvaluator
1057 // XXX - Are vectors of pointers possible here? in compute()
1058 IntTy = cast<IntegerType>(DL.getIndexType(V->getType())); in compute()
1069 // non-computable results can be safely cached in compute()
1070 if (CacheIt != CacheMap.end() && CacheIt->second.anyKnown()) in compute()
1076 I->replaceAllUsesWith(PoisonValue::get(I->getType())); in compute()
1077 I->eraseFromParent(); in compute()
1088 SizeOffsetAPInt Const = Visitor.compute(V); in compute_()
1093 V = V->stripPointerCasts(); in compute_()
1098 return CacheIt->second; in compute_()
1106 // Now compute the size and offset. in compute_()
1120 cast<ConstantExpr>(V)->getOpcode() == Instruction::IntToPtr) || in compute_()
1127 dbgs() << "ObjectSizeOffsetEvaluator::compute() unhandled value: " << *V in compute_()
1138 if (!I.getAllocatedType()->isSized()) in visitAllocaInst()
1142 assert(I.isArrayAllocation() || I.getAllocatedType()->isScalableTy()); in visitAllocaInst()
1149 assert(ArraySize->getType() == Zero->getType() && in visitAllocaInst()
1153 ArraySize->getType(), DL.getTypeAllocSize(I.getAllocatedType())); in visitAllocaInst()
1158 SizeOffsetValue ObjectSizeOffsetEvaluator::visitCallBase(CallBase &CB) { in visitCallBase() argument
1159 std::optional<AllocFnsTy> FnData = getAllocationSize(&CB, TLI); in visitCallBase()
1163 // Handle strdup-like functions separately. in visitCallBase()
1164 if (FnData->AllocTy == StrDupLike) { in visitCallBase()
1169 Value *FirstArg = CB.getArgOperand(FnData->FstParam); in visitCallBase()
1171 if (FnData->SndParam < 0) in visitCallBase()
1174 Value *SecondArg = CB.getArgOperand(FnData->SndParam); in visitCallBase()
1217 // Compute offset/size for each PHI incoming pointer. in visitPHINode()
1220 Builder.SetInsertPoint(IncomingBlock, IncomingBlock->getFirstInsertionPt()); in visitPHINode()
1224 OffsetPHI->replaceAllUsesWith(PoisonValue::get(IntTy)); in visitPHINode()
1225 OffsetPHI->eraseFromParent(); in visitPHINode()
1227 SizePHI->replaceAllUsesWith(PoisonValue::get(IntTy)); in visitPHINode()
1228 SizePHI->eraseFromParent(); in visitPHINode()
1232 SizePHI->addIncoming(EdgeData.Size, IncomingBlock); in visitPHINode()
1233 OffsetPHI->addIncoming(EdgeData.Offset, IncomingBlock); in visitPHINode()
1237 if (Value *Tmp = SizePHI->hasConstantValue()) { in visitPHINode()
1239 SizePHI->replaceAllUsesWith(Size); in visitPHINode()
1240 SizePHI->eraseFromParent(); in visitPHINode()
1243 if (Value *Tmp = OffsetPHI->hasConstantValue()) { in visitPHINode()
1245 OffsetPHI->replaceAllUsesWith(Offset); in visitPHINode()
1246 OffsetPHI->eraseFromParent(); in visitPHINode()