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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // This implements a Hexagon-specific pass to optimize addressing mode for 9 // 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 44 using namespace llvm; 45 using namespace rdf; 46 47 static 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 51 extern cl::opt<unsigned> RDFFuncBlockLimit; 52 53 namespace { 54 55 class HexagonOptAddrMode : public MachineFunctionPass { 56 public: 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 74 private: 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 unsigned 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 namespace 125 126 char HexagonOptAddrMode::ID = 0; 127 128 INITIALIZE_PASS_BEGIN(HexagonOptAddrMode, "amode-opt", 129 "Optimize addressing mode", false, false) 130 INITIALIZE_PASS_DEPENDENCY(MachineDominatorTreeWrapperPass) 131 INITIALIZE_PASS_DEPENDENCY(MachineDominanceFrontier) 132 INITIALIZE_PASS_END(HexagonOptAddrMode, "amode-opt", "Optimize addressing mode", 133 false, false) 134 135 bool 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 only 158 // if it's feeding to only load/store instructions with base + register 159 // offset as these instruction can be transformed to use 'absolute plus 160 // shifted register offset'. 161 // ex: 162 // Rs = ##foo 163 // 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 167 bool HexagonOptAddrMode::canRemoveAddasl(NodeAddr<StmtNode *> AddAslSN, 168 MachineInstr &MI, 169 const NodeList &UNodeList) { 170 // check offset size in addasl. if 'offset > 3' return false 171 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.Reg) { 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 230 bool 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 262 void 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 } else 297 UNodeList.push_back(UA); 298 } 299 } 300 } 301 302 bool HexagonOptAddrMode::isSafeToExtLR(NodeAddr<StmtNode *> SN, 303 MachineInstr *MI, unsigned LRExtReg, 304 const NodeList &UNodeList) { 305 RegisterRef LRExtRR; 306 NodeId LRExtRegRD = 0; 307 // Iterate through all the UseNodes in SN and find the reaching def 308 // 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.Reg) { 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 the 321 // 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 be 334 // 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 356 bool HexagonOptAddrMode::isValidOffset(MachineInstr *MI, int Offset) { 357 if (HII->isHVXVec(*MI)) { 358 // only HVX vgather instructions handled 359 // TODO: extend the pass to other vector load/store operations 360 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 counts 371 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 405 unsigned HexagonOptAddrMode::getBaseOpPosition(MachineInstr *MI) { 406 const MCInstrDesc &MID = MI->getDesc(); 407 switch (MI->getOpcode()) { 408 // vgather pseudos are mayLoad and mayStore 409 // hence need to explicitly specify Base and 410 // Offset operand positions 411 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 423 unsigned 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 mayStore 431 // hence need to explicitly specify Base and 432 // Offset operand positions 433 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 445 bool 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 464 bool 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 the 469 // AddiList This is the Addi that should be preserved so that we do not need 470 // to handle the complexity of moving instructions 471 // 472 // TODO: find Addi instructions across basic blocks 473 // 474 // TODO: Try to remove this and add a solution that optimizes the number of 475 // Addi instructions that can be modified. 476 // This change requires choosing the Addi with the median offset value, but 477 // would also require moving that instruction above the others. Since this 478 // pass runs after register allocation, there might be multiple cases that 479 // need to be handled if we move instructions around 480 MachineBasicBlock *CurrentMBB = AddMI->getParent(); 481 for (auto &InstIter : *CurrentMBB) { 482 // If the instruction is an Addi and is in the AddiList 483 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::Addi 497 // instructions, so that the immediates could then be moved into a load/store 498 // instruction with offset and the add removed completely when we call 499 // processAddUses 500 // 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 to 510 // 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 the 519 // immediates #128 and #256 into a load/store instruction that can take an 520 // offset, like the Vd = mem(Rt+#s4) 521 bool 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 return 532 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 Instructions 545 Register BaseReg = AddMI->getOperand(1).getReg(); 546 547 // Store a list of all Addi instructions that share the above common base 548 // register 549 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 reachingDef 553 for (NodeAddr<UseNode *> UA : AddSN.Addr->members_if(DFG->IsUse, *DFG)) { 554 RegisterRef URR = UA.Addr->getRegRef(*DFG); 555 if (BaseReg != URR.Reg) 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 be 570 // 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 them 578 // to the AddiList 579 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 once 590 ProcessedAddiInsts.insert(MI); 591 } 592 } 593 594 // If there's only one Addi instruction, nothing to do here 595 if (AddiList.size() <= 1) 596 return Changed; 597 598 NodeAddr<StmtNode *> FirstReachedUseSN; 599 // Find the first reached use of Addi instruction from the list 600 if (!findFirstReachedInst(AddMI, AddiList, FirstReachedUseSN)) 601 return Changed; 602 603 // If we reach this point we know that the StmtNode FirstReachedUseSN is for 604 // an Addi instruction. So, we're guaranteed to have just one DefNode, and 605 // hence we can access the front() directly without checks 606 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 be 624 // a global value and not an immediate 625 if (!CurrentMIImmOp.isImm()) 626 continue; 627 628 NewOffset = CurrentMIImmOp.getImm() - FirstReachedMIImmOp.getImm(); 629 630 // This is the first occurring Addi, so skip modifying this 631 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 a 639 // future load/store instruction and get removed 640 // 641 // This check is needed because, if we modify the current Addi instruction 642 // we create RAW dependence between the FirstReached Addi and the current 643 // one, which could result in extra packets. So we only do this change if 644 // we know the current Addi would get removed later 645 if (!usedInLoadStore(CurrentInstSN, NewOffset)) { 646 return false; 647 } 648 649 // Verify whether the First Addi's definition register is still live when 650 // we reach the current Addi 651 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 FirstReachedDef 659 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 of 670 // FirstReachedMI 671 Changed |= updateAddBases(CurrentMI, FirstReachedMI, NewOffset); 672 673 // Update the reachingDef of the Current AddI use after change 674 CurrentInstUN.Addr->linkToDef(CurrentInstUN.Id, FirstReachedUseDN); 675 } 676 677 return Changed; 678 } 679 680 bool 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 699 bool 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) = Rs 733 // will be replaced with => memw(Rt+#10) = Rs 734 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 def 740 // 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.Reg) 744 LRExtRegRD = UA.Addr->getReachingDef(); 745 } 746 747 // Update all the uses of 'add' with the appropriate base and offset 748 // 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 consideration 762 // after updating the Add use. This local change is 763 // 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 774 bool 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 791 bool 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 } else 824 SizeInc++; 825 } else 826 // Currently, only load/store and addasl are handled. 827 // Some other instructions to consider - 828 // A2_add -> A2_addi 829 // M4_mpyrr_addr -> M4_mpyrr_addi 830 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 843 bool 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 } else 878 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 904 bool 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 956 short 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 964 bool 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 } else 1018 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 1028 bool 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 1047 bool 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 address 1075 // in the base+immediate addressing mode load/store instructions, see if 1076 // 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) = Rs 1080 // This can be replaced with memw(Rt+#12) = Rs 1081 // 1082 // This transformation is only performed if all uses can be updated and 1083 // 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 optimization 1094 // 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 used 1124 // 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 1140 bool HexagonOptAddrMode::runOnMachineFunction(MachineFunction &MF) { 1141 if (skipFunction(MF.getFunction())) 1142 return false; 1143 1144 // Perform RDF optimizations only if number of basic blocks in the 1145 // function is less than the limit 1146 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 into 1163 // 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 Functions 1195 //===----------------------------------------------------------------------===// 1196 1197 FunctionPass *llvm::createHexagonOptAddrMode() { 1198 return new HexagonOptAddrMode(); 1199 } 1200