Path: blob/main/contrib/llvm-project/llvm/lib/Target/Hexagon/HexagonCopyHoisting.cpp
35266 views
//===--------- HexagonCopyHoisting.cpp - Hexagon Copy Hoisting ----------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7// The purpose of this pass is to move the copy instructions that are8// present in all the successor of a basic block (BB) to the end of BB.9//===----------------------------------------------------------------------===//1011#include "HexagonTargetMachine.h"12#include "llvm/ADT/DenseMap.h"13#include "llvm/ADT/PostOrderIterator.h"14#include "llvm/ADT/StringRef.h"15#include "llvm/ADT/Twine.h"16#include "llvm/CodeGen/LiveInterval.h"17#include "llvm/CodeGen/LiveIntervals.h"18#include "llvm/CodeGen/MachineDominators.h"19#include "llvm/CodeGen/MachineRegisterInfo.h"20#include "llvm/Support/CommandLine.h"21#include "llvm/Support/Debug.h"2223#define DEBUG_TYPE "CopyHoist"2425using namespace llvm;2627static cl::opt<std::string> CPHoistFn("cphoistfn", cl::Hidden, cl::desc(""),28cl::init(""));2930namespace llvm {31void initializeHexagonCopyHoistingPass(PassRegistry &Registry);32FunctionPass *createHexagonCopyHoisting();33} // namespace llvm3435namespace {3637class HexagonCopyHoisting : public MachineFunctionPass {3839public:40static char ID;41HexagonCopyHoisting() : MachineFunctionPass(ID), MFN(nullptr), MRI(nullptr) {42initializeHexagonCopyHoistingPass(*PassRegistry::getPassRegistry());43}4445StringRef getPassName() const override { return "Hexagon Copy Hoisting"; }4647void getAnalysisUsage(AnalysisUsage &AU) const override {48AU.addRequired<SlotIndexesWrapperPass>();49AU.addRequired<LiveIntervalsWrapperPass>();50AU.addPreserved<SlotIndexesWrapperPass>();51AU.addPreserved<LiveIntervalsWrapperPass>();52AU.addRequired<MachineDominatorTreeWrapperPass>();53AU.addPreserved<MachineDominatorTreeWrapperPass>();54MachineFunctionPass::getAnalysisUsage(AU);55}5657bool runOnMachineFunction(MachineFunction &Fn) override;58void collectCopyInst();59void addMItoCopyList(MachineInstr *MI);60bool analyzeCopy(MachineBasicBlock *BB);61bool isSafetoMove(MachineInstr *CandMI);62void moveCopyInstr(MachineBasicBlock *DestBB,63std::pair<Register, Register> Key, MachineInstr *MI);6465MachineFunction *MFN;66MachineRegisterInfo *MRI;67std::vector<DenseMap<std::pair<Register, Register>, MachineInstr *>>68CopyMIList;69};7071} // namespace7273char HexagonCopyHoisting::ID = 0;7475namespace llvm {76char &HexagonCopyHoistingID = HexagonCopyHoisting::ID;77} // namespace llvm7879bool HexagonCopyHoisting::runOnMachineFunction(MachineFunction &Fn) {8081if ((CPHoistFn != "") && (CPHoistFn != Fn.getFunction().getName()))82return false;8384MFN = &Fn;85MRI = &Fn.getRegInfo();8687LLVM_DEBUG(dbgs() << "\nCopy Hoisting:" << "\'" << Fn.getName() << "\'\n");8889CopyMIList.clear();90CopyMIList.resize(Fn.getNumBlockIDs());9192// Traverse through all basic blocks and collect copy instructions.93collectCopyInst();9495// Traverse through the basic blocks again and move the COPY instructions96// that are present in all the successors of BB to BB.97bool Changed = false;98for (MachineBasicBlock *BB : post_order(&Fn)) {99if (!BB->empty()) {100if (BB->pred_size() != 1)101continue;102auto &BBCopyInst = CopyMIList[BB->getNumber()];103if (BBCopyInst.size() > 0)104Changed |= analyzeCopy(*BB->pred_begin());105}106}107// Re-compute liveness108if (Changed) {109LiveIntervals &LIS = getAnalysis<LiveIntervalsWrapperPass>().getLIS();110SlotIndexes *SI = LIS.getSlotIndexes();111SI->reanalyze(Fn);112LIS.reanalyze(Fn);113}114return Changed;115}116117//===----------------------------------------------------------------------===//118// Save all COPY instructions for each basic block in CopyMIList vector.119//===----------------------------------------------------------------------===//120void HexagonCopyHoisting::collectCopyInst() {121for (MachineBasicBlock &BB : *MFN) {122#ifndef NDEBUG123auto &BBCopyInst = CopyMIList[BB.getNumber()];124LLVM_DEBUG(dbgs() << "Visiting BB#" << BB.getNumber() << ":\n");125#endif126127for (MachineInstr &MI : BB) {128if (MI.getOpcode() == TargetOpcode::COPY)129addMItoCopyList(&MI);130}131LLVM_DEBUG(dbgs() << "\tNumber of copies: " << BBCopyInst.size() << "\n");132}133}134135void HexagonCopyHoisting::addMItoCopyList(MachineInstr *MI) {136unsigned BBNum = MI->getParent()->getNumber();137auto &BBCopyInst = CopyMIList[BBNum];138Register DstReg = MI->getOperand(0).getReg();139Register SrcReg = MI->getOperand(1).getReg();140141if (!Register::isVirtualRegister(DstReg) ||142!Register::isVirtualRegister(SrcReg) ||143MRI->getRegClass(DstReg) != &Hexagon::IntRegsRegClass ||144MRI->getRegClass(SrcReg) != &Hexagon::IntRegsRegClass)145return;146147BBCopyInst.insert(std::pair(std::pair(SrcReg, DstReg), MI));148#ifndef NDEBUG149LLVM_DEBUG(dbgs() << "\tAdding Copy Instr to the list: " << MI << "\n");150for (auto II : BBCopyInst) {151MachineInstr *TempMI = II.getSecond();152LLVM_DEBUG(dbgs() << "\tIn the list: " << TempMI << "\n");153}154#endif155}156157//===----------------------------------------------------------------------===//158// Look at the COPY instructions of all the successors of BB. If the same159// instruction is present in every successor and can be safely moved,160// pull it into BB.161//===----------------------------------------------------------------------===//162bool HexagonCopyHoisting::analyzeCopy(MachineBasicBlock *BB) {163164bool Changed = false;165if (BB->succ_size() < 2)166return false;167168for (MachineBasicBlock *SB : BB->successors()) {169if (SB->pred_size() != 1 || SB->isEHPad() || SB->hasAddressTaken())170return false;171}172173MachineBasicBlock *SBB1 = *BB->succ_begin();174auto &BBCopyInst1 = CopyMIList[SBB1->getNumber()];175176for (auto II : BBCopyInst1) {177std::pair<Register, Register> Key = II.getFirst();178MachineInstr *MI = II.getSecond();179bool IsSafetoMove = true;180for (MachineBasicBlock *SuccBB : BB->successors()) {181auto &SuccBBCopyInst = CopyMIList[SuccBB->getNumber()];182if (!SuccBBCopyInst.count(Key)) {183// Same copy not present in this successor184IsSafetoMove = false;185break;186}187// If present, make sure that it's safe to pull this copy instruction188// into the predecessor.189MachineInstr *SuccMI = SuccBBCopyInst[Key];190if (!isSafetoMove(SuccMI)) {191IsSafetoMove = false;192break;193}194}195// If we have come this far, this copy instruction can be safely196// moved to the predecessor basic block.197if (IsSafetoMove) {198LLVM_DEBUG(dbgs() << "\t\t Moving instr to BB#" << BB->getNumber() << ": "199<< MI << "\n");200moveCopyInstr(BB, Key, MI);201// Add my into BB copyMI list.202Changed = true;203}204}205206#ifndef NDEBUG207auto &BBCopyInst = CopyMIList[BB->getNumber()];208for (auto II : BBCopyInst) {209MachineInstr *TempMI = II.getSecond();210LLVM_DEBUG(dbgs() << "\tIn the list: " << TempMI << "\n");211}212#endif213return Changed;214}215216bool HexagonCopyHoisting::isSafetoMove(MachineInstr *CandMI) {217// Make sure that it's safe to move this 'copy' instruction to the predecessor218// basic block.219assert(CandMI->getOperand(0).isReg() && CandMI->getOperand(1).isReg());220Register DefR = CandMI->getOperand(0).getReg();221Register UseR = CandMI->getOperand(1).getReg();222223MachineBasicBlock *BB = CandMI->getParent();224// There should not be a def/use of DefR between the start of BB and CandMI.225MachineBasicBlock::iterator MII, MIE;226for (MII = BB->begin(), MIE = CandMI; MII != MIE; ++MII) {227MachineInstr *OtherMI = &*MII;228for (const MachineOperand &Mo : OtherMI->operands())229if (Mo.isReg() && Mo.getReg() == DefR)230return false;231}232// There should not be a def of UseR between the start of BB and CandMI.233for (MII = BB->begin(), MIE = CandMI; MII != MIE; ++MII) {234MachineInstr *OtherMI = &*MII;235for (const MachineOperand &Mo : OtherMI->operands())236if (Mo.isReg() && Mo.isDef() && Mo.getReg() == UseR)237return false;238}239return true;240}241242void HexagonCopyHoisting::moveCopyInstr(MachineBasicBlock *DestBB,243std::pair<Register, Register> Key,244MachineInstr *MI) {245MachineBasicBlock::iterator FirstTI = DestBB->getFirstTerminator();246assert(FirstTI != DestBB->end());247248DestBB->splice(FirstTI, MI->getParent(), MI);249250addMItoCopyList(MI);251for (auto I = ++(DestBB->succ_begin()), E = DestBB->succ_end(); I != E; ++I) {252MachineBasicBlock *SuccBB = *I;253auto &BBCopyInst = CopyMIList[SuccBB->getNumber()];254MachineInstr *SuccMI = BBCopyInst[Key];255SuccMI->eraseFromParent();256BBCopyInst.erase(Key);257}258}259260//===----------------------------------------------------------------------===//261// Public Constructor Functions262//===----------------------------------------------------------------------===//263264INITIALIZE_PASS(HexagonCopyHoisting, "hexagon-move-phicopy",265"Hexagon move phi copy", false, false)266267FunctionPass *llvm::createHexagonCopyHoisting() {268return new HexagonCopyHoisting();269}270271272