LLVM: lib/Target/Mips/MipsConstantIslandPass.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
38#include "llvm/Config/llvm-config.h"
50#include
51#include
52#include
53#include
54
55using namespace llvm;
56
57#define DEBUG_TYPE "mips-constant-islands"
58
59STATISTIC(NumCPEs, "Number of constpool entries");
60STATISTIC(NumSplit, "Number of uncond branches inserted");
61STATISTIC(NumCBrFixed, "Number of cond branches fixed");
62STATISTIC(NumUBrFixed, "Number of uncond branches fixed");
63
64
67 cl::desc("Align constant islands in code"));
68
69
70
72 "mips-constant-islands-small-offset",
74 cl::desc("Make small offsets be this amount for testing purposes"),
76
77
78
80 "mips-constant-islands-no-load-relaxation",
82 cl::desc("Don't relax loads to long loads - for testing purposes"),
84
86 switch (MI->getOpcode()) {
87 case Mips::Bimm16:
88 case Mips::BimmX16:
89 case Mips::Bteqz16:
90 case Mips::BteqzX16:
91 case Mips::Btnez16:
92 case Mips::BtnezX16:
93 case Mips::JalB16:
94 return 0;
95 case Mips::BeqzRxImm16:
96 case Mips::BeqzRxImmX16:
97 case Mips::BnezRxImm16:
98 case Mips::BnezRxImmX16:
99 return 1;
100 }
102}
103
105 switch (Opcode) {
106 case Mips::Bimm16:
107 case Mips::BimmX16:
108 return Mips::BimmX16;
109 case Mips::Bteqz16:
110 case Mips::BteqzX16:
111 return Mips::BteqzX16;
112 case Mips::Btnez16:
113 case Mips::BtnezX16:
114 return Mips::BtnezX16;
115 case Mips::JalB16:
116 return Mips::JalB16;
117 case Mips::BeqzRxImm16:
118 case Mips::BeqzRxImmX16:
119 return Mips::BeqzRxImmX16;
120 case Mips::BnezRxImm16:
121 case Mips::BnezRxImmX16:
122 return Mips::BnezRxImmX16;
123 }
125}
126
127
128
129
130
132 unsigned Bits, Scale;
133 switch (Opcode) {
134 case Mips::Bimm16:
135 Bits = 11;
136 Scale = 2;
137 break;
138 case Mips::BimmX16:
139 Bits = 16;
140 Scale = 2;
141 break;
142 case Mips::BeqzRxImm16:
143 Bits = 8;
144 Scale = 2;
145 break;
146 case Mips::BeqzRxImmX16:
147 Bits = 16;
148 Scale = 2;
149 break;
150 case Mips::BnezRxImm16:
151 Bits = 8;
152 Scale = 2;
153 break;
154 case Mips::BnezRxImmX16:
155 Bits = 16;
156 Scale = 2;
157 break;
158 case Mips::Bteqz16:
159 Bits = 8;
160 Scale = 2;
161 break;
162 case Mips::BteqzX16:
163 Bits = 16;
164 Scale = 2;
165 break;
166 case Mips::Btnez16:
167 Bits = 8;
168 Scale = 2;
169 break;
170 case Mips::BtnezX16:
171 Bits = 16;
172 Scale = 2;
173 break;
174 default:
176 }
177 unsigned MaxOffs = ((1 << (Bits-1))-1) * Scale;
178 return MaxOffs;
179}
180
181namespace {
182
185
186
187
188
189
190
191
192
193
194
195
196
197
199
200
201 struct BasicBlockInfo {
202
203
204
205
206
207
208
209
210
211 unsigned Offset = 0;
212
213
214
215
216
217
218 unsigned Size = 0;
219
220 BasicBlockInfo() = default;
221
222 unsigned postOffset() const { return Offset + Size; }
223 };
224
225 std::vector BBInfo;
226
227
228
229
230 std::vector<MachineBasicBlock*> WaterList;
231
232
233
234 SmallPtrSet<MachineBasicBlock *, 4> NewWaterList;
235
236 using water_iterator = std::vector<MachineBasicBlock *>::iterator;
237
238
239
240
241
242
243
244
245
246
247
248
249
250 struct CPUser {
251 MachineInstr *MI;
252 MachineInstr *CPEMI;
253 MachineBasicBlock *HighWaterMark;
254
255 private:
256 unsigned MaxDisp;
257 unsigned LongFormMaxDisp;
258
259 unsigned LongFormOpcode;
260
261 public:
262 bool NegOk;
263
264 CPUser(MachineInstr *mi, MachineInstr *cpemi, unsigned maxdisp,
265 bool neg,
266 unsigned longformmaxdisp, unsigned longformopcode)
267 : MI(mi), CPEMI(cpemi), MaxDisp(maxdisp),
268 LongFormMaxDisp(longformmaxdisp), LongFormOpcode(longformopcode),
269 NegOk(neg){
270 HighWaterMark = CPEMI->getParent();
271 }
272
273
274 unsigned getMaxDisp() const {
277 return xMaxDisp;
278 }
279
280 void setMaxDisp(unsigned val) {
281 MaxDisp = val;
282 }
283
284 unsigned getLongFormMaxDisp() const {
285 return LongFormMaxDisp;
286 }
287
288 unsigned getLongFormOpcode() const {
289 return LongFormOpcode;
290 }
291 };
292
293
294
295 std::vector CPUsers;
296
297
298
299
300 struct CPEntry {
301 MachineInstr *CPEMI;
302 unsigned CPI;
303 unsigned RefCount;
304
305 CPEntry(MachineInstr *cpemi, unsigned cpi, unsigned rc = 0)
306 : CPEMI(cpemi), CPI(cpi), RefCount(rc) {}
307 };
308
309
310
311
312
313
314 std::vector<std::vector> CPEntries;
315
316
317
318
319
320 struct ImmBranch {
321 MachineInstr *MI;
322 unsigned MaxDisp : 31;
324 unsigned isCond : 1;
325 int UncondBr;
326
327 ImmBranch(MachineInstr *mi, unsigned maxdisp, bool cond, int ubr)
328 : MI(mi), MaxDisp(maxdisp), isCond(cond), UncondBr(ubr) {}
329 };
330
331
332
333 std::vector ImmBranches;
334
335
336
337 bool HasFarJump;
338
339 const MipsSubtarget *STI = nullptr;
340 const Mips16InstrInfo *TII;
341 MipsFunctionInfo *MFI;
342 MachineFunction *MF = nullptr;
343 MachineConstantPool *MCP = nullptr;
344
345 unsigned PICLabelUId;
346 bool PrescannedForConstants = false;
347
348 void initPICLabelUId(unsigned UId) {
349 PICLabelUId = UId;
350 }
351
352 unsigned createPICLabelUId() {
353 return PICLabelUId++;
354 }
355
356 public:
357 static char ID;
358
359 MipsConstantIslands() : MachineFunctionPass(ID) {}
360
361 StringRef getPassName() const override { return "Mips Constant Islands"; }
362
363 bool runOnMachineFunction(MachineFunction &F) override;
364
365 MachineFunctionProperties getRequiredProperties() const override {
366 return MachineFunctionProperties().setNoVRegs();
367 }
368
369 void doInitialPlacement(std::vector<MachineInstr*> &CPEMIs);
370 CPEntry *findConstPoolEntry(unsigned CPI, const MachineInstr *CPEMI);
371 Align getCPEAlign(const MachineInstr &CPEMI);
372 void initializeFunctionInfo(const std::vector<MachineInstr*> &CPEMIs);
373 unsigned getOffsetOf(MachineInstr *MI) const;
374 unsigned getUserOffset(CPUser&) const;
375 void dumpBBs();
376
377 bool isOffsetInRange(unsigned UserOffset, unsigned TrialOffset,
378 unsigned Disp, bool NegativeOK);
379 bool isOffsetInRange(unsigned UserOffset, unsigned TrialOffset,
380 const CPUser &U);
381
382 void computeBlockSize(MachineBasicBlock *MBB);
383 MachineBasicBlock *splitBlockBeforeInstr(MachineInstr &MI);
384 void updateForInsertedWaterBlock(MachineBasicBlock *NewBB);
385 void adjustBBOffsetsAfter(MachineBasicBlock *BB);
386 bool decrementCPEReferenceCount(unsigned CPI, MachineInstr* CPEMI);
387 int findInRangeCPEntry(CPUser& U, unsigned UserOffset);
388 int findLongFormInRangeCPEntry(CPUser& U, unsigned UserOffset);
389 bool findAvailableWater(CPUser&U, unsigned UserOffset,
390 water_iterator &WaterIter);
391 void createNewWater(unsigned CPUserIndex, unsigned UserOffset,
392 MachineBasicBlock *&NewMBB);
393 bool handleConstantPoolUser(unsigned CPUserIndex);
394 void removeDeadCPEMI(MachineInstr *CPEMI);
395 bool removeUnusedCPEntries();
396 bool isCPEntryInRange(MachineInstr *MI, unsigned UserOffset,
397 MachineInstr *CPEMI, unsigned Disp, bool NegOk,
398 bool DoDump = false);
399 bool isWaterInRange(unsigned UserOffset, MachineBasicBlock *Water,
400 CPUser &U, unsigned &Growth);
401 bool isBBInRange(MachineInstr *MI, MachineBasicBlock *BB, unsigned Disp);
402 bool fixupImmediateBr(ImmBranch &Br);
403 bool fixupConditionalBr(ImmBranch &Br);
404 bool fixupUnconditionalBr(ImmBranch &Br);
405
406 void prescanForConstants();
407 };
408
409}
410
411char MipsConstantIslands::ID = 0;
412
413bool MipsConstantIslands::isOffsetInRange
414 (unsigned UserOffset, unsigned TrialOffset,
415 const CPUser &U) {
416 return isOffsetInRange(UserOffset, TrialOffset,
418}
419
420#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
421
423 for (unsigned J = 0, E = BBInfo.size(); J !=E; ++J) {
424 const BasicBlockInfo &BBI = BBInfo[J];
426 << format(" size=%#x\n", BBInfo[J].Size);
427 }
428}
429#endif
430
431bool MipsConstantIslands::runOnMachineFunction(MachineFunction &mf) {
432
433
434 MF = &mf;
437 LLVM_DEBUG(dbgs() << "constant island machine function "
438 << "\n");
440 return false;
441 }
443 MFI = MF->getInfo();
445 << "\n");
446
447
448
449
450 if (!PrescannedForConstants) prescanForConstants();
451
452 HasFarJump = false;
453
455
456
457
459
460 bool MadeChange = false;
461
462
463
464 std::vector<MachineInstr*> CPEMIs;
466 doInitialPlacement(CPEMIs);
467
468
469 initPICLabelUId(CPEMIs.size());
470
471
472
473
474 initializeFunctionInfo(CPEMIs);
475 CPEMIs.clear();
477
478
479 MadeChange |= removeUnusedCPEntries();
480
481
482
483 unsigned NoCPIters = 0, NoBRIters = 0;
484 (void)NoBRIters;
485 while (true) {
486 LLVM_DEBUG(dbgs() << "Beginning CP iteration #" << NoCPIters << '\n');
487 bool CPChange = false;
488 for (unsigned i = 0, e = CPUsers.size(); i != e; ++i)
489 CPChange |= handleConstantPoolUser(i);
490 if (CPChange && ++NoCPIters > 30)
493
494
495
496 NewWaterList.clear();
497
498 LLVM_DEBUG(dbgs() << "Beginning BR iteration #" << NoBRIters << '\n');
499 bool BRChange = false;
500 for (unsigned i = 0, e = ImmBranches.size(); i != e; ++i)
501 BRChange |= fixupImmediateBr(ImmBranches[i]);
502 if (BRChange && ++NoBRIters > 30)
505 if (!CPChange && !BRChange)
506 break;
507 MadeChange = true;
508 }
509
511
512 BBInfo.clear();
513 WaterList.clear();
514 CPUsers.clear();
515 CPEntries.clear();
516 ImmBranches.clear();
517 return MadeChange;
518}
519
520
521
522void
523MipsConstantIslands::doInitialPlacement(std::vector<MachineInstr*> &CPEMIs) {
524
527
528
530
531
532
534
535
536
538
539
540
541
542
544 BB->end());
545
546
547
548 const std::vector &CPs = MCP->getConstants();
549
551 for (unsigned i = 0, e = CPs.size(); i != e; ++i) {
552 unsigned Size = CPs[i].getSizeInBytes(TD);
553 assert(Size >= 4 && "Too small constant pool entry");
554 Align Alignment = CPs[i].getAlign();
555
556
557 assert(isAligned(Alignment, Size) && "CP Entry not multiple of 4 bytes!");
558
559
560 unsigned LogAlign = Log2(Alignment);
562
563 MachineInstr *CPEMI =
566
567 CPEMIs.push_back(CPEMI);
568
569
570
571 for (unsigned a = LogAlign + 1; a <= Log2(MaxAlign); ++a)
572 if (InsPoint[a] == InsAt)
573 InsPoint[a] = CPEMI;
574
575 CPEntries.emplace_back(1, CPEntry(CPEMI, i));
576 ++NumCPEs;
577 LLVM_DEBUG(dbgs() << "Moved CPI#" << i << " to end of function, size = "
578 << Size << ", align = " << Alignment.value() << '\n');
579 }
581}
582
583
584
586
588
589 if (std::next(MBBI) == MBB->getParent()->end())
590 return false;
591
594}
595
596
597
598MipsConstantIslands::CPEntry
599*MipsConstantIslands::findConstPoolEntry(unsigned CPI,
600 const MachineInstr *CPEMI) {
601 std::vector &CPEs = CPEntries[CPI];
602
603
604 for (CPEntry &CPE : CPEs) {
605 if (CPE.CPEMI == CPEMI)
606 return &CPE;
607 }
608 return nullptr;
609}
610
611
612
613Align MipsConstantIslands::getCPEAlign(const MachineInstr &CPEMI) {
615
616
619
621 assert(CPI < MCP->getConstants().size() && "Invalid constant pool index.");
623}
624
625
626
627
628void MipsConstantIslands::
629initializeFunctionInfo(const std::vector<MachineInstr*> &CPEMIs) {
630 BBInfo.clear();
632
633
634
635
636
637 for (MachineBasicBlock &MBB : *MF)
638 computeBlockSize(&MBB);
639
640
641 adjustBBOffsetsAfter(&MF->front());
642
643
644 for (MachineBasicBlock &MBB : *MF) {
645
646
648 WaterList.push_back(&MBB);
649 for (MachineInstr &MI : MBB) {
650 if (MI.isDebugInstr())
651 continue;
652
654 if (MI.isBranch()) {
655 bool isCond = false;
656 unsigned Bits = 0;
657 unsigned Scale = 1;
658 int UOpc = Opc;
659 switch (Opc) {
660 default:
661 continue;
662 case Mips::Bimm16:
664 Scale = 2;
665 isCond = false;
666 break;
667 case Mips::BimmX16:
669 Scale = 2;
670 isCond = false;
671 break;
672 case Mips::BeqzRxImm16:
673 UOpc=Mips::Bimm16;
675 Scale = 2;
676 isCond = true;
677 break;
678 case Mips::BeqzRxImmX16:
679 UOpc=Mips::Bimm16;
681 Scale = 2;
682 isCond = true;
683 break;
684 case Mips::BnezRxImm16:
685 UOpc=Mips::Bimm16;
687 Scale = 2;
688 isCond = true;
689 break;
690 case Mips::BnezRxImmX16:
691 UOpc=Mips::Bimm16;
693 Scale = 2;
694 isCond = true;
695 break;
696 case Mips::Bteqz16:
697 UOpc=Mips::Bimm16;
699 Scale = 2;
700 isCond = true;
701 break;
702 case Mips::BteqzX16:
703 UOpc=Mips::Bimm16;
705 Scale = 2;
706 isCond = true;
707 break;
708 case Mips::Btnez16:
709 UOpc=Mips::Bimm16;
711 Scale = 2;
712 isCond = true;
713 break;
714 case Mips::BtnezX16:
715 UOpc=Mips::Bimm16;
717 Scale = 2;
718 isCond = true;
719 break;
720 }
721
722 unsigned MaxOffs = ((1 << (Bits-1))-1) * Scale;
723 ImmBranches.push_back(ImmBranch(&MI, MaxOffs, isCond, UOpc));
724 }
725
726 if (Opc == Mips::CONSTPOOL_ENTRY)
727 continue;
728
729
730 for (const MachineOperand &MO : MI.operands())
731 if (MO.isCPI()) {
732
733
734
735
736 unsigned Bits = 0;
737 unsigned Scale = 1;
738 bool NegOk = false;
739 unsigned LongFormBits = 0;
740 unsigned LongFormScale = 0;
741 unsigned LongFormOpcode = 0;
742 switch (Opc) {
743 default:
744 llvm_unreachable("Unknown addressing mode for CP reference!");
745 case Mips::LwRxPcTcp16:
747 Scale = 4;
748 LongFormOpcode = Mips::LwRxPcTcpX16;
749 LongFormBits = 14;
750 LongFormScale = 1;
751 break;
752 case Mips::LwRxPcTcpX16:
754 Scale = 1;
755 NegOk = true;
756 break;
757 }
758
759 unsigned CPI = MO.getIndex();
760 MachineInstr *CPEMI = CPEMIs[CPI];
761 unsigned MaxOffs = ((1 << Bits)-1) * Scale;
762 unsigned LongFormMaxOffs = ((1 << LongFormBits)-1) * LongFormScale;
763 CPUsers.push_back(CPUser(&MI, CPEMI, MaxOffs, NegOk, LongFormMaxOffs,
764 LongFormOpcode));
765
766
767 CPEntry *CPE = findConstPoolEntry(CPI, CPEMI);
768 assert(CPE && "Cannot find a corresponding CPEntry!");
769 CPE->RefCount++;
770
771
772
773 break;
774 }
775 }
776 }
777}
778
779
780
781void MipsConstantIslands::computeBlockSize(MachineBasicBlock *MBB) {
782 BasicBlockInfo &BBI = BBInfo[MBB->getNumber()];
783 BBI.Size = 0;
784
785 for (const MachineInstr &MI : *MBB)
787}
788
789
790
791
792unsigned MipsConstantIslands::getOffsetOf(MachineInstr *MI) const {
793 MachineBasicBlock *MBB = MI->getParent();
794
795
796
797
799
800
802 assert(I != MBB->end() && "Didn't find MI in its own basic block?");
804 }
806}
807
808
809
812 return LHS->getNumber() < RHS->getNumber();
813}
814
815
816
817
818void MipsConstantIslands::updateForInsertedWaterBlock
819 (MachineBasicBlock *NewBB) {
820
822
823
824
825 BBInfo.insert(BBInfo.begin() + NewBB->getNumber(), BasicBlockInfo());
826
827
828
830 WaterList.insert(IP, NewBB);
831}
832
833unsigned MipsConstantIslands::getUserOffset(CPUser &U) const {
834 return getOffsetOf(U.MI);
835}
836
837
838
839
840MachineBasicBlock *
841MipsConstantIslands::splitBlockBeforeInstr(MachineInstr &MI) {
842 MachineBasicBlock *OrigBB = MI.getParent();
843
844
845 MachineBasicBlock *NewBB =
846 MF->CreateMachineBasicBlock(OrigBB->getBasicBlock());
848 MF->insert(MBBI, NewBB);
849
850
851 NewBB->splice(NewBB->end(), OrigBB, MI, OrigBB->end());
852
853
854
855
856
858 ++NumSplit;
859
860
862
863
865
866
867
868
869 MF->RenumberBlocks(NewBB);
870
871
872
873 BBInfo.insert(BBInfo.begin() + NewBB->getNumber(), BasicBlockInfo());
874
875
876
877
878
880 MachineBasicBlock* WaterBB = *IP;
881 if (WaterBB == OrigBB)
882 WaterList.insert(std::next(IP), NewBB);
883 else
884 WaterList.insert(IP, OrigBB);
885 NewWaterList.insert(OrigBB);
886
887
888
889
890
891
892 computeBlockSize(OrigBB);
893
894
895
896 computeBlockSize(NewBB);
897
898
899 adjustBBOffsetsAfter(OrigBB);
900
901 return NewBB;
902}
903
904
905
906
907bool MipsConstantIslands::isOffsetInRange(unsigned UserOffset,
908 unsigned TrialOffset, unsigned MaxDisp,
909 bool NegativeOK) {
910 if (UserOffset <= TrialOffset) {
911
912 if (TrialOffset - UserOffset <= MaxDisp)
913 return true;
914 } else if (NegativeOK) {
915 if (UserOffset - TrialOffset <= MaxDisp)
916 return true;
917 }
918 return false;
919}
920
921
922
923
924
925bool MipsConstantIslands::isWaterInRange(unsigned UserOffset,
926 MachineBasicBlock* Water, CPUser &U,
927 unsigned &Growth) {
928 unsigned CPEOffset = BBInfo[Water->getNumber()].postOffset();
929 unsigned NextBlockOffset;
930 Align NextBlockAlignment;
932 if (NextBlock == MF->end()) {
933 NextBlockOffset = BBInfo[Water->getNumber()].postOffset();
934 NextBlockAlignment = Align(1);
935 } else {
936 NextBlockOffset = BBInfo[NextBlock->getNumber()].Offset;
937 NextBlockAlignment = NextBlock->getAlignment();
938 }
939 unsigned Size = U.CPEMI->getOperand(2).getImm();
940 unsigned CPEEnd = CPEOffset + Size;
941
942
943
944
945 if (CPEEnd > NextBlockOffset) {
946 Growth = CPEEnd - NextBlockOffset;
947
948
950
951
952
953
954 if (CPEOffset < UserOffset)
955 UserOffset += Growth;
956 } else
957
958 Growth = 0;
959
960 return isOffsetInRange(UserOffset, CPEOffset, U);
961}
962
963
964
965bool MipsConstantIslands::isCPEntryInRange
966 (MachineInstr *MI, unsigned UserOffset,
967 MachineInstr *CPEMI, unsigned MaxDisp,
968 bool NegOk, bool DoDump) {
969 unsigned CPEOffset = getOffsetOf(CPEMI);
970
971 if (DoDump) {
973 unsigned Block = MI->getParent()->getNumber();
974 const BasicBlockInfo &BBI = BBInfo[Block];
976 << " max delta=" << MaxDisp
977 << format(" insn address=%#x", UserOffset) << " in "
980 << format("CPE address=%#x offset=%+d: ", CPEOffset,
981 int(CPEOffset - UserOffset));
982 });
983 }
984
985 return isOffsetInRange(UserOffset, CPEOffset, MaxDisp, NegOk);
986}
987
988#ifndef NDEBUG
989
990
992 if (MBB->pred_size() != 1 || MBB->succ_size() != 1)
993 return false;
997 if (PredMI->getOpcode() == Mips::Bimm16)
999 return false;
1000}
1001#endif
1002
1003void MipsConstantIslands::adjustBBOffsetsAfter(MachineBasicBlock *BB) {
1004 unsigned BBNum = BB->getNumber();
1005 for(unsigned i = BBNum + 1, e = MF->getNumBlockIDs(); i < e; ++i) {
1006
1007
1008 unsigned Offset = BBInfo[i - 1].Offset + BBInfo[i - 1].Size;
1009 BBInfo[i].Offset = Offset;
1010 }
1011}
1012
1013
1014
1015
1016
1017bool MipsConstantIslands::decrementCPEReferenceCount(unsigned CPI,
1018 MachineInstr *CPEMI) {
1019
1020 CPEntry *CPE = findConstPoolEntry(CPI, CPEMI);
1021 assert(CPE && "Unexpected!");
1022 if (--CPE->RefCount == 0) {
1023 removeDeadCPEMI(CPEMI);
1024 CPE->CPEMI = nullptr;
1025 --NumCPEs;
1026 return true;
1027 }
1028 return false;
1029}
1030
1031
1032
1033
1034
1035
1036
1037int MipsConstantIslands::findInRangeCPEntry(CPUser& U, unsigned UserOffset)
1038{
1039 MachineInstr *UserMI = U.MI;
1040 MachineInstr *CPEMI = U.CPEMI;
1041
1042
1043 if (isCPEntryInRange(UserMI, UserOffset, CPEMI, U.getMaxDisp(), U.NegOk,
1044 true)) {
1046 return 1;
1047 }
1048
1049
1051 std::vector &CPEs = CPEntries[CPI];
1052 for (CPEntry &CPE : CPEs) {
1053
1054 if (CPE.CPEMI == CPEMI)
1055 continue;
1056
1057 if (CPE.CPEMI == nullptr)
1058 continue;
1059 if (isCPEntryInRange(UserMI, UserOffset, CPE.CPEMI, U.getMaxDisp(),
1060 U.NegOk)) {
1061 LLVM_DEBUG(dbgs() << "Replacing CPE#" << CPI << " with CPE#" << CPE.CPI
1062 << "\n");
1063
1064 U.CPEMI = CPE.CPEMI;
1065
1066 for (MachineOperand &MO : UserMI->operands())
1067 if (MO.isCPI()) {
1068 MO.setIndex(CPE.CPI);
1069 break;
1070 }
1071
1072 CPE.RefCount++;
1073
1074
1075 return decrementCPEReferenceCount(CPI, CPEMI) ? 2 : 1;
1076 }
1077 }
1078 return 0;
1079}
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089int MipsConstantIslands::findLongFormInRangeCPEntry
1090 (CPUser& U, unsigned UserOffset)
1091{
1092 MachineInstr *UserMI = U.MI;
1093 MachineInstr *CPEMI = U.CPEMI;
1094
1095
1096 if (isCPEntryInRange(UserMI, UserOffset, CPEMI,
1097 U.getLongFormMaxDisp(), U.NegOk,
1098 true)) {
1101 U.setMaxDisp(U.getLongFormMaxDisp());
1102 return 2;
1103 }
1104
1105
1107 std::vector &CPEs = CPEntries[CPI];
1108 for (CPEntry &CPE : CPEs) {
1109
1110 if (CPE.CPEMI == CPEMI)
1111 continue;
1112
1113 if (CPE.CPEMI == nullptr)
1114 continue;
1115 if (isCPEntryInRange(UserMI, UserOffset, CPE.CPEMI, U.getLongFormMaxDisp(),
1116 U.NegOk)) {
1117 LLVM_DEBUG(dbgs() << "Replacing CPE#" << CPI << " with CPE#" << CPE.CPI
1118 << "\n");
1119
1120 U.CPEMI = CPE.CPEMI;
1121
1122 for (MachineOperand &MO : UserMI->operands())
1123 if (MO.isCPI()) {
1124 MO.setIndex(CPE.CPI);
1125 break;
1126 }
1127
1128 CPE.RefCount++;
1129
1130
1131 return decrementCPEReferenceCount(CPI, CPEMI) ? 2 : 1;
1132 }
1133 }
1134 return 0;
1135}
1136
1137
1138
1140 switch (Opc) {
1141 case Mips::Bimm16:
1142 return ((1<<10)-1)*2;
1143 case Mips::BimmX16:
1144 return ((1<<16)-1)*2;
1145 default:
1146 break;
1147 }
1148 return ((1<<16)-1)*2;
1149}
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159bool MipsConstantIslands::findAvailableWater(CPUser &U, unsigned UserOffset,
1160 water_iterator &WaterIter) {
1161 if (WaterList.empty())
1162 return false;
1163
1164 unsigned BestGrowth = ~0u;
1165 for (water_iterator IP = std::prev(WaterList.end()), B = WaterList.begin();;
1166 --IP) {
1167 MachineBasicBlock* WaterBB = *IP;
1168
1169
1170
1171
1172
1173
1174
1175
1176 unsigned Growth;
1177 if (isWaterInRange(UserOffset, WaterBB, U, Growth) &&
1178 (WaterBB->getNumber() < U.HighWaterMark->getNumber() ||
1179 NewWaterList.count(WaterBB)) && Growth < BestGrowth) {
1180
1181 BestGrowth = Growth;
1182 WaterIter = IP;
1184 << " Growth=" << Growth << '\n');
1185
1186
1187 if (BestGrowth == 0)
1188 return true;
1189 }
1190 if (IP == B)
1191 break;
1192 }
1193 return BestGrowth != ~0u;
1194}
1195
1196
1197
1198
1199
1200
1201
1202
1203void MipsConstantIslands::createNewWater(unsigned CPUserIndex,
1204 unsigned UserOffset,
1205 MachineBasicBlock *&NewMBB) {
1206 CPUser &U = CPUsers[CPUserIndex];
1207 MachineInstr *UserMI = U.MI;
1208 MachineInstr *CPEMI = U.CPEMI;
1209 MachineBasicBlock *UserMBB = UserMI->getParent();
1210 const BasicBlockInfo &UserBBI = BBInfo[UserMBB->getNumber()];
1211
1212
1213
1215
1216 unsigned Delta = 2;
1217
1218 unsigned CPEOffset = UserBBI.postOffset() + Delta;
1219
1220 if (isOffsetInRange(UserOffset, CPEOffset, U)) {
1222 << format(", expected CPE offset %#x\n", CPEOffset));
1224
1225
1226
1227
1228
1229 int UncondBr = Mips::Bimm16;
1232 ImmBranches.push_back(ImmBranch(&UserMBB->back(),
1233 MaxDisp, false, UncondBr));
1234 BBInfo[UserMBB->getNumber()].Size += Delta;
1235 adjustBBOffsetsAfter(UserMBB);
1236 return;
1237 }
1238 }
1239
1240
1241
1242
1243
1244
1245 const Align Align = MF->getAlignment();
1246 unsigned BaseInsertOffset = UserOffset + U.getMaxDisp();
1248 BaseInsertOffset));
1249
1250
1251
1252
1253 BaseInsertOffset -= 4;
1254
1256 << " la=" << Log2(Align) << '\n');
1257
1258
1259
1260
1261
1262 if (BaseInsertOffset + 8 >= UserBBI.postOffset()) {
1263 BaseInsertOffset = UserBBI.postOffset() - 8;
1265 }
1266 unsigned EndInsertOffset = BaseInsertOffset + 4 +
1269 ++MI;
1270 unsigned CPUIndex = CPUserIndex+1;
1271 unsigned NumCPUsers = CPUsers.size();
1272
1274 Offset < BaseInsertOffset;
1276 assert(MI != UserMBB->end() && "Fell off end of block");
1277 if (CPUIndex < NumCPUsers && CPUsers[CPUIndex].MI == MI) {
1278 CPUser &U = CPUsers[CPUIndex];
1279 if (!isOffsetInRange(Offset, EndInsertOffset, U)) {
1280
1281 BaseInsertOffset -= Align.value();
1282 EndInsertOffset -= Align.value();
1283 }
1284
1285
1286
1287
1288 EndInsertOffset += U.CPEMI->getOperand(2).getImm();
1289 CPUIndex++;
1290 }
1291 }
1292
1293 NewMBB = splitBlockBeforeInstr(*--MI);
1294}
1295
1296
1297
1298
1299
1300bool MipsConstantIslands::handleConstantPoolUser(unsigned CPUserIndex) {
1301 CPUser &U = CPUsers[CPUserIndex];
1302 MachineInstr *UserMI = U.MI;
1303 MachineInstr *CPEMI = U.CPEMI;
1306
1307 unsigned UserOffset = getUserOffset(U);
1308
1309
1310
1311 int result = findInRangeCPEntry(U, UserOffset);
1312 if (result==1) return false;
1313 else if (result==2) return true;
1314
1315
1316 MachineBasicBlock *NewIsland = MF->CreateMachineBasicBlock();
1317 MachineBasicBlock *NewMBB;
1318 water_iterator IP;
1319 if (findAvailableWater(U, UserOffset, IP)) {
1321 MachineBasicBlock *WaterBB = *IP;
1322
1323
1324
1325
1326 if (NewWaterList.erase(WaterBB))
1327 NewWaterList.insert(NewIsland);
1328
1329
1331 } else {
1332
1333
1334
1336 result = findLongFormInRangeCPEntry(U, UserOffset);
1337 if (result != 0) return true;
1338 }
1340 createNewWater(CPUserIndex, UserOffset, NewMBB);
1341
1342
1343
1344
1345
1346
1347 MachineBasicBlock *WaterBB = &*--NewMBB->getIterator();
1348 IP = llvm::find(WaterList, WaterBB);
1349 if (IP != WaterList.end())
1350 NewWaterList.erase(WaterBB);
1351
1352
1353 NewWaterList.insert(NewIsland);
1354 }
1355
1356
1357
1358
1359
1360 if (IP != WaterList.end())
1361 WaterList.erase(IP);
1362
1363
1364 MF->insert(NewMBB->getIterator(), NewIsland);
1365
1366
1367 updateForInsertedWaterBlock(NewIsland);
1368
1369
1370 decrementCPEReferenceCount(CPI, CPEMI);
1371
1372
1373
1374 unsigned ID = createPICLabelUId();
1375
1376
1377
1378 U.HighWaterMark = NewIsland;
1381 CPEntries[CPI].push_back(CPEntry(U.CPEMI, ID, 1));
1382 ++NumCPEs;
1383
1384
1386
1387
1389 adjustBBOffsetsAfter(&*--NewIsland->getIterator());
1390
1391
1392 for (MachineOperand &MO : UserMI->operands())
1393 if (MO.isCPI()) {
1394 MO.setIndex(ID);
1395 break;
1396 }
1397
1399 dbgs() << " Moved CPE to #" << ID << " CPI=" << CPI
1400 << format(" offset=%#x\n", BBInfo[NewIsland->getNumber()].Offset));
1401
1402 return true;
1403}
1404
1405
1406
1407void MipsConstantIslands::removeDeadCPEMI(MachineInstr *CPEMI) {
1408 MachineBasicBlock *CPEBB = CPEMI->getParent();
1412
1413 if (CPEBB->empty()) {
1414 BBInfo[CPEBB->getNumber()].Size = 0;
1415
1416
1418 } else {
1419
1421 }
1422
1423 adjustBBOffsetsAfter(CPEBB);
1424
1425
1426
1428
1429}
1430
1431
1432
1433bool MipsConstantIslands::removeUnusedCPEntries() {
1434 unsigned MadeChange = false;
1435 for (std::vector &CPEs : CPEntries) {
1436 for (CPEntry &CPE : CPEs) {
1437 if (CPE.RefCount == 0 && CPE.CPEMI) {
1438 removeDeadCPEMI(CPE.CPEMI);
1439 CPE.CPEMI = nullptr;
1440 MadeChange = true;
1441 }
1442 }
1443 }
1444 return MadeChange;
1445}
1446
1447
1448
1449bool MipsConstantIslands::isBBInRange
1450 (MachineInstr *MI,MachineBasicBlock *DestBB, unsigned MaxDisp) {
1451 unsigned PCAdj = 4;
1452 unsigned BrOffset = getOffsetOf(MI) + PCAdj;
1453 unsigned DestOffset = BBInfo[DestBB->getNumber()].Offset;
1454
1457 << " max delta=" << MaxDisp << " from " << getOffsetOf(MI)
1458 << " to " << DestOffset << " offset "
1459 << int(DestOffset - BrOffset) << "\t" << *MI);
1460
1461 if (BrOffset <= DestOffset) {
1462
1463 if (DestOffset-BrOffset <= MaxDisp)
1464 return true;
1465 } else {
1466 if (BrOffset-DestOffset <= MaxDisp)
1467 return true;
1468 }
1469 return false;
1470}
1471
1472
1473
1474bool MipsConstantIslands::fixupImmediateBr(ImmBranch &Br) {
1475 MachineInstr *MI = Br.MI;
1477 MachineBasicBlock *DestBB = MI->getOperand(TargetOperand).getMBB();
1478
1479
1480 if (isBBInRange(MI, DestBB, Br.MaxDisp))
1481 return false;
1482
1483 if (!Br.isCond)
1484 return fixupUnconditionalBr(Br);
1485 return fixupConditionalBr(Br);
1486}
1487
1488
1489
1490
1491
1492bool
1493MipsConstantIslands::fixupUnconditionalBr(ImmBranch &Br) {
1494 MachineInstr *MI = Br.MI;
1495 MachineBasicBlock *MBB = MI->getParent();
1496 MachineBasicBlock *DestBB = MI->getOperand(0).getMBB();
1497
1498 unsigned BimmX16MaxDisp = ((1 << 16)-1) * 2;
1499 if (isBBInRange(MI, DestBB, BimmX16MaxDisp)) {
1500 Br.MaxDisp = BimmX16MaxDisp;
1501 MI->setDesc(TII->get(Mips::BimmX16));
1502 }
1503 else {
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1516 Br.MaxDisp = ((1<<24)-1) * 2;
1517 MI->setDesc(TII->get(Mips::JalB16));
1518 }
1520 adjustBBOffsetsAfter(MBB);
1521 HasFarJump = true;
1522 ++NumUBrFixed;
1523
1525
1526 return true;
1527}
1528
1529
1530
1531
1532bool
1533MipsConstantIslands::fixupConditionalBr(ImmBranch &Br) {
1534 MachineInstr *MI = Br.MI;
1536 MachineBasicBlock *DestBB = MI->getOperand(TargetOperand).getMBB();
1537 unsigned Opcode = MI->getOpcode();
1540
1541
1542 if (isBBInRange(MI, DestBB, LongFormMaxOff)) {
1543 Br.MaxDisp = LongFormMaxOff;
1544 MI->setDesc(TII->get(LongFormOpcode));
1545 return true;
1546 }
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559 MachineBasicBlock *MBB = MI->getParent();
1560 MachineInstr *BMI = &MBB->back();
1562 unsigned OppositeBranchOpcode = TII->getOppositeBranchOpc(Opcode);
1563
1564 ++NumCBrFixed;
1565 if (BMI != MI) {
1568
1569
1570
1571
1572
1573
1574
1576 MachineBasicBlock *NewDest =
1578 if (isBBInRange(MI, NewDest, Br.MaxDisp)) {
1580 dbgs() << " Invert Bcc condition and swap its destination with "
1581 << *BMI);
1582 MI->setDesc(TII->get(OppositeBranchOpcode));
1584 MI->getOperand(TargetOperand).setMBB(NewDest);
1585 return true;
1586 }
1587 }
1588 }
1589
1590 if (NeedSplit) {
1591 splitBlockBeforeInstr(*MI);
1592
1593
1597
1598 }
1600
1602 << " also invert condition and change dest. to "
1604
1605
1606
1607 if (MI->getNumExplicitOperands() == 2) {
1609 .addReg(MI->getOperand(0).getReg())
1611 } else {
1614 }
1620 ImmBranches.push_back(ImmBranch(&MBB->back(), MaxDisp, false, Br.UncondBr));
1621
1622
1624 MI->eraseFromParent();
1625 adjustBBOffsetsAfter(MBB);
1626 return true;
1627}
1628
1629void MipsConstantIslands::prescanForConstants() {
1630 for (MachineBasicBlock &B : *MF) {
1631 for (MachineInstr &MI : B) {
1632 switch (MI.getDesc().getOpcode()) {
1633 case Mips::LwConstant32: {
1634 PrescannedForConstants = true;
1635 LLVM_DEBUG(dbgs() << "constant island constant " << MI << "\n");
1636 LLVM_DEBUG(dbgs() << "num operands " << MI.getNumOperands() << "\n");
1637 MachineOperand &Literal = MI.getOperand(1);
1639 int64_t V = Literal.getImm();
1641 Type *Int32Ty = Type::getInt32Ty(MF->getFunction().getContext());
1644 MI.getOperand(2).ChangeToImmediate(index);
1645 LLVM_DEBUG(dbgs() << "constant island constant " << MI << "\n");
1646 MI.setDesc(TII->get(Mips::LwRxPcTcp16));
1647 MI.removeOperand(1);
1648 MI.removeOperand(1);
1650 }
1651 break;
1652 }
1653 default:
1654 break;
1655 }
1656 }
1657 }
1658}
1659
1660
1662 return new MipsConstantIslands();
1663}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
const TargetInstrInfo & TII
static bool CompareMBBNumbers(const MachineBasicBlock *LHS, const MachineBasicBlock *RHS)
CompareMBBNumbers - Little predicate function to sort the WaterList by MBB ID.
static unsigned getUnconditionalBrDisp(int Opc)
getUnconditionalBrDisp - Returns the maximum displacement that can fit in the specific unconditional ...
static bool BBIsJumpedOver(MachineBasicBlock *MBB)
BBIsJumpedOver - Return true of the specified basic block's only predecessor unconditionally branches...
MachineBasicBlock MachineBasicBlock::iterator MBBI
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#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 ...
static unsigned int longformBranchOpcode(unsigned int Opcode)
Definition MipsConstantIslandPass.cpp:104
static unsigned int branchMaxOffsets(unsigned int Opcode)
Definition MipsConstantIslandPass.cpp:131
static cl::opt< bool > NoLoadRelaxation("mips-constant-islands-no-load-relaxation", cl::init(false), cl::desc("Don't relax loads to long loads - for testing purposes"), cl::Hidden)
static cl::opt< int > ConstantIslandsSmallOffset("mips-constant-islands-small-offset", cl::init(0), cl::desc("Make small offsets be this amount for testing purposes"), cl::Hidden)
static bool BBHasFallthrough(MachineBasicBlock *MBB)
BBHasFallthrough - Return true if the specified basic block can fallthrough into the block immediatel...
Definition MipsConstantIslandPass.cpp:585
static cl::opt< bool > AlignConstantIslands("mips-align-constant-islands", cl::Hidden, cl::init(true), cl::desc("Align constant islands in code"))
static unsigned int branchTargetOperand(MachineInstr *MI)
Definition MipsConstantIslandPass.cpp:85
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)
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...
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.
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.
unsigned getConstantPoolIndex(const Constant *C, Align Alignment)
getConstantPoolIndex - Create a new entry in the constant pool or return an existing one.
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.
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
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
LLVM_ABI void setDesc(const MCInstrDesc &TID)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one.
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
void setMBB(MachineBasicBlock *MBB)
static MachineOperand CreateCPI(unsigned Idx, int Offset, unsigned TargetFlags=0)
void invalidateLiveness()
invalidateLiveness - Indicates that register liveness is no longer being tracked accurately.
static bool useConstantIslands()
const MipsInstrInfo * getInstrInfo() const override
bool inMips16Mode() const
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 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.
@ C
The default llvm calling convention, compatible with C.
initializer< Ty > init(const Ty &Val)
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.
FunctionAddr VTableAddr uintptr_t uintptr_t Int32Ty
bool isAligned(Align Lhs, uint64_t SizeInBytes)
Checks that SizeInBytes is a multiple of the alignment.
FunctionPass * createMipsConstantIslandPass()
Returns a pass that converts branches to long branches.
Definition MipsConstantIslandPass.cpp:1661
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...
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
APFloat neg(APFloat X)
Returns the negated value of the argument.
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.
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.