24#define DEBUG_TYPE "lower-mem-intrinsics"
35 Value *OpSize,
unsigned OpSizeVal) {
38 return B.CreateAnd(Len, OpSizeVal - 1);
39 return B.CreateURem(Len, OpSize);
48 Value *RTLoopRemainder =
nullptr) {
51 return B.CreateSub(Len, RTLoopRemainder);
56struct LoopExpansionInfo {
61 Value *MainLoopIndex =
nullptr;
69 Value *ResidualLoopIndex =
nullptr;
72std::optional<uint64_t> getAverageMemOpLoopTripCount(
const MemIntrinsic &
I) {
75 if (std::optional<Function::ProfileCount> EC =
76 I.getFunction()->getEntryCount();
77 !EC || !
EC->getCount())
79 if (
const auto Len =
I.getLengthInBytes())
80 return Len->getZExtValue();
84 std::numeric_limits<uint32_t>::max(),
Total);
88 for (
const auto &
P : ProfData)
89 TripCount +=
P.Count *
P.Value;
90 return std::round(1.0 * TripCount /
Total);
127static LoopExpansionInfo
129 unsigned MainLoopStep,
unsigned ResidualLoopStep,
131 std::optional<uint64_t> AverageTripCount) {
132 assert((ResidualLoopStep == 0 || MainLoopStep % ResidualLoopStep == 0) &&
133 "ResidualLoopStep must divide MainLoopStep if specified");
134 assert(ResidualLoopStep <= MainLoopStep &&
135 "ResidualLoopStep cannot be larger than MainLoopStep");
136 assert(MainLoopStep > 0 &&
"MainLoopStep must be non-zero");
137 LoopExpansionInfo LEI;
140 InsertBefore, BBNamePrefix +
"-post-expansion");
149 Type *LenType = Len->getType();
151 ConstantInt *CIMainLoopStep = ConstantInt::get(ILenType, MainLoopStep);
153 Value *LoopUnits = Len;
154 Value *ResidualUnits =
nullptr;
157 bool MustTakeMainLoop =
false;
158 if (MainLoopStep != 1) {
160 uint64_t TotalUnits = CLen->getZExtValue();
162 uint64_t ResidualCount = TotalUnits - LoopEndCount;
163 LoopUnits = ConstantInt::get(LenType, LoopEndCount);
164 ResidualUnits = ConstantInt::get(LenType, ResidualCount);
165 MustTakeMainLoop = LoopEndCount > 0;
173 CIMainLoopStep, MainLoopStep);
175 MainLoopStep, ResidualUnits);
178 MustTakeMainLoop = CLen->getZExtValue() > 0;
182 Ctx, BBNamePrefix +
"-expansion-main-body", ParentFunc, PostLoopBB);
187 LEI.MainLoopIndex = LoopIndex;
188 LoopIndex->
addIncoming(ConstantInt::get(LenType, 0U), PreLoopBB);
191 LoopBuilder.
CreateAdd(LoopIndex, ConstantInt::get(LenType, MainLoopStep));
198 if (ResidualLoopStep > 0 && ResidualLoopStep < MainLoopStep) {
209 ConstantInt *Zero = ConstantInt::get(ILenType, 0U);
210 if (MustTakeMainLoop)
211 PreLoopBuilder.
CreateBr(MainLoopBB);
214 PreLoopBuilder.
CreateICmpNE(LoopUnits, Zero), MainLoopBB,
216 if (AverageTripCount.has_value()) {
219 {AverageTripCount.value() % MainLoopStep, 1},
230 MainLoopBB, ResidualCondBB);
236 ResLoopBB, PostLoopBB);
241 ResBuilder.
CreatePHI(LenType, 2,
"residual-loop-index");
246 Value *FullOffset = ResBuilder.
CreateAdd(LoopUnits, ResidualIndex);
247 LEI.ResidualLoopIndex = FullOffset;
250 ResidualIndex, ConstantInt::get(LenType, ResidualLoopStep));
251 ResidualIndex->
addIncoming(ResNewIndex, ResLoopBB);
259 ResBuilder.
CreateICmpULT(ResNewIndex, ResidualUnits), ResLoopBB,
267 if (MustTakeMainLoop) {
268 PreLoopBuilder.
CreateBr(MainLoopBB);
270 ConstantInt *Zero = ConstantInt::get(ILenType, 0U);
273 MainLoopBB, PostLoopBB,
274 B.createLikelyBranchWeights());
279 LoopBuilder.
CreateICmpULT(NewIndex, LoopUnits), MainLoopBB, PostLoopBB);
280 if (AverageTripCount.has_value())
292 bool SrcIsVolatile,
bool DstIsVolatile,
295 std::optional<uint32_t> AtomicElementSize,
296 std::optional<uint64_t> AverageTripCount) {
314 Type *LoopOpType =
TTI.getMemcpyLoopLoweringType(
315 Ctx, CopyLen, SrcAS, DstAS, SrcAlign, DstAlign, AtomicElementSize);
317 "Atomic memcpy lowering is not supported for vector operand type");
320 unsigned LoopOpSize =
DL.getTypeStoreSize(LoopOpType);
321 assert((!AtomicElementSize || LoopOpSize % *AtomicElementSize == 0) &&
322 "Atomic memcpy lowering is not supported for selected operand size");
327 if (LoopEndCount != 0) {
328 LoopExpansionInfo LEI =
330 "static-memcpy", AverageTripCount);
344 LoopOpType, SrcGEP, PartSrcAlign, SrcIsVolatile);
347 Load->setMetadata(LLVMContext::MD_alias_scope,
353 Load, DstGEP, PartDstAlign, DstIsVolatile);
356 Store->setMetadata(LLVMContext::MD_noalias,
MDNode::get(Ctx, NewScope));
358 if (AtomicElementSize) {
362 assert(!LEI.ResidualLoopIP && !LEI.ResidualLoopIndex &&
363 "No residual loop was requested");
367 uint64_t BytesCopied = LoopEndCount;
369 if (RemainingBytes == 0)
374 TTI.getMemcpyLoopResidualLoweringType(RemainingOps, Ctx, RemainingBytes,
375 SrcAS, DstAS, SrcAlign, DstAlign,
378 for (
auto *OpTy : RemainingOps) {
382 unsigned OperandSize =
DL.getTypeStoreSize(OpTy);
383 assert((!AtomicElementSize || OperandSize % *AtomicElementSize == 0) &&
384 "Atomic memcpy lowering is not supported for selected operand size");
387 Int8Type, SrcAddr, ConstantInt::get(TypeOfCopyLen, BytesCopied));
392 Load->setMetadata(LLVMContext::MD_alias_scope,
396 Int8Type, DstAddr, ConstantInt::get(TypeOfCopyLen, BytesCopied));
401 Store->setMetadata(LLVMContext::MD_noalias,
MDNode::get(Ctx, NewScope));
403 if (AtomicElementSize) {
407 BytesCopied += OperandSize;
410 "Bytes copied should match size in the call!");
415 Align SrcAlign,
Align DstAlign,
bool SrcIsVolatile,
bool DstIsVolatile,
417 std::optional<uint32_t> AtomicElementSize,
418 std::optional<uint64_t> AverageTripCount) {
424 MDNode *NewDomain = MDB.createAnonymousAliasScopeDomain(
"MemCopyDomain");
426 MDNode *NewScope = MDB.createAnonymousAliasScope(NewDomain, Name);
431 Type *LoopOpType =
TTI.getMemcpyLoopLoweringType(
432 Ctx, CopyLen, SrcAS, DstAS, SrcAlign, DstAlign, AtomicElementSize);
434 "Atomic memcpy lowering is not supported for vector operand type");
435 unsigned LoopOpSize =
DL.getTypeStoreSize(LoopOpType);
436 assert((!AtomicElementSize || LoopOpSize % *AtomicElementSize == 0) &&
437 "Atomic memcpy lowering is not supported for selected operand size");
441 Type *ResidualLoopOpType = AtomicElementSize
444 unsigned ResidualLoopOpSize =
DL.getTypeStoreSize(ResidualLoopOpType);
445 assert(ResidualLoopOpSize == (AtomicElementSize ? *AtomicElementSize : 1) &&
446 "Store size is expected to match type size");
448 LoopExpansionInfo LEI =
450 "dynamic-memcpy", AverageTripCount);
462 MainLoopBuilder.CreateInBoundsGEP(Int8Type, SrcAddr, LEI.MainLoopIndex);
463 LoadInst *Load = MainLoopBuilder.CreateAlignedLoad(
464 LoopOpType, SrcGEP, PartSrcAlign, SrcIsVolatile);
467 Load->setMetadata(LLVMContext::MD_alias_scope,
MDNode::get(Ctx, NewScope));
470 MainLoopBuilder.CreateInBoundsGEP(Int8Type, DstAddr, LEI.MainLoopIndex);
472 Load, DstGEP, PartDstAlign, DstIsVolatile);
477 if (AtomicElementSize) {
483 if (!LEI.ResidualLoopIP)
490 Value *ResSrcGEP = ResLoopBuilder.CreateInBoundsGEP(Int8Type, SrcAddr,
491 LEI.ResidualLoopIndex);
492 LoadInst *ResLoad = ResLoopBuilder.CreateAlignedLoad(
493 ResidualLoopOpType, ResSrcGEP, ResSrcAlign, SrcIsVolatile);
499 Value *ResDstGEP = ResLoopBuilder.CreateInBoundsGEP(Int8Type, DstAddr,
500 LEI.ResidualLoopIndex);
501 StoreInst *ResStore = ResLoopBuilder.CreateAlignedStore(
502 ResLoad, ResDstGEP, ResDstAlign, DstIsVolatile);
507 if (AtomicElementSize) {
517static std::pair<Value *, Value *>
520 Value *ResAddr1 = Addr1;
521 Value *ResAddr2 = Addr2;
526 if (
TTI.isValidAddrSpaceCast(AS2, AS1))
527 ResAddr2 =
B.CreateAddrSpaceCast(Addr2, Addr1->
getType());
528 else if (
TTI.isValidAddrSpaceCast(AS1, AS2))
529 ResAddr1 =
B.CreateAddrSpaceCast(Addr1, Addr2->
getType());
532 "support addrspacecast");
534 return {ResAddr1, ResAddr2};
566 Align DstAlign,
bool SrcIsVolatile,
577 Type *LoopOpType =
TTI.getMemcpyLoopLoweringType(Ctx, CopyLen, SrcAS, DstAS,
579 unsigned LoopOpSize =
DL.getTypeStoreSize(LoopOpType);
581 bool LoopOpIsInt8 = LoopOpType == Int8Type;
585 bool RequiresResidual = !LoopOpIsInt8;
587 Type *ResidualLoopOpType = Int8Type;
588 unsigned ResidualLoopOpSize =
DL.getTypeStoreSize(ResidualLoopOpType);
592 ConstantInt *CILoopOpSize = ConstantInt::get(ILengthType, LoopOpSize);
594 ConstantInt::get(ILengthType, ResidualLoopOpSize);
595 ConstantInt *Zero = ConstantInt::get(ILengthType, 0);
601 Value *RuntimeLoopBytes = CopyLen;
602 Value *RuntimeLoopRemainder =
nullptr;
603 Value *SkipResidualCondition =
nullptr;
604 if (RequiresResidual) {
605 RuntimeLoopRemainder =
608 LoopOpSize, RuntimeLoopRemainder);
609 SkipResidualCondition =
610 PLBuilder.
CreateICmpEQ(RuntimeLoopRemainder, Zero,
"skip_residual");
612 Value *SkipMainCondition =
613 PLBuilder.
CreateICmpEQ(RuntimeLoopBytes, Zero,
"skip_main");
624 auto [CmpSrcAddr, CmpDstAddr] =
627 PLBuilder.
CreateICmpULT(CmpSrcAddr, CmpDstAddr,
"compare_src_dst");
630 &ThenTerm, &ElseTerm);
657 CopyBackwardsBB->
setName(
"memmove_copy_backwards");
659 CopyForwardBB->
setName(
"memmove_copy_forward");
661 ExitBB->
setName(
"memmove_done");
674 F->getContext(),
"memmove_bwd_main_loop",
F, CopyForwardBB);
680 if (RequiresResidual) {
683 F->getContext(),
"memmove_bwd_residual_loop",
F, MainLoopBB);
688 ResidualLoopPhi, CIResidualLoopOpSize,
"bwd_residual_index");
696 ResidualLoopOpType, LoadGEP, ResidualSrcAlign, SrcIsVolatile,
701 ResidualDstAlign, DstIsVolatile);
705 F->getContext(),
"memmove_bwd_middle",
F, MainLoopBB);
711 ResidualLoopBuilder.
CreateICmpEQ(ResidualIndex, RuntimeLoopBytes),
712 IntermediateBB, ResidualLoopBB);
714 ResidualLoopPhi->
addIncoming(ResidualIndex, ResidualLoopBB);
715 ResidualLoopPhi->
addIncoming(CopyLen, CopyBackwardsBB);
724 PredBB = IntermediateBB;
732 MainLoopBuilder.
CreateSub(MainLoopPhi, CILoopOpSize,
"bwd_main_index");
736 LoopOpType, LoadGEP, PartSrcAlign, SrcIsVolatile,
"element");
744 MainLoopPhi->
addIncoming(RuntimeLoopBytes, PredBB);
749 ExitBB, MainLoopBB, SkipMainCondition, PredBBTerm->
getIterator());
762 MainLoopBuilder.
CreatePHI(ILengthType, 0,
"fwd_main_index");
766 LoopOpType, LoadGEP, PartSrcAlign, SrcIsVolatile,
"element");
771 Value *MainIndex = MainLoopBuilder.
CreateAdd(MainLoopPhi, CILoopOpSize);
777 if (RequiresResidual)
783 MainLoopBuilder.
CreateICmpEQ(MainIndex, RuntimeLoopBytes), SuccessorBB,
793 if (RequiresResidual) {
798 F->getContext(),
"memmove_fwd_residual_loop",
F, ExitBB);
799 IntermediateBuilder.
CreateCondBr(SkipResidualCondition, ExitBB,
806 ResidualLoopBuilder.
CreatePHI(ILengthType, 0,
"fwd_residual_index");
810 ResidualLoopOpType, LoadGEP, ResidualSrcAlign, SrcIsVolatile,
815 ResidualDstAlign, DstIsVolatile);
816 Value *ResidualIndex =
817 ResidualLoopBuilder.
CreateAdd(ResidualLoopPhi, CIResidualLoopOpSize);
819 ResidualLoopBuilder.
CreateICmpEQ(ResidualIndex, CopyLen), ExitBB,
821 ResidualLoopPhi->
addIncoming(ResidualIndex, ResidualLoopBB);
822 ResidualLoopPhi->
addIncoming(RuntimeLoopBytes, IntermediateBB);
833 Align DstAlign,
bool SrcIsVolatile,
848 Type *LoopOpType =
TTI.getMemcpyLoopLoweringType(Ctx, CopyLen, SrcAS, DstAS,
850 unsigned LoopOpSize =
DL.getTypeStoreSize(LoopOpType);
858 ConstantInt *Zero = ConstantInt::get(ILengthType, 0);
859 ConstantInt *LoopBound = ConstantInt::get(ILengthType, BytesCopiedInLoop);
860 ConstantInt *CILoopOpSize = ConstantInt::get(ILengthType, LoopOpSize);
866 auto [CmpSrcAddr, CmpDstAddr] =
869 PLBuilder.
CreateICmpULT(CmpSrcAddr, CmpDstAddr,
"compare_src_dst");
872 &ThenTerm, &ElseTerm);
877 ExitBB->
setName(
"memmove_done");
889 unsigned OperandSize =
DL.getTypeStoreSize(OpTy);
895 Value *SrcGEP = Builder.CreateInBoundsGEP(
896 Int8Type, SrcAddr, ConstantInt::get(TypeOfCopyLen, BytesCopied));
898 Builder.CreateAlignedLoad(OpTy, SrcGEP, ResSrcAlign, SrcIsVolatile);
899 Value *DstGEP = Builder.CreateInBoundsGEP(
900 Int8Type, DstAddr, ConstantInt::get(TypeOfCopyLen, BytesCopied));
901 Builder.CreateAlignedStore(Load, DstGEP, ResDstAlign, DstIsVolatile);
902 BytesCopied += OperandSize;
906 if (RemainingBytes != 0) {
907 CopyBackwardsBB->
setName(
"memmove_bwd_residual");
908 uint64_t BytesCopied = BytesCopiedInLoop;
919 TTI.getMemcpyLoopResidualLoweringType(RemainingOps, Ctx, RemainingBytes,
920 SrcAS, DstAS, PartSrcAlign,
922 for (
auto *OpTy : RemainingOps) {
926 GenerateResidualLdStPair(OpTy, BwdResBuilder, BytesCopied);
929 if (BytesCopiedInLoop != 0) {
932 if (RemainingBytes != 0) {
936 PredBB = CopyBackwardsBB;
938 CopyBackwardsBB->
setName(
"memmove_bwd_loop");
943 Value *Index = LoopBuilder.
CreateSub(LoopPhi, CILoopOpSize,
"bwd_index");
946 LoopOpType, LoadGEP, PartSrcAlign, SrcIsVolatile,
"element");
964 if (BytesCopiedInLoop != 0) {
965 CopyForwardBB->
setName(
"memmove_fwd_loop");
968 if (RemainingBytes != 0) {
971 "memmove_fwd_residual");
972 FwdResidualBB = SuccBB;
979 LoopOpType, LoadGEP, PartSrcAlign, SrcIsVolatile,
"element");
994 if (RemainingBytes != 0) {
995 uint64_t BytesCopied = BytesCopiedInLoop;
1002 TTI.getMemcpyLoopResidualLoweringType(RemainingOps, Ctx, RemainingBytes,
1003 SrcAS, DstAS, PartSrcAlign,
1005 for (
auto *OpTy : RemainingOps)
1006 GenerateResidualLdStPair(OpTy, FwdResBuilder, BytesCopied);
1012 std::optional<uint64_t> AverageTripCount,
1025 Builder.SetCurrentDebugLocation(DbgLoc);
1027 auto *ToLoopBR = Builder.CreateCondBr(
1028 Builder.CreateICmpEQ(ConstantInt::get(TypeOfCopyLen, 0), CopyLen), NewBB,
1031 if (AverageTripCount.has_value())
1032 ToLoopBR->setMetadata(LLVMContext::MD_prof,
1039 unsigned PartSize =
DL.getTypeStoreSize(
SetValue->getType());
1045 LoopIndex->
addIncoming(ConstantInt::get(TypeOfCopyLen, 0), OrigBB);
1050 PartAlign, IsVolatile);
1053 LoopBuilder.
CreateAdd(LoopIndex, ConstantInt::get(TypeOfCopyLen, 1));
1057 LoopBuilder.
CreateICmpULT(NewIndex, CopyLen), LoopBB, NewBB);
1058 if (AverageTripCount.has_value())
1065template <
typename T>
1069 const SCEV *DestSCEV = SE->
getSCEV(Memcpy->getRawDest());
1080 auto TripCount = getAverageMemOpLoopTripCount(*Memcpy);
1120 bool DstIsVolatile = SrcIsVolatile;
1126 if (SrcAS != DstAS) {
1127 if (!
TTI.addrspacesMayAlias(SrcAS, DstAS)) {
1130 auto AverageTripCount = getAverageMemOpLoopTripCount(*Memmove);
1133 Memmove, SrcAddr, DstAddr, CI, SrcAlign, DstAlign,
1134 SrcIsVolatile, DstIsVolatile,
1135 false,
TTI, std::nullopt, AverageTripCount);
1138 Memmove, SrcAddr, DstAddr, CopyLen, SrcAlign,
1139 DstAlign, SrcIsVolatile, DstIsVolatile,
1140 false,
TTI, std::nullopt, AverageTripCount);
1146 if (!(
TTI.isValidAddrSpaceCast(DstAS, SrcAS) ||
1147 TTI.isValidAddrSpaceCast(SrcAS, DstAS))) {
1152 dbgs() <<
"Do not know how to expand memmove between different "
1153 "address spaces\n");
1160 Memmove, SrcAddr, DstAddr, CI, SrcAlign, DstAlign,
1161 SrcIsVolatile, DstIsVolatile,
TTI);
1164 Memmove, SrcAddr, DstAddr, CopyLen, SrcAlign, DstAlign,
1165 SrcIsVolatile, DstIsVolatile,
TTI);
1176 getAverageMemOpLoopTripCount(*Memset),
1186 getAverageMemOpLoopTripCount(*Memset),
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static void SetValue(Value *V, GenericValue Val, ExecutionContext &SF)
static std::pair< Value *, Value * > tryInsertCastToCommonAddrSpace(IRBuilderBase &B, Value *Addr1, Value *Addr2, const TargetTransformInfo &TTI)
static bool canOverlap(MemTransferBase< T > *Memcpy, ScalarEvolution *SE)
static LoopExpansionInfo insertLoopExpansion(Instruction *InsertBefore, Value *Len, unsigned MainLoopStep, unsigned ResidualLoopStep, StringRef BBNamePrefix, std::optional< uint64_t > AverageTripCount)
Insert the control flow and loop counters for a memcpy/memset loop expansion.
static void createMemMoveLoopKnownSize(Instruction *InsertBefore, Value *SrcAddr, Value *DstAddr, ConstantInt *CopyLen, Align SrcAlign, Align DstAlign, bool SrcIsVolatile, bool DstIsVolatile, const TargetTransformInfo &TTI)
static Value * getRuntimeLoopRemainder(IRBuilderBase &B, Value *Len, Value *OpSize, unsigned OpSizeVal)
static Value * getRuntimeLoopUnits(IRBuilderBase &B, Value *Len, Value *OpSize, unsigned OpSizeVal, Value *RTLoopRemainder=nullptr)
static void createMemMoveLoopUnknownSize(Instruction *InsertBefore, Value *SrcAddr, Value *DstAddr, Value *CopyLen, Align SrcAlign, Align DstAlign, bool SrcIsVolatile, bool DstIsVolatile, const TargetTransformInfo &TTI)
static void createMemSetLoop(Instruction *InsertBefore, Value *DstAddr, Value *CopyLen, Value *SetValue, Align DstAlign, std::optional< uint64_t > AverageTripCount, bool IsVolatile)
This file contains the declarations for profiling metadata utility functions.
This class represents any memcpy intrinsic i.e.
uint32_t getElementSizeInBytes() const
LLVM Basic Block Representation.
const Function * getParent() const
Return the enclosing method, or null if none.
LLVM_ABI InstListType::const_iterator getFirstNonPHIIt() const
Returns an iterator to the first instruction in this block that is not a PHINode instruction.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
LLVM_ABI BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="", bool Before=false)
Split the basic block into two basic blocks at the specified instruction.
LLVM_ABI LLVMContext & getContext() const
Get the context in which this basic block lives.
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
Conditional or Unconditional Branch instruction.
static BranchInst * Create(BasicBlock *IfTrue, InsertPosition InsertBefore=nullptr)
This is the shared class of boolean and integer constants.
bool isZero() const
This is just a convenience method to make client code smaller for a common code.
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
A parsed version of the target data layout string in and methods for querying it.
const DataLayout & getDataLayout() const
Get the data layout of the module this function belongs to.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Common base class shared among various IRBuilders.
Value * CreateICmpULT(Value *LHS, Value *RHS, const Twine &Name="")
LoadInst * CreateAlignedLoad(Type *Ty, Value *Ptr, MaybeAlign Align, const char *Name)
UnreachableInst * CreateUnreachable()
void SetCurrentDebugLocation(DebugLoc L)
Set location information used by debugging information.
Value * CreateInBoundsGEP(Type *Ty, Value *Ptr, ArrayRef< Value * > IdxList, const Twine &Name="")
Value * CreateICmpNE(Value *LHS, Value *RHS, const Twine &Name="")
PHINode * CreatePHI(Type *Ty, unsigned NumReservedValues, const Twine &Name="")
Value * CreateICmpEQ(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateSub(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
BranchInst * CreateCondBr(Value *Cond, BasicBlock *True, BasicBlock *False, MDNode *BranchWeights=nullptr, MDNode *Unpredictable=nullptr)
Create a conditional 'br Cond, TrueDest, FalseDest' instruction.
Value * CreateAdd(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
BranchInst * CreateBr(BasicBlock *Dest)
Create an unconditional 'br label X' instruction.
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
StoreInst * CreateAlignedStore(Value *Val, Value *Ptr, MaybeAlign Align, bool isVolatile=false)
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
LLVM_ABI const DebugLoc & getStableDebugLoc() const
Fetch the debug location for this node, unless this is a debug intrinsic, in which case fetch the deb...
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
Class to represent integer types.
This is an important class for using LLVM in a threaded context.
An instruction for reading from memory.
void setAtomic(AtomicOrdering Ordering, SyncScope::ID SSID=SyncScope::System)
Sets the ordering constraint and the synchronization scope ID of this load instruction.
MDNode * createAnonymousAliasScope(MDNode *Domain, StringRef Name=StringRef())
Return metadata appropriate for an alias scope root node.
LLVM_ABI MDNode * createLikelyBranchWeights()
Return metadata containing two branch weights, with significant bias towards true destination.
MDNode * createAnonymousAliasScopeDomain(StringRef Name=StringRef())
Return metadata appropriate for an alias scope domain node.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
This class wraps the llvm.memcpy intrinsic.
Value * getLength() const
Value * getRawDest() const
MaybeAlign getDestAlign() const
This is the common base class for memset/memcpy/memmove.
This class wraps the llvm.memmove intrinsic.
This class wraps the llvm.memset and llvm.memset.inline intrinsics.
This class wraps the llvm.experimental.memset.pattern intrinsic.
Common base class for all memory transfer intrinsics.
Value * getRawSource() const
Return the arguments to the instruction.
MaybeAlign getSourceAlign() const
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
This class represents an analyzed expression in the program.
The main scalar evolution driver.
LLVM_ABI const SCEV * getSCEV(Value *V)
Return a SCEV expression for the full generality of the specified expression.
LLVM_ABI bool isKnownPredicateAt(CmpPredicate Pred, const SCEV *LHS, const SCEV *RHS, const Instruction *CtxI)
Test if the given expression is known to satisfy the condition described by Pred, LHS,...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
void setAtomic(AtomicOrdering Ordering, SyncScope::ID SSID=SyncScope::System)
Sets the ordering constraint and the synchronization scope ID of this store instruction.
StringRef - Represent a constant reference to a string, i.e.
The instances of the Type class are immutable: once they are created, they are never changed.
bool isVectorTy() const
True if this is an instance of VectorType.
LLVM_ABI unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void setName(const Twine &Name)
Change the name of the value.
const ParentTy * getParent() const
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI void createMemCpyLoopKnownSize(Instruction *InsertBefore, Value *SrcAddr, Value *DstAddr, ConstantInt *CopyLen, Align SrcAlign, Align DestAlign, bool SrcIsVolatile, bool DstIsVolatile, bool CanOverlap, const TargetTransformInfo &TTI, std::optional< uint32_t > AtomicCpySize=std::nullopt, std::optional< uint64_t > AverageTripCount=std::nullopt)
Emit a loop implementing the semantics of an llvm.memcpy whose size is a compile time constant.
FunctionAddr VTableAddr Value
LLVM_ABI void setExplicitlyUnknownBranchWeightsIfProfiled(Instruction &I, StringRef PassName, const Function *F=nullptr)
Like setExplicitlyUnknownBranchWeights(...), but only sets unknown branch weights in the new instruct...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI void expandMemSetPatternAsLoop(MemSetPatternInst *MemSet)
Expand MemSetPattern as a loop. MemSet is not deleted.
LLVM_ABI bool expandMemMoveAsLoop(MemMoveInst *MemMove, const TargetTransformInfo &TTI)
Expand MemMove as a loop.
constexpr T alignDown(U Value, V Align, W Skew=0)
Returns the largest unsigned integer less than or equal to Value and is Skew mod Align.
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
LLVM_ABI void SplitBlockAndInsertIfThenElse(Value *Cond, BasicBlock::iterator SplitBefore, Instruction **ThenTerm, Instruction **ElseTerm, MDNode *BranchWeights=nullptr, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr)
SplitBlockAndInsertIfThenElse is similar to SplitBlockAndInsertIfThen, but also creates the ElseBlock...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI SmallVector< InstrProfValueData, 4 > getValueProfDataFromInst(const Instruction &Inst, InstrProfValueKind ValueKind, uint32_t MaxNumValueData, uint64_t &TotalC, bool GetNoICPValue=false)
Extract the value profile data from Inst and returns them if Inst is annotated with value profile dat...
LLVM_ABI void expandAtomicMemCpyAsLoop(AnyMemCpyInst *AtomicMemCpy, const TargetTransformInfo &TTI, ScalarEvolution *SE)
Expand AtomicMemCpy as a loop. AtomicMemCpy is not deleted.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
LLVM_ABI void expandMemCpyAsLoop(MemCpyInst *MemCpy, const TargetTransformInfo &TTI, ScalarEvolution *SE=nullptr)
Expand MemCpy as a loop. MemCpy is not deleted.
cl::opt< bool > ProfcheckDisableMetadataFixes("profcheck-disable-metadata-fixes", cl::Hidden, cl::init(false), cl::desc("Disable metadata propagation fixes discovered through Issue #147390"))
LLVM_ABI void setFittedBranchWeights(Instruction &I, ArrayRef< uint64_t > Weights, bool IsExpected, bool ElideAllZero=false)
Variant of setBranchWeights where the Weights will be fit first to uint32_t by shifting right.
LLVM_ABI void createMemCpyLoopUnknownSize(Instruction *InsertBefore, Value *SrcAddr, Value *DstAddr, Value *CopyLen, Align SrcAlign, Align DestAlign, bool SrcIsVolatile, bool DstIsVolatile, bool CanOverlap, const TargetTransformInfo &TTI, std::optional< unsigned > AtomicSize=std::nullopt, std::optional< uint64_t > AverageTripCount=std::nullopt)
Emit a loop implementing the semantics of llvm.memcpy where the size is not a compile-time constant.
LLVM_ABI void expandMemSetAsLoop(MemSetInst *MemSet)
Expand MemSet as a loop. MemSet is not deleted.
This struct is a compact representation of a valid (non-zero power of two) alignment.
Align valueOrOne() const
For convenience, returns a valid alignment or 1 if undefined.