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) {
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");
1147 std::optional<uint64_t> AverageTripCount) {
1159 Type *TypeOfLen = Len->getType();
1163 Type *LoopOpType = Int8Type;
1167 LoopOpType =
TTI->getMemcpyLoopLoweringType(
1168 Ctx, Len, DstAS, DstAS, DstAlign, DstAlign, std::nullopt);
1170 TypeSize LoopOpSize =
DL.getTypeStoreSize(LoopOpType);
1171 assert(LoopOpSize.
isFixed() &&
"LoopOpType cannot be a scalable vector type");
1176 if (LoopEndCount != 0) {
1177 Value *SplatSetValue =
nullptr;
1187 InsertBefore, Len, LoopOpSize, 0,
"static-memset", AverageTripCount);
1188 assert(LEI.MainLoopIP && LEI.MainLoopIndex &&
1189 "Main loop should be generated for non-zero loop count");
1201 assert(!LEI.ResidualLoopIP && !LEI.ResidualLoopIndex &&
1202 "No residual loop was requested");
1206 uint64_t RemainingBytes = Len->getZExtValue() - BytesSet;
1207 if (RemainingBytes == 0)
1212 assert(
TTI &&
"there cannot be a residual loop without TTI");
1214 TTI->getMemcpyLoopResidualLoweringType(RemainingOps, Ctx, RemainingBytes,
1215 DstAS, DstAS, DstAlign, DstAlign,
1218 Type *PreviousOpTy =
nullptr;
1219 Value *SplatSetValue =
nullptr;
1220 for (
auto *
OpTy : RemainingOps) {
1223 "Operand types cannot be scalable vector types");
1228 if (
OpTy != PreviousOpTy)
1232 Int8Type, DstAddr, ConstantInt::get(TypeOfLen, BytesSet));
1235 BytesSet += OperandSize;
1236 PreviousOpTy =
OpTy;
1238 assert(BytesSet == Len->getZExtValue() &&
1239 "Bytes set should match size in the call!");
1246 std::optional<uint64_t> AverageTripCount) {
1257 Type *LoopOpType = Int8Type;
1259 LoopOpType =
TTI->getMemcpyLoopLoweringType(
1260 Ctx, Len, DstAS, DstAS, DstAlign, DstAlign, std::nullopt);
1262 TypeSize LoopOpSize =
DL.getTypeStoreSize(LoopOpType);
1263 assert(LoopOpSize.
isFixed() &&
"LoopOpType cannot be a scalable vector type");
1265 Type *ResidualLoopOpType = Int8Type;
1266 TypeSize ResidualLoopOpSize =
DL.getTypeStoreSize(ResidualLoopOpType);
1274 LoopExpansionInfo LEI =
1276 "dynamic-memset", AverageTripCount);
1277 assert(LEI.MainLoopIP && LEI.MainLoopIndex &&
1278 "Main loop should be generated for unknown size memset");
1290 if (!LEI.ResidualLoopIP)
1298 LEI.ResidualLoopIndex);
1307 std::optional<uint64_t> AverageTripCount) {
1322 PreferredLoopOpType =
TTI->getMemcpyLoopLoweringType(
1323 Ctx, Len, DstAS, DstAS, DstAlign, DstAlign, std::nullopt);
1325 TypeSize PreferredLoopOpStoreSize =
DL.getTypeStoreSize(PreferredLoopOpType);
1327 "PreferredLoopOpType cannot be a scalable vector type");
1329 TypeSize PreferredLoopOpAllocSize =
DL.getTypeAllocSize(PreferredLoopOpType);
1332 TypeSize OriginalTypeStoreSize =
DL.getTypeStoreSize(OriginalType);
1333 TypeSize OriginalTypeAllocSize =
DL.getTypeAllocSize(OriginalType);
1344 unsigned MainLoopStep = 1;
1345 Type *MainLoopType = OriginalType;
1346 TypeSize MainLoopAllocSize = OriginalTypeAllocSize;
1347 unsigned ResidualLoopStep = 0;
1348 Type *ResidualLoopType =
nullptr;
1350 if (PreferredLoopOpStoreSize == PreferredLoopOpAllocSize &&
1351 OriginalTypeStoreSize == OriginalTypeAllocSize &&
1352 OriginalTypeStoreSize < PreferredLoopOpStoreSize &&
1353 PreferredLoopOpStoreSize % OriginalTypeStoreSize == 0) {
1356 MainLoopStep = PreferredLoopOpStoreSize / OriginalTypeStoreSize;
1357 MainLoopType = PreferredLoopOpType;
1358 MainLoopAllocSize = PreferredLoopOpStoreSize;
1360 ResidualLoopStep = 1;
1361 ResidualLoopType = OriginalType;
1366 LoopExpansionInfo LEI =
1368 "memset.pattern", AverageTripCount);
1372 if (LEI.MainLoopIP) {
1376 if (MainLoopType != OriginalType)
1388 if (!LEI.ResidualLoopIP)
1397 LEI.ResidualLoopIndex);
1402template <
typename T>
1406 const SCEV *DestSCEV = SE->
getSCEV(Memcpy->getRawDest());
1417 auto TripCount = getAverageMemOpLoopTripCount(*Memcpy);
1457 bool DstIsVolatile = SrcIsVolatile;
1463 if (SrcAS != DstAS) {
1464 if (!
TTI.addrspacesMayAlias(SrcAS, DstAS)) {
1467 auto AverageTripCount = getAverageMemOpLoopTripCount(*Memmove);
1470 Memmove, SrcAddr, DstAddr, CI, SrcAlign, DstAlign,
1471 SrcIsVolatile, DstIsVolatile,
1472 false,
TTI, std::nullopt, AverageTripCount);
1475 Memmove, SrcAddr, DstAddr, CopyLen, SrcAlign,
1476 DstAlign, SrcIsVolatile, DstIsVolatile,
1477 false,
TTI, std::nullopt, AverageTripCount);
1483 if (!(
TTI.isValidAddrSpaceCast(DstAS, SrcAS) ||
1484 TTI.isValidAddrSpaceCast(SrcAS, DstAS))) {
1489 dbgs() <<
"Do not know how to expand memmove between different "
1490 "address spaces\n");
1497 Memmove, SrcAddr, DstAddr, CI, SrcAlign, DstAlign,
1498 SrcIsVolatile, DstIsVolatile,
TTI);
1501 Memmove, SrcAddr, DstAddr, CopyLen, SrcAlign, DstAlign,
1502 SrcIsVolatile, DstIsVolatile,
TTI);
1509 auto AverageTripCount = getAverageMemOpLoopTripCount(*Memset);
1548 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.
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.
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.