brintos

brintos / llvm-project-archived public Read only

0
0
Text · 43.3 KiB · 53afbc4 Raw
1200 lines · cpp
1//===- HexagonOptAddrMode.cpp ---------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8// This implements a Hexagon-specific pass to optimize addressing mode for9// load/store instructions.10//===----------------------------------------------------------------------===//11 12#include "Hexagon.h"13#include "HexagonInstrInfo.h"14#include "HexagonSubtarget.h"15#include "MCTargetDesc/HexagonBaseInfo.h"16#include "llvm/ADT/DenseMap.h"17#include "llvm/ADT/DenseSet.h"18#include "llvm/ADT/StringRef.h"19#include "llvm/CodeGen/MachineBasicBlock.h"20#include "llvm/CodeGen/MachineDominanceFrontier.h"21#include "llvm/CodeGen/MachineDominators.h"22#include "llvm/CodeGen/MachineFunction.h"23#include "llvm/CodeGen/MachineFunctionPass.h"24#include "llvm/CodeGen/MachineInstr.h"25#include "llvm/CodeGen/MachineInstrBuilder.h"26#include "llvm/CodeGen/MachineOperand.h"27#include "llvm/CodeGen/MachineRegisterInfo.h"28#include "llvm/CodeGen/RDFGraph.h"29#include "llvm/CodeGen/RDFLiveness.h"30#include "llvm/CodeGen/RDFRegisters.h"31#include "llvm/CodeGen/TargetSubtargetInfo.h"32#include "llvm/InitializePasses.h"33#include "llvm/MC/MCInstrDesc.h"34#include "llvm/Pass.h"35#include "llvm/Support/CommandLine.h"36#include "llvm/Support/Debug.h"37#include "llvm/Support/ErrorHandling.h"38#include "llvm/Support/raw_ostream.h"39#include <cassert>40#include <cstdint>41 42#define DEBUG_TYPE "opt-addr-mode"43 44using namespace llvm;45using namespace rdf;46 47static cl::opt<int> CodeGrowthLimit("hexagon-amode-growth-limit",48  cl::Hidden, cl::init(0), cl::desc("Code growth limit for address mode "49  "optimization"));50 51extern cl::opt<unsigned> RDFFuncBlockLimit;52 53namespace {54 55class HexagonOptAddrMode : public MachineFunctionPass {56public:57  static char ID;58 59  HexagonOptAddrMode() : MachineFunctionPass(ID) {}60 61  StringRef getPassName() const override {62    return "Optimize addressing mode of load/store";63  }64 65  void getAnalysisUsage(AnalysisUsage &AU) const override {66    MachineFunctionPass::getAnalysisUsage(AU);67    AU.addRequired<MachineDominatorTreeWrapperPass>();68    AU.addRequired<MachineDominanceFrontier>();69    AU.setPreservesAll();70  }71 72  bool runOnMachineFunction(MachineFunction &MF) override;73 74private:75  using MISetType = DenseSet<MachineInstr *>;76  using InstrEvalMap = DenseMap<MachineInstr *, bool>;77  DenseSet<MachineInstr *> ProcessedAddiInsts;78 79  MachineRegisterInfo *MRI = nullptr;80  const TargetRegisterInfo *TRI = nullptr;81  const HexagonInstrInfo *HII = nullptr;82  const HexagonRegisterInfo *HRI = nullptr;83  MachineDominatorTree *MDT = nullptr;84  DataFlowGraph *DFG = nullptr;85  DataFlowGraph::DefStackMap DefM;86  Liveness *LV = nullptr;87  MISetType Deleted;88 89  bool processBlock(NodeAddr<BlockNode *> BA);90  bool xformUseMI(MachineInstr *TfrMI, MachineInstr *UseMI,91                  NodeAddr<UseNode *> UseN, unsigned UseMOnum);92  bool processAddBases(NodeAddr<StmtNode *> AddSN, MachineInstr *AddMI);93  bool usedInLoadStore(NodeAddr<StmtNode *> CurrentInstSN, int64_t NewOffset);94  bool findFirstReachedInst(95      MachineInstr *AddMI,96      std::vector<std::pair<NodeAddr<StmtNode *>, NodeAddr<UseNode *>>>97          &AddiList,98      NodeAddr<StmtNode *> &UseSN);99  bool updateAddBases(MachineInstr *CurrentMI, MachineInstr *FirstReachedMI,100                      int64_t NewOffset);101  bool processAddUses(NodeAddr<StmtNode *> AddSN, MachineInstr *AddMI,102                      const NodeList &UNodeList);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,108                       const NodeList &UNodeList);109  bool isSafeToExtLR(NodeAddr<StmtNode *> SN, MachineInstr *MI,110                     Register LRExtReg, const NodeList &UNodeList);111  void getAllRealUses(NodeAddr<StmtNode *> SN, NodeList &UNodeList);112  bool allValidCandidates(NodeAddr<StmtNode *> SA, NodeList &UNodeList);113  short getBaseWithLongOffset(const MachineInstr &MI) const;114  bool changeStore(MachineInstr *OldMI, MachineOperand ImmOp,115                   unsigned ImmOpNum);116  bool changeLoad(MachineInstr *OldMI, MachineOperand ImmOp, unsigned ImmOpNum);117  bool changeAddAsl(NodeAddr<UseNode *> AddAslUN, MachineInstr *AddAslMI,118                    const MachineOperand &ImmOp, unsigned ImmOpNum);119  bool isValidOffset(MachineInstr *MI, int Offset);120  unsigned getBaseOpPosition(MachineInstr *MI);121  unsigned getOffsetOpPosition(MachineInstr *MI);122};123 124} // end anonymous namespace125 126char HexagonOptAddrMode::ID = 0;127 128INITIALIZE_PASS_BEGIN(HexagonOptAddrMode, "amode-opt",129                      "Optimize addressing mode", false, false)130INITIALIZE_PASS_DEPENDENCY(MachineDominatorTreeWrapperPass)131INITIALIZE_PASS_DEPENDENCY(MachineDominanceFrontier)132INITIALIZE_PASS_END(HexagonOptAddrMode, "amode-opt", "Optimize addressing mode",133                    false, false)134 135bool HexagonOptAddrMode::hasRepForm(MachineInstr &MI, unsigned TfrDefR) {136  const MCInstrDesc &MID = MI.getDesc();137 138  if ((!MID.mayStore() && !MID.mayLoad()) || HII->isPredicated(MI))139    return false;140 141  if (MID.mayStore()) {142    MachineOperand StOp = MI.getOperand(MI.getNumOperands() - 1);143    if (StOp.isReg() && StOp.getReg() == TfrDefR)144      return false;145  }146 147  if (HII->getAddrMode(MI) == HexagonII::BaseRegOffset)148    // Transform to Absolute plus register offset.149    return (HII->changeAddrMode_rr_ur(MI) >= 0);150  else if (HII->getAddrMode(MI) == HexagonII::BaseImmOffset)151    // Transform to absolute addressing mode.152    return (HII->changeAddrMode_io_abs(MI) >= 0);153 154  return false;155}156 157// Check if addasl instruction can be removed. This is possible only158// if it's feeding to only load/store instructions with base + register159// offset as these instruction can be transformed to use 'absolute plus160// shifted register offset'.161// ex:162// Rs = ##foo163// Rx = addasl(Rs, Rt, #2)164// Rd = memw(Rx + #28)165// Above three instructions can be replaced with Rd = memw(Rt<<#2 + ##foo+28)166 167bool HexagonOptAddrMode::canRemoveAddasl(NodeAddr<StmtNode *> AddAslSN,168                                         MachineInstr &MI,169                                         const NodeList &UNodeList) {170  // check offset size in addasl. if 'offset > 3' return false171  const MachineOperand &OffsetOp = MI.getOperand(3);172  if (!OffsetOp.isImm() || OffsetOp.getImm() > 3)173    return false;174 175  Register OffsetReg = MI.getOperand(2).getReg();176  RegisterRef OffsetRR;177  NodeId OffsetRegRD = 0;178  for (NodeAddr<UseNode *> UA : AddAslSN.Addr->members_if(DFG->IsUse, *DFG)) {179    RegisterRef RR = UA.Addr->getRegRef(*DFG);180    if (OffsetReg == RR.asMCReg()) {181      OffsetRR = RR;182      OffsetRegRD = UA.Addr->getReachingDef();183    }184  }185 186  for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) {187    NodeAddr<UseNode *> UA = *I;188    NodeAddr<InstrNode *> IA = UA.Addr->getOwner(*DFG);189    if (UA.Addr->getFlags() & NodeAttrs::PhiRef)190      return false;191    NodeAddr<RefNode*> AA = LV->getNearestAliasedRef(OffsetRR, IA);192    if ((DFG->IsDef(AA) && AA.Id != OffsetRegRD) ||193         AA.Addr->getReachingDef() != OffsetRegRD)194      return false;195 196    MachineInstr &UseMI = *NodeAddr<StmtNode *>(IA).Addr->getCode();197    NodeAddr<DefNode *> OffsetRegDN = DFG->addr<DefNode *>(OffsetRegRD);198    // Reaching Def to an offset register can't be a phi.199    if ((OffsetRegDN.Addr->getFlags() & NodeAttrs::PhiRef) &&200        MI.getParent() != UseMI.getParent())201      return false;202 203    const MCInstrDesc &UseMID = UseMI.getDesc();204    if ((!UseMID.mayLoad() && !UseMID.mayStore()) ||205        HII->getAddrMode(UseMI) != HexagonII::BaseImmOffset ||206        getBaseWithLongOffset(UseMI) < 0)207      return false;208 209    // Addasl output can't be a store value.210    if (UseMID.mayStore() && UseMI.getOperand(2).isReg() &&211        UseMI.getOperand(2).getReg() == MI.getOperand(0).getReg())212      return false;213 214    for (auto &Mo : UseMI.operands())215      // Is it a frame index?216      if (Mo.isFI())217        return false;218    // Is the OffsetReg definition actually reaches UseMI?219    if (!UseMI.getParent()->isLiveIn(OffsetReg) &&220        MI.getParent() != UseMI.getParent()) {221      LLVM_DEBUG(dbgs() << "  The offset reg " << printReg(OffsetReg, TRI)222                        << " is NOT live in to MBB "223                        << UseMI.getParent()->getName() << "\n");224      return false;225    }226  }227  return true;228}229 230bool HexagonOptAddrMode::allValidCandidates(NodeAddr<StmtNode *> SA,231                                            NodeList &UNodeList) {232  for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) {233    NodeAddr<UseNode *> UN = *I;234    RegisterRef UR = UN.Addr->getRegRef(*DFG);235    NodeSet Visited, Defs;236    const auto &P = LV->getAllReachingDefsRec(UR, UN, Visited, Defs);237    if (!P.second) {238      LLVM_DEBUG({239        dbgs() << "*** Unable to collect all reaching defs for use ***\n"240               << PrintNode<UseNode*>(UN, *DFG) << '\n'241               << "The program's complexity may exceed the limits.\n";242      });243      return false;244    }245    const auto &ReachingDefs = P.first;246    if (ReachingDefs.size() > 1) {247      LLVM_DEBUG({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]: "253                 << Print<NodeAddr<InstrNode *>>(TempIA, *DFG) << "\n";254        }255      });256      return false;257    }258  }259  return true;260}261 262void HexagonOptAddrMode::getAllRealUses(NodeAddr<StmtNode *> SA,263                                        NodeList &UNodeList) {264  for (NodeAddr<DefNode *> DA : SA.Addr->members_if(DFG->IsDef, *DFG)) {265    LLVM_DEBUG(dbgs() << "\t\t[DefNode]: "266                      << Print<NodeAddr<DefNode *>>(DA, *DFG) << "\n");267    RegisterRef DR = DA.Addr->getRegRef(*DFG);268 269    auto UseSet = LV->getAllReachedUses(DR, DA);270 271    for (auto UI : UseSet) {272      NodeAddr<UseNode *> UA = DFG->addr<UseNode *>(UI);273      LLVM_DEBUG({274        NodeAddr<StmtNode *> TempIA = UA.Addr->getOwner(*DFG);275        dbgs() << "\t\t\t[Reached Use]: "276               << Print<NodeAddr<InstrNode *>>(TempIA, *DFG) << "\n";277      });278 279      if (UA.Addr->getFlags() & NodeAttrs::PhiRef) {280        NodeAddr<PhiNode *> PA = UA.Addr->getOwner(*DFG);281        NodeId id = PA.Id;282        const Liveness::RefMap &phiUse = LV->getRealUses(id);283        LLVM_DEBUG(dbgs() << "\t\t\t\tphi real Uses"284                          << Print<Liveness::RefMap>(phiUse, *DFG) << "\n");285        if (!phiUse.empty()) {286          for (auto I : phiUse) {287            if (!DFG->getPRI().alias(RegisterRef(I.first), DR))288              continue;289            auto phiUseSet = I.second;290            for (auto phiUI : phiUseSet) {291              NodeAddr<UseNode *> phiUA = DFG->addr<UseNode *>(phiUI.first);292              UNodeList.push_back(phiUA);293            }294          }295        }296      } else297        UNodeList.push_back(UA);298    }299  }300}301 302bool HexagonOptAddrMode::isSafeToExtLR(NodeAddr<StmtNode *> SN,303                                       MachineInstr *MI, Register LRExtReg,304                                       const NodeList &UNodeList) {305  RegisterRef LRExtRR;306  NodeId LRExtRegRD = 0;307  // Iterate through all the UseNodes in SN and find the reaching def308  // for the LRExtReg.309  for (NodeAddr<UseNode *> UA : SN.Addr->members_if(DFG->IsUse, *DFG)) {310    RegisterRef RR = UA.Addr->getRegRef(*DFG);311    if (LRExtReg == RR.asMCReg()) {312      LRExtRR = RR;313      LRExtRegRD = UA.Addr->getReachingDef();314    }315  }316 317  for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) {318    NodeAddr<UseNode *> UA = *I;319    NodeAddr<InstrNode *> IA = UA.Addr->getOwner(*DFG);320    // The reaching def of LRExtRR at load/store node should be same as the321    // one reaching at the SN.322    if (UA.Addr->getFlags() & NodeAttrs::PhiRef)323      return false;324    NodeAddr<RefNode*> AA = LV->getNearestAliasedRef(LRExtRR, IA);325    if ((DFG->IsDef(AA) && AA.Id != LRExtRegRD) ||326        AA.Addr->getReachingDef() != LRExtRegRD) {327      LLVM_DEBUG(328          dbgs() << "isSafeToExtLR: Returning false; another reaching def\n");329      return false;330    }331 332    // If the register is undefined (for example if it's a reserved register),333    // it may still be possible to extend the range, but it's safer to be334    // conservative and just punt.335    if (LRExtRegRD == 0)336      return false;337 338    MachineInstr *UseMI = NodeAddr<StmtNode *>(IA).Addr->getCode();339    NodeAddr<DefNode *> LRExtRegDN = DFG->addr<DefNode *>(LRExtRegRD);340    // Reaching Def to LRExtReg can't be a phi.341    if ((LRExtRegDN.Addr->getFlags() & NodeAttrs::PhiRef) &&342        MI->getParent() != UseMI->getParent())343      return false;344    // Is the OffsetReg definition actually reaches UseMI?345    if (!UseMI->getParent()->isLiveIn(LRExtReg) &&346        MI->getParent() != UseMI->getParent()) {347      LLVM_DEBUG(dbgs() << "  The LRExtReg reg " << printReg(LRExtReg, TRI)348                        << " is NOT live in to MBB "349                        << UseMI->getParent()->getName() << "\n");350      return false;351    }352  }353  return true;354}355 356bool HexagonOptAddrMode::isValidOffset(MachineInstr *MI, int Offset) {357  if (HII->isHVXVec(*MI)) {358    // only HVX vgather instructions handled359    // TODO: extend the pass to other vector load/store operations360    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:367      return HII->isValidOffset(MI->getOpcode(), Offset, HRI, false);368    default:369      if (HII->getAddrMode(*MI) == HexagonII::BaseImmOffset) {370        // The immediates are mentioned in multiples of vector counts371        unsigned AlignMask = HII->getMemAccessSize(*MI) - 1;372        if ((AlignMask & Offset) == 0)373          return HII->isValidOffset(MI->getOpcode(), Offset, HRI, false);374      }375      return false;376    }377  }378 379  if (HII->getAddrMode(*MI) != HexagonII::BaseImmOffset)380    return false;381 382  unsigned AlignMask = 0;383  switch (HII->getMemAccessSize(*MI)) {384  case HexagonII::MemAccessSize::DoubleWordAccess:385    AlignMask = 0x7;386    break;387  case HexagonII::MemAccessSize::WordAccess:388    AlignMask = 0x3;389    break;390  case HexagonII::MemAccessSize::HalfWordAccess:391    AlignMask = 0x1;392    break;393  case HexagonII::MemAccessSize::ByteAccess:394    AlignMask = 0x0;395    break;396  default:397    return false;398  }399 400  if ((AlignMask & Offset) != 0)401    return false;402  return HII->isValidOffset(MI->getOpcode(), Offset, HRI, false);403}404 405unsigned HexagonOptAddrMode::getBaseOpPosition(MachineInstr *MI) {406  const MCInstrDesc &MID = MI->getDesc();407  switch (MI->getOpcode()) {408  // vgather pseudos are mayLoad and mayStore409  // hence need to explicitly specify Base and410  // Offset operand positions411  case Hexagon::V6_vgathermh_pseudo:412  case Hexagon::V6_vgathermw_pseudo:413  case Hexagon::V6_vgathermhw_pseudo:414  case Hexagon::V6_vgathermhq_pseudo:415  case Hexagon::V6_vgathermwq_pseudo:416  case Hexagon::V6_vgathermhwq_pseudo:417    return 0;418  default:419    return MID.mayLoad() ? 1 : 0;420  }421}422 423unsigned HexagonOptAddrMode::getOffsetOpPosition(MachineInstr *MI) {424  assert(425      (HII->getAddrMode(*MI) == HexagonII::BaseImmOffset) &&426      "Looking for an offset in non-BaseImmOffset addressing mode instruction");427 428  const MCInstrDesc &MID = MI->getDesc();429  switch (MI->getOpcode()) {430  // vgather pseudos are mayLoad and mayStore431  // hence need to explicitly specify Base and432  // Offset operand positions433  case Hexagon::V6_vgathermh_pseudo:434  case Hexagon::V6_vgathermw_pseudo:435  case Hexagon::V6_vgathermhw_pseudo:436  case Hexagon::V6_vgathermhq_pseudo:437  case Hexagon::V6_vgathermwq_pseudo:438  case Hexagon::V6_vgathermhwq_pseudo:439    return 1;440  default:441    return MID.mayLoad() ? 2 : 1;442  }443}444 445bool HexagonOptAddrMode::usedInLoadStore(NodeAddr<StmtNode *> CurrentInstSN,446                                         int64_t NewOffset) {447  NodeList LoadStoreUseList;448 449  getAllRealUses(CurrentInstSN, LoadStoreUseList);450  bool FoundLoadStoreUse = false;451  for (NodeAddr<UseNode *> UN : LoadStoreUseList) {452    NodeAddr<StmtNode *> SN = UN.Addr->getOwner(*DFG);453    MachineInstr *LoadStoreMI = SN.Addr->getCode();454    const MCInstrDesc &MID = LoadStoreMI->getDesc();455    if ((MID.mayLoad() || MID.mayStore()) &&456        isValidOffset(LoadStoreMI, NewOffset)) {457      FoundLoadStoreUse = true;458      break;459    }460  }461  return FoundLoadStoreUse;462}463 464bool HexagonOptAddrMode::findFirstReachedInst(465    MachineInstr *AddMI,466    std::vector<std::pair<NodeAddr<StmtNode *>, NodeAddr<UseNode *>>> &AddiList,467    NodeAddr<StmtNode *> &UseSN) {468  // Find the very first Addi instruction in the current basic block among the469  // AddiList This is the Addi that should be preserved so that we do not need470  // to handle the complexity of moving instructions471  //472  // TODO: find Addi instructions across basic blocks473  //474  // TODO: Try to remove this and add a solution that optimizes the number of475  // Addi instructions that can be modified.476  // This change requires choosing the Addi with the median offset value, but477  // would also require moving that instruction above the others. Since this478  // pass runs after register allocation, there might be multiple cases that479  // need to be handled if we move instructions around480  MachineBasicBlock *CurrentMBB = AddMI->getParent();481  for (auto &InstIter : *CurrentMBB) {482    // If the instruction is an Addi and is in the AddiList483    if (InstIter.getOpcode() == Hexagon::A2_addi) {484      auto Iter = llvm::find_if(AddiList, [&InstIter](const auto &SUPair) {485        return SUPair.first.Addr->getCode() == &InstIter;486      });487      if (Iter != AddiList.end()) {488        UseSN = Iter->first;489        return true;490      }491    }492  }493  return false;494}495 496// This function tries to modify the immediate value in Hexagon::Addi497// instructions, so that the immediates could then be moved into a load/store498// instruction with offset and the add removed completely when we call499// processAddUses500//501// For Example, If we have the below sequence of instructions:502//503//         r1 = add(r2,#1024)504//               ...505//         r3 = add(r2,#1152)506//               ...507//         r4 = add(r2,#1280)508//509// Where the register r2 has the same reaching definition, They get modified to510// the below sequence:511//512//         r1 = add(r2,#1024)513//              ...514//         r3 = add(r1,#128)515//              ...516//         r4 = add(r1,#256)517//518//  The below change helps the processAddUses method to later move the519//  immediates #128 and #256 into a load/store instruction that can take an520//  offset, like the Vd = mem(Rt+#s4)521bool HexagonOptAddrMode::processAddBases(NodeAddr<StmtNode *> AddSN,522                                         MachineInstr *AddMI) {523 524  bool Changed = false;525 526  LLVM_DEBUG(dbgs() << "\n\t\t[Processing Addi]: " << *AddMI << "\n");527 528  auto Processed =529      [](const MachineInstr *MI,530         const DenseSet<MachineInstr *> &ProcessedAddiInsts) -> bool {531    // If we've already processed this Addi, just return532    if (ProcessedAddiInsts.contains(MI)) {533      LLVM_DEBUG(dbgs() << "\t\t\tAddi already found in ProcessedAddiInsts: "534                        << *MI << "\n\t\t\tSkipping...");535      return true;536    }537    return false;538  };539 540  if (Processed(AddMI, ProcessedAddiInsts))541    return Changed;542  ProcessedAddiInsts.insert(AddMI);543 544  // Get the base register that would be shared by other Addi Instructions545  Register BaseReg = AddMI->getOperand(1).getReg();546 547  // Store a list of all Addi instructions that share the above common base548  // register549  std::vector<std::pair<NodeAddr<StmtNode *>, NodeAddr<UseNode *>>> AddiList;550 551  NodeId UAReachingDefID;552  // Find the UseNode that contains the base register and it's reachingDef553  for (NodeAddr<UseNode *> UA : AddSN.Addr->members_if(DFG->IsUse, *DFG)) {554    RegisterRef URR = UA.Addr->getRegRef(*DFG);555    if (BaseReg != URR.asMCReg())556      continue;557 558    UAReachingDefID = UA.Addr->getReachingDef();559    NodeAddr<DefNode *> UADef = DFG->addr<DefNode *>(UAReachingDefID);560    if (!UAReachingDefID || UADef.Addr->getFlags() & NodeAttrs::PhiRef) {561      LLVM_DEBUG(dbgs() << "\t\t\t Could not find reachingDef. Skipping...\n");562      return false;563    }564  }565 566  NodeAddr<DefNode *> UAReachingDef = DFG->addr<DefNode *>(UAReachingDefID);567  NodeAddr<StmtNode *> ReachingDefStmt = UAReachingDef.Addr->getOwner(*DFG);568 569  // If the reaching definition is a predicated instruction, this might not be570  // the only definition of our base register, so return immediately.571  MachineInstr *ReachingDefInstr = ReachingDefStmt.Addr->getCode();572  if (HII->isPredicated(*ReachingDefInstr))573    return false;574 575  NodeList AddiUseList;576 577  // Find all Addi instructions that share the same base register and add them578  // to the AddiList579  getAllRealUses(ReachingDefStmt, AddiUseList);580  for (NodeAddr<UseNode *> UN : AddiUseList) {581    NodeAddr<StmtNode *> SN = UN.Addr->getOwner(*DFG);582    MachineInstr *MI = SN.Addr->getCode();583 584    // Only add instructions if it's an Addi and it's not already processed.585    if (MI->getOpcode() == Hexagon::A2_addi &&586        !(MI != AddMI && Processed(MI, ProcessedAddiInsts))) {587      AddiList.push_back({SN, UN});588 589      // This ensures that we process each instruction only once590      ProcessedAddiInsts.insert(MI);591    }592  }593 594  // If there's only one Addi instruction, nothing to do here595  if (AddiList.size() <= 1)596    return Changed;597 598  NodeAddr<StmtNode *> FirstReachedUseSN;599  // Find the first reached use of Addi instruction from the list600  if (!findFirstReachedInst(AddMI, AddiList, FirstReachedUseSN))601    return Changed;602 603  // If we reach this point we know that the StmtNode FirstReachedUseSN is for604  // an Addi instruction. So, we're guaranteed to have just one DefNode, and605  // hence we can access the front() directly without checks606  NodeAddr<DefNode *> FirstReachedUseDN =607      FirstReachedUseSN.Addr->members_if(DFG->IsDef, *DFG).front();608 609  MachineInstr *FirstReachedMI = FirstReachedUseSN.Addr->getCode();610  const MachineOperand FirstReachedMIImmOp = FirstReachedMI->getOperand(2);611  if (!FirstReachedMIImmOp.isImm())612    return false;613 614  for (auto &I : AddiList) {615    NodeAddr<StmtNode *> CurrentInstSN = I.first;616    NodeAddr<UseNode *> CurrentInstUN = I.second;617 618    MachineInstr *CurrentMI = CurrentInstSN.Addr->getCode();619    MachineOperand &CurrentMIImmOp = CurrentMI->getOperand(2);620 621    int64_t NewOffset;622 623    // Even though we know it's an Addi instruction, the second operand could be624    // a global value and not an immediate625    if (!CurrentMIImmOp.isImm())626      continue;627 628    NewOffset = CurrentMIImmOp.getImm() - FirstReachedMIImmOp.getImm();629 630    // This is the first occurring Addi, so skip modifying this631    if (CurrentMI == FirstReachedMI) {632      continue;633    }634 635    if (CurrentMI->getParent() != FirstReachedMI->getParent())636      continue;637 638    // Modify the Addi instruction only if it could be used to modify a639    // future load/store instruction and get removed640    //641    // This check is needed because, if we modify the current Addi instruction642    // we create RAW dependence between the FirstReached Addi and the current643    // one, which could result in extra packets. So we only do this change if644    // we know the current Addi would get removed later645    if (!usedInLoadStore(CurrentInstSN, NewOffset)) {646      return false;647    }648 649    // Verify whether the First Addi's definition register is still live when650    // we reach the current Addi651    RegisterRef FirstReachedDefRR = FirstReachedUseDN.Addr->getRegRef(*DFG);652    NodeAddr<InstrNode *> CurrentAddiIN = CurrentInstUN.Addr->getOwner(*DFG);653    NodeAddr<RefNode *> NearestAA =654        LV->getNearestAliasedRef(FirstReachedDefRR, CurrentAddiIN);655    if ((DFG->IsDef(NearestAA) && NearestAA.Id != FirstReachedUseDN.Id) ||656        (!DFG->IsDef(NearestAA) &&657         NearestAA.Addr->getReachingDef() != FirstReachedUseDN.Id)) {658      // Found another definition of FirstReachedDef659      LLVM_DEBUG(dbgs() << "\t\t\tCould not modify below Addi since the first "660                           "defined Addi register was redefined\n");661      continue;662    }663 664    MachineOperand CurrentMIBaseOp = CurrentMI->getOperand(1);665    if (CurrentMIBaseOp.getReg() != FirstReachedMI->getOperand(1).getReg()) {666      continue;667    }668 669    // If we reached this point, then we can modify MI to use the result of670    // FirstReachedMI671    Changed |= updateAddBases(CurrentMI, FirstReachedMI, NewOffset);672 673    // Update the reachingDef of the Current AddI use after change674    CurrentInstUN.Addr->linkToDef(CurrentInstUN.Id, FirstReachedUseDN);675  }676 677  return Changed;678}679 680bool HexagonOptAddrMode::updateAddBases(MachineInstr *CurrentMI,681                                        MachineInstr *FirstReachedMI,682                                        int64_t NewOffset) {683  LLVM_DEBUG(dbgs() << "[About to modify the Addi]: " << *CurrentMI << "\n");684  const MachineOperand FirstReachedDef = FirstReachedMI->getOperand(0);685  Register FirstDefRegister = FirstReachedDef.getReg();686 687  MachineOperand &CurrentMIBaseOp = CurrentMI->getOperand(1);688  MachineOperand &CurrentMIImmOp = CurrentMI->getOperand(2);689 690  CurrentMIBaseOp.setReg(FirstDefRegister);691  CurrentMIBaseOp.setIsUndef(FirstReachedDef.isUndef());692  CurrentMIBaseOp.setImplicit(FirstReachedDef.isImplicit());693  CurrentMIImmOp.setImm(NewOffset);694  ProcessedAddiInsts.insert(CurrentMI);695  MRI->clearKillFlags(FirstDefRegister);696  return true;697}698 699bool HexagonOptAddrMode::processAddUses(NodeAddr<StmtNode *> AddSN,700                                        MachineInstr *AddMI,701                                        const NodeList &UNodeList) {702 703  Register AddDefR = AddMI->getOperand(0).getReg();704  Register BaseReg = AddMI->getOperand(1).getReg();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();710    if ((!MID.mayLoad() && !MID.mayStore()) ||711        HII->getAddrMode(*MI) != HexagonII::BaseImmOffset)712      return false;713 714    MachineOperand BaseOp = MI->getOperand(getBaseOpPosition(MI));715 716    if (!BaseOp.isReg() || BaseOp.getReg() != AddDefR)717      return false;718 719    MachineOperand OffsetOp = MI->getOperand(getOffsetOpPosition(MI));720    if (!OffsetOp.isImm())721      return false;722 723    int64_t newOffset = OffsetOp.getImm() + AddMI->getOperand(2).getImm();724    if (!isValidOffset(MI, newOffset))725      return false;726 727    // Since we'll be extending the live range of Rt in the following example,728    // make sure that is safe. another definition of Rt doesn't exist between 'add'729    // and load/store instruction.730    //731    // Ex: Rx= add(Rt,#10)732    //     memw(Rx+#0) = Rs733    // will be replaced with =>  memw(Rt+#10) = Rs734    if (!isSafeToExtLR(AddSN, AddMI, BaseReg, UNodeList))735      return false;736  }737 738  NodeId LRExtRegRD = 0;739  // Iterate through all the UseNodes in SN and find the reaching def740  // for the LRExtReg.741  for (NodeAddr<UseNode *> UA : AddSN.Addr->members_if(DFG->IsUse, *DFG)) {742    RegisterRef RR = UA.Addr->getRegRef(*DFG);743    if (BaseReg == RR.asMCReg())744      LRExtRegRD = UA.Addr->getReachingDef();745  }746 747  // Update all the uses of 'add' with the appropriate base and offset748  // values.749  bool Changed = false;750  for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) {751    NodeAddr<UseNode *> UseN = *I;752    assert(!(UseN.Addr->getFlags() & NodeAttrs::PhiRef) &&753           "Found a PhiRef node as a real reached use!!");754 755    NodeAddr<StmtNode *> OwnerN = UseN.Addr->getOwner(*DFG);756    MachineInstr *UseMI = OwnerN.Addr->getCode();757    LLVM_DEBUG(dbgs() << "\t\t[MI <BB#" << UseMI->getParent()->getNumber()758                      << ">]: " << *UseMI << "\n");759    Changed |= updateAddUses(AddMI, UseMI);760 761    // Set the reachingDef for UseNode under consideration762    // after updating the Add use. This local change is763    // to avoid rebuilding of the RDF graph after update.764    NodeAddr<DefNode *> LRExtRegDN = DFG->addr<DefNode *>(LRExtRegRD);765    UseN.Addr->linkToDef(UseN.Id, LRExtRegDN);766  }767 768  if (Changed)769    Deleted.insert(AddMI);770 771  return Changed;772}773 774bool HexagonOptAddrMode::updateAddUses(MachineInstr *AddMI,775                                       MachineInstr *UseMI) {776  const MachineOperand ImmOp = AddMI->getOperand(2);777  const MachineOperand AddRegOp = AddMI->getOperand(1);778  Register NewReg = AddRegOp.getReg();779 780  MachineOperand &BaseOp = UseMI->getOperand(getBaseOpPosition(UseMI));781  MachineOperand &OffsetOp = UseMI->getOperand(getOffsetOpPosition(UseMI));782  BaseOp.setReg(NewReg);783  BaseOp.setIsUndef(AddRegOp.isUndef());784  BaseOp.setImplicit(AddRegOp.isImplicit());785  OffsetOp.setImm(ImmOp.getImm() + OffsetOp.getImm());786  MRI->clearKillFlags(NewReg);787 788  return true;789}790 791bool HexagonOptAddrMode::analyzeUses(unsigned tfrDefR,792                                     const NodeList &UNodeList,793                                     InstrEvalMap &InstrEvalResult,794                                     short &SizeInc) {795  bool KeepTfr = false;796  bool HasRepInstr = false;797  InstrEvalResult.clear();798 799  for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) {800    bool CanBeReplaced = false;801    NodeAddr<UseNode *> UN = *I;802    NodeAddr<StmtNode *> SN = UN.Addr->getOwner(*DFG);803    MachineInstr &MI = *SN.Addr->getCode();804    const MCInstrDesc &MID = MI.getDesc();805    if ((MID.mayLoad() || MID.mayStore())) {806      if (!hasRepForm(MI, tfrDefR)) {807        KeepTfr = true;808        continue;809      }810      SizeInc++;811      CanBeReplaced = true;812    } else if (MI.getOpcode() == Hexagon::S2_addasl_rrri) {813      NodeList AddaslUseList;814 815      LLVM_DEBUG(dbgs() << "\nGetting ReachedUses for === " << MI << "\n");816      getAllRealUses(SN, AddaslUseList);817      // Process phi nodes.818      if (allValidCandidates(SN, AddaslUseList) &&819          canRemoveAddasl(SN, MI, AddaslUseList)) {820        SizeInc += AddaslUseList.size();821        SizeInc -= 1; // Reduce size by 1 as addasl itself can be removed.822        CanBeReplaced = true;823      } else824        SizeInc++;825    } else826      // Currently, only load/store and addasl are handled.827      // Some other instructions to consider -828      // A2_add -> A2_addi829      // M4_mpyrr_addr -> M4_mpyrr_addi830      KeepTfr = true;831 832    InstrEvalResult[&MI] = CanBeReplaced;833    HasRepInstr |= CanBeReplaced;834  }835 836  // Reduce total size by 2 if original tfr can be deleted.837  if (!KeepTfr)838    SizeInc -= 2;839 840  return HasRepInstr;841}842 843bool HexagonOptAddrMode::changeLoad(MachineInstr *OldMI, MachineOperand ImmOp,844                                    unsigned ImmOpNum) {845  bool Changed = false;846  MachineBasicBlock *BB = OldMI->getParent();847  auto UsePos = MachineBasicBlock::iterator(OldMI);848  MachineBasicBlock::instr_iterator InsertPt = UsePos.getInstrIterator();849  ++InsertPt;850  unsigned OpStart;851  unsigned OpEnd = OldMI->getNumOperands();852  MachineInstrBuilder MIB;853 854  if (ImmOpNum == 1) {855    if (HII->getAddrMode(*OldMI) == HexagonII::BaseRegOffset) {856      short NewOpCode = HII->changeAddrMode_rr_ur(*OldMI);857      assert(NewOpCode >= 0 && "Invalid New opcode\n");858      MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode));859      MIB.add(OldMI->getOperand(0));860      MIB.add(OldMI->getOperand(2));861      MIB.add(OldMI->getOperand(3));862      MIB.add(ImmOp);863      OpStart = 4;864      Changed = true;865    } else if (HII->getAddrMode(*OldMI) == HexagonII::BaseImmOffset &&866               OldMI->getOperand(2).isImm()) {867      short NewOpCode = HII->changeAddrMode_io_abs(*OldMI);868      assert(NewOpCode >= 0 && "Invalid New opcode\n");869      MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode))870                .add(OldMI->getOperand(0));871      const GlobalValue *GV = ImmOp.getGlobal();872      int64_t Offset = ImmOp.getOffset() + OldMI->getOperand(2).getImm();873 874      MIB.addGlobalAddress(GV, Offset, ImmOp.getTargetFlags());875      OpStart = 3;876      Changed = true;877    } else878      Changed = false;879 880    LLVM_DEBUG(dbgs() << "[Changing]: " << *OldMI << "\n");881    LLVM_DEBUG(dbgs() << "[TO]: " << *MIB << "\n");882  } else if (ImmOpNum == 2) {883    if (OldMI->getOperand(3).isImm() && OldMI->getOperand(3).getImm() == 0) {884      short NewOpCode = HII->changeAddrMode_rr_io(*OldMI);885      assert(NewOpCode >= 0 && "Invalid New opcode\n");886      MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode));887      MIB.add(OldMI->getOperand(0));888      MIB.add(OldMI->getOperand(1));889      MIB.add(ImmOp);890      OpStart = 4;891      Changed = true;892      LLVM_DEBUG(dbgs() << "[Changing]: " << *OldMI << "\n");893      LLVM_DEBUG(dbgs() << "[TO]: " << *MIB << "\n");894    }895  }896 897  if (Changed)898    for (unsigned i = OpStart; i < OpEnd; ++i)899      MIB.add(OldMI->getOperand(i));900 901  return Changed;902}903 904bool HexagonOptAddrMode::changeStore(MachineInstr *OldMI, MachineOperand ImmOp,905                                     unsigned ImmOpNum) {906  bool Changed = false;907  unsigned OpStart = 0;908  unsigned OpEnd = OldMI->getNumOperands();909  MachineBasicBlock *BB = OldMI->getParent();910  auto UsePos = MachineBasicBlock::iterator(OldMI);911  MachineBasicBlock::instr_iterator InsertPt = UsePos.getInstrIterator();912  ++InsertPt;913  MachineInstrBuilder MIB;914  if (ImmOpNum == 0) {915    if (HII->getAddrMode(*OldMI) == HexagonII::BaseRegOffset) {916      short NewOpCode = HII->changeAddrMode_rr_ur(*OldMI);917      assert(NewOpCode >= 0 && "Invalid New opcode\n");918      MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode));919      MIB.add(OldMI->getOperand(1));920      MIB.add(OldMI->getOperand(2));921      MIB.add(ImmOp);922      MIB.add(OldMI->getOperand(3));923      OpStart = 4;924      Changed = true;925    } else if (HII->getAddrMode(*OldMI) == HexagonII::BaseImmOffset) {926      short NewOpCode = HII->changeAddrMode_io_abs(*OldMI);927      assert(NewOpCode >= 0 && "Invalid New opcode\n");928      MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode));929      const GlobalValue *GV = ImmOp.getGlobal();930      int64_t Offset = ImmOp.getOffset() + OldMI->getOperand(1).getImm();931      MIB.addGlobalAddress(GV, Offset, ImmOp.getTargetFlags());932      MIB.add(OldMI->getOperand(2));933      OpStart = 3;934      Changed = true;935    }936  } else if (ImmOpNum == 1 && OldMI->getOperand(2).getImm() == 0) {937    short NewOpCode = HII->changeAddrMode_rr_io(*OldMI);938    assert(NewOpCode >= 0 && "Invalid New opcode\n");939    MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode));940    MIB.add(OldMI->getOperand(0));941    MIB.add(ImmOp);942    OpStart = 3;943    Changed = true;944  }945  if (Changed) {946    LLVM_DEBUG(dbgs() << "[Changing]: " << *OldMI << "\n");947    LLVM_DEBUG(dbgs() << "[TO]: " << *MIB << "\n");948 949    for (unsigned i = OpStart; i < OpEnd; ++i)950      MIB.add(OldMI->getOperand(i));951  }952 953  return Changed;954}955 956short HexagonOptAddrMode::getBaseWithLongOffset(const MachineInstr &MI) const {957  if (HII->getAddrMode(MI) == HexagonII::BaseImmOffset) {958    short TempOpCode = HII->changeAddrMode_io_rr(MI);959    return HII->changeAddrMode_rr_ur(TempOpCode);960  }961  return HII->changeAddrMode_rr_ur(MI);962}963 964bool HexagonOptAddrMode::changeAddAsl(NodeAddr<UseNode *> AddAslUN,965                                      MachineInstr *AddAslMI,966                                      const MachineOperand &ImmOp,967                                      unsigned ImmOpNum) {968  NodeAddr<StmtNode *> SA = AddAslUN.Addr->getOwner(*DFG);969 970  LLVM_DEBUG(dbgs() << "Processing addasl :" << *AddAslMI << "\n");971 972  NodeList UNodeList;973  getAllRealUses(SA, UNodeList);974 975  for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) {976    NodeAddr<UseNode *> UseUN = *I;977    assert(!(UseUN.Addr->getFlags() & NodeAttrs::PhiRef) &&978           "Can't transform this 'AddAsl' instruction!");979 980    NodeAddr<StmtNode *> UseIA = UseUN.Addr->getOwner(*DFG);981    LLVM_DEBUG(dbgs() << "[InstrNode]: "982                      << Print<NodeAddr<InstrNode *>>(UseIA, *DFG) << "\n");983    MachineInstr *UseMI = UseIA.Addr->getCode();984    LLVM_DEBUG(dbgs() << "[MI <" << printMBBReference(*UseMI->getParent())985                      << ">]: " << *UseMI << "\n");986    const MCInstrDesc &UseMID = UseMI->getDesc();987    assert(HII->getAddrMode(*UseMI) == HexagonII::BaseImmOffset);988 989    auto UsePos = MachineBasicBlock::iterator(UseMI);990    MachineBasicBlock::instr_iterator InsertPt = UsePos.getInstrIterator();991    short NewOpCode = getBaseWithLongOffset(*UseMI);992    assert(NewOpCode >= 0 && "Invalid New opcode\n");993 994    unsigned OpStart;995    unsigned OpEnd = UseMI->getNumOperands();996 997    MachineBasicBlock *BB = UseMI->getParent();998    MachineInstrBuilder MIB =999        BuildMI(*BB, InsertPt, UseMI->getDebugLoc(), HII->get(NewOpCode));1000    // change mem(Rs + # ) -> mem(Rt << # + ##)1001    if (UseMID.mayLoad()) {1002      MIB.add(UseMI->getOperand(0));1003      MIB.add(AddAslMI->getOperand(2));1004      MIB.add(AddAslMI->getOperand(3));1005      const GlobalValue *GV = ImmOp.getGlobal();1006      MIB.addGlobalAddress(GV, UseMI->getOperand(2).getImm()+ImmOp.getOffset(),1007                           ImmOp.getTargetFlags());1008      OpStart = 3;1009    } else if (UseMID.mayStore()) {1010      MIB.add(AddAslMI->getOperand(2));1011      MIB.add(AddAslMI->getOperand(3));1012      const GlobalValue *GV = ImmOp.getGlobal();1013      MIB.addGlobalAddress(GV, UseMI->getOperand(1).getImm()+ImmOp.getOffset(),1014                           ImmOp.getTargetFlags());1015      MIB.add(UseMI->getOperand(2));1016      OpStart = 3;1017    } else1018      llvm_unreachable("Unhandled instruction");1019 1020    for (unsigned i = OpStart; i < OpEnd; ++i)1021      MIB.add(UseMI->getOperand(i));1022    Deleted.insert(UseMI);1023  }1024 1025  return true;1026}1027 1028bool HexagonOptAddrMode::xformUseMI(MachineInstr *TfrMI, MachineInstr *UseMI,1029                                    NodeAddr<UseNode *> UseN,1030                                    unsigned UseMOnum) {1031  const MachineOperand ImmOp = TfrMI->getOperand(1);1032  const MCInstrDesc &MID = UseMI->getDesc();1033  unsigned Changed = false;1034  if (MID.mayLoad())1035    Changed = changeLoad(UseMI, ImmOp, UseMOnum);1036  else if (MID.mayStore())1037    Changed = changeStore(UseMI, ImmOp, UseMOnum);1038  else if (UseMI->getOpcode() == Hexagon::S2_addasl_rrri)1039    Changed = changeAddAsl(UseN, UseMI, ImmOp, UseMOnum);1040 1041  if (Changed)1042    Deleted.insert(UseMI);1043 1044  return Changed;1045}1046 1047bool HexagonOptAddrMode::processBlock(NodeAddr<BlockNode *> BA) {1048  bool Changed = false;1049 1050  for (auto IA : BA.Addr->members(*DFG)) {1051    if (!DFG->IsCode<NodeAttrs::Stmt>(IA))1052      continue;1053 1054    NodeAddr<StmtNode *> SA = IA;1055    MachineInstr *MI = SA.Addr->getCode();1056    if ((MI->getOpcode() != Hexagon::A2_tfrsi ||1057         !MI->getOperand(1).isGlobal()) &&1058        (MI->getOpcode() != Hexagon::A2_addi ||1059         !MI->getOperand(2).isImm() || HII->isConstExtended(*MI)))1060    continue;1061 1062    LLVM_DEBUG(dbgs() << "[Analyzing " << HII->getName(MI->getOpcode())1063                      << "]: " << *MI << "\n\t[InstrNode]: "1064                      << Print<NodeAddr<InstrNode *>>(IA, *DFG) << '\n');1065 1066    if (MI->getOpcode() == Hexagon::A2_addi)1067      Changed |= processAddBases(SA, MI);1068    NodeList UNodeList;1069    getAllRealUses(SA, UNodeList);1070 1071    if (!allValidCandidates(SA, UNodeList))1072      continue;1073 1074    // Analyze all uses of 'add'. If the output of 'add' is used as an address1075    // in the base+immediate addressing mode load/store instructions, see if1076    // they can be updated to use the immediate value as an offset. Thus,1077    // providing us the opportunity to eliminate 'add'.1078    // Ex: Rx= add(Rt,#12)1079    //     memw(Rx+#0) = Rs1080    // This can be replaced with memw(Rt+#12) = Rs1081    //1082    // This transformation is only performed if all uses can be updated and1083    // the offset isn't required to be constant extended.1084    if (MI->getOpcode() == Hexagon::A2_addi) {1085      Changed |= processAddUses(SA, MI, UNodeList);1086      continue;1087    }1088 1089    short SizeInc = 0;1090    Register DefR = MI->getOperand(0).getReg();1091    InstrEvalMap InstrEvalResult;1092 1093    // Analyze all uses and calculate increase in size. Perform the optimization1094    // only if there is no increase in size.1095    if (!analyzeUses(DefR, UNodeList, InstrEvalResult, SizeInc))1096      continue;1097    if (SizeInc > CodeGrowthLimit)1098      continue;1099 1100    bool KeepTfr = false;1101 1102    LLVM_DEBUG(dbgs() << "\t[Total reached uses] : " << UNodeList.size()1103                      << "\n");1104    LLVM_DEBUG(dbgs() << "\t[Processing Reached Uses] ===\n");1105    for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) {1106      NodeAddr<UseNode *> UseN = *I;1107      assert(!(UseN.Addr->getFlags() & NodeAttrs::PhiRef) &&1108             "Found a PhiRef node as a real reached use!!");1109 1110      NodeAddr<StmtNode *> OwnerN = UseN.Addr->getOwner(*DFG);1111      MachineInstr *UseMI = OwnerN.Addr->getCode();1112      LLVM_DEBUG(dbgs() << "\t\t[MI <" << printMBBReference(*UseMI->getParent())1113                        << ">]: " << *UseMI << "\n");1114 1115      int UseMOnum = -1;1116      unsigned NumOperands = UseMI->getNumOperands();1117      for (unsigned j = 0; j < NumOperands - 1; ++j) {1118        const MachineOperand &op = UseMI->getOperand(j);1119        if (op.isReg() && op.isUse() && DefR == op.getReg())1120          UseMOnum = j;1121      }1122      // It is possible that the register will not be found in any operand.1123      // This could happen, for example, when DefR = R4, but the used1124      // register is D2.1125 1126      // Change UseMI if replacement is possible. If any replacement failed,1127      // or wasn't attempted, make sure to keep the TFR.1128      bool Xformed = false;1129      if (UseMOnum >= 0 && InstrEvalResult[UseMI])1130        Xformed = xformUseMI(MI, UseMI, UseN, UseMOnum);1131      Changed |=  Xformed;1132      KeepTfr |= !Xformed;1133    }1134    if (!KeepTfr)1135      Deleted.insert(MI);1136  }1137  return Changed;1138}1139 1140bool HexagonOptAddrMode::runOnMachineFunction(MachineFunction &MF) {1141  if (skipFunction(MF.getFunction()))1142    return false;1143 1144  // Perform RDF optimizations only if number of basic blocks in the1145  // function is less than the limit1146  if (MF.size() > RDFFuncBlockLimit) {1147    LLVM_DEBUG(dbgs() << "Skipping " << getPassName()1148                      << ": too many basic blocks\n");1149    return false;1150  }1151 1152  bool Changed = false;1153  auto &HST = MF.getSubtarget<HexagonSubtarget>();1154  MRI = &MF.getRegInfo();1155  TRI = MF.getSubtarget().getRegisterInfo();1156  HII = HST.getInstrInfo();1157  HRI = HST.getRegisterInfo();1158  const auto &MDF = getAnalysis<MachineDominanceFrontier>();1159  MDT = &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();1160 1161  DataFlowGraph G(MF, *HII, *HRI, *MDT, MDF);1162  // Need to keep dead phis because we can propagate uses of registers into1163  // nodes dominated by those would-be phis.1164  G.build(BuildOptions::KeepDeadPhis);1165  DFG = &G;1166 1167  Liveness L(*MRI, *DFG);1168  L.computePhiInfo();1169  LV = &L;1170 1171  Deleted.clear();1172  ProcessedAddiInsts.clear();1173  NodeAddr<FuncNode *> FA = DFG->getFunc();1174  LLVM_DEBUG(dbgs() << "==== [RefMap#]=====:\n "1175                    << Print<NodeAddr<FuncNode *>>(FA, *DFG) << "\n");1176 1177  for (NodeAddr<BlockNode *> BA : FA.Addr->members(*DFG))1178    Changed |= processBlock(BA);1179 1180  for (auto *MI : Deleted)1181    MI->eraseFromParent();1182 1183  if (Changed) {1184    G.build();1185    L.computeLiveIns();1186    L.resetLiveIns();1187    L.resetKills();1188  }1189 1190  return Changed;1191}1192 1193//===----------------------------------------------------------------------===//1194//                         Public Constructor Functions1195//===----------------------------------------------------------------------===//1196 1197FunctionPass *llvm::createHexagonOptAddrMode() {1198  return new HexagonOptAddrMode();1199}1200