1 //===--- HexagonOptAddrMode.cpp -------------------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 // This implements a Hexagon-specific pass to optimize addressing mode for
10 // load/store instructions.
11 //===----------------------------------------------------------------------===//
12 
13 #define DEBUG_TYPE "opt-addr-mode"
14 
15 #include "HexagonTargetMachine.h"
16 #include "RDFGraph.h"
17 #include "RDFLiveness.h"
18 
19 #include "llvm/ADT/DenseSet.h"
20 #include "llvm/CodeGen/MachineBasicBlock.h"
21 #include "llvm/CodeGen/MachineDominanceFrontier.h"
22 #include "llvm/CodeGen/MachineDominators.h"
23 #include "llvm/CodeGen/MachineFunction.h"
24 #include "llvm/CodeGen/MachineInstrBuilder.h"
25 #include "llvm/CodeGen/MachineRegisterInfo.h"
26 #include "llvm/CodeGen/Passes.h"
27 #include "llvm/Support/CommandLine.h"
28 #include "llvm/Support/Debug.h"
29 #include "llvm/Support/raw_ostream.h"
30 #include "llvm/Target/TargetInstrInfo.h"
31 #include "llvm/Target/TargetMachine.h"
32 #include "llvm/Target/TargetRegisterInfo.h"
33 
34 static cl::opt<int> CodeGrowthLimit("hexagon-amode-growth-limit",
35   cl::Hidden, cl::init(0), cl::desc("Code growth limit for address mode "
36   "optimization"));
37 
38 using namespace llvm;
39 using namespace rdf;
40 
41 namespace llvm {
42   FunctionPass *createHexagonOptAddrMode();
43   void initializeHexagonOptAddrModePass(PassRegistry &);
44 }
45 
46 namespace {
47 class HexagonOptAddrMode : public MachineFunctionPass {
48 public:
49   static char ID;
50   HexagonOptAddrMode()
51       : MachineFunctionPass(ID), HII(0), MDT(0), DFG(0), LV(0) {
52     PassRegistry &R = *PassRegistry::getPassRegistry();
53     initializeHexagonOptAddrModePass(R);
54   }
55   const char *getPassName() const override {
56     return "Optimize addressing mode of load/store";
57   }
58   void getAnalysisUsage(AnalysisUsage &AU) const override {
59     MachineFunctionPass::getAnalysisUsage(AU);
60     AU.addRequired<MachineDominatorTree>();
61     AU.addRequired<MachineDominanceFrontier>();
62     AU.setPreservesAll();
63   }
64   bool runOnMachineFunction(MachineFunction &MF) override;
65 
66 private:
67   typedef DenseSet<MachineInstr *> MISetType;
68   typedef DenseMap<MachineInstr *, bool> InstrEvalMap;
69   const HexagonInstrInfo *HII;
70   MachineDominatorTree *MDT;
71   DataFlowGraph *DFG;
72   DataFlowGraph::DefStackMap DefM;
73   std::map<RegisterRef, std::map<NodeId, NodeId>> RDefMap;
74   Liveness *LV;
75   MISetType Deleted;
76 
77   bool processBlock(NodeAddr<BlockNode *> BA);
78   bool xformUseMI(MachineInstr *TfrMI, MachineInstr *UseMI,
79                   NodeAddr<UseNode *> UseN, unsigned UseMOnum);
80   bool analyzeUses(unsigned DefR, const NodeList &UNodeList,
81                    InstrEvalMap &InstrEvalResult, short &SizeInc);
82   bool hasRepForm(MachineInstr *MI, unsigned TfrDefR);
83   MachineInstr *getReachedDefMI(NodeAddr<StmtNode *> SN, unsigned OffsetReg,
84                                 bool &HasReachingDef);
85   bool canRemoveAddasl(NodeAddr<StmtNode *> AddAslSN, MachineInstr *MI,
86                        const NodeList &UNodeList);
87   void getAllRealUses(NodeAddr<StmtNode *> SN, NodeList &UNodeList);
88   bool allValidCandidates(NodeAddr<StmtNode *> SA, NodeList &UNodeList);
89   short getBaseWithLongOffset(const MachineInstr *MI) const;
90   void updateMap(NodeAddr<InstrNode *> IA);
91   bool constructDefMap(MachineBasicBlock *B);
92   bool changeStore(MachineInstr *OldMI, MachineOperand ImmOp,
93                    unsigned ImmOpNum);
94   bool changeLoad(MachineInstr *OldMI, MachineOperand ImmOp, unsigned ImmOpNum);
95   bool changeAddAsl(NodeAddr<UseNode *> AddAslUN, MachineInstr *AddAslMI,
96                     const MachineOperand &ImmOp, unsigned ImmOpNum);
97 };
98 }
99 
100 char HexagonOptAddrMode::ID = 0;
101 
102 INITIALIZE_PASS_BEGIN(HexagonOptAddrMode, "opt-amode",
103                       "Optimize addressing mode", false, false)
104 INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)
105 INITIALIZE_PASS_DEPENDENCY(MachineDominanceFrontier)
106 INITIALIZE_PASS_END(HexagonOptAddrMode, "opt-amode", "Optimize addressing mode",
107                     false, false)
108 
109 bool HexagonOptAddrMode::hasRepForm(MachineInstr *MI, unsigned TfrDefR) {
110   const MCInstrDesc &MID = MI->getDesc();
111 
112   if ((!MID.mayStore() && !MID.mayLoad()) || HII->isPredicated(*MI))
113     return false;
114 
115   if (MID.mayStore()) {
116     MachineOperand StOp = MI->getOperand(MI->getNumOperands() - 1);
117     if (StOp.isReg() && StOp.getReg() == TfrDefR)
118       return false;
119   }
120 
121   if (HII->getAddrMode(MI) == HexagonII::BaseRegOffset)
122     // Tranform to Absolute plus register offset.
123     return (HII->getBaseWithLongOffset(MI) >= 0);
124   else if (HII->getAddrMode(MI) == HexagonII::BaseImmOffset)
125     // Tranform to absolute addressing mode.
126     return (HII->getAbsoluteForm(MI) >= 0);
127 
128   return false;
129 }
130 
131 MachineInstr *HexagonOptAddrMode::getReachedDefMI(NodeAddr<StmtNode *> SN,
132                                                   unsigned OffsetReg,
133                                                   bool &HasReachingDef) {
134   MachineInstr *ReachedDefMI = NULL;
135   NodeId RD = 0;
136   for (NodeAddr<UseNode *> UN : SN.Addr->members_if(DFG->IsUse, *DFG)) {
137     RegisterRef UR = UN.Addr->getRegRef();
138     if (OffsetReg == UR.Reg) {
139       RD = UN.Addr->getReachingDef();
140       if (!RD)
141         continue;
142       HasReachingDef = true;
143     }
144   }
145   if (HasReachingDef) {
146     NodeAddr<DefNode *> RDN = DFG->addr<DefNode *>(RD);
147     DEBUG({
148       NodeAddr<StmtNode *> ReachingIA = RDN.Addr->getOwner(*DFG);
149       dbgs() << "\t\t\t[Def Node]: "
150              << Print<NodeAddr<InstrNode *>>(ReachingIA, *DFG) << "\n";
151     });
152     NodeId ReachedID = RDN.Addr->getReachedDef();
153     if (!ReachedID)
154       return ReachedDefMI;
155 
156     NodeAddr<DefNode *> ReachedDN = DFG->addr<DefNode *>(ReachedID);
157     NodeAddr<StmtNode *> ReachedIA = ReachedDN.Addr->getOwner(*DFG);
158     DEBUG(dbgs() << "\t\t\t[Reached Def Node]: "
159                  << Print<NodeAddr<InstrNode *>>(ReachedIA, *DFG) << "\n");
160     ReachedDefMI = ReachedIA.Addr->getCode();
161     DEBUG(dbgs() << "\nReached Def MI === " << *ReachedDefMI << "\n");
162   }
163   return ReachedDefMI;
164 }
165 
166 // Check if addasl instruction can be removed. This is possible only
167 // if it's feeding to only load/store instructions with base + register
168 // offset as these instruction can be tranformed to use 'absolute plus
169 // shifted register offset'.
170 // ex:
171 // Rs = ##foo
172 // Rx = addasl(Rs, Rt, #2)
173 // Rd = memw(Rx + #28)
174 // Above three instructions can be replaced with Rd = memw(Rt<<#2 + ##foo+28)
175 
176 bool HexagonOptAddrMode::canRemoveAddasl(NodeAddr<StmtNode *> AddAslSN,
177                                          MachineInstr *MI,
178                                          const NodeList &UNodeList) {
179   // check offset size in addasl. if 'offset > 3' return false
180   const MachineOperand &OffsetOp = MI->getOperand(3);
181   if (!OffsetOp.isImm() || OffsetOp.getImm() > 3)
182     return false;
183 
184   unsigned OffsetReg = MI->getOperand(2).getReg();
185   RegisterRef OffsetRR;
186   NodeId OffsetRegRD = 0;
187   for (NodeAddr<UseNode *> UA : AddAslSN.Addr->members_if(DFG->IsUse, *DFG)) {
188     RegisterRef RR = UA.Addr->getRegRef();
189     if (OffsetReg == RR.Reg) {
190       OffsetRR = RR;
191       OffsetRegRD = UA.Addr->getReachingDef();
192     }
193   }
194 
195   for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) {
196     NodeAddr<UseNode *> UA = *I;
197     NodeAddr<InstrNode *> IA = UA.Addr->getOwner(*DFG);
198     if ((UA.Addr->getFlags() & NodeAttrs::PhiRef) ||
199         RDefMap[OffsetRR][IA.Id] != OffsetRegRD)
200       return false;
201 
202     MachineInstr *UseMI = NodeAddr<StmtNode *>(IA).Addr->getCode();
203     NodeAddr<DefNode *> OffsetRegDN = DFG->addr<DefNode *>(OffsetRegRD);
204     // Reaching Def to an offset register can't be a phi.
205     if ((OffsetRegDN.Addr->getFlags() & NodeAttrs::PhiRef) &&
206         MI->getParent() != UseMI->getParent())
207     return false;
208 
209     const MCInstrDesc &UseMID = UseMI->getDesc();
210     if ((!UseMID.mayLoad() && !UseMID.mayStore()) ||
211         HII->getAddrMode(UseMI) != HexagonII::BaseImmOffset ||
212         getBaseWithLongOffset(UseMI) < 0)
213       return false;
214 
215     // Addasl output can't be a store value.
216     if (UseMID.mayStore() && UseMI->getOperand(2).isReg() &&
217         UseMI->getOperand(2).getReg() == MI->getOperand(0).getReg())
218       return false;
219 
220     for (auto &Mo : UseMI->operands())
221       if (Mo.isFI())
222         return false;
223   }
224   return true;
225 }
226 
227 bool HexagonOptAddrMode::allValidCandidates(NodeAddr<StmtNode *> SA,
228                                             NodeList &UNodeList) {
229   for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) {
230     NodeAddr<UseNode *> UN = *I;
231     RegisterRef UR = UN.Addr->getRegRef();
232     NodeSet Visited, Defs;
233     const auto &ReachingDefs = LV->getAllReachingDefsRec(UR, UN, Visited, Defs);
234     if (ReachingDefs.size() > 1) {
235       DEBUG({
236         dbgs() << "*** Multiple Reaching Defs found!!! ***\n";
237         for (auto DI : ReachingDefs) {
238           NodeAddr<UseNode *> DA = DFG->addr<UseNode *>(DI);
239           NodeAddr<StmtNode *> TempIA = DA.Addr->getOwner(*DFG);
240           dbgs() << "\t\t[Reaching Def]: "
241                  << Print<NodeAddr<InstrNode *>>(TempIA, *DFG) << "\n";
242         }
243       });
244       return false;
245     }
246   }
247   return true;
248 }
249 
250 void HexagonOptAddrMode::getAllRealUses(NodeAddr<StmtNode *> SA,
251                                         NodeList &UNodeList) {
252   for (NodeAddr<DefNode *> DA : SA.Addr->members_if(DFG->IsDef, *DFG)) {
253     DEBUG(dbgs() << "\t\t[DefNode]: " << Print<NodeAddr<DefNode *>>(DA, *DFG)
254                  << "\n");
255     RegisterRef DR = DA.Addr->getRegRef();
256     auto UseSet = LV->getAllReachedUses(DR, DA);
257 
258     for (auto UI : UseSet) {
259       NodeAddr<UseNode *> UA = DFG->addr<UseNode *>(UI);
260       DEBUG({
261         NodeAddr<StmtNode *> TempIA = UA.Addr->getOwner(*DFG);
262         dbgs() << "\t\t\t[Reached Use]: "
263                << Print<NodeAddr<InstrNode *>>(TempIA, *DFG) << "\n";
264       });
265 
266       if (UA.Addr->getFlags() & NodeAttrs::PhiRef) {
267         NodeAddr<PhiNode *> PA = UA.Addr->getOwner(*DFG);
268         NodeId id = PA.Id;
269         const Liveness::RefMap &phiUse = LV->getRealUses(id);
270         DEBUG(dbgs() << "\t\t\t\tphi real Uses"
271                      << Print<Liveness::RefMap>(phiUse, *DFG) << "\n");
272         if (phiUse.size() > 0) {
273           for (auto I : phiUse) {
274             if (DR != I.first)
275               continue;
276             auto phiUseSet = I.second;
277             for (auto phiUI : phiUseSet) {
278               NodeAddr<UseNode *> phiUA = DFG->addr<UseNode *>(phiUI);
279               UNodeList.push_back(phiUA);
280             }
281           }
282         }
283       } else
284         UNodeList.push_back(UA);
285     }
286   }
287 }
288 
289 bool HexagonOptAddrMode::analyzeUses(unsigned tfrDefR,
290                                      const NodeList &UNodeList,
291                                      InstrEvalMap &InstrEvalResult,
292                                      short &SizeInc) {
293   bool KeepTfr = false;
294   bool HasRepInstr = false;
295   InstrEvalResult.clear();
296 
297   for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) {
298     bool CanBeReplaced = false;
299     NodeAddr<UseNode *> UN = *I;
300     NodeAddr<StmtNode *> SN = UN.Addr->getOwner(*DFG);
301     MachineInstr *MI = SN.Addr->getCode();
302     const MCInstrDesc &MID = MI->getDesc();
303     if ((MID.mayLoad() || MID.mayStore())) {
304       if (!hasRepForm(MI, tfrDefR)) {
305         KeepTfr = true;
306         continue;
307       }
308       SizeInc++;
309       CanBeReplaced = true;
310     } else if (MI->getOpcode() == Hexagon::S2_addasl_rrri) {
311       NodeList AddaslUseList;
312 
313       DEBUG(dbgs() << "\nGetting ReachedUses for === " << *MI << "\n");
314       getAllRealUses(SN, AddaslUseList);
315       // Process phi nodes.
316       if (allValidCandidates(SN, AddaslUseList) &&
317           canRemoveAddasl(SN, MI, AddaslUseList)) {
318         SizeInc += AddaslUseList.size();
319         SizeInc -= 1; // Reduce size by 1 as addasl itself can be removed.
320         CanBeReplaced = true;
321       } else
322         SizeInc++;
323     } else
324       // Currently, only load/store and addasl are handled.
325       // Some other instructions to consider -
326       // A2_add -> A2_addi
327       // M4_mpyrr_addr -> M4_mpyrr_addi
328       KeepTfr = true;
329 
330     InstrEvalResult[MI] = CanBeReplaced;
331     HasRepInstr |= CanBeReplaced;
332   }
333 
334   // Reduce total size by 2 if original tfr can be deleted.
335   if (!KeepTfr)
336     SizeInc -= 2;
337 
338   return HasRepInstr;
339 }
340 
341 bool HexagonOptAddrMode::changeLoad(MachineInstr *OldMI, MachineOperand ImmOp,
342                                     unsigned ImmOpNum) {
343   bool Changed = false;
344   MachineBasicBlock *BB = OldMI->getParent();
345   auto UsePos = MachineBasicBlock::iterator(OldMI);
346   MachineBasicBlock::instr_iterator InsertPt = UsePos.getInstrIterator();
347   ++InsertPt;
348   unsigned OpStart;
349   unsigned OpEnd = OldMI->getNumOperands();
350   MachineInstrBuilder MIB;
351 
352   if (ImmOpNum == 1) {
353     if (HII->getAddrMode(OldMI) == HexagonII::BaseRegOffset) {
354       short NewOpCode = HII->getBaseWithLongOffset(OldMI);
355       assert(NewOpCode >= 0 && "Invalid New opcode\n");
356       MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode));
357       MIB.addOperand(OldMI->getOperand(0));
358       MIB.addOperand(OldMI->getOperand(2));
359       MIB.addOperand(OldMI->getOperand(3));
360       MIB.addOperand(ImmOp);
361       OpStart = 4;
362       Changed = true;
363     } else if (HII->getAddrMode(OldMI) == HexagonII::BaseImmOffset) {
364       short NewOpCode = HII->getAbsoluteForm(OldMI);
365       assert(NewOpCode >= 0 && "Invalid New opcode\n");
366       MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode))
367                 .addOperand(OldMI->getOperand(0));
368       const GlobalValue *GV = ImmOp.getGlobal();
369       int64_t Offset = ImmOp.getOffset() + OldMI->getOperand(2).getImm();
370 
371       MIB.addGlobalAddress(GV, Offset, ImmOp.getTargetFlags());
372       OpStart = 3;
373       Changed = true;
374     } else
375       Changed = false;
376 
377     DEBUG(dbgs() << "[Changing]: " << *OldMI << "\n");
378     DEBUG(dbgs() << "[TO]: " << MIB << "\n");
379   } else if (ImmOpNum == 2 && OldMI->getOperand(3).getImm() == 0) {
380     short NewOpCode = HII->xformRegToImmOffset(OldMI);
381     assert(NewOpCode >= 0 && "Invalid New opcode\n");
382     MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode));
383     MIB.addOperand(OldMI->getOperand(0));
384     MIB.addOperand(OldMI->getOperand(1));
385     MIB.addOperand(ImmOp);
386     OpStart = 4;
387     Changed = true;
388     DEBUG(dbgs() << "[Changing]: " << *OldMI << "\n");
389     DEBUG(dbgs() << "[TO]: " << MIB << "\n");
390   }
391 
392   if (Changed)
393     for (unsigned i = OpStart; i < OpEnd; ++i)
394       MIB.addOperand(OldMI->getOperand(i));
395 
396   return Changed;
397 }
398 
399 bool HexagonOptAddrMode::changeStore(MachineInstr *OldMI, MachineOperand ImmOp,
400                                      unsigned ImmOpNum) {
401   bool Changed = false;
402   unsigned OpStart;
403   unsigned OpEnd = OldMI->getNumOperands();
404   MachineBasicBlock *BB = OldMI->getParent();
405   auto UsePos = MachineBasicBlock::iterator(OldMI);
406   MachineBasicBlock::instr_iterator InsertPt = UsePos.getInstrIterator();
407   ++InsertPt;
408   MachineInstrBuilder MIB;
409   if (ImmOpNum == 0) {
410     if (HII->getAddrMode(OldMI) == HexagonII::BaseRegOffset) {
411       short NewOpCode = HII->getBaseWithLongOffset(OldMI);
412       assert(NewOpCode >= 0 && "Invalid New opcode\n");
413       MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode));
414       MIB.addOperand(OldMI->getOperand(1));
415       MIB.addOperand(OldMI->getOperand(2));
416       MIB.addOperand(ImmOp);
417       MIB.addOperand(OldMI->getOperand(3));
418       OpStart = 4;
419     } else if (HII->getAddrMode(OldMI) == HexagonII::BaseImmOffset) {
420       short NewOpCode = HII->getAbsoluteForm(OldMI);
421       assert(NewOpCode >= 0 && "Invalid New opcode\n");
422       MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode));
423       const GlobalValue *GV = ImmOp.getGlobal();
424       int64_t Offset = ImmOp.getOffset() + OldMI->getOperand(1).getImm();
425       MIB.addGlobalAddress(GV, Offset, ImmOp.getTargetFlags());
426       MIB.addOperand(OldMI->getOperand(2));
427       OpStart = 3;
428     }
429     Changed = true;
430     DEBUG(dbgs() << "[Changing]: " << *OldMI << "\n");
431     DEBUG(dbgs() << "[TO]: " << MIB << "\n");
432   } else if (ImmOpNum == 1 && OldMI->getOperand(2).getImm() == 0) {
433     short NewOpCode = HII->xformRegToImmOffset(OldMI);
434     assert(NewOpCode >= 0 && "Invalid New opcode\n");
435     MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode));
436     MIB.addOperand(OldMI->getOperand(0));
437     MIB.addOperand(ImmOp);
438     MIB.addOperand(OldMI->getOperand(1));
439     OpStart = 2;
440     Changed = true;
441     DEBUG(dbgs() << "[Changing]: " << *OldMI << "\n");
442     DEBUG(dbgs() << "[TO]: " << MIB << "\n");
443   }
444   if (Changed)
445     for (unsigned i = OpStart; i < OpEnd; ++i)
446       MIB.addOperand(OldMI->getOperand(i));
447 
448   return Changed;
449 }
450 
451 short HexagonOptAddrMode::getBaseWithLongOffset(const MachineInstr *MI) const {
452   if (HII->getAddrMode(MI) == HexagonII::BaseImmOffset) {
453     short TempOpCode = HII->getBaseWithRegOffset(MI);
454     return HII->getBaseWithLongOffset(TempOpCode);
455   } else
456     return HII->getBaseWithLongOffset(MI);
457 }
458 
459 bool HexagonOptAddrMode::changeAddAsl(NodeAddr<UseNode *> AddAslUN,
460                                       MachineInstr *AddAslMI,
461                                       const MachineOperand &ImmOp,
462                                       unsigned ImmOpNum) {
463   NodeAddr<StmtNode *> SA = AddAslUN.Addr->getOwner(*DFG);
464 
465   DEBUG(dbgs() << "Processing addasl :" << *AddAslMI << "\n");
466 
467   NodeList UNodeList;
468   getAllRealUses(SA, UNodeList);
469 
470   for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) {
471     NodeAddr<UseNode *> UseUN = *I;
472     assert(!(UseUN.Addr->getFlags() & NodeAttrs::PhiRef) &&
473            "Can't transform this 'AddAsl' instruction!");
474 
475     NodeAddr<StmtNode *> UseIA = UseUN.Addr->getOwner(*DFG);
476     DEBUG(dbgs() << "[InstrNode]: " << Print<NodeAddr<InstrNode *>>(UseIA, *DFG)
477                  << "\n");
478     MachineInstr *UseMI = UseIA.Addr->getCode();
479     DEBUG(dbgs() << "[MI <BB#" << UseMI->getParent()->getNumber()
480                  << ">]: " << *UseMI << "\n");
481     const MCInstrDesc &UseMID = UseMI->getDesc();
482     assert(HII->getAddrMode(UseMI) == HexagonII::BaseImmOffset);
483 
484     auto UsePos = MachineBasicBlock::iterator(UseMI);
485     MachineBasicBlock::instr_iterator InsertPt = UsePos.getInstrIterator();
486     short NewOpCode = getBaseWithLongOffset(UseMI);
487     assert(NewOpCode >= 0 && "Invalid New opcode\n");
488 
489     unsigned OpStart;
490     unsigned OpEnd = UseMI->getNumOperands();
491 
492     MachineBasicBlock *BB = UseMI->getParent();
493     MachineInstrBuilder MIB =
494         BuildMI(*BB, InsertPt, UseMI->getDebugLoc(), HII->get(NewOpCode));
495     // change mem(Rs + # ) -> mem(Rt << # + ##)
496     if (UseMID.mayLoad()) {
497       MIB.addOperand(UseMI->getOperand(0));
498       MIB.addOperand(AddAslMI->getOperand(2));
499       MIB.addOperand(AddAslMI->getOperand(3));
500       const GlobalValue *GV = ImmOp.getGlobal();
501       MIB.addGlobalAddress(GV, UseMI->getOperand(2).getImm(),
502                            ImmOp.getTargetFlags());
503       OpStart = 3;
504     } else if (UseMID.mayStore()) {
505       MIB.addOperand(AddAslMI->getOperand(2));
506       MIB.addOperand(AddAslMI->getOperand(3));
507       const GlobalValue *GV = ImmOp.getGlobal();
508       MIB.addGlobalAddress(GV, UseMI->getOperand(1).getImm(),
509                            ImmOp.getTargetFlags());
510       MIB.addOperand(UseMI->getOperand(2));
511       OpStart = 3;
512     } else
513       llvm_unreachable("Unhandled instruction");
514 
515     for (unsigned i = OpStart; i < OpEnd; ++i)
516       MIB.addOperand(UseMI->getOperand(i));
517 
518     Deleted.insert(UseMI);
519   }
520 
521   return true;
522 }
523 
524 bool HexagonOptAddrMode::xformUseMI(MachineInstr *TfrMI, MachineInstr *UseMI,
525                                     NodeAddr<UseNode *> UseN,
526                                     unsigned UseMOnum) {
527   const MachineOperand ImmOp = TfrMI->getOperand(1);
528   const MCInstrDesc &MID = UseMI->getDesc();
529   unsigned Changed = false;
530   if (MID.mayLoad())
531     Changed = changeLoad(UseMI, ImmOp, UseMOnum);
532   else if (MID.mayStore())
533     Changed = changeStore(UseMI, ImmOp, UseMOnum);
534   else if (UseMI->getOpcode() == Hexagon::S2_addasl_rrri)
535     Changed = changeAddAsl(UseN, UseMI, ImmOp, UseMOnum);
536 
537   if (Changed)
538     Deleted.insert(UseMI);
539 
540   return Changed;
541 }
542 
543 bool HexagonOptAddrMode::processBlock(NodeAddr<BlockNode *> BA) {
544   bool Changed = false;
545 
546   for (auto IA : BA.Addr->members(*DFG)) {
547     if (!DFG->IsCode<NodeAttrs::Stmt>(IA))
548       continue;
549 
550     NodeAddr<StmtNode *> SA = IA;
551     MachineInstr *MI = SA.Addr->getCode();
552     if (MI->getOpcode() != Hexagon::A2_tfrsi ||
553         !MI->getOperand(1).isGlobal())
554       continue;
555 
556     DEBUG(dbgs() << "[Analyzing A2_tfrsi]: " << *MI << "\n");
557     DEBUG(dbgs() << "\t[InstrNode]: " << Print<NodeAddr<InstrNode *>>(IA, *DFG)
558                  << "\n");
559 
560     NodeList UNodeList;
561     getAllRealUses(SA, UNodeList);
562 
563     if (!allValidCandidates(SA, UNodeList))
564       continue;
565 
566     short SizeInc = 0;
567     unsigned DefR = MI->getOperand(0).getReg();
568     InstrEvalMap InstrEvalResult;
569 
570     // Analyze all uses and calculate increase in size. Perform the optimization
571     // only if there is no increase in size.
572     if (!analyzeUses(DefR, UNodeList, InstrEvalResult, SizeInc))
573       continue;
574     if (SizeInc > CodeGrowthLimit)
575       continue;
576 
577     bool KeepTfr = false;
578 
579     DEBUG(dbgs() << "\t[Total reached uses] : " << UNodeList.size() << "\n");
580     DEBUG(dbgs() << "\t[Processing Reached Uses] ===\n");
581     for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) {
582       NodeAddr<UseNode *> UseN = *I;
583       assert(!(UseN.Addr->getFlags() & NodeAttrs::PhiRef) &&
584              "Found a PhiRef node as a real reached use!!");
585 
586       NodeAddr<StmtNode *> OwnerN = UseN.Addr->getOwner(*DFG);
587       MachineInstr *UseMI = OwnerN.Addr->getCode();
588       DEBUG(dbgs() << "\t\t[MI <BB#" << UseMI->getParent()->getNumber()
589                    << ">]: " << *UseMI << "\n");
590 
591       int UseMOnum = -1;
592       unsigned NumOperands = UseMI->getNumOperands();
593       for (unsigned j = 0; j < NumOperands - 1; ++j) {
594         const MachineOperand &op = UseMI->getOperand(j);
595         if (op.isReg() && op.isUse() && DefR == op.getReg())
596           UseMOnum = j;
597       }
598       assert(UseMOnum >= 0 && "Invalid reached use!");
599 
600       if (InstrEvalResult[UseMI])
601         // Change UseMI if replacement is possible.
602         Changed |= xformUseMI(MI, UseMI, UseN, UseMOnum);
603       else
604         KeepTfr = true;
605     }
606     if (!KeepTfr)
607       Deleted.insert(MI);
608   }
609   return Changed;
610 }
611 
612 void HexagonOptAddrMode::updateMap(NodeAddr<InstrNode *> IA) {
613   RegisterSet RRs;
614   for (NodeAddr<RefNode *> RA : IA.Addr->members(*DFG))
615     RRs.insert(RA.Addr->getRegRef());
616   bool Common = false;
617   for (auto &R : RDefMap) {
618     if (!RRs.count(R.first))
619       continue;
620     Common = true;
621     break;
622   }
623   if (!Common)
624     return;
625 
626   for (auto &R : RDefMap) {
627     auto F = DefM.find(R.first);
628     if (F == DefM.end() || F->second.empty())
629       continue;
630     R.second[IA.Id] = F->second.top()->Id;
631   }
632 }
633 
634 bool HexagonOptAddrMode::constructDefMap(MachineBasicBlock *B) {
635   bool Changed = false;
636   auto BA = DFG->getFunc().Addr->findBlock(B, *DFG);
637   DFG->markBlock(BA.Id, DefM);
638 
639   for (NodeAddr<InstrNode *> IA : BA.Addr->members(*DFG)) {
640     updateMap(IA);
641     DFG->pushDefs(IA, DefM);
642   }
643 
644   MachineDomTreeNode *N = MDT->getNode(B);
645   for (auto I : *N)
646     Changed |= constructDefMap(I->getBlock());
647 
648   DFG->releaseBlock(BA.Id, DefM);
649   return Changed;
650 }
651 
652 bool HexagonOptAddrMode::runOnMachineFunction(MachineFunction &MF) {
653   bool Changed = false;
654   auto &HST = MF.getSubtarget<HexagonSubtarget>();
655   auto &MRI = MF.getRegInfo();
656   HII = HST.getInstrInfo();
657   const auto &MDF = getAnalysis<MachineDominanceFrontier>();
658   MDT = &getAnalysis<MachineDominatorTree>();
659   const auto &TRI = *MF.getSubtarget().getRegisterInfo();
660   const TargetOperandInfo TOI(*HII);
661 
662   RegisterAliasInfo RAI(TRI);
663   DataFlowGraph G(MF, *HII, TRI, *MDT, MDF, RAI, TOI);
664   G.build();
665   DFG = &G;
666 
667   Liveness L(MRI, *DFG);
668   L.computePhiInfo();
669   LV = &L;
670 
671   constructDefMap(&DFG->getMF().front());
672 
673   Deleted.clear();
674   NodeAddr<FuncNode *> FA = DFG->getFunc();
675   DEBUG(dbgs() << "==== [RefMap#]=====:\n "
676                << Print<NodeAddr<FuncNode *>>(FA, *DFG) << "\n");
677 
678   for (NodeAddr<BlockNode *> BA : FA.Addr->members(*DFG))
679     Changed |= processBlock(BA);
680 
681   for (auto MI : Deleted)
682     MI->eraseFromParent();
683 
684   if (Changed) {
685     G.build();
686     L.computeLiveIns();
687     L.resetLiveIns();
688     L.resetKills();
689   }
690 
691   return Changed;
692 }
693 
694 //===----------------------------------------------------------------------===//
695 //                         Public Constructor Functions
696 //===----------------------------------------------------------------------===//
697 
698 FunctionPass *llvm::createHexagonOptAddrMode() {
699   return new HexagonOptAddrMode();
700 }
701