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     NodeAddr<StmtNode *> ReachingIA = RDN.Addr->getOwner(*DFG);
148     DEBUG(dbgs() << "\t\t\t[Def Node]: "
149                  << Print<NodeAddr<InstrNode *>>(ReachingIA, *DFG) << "\n");
150     (void)ReachingIA;
151     NodeId ReachedID = RDN.Addr->getReachedDef();
152     if (!ReachedID)
153       return ReachedDefMI;
154 
155     NodeAddr<DefNode *> ReachedDN = DFG->addr<DefNode *>(ReachedID);
156     NodeAddr<StmtNode *> ReachedIA = ReachedDN.Addr->getOwner(*DFG);
157     DEBUG(dbgs() << "\t\t\t[Reached Def Node]: "
158                  << Print<NodeAddr<InstrNode *>>(ReachedIA, *DFG) << "\n");
159     ReachedDefMI = ReachedIA.Addr->getCode();
160     DEBUG(dbgs() << "\nReached Def MI === " << *ReachedDefMI << "\n");
161   }
162   return ReachedDefMI;
163 }
164 
165 // Check if addasl instruction can be removed. This is possible only
166 // if it's feeding to only load/store instructions with base + register
167 // offset as these instruction can be tranformed to use 'absolute plus
168 // shifted register offset'.
169 // ex:
170 // Rs = ##foo
171 // Rx = addasl(Rs, Rt, #2)
172 // Rd = memw(Rx + #28)
173 // Above three instructions can be replaced with Rd = memw(Rt<<#2 + ##foo+28)
174 
175 bool HexagonOptAddrMode::canRemoveAddasl(NodeAddr<StmtNode *> AddAslSN,
176                                          MachineInstr *MI,
177                                          const NodeList &UNodeList) {
178   // check offset size in addasl. if 'offset > 3' return false
179   const MachineOperand &OffsetOp = MI->getOperand(3);
180   if (!OffsetOp.isImm() || OffsetOp.getImm() > 3)
181     return false;
182 
183   unsigned OffsetReg = MI->getOperand(2).getReg();
184   RegisterRef OffsetRR;
185   NodeId OffsetRegRD = 0;
186   for (NodeAddr<UseNode *> UA : AddAslSN.Addr->members_if(DFG->IsUse, *DFG)) {
187     RegisterRef RR = UA.Addr->getRegRef();
188     if (OffsetReg == RR.Reg) {
189       OffsetRR = RR;
190       OffsetRegRD = UA.Addr->getReachingDef();
191     }
192   }
193 
194   for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) {
195     NodeAddr<UseNode *> UA = *I;
196     NodeAddr<InstrNode *> IA = UA.Addr->getOwner(*DFG);
197     if ((UA.Addr->getFlags() & NodeAttrs::PhiRef) ||
198         RDefMap[OffsetRR][IA.Id] != OffsetRegRD)
199       return false;
200 
201     MachineInstr *UseMI = NodeAddr<StmtNode *>(IA).Addr->getCode();
202     NodeAddr<DefNode *> OffsetRegDN = DFG->addr<DefNode *>(OffsetRegRD);
203     // Reaching Def to an offset register can't be a phi.
204     if ((OffsetRegDN.Addr->getFlags() & NodeAttrs::PhiRef) &&
205         MI->getParent() != UseMI->getParent())
206     return false;
207 
208     const MCInstrDesc &UseMID = UseMI->getDesc();
209     if ((!UseMID.mayLoad() && !UseMID.mayStore()) ||
210         HII->getAddrMode(UseMI) != HexagonII::BaseImmOffset ||
211         getBaseWithLongOffset(UseMI) < 0)
212       return false;
213 
214     // Addasl output can't be a store value.
215     if (UseMID.mayStore() && UseMI->getOperand(2).isReg() &&
216         UseMI->getOperand(2).getReg() == MI->getOperand(0).getReg())
217       return false;
218 
219     for (auto &Mo : UseMI->operands())
220       if (Mo.isFI())
221         return false;
222   }
223   return true;
224 }
225 
226 bool HexagonOptAddrMode::allValidCandidates(NodeAddr<StmtNode *> SA,
227                                             NodeList &UNodeList) {
228   for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) {
229     NodeAddr<UseNode *> UN = *I;
230     RegisterRef UR = UN.Addr->getRegRef();
231     NodeSet Visited, Defs;
232     const auto &ReachingDefs = LV->getAllReachingDefsRec(UR, UN, Visited, Defs);
233     if (ReachingDefs.size() > 1) {
234       DEBUG(dbgs() << "*** Multiple Reaching Defs found!!! *** \n");
235       for (auto DI : ReachingDefs) {
236         NodeAddr<UseNode *> DA = DFG->addr<UseNode *>(DI);
237         NodeAddr<StmtNode *> TempIA = DA.Addr->getOwner(*DFG);
238         (void)TempIA;
239         DEBUG(dbgs() << "\t\t[Reaching Def]: "
240                      << Print<NodeAddr<InstrNode *>>(TempIA, *DFG) << "\n");
241       }
242       return false;
243     }
244   }
245   return true;
246 }
247 
248 void HexagonOptAddrMode::getAllRealUses(NodeAddr<StmtNode *> SA,
249                                         NodeList &UNodeList) {
250   for (NodeAddr<DefNode *> DA : SA.Addr->members_if(DFG->IsDef, *DFG)) {
251     DEBUG(dbgs() << "\t\t[DefNode]: " << Print<NodeAddr<DefNode *>>(DA, *DFG)
252                  << "\n");
253     RegisterRef DR = DA.Addr->getRegRef();
254     auto UseSet = LV->getAllReachedUses(DR, DA);
255 
256     for (auto UI : UseSet) {
257       NodeAddr<UseNode *> UA = DFG->addr<UseNode *>(UI);
258       NodeAddr<StmtNode *> TempIA = UA.Addr->getOwner(*DFG);
259       (void)TempIA;
260       DEBUG(dbgs() << "\t\t\t[Reached Use]: "
261                    << Print<NodeAddr<InstrNode *>>(TempIA, *DFG) << "\n");
262 
263       if (UA.Addr->getFlags() & NodeAttrs::PhiRef) {
264         NodeAddr<PhiNode *> PA = UA.Addr->getOwner(*DFG);
265         NodeId id = PA.Id;
266         const Liveness::RefMap &phiUse = LV->getRealUses(id);
267         DEBUG(dbgs() << "\t\t\t\tphi real Uses"
268                      << Print<Liveness::RefMap>(phiUse, *DFG) << "\n");
269         if (phiUse.size() > 0) {
270           for (auto I : phiUse) {
271             if (DR != I.first)
272               continue;
273             auto phiUseSet = I.second;
274             for (auto phiUI : phiUseSet) {
275               NodeAddr<UseNode *> phiUA = DFG->addr<UseNode *>(phiUI);
276               UNodeList.push_back(phiUA);
277             }
278           }
279         }
280       } else
281         UNodeList.push_back(UA);
282     }
283   }
284 }
285 
286 bool HexagonOptAddrMode::analyzeUses(unsigned tfrDefR,
287                                      const NodeList &UNodeList,
288                                      InstrEvalMap &InstrEvalResult,
289                                      short &SizeInc) {
290   bool KeepTfr = false;
291   bool HasRepInstr = false;
292   InstrEvalResult.clear();
293 
294   for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) {
295     bool CanBeReplaced = false;
296     NodeAddr<UseNode *> UN = *I;
297     NodeAddr<StmtNode *> SN = UN.Addr->getOwner(*DFG);
298     MachineInstr *MI = SN.Addr->getCode();
299     const MCInstrDesc &MID = MI->getDesc();
300     if ((MID.mayLoad() || MID.mayStore())) {
301       if (!hasRepForm(MI, tfrDefR)) {
302         KeepTfr = true;
303         continue;
304       }
305       SizeInc++;
306       CanBeReplaced = true;
307     } else if (MI->getOpcode() == Hexagon::S2_addasl_rrri) {
308       NodeList AddaslUseList;
309 
310       DEBUG(dbgs() << "\nGetting ReachedUses for === " << *MI << "\n");
311       getAllRealUses(SN, AddaslUseList);
312       // Process phi nodes.
313       if (allValidCandidates(SN, AddaslUseList) &&
314           canRemoveAddasl(SN, MI, AddaslUseList)) {
315         SizeInc += AddaslUseList.size();
316         SizeInc -= 1; // Reduce size by 1 as addasl itself can be removed.
317         CanBeReplaced = true;
318       } else
319         SizeInc++;
320     } else
321       // Currently, only load/store and addasl are handled.
322       // Some other instructions to consider -
323       // A2_add -> A2_addi
324       // M4_mpyrr_addr -> M4_mpyrr_addi
325       KeepTfr = true;
326 
327     InstrEvalResult[MI] = CanBeReplaced;
328     HasRepInstr |= CanBeReplaced;
329   }
330 
331   // Reduce total size by 2 if original tfr can be deleted.
332   if (!KeepTfr)
333     SizeInc -= 2;
334 
335   return HasRepInstr;
336 }
337 
338 bool HexagonOptAddrMode::changeLoad(MachineInstr *OldMI, MachineOperand ImmOp,
339                                     unsigned ImmOpNum) {
340   bool Changed = false;
341   MachineBasicBlock *BB = OldMI->getParent();
342   auto UsePos = MachineBasicBlock::iterator(OldMI);
343   MachineBasicBlock::instr_iterator InsertPt = UsePos.getInstrIterator();
344   ++InsertPt;
345   unsigned OpStart;
346   unsigned OpEnd = OldMI->getNumOperands();
347   MachineInstrBuilder MIB;
348 
349   if (ImmOpNum == 1) {
350     if (HII->getAddrMode(OldMI) == HexagonII::BaseRegOffset) {
351       short NewOpCode = HII->getBaseWithLongOffset(OldMI);
352       assert(NewOpCode >= 0 && "Invalid New opcode\n");
353       MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode));
354       MIB.addOperand(OldMI->getOperand(0));
355       MIB.addOperand(OldMI->getOperand(2));
356       MIB.addOperand(OldMI->getOperand(3));
357       MIB.addOperand(ImmOp);
358       OpStart = 4;
359       Changed = true;
360     } else if (HII->getAddrMode(OldMI) == HexagonII::BaseImmOffset) {
361       short NewOpCode = HII->getAbsoluteForm(OldMI);
362       assert(NewOpCode >= 0 && "Invalid New opcode\n");
363       MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode))
364                 .addOperand(OldMI->getOperand(0));
365       const GlobalValue *GV = ImmOp.getGlobal();
366       int64_t Offset = ImmOp.getOffset() + OldMI->getOperand(2).getImm();
367 
368       MIB.addGlobalAddress(GV, Offset, ImmOp.getTargetFlags());
369       OpStart = 3;
370       Changed = true;
371     } else
372       Changed = false;
373 
374     DEBUG(dbgs() << "[Changing]: " << *OldMI << "\n");
375     DEBUG(dbgs() << "[TO]: " << MIB << "\n");
376   } else if (ImmOpNum == 2 && OldMI->getOperand(3).getImm() == 0) {
377     short NewOpCode = HII->xformRegToImmOffset(OldMI);
378     assert(NewOpCode >= 0 && "Invalid New opcode\n");
379     MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode));
380     MIB.addOperand(OldMI->getOperand(0));
381     MIB.addOperand(OldMI->getOperand(1));
382     MIB.addOperand(ImmOp);
383     OpStart = 4;
384     Changed = true;
385     DEBUG(dbgs() << "[Changing]: " << *OldMI << "\n");
386     DEBUG(dbgs() << "[TO]: " << MIB << "\n");
387   }
388 
389   if (Changed)
390     for (unsigned i = OpStart; i < OpEnd; ++i)
391       MIB.addOperand(OldMI->getOperand(i));
392 
393   return Changed;
394 }
395 
396 bool HexagonOptAddrMode::changeStore(MachineInstr *OldMI, MachineOperand ImmOp,
397                                      unsigned ImmOpNum) {
398   bool Changed = false;
399   unsigned OpStart;
400   unsigned OpEnd = OldMI->getNumOperands();
401   MachineBasicBlock *BB = OldMI->getParent();
402   auto UsePos = MachineBasicBlock::iterator(OldMI);
403   MachineBasicBlock::instr_iterator InsertPt = UsePos.getInstrIterator();
404   ++InsertPt;
405   MachineInstrBuilder MIB;
406   if (ImmOpNum == 0) {
407     if (HII->getAddrMode(OldMI) == HexagonII::BaseRegOffset) {
408       short NewOpCode = HII->getBaseWithLongOffset(OldMI);
409       assert(NewOpCode >= 0 && "Invalid New opcode\n");
410       MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode));
411       MIB.addOperand(OldMI->getOperand(1));
412       MIB.addOperand(OldMI->getOperand(2));
413       MIB.addOperand(ImmOp);
414       MIB.addOperand(OldMI->getOperand(3));
415       OpStart = 4;
416     } else if (HII->getAddrMode(OldMI) == HexagonII::BaseImmOffset) {
417       short NewOpCode = HII->getAbsoluteForm(OldMI);
418       assert(NewOpCode >= 0 && "Invalid New opcode\n");
419       MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode));
420       const GlobalValue *GV = ImmOp.getGlobal();
421       int64_t Offset = ImmOp.getOffset() + OldMI->getOperand(1).getImm();
422       MIB.addGlobalAddress(GV, Offset, ImmOp.getTargetFlags());
423       MIB.addOperand(OldMI->getOperand(2));
424       OpStart = 3;
425     }
426     Changed = true;
427     DEBUG(dbgs() << "[Changing]: " << *OldMI << "\n");
428     DEBUG(dbgs() << "[TO]: " << MIB << "\n");
429   } else if (ImmOpNum == 1 && OldMI->getOperand(2).getImm() == 0) {
430     short NewOpCode = HII->xformRegToImmOffset(OldMI);
431     assert(NewOpCode >= 0 && "Invalid New opcode\n");
432     MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode));
433     MIB.addOperand(OldMI->getOperand(0));
434     MIB.addOperand(ImmOp);
435     MIB.addOperand(OldMI->getOperand(1));
436     OpStart = 2;
437     Changed = true;
438     DEBUG(dbgs() << "[Changing]: " << *OldMI << "\n");
439     DEBUG(dbgs() << "[TO]: " << MIB << "\n");
440   }
441   if (Changed)
442     for (unsigned i = OpStart; i < OpEnd; ++i)
443       MIB.addOperand(OldMI->getOperand(i));
444 
445   return Changed;
446 }
447 
448 short HexagonOptAddrMode::getBaseWithLongOffset(const MachineInstr *MI) const {
449   if (HII->getAddrMode(MI) == HexagonII::BaseImmOffset) {
450     short TempOpCode = HII->getBaseWithRegOffset(MI);
451     return HII->getBaseWithLongOffset(TempOpCode);
452   } else
453     return HII->getBaseWithLongOffset(MI);
454 }
455 
456 bool HexagonOptAddrMode::changeAddAsl(NodeAddr<UseNode *> AddAslUN,
457                                       MachineInstr *AddAslMI,
458                                       const MachineOperand &ImmOp,
459                                       unsigned ImmOpNum) {
460   NodeAddr<StmtNode *> SA = AddAslUN.Addr->getOwner(*DFG);
461 
462   DEBUG(dbgs() << "Processing addasl :" << *AddAslMI << "\n");
463 
464   NodeList UNodeList;
465   getAllRealUses(SA, UNodeList);
466 
467   for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) {
468     NodeAddr<UseNode *> UseUN = *I;
469     assert(!(UseUN.Addr->getFlags() & NodeAttrs::PhiRef) &&
470            "Can't transform this 'AddAsl' instruction!");
471 
472     NodeAddr<StmtNode *> UseIA = UseUN.Addr->getOwner(*DFG);
473     DEBUG(dbgs() << "[InstrNode]: " << Print<NodeAddr<InstrNode *>>(UseIA, *DFG)
474                  << "\n");
475     MachineInstr *UseMI = UseIA.Addr->getCode();
476     DEBUG(dbgs() << "[MI <BB#" << UseMI->getParent()->getNumber()
477                  << ">]: " << *UseMI << "\n");
478     const MCInstrDesc &UseMID = UseMI->getDesc();
479     assert(HII->getAddrMode(UseMI) == HexagonII::BaseImmOffset);
480 
481     auto UsePos = MachineBasicBlock::iterator(UseMI);
482     MachineBasicBlock::instr_iterator InsertPt = UsePos.getInstrIterator();
483     short NewOpCode = getBaseWithLongOffset(UseMI);
484     assert(NewOpCode >= 0 && "Invalid New opcode\n");
485 
486     unsigned OpStart;
487     unsigned OpEnd = UseMI->getNumOperands();
488 
489     MachineBasicBlock *BB = UseMI->getParent();
490     MachineInstrBuilder MIB =
491         BuildMI(*BB, InsertPt, UseMI->getDebugLoc(), HII->get(NewOpCode));
492     // change mem(Rs + # ) -> mem(Rt << # + ##)
493     if (UseMID.mayLoad()) {
494       MIB.addOperand(UseMI->getOperand(0));
495       MIB.addOperand(AddAslMI->getOperand(2));
496       MIB.addOperand(AddAslMI->getOperand(3));
497       const GlobalValue *GV = ImmOp.getGlobal();
498       MIB.addGlobalAddress(GV, UseMI->getOperand(2).getImm(),
499                            ImmOp.getTargetFlags());
500       OpStart = 3;
501     } else if (UseMID.mayStore()) {
502       MIB.addOperand(AddAslMI->getOperand(2));
503       MIB.addOperand(AddAslMI->getOperand(3));
504       const GlobalValue *GV = ImmOp.getGlobal();
505       MIB.addGlobalAddress(GV, UseMI->getOperand(1).getImm(),
506                            ImmOp.getTargetFlags());
507       MIB.addOperand(UseMI->getOperand(2));
508       OpStart = 3;
509     } else
510       llvm_unreachable("Unhandled instruction");
511 
512     for (unsigned i = OpStart; i < OpEnd; ++i)
513       MIB.addOperand(UseMI->getOperand(i));
514 
515     Deleted.insert(UseMI);
516   }
517 
518   return true;
519 }
520 
521 bool HexagonOptAddrMode::xformUseMI(MachineInstr *TfrMI, MachineInstr *UseMI,
522                                     NodeAddr<UseNode *> UseN,
523                                     unsigned UseMOnum) {
524   const MachineOperand ImmOp = TfrMI->getOperand(1);
525   const MCInstrDesc &MID = UseMI->getDesc();
526   unsigned Changed = false;
527   if (MID.mayLoad())
528     Changed = changeLoad(UseMI, ImmOp, UseMOnum);
529   else if (MID.mayStore())
530     Changed = changeStore(UseMI, ImmOp, UseMOnum);
531   else if (UseMI->getOpcode() == Hexagon::S2_addasl_rrri)
532     Changed = changeAddAsl(UseN, UseMI, ImmOp, UseMOnum);
533 
534   if (Changed)
535     Deleted.insert(UseMI);
536 
537   return Changed;
538 }
539 
540 bool HexagonOptAddrMode::processBlock(NodeAddr<BlockNode *> BA) {
541   bool Changed = false;
542 
543   for (auto IA : BA.Addr->members(*DFG)) {
544     if (!DFG->IsCode<NodeAttrs::Stmt>(IA))
545       continue;
546 
547     NodeAddr<StmtNode *> SA = IA;
548     MachineInstr *MI = SA.Addr->getCode();
549     if (MI->getOpcode() != Hexagon::A2_tfrsi ||
550         !MI->getOperand(1).isGlobal())
551       continue;
552 
553     DEBUG(dbgs() << "[Analyzing A2_tfrsi]: " << *MI << "\n");
554     DEBUG(dbgs() << "\t[InstrNode]: " << Print<NodeAddr<InstrNode *>>(IA, *DFG)
555                  << "\n");
556 
557     NodeList UNodeList;
558     getAllRealUses(SA, UNodeList);
559 
560     if (!allValidCandidates(SA, UNodeList))
561       continue;
562 
563     short SizeInc = 0;
564     unsigned DefR = MI->getOperand(0).getReg();
565     InstrEvalMap InstrEvalResult;
566 
567     // Analyze all uses and calculate increase in size. Perform the optimization
568     // only if there is no increase in size.
569     if (!analyzeUses(DefR, UNodeList, InstrEvalResult, SizeInc))
570       continue;
571     if (SizeInc > CodeGrowthLimit)
572       continue;
573 
574     bool KeepTfr = false;
575 
576     DEBUG(dbgs() << "\t[Total reached uses] : " << UNodeList.size() << "\n");
577     DEBUG(dbgs() << "\t[Processing Reached Uses] ===\n");
578     for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) {
579       NodeAddr<UseNode *> UseN = *I;
580       assert(!(UseN.Addr->getFlags() & NodeAttrs::PhiRef) &&
581              "Found a PhiRef node as a real reached use!!");
582 
583       NodeAddr<StmtNode *> OwnerN = UseN.Addr->getOwner(*DFG);
584       MachineInstr *UseMI = OwnerN.Addr->getCode();
585       unsigned BBNum = UseMI->getParent()->getNumber();
586       (void)BBNum;
587       DEBUG(dbgs() << "\t\t[MI <BB#" << BBNum << ">]: " << *UseMI << "\n");
588 
589       int UseMOnum = -1;
590       unsigned NumOperands = UseMI->getNumOperands();
591       for (unsigned j = 0; j < NumOperands - 1; ++j) {
592         const MachineOperand &op = UseMI->getOperand(j);
593         if (op.isReg() && op.isUse() && DefR == op.getReg())
594           UseMOnum = j;
595       }
596       assert(UseMOnum >= 0 && "Invalid reached use!");
597 
598       if (InstrEvalResult[UseMI])
599         // Change UseMI if replacement is possible.
600         Changed |= xformUseMI(MI, UseMI, UseN, UseMOnum);
601       else
602         KeepTfr = true;
603     }
604     if (!KeepTfr)
605       Deleted.insert(MI);
606   }
607   return Changed;
608 }
609 
610 void HexagonOptAddrMode::updateMap(NodeAddr<InstrNode *> IA) {
611   RegisterSet RRs;
612   for (NodeAddr<RefNode *> RA : IA.Addr->members(*DFG))
613     RRs.insert(RA.Addr->getRegRef());
614   bool Common = false;
615   for (auto &R : RDefMap) {
616     if (!RRs.count(R.first))
617       continue;
618     Common = true;
619     break;
620   }
621   if (!Common)
622     return;
623 
624   for (auto &R : RDefMap) {
625     auto F = DefM.find(R.first);
626     if (F == DefM.end() || F->second.empty())
627       continue;
628     R.second[IA.Id] = F->second.top()->Id;
629   }
630 }
631 
632 bool HexagonOptAddrMode::constructDefMap(MachineBasicBlock *B) {
633   bool Changed = false;
634   auto BA = DFG->getFunc().Addr->findBlock(B, *DFG);
635   DFG->markBlock(BA.Id, DefM);
636 
637   for (NodeAddr<InstrNode *> IA : BA.Addr->members(*DFG)) {
638     updateMap(IA);
639     DFG->pushDefs(IA, DefM);
640   }
641 
642   MachineDomTreeNode *N = MDT->getNode(B);
643   for (auto I : *N)
644     Changed |= constructDefMap(I->getBlock());
645 
646   DFG->releaseBlock(BA.Id, DefM);
647   return Changed;
648 }
649 
650 bool HexagonOptAddrMode::runOnMachineFunction(MachineFunction &MF) {
651   bool Changed = false;
652   auto &HST = MF.getSubtarget<HexagonSubtarget>();
653   auto &MRI = MF.getRegInfo();
654   HII = HST.getInstrInfo();
655   const auto &MDF = getAnalysis<MachineDominanceFrontier>();
656   MDT = &getAnalysis<MachineDominatorTree>();
657   const auto &TRI = *MF.getSubtarget().getRegisterInfo();
658   const TargetOperandInfo TOI(*HII);
659 
660   RegisterAliasInfo RAI(TRI);
661   DataFlowGraph G(MF, *HII, TRI, *MDT, MDF, RAI, TOI);
662   G.build();
663   DFG = &G;
664 
665   Liveness L(MRI, *DFG);
666   L.computePhiInfo();
667   LV = &L;
668 
669   constructDefMap(&DFG->getMF().front());
670 
671   Deleted.clear();
672   NodeAddr<FuncNode *> FA = DFG->getFunc();
673   DEBUG(dbgs() << "==== [RefMap#]=====:\n "
674                << Print<NodeAddr<FuncNode *>>(FA, *DFG) << "\n");
675 
676   for (NodeAddr<BlockNode *> BA : FA.Addr->members(*DFG))
677     Changed |= processBlock(BA);
678 
679   for (auto MI : Deleted)
680     MI->eraseFromParent();
681 
682   if (Changed) {
683     G.build();
684     L.computeLiveIns();
685     L.resetLiveIns();
686     L.resetKills();
687   }
688 
689   return Changed;
690 }
691 
692 //===----------------------------------------------------------------------===//
693 //                         Public Constructor Functions
694 //===----------------------------------------------------------------------===//
695 
696 FunctionPass *llvm::createHexagonOptAddrMode() {
697   return new HexagonOptAddrMode();
698 }
699