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