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) {
114 IRBuilder<> RBuilder(InsertIt->getParent(), InsertIt);
118 SrcAS, DstAS, SrcAlign, DstAlign,
121 for (
auto *OpTy : RemainingOps) {
125 unsigned OperandSize =
DL.getTypeStoreSize(OpTy);
127 (!AtomicElementSize || OperandSize % *AtomicElementSize == 0) &&
128 "Atomic memcpy lowering is not supported for selected operand size");
131 Int8Type, SrcAddr, ConstantInt::get(TypeOfCopyLen, BytesCopied));
136 Load->setMetadata(LLVMContext::MD_alias_scope,
140 Int8Type, DstAddr, ConstantInt::get(TypeOfCopyLen, BytesCopied));
145 Store->setMetadata(LLVMContext::MD_noalias,
MDNode::get(Ctx, NewScope));
147 if (AtomicElementSize) {
148 Load->setAtomic(AtomicOrdering::Unordered);
149 Store->setAtomic(AtomicOrdering::Unordered);
151 BytesCopied += OperandSize;
155 "Bytes copied should match size in the call!");
161 unsigned OpSizeVal) {
164 return B.CreateAnd(Len, OpSizeVal - 1);
165 return B.CreateURem(Len, OpSize);
173 Value *Len,
Value *OpSize,
unsigned OpSizeVal,
174 Value *RTLoopRemainder =
nullptr) {
175 if (!RTLoopRemainder)
177 return B.CreateSub(Len, RTLoopRemainder);
182 Align SrcAlign,
Align DstAlign,
bool SrcIsVolatile,
bool DstIsVolatile,
184 std::optional<uint32_t> AtomicElementSize) {
187 PreLoopBB->
splitBasicBlock(InsertBefore,
"post-loop-memcpy-expansion");
193 MDNode *NewDomain = MDB.createAnonymousAliasScopeDomain(
"MemCopyDomain");
195 MDNode *NewScope = MDB.createAnonymousAliasScope(NewDomain,
Name);
197 unsigned SrcAS = cast<PointerType>(SrcAddr->
getType())->getAddressSpace();
198 unsigned DstAS = cast<PointerType>(DstAddr->
getType())->getAddressSpace();
201 Ctx, CopyLen, SrcAS, DstAS, SrcAlign, DstAlign, AtomicElementSize);
203 "Atomic memcpy lowering is not supported for vector operand type");
204 unsigned LoopOpSize =
DL.getTypeStoreSize(LoopOpType);
205 assert((!AtomicElementSize || LoopOpSize % *AtomicElementSize == 0) &&
206 "Atomic memcpy lowering is not supported for selected operand size");
212 IntegerType *ILengthType = dyn_cast<IntegerType>(CopyLenType);
214 "expected size argument to memcpy to be an integer type!");
216 bool LoopOpIsInt8 = LoopOpType == Int8Type;
217 ConstantInt *CILoopOpSize = ConstantInt::get(ILengthType, LoopOpSize);
219 Value *RuntimeLoopBytes = CopyLen;
220 Value *RuntimeResidualBytes =
nullptr;
223 CILoopOpSize, LoopOpSize);
225 LoopOpSize, RuntimeResidualBytes);
235 PHINode *LoopIndex = LoopBuilder.CreatePHI(CopyLenType, 2,
"loop-index");
236 LoopIndex->
addIncoming(ConstantInt::get(CopyLenType, 0U), PreLoopBB);
242 Value *SrcGEP = LoopBuilder.CreateInBoundsGEP(Int8Type, SrcAddr, LoopIndex);
243 LoadInst *
Load = LoopBuilder.CreateAlignedLoad(LoopOpType, SrcGEP,
244 PartSrcAlign, SrcIsVolatile);
247 Load->setMetadata(LLVMContext::MD_alias_scope,
MDNode::get(Ctx, NewScope));
249 Value *DstGEP = LoopBuilder.CreateInBoundsGEP(Int8Type, DstAddr, LoopIndex);
251 LoopBuilder.CreateAlignedStore(Load, DstGEP, PartDstAlign, DstIsVolatile);
256 if (AtomicElementSize) {
257 Load->setAtomic(AtomicOrdering::Unordered);
258 Store->setAtomic(AtomicOrdering::Unordered);
260 Value *NewIndex = LoopBuilder.CreateAdd(
261 LoopIndex, ConstantInt::get(CopyLenType, LoopOpSize));
264 bool RequiresResidual =
265 !LoopOpIsInt8 && !(AtomicElementSize && LoopOpSize == AtomicElementSize);
266 if (RequiresResidual) {
267 Type *ResLoopOpType = AtomicElementSize
270 unsigned ResLoopOpSize =
DL.getTypeStoreSize(ResLoopOpType);
271 assert((ResLoopOpSize == AtomicElementSize ? *AtomicElementSize : 1) &&
272 "Store size is expected to match type size");
279 Ctx,
"loop-memcpy-residual", PreLoopBB->
getParent(), PostLoopBB);
282 Ctx,
"loop-memcpy-residual-header", PreLoopBB->
getParent(),
nullptr);
290 PLBuilder.CreateCondBr(PLBuilder.CreateICmpNE(RuntimeLoopBytes, Zero),
291 LoopBB, ResHeaderBB);
294 LoopBuilder.CreateCondBr(
295 LoopBuilder.CreateICmpULT(NewIndex, RuntimeLoopBytes), LoopBB,
300 RHBuilder.CreateCondBr(RHBuilder.CreateICmpNE(RuntimeResidualBytes, Zero),
301 ResLoopBB, PostLoopBB);
306 ResBuilder.CreatePHI(CopyLenType, 2,
"residual-loop-index");
309 Value *FullOffset = ResBuilder.CreateAdd(RuntimeLoopBytes, ResidualIndex);
310 Value *SrcGEP = ResBuilder.CreateInBoundsGEP(Int8Type, SrcAddr, FullOffset);
311 LoadInst *
Load = ResBuilder.CreateAlignedLoad(ResLoopOpType, SrcGEP,
312 ResSrcAlign, SrcIsVolatile);
315 Load->setMetadata(LLVMContext::MD_alias_scope,
318 Value *DstGEP = ResBuilder.CreateInBoundsGEP(Int8Type, DstAddr, FullOffset);
320 ResBuilder.CreateAlignedStore(Load, DstGEP, ResDstAlign, DstIsVolatile);
325 if (AtomicElementSize) {
326 Load->setAtomic(AtomicOrdering::Unordered);
327 Store->setAtomic(AtomicOrdering::Unordered);
329 Value *ResNewIndex = ResBuilder.CreateAdd(
330 ResidualIndex, ConstantInt::get(CopyLenType, ResLoopOpSize));
331 ResidualIndex->
addIncoming(ResNewIndex, ResLoopBB);
334 ResBuilder.CreateCondBr(
335 ResBuilder.CreateICmpULT(ResNewIndex, RuntimeResidualBytes), ResLoopBB,
343 PLBuilder.CreateCondBr(PLBuilder.CreateICmpNE(RuntimeLoopBytes, Zero),
346 LoopBuilder.CreateCondBr(
347 LoopBuilder.CreateICmpULT(NewIndex, RuntimeLoopBytes), LoopBB,
356static std::pair<Value *, Value *>
359 Value *ResAddr1 = Addr1;
360 Value *ResAddr2 = Addr2;
362 unsigned AS1 = cast<PointerType>(Addr1->
getType())->getAddressSpace();
363 unsigned AS2 = cast<PointerType>(Addr2->
getType())->getAddressSpace();
366 ResAddr2 =
B.CreateAddrSpaceCast(Addr2, Addr1->
getType());
368 ResAddr1 =
B.CreateAddrSpaceCast(Addr1, Addr2->
getType());
371 "support addrspacecast");
373 return {ResAddr1, ResAddr2};
405 Align DstAlign,
bool SrcIsVolatile,
413 unsigned SrcAS = cast<PointerType>(SrcAddr->
getType())->getAddressSpace();
414 unsigned DstAS = cast<PointerType>(DstAddr->
getType())->getAddressSpace();
418 unsigned LoopOpSize =
DL.getTypeStoreSize(LoopOpType);
420 bool LoopOpIsInt8 = LoopOpType == Int8Type;
424 bool RequiresResidual = !LoopOpIsInt8;
426 Type *ResidualLoopOpType = Int8Type;
427 unsigned ResidualLoopOpSize =
DL.getTypeStoreSize(ResidualLoopOpType);
430 IntegerType *ILengthType = cast<IntegerType>(TypeOfCopyLen);
431 ConstantInt *CILoopOpSize = ConstantInt::get(ILengthType, LoopOpSize);
433 ConstantInt::get(ILengthType, ResidualLoopOpSize);
434 ConstantInt *Zero = ConstantInt::get(ILengthType, 0);
438 Value *RuntimeLoopBytes = CopyLen;
439 Value *RuntimeLoopRemainder =
nullptr;
440 Value *SkipResidualCondition =
nullptr;
441 if (RequiresResidual) {
443 CILoopOpSize, LoopOpSize);
445 LoopOpSize, RuntimeLoopRemainder);
446 SkipResidualCondition =
447 PLBuilder.
CreateICmpEQ(RuntimeLoopRemainder, Zero,
"skip_residual");
449 Value *SkipMainCondition =
450 PLBuilder.
CreateICmpEQ(RuntimeLoopBytes, Zero,
"skip_main");
461 auto [CmpSrcAddr, CmpDstAddr] =
464 PLBuilder.
CreateICmpULT(CmpSrcAddr, CmpDstAddr,
"compare_src_dst");
467 &ThenTerm, &ElseTerm);
494 CopyBackwardsBB->
setName(
"memmove_copy_backwards");
496 CopyForwardBB->
setName(
"memmove_copy_forward");
498 ExitBB->
setName(
"memmove_done");
511 F->getContext(),
"memmove_bwd_main_loop",
F, CopyForwardBB);
517 if (RequiresResidual) {
520 F->getContext(),
"memmove_bwd_residual_loop",
F, MainLoopBB);
524 ResidualLoopPhi, CIResidualLoopOpSize,
"bwd_residual_index");
532 ResidualLoopOpType, LoadGEP, ResidualSrcAlign, SrcIsVolatile,
537 ResidualDstAlign, DstIsVolatile);
541 F->getContext(),
"memmove_bwd_middle",
F, MainLoopBB);
546 ResidualLoopBuilder.
CreateICmpEQ(ResidualIndex, RuntimeLoopBytes),
547 IntermediateBB, ResidualLoopBB);
549 ResidualLoopPhi->
addIncoming(ResidualIndex, ResidualLoopBB);
550 ResidualLoopPhi->
addIncoming(CopyLen, CopyBackwardsBB);
557 PredBB = IntermediateBB;
564 MainLoopBuilder.
CreateSub(MainLoopPhi, CILoopOpSize,
"bwd_main_index");
568 LoopOpType, LoadGEP, PartSrcAlign, SrcIsVolatile,
"element");
576 MainLoopPhi->
addIncoming(RuntimeLoopBytes, PredBB);
592 MainLoopBuilder.
CreatePHI(ILengthType, 0,
"fwd_main_index");
596 LoopOpType, LoadGEP, PartSrcAlign, SrcIsVolatile,
"element");
601 Value *MainIndex = MainLoopBuilder.
CreateAdd(MainLoopPhi, CILoopOpSize);
607 if (RequiresResidual)
613 MainLoopBuilder.
CreateICmpEQ(MainIndex, RuntimeLoopBytes), SuccessorBB,
621 if (RequiresResidual) {
625 F->getContext(),
"memmove_fwd_residual_loop",
F, ExitBB);
626 IntermediateBuilder.
CreateCondBr(SkipResidualCondition, ExitBB,
632 ResidualLoopBuilder.
CreatePHI(ILengthType, 0,
"fwd_residual_index");
636 ResidualLoopOpType, LoadGEP, ResidualSrcAlign, SrcIsVolatile,
641 ResidualDstAlign, DstIsVolatile);
642 Value *ResidualIndex =
643 ResidualLoopBuilder.
CreateAdd(ResidualLoopPhi, CIResidualLoopOpSize);
645 ResidualLoopBuilder.
CreateICmpEQ(ResidualIndex, CopyLen), ExitBB,
647 ResidualLoopPhi->
addIncoming(ResidualIndex, ResidualLoopBB);
648 ResidualLoopPhi->
addIncoming(RuntimeLoopBytes, IntermediateBB);
659 Align DstAlign,
bool SrcIsVolatile,
671 unsigned SrcAS = cast<PointerType>(SrcAddr->
getType())->getAddressSpace();
672 unsigned DstAS = cast<PointerType>(DstAddr->
getType())->getAddressSpace();
676 unsigned LoopOpSize =
DL.getTypeStoreSize(LoopOpType);
683 IntegerType *ILengthType = cast<IntegerType>(TypeOfCopyLen);
684 ConstantInt *Zero = ConstantInt::get(ILengthType, 0);
685 ConstantInt *LoopBound = ConstantInt::get(ILengthType, BytesCopiedInLoop);
686 ConstantInt *CILoopOpSize = ConstantInt::get(ILengthType, LoopOpSize);
690 auto [CmpSrcAddr, CmpDstAddr] =
693 PLBuilder.
CreateICmpULT(CmpSrcAddr, CmpDstAddr,
"compare_src_dst");
696 &ThenTerm, &ElseTerm);
701 ExitBB->
setName(
"memmove_done");
713 unsigned OperandSize =
DL.getTypeStoreSize(OpTy);
719 Value *SrcGEP = Builder.CreateInBoundsGEP(
720 Int8Type, SrcAddr, ConstantInt::get(TypeOfCopyLen, BytesCopied));
722 Builder.CreateAlignedLoad(OpTy, SrcGEP, ResSrcAlign, SrcIsVolatile);
723 Value *DstGEP = Builder.CreateInBoundsGEP(
724 Int8Type, DstAddr, ConstantInt::get(TypeOfCopyLen, BytesCopied));
725 Builder.CreateAlignedStore(Load, DstGEP, ResDstAlign, DstIsVolatile);
726 BytesCopied += OperandSize;
730 if (RemainingBytes != 0) {
731 CopyBackwardsBB->
setName(
"memmove_bwd_residual");
732 uint64_t BytesCopied = BytesCopiedInLoop;
743 SrcAS, DstAS, PartSrcAlign,
745 for (
auto *OpTy : RemainingOps) {
749 GenerateResidualLdStPair(OpTy, BwdResBuilder, BytesCopied);
752 if (BytesCopiedInLoop != 0) {
755 if (RemainingBytes != 0) {
759 PredBB = CopyBackwardsBB;
761 CopyBackwardsBB->
setName(
"memmove_bwd_loop");
765 Value *Index = LoopBuilder.
CreateSub(LoopPhi, CILoopOpSize,
"bwd_index");
768 LoopOpType, LoadGEP, PartSrcAlign, SrcIsVolatile,
"element");
786 if (BytesCopiedInLoop != 0) {
787 CopyForwardBB->
setName(
"memmove_fwd_loop");
790 if (RemainingBytes != 0) {
793 "memmove_fwd_residual");
794 FwdResidualBB = SuccBB;
800 LoopOpType, LoadGEP, PartSrcAlign, SrcIsVolatile,
"element");
815 if (RemainingBytes != 0) {
816 uint64_t BytesCopied = BytesCopiedInLoop;
823 SrcAS, DstAS, PartSrcAlign,
825 for (
auto *OpTy : RemainingOps)
826 GenerateResidualLdStPair(OpTy, FwdResBuilder, BytesCopied);
845 Builder.
CreateICmpEQ(ConstantInt::get(TypeOfCopyLen, 0), CopyLen), NewBB,
849 unsigned PartSize =
DL.getTypeStoreSize(
SetValue->getType());
854 LoopIndex->
addIncoming(ConstantInt::get(TypeOfCopyLen, 0), OrigBB);
859 PartAlign, IsVolatile);
862 LoopBuilder.
CreateAdd(LoopIndex, ConstantInt::get(TypeOfCopyLen, 1));
873 const SCEV *DestSCEV = SE->
getSCEV(Memcpy->getRawDest());
919 bool DstIsVolatile = SrcIsVolatile;
924 if (SrcAS != DstAS) {
928 if (
ConstantInt *CI = dyn_cast<ConstantInt>(CopyLen)) {
930 CI, SrcAlign, DstAlign, SrcIsVolatile,
935 CopyLen, SrcAlign, DstAlign, SrcIsVolatile,
949 dbgs() <<
"Do not know how to expand memmove between different "
955 if (
ConstantInt *CI = dyn_cast<ConstantInt>(CopyLen)) {
957 Memmove, SrcAddr, DstAddr, CI, SrcAlign, DstAlign,
958 SrcIsVolatile, DstIsVolatile,
TTI);
961 Memmove, SrcAddr, DstAddr, CopyLen, SrcAlign, DstAlign,
962 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.
InstListType::const_iterator getFirstNonPHIIt() const
Iterator returning form of getFirstNonPHI.
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.
InstListType::iterator iterator
Instruction iterators...
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(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.
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.