61#define DEBUG_TYPE "memcpyopt"
64 "enable-memcpyopt-without-libcalls",
cl::Hidden,
65 cl::desc(
"Enable memcpyopt even when libcalls are disabled"));
67STATISTIC(NumMemCpyInstr,
"Number of memcpy instructions deleted");
68STATISTIC(NumMemSetInfer,
"Number of memsets inferred");
69STATISTIC(NumMoveToCpy,
"Number of memmoves converted to memcpy");
70STATISTIC(NumCpyToSet,
"Number of memcpys converted to memset");
71STATISTIC(NumCallSlot,
"Number of call slot optimizations performed");
100 bool isProfitableToUseMemset(
const DataLayout &
DL)
const;
105bool MemsetRange::isProfitableToUseMemset(
const DataLayout &
DL)
const {
107 if (TheStores.size() >= 4 ||
End-Start >= 16)
return true;
110 if (TheStores.size() < 2)
return false;
115 if (!isa<StoreInst>(SI))
120 if (TheStores.size() == 2)
return false;
133 unsigned MaxIntSize =
DL.getLargestLegalIntTypeSizeInBits() / 8;
136 unsigned NumPointerStores = Bytes / MaxIntSize;
139 unsigned NumByteStores = Bytes % MaxIntSize;
144 return TheStores.size() > NumPointerStores+NumByteStores;
164 bool empty()
const {
return Ranges.empty(); }
166 void addInst(int64_t OffsetFromFirst,
Instruction *Inst) {
167 if (
auto *SI = dyn_cast<StoreInst>(Inst))
168 addStore(OffsetFromFirst, SI);
170 addMemSet(OffsetFromFirst, cast<MemSetInst>(Inst));
173 void addStore(int64_t OffsetFromFirst,
StoreInst *SI) {
174 TypeSize StoreSize =
DL.getTypeStoreSize(
SI->getOperand(0)->getType());
177 SI->getPointerOperand(),
SI->getAlign(), SI);
180 void addMemSet(int64_t OffsetFromFirst,
MemSetInst *MSI) {
181 int64_t
Size = cast<ConstantInt>(MSI->
getLength())->getZExtValue();
194void MemsetRanges::addRange(int64_t Start, int64_t
Size,
Value *
Ptr,
199 Ranges, [=](
const MemsetRange &O) {
return O.End < Start; });
204 if (
I ==
Ranges.end() || End < I->Start) {
205 MemsetRange &
R = *
Ranges.insert(
I, MemsetRange());
209 R.Alignment = Alignment;
210 R.TheStores.push_back(Inst);
215 I->TheStores.push_back(Inst);
219 if (
I->Start <= Start &&
I->End >=
End)
228 if (Start < I->Start) {
231 I->Alignment = Alignment;
239 range_iterator NextI =
I;
240 while (++NextI !=
Ranges.end() &&
End >= NextI->Start) {
242 I->TheStores.append(NextI->TheStores.begin(), NextI->TheStores.end());
243 if (NextI->End >
I->End)
259 assert(Start->getParent() ==
End->getParent() &&
"Must be in same block");
261 if (Start->getFunction()->doesNotThrow())
266 bool RequiresNoCaptureBeforeUnwind;
268 RequiresNoCaptureBeforeUnwind) &&
269 !RequiresNoCaptureBeforeUnwind)
279 I->eraseFromParent();
290 assert(Start->getBlock() ==
End->getBlock() &&
"Only local supported");
293 Instruction *
I = cast<MemoryUseOrDef>(MA).getMemoryInst();
295 auto *II = dyn_cast<IntrinsicInst>(
I);
296 if (II && II->getIntrinsicID() == Intrinsic::lifetime_start &&
297 SkippedLifetimeStart && !*SkippedLifetimeStart) {
298 *SkippedLifetimeStart =
I;
313 if (isa<MemoryUse>(
End)) {
317 return Start->getBlock() !=
End->getBlock() ||
319 make_range(std::next(Start->getIterator()),
End->getIterator()),
321 if (isa<MemoryUse>(&Acc))
323 Instruction *AccInst =
324 cast<MemoryUseOrDef>(&Acc)->getMemoryInst();
325 return isModSet(AA.getModRefInfo(AccInst, Loc));
331 End->getDefiningAccess(), Loc, AA);
345 if (
auto *SI = dyn_cast<StoreInst>(StartInst))
346 if (
DL.getTypeStoreSize(
SI->getOperand(0)->getType()).isScalable())
366 for (++BI; !BI->isTerminator(); ++BI) {
367 auto *CurrentAcc = cast_or_null<MemoryUseOrDef>(
370 MemInsertPoint = CurrentAcc;
371 if (
auto *CurrentDef = dyn_cast<MemoryDef>(CurrentAcc))
372 LastMemDef = CurrentDef;
377 if (
auto *CB = dyn_cast<CallBase>(BI)) {
378 if (CB->onlyAccessesInaccessibleMemory())
382 if (!isa<StoreInst>(BI) && !isa<MemSetInst>(BI)) {
386 if (BI->mayWriteToMemory() || BI->mayReadFromMemory())
391 if (
auto *NextStore = dyn_cast<StoreInst>(BI)) {
393 if (!NextStore->isSimple())
break;
395 Value *StoredVal = NextStore->getValueOperand();
403 if (
DL.getTypeStoreSize(StoredVal->
getType()).isScalable())
408 if (isa<UndefValue>(ByteVal) && StoredByte)
409 ByteVal = StoredByte;
410 if (ByteVal != StoredByte)
414 std::optional<int64_t>
Offset =
415 NextStore->getPointerOperand()->getPointerOffsetFrom(StartPtr,
DL);
421 auto *MSI = cast<MemSetInst>(BI);
423 if (MSI->isVolatile() || ByteVal != MSI->getValue() ||
424 !isa<ConstantInt>(MSI->getLength()))
428 std::optional<int64_t>
Offset =
429 MSI->getDest()->getPointerOffsetFrom(StartPtr,
DL);
445 Ranges.addInst(0, StartInst);
455 for (
const MemsetRange &Range : Ranges) {
456 if (
Range.TheStores.size() == 1)
continue;
459 if (!
Range.isProfitableToUseMemset(
DL))
464 StartPtr =
Range.StartPtr;
473 dbgs() <<
"With: " << *AMemSet <<
'\n');
474 if (!
Range.TheStores.empty())
477 assert(LastMemDef && MemInsertPoint &&
478 "Both LastMemDef and MemInsertPoint need to be set");
482 AMemSet, LastMemDef, MemInsertPoint)
484 AMemSet, LastMemDef, MemInsertPoint));
487 MemInsertPoint = NewDef;
491 eraseInstruction(SI);
513 auto *
I = dyn_cast<Instruction>(
Arg);
514 if (
I &&
I->getParent() ==
SI->getParent()) {
516 if (
I ==
P)
return false;
521 if (!AddArg(
SI->getPointerOperand()))
535 for (
auto I = --
SI->getIterator(),
E =
P->getIterator();
I !=
E; --
I) {
545 bool NeedLift =
false;
567 else if (
const auto *Call = dyn_cast<CallBase>(
C)) {
573 }
else if (isa<LoadInst>(
C) || isa<StoreInst>(
C) || isa<VAArgInst>(
C)) {
579 MemLocs.push_back(
ML);
586 for (
Value *Op :
C->operands())
600 MemInsertPoint = cast<MemoryUseOrDef>(--MA->getIterator());
616 assert(MemInsertPoint &&
"Must have found insert point");
638 if (
T->isAggregateType() &&
640 (TLI->
has(LibFunc_memcpy) && TLI->
has(LibFunc_memmove)))) {
661 if (!moveUp(SI,
P, LI))
672 bool UseMemMove =
false;
682 SI->getPointerOperand(),
SI->getAlign(),
686 SI->getPointerOperand(),
SI->getAlign(),
688 M->copyMetadata(*SI, LLVMContext::MD_DIAssignID);
690 LLVM_DEBUG(
dbgs() <<
"Promoting " << *LI <<
" to " << *SI <<
" => "
696 MSSAU->
insertDef(cast<MemoryDef>(NewAccess),
true);
698 eraseInstruction(SI);
699 eraseInstruction(LI);
703 BBI =
M->getIterator();
712 auto GetCall = [&]() ->
CallInst * {
715 if (
auto *LoadClobber = dyn_cast<MemoryUseOrDef>(
717 return dyn_cast_or_null<CallInst>(LoadClobber->getMemoryInst());
721 bool Changed = performCallSlotOptzn(
722 LI, SI,
SI->getPointerOperand()->stripPointerCasts(),
724 DL.getTypeStoreSize(
SI->getOperand(0)->getType()),
725 std::min(
SI->getAlign(), LI->
getAlign()), BAA, GetCall);
727 eraseInstruction(SI);
728 eraseInstruction(LI);
737 if (!
SI->isSimple())
return false;
745 if (
SI->getMetadata(LLVMContext::MD_nontemporal))
750 Value *StoredVal =
SI->getValueOperand();
758 if (
auto *LI = dyn_cast<LoadInst>(StoredVal))
759 return processStoreOfLoad(SI, LI,
DL, BBI);
774 auto *
V =
SI->getOperand(0);
776 if (
Instruction *
I = tryMergingIntoMemset(SI,
SI->getPointerOperand(),
778 BBI =
I->getIterator();
785 auto *
T =
V->getType();
786 if (
T->isAggregateType()) {
789 auto *
M =
Builder.CreateMemSet(
SI->getPointerOperand(), ByteVal,
Size,
791 M->copyMetadata(*SI, LLVMContext::MD_DIAssignID);
793 LLVM_DEBUG(
dbgs() <<
"Promoting " << *SI <<
" to " << *M <<
"\n");
799 M, StoreDef->getDefiningAccess(), StoreDef);
800 MSSAU->
insertDef(cast<MemoryDef>(NewAccess),
false);
802 eraseInstruction(SI);
806 BBI =
M->getIterator();
820 BBI =
I->getIterator();
829bool MemCpyOptPass::performCallSlotOptzn(
Instruction *cpyLoad,
853 auto *srcAlloca = dyn_cast<AllocaInst>(cpySrc);
857 ConstantInt *srcArraySize = dyn_cast<ConstantInt>(srcAlloca->getArraySize());
862 uint64_t srcSize =
DL.getTypeAllocSize(srcAlloca->getAllocatedType()) *
865 if (cpySize < srcSize)
874 if (
F->isIntrinsic() &&
F->getIntrinsicID() == Intrinsic::lifetime_start)
878 if (
C->getParent() != cpyStore->
getParent()) {
892 LLVM_DEBUG(
dbgs() <<
"Call Slot: Dest pointer modified after call\n");
899 if (SkippedLifetimeStart) {
901 dyn_cast<Instruction>(SkippedLifetimeStart->
getOperand(1));
902 if (LifetimeArg && LifetimeArg->getParent() ==
C->getParent() &&
903 C->comesBefore(LifetimeArg))
912 LLVM_DEBUG(
dbgs() <<
"Call Slot: Dest pointer not dereferenceable\n");
931 LLVM_DEBUG(
dbgs() <<
"Call Slot: Dest may be visible through unwinding\n");
936 Align srcAlign = srcAlloca->getAlign();
937 bool isDestSufficientlyAligned = srcAlign <= cpyDestAlign;
940 if (!isDestSufficientlyAligned && !isa<AllocaInst>(cpyDest)) {
941 LLVM_DEBUG(
dbgs() <<
"Call Slot: Dest not sufficiently aligned\n");
950 while (!srcUseList.empty()) {
951 User *
U = srcUseList.pop_back_val();
953 if (isa<BitCastInst>(U) || isa<AddrSpaceCastInst>(U)) {
957 if (
const auto *
G = dyn_cast<GetElementPtrInst>(U)) {
958 if (!
G->hasAllZeroIndices())
964 if (
const auto *
IT = dyn_cast<IntrinsicInst>(U))
965 if (
IT->isLifetimeStartOrEnd())
968 if (U !=
C && U != cpyLoad)
974 bool SrcIsCaptured =
any_of(
C->args(), [&](
Use &U) {
975 return U->stripPointerCasts() == cpySrc &&
976 !C->doesNotCapture(C->getArgOperandNo(&U));
997 make_range(++
C->getIterator(),
C->getParent()->end())) {
999 if (
auto *II = dyn_cast<IntrinsicInst>(&
I)) {
1000 if (II->getIntrinsicID() == Intrinsic::lifetime_end &&
1001 II->getArgOperand(1)->stripPointerCasts() == srcAlloca &&
1002 cast<ConstantInt>(II->getArgOperand(0))->uge(srcSize))
1007 if (isa<ReturnInst>(&
I))
1027 auto *
GEP = dyn_cast<GetElementPtrInst>(cpyDest);
1028 if (
GEP &&
GEP->hasAllConstantIndices() &&
1052 for (
unsigned ArgI = 0; ArgI <
C->arg_size(); ++ArgI)
1053 if (
C->getArgOperand(ArgI)->stripPointerCasts() == cpySrc &&
1055 C->getArgOperand(ArgI)->getType()->getPointerAddressSpace())
1059 bool changedArgument =
false;
1060 for (
unsigned ArgI = 0; ArgI <
C->arg_size(); ++ArgI)
1061 if (
C->getArgOperand(ArgI)->stripPointerCasts() == cpySrc) {
1065 changedArgument =
true;
1066 if (
C->getArgOperand(ArgI)->getType() == Dest->
getType())
1067 C->setArgOperand(ArgI, Dest);
1070 Dest,
C->getArgOperand(ArgI)->getType(),
1074 if (!changedArgument)
1078 if (!isDestSufficientlyAligned) {
1079 assert(isa<AllocaInst>(cpyDest) &&
"Can only increase alloca alignment!");
1080 cast<AllocaInst>(cpyDest)->setAlignment(srcAlign);
1083 if (SkippedLifetimeStart) {
1092 unsigned KnownIDs[] = {LLVMContext::MD_tbaa, LLVMContext::MD_alias_scope,
1093 LLVMContext::MD_noalias,
1094 LLVMContext::MD_invariant_group,
1095 LLVMContext::MD_access_group};
1097 if (cpyLoad != cpyStore)
1106bool MemCpyOptPass::processMemCpyMemCpyDependence(
MemCpyInst *M,
1125 auto *MDepLen = dyn_cast<ConstantInt>(MDep->
getLength());
1126 auto *MLen = dyn_cast<ConstantInt>(
M->getLength());
1127 if (!MDepLen || !MLen || MDepLen->getZExtValue() < MLen->getZExtValue())
1151 bool UseMemMove =
false;
1156 if (isa<MemCpyInlineInst>(M))
1162 LLVM_DEBUG(
dbgs() <<
"MemCpyOptPass: Forwarding memcpy->memcpy src:\n"
1163 << *MDep <<
'\n' << *M <<
'\n');
1170 NewM =
Builder.CreateMemMove(
M->getRawDest(),
M->getDestAlign(),
1172 M->getLength(),
M->isVolatile());
1173 else if (isa<MemCpyInlineInst>(M)) {
1177 NewM =
Builder.CreateMemCpyInline(
1181 NewM =
Builder.CreateMemCpy(
M->getRawDest(),
M->getDestAlign(),
1183 M->getLength(),
M->isVolatile());
1189 MSSAU->
insertDef(cast<MemoryDef>(NewAccess),
true);
1192 eraseInstruction(M);
1216bool MemCpyOptPass::processMemSetMemCpyDependence(
MemCpyInst *MemCpy,
1246 if (DestSize == SrcSize) {
1247 eraseInstruction(MemSet);
1258 if (
auto *SrcSizeC = dyn_cast<ConstantInt>(SrcSize))
1269 "Preserving debug location based on moving memset within BB.");
1282 Value *SizeDiff =
Builder.CreateSub(DestSize, SrcSize);
1291 MemSet->
getOperand(1), MemsetLen, Alignment);
1294 "MemCpy must be a MemoryDef");
1300 NewMemSet, LastDef->getDefiningAccess(), LastDef);
1301 MSSAU->
insertDef(cast<MemoryDef>(NewAccess),
true);
1303 eraseInstruction(MemSet);
1314 if (
auto *II = dyn_cast_or_null<IntrinsicInst>(Def->getMemoryInst())) {
1315 if (II->getIntrinsicID() == Intrinsic::lifetime_start) {
1316 auto *LTSize = cast<ConstantInt>(II->getArgOperand(0));
1318 if (
auto *CSize = dyn_cast<ConstantInt>(
Size)) {
1320 LTSize->getZExtValue() >= CSize->getZExtValue())
1330 const DataLayout &
DL = Alloca->getModule()->getDataLayout();
1331 if (std::optional<TypeSize> AllocaSize =
1332 Alloca->getAllocationSize(
DL))
1333 if (*AllocaSize == LTSize->getValue())
1355bool MemCpyOptPass::performMemCpyToMemSetOptzn(
MemCpyInst *MemCpy,
1366 if (MemSetSize != CopySize) {
1371 auto *CMemSetSize = dyn_cast<ConstantInt>(MemSetSize);
1376 auto *CCopySize = dyn_cast<ConstantInt>(CopySize);
1379 if (CCopySize->getZExtValue() > CMemSetSize->getZExtValue()) {
1385 bool CanReduceSize =
false;
1389 if (
auto *MD = dyn_cast<MemoryDef>(Clobber))
1391 CanReduceSize =
true;
1395 CopySize = MemSetSize;
1406 MSSAU->
insertDef(cast<MemoryDef>(NewAccess),
true);
1418 if (
M->isVolatile())
return false;
1421 if (
M->getSource() ==
M->getDest()) {
1423 eraseInstruction(M);
1428 if (
auto *GV = dyn_cast<GlobalVariable>(
M->getSource()))
1429 if (GV->isConstant() && GV->hasDefinitiveInitializer())
1431 M->getModule()->getDataLayout())) {
1434 M->getRawDest(), ByteVal,
M->getLength(),
M->getDestAlign(),
false);
1439 MSSAU->
insertDef(cast<MemoryDef>(NewAccess),
true);
1441 eraseInstruction(M);
1458 if (
auto *MD = dyn_cast<MemoryDef>(DestClobber))
1459 if (
auto *MDep = dyn_cast_or_null<MemSetInst>(MD->getMemoryInst()))
1460 if (DestClobber->
getBlock() ==
M->getParent())
1461 if (processMemSetMemCpyDependence(M, MDep, BAA))
1474 if (
auto *MD = dyn_cast<MemoryDef>(SrcClobber)) {
1476 if (
auto *CopySize = dyn_cast<ConstantInt>(
M->getLength())) {
1477 if (
auto *
C = dyn_cast<CallInst>(
MI)) {
1478 if (performCallSlotOptzn(M, M,
M->getDest(),
M->getSource(),
1480 M->getDestAlign().valueOrOne(), BAA,
1483 <<
" call: " << *
C <<
"\n"
1484 <<
" memcpy: " << *M <<
"\n");
1485 eraseInstruction(M);
1491 if (
auto *MDep = dyn_cast<MemCpyInst>(
MI))
1492 return processMemCpyMemCpyDependence(M, MDep, BAA);
1493 if (
auto *MDep = dyn_cast<MemSetInst>(
MI)) {
1494 if (performMemCpyToMemSetOptzn(M, MDep, BAA)) {
1496 eraseInstruction(M);
1505 eraseInstruction(M);
1516bool MemCpyOptPass::processMemMove(
MemMoveInst *M) {
1521 LLVM_DEBUG(
dbgs() <<
"MemCpyOptPass: Optimizing memmove -> memcpy: " << *M
1525 Type *ArgTys[3] = {
M->getRawDest()->getType(),
1526 M->getRawSource()->getType(),
1527 M->getLength()->getType() };
1529 Intrinsic::memcpy, ArgTys));
1539bool MemCpyOptPass::processByValArgument(
CallBase &CB,
unsigned ArgNo) {
1544 TypeSize ByValSize =
DL.getTypeAllocSize(ByValTy);
1553 if (
auto *MD = dyn_cast<MemoryDef>(Clobber))
1554 MDep = dyn_cast_or_null<MemCpyInst>(MD->getMemoryInst());
1564 auto *C1 = dyn_cast<ConstantInt>(MDep->
getLength());
1572 if (!ByValAlign)
return false;
1577 if ((!MemDepAlign || *MemDepAlign < *ByValAlign) &&
1603 TmpCast = TmpBitCast;
1606 LLVM_DEBUG(
dbgs() <<
"MemCpyOptPass: Forwarding memcpy to byval:\n"
1607 <<
" " << *MDep <<
"\n"
1608 <<
" " << CB <<
"\n");
1617bool MemCpyOptPass::iterateOnFunction(
Function &
F) {
1618 bool MadeChange =
false;
1633 bool RepeatInstruction =
false;
1635 if (
auto *SI = dyn_cast<StoreInst>(
I))
1636 MadeChange |= processStore(SI, BI);
1637 else if (
auto *M = dyn_cast<MemSetInst>(
I))
1638 RepeatInstruction = processMemSet(M, BI);
1639 else if (
auto *M = dyn_cast<MemCpyInst>(
I))
1640 RepeatInstruction = processMemCpy(M, BI);
1641 else if (
auto *M = dyn_cast<MemMoveInst>(
I))
1642 RepeatInstruction = processMemMove(M);
1643 else if (
auto *CB = dyn_cast<CallBase>(
I)) {
1644 for (
unsigned i = 0, e = CB->
arg_size(); i != e; ++i)
1646 MadeChange |= processByValArgument(*CB, i);
1650 if (RepeatInstruction) {
1651 if (BI != BB.begin())
1668 bool MadeChange =
runImpl(
F, &TLI, AA, AC, DT, &MSSA->getMSSA());
1681 bool MadeChange =
false;
1691 if (!iterateOnFunction(
F))
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
amdgpu Simplify well known AMD library false FunctionCallee Value * Arg
static cl::opt< ITMode > IT(cl::desc("IT block support"), cl::Hidden, cl::init(DefaultIT), cl::values(clEnumValN(DefaultIT, "arm-default-it", "Generate any type of IT block"), clEnumValN(RestrictedIT, "arm-restrict-it", "Disallow complex IT blocks")))
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file defines the DenseSet and SmallDenseSet classes.
This is the interface for a simple mod/ref and alias analysis over globals.
static bool mayBeVisibleThroughUnwinding(Value *V, Instruction *Start, Instruction *End)
static bool accessedBetween(BatchAAResults &AA, MemoryLocation Loc, const MemoryUseOrDef *Start, const MemoryUseOrDef *End, Instruction **SkippedLifetimeStart=nullptr)
static bool hasUndefContents(MemorySSA *MSSA, BatchAAResults &AA, Value *V, MemoryDef *Def, Value *Size)
Determine whether the instruction has undefined content for the given Size, either because it was fre...
static cl::opt< bool > EnableMemCpyOptWithoutLibcalls("enable-memcpyopt-without-libcalls", cl::Hidden, cl::desc("Enable memcpyopt even when libcalls are disabled"))
static bool writtenBetween(MemorySSA *MSSA, BatchAAResults &AA, MemoryLocation Loc, const MemoryUseOrDef *Start, const MemoryUseOrDef *End)
This file provides utility analysis objects describing memory locations.
This file exposes an interface to building/using memory SSA to walk memory instructions using a use/d...
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
A manager for alias analyses.
ModRefInfo getModRefInfo(const Instruction *I, const std::optional< MemoryLocation > &OptLoc)
Check whether or not an instruction may read or write the optionally specified memory location.
Class for arbitrary precision integers.
A container for analyses that lazily runs them and caches their results.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
A function analysis which provides an AssumptionCache.
A cache of @llvm.assume calls within a function.
LLVM Basic Block Representation.
InstListType::iterator iterator
Instruction iterators...
This class is a wrapper over an AAResults, and it is intended to be used only when there are no IR ch...
bool isMustAlias(const MemoryLocation &LocA, const MemoryLocation &LocB)
ModRefInfo getModRefInfo(const Instruction *I, const std::optional< MemoryLocation > &OptLoc)
ModRefInfo callCapturesBefore(const Instruction *I, const MemoryLocation &MemLoc, DominatorTree *DT)
This class represents a no-op cast from one type to another.
Represents analyses that only rely on functions' control flow.
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
bool isByValArgument(unsigned ArgNo) const
Determine whether this argument is passed by value.
MaybeAlign getParamAlign(unsigned ArgNo) const
Extract the alignment for a call or parameter (0=unknown).
Type * getParamByValType(unsigned ArgNo) const
Extract the byval type for a call or parameter.
Value * getArgOperand(unsigned i) const
void setArgOperand(unsigned i, Value *v)
unsigned arg_size() const
Function * getCaller()
Helper to get the caller (the parent function).
This class represents a function call, abstracting a target machine's calling convention.
static CastInst * CreatePointerCast(Value *S, Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd)
Create a BitCast AddrSpaceCast, or a PtrToInt cast instruction.
This is the shared class of boolean and integer constants.
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
static Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
A parsed version of the target data layout string in and methods for querying it.
Implements a dense probed hash-table based set.
Analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
bool isReachableFromEntry(const Use &U) const
Provide an overload for a Use.
bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
Module * getParent()
Get the module that this global value is contained inside of...
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
void mergeDIAssignID(ArrayRef< const Instruction * > SourceInstructions)
Merge the DIAssignID metadata from this instruction and those attached to instructions in SourceInstr...
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
const BasicBlock * getParent() const
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
void copyMetadata(const Instruction &SrcInst, ArrayRef< unsigned > WL=ArrayRef< unsigned >())
Copy metadata from SrcInst to this instruction.
void moveBefore(Instruction *MovePos)
Unlink this instruction from its current basic block and insert it into the basic block that MovePos ...
An instruction for reading from memory.
Value * getPointerOperand()
Align getAlign() const
Return the alignment of the access that is being performed.
static LocationSize precise(uint64_t Value)
This class wraps the llvm.memcpy intrinsic.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
bool runImpl(Function &F, TargetLibraryInfo *TLI, AAResults *AA, AssumptionCache *AC, DominatorTree *DT, MemorySSA *MSSA)
Value * getLength() const
Value * getRawDest() const
Value * getDest() const
This is just like getRawDest, but it strips off any cast instructions (including addrspacecast) that ...
MaybeAlign getDestAlign() const
This class wraps the llvm.memmove intrinsic.
This class wraps the llvm.memset and llvm.memset.inline intrinsics.
Value * getRawSource() const
Return the arguments to the instruction.
MaybeAlign getSourceAlign() const
Value * getSource() const
This is just like getRawSource, but it strips off any cast instructions that feed it,...
BasicBlock * getBlock() const
Represents a read-write access to memory, whether it is a must-alias, or a may-alias.
Representation for a specific memory location.
static MemoryLocation get(const LoadInst *LI)
Return a location with information about the memory reference by the given instruction.
static MemoryLocation getForSource(const MemTransferInst *MTI)
Return a location representing the source of a memory transfer.
static MemoryLocation getForDest(const MemIntrinsic *MI)
Return a location representing the destination of a memory set or transfer.
An analysis that produces MemorySSA for a function.
MemorySSA * getMemorySSA() const
Get handle on MemorySSA.
MemoryUseOrDef * createMemoryAccessBefore(Instruction *I, MemoryAccess *Definition, MemoryUseOrDef *InsertPt)
Create a MemoryAccess in MemorySSA before or after an existing MemoryAccess.
void insertDef(MemoryDef *Def, bool RenameUses=false)
Insert a definition into the MemorySSA IR.
void moveAfter(MemoryUseOrDef *What, MemoryUseOrDef *Where)
void removeMemoryAccess(MemoryAccess *, bool OptimizePhis=false)
Remove a MemoryAccess from MemorySSA, including updating all definitions and uses.
MemoryUseOrDef * createMemoryAccessAfter(Instruction *I, MemoryAccess *Definition, MemoryAccess *InsertPt)
void moveBefore(MemoryUseOrDef *What, MemoryUseOrDef *Where)
MemoryAccess * getClobberingMemoryAccess(const Instruction *I, BatchAAResults &AA)
Given a memory Mod/Ref/ModRef'ing instruction, calling this will give you the nearest dominating Memo...
Encapsulates MemorySSA, including all data associated with memory accesses.
bool dominates(const MemoryAccess *A, const MemoryAccess *B) const
Given two memory accesses in potentially different blocks, determine whether MemoryAccess A dominates...
void verifyMemorySSA(VerificationLevel=VerificationLevel::Fast) const
Verify that MemorySSA is self consistent (IE definitions dominate all uses, uses appear in the right ...
MemorySSAWalker * getWalker()
MemoryUseOrDef * getMemoryAccess(const Instruction *I) const
Given a memory Mod/Ref'ing instruction, get the MemorySSA access associated with it.
bool isLiveOnEntryDef(const MemoryAccess *MA) const
Return true if MA represents the live on entry value.
Class that has the common methods + fields of memory uses/defs.
MemoryAccess * getDefiningAccess() const
Get the access that produces the memory state used by this Use.
Instruction * getMemoryInst() const
Get the instruction that this MemoryUse represents.
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
void preserveSet()
Mark an analysis set as preserved.
void preserve()
Mark an analysis as preserved.
typename SuperClass::const_iterator const_iterator
typename SuperClass::iterator iterator
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
bool has(LibFunc F) const
Tests whether a library function is available.
static constexpr TypeSize getFixed(ScalarTy ExactSize)
The instances of the Type class are immutable: once they are created, they are never changed.
unsigned getIntegerBitWidth() const
unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
A Use represents the edge between a Value definition and its users.
Value * getOperand(unsigned i) const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
bool hasOneUse() const
Return true if there is exactly one use of this value.
const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
StringRef getName() const
Return a constant reference to the value's name.
constexpr ScalarTy getFixedValue() const
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
static constexpr bool isKnownGE(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)
reverse_self_iterator getReverseIterator()
self_iterator getIterator()
This provides a very simple, boring adaptor for a begin and end iterator into a range type.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
@ C
The default llvm calling convention, compatible with C.
Function * getDeclaration(Module *M, ID id, ArrayRef< Type * > Tys=std::nullopt)
Create or insert an LLVM Function declaration for an intrinsic, and return it.
const_iterator begin(StringRef path, Style style=Style::native)
Get begin iterator over path.
const_iterator end(StringRef path)
Get end iterator over path.
This is an optimization pass for GlobalISel generic memory operations.
bool isDereferenceableAndAlignedPointer(const Value *V, Type *Ty, Align Alignment, const DataLayout &DL, const Instruction *CtxI=nullptr, AssumptionCache *AC=nullptr, const DominatorTree *DT=nullptr, const TargetLibraryInfo *TLI=nullptr)
Returns true if V is always a dereferenceable pointer with alignment greater or equal than requested.
auto partition_point(R &&Range, Predicate P)
Binary search for the first iterator in a range where a predicate is false.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
bool PointerMayBeCapturedBefore(const Value *V, bool ReturnCaptures, bool StoreCaptures, const Instruction *I, const DominatorTree *DT, bool IncludeI=false, unsigned MaxUsesToExplore=0, const LoopInfo *LI=nullptr)
PointerMayBeCapturedBefore - Return true if this pointer value may be captured by the enclosing funct...
void append_range(Container &C, Range &&R)
Wrapper function to append a range to a container.
const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=6)
This method strips off any GEP address adjustments and pointer casts from the specified value,...
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
auto reverse(ContainerTy &&C)
Align getOrEnforceKnownAlignment(Value *V, MaybeAlign PrefAlign, const DataLayout &DL, const Instruction *CxtI=nullptr, AssumptionCache *AC=nullptr, const DominatorTree *DT=nullptr)
Try to ensure that the alignment of V is at least PrefAlign bytes.
bool isModSet(const ModRefInfo MRI)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool isModOrRefSet(const ModRefInfo MRI)
bool isNotVisibleOnUnwind(const Value *Object, bool &RequiresNoCaptureBeforeUnwind)
Return true if Object memory is not visible after an unwind, in the sense that program semantics cann...
void combineMetadata(Instruction *K, const Instruction *J, ArrayRef< unsigned > KnownIDs, bool DoesKMove)
Combine the metadata of two instructions so that K can replace J.
ModRefInfo
Flags indicating whether a memory access modifies or references memory.
bool VerifyMemorySSA
Enables verification of MemorySSA.
bool isIdentifiedFunctionLocal(const Value *V)
Return true if V is umabigously identified at the function-level.
bool isGuaranteedToTransferExecutionToSuccessor(const Instruction *I)
Return true if this function can prove that the instruction I will always transfer execution to one o...
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Value * isBytewiseValue(Value *V, const DataLayout &DL)
If the specified value can be set by repeating the same byte in memory, return the i8 value that it i...
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
This struct is a compact representation of a valid (non-zero power of two) alignment.
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
Align valueOrOne() const
For convenience, returns a valid alignment or 1 if undefined.