LLVM: lib/Target/CSKY/CSKYConstantIslandPass.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
38#include "llvm/Config/llvm-config.h"
51#include
52#include
53#include
54#include
55
56using namespace llvm;
57
58#define DEBUG_TYPE "CSKY-constant-islands"
59
60STATISTIC(NumCPEs, "Number of constpool entries");
61STATISTIC(NumSplit, "Number of uncond branches inserted");
62STATISTIC(NumCBrFixed, "Number of cond branches fixed");
63STATISTIC(NumUBrFixed, "Number of uncond branches fixed");
64
65namespace {
66
69
70
71
72
73
74
75
76
77
78
79
80
81
83
84
86
87
88
89
90
91
92
93
94
96
97
98
99
100
101
102 unsigned Size = 0;
103
105
106 unsigned postOffset() const { return Offset + Size; }
107 };
108
109 std::vector BBInfo;
110
111
112
113
114 std::vector<MachineBasicBlock *> WaterList;
115
116
117
118 SmallPtrSet<MachineBasicBlock *, 4> NewWaterList;
119
120 using water_iterator = std::vector<MachineBasicBlock *>::iterator;
121
122
123
124
125
126
127
128
129
130
131
132
133
134 struct CPUser {
135 MachineInstr *MI;
136 MachineInstr *CPEMI;
137 MachineBasicBlock *HighWaterMark;
138
139 private:
140 unsigned MaxDisp;
141
142 public:
143 bool NegOk;
144
145 CPUser(MachineInstr *Mi, MachineInstr *Cpemi, unsigned Maxdisp, bool Neg)
146 : MI(Mi), CPEMI(Cpemi), MaxDisp(Maxdisp), NegOk(Neg) {
147 HighWaterMark = CPEMI->getParent();
148 }
149
150
151 unsigned getMaxDisp() const { return MaxDisp - 16; }
152
153 void setMaxDisp(unsigned Val) { MaxDisp = Val; }
154 };
155
156
157
158 std::vector CPUsers;
159
160
161
162
163 struct CPEntry {
164 MachineInstr *CPEMI;
165 unsigned CPI;
166 unsigned RefCount;
167
168 CPEntry(MachineInstr *Cpemi, unsigned Cpi, unsigned Rc = 0)
169 : CPEMI(Cpemi), CPI(Cpi), RefCount(Rc) {}
170 };
171
172
173
174
175
176
177 std::vector<std::vector> CPEntries;
178
179
180
181
182
183 struct ImmBranch {
184 MachineInstr *MI;
185 unsigned MaxDisp : 31;
187 unsigned IsCond : 1;
188 int UncondBr;
189
190 ImmBranch(MachineInstr *Mi, unsigned Maxdisp, bool Cond, int Ubr)
191 : MI(Mi), MaxDisp(Maxdisp), IsCond(Cond), UncondBr(Ubr) {}
192 };
193
194
195
196 std::vector ImmBranches;
197
198 const CSKYSubtarget *STI = nullptr;
199 const CSKYInstrInfo *TII;
200 CSKYMachineFunctionInfo *MFI;
201 MachineFunction *MF = nullptr;
202 MachineConstantPool *MCP = nullptr;
203
204 unsigned PICLabelUId;
205
206 void initPICLabelUId(unsigned UId) { PICLabelUId = UId; }
207
208 unsigned createPICLabelUId() { return PICLabelUId++; }
209
210public:
211 static char ID;
212
213 CSKYConstantIslands() : MachineFunctionPass(ID) {}
214
215 StringRef getPassName() const override { return "CSKY Constant Islands"; }
216
217 bool runOnMachineFunction(MachineFunction &F) override;
218
219 MachineFunctionProperties getRequiredProperties() const override {
220 return MachineFunctionProperties().setNoVRegs();
221 }
222
223 void doInitialPlacement(std::vector<MachineInstr *> &CPEMIs);
224 CPEntry *findConstPoolEntry(unsigned CPI, const MachineInstr *CPEMI);
225 Align getCPEAlign(const MachineInstr &CPEMI);
226 void initializeFunctionInfo(const std::vector<MachineInstr *> &CPEMIs);
227 unsigned getOffsetOf(MachineInstr *MI) const;
228 unsigned getUserOffset(CPUser &) const;
229 void dumpBBs();
230
231 bool isOffsetInRange(unsigned UserOffset, unsigned TrialOffset, unsigned Disp,
232 bool NegativeOK);
233 bool isOffsetInRange(unsigned UserOffset, unsigned TrialOffset,
234 const CPUser &U);
235
236 void computeBlockSize(MachineBasicBlock *MBB);
237 MachineBasicBlock *splitBlockBeforeInstr(MachineInstr &MI);
238 void updateForInsertedWaterBlock(MachineBasicBlock *NewBB);
239 void adjustBBOffsetsAfter(MachineBasicBlock *BB);
240 bool decrementCPEReferenceCount(unsigned CPI, MachineInstr *CPEMI);
241 int findInRangeCPEntry(CPUser &U, unsigned UserOffset);
242 bool findAvailableWater(CPUser &U, unsigned UserOffset,
243 water_iterator &WaterIter);
244 void createNewWater(unsigned CPUserIndex, unsigned UserOffset,
245 MachineBasicBlock *&NewMBB);
246 bool handleConstantPoolUser(unsigned CPUserIndex);
247 void removeDeadCPEMI(MachineInstr *CPEMI);
248 bool removeUnusedCPEntries();
249 bool isCPEntryInRange(MachineInstr *MI, unsigned UserOffset,
250 MachineInstr *CPEMI, unsigned Disp, bool NegOk,
251 bool DoDump = false);
252 bool isWaterInRange(unsigned UserOffset, MachineBasicBlock *Water, CPUser &U,
253 unsigned &Growth);
254 bool isBBInRange(MachineInstr *MI, MachineBasicBlock *BB, unsigned Disp);
255 bool fixupImmediateBr(ImmBranch &Br);
256 bool fixupConditionalBr(ImmBranch &Br);
257 bool fixupUnconditionalBr(ImmBranch &Br);
258};
259}
260
261char CSKYConstantIslands::ID = 0;
262
263bool CSKYConstantIslands::isOffsetInRange(unsigned UserOffset,
264 unsigned TrialOffset,
265 const CPUser &U) {
266 return isOffsetInRange(UserOffset, TrialOffset, U.getMaxDisp(), U.NegOk);
267}
268
269#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
270
272 for (unsigned J = 0, E = BBInfo.size(); J != E; ++J) {
273 const BasicBlockInfo &BBI = BBInfo[J];
275 << format(" size=%#x\n", BBInfo[J].Size);
276 }
277}
278#endif
279
280bool CSKYConstantIslands::runOnMachineFunction(MachineFunction &Mf) {
281 MF = &Mf;
284
286 << MCP->getConstants().size() << " CP entries, aligned to "
288
290 MFI = MF->getInfo();
291
292
294
295
296
298
299 bool MadeChange = false;
300
301
302
303 std::vector<MachineInstr *> CPEMIs;
305 doInitialPlacement(CPEMIs);
306
307
308 initPICLabelUId(CPEMIs.size());
309
310
311
312
313 initializeFunctionInfo(CPEMIs);
314 CPEMIs.clear();
316
317
318 MadeChange |= removeUnusedCPEntries();
319
320
321
322 unsigned NoCPIters = 0, NoBRIters = 0;
323 (void)NoBRIters;
324 while (true) {
325 LLVM_DEBUG(dbgs() << "Beginning CP iteration #" << NoCPIters << '\n');
326 bool CPChange = false;
327 for (unsigned I = 0, E = CPUsers.size(); I != E; ++I)
328 CPChange |= handleConstantPoolUser(I);
329 if (CPChange && ++NoCPIters > 30)
332
333
334
335 NewWaterList.clear();
336
337 LLVM_DEBUG(dbgs() << "Beginning BR iteration #" << NoBRIters << '\n');
338 bool BRChange = false;
339 for (unsigned I = 0, E = ImmBranches.size(); I != E; ++I)
340 BRChange |= fixupImmediateBr(ImmBranches[I]);
341 if (BRChange && ++NoBRIters > 30)
344 if (!CPChange && !BRChange)
345 break;
346 MadeChange = true;
347 }
348
350
351 BBInfo.clear();
352 WaterList.clear();
353 CPUsers.clear();
354 CPEntries.clear();
355 ImmBranches.clear();
356 return MadeChange;
357}
358
359
360
361void CSKYConstantIslands::doInitialPlacement(
362 std::vector<MachineInstr *> &CPEMIs) {
363
366
367
369
370
372
373
374
376
377
378
379
380
382 BB->end());
383
384
385
386 const std::vector &CPs = MCP->getConstants();
387
389 for (unsigned I = 0, E = CPs.size(); I != E; ++I) {
390 unsigned Size = CPs[I].getSizeInBytes(TD);
391 assert(Size >= 4 && "Too small constant pool entry");
392 Align Alignment = CPs[I].getAlign();
393
394
395 assert(isAligned(Alignment, Size) && "CP Entry not multiple of 4 bytes!");
396
397
398 unsigned LogAlign = Log2(Alignment);
400
401 MachineInstr *CPEMI =
406
407 CPEMIs.push_back(CPEMI);
408
409
410
411 for (unsigned A = LogAlign + 1; A <= Log2(MaxAlign); ++A)
412 if (InsPoint[A] == InsAt)
413 InsPoint[A] = CPEMI;
414
415 CPEntries.emplace_back(1, CPEntry(CPEMI, I));
416 ++NumCPEs;
417 LLVM_DEBUG(dbgs() << "Moved CPI#" << I << " to end of function, size = "
418 << Size << ", align = " << Alignment.value() << '\n');
419 }
421}
422
423
424
426
428
429 if (std::next(MBBI) == MBB->getParent()->end())
430 return false;
431
436 if (*I == NextBB)
437 return true;
438
439 return false;
440}
441
442
443
444CSKYConstantIslands::CPEntry *
445CSKYConstantIslands::findConstPoolEntry(unsigned CPI,
446 const MachineInstr *CPEMI) {
447 std::vector &CPEs = CPEntries[CPI];
448
449
450 for (unsigned I = 0, E = CPEs.size(); I != E; ++I) {
451 if (CPEs[I].CPEMI == CPEMI)
452 return &CPEs[I];
453 }
454 return nullptr;
455}
456
457
458
459Align CSKYConstantIslands::getCPEAlign(const MachineInstr &CPEMI) {
461
463 assert(CPI < MCP->getConstants().size() && "Invalid constant pool index.");
465}
466
467
468
469
470void CSKYConstantIslands::initializeFunctionInfo(
471 const std::vector<MachineInstr *> &CPEMIs) {
472 BBInfo.clear();
474
475
476
477
478
480 computeBlockSize(&*I);
481
482
483 adjustBBOffsetsAfter(&MF->front());
484
485
486 for (MachineBasicBlock &MBB : *MF) {
487
488
490 WaterList.push_back(&MBB);
491 for (MachineInstr &MI : MBB) {
492 if (MI.isDebugInstr())
493 continue;
494
496 if (MI.isBranch() && .isIndirectBranch()) {
497 bool IsCond = MI.isConditionalBranch();
498 unsigned Bits = 0;
499 unsigned Scale = 1;
500 int UOpc = CSKY::BR32;
501
502 switch (MI.getOpcode()) {
503 case CSKY::BR16:
504 case CSKY::BF16:
505 case CSKY::BT16:
507 Scale = 2;
508 break;
509 default:
511 Scale = 2;
512 break;
513 }
514
515
516 unsigned MaxOffs = ((1 << (Bits - 1)) - 1) * Scale;
517 ImmBranches.push_back(ImmBranch(&MI, MaxOffs, IsCond, UOpc));
518 }
519
520 if (Opc == CSKY::CONSTPOOL_ENTRY)
521 continue;
522
523
524 for (unsigned Op = 0, E = MI.getNumOperands(); Op != E; ++Op)
525 if (MI.getOperand(Op).isCPI()) {
526
527
528
529
530 unsigned Bits = 0;
531 unsigned Scale = 1;
532 bool NegOk = false;
533
534 switch (Opc) {
535 default:
536 llvm_unreachable("Unknown addressing mode for CP reference!");
537 case CSKY::MOVIH32:
538 case CSKY::ORI32:
539 continue;
540 case CSKY::PseudoTLSLA32:
541 case CSKY::JSRI32:
542 case CSKY::JMPI32:
543 case CSKY::LRW32:
544 case CSKY::LRW32_Gen:
546 Scale = 4;
547 break;
548 case CSKY::f2FLRW_S:
549 case CSKY::f2FLRW_D:
551 Scale = 4;
552 break;
553 case CSKY::GRS32:
555 Scale = 2;
556 NegOk = true;
557 break;
558 }
559
560 unsigned CPI = MI.getOperand(Op).getIndex();
561 MachineInstr *CPEMI = CPEMIs[CPI];
562 unsigned MaxOffs = ((1 << Bits) - 1) * Scale;
563 CPUsers.push_back(CPUser(&MI, CPEMI, MaxOffs, NegOk));
564
565
566 CPEntry *CPE = findConstPoolEntry(CPI, CPEMI);
567 assert(CPE && "Cannot find a corresponding CPEntry!");
568 CPE->RefCount++;
569 }
570 }
571 }
572}
573
574
575
576void CSKYConstantIslands::computeBlockSize(MachineBasicBlock *MBB) {
577 BasicBlockInfo &BBI = BBInfo[MBB->getNumber()];
578 BBI.Size = 0;
579
580 for (const MachineInstr &MI : *MBB)
582}
583
584
585
586
587unsigned CSKYConstantIslands::getOffsetOf(MachineInstr *MI) const {
588 MachineBasicBlock *MBB = MI->getParent();
589
590
591
592
594
595
597 assert(I != MBB->end() && "Didn't find MI in its own basic block?");
599 }
601}
602
603
604
607 return LHS->getNumber() < RHS->getNumber();
608}
609
610
611
612
613void CSKYConstantIslands::updateForInsertedWaterBlock(
614 MachineBasicBlock *NewBB) {
615
617
618
619
620 BBInfo.insert(BBInfo.begin() + NewBB->getNumber(), BasicBlockInfo());
621
622
623
625 WaterList.insert(IP, NewBB);
626}
627
628unsigned CSKYConstantIslands::getUserOffset(CPUser &U) const {
629 unsigned UserOffset = getOffsetOf(U.MI);
630
631 UserOffset &= ~3u;
632
633 return UserOffset;
634}
635
636
637
638
639MachineBasicBlock *
640CSKYConstantIslands::splitBlockBeforeInstr(MachineInstr &MI) {
641 MachineBasicBlock *OrigBB = MI.getParent();
642
643
644 MachineBasicBlock *NewBB =
645 MF->CreateMachineBasicBlock(OrigBB->getBasicBlock());
647 MF->insert(MBBI, NewBB);
648
649
650 NewBB->splice(NewBB->end(), OrigBB, MI, OrigBB->end());
651
652
653
654
655
656
657
659 ++NumSplit;
660
661
663
664
666
667
668
669
670 MF->RenumberBlocks(NewBB);
671
672
673
674 BBInfo.insert(BBInfo.begin() + NewBB->getNumber(), BasicBlockInfo());
675
676
677
678
679
681 MachineBasicBlock *WaterBB = *IP;
682 if (WaterBB == OrigBB)
683 WaterList.insert(std::next(IP), NewBB);
684 else
685 WaterList.insert(IP, OrigBB);
686 NewWaterList.insert(OrigBB);
687
688
689
690
691
692
693 computeBlockSize(OrigBB);
694
695
696
697 computeBlockSize(NewBB);
698
699
700 adjustBBOffsetsAfter(OrigBB);
701
702 return NewBB;
703}
704
705
706
707
708bool CSKYConstantIslands::isOffsetInRange(unsigned UserOffset,
709 unsigned TrialOffset,
710 unsigned MaxDisp, bool NegativeOK) {
711 if (UserOffset <= TrialOffset) {
712
713 if (TrialOffset - UserOffset <= MaxDisp)
714 return true;
715 } else if (NegativeOK) {
716 if (UserOffset - TrialOffset <= MaxDisp)
717 return true;
718 }
719 return false;
720}
721
722
723
724
725
726bool CSKYConstantIslands::isWaterInRange(unsigned UserOffset,
727 MachineBasicBlock *Water, CPUser &U,
728 unsigned &Growth) {
729 unsigned CPEOffset = BBInfo[Water->getNumber()].postOffset();
730 unsigned NextBlockOffset;
731 Align NextBlockAlignment;
733 if (NextBlock == MF->end()) {
734 NextBlockOffset = BBInfo[Water->getNumber()].postOffset();
735 NextBlockAlignment = Align(4);
736 } else {
737 NextBlockOffset = BBInfo[NextBlock->getNumber()].Offset;
738 NextBlockAlignment = NextBlock->getAlignment();
739 }
740 unsigned Size = U.CPEMI->getOperand(2).getImm();
741 unsigned CPEEnd = CPEOffset + Size;
742
743
744
745
746 if (CPEEnd > NextBlockOffset) {
747 Growth = CPEEnd - NextBlockOffset;
748
749
751
752
753
754
755 if (CPEOffset < UserOffset)
756 UserOffset += Growth;
757 } else
758
759 Growth = 0;
760
761 return isOffsetInRange(UserOffset, CPEOffset, U);
762}
763
764
765
766bool CSKYConstantIslands::isCPEntryInRange(MachineInstr *MI,
767 unsigned UserOffset,
768 MachineInstr *CPEMI,
769 unsigned MaxDisp, bool NegOk,
770 bool DoDump) {
771 unsigned CPEOffset = getOffsetOf(CPEMI);
772
773 if (DoDump) {
775 unsigned Block = MI->getParent()->getNumber();
776 const BasicBlockInfo &BBI = BBInfo[Block];
778 << " max delta=" << MaxDisp
779 << format(" insn address=%#x", UserOffset) << " in "
782 << format("CPE address=%#x offset=%+d: ", CPEOffset,
783 int(CPEOffset - UserOffset));
784 });
785 }
786
787 return isOffsetInRange(UserOffset, CPEOffset, MaxDisp, NegOk);
788}
789
790#ifndef NDEBUG
791
792
794 if (MBB->pred_size() != 1 || MBB->succ_size() != 1)
795 return false;
799 if (PredMI->getOpcode() == CSKY::BR32 )
801 return false;
802}
803#endif
804
805void CSKYConstantIslands::adjustBBOffsetsAfter(MachineBasicBlock *BB) {
806 unsigned BBNum = BB->getNumber();
807 for (unsigned I = BBNum + 1, E = MF->getNumBlockIDs(); I < E; ++I) {
808
809
810 unsigned Offset = BBInfo[I - 1].Offset + BBInfo[I - 1].Size;
811 BBInfo[I].Offset = Offset;
812 }
813}
814
815
816
817
818
819bool CSKYConstantIslands::decrementCPEReferenceCount(unsigned CPI,
820 MachineInstr *CPEMI) {
821
822 CPEntry *CPE = findConstPoolEntry(CPI, CPEMI);
823 assert(CPE && "Unexpected!");
824 if (--CPE->RefCount == 0) {
825 removeDeadCPEMI(CPEMI);
826 CPE->CPEMI = nullptr;
827 --NumCPEs;
828 return true;
829 }
830 return false;
831}
832
833
834
835
836
837
838
839int CSKYConstantIslands::findInRangeCPEntry(CPUser &U, unsigned UserOffset) {
840 MachineInstr *UserMI = U.MI;
841 MachineInstr *CPEMI = U.CPEMI;
842
843
844 if (isCPEntryInRange(UserMI, UserOffset, CPEMI, U.getMaxDisp(), U.NegOk,
845 true)) {
847 return 1;
848 }
849
850
852 std::vector &CPEs = CPEntries[CPI];
853 for (unsigned I = 0, E = CPEs.size(); I != E; ++I) {
854
855 if (CPEs[I].CPEMI == CPEMI)
856 continue;
857
858 if (CPEs[I].CPEMI == nullptr)
859 continue;
860 if (isCPEntryInRange(UserMI, UserOffset, CPEs[I].CPEMI, U.getMaxDisp(),
861 U.NegOk)) {
862 LLVM_DEBUG(dbgs() << "Replacing CPE#" << CPI << " with CPE#"
863 << CPEs[I].CPI << "\n");
864
866
867 for (unsigned J = 0, E = UserMI->getNumOperands(); J != E; ++J)
870 break;
871 }
872
873 CPEs[I].RefCount++;
874
875
876 return decrementCPEReferenceCount(CPI, CPEMI) ? 2 : 1;
877 }
878 }
879 return 0;
880}
881
882
883
885 unsigned Bits, Scale;
886
887 switch (Opc) {
888 case CSKY::BR16:
889 Bits = 10;
890 Scale = 2;
891 break;
892 case CSKY::BR32:
893 Bits = 16;
894 Scale = 2;
895 break;
896 default:
898 }
899
900 unsigned MaxOffs = ((1 << (Bits - 1)) - 1) * Scale;
901 return MaxOffs;
902}
903
904
905
906
907
908
909
910
911
912bool CSKYConstantIslands::findAvailableWater(CPUser &U, unsigned UserOffset,
913 water_iterator &WaterIter) {
914 if (WaterList.empty())
915 return false;
916
917 unsigned BestGrowth = ~0u;
918 for (water_iterator IP = std::prev(WaterList.end()), B = WaterList.begin();;
919 --IP) {
920 MachineBasicBlock *WaterBB = *IP;
921
922
923
924
925
926
927
928
929 unsigned Growth;
930 if (isWaterInRange(UserOffset, WaterBB, U, Growth) &&
931 (WaterBB->getNumber() < U.HighWaterMark->getNumber() ||
932 NewWaterList.count(WaterBB)) &&
933 Growth < BestGrowth) {
934
935 BestGrowth = Growth;
936 WaterIter = IP;
938 << " Growth=" << Growth << '\n');
939
940
941 if (BestGrowth == 0)
942 return true;
943 }
944 if (IP == B)
945 break;
946 }
947 return BestGrowth != ~0u;
948}
949
950
951
952
953
954
955
956
957void CSKYConstantIslands::createNewWater(unsigned CPUserIndex,
958 unsigned UserOffset,
959 MachineBasicBlock *&NewMBB) {
960 CPUser &U = CPUsers[CPUserIndex];
961 MachineInstr *UserMI = U.MI;
962 MachineInstr *CPEMI = U.CPEMI;
963 MachineBasicBlock *UserMBB = UserMI->getParent();
964 const BasicBlockInfo &UserBBI = BBInfo[UserMBB->getNumber()];
965
966
967
969
970 unsigned Delta = 4;
971
972 unsigned CPEOffset = UserBBI.postOffset() + Delta;
973
974 if (isOffsetInRange(UserOffset, CPEOffset, U)) {
976 << format(", expected CPE offset %#x\n", CPEOffset));
978
979
980
981
982
983
984
985 int UncondBr = CSKY::BR32;
990 ImmBranches.push_back(
991 ImmBranch(&UserMBB->back(), MaxDisp, false, UncondBr));
993 adjustBBOffsetsAfter(UserMBB);
994 return;
995 }
996 }
997
998
999
1000
1001
1002
1003 const Align Align = MF->getAlignment();
1004 unsigned BaseInsertOffset = UserOffset + U.getMaxDisp();
1006 BaseInsertOffset));
1007
1008
1009
1010
1011 BaseInsertOffset -= 4;
1012
1014 << " la=" << Log2(Align) << '\n');
1015
1016
1017
1018
1019
1020 if (BaseInsertOffset + 8 >= UserBBI.postOffset()) {
1021 BaseInsertOffset = UserBBI.postOffset() - 8;
1023 }
1024 unsigned EndInsertOffset =
1027 ++MI;
1028 unsigned CPUIndex = CPUserIndex + 1;
1029 unsigned NumCPUsers = CPUsers.size();
1031 Offset < BaseInsertOffset;
1033 assert(MI != UserMBB->end() && "Fell off end of block");
1034 if (CPUIndex < NumCPUsers && CPUsers[CPUIndex].MI == MI) {
1035 CPUser &U = CPUsers[CPUIndex];
1036 if (!isOffsetInRange(Offset, EndInsertOffset, U)) {
1037
1038 BaseInsertOffset -= Align.value();
1039 EndInsertOffset -= Align.value();
1040 }
1041
1042
1043
1044
1045 EndInsertOffset += U.CPEMI->getOperand(2).getImm();
1046 CPUIndex++;
1047 }
1048 }
1049
1050 NewMBB = splitBlockBeforeInstr(*--MI);
1051}
1052
1053
1054
1055
1056
1057bool CSKYConstantIslands::handleConstantPoolUser(unsigned CPUserIndex) {
1058 CPUser &U = CPUsers[CPUserIndex];
1059 MachineInstr *UserMI = U.MI;
1060 MachineInstr *CPEMI = U.CPEMI;
1063
1064 unsigned UserOffset = getUserOffset(U);
1065
1066
1067
1068 int result = findInRangeCPEntry(U, UserOffset);
1069 if (result == 1)
1070 return false;
1071 if (result == 2)
1072 return true;
1073
1074
1075 MachineBasicBlock *NewIsland = MF->CreateMachineBasicBlock();
1076 MachineBasicBlock *NewMBB;
1077 water_iterator IP;
1078 if (findAvailableWater(U, UserOffset, IP)) {
1080 MachineBasicBlock *WaterBB = *IP;
1081
1082
1083
1084
1085 if (NewWaterList.erase(WaterBB))
1086 NewWaterList.insert(NewIsland);
1087
1088
1090 } else {
1092 createNewWater(CPUserIndex, UserOffset, NewMBB);
1093
1094
1095
1096
1097
1098
1099 MachineBasicBlock *WaterBB = &*--NewMBB->getIterator();
1100 IP = llvm::find(WaterList, WaterBB);
1101 if (IP != WaterList.end())
1102 NewWaterList.erase(WaterBB);
1103
1104
1105 NewWaterList.insert(NewIsland);
1106 }
1107
1108
1109
1110
1111
1112 if (IP != WaterList.end())
1113 WaterList.erase(IP);
1114
1115
1116 MF->insert(NewMBB->getIterator(), NewIsland);
1117
1118
1119 updateForInsertedWaterBlock(NewIsland);
1120
1121
1122 decrementCPEReferenceCount(CPI, CPEMI);
1123
1124
1125
1126 unsigned ID = createPICLabelUId();
1127
1128
1129
1130 U.HighWaterMark = NewIsland;
1135 CPEntries[CPI].push_back(CPEntry(U.CPEMI, ID, 1));
1136 ++NumCPEs;
1137
1138
1140
1141
1143 adjustBBOffsetsAfter(&*--NewIsland->getIterator());
1144
1145
1149 break;
1150 }
1151
1153 dbgs() << " Moved CPE to #" << ID << " CPI=" << CPI
1154 << format(" offset=%#x\n", BBInfo[NewIsland->getNumber()].Offset));
1155
1156 return true;
1157}
1158
1159
1160
1161void CSKYConstantIslands::removeDeadCPEMI(MachineInstr *CPEMI) {
1162 MachineBasicBlock *CPEBB = CPEMI->getParent();
1166
1167 if (CPEBB->empty()) {
1168 BBInfo[CPEBB->getNumber()].Size = 0;
1169
1170
1172 } else {
1173
1175 }
1176
1177 adjustBBOffsetsAfter(CPEBB);
1178
1179
1180
1182
1183}
1184
1185
1186
1187bool CSKYConstantIslands::removeUnusedCPEntries() {
1188 unsigned MadeChange = false;
1189 for (unsigned I = 0, E = CPEntries.size(); I != E; ++I) {
1190 std::vector &CPEs = CPEntries[I];
1191 for (unsigned J = 0, Ee = CPEs.size(); J != Ee; ++J) {
1192 if (CPEs[J].RefCount == 0 && CPEs[J].CPEMI) {
1193 removeDeadCPEMI(CPEs[J].CPEMI);
1194 CPEs[J].CPEMI = nullptr;
1195 MadeChange = true;
1196 }
1197 }
1198 }
1199 return MadeChange;
1200}
1201
1202
1203
1204bool CSKYConstantIslands::isBBInRange(MachineInstr *MI,
1205 MachineBasicBlock *DestBB,
1206 unsigned MaxDisp) {
1207 unsigned BrOffset = getOffsetOf(MI);
1208 unsigned DestOffset = BBInfo[DestBB->getNumber()].Offset;
1209
1212 << " max delta=" << MaxDisp << " from " << getOffsetOf(MI)
1213 << " to " << DestOffset << " offset "
1214 << int(DestOffset - BrOffset) << "\t" << *MI);
1215
1216 if (BrOffset <= DestOffset) {
1217
1218 if (DestOffset - BrOffset <= MaxDisp)
1219 return true;
1220 } else {
1221 if (BrOffset - DestOffset <= MaxDisp)
1222 return true;
1223 }
1224 return false;
1225}
1226
1227
1228
1229bool CSKYConstantIslands::fixupImmediateBr(ImmBranch &Br) {
1230 MachineInstr *MI = Br.MI;
1232
1233
1234 if (isBBInRange(MI, DestBB, Br.MaxDisp))
1235 return false;
1236
1237 if (!Br.IsCond)
1238 return fixupUnconditionalBr(Br);
1239 return fixupConditionalBr(Br);
1240}
1241
1242
1243
1244
1245
1246bool CSKYConstantIslands::fixupUnconditionalBr(ImmBranch &Br) {
1247 MachineInstr *MI = Br.MI;
1248 MachineBasicBlock *MBB = MI->getParent();
1249
1252
1253
1254 Br.MaxDisp = ((1 << (26 - 1)) - 1) * 2;
1255 MI->setDesc(TII->get(CSKY::BSR32_BR));
1257 adjustBBOffsetsAfter(MBB);
1258 ++NumUBrFixed;
1259
1261
1262 return true;
1263}
1264
1265
1266
1267
1268bool CSKYConstantIslands::fixupConditionalBr(ImmBranch &Br) {
1269 MachineInstr *MI = Br.MI;
1271
1274 Cond.push_back(MI->getOperand(0));
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288 MachineBasicBlock *MBB = MI->getParent();
1289 MachineInstr *BMI = &MBB->back();
1291
1292 ++NumCBrFixed;
1293 if (BMI != MI) {
1296
1297
1298
1299
1300
1301
1302
1304 if (isBBInRange(MI, NewDest, Br.MaxDisp)) {
1306 dbgs() << " Invert Bcc condition and swap its destination with "
1307 << *BMI);
1309 MI->getOperand(MI->getNumExplicitOperands() - 1).setMBB(NewDest);
1310
1312 return true;
1313 }
1314 }
1315 }
1316
1317 if (NeedSplit) {
1318 splitBlockBeforeInstr(*MI);
1319
1320
1324
1325
1326
1327
1329 std::next(MBB->getIterator())->removeSuccessor(DestBB);
1330 }
1332
1334 << " also invert condition and change dest. to "
1336
1337
1338
1339
1341 .addReg(MI->getOperand(0).getReg())
1343
1349 ImmBranches.push_back(ImmBranch(&MBB->back(), MaxDisp, false, Br.UncondBr));
1350
1351
1353 MI->eraseFromParent();
1354 adjustBBOffsetsAfter(MBB);
1355 return true;
1356}
1357
1358
1360 return new CSKYConstantIslands();
1361}
1362
1364 "CSKY constant island placement and branch shortening pass",
1365 false, false)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
const TargetInstrInfo & TII
static unsigned getUnconditionalBrDisp(int Opc)
getUnconditionalBrDisp - Returns the maximum displacement that can fit in the specific unconditional ...
MachineBasicBlock MachineBasicBlock::iterator MBBI
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static bool bbHasFallthrough(MachineBasicBlock *MBB)
BBHasFallthrough - Return true if the specified basic block can fallthrough into the block immediatel...
Definition CSKYConstantIslandPass.cpp:425
static bool bbIsJumpedOver(MachineBasicBlock *MBB)
BBIsJumpedOver - Return true of the specified basic block's only predecessor unconditionally branches...
Definition CSKYConstantIslandPass.cpp:793
static bool compareMbbNumbers(const MachineBasicBlock *LHS, const MachineBasicBlock *RHS)
CompareMBBNumbers - Little predicate function to sort the WaterList by MBB ID.
Definition CSKYConstantIslandPass.cpp:605
#define LLVM_PREFERRED_TYPE(T)
\macro LLVM_PREFERRED_TYPE Adjust type of bit-field in debug info.
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
const SmallVectorImpl< MachineOperand > & Cond
This file defines the SmallSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
const CSKYInstrInfo * getInstrInfo() const override
FunctionPass class - This class is used to implement most global optimizations.
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
LLVM_ABI void transferSuccessors(MachineBasicBlock *FromMBB)
Transfers all the successors from MBB to this machine basic block (i.e., copies all the successors Fr...
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
void push_back(MachineInstr *MI)
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
void setAlignment(Align A)
Set alignment of the basic block.
LLVM_ABI void dump() const
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
SmallVectorImpl< MachineBasicBlock * >::iterator succ_iterator
MachineInstrBundleIterator< MachineInstr, true > reverse_iterator
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
Align getAlignment() const
Return alignment of the basic block.
MachineInstrBundleIterator< MachineInstr > iterator
Align getConstantPoolAlign() const
Return the alignment required by the whole constant pool, of which the first element must be aligned.
const std::vector< MachineConstantPoolEntry > & getConstants() const
bool isEmpty() const
isEmpty - Return true if this constant pool contains no constants.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
void ensureAlignment(Align A)
ensureAlignment - Make sure the function is at least A bytes aligned.
void push_back(MachineBasicBlock *MBB)
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
unsigned getNumBlockIDs() const
getNumBlockIDs - Return the number of MBB ID's allocated.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
MachineConstantPool * getConstantPool()
getConstantPool - Return the constant pool object for the current function.
void RenumberBlocks(MachineBasicBlock *MBBFrom=nullptr)
RenumberBlocks - This discards all of the MachineBasicBlock numbers and recomputes them.
const MachineBasicBlock & front() const
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
BasicBlockListType::const_iterator const_iterator
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addConstantPoolIndex(unsigned Idx, int Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
unsigned getNumOperands() const
Retuns the total number of operands.
LLVM_ABI unsigned getNumExplicitOperands() const
Returns the number of non-implicit operands.
bool isUnconditionalBranch(QueryType Type=AnyInBundle) const
Return true if this is a branch which always transfers control flow to some other block.
LLVM_ABI void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
const MachineOperand & getOperand(unsigned i) const
MachineBasicBlock * getMBB() const
bool isCPI() const
isCPI - Tests if this is a MO_ConstantPoolIndex operand.
void setMBB(MachineBasicBlock *MBB)
static MachineOperand CreateImm(int64_t Val)
void invalidateLiveness()
invalidateLiveness - Indicates that register liveness is no longer being tracked accurately.
bool erase(PtrType Ptr)
Remove pointer from the set.
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
virtual bool reverseBranchCondition(SmallVectorImpl< MachineOperand > &Cond) const
Reverses the branch condition of the specified condition list, returning false on success and true if...
virtual MachineBasicBlock * getBranchDestBlock(const MachineInstr &MI) const
virtual unsigned getInstSizeInBytes(const MachineInstr &MI) const
Returns the size in bytes of the specified MachineInstr, or ~0U when this function is not implemented...
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
This is an optimization pass for GlobalISel generic memory operations.
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
bool isAligned(Align Lhs, uint64_t SizeInBytes)
Checks that SizeInBytes is a multiple of the alignment.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
uint64_t offsetToAlignment(uint64_t Value, Align Alignment)
Returns the offset to the next integer (mod 2**64) that is greater than or equal to Value and is a mu...
auto lower_bound(R &&Range, T &&Value)
Provide wrappers to std::lower_bound which take ranges instead of having to pass begin/end explicitly...
FunctionPass * createCSKYConstantIslandPass()
Returns a pass that converts branches to long branches.
Definition CSKYConstantIslandPass.cpp:1359
DWARFExpression::Operation Op
unsigned Log2(Align A)
Returns the log2 of the alignment.
LLVM_ABI Printable printMBBReference(const MachineBasicBlock &MBB)
Prints a machine basic block reference.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
BasicBlockInfo - Information about the offset and size of a single basic block.
unsigned Size
Size - Size of the basic block in bytes.
unsigned postOffset(Align Alignment=Align(1)) const
Compute the offset immediately following this block.
unsigned Offset
Offset - Distance from the beginning of the function to the beginning of this basic block.