20#define DEBUG_TYPE "lower-mem-intrinsics"
28 std::optional<uint32_t> AtomicElementSize) {
43 unsigned SrcAS = cast<PointerType>(SrcAddr->
getType())->getAddressSpace();
44 unsigned DstAS = cast<PointerType>(DstAddr->
getType())->getAddressSpace();
48 Ctx, CopyLen, SrcAS, DstAS, SrcAlign, DstAlign, AtomicElementSize);
50 "Atomic memcpy lowering is not supported for vector operand type");
53 unsigned LoopOpSize =
DL.getTypeStoreSize(LoopOpType);
54 assert((!AtomicElementSize || LoopOpSize % *AtomicElementSize == 0) &&
55 "Atomic memcpy lowering is not supported for selected operand size");
59 if (LoopEndCount != 0) {
73 LoopIndex->
addIncoming(ConstantInt::get(TypeOfCopyLen, 0U), PreLoopBB);
82 PartSrcAlign, SrcIsVolatile);
85 Load->setMetadata(LLVMContext::MD_alias_scope,
90 Load, DstGEP, PartDstAlign, DstIsVolatile);
93 Store->setMetadata(LLVMContext::MD_noalias,
MDNode::get(Ctx, NewScope));
95 if (AtomicElementSize) {
96 Load->setAtomic(AtomicOrdering::Unordered);
97 Store->setAtomic(AtomicOrdering::Unordered);
100 LoopIndex, ConstantInt::get(TypeOfCopyLen, LoopOpSize));
104 Constant *LoopEndCI = ConstantInt::get(TypeOfCopyLen, LoopEndCount);
109 uint64_t BytesCopied = LoopEndCount;
111 if (RemainingBytes) {
117 SrcAS, DstAS, SrcAlign, DstAlign,
120 for (
auto *OpTy : RemainingOps) {
124 unsigned OperandSize =
DL.getTypeStoreSize(OpTy);
126 (!AtomicElementSize || OperandSize % *AtomicElementSize == 0) &&
127 "Atomic memcpy lowering is not supported for selected operand size");
130 Int8Type, SrcAddr, ConstantInt::get(TypeOfCopyLen, BytesCopied));
135 Load->setMetadata(LLVMContext::MD_alias_scope,
139 Int8Type, DstAddr, ConstantInt::get(TypeOfCopyLen, BytesCopied));
144 Store->setMetadata(LLVMContext::MD_noalias,
MDNode::get(Ctx, NewScope));
146 if (AtomicElementSize) {
147 Load->setAtomic(AtomicOrdering::Unordered);
148 Store->setAtomic(AtomicOrdering::Unordered);
150 BytesCopied += OperandSize;
154 "Bytes copied should match size in the call!");
160 unsigned OpSizeVal) {
163 return B.CreateAnd(Len, OpSizeVal - 1);
164 return B.CreateURem(Len, OpSize);
172 Value *Len,
Value *OpSize,
unsigned OpSizeVal,
173 Value *RTLoopRemainder =
nullptr) {
174 if (!RTLoopRemainder)
176 return B.CreateSub(Len, RTLoopRemainder);
181 Align SrcAlign,
Align DstAlign,
bool SrcIsVolatile,
bool DstIsVolatile,
183 std::optional<uint32_t> AtomicElementSize) {
186 PreLoopBB->
splitBasicBlock(InsertBefore,
"post-loop-memcpy-expansion");
192 MDNode *NewDomain = MDB.createAnonymousAliasScopeDomain(
"MemCopyDomain");
194 MDNode *NewScope = MDB.createAnonymousAliasScope(NewDomain,
Name);
196 unsigned SrcAS = cast<PointerType>(SrcAddr->
getType())->getAddressSpace();
197 unsigned DstAS = cast<PointerType>(DstAddr->
getType())->getAddressSpace();
200 Ctx, CopyLen, SrcAS, DstAS, SrcAlign, DstAlign, AtomicElementSize);
202 "Atomic memcpy lowering is not supported for vector operand type");
203 unsigned LoopOpSize =
DL.getTypeStoreSize(LoopOpType);
204 assert((!AtomicElementSize || LoopOpSize % *AtomicElementSize == 0) &&
205 "Atomic memcpy lowering is not supported for selected operand size");
211 IntegerType *ILengthType = dyn_cast<IntegerType>(CopyLenType);
213 "expected size argument to memcpy to be an integer type!");
215 bool LoopOpIsInt8 = LoopOpType == Int8Type;
216 ConstantInt *CILoopOpSize = ConstantInt::get(ILengthType, LoopOpSize);
218 Value *RuntimeLoopBytes = CopyLen;
219 Value *RuntimeResidualBytes =
nullptr;
222 CILoopOpSize, LoopOpSize);
224 LoopOpSize, RuntimeResidualBytes);
234 PHINode *LoopIndex = LoopBuilder.CreatePHI(CopyLenType, 2,
"loop-index");
235 LoopIndex->
addIncoming(ConstantInt::get(CopyLenType, 0U), PreLoopBB);
241 Value *SrcGEP = LoopBuilder.CreateInBoundsGEP(Int8Type, SrcAddr, LoopIndex);
242 LoadInst *
Load = LoopBuilder.CreateAlignedLoad(LoopOpType, SrcGEP,
243 PartSrcAlign, SrcIsVolatile);
246 Load->setMetadata(LLVMContext::MD_alias_scope,
MDNode::get(Ctx, NewScope));
248 Value *DstGEP = LoopBuilder.CreateInBoundsGEP(Int8Type, DstAddr, LoopIndex);
250 LoopBuilder.CreateAlignedStore(Load, DstGEP, PartDstAlign, DstIsVolatile);
255 if (AtomicElementSize) {
256 Load->setAtomic(AtomicOrdering::Unordered);
257 Store->setAtomic(AtomicOrdering::Unordered);
259 Value *NewIndex = LoopBuilder.CreateAdd(
260 LoopIndex, ConstantInt::get(CopyLenType, LoopOpSize));
263 bool RequiresResidual =
264 !LoopOpIsInt8 && !(AtomicElementSize && LoopOpSize == AtomicElementSize);
265 if (RequiresResidual) {
266 Type *ResLoopOpType = AtomicElementSize
269 unsigned ResLoopOpSize =
DL.getTypeStoreSize(ResLoopOpType);
270 assert((ResLoopOpSize == AtomicElementSize ? *AtomicElementSize : 1) &&
271 "Store size is expected to match type size");
278 Ctx,
"loop-memcpy-residual", PreLoopBB->
getParent(), PostLoopBB);
281 Ctx,
"loop-memcpy-residual-header", PreLoopBB->
getParent(),
nullptr);
289 PLBuilder.CreateCondBr(PLBuilder.CreateICmpNE(RuntimeLoopBytes, Zero),
290 LoopBB, ResHeaderBB);
293 LoopBuilder.CreateCondBr(
294 LoopBuilder.CreateICmpULT(NewIndex, RuntimeLoopBytes), LoopBB,
299 RHBuilder.CreateCondBr(RHBuilder.CreateICmpNE(RuntimeResidualBytes, Zero),
300 ResLoopBB, PostLoopBB);
305 ResBuilder.CreatePHI(CopyLenType, 2,
"residual-loop-index");
308 Value *FullOffset = ResBuilder.CreateAdd(RuntimeLoopBytes, ResidualIndex);
309 Value *SrcGEP = ResBuilder.CreateInBoundsGEP(Int8Type, SrcAddr, FullOffset);
310 LoadInst *
Load = ResBuilder.CreateAlignedLoad(ResLoopOpType, SrcGEP,
311 ResSrcAlign, SrcIsVolatile);
314 Load->setMetadata(LLVMContext::MD_alias_scope,
317 Value *DstGEP = ResBuilder.CreateInBoundsGEP(Int8Type, DstAddr, FullOffset);
319 ResBuilder.CreateAlignedStore(Load, DstGEP, ResDstAlign, DstIsVolatile);
324 if (AtomicElementSize) {
325 Load->setAtomic(AtomicOrdering::Unordered);
326 Store->setAtomic(AtomicOrdering::Unordered);
328 Value *ResNewIndex = ResBuilder.CreateAdd(
329 ResidualIndex, ConstantInt::get(CopyLenType, ResLoopOpSize));
330 ResidualIndex->
addIncoming(ResNewIndex, ResLoopBB);
333 ResBuilder.CreateCondBr(
334 ResBuilder.CreateICmpULT(ResNewIndex, RuntimeResidualBytes), ResLoopBB,
342 PLBuilder.CreateCondBr(PLBuilder.CreateICmpNE(RuntimeLoopBytes, Zero),
345 LoopBuilder.CreateCondBr(
346 LoopBuilder.CreateICmpULT(NewIndex, RuntimeLoopBytes), LoopBB,
355static std::pair<Value *, Value *>
358 Value *ResAddr1 = Addr1;
359 Value *ResAddr2 = Addr2;
361 unsigned AS1 = cast<PointerType>(Addr1->
getType())->getAddressSpace();
362 unsigned AS2 = cast<PointerType>(Addr2->
getType())->getAddressSpace();
365 ResAddr2 =
B.CreateAddrSpaceCast(Addr2, Addr1->
getType());
367 ResAddr1 =
B.CreateAddrSpaceCast(Addr1, Addr2->
getType());
370 "support addrspacecast");
372 return {ResAddr1, ResAddr2};
404 Align DstAlign,
bool SrcIsVolatile,
412 unsigned SrcAS = cast<PointerType>(SrcAddr->
getType())->getAddressSpace();
413 unsigned DstAS = cast<PointerType>(DstAddr->
getType())->getAddressSpace();
417 unsigned LoopOpSize =
DL.getTypeStoreSize(LoopOpType);
419 bool LoopOpIsInt8 = LoopOpType == Int8Type;
423 bool RequiresResidual = !LoopOpIsInt8;
425 Type *ResidualLoopOpType = Int8Type;
426 unsigned ResidualLoopOpSize =
DL.getTypeStoreSize(ResidualLoopOpType);
429 IntegerType *ILengthType = cast<IntegerType>(TypeOfCopyLen);
430 ConstantInt *CILoopOpSize = ConstantInt::get(ILengthType, LoopOpSize);
432 ConstantInt::get(ILengthType, ResidualLoopOpSize);
433 ConstantInt *Zero = ConstantInt::get(ILengthType, 0);
437 Value *RuntimeLoopBytes = CopyLen;
438 Value *RuntimeLoopRemainder =
nullptr;
439 Value *SkipResidualCondition =
nullptr;
440 if (RequiresResidual) {
442 CILoopOpSize, LoopOpSize);
444 LoopOpSize, RuntimeLoopRemainder);
445 SkipResidualCondition =
446 PLBuilder.
CreateICmpEQ(RuntimeLoopRemainder, Zero,
"skip_residual");
448 Value *SkipMainCondition =
449 PLBuilder.
CreateICmpEQ(RuntimeLoopBytes, Zero,
"skip_main");
460 auto [CmpSrcAddr, CmpDstAddr] =
463 PLBuilder.
CreateICmpULT(CmpSrcAddr, CmpDstAddr,
"compare_src_dst");
466 &ThenTerm, &ElseTerm);
493 CopyBackwardsBB->
setName(
"memmove_copy_backwards");
495 CopyForwardBB->
setName(
"memmove_copy_forward");
497 ExitBB->
setName(
"memmove_done");
510 F->getContext(),
"memmove_bwd_main_loop",
F, CopyForwardBB);
516 if (RequiresResidual) {
519 F->getContext(),
"memmove_bwd_residual_loop",
F, MainLoopBB);
523 ResidualLoopPhi, CIResidualLoopOpSize,
"bwd_residual_index");
531 ResidualLoopOpType, LoadGEP, ResidualSrcAlign, SrcIsVolatile,
536 ResidualDstAlign, DstIsVolatile);
540 F->getContext(),
"memmove_bwd_middle",
F, MainLoopBB);
545 ResidualLoopBuilder.
CreateICmpEQ(ResidualIndex, RuntimeLoopBytes),
546 IntermediateBB, ResidualLoopBB);
548 ResidualLoopPhi->
addIncoming(ResidualIndex, ResidualLoopBB);
549 ResidualLoopPhi->
addIncoming(CopyLen, CopyBackwardsBB);
556 PredBB = IntermediateBB;
563 MainLoopBuilder.
CreateSub(MainLoopPhi, CILoopOpSize,
"bwd_main_index");
567 LoopOpType, LoadGEP, PartSrcAlign, SrcIsVolatile,
"element");
575 MainLoopPhi->
addIncoming(RuntimeLoopBytes, PredBB);
591 MainLoopBuilder.
CreatePHI(ILengthType, 0,
"fwd_main_index");
595 LoopOpType, LoadGEP, PartSrcAlign, SrcIsVolatile,
"element");
600 Value *MainIndex = MainLoopBuilder.
CreateAdd(MainLoopPhi, CILoopOpSize);
606 if (RequiresResidual)
612 MainLoopBuilder.
CreateICmpEQ(MainIndex, RuntimeLoopBytes), SuccessorBB,
620 if (RequiresResidual) {
624 F->getContext(),
"memmove_fwd_residual_loop",
F, ExitBB);
625 IntermediateBuilder.
CreateCondBr(SkipResidualCondition, ExitBB,
631 ResidualLoopBuilder.
CreatePHI(ILengthType, 0,
"fwd_residual_index");
635 ResidualLoopOpType, LoadGEP, ResidualSrcAlign, SrcIsVolatile,
640 ResidualDstAlign, DstIsVolatile);
641 Value *ResidualIndex =
642 ResidualLoopBuilder.
CreateAdd(ResidualLoopPhi, CIResidualLoopOpSize);
644 ResidualLoopBuilder.
CreateICmpEQ(ResidualIndex, CopyLen), ExitBB,
646 ResidualLoopPhi->
addIncoming(ResidualIndex, ResidualLoopBB);
647 ResidualLoopPhi->
addIncoming(RuntimeLoopBytes, IntermediateBB);
658 Align DstAlign,
bool SrcIsVolatile,
670 unsigned SrcAS = cast<PointerType>(SrcAddr->
getType())->getAddressSpace();
671 unsigned DstAS = cast<PointerType>(DstAddr->
getType())->getAddressSpace();
675 unsigned LoopOpSize =
DL.getTypeStoreSize(LoopOpType);
682 IntegerType *ILengthType = cast<IntegerType>(TypeOfCopyLen);
683 ConstantInt *Zero = ConstantInt::get(ILengthType, 0);
684 ConstantInt *LoopBound = ConstantInt::get(ILengthType, BytesCopiedInLoop);
685 ConstantInt *CILoopOpSize = ConstantInt::get(ILengthType, LoopOpSize);
689 auto [CmpSrcAddr, CmpDstAddr] =
692 PLBuilder.
CreateICmpULT(CmpSrcAddr, CmpDstAddr,
"compare_src_dst");
695 &ThenTerm, &ElseTerm);
700 ExitBB->
setName(
"memmove_done");
712 unsigned OperandSize =
DL.getTypeStoreSize(OpTy);
718 Value *SrcGEP = Builder.CreateInBoundsGEP(
719 Int8Type, SrcAddr, ConstantInt::get(TypeOfCopyLen, BytesCopied));
721 Builder.CreateAlignedLoad(OpTy, SrcGEP, ResSrcAlign, SrcIsVolatile);
722 Value *DstGEP = Builder.CreateInBoundsGEP(
723 Int8Type, DstAddr, ConstantInt::get(TypeOfCopyLen, BytesCopied));
724 Builder.CreateAlignedStore(Load, DstGEP, ResDstAlign, DstIsVolatile);
725 BytesCopied += OperandSize;
729 if (RemainingBytes != 0) {
730 CopyBackwardsBB->
setName(
"memmove_bwd_residual");
731 uint64_t BytesCopied = BytesCopiedInLoop;
741 SrcAS, DstAS, PartSrcAlign,
743 for (
auto *OpTy : RemainingOps) {
746 GenerateResidualLdStPair(OpTy, BwdResBuilder, BytesCopied);
749 if (BytesCopiedInLoop != 0) {
752 if (RemainingBytes != 0) {
756 PredBB = CopyBackwardsBB;
758 CopyBackwardsBB->
setName(
"memmove_bwd_loop");
762 Value *Index = LoopBuilder.
CreateSub(LoopPhi, CILoopOpSize,
"bwd_index");
765 LoopOpType, LoadGEP, PartSrcAlign, SrcIsVolatile,
"element");
783 if (BytesCopiedInLoop != 0) {
784 CopyForwardBB->
setName(
"memmove_fwd_loop");
787 if (RemainingBytes != 0) {
790 "memmove_fwd_residual");
791 FwdResidualBB = SuccBB;
797 LoopOpType, LoadGEP, PartSrcAlign, SrcIsVolatile,
"element");
812 if (RemainingBytes != 0) {
813 uint64_t BytesCopied = BytesCopiedInLoop;
820 SrcAS, DstAS, PartSrcAlign,
822 for (
auto *OpTy : RemainingOps)
823 GenerateResidualLdStPair(OpTy, FwdResBuilder, BytesCopied);
842 Builder.
CreateICmpEQ(ConstantInt::get(TypeOfCopyLen, 0), CopyLen), NewBB,
846 unsigned PartSize =
DL.getTypeStoreSize(
SetValue->getType());
851 LoopIndex->
addIncoming(ConstantInt::get(TypeOfCopyLen, 0), OrigBB);
856 PartAlign, IsVolatile);
859 LoopBuilder.
CreateAdd(LoopIndex, ConstantInt::get(TypeOfCopyLen, 1));
870 const SCEV *DestSCEV = SE->
getSCEV(Memcpy->getRawDest());
916 bool DstIsVolatile = SrcIsVolatile;
921 if (SrcAS != DstAS) {
925 if (
ConstantInt *CI = dyn_cast<ConstantInt>(CopyLen)) {
927 CI, SrcAlign, DstAlign, SrcIsVolatile,
932 CopyLen, SrcAlign, DstAlign, SrcIsVolatile,
946 dbgs() <<
"Do not know how to expand memmove between different "
952 if (
ConstantInt *CI = dyn_cast<ConstantInt>(CopyLen)) {
954 Memmove, SrcAddr, DstAddr, CI, SrcAlign, DstAlign,
955 SrcIsVolatile, DstIsVolatile,
TTI);
958 Memmove, SrcAddr, DstAddr, CopyLen, SrcAlign, DstAlign,
959 SrcIsVolatile, DstIsVolatile,
TTI);
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 void createMemMoveLoopKnownSize(Instruction *InsertBefore, Value *SrcAddr, Value *DstAddr, ConstantInt *CopyLen, Align SrcAlign, Align DstAlign, bool SrcIsVolatile, bool DstIsVolatile, const TargetTransformInfo &TTI)
static Value * getRuntimeLoopRemainder(const DataLayout &DL, IRBuilderBase &B, Value *Len, Value *OpSize, unsigned OpSizeVal)
static void createMemSetLoop(Instruction *InsertBefore, Value *DstAddr, Value *CopyLen, Value *SetValue, Align DstAlign, bool IsVolatile)
static Value * getRuntimeLoopBytes(const DataLayout &DL, 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)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This class represents the atomic memcpy intrinsic i.e.
uint32_t getElementSizeInBytes() const
LLVM Basic Block Representation.
const Instruction * getFirstNonPHI() const
Returns a pointer 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.
BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="", bool Before=false)
Split the basic block into two basic blocks at the specified instruction.
const Function * getParent() const
Return the enclosing method, or null if none.
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...
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...
This is an important base class in LLVM.
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.
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()
Value * CreateInBoundsGEP(Type *Ty, Value *Ptr, ArrayRef< Value * > IdxList, 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)
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...
InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
bool isVolatile() const LLVM_READONLY
Return true if this instruction has a volatile memory access.
void setSuccessor(unsigned Idx, BasicBlock *BB)
Update the specified successor to point at the provided block.
Class to represent integer types.
This is an important class for using LLVM in a threaded context.
An instruction for reading from memory.
MDNode * createAnonymousAliasScope(MDNode *Domain, StringRef Name=StringRef())
Return metadata appropriate for an alias scope root node.
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 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.
const SCEV * getSCEV(Value *V)
Return a SCEV expression for the full generality of the specified expression.
bool isKnownPredicateAt(ICmpInst::Predicate 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.
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.
unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
static IntegerType * getIntNTy(LLVMContext &C, unsigned N)
static IntegerType * getInt8Ty(LLVMContext &C)
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
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.
This is an optimization pass for GlobalISel generic memory operations.
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)
Emit a loop implementing the semantics of an llvm.memcpy whose size is a compile time constant.
void expandMemSetPatternAsLoop(MemSetPatternInst *MemSet)
Expand MemSetPattern as a loop. MemSet is not deleted.
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.
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)
Emit a loop implementing the semantics of llvm.memcpy where the size is not a compile-time constant.
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
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...
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
void expandMemCpyAsLoop(MemCpyInst *MemCpy, const TargetTransformInfo &TTI, ScalarEvolution *SE=nullptr)
Expand MemCpy as a loop. MemCpy is not deleted.
void expandAtomicMemCpyAsLoop(AtomicMemCpyInst *AtomicMemCpy, const TargetTransformInfo &TTI, ScalarEvolution *SE)
Expand AtomicMemCpy as a loop. AtomicMemCpy is not deleted.
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.