LLVM: lib/Target/Hexagon/HexagonOptAddrMode.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
39#include
40#include
41
42#define DEBUG_TYPE "opt-addr-mode"
43
44using namespace llvm;
45using namespace rdf;
46
49 "optimization"));
50
52
53namespace {
54
56public:
57 static char ID;
58
60
61 StringRef getPassName() const override {
62 return "Optimize addressing mode of load/store";
63 }
64
65 void getAnalysisUsage(AnalysisUsage &AU) const override {
67 AU.addRequired();
68 AU.addRequired();
70 }
71
72 bool runOnMachineFunction(MachineFunction &MF) override;
73
74private:
75 using MISetType = DenseSet<MachineInstr *>;
76 using InstrEvalMap = DenseMap<MachineInstr *, bool>;
77 DenseSet<MachineInstr *> ProcessedAddiInsts;
78
79 MachineRegisterInfo *MRI = nullptr;
80 const TargetRegisterInfo *TRI = nullptr;
81 const HexagonInstrInfo *HII = nullptr;
82 const HexagonRegisterInfo *HRI = nullptr;
83 MachineDominatorTree *MDT = nullptr;
84 DataFlowGraph *DFG = nullptr;
86 Liveness *LV = nullptr;
87 MISetType Deleted;
88
89 bool processBlock(NodeAddr<BlockNode *> BA);
90 bool xformUseMI(MachineInstr *TfrMI, MachineInstr *UseMI,
91 NodeAddr<UseNode *> UseN, unsigned UseMOnum);
92 bool processAddBases(NodeAddr<StmtNode *> AddSN, MachineInstr *AddMI);
93 bool usedInLoadStore(NodeAddr<StmtNode *> CurrentInstSN, int64_t NewOffset);
94 bool findFirstReachedInst(
95 MachineInstr *AddMI,
96 std::vector<std::pair<NodeAddr<StmtNode *>, NodeAddr<UseNode *>>>
97 &AddiList,
98 NodeAddr<StmtNode *> &UseSN);
99 bool updateAddBases(MachineInstr *CurrentMI, MachineInstr *FirstReachedMI,
100 int64_t NewOffset);
101 bool processAddUses(NodeAddr<StmtNode *> AddSN, MachineInstr *AddMI,
103 bool updateAddUses(MachineInstr *AddMI, MachineInstr *UseMI);
104 bool analyzeUses(unsigned DefR, const NodeList &UNodeList,
105 InstrEvalMap &InstrEvalResult, short &SizeInc);
106 bool hasRepForm(MachineInstr &MI, unsigned TfrDefR);
107 bool canRemoveAddasl(NodeAddr<StmtNode *> AddAslSN, MachineInstr &MI,
109 bool isSafeToExtLR(NodeAddr<StmtNode *> SN, MachineInstr *MI,
111 void getAllRealUses(NodeAddr<StmtNode *> SN, NodeList &UNodeList);
112 bool allValidCandidates(NodeAddr<StmtNode *> SA, NodeList &UNodeList);
113 short getBaseWithLongOffset(const MachineInstr &MI) const;
114 bool changeStore(MachineInstr *OldMI, MachineOperand ImmOp,
115 unsigned ImmOpNum);
116 bool changeLoad(MachineInstr *OldMI, MachineOperand ImmOp, unsigned ImmOpNum);
117 bool changeAddAsl(NodeAddr<UseNode *> AddAslUN, MachineInstr *AddAslMI,
118 const MachineOperand &ImmOp, unsigned ImmOpNum);
119 bool isValidOffset(MachineInstr *MI, int Offset);
120 unsigned getBaseOpPosition(MachineInstr *MI);
121 unsigned getOffsetOpPosition(MachineInstr *MI);
122};
123
124}
125
126char HexagonOptAddrMode::ID = 0;
127
129 "Optimize addressing mode", false, false)
134
135bool HexagonOptAddrMode::hasRepForm(MachineInstr &MI, unsigned TfrDefR) {
137
138 if ((!MID.mayStore() && !MID.mayLoad()) || HII->isPredicated(MI))
139 return false;
140
142 MachineOperand StOp = MI.getOperand(MI.getNumOperands() - 1);
143 if (StOp.isReg() && StOp.getReg() == TfrDefR)
144 return false;
145 }
146
148
149 return (HII->changeAddrMode_rr_ur(MI) >= 0);
151
152 return (HII->changeAddrMode_io_abs(MI) >= 0);
153
154 return false;
155}
156
157
158
159
160
161
162
163
164
165
166
170
171 const MachineOperand &OffsetOp = MI.getOperand(3);
173 return false;
174
175 Register OffsetReg = MI.getOperand(2).getReg();
176 RegisterRef OffsetRR;
177 NodeId OffsetRegRD = 0;
178 for (NodeAddr<UseNode *> UA : AddAslSN.Addr->members_if(DFG->IsUse, *DFG)) {
179 RegisterRef RR = UA.Addr->getRegRef(*DFG);
180 if (OffsetReg == RR.asMCReg()) {
181 OffsetRR = RR;
182 OffsetRegRD = UA.Addr->getReachingDef();
183 }
184 }
185
186 for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) {
187 NodeAddr<UseNode *> UA = *I;
188 NodeAddr<InstrNode *> IA = UA.Addr->getOwner(*DFG);
190 return false;
192 if ((DFG->IsDef(AA) && AA.Id != OffsetRegRD) ||
193 AA.Addr->getReachingDef() != OffsetRegRD)
194 return false;
195
196 MachineInstr &UseMI = *NodeAddr<StmtNode *>(IA).Addr->getCode();
197 NodeAddr<DefNode *> OffsetRegDN = DFG->addr<DefNode *>(OffsetRegRD);
198
200 MI.getParent() != UseMI.getParent())
201 return false;
202
203 const MCInstrDesc &UseMID = UseMI.getDesc();
206 getBaseWithLongOffset(UseMI) < 0)
207 return false;
208
209
210 if (UseMID.mayStore() && UseMI.getOperand(2).isReg() &&
211 UseMI.getOperand(2).getReg() == MI.getOperand(0).getReg())
212 return false;
213
214 for (auto &Mo : UseMI.operands())
215
216 if (Mo.isFI())
217 return false;
218
219 if (.getParent()->isLiveIn(OffsetReg) &&
220 MI.getParent() != UseMI.getParent()) {
222 << " is NOT live in to MBB "
223 << UseMI.getParent()->getName() << "\n");
224 return false;
225 }
226 }
227 return true;
228}
229
230bool HexagonOptAddrMode::allValidCandidates(NodeAddr<StmtNode *> SA,
232 for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) {
233 NodeAddr<UseNode *> UN = *I;
234 RegisterRef UR = UN.Addr->getRegRef(*DFG);
237 if (.second) {
239 dbgs() << "*** Unable to collect all reaching defs for use ***\n"
240 << PrintNode<UseNode*>(UN, *DFG) << '\n'
241 << "The program's complexity may exceed the limits.\n";
242 });
243 return false;
244 }
245 const auto &ReachingDefs = P.first;
246 if (ReachingDefs.size() > 1) {
248 dbgs() << "*** Multiple Reaching Defs found!!! ***\n";
249 for (auto DI : ReachingDefs) {
250 NodeAddr<UseNode *> DA = DFG->addr<UseNode *>(DI);
251 NodeAddr<StmtNode *> TempIA = DA.Addr->getOwner(*DFG);
252 dbgs() << "\t\t[Reaching Def]: "
254 }
255 });
256 return false;
257 }
258 }
259 return true;
260}
261
262void HexagonOptAddrMode::getAllRealUses(NodeAddr<StmtNode *> SA,
264 for (NodeAddr<DefNode *> DA : SA.Addr->members_if(DFG->IsDef, *DFG)) {
266 << Print<NodeAddr<DefNode *>>(DA, *DFG) << "\n");
267 RegisterRef DR = DA.Addr->getRegRef(*DFG);
268
270
271 for (auto UI : UseSet) {
272 NodeAddr<UseNode *> UA = DFG->addr<UseNode *>(UI);
274 NodeAddr<StmtNode *> TempIA = UA.Addr->getOwner(*DFG);
275 dbgs() << "\t\t\t[Reached Use]: "
277 });
278
280 NodeAddr<PhiNode *> PA = UA.Addr->getOwner(*DFG);
285 if (!phiUse.empty()) {
286 for (auto I : phiUse) {
287 if (!DFG->getPRI().alias(RegisterRef(I.first), DR))
288 continue;
289 auto phiUseSet = I.second;
290 for (auto phiUI : phiUseSet) {
291 NodeAddr<UseNode *> phiUA = DFG->addr<UseNode *>(phiUI.first);
292 UNodeList.push_back(phiUA);
293 }
294 }
295 }
296 } else
297 UNodeList.push_back(UA);
298 }
299 }
300}
301
302bool HexagonOptAddrMode::isSafeToExtLR(NodeAddr<StmtNode *> SN,
305 RegisterRef LRExtRR;
306 NodeId LRExtRegRD = 0;
307
308
309 for (NodeAddr<UseNode *> UA : SN.Addr->members_if(DFG->IsUse, *DFG)) {
310 RegisterRef RR = UA.Addr->getRegRef(*DFG);
311 if (LRExtReg == RR.asMCReg()) {
312 LRExtRR = RR;
313 LRExtRegRD = UA.Addr->getReachingDef();
314 }
315 }
316
317 for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) {
318 NodeAddr<UseNode *> UA = *I;
319 NodeAddr<InstrNode *> IA = UA.Addr->getOwner(*DFG);
320
321
323 return false;
325 if ((DFG->IsDef(AA) && AA.Id != LRExtRegRD) ||
326 AA.Addr->getReachingDef() != LRExtRegRD) {
328 dbgs() << "isSafeToExtLR: Returning false; another reaching def\n");
329 return false;
330 }
331
332
333
334
335 if (LRExtRegRD == 0)
336 return false;
337
338 MachineInstr *UseMI = NodeAddr<StmtNode *>(IA).Addr->getCode();
339 NodeAddr<DefNode *> LRExtRegDN = DFG->addr<DefNode *>(LRExtRegRD);
340
343 return false;
344
348 << " is NOT live in to MBB "
350 return false;
351 }
352 }
353 return true;
354}
355
356bool HexagonOptAddrMode::isValidOffset(MachineInstr *MI, int Offset) {
358
359
360 switch (MI->getOpcode()) {
361 case Hexagon::V6_vgathermh_pseudo:
362 case Hexagon::V6_vgathermw_pseudo:
363 case Hexagon::V6_vgathermhw_pseudo:
364 case Hexagon::V6_vgathermhq_pseudo:
365 case Hexagon::V6_vgathermwq_pseudo:
366 case Hexagon::V6_vgathermhwq_pseudo:
368 default:
370
372 if ((AlignMask & Offset) == 0)
374 }
375 return false;
376 }
377 }
378
380 return false;
381
382 unsigned AlignMask = 0;
384 case HexagonII::MemAccessSize::DoubleWordAccess:
385 AlignMask = 0x7;
386 break;
387 case HexagonII::MemAccessSize::WordAccess:
388 AlignMask = 0x3;
389 break;
390 case HexagonII::MemAccessSize::HalfWordAccess:
391 AlignMask = 0x1;
392 break;
393 case HexagonII::MemAccessSize::ByteAccess:
394 AlignMask = 0x0;
395 break;
396 default:
397 return false;
398 }
399
400 if ((AlignMask & Offset) != 0)
401 return false;
403}
404
405unsigned HexagonOptAddrMode::getBaseOpPosition(MachineInstr *MI) {
406 const MCInstrDesc &MID = MI->getDesc();
407 switch (MI->getOpcode()) {
408
409
410
411 case Hexagon::V6_vgathermh_pseudo:
412 case Hexagon::V6_vgathermw_pseudo:
413 case Hexagon::V6_vgathermhw_pseudo:
414 case Hexagon::V6_vgathermhq_pseudo:
415 case Hexagon::V6_vgathermwq_pseudo:
416 case Hexagon::V6_vgathermhwq_pseudo:
417 return 0;
418 default:
419 return MID.mayLoad() ? 1 : 0;
420 }
421}
422
423unsigned HexagonOptAddrMode::getOffsetOpPosition(MachineInstr *MI) {
426 "Looking for an offset in non-BaseImmOffset addressing mode instruction");
427
428 const MCInstrDesc &MID = MI->getDesc();
429 switch (MI->getOpcode()) {
430
431
432
433 case Hexagon::V6_vgathermh_pseudo:
434 case Hexagon::V6_vgathermw_pseudo:
435 case Hexagon::V6_vgathermhw_pseudo:
436 case Hexagon::V6_vgathermhq_pseudo:
437 case Hexagon::V6_vgathermwq_pseudo:
438 case Hexagon::V6_vgathermhwq_pseudo:
439 return 1;
440 default:
441 return MID.mayLoad() ? 2 : 1;
442 }
443}
444
445bool HexagonOptAddrMode::usedInLoadStore(NodeAddr<StmtNode *> CurrentInstSN,
446 int64_t NewOffset) {
448
449 getAllRealUses(CurrentInstSN, LoadStoreUseList);
450 bool FoundLoadStoreUse = false;
451 for (NodeAddr<UseNode *> UN : LoadStoreUseList) {
452 NodeAddr<StmtNode *> SN = UN.Addr->getOwner(*DFG);
453 MachineInstr *LoadStoreMI = SN.Addr->getCode();
454 const MCInstrDesc &MID = LoadStoreMI->getDesc();
456 isValidOffset(LoadStoreMI, NewOffset)) {
457 FoundLoadStoreUse = true;
458 break;
459 }
460 }
461 return FoundLoadStoreUse;
462}
463
464bool HexagonOptAddrMode::findFirstReachedInst(
465 MachineInstr *AddMI,
466 std::vector<std::pair<NodeAddr<StmtNode *>, NodeAddr<UseNode *>>> &AddiList,
467 NodeAddr<StmtNode *> &UseSN) {
468
469
470
471
472
473
474
475
476
477
478
479
480 MachineBasicBlock *CurrentMBB = AddMI->getParent();
481 for (auto &InstIter : *CurrentMBB) {
482
483 if (InstIter.getOpcode() == Hexagon::A2_addi) {
484 auto Iter = llvm::find_if(AddiList, [&InstIter](const auto &SUPair) {
485 return SUPair.first.Addr->getCode() == &InstIter;
486 });
487 if (Iter != AddiList.end()) {
488 UseSN = Iter->first;
489 return true;
490 }
491 }
492 }
493 return false;
494}
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521bool HexagonOptAddrMode::processAddBases(NodeAddr<StmtNode *> AddSN,
522 MachineInstr *AddMI) {
523
525
526 LLVM_DEBUG(dbgs() << "\n\t\t[Processing Addi]: " << *AddMI << "\n");
527
528 auto Processed =
529 [](const MachineInstr *MI,
530 const DenseSet<MachineInstr *> &ProcessedAddiInsts) -> bool {
531
532 if (ProcessedAddiInsts.contains(MI)) {
533 LLVM_DEBUG(dbgs() << "\t\t\tAddi already found in ProcessedAddiInsts: "
534 << *MI << "\n\t\t\tSkipping...");
535 return true;
536 }
537 return false;
538 };
539
540 if (Processed(AddMI, ProcessedAddiInsts))
542 ProcessedAddiInsts.insert(AddMI);
543
544
546
547
548
549 std::vector<std::pair<NodeAddr<StmtNode *>, NodeAddr<UseNode *>>> AddiList;
550
551 NodeId UAReachingDefID;
552
553 for (NodeAddr<UseNode *> UA : AddSN.Addr->members_if(DFG->IsUse, *DFG)) {
554 RegisterRef URR = UA.Addr->getRegRef(*DFG);
555 if (BaseReg != URR.asMCReg())
556 continue;
557
558 UAReachingDefID = UA.Addr->getReachingDef();
559 NodeAddr<DefNode *> UADef = DFG->addr<DefNode *>(UAReachingDefID);
561 LLVM_DEBUG(dbgs() << "\t\t\t Could not find reachingDef. Skipping...\n");
562 return false;
563 }
564 }
565
566 NodeAddr<DefNode *> UAReachingDef = DFG->addr<DefNode *>(UAReachingDefID);
567 NodeAddr<StmtNode *> ReachingDefStmt = UAReachingDef.Addr->getOwner(*DFG);
568
569
570
571 MachineInstr *ReachingDefInstr = ReachingDefStmt.Addr->getCode();
573 return false;
574
576
577
578
579 getAllRealUses(ReachingDefStmt, AddiUseList);
580 for (NodeAddr<UseNode *> UN : AddiUseList) {
581 NodeAddr<StmtNode *> SN = UN.Addr->getOwner(*DFG);
582 MachineInstr *MI = SN.Addr->getCode();
583
584
585 if (MI->getOpcode() == Hexagon::A2_addi &&
586 !(MI != AddMI && Processed(MI, ProcessedAddiInsts))) {
587 AddiList.push_back({SN, UN});
588
589
590 ProcessedAddiInsts.insert(MI);
591 }
592 }
593
594
595 if (AddiList.size() <= 1)
597
598 NodeAddr<StmtNode *> FirstReachedUseSN;
599
600 if (!findFirstReachedInst(AddMI, AddiList, FirstReachedUseSN))
602
603
604
605
606 NodeAddr<DefNode *> FirstReachedUseDN =
607 FirstReachedUseSN.Addr->members_if(DFG->IsDef, *DFG).front();
608
609 MachineInstr *FirstReachedMI = FirstReachedUseSN.Addr->getCode();
610 const MachineOperand FirstReachedMIImmOp = FirstReachedMI->getOperand(2);
611 if (!FirstReachedMIImmOp.isImm())
612 return false;
613
614 for (auto &I : AddiList) {
615 NodeAddr<StmtNode *> CurrentInstSN = I.first;
616 NodeAddr<UseNode *> CurrentInstUN = I.second;
617
618 MachineInstr *CurrentMI = CurrentInstSN.Addr->getCode();
619 MachineOperand &CurrentMIImmOp = CurrentMI->getOperand(2);
620
621 int64_t NewOffset;
622
623
624
625 if (!CurrentMIImmOp.isImm())
626 continue;
627
628 NewOffset = CurrentMIImmOp.getImm() - FirstReachedMIImmOp.getImm();
629
630
631 if (CurrentMI == FirstReachedMI) {
632 continue;
633 }
634
636 continue;
637
638
639
640
641
642
643
644
645 if (!usedInLoadStore(CurrentInstSN, NewOffset)) {
646 return false;
647 }
648
649
650
651 RegisterRef FirstReachedDefRR = FirstReachedUseDN.Addr->getRegRef(*DFG);
652 NodeAddr<InstrNode *> CurrentAddiIN = CurrentInstUN.Addr->getOwner(*DFG);
653 NodeAddr<RefNode *> NearestAA =
655 if ((DFG->IsDef(NearestAA) && NearestAA.Id != FirstReachedUseDN.Id) ||
656 (!DFG->IsDef(NearestAA) &&
657 NearestAA.Addr->getReachingDef() != FirstReachedUseDN.Id)) {
658
659 LLVM_DEBUG(dbgs() << "\t\t\tCould not modify below Addi since the first "
660 "defined Addi register was redefined\n");
661 continue;
662 }
663
664 MachineOperand CurrentMIBaseOp = CurrentMI->getOperand(1);
666 continue;
667 }
668
669
670
671 Changed |= updateAddBases(CurrentMI, FirstReachedMI, NewOffset);
672
673
674 CurrentInstUN.Addr->linkToDef(CurrentInstUN.Id, FirstReachedUseDN);
675 }
676
678}
679
680bool HexagonOptAddrMode::updateAddBases(MachineInstr *CurrentMI,
681 MachineInstr *FirstReachedMI,
682 int64_t NewOffset) {
683 LLVM_DEBUG(dbgs() << "[About to modify the Addi]: " << *CurrentMI << "\n");
684 const MachineOperand FirstReachedDef = FirstReachedMI->getOperand(0);
685 Register FirstDefRegister = FirstReachedDef.getReg();
686
687 MachineOperand &CurrentMIBaseOp = CurrentMI->getOperand(1);
688 MachineOperand &CurrentMIImmOp = CurrentMI->getOperand(2);
689
690 CurrentMIBaseOp.setReg(FirstDefRegister);
693 CurrentMIImmOp.setImm(NewOffset);
694 ProcessedAddiInsts.insert(CurrentMI);
695 MRI->clearKillFlags(FirstDefRegister);
696 return true;
697}
698
699bool HexagonOptAddrMode::processAddUses(NodeAddr<StmtNode *> AddSN,
700 MachineInstr *AddMI,
702
705 for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) {
706 NodeAddr<UseNode *> UN = *I;
707 NodeAddr<StmtNode *> SN = UN.Addr->getOwner(*DFG);
708 MachineInstr *MI = SN.Addr->getCode();
709 const MCInstrDesc &MID = MI->getDesc();
712 return false;
713
714 MachineOperand BaseOp = MI->getOperand(getBaseOpPosition(MI));
715
716 if (!BaseOp.isReg() || BaseOp.getReg() != AddDefR)
717 return false;
718
719 MachineOperand OffsetOp = MI->getOperand(getOffsetOpPosition(MI));
721 return false;
722
724 if (!isValidOffset(MI, newOffset))
725 return false;
726
727
728
729
730
731
732
733
734 if (!isSafeToExtLR(AddSN, AddMI, BaseReg, UNodeList))
735 return false;
736 }
737
738 NodeId LRExtRegRD = 0;
739
740
741 for (NodeAddr<UseNode *> UA : AddSN.Addr->members_if(DFG->IsUse, *DFG)) {
742 RegisterRef RR = UA.Addr->getRegRef(*DFG);
743 if (BaseReg == RR.asMCReg())
744 LRExtRegRD = UA.Addr->getReachingDef();
745 }
746
747
748
750 for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) {
751 NodeAddr<UseNode *> UseN = *I;
753 "Found a PhiRef node as a real reached use!!");
754
755 NodeAddr<StmtNode *> OwnerN = UseN.Addr->getOwner(*DFG);
756 MachineInstr *UseMI = OwnerN.Addr->getCode();
758 << ">]: " << *UseMI << "\n");
760
761
762
763
764 NodeAddr<DefNode *> LRExtRegDN = DFG->addr<DefNode *>(LRExtRegRD);
765 UseN.Addr->linkToDef(UseN.Id, LRExtRegDN);
766 }
767
770
772}
773
774bool HexagonOptAddrMode::updateAddUses(MachineInstr *AddMI,
775 MachineInstr *UseMI) {
776 const MachineOperand ImmOp = AddMI->getOperand(2);
777 const MachineOperand AddRegOp = AddMI->getOperand(1);
779
782 BaseOp.setReg(NewReg);
786 MRI->clearKillFlags(NewReg);
787
788 return true;
789}
790
791bool HexagonOptAddrMode::analyzeUses(unsigned tfrDefR,
793 InstrEvalMap &InstrEvalResult,
794 short &SizeInc) {
795 bool KeepTfr = false;
796 bool HasRepInstr = false;
797 InstrEvalResult.clear();
798
799 for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) {
800 bool CanBeReplaced = false;
801 NodeAddr<UseNode *> UN = *I;
802 NodeAddr<StmtNode *> SN = UN.Addr->getOwner(*DFG);
803 MachineInstr &MI = *SN.Addr->getCode();
804 const MCInstrDesc &MID = MI.getDesc();
806 if (!hasRepForm(MI, tfrDefR)) {
807 KeepTfr = true;
808 continue;
809 }
810 SizeInc++;
811 CanBeReplaced = true;
812 } else if (MI.getOpcode() == Hexagon::S2_addasl_rrri) {
814
815 LLVM_DEBUG(dbgs() << "\nGetting ReachedUses for === " << MI << "\n");
816 getAllRealUses(SN, AddaslUseList);
817
818 if (allValidCandidates(SN, AddaslUseList) &&
819 canRemoveAddasl(SN, MI, AddaslUseList)) {
820 SizeInc += AddaslUseList.size();
821 SizeInc -= 1;
822 CanBeReplaced = true;
823 } else
824 SizeInc++;
825 } else
826
827
828
829
830 KeepTfr = true;
831
832 InstrEvalResult[&MI] = CanBeReplaced;
833 HasRepInstr |= CanBeReplaced;
834 }
835
836
837 if (!KeepTfr)
838 SizeInc -= 2;
839
840 return HasRepInstr;
841}
842
843bool HexagonOptAddrMode::changeLoad(MachineInstr *OldMI, MachineOperand ImmOp,
844 unsigned ImmOpNum) {
846 MachineBasicBlock *BB = OldMI->getParent();
849 ++InsertPt;
850 unsigned OpStart;
852 MachineInstrBuilder MIB;
853
854 if (ImmOpNum == 1) {
857 assert(NewOpCode >= 0 && "Invalid New opcode\n");
858 MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode));
862 MIB.add(ImmOp);
863 OpStart = 4;
868 assert(NewOpCode >= 0 && "Invalid New opcode\n");
869 MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode))
871 const GlobalValue *GV = ImmOp.getGlobal();
873
875 OpStart = 3;
877 } else
879
880 LLVM_DEBUG(dbgs() << "[Changing]: " << *OldMI << "\n");
882 } else if (ImmOpNum == 2) {
885 assert(NewOpCode >= 0 && "Invalid New opcode\n");
886 MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode));
889 MIB.add(ImmOp);
890 OpStart = 4;
892 LLVM_DEBUG(dbgs() << "[Changing]: " << *OldMI << "\n");
894 }
895 }
896
898 for (unsigned i = OpStart; i < OpEnd; ++i)
900
902}
903
904bool HexagonOptAddrMode::changeStore(MachineInstr *OldMI, MachineOperand ImmOp,
905 unsigned ImmOpNum) {
907 unsigned OpStart = 0;
909 MachineBasicBlock *BB = OldMI->getParent();
912 ++InsertPt;
913 MachineInstrBuilder MIB;
914 if (ImmOpNum == 0) {
917 assert(NewOpCode >= 0 && "Invalid New opcode\n");
918 MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode));
921 MIB.add(ImmOp);
923 OpStart = 4;
927 assert(NewOpCode >= 0 && "Invalid New opcode\n");
928 MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode));
929 const GlobalValue *GV = ImmOp.getGlobal();
933 OpStart = 3;
935 }
936 } else if (ImmOpNum == 1 && OldMI->getOperand(2).getImm() == 0) {
938 assert(NewOpCode >= 0 && "Invalid New opcode\n");
939 MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode));
941 MIB.add(ImmOp);
942 OpStart = 3;
944 }
946 LLVM_DEBUG(dbgs() << "[Changing]: " << *OldMI << "\n");
948
949 for (unsigned i = OpStart; i < OpEnd; ++i)
951 }
952
954}
955
956short HexagonOptAddrMode::getBaseWithLongOffset(const MachineInstr &MI) const {
960 }
962}
963
964bool HexagonOptAddrMode::changeAddAsl(NodeAddr<UseNode *> AddAslUN,
965 MachineInstr *AddAslMI,
966 const MachineOperand &ImmOp,
967 unsigned ImmOpNum) {
968 NodeAddr<StmtNode *> SA = AddAslUN.Addr->getOwner(*DFG);
969
970 LLVM_DEBUG(dbgs() << "Processing addasl :" << *AddAslMI << "\n");
971
973 getAllRealUses(SA, UNodeList);
974
975 for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) {
976 NodeAddr<UseNode *> UseUN = *I;
978 "Can't transform this 'AddAsl' instruction!");
979
980 NodeAddr<StmtNode *> UseIA = UseUN.Addr->getOwner(*DFG);
982 << Print<NodeAddr<InstrNode *>>(UseIA, *DFG) << "\n");
983 MachineInstr *UseMI = UseIA.Addr->getCode();
985 << ">]: " << *UseMI << "\n");
986 const MCInstrDesc &UseMID = UseMI->getDesc();
988
991 short NewOpCode = getBaseWithLongOffset(*UseMI);
992 assert(NewOpCode >= 0 && "Invalid New opcode\n");
993
994 unsigned OpStart;
996
998 MachineInstrBuilder MIB =
1000
1005 const GlobalValue *GV = ImmOp.getGlobal();
1008 OpStart = 3;
1009 } else if (UseMID.mayStore()) {
1012 const GlobalValue *GV = ImmOp.getGlobal();
1016 OpStart = 3;
1017 } else
1019
1020 for (unsigned i = OpStart; i < OpEnd; ++i)
1023 }
1024
1025 return true;
1026}
1027
1028bool HexagonOptAddrMode::xformUseMI(MachineInstr *TfrMI, MachineInstr *UseMI,
1029 NodeAddr<UseNode *> UseN,
1030 unsigned UseMOnum) {
1031 const MachineOperand ImmOp = TfrMI->getOperand(1);
1033 unsigned Changed = false;
1035 Changed = changeLoad(UseMI, ImmOp, UseMOnum);
1037 Changed = changeStore(UseMI, ImmOp, UseMOnum);
1038 else if (UseMI->getOpcode() == Hexagon::S2_addasl_rrri)
1039 Changed = changeAddAsl(UseN, UseMI, ImmOp, UseMOnum);
1040
1043
1045}
1046
1047bool HexagonOptAddrMode::processBlock(NodeAddr<BlockNode *> BA) {
1049
1050 for (auto IA : BA.Addr->members(*DFG)) {
1052 continue;
1053
1054 NodeAddr<StmtNode *> SA = IA;
1055 MachineInstr *MI = SA.Addr->getCode();
1056 if ((MI->getOpcode() != Hexagon::A2_tfrsi ||
1057 ->getOperand(1).isGlobal()) &&
1058 (MI->getOpcode() != Hexagon::A2_addi ||
1060 continue;
1061
1062 LLVM_DEBUG(dbgs() << "[Analyzing " << HII->getName(MI->getOpcode())
1063 << "]: " << *MI << "\n\t[InstrNode]: "
1064 << Print<NodeAddr<InstrNode *>>(IA, *DFG) << '\n');
1065
1066 if (MI->getOpcode() == Hexagon::A2_addi)
1067 Changed |= processAddBases(SA, MI);
1069 getAllRealUses(SA, UNodeList);
1070
1071 if (!allValidCandidates(SA, UNodeList))
1072 continue;
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084 if (MI->getOpcode() == Hexagon::A2_addi) {
1085 Changed |= processAddUses(SA, MI, UNodeList);
1086 continue;
1087 }
1088
1089 short SizeInc = 0;
1090 Register DefR = MI->getOperand(0).getReg();
1091 InstrEvalMap InstrEvalResult;
1092
1093
1094
1095 if (!analyzeUses(DefR, UNodeList, InstrEvalResult, SizeInc))
1096 continue;
1098 continue;
1099
1100 bool KeepTfr = false;
1101
1102 LLVM_DEBUG(dbgs() << "\t[Total reached uses] : " << UNodeList.size()
1103 << "\n");
1104 LLVM_DEBUG(dbgs() << "\t[Processing Reached Uses] ===\n");
1105 for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) {
1106 NodeAddr<UseNode *> UseN = *I;
1108 "Found a PhiRef node as a real reached use!!");
1109
1110 NodeAddr<StmtNode *> OwnerN = UseN.Addr->getOwner(*DFG);
1111 MachineInstr *UseMI = OwnerN.Addr->getCode();
1113 << ">]: " << *UseMI << "\n");
1114
1115 int UseMOnum = -1;
1117 for (unsigned j = 0; j < NumOperands - 1; ++j) {
1119 if (op.isReg() && op.isUse() && DefR == op.getReg())
1120 UseMOnum = j;
1121 }
1122
1123
1124
1125
1126
1127
1128 bool Xformed = false;
1129 if (UseMOnum >= 0 && InstrEvalResult[UseMI])
1130 Xformed = xformUseMI(MI, UseMI, UseN, UseMOnum);
1132 KeepTfr |= !Xformed;
1133 }
1134 if (!KeepTfr)
1136 }
1138}
1139
1140bool HexagonOptAddrMode::runOnMachineFunction(MachineFunction &MF) {
1142 return false;
1143
1144
1145
1148 << ": too many basic blocks\n");
1149 return false;
1150 }
1151
1153 auto &HST = MF.getSubtarget();
1156 HII = HST.getInstrInfo();
1157 HRI = HST.getRegisterInfo();
1158 const auto &MDF = getAnalysis();
1159 MDT = &getAnalysis().getDomTree();
1160
1161 DataFlowGraph G(MF, *HII, *HRI, *MDT, MDF);
1162
1163
1165 DFG = &G;
1166
1168 L.computePhiInfo();
1169 LV = &L;
1170
1172 ProcessedAddiInsts.clear();
1173 NodeAddr<FuncNode *> FA = DFG->getFunc();
1175 << Print<NodeAddr<FuncNode *>>(FA, *DFG) << "\n");
1176
1177 for (NodeAddr<BlockNode *> BA : FA.Addr->members(*DFG))
1178 Changed |= processBlock(BA);
1179
1181 MI->eraseFromParent();
1182
1184 G.build();
1185 L.computeLiveIns();
1186 L.resetLiveIns();
1187 L.resetKills();
1188 }
1189
1191}
1192
1193
1194
1195
1196
1198 return new HexagonOptAddrMode();
1199}
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder & UseMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file defines the DenseMap class.
This file defines the DenseSet and SmallDenseSet classes.
static cl::opt< int > CodeGrowthLimit("hexagon-amode-growth-limit", cl::Hidden, cl::init(0), cl::desc("Code growth limit for address mode " "optimization"))
cl::opt< unsigned > RDFFuncBlockLimit
std::pair< Instruction::BinaryOps, Value * > OffsetOp
Find all possible pairs (BinOp, RHS) that BinOp V, RHS can be simplified.
Register const TargetRegisterInfo * TRI
Promote Memory to Register
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
AnalysisUsage & addRequired()
void setPreservesAll()
Set by analyses that do not transform their input at all.
FunctionPass class - This class is used to implement most global optimizations.
bool isPredicated(const MachineInstr &MI) const override
Returns true if the instruction is already predicated.
unsigned getAddrMode(const MachineInstr &MI) const
bool isValidOffset(unsigned Opcode, int Offset, const TargetRegisterInfo *TRI, bool Extend=true) const
bool isConstExtended(const MachineInstr &MI) const
short changeAddrMode_rr_ur(short Opc) const
unsigned getMemAccessSize(const MachineInstr &MI) const
short changeAddrMode_io_abs(short Opc) const
short changeAddrMode_rr_io(short Opc) const
bool isHVXVec(const MachineInstr &MI) const
short changeAddrMode_io_rr(short Opc) const
Describe properties that are true of each instruction in the target description file.
bool mayStore() const
Return true if this instruction could possibly modify memory.
bool mayLoad() const
Return true if this instruction could possibly read memory.
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
Instructions::iterator instr_iterator
MachineInstrBundleIterator< MachineInstr > iterator
LLVM_ABI StringRef getName() const
Return the name of the corresponding LLVM basic block, or an empty string.
LLVM_ABI bool isLiveIn(MCRegister Reg, LaneBitmask LaneMask=LaneBitmask::getAll()) const
Return true if the specified register is in the live in set.
Analysis pass which computes a MachineDominatorTree.
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.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
Register getReg(unsigned Idx) const
Get the register for the operand index.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
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.
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
const MachineOperand & getOperand(unsigned i) const
const GlobalValue * getGlobal() const
void setImplicit(bool Val=true)
void setImm(int64_t immVal)
bool isReg() const
isReg - Tests if this is a MO_Register operand.
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
unsigned getTargetFlags() const
void setIsUndef(bool Val=true)
Register getReg() const
getReg - Returns the register number.
int64_t getOffset() const
Return the offset from the symbol in this operand.
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
std::pair< iterator, bool > insert(const ValueT &V)
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
initializer< Ty > init(const Ty &Val)
Print(const T &, const DataFlowGraph &) -> Print< T >
std::set< NodeId > NodeSet
SmallVector< Node, 4 > NodeList
BaseReg
Stack frame base register. Bit 0 of FREInfo.Info.
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.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
FunctionPass * createHexagonOptAddrMode()
Definition HexagonOptAddrMode.cpp:1197
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
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.
static bool IsDef(const Node BA)
static bool IsUse(const Node BA)
const PhysicalRegisterInfo & getPRI() const
static bool IsCode(const Node BA)
std::unordered_map< RegisterId, DefStack > DefStackMap
NodeAddr< T > addr(NodeId N) const
const RefMap & getRealUses(NodeId P) const
NodeAddr< RefNode * > getNearestAliasedRef(RegisterRef RefRR, NodeAddr< InstrNode * > IA)
Find the nearest ref node aliased to RefRR, going upwards in the data flow, starting from the instruc...
std::pair< NodeSet, bool > getAllReachingDefsRec(RegisterRef RefRR, NodeAddr< RefNode * > RefA, NodeSet &Visited, const NodeSet &Defs)
std::unordered_map< RegisterId, NodeRefSet > RefMap
NodeSet getAllReachedUses(RegisterRef RefRR, NodeAddr< DefNode * > DefA, const RegisterAggr &DefRRs)
bool alias(RegisterRef RA, RegisterRef RB) const
constexpr MCRegister asMCReg() const