xref: /freebsd/contrib/llvm-project/llvm/lib/CodeGen/RegUsageInfoPropagate.cpp (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
10b57cec5SDimitry Andric //=--- RegUsageInfoPropagate.cpp - Register Usage Informartion Propagation --=//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric ///
90b57cec5SDimitry Andric /// This pass is required to take advantage of the interprocedural register
100b57cec5SDimitry Andric /// allocation infrastructure.
110b57cec5SDimitry Andric ///
120b57cec5SDimitry Andric /// This pass iterates through MachineInstrs in a given MachineFunction and at
130b57cec5SDimitry Andric /// each callsite queries RegisterUsageInfo for RegMask (calculated based on
140b57cec5SDimitry Andric /// actual register allocation) of the callee function, if the RegMask detail
150b57cec5SDimitry Andric /// is available then this pass will update the RegMask of the call instruction.
160b57cec5SDimitry Andric /// This updated RegMask will be used by the register allocator while allocating
170b57cec5SDimitry Andric /// the current MachineFunction.
180b57cec5SDimitry Andric ///
190b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
200b57cec5SDimitry Andric 
210b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
220b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
23*81ad6265SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
240b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
250b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
260b57cec5SDimitry Andric #include "llvm/CodeGen/Passes.h"
270b57cec5SDimitry Andric #include "llvm/CodeGen/RegisterUsageInfo.h"
280b57cec5SDimitry Andric #include "llvm/IR/Module.h"
295ffd83dbSDimitry Andric #include "llvm/Pass.h"
300b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
310b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric using namespace llvm;
340b57cec5SDimitry Andric 
350b57cec5SDimitry Andric #define DEBUG_TYPE "ip-regalloc"
360b57cec5SDimitry Andric 
370b57cec5SDimitry Andric #define RUIP_NAME "Register Usage Information Propagation"
380b57cec5SDimitry Andric 
390b57cec5SDimitry Andric namespace {
400b57cec5SDimitry Andric 
410b57cec5SDimitry Andric class RegUsageInfoPropagation : public MachineFunctionPass {
420b57cec5SDimitry Andric public:
RegUsageInfoPropagation()430b57cec5SDimitry Andric   RegUsageInfoPropagation() : MachineFunctionPass(ID) {
440b57cec5SDimitry Andric     PassRegistry &Registry = *PassRegistry::getPassRegistry();
450b57cec5SDimitry Andric     initializeRegUsageInfoPropagationPass(Registry);
460b57cec5SDimitry Andric   }
470b57cec5SDimitry Andric 
getPassName() const480b57cec5SDimitry Andric   StringRef getPassName() const override { return RUIP_NAME; }
490b57cec5SDimitry Andric 
500b57cec5SDimitry Andric   bool runOnMachineFunction(MachineFunction &MF) override;
510b57cec5SDimitry Andric 
getAnalysisUsage(AnalysisUsage & AU) const520b57cec5SDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {
530b57cec5SDimitry Andric     AU.addRequired<PhysicalRegisterUsageInfo>();
540b57cec5SDimitry Andric     AU.setPreservesAll();
550b57cec5SDimitry Andric     MachineFunctionPass::getAnalysisUsage(AU);
560b57cec5SDimitry Andric   }
570b57cec5SDimitry Andric 
580b57cec5SDimitry Andric   static char ID;
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric private:
setRegMask(MachineInstr & MI,ArrayRef<uint32_t> RegMask)610b57cec5SDimitry Andric   static void setRegMask(MachineInstr &MI, ArrayRef<uint32_t> RegMask) {
620b57cec5SDimitry Andric     assert(RegMask.size() ==
630b57cec5SDimitry Andric            MachineOperand::getRegMaskSize(MI.getParent()->getParent()
640b57cec5SDimitry Andric                                           ->getRegInfo().getTargetRegisterInfo()
650b57cec5SDimitry Andric                                           ->getNumRegs())
660b57cec5SDimitry Andric            && "expected register mask size");
670b57cec5SDimitry Andric     for (MachineOperand &MO : MI.operands()) {
680b57cec5SDimitry Andric       if (MO.isRegMask())
690b57cec5SDimitry Andric         MO.setRegMask(RegMask.data());
700b57cec5SDimitry Andric     }
710b57cec5SDimitry Andric   }
720b57cec5SDimitry Andric };
730b57cec5SDimitry Andric 
740b57cec5SDimitry Andric } // end of anonymous namespace
750b57cec5SDimitry Andric 
760b57cec5SDimitry Andric INITIALIZE_PASS_BEGIN(RegUsageInfoPropagation, "reg-usage-propagation",
770b57cec5SDimitry Andric                       RUIP_NAME, false, false)
780b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(PhysicalRegisterUsageInfo)
790b57cec5SDimitry Andric INITIALIZE_PASS_END(RegUsageInfoPropagation, "reg-usage-propagation",
800b57cec5SDimitry Andric                     RUIP_NAME, false, false)
810b57cec5SDimitry Andric 
820b57cec5SDimitry Andric char RegUsageInfoPropagation::ID = 0;
830b57cec5SDimitry Andric 
840b57cec5SDimitry Andric // Assumes call instructions have a single reference to a function.
findCalledFunction(const Module & M,const MachineInstr & MI)850b57cec5SDimitry Andric static const Function *findCalledFunction(const Module &M,
860b57cec5SDimitry Andric                                           const MachineInstr &MI) {
870b57cec5SDimitry Andric   for (const MachineOperand &MO : MI.operands()) {
880b57cec5SDimitry Andric     if (MO.isGlobal())
890b57cec5SDimitry Andric       return dyn_cast<const Function>(MO.getGlobal());
900b57cec5SDimitry Andric 
910b57cec5SDimitry Andric     if (MO.isSymbol())
920b57cec5SDimitry Andric       return M.getFunction(MO.getSymbolName());
930b57cec5SDimitry Andric   }
940b57cec5SDimitry Andric 
950b57cec5SDimitry Andric   return nullptr;
960b57cec5SDimitry Andric }
970b57cec5SDimitry Andric 
runOnMachineFunction(MachineFunction & MF)980b57cec5SDimitry Andric bool RegUsageInfoPropagation::runOnMachineFunction(MachineFunction &MF) {
990b57cec5SDimitry Andric   const Module &M = *MF.getFunction().getParent();
1000b57cec5SDimitry Andric   PhysicalRegisterUsageInfo *PRUI = &getAnalysis<PhysicalRegisterUsageInfo>();
1010b57cec5SDimitry Andric 
1020b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << " ++++++++++++++++++++ " << getPassName()
1030b57cec5SDimitry Andric                     << " ++++++++++++++++++++  \n");
1040b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "MachineFunction : " << MF.getName() << "\n");
1050b57cec5SDimitry Andric 
1060b57cec5SDimitry Andric   const MachineFrameInfo &MFI = MF.getFrameInfo();
1070b57cec5SDimitry Andric   if (!MFI.hasCalls() && !MFI.hasTailCall())
1080b57cec5SDimitry Andric     return false;
1090b57cec5SDimitry Andric 
1100b57cec5SDimitry Andric   bool Changed = false;
1110b57cec5SDimitry Andric 
1120b57cec5SDimitry Andric   for (MachineBasicBlock &MBB : MF) {
1130b57cec5SDimitry Andric     for (MachineInstr &MI : MBB) {
1140b57cec5SDimitry Andric       if (!MI.isCall())
1150b57cec5SDimitry Andric         continue;
1160b57cec5SDimitry Andric       LLVM_DEBUG(
1170b57cec5SDimitry Andric           dbgs()
1185ffd83dbSDimitry Andric           << "Call Instruction Before Register Usage Info Propagation : \n"
1195ffd83dbSDimitry Andric           << MI << "\n");
1200b57cec5SDimitry Andric 
1210b57cec5SDimitry Andric       auto UpdateRegMask = [&](const Function &F) {
1220b57cec5SDimitry Andric         const ArrayRef<uint32_t> RegMask = PRUI->getRegUsageInfo(F);
1230b57cec5SDimitry Andric         if (RegMask.empty())
1240b57cec5SDimitry Andric           return;
1250b57cec5SDimitry Andric         setRegMask(MI, RegMask);
1260b57cec5SDimitry Andric         Changed = true;
1270b57cec5SDimitry Andric       };
1280b57cec5SDimitry Andric 
1290b57cec5SDimitry Andric       if (const Function *F = findCalledFunction(M, MI)) {
1308bcb0991SDimitry Andric         if (F->isDefinitionExact()) {
1310b57cec5SDimitry Andric           UpdateRegMask(*F);
1320b57cec5SDimitry Andric         } else {
1338bcb0991SDimitry Andric           LLVM_DEBUG(dbgs() << "Function definition is not exact\n");
1348bcb0991SDimitry Andric         }
1358bcb0991SDimitry Andric       } else {
1360b57cec5SDimitry Andric         LLVM_DEBUG(dbgs() << "Failed to find call target function\n");
1370b57cec5SDimitry Andric       }
1380b57cec5SDimitry Andric 
1390b57cec5SDimitry Andric       LLVM_DEBUG(
1405ffd83dbSDimitry Andric           dbgs()
1415ffd83dbSDimitry Andric           << "Call Instruction After Register Usage Info Propagation : \n"
1420b57cec5SDimitry Andric           << MI << '\n');
1430b57cec5SDimitry Andric     }
1440b57cec5SDimitry Andric   }
1450b57cec5SDimitry Andric 
1460b57cec5SDimitry Andric   LLVM_DEBUG(
1470b57cec5SDimitry Andric       dbgs() << " +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
1480b57cec5SDimitry Andric                 "++++++ \n");
1490b57cec5SDimitry Andric   return Changed;
1500b57cec5SDimitry Andric }
1510b57cec5SDimitry Andric 
createRegUsageInfoPropPass()1520b57cec5SDimitry Andric FunctionPass *llvm::createRegUsageInfoPropPass() {
1530b57cec5SDimitry Andric   return new RegUsageInfoPropagation();
1540b57cec5SDimitry Andric }
155