26#define DEBUG_TYPE "lower-mem-intrinsics"
33 Value *OpSize,
unsigned OpSizeVal) {
36 return B.CreateAnd(Len, OpSizeVal - 1);
37 return B.CreateURem(Len, OpSize);
46 Value *RTLoopRemainder =
nullptr) {
49 return B.CreateSub(Len, RTLoopRemainder);
54struct LoopExpansionInfo {
59 Value *MainLoopIndex =
nullptr;
67 Value *ResidualLoopIndex =
nullptr;
70std::optional<uint64_t> getAverageMemOpLoopTripCount(
const MemIntrinsic &
I) {
71 if (std::optional<uint64_t> EC =
I.getFunction()->getEntryCount();
74 if (
const auto Len =
I.getLengthInBytes())
75 return Len->getZExtValue();
79 std::numeric_limits<uint32_t>::max(),
Total);
83 for (
const auto &
P : ProfData)
84 TripCount +=
P.Count *
P.Value;
85 return std::round(1.0 * TripCount /
Total);
125static LoopExpansionInfo
127 unsigned MainLoopStep,
unsigned ResidualLoopStep,
129 std::optional<uint64_t> ExpectedUnits) {
130 assert((ResidualLoopStep == 0 || MainLoopStep % ResidualLoopStep == 0) &&
131 "ResidualLoopStep must divide MainLoopStep if specified");
132 assert(ResidualLoopStep <= MainLoopStep &&
133 "ResidualLoopStep cannot be larger than MainLoopStep");
134 assert(MainLoopStep > 0 &&
"MainLoopStep must be non-zero");
135 LoopExpansionInfo LEI;
144 InsertBefore, BBNamePrefix +
"-post-expansion");
153 Type *LenType = Len->getType();
155 ConstantInt *CIMainLoopStep = ConstantInt::get(ILenType, MainLoopStep);
164 bool MustTakeMainLoop =
false;
165 bool MayTakeMainLoop =
true;
166 bool MustTakeResidualLoop =
false;
167 bool MayTakeResidualLoop =
true;
169 Value *LoopUnits = Len;
170 Value *ResidualUnits =
nullptr;
171 if (MainLoopStep != 1) {
173 uint64_t TotalUnits = CLen->getZExtValue();
175 uint64_t ResidualCount = TotalUnits - LoopEndCount;
176 LoopUnits = ConstantInt::get(LenType, LoopEndCount);
177 ResidualUnits = ConstantInt::get(LenType, ResidualCount);
178 MustTakeMainLoop = LoopEndCount > 0;
179 MayTakeMainLoop = MustTakeMainLoop;
180 MustTakeResidualLoop = ResidualCount > 0;
181 MayTakeResidualLoop = MustTakeResidualLoop;
187 CIMainLoopStep, MainLoopStep);
189 MainLoopStep, ResidualUnits);
192 MustTakeMainLoop = CLen->getZExtValue() > 0;
193 MayTakeMainLoop = MustTakeMainLoop;
198 assert((MayTakeMainLoop || MayTakeResidualLoop) &&
199 "At least one of the loops must be generated");
205 if (MayTakeMainLoop) {
207 ParentFunc, PostLoopBB);
212 LEI.MainLoopIndex = LoopIndex;
213 LoopIndex->
addIncoming(ConstantInt::get(LenType, 0U), PreLoopBB);
216 LoopIndex, ConstantInt::get(LenType, MainLoopStep));
226 LoopBuilder.
CreateICmpULT(NewIndex, LoopUnits), MainLoopBB, PostLoopBB);
228 if (ExpectedUnits.has_value()) {
229 uint64_t BackedgeTakenCount = ExpectedUnits.value() / MainLoopStep;
230 if (BackedgeTakenCount > 0)
231 BackedgeTakenCount -= 1;
242 bool ResidualLoopRequested =
243 ResidualLoopStep > 0 && ResidualLoopStep < MainLoopStep;
246 if (ResidualLoopRequested && MayTakeResidualLoop) {
260 if (MustTakeResidualLoop) {
262 PredOfResLoopBody = MainLoopBB;
274 ResidualLoopBB, PostLoopBB);
275 if (ExpectedUnits.has_value()) {
277 BR->setMetadata(LLVMContext::MD_prof,
284 PredOfResLoopBody = ResidualCondBB;
291 ResBuilder.
CreatePHI(LenType, 2,
"residual-loop-index");
298 LEI.ResidualLoopIndex = ResBuilder.
CreateAdd(LoopUnits, ResidualIndex);
300 LEI.ResidualLoopIndex = ResidualIndex;
303 ResidualIndex, ConstantInt::get(LenType, ResidualLoopStep));
304 ResidualIndex->
addIncoming(ResNewIndex, ResidualLoopBB);
312 ResBuilder.
CreateICmpULT(ResNewIndex, ResidualUnits), ResidualLoopBB,
315 if (ExpectedUnits.has_value()) {
317 (ExpectedUnits.value() % MainLoopStep) / ResidualLoopStep;
318 if (BackedgeTakenCount > 0)
319 BackedgeTakenCount -= 1;
329 if (MustTakeMainLoop) {
333 PreLoopBuilder.
CreateBr(MainLoopBB);
334 }
else if (!MainLoopBB && ResidualLoopBB) {
335 if (MustTakeResidualLoop) {
338 PreLoopBuilder.
CreateBr(ResidualLoopBB);
346 if (ExpectedUnits.has_value()) {
357 if (ResidualCondBB) {
360 FalseBB = ResidualCondBB;
361 }
else if (ResidualLoopBB) {
365 assert(MustTakeResidualLoop);
366 FalseBB = ResidualLoopBB;
372 if (ExpectedUnits.has_value()) {
388 bool SrcIsVolatile,
bool DstIsVolatile,
391 std::optional<uint32_t> AtomicElementSize,
392 std::optional<uint64_t> AverageTripCount) {
410 Type *LoopOpType =
TTI.getMemcpyLoopLoweringType(
411 Ctx, CopyLen, SrcAS, DstAS, SrcAlign, DstAlign, AtomicElementSize);
413 "Atomic memcpy lowering is not supported for vector operand type");
416 TypeSize LoopOpSize =
DL.getTypeStoreSize(LoopOpType);
417 assert(LoopOpSize.
isFixed() &&
"LoopOpType cannot be a scalable vector type");
418 assert((!AtomicElementSize || LoopOpSize % *AtomicElementSize == 0) &&
419 "Atomic memcpy lowering is not supported for selected operand size");
421 uint64_t LoopEndCount =
425 if (LoopEndCount != 0) {
426 LoopExpansionInfo LEI =
428 "static-memcpy", AverageTripCount);
429 assert(LEI.MainLoopIP && LEI.MainLoopIndex &&
430 "Main loop should be generated for non-zero loop count");
444 LoopOpType, SrcGEP, PartSrcAlign, SrcIsVolatile);
447 Load->setMetadata(LLVMContext::MD_alias_scope,
453 Load, DstGEP, PartDstAlign, DstIsVolatile);
458 if (AtomicElementSize) {
462 assert(!LEI.ResidualLoopIP && !LEI.ResidualLoopIndex &&
463 "No residual loop was requested");
467 uint64_t BytesCopied = LoopEndCount;
468 uint64_t RemainingBytes = CopyLen->
getZExtValue() - BytesCopied;
469 if (RemainingBytes == 0)
474 TTI.getMemcpyLoopResidualLoweringType(RemainingOps, Ctx, RemainingBytes,
475 SrcAS, DstAS, SrcAlign, DstAlign,
478 for (
auto *
OpTy : RemainingOps) {
483 assert((!AtomicElementSize || OperandSize % *AtomicElementSize == 0) &&
484 "Atomic memcpy lowering is not supported for selected operand size");
487 Int8Type, SrcAddr, ConstantInt::get(TypeOfCopyLen, BytesCopied));
492 Load->setMetadata(LLVMContext::MD_alias_scope,
496 Int8Type, DstAddr, ConstantInt::get(TypeOfCopyLen, BytesCopied));
503 if (AtomicElementSize) {
507 BytesCopied += OperandSize;
510 "Bytes copied should match size in the call!");
515 Align SrcAlign,
Align DstAlign,
bool SrcIsVolatile,
bool DstIsVolatile,
517 std::optional<uint32_t> AtomicElementSize,
518 std::optional<uint64_t> AverageTripCount) {
524 MDNode *NewDomain = MDB.createAnonymousAliasScopeDomain(
"MemCopyDomain");
526 MDNode *NewScope = MDB.createAnonymousAliasScope(NewDomain, Name);
531 Type *LoopOpType =
TTI.getMemcpyLoopLoweringType(
532 Ctx, CopyLen, SrcAS, DstAS, SrcAlign, DstAlign, AtomicElementSize);
534 "Atomic memcpy lowering is not supported for vector operand type");
535 TypeSize LoopOpSize =
DL.getTypeStoreSize(LoopOpType);
536 assert((!AtomicElementSize || LoopOpSize % *AtomicElementSize == 0) &&
537 "Atomic memcpy lowering is not supported for selected operand size");
541 Type *ResidualLoopOpType = AtomicElementSize
544 TypeSize ResidualLoopOpSize =
DL.getTypeStoreSize(ResidualLoopOpType);
545 assert(ResidualLoopOpSize == (AtomicElementSize ? *AtomicElementSize : 1) &&
546 "Store size is expected to match type size");
548 LoopExpansionInfo LEI =
550 "dynamic-memcpy", AverageTripCount);
551 assert(LEI.MainLoopIP && LEI.MainLoopIndex &&
552 "Main loop should be generated for unknown size copy");
564 MainLoopBuilder.CreateInBoundsGEP(Int8Type, SrcAddr, LEI.MainLoopIndex);
566 LoopOpType, SrcGEP, PartSrcAlign, SrcIsVolatile);
569 Load->setMetadata(LLVMContext::MD_alias_scope,
MDNode::get(Ctx, NewScope));
572 MainLoopBuilder.CreateInBoundsGEP(Int8Type, DstAddr, LEI.MainLoopIndex);
574 Load, DstGEP, PartDstAlign, DstIsVolatile);
579 if (AtomicElementSize) {
585 if (!LEI.ResidualLoopIP)
592 Value *ResSrcGEP = ResLoopBuilder.CreateInBoundsGEP(Int8Type, SrcAddr,
593 LEI.ResidualLoopIndex);
594 LoadInst *ResLoad = ResLoopBuilder.CreateAlignedLoad(
595 ResidualLoopOpType, ResSrcGEP, ResSrcAlign, SrcIsVolatile);
601 Value *ResDstGEP = ResLoopBuilder.CreateInBoundsGEP(Int8Type, DstAddr,
602 LEI.ResidualLoopIndex);
603 StoreInst *ResStore = ResLoopBuilder.CreateAlignedStore(
604 ResLoad, ResDstGEP, ResDstAlign, DstIsVolatile);
609 if (AtomicElementSize) {
619static std::pair<Value *, Value *>
622 Value *ResAddr1 = Addr1;
623 Value *ResAddr2 = Addr2;
628 if (
TTI.isValidAddrSpaceCast(AS2, AS1))
629 ResAddr2 =
B.CreateAddrSpaceCast(Addr2, Addr1->
getType());
630 else if (
TTI.isValidAddrSpaceCast(AS1, AS2))
631 ResAddr1 =
B.CreateAddrSpaceCast(Addr1, Addr2->
getType());
634 "support addrspacecast");
636 return {ResAddr1, ResAddr2};
668 Align DstAlign,
bool SrcIsVolatile,
679 Type *LoopOpType =
TTI.getMemcpyLoopLoweringType(Ctx, CopyLen, SrcAS, DstAS,
681 TypeSize LoopOpSize =
DL.getTypeStoreSize(LoopOpType);
683 bool LoopOpIsInt8 = LoopOpType == Int8Type;
687 bool RequiresResidual = !LoopOpIsInt8;
689 Type *ResidualLoopOpType = Int8Type;
690 TypeSize ResidualLoopOpSize =
DL.getTypeStoreSize(ResidualLoopOpType);
694 ConstantInt *CILoopOpSize = ConstantInt::get(ILengthType, LoopOpSize);
696 ConstantInt::get(ILengthType, ResidualLoopOpSize);
703 Value *RuntimeLoopBytes = CopyLen;
704 Value *RuntimeLoopRemainder =
nullptr;
705 Value *SkipResidualCondition =
nullptr;
706 if (RequiresResidual) {
707 RuntimeLoopRemainder =
710 LoopOpSize, RuntimeLoopRemainder);
711 SkipResidualCondition =
714 Value *SkipMainCondition =
726 auto [CmpSrcAddr, CmpDstAddr] =
729 PLBuilder.
CreateICmpULT(CmpSrcAddr, CmpDstAddr,
"compare_src_dst");
732 &ThenTerm, &ElseTerm);
759 CopyBackwardsBB->
setName(
"memmove_copy_backwards");
761 CopyForwardBB->
setName(
"memmove_copy_forward");
763 ExitBB->
setName(
"memmove_done");
776 F->getContext(),
"memmove_bwd_main_loop",
F, CopyForwardBB);
782 if (RequiresResidual) {
785 F->getContext(),
"memmove_bwd_residual_loop",
F, MainLoopBB);
790 ResidualLoopPhi, CIResidualLoopOpSize,
"bwd_residual_index");
798 ResidualLoopOpType, LoadGEP, ResidualSrcAlign, SrcIsVolatile,
803 ResidualDstAlign, DstIsVolatile);
807 F->getContext(),
"memmove_bwd_middle",
F, MainLoopBB);
813 ResidualLoopBuilder.
CreateICmpEQ(ResidualIndex, RuntimeLoopBytes),
814 IntermediateBB, ResidualLoopBB);
816 ResidualLoopPhi->
addIncoming(ResidualIndex, ResidualLoopBB);
817 ResidualLoopPhi->
addIncoming(CopyLen, CopyBackwardsBB);
826 PredBB = IntermediateBB;
834 MainLoopBuilder.
CreateSub(MainLoopPhi, CILoopOpSize,
"bwd_main_index");
838 LoopOpType, LoadGEP, PartSrcAlign, SrcIsVolatile,
"element");
846 MainLoopPhi->
addIncoming(RuntimeLoopBytes, PredBB);
851 SkipMainCondition, ExitBB, MainLoopBB, PredBBTerm->
getIterator());
864 MainLoopBuilder.
CreatePHI(ILengthType, 0,
"fwd_main_index");
868 LoopOpType, LoadGEP, PartSrcAlign, SrcIsVolatile,
"element");
873 Value *MainIndex = MainLoopBuilder.
CreateAdd(MainLoopPhi, CILoopOpSize);
879 if (RequiresResidual)
885 MainLoopBuilder.
CreateICmpEQ(MainIndex, RuntimeLoopBytes), SuccessorBB,
895 if (RequiresResidual) {
900 F->getContext(),
"memmove_fwd_residual_loop",
F, ExitBB);
901 IntermediateBuilder.
CreateCondBr(SkipResidualCondition, ExitBB,
908 ResidualLoopBuilder.
CreatePHI(ILengthType, 0,
"fwd_residual_index");
912 ResidualLoopOpType, LoadGEP, ResidualSrcAlign, SrcIsVolatile,
917 ResidualDstAlign, DstIsVolatile);
918 Value *ResidualIndex =
919 ResidualLoopBuilder.
CreateAdd(ResidualLoopPhi, CIResidualLoopOpSize);
921 ResidualLoopBuilder.
CreateICmpEQ(ResidualIndex, CopyLen), ExitBB,
923 ResidualLoopPhi->
addIncoming(ResidualIndex, ResidualLoopBB);
924 ResidualLoopPhi->
addIncoming(RuntimeLoopBytes, IntermediateBB);
935 Align DstAlign,
bool SrcIsVolatile,
950 Type *LoopOpType =
TTI.getMemcpyLoopLoweringType(Ctx, CopyLen, SrcAS, DstAS,
952 TypeSize LoopOpSize =
DL.getTypeStoreSize(LoopOpType);
953 assert(LoopOpSize.
isFixed() &&
"LoopOpType cannot be a scalable vector type");
963 ConstantInt *LoopBound = ConstantInt::get(ILengthType, BytesCopiedInLoop);
964 ConstantInt *CILoopOpSize = ConstantInt::get(ILengthType, LoopOpSize);
970 auto [CmpSrcAddr, CmpDstAddr] =
973 PLBuilder.
CreateICmpULT(CmpSrcAddr, CmpDstAddr,
"compare_src_dst");
976 &ThenTerm, &ElseTerm);
981 ExitBB->
setName(
"memmove_done");
999 Value *SrcGEP = Builder.CreateInBoundsGEP(
1000 Int8Type, SrcAddr, ConstantInt::get(TypeOfCopyLen, BytesCopied));
1002 Builder.CreateAlignedLoad(
OpTy, SrcGEP, ResSrcAlign, SrcIsVolatile);
1003 Value *DstGEP = Builder.CreateInBoundsGEP(
1004 Int8Type, DstAddr, ConstantInt::get(TypeOfCopyLen, BytesCopied));
1005 Builder.CreateAlignedStore(
Load, DstGEP, ResDstAlign, DstIsVolatile);
1006 BytesCopied += OperandSize;
1010 if (RemainingBytes != 0) {
1011 CopyBackwardsBB->
setName(
"memmove_bwd_residual");
1012 uint64_t BytesCopied = BytesCopiedInLoop;
1022 TTI.getMemcpyLoopResidualLoweringType(RemainingOps, Ctx, RemainingBytes,
1023 SrcAS, DstAS, PartSrcAlign,
1025 for (
auto *
OpTy : RemainingOps) {
1028 GenerateResidualLdStPair(
OpTy, BwdResBuilder, BytesCopied);
1031 if (BytesCopiedInLoop != 0) {
1034 if (RemainingBytes != 0) {
1038 PredBB = CopyBackwardsBB;
1040 CopyBackwardsBB->
setName(
"memmove_bwd_loop");
1045 Value *Index = LoopBuilder.
CreateSub(LoopPhi, CILoopOpSize,
"bwd_index");
1048 LoopOpType, LoadGEP, PartSrcAlign, SrcIsVolatile,
"element");
1066 if (BytesCopiedInLoop != 0) {
1067 CopyForwardBB->
setName(
"memmove_fwd_loop");
1070 if (RemainingBytes != 0) {
1073 "memmove_fwd_residual");
1074 FwdResidualBB = SuccBB;
1081 LoopOpType, LoadGEP, PartSrcAlign, SrcIsVolatile,
"element");
1096 if (RemainingBytes != 0) {
1097 uint64_t BytesCopied = BytesCopiedInLoop;
1104 TTI.getMemcpyLoopResidualLoweringType(RemainingOps, Ctx, RemainingBytes,
1105 SrcAS, DstAS, PartSrcAlign,
1107 for (
auto *
OpTy : RemainingOps)
1108 GenerateResidualLdStPair(
OpTy, FwdResBuilder, BytesCopied);
1116 TypeSize DstSize =
DL.getTypeStoreSize(DstType);
1118 TypeSize SetValueSize =
DL.getTypeStoreSize(SetValueType);
1119 assert(SetValueSize ==
DL.getTypeAllocSize(SetValueType) &&
1120 "Store size and alloc size of SetValue's type must match");
1121 assert(SetValueSize != 0 && DstSize % SetValueSize == 0 &&
1122 "DstType size must be a multiple of SetValue size");
1125 if (DstSize != SetValueSize) {
1134 B.CreateVectorSplat(DstSize / SetValueSize, Result,
"setvalue.splat");
1139 Result =
B.CreateBitCast(Result, DstType,
"setvalue.splat.cast");
1150 B.CreateZExt(
SetValue, IntTy,
"setvalue.zext"),
1154 return B.CreateVectorSplat(
Size,
SetValue,
"setvalue.splat");
1161 std::optional<uint64_t> AverageTripCount) {
1173 Type *TypeOfLen = Len->getType();
1177 Type *LoopOpType = Int8Type;
1181 LoopOpType =
TTI->getMemcpyLoopLoweringType(
1182 Ctx, Len, DstAS, DstAS, DstAlign, DstAlign, std::nullopt);
1184 TypeSize LoopOpSize =
DL.getTypeStoreSize(LoopOpType);
1185 assert(LoopOpSize.
isFixed() &&
"LoopOpType cannot be a scalable vector type");
1190 if (LoopEndCount != 0) {
1191 Value *SplatSetValue =
nullptr;
1201 InsertBefore, Len, LoopOpSize, 0,
"static-memset", AverageTripCount);
1202 assert(LEI.MainLoopIP && LEI.MainLoopIndex &&
1203 "Main loop should be generated for non-zero loop count");
1215 assert(!LEI.ResidualLoopIP && !LEI.ResidualLoopIndex &&
1216 "No residual loop was requested");
1220 uint64_t RemainingBytes = Len->getZExtValue() - BytesSet;
1221 if (RemainingBytes == 0)
1226 assert(
TTI &&
"there cannot be a residual loop without TTI");
1228 TTI->getMemcpyLoopResidualLoweringType(RemainingOps, Ctx, RemainingBytes,
1229 DstAS, DstAS, DstAlign, DstAlign,
1232 Type *PreviousOpTy =
nullptr;
1233 Value *SplatSetValue =
nullptr;
1234 for (
auto *
OpTy : RemainingOps) {
1237 "Operand types cannot be scalable vector types");
1242 if (
OpTy != PreviousOpTy)
1246 Int8Type, DstAddr, ConstantInt::get(TypeOfLen, BytesSet));
1249 BytesSet += OperandSize;
1250 PreviousOpTy =
OpTy;
1252 assert(BytesSet == Len->getZExtValue() &&
1253 "Bytes set should match size in the call!");
1260 std::optional<uint64_t> AverageTripCount) {
1271 Type *LoopOpType = Int8Type;
1273 LoopOpType =
TTI->getMemcpyLoopLoweringType(
1274 Ctx, Len, DstAS, DstAS, DstAlign, DstAlign, std::nullopt);
1276 TypeSize LoopOpSize =
DL.getTypeStoreSize(LoopOpType);
1277 assert(LoopOpSize.
isFixed() &&
"LoopOpType cannot be a scalable vector type");
1279 Type *ResidualLoopOpType = Int8Type;
1280 TypeSize ResidualLoopOpSize =
DL.getTypeStoreSize(ResidualLoopOpType);
1288 LoopExpansionInfo LEI =
1290 "dynamic-memset", AverageTripCount);
1291 assert(LEI.MainLoopIP && LEI.MainLoopIndex &&
1292 "Main loop should be generated for unknown size memset");
1304 if (!LEI.ResidualLoopIP)
1312 LEI.ResidualLoopIndex);
1321 std::optional<uint64_t> AverageTripCount) {
1336 PreferredLoopOpType =
TTI->getMemcpyLoopLoweringType(
1337 Ctx, Len, DstAS, DstAS, DstAlign, DstAlign, std::nullopt);
1339 TypeSize PreferredLoopOpStoreSize =
DL.getTypeStoreSize(PreferredLoopOpType);
1341 "PreferredLoopOpType cannot be a scalable vector type");
1343 TypeSize PreferredLoopOpAllocSize =
DL.getTypeAllocSize(PreferredLoopOpType);
1346 TypeSize OriginalTypeStoreSize =
DL.getTypeStoreSize(OriginalType);
1347 TypeSize OriginalTypeAllocSize =
DL.getTypeAllocSize(OriginalType);
1358 unsigned MainLoopStep = 1;
1359 Type *MainLoopType = OriginalType;
1360 TypeSize MainLoopAllocSize = OriginalTypeAllocSize;
1361 unsigned ResidualLoopStep = 0;
1362 Type *ResidualLoopType =
nullptr;
1364 if (PreferredLoopOpStoreSize == PreferredLoopOpAllocSize &&
1365 OriginalTypeStoreSize == OriginalTypeAllocSize &&
1366 OriginalTypeStoreSize < PreferredLoopOpStoreSize &&
1367 PreferredLoopOpStoreSize % OriginalTypeStoreSize == 0) {
1370 MainLoopStep = PreferredLoopOpStoreSize / OriginalTypeStoreSize;
1371 MainLoopType = PreferredLoopOpType;
1372 MainLoopAllocSize = PreferredLoopOpStoreSize;
1374 ResidualLoopStep = 1;
1375 ResidualLoopType = OriginalType;
1380 LoopExpansionInfo LEI =
1382 "memset.pattern", AverageTripCount);
1386 if (LEI.MainLoopIP) {
1390 if (MainLoopType != OriginalType)
1402 if (!LEI.ResidualLoopIP)
1411 LEI.ResidualLoopIndex);
1416template <
typename T>
1420 const SCEV *DestSCEV = SE->
getSCEV(Memcpy->getRawDest());
1431 auto TripCount = getAverageMemOpLoopTripCount(*Memcpy);
1471 bool DstIsVolatile = SrcIsVolatile;
1477 if (SrcAS != DstAS) {
1478 if (!
TTI.addrspacesMayAlias(SrcAS, DstAS)) {
1481 auto AverageTripCount = getAverageMemOpLoopTripCount(*Memmove);
1484 Memmove, SrcAddr, DstAddr, CI, SrcAlign, DstAlign,
1485 SrcIsVolatile, DstIsVolatile,
1486 false,
TTI, std::nullopt, AverageTripCount);
1489 Memmove, SrcAddr, DstAddr, CopyLen, SrcAlign,
1490 DstAlign, SrcIsVolatile, DstIsVolatile,
1491 false,
TTI, std::nullopt, AverageTripCount);
1497 if (!(
TTI.isValidAddrSpaceCast(DstAS, SrcAS) ||
1498 TTI.isValidAddrSpaceCast(SrcAS, DstAS))) {
1503 dbgs() <<
"Do not know how to expand memmove between different "
1504 "address spaces\n");
1511 Memmove, SrcAddr, DstAddr, CI, SrcAlign, DstAlign,
1512 SrcIsVolatile, DstIsVolatile,
TTI);
1515 Memmove, SrcAddr, DstAddr, CopyLen, SrcAlign, DstAlign,
1516 SrcIsVolatile, DstIsVolatile,
TTI);
1523 auto AverageTripCount = getAverageMemOpLoopTripCount(*Memset);
1553 uint64_t MaxLen,
const KnownBits &LenKnown) {
1554 assert(MinLen <= MaxLen &&
"Invalid length bounds");
1559 uint64_t MinStoreSize =
uint64_t(1)
1561 if (MaxLen < MinStoreSize)
1567 Type *LenTy = Len->getType();
1617 for (uint64_t
Size = TopSize;
Size >= MinStoreSize;
Size /= 2) {
1619 if (MinLen <
Size) {
1621 Value *
Cond =
B.CreateICmpUGE(Len, ConstantInt::get(LenTy,
Size),
1623 if (
Size == MinStoreSize) {
1629 &ElseTerm, Weights);
1631 InsertBefore = ElseTerm;
1639 B.CreateAlignedStore(Val, Dst, DstAlign);
1642 uint64_t MaxLenForSize =
Size == TopSize ? MaxLen : 2 *
Size - MinStoreSize;
1643 if (MaxLenForSize >
Size) {
1645 B.CreateSub(Len, ConstantInt::get(LenTy,
Size),
"tail.off");
1646 Value *TailPtr =
B.CreateInBoundsGEP(
B.getInt8Ty(), Dst, TailOff,
"tail");
1647 B.CreateAlignedStore(Val, TailPtr, TailAlign);
1654 MemSet->
getParent()->setName(
"memset_done");
1667 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 Value * createMemSetSplat(const DataLayout &DL, IRBuilderBase &B, Value *SetValue, Type *DstType)
Create a Value of DstType that consists of a sequence of copies of SetValue, using bitcasts and a vec...
static std::pair< Value *, Value * > tryInsertCastToCommonAddrSpace(IRBuilderBase &B, Value *Addr1, Value *Addr2, const TargetTransformInfo &TTI)
static void createMemSetPatternLoop(Instruction *InsertBefore, Value *DstAddr, Value *Len, Value *SetValue, Align DstAlign, bool IsVolatile, const TargetTransformInfo *TTI, std::optional< uint64_t > AverageTripCount)
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 * createBoundedMemSetSplat(IRBuilderBase &B, Value *SetValue, uint64_t Size)
static void createMemSetLoopUnknownSize(Instruction *InsertBefore, Value *DstAddr, Value *Len, Value *SetValue, Align DstAlign, bool IsVolatile, const TargetTransformInfo *TTI, std::optional< uint64_t > AverageTripCount)
static Value * getRuntimeLoopRemainder(IRBuilderBase &B, Value *Len, Value *OpSize, unsigned OpSizeVal)
static void createMemSetLoopKnownSize(Instruction *InsertBefore, Value *DstAddr, ConstantInt *Len, Value *SetValue, Align DstAlign, bool IsVolatile, const TargetTransformInfo *TTI, std::optional< uint64_t > AverageTripCount)
static Value * getRuntimeLoopUnits(IRBuilderBase &B, Value *Len, Value *OpSize, unsigned OpSizeVal, Value *RTLoopRemainder=nullptr)
static LoopExpansionInfo insertLoopExpansion(Instruction *InsertBefore, Value *Len, unsigned MainLoopStep, unsigned ResidualLoopStep, StringRef BBNamePrefix, std::optional< uint64_t > ExpectedUnits)
Insert the control flow and loop counters for a memcpy/memset loop expansion.
static void createMemMoveLoopUnknownSize(Instruction *InsertBefore, Value *SrcAddr, Value *DstAddr, Value *CopyLen, Align SrcAlign, Align DstAlign, bool SrcIsVolatile, bool DstIsVolatile, const TargetTransformInfo &TTI)
This file contains the declarations for profiling metadata utility functions.
SmallVector< MachineOperand, 4 > Cond
Class for arbitrary precision integers.
static LLVM_ABI APInt getSplat(unsigned NewLen, const APInt &V)
Return a value containing V broadcasted over NewLen bits.
This class represents any memcpy intrinsic i.e.
uint32_t getElementSizeInBytes() const
LLVM Basic Block Representation.
LLVM_ABI BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="")
Split the basic block into two basic blocks at the specified instruction.
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 LLVMContext & getContext() const
Get the context in which this basic block lives.
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
Conditional Branch instruction.
static CondBrInst * Create(Value *Cond, BasicBlock *IfTrue, BasicBlock *IfFalse, InsertPosition InsertBefore=nullptr)
void setSuccessor(unsigned idx, BasicBlock *NewSucc)
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)
CondBrInst * CreateCondBr(Value *Cond, BasicBlock *True, BasicBlock *False, MDNode *BranchWeights=nullptr, MDNode *Unpredictable=nullptr)
Create a conditional 'br Cond, TrueDest, FalseDest' instruction.
UnreachableInst * CreateUnreachable()
void SetCurrentDebugLocation(const 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="")
UncondBrInst * CreateBr(BasicBlock *Dest)
Create an unconditional 'br label X' instruction.
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)
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...
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
LLVM_ABI const Function * getFunction() const
Return the function this instruction belongs to.
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.
LLVM_ABI MDNode * createAnonymousAliasScopeDomain(StringRef Description=StringRef(), bool DisjointScopes=false)
Return metadata appropriate for an alias scope domain node, described by Description,...
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.
Represent a constant reference to a string, i.e.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
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)
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
bool isIntegerTy() const
True if this is an instance of IntegerType.
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.
constexpr ScalarTy getFixedValue() const
constexpr bool isFixed() const
Returns true if the quantity is not scaled by vscale.
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.
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.
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
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.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
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 MDNode * getExplicitlyUnknownBranchWeightsIfProfiled(Function &F, StringRef PassName)
Returns a metadata node containing unknown branch weights if the function has an entry count,...
LLVM_ABI void expandAtomicMemCpyAsLoop(AnyMemCpyInst *AtomicMemCpy, const TargetTransformInfo &TTI, ScalarEvolution *SE)
Expand AtomicMemCpy as a loop. AtomicMemCpy is not deleted.
LLVM_ABI void expandBoundedMemSet(MemSetInst *MemSet, uint64_t MinLen, uint64_t MaxLen, const KnownBits &LenKnown)
Expand MemSet, whose length is known to be in [MinLen, MaxLen] and to have the known bits LenKnown,...
LLVM_ABI void expandMemSetAsLoop(MemSetInst *MemSet, const TargetTransformInfo *TTI=nullptr)
Expand MemSet as a loop.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI void expandMemSetPatternAsLoop(MemSetPatternInst *MemSet, const TargetTransformInfo *TTI=nullptr)
Expand MemSetPattern as a loop.
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.
LLVM_ABI Instruction * SplitBlockAndInsertIfThen(Value *Cond, BasicBlock::iterator SplitBefore, bool Unreachable, MDNode *BranchWeights=nullptr, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr, BasicBlock *ThenBlock=nullptr)
Split the containing block at the specified instruction - everything before SplitBefore stays in the ...
T bit_floor(T Value)
Returns the largest integral power of two no greater than Value if Value is nonzero.
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.
This struct is a compact representation of a valid (non-zero power of two) alignment.
unsigned countMinTrailingZeros() const
Returns the minimum number of trailing zero bits.
Align valueOrOne() const
For convenience, returns a valid alignment or 1 if undefined.