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