LLVM: lib/Transforms/Utils/LowerMemIntrinsics.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
18#include
19
20#define DEBUG_TYPE "lower-mem-intrinsics"
21
22using namespace llvm;
23
24
25
27 Value *OpSize, unsigned OpSizeVal) {
28
30 return B.CreateAnd(Len, OpSizeVal - 1);
31 return B.CreateURem(Len, OpSize);
32}
33
34
35
36
37
39 unsigned OpSizeVal,
40 Value *RTLoopRemainder = nullptr) {
41 if (!RTLoopRemainder)
43 return B.CreateSub(Len, RTLoopRemainder);
44}
45
46namespace {
47
48struct LoopExpansionInfo {
49
51
52
53 Value *MainLoopIndex = nullptr;
54
55
56
58
59
60
61 Value *ResidualLoopIndex = nullptr;
62};
63}
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
98 Value *Len, unsigned MainLoopStep,
99 unsigned ResidualLoopStep,
101 assert((ResidualLoopStep == 0 || MainLoopStep % ResidualLoopStep == 0) &&
102 "ResidualLoopStep must divide MainLoopStep if specified");
103 assert(ResidualLoopStep <= MainLoopStep &&
104 "ResidualLoopStep cannot be larger than MainLoopStep");
105 assert(MainLoopStep > 0 && "MainLoopStep must be non-zero");
106 LoopExpansionInfo LEI;
109 InsertBefore, BBNamePrefix + "-post-expansion");
113
114
115
116 Type *LenType = Len->getType();
118 ConstantInt *CIMainLoopStep = ConstantInt::get(ILenType, MainLoopStep);
119
120 Value *LoopUnits = Len;
121 Value *ResidualUnits = nullptr;
122
123
124 bool MustTakeMainLoop = false;
125 if (MainLoopStep != 1) {
127 uint64_t TotalUnits = CLen->getZExtValue();
129 uint64_t ResidualCount = TotalUnits - LoopEndCount;
130 LoopUnits = ConstantInt::get(LenType, LoopEndCount);
131 ResidualUnits = ConstantInt::get(LenType, ResidualCount);
132 MustTakeMainLoop = LoopEndCount > 0;
133
134
135
136
137
138 } else {
140 CIMainLoopStep, MainLoopStep);
142 MainLoopStep, ResidualUnits);
143 }
145 MustTakeMainLoop = CLen->getZExtValue() > 0;
146 }
147
149 Ctx, BBNamePrefix + "-expansion-main-body", ParentFunc, PostLoopBB);
151
152 PHINode *LoopIndex = LoopBuilder.CreatePHI(LenType, 2, "loop-index");
153 LEI.MainLoopIndex = LoopIndex;
154 LoopIndex->addIncoming(ConstantInt::get(LenType, 0U), PreLoopBB);
155
156 Value *NewIndex =
157 LoopBuilder.CreateAdd(LoopIndex, ConstantInt::get(LenType, MainLoopStep));
158 LoopIndex->addIncoming(NewIndex, MainLoopBB);
159
160
161
163
164 if (ResidualLoopStep > 0 && ResidualLoopStep < MainLoopStep) {
165
168 PreLoopBB->getParent(), PostLoopBB);
169
172 PreLoopBB->getParent(), ResLoopBB);
173
174
175 ConstantInt *Zero = ConstantInt::get(ILenType, 0U);
176 if (MustTakeMainLoop)
177 PreLoopBuilder.CreateBr(MainLoopBB);
178 else
180 MainLoopBB, ResidualCondBB);
182
183
184
186 MainLoopBB, ResidualCondBB);
187
188
191 ResLoopBB, PostLoopBB);
192
195 ResBuilder.CreatePHI(LenType, 2, "residual-loop-index");
196 ResidualIndex->addIncoming(Zero, ResidualCondBB);
197
198
199
200 Value *FullOffset = ResBuilder.CreateAdd(LoopUnits, ResidualIndex);
201 LEI.ResidualLoopIndex = FullOffset;
202
204 ResidualIndex, ConstantInt::get(LenType, ResidualLoopStep));
205 ResidualIndex->addIncoming(ResNewIndex, ResLoopBB);
206
207
208
210
211
213 ResBuilder.CreateICmpULT(ResNewIndex, ResidualUnits), ResLoopBB,
214 PostLoopBB);
215 } else {
216
217
218
219
220
221 if (MustTakeMainLoop) {
222 PreLoopBuilder.CreateBr(MainLoopBB);
223 } else {
224 ConstantInt *Zero = ConstantInt::get(ILenType, 0U);
226 MainLoopBB, PostLoopBB);
227 }
229
231 MainLoopBB, PostLoopBB);
232 }
233 return LEI;
234}
235
240 std::optional<uint32_t> AtomicElementSize) {
241
242 if (CopyLen->isZero())
243 return;
244
251 StringRef Name = "MemCopyAliasScope";
253
256
257 Type *TypeOfCopyLen = CopyLen->getType();
258 Type *LoopOpType = TTI.getMemcpyLoopLoweringType(
259 Ctx, CopyLen, SrcAS, DstAS, SrcAlign, DstAlign, AtomicElementSize);
261 "Atomic memcpy lowering is not supported for vector operand type");
262
264 unsigned LoopOpSize = DL.getTypeStoreSize(LoopOpType);
265 assert((!AtomicElementSize || LoopOpSize % *AtomicElementSize == 0) &&
266 "Atomic memcpy lowering is not supported for selected operand size");
267
269
270
271 if (LoopEndCount != 0) {
273 LoopOpSize, 0, "static-memcpy");
274
275
276 IRBuilder<> MainLoopBuilder(LEI.MainLoopIP);
279
280
281
282
283
285 MainLoopBuilder.CreateInBoundsGEP(Int8Type, SrcAddr, LEI.MainLoopIndex);
287 LoopOpType, SrcGEP, PartSrcAlign, SrcIsVolatile);
288 if (!CanOverlap) {
289
290 Load->setMetadata(LLVMContext::MD_alias_scope,
292 }
294 MainLoopBuilder.CreateInBoundsGEP(Int8Type, DstAddr, LEI.MainLoopIndex);
296 Load, DstGEP, PartDstAlign, DstIsVolatile);
297 if (!CanOverlap) {
298
299 Store->setMetadata(LLVMContext::MD_noalias, MDNode::get(Ctx, NewScope));
300 }
301 if (AtomicElementSize) {
304 }
305 assert(!LEI.ResidualLoopIP && !LEI.ResidualLoopIndex &&
306 "No residual loop was requested");
307 }
308
309
310 uint64_t BytesCopied = LoopEndCount;
312 if (RemainingBytes == 0)
313 return;
314
317 TTI.getMemcpyLoopResidualLoweringType(RemainingOps, Ctx, RemainingBytes,
318 SrcAS, DstAS, SrcAlign, DstAlign,
319 AtomicElementSize);
320
321 for (auto *OpTy : RemainingOps) {
324
325 unsigned OperandSize = DL.getTypeStoreSize(OpTy);
326 assert((!AtomicElementSize || OperandSize % *AtomicElementSize == 0) &&
327 "Atomic memcpy lowering is not supported for selected operand size");
328
330 Int8Type, SrcAddr, ConstantInt::get(TypeOfCopyLen, BytesCopied));
332 RBuilder.CreateAlignedLoad(OpTy, SrcGEP, PartSrcAlign, SrcIsVolatile);
333 if (!CanOverlap) {
334
335 Load->setMetadata(LLVMContext::MD_alias_scope,
337 }
339 Int8Type, DstAddr, ConstantInt::get(TypeOfCopyLen, BytesCopied));
341 RBuilder.CreateAlignedStore(Load, DstGEP, PartDstAlign, DstIsVolatile);
342 if (!CanOverlap) {
343
344 Store->setMetadata(LLVMContext::MD_noalias, MDNode::get(Ctx, NewScope));
345 }
346 if (AtomicElementSize) {
349 }
350 BytesCopied += OperandSize;
351 }
353 "Bytes copied should match size in the call!");
354}
355
358 Align SrcAlign, Align DstAlign, bool SrcIsVolatile, bool DstIsVolatile,
360 std::optional<uint32_t> AtomicElementSize) {
366 MDNode *NewDomain = MDB.createAnonymousAliasScopeDomain("MemCopyDomain");
367 StringRef Name = "MemCopyAliasScope";
368 MDNode *NewScope = MDB.createAnonymousAliasScope(NewDomain, Name);
369
372
373 Type *LoopOpType = TTI.getMemcpyLoopLoweringType(
374 Ctx, CopyLen, SrcAS, DstAS, SrcAlign, DstAlign, AtomicElementSize);
376 "Atomic memcpy lowering is not supported for vector operand type");
377 unsigned LoopOpSize = DL.getTypeStoreSize(LoopOpType);
378 assert((!AtomicElementSize || LoopOpSize % *AtomicElementSize == 0) &&
379 "Atomic memcpy lowering is not supported for selected operand size");
380
382
383 Type *ResidualLoopOpType = AtomicElementSize
385 : Int8Type;
386 unsigned ResidualLoopOpSize = DL.getTypeStoreSize(ResidualLoopOpType);
387 assert(ResidualLoopOpSize == (AtomicElementSize ? *AtomicElementSize : 1) &&
388 "Store size is expected to match type size");
389
391 InsertBefore, CopyLen, LoopOpSize, ResidualLoopOpSize, "dynamic-memcpy");
392
393
394 IRBuilder<> MainLoopBuilder(LEI.MainLoopIP);
397
398
399
400
401
403 MainLoopBuilder.CreateInBoundsGEP(Int8Type, SrcAddr, LEI.MainLoopIndex);
404 LoadInst *Load = MainLoopBuilder.CreateAlignedLoad(
405 LoopOpType, SrcGEP, PartSrcAlign, SrcIsVolatile);
406 if (!CanOverlap) {
407
408 Load->setMetadata(LLVMContext::MD_alias_scope, MDNode::get(Ctx, NewScope));
409 }
411 MainLoopBuilder.CreateInBoundsGEP(Int8Type, DstAddr, LEI.MainLoopIndex);
412 StoreInst *Store = MainLoopBuilder.CreateAlignedStore(
413 Load, DstGEP, PartDstAlign, DstIsVolatile);
414 if (!CanOverlap) {
415
416 Store->setMetadata(LLVMContext::MD_noalias, MDNode::get(Ctx, NewScope));
417 }
418 if (AtomicElementSize) {
421 }
422
423
424 if (!LEI.ResidualLoopIP)
425 return;
426
429
430 IRBuilder<> ResLoopBuilder(LEI.ResidualLoopIP);
431 Value *ResSrcGEP = ResLoopBuilder.CreateInBoundsGEP(Int8Type, SrcAddr,
432 LEI.ResidualLoopIndex);
433 LoadInst *ResLoad = ResLoopBuilder.CreateAlignedLoad(
434 ResidualLoopOpType, ResSrcGEP, ResSrcAlign, SrcIsVolatile);
435 if (!CanOverlap) {
436
437 ResLoad->setMetadata(LLVMContext::MD_alias_scope,
439 }
440 Value *ResDstGEP = ResLoopBuilder.CreateInBoundsGEP(Int8Type, DstAddr,
441 LEI.ResidualLoopIndex);
442 StoreInst *ResStore = ResLoopBuilder.CreateAlignedStore(
443 ResLoad, ResDstGEP, ResDstAlign, DstIsVolatile);
444 if (!CanOverlap) {
445
447 }
448 if (AtomicElementSize) {
451 }
452}
453
454
455
456
457
458static std::pair<Value *, Value *>
461 Value *ResAddr1 = Addr1;
462 Value *ResAddr2 = Addr2;
463
466 if (AS1 != AS2) {
467 if (TTI.isValidAddrSpaceCast(AS2, AS1))
468 ResAddr2 = B.CreateAddrSpaceCast(Addr2, Addr1->getType());
469 else if (TTI.isValidAddrSpaceCast(AS1, AS2))
470 ResAddr1 = B.CreateAddrSpaceCast(Addr1, Addr2->getType());
471 else
472 llvm_unreachable("Can only lower memmove between address spaces if they "
473 "support addrspacecast");
474 }
475 return {ResAddr1, ResAddr2};
476}
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
507 Align DstAlign, bool SrcIsVolatile,
508 bool DstIsVolatile,
510 Type *TypeOfCopyLen = CopyLen->getType();
517
518 Type *LoopOpType = TTI.getMemcpyLoopLoweringType(Ctx, CopyLen, SrcAS, DstAS,
519 SrcAlign, DstAlign);
520 unsigned LoopOpSize = DL.getTypeStoreSize(LoopOpType);
522 bool LoopOpIsInt8 = LoopOpType == Int8Type;
523
524
525
526 bool RequiresResidual = !LoopOpIsInt8;
527
528 Type *ResidualLoopOpType = Int8Type;
529 unsigned ResidualLoopOpSize = DL.getTypeStoreSize(ResidualLoopOpType);
530
531
533 ConstantInt *CILoopOpSize = ConstantInt::get(ILengthType, LoopOpSize);
535 ConstantInt::get(ILengthType, ResidualLoopOpSize);
536 ConstantInt *Zero = ConstantInt::get(ILengthType, 0);
537
539
540 Value *RuntimeLoopBytes = CopyLen;
541 Value *RuntimeLoopRemainder = nullptr;
542 Value *SkipResidualCondition = nullptr;
543 if (RequiresResidual) {
544 RuntimeLoopRemainder =
547 LoopOpSize, RuntimeLoopRemainder);
548 SkipResidualCondition =
549 PLBuilder.CreateICmpEQ(RuntimeLoopRemainder, Zero, "skip_residual");
550 }
551 Value *SkipMainCondition =
552 PLBuilder.CreateICmpEQ(RuntimeLoopBytes, Zero, "skip_main");
553
554
555
556
557
558
559
560
561
562
563 auto [CmpSrcAddr, CmpDstAddr] =
565 Value *PtrCompare =
566 PLBuilder.CreateICmpULT(CmpSrcAddr, CmpDstAddr, "compare_src_dst");
569 &ThenTerm, &ElseTerm);
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
596 CopyBackwardsBB->setName("memmove_copy_backwards");
598 CopyForwardBB->setName("memmove_copy_forward");
600 ExitBB->setName("memmove_done");
601
604
605
606
609
610
611 {
613 F->getContext(), "memmove_bwd_main_loop", F, CopyForwardBB);
614
615
616
617 BasicBlock *PredBB = CopyBackwardsBB;
618
619 if (RequiresResidual) {
620
622 F->getContext(), "memmove_bwd_residual_loop", F, MainLoopBB);
623 IRBuilder<> ResidualLoopBuilder(ResidualLoopBB);
624 PHINode *ResidualLoopPhi = ResidualLoopBuilder.CreatePHI(ILengthType, 0);
625 Value *ResidualIndex = ResidualLoopBuilder.CreateSub(
626 ResidualLoopPhi, CIResidualLoopOpSize, "bwd_residual_index");
627
628
629
630
632 ResidualIndex);
634 ResidualLoopOpType, LoadGEP, ResidualSrcAlign, SrcIsVolatile,
635 "element");
637 ResidualIndex);
639 ResidualDstAlign, DstIsVolatile);
640
641
643 F->getContext(), "memmove_bwd_middle", F, MainLoopBB);
644
645 IRBuilder<> IntermediateBuilder(IntermediateBB);
648 ResidualLoopBuilder.CreateICmpEQ(ResidualIndex, RuntimeLoopBytes),
649 IntermediateBB, ResidualLoopBB);
650
651 ResidualLoopPhi->addIncoming(ResidualIndex, ResidualLoopBB);
652 ResidualLoopPhi->addIncoming(CopyLen, CopyBackwardsBB);
653
654
655 BranchInst::Create(IntermediateBB, ResidualLoopBB, SkipResidualCondition,
658
659 PredBB = IntermediateBB;
660 }
661
662
664 PHINode *MainLoopPhi = MainLoopBuilder.CreatePHI(ILengthType, 0);
665 Value *MainIndex =
666 MainLoopBuilder.CreateSub(MainLoopPhi, CILoopOpSize, "bwd_main_index");
670 LoopOpType, LoadGEP, PartSrcAlign, SrcIsVolatile, "element");
671 Value *StoreGEP =
674 DstIsVolatile);
676 ExitBB, MainLoopBB);
677 MainLoopPhi->addIncoming(MainIndex, MainLoopBB);
678 MainLoopPhi->addIncoming(RuntimeLoopBytes, PredBB);
679
680
685 }
686
687
688
689 {
694 MainLoopBuilder.CreatePHI(ILengthType, 0, "fwd_main_index");
696 MainLoopBuilder.CreateInBoundsGEP(Int8Type, SrcAddr, MainLoopPhi);
698 LoopOpType, LoadGEP, PartSrcAlign, SrcIsVolatile, "element");
699 Value *StoreGEP =
700 MainLoopBuilder.CreateInBoundsGEP(Int8Type, DstAddr, MainLoopPhi);
702 DstIsVolatile);
703 Value *MainIndex = MainLoopBuilder.CreateAdd(MainLoopPhi, CILoopOpSize);
704 MainLoopPhi->addIncoming(MainIndex, MainLoopBB);
705 MainLoopPhi->addIncoming(Zero, CopyForwardBB);
706
709 if (RequiresResidual)
710 SuccessorBB =
712
713
715 MainLoopBuilder.CreateICmpEQ(MainIndex, RuntimeLoopBytes), SuccessorBB,
716 MainLoopBB);
717
718
722
723 if (RequiresResidual) {
724 BasicBlock *IntermediateBB = SuccessorBB;
725 IRBuilder<> IntermediateBuilder(IntermediateBB);
727 F->getContext(), "memmove_fwd_residual_loop", F, ExitBB);
728 IntermediateBuilder.CreateCondBr(SkipResidualCondition, ExitBB,
729 ResidualLoopBB);
730
731
732 IRBuilder<> ResidualLoopBuilder(ResidualLoopBB);
733 PHINode *ResidualLoopPhi =
734 ResidualLoopBuilder.CreatePHI(ILengthType, 0, "fwd_residual_index");
736 ResidualLoopPhi);
738 ResidualLoopOpType, LoadGEP, ResidualSrcAlign, SrcIsVolatile,
739 "element");
741 ResidualLoopPhi);
743 ResidualDstAlign, DstIsVolatile);
744 Value *ResidualIndex =
745 ResidualLoopBuilder.CreateAdd(ResidualLoopPhi, CIResidualLoopOpSize);
747 ResidualLoopBuilder.CreateICmpEQ(ResidualIndex, CopyLen), ExitBB,
748 ResidualLoopBB);
749 ResidualLoopPhi->addIncoming(ResidualIndex, ResidualLoopBB);
750 ResidualLoopPhi->addIncoming(RuntimeLoopBytes, IntermediateBB);
751 }
752 }
753}
754
755
756
757
761 Align DstAlign, bool SrcIsVolatile,
762 bool DstIsVolatile,
764
765 if (CopyLen->isZero())
766 return;
767
768 Type *TypeOfCopyLen = CopyLen->getType();
775
776 Type *LoopOpType = TTI.getMemcpyLoopLoweringType(Ctx, CopyLen, SrcAS, DstAS,
777 SrcAlign, DstAlign);
778 unsigned LoopOpSize = DL.getTypeStoreSize(LoopOpType);
780
781
784
786 ConstantInt *Zero = ConstantInt::get(ILengthType, 0);
787 ConstantInt *LoopBound = ConstantInt::get(ILengthType, BytesCopiedInLoop);
788 ConstantInt *CILoopOpSize = ConstantInt::get(ILengthType, LoopOpSize);
789
791
792 auto [CmpSrcAddr, CmpDstAddr] =
794 Value *PtrCompare =
795 PLBuilder.CreateICmpULT(CmpSrcAddr, CmpDstAddr, "compare_src_dst");
798 &ThenTerm, &ElseTerm);
799
803 ExitBB->setName("memmove_done");
804
807
808
809
810 auto GenerateResidualLdStPair = [&](Type *OpTy, IRBuilderBase &Builder,
814
815 unsigned OperandSize = DL.getTypeStoreSize(OpTy);
816
817
818
819
820
821 Value *SrcGEP = Builder.CreateInBoundsGEP(
822 Int8Type, SrcAddr, ConstantInt::get(TypeOfCopyLen, BytesCopied));
824 Builder.CreateAlignedLoad(OpTy, SrcGEP, ResSrcAlign, SrcIsVolatile);
825 Value *DstGEP = Builder.CreateInBoundsGEP(
826 Int8Type, DstAddr, ConstantInt::get(TypeOfCopyLen, BytesCopied));
827 Builder.CreateAlignedStore(Load, DstGEP, ResDstAlign, DstIsVolatile);
828 BytesCopied += OperandSize;
829 };
830
831
832 if (RemainingBytes != 0) {
833 CopyBackwardsBB->setName("memmove_bwd_residual");
834 uint64_t BytesCopied = BytesCopiedInLoop;
835
836
837
838
839
840
841 IRBuilder<> BwdResBuilder(CopyBackwardsBB,
844 TTI.getMemcpyLoopResidualLoweringType(RemainingOps, Ctx, RemainingBytes,
845 SrcAS, DstAS, PartSrcAlign,
846 PartDstAlign);
847 for (auto *OpTy : RemainingOps) {
848
851 GenerateResidualLdStPair(OpTy, BwdResBuilder, BytesCopied);
852 }
853 }
854 if (BytesCopiedInLoop != 0) {
855 BasicBlock *LoopBB = CopyBackwardsBB;
857 if (RemainingBytes != 0) {
858
860 CopyBackwardsBB->getTerminator(), "memmove_bwd_loop");
861 PredBB = CopyBackwardsBB;
862 } else {
863 CopyBackwardsBB->setName("memmove_bwd_loop");
864 }
867 Value *Index = LoopBuilder.CreateSub(LoopPhi, CILoopOpSize, "bwd_index");
870 LoopOpType, LoadGEP, PartSrcAlign, SrcIsVolatile, "element");
873 DstIsVolatile);
874
875
876
879 LoopBB);
881
884 }
885
886
887 BasicBlock *FwdResidualBB = CopyForwardBB;
888 if (BytesCopiedInLoop != 0) {
889 CopyForwardBB->setName("memmove_fwd_loop");
892 if (RemainingBytes != 0) {
893
895 "memmove_fwd_residual");
896 FwdResidualBB = SuccBB;
897 }
899 PHINode *LoopPhi = LoopBuilder.CreatePHI(ILengthType, 0, "fwd_index");
902 LoopOpType, LoadGEP, PartSrcAlign, SrcIsVolatile, "element");
905 DstIsVolatile);
906 Value *Index = LoopBuilder.CreateAdd(LoopPhi, CILoopOpSize);
909
910
913 LoopBB);
915 }
916
917 if (RemainingBytes != 0) {
918 uint64_t BytesCopied = BytesCopiedInLoop;
919
920
921
924 TTI.getMemcpyLoopResidualLoweringType(RemainingOps, Ctx, RemainingBytes,
925 SrcAS, DstAS, PartSrcAlign,
926 PartDstAlign);
927 for (auto *OpTy : RemainingOps)
928 GenerateResidualLdStPair(OpTy, FwdResBuilder, BytesCopied);
929 }
930}
931
934 bool IsVolatile) {
935 Type *TypeOfCopyLen = CopyLen->getType();
943
945
946 Builder.CreateCondBr(
947 Builder.CreateICmpEQ(ConstantInt::get(TypeOfCopyLen, 0), CopyLen), NewBB,
948 LoopBB);
950
951 unsigned PartSize = DL.getTypeStoreSize(SetValue->getType());
953
955 PHINode *LoopIndex = LoopBuilder.CreatePHI(TypeOfCopyLen, 0);
956 LoopIndex->addIncoming(ConstantInt::get(TypeOfCopyLen, 0), OrigBB);
957
961 PartAlign, IsVolatile);
962
963 Value *NewIndex =
964 LoopBuilder.CreateAdd(LoopIndex, ConstantInt::get(TypeOfCopyLen, 1));
965 LoopIndex->addIncoming(NewIndex, LoopBB);
966
968 NewBB);
969}
970
971template
973 if (SE) {
975 const SCEV *DestSCEV = SE->getSCEV(Memcpy->getRawDest());
977 return false;
978 }
979 return true;
980}
981
985 bool CanOverlap = canOverlap(Memcpy, SE);
988 Memcpy,
991 CI,
994 Memcpy->isVolatile(),
995 Memcpy->isVolatile(),
996 CanOverlap,
997 TTI);
998 } else {
1000 Memcpy,
1003 Memcpy->getLength(),
1006 Memcpy->isVolatile(),
1007 Memcpy->isVolatile(),
1008 CanOverlap,
1009 TTI);
1010 }
1011}
1012
1020 bool SrcIsVolatile = Memmove->isVolatile();
1021 bool DstIsVolatile = SrcIsVolatile;
1023
1026 if (SrcAS != DstAS) {
1027 if (.addrspacesMayAlias(SrcAS, DstAS)) {
1028
1029
1032 CI, SrcAlign, DstAlign, SrcIsVolatile,
1033 DstIsVolatile,
1034 false, TTI);
1035 } else {
1037 CopyLen, SrcAlign, DstAlign, SrcIsVolatile,
1038 DstIsVolatile,
1039 false, TTI);
1040 }
1041
1042 return true;
1043 }
1044
1045 if (!(TTI.isValidAddrSpaceCast(DstAS, SrcAS) ||
1046 TTI.isValidAddrSpaceCast(SrcAS, DstAS))) {
1047
1048
1049
1051 dbgs() << "Do not know how to expand memmove between different "
1052 "address spaces\n");
1053 return false;
1054 }
1055 }
1056
1059 Memmove, SrcAddr, DstAddr, CI, SrcAlign, DstAlign,
1060 SrcIsVolatile, DstIsVolatile, TTI);
1061 } else {
1063 Memmove, SrcAddr, DstAddr, CopyLen, SrcAlign, DstAlign,
1064 SrcIsVolatile, DstIsVolatile, TTI);
1065 }
1066 return true;
1067}
1068
1077
1086
1093 AtomicMemcpy,
1095 AtomicMemcpy->getRawDest(),
1096 CI,
1099 AtomicMemcpy->isVolatile(),
1100 AtomicMemcpy->isVolatile(),
1101 false,
1102 TTI,
1104 } else {
1106 AtomicMemcpy,
1108 AtomicMemcpy->getRawDest(),
1109 AtomicMemcpy->getLength(),
1112 AtomicMemcpy->isVolatile(),
1113 AtomicMemcpy->isVolatile(),
1114 false,
1115 TTI,
1117 }
1118}
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 std::pair< Value *, Value * > tryInsertCastToCommonAddrSpace(IRBuilderBase &B, Value *Addr1, Value *Addr2, const TargetTransformInfo &TTI)
Definition LowerMemIntrinsics.cpp:459
static bool canOverlap(MemTransferBase< T > *Memcpy, ScalarEvolution *SE)
Definition LowerMemIntrinsics.cpp:972
static void createMemMoveLoopKnownSize(Instruction *InsertBefore, Value *SrcAddr, Value *DstAddr, ConstantInt *CopyLen, Align SrcAlign, Align DstAlign, bool SrcIsVolatile, bool DstIsVolatile, const TargetTransformInfo &TTI)
Definition LowerMemIntrinsics.cpp:758
static void createMemSetLoop(Instruction *InsertBefore, Value *DstAddr, Value *CopyLen, Value *SetValue, Align DstAlign, bool IsVolatile)
Definition LowerMemIntrinsics.cpp:932
static Value * getRuntimeLoopRemainder(IRBuilderBase &B, Value *Len, Value *OpSize, unsigned OpSizeVal)
Definition LowerMemIntrinsics.cpp:26
static Value * getRuntimeLoopUnits(IRBuilderBase &B, Value *Len, Value *OpSize, unsigned OpSizeVal, Value *RTLoopRemainder=nullptr)
Definition LowerMemIntrinsics.cpp:38
static LoopExpansionInfo insertLoopExpansion(Instruction *InsertBefore, Value *Len, unsigned MainLoopStep, unsigned ResidualLoopStep, StringRef BBNamePrefix)
Insert the control flow and loop counters for a memcpy/memset loop expansion.
Definition LowerMemIntrinsics.cpp:97
static void createMemMoveLoopUnknownSize(Instruction *InsertBefore, Value *SrcAddr, Value *DstAddr, Value *CopyLen, Align SrcAlign, Align DstAlign, bool SrcIsVolatile, bool DstIsVolatile, const TargetTransformInfo &TTI)
Definition LowerMemIntrinsics.cpp:504
This pass exposes codegen information to IR-level passes.
This class represents any memcpy intrinsic i.e.
uint32_t getElementSizeInBytes() const
LLVM Basic Block Representation.
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 BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="", bool Before=false)
Split the basic block into two basic blocks at the specified instruction.
LLVM_ABI LLVMContext & getContext() const
Get the context in which this basic block lives.
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
static BranchInst * Create(BasicBlock *IfTrue, InsertPosition InsertBefore=nullptr)
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.
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)
UnreachableInst * CreateUnreachable()
Value * CreateInBoundsGEP(Type *Ty, Value *Ptr, ArrayRef< Value * > IdxList, const Twine &Name="")
Value * CreateICmpNE(Value *LHS, Value *RHS, const Twine &Name="")
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)
BranchInst * CreateCondBr(Value *Cond, BasicBlock *True, BasicBlock *False, MDNode *BranchWeights=nullptr, MDNode *Unpredictable=nullptr)
Create a conditional 'br Cond, TrueDest, FalseDest' instruction.
Value * CreateAdd(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
BranchInst * CreateBr(BasicBlock *Dest)
Create an unconditional 'br label X' instruction.
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 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.
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.
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 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.
StringRef - Represent a constant reference to a string, i.e.
This pass provides access to the codegen interfaces that are needed for IR-level transformations.
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)
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.
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.
FunctionAddr VTableAddr Value
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)
Emit a loop implementing the semantics of an llvm.memcpy whose size is a compile time constant.
Definition LowerMemIntrinsics.cpp:236
decltype(auto) dyn_cast(const From &Val)
dyn_cast - Return the argument parameter cast to the specified type.
LLVM_ABI void expandMemSetPatternAsLoop(MemSetPatternInst *MemSet)
Expand MemSetPattern as a loop. MemSet is not deleted.
Definition LowerMemIntrinsics.cpp:1078
LLVM_ABI bool expandMemMoveAsLoop(MemMoveInst *MemMove, const TargetTransformInfo &TTI)
Expand MemMove as a loop.
Definition LowerMemIntrinsics.cpp:1013
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.
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 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)
Emit a loop implementing the semantics of llvm.memcpy where the size is not a compile-time constant.
LLVM_ABI void expandAtomicMemCpyAsLoop(AnyMemCpyInst *AtomicMemCpy, const TargetTransformInfo &TTI, ScalarEvolution *SE)
Expand AtomicMemCpy as a loop. AtomicMemCpy is not deleted.
Definition LowerMemIntrinsics.cpp:1087
decltype(auto) cast(const From &Val)
cast - Return the argument parameter cast to the specified type.
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.
Definition LowerMemIntrinsics.cpp:982
LLVM_ABI void expandMemSetAsLoop(MemSetInst *MemSet)
Expand MemSet as a loop. MemSet is not deleted.
Definition LowerMemIntrinsics.cpp:1069
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.