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