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