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;
1021 TTI.getMemcpyLoopResidualLoweringType(RemainingOps, Ctx, RemainingBytes,
1022 SrcAS, DstAS, PartSrcAlign,
1024 for (
auto *
OpTy : RemainingOps) {
1027 GenerateResidualLdStPair(
OpTy, BwdResBuilder, BytesCopied);
1030 if (BytesCopiedInLoop != 0) {
1033 if (RemainingBytes != 0) {
1037 PredBB = CopyBackwardsBB;
1039 CopyBackwardsBB->
setName(
"memmove_bwd_loop");
1044 Value *Index = LoopBuilder.
CreateSub(LoopPhi, CILoopOpSize,
"bwd_index");
1047 LoopOpType, LoadGEP, PartSrcAlign, SrcIsVolatile,
"element");
1065 if (BytesCopiedInLoop != 0) {
1066 CopyForwardBB->
setName(
"memmove_fwd_loop");
1069 if (RemainingBytes != 0) {
1072 "memmove_fwd_residual");
1073 FwdResidualBB = SuccBB;
1080 LoopOpType, LoadGEP, PartSrcAlign, SrcIsVolatile,
"element");
1095 if (RemainingBytes != 0) {
1096 uint64_t BytesCopied = BytesCopiedInLoop;
1103 TTI.getMemcpyLoopResidualLoweringType(RemainingOps, Ctx, RemainingBytes,
1104 SrcAS, DstAS, PartSrcAlign,
1106 for (
auto *
OpTy : RemainingOps)
1107 GenerateResidualLdStPair(
OpTy, FwdResBuilder, BytesCopied);
1115 TypeSize DstSize =
DL.getTypeStoreSize(DstType);
1117 TypeSize SetValueSize =
DL.getTypeStoreSize(SetValueType);
1118 assert(SetValueSize ==
DL.getTypeAllocSize(SetValueType) &&
1119 "Store size and alloc size of SetValue's type must match");
1120 assert(SetValueSize != 0 && DstSize % SetValueSize == 0 &&
1121 "DstType size must be a multiple of SetValue size");
1124 if (DstSize != SetValueSize) {
1133 B.CreateVectorSplat(DstSize / SetValueSize, Result,
"setvalue.splat");
1138 Result =
B.CreateBitCast(Result, DstType,
"setvalue.splat.cast");
1146 std::optional<uint64_t> AverageTripCount) {
1158 Type *TypeOfLen = Len->getType();
1162 Type *LoopOpType = Int8Type;
1166 LoopOpType =
TTI->getMemcpyLoopLoweringType(
1167 Ctx, Len, DstAS, DstAS, DstAlign, DstAlign, std::nullopt);
1169 TypeSize LoopOpSize =
DL.getTypeStoreSize(LoopOpType);
1170 assert(LoopOpSize.
isFixed() &&
"LoopOpType cannot be a scalable vector type");
1175 if (LoopEndCount != 0) {
1176 Value *SplatSetValue =
nullptr;
1186 InsertBefore, Len, LoopOpSize, 0,
"static-memset", AverageTripCount);
1187 assert(LEI.MainLoopIP && LEI.MainLoopIndex &&
1188 "Main loop should be generated for non-zero loop count");
1200 assert(!LEI.ResidualLoopIP && !LEI.ResidualLoopIndex &&
1201 "No residual loop was requested");
1205 uint64_t RemainingBytes = Len->getZExtValue() - BytesSet;
1206 if (RemainingBytes == 0)
1211 assert(
TTI &&
"there cannot be a residual loop without TTI");
1213 TTI->getMemcpyLoopResidualLoweringType(RemainingOps, Ctx, RemainingBytes,
1214 DstAS, DstAS, DstAlign, DstAlign,
1217 Type *PreviousOpTy =
nullptr;
1218 Value *SplatSetValue =
nullptr;
1219 for (
auto *
OpTy : RemainingOps) {
1222 "Operand types cannot be scalable vector types");
1227 if (
OpTy != PreviousOpTy)
1231 Int8Type, DstAddr, ConstantInt::get(TypeOfLen, BytesSet));
1234 BytesSet += OperandSize;
1235 PreviousOpTy =
OpTy;
1237 assert(BytesSet == Len->getZExtValue() &&
1238 "Bytes set should match size in the call!");
1245 std::optional<uint64_t> AverageTripCount) {
1256 Type *LoopOpType = Int8Type;
1258 LoopOpType =
TTI->getMemcpyLoopLoweringType(
1259 Ctx, Len, DstAS, DstAS, DstAlign, DstAlign, std::nullopt);
1261 TypeSize LoopOpSize =
DL.getTypeStoreSize(LoopOpType);
1262 assert(LoopOpSize.
isFixed() &&
"LoopOpType cannot be a scalable vector type");
1264 Type *ResidualLoopOpType = Int8Type;
1265 TypeSize ResidualLoopOpSize =
DL.getTypeStoreSize(ResidualLoopOpType);
1273 LoopExpansionInfo LEI =
1275 "dynamic-memset", AverageTripCount);
1276 assert(LEI.MainLoopIP && LEI.MainLoopIndex &&
1277 "Main loop should be generated for unknown size memset");
1289 if (!LEI.ResidualLoopIP)
1297 LEI.ResidualLoopIndex);
1306 std::optional<uint64_t> AverageTripCount) {
1321 PreferredLoopOpType =
TTI->getMemcpyLoopLoweringType(
1322 Ctx, Len, DstAS, DstAS, DstAlign, DstAlign, std::nullopt);
1324 TypeSize PreferredLoopOpStoreSize =
DL.getTypeStoreSize(PreferredLoopOpType);
1326 "PreferredLoopOpType cannot be a scalable vector type");
1328 TypeSize PreferredLoopOpAllocSize =
DL.getTypeAllocSize(PreferredLoopOpType);
1331 TypeSize OriginalTypeStoreSize =
DL.getTypeStoreSize(OriginalType);
1332 TypeSize OriginalTypeAllocSize =
DL.getTypeAllocSize(OriginalType);
1343 unsigned MainLoopStep = 1;
1344 Type *MainLoopType = OriginalType;
1345 TypeSize MainLoopAllocSize = OriginalTypeAllocSize;
1346 unsigned ResidualLoopStep = 0;
1347 Type *ResidualLoopType =
nullptr;
1349 if (PreferredLoopOpStoreSize == PreferredLoopOpAllocSize &&
1350 OriginalTypeStoreSize == OriginalTypeAllocSize &&
1351 OriginalTypeStoreSize < PreferredLoopOpStoreSize &&
1352 PreferredLoopOpStoreSize % OriginalTypeStoreSize == 0) {
1355 MainLoopStep = PreferredLoopOpStoreSize / OriginalTypeStoreSize;
1356 MainLoopType = PreferredLoopOpType;
1357 MainLoopAllocSize = PreferredLoopOpStoreSize;
1359 ResidualLoopStep = 1;
1360 ResidualLoopType = OriginalType;
1365 LoopExpansionInfo LEI =
1367 "memset.pattern", AverageTripCount);
1371 if (LEI.MainLoopIP) {
1375 if (MainLoopType != OriginalType)
1387 if (!LEI.ResidualLoopIP)
1396 LEI.ResidualLoopIndex);
1401template <
typename T>
1405 const SCEV *DestSCEV = SE->
getSCEV(Memcpy->getRawDest());
1416 auto TripCount = getAverageMemOpLoopTripCount(*Memcpy);
1456 bool DstIsVolatile = SrcIsVolatile;
1462 if (SrcAS != DstAS) {
1463 if (!
TTI.addrspacesMayAlias(SrcAS, DstAS)) {
1466 auto AverageTripCount = getAverageMemOpLoopTripCount(*Memmove);
1469 Memmove, SrcAddr, DstAddr, CI, SrcAlign, DstAlign,
1470 SrcIsVolatile, DstIsVolatile,
1471 false,
TTI, std::nullopt, AverageTripCount);
1474 Memmove, SrcAddr, DstAddr, CopyLen, SrcAlign,
1475 DstAlign, SrcIsVolatile, DstIsVolatile,
1476 false,
TTI, std::nullopt, AverageTripCount);
1482 if (!(
TTI.isValidAddrSpaceCast(DstAS, SrcAS) ||
1483 TTI.isValidAddrSpaceCast(SrcAS, DstAS))) {
1488 dbgs() <<
"Do not know how to expand memmove between different "
1489 "address spaces\n");
1496 Memmove, SrcAddr, DstAddr, CI, SrcAlign, DstAlign,
1497 SrcIsVolatile, DstIsVolatile,
TTI);
1500 Memmove, SrcAddr, DstAddr, CopyLen, SrcAlign, DstAlign,
1501 SrcIsVolatile, DstIsVolatile,
TTI);
1508 auto AverageTripCount = getAverageMemOpLoopTripCount(*Memset);
1547 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.