64#define DEBUG_TYPE "memcpyopt"
67 "enable-memcpyopt-without-libcalls",
cl::Hidden,
68 cl::desc(
"Enable memcpyopt even when libcalls are disabled"));
70STATISTIC(NumMemCpyInstr,
"Number of memcpy instructions deleted");
71STATISTIC(NumMemSetInfer,
"Number of memsets inferred");
72STATISTIC(NumMoveToCpy,
"Number of memmoves converted to memcpy");
73STATISTIC(NumCpyToSet,
"Number of memcpys converted to memset");
74STATISTIC(NumCallSlot,
"Number of call slot optimizations performed");
103 bool isProfitableToUseMemset(
const DataLayout &
DL)
const;
108bool MemsetRange::isProfitableToUseMemset(
const DataLayout &
DL)
const {
110 if (TheStores.size() >= 4 || End-Start >= 16)
return true;
113 if (TheStores.size() < 2)
return false;
118 if (!isa<StoreInst>(SI))
123 if (TheStores.size() == 2)
return false;
135 unsigned Bytes =
unsigned(End-Start);
136 unsigned MaxIntSize =
DL.getLargestLegalIntTypeSizeInBits() / 8;
139 unsigned NumPointerStores = Bytes / MaxIntSize;
142 unsigned NumByteStores = Bytes % MaxIntSize;
147 return TheStores.size() > NumPointerStores+NumByteStores;
167 bool empty()
const {
return Ranges.empty(); }
169 void addInst(int64_t OffsetFromFirst,
Instruction *Inst) {
170 if (
auto *SI = dyn_cast<StoreInst>(Inst))
171 addStore(OffsetFromFirst, SI);
173 addMemSet(OffsetFromFirst, cast<MemSetInst>(Inst));
176 void addStore(int64_t OffsetFromFirst,
StoreInst *SI) {
177 TypeSize StoreSize =
DL.getTypeStoreSize(
SI->getOperand(0)->getType());
180 SI->getPointerOperand(),
SI->getAlign(), SI);
183 void addMemSet(int64_t OffsetFromFirst,
MemSetInst *MSI) {
184 int64_t
Size = cast<ConstantInt>(MSI->
getLength())->getZExtValue();
197void MemsetRanges::addRange(int64_t Start, int64_t
Size,
Value *
Ptr,
199 int64_t End = Start+
Size;
202 Ranges, [=](
const MemsetRange &O) {
return O.End < Start; });
207 if (
I ==
Ranges.end() || End < I->Start) {
208 MemsetRange &
R = *
Ranges.insert(
I, MemsetRange());
212 R.Alignment = Alignment;
213 R.TheStores.push_back(Inst);
218 I->TheStores.push_back(Inst);
222 if (
I->Start <= Start &&
I->End >= End)
231 if (Start < I->Start) {
234 I->Alignment = Alignment;
242 range_iterator NextI =
I;
243 while (++NextI !=
Ranges.end() && End >= NextI->Start) {
245 I->TheStores.append(NextI->TheStores.begin(), NextI->TheStores.end());
246 if (NextI->End >
I->End)
290char MemCpyOptLegacyPass::ID = 0;
310 assert(Start->getParent() == End->getParent() &&
"Must be in same block");
312 if (Start->getFunction()->doesNotThrow())
317 bool RequiresNoCaptureBeforeUnwind;
319 RequiresNoCaptureBeforeUnwind) &&
320 !RequiresNoCaptureBeforeUnwind)
330 I->eraseFromParent();
341 assert(Start->getBlock() == End->getBlock() &&
"Only local supported");
343 make_range(++Start->getIterator(), End->getIterator())) {
344 Instruction *
I = cast<MemoryUseOrDef>(MA).getMemoryInst();
346 auto *II = dyn_cast<IntrinsicInst>(
I);
347 if (II && II->getIntrinsicID() == Intrinsic::lifetime_start &&
348 SkippedLifetimeStart && !*SkippedLifetimeStart) {
349 *SkippedLifetimeStart =
I;
364 if (isa<MemoryUse>(End)) {
368 return Start->getBlock() != End->getBlock() ||
370 make_range(std::next(Start->getIterator()), End->getIterator()),
372 if (isa<MemoryUse>(&Acc))
374 Instruction *AccInst =
375 cast<MemoryUseOrDef>(&Acc)->getMemoryInst();
376 return isModSet(AA.getModRefInfo(AccInst, Loc));
382 End->getDefiningAccess(), Loc, AA);
396 if (
auto *SI = dyn_cast<StoreInst>(StartInst))
397 if (
DL.getTypeStoreSize(
SI->getOperand(0)->getType()).isScalable())
417 for (++BI; !BI->isTerminator(); ++BI) {
418 auto *CurrentAcc = cast_or_null<MemoryUseOrDef>(
421 MemInsertPoint = CurrentAcc;
422 if (
auto *CurrentDef = dyn_cast<MemoryDef>(CurrentAcc))
423 LastMemDef = CurrentDef;
428 if (
auto *CB = dyn_cast<CallBase>(BI)) {
429 if (CB->onlyAccessesInaccessibleMemory())
433 if (!isa<StoreInst>(BI) && !isa<MemSetInst>(BI)) {
437 if (BI->mayWriteToMemory() || BI->mayReadFromMemory())
442 if (
auto *NextStore = dyn_cast<StoreInst>(BI)) {
444 if (!NextStore->isSimple())
break;
446 Value *StoredVal = NextStore->getValueOperand();
454 if (
DL.getTypeStoreSize(StoredVal->
getType()).isScalable())
459 if (isa<UndefValue>(ByteVal) && StoredByte)
460 ByteVal = StoredByte;
461 if (ByteVal != StoredByte)
465 std::optional<int64_t>
Offset =
472 auto *MSI = cast<MemSetInst>(BI);
474 if (MSI->isVolatile() || ByteVal != MSI->getValue() ||
475 !isa<ConstantInt>(MSI->getLength()))
479 std::optional<int64_t>
Offset =
496 Ranges.addInst(0, StartInst);
506 for (
const MemsetRange &Range : Ranges) {
507 if (
Range.TheStores.size() == 1)
continue;
510 if (!
Range.isProfitableToUseMemset(
DL))
515 StartPtr =
Range.StartPtr;
524 dbgs() <<
"With: " << *AMemSet <<
'\n');
525 if (!
Range.TheStores.empty())
528 assert(LastMemDef && MemInsertPoint &&
529 "Both LastMemDef and MemInsertPoint need to be set");
533 AMemSet, LastMemDef, MemInsertPoint)
535 AMemSet, LastMemDef, MemInsertPoint));
538 MemInsertPoint = NewDef;
542 eraseInstruction(SI);
564 auto *
I = dyn_cast<Instruction>(
Arg);
565 if (
I &&
I->getParent() ==
SI->getParent()) {
567 if (
I ==
P)
return false;
572 if (!AddArg(
SI->getPointerOperand()))
586 for (
auto I = --
SI->getIterator(),
E =
P->getIterator();
I !=
E; --
I) {
596 bool NeedLift =
false;
618 else if (
const auto *Call = dyn_cast<CallBase>(
C)) {
624 }
else if (isa<LoadInst>(
C) || isa<StoreInst>(
C) || isa<VAArgInst>(
C)) {
630 MemLocs.push_back(
ML);
637 for (
Value *Op :
C->operands())
651 MemInsertPoint = cast<MemoryUseOrDef>(--MA->getIterator());
667 assert(MemInsertPoint &&
"Must have found insert point");
689 if (
T->isAggregateType() &&
691 (TLI->
has(LibFunc_memcpy) && TLI->
has(LibFunc_memmove)))) {
712 if (!moveUp(SI,
P, LI))
723 bool UseMemMove =
false;
733 SI->getPointerOperand(),
SI->getAlign(),
737 SI->getPointerOperand(),
SI->getAlign(),
739 M->copyMetadata(*SI, LLVMContext::MD_DIAssignID);
741 LLVM_DEBUG(
dbgs() <<
"Promoting " << *LI <<
" to " << *SI <<
" => "
747 MSSAU->
insertDef(cast<MemoryDef>(NewAccess),
true);
749 eraseInstruction(SI);
750 eraseInstruction(LI);
754 BBI =
M->getIterator();
763 auto GetCall = [&]() ->
CallInst * {
766 if (
auto *LoadClobber = dyn_cast<MemoryUseOrDef>(
768 return dyn_cast_or_null<CallInst>(LoadClobber->getMemoryInst());
772 bool Changed = performCallSlotOptzn(
773 LI, SI,
SI->getPointerOperand()->stripPointerCasts(),
775 DL.getTypeStoreSize(
SI->getOperand(0)->getType()),
776 std::min(
SI->getAlign(), LI->
getAlign()), BAA, GetCall);
778 eraseInstruction(SI);
779 eraseInstruction(LI);
788 if (!
SI->isSimple())
return false;
796 if (
SI->getMetadata(LLVMContext::MD_nontemporal))
801 Value *StoredVal =
SI->getValueOperand();
809 if (
auto *LI = dyn_cast<LoadInst>(StoredVal))
810 return processStoreOfLoad(SI, LI,
DL, BBI);
825 auto *V =
SI->getOperand(0);
827 if (
Instruction *
I = tryMergingIntoMemset(SI,
SI->getPointerOperand(),
829 BBI =
I->getIterator();
836 auto *
T = V->getType();
837 if (
T->isAggregateType()) {
840 auto *
M =
Builder.CreateMemSet(
SI->getPointerOperand(), ByteVal,
Size,
842 M->copyMetadata(*SI, LLVMContext::MD_DIAssignID);
844 LLVM_DEBUG(
dbgs() <<
"Promoting " << *SI <<
" to " << *M <<
"\n");
850 M, StoreDef->getDefiningAccess(), StoreDef);
851 MSSAU->
insertDef(cast<MemoryDef>(NewAccess),
false);
853 eraseInstruction(SI);
857 BBI =
M->getIterator();
871 BBI =
I->getIterator();
880bool MemCpyOptPass::performCallSlotOptzn(
Instruction *cpyLoad,
904 auto *srcAlloca = dyn_cast<AllocaInst>(cpySrc);
908 ConstantInt *srcArraySize = dyn_cast<ConstantInt>(srcAlloca->getArraySize());
913 uint64_t srcSize =
DL.getTypeAllocSize(srcAlloca->getAllocatedType()) *
916 if (cpySize < srcSize)
925 if (
F->isIntrinsic() &&
F->getIntrinsicID() == Intrinsic::lifetime_start)
929 if (
C->getParent() != cpyStore->
getParent()) {
943 LLVM_DEBUG(
dbgs() <<
"Call Slot: Dest pointer modified after call\n");
950 if (SkippedLifetimeStart) {
952 dyn_cast<Instruction>(SkippedLifetimeStart->
getOperand(1));
953 if (LifetimeArg && LifetimeArg->getParent() ==
C->getParent() &&
954 C->comesBefore(LifetimeArg))
963 LLVM_DEBUG(
dbgs() <<
"Call Slot: Dest pointer not dereferenceable\n");
982 LLVM_DEBUG(
dbgs() <<
"Call Slot: Dest may be visible through unwinding\n");
987 Align srcAlign = srcAlloca->getAlign();
988 bool isDestSufficientlyAligned = srcAlign <= cpyDestAlign;
991 if (!isDestSufficientlyAligned && !isa<AllocaInst>(cpyDest)) {
992 LLVM_DEBUG(
dbgs() <<
"Call Slot: Dest not sufficiently aligned\n");
1001 while (!srcUseList.empty()) {
1002 User *U = srcUseList.pop_back_val();
1004 if (isa<BitCastInst>(U) || isa<AddrSpaceCastInst>(U)) {
1008 if (
const auto *
G = dyn_cast<GetElementPtrInst>(U)) {
1009 if (!
G->hasAllZeroIndices())
1015 if (
const auto *
IT = dyn_cast<IntrinsicInst>(U))
1016 if (
IT->isLifetimeStartOrEnd())
1019 if (U !=
C && U != cpyLoad)
1025 bool SrcIsCaptured =
any_of(
C->args(), [&](
Use &U) {
1026 return U->stripPointerCasts() == cpySrc &&
1027 !C->doesNotCapture(C->getArgOperandNo(&U));
1033 if (SrcIsCaptured) {
1048 make_range(++
C->getIterator(),
C->getParent()->end())) {
1050 if (
auto *II = dyn_cast<IntrinsicInst>(&
I)) {
1051 if (II->getIntrinsicID() == Intrinsic::lifetime_end &&
1052 II->getArgOperand(1)->stripPointerCasts() == srcAlloca &&
1053 cast<ConstantInt>(II->getArgOperand(0))->uge(srcSize))
1058 if (isa<ReturnInst>(&
I))
1078 auto *
GEP = dyn_cast<GetElementPtrInst>(cpyDest);
1079 if (
GEP &&
GEP->hasAllConstantIndices() &&
1103 for (
unsigned ArgI = 0; ArgI <
C->arg_size(); ++ArgI)
1104 if (
C->getArgOperand(ArgI)->stripPointerCasts() == cpySrc &&
1106 C->getArgOperand(ArgI)->getType()->getPointerAddressSpace())
1110 bool changedArgument =
false;
1111 for (
unsigned ArgI = 0; ArgI <
C->arg_size(); ++ArgI)
1112 if (
C->getArgOperand(ArgI)->stripPointerCasts() == cpySrc) {
1116 changedArgument =
true;
1117 if (
C->getArgOperand(ArgI)->getType() == Dest->
getType())
1118 C->setArgOperand(ArgI, Dest);
1121 Dest,
C->getArgOperand(ArgI)->getType(),
1125 if (!changedArgument)
1129 if (!isDestSufficientlyAligned) {
1130 assert(isa<AllocaInst>(cpyDest) &&
"Can only increase alloca alignment!");
1131 cast<AllocaInst>(cpyDest)->setAlignment(srcAlign);
1134 if (SkippedLifetimeStart) {
1143 unsigned KnownIDs[] = {LLVMContext::MD_tbaa, LLVMContext::MD_alias_scope,
1144 LLVMContext::MD_noalias,
1145 LLVMContext::MD_invariant_group,
1146 LLVMContext::MD_access_group};
1148 if (cpyLoad != cpyStore)
1157bool MemCpyOptPass::processMemCpyMemCpyDependence(
MemCpyInst *M,
1176 auto *MDepLen = dyn_cast<ConstantInt>(MDep->
getLength());
1177 auto *MLen = dyn_cast<ConstantInt>(
M->getLength());
1178 if (!MDepLen || !MLen || MDepLen->getZExtValue() < MLen->getZExtValue())
1202 bool UseMemMove =
false;
1207 LLVM_DEBUG(
dbgs() <<
"MemCpyOptPass: Forwarding memcpy->memcpy src:\n"
1208 << *MDep <<
'\n' << *M <<
'\n');
1215 NewM =
Builder.CreateMemMove(
M->getRawDest(),
M->getDestAlign(),
1217 M->getLength(),
M->isVolatile());
1218 else if (isa<MemCpyInlineInst>(M)) {
1222 NewM =
Builder.CreateMemCpyInline(
1226 NewM =
Builder.CreateMemCpy(
M->getRawDest(),
M->getDestAlign(),
1228 M->getLength(),
M->isVolatile());
1234 MSSAU->
insertDef(cast<MemoryDef>(NewAccess),
true);
1237 eraseInstruction(M);
1256bool MemCpyOptPass::processMemSetMemCpyDependence(
MemCpyInst *MemCpy,
1286 if (DestSize == SrcSize) {
1287 eraseInstruction(MemSet);
1298 if (
auto *SrcSizeC = dyn_cast<ConstantInt>(SrcSize))
1313 Value *SizeDiff =
Builder.CreateSub(DestSize, SrcSize);
1322 MemSet->
getOperand(1), MemsetLen, Alignment);
1325 "MemCpy must be a MemoryDef");
1332 NewMemSet, LastDef->getDefiningAccess(), LastDef);
1333 MSSAU->
insertDef(cast<MemoryDef>(NewAccess),
true);
1335 eraseInstruction(MemSet);
1346 if (
auto *II = dyn_cast_or_null<IntrinsicInst>(Def->getMemoryInst())) {
1347 if (II->getIntrinsicID() == Intrinsic::lifetime_start) {
1348 auto *LTSize = cast<ConstantInt>(II->getArgOperand(0));
1350 if (
auto *CSize = dyn_cast<ConstantInt>(
Size)) {
1352 LTSize->getZExtValue() >= CSize->getZExtValue())
1362 const DataLayout &
DL = Alloca->getModule()->getDataLayout();
1363 if (std::optional<TypeSize> AllocaSize =
1364 Alloca->getAllocationSize(
DL))
1365 if (*AllocaSize == LTSize->getValue())
1387bool MemCpyOptPass::performMemCpyToMemSetOptzn(
MemCpyInst *MemCpy,
1398 if (MemSetSize != CopySize) {
1403 auto *CMemSetSize = dyn_cast<ConstantInt>(MemSetSize);
1408 auto *CCopySize = dyn_cast<ConstantInt>(CopySize);
1411 if (CCopySize->getZExtValue() > CMemSetSize->getZExtValue()) {
1417 bool CanReduceSize =
false;
1421 if (
auto *MD = dyn_cast<MemoryDef>(Clobber))
1423 CanReduceSize =
true;
1427 CopySize = MemSetSize;
1438 MSSAU->
insertDef(cast<MemoryDef>(NewAccess),
true);
1450 if (
M->isVolatile())
return false;
1453 if (
M->getSource() ==
M->getDest()) {
1455 eraseInstruction(M);
1460 if (
auto *GV = dyn_cast<GlobalVariable>(
M->getSource()))
1461 if (GV->isConstant() && GV->hasDefinitiveInitializer())
1463 M->getModule()->getDataLayout())) {
1466 M->getRawDest(), ByteVal,
M->getLength(),
M->getDestAlign(),
false);
1471 MSSAU->
insertDef(cast<MemoryDef>(NewAccess),
true);
1473 eraseInstruction(M);
1490 if (
auto *MD = dyn_cast<MemoryDef>(DestClobber))
1491 if (
auto *MDep = dyn_cast_or_null<MemSetInst>(MD->getMemoryInst()))
1492 if (DestClobber->
getBlock() ==
M->getParent())
1493 if (processMemSetMemCpyDependence(M, MDep, BAA))
1506 if (
auto *MD = dyn_cast<MemoryDef>(SrcClobber)) {
1508 if (
auto *CopySize = dyn_cast<ConstantInt>(
M->getLength())) {
1509 if (
auto *
C = dyn_cast<CallInst>(
MI)) {
1510 if (performCallSlotOptzn(M, M,
M->getDest(),
M->getSource(),
1512 M->getDestAlign().valueOrOne(), BAA,
1515 <<
" call: " << *
C <<
"\n"
1516 <<
" memcpy: " << *M <<
"\n");
1517 eraseInstruction(M);
1523 if (
auto *MDep = dyn_cast<MemCpyInst>(
MI))
1524 return processMemCpyMemCpyDependence(M, MDep, BAA);
1525 if (
auto *MDep = dyn_cast<MemSetInst>(
MI)) {
1526 if (performMemCpyToMemSetOptzn(M, MDep, BAA)) {
1528 eraseInstruction(M);
1537 eraseInstruction(M);
1548bool MemCpyOptPass::processMemMove(
MemMoveInst *M) {
1553 LLVM_DEBUG(
dbgs() <<
"MemCpyOptPass: Optimizing memmove -> memcpy: " << *M
1557 Type *ArgTys[3] = {
M->getRawDest()->getType(),
1558 M->getRawSource()->getType(),
1559 M->getLength()->getType() };
1561 Intrinsic::memcpy, ArgTys));
1571bool MemCpyOptPass::processByValArgument(
CallBase &CB,
unsigned ArgNo) {
1576 TypeSize ByValSize =
DL.getTypeAllocSize(ByValTy);
1585 if (
auto *MD = dyn_cast<MemoryDef>(Clobber))
1586 MDep = dyn_cast_or_null<MemCpyInst>(MD->getMemoryInst());
1596 auto *C1 = dyn_cast<ConstantInt>(MDep->
getLength());
1604 if (!ByValAlign)
return false;
1609 if ((!MemDepAlign || *MemDepAlign < *ByValAlign) &&
1635 TmpCast = TmpBitCast;
1638 LLVM_DEBUG(
dbgs() <<
"MemCpyOptPass: Forwarding memcpy to byval:\n"
1639 <<
" " << *MDep <<
"\n"
1640 <<
" " << CB <<
"\n");
1649bool MemCpyOptPass::iterateOnFunction(
Function &
F) {
1650 bool MadeChange =
false;
1665 bool RepeatInstruction =
false;
1667 if (
auto *SI = dyn_cast<StoreInst>(
I))
1668 MadeChange |= processStore(SI, BI);
1669 else if (
auto *M = dyn_cast<MemSetInst>(
I))
1670 RepeatInstruction = processMemSet(M, BI);
1671 else if (
auto *M = dyn_cast<MemCpyInst>(
I))
1672 RepeatInstruction = processMemCpy(M, BI);
1673 else if (
auto *M = dyn_cast<MemMoveInst>(
I))
1674 RepeatInstruction = processMemMove(M);
1675 else if (
auto *CB = dyn_cast<CallBase>(
I)) {
1676 for (
unsigned i = 0, e = CB->
arg_size(); i != e; ++i)
1678 MadeChange |= processByValArgument(*CB, i);
1682 if (RepeatInstruction) {
1683 if (BI != BB.begin())
1700 bool MadeChange =
runImpl(
F, &TLI, AA, AC, DT, &MSSA->getMSSA());
1713 bool MadeChange =
false;
1723 if (!iterateOnFunction(
F))
1735bool MemCpyOptLegacyPass::runOnFunction(
Function &
F) {
1736 if (skipFunction(
F))
1739 auto *TLI = &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(
F);
1740 auto *AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
1741 auto *AC = &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(
F);
1742 auto *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
1743 auto *MSSA = &getAnalysis<MemorySSAWrapperPass>().getMSSA();
1745 return Impl.
runImpl(
F, TLI, AA, AC, DT, MSSA);
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.
MemCpy static false 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.
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
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.
A wrapper pass to provide the legacy pass manager access to a suitably prepared AAResults object.
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.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
void setPreservesCFG()
This function should be called by the pass, iff they do not:
A function analysis which provides an AssumptionCache.
An immutable pass that tracks lazily created AssumptionCache objects.
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.
Legacy 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.
FunctionPass class - This class is used to implement most global optimizations.
virtual bool runOnFunction(Function &F)=0
runOnFunction - Virtual method overriden by subclasses to do the per-function processing of the pass.
Module * getParent()
Get the module that this global value is contained inside of...
Legacy wrapper pass to provide the GlobalsAAResult object.
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...
Legacy analysis pass which computes MemorySSA.
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.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
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.
iterator_range< user_iterator > users()
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.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ 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.
void initializeMemCpyOptLegacyPassPass(PassRegistry &)
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,...
FunctionPass * createMemCpyOptPass()
The public interface to this file...
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.
std::optional< int64_t > isPointerOffset(const Value *Ptr1, const Value *Ptr2, const DataLayout &DL)
If Ptr1 is provably equal to Ptr2 plus a constant offset, return that offset.
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.