42#define DEBUG_TYPE "opt-addr-mode"
61 StringRef getPassName()
const override {
62 return "Optimize addressing mode of load/store";
65 void getAnalysisUsage(AnalysisUsage &AU)
const override {
68 AU.
addRequired<MachineDominanceFrontierWrapperPass>();
72 bool runOnMachineFunction(MachineFunction &MF)
override;
75 using MISetType = DenseSet<MachineInstr *>;
76 using InstrEvalMap = DenseMap<MachineInstr *, bool>;
77 DenseSet<MachineInstr *> ProcessedAddiInsts;
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;
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(
96 std::vector<std::pair<NodeAddr<StmtNode *>, NodeAddr<UseNode *>>>
98 NodeAddr<StmtNode *> &UseSN);
99 bool updateAddBases(MachineInstr *CurrentMI, MachineInstr *FirstReachedMI,
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,
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);
126char HexagonOptAddrMode::ID = 0;
129 "Optimize addressing mode",
false,
false)
135bool HexagonOptAddrMode::hasRepForm(
MachineInstr &
MI,
unsigned TfrDefR) {
142 MachineOperand StOp = MI.getOperand(MI.getNumOperands() - 1);
143 if (StOp.isReg() && StOp.getReg() == TfrDefR)
149 return (HII->changeAddrMode_rr_ur(
MI) >= 0);
152 return (HII->changeAddrMode_io_abs(
MI) >= 0);
171 const MachineOperand &
OffsetOp =
MI.getOperand(3);
175 Register OffsetReg =
MI.getOperand(2).getReg();
176 RegisterRef OffsetRR;
178 for (NodeAddr<UseNode *> UA : AddAslSN.
Addr->members_if(DFG->
IsUse, *DFG)) {
179 RegisterRef RR = UA.Addr->getRegRef(*DFG);
180 if (OffsetReg == RR.
asMCReg()) {
182 OffsetRegRD = UA.Addr->getReachingDef();
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);
192 if ((DFG->
IsDef(AA) && AA.
Id != OffsetRegRD) ||
193 AA.
Addr->getReachingDef() != OffsetRegRD)
196 MachineInstr &
UseMI = *NodeAddr<StmtNode *>(IA).Addr->getCode();
197 NodeAddr<DefNode *> OffsetRegDN = DFG->
addr<DefNode *>(OffsetRegRD);
200 MI.getParent() !=
UseMI.getParent())
203 const MCInstrDesc &UseMID =
UseMI.getDesc();
206 getBaseWithLongOffset(
UseMI) < 0)
214 for (
auto &Mo :
UseMI.operands())
219 if (!
UseMI.getParent()->isLiveIn(OffsetReg) &&
220 MI.getParent() !=
UseMI.getParent()) {
222 <<
" is NOT live in to MBB "
223 <<
UseMI.getParent()->getName() <<
"\n");
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);
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";
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]: "
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);
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]: "
280 NodeAddr<PhiNode *> PA = UA.
Addr->getOwner(*DFG);
285 if (!phiUse.empty()) {
286 for (
auto I : phiUse) {
289 auto phiUseSet =
I.second;
290 for (
auto phiUI : phiUseSet) {
291 NodeAddr<UseNode *> phiUA = DFG->
addr<UseNode *>(phiUI.first);
292 UNodeList.push_back(phiUA);
297 UNodeList.push_back(UA);
302bool HexagonOptAddrMode::isSafeToExtLR(NodeAddr<StmtNode *> SN,
309 for (NodeAddr<UseNode *> UA : SN.
Addr->members_if(DFG->
IsUse, *DFG)) {
310 RegisterRef RR = UA.
Addr->getRegRef(*DFG);
311 if (LRExtReg == RR.
asMCReg()) {
313 LRExtRegRD = UA.
Addr->getReachingDef();
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);
325 if ((DFG->
IsDef(AA) && AA.
Id != LRExtRegRD) ||
326 AA.
Addr->getReachingDef() != LRExtRegRD) {
328 dbgs() <<
"isSafeToExtLR: Returning false; another reaching def\n");
338 MachineInstr *
UseMI = NodeAddr<StmtNode *>(IA).Addr->getCode();
339 NodeAddr<DefNode *> LRExtRegDN = DFG->
addr<DefNode *>(LRExtRegRD);
348 <<
" is NOT live in to MBB "
356bool HexagonOptAddrMode::isValidOffset(MachineInstr *
MI,
int Offset) {
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:
372 if ((AlignMask &
Offset) == 0)
382 unsigned AlignMask = 0;
384 case HexagonII::MemAccessSize::DoubleWordAccess:
387 case HexagonII::MemAccessSize::WordAccess:
390 case HexagonII::MemAccessSize::HalfWordAccess:
393 case HexagonII::MemAccessSize::ByteAccess:
400 if ((AlignMask &
Offset) != 0)
405unsigned HexagonOptAddrMode::getBaseOpPosition(MachineInstr *
MI) {
406 const MCInstrDesc &MID =
MI->getDesc();
407 switch (
MI->getOpcode()) {
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:
423unsigned HexagonOptAddrMode::getOffsetOpPosition(MachineInstr *
MI) {
426 "Looking for an offset in non-BaseImmOffset addressing mode instruction");
428 const MCInstrDesc &MID =
MI->getDesc();
429 switch (
MI->getOpcode()) {
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:
445bool HexagonOptAddrMode::usedInLoadStore(NodeAddr<StmtNode *> CurrentInstSN,
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;
461 return FoundLoadStoreUse;
464bool HexagonOptAddrMode::findFirstReachedInst(
466 std::vector<std::pair<NodeAddr<StmtNode *>, NodeAddr<UseNode *>>> &AddiList,
467 NodeAddr<StmtNode *> &UseSN) {
480 MachineBasicBlock *CurrentMBB = AddMI->
getParent();
481 for (
auto &InstIter : *CurrentMBB) {
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;
487 if (Iter != AddiList.end()) {
521bool HexagonOptAddrMode::processAddBases(NodeAddr<StmtNode *> AddSN,
522 MachineInstr *AddMI) {
526 LLVM_DEBUG(
dbgs() <<
"\n\t\t[Processing Addi]: " << *AddMI <<
"\n");
529 [](
const MachineInstr *
MI,
530 const DenseSet<MachineInstr *> &ProcessedAddiInsts) ->
bool {
533 LLVM_DEBUG(
dbgs() <<
"\t\t\tAddi already found in ProcessedAddiInsts: "
534 << *
MI <<
"\n\t\t\tSkipping...");
540 if (Processed(AddMI, ProcessedAddiInsts))
542 ProcessedAddiInsts.
insert(AddMI);
549 std::vector<std::pair<NodeAddr<StmtNode *>, NodeAddr<UseNode *>>> AddiList;
553 for (NodeAddr<UseNode *> UA : AddSN.
Addr->members_if(DFG->
IsUse, *DFG)) {
554 RegisterRef URR = UA.
Addr->getRegRef(*DFG);
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");
566 NodeAddr<DefNode *> UAReachingDef = DFG->
addr<DefNode *>(UAReachingDefID);
567 NodeAddr<StmtNode *> ReachingDefStmt = UAReachingDef.
Addr->getOwner(*DFG);
571 MachineInstr *ReachingDefInstr = ReachingDefStmt.Addr->getCode();
579 getAllRealUses(ReachingDefStmt, AddiUseList);
580 for (NodeAddr<UseNode *> UN : AddiUseList) {
581 NodeAddr<StmtNode *> SN = UN.
Addr->getOwner(*DFG);
582 MachineInstr *
MI = SN.
Addr->getCode();
585 if (
MI->getOpcode() == Hexagon::A2_addi &&
586 !(
MI != AddMI && Processed(
MI, ProcessedAddiInsts))) {
587 AddiList.push_back({SN, UN});
595 if (AddiList.size() <= 1)
598 NodeAddr<StmtNode *> FirstReachedUseSN;
600 if (!findFirstReachedInst(AddMI, AddiList, FirstReachedUseSN))
606 NodeAddr<DefNode *> FirstReachedUseDN =
607 FirstReachedUseSN.
Addr->members_if(DFG->
IsDef, *DFG).front();
609 MachineInstr *FirstReachedMI = FirstReachedUseSN.
Addr->getCode();
610 const MachineOperand FirstReachedMIImmOp = FirstReachedMI->
getOperand(2);
611 if (!FirstReachedMIImmOp.
isImm())
614 for (
auto &
I : AddiList) {
615 NodeAddr<StmtNode *> CurrentInstSN =
I.first;
616 NodeAddr<UseNode *> CurrentInstUN =
I.second;
618 MachineInstr *CurrentMI = CurrentInstSN.
Addr->getCode();
619 MachineOperand &CurrentMIImmOp = CurrentMI->
getOperand(2);
625 if (!CurrentMIImmOp.
isImm())
628 NewOffset = CurrentMIImmOp.
getImm() - FirstReachedMIImmOp.
getImm();
631 if (CurrentMI == FirstReachedMI) {
645 if (!usedInLoadStore(CurrentInstSN, NewOffset)) {
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)) {
659 LLVM_DEBUG(
dbgs() <<
"\t\t\tCould not modify below Addi since the first "
660 "defined Addi register was redefined\n");
664 MachineOperand CurrentMIBaseOp = CurrentMI->
getOperand(1);
671 Changed |= updateAddBases(CurrentMI, FirstReachedMI, NewOffset);
674 CurrentInstUN.
Addr->linkToDef(CurrentInstUN.
Id, FirstReachedUseDN);
680bool HexagonOptAddrMode::updateAddBases(MachineInstr *CurrentMI,
681 MachineInstr *FirstReachedMI,
683 LLVM_DEBUG(
dbgs() <<
"[About to modify the Addi]: " << *CurrentMI <<
"\n");
684 const MachineOperand FirstReachedDef = FirstReachedMI->
getOperand(0);
687 MachineOperand &CurrentMIBaseOp = CurrentMI->
getOperand(1);
688 MachineOperand &CurrentMIImmOp = CurrentMI->
getOperand(2);
690 CurrentMIBaseOp.
setReg(FirstDefRegister);
693 CurrentMIImmOp.
setImm(NewOffset);
694 ProcessedAddiInsts.
insert(CurrentMI);
699bool HexagonOptAddrMode::processAddUses(NodeAddr<StmtNode *> AddSN,
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();
714 MachineOperand BaseOp =
MI->getOperand(getBaseOpPosition(
MI));
719 MachineOperand
OffsetOp =
MI->getOperand(getOffsetOpPosition(
MI));
724 if (!isValidOffset(
MI, newOffset))
737 if (!isSafeToExtLR(AddSN, AddMI, BaseReg, UNodeList))
743 for (NodeAddr<UseNode *> UA : AddSN.
Addr->members_if(DFG->
IsUse, *DFG)) {
744 RegisterRef RR = UA.
Addr->getRegRef(*DFG);
746 LRExtRegRD = UA.
Addr->getReachingDef();
752 for (
auto I = UNodeList.rbegin(),
E = UNodeList.rend();
I !=
E; ++
I) {
753 NodeAddr<UseNode *> UseN = *
I;
755 "Found a PhiRef node as a real reached use!!");
757 NodeAddr<StmtNode *> OwnerN = UseN.
Addr->getOwner(*DFG);
758 MachineInstr *
UseMI = OwnerN.
Addr->getCode();
760 <<
">]: " << *
UseMI <<
"\n");
766 NodeAddr<DefNode *> LRExtRegDN = DFG->
addr<DefNode *>(LRExtRegRD);
767 UseN.
Addr->linkToDef(UseN.
Id, LRExtRegDN);
776bool HexagonOptAddrMode::updateAddUses(MachineInstr *AddMI,
777 MachineInstr *
UseMI) {
778 const MachineOperand ImmOp = AddMI->
getOperand(2);
779 const MachineOperand AddRegOp = AddMI->
getOperand(1);
793bool HexagonOptAddrMode::analyzeUses(
unsigned tfrDefR,
795 InstrEvalMap &InstrEvalResult,
797 bool KeepTfr =
false;
798 bool HasRepInstr =
false;
799 InstrEvalResult.clear();
801 for (
auto I = UNodeList.rbegin(),
E = UNodeList.rend();
I !=
E; ++
I) {
802 bool CanBeReplaced =
false;
803 NodeAddr<UseNode *> UN = *
I;
804 NodeAddr<StmtNode *> SN = UN.
Addr->getOwner(*DFG);
805 MachineInstr &
MI = *SN.
Addr->getCode();
806 const MCInstrDesc &MID =
MI.getDesc();
808 if (!hasRepForm(
MI, tfrDefR)) {
813 CanBeReplaced =
true;
814 }
else if (
MI.getOpcode() == Hexagon::S2_addasl_rrri) {
818 getAllRealUses(SN, AddaslUseList);
820 if (allValidCandidates(SN, AddaslUseList) &&
821 canRemoveAddasl(SN,
MI, AddaslUseList)) {
822 SizeInc += AddaslUseList.size();
824 CanBeReplaced =
true;
834 InstrEvalResult[&
MI] = CanBeReplaced;
835 HasRepInstr |= CanBeReplaced;
845bool HexagonOptAddrMode::changeLoad(MachineInstr *OldMI, MachineOperand ImmOp,
848 MachineBasicBlock *BB = OldMI->
getParent();
854 MachineInstrBuilder MIB;
859 assert(NewOpCode >= 0 &&
"Invalid New opcode\n");
870 assert(NewOpCode >= 0 &&
"Invalid New opcode\n");
873 const GlobalValue *GV = ImmOp.
getGlobal();
884 }
else if (ImmOpNum == 2) {
887 assert(NewOpCode >= 0 &&
"Invalid New opcode\n");
900 for (
unsigned i = OpStart; i < OpEnd; ++i)
906bool HexagonOptAddrMode::changeStore(MachineInstr *OldMI, MachineOperand ImmOp,
909 unsigned OpStart = 0;
911 MachineBasicBlock *BB = OldMI->
getParent();
915 MachineInstrBuilder MIB;
919 assert(NewOpCode >= 0 &&
"Invalid New opcode\n");
929 assert(NewOpCode >= 0 &&
"Invalid New opcode\n");
931 const GlobalValue *GV = ImmOp.
getGlobal();
940 assert(NewOpCode >= 0 &&
"Invalid New opcode\n");
951 for (
unsigned i = OpStart; i < OpEnd; ++i)
958short HexagonOptAddrMode::getBaseWithLongOffset(
const MachineInstr &
MI)
const {
966bool HexagonOptAddrMode::changeAddAsl(NodeAddr<UseNode *> AddAslUN,
967 MachineInstr *AddAslMI,
968 const MachineOperand &ImmOp,
970 NodeAddr<StmtNode *> SA = AddAslUN.
Addr->getOwner(*DFG);
975 getAllRealUses(SA, UNodeList);
977 for (
auto I = UNodeList.rbegin(),
E = UNodeList.rend();
I !=
E; ++
I) {
978 NodeAddr<UseNode *> UseUN = *
I;
980 "Can't transform this 'AddAsl' instruction!");
982 NodeAddr<StmtNode *> UseIA = UseUN.
Addr->getOwner(*DFG);
984 <<
Print<NodeAddr<InstrNode *>>(UseIA, *DFG) <<
"\n");
985 MachineInstr *
UseMI = UseIA.
Addr->getCode();
987 <<
">]: " << *
UseMI <<
"\n");
993 short NewOpCode = getBaseWithLongOffset(*
UseMI);
994 assert(NewOpCode >= 0 &&
"Invalid New opcode\n");
1000 MachineInstrBuilder MIB =
1007 const GlobalValue *GV = ImmOp.
getGlobal();
1014 const GlobalValue *GV = ImmOp.
getGlobal();
1022 for (
unsigned i = OpStart; i < OpEnd; ++i)
1030bool HexagonOptAddrMode::xformUseMI(MachineInstr *TfrMI, MachineInstr *
UseMI,
1031 NodeAddr<UseNode *> UseN,
1032 unsigned UseMOnum) {
1033 const MachineOperand ImmOp = TfrMI->
getOperand(1);
1049bool HexagonOptAddrMode::processBlock(NodeAddr<BlockNode *> BA) {
1052 for (
auto IA : BA.
Addr->members(*DFG)) {
1056 NodeAddr<StmtNode *> SA =
IA;
1057 MachineInstr *
MI = SA.
Addr->getCode();
1058 if ((
MI->getOpcode() != Hexagon::A2_tfrsi ||
1059 !
MI->getOperand(1).isGlobal()) &&
1060 (
MI->getOpcode() != Hexagon::A2_addi ||
1065 <<
"]: " << *
MI <<
"\n\t[InstrNode]: "
1066 <<
Print<NodeAddr<InstrNode *>>(IA, *DFG) <<
'\n');
1068 if (
MI->getOpcode() == Hexagon::A2_addi)
1071 getAllRealUses(SA, UNodeList);
1073 if (!allValidCandidates(SA, UNodeList))
1086 if (
MI->getOpcode() == Hexagon::A2_addi) {
1087 Changed |= processAddUses(SA,
MI, UNodeList);
1093 InstrEvalMap InstrEvalResult;
1097 if (!analyzeUses(DefR, UNodeList, InstrEvalResult, SizeInc))
1102 bool KeepTfr =
false;
1104 LLVM_DEBUG(
dbgs() <<
"\t[Total reached uses] : " << UNodeList.size()
1107 for (
auto I = UNodeList.rbegin(),
E = UNodeList.rend();
I !=
E; ++
I) {
1108 NodeAddr<UseNode *> UseN = *
I;
1110 "Found a PhiRef node as a real reached use!!");
1112 NodeAddr<StmtNode *> OwnerN = UseN.
Addr->getOwner(*DFG);
1113 MachineInstr *
UseMI = OwnerN.
Addr->getCode();
1115 <<
">]: " << *
UseMI <<
"\n");
1119 for (
unsigned j = 0;
j < NumOperands - 1; ++
j) {
1121 if (
op.isReg() &&
op.isUse() && DefR ==
op.getReg())
1130 bool Xformed =
false;
1131 if (UseMOnum >= 0 && InstrEvalResult[
UseMI])
1132 Xformed = xformUseMI(
MI,
UseMI, UseN, UseMOnum);
1134 KeepTfr |= !Xformed;
1142bool HexagonOptAddrMode::runOnMachineFunction(MachineFunction &MF) {
1150 <<
": too many basic blocks\n");
1158 HII = HST.getInstrInfo();
1159 HRI = HST.getRegisterInfo();
1160 const auto &MDF = getAnalysis<MachineDominanceFrontierWrapperPass>().getMDF();
1161 MDT = &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
1163 DataFlowGraph
G(MF, *HII, *HRI, *MDT, MDF);
1169 Liveness
L(*MRI, *DFG);
1174 ProcessedAddiInsts.
clear();
1175 NodeAddr<FuncNode *> FA = DFG->
getFunc();
1177 <<
Print<NodeAddr<FuncNode *>>(FA, *DFG) <<
"\n");
1179 for (NodeAddr<BlockNode *> BA : FA.
Addr->members(*DFG))
1183 MI->eraseFromParent();
1200 return new HexagonOptAddrMode();
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.
LLVM_ABI void clearKillFlags(Register Reg) const
clearKillFlags - Iterate over all the uses of the given register and clear the kill flag from the Mac...
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()
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