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