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 "HexagonInstrInfo.h" 13 #include "HexagonSubtarget.h" 14 #include "MCTargetDesc/HexagonBaseInfo.h" 15 #include "llvm/ADT/DenseMap.h" 16 #include "llvm/ADT/DenseSet.h" 17 #include "llvm/ADT/StringRef.h" 18 #include "llvm/CodeGen/MachineBasicBlock.h" 19 #include "llvm/CodeGen/MachineDominanceFrontier.h" 20 #include "llvm/CodeGen/MachineDominators.h" 21 #include "llvm/CodeGen/MachineFunction.h" 22 #include "llvm/CodeGen/MachineFunctionPass.h" 23 #include "llvm/CodeGen/MachineInstr.h" 24 #include "llvm/CodeGen/MachineInstrBuilder.h" 25 #include "llvm/CodeGen/MachineOperand.h" 26 #include "llvm/CodeGen/MachineRegisterInfo.h" 27 #include "llvm/CodeGen/RDFGraph.h" 28 #include "llvm/CodeGen/RDFLiveness.h" 29 #include "llvm/CodeGen/RDFRegisters.h" 30 #include "llvm/CodeGen/TargetSubtargetInfo.h" 31 #include "llvm/InitializePasses.h" 32 #include "llvm/MC/MCInstrDesc.h" 33 #include "llvm/Pass.h" 34 #include "llvm/Support/CommandLine.h" 35 #include "llvm/Support/Debug.h" 36 #include "llvm/Support/ErrorHandling.h" 37 #include "llvm/Support/raw_ostream.h" 38 #include <cassert> 39 #include <cstdint> 40 41 #define DEBUG_TYPE "opt-addr-mode" 42 43 using namespace llvm; 44 using namespace rdf; 45 46 static cl::opt<int> CodeGrowthLimit("hexagon-amode-growth-limit", 47 cl::Hidden, cl::init(0), cl::desc("Code growth limit for address mode " 48 "optimization")); 49 50 namespace llvm { 51 52 FunctionPass *createHexagonOptAddrMode(); 53 void initializeHexagonOptAddrModePass(PassRegistry&); 54 55 } // end namespace llvm 56 57 namespace { 58 59 class HexagonOptAddrMode : public MachineFunctionPass { 60 public: 61 static char ID; 62 63 HexagonOptAddrMode() : MachineFunctionPass(ID) {} 64 65 StringRef getPassName() const override { 66 return "Optimize addressing mode of load/store"; 67 } 68 69 void getAnalysisUsage(AnalysisUsage &AU) const override { 70 MachineFunctionPass::getAnalysisUsage(AU); 71 AU.addRequired<MachineDominatorTree>(); 72 AU.addRequired<MachineDominanceFrontier>(); 73 AU.setPreservesAll(); 74 } 75 76 bool runOnMachineFunction(MachineFunction &MF) override; 77 78 private: 79 using MISetType = DenseSet<MachineInstr *>; 80 using InstrEvalMap = DenseMap<MachineInstr *, bool>; 81 82 MachineRegisterInfo *MRI = nullptr; 83 const HexagonInstrInfo *HII = nullptr; 84 const HexagonRegisterInfo *HRI = nullptr; 85 MachineDominatorTree *MDT = nullptr; 86 DataFlowGraph *DFG = nullptr; 87 DataFlowGraph::DefStackMap DefM; 88 Liveness *LV = nullptr; 89 MISetType Deleted; 90 91 bool processBlock(NodeAddr<BlockNode *> BA); 92 bool xformUseMI(MachineInstr *TfrMI, MachineInstr *UseMI, 93 NodeAddr<UseNode *> UseN, unsigned UseMOnum); 94 bool processAddUses(NodeAddr<StmtNode *> AddSN, MachineInstr *AddMI, 95 const NodeList &UNodeList); 96 bool updateAddUses(MachineInstr *AddMI, MachineInstr *UseMI); 97 bool analyzeUses(unsigned DefR, const NodeList &UNodeList, 98 InstrEvalMap &InstrEvalResult, short &SizeInc); 99 bool hasRepForm(MachineInstr &MI, unsigned TfrDefR); 100 bool canRemoveAddasl(NodeAddr<StmtNode *> AddAslSN, MachineInstr &MI, 101 const NodeList &UNodeList); 102 bool isSafeToExtLR(NodeAddr<StmtNode *> SN, MachineInstr *MI, 103 unsigned LRExtReg, const NodeList &UNodeList); 104 void getAllRealUses(NodeAddr<StmtNode *> SN, NodeList &UNodeList); 105 bool allValidCandidates(NodeAddr<StmtNode *> SA, NodeList &UNodeList); 106 short getBaseWithLongOffset(const MachineInstr &MI) const; 107 bool changeStore(MachineInstr *OldMI, MachineOperand ImmOp, 108 unsigned ImmOpNum); 109 bool changeLoad(MachineInstr *OldMI, MachineOperand ImmOp, unsigned ImmOpNum); 110 bool changeAddAsl(NodeAddr<UseNode *> AddAslUN, MachineInstr *AddAslMI, 111 const MachineOperand &ImmOp, unsigned ImmOpNum); 112 bool isValidOffset(MachineInstr *MI, int Offset); 113 unsigned getBaseOpPosition(MachineInstr *MI); 114 unsigned getOffsetOpPosition(MachineInstr *MI); 115 }; 116 117 } // end anonymous namespace 118 119 char HexagonOptAddrMode::ID = 0; 120 121 INITIALIZE_PASS_BEGIN(HexagonOptAddrMode, "amode-opt", 122 "Optimize addressing mode", false, false) 123 INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree) 124 INITIALIZE_PASS_DEPENDENCY(MachineDominanceFrontier) 125 INITIALIZE_PASS_END(HexagonOptAddrMode, "amode-opt", "Optimize addressing mode", 126 false, false) 127 128 bool HexagonOptAddrMode::hasRepForm(MachineInstr &MI, unsigned TfrDefR) { 129 const MCInstrDesc &MID = MI.getDesc(); 130 131 if ((!MID.mayStore() && !MID.mayLoad()) || HII->isPredicated(MI)) 132 return false; 133 134 if (MID.mayStore()) { 135 MachineOperand StOp = MI.getOperand(MI.getNumOperands() - 1); 136 if (StOp.isReg() && StOp.getReg() == TfrDefR) 137 return false; 138 } 139 140 if (HII->getAddrMode(MI) == HexagonII::BaseRegOffset) 141 // Tranform to Absolute plus register offset. 142 return (HII->changeAddrMode_rr_ur(MI) >= 0); 143 else if (HII->getAddrMode(MI) == HexagonII::BaseImmOffset) 144 // Tranform to absolute addressing mode. 145 return (HII->changeAddrMode_io_abs(MI) >= 0); 146 147 return false; 148 } 149 150 // Check if addasl instruction can be removed. This is possible only 151 // if it's feeding to only load/store instructions with base + register 152 // offset as these instruction can be tranformed to use 'absolute plus 153 // shifted register offset'. 154 // ex: 155 // Rs = ##foo 156 // Rx = addasl(Rs, Rt, #2) 157 // Rd = memw(Rx + #28) 158 // Above three instructions can be replaced with Rd = memw(Rt<<#2 + ##foo+28) 159 160 bool HexagonOptAddrMode::canRemoveAddasl(NodeAddr<StmtNode *> AddAslSN, 161 MachineInstr &MI, 162 const NodeList &UNodeList) { 163 // check offset size in addasl. if 'offset > 3' return false 164 const MachineOperand &OffsetOp = MI.getOperand(3); 165 if (!OffsetOp.isImm() || OffsetOp.getImm() > 3) 166 return false; 167 168 Register OffsetReg = MI.getOperand(2).getReg(); 169 RegisterRef OffsetRR; 170 NodeId OffsetRegRD = 0; 171 for (NodeAddr<UseNode *> UA : AddAslSN.Addr->members_if(DFG->IsUse, *DFG)) { 172 RegisterRef RR = UA.Addr->getRegRef(*DFG); 173 if (OffsetReg == RR.Reg) { 174 OffsetRR = RR; 175 OffsetRegRD = UA.Addr->getReachingDef(); 176 } 177 } 178 179 for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) { 180 NodeAddr<UseNode *> UA = *I; 181 NodeAddr<InstrNode *> IA = UA.Addr->getOwner(*DFG); 182 if (UA.Addr->getFlags() & NodeAttrs::PhiRef) 183 return false; 184 NodeAddr<RefNode*> AA = LV->getNearestAliasedRef(OffsetRR, IA); 185 if ((DFG->IsDef(AA) && AA.Id != OffsetRegRD) || 186 AA.Addr->getReachingDef() != OffsetRegRD) 187 return false; 188 189 MachineInstr &UseMI = *NodeAddr<StmtNode *>(IA).Addr->getCode(); 190 NodeAddr<DefNode *> OffsetRegDN = DFG->addr<DefNode *>(OffsetRegRD); 191 // Reaching Def to an offset register can't be a phi. 192 if ((OffsetRegDN.Addr->getFlags() & NodeAttrs::PhiRef) && 193 MI.getParent() != UseMI.getParent()) 194 return false; 195 196 const MCInstrDesc &UseMID = UseMI.getDesc(); 197 if ((!UseMID.mayLoad() && !UseMID.mayStore()) || 198 HII->getAddrMode(UseMI) != HexagonII::BaseImmOffset || 199 getBaseWithLongOffset(UseMI) < 0) 200 return false; 201 202 // Addasl output can't be a store value. 203 if (UseMID.mayStore() && UseMI.getOperand(2).isReg() && 204 UseMI.getOperand(2).getReg() == MI.getOperand(0).getReg()) 205 return false; 206 207 for (auto &Mo : UseMI.operands()) 208 if (Mo.isFI()) 209 return false; 210 } 211 return true; 212 } 213 214 bool HexagonOptAddrMode::allValidCandidates(NodeAddr<StmtNode *> SA, 215 NodeList &UNodeList) { 216 for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) { 217 NodeAddr<UseNode *> UN = *I; 218 RegisterRef UR = UN.Addr->getRegRef(*DFG); 219 NodeSet Visited, Defs; 220 const auto &P = LV->getAllReachingDefsRec(UR, UN, Visited, Defs); 221 if (!P.second) { 222 LLVM_DEBUG({ 223 dbgs() << "*** Unable to collect all reaching defs for use ***\n" 224 << PrintNode<UseNode*>(UN, *DFG) << '\n' 225 << "The program's complexity may exceed the limits.\n"; 226 }); 227 return false; 228 } 229 const auto &ReachingDefs = P.first; 230 if (ReachingDefs.size() > 1) { 231 LLVM_DEBUG({ 232 dbgs() << "*** Multiple Reaching Defs found!!! ***\n"; 233 for (auto DI : ReachingDefs) { 234 NodeAddr<UseNode *> DA = DFG->addr<UseNode *>(DI); 235 NodeAddr<StmtNode *> TempIA = DA.Addr->getOwner(*DFG); 236 dbgs() << "\t\t[Reaching Def]: " 237 << Print<NodeAddr<InstrNode *>>(TempIA, *DFG) << "\n"; 238 } 239 }); 240 return false; 241 } 242 } 243 return true; 244 } 245 246 void HexagonOptAddrMode::getAllRealUses(NodeAddr<StmtNode *> SA, 247 NodeList &UNodeList) { 248 for (NodeAddr<DefNode *> DA : SA.Addr->members_if(DFG->IsDef, *DFG)) { 249 LLVM_DEBUG(dbgs() << "\t\t[DefNode]: " 250 << Print<NodeAddr<DefNode *>>(DA, *DFG) << "\n"); 251 RegisterRef DR = DA.Addr->getRegRef(*DFG); 252 253 auto UseSet = LV->getAllReachedUses(DR, DA); 254 255 for (auto UI : UseSet) { 256 NodeAddr<UseNode *> UA = DFG->addr<UseNode *>(UI); 257 LLVM_DEBUG({ 258 NodeAddr<StmtNode *> TempIA = UA.Addr->getOwner(*DFG); 259 dbgs() << "\t\t\t[Reached Use]: " 260 << Print<NodeAddr<InstrNode *>>(TempIA, *DFG) << "\n"; 261 }); 262 263 if (UA.Addr->getFlags() & NodeAttrs::PhiRef) { 264 NodeAddr<PhiNode *> PA = UA.Addr->getOwner(*DFG); 265 NodeId id = PA.Id; 266 const Liveness::RefMap &phiUse = LV->getRealUses(id); 267 LLVM_DEBUG(dbgs() << "\t\t\t\tphi real Uses" 268 << Print<Liveness::RefMap>(phiUse, *DFG) << "\n"); 269 if (!phiUse.empty()) { 270 for (auto I : phiUse) { 271 if (!DFG->getPRI().alias(RegisterRef(I.first), DR)) 272 continue; 273 auto phiUseSet = I.second; 274 for (auto phiUI : phiUseSet) { 275 NodeAddr<UseNode *> phiUA = DFG->addr<UseNode *>(phiUI.first); 276 UNodeList.push_back(phiUA); 277 } 278 } 279 } 280 } else 281 UNodeList.push_back(UA); 282 } 283 } 284 } 285 286 bool HexagonOptAddrMode::isSafeToExtLR(NodeAddr<StmtNode *> SN, 287 MachineInstr *MI, unsigned LRExtReg, 288 const NodeList &UNodeList) { 289 RegisterRef LRExtRR; 290 NodeId LRExtRegRD = 0; 291 // Iterate through all the UseNodes in SN and find the reaching def 292 // for the LRExtReg. 293 for (NodeAddr<UseNode *> UA : SN.Addr->members_if(DFG->IsUse, *DFG)) { 294 RegisterRef RR = UA.Addr->getRegRef(*DFG); 295 if (LRExtReg == RR.Reg) { 296 LRExtRR = RR; 297 LRExtRegRD = UA.Addr->getReachingDef(); 298 } 299 } 300 301 for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) { 302 NodeAddr<UseNode *> UA = *I; 303 NodeAddr<InstrNode *> IA = UA.Addr->getOwner(*DFG); 304 // The reaching def of LRExtRR at load/store node should be same as the 305 // one reaching at the SN. 306 if (UA.Addr->getFlags() & NodeAttrs::PhiRef) 307 return false; 308 NodeAddr<RefNode*> AA = LV->getNearestAliasedRef(LRExtRR, IA); 309 if ((DFG->IsDef(AA) && AA.Id != LRExtRegRD) || 310 AA.Addr->getReachingDef() != LRExtRegRD) { 311 LLVM_DEBUG( 312 dbgs() << "isSafeToExtLR: Returning false; another reaching def\n"); 313 return false; 314 } 315 316 MachineInstr *UseMI = NodeAddr<StmtNode *>(IA).Addr->getCode(); 317 NodeAddr<DefNode *> LRExtRegDN = DFG->addr<DefNode *>(LRExtRegRD); 318 // Reaching Def to LRExtReg can't be a phi. 319 if ((LRExtRegDN.Addr->getFlags() & NodeAttrs::PhiRef) && 320 MI->getParent() != UseMI->getParent()) 321 return false; 322 } 323 return true; 324 } 325 326 bool HexagonOptAddrMode::isValidOffset(MachineInstr *MI, int Offset) { 327 if (HII->isHVXVec(*MI)) { 328 // only HVX vgather instructions handled 329 // TODO: extend the pass to other vector load/store operations 330 switch (MI->getOpcode()) { 331 case Hexagon::V6_vgathermh_pseudo: 332 case Hexagon::V6_vgathermw_pseudo: 333 case Hexagon::V6_vgathermhw_pseudo: 334 case Hexagon::V6_vgathermhq_pseudo: 335 case Hexagon::V6_vgathermwq_pseudo: 336 case Hexagon::V6_vgathermhwq_pseudo: 337 return HII->isValidOffset(MI->getOpcode(), Offset, HRI, false); 338 default: 339 return false; 340 } 341 } 342 343 if (HII->getAddrMode(*MI) != HexagonII::BaseImmOffset) 344 return false; 345 346 unsigned AlignMask = 0; 347 switch (HII->getMemAccessSize(*MI)) { 348 case HexagonII::MemAccessSize::DoubleWordAccess: 349 AlignMask = 0x7; 350 break; 351 case HexagonII::MemAccessSize::WordAccess: 352 AlignMask = 0x3; 353 break; 354 case HexagonII::MemAccessSize::HalfWordAccess: 355 AlignMask = 0x1; 356 break; 357 case HexagonII::MemAccessSize::ByteAccess: 358 AlignMask = 0x0; 359 break; 360 default: 361 return false; 362 } 363 364 if ((AlignMask & Offset) != 0) 365 return false; 366 return HII->isValidOffset(MI->getOpcode(), Offset, HRI, false); 367 } 368 369 unsigned HexagonOptAddrMode::getBaseOpPosition(MachineInstr *MI) { 370 const MCInstrDesc &MID = MI->getDesc(); 371 switch (MI->getOpcode()) { 372 // vgather pseudos are mayLoad and mayStore 373 // hence need to explicitly specify Base and 374 // Offset operand positions 375 case Hexagon::V6_vgathermh_pseudo: 376 case Hexagon::V6_vgathermw_pseudo: 377 case Hexagon::V6_vgathermhw_pseudo: 378 case Hexagon::V6_vgathermhq_pseudo: 379 case Hexagon::V6_vgathermwq_pseudo: 380 case Hexagon::V6_vgathermhwq_pseudo: 381 return 0; 382 default: 383 return MID.mayLoad() ? 1 : 0; 384 } 385 } 386 387 unsigned HexagonOptAddrMode::getOffsetOpPosition(MachineInstr *MI) { 388 assert( 389 (HII->getAddrMode(*MI) == HexagonII::BaseImmOffset) && 390 "Looking for an offset in non-BaseImmOffset addressing mode instruction"); 391 392 const MCInstrDesc &MID = MI->getDesc(); 393 switch (MI->getOpcode()) { 394 // vgather pseudos are mayLoad and mayStore 395 // hence need to explicitly specify Base and 396 // Offset operand positions 397 case Hexagon::V6_vgathermh_pseudo: 398 case Hexagon::V6_vgathermw_pseudo: 399 case Hexagon::V6_vgathermhw_pseudo: 400 case Hexagon::V6_vgathermhq_pseudo: 401 case Hexagon::V6_vgathermwq_pseudo: 402 case Hexagon::V6_vgathermhwq_pseudo: 403 return 1; 404 default: 405 return MID.mayLoad() ? 2 : 1; 406 } 407 } 408 409 bool HexagonOptAddrMode::processAddUses(NodeAddr<StmtNode *> AddSN, 410 MachineInstr *AddMI, 411 const NodeList &UNodeList) { 412 413 Register AddDefR = AddMI->getOperand(0).getReg(); 414 Register BaseReg = AddMI->getOperand(1).getReg(); 415 for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) { 416 NodeAddr<UseNode *> UN = *I; 417 NodeAddr<StmtNode *> SN = UN.Addr->getOwner(*DFG); 418 MachineInstr *MI = SN.Addr->getCode(); 419 const MCInstrDesc &MID = MI->getDesc(); 420 if ((!MID.mayLoad() && !MID.mayStore()) || 421 HII->getAddrMode(*MI) != HexagonII::BaseImmOffset) 422 return false; 423 424 MachineOperand BaseOp = MI->getOperand(getBaseOpPosition(MI)); 425 426 if (!BaseOp.isReg() || BaseOp.getReg() != AddDefR) 427 return false; 428 429 MachineOperand OffsetOp = MI->getOperand(getOffsetOpPosition(MI)); 430 if (!OffsetOp.isImm()) 431 return false; 432 433 int64_t newOffset = OffsetOp.getImm() + AddMI->getOperand(2).getImm(); 434 if (!isValidOffset(MI, newOffset)) 435 return false; 436 437 // Since we'll be extending the live range of Rt in the following example, 438 // make sure that is safe. another definition of Rt doesn't exist between 'add' 439 // and load/store instruction. 440 // 441 // Ex: Rx= add(Rt,#10) 442 // memw(Rx+#0) = Rs 443 // will be replaced with => memw(Rt+#10) = Rs 444 if (!isSafeToExtLR(AddSN, AddMI, BaseReg, UNodeList)) 445 return false; 446 } 447 448 NodeId LRExtRegRD = 0; 449 // Iterate through all the UseNodes in SN and find the reaching def 450 // for the LRExtReg. 451 for (NodeAddr<UseNode *> UA : AddSN.Addr->members_if(DFG->IsUse, *DFG)) { 452 RegisterRef RR = UA.Addr->getRegRef(*DFG); 453 if (BaseReg == RR.Reg) 454 LRExtRegRD = UA.Addr->getReachingDef(); 455 } 456 457 // Update all the uses of 'add' with the appropriate base and offset 458 // values. 459 bool Changed = false; 460 for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) { 461 NodeAddr<UseNode *> UseN = *I; 462 assert(!(UseN.Addr->getFlags() & NodeAttrs::PhiRef) && 463 "Found a PhiRef node as a real reached use!!"); 464 465 NodeAddr<StmtNode *> OwnerN = UseN.Addr->getOwner(*DFG); 466 MachineInstr *UseMI = OwnerN.Addr->getCode(); 467 LLVM_DEBUG(dbgs() << "\t\t[MI <BB#" << UseMI->getParent()->getNumber() 468 << ">]: " << *UseMI << "\n"); 469 Changed |= updateAddUses(AddMI, UseMI); 470 471 // Set the reachingDef for UseNode under consideration 472 // after updating the Add use. This local change is 473 // to avoid rebuilding of the RDF graph after update. 474 NodeAddr<DefNode *> LRExtRegDN = DFG->addr<DefNode *>(LRExtRegRD); 475 UseN.Addr->linkToDef(UseN.Id, LRExtRegDN); 476 } 477 478 if (Changed) 479 Deleted.insert(AddMI); 480 481 return Changed; 482 } 483 484 bool HexagonOptAddrMode::updateAddUses(MachineInstr *AddMI, 485 MachineInstr *UseMI) { 486 const MachineOperand ImmOp = AddMI->getOperand(2); 487 const MachineOperand AddRegOp = AddMI->getOperand(1); 488 Register NewReg = AddRegOp.getReg(); 489 490 MachineOperand &BaseOp = UseMI->getOperand(getBaseOpPosition(UseMI)); 491 MachineOperand &OffsetOp = UseMI->getOperand(getOffsetOpPosition(UseMI)); 492 BaseOp.setReg(NewReg); 493 BaseOp.setIsUndef(AddRegOp.isUndef()); 494 BaseOp.setImplicit(AddRegOp.isImplicit()); 495 OffsetOp.setImm(ImmOp.getImm() + OffsetOp.getImm()); 496 MRI->clearKillFlags(NewReg); 497 498 return true; 499 } 500 501 bool HexagonOptAddrMode::analyzeUses(unsigned tfrDefR, 502 const NodeList &UNodeList, 503 InstrEvalMap &InstrEvalResult, 504 short &SizeInc) { 505 bool KeepTfr = false; 506 bool HasRepInstr = false; 507 InstrEvalResult.clear(); 508 509 for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) { 510 bool CanBeReplaced = false; 511 NodeAddr<UseNode *> UN = *I; 512 NodeAddr<StmtNode *> SN = UN.Addr->getOwner(*DFG); 513 MachineInstr &MI = *SN.Addr->getCode(); 514 const MCInstrDesc &MID = MI.getDesc(); 515 if ((MID.mayLoad() || MID.mayStore())) { 516 if (!hasRepForm(MI, tfrDefR)) { 517 KeepTfr = true; 518 continue; 519 } 520 SizeInc++; 521 CanBeReplaced = true; 522 } else if (MI.getOpcode() == Hexagon::S2_addasl_rrri) { 523 NodeList AddaslUseList; 524 525 LLVM_DEBUG(dbgs() << "\nGetting ReachedUses for === " << MI << "\n"); 526 getAllRealUses(SN, AddaslUseList); 527 // Process phi nodes. 528 if (allValidCandidates(SN, AddaslUseList) && 529 canRemoveAddasl(SN, MI, AddaslUseList)) { 530 SizeInc += AddaslUseList.size(); 531 SizeInc -= 1; // Reduce size by 1 as addasl itself can be removed. 532 CanBeReplaced = true; 533 } else 534 SizeInc++; 535 } else 536 // Currently, only load/store and addasl are handled. 537 // Some other instructions to consider - 538 // A2_add -> A2_addi 539 // M4_mpyrr_addr -> M4_mpyrr_addi 540 KeepTfr = true; 541 542 InstrEvalResult[&MI] = CanBeReplaced; 543 HasRepInstr |= CanBeReplaced; 544 } 545 546 // Reduce total size by 2 if original tfr can be deleted. 547 if (!KeepTfr) 548 SizeInc -= 2; 549 550 return HasRepInstr; 551 } 552 553 bool HexagonOptAddrMode::changeLoad(MachineInstr *OldMI, MachineOperand ImmOp, 554 unsigned ImmOpNum) { 555 bool Changed = false; 556 MachineBasicBlock *BB = OldMI->getParent(); 557 auto UsePos = MachineBasicBlock::iterator(OldMI); 558 MachineBasicBlock::instr_iterator InsertPt = UsePos.getInstrIterator(); 559 ++InsertPt; 560 unsigned OpStart; 561 unsigned OpEnd = OldMI->getNumOperands(); 562 MachineInstrBuilder MIB; 563 564 if (ImmOpNum == 1) { 565 if (HII->getAddrMode(*OldMI) == HexagonII::BaseRegOffset) { 566 short NewOpCode = HII->changeAddrMode_rr_ur(*OldMI); 567 assert(NewOpCode >= 0 && "Invalid New opcode\n"); 568 MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode)); 569 MIB.add(OldMI->getOperand(0)); 570 MIB.add(OldMI->getOperand(2)); 571 MIB.add(OldMI->getOperand(3)); 572 MIB.add(ImmOp); 573 OpStart = 4; 574 Changed = true; 575 } else if (HII->getAddrMode(*OldMI) == HexagonII::BaseImmOffset && 576 OldMI->getOperand(2).isImm()) { 577 short NewOpCode = HII->changeAddrMode_io_abs(*OldMI); 578 assert(NewOpCode >= 0 && "Invalid New opcode\n"); 579 MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode)) 580 .add(OldMI->getOperand(0)); 581 const GlobalValue *GV = ImmOp.getGlobal(); 582 int64_t Offset = ImmOp.getOffset() + OldMI->getOperand(2).getImm(); 583 584 MIB.addGlobalAddress(GV, Offset, ImmOp.getTargetFlags()); 585 OpStart = 3; 586 Changed = true; 587 } else 588 Changed = false; 589 590 LLVM_DEBUG(dbgs() << "[Changing]: " << *OldMI << "\n"); 591 LLVM_DEBUG(dbgs() << "[TO]: " << *MIB << "\n"); 592 } else if (ImmOpNum == 2) { 593 if (OldMI->getOperand(3).isImm() && OldMI->getOperand(3).getImm() == 0) { 594 short NewOpCode = HII->changeAddrMode_rr_io(*OldMI); 595 assert(NewOpCode >= 0 && "Invalid New opcode\n"); 596 MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode)); 597 MIB.add(OldMI->getOperand(0)); 598 MIB.add(OldMI->getOperand(1)); 599 MIB.add(ImmOp); 600 OpStart = 4; 601 Changed = true; 602 LLVM_DEBUG(dbgs() << "[Changing]: " << *OldMI << "\n"); 603 LLVM_DEBUG(dbgs() << "[TO]: " << *MIB << "\n"); 604 } 605 } 606 607 if (Changed) 608 for (unsigned i = OpStart; i < OpEnd; ++i) 609 MIB.add(OldMI->getOperand(i)); 610 611 return Changed; 612 } 613 614 bool HexagonOptAddrMode::changeStore(MachineInstr *OldMI, MachineOperand ImmOp, 615 unsigned ImmOpNum) { 616 bool Changed = false; 617 unsigned OpStart = 0; 618 unsigned OpEnd = OldMI->getNumOperands(); 619 MachineBasicBlock *BB = OldMI->getParent(); 620 auto UsePos = MachineBasicBlock::iterator(OldMI); 621 MachineBasicBlock::instr_iterator InsertPt = UsePos.getInstrIterator(); 622 ++InsertPt; 623 MachineInstrBuilder MIB; 624 if (ImmOpNum == 0) { 625 if (HII->getAddrMode(*OldMI) == HexagonII::BaseRegOffset) { 626 short NewOpCode = HII->changeAddrMode_rr_ur(*OldMI); 627 assert(NewOpCode >= 0 && "Invalid New opcode\n"); 628 MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode)); 629 MIB.add(OldMI->getOperand(1)); 630 MIB.add(OldMI->getOperand(2)); 631 MIB.add(ImmOp); 632 MIB.add(OldMI->getOperand(3)); 633 OpStart = 4; 634 Changed = true; 635 } else if (HII->getAddrMode(*OldMI) == HexagonII::BaseImmOffset) { 636 short NewOpCode = HII->changeAddrMode_io_abs(*OldMI); 637 assert(NewOpCode >= 0 && "Invalid New opcode\n"); 638 MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode)); 639 const GlobalValue *GV = ImmOp.getGlobal(); 640 int64_t Offset = ImmOp.getOffset() + OldMI->getOperand(1).getImm(); 641 MIB.addGlobalAddress(GV, Offset, ImmOp.getTargetFlags()); 642 MIB.add(OldMI->getOperand(2)); 643 OpStart = 3; 644 Changed = true; 645 } 646 } else if (ImmOpNum == 1 && OldMI->getOperand(2).getImm() == 0) { 647 short NewOpCode = HII->changeAddrMode_rr_io(*OldMI); 648 assert(NewOpCode >= 0 && "Invalid New opcode\n"); 649 MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode)); 650 MIB.add(OldMI->getOperand(0)); 651 MIB.add(ImmOp); 652 OpStart = 3; 653 Changed = true; 654 } 655 if (Changed) { 656 LLVM_DEBUG(dbgs() << "[Changing]: " << *OldMI << "\n"); 657 LLVM_DEBUG(dbgs() << "[TO]: " << *MIB << "\n"); 658 659 for (unsigned i = OpStart; i < OpEnd; ++i) 660 MIB.add(OldMI->getOperand(i)); 661 } 662 663 return Changed; 664 } 665 666 short HexagonOptAddrMode::getBaseWithLongOffset(const MachineInstr &MI) const { 667 if (HII->getAddrMode(MI) == HexagonII::BaseImmOffset) { 668 short TempOpCode = HII->changeAddrMode_io_rr(MI); 669 return HII->changeAddrMode_rr_ur(TempOpCode); 670 } 671 return HII->changeAddrMode_rr_ur(MI); 672 } 673 674 bool HexagonOptAddrMode::changeAddAsl(NodeAddr<UseNode *> AddAslUN, 675 MachineInstr *AddAslMI, 676 const MachineOperand &ImmOp, 677 unsigned ImmOpNum) { 678 NodeAddr<StmtNode *> SA = AddAslUN.Addr->getOwner(*DFG); 679 680 LLVM_DEBUG(dbgs() << "Processing addasl :" << *AddAslMI << "\n"); 681 682 NodeList UNodeList; 683 getAllRealUses(SA, UNodeList); 684 685 for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) { 686 NodeAddr<UseNode *> UseUN = *I; 687 assert(!(UseUN.Addr->getFlags() & NodeAttrs::PhiRef) && 688 "Can't transform this 'AddAsl' instruction!"); 689 690 NodeAddr<StmtNode *> UseIA = UseUN.Addr->getOwner(*DFG); 691 LLVM_DEBUG(dbgs() << "[InstrNode]: " 692 << Print<NodeAddr<InstrNode *>>(UseIA, *DFG) << "\n"); 693 MachineInstr *UseMI = UseIA.Addr->getCode(); 694 LLVM_DEBUG(dbgs() << "[MI <" << printMBBReference(*UseMI->getParent()) 695 << ">]: " << *UseMI << "\n"); 696 const MCInstrDesc &UseMID = UseMI->getDesc(); 697 assert(HII->getAddrMode(*UseMI) == HexagonII::BaseImmOffset); 698 699 auto UsePos = MachineBasicBlock::iterator(UseMI); 700 MachineBasicBlock::instr_iterator InsertPt = UsePos.getInstrIterator(); 701 short NewOpCode = getBaseWithLongOffset(*UseMI); 702 assert(NewOpCode >= 0 && "Invalid New opcode\n"); 703 704 unsigned OpStart; 705 unsigned OpEnd = UseMI->getNumOperands(); 706 707 MachineBasicBlock *BB = UseMI->getParent(); 708 MachineInstrBuilder MIB = 709 BuildMI(*BB, InsertPt, UseMI->getDebugLoc(), HII->get(NewOpCode)); 710 // change mem(Rs + # ) -> mem(Rt << # + ##) 711 if (UseMID.mayLoad()) { 712 MIB.add(UseMI->getOperand(0)); 713 MIB.add(AddAslMI->getOperand(2)); 714 MIB.add(AddAslMI->getOperand(3)); 715 const GlobalValue *GV = ImmOp.getGlobal(); 716 MIB.addGlobalAddress(GV, UseMI->getOperand(2).getImm()+ImmOp.getOffset(), 717 ImmOp.getTargetFlags()); 718 OpStart = 3; 719 } else if (UseMID.mayStore()) { 720 MIB.add(AddAslMI->getOperand(2)); 721 MIB.add(AddAslMI->getOperand(3)); 722 const GlobalValue *GV = ImmOp.getGlobal(); 723 MIB.addGlobalAddress(GV, UseMI->getOperand(1).getImm()+ImmOp.getOffset(), 724 ImmOp.getTargetFlags()); 725 MIB.add(UseMI->getOperand(2)); 726 OpStart = 3; 727 } else 728 llvm_unreachable("Unhandled instruction"); 729 730 for (unsigned i = OpStart; i < OpEnd; ++i) 731 MIB.add(UseMI->getOperand(i)); 732 733 Deleted.insert(UseMI); 734 } 735 736 return true; 737 } 738 739 bool HexagonOptAddrMode::xformUseMI(MachineInstr *TfrMI, MachineInstr *UseMI, 740 NodeAddr<UseNode *> UseN, 741 unsigned UseMOnum) { 742 const MachineOperand ImmOp = TfrMI->getOperand(1); 743 const MCInstrDesc &MID = UseMI->getDesc(); 744 unsigned Changed = false; 745 if (MID.mayLoad()) 746 Changed = changeLoad(UseMI, ImmOp, UseMOnum); 747 else if (MID.mayStore()) 748 Changed = changeStore(UseMI, ImmOp, UseMOnum); 749 else if (UseMI->getOpcode() == Hexagon::S2_addasl_rrri) 750 Changed = changeAddAsl(UseN, UseMI, ImmOp, UseMOnum); 751 752 if (Changed) 753 Deleted.insert(UseMI); 754 755 return Changed; 756 } 757 758 bool HexagonOptAddrMode::processBlock(NodeAddr<BlockNode *> BA) { 759 bool Changed = false; 760 761 for (auto IA : BA.Addr->members(*DFG)) { 762 if (!DFG->IsCode<NodeAttrs::Stmt>(IA)) 763 continue; 764 765 NodeAddr<StmtNode *> SA = IA; 766 MachineInstr *MI = SA.Addr->getCode(); 767 if ((MI->getOpcode() != Hexagon::A2_tfrsi || 768 !MI->getOperand(1).isGlobal()) && 769 (MI->getOpcode() != Hexagon::A2_addi || 770 !MI->getOperand(2).isImm() || HII->isConstExtended(*MI))) 771 continue; 772 773 LLVM_DEBUG(dbgs() << "[Analyzing " << HII->getName(MI->getOpcode()) 774 << "]: " << *MI << "\n\t[InstrNode]: " 775 << Print<NodeAddr<InstrNode *>>(IA, *DFG) << '\n'); 776 777 NodeList UNodeList; 778 getAllRealUses(SA, UNodeList); 779 780 if (!allValidCandidates(SA, UNodeList)) 781 continue; 782 783 // Analyze all uses of 'add'. If the output of 'add' is used as an address 784 // in the base+immediate addressing mode load/store instructions, see if 785 // they can be updated to use the immediate value as an offet. Thus, 786 // providing us the opportunity to eliminate 'add'. 787 // Ex: Rx= add(Rt,#12) 788 // memw(Rx+#0) = Rs 789 // This can be replaced with memw(Rt+#12) = Rs 790 // 791 // This transformation is only performed if all uses can be updated and 792 // the offset isn't required to be constant extended. 793 if (MI->getOpcode() == Hexagon::A2_addi) { 794 Changed |= processAddUses(SA, MI, UNodeList); 795 continue; 796 } 797 798 short SizeInc = 0; 799 Register DefR = MI->getOperand(0).getReg(); 800 InstrEvalMap InstrEvalResult; 801 802 // Analyze all uses and calculate increase in size. Perform the optimization 803 // only if there is no increase in size. 804 if (!analyzeUses(DefR, UNodeList, InstrEvalResult, SizeInc)) 805 continue; 806 if (SizeInc > CodeGrowthLimit) 807 continue; 808 809 bool KeepTfr = false; 810 811 LLVM_DEBUG(dbgs() << "\t[Total reached uses] : " << UNodeList.size() 812 << "\n"); 813 LLVM_DEBUG(dbgs() << "\t[Processing Reached Uses] ===\n"); 814 for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) { 815 NodeAddr<UseNode *> UseN = *I; 816 assert(!(UseN.Addr->getFlags() & NodeAttrs::PhiRef) && 817 "Found a PhiRef node as a real reached use!!"); 818 819 NodeAddr<StmtNode *> OwnerN = UseN.Addr->getOwner(*DFG); 820 MachineInstr *UseMI = OwnerN.Addr->getCode(); 821 LLVM_DEBUG(dbgs() << "\t\t[MI <" << printMBBReference(*UseMI->getParent()) 822 << ">]: " << *UseMI << "\n"); 823 824 int UseMOnum = -1; 825 unsigned NumOperands = UseMI->getNumOperands(); 826 for (unsigned j = 0; j < NumOperands - 1; ++j) { 827 const MachineOperand &op = UseMI->getOperand(j); 828 if (op.isReg() && op.isUse() && DefR == op.getReg()) 829 UseMOnum = j; 830 } 831 // It is possible that the register will not be found in any operand. 832 // This could happen, for example, when DefR = R4, but the used 833 // register is D2. 834 835 // Change UseMI if replacement is possible. If any replacement failed, 836 // or wasn't attempted, make sure to keep the TFR. 837 bool Xformed = false; 838 if (UseMOnum >= 0 && InstrEvalResult[UseMI]) 839 Xformed = xformUseMI(MI, UseMI, UseN, UseMOnum); 840 Changed |= Xformed; 841 KeepTfr |= !Xformed; 842 } 843 if (!KeepTfr) 844 Deleted.insert(MI); 845 } 846 return Changed; 847 } 848 849 bool HexagonOptAddrMode::runOnMachineFunction(MachineFunction &MF) { 850 if (skipFunction(MF.getFunction())) 851 return false; 852 853 bool Changed = false; 854 auto &HST = MF.getSubtarget<HexagonSubtarget>(); 855 MRI = &MF.getRegInfo(); 856 HII = HST.getInstrInfo(); 857 HRI = HST.getRegisterInfo(); 858 const auto &MDF = getAnalysis<MachineDominanceFrontier>(); 859 MDT = &getAnalysis<MachineDominatorTree>(); 860 const TargetOperandInfo TOI(*HII); 861 862 DataFlowGraph G(MF, *HII, *HRI, *MDT, MDF, TOI); 863 // Need to keep dead phis because we can propagate uses of registers into 864 // nodes dominated by those would-be phis. 865 G.build(BuildOptions::KeepDeadPhis); 866 DFG = &G; 867 868 Liveness L(*MRI, *DFG); 869 L.computePhiInfo(); 870 LV = &L; 871 872 Deleted.clear(); 873 NodeAddr<FuncNode *> FA = DFG->getFunc(); 874 LLVM_DEBUG(dbgs() << "==== [RefMap#]=====:\n " 875 << Print<NodeAddr<FuncNode *>>(FA, *DFG) << "\n"); 876 877 for (NodeAddr<BlockNode *> BA : FA.Addr->members(*DFG)) 878 Changed |= processBlock(BA); 879 880 for (auto MI : Deleted) 881 MI->eraseFromParent(); 882 883 if (Changed) { 884 G.build(); 885 L.computeLiveIns(); 886 L.resetLiveIns(); 887 L.resetKills(); 888 } 889 890 return Changed; 891 } 892 893 //===----------------------------------------------------------------------===// 894 // Public Constructor Functions 895 //===----------------------------------------------------------------------===// 896 897 FunctionPass *llvm::createHexagonOptAddrMode() { 898 return new HexagonOptAddrMode(); 899 } 900