25#define DEBUG_TYPE "lower-mem-intrinsics"
32 Value *OpSize,
unsigned OpSizeVal) {
35 return B.CreateAnd(Len, OpSizeVal - 1);
36 return B.CreateURem(Len, OpSize);
45 Value *RTLoopRemainder =
nullptr) {
48 return B.CreateSub(Len, RTLoopRemainder);
53struct LoopExpansionInfo {
58 Value *MainLoopIndex =
nullptr;
66 Value *ResidualLoopIndex =
nullptr;
69std::optional<uint64_t> getAverageMemOpLoopTripCount(
const MemIntrinsic &
I) {
70 if (std::optional<uint64_t> EC =
I.getFunction()->getEntryCount();
73 if (
const auto Len =
I.getLengthInBytes())
74 return Len->getZExtValue();
78 std::numeric_limits<uint32_t>::max(),
Total);
82 for (
const auto &
P : ProfData)
83 TripCount +=
P.Count *
P.Value;
84 return std::round(1.0 * TripCount /
Total);
124static LoopExpansionInfo
126 unsigned MainLoopStep,
unsigned ResidualLoopStep,
128 std::optional<uint64_t> ExpectedUnits) {
129 assert((ResidualLoopStep == 0 || MainLoopStep % ResidualLoopStep == 0) &&
130 "ResidualLoopStep must divide MainLoopStep if specified");
131 assert(ResidualLoopStep <= MainLoopStep &&
132 "ResidualLoopStep cannot be larger than MainLoopStep");
133 assert(MainLoopStep > 0 &&
"MainLoopStep must be non-zero");
134 LoopExpansionInfo LEI;
143 InsertBefore, BBNamePrefix +
"-post-expansion");
152 Type *LenType = Len->getType();
154 ConstantInt *CIMainLoopStep = ConstantInt::get(ILenType, MainLoopStep);
155 ConstantInt *Zero = ConstantInt::get(ILenType, 0U);
163 bool MustTakeMainLoop =
false;
164 bool MayTakeMainLoop =
true;
165 bool MustTakeResidualLoop =
false;
166 bool MayTakeResidualLoop =
true;
168 Value *LoopUnits = Len;
169 Value *ResidualUnits =
nullptr;
170 if (MainLoopStep != 1) {
172 uint64_t TotalUnits = CLen->getZExtValue();
174 uint64_t ResidualCount = TotalUnits - LoopEndCount;
175 LoopUnits = ConstantInt::get(LenType, LoopEndCount);
176 ResidualUnits = ConstantInt::get(LenType, ResidualCount);
177 MustTakeMainLoop = LoopEndCount > 0;
178 MayTakeMainLoop = MustTakeMainLoop;
179 MustTakeResidualLoop = ResidualCount > 0;
180 MayTakeResidualLoop = MustTakeResidualLoop;
186 CIMainLoopStep, MainLoopStep);
188 MainLoopStep, ResidualUnits);
191 MustTakeMainLoop = CLen->getZExtValue() > 0;
192 MayTakeMainLoop = MustTakeMainLoop;
197 assert((MayTakeMainLoop || MayTakeResidualLoop) &&
198 "At least one of the loops must be generated");
204 if (MayTakeMainLoop) {
206 ParentFunc, PostLoopBB);
211 LEI.MainLoopIndex = LoopIndex;
212 LoopIndex->
addIncoming(ConstantInt::get(LenType, 0U), PreLoopBB);
215 LoopIndex, ConstantInt::get(LenType, MainLoopStep));
225 LoopBuilder.
CreateICmpULT(NewIndex, LoopUnits), MainLoopBB, PostLoopBB);
227 if (ExpectedUnits.has_value()) {
228 uint64_t BackedgeTakenCount = ExpectedUnits.value() / MainLoopStep;
229 if (BackedgeTakenCount > 0)
230 BackedgeTakenCount -= 1;
241 bool ResidualLoopRequested =
242 ResidualLoopStep > 0 && ResidualLoopStep < MainLoopStep;
245 if (ResidualLoopRequested && MayTakeResidualLoop) {
259 if (MustTakeResidualLoop) {
261 PredOfResLoopBody = MainLoopBB;
273 ResidualLoopBB, PostLoopBB);
274 if (ExpectedUnits.has_value()) {
276 BR->setMetadata(LLVMContext::MD_prof,
283 PredOfResLoopBody = ResidualCondBB;
290 ResBuilder.
CreatePHI(LenType, 2,
"residual-loop-index");
291 ResidualIndex->
addIncoming(Zero, PredOfResLoopBody);
297 LEI.ResidualLoopIndex = ResBuilder.
CreateAdd(LoopUnits, ResidualIndex);
299 LEI.ResidualLoopIndex = ResidualIndex;
302 ResidualIndex, ConstantInt::get(LenType, ResidualLoopStep));
303 ResidualIndex->
addIncoming(ResNewIndex, ResidualLoopBB);
311 ResBuilder.
CreateICmpULT(ResNewIndex, ResidualUnits), ResidualLoopBB,
314 if (ExpectedUnits.has_value()) {
316 (ExpectedUnits.value() % MainLoopStep) / ResidualLoopStep;
317 if (BackedgeTakenCount > 0)
318 BackedgeTakenCount -= 1;
328 if (MustTakeMainLoop) {
332 PreLoopBuilder.
CreateBr(MainLoopBB);
333 }
else if (!MainLoopBB && ResidualLoopBB) {
334 if (MustTakeResidualLoop) {
337 PreLoopBuilder.
CreateBr(ResidualLoopBB);
343 PreLoopBuilder.
CreateICmpNE(ResidualUnits, Zero), ResidualLoopBB,
345 if (ExpectedUnits.has_value()) {
356 if (ResidualCondBB) {
359 FalseBB = ResidualCondBB;
360 }
else if (ResidualLoopBB) {
364 assert(MustTakeResidualLoop);
365 FalseBB = ResidualLoopBB;
369 PreLoopBuilder.
CreateICmpNE(LoopUnits, Zero), MainLoopBB, FalseBB);
371 if (ExpectedUnits.has_value()) {
387 bool SrcIsVolatile,
bool DstIsVolatile,
390 std::optional<uint32_t> AtomicElementSize,
391 std::optional<uint64_t> AverageTripCount) {
409 Type *LoopOpType =
TTI.getMemcpyLoopLoweringType(
410 Ctx, CopyLen, SrcAS, DstAS, SrcAlign, DstAlign, AtomicElementSize);
412 "Atomic memcpy lowering is not supported for vector operand type");
415 TypeSize LoopOpSize =
DL.getTypeStoreSize(LoopOpType);
416 assert(LoopOpSize.
isFixed() &&
"LoopOpType cannot be a scalable vector type");
417 assert((!AtomicElementSize || LoopOpSize % *AtomicElementSize == 0) &&
418 "Atomic memcpy lowering is not supported for selected operand size");
420 uint64_t LoopEndCount =
424 if (LoopEndCount != 0) {
425 LoopExpansionInfo LEI =
427 "static-memcpy", AverageTripCount);
428 assert(LEI.MainLoopIP && LEI.MainLoopIndex &&
429 "Main loop should be generated for non-zero loop count");
443 LoopOpType, SrcGEP, PartSrcAlign, SrcIsVolatile);
446 Load->setMetadata(LLVMContext::MD_alias_scope,
452 Load, DstGEP, PartDstAlign, DstIsVolatile);
457 if (AtomicElementSize) {
461 assert(!LEI.ResidualLoopIP && !LEI.ResidualLoopIndex &&
462 "No residual loop was requested");
466 uint64_t BytesCopied = LoopEndCount;
467 uint64_t RemainingBytes = CopyLen->
getZExtValue() - BytesCopied;
468 if (RemainingBytes == 0)
473 TTI.getMemcpyLoopResidualLoweringType(RemainingOps, Ctx, RemainingBytes,
474 SrcAS, DstAS, SrcAlign, DstAlign,
477 for (
auto *
OpTy : RemainingOps) {
482 assert((!AtomicElementSize || OperandSize % *AtomicElementSize == 0) &&
483 "Atomic memcpy lowering is not supported for selected operand size");
486 Int8Type, SrcAddr, ConstantInt::get(TypeOfCopyLen, BytesCopied));
491 Load->setMetadata(LLVMContext::MD_alias_scope,
495 Int8Type, DstAddr, ConstantInt::get(TypeOfCopyLen, BytesCopied));
502 if (AtomicElementSize) {
506 BytesCopied += OperandSize;
509 "Bytes copied should match size in the call!");
514 Align SrcAlign,
Align DstAlign,
bool SrcIsVolatile,
bool DstIsVolatile,
516 std::optional<uint32_t> AtomicElementSize,
517 std::optional<uint64_t> AverageTripCount) {
523 MDNode *NewDomain = MDB.createAnonymousAliasScopeDomain(
"MemCopyDomain");
525 MDNode *NewScope = MDB.createAnonymousAliasScope(NewDomain, Name);
530 Type *LoopOpType =
TTI.getMemcpyLoopLoweringType(
531 Ctx, CopyLen, SrcAS, DstAS, SrcAlign, DstAlign, AtomicElementSize);
533 "Atomic memcpy lowering is not supported for vector operand type");
534 TypeSize LoopOpSize =
DL.getTypeStoreSize(LoopOpType);
535 assert((!AtomicElementSize || LoopOpSize % *AtomicElementSize == 0) &&
536 "Atomic memcpy lowering is not supported for selected operand size");
540 Type *ResidualLoopOpType = AtomicElementSize
543 TypeSize ResidualLoopOpSize =
DL.getTypeStoreSize(ResidualLoopOpType);
544 assert(ResidualLoopOpSize == (AtomicElementSize ? *AtomicElementSize : 1) &&
545 "Store size is expected to match type size");
547 LoopExpansionInfo LEI =
549 "dynamic-memcpy", AverageTripCount);
550 assert(LEI.MainLoopIP && LEI.MainLoopIndex &&
551 "Main loop should be generated for unknown size copy");
563 MainLoopBuilder.CreateInBoundsGEP(Int8Type, SrcAddr, LEI.MainLoopIndex);
565 LoopOpType, SrcGEP, PartSrcAlign, SrcIsVolatile);
568 Load->setMetadata(LLVMContext::MD_alias_scope,
MDNode::get(Ctx, NewScope));
571 MainLoopBuilder.CreateInBoundsGEP(Int8Type, DstAddr, LEI.MainLoopIndex);
573 Load, DstGEP, PartDstAlign, DstIsVolatile);
578 if (AtomicElementSize) {
584 if (!LEI.ResidualLoopIP)
591 Value *ResSrcGEP = ResLoopBuilder.CreateInBoundsGEP(Int8Type, SrcAddr,
592 LEI.ResidualLoopIndex);
593 LoadInst *ResLoad = ResLoopBuilder.CreateAlignedLoad(
594 ResidualLoopOpType, ResSrcGEP, ResSrcAlign, SrcIsVolatile);
600 Value *ResDstGEP = ResLoopBuilder.CreateInBoundsGEP(Int8Type, DstAddr,
601 LEI.ResidualLoopIndex);
602 StoreInst *ResStore = ResLoopBuilder.CreateAlignedStore(
603 ResLoad, ResDstGEP, ResDstAlign, DstIsVolatile);
608 if (AtomicElementSize) {
618static std::pair<Value *, Value *>
621 Value *ResAddr1 = Addr1;
622 Value *ResAddr2 = Addr2;
627 if (
TTI.isValidAddrSpaceCast(AS2, AS1))
628 ResAddr2 =
B.CreateAddrSpaceCast(Addr2, Addr1->
getType());
629 else if (
TTI.isValidAddrSpaceCast(AS1, AS2))
630 ResAddr1 =
B.CreateAddrSpaceCast(Addr1, Addr2->
getType());
633 "support addrspacecast");
635 return {ResAddr1, ResAddr2};
667 Align DstAlign,
bool SrcIsVolatile,
678 Type *LoopOpType =
TTI.getMemcpyLoopLoweringType(Ctx, CopyLen, SrcAS, DstAS,
680 TypeSize LoopOpSize =
DL.getTypeStoreSize(LoopOpType);
682 bool LoopOpIsInt8 = LoopOpType == Int8Type;
686 bool RequiresResidual = !LoopOpIsInt8;
688 Type *ResidualLoopOpType = Int8Type;
689 TypeSize ResidualLoopOpSize =
DL.getTypeStoreSize(ResidualLoopOpType);
693 ConstantInt *CILoopOpSize = ConstantInt::get(ILengthType, LoopOpSize);
695 ConstantInt::get(ILengthType, ResidualLoopOpSize);
696 ConstantInt *Zero = ConstantInt::get(ILengthType, 0);
702 Value *RuntimeLoopBytes = CopyLen;
703 Value *RuntimeLoopRemainder =
nullptr;
704 Value *SkipResidualCondition =
nullptr;
705 if (RequiresResidual) {
706 RuntimeLoopRemainder =
709 LoopOpSize, RuntimeLoopRemainder);
710 SkipResidualCondition =
711 PLBuilder.
CreateICmpEQ(RuntimeLoopRemainder, Zero,
"skip_residual");
713 Value *SkipMainCondition =
714 PLBuilder.
CreateICmpEQ(RuntimeLoopBytes, Zero,
"skip_main");
725 auto [CmpSrcAddr, CmpDstAddr] =
728 PLBuilder.
CreateICmpULT(CmpSrcAddr, CmpDstAddr,
"compare_src_dst");
731 &ThenTerm, &ElseTerm);
758 CopyBackwardsBB->
setName(
"memmove_copy_backwards");
760 CopyForwardBB->
setName(
"memmove_copy_forward");
762 ExitBB->
setName(
"memmove_done");
775 F->getContext(),
"memmove_bwd_main_loop",
F, CopyForwardBB);
781 if (RequiresResidual) {
784 F->getContext(),
"memmove_bwd_residual_loop",
F, MainLoopBB);
789 ResidualLoopPhi, CIResidualLoopOpSize,
"bwd_residual_index");
797 ResidualLoopOpType, LoadGEP, ResidualSrcAlign, SrcIsVolatile,
802 ResidualDstAlign, DstIsVolatile);
806 F->getContext(),
"memmove_bwd_middle",
F, MainLoopBB);
812 ResidualLoopBuilder.
CreateICmpEQ(ResidualIndex, RuntimeLoopBytes),
813 IntermediateBB, ResidualLoopBB);
815 ResidualLoopPhi->
addIncoming(ResidualIndex, ResidualLoopBB);
816 ResidualLoopPhi->
addIncoming(CopyLen, CopyBackwardsBB);
825 PredBB = IntermediateBB;
833 MainLoopBuilder.
CreateSub(MainLoopPhi, CILoopOpSize,
"bwd_main_index");
837 LoopOpType, LoadGEP, PartSrcAlign, SrcIsVolatile,
"element");
845 MainLoopPhi->
addIncoming(RuntimeLoopBytes, PredBB);
850 SkipMainCondition, ExitBB, MainLoopBB, PredBBTerm->
getIterator());
863 MainLoopBuilder.
CreatePHI(ILengthType, 0,
"fwd_main_index");
867 LoopOpType, LoadGEP, PartSrcAlign, SrcIsVolatile,
"element");
872 Value *MainIndex = MainLoopBuilder.
CreateAdd(MainLoopPhi, CILoopOpSize);
878 if (RequiresResidual)
884 MainLoopBuilder.
CreateICmpEQ(MainIndex, RuntimeLoopBytes), SuccessorBB,
894 if (RequiresResidual) {
899 F->getContext(),
"memmove_fwd_residual_loop",
F, ExitBB);
900 IntermediateBuilder.
CreateCondBr(SkipResidualCondition, ExitBB,
907 ResidualLoopBuilder.
CreatePHI(ILengthType, 0,
"fwd_residual_index");
911 ResidualLoopOpType, LoadGEP, ResidualSrcAlign, SrcIsVolatile,
916 ResidualDstAlign, DstIsVolatile);
917 Value *ResidualIndex =
918 ResidualLoopBuilder.
CreateAdd(ResidualLoopPhi, CIResidualLoopOpSize);
920 ResidualLoopBuilder.
CreateICmpEQ(ResidualIndex, CopyLen), ExitBB,
922 ResidualLoopPhi->
addIncoming(ResidualIndex, ResidualLoopBB);
923 ResidualLoopPhi->
addIncoming(RuntimeLoopBytes, IntermediateBB);
934 Align DstAlign,
bool SrcIsVolatile,
949 Type *LoopOpType =
TTI.getMemcpyLoopLoweringType(Ctx, CopyLen, SrcAS, DstAS,
951 TypeSize LoopOpSize =
DL.getTypeStoreSize(LoopOpType);
952 assert(LoopOpSize.
isFixed() &&
"LoopOpType cannot be a scalable vector type");
961 ConstantInt *Zero = ConstantInt::get(ILengthType, 0);
962 ConstantInt *LoopBound = ConstantInt::get(ILengthType, BytesCopiedInLoop);
963 ConstantInt *CILoopOpSize = ConstantInt::get(ILengthType, LoopOpSize);
969 auto [CmpSrcAddr, CmpDstAddr] =
972 PLBuilder.
CreateICmpULT(CmpSrcAddr, CmpDstAddr,
"compare_src_dst");
975 &ThenTerm, &ElseTerm);
980 ExitBB->
setName(
"memmove_done");
998 Value *SrcGEP = Builder.CreateInBoundsGEP(
999 Int8Type, SrcAddr, ConstantInt::get(TypeOfCopyLen, BytesCopied));
1001 Builder.CreateAlignedLoad(
OpTy, SrcGEP, ResSrcAlign, SrcIsVolatile);
1002 Value *DstGEP = Builder.CreateInBoundsGEP(
1003 Int8Type, DstAddr, ConstantInt::get(TypeOfCopyLen, BytesCopied));
1004 Builder.CreateAlignedStore(
Load, DstGEP, ResDstAlign, DstIsVolatile);
1005 BytesCopied += OperandSize;
1009 if (RemainingBytes != 0) {
1010 CopyBackwardsBB->
setName(
"memmove_bwd_residual");
1011 uint64_t BytesCopied = BytesCopiedInLoop;
1022 TTI.getMemcpyLoopResidualLoweringType(RemainingOps, Ctx, RemainingBytes,
1023 SrcAS, DstAS, PartSrcAlign,
1025 for (
auto *
OpTy : RemainingOps) {
1029 GenerateResidualLdStPair(
OpTy, BwdResBuilder, BytesCopied);
1032 if (BytesCopiedInLoop != 0) {
1035 if (RemainingBytes != 0) {
1039 PredBB = CopyBackwardsBB;
1041 CopyBackwardsBB->
setName(
"memmove_bwd_loop");
1046 Value *Index = LoopBuilder.
CreateSub(LoopPhi, CILoopOpSize,
"bwd_index");
1049 LoopOpType, LoadGEP, PartSrcAlign, SrcIsVolatile,
"element");
1067 if (BytesCopiedInLoop != 0) {
1068 CopyForwardBB->
setName(
"memmove_fwd_loop");
1071 if (RemainingBytes != 0) {
1074 "memmove_fwd_residual");
1075 FwdResidualBB = SuccBB;
1082 LoopOpType, LoadGEP, PartSrcAlign, SrcIsVolatile,
"element");
1097 if (RemainingBytes != 0) {
1098 uint64_t BytesCopied = BytesCopiedInLoop;
1105 TTI.getMemcpyLoopResidualLoweringType(RemainingOps, Ctx, RemainingBytes,
1106 SrcAS, DstAS, PartSrcAlign,
1108 for (
auto *
OpTy : RemainingOps)
1109 GenerateResidualLdStPair(
OpTy, FwdResBuilder, BytesCopied);
1117 TypeSize DstSize =
DL.getTypeStoreSize(DstType);
1119 TypeSize SetValueSize =
DL.getTypeStoreSize(SetValueType);
1120 assert(SetValueSize ==
DL.getTypeAllocSize(SetValueType) &&
1121 "Store size and alloc size of SetValue's type must match");
1122 assert(SetValueSize != 0 && DstSize % SetValueSize == 0 &&
1123 "DstType size must be a multiple of SetValue size");
1126 if (DstSize != SetValueSize) {
1135 B.CreateVectorSplat(DstSize / SetValueSize, Result,
"setvalue.splat");
1140 Result =
B.CreateBitCast(Result, DstType,
"setvalue.splat.cast");
1148 std::optional<uint64_t> AverageTripCount) {
1160 Type *TypeOfLen = Len->getType();
1164 Type *LoopOpType = Int8Type;
1168 LoopOpType =
TTI->getMemcpyLoopLoweringType(
1169 Ctx, Len, DstAS, DstAS, DstAlign, DstAlign, std::nullopt);
1171 TypeSize LoopOpSize =
DL.getTypeStoreSize(LoopOpType);
1172 assert(LoopOpSize.
isFixed() &&
"LoopOpType cannot be a scalable vector type");
1177 if (LoopEndCount != 0) {
1178 Value *SplatSetValue =
nullptr;
1188 InsertBefore, Len, LoopOpSize, 0,
"static-memset", AverageTripCount);
1189 assert(LEI.MainLoopIP && LEI.MainLoopIndex &&
1190 "Main loop should be generated for non-zero loop count");
1202 assert(!LEI.ResidualLoopIP && !LEI.ResidualLoopIndex &&
1203 "No residual loop was requested");
1207 uint64_t RemainingBytes = Len->getZExtValue() - BytesSet;
1208 if (RemainingBytes == 0)
1213 assert(
TTI &&
"there cannot be a residual loop without TTI");
1215 TTI->getMemcpyLoopResidualLoweringType(RemainingOps, Ctx, RemainingBytes,
1216 DstAS, DstAS, DstAlign, DstAlign,
1219 Type *PreviousOpTy =
nullptr;
1220 Value *SplatSetValue =
nullptr;
1221 for (
auto *
OpTy : RemainingOps) {
1224 "Operand types cannot be scalable vector types");
1229 if (
OpTy != PreviousOpTy)
1233 Int8Type, DstAddr, ConstantInt::get(TypeOfLen, BytesSet));
1236 BytesSet += OperandSize;
1237 PreviousOpTy =
OpTy;
1239 assert(BytesSet == Len->getZExtValue() &&
1240 "Bytes set should match size in the call!");
1247 std::optional<uint64_t> AverageTripCount) {
1258 Type *LoopOpType = Int8Type;
1260 LoopOpType =
TTI->getMemcpyLoopLoweringType(
1261 Ctx, Len, DstAS, DstAS, DstAlign, DstAlign, std::nullopt);
1263 TypeSize LoopOpSize =
DL.getTypeStoreSize(LoopOpType);
1264 assert(LoopOpSize.
isFixed() &&
"LoopOpType cannot be a scalable vector type");
1266 Type *ResidualLoopOpType = Int8Type;
1267 TypeSize ResidualLoopOpSize =
DL.getTypeStoreSize(ResidualLoopOpType);
1275 LoopExpansionInfo LEI =
1277 "dynamic-memset", AverageTripCount);
1278 assert(LEI.MainLoopIP && LEI.MainLoopIndex &&
1279 "Main loop should be generated for unknown size memset");
1291 if (!LEI.ResidualLoopIP)
1299 LEI.ResidualLoopIndex);
1308 std::optional<uint64_t> AverageTripCount) {
1323 PreferredLoopOpType =
TTI->getMemcpyLoopLoweringType(
1324 Ctx, Len, DstAS, DstAS, DstAlign, DstAlign, std::nullopt);
1326 TypeSize PreferredLoopOpStoreSize =
DL.getTypeStoreSize(PreferredLoopOpType);
1328 "PreferredLoopOpType cannot be a scalable vector type");
1330 TypeSize PreferredLoopOpAllocSize =
DL.getTypeAllocSize(PreferredLoopOpType);
1333 TypeSize OriginalTypeStoreSize =
DL.getTypeStoreSize(OriginalType);
1334 TypeSize OriginalTypeAllocSize =
DL.getTypeAllocSize(OriginalType);
1345 unsigned MainLoopStep = 1;
1346 Type *MainLoopType = OriginalType;
1347 TypeSize MainLoopAllocSize = OriginalTypeAllocSize;
1348 unsigned ResidualLoopStep = 0;
1349 Type *ResidualLoopType =
nullptr;
1351 if (PreferredLoopOpStoreSize == PreferredLoopOpAllocSize &&
1352 OriginalTypeStoreSize == OriginalTypeAllocSize &&
1353 OriginalTypeStoreSize < PreferredLoopOpStoreSize &&
1354 PreferredLoopOpStoreSize % OriginalTypeStoreSize == 0) {
1357 MainLoopStep = PreferredLoopOpStoreSize / OriginalTypeStoreSize;
1358 MainLoopType = PreferredLoopOpType;
1359 MainLoopAllocSize = PreferredLoopOpStoreSize;
1361 ResidualLoopStep = 1;
1362 ResidualLoopType = OriginalType;
1367 LoopExpansionInfo LEI =
1369 "memset.pattern", AverageTripCount);
1373 if (LEI.MainLoopIP) {
1377 if (MainLoopType != OriginalType)
1389 if (!LEI.ResidualLoopIP)
1398 LEI.ResidualLoopIndex);
1403template <
typename T>
1407 const SCEV *DestSCEV = SE->
getSCEV(Memcpy->getRawDest());
1418 auto TripCount = getAverageMemOpLoopTripCount(*Memcpy);
1458 bool DstIsVolatile = SrcIsVolatile;
1464 if (SrcAS != DstAS) {
1465 if (!
TTI.addrspacesMayAlias(SrcAS, DstAS)) {
1468 auto AverageTripCount = getAverageMemOpLoopTripCount(*Memmove);
1471 Memmove, SrcAddr, DstAddr, CI, SrcAlign, DstAlign,
1472 SrcIsVolatile, DstIsVolatile,
1473 false,
TTI, std::nullopt, AverageTripCount);
1476 Memmove, SrcAddr, DstAddr, CopyLen, SrcAlign,
1477 DstAlign, SrcIsVolatile, DstIsVolatile,
1478 false,
TTI, std::nullopt, AverageTripCount);
1484 if (!(
TTI.isValidAddrSpaceCast(DstAS, SrcAS) ||
1485 TTI.isValidAddrSpaceCast(SrcAS, DstAS))) {
1490 dbgs() <<
"Do not know how to expand memmove between different "
1491 "address spaces\n");
1498 Memmove, SrcAddr, DstAddr, CI, SrcAlign, DstAlign,
1499 SrcIsVolatile, DstIsVolatile,
TTI);
1502 Memmove, SrcAddr, DstAddr, CopyLen, SrcAlign, DstAlign,
1503 SrcIsVolatile, DstIsVolatile,
TTI);
1510 auto AverageTripCount = getAverageMemOpLoopTripCount(*Memset);
1549 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 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.
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...
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.
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)
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 void expandAtomicMemCpyAsLoop(AnyMemCpyInst *AtomicMemCpy, const TargetTransformInfo &TTI, ScalarEvolution *SE)
Expand AtomicMemCpy as a loop. AtomicMemCpy is not deleted.
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 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.
Align valueOrOne() const
For convenience, returns a valid alignment or 1 if undefined.