1cb508a00SPerry MacMurray //===--------- HexagonCopyHoisting.cpp - Hexagon Copy Hoisting ----------===// 2cb508a00SPerry MacMurray // 3cb508a00SPerry MacMurray // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4cb508a00SPerry MacMurray // See https://llvm.org/LICENSE.txt for license information. 5cb508a00SPerry MacMurray // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6cb508a00SPerry MacMurray // 7cb508a00SPerry MacMurray //===----------------------------------------------------------------------===// 8cb508a00SPerry MacMurray // The purpose of this pass is to move the copy instructions that are 9cb508a00SPerry MacMurray // present in all the successor of a basic block (BB) to the end of BB. 10cb508a00SPerry MacMurray //===----------------------------------------------------------------------===// 11cb508a00SPerry MacMurray 12cb508a00SPerry MacMurray #include "HexagonTargetMachine.h" 13cb508a00SPerry MacMurray #include "llvm/ADT/DenseMap.h" 14cb508a00SPerry MacMurray #include "llvm/ADT/PostOrderIterator.h" 15cb508a00SPerry MacMurray #include "llvm/ADT/StringRef.h" 16cb508a00SPerry MacMurray #include "llvm/ADT/Twine.h" 17cb508a00SPerry MacMurray #include "llvm/CodeGen/LiveInterval.h" 18cb508a00SPerry MacMurray #include "llvm/CodeGen/LiveIntervals.h" 19cb508a00SPerry MacMurray #include "llvm/CodeGen/MachineDominators.h" 20cb508a00SPerry MacMurray #include "llvm/CodeGen/MachineRegisterInfo.h" 21cb508a00SPerry MacMurray #include "llvm/Support/CommandLine.h" 22cb508a00SPerry MacMurray #include "llvm/Support/Debug.h" 23cb508a00SPerry MacMurray 24cb508a00SPerry MacMurray #define DEBUG_TYPE "CopyHoist" 25cb508a00SPerry MacMurray 26cb508a00SPerry MacMurray using namespace llvm; 27cb508a00SPerry MacMurray 28cb508a00SPerry MacMurray static cl::opt<std::string> CPHoistFn("cphoistfn", cl::Hidden, cl::desc(""), 29cb508a00SPerry MacMurray cl::init("")); 30cb508a00SPerry MacMurray 31cb508a00SPerry MacMurray namespace llvm { 32cb508a00SPerry MacMurray void initializeHexagonCopyHoistingPass(PassRegistry &Registry); 33cb508a00SPerry MacMurray FunctionPass *createHexagonCopyHoisting(); 34cb508a00SPerry MacMurray } // namespace llvm 35cb508a00SPerry MacMurray 36cb508a00SPerry MacMurray namespace { 37cb508a00SPerry MacMurray 38cb508a00SPerry MacMurray class HexagonCopyHoisting : public MachineFunctionPass { 39cb508a00SPerry MacMurray 40cb508a00SPerry MacMurray public: 41cb508a00SPerry MacMurray static char ID; 42cb508a00SPerry MacMurray HexagonCopyHoisting() : MachineFunctionPass(ID), MFN(nullptr), MRI(nullptr) { 43cb508a00SPerry MacMurray initializeHexagonCopyHoistingPass(*PassRegistry::getPassRegistry()); 44cb508a00SPerry MacMurray } 45cb508a00SPerry MacMurray 46cb508a00SPerry MacMurray StringRef getPassName() const override { return "Hexagon Copy Hoisting"; } 47cb508a00SPerry MacMurray 48cb508a00SPerry MacMurray void getAnalysisUsage(AnalysisUsage &AU) const override { 494010f894Spaperchalice AU.addRequired<SlotIndexesWrapperPass>(); 50abde52aaSpaperchalice AU.addRequired<LiveIntervalsWrapperPass>(); 514010f894Spaperchalice AU.addPreserved<SlotIndexesWrapperPass>(); 52abde52aaSpaperchalice AU.addPreserved<LiveIntervalsWrapperPass>(); 53837dc542Spaperchalice AU.addRequired<MachineDominatorTreeWrapperPass>(); 54837dc542Spaperchalice AU.addPreserved<MachineDominatorTreeWrapperPass>(); 55cb508a00SPerry MacMurray MachineFunctionPass::getAnalysisUsage(AU); 56cb508a00SPerry MacMurray } 57cb508a00SPerry MacMurray 58cb508a00SPerry MacMurray bool runOnMachineFunction(MachineFunction &Fn) override; 59cb508a00SPerry MacMurray void collectCopyInst(); 60cb508a00SPerry MacMurray void addMItoCopyList(MachineInstr *MI); 61cb508a00SPerry MacMurray bool analyzeCopy(MachineBasicBlock *BB); 62cb508a00SPerry MacMurray bool isSafetoMove(MachineInstr *CandMI); 63cb508a00SPerry MacMurray void moveCopyInstr(MachineBasicBlock *DestBB, 64cb508a00SPerry MacMurray std::pair<Register, Register> Key, MachineInstr *MI); 65cb508a00SPerry MacMurray 66cb508a00SPerry MacMurray MachineFunction *MFN; 67cb508a00SPerry MacMurray MachineRegisterInfo *MRI; 68cb508a00SPerry MacMurray std::vector<DenseMap<std::pair<Register, Register>, MachineInstr *>> 69cb508a00SPerry MacMurray CopyMIList; 70cb508a00SPerry MacMurray }; 71cb508a00SPerry MacMurray 72cb508a00SPerry MacMurray } // namespace 73cb508a00SPerry MacMurray 74cb508a00SPerry MacMurray char HexagonCopyHoisting::ID = 0; 75cb508a00SPerry MacMurray 76cb508a00SPerry MacMurray namespace llvm { 77cb508a00SPerry MacMurray char &HexagonCopyHoistingID = HexagonCopyHoisting::ID; 78cb508a00SPerry MacMurray } // namespace llvm 79cb508a00SPerry MacMurray 80cb508a00SPerry MacMurray bool HexagonCopyHoisting::runOnMachineFunction(MachineFunction &Fn) { 81cb508a00SPerry MacMurray 82cb508a00SPerry MacMurray if ((CPHoistFn != "") && (CPHoistFn != Fn.getFunction().getName())) 83cb508a00SPerry MacMurray return false; 84cb508a00SPerry MacMurray 85cb508a00SPerry MacMurray MFN = &Fn; 86cb508a00SPerry MacMurray MRI = &Fn.getRegInfo(); 87cb508a00SPerry MacMurray 88cb508a00SPerry MacMurray LLVM_DEBUG(dbgs() << "\nCopy Hoisting:" << "\'" << Fn.getName() << "\'\n"); 89cb508a00SPerry MacMurray 90cb508a00SPerry MacMurray CopyMIList.clear(); 91cb508a00SPerry MacMurray CopyMIList.resize(Fn.getNumBlockIDs()); 92cb508a00SPerry MacMurray 93cb508a00SPerry MacMurray // Traverse through all basic blocks and collect copy instructions. 94cb508a00SPerry MacMurray collectCopyInst(); 95cb508a00SPerry MacMurray 96cb508a00SPerry MacMurray // Traverse through the basic blocks again and move the COPY instructions 97cb508a00SPerry MacMurray // that are present in all the successors of BB to BB. 98cb508a00SPerry MacMurray bool Changed = false; 99cb508a00SPerry MacMurray for (MachineBasicBlock *BB : post_order(&Fn)) { 100cb508a00SPerry MacMurray if (!BB->empty()) { 101cb508a00SPerry MacMurray if (BB->pred_size() != 1) 102cb508a00SPerry MacMurray continue; 103cb508a00SPerry MacMurray auto &BBCopyInst = CopyMIList[BB->getNumber()]; 104cb508a00SPerry MacMurray if (BBCopyInst.size() > 0) 105cb508a00SPerry MacMurray Changed |= analyzeCopy(*BB->pred_begin()); 106cb508a00SPerry MacMurray } 107cb508a00SPerry MacMurray } 108cb508a00SPerry MacMurray // Re-compute liveness 109cb508a00SPerry MacMurray if (Changed) { 110abde52aaSpaperchalice LiveIntervals &LIS = getAnalysis<LiveIntervalsWrapperPass>().getLIS(); 111cb508a00SPerry MacMurray SlotIndexes *SI = LIS.getSlotIndexes(); 1124010f894Spaperchalice SI->reanalyze(Fn); 113abde52aaSpaperchalice LIS.reanalyze(Fn); 114cb508a00SPerry MacMurray } 115cb508a00SPerry MacMurray return Changed; 116cb508a00SPerry MacMurray } 117cb508a00SPerry MacMurray 118cb508a00SPerry MacMurray //===----------------------------------------------------------------------===// 119cb508a00SPerry MacMurray // Save all COPY instructions for each basic block in CopyMIList vector. 120cb508a00SPerry MacMurray //===----------------------------------------------------------------------===// 121cb508a00SPerry MacMurray void HexagonCopyHoisting::collectCopyInst() { 122cb508a00SPerry MacMurray for (MachineBasicBlock &BB : *MFN) { 123cb508a00SPerry MacMurray #ifndef NDEBUG 124cb508a00SPerry MacMurray auto &BBCopyInst = CopyMIList[BB.getNumber()]; 125cb508a00SPerry MacMurray LLVM_DEBUG(dbgs() << "Visiting BB#" << BB.getNumber() << ":\n"); 126cb508a00SPerry MacMurray #endif 127cb508a00SPerry MacMurray 128cb508a00SPerry MacMurray for (MachineInstr &MI : BB) { 129cb508a00SPerry MacMurray if (MI.getOpcode() == TargetOpcode::COPY) 130cb508a00SPerry MacMurray addMItoCopyList(&MI); 131cb508a00SPerry MacMurray } 132cb508a00SPerry MacMurray LLVM_DEBUG(dbgs() << "\tNumber of copies: " << BBCopyInst.size() << "\n"); 133cb508a00SPerry MacMurray } 134cb508a00SPerry MacMurray } 135cb508a00SPerry MacMurray 136cb508a00SPerry MacMurray void HexagonCopyHoisting::addMItoCopyList(MachineInstr *MI) { 137cb508a00SPerry MacMurray unsigned BBNum = MI->getParent()->getNumber(); 138cb508a00SPerry MacMurray auto &BBCopyInst = CopyMIList[BBNum]; 139cb508a00SPerry MacMurray Register DstReg = MI->getOperand(0).getReg(); 140cb508a00SPerry MacMurray Register SrcReg = MI->getOperand(1).getReg(); 141cb508a00SPerry MacMurray 142cb508a00SPerry MacMurray if (!Register::isVirtualRegister(DstReg) || 143cb508a00SPerry MacMurray !Register::isVirtualRegister(SrcReg) || 144cb508a00SPerry MacMurray MRI->getRegClass(DstReg) != &Hexagon::IntRegsRegClass || 145cb508a00SPerry MacMurray MRI->getRegClass(SrcReg) != &Hexagon::IntRegsRegClass) 146cb508a00SPerry MacMurray return; 147cb508a00SPerry MacMurray 148cb508a00SPerry MacMurray BBCopyInst.insert(std::pair(std::pair(SrcReg, DstReg), MI)); 149cb508a00SPerry MacMurray #ifndef NDEBUG 150cb508a00SPerry MacMurray LLVM_DEBUG(dbgs() << "\tAdding Copy Instr to the list: " << MI << "\n"); 151cb508a00SPerry MacMurray for (auto II : BBCopyInst) { 152cb508a00SPerry MacMurray MachineInstr *TempMI = II.getSecond(); 153cb508a00SPerry MacMurray LLVM_DEBUG(dbgs() << "\tIn the list: " << TempMI << "\n"); 154cb508a00SPerry MacMurray } 155cb508a00SPerry MacMurray #endif 156cb508a00SPerry MacMurray } 157cb508a00SPerry MacMurray 158cb508a00SPerry MacMurray //===----------------------------------------------------------------------===// 159cb508a00SPerry MacMurray // Look at the COPY instructions of all the successors of BB. If the same 160cb508a00SPerry MacMurray // instruction is present in every successor and can be safely moved, 161cb508a00SPerry MacMurray // pull it into BB. 162cb508a00SPerry MacMurray //===----------------------------------------------------------------------===// 163cb508a00SPerry MacMurray bool HexagonCopyHoisting::analyzeCopy(MachineBasicBlock *BB) { 164cb508a00SPerry MacMurray 165cb508a00SPerry MacMurray bool Changed = false; 166cb508a00SPerry MacMurray if (BB->succ_size() < 2) 167cb508a00SPerry MacMurray return false; 168cb508a00SPerry MacMurray 169cb508a00SPerry MacMurray for (MachineBasicBlock *SB : BB->successors()) { 170cb508a00SPerry MacMurray if (SB->pred_size() != 1 || SB->isEHPad() || SB->hasAddressTaken()) 171cb508a00SPerry MacMurray return false; 172cb508a00SPerry MacMurray } 173cb508a00SPerry MacMurray 174cb508a00SPerry MacMurray MachineBasicBlock *SBB1 = *BB->succ_begin(); 175cb508a00SPerry MacMurray auto &BBCopyInst1 = CopyMIList[SBB1->getNumber()]; 176cb508a00SPerry MacMurray 177cb508a00SPerry MacMurray for (auto II : BBCopyInst1) { 178cb508a00SPerry MacMurray std::pair<Register, Register> Key = II.getFirst(); 179cb508a00SPerry MacMurray MachineInstr *MI = II.getSecond(); 180cb508a00SPerry MacMurray bool IsSafetoMove = true; 181cb508a00SPerry MacMurray for (MachineBasicBlock *SuccBB : BB->successors()) { 182cb508a00SPerry MacMurray auto &SuccBBCopyInst = CopyMIList[SuccBB->getNumber()]; 183cb508a00SPerry MacMurray if (!SuccBBCopyInst.count(Key)) { 184cb508a00SPerry MacMurray // Same copy not present in this successor 185cb508a00SPerry MacMurray IsSafetoMove = false; 186cb508a00SPerry MacMurray break; 187cb508a00SPerry MacMurray } 188cb508a00SPerry MacMurray // If present, make sure that it's safe to pull this copy instruction 189cb508a00SPerry MacMurray // into the predecessor. 190cb508a00SPerry MacMurray MachineInstr *SuccMI = SuccBBCopyInst[Key]; 191cb508a00SPerry MacMurray if (!isSafetoMove(SuccMI)) { 192cb508a00SPerry MacMurray IsSafetoMove = false; 193cb508a00SPerry MacMurray break; 194cb508a00SPerry MacMurray } 195cb508a00SPerry MacMurray } 196cb508a00SPerry MacMurray // If we have come this far, this copy instruction can be safely 197cb508a00SPerry MacMurray // moved to the predecessor basic block. 198cb508a00SPerry MacMurray if (IsSafetoMove) { 199cb508a00SPerry MacMurray LLVM_DEBUG(dbgs() << "\t\t Moving instr to BB#" << BB->getNumber() << ": " 200cb508a00SPerry MacMurray << MI << "\n"); 201cb508a00SPerry MacMurray moveCopyInstr(BB, Key, MI); 202cb508a00SPerry MacMurray // Add my into BB copyMI list. 203cb508a00SPerry MacMurray Changed = true; 204cb508a00SPerry MacMurray } 205cb508a00SPerry MacMurray } 206cb508a00SPerry MacMurray 207cb508a00SPerry MacMurray #ifndef NDEBUG 208cb508a00SPerry MacMurray auto &BBCopyInst = CopyMIList[BB->getNumber()]; 209cb508a00SPerry MacMurray for (auto II : BBCopyInst) { 210cb508a00SPerry MacMurray MachineInstr *TempMI = II.getSecond(); 211cb508a00SPerry MacMurray LLVM_DEBUG(dbgs() << "\tIn the list: " << TempMI << "\n"); 212cb508a00SPerry MacMurray } 213cb508a00SPerry MacMurray #endif 214cb508a00SPerry MacMurray return Changed; 215cb508a00SPerry MacMurray } 216cb508a00SPerry MacMurray 217cb508a00SPerry MacMurray bool HexagonCopyHoisting::isSafetoMove(MachineInstr *CandMI) { 218cb508a00SPerry MacMurray // Make sure that it's safe to move this 'copy' instruction to the predecessor 219cb508a00SPerry MacMurray // basic block. 220cb508a00SPerry MacMurray assert(CandMI->getOperand(0).isReg() && CandMI->getOperand(1).isReg()); 221cb508a00SPerry MacMurray Register DefR = CandMI->getOperand(0).getReg(); 222cb508a00SPerry MacMurray Register UseR = CandMI->getOperand(1).getReg(); 223cb508a00SPerry MacMurray 224cb508a00SPerry MacMurray MachineBasicBlock *BB = CandMI->getParent(); 225cb508a00SPerry MacMurray // There should not be a def/use of DefR between the start of BB and CandMI. 226cb508a00SPerry MacMurray MachineBasicBlock::iterator MII, MIE; 227cb508a00SPerry MacMurray for (MII = BB->begin(), MIE = CandMI; MII != MIE; ++MII) { 228cb508a00SPerry MacMurray MachineInstr *OtherMI = &*MII; 229cb508a00SPerry MacMurray for (const MachineOperand &Mo : OtherMI->operands()) 230cb508a00SPerry MacMurray if (Mo.isReg() && Mo.getReg() == DefR) 231cb508a00SPerry MacMurray return false; 232cb508a00SPerry MacMurray } 233cb508a00SPerry MacMurray // There should not be a def of UseR between the start of BB and CandMI. 234cb508a00SPerry MacMurray for (MII = BB->begin(), MIE = CandMI; MII != MIE; ++MII) { 235cb508a00SPerry MacMurray MachineInstr *OtherMI = &*MII; 236cb508a00SPerry MacMurray for (const MachineOperand &Mo : OtherMI->operands()) 237cb508a00SPerry MacMurray if (Mo.isReg() && Mo.isDef() && Mo.getReg() == UseR) 238cb508a00SPerry MacMurray return false; 239cb508a00SPerry MacMurray } 240cb508a00SPerry MacMurray return true; 241cb508a00SPerry MacMurray } 242cb508a00SPerry MacMurray 243cb508a00SPerry MacMurray void HexagonCopyHoisting::moveCopyInstr(MachineBasicBlock *DestBB, 244cb508a00SPerry MacMurray std::pair<Register, Register> Key, 245cb508a00SPerry MacMurray MachineInstr *MI) { 246cb508a00SPerry MacMurray MachineBasicBlock::iterator FirstTI = DestBB->getFirstTerminator(); 247cb508a00SPerry MacMurray assert(FirstTI != DestBB->end()); 248cb508a00SPerry MacMurray 249cb508a00SPerry MacMurray DestBB->splice(FirstTI, MI->getParent(), MI); 250cb508a00SPerry MacMurray 251cb508a00SPerry MacMurray addMItoCopyList(MI); 252*66878ff6SKazu Hirata for (MachineBasicBlock *SuccBB : drop_begin(DestBB->successors())) { 253cb508a00SPerry MacMurray auto &BBCopyInst = CopyMIList[SuccBB->getNumber()]; 254cb508a00SPerry MacMurray MachineInstr *SuccMI = BBCopyInst[Key]; 255cb508a00SPerry MacMurray SuccMI->eraseFromParent(); 256cb508a00SPerry MacMurray BBCopyInst.erase(Key); 257cb508a00SPerry MacMurray } 258cb508a00SPerry MacMurray } 259cb508a00SPerry MacMurray 260cb508a00SPerry MacMurray //===----------------------------------------------------------------------===// 261cb508a00SPerry MacMurray // Public Constructor Functions 262cb508a00SPerry MacMurray //===----------------------------------------------------------------------===// 263cb508a00SPerry MacMurray 264cb508a00SPerry MacMurray INITIALIZE_PASS(HexagonCopyHoisting, "hexagon-move-phicopy", 265cb508a00SPerry MacMurray "Hexagon move phi copy", false, false) 266cb508a00SPerry MacMurray 267cb508a00SPerry MacMurray FunctionPass *llvm::createHexagonCopyHoisting() { 268cb508a00SPerry MacMurray return new HexagonCopyHoisting(); 269cb508a00SPerry MacMurray } 270