24#define DEBUG_TYPE "lower-mem-intrinsics"
35 Value *OpSize,
unsigned OpSizeVal) {
38 return B.CreateAnd(Len, OpSizeVal - 1);
39 return B.CreateURem(Len, OpSize);
48 Value *RTLoopRemainder =
nullptr) {
51 return B.CreateSub(Len, RTLoopRemainder);
56struct LoopExpansionInfo {
61 Value *MainLoopIndex =
nullptr;
69 Value *ResidualLoopIndex =
nullptr;
72std::optional<uint64_t> getAverageMemOpLoopTripCount(
const MemIntrinsic &
I) {
75 if (std::optional<uint64_t> EC =
I.getFunction()->getEntryCount();
78 if (
const auto Len =
I.getLengthInBytes())
79 return Len->getZExtValue();
83 std::numeric_limits<uint32_t>::max(),
Total);
87 for (
const auto &
P : ProfData)
88 TripCount +=
P.Count *
P.Value;
89 return std::round(1.0 * TripCount /
Total);
129static LoopExpansionInfo
131 unsigned MainLoopStep,
unsigned ResidualLoopStep,
133 std::optional<uint64_t> ExpectedUnits) {
134 assert((ResidualLoopStep == 0 || MainLoopStep % ResidualLoopStep == 0) &&
135 "ResidualLoopStep must divide MainLoopStep if specified");
136 assert(ResidualLoopStep <= MainLoopStep &&
137 "ResidualLoopStep cannot be larger than MainLoopStep");
138 assert(MainLoopStep > 0 &&
"MainLoopStep must be non-zero");
139 LoopExpansionInfo LEI;
148 InsertBefore, BBNamePrefix +
"-post-expansion");
157 Type *LenType = Len->getType();
159 ConstantInt *CIMainLoopStep = ConstantInt::get(ILenType, MainLoopStep);
160 ConstantInt *Zero = ConstantInt::get(ILenType, 0U);
168 bool MustTakeMainLoop =
false;
169 bool MayTakeMainLoop =
true;
170 bool MustTakeResidualLoop =
false;
171 bool MayTakeResidualLoop =
true;
173 Value *LoopUnits = Len;
174 Value *ResidualUnits =
nullptr;
175 if (MainLoopStep != 1) {
177 uint64_t TotalUnits = CLen->getZExtValue();
179 uint64_t ResidualCount = TotalUnits - LoopEndCount;
180 LoopUnits = ConstantInt::get(LenType, LoopEndCount);
181 ResidualUnits = ConstantInt::get(LenType, ResidualCount);
182 MustTakeMainLoop = LoopEndCount > 0;
183 MayTakeMainLoop = MustTakeMainLoop;
184 MustTakeResidualLoop = ResidualCount > 0;
185 MayTakeResidualLoop = MustTakeResidualLoop;
191 CIMainLoopStep, MainLoopStep);
193 MainLoopStep, ResidualUnits);
196 MustTakeMainLoop = CLen->getZExtValue() > 0;
197 MayTakeMainLoop = MustTakeMainLoop;
202 assert((MayTakeMainLoop || MayTakeResidualLoop) &&
203 "At least one of the loops must be generated");
209 if (MayTakeMainLoop) {
211 ParentFunc, PostLoopBB);
216 LEI.MainLoopIndex = LoopIndex;
217 LoopIndex->
addIncoming(ConstantInt::get(LenType, 0U), PreLoopBB);
220 LoopIndex, ConstantInt::get(LenType, MainLoopStep));
230 LoopBuilder.
CreateICmpULT(NewIndex, LoopUnits), MainLoopBB, PostLoopBB);
232 if (ExpectedUnits.has_value()) {
233 uint64_t BackedgeTakenCount = ExpectedUnits.value() / MainLoopStep;
234 if (BackedgeTakenCount > 0)
235 BackedgeTakenCount -= 1;
246 bool ResidualLoopRequested =
247 ResidualLoopStep > 0 && ResidualLoopStep < MainLoopStep;
250 if (ResidualLoopRequested && MayTakeResidualLoop) {
264 if (MustTakeResidualLoop) {
266 PredOfResLoopBody = MainLoopBB;
278 ResidualLoopBB, PostLoopBB);
279 if (ExpectedUnits.has_value()) {
281 BR->setMetadata(LLVMContext::MD_prof,
288 PredOfResLoopBody = ResidualCondBB;
295 ResBuilder.
CreatePHI(LenType, 2,
"residual-loop-index");
296 ResidualIndex->
addIncoming(Zero, PredOfResLoopBody);
302 LEI.ResidualLoopIndex = ResBuilder.
CreateAdd(LoopUnits, ResidualIndex);
304 LEI.ResidualLoopIndex = ResidualIndex;
307 ResidualIndex, ConstantInt::get(LenType, ResidualLoopStep));
308 ResidualIndex->
addIncoming(ResNewIndex, ResidualLoopBB);
316 ResBuilder.
CreateICmpULT(ResNewIndex, ResidualUnits), ResidualLoopBB,
319 if (ExpectedUnits.has_value()) {
321 (ExpectedUnits.value() % MainLoopStep) / ResidualLoopStep;
322 if (BackedgeTakenCount > 0)
323 BackedgeTakenCount -= 1;
333 if (MustTakeMainLoop) {
337 PreLoopBuilder.
CreateBr(MainLoopBB);
338 }
else if (!MainLoopBB && ResidualLoopBB) {
339 if (MustTakeResidualLoop) {
342 PreLoopBuilder.
CreateBr(ResidualLoopBB);
348 PreLoopBuilder.
CreateICmpNE(ResidualUnits, Zero), ResidualLoopBB,
350 if (ExpectedUnits.has_value()) {
361 if (ResidualCondBB) {
364 FalseBB = ResidualCondBB;
365 }
else if (ResidualLoopBB) {
369 assert(MustTakeResidualLoop);
370 FalseBB = ResidualLoopBB;
374 PreLoopBuilder.
CreateICmpNE(LoopUnits, Zero), MainLoopBB, FalseBB);
376 if (ExpectedUnits.has_value()) {
392 bool SrcIsVolatile,
bool DstIsVolatile,
395 std::optional<uint32_t> AtomicElementSize,
396 std::optional<uint64_t> AverageTripCount) {
414 Type *LoopOpType =
TTI.getMemcpyLoopLoweringType(
415 Ctx, CopyLen, SrcAS, DstAS, SrcAlign, DstAlign, AtomicElementSize);
417 "Atomic memcpy lowering is not supported for vector operand type");
420 TypeSize LoopOpSize =
DL.getTypeStoreSize(LoopOpType);
421 assert(LoopOpSize.
isFixed() &&
"LoopOpType cannot be a scalable vector type");
422 assert((!AtomicElementSize || LoopOpSize % *AtomicElementSize == 0) &&
423 "Atomic memcpy lowering is not supported for selected operand size");
429 if (LoopEndCount != 0) {
430 LoopExpansionInfo LEI =
432 "static-memcpy", AverageTripCount);
433 assert(LEI.MainLoopIP && LEI.MainLoopIndex &&
434 "Main loop should be generated for non-zero loop count");
448 LoopOpType, SrcGEP, PartSrcAlign, SrcIsVolatile);
451 Load->setMetadata(LLVMContext::MD_alias_scope,
457 Load, DstGEP, PartDstAlign, DstIsVolatile);
462 if (AtomicElementSize) {
466 assert(!LEI.ResidualLoopIP && !LEI.ResidualLoopIndex &&
467 "No residual loop was requested");
471 uint64_t BytesCopied = LoopEndCount;
473 if (RemainingBytes == 0)
478 TTI.getMemcpyLoopResidualLoweringType(RemainingOps, Ctx, RemainingBytes,
479 SrcAS, DstAS, SrcAlign, DstAlign,
482 for (
auto *
OpTy : RemainingOps) {
487 assert((!AtomicElementSize || OperandSize % *AtomicElementSize == 0) &&
488 "Atomic memcpy lowering is not supported for selected operand size");
491 Int8Type, SrcAddr, ConstantInt::get(TypeOfCopyLen, BytesCopied));
496 Load->setMetadata(LLVMContext::MD_alias_scope,
500 Int8Type, DstAddr, ConstantInt::get(TypeOfCopyLen, BytesCopied));
507 if (AtomicElementSize) {
511 BytesCopied += OperandSize;
514 "Bytes copied should match size in the call!");
519 Align SrcAlign,
Align DstAlign,
bool SrcIsVolatile,
bool DstIsVolatile,
521 std::optional<uint32_t> AtomicElementSize,
522 std::optional<uint64_t> AverageTripCount) {
528 MDNode *NewDomain = MDB.createAnonymousAliasScopeDomain(
"MemCopyDomain");
530 MDNode *NewScope = MDB.createAnonymousAliasScope(NewDomain, Name);
535 Type *LoopOpType =
TTI.getMemcpyLoopLoweringType(
536 Ctx, CopyLen, SrcAS, DstAS, SrcAlign, DstAlign, AtomicElementSize);
538 "Atomic memcpy lowering is not supported for vector operand type");
539 TypeSize LoopOpSize =
DL.getTypeStoreSize(LoopOpType);
540 assert((!AtomicElementSize || LoopOpSize % *AtomicElementSize == 0) &&
541 "Atomic memcpy lowering is not supported for selected operand size");
545 Type *ResidualLoopOpType = AtomicElementSize
548 TypeSize ResidualLoopOpSize =
DL.getTypeStoreSize(ResidualLoopOpType);
549 assert(ResidualLoopOpSize == (AtomicElementSize ? *AtomicElementSize : 1) &&
550 "Store size is expected to match type size");
552 LoopExpansionInfo LEI =
554 "dynamic-memcpy", AverageTripCount);
555 assert(LEI.MainLoopIP && LEI.MainLoopIndex &&
556 "Main loop should be generated for unknown size copy");
568 MainLoopBuilder.CreateInBoundsGEP(Int8Type, SrcAddr, LEI.MainLoopIndex);
570 LoopOpType, SrcGEP, PartSrcAlign, SrcIsVolatile);
573 Load->setMetadata(LLVMContext::MD_alias_scope,
MDNode::get(Ctx, NewScope));
576 MainLoopBuilder.CreateInBoundsGEP(Int8Type, DstAddr, LEI.MainLoopIndex);
578 Load, DstGEP, PartDstAlign, DstIsVolatile);
583 if (AtomicElementSize) {
589 if (!LEI.ResidualLoopIP)
596 Value *ResSrcGEP = ResLoopBuilder.CreateInBoundsGEP(Int8Type, SrcAddr,
597 LEI.ResidualLoopIndex);
598 LoadInst *ResLoad = ResLoopBuilder.CreateAlignedLoad(
599 ResidualLoopOpType, ResSrcGEP, ResSrcAlign, SrcIsVolatile);
605 Value *ResDstGEP = ResLoopBuilder.CreateInBoundsGEP(Int8Type, DstAddr,
606 LEI.ResidualLoopIndex);
607 StoreInst *ResStore = ResLoopBuilder.CreateAlignedStore(
608 ResLoad, ResDstGEP, ResDstAlign, DstIsVolatile);
613 if (AtomicElementSize) {
623static std::pair<Value *, Value *>
626 Value *ResAddr1 = Addr1;
627 Value *ResAddr2 = Addr2;
632 if (
TTI.isValidAddrSpaceCast(AS2, AS1))
633 ResAddr2 =
B.CreateAddrSpaceCast(Addr2, Addr1->
getType());
634 else if (
TTI.isValidAddrSpaceCast(AS1, AS2))
635 ResAddr1 =
B.CreateAddrSpaceCast(Addr1, Addr2->
getType());
638 "support addrspacecast");
640 return {ResAddr1, ResAddr2};
672 Align DstAlign,
bool SrcIsVolatile,
683 Type *LoopOpType =
TTI.getMemcpyLoopLoweringType(Ctx, CopyLen, SrcAS, DstAS,
685 TypeSize LoopOpSize =
DL.getTypeStoreSize(LoopOpType);
687 bool LoopOpIsInt8 = LoopOpType == Int8Type;
691 bool RequiresResidual = !LoopOpIsInt8;
693 Type *ResidualLoopOpType = Int8Type;
694 TypeSize ResidualLoopOpSize =
DL.getTypeStoreSize(ResidualLoopOpType);
698 ConstantInt *CILoopOpSize = ConstantInt::get(ILengthType, LoopOpSize);
700 ConstantInt::get(ILengthType, ResidualLoopOpSize);
701 ConstantInt *Zero = ConstantInt::get(ILengthType, 0);
707 Value *RuntimeLoopBytes = CopyLen;
708 Value *RuntimeLoopRemainder =
nullptr;
709 Value *SkipResidualCondition =
nullptr;
710 if (RequiresResidual) {
711 RuntimeLoopRemainder =
714 LoopOpSize, RuntimeLoopRemainder);
715 SkipResidualCondition =
716 PLBuilder.
CreateICmpEQ(RuntimeLoopRemainder, Zero,
"skip_residual");
718 Value *SkipMainCondition =
719 PLBuilder.
CreateICmpEQ(RuntimeLoopBytes, Zero,
"skip_main");
730 auto [CmpSrcAddr, CmpDstAddr] =
733 PLBuilder.
CreateICmpULT(CmpSrcAddr, CmpDstAddr,
"compare_src_dst");
736 &ThenTerm, &ElseTerm);
763 CopyBackwardsBB->
setName(
"memmove_copy_backwards");
765 CopyForwardBB->
setName(
"memmove_copy_forward");
767 ExitBB->
setName(
"memmove_done");
780 F->getContext(),
"memmove_bwd_main_loop",
F, CopyForwardBB);
786 if (RequiresResidual) {
789 F->getContext(),
"memmove_bwd_residual_loop",
F, MainLoopBB);
794 ResidualLoopPhi, CIResidualLoopOpSize,
"bwd_residual_index");
802 ResidualLoopOpType, LoadGEP, ResidualSrcAlign, SrcIsVolatile,
807 ResidualDstAlign, DstIsVolatile);
811 F->getContext(),
"memmove_bwd_middle",
F, MainLoopBB);
817 ResidualLoopBuilder.
CreateICmpEQ(ResidualIndex, RuntimeLoopBytes),
818 IntermediateBB, ResidualLoopBB);
820 ResidualLoopPhi->
addIncoming(ResidualIndex, ResidualLoopBB);
821 ResidualLoopPhi->
addIncoming(CopyLen, CopyBackwardsBB);
830 PredBB = IntermediateBB;
838 MainLoopBuilder.
CreateSub(MainLoopPhi, CILoopOpSize,
"bwd_main_index");
842 LoopOpType, LoadGEP, PartSrcAlign, SrcIsVolatile,
"element");
850 MainLoopPhi->
addIncoming(RuntimeLoopBytes, PredBB);
855 SkipMainCondition, ExitBB, MainLoopBB, PredBBTerm->
getIterator());
868 MainLoopBuilder.
CreatePHI(ILengthType, 0,
"fwd_main_index");
872 LoopOpType, LoadGEP, PartSrcAlign, SrcIsVolatile,
"element");
877 Value *MainIndex = MainLoopBuilder.
CreateAdd(MainLoopPhi, CILoopOpSize);
883 if (RequiresResidual)
889 MainLoopBuilder.
CreateICmpEQ(MainIndex, RuntimeLoopBytes), SuccessorBB,
899 if (RequiresResidual) {
904 F->getContext(),
"memmove_fwd_residual_loop",
F, ExitBB);
905 IntermediateBuilder.
CreateCondBr(SkipResidualCondition, ExitBB,
912 ResidualLoopBuilder.
CreatePHI(ILengthType, 0,
"fwd_residual_index");
916 ResidualLoopOpType, LoadGEP, ResidualSrcAlign, SrcIsVolatile,
921 ResidualDstAlign, DstIsVolatile);
922 Value *ResidualIndex =
923 ResidualLoopBuilder.
CreateAdd(ResidualLoopPhi, CIResidualLoopOpSize);
925 ResidualLoopBuilder.
CreateICmpEQ(ResidualIndex, CopyLen), ExitBB,
927 ResidualLoopPhi->
addIncoming(ResidualIndex, ResidualLoopBB);
928 ResidualLoopPhi->
addIncoming(RuntimeLoopBytes, IntermediateBB);
939 Align DstAlign,
bool SrcIsVolatile,
954 Type *LoopOpType =
TTI.getMemcpyLoopLoweringType(Ctx, CopyLen, SrcAS, DstAS,
956 TypeSize LoopOpSize =
DL.getTypeStoreSize(LoopOpType);
957 assert(LoopOpSize.
isFixed() &&
"LoopOpType cannot be a scalable vector type");
966 ConstantInt *Zero = ConstantInt::get(ILengthType, 0);
967 ConstantInt *LoopBound = ConstantInt::get(ILengthType, BytesCopiedInLoop);
968 ConstantInt *CILoopOpSize = ConstantInt::get(ILengthType, LoopOpSize);
974 auto [CmpSrcAddr, CmpDstAddr] =
977 PLBuilder.
CreateICmpULT(CmpSrcAddr, CmpDstAddr,
"compare_src_dst");
980 &ThenTerm, &ElseTerm);
985 ExitBB->
setName(
"memmove_done");
1003 Value *SrcGEP = Builder.CreateInBoundsGEP(
1004 Int8Type, SrcAddr, ConstantInt::get(TypeOfCopyLen, BytesCopied));
1006 Builder.CreateAlignedLoad(
OpTy, SrcGEP, ResSrcAlign, SrcIsVolatile);
1007 Value *DstGEP = Builder.CreateInBoundsGEP(
1008 Int8Type, DstAddr, ConstantInt::get(TypeOfCopyLen, BytesCopied));
1009 Builder.CreateAlignedStore(
Load, DstGEP, ResDstAlign, DstIsVolatile);
1010 BytesCopied += OperandSize;
1014 if (RemainingBytes != 0) {
1015 CopyBackwardsBB->
setName(
"memmove_bwd_residual");
1016 uint64_t BytesCopied = BytesCopiedInLoop;
1027 TTI.getMemcpyLoopResidualLoweringType(RemainingOps, Ctx, RemainingBytes,
1028 SrcAS, DstAS, PartSrcAlign,
1030 for (
auto *
OpTy : RemainingOps) {
1034 GenerateResidualLdStPair(
OpTy, BwdResBuilder, BytesCopied);
1037 if (BytesCopiedInLoop != 0) {
1040 if (RemainingBytes != 0) {
1044 PredBB = CopyBackwardsBB;
1046 CopyBackwardsBB->
setName(
"memmove_bwd_loop");
1051 Value *Index = LoopBuilder.
CreateSub(LoopPhi, CILoopOpSize,
"bwd_index");
1054 LoopOpType, LoadGEP, PartSrcAlign, SrcIsVolatile,
"element");
1072 if (BytesCopiedInLoop != 0) {
1073 CopyForwardBB->
setName(
"memmove_fwd_loop");
1076 if (RemainingBytes != 0) {
1079 "memmove_fwd_residual");
1080 FwdResidualBB = SuccBB;
1087 LoopOpType, LoadGEP, PartSrcAlign, SrcIsVolatile,
"element");
1102 if (RemainingBytes != 0) {
1103 uint64_t BytesCopied = BytesCopiedInLoop;
1110 TTI.getMemcpyLoopResidualLoweringType(RemainingOps, Ctx, RemainingBytes,
1111 SrcAS, DstAS, PartSrcAlign,
1113 for (
auto *
OpTy : RemainingOps)
1114 GenerateResidualLdStPair(
OpTy, FwdResBuilder, BytesCopied);
1122 TypeSize DstSize =
DL.getTypeStoreSize(DstType);
1124 TypeSize SetValueSize =
DL.getTypeStoreSize(SetValueType);
1125 assert(SetValueSize ==
DL.getTypeAllocSize(SetValueType) &&
1126 "Store size and alloc size of SetValue's type must match");
1127 assert(SetValueSize != 0 && DstSize % SetValueSize == 0 &&
1128 "DstType size must be a multiple of SetValue size");
1131 if (DstSize != SetValueSize) {
1140 B.CreateVectorSplat(DstSize / SetValueSize, Result,
"setvalue.splat");
1145 Result =
B.CreateBitCast(Result, DstType,
"setvalue.splat.cast");
1153 std::optional<uint64_t> AverageTripCount) {
1165 Type *TypeOfLen = Len->getType();
1169 Type *LoopOpType = Int8Type;
1173 LoopOpType =
TTI->getMemcpyLoopLoweringType(
1174 Ctx, Len, DstAS, DstAS, DstAlign, DstAlign, std::nullopt);
1176 TypeSize LoopOpSize =
DL.getTypeStoreSize(LoopOpType);
1177 assert(LoopOpSize.
isFixed() &&
"LoopOpType cannot be a scalable vector type");
1182 if (LoopEndCount != 0) {
1183 Value *SplatSetValue =
nullptr;
1193 InsertBefore, Len, LoopOpSize, 0,
"static-memset", AverageTripCount);
1194 assert(LEI.MainLoopIP && LEI.MainLoopIndex &&
1195 "Main loop should be generated for non-zero loop count");
1207 assert(!LEI.ResidualLoopIP && !LEI.ResidualLoopIndex &&
1208 "No residual loop was requested");
1212 uint64_t RemainingBytes = Len->getZExtValue() - BytesSet;
1213 if (RemainingBytes == 0)
1218 assert(
TTI &&
"there cannot be a residual loop without TTI");
1220 TTI->getMemcpyLoopResidualLoweringType(RemainingOps, Ctx, RemainingBytes,
1221 DstAS, DstAS, DstAlign, DstAlign,
1224 Type *PreviousOpTy =
nullptr;
1225 Value *SplatSetValue =
nullptr;
1226 for (
auto *
OpTy : RemainingOps) {
1229 "Operand types cannot be scalable vector types");
1234 if (
OpTy != PreviousOpTy)
1238 Int8Type, DstAddr, ConstantInt::get(TypeOfLen, BytesSet));
1241 BytesSet += OperandSize;
1242 PreviousOpTy =
OpTy;
1244 assert(BytesSet == Len->getZExtValue() &&
1245 "Bytes set should match size in the call!");
1252 std::optional<uint64_t> AverageTripCount) {
1263 Type *LoopOpType = Int8Type;
1265 LoopOpType =
TTI->getMemcpyLoopLoweringType(
1266 Ctx, Len, DstAS, DstAS, DstAlign, DstAlign, std::nullopt);
1268 TypeSize LoopOpSize =
DL.getTypeStoreSize(LoopOpType);
1269 assert(LoopOpSize.
isFixed() &&
"LoopOpType cannot be a scalable vector type");
1271 Type *ResidualLoopOpType = Int8Type;
1272 TypeSize ResidualLoopOpSize =
DL.getTypeStoreSize(ResidualLoopOpType);
1280 LoopExpansionInfo LEI =
1282 "dynamic-memset", AverageTripCount);
1283 assert(LEI.MainLoopIP && LEI.MainLoopIndex &&
1284 "Main loop should be generated for unknown size memset");
1296 if (!LEI.ResidualLoopIP)
1304 LEI.ResidualLoopIndex);
1313 std::optional<uint64_t> AverageTripCount) {
1328 PreferredLoopOpType =
TTI->getMemcpyLoopLoweringType(
1329 Ctx, Len, DstAS, DstAS, DstAlign, DstAlign, std::nullopt);
1331 TypeSize PreferredLoopOpStoreSize =
DL.getTypeStoreSize(PreferredLoopOpType);
1333 "PreferredLoopOpType cannot be a scalable vector type");
1335 TypeSize PreferredLoopOpAllocSize =
DL.getTypeAllocSize(PreferredLoopOpType);
1338 TypeSize OriginalTypeStoreSize =
DL.getTypeStoreSize(OriginalType);
1339 TypeSize OriginalTypeAllocSize =
DL.getTypeAllocSize(OriginalType);
1350 unsigned MainLoopStep = 1;
1351 Type *MainLoopType = OriginalType;
1352 TypeSize MainLoopAllocSize = OriginalTypeAllocSize;
1353 unsigned ResidualLoopStep = 0;
1354 Type *ResidualLoopType =
nullptr;
1356 if (PreferredLoopOpStoreSize == PreferredLoopOpAllocSize &&
1357 OriginalTypeStoreSize == OriginalTypeAllocSize &&
1358 OriginalTypeStoreSize < PreferredLoopOpStoreSize &&
1359 PreferredLoopOpStoreSize % OriginalTypeStoreSize == 0) {
1362 MainLoopStep = PreferredLoopOpStoreSize / OriginalTypeStoreSize;
1363 MainLoopType = PreferredLoopOpType;
1364 MainLoopAllocSize = PreferredLoopOpStoreSize;
1366 ResidualLoopStep = 1;
1367 ResidualLoopType = OriginalType;
1372 LoopExpansionInfo LEI =
1374 "memset.pattern", AverageTripCount);
1378 if (LEI.MainLoopIP) {
1382 if (MainLoopType != OriginalType)
1394 if (!LEI.ResidualLoopIP)
1403 LEI.ResidualLoopIndex);
1408template <
typename T>
1412 const SCEV *DestSCEV = SE->
getSCEV(Memcpy->getRawDest());
1423 auto TripCount = getAverageMemOpLoopTripCount(*Memcpy);
1463 bool DstIsVolatile = SrcIsVolatile;
1469 if (SrcAS != DstAS) {
1470 if (!
TTI.addrspacesMayAlias(SrcAS, DstAS)) {
1473 auto AverageTripCount = getAverageMemOpLoopTripCount(*Memmove);
1476 Memmove, SrcAddr, DstAddr, CI, SrcAlign, DstAlign,
1477 SrcIsVolatile, DstIsVolatile,
1478 false,
TTI, std::nullopt, AverageTripCount);
1481 Memmove, SrcAddr, DstAddr, CopyLen, SrcAlign,
1482 DstAlign, SrcIsVolatile, DstIsVolatile,
1483 false,
TTI, std::nullopt, AverageTripCount);
1489 if (!(
TTI.isValidAddrSpaceCast(DstAS, SrcAS) ||
1490 TTI.isValidAddrSpaceCast(SrcAS, DstAS))) {
1495 dbgs() <<
"Do not know how to expand memmove between different "
1496 "address spaces\n");
1503 Memmove, SrcAddr, DstAddr, CI, SrcAlign, DstAlign,
1504 SrcIsVolatile, DstIsVolatile,
TTI);
1507 Memmove, SrcAddr, DstAddr, CopyLen, SrcAlign, DstAlign,
1508 SrcIsVolatile, DstIsVolatile,
TTI);
1515 auto AverageTripCount = getAverageMemOpLoopTripCount(*Memset);
1554 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 cl::opt< bool > ProfcheckDisableMetadataFixes
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.