LLVM: lib/Target/Hexagon/HexagonSplitDouble.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
27#include "llvm/Config/llvm-config.h"
35#include
36#include
37#include
38#include
39#include
40#include
41#include
42#include
43
44#define DEBUG_TYPE "hsdr"
45
46using namespace llvm;
47
49 cl::desc("Maximum number of split partitions"));
51 cl::desc("Do not split loads or stores"));
53 cl::desc("Split all partitions"));
54
55namespace {
56
58 public:
59 static char ID;
60
62
63 StringRef getPassName() const override {
64 return "Hexagon Split Double Registers";
65 }
66
67 void getAnalysisUsage(AnalysisUsage &AU) const override {
68 AU.addRequired();
69 AU.addPreserved();
71 }
72
73 bool runOnMachineFunction(MachineFunction &MF) override;
74
75 private:
76 static const TargetRegisterClass *const DoubleRC;
77
78 const HexagonRegisterInfo *TRI = nullptr;
79 const HexagonInstrInfo *TII = nullptr;
80 const MachineLoopInfo *MLI;
81 MachineRegisterInfo *MRI;
82
83 using USet = std::set;
84 using UUSetMap = std::map<unsigned, USet>;
85 using UUPair = std::pair<unsigned, unsigned>;
86 using UUPairMap = std::map<unsigned, UUPair>;
87 using LoopRegMap = std::map<const MachineLoop *, USet>;
88
89 bool isInduction(unsigned Reg, LoopRegMap &IRM) const;
90 bool isVolatileInstr(const MachineInstr *MI) const;
91 bool isFixedInstr(const MachineInstr *MI) const;
92 void partitionRegisters(UUSetMap &P2Rs);
93 int32_t profit(const MachineInstr *MI) const;
95 bool isProfitable(const USet &Part, LoopRegMap &IRM) const;
96
97 void collectIndRegsForLoop(const MachineLoop *L, USet &Rs);
98 void collectIndRegs(LoopRegMap &IRM);
99
100 void createHalfInstr(unsigned Opc, MachineInstr *MI,
101 const UUPairMap &PairMap, unsigned SubR);
102 void splitMemRef(MachineInstr *MI, const UUPairMap &PairMap);
103 void splitImmediate(MachineInstr *MI, const UUPairMap &PairMap);
104 void splitCombine(MachineInstr *MI, const UUPairMap &PairMap);
105 void splitExt(MachineInstr *MI, const UUPairMap &PairMap);
106 void splitShift(MachineInstr *MI, const UUPairMap &PairMap);
107 void splitAslOr(MachineInstr *MI, const UUPairMap &PairMap);
108 bool splitInstr(MachineInstr *MI, const UUPairMap &PairMap);
109 void replaceSubregUses(MachineInstr *MI, const UUPairMap &PairMap);
110 void collapseRegPairs(MachineInstr *MI, const UUPairMap &PairMap);
111 bool splitPartition(const USet &Part);
112
113 static int Counter;
114
115 static void dump_partition(raw_ostream&, const USet&,
116 const TargetRegisterInfo&);
117 };
118
119}
120
121char HexagonSplitDoubleRegs::ID;
122int HexagonSplitDoubleRegs::Counter = 0;
124 &Hexagon::DoubleRegsRegClass;
125
127 "Hexagon Split Double Registers", false, false)
128
129#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
132 dbgs() << '{';
133 for (auto I : Part)
135 dbgs() << " }";
136}
137#endif
138
139bool HexagonSplitDoubleRegs::isInduction(unsigned Reg, LoopRegMap &IRM) const {
140 for (auto I : IRM) {
141 const USet &Rs = I.second;
142 if (Rs.find(Reg) != Rs.end())
143 return true;
144 }
145 return false;
146}
147
148bool HexagonSplitDoubleRegs::isVolatileInstr(const MachineInstr *MI) const {
149 for (auto &MO : MI->memoperands())
150 if (MO->isVolatile() || MO->isAtomic())
151 return true;
152 return false;
153}
154
155bool HexagonSplitDoubleRegs::isFixedInstr(const MachineInstr *MI) const {
156 if (MI->mayLoadOrStore())
158 return true;
159 if (MI->isDebugInstr())
160 return false;
161
162 unsigned Opc = MI->getOpcode();
163 switch (Opc) {
164 default:
165 return true;
166
167 case TargetOpcode::PHI:
168 case TargetOpcode::COPY:
169 break;
170
171 case Hexagon::L2_loadrd_io:
172
173 if (MI->getOperand(1).isReg())
174 break;
175 return true;
176 case Hexagon::S2_storerd_io:
177
178 if (MI->getOperand(0).isReg())
179 break;
180 return true;
181 case Hexagon::L2_loadrd_pi:
182 case Hexagon::S2_storerd_pi:
183
184 case Hexagon::A2_tfrpi:
185 case Hexagon::A2_combineii:
186 case Hexagon::A4_combineir:
187 case Hexagon::A4_combineii:
188 case Hexagon::A4_combineri:
189 case Hexagon::A2_combinew:
190 case Hexagon::CONST64:
191
192 case Hexagon::A2_sxtw:
193
194 case Hexagon::A2_andp:
195 case Hexagon::A2_orp:
196 case Hexagon::A2_xorp:
197 case Hexagon::S2_asl_i_p_or:
198 case Hexagon::S2_asl_i_p:
199 case Hexagon::S2_asr_i_p:
200 case Hexagon::S2_lsr_i_p:
201 break;
202 }
203
204 for (auto &Op : MI->operands()) {
205 if (.isReg())
206 continue;
208 if (.isVirtual())
209 return true;
210 }
211 return false;
212}
213
214void HexagonSplitDoubleRegs::partitionRegisters(UUSetMap &P2Rs) {
215 using UUMap = std::map<unsigned, unsigned>;
216 using UVect = std::vector;
217
218 unsigned NumRegs = MRI->getNumVirtRegs();
220 for (unsigned i = 0; i < NumRegs; ++i) {
221 Register R = Register::index2VirtReg(i);
222 if (MRI->getRegClass(R) == DoubleRC)
224 }
225
226 BitVector FixedRegs(NumRegs);
228 Register R = Register::index2VirtReg(x);
229 MachineInstr *DefI = MRI->getVRegDef(R);
230
231
232
233 if (!DefI || isFixedInstr(DefI))
234 FixedRegs.set(x);
235 }
236
237 UUSetMap AssocMap;
239 if (FixedRegs[x])
240 continue;
241 Register R = Register::index2VirtReg(x);
243 USet &Asc = AssocMap[R];
244 for (auto U = MRI->use_nodbg_begin(R), Z = MRI->use_nodbg_end();
245 U != Z; ++U) {
247 MachineInstr *UseI = Op.getParent();
248 if (isFixedInstr(UseI))
249 continue;
250 for (MachineOperand &MO : UseI->operands()) {
251
252 if (&MO == &Op || !MO.isReg() || MO.getSubReg())
253 continue;
255 if (.isVirtual()) {
256 FixedRegs.set(x);
257 continue;
258 }
259 if (MRI->getRegClass(T) != DoubleRC)
260 continue;
261 unsigned u = T.virtRegIndex();
262 if (FixedRegs[u])
263 continue;
265 Asc.insert(T);
266
267 AssocMap[T].insert(R);
268 }
269 }
271 }
272
273 UUMap R2P;
274 unsigned NextP = 1;
275 USet Visited;
277 Register R = Register::index2VirtReg(x);
278 if (Visited.count(R))
279 continue;
280
281 unsigned ThisP = FixedRegs[x] ? 0 : NextP++;
282 UVect WorkQ;
283 WorkQ.push_back(R);
284 for (unsigned i = 0; i < WorkQ.size(); ++i) {
285 unsigned T = WorkQ[i];
286 if (Visited.count(T))
287 continue;
288 R2P[T] = ThisP;
289 Visited.insert(T);
290
291 USet &Asc = AssocMap[T];
293 }
294 }
295
296 for (auto I : R2P)
297 P2Rs[I.second].insert(I.first);
298}
299
300static inline int32_t profitImm(unsigned Imm) {
301 int32_t P = 0;
302 if (Imm == 0 || Imm == 0xFFFFFFFF)
303 P += 10;
304 return P;
305}
306
307int32_t HexagonSplitDoubleRegs::profit(const MachineInstr *MI) const {
308 unsigned ImmX = 0;
309 unsigned Opc = MI->getOpcode();
310 switch (Opc) {
311 case TargetOpcode::PHI:
312 for (const auto &Op : MI->operands())
313 if (.getSubReg())
314 return 0;
315 return 10;
316 case TargetOpcode::COPY:
317 if (MI->getOperand(1).getSubReg() != 0)
318 return 10;
319 return 0;
320
321 case Hexagon::L2_loadrd_io:
322 case Hexagon::S2_storerd_io:
323 return -1;
324 case Hexagon::L2_loadrd_pi:
325 case Hexagon::S2_storerd_pi:
326 return 2;
327
328 case Hexagon::A2_tfrpi:
329 case Hexagon::CONST64: {
330 uint64_t D = MI->getOperand(1).getImm();
331 unsigned Lo = D & 0xFFFFFFFFULL;
334 }
335 case Hexagon::A2_combineii:
336 case Hexagon::A4_combineii: {
337 const MachineOperand &Op1 = MI->getOperand(1);
338 const MachineOperand &Op2 = MI->getOperand(2);
341 return Prof1 + Prof2;
342 }
343 case Hexagon::A4_combineri:
344 ImmX++;
345
346 [[fallthrough]];
347 case Hexagon::A4_combineir: {
348 ImmX++;
349 const MachineOperand &OpX = MI->getOperand(ImmX);
350 if (OpX.isImm()) {
352 if (V == 0 || V == -1)
353 return 10;
354 }
355
356 [[fallthrough]];
357 }
358 case Hexagon::A2_combinew:
359 return 2;
360
361 case Hexagon::A2_sxtw:
362 return 3;
363
364 case Hexagon::A2_andp:
365 case Hexagon::A2_orp:
366 case Hexagon::A2_xorp: {
367 Register Rs = MI->getOperand(1).getReg();
368 Register Rt = MI->getOperand(2).getReg();
369 return profit(Rs) + profit(Rt);
370 }
371
372 case Hexagon::S2_asl_i_p_or: {
373 unsigned S = MI->getOperand(3).getImm();
374 if (S == 0 || S == 32)
375 return 10;
376 return -1;
377 }
378 case Hexagon::S2_asl_i_p:
379 case Hexagon::S2_asr_i_p:
380 case Hexagon::S2_lsr_i_p:
381 unsigned S = MI->getOperand(2).getImm();
382 if (S == 0 || S == 32)
383 return 10;
384 if (S == 16)
385 return 5;
386 if (S == 48)
387 return 7;
388 return -10;
389 }
390
391 return 0;
392}
393
394int32_t HexagonSplitDoubleRegs::profit(Register Reg) const {
396
397 const MachineInstr *DefI = MRI->getVRegDef(Reg);
399 case Hexagon::A2_tfrpi:
400 case Hexagon::CONST64:
401 case Hexagon::A2_combineii:
402 case Hexagon::A4_combineii:
403 case Hexagon::A4_combineri:
404 case Hexagon::A4_combineir:
405 case Hexagon::A2_combinew:
406 return profit(DefI);
407 default:
408 break;
409 }
410 return 0;
411}
412
413bool HexagonSplitDoubleRegs::isProfitable(const USet &Part, LoopRegMap &IRM)
414 const {
415 unsigned FixedNum = 0, LoopPhiNum = 0;
416 int32_t TotalP = 0;
417
418 for (unsigned DR : Part) {
419 MachineInstr *DefI = MRI->getVRegDef(DR);
420 int32_t P = profit(DefI);
421 if (P == std::numeric_limits::min())
422 return false;
423 TotalP += P;
424
425 if (isInduction(DR, IRM))
426 TotalP -= 30;
427
428 for (auto U = MRI->use_nodbg_begin(DR), W = MRI->use_nodbg_end();
429 U != W; ++U) {
430 MachineInstr *UseI = U->getParent();
431 if (isFixedInstr(UseI)) {
432 FixedNum++;
433
435 if (Op.isReg() && Part.count(Op.getReg()))
436 if (Op.getSubReg())
437 TotalP -= 2;
438 }
439 continue;
440 }
441
442
443
444
445 if (UseI->isPHI()) {
446 const MachineBasicBlock *PB = UseI->getParent();
448 if (L && L->getHeader() == PB)
449 LoopPhiNum++;
450 }
451
452 int32_t P = profit(UseI);
453 if (P == std::numeric_limits::min())
454 return false;
455 TotalP += P;
456 }
457 }
458
459 if (FixedNum > 0 && LoopPhiNum > 0)
460 TotalP -= 20*LoopPhiNum;
461
462 LLVM_DEBUG(dbgs() << "Partition profit: " << TotalP << '\n');
464 return true;
465 return TotalP > 0;
466}
467
468void HexagonSplitDoubleRegs::collectIndRegsForLoop(const MachineLoop *L,
469 USet &Rs) {
470 const MachineBasicBlock *HB = L->getHeader();
471 const MachineBasicBlock *LB = L->getLoopLatch();
472 if (!HB || !LB)
473 return;
474
475
476
477 MachineBasicBlock *TB = nullptr, *FB = nullptr;
478 MachineBasicBlock *TmpLB = const_cast<MachineBasicBlock*>(LB);
481
482
483
484 if (BadLB || Cond.size() != 2)
485 return;
486
487 if (->PredOpcodeHasJMP_c(Cond[0].getImm()))
488 return;
489
490 if (TB != HB && FB != HB)
491 return;
492 assert(Cond[1].isReg() && "Unexpected Cond vector from analyzeBranch");
493
495 assert(MRI->getRegClass(PR) == &Hexagon::PredRegsRegClass);
496
497
498
500 const MachineInstr *CmpI = MRI->getVRegDef(PR);
501 while (CmpI->getOpcode() == Hexagon::C2_not)
503
504 int64_t Mask = 0, Val = 0;
506 if (!OkCI)
507 return;
508
509 if (CmpR1 && MRI->getRegClass(CmpR1) != DoubleRC)
510 CmpR1 = 0;
511 if (CmpR2 && MRI->getRegClass(CmpR2) != DoubleRC)
512 CmpR2 = 0;
513 if (!CmpR1 && !CmpR2)
514 return;
515
516
517
518
519
520
521
522
523 using UVect = std::vector;
524
525 UVect DP;
526 for (auto &MI : *HB) {
527 if (.isPHI())
528 break;
529 const MachineOperand &MD = MI.getOperand(0);
531 if (MRI->getRegClass(R) == DoubleRC)
532 DP.push_back(R);
533 }
534 if (DP.empty())
535 return;
536
537 auto NoIndOp = [this, CmpR1, CmpR2] (unsigned R) -> bool {
538 for (auto I = MRI->use_nodbg_begin(R), E = MRI->use_nodbg_end();
540 const MachineInstr *UseI = I->getParent();
541 if (UseI->getOpcode() != Hexagon::A2_addp)
542 continue;
543
544
545
547 if (T == CmpR1 || T == CmpR2)
548 return false;
549 }
550 return true;
551 };
553 Rs.insert(DP.begin(), End);
554 Rs.insert(CmpR1);
555 Rs.insert(CmpR2);
556
559 dump_partition(dbgs(), Rs, *TRI);
560 dbgs() << '\n';
561 });
562}
563
564void HexagonSplitDoubleRegs::collectIndRegs(LoopRegMap &IRM) {
565 using LoopVector = std::vector<MachineLoop *>;
566
568
570 for (unsigned i = 0; i < WorkQ.size(); ++i)
572
573 USet Rs;
574 for (MachineLoop *L : WorkQ) {
575 Rs.clear();
576 collectIndRegsForLoop(L, Rs);
577 if (!Rs.empty())
578 IRM.insert(std::make_pair(L, Rs));
579 }
580}
581
582void HexagonSplitDoubleRegs::createHalfInstr(unsigned Opc, MachineInstr *MI,
583 const UUPairMap &PairMap, unsigned SubR) {
584 MachineBasicBlock &B = *MI->getParent();
587
588 for (auto &Op : MI->operands()) {
589 if (.isReg()) {
591 continue;
592 }
593
595 unsigned SR = Op.getSubReg();
596 bool isVirtReg = R.isVirtual();
597 bool isKill = Op.isKill();
598 if (isVirtReg && MRI->getRegClass(R) == DoubleRC) {
599 isKill = false;
600 UUPairMap::const_iterator F = PairMap.find(R);
601 if (F == PairMap.end()) {
602 SR = SubR;
603 } else {
604 const UUPair &P = F->second;
605 R = (SubR == Hexagon::isub_lo) ? P.first : P.second;
606 SR = 0;
607 }
608 }
610 Op.isDead(), Op.isUndef(), Op.isEarlyClobber(), SR, Op.isDebug(),
611 Op.isInternalRead());
613 }
614}
615
616void HexagonSplitDoubleRegs::splitMemRef(MachineInstr *MI,
617 const UUPairMap &PairMap) {
618 bool Load = MI->mayLoad();
619 unsigned OrigOpc = MI->getOpcode();
620 bool PostInc = (OrigOpc == Hexagon::L2_loadrd_pi ||
621 OrigOpc == Hexagon::S2_storerd_pi);
622 MachineInstr *LowI, *HighI;
623 MachineBasicBlock &B = *MI->getParent();
625
626
628 : (Load ? 1 : 0);
629 MachineOperand &AdrOp = MI->getOperand(AdrX);
631 MachineOperand &ValOp = Load ? MI->getOperand(0)
633 : MI->getOperand(2));
634 UUPairMap::const_iterator F = PairMap.find(ValOp.getReg());
635 assert(F != PairMap.end());
636
637 if (Load) {
638 const UUPair &P = F->second;
639 int64_t Off = PostInc ? 0 : MI->getOperand(2).getImm();
646 } else {
647 const UUPair &P = F->second;
648 int64_t Off = PostInc ? 0 : MI->getOperand(1).getImm();
657 }
658
660
661 int64_t Inc = Load ? MI->getOperand(3).getImm()
662 : MI->getOperand(2).getImm();
663 MachineOperand &UpdOp = Load ? MI->getOperand(1) : MI->getOperand(0);
664 const TargetRegisterClass *RC = MRI->getRegClass(UpdOp.getReg());
665 Register NewR = MRI->createVirtualRegister(RC);
670 MRI->replaceRegWith(UpdOp.getReg(), NewR);
671
672 }
673
674
675 MachineFunction &MF = *B.getParent();
676 for (auto &MO : MI->memoperands()) {
677 const MachinePointerInfo &Ptr = MO->getPointerInfo();
680
683 auto *Tmp2 =
686 }
687}
688
689void HexagonSplitDoubleRegs::splitImmediate(MachineInstr *MI,
690 const UUPairMap &PairMap) {
691 MachineOperand &Op0 = MI->getOperand(0);
692 MachineOperand &Op1 = MI->getOperand(1);
694 uint64_t V = Op1.getImm();
695
696 MachineBasicBlock &B = *MI->getParent();
698 UUPairMap::const_iterator F = PairMap.find(Op0.getReg());
699 assert(F != PairMap.end());
700 const UUPair &P = F->second;
701
702
703
704
705
706
707
708
709
711 .addImm(int32_t(V & 0xFFFFFFFFULL));
713 .addImm(int32_t(V >> 32));
714}
715
716void HexagonSplitDoubleRegs::splitCombine(MachineInstr *MI,
717 const UUPairMap &PairMap) {
718 MachineOperand &Op0 = MI->getOperand(0);
719 MachineOperand &Op1 = MI->getOperand(1);
720 MachineOperand &Op2 = MI->getOperand(2);
722
723 MachineBasicBlock &B = *MI->getParent();
725 UUPairMap::const_iterator F = PairMap.find(Op0.getReg());
726 assert(F != PairMap.end());
727 const UUPair &P = F->second;
728
729 if (!Op1.isReg()) {
731 .add(Op1);
732 } else {
735 }
736
737 if (!Op2.isReg()) {
739 .add(Op2);
740 } else {
743 }
744}
745
746void HexagonSplitDoubleRegs::splitExt(MachineInstr *MI,
747 const UUPairMap &PairMap) {
748 MachineOperand &Op0 = MI->getOperand(0);
749 MachineOperand &Op1 = MI->getOperand(1);
751
752 MachineBasicBlock &B = *MI->getParent();
754 UUPairMap::const_iterator F = PairMap.find(Op0.getReg());
755 assert(F != PairMap.end());
756 const UUPair &P = F->second;
758
764}
765
766void HexagonSplitDoubleRegs::splitShift(MachineInstr *MI,
767 const UUPairMap &PairMap) {
768 using namespace Hexagon;
769
770 MachineOperand &Op0 = MI->getOperand(0);
771 MachineOperand &Op1 = MI->getOperand(1);
772 MachineOperand &Op2 = MI->getOperand(2);
774 int64_t Sh64 = Op2.getImm();
775 assert(Sh64 >= 0 && Sh64 < 64);
776 unsigned S = Sh64;
777
778 UUPairMap::const_iterator F = PairMap.find(Op0.getReg());
779 assert(F != PairMap.end());
780 const UUPair &P = F->second;
783
784 unsigned Opc = MI->getOpcode();
785 bool Right = (Opc == S2_lsr_i_p || Opc == S2_asr_i_p);
787 bool Signed = (Opc == S2_asr_i_p);
788
789 MachineBasicBlock &B = *MI->getParent();
793 : (Signed ? S2_asr_i_r : S2_lsr_i_r);
794 unsigned LoSR = isub_lo;
795 unsigned HiSR = isub_hi;
796
797 if (S == 0) {
798
803 } else if (S < 32) {
804 const TargetRegisterClass *IntRC = &IntRegsRegClass;
805 Register TmpR = MRI->createVirtualRegister(IntRC);
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823 if (S == 16 && Left)
826 else if (S == 16 && Signed)
829 else
833
835
840
845 } else {
846
850
856 }
857 } else if (S == 32) {
863 else
867 } else if (S < 64) {
868 S -= 32;
869 if (S == 16 && Left)
872 else if (S == 16 && Signed)
875 else
879
884 else
887 }
888}
889
890void HexagonSplitDoubleRegs::splitAslOr(MachineInstr *MI,
891 const UUPairMap &PairMap) {
892 using namespace Hexagon;
893
894 MachineOperand &Op0 = MI->getOperand(0);
895 MachineOperand &Op1 = MI->getOperand(1);
896 MachineOperand &Op2 = MI->getOperand(2);
897 MachineOperand &Op3 = MI->getOperand(3);
899 int64_t Sh64 = Op3.getImm();
900 assert(Sh64 >= 0 && Sh64 < 64);
901 unsigned S = Sh64;
902
903 UUPairMap::const_iterator F = PairMap.find(Op0.getReg());
904 assert(F != PairMap.end());
905 const UUPair &P = F->second;
906 unsigned LoR = P.first;
907 unsigned HiR = P.second;
908
909 MachineBasicBlock &B = *MI->getParent();
913 const TargetRegisterClass *IntRC = &IntRegsRegClass;
914
915 unsigned LoSR = isub_lo;
916 unsigned HiSR = isub_hi;
917
918
919
920
921
922
923
924
925
926
927
928
929 if (S == 0) {
930
931
932
933
940 } else if (S < 32) {
945 Register TmpR1 = MRI->createVirtualRegister(IntRC);
950 Register TmpR2 = MRI->createVirtualRegister(IntRC);
958 } else if (S == 32) {
959
960
961
962
968 } else if (S < 64) {
969
970
971
972
973 S -= 32;
980 }
981}
982
983bool HexagonSplitDoubleRegs::splitInstr(MachineInstr *MI,
984 const UUPairMap &PairMap) {
985 using namespace Hexagon;
986
988 bool Split = false;
989 unsigned Opc = MI->getOpcode();
990
991 switch (Opc) {
992 case TargetOpcode::PHI:
993 case TargetOpcode::COPY: {
994 Register DstR = MI->getOperand(0).getReg();
995 if (MRI->getRegClass(DstR) == DoubleRC) {
996 createHalfInstr(Opc, MI, PairMap, isub_lo);
997 createHalfInstr(Opc, MI, PairMap, isub_hi);
999 }
1000 break;
1001 }
1002 case A2_andp:
1003 createHalfInstr(A2_and, MI, PairMap, isub_lo);
1004 createHalfInstr(A2_and, MI, PairMap, isub_hi);
1006 break;
1007 case A2_orp:
1008 createHalfInstr(A2_or, MI, PairMap, isub_lo);
1009 createHalfInstr(A2_or, MI, PairMap, isub_hi);
1011 break;
1012 case A2_xorp:
1013 createHalfInstr(A2_xor, MI, PairMap, isub_lo);
1014 createHalfInstr(A2_xor, MI, PairMap, isub_hi);
1016 break;
1017
1018 case L2_loadrd_io:
1019 case L2_loadrd_pi:
1020 case S2_storerd_io:
1021 case S2_storerd_pi:
1022 splitMemRef(MI, PairMap);
1024 break;
1025
1026 case A2_tfrpi:
1027 case CONST64:
1028 splitImmediate(MI, PairMap);
1030 break;
1031
1032 case A2_combineii:
1033 case A4_combineir:
1034 case A4_combineii:
1035 case A4_combineri:
1036 case A2_combinew:
1037 splitCombine(MI, PairMap);
1039 break;
1040
1041 case A2_sxtw:
1042 splitExt(MI, PairMap);
1044 break;
1045
1046 case S2_asl_i_p:
1047 case S2_asr_i_p:
1048 case S2_lsr_i_p:
1049 splitShift(MI, PairMap);
1051 break;
1052
1053 case S2_asl_i_p_or:
1054 splitAslOr(MI, PairMap);
1056 break;
1057
1058 default:
1060 return false;
1061 }
1062
1064}
1065
1066void HexagonSplitDoubleRegs::replaceSubregUses(MachineInstr *MI,
1067 const UUPairMap &PairMap) {
1068 for (auto &Op : MI->operands()) {
1069 if (.isReg() ||
.isUse() ||
.getSubReg())
1070 continue;
1072 UUPairMap::const_iterator F = PairMap.find(R);
1073 if (F == PairMap.end())
1074 continue;
1075 const UUPair &P = F->second;
1076 switch (Op.getSubReg()) {
1077 case Hexagon::isub_lo:
1079 break;
1080 case Hexagon::isub_hi:
1082 break;
1083 }
1084 Op.setSubReg(0);
1085 }
1086}
1087
1088void HexagonSplitDoubleRegs::collapseRegPairs(MachineInstr *MI,
1089 const UUPairMap &PairMap) {
1090 MachineBasicBlock &B = *MI->getParent();
1092
1093 for (auto &Op : MI->operands()) {
1094 if (.isReg() ||
.isUse())
1095 continue;
1097 if (.isVirtual())
1098 continue;
1099 if (MRI->getRegClass(R) != DoubleRC || Op.getSubReg())
1100 continue;
1101 UUPairMap::const_iterator F = PairMap.find(R);
1102 if (F == PairMap.end())
1103 continue;
1104 const UUPair &Pr = F->second;
1105 Register NewDR = MRI->createVirtualRegister(DoubleRC);
1108 .addImm(Hexagon::isub_lo)
1110 .addImm(Hexagon::isub_hi);
1111 Op.setReg(NewDR);
1112 }
1113}
1114
1115bool HexagonSplitDoubleRegs::splitPartition(const USet &Part) {
1116 using MISet = std::set<MachineInstr *>;
1117
1118 const TargetRegisterClass *IntRC = &Hexagon::IntRegsRegClass;
1120
1122 dump_partition(dbgs(), Part, *TRI); dbgs() << '\n');
1123
1124 UUPairMap PairMap;
1125
1126 MISet SplitIns;
1127 for (unsigned DR : Part) {
1128 MachineInstr *DefI = MRI->getVRegDef(DR);
1129 SplitIns.insert(DefI);
1130
1131
1132
1133 for (auto U = MRI->use_nodbg_begin(DR), W = MRI->use_nodbg_end();
1134 U != W; ++U)
1135 SplitIns.insert(U->getParent());
1136
1137 Register LoR = MRI->createVirtualRegister(IntRC);
1138 Register HiR = MRI->createVirtualRegister(IntRC);
1141 << '\n');
1142 PairMap.insert(std::make_pair(DR, UUPair(LoR, HiR)));
1143 }
1144
1145 MISet Erase;
1146 for (auto *MI : SplitIns) {
1147 if (isFixedInstr(MI)) {
1148 collapseRegPairs(MI, PairMap);
1149 } else {
1150 bool Done = splitInstr(MI, PairMap);
1152 Erase.insert(MI);
1154 }
1155 }
1156
1157 for (unsigned DR : Part) {
1158
1159
1160
1162 for (auto U = MRI->use_nodbg_begin(DR), W = MRI->use_nodbg_end();
1163 U != W; ++U)
1164 Uses.insert(U->getParent());
1165 for (auto *M : Uses)
1166 replaceSubregUses(M, PairMap);
1167 }
1168
1169 for (auto *MI : Erase) {
1170 MachineBasicBlock *B = MI->getParent();
1172 }
1173
1175}
1176
1177bool HexagonSplitDoubleRegs::runOnMachineFunction(MachineFunction &MF) {
1179 return false;
1180
1181 LLVM_DEBUG(dbgs() << "Splitting double registers in function: "
1182 << MF.getName() << '\n');
1183
1185 TRI = ST.getRegisterInfo();
1188 MLI = &getAnalysis().getLI();
1189
1190 UUSetMap P2Rs;
1191 LoopRegMap IRM;
1192
1193 collectIndRegs(IRM);
1194 partitionRegisters(P2Rs);
1195
1197 dbgs() << "Register partitioning: (partition #0 is fixed)\n";
1198 for (UUSetMap::iterator I = P2Rs.begin(), E = P2Rs.end(); I != E; ++I) {
1199 dbgs() << '#' << I->first << " -> ";
1200 dump_partition(dbgs(), I->second, *TRI);
1201 dbgs() << '\n';
1202 }
1203 });
1204
1207
1208 for (UUSetMap::iterator I = P2Rs.begin(), E = P2Rs.end(); I != E; ++I) {
1209 if (I->first == 0)
1210 continue;
1211 if (Limit >= 0 && Counter >= Limit)
1212 break;
1213 USet &Part = I->second;
1214 LLVM_DEBUG(dbgs() << "Calculating profit for partition #" << I->first
1215 << '\n');
1217 continue;
1218 Counter++;
1219 Changed |= splitPartition(Part);
1220 }
1221
1223}
1224
1226 return new HexagonSplitDoubleRegs();
1227}
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
const TargetInstrInfo & TII
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file implements the BitVector class.
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
static cl::opt< bool > MemRefsFixed("hsdr-no-mem", cl::Hidden, cl::init(true), cl::desc("Do not split loads or stores"))
static cl::opt< bool > SplitAll("hsdr-split-all", cl::Hidden, cl::init(false), cl::desc("Split all partitions"))
static cl::opt< int > MaxHSDR("max-hsdr", cl::Hidden, cl::init(-1), cl::desc("Maximum number of split partitions"))
static int32_t profitImm(unsigned Imm)
Definition HexagonSplitDouble.cpp:300
SmallVector< Loop *, 4 > LoopVector
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static bool isReg(const MCInst &MI, unsigned OpNo)
PassBuilder PB(Machine, PassOpts->PTO, std::nullopt, &PIC)
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
const SmallVectorImpl< MachineOperand > & Cond
Remove Loads Into Fake Uses
This file defines the SmallVector class.
static const MCPhysReg DoubleRegs[32]
static bool isProfitable(const StableFunctionMap::StableFunctionEntries &SFS)
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
FunctionPass class - This class is used to implement most global optimizations.
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
LLVM_ABI void addOperand(MachineFunction &MF, const MachineOperand &Op)
Add the specified operand to the instruction.
const MachineOperand & getOperand(unsigned i) const
LLVM_ABI void addMemOperand(MachineFunction &MF, MachineMemOperand *MO)
Add a MachineMemOperand to the machine instruction.
Flags
Flags values. These may be or'd together.
unsigned getSubReg() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
Register getReg() const
getReg - Returns the register number.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
virtual bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify=false) const
Analyze the branching code at the end of MBB, returning true if it cannot be understood (e....
virtual bool analyzeCompare(const MachineInstr &MI, Register &SrcReg, Register &SrcReg2, int64_t &Mask, int64_t &Value) const
For a comparison instruction, return the source registers in SrcReg and SrcReg2 if having two registe...
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ Kill
The last use of a register.
@ TB
TB - TwoByte - Set if this instruction has a two byte opcode, which starts with a 0x0F byte before th...
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
auto remove_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::remove_if which take ranges instead of having to pass begin/end explicitly.
unsigned getRegState(const MachineOperand &RegOp)
Get all register state flags from machine operand RegOp.
DWARFExpression::Operation Op
FunctionPass * createHexagonSplitDoubleRegs()
Definition HexagonSplitDouble.cpp:1225
LLVM_ABI Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
LLVM_ABI Printable printMBBReference(const MachineBasicBlock &MBB)
Prints a machine basic block reference.