1*0b57cec5SDimitry Andric //=--- RegUsageInfoPropagate.cpp - Register Usage Informartion Propagation --=// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric /// 9*0b57cec5SDimitry Andric /// This pass is required to take advantage of the interprocedural register 10*0b57cec5SDimitry Andric /// allocation infrastructure. 11*0b57cec5SDimitry Andric /// 12*0b57cec5SDimitry Andric /// This pass iterates through MachineInstrs in a given MachineFunction and at 13*0b57cec5SDimitry Andric /// each callsite queries RegisterUsageInfo for RegMask (calculated based on 14*0b57cec5SDimitry Andric /// actual register allocation) of the callee function, if the RegMask detail 15*0b57cec5SDimitry Andric /// is available then this pass will update the RegMask of the call instruction. 16*0b57cec5SDimitry Andric /// This updated RegMask will be used by the register allocator while allocating 17*0b57cec5SDimitry Andric /// the current MachineFunction. 18*0b57cec5SDimitry Andric /// 19*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 20*0b57cec5SDimitry Andric 21*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h" 22*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h" 23*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h" 24*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h" 25*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 26*0b57cec5SDimitry Andric #include "llvm/CodeGen/Passes.h" 27*0b57cec5SDimitry Andric #include "llvm/CodeGen/RegisterUsageInfo.h" 28*0b57cec5SDimitry Andric #include "llvm/IR/Module.h" 29*0b57cec5SDimitry Andric #include "llvm/PassAnalysisSupport.h" 30*0b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 31*0b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 32*0b57cec5SDimitry Andric #include "llvm/Target/TargetMachine.h" 33*0b57cec5SDimitry Andric #include <map> 34*0b57cec5SDimitry Andric #include <string> 35*0b57cec5SDimitry Andric 36*0b57cec5SDimitry Andric using namespace llvm; 37*0b57cec5SDimitry Andric 38*0b57cec5SDimitry Andric #define DEBUG_TYPE "ip-regalloc" 39*0b57cec5SDimitry Andric 40*0b57cec5SDimitry Andric #define RUIP_NAME "Register Usage Information Propagation" 41*0b57cec5SDimitry Andric 42*0b57cec5SDimitry Andric namespace { 43*0b57cec5SDimitry Andric 44*0b57cec5SDimitry Andric class RegUsageInfoPropagation : public MachineFunctionPass { 45*0b57cec5SDimitry Andric public: 46*0b57cec5SDimitry Andric RegUsageInfoPropagation() : MachineFunctionPass(ID) { 47*0b57cec5SDimitry Andric PassRegistry &Registry = *PassRegistry::getPassRegistry(); 48*0b57cec5SDimitry Andric initializeRegUsageInfoPropagationPass(Registry); 49*0b57cec5SDimitry Andric } 50*0b57cec5SDimitry Andric 51*0b57cec5SDimitry Andric StringRef getPassName() const override { return RUIP_NAME; } 52*0b57cec5SDimitry Andric 53*0b57cec5SDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override; 54*0b57cec5SDimitry Andric 55*0b57cec5SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override { 56*0b57cec5SDimitry Andric AU.addRequired<PhysicalRegisterUsageInfo>(); 57*0b57cec5SDimitry Andric AU.setPreservesAll(); 58*0b57cec5SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU); 59*0b57cec5SDimitry Andric } 60*0b57cec5SDimitry Andric 61*0b57cec5SDimitry Andric static char ID; 62*0b57cec5SDimitry Andric 63*0b57cec5SDimitry Andric private: 64*0b57cec5SDimitry Andric static void setRegMask(MachineInstr &MI, ArrayRef<uint32_t> RegMask) { 65*0b57cec5SDimitry Andric assert(RegMask.size() == 66*0b57cec5SDimitry Andric MachineOperand::getRegMaskSize(MI.getParent()->getParent() 67*0b57cec5SDimitry Andric ->getRegInfo().getTargetRegisterInfo() 68*0b57cec5SDimitry Andric ->getNumRegs()) 69*0b57cec5SDimitry Andric && "expected register mask size"); 70*0b57cec5SDimitry Andric for (MachineOperand &MO : MI.operands()) { 71*0b57cec5SDimitry Andric if (MO.isRegMask()) 72*0b57cec5SDimitry Andric MO.setRegMask(RegMask.data()); 73*0b57cec5SDimitry Andric } 74*0b57cec5SDimitry Andric } 75*0b57cec5SDimitry Andric }; 76*0b57cec5SDimitry Andric 77*0b57cec5SDimitry Andric } // end of anonymous namespace 78*0b57cec5SDimitry Andric 79*0b57cec5SDimitry Andric INITIALIZE_PASS_BEGIN(RegUsageInfoPropagation, "reg-usage-propagation", 80*0b57cec5SDimitry Andric RUIP_NAME, false, false) 81*0b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(PhysicalRegisterUsageInfo) 82*0b57cec5SDimitry Andric INITIALIZE_PASS_END(RegUsageInfoPropagation, "reg-usage-propagation", 83*0b57cec5SDimitry Andric RUIP_NAME, false, false) 84*0b57cec5SDimitry Andric 85*0b57cec5SDimitry Andric char RegUsageInfoPropagation::ID = 0; 86*0b57cec5SDimitry Andric 87*0b57cec5SDimitry Andric // Assumes call instructions have a single reference to a function. 88*0b57cec5SDimitry Andric static const Function *findCalledFunction(const Module &M, 89*0b57cec5SDimitry Andric const MachineInstr &MI) { 90*0b57cec5SDimitry Andric for (const MachineOperand &MO : MI.operands()) { 91*0b57cec5SDimitry Andric if (MO.isGlobal()) 92*0b57cec5SDimitry Andric return dyn_cast<const Function>(MO.getGlobal()); 93*0b57cec5SDimitry Andric 94*0b57cec5SDimitry Andric if (MO.isSymbol()) 95*0b57cec5SDimitry Andric return M.getFunction(MO.getSymbolName()); 96*0b57cec5SDimitry Andric } 97*0b57cec5SDimitry Andric 98*0b57cec5SDimitry Andric return nullptr; 99*0b57cec5SDimitry Andric } 100*0b57cec5SDimitry Andric 101*0b57cec5SDimitry Andric bool RegUsageInfoPropagation::runOnMachineFunction(MachineFunction &MF) { 102*0b57cec5SDimitry Andric const Module &M = *MF.getFunction().getParent(); 103*0b57cec5SDimitry Andric PhysicalRegisterUsageInfo *PRUI = &getAnalysis<PhysicalRegisterUsageInfo>(); 104*0b57cec5SDimitry Andric 105*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " ++++++++++++++++++++ " << getPassName() 106*0b57cec5SDimitry Andric << " ++++++++++++++++++++ \n"); 107*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "MachineFunction : " << MF.getName() << "\n"); 108*0b57cec5SDimitry Andric 109*0b57cec5SDimitry Andric const MachineFrameInfo &MFI = MF.getFrameInfo(); 110*0b57cec5SDimitry Andric if (!MFI.hasCalls() && !MFI.hasTailCall()) 111*0b57cec5SDimitry Andric return false; 112*0b57cec5SDimitry Andric 113*0b57cec5SDimitry Andric bool Changed = false; 114*0b57cec5SDimitry Andric 115*0b57cec5SDimitry Andric for (MachineBasicBlock &MBB : MF) { 116*0b57cec5SDimitry Andric for (MachineInstr &MI : MBB) { 117*0b57cec5SDimitry Andric if (!MI.isCall()) 118*0b57cec5SDimitry Andric continue; 119*0b57cec5SDimitry Andric LLVM_DEBUG( 120*0b57cec5SDimitry Andric dbgs() 121*0b57cec5SDimitry Andric << "Call Instruction Before Register Usage Info Propagation : \n"); 122*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << MI << "\n"); 123*0b57cec5SDimitry Andric 124*0b57cec5SDimitry Andric auto UpdateRegMask = [&](const Function &F) { 125*0b57cec5SDimitry Andric const ArrayRef<uint32_t> RegMask = PRUI->getRegUsageInfo(F); 126*0b57cec5SDimitry Andric if (RegMask.empty()) 127*0b57cec5SDimitry Andric return; 128*0b57cec5SDimitry Andric setRegMask(MI, RegMask); 129*0b57cec5SDimitry Andric Changed = true; 130*0b57cec5SDimitry Andric }; 131*0b57cec5SDimitry Andric 132*0b57cec5SDimitry Andric if (const Function *F = findCalledFunction(M, MI)) { 133*0b57cec5SDimitry Andric UpdateRegMask(*F); 134*0b57cec5SDimitry Andric } else { 135*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Failed to find call target function\n"); 136*0b57cec5SDimitry Andric } 137*0b57cec5SDimitry Andric 138*0b57cec5SDimitry Andric LLVM_DEBUG( 139*0b57cec5SDimitry Andric dbgs() << "Call Instruction After Register Usage Info Propagation : " 140*0b57cec5SDimitry Andric << MI << '\n'); 141*0b57cec5SDimitry Andric } 142*0b57cec5SDimitry Andric } 143*0b57cec5SDimitry Andric 144*0b57cec5SDimitry Andric LLVM_DEBUG( 145*0b57cec5SDimitry Andric dbgs() << " +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" 146*0b57cec5SDimitry Andric "++++++ \n"); 147*0b57cec5SDimitry Andric return Changed; 148*0b57cec5SDimitry Andric } 149*0b57cec5SDimitry Andric 150*0b57cec5SDimitry Andric FunctionPass *llvm::createRegUsageInfoPropPass() { 151*0b57cec5SDimitry Andric return new RegUsageInfoPropagation(); 152*0b57cec5SDimitry Andric } 153