xref: /freebsd/contrib/llvm-project/llvm/lib/CodeGen/RegUsageInfoPropagate.cpp (revision 5ffd83dbcc34f10e07f6d3e968ae6365869615f4)
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/MachineFunctionPass.h"
230b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.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"
29*5ffd83dbSDimitry Andric #include "llvm/Pass.h"
300b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
310b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
320b57cec5SDimitry Andric #include "llvm/Target/TargetMachine.h"
330b57cec5SDimitry Andric #include <map>
340b57cec5SDimitry Andric #include <string>
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric using namespace llvm;
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric #define DEBUG_TYPE "ip-regalloc"
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric #define RUIP_NAME "Register Usage Information Propagation"
410b57cec5SDimitry Andric 
420b57cec5SDimitry Andric namespace {
430b57cec5SDimitry Andric 
440b57cec5SDimitry Andric class RegUsageInfoPropagation : public MachineFunctionPass {
450b57cec5SDimitry Andric public:
460b57cec5SDimitry Andric   RegUsageInfoPropagation() : MachineFunctionPass(ID) {
470b57cec5SDimitry Andric     PassRegistry &Registry = *PassRegistry::getPassRegistry();
480b57cec5SDimitry Andric     initializeRegUsageInfoPropagationPass(Registry);
490b57cec5SDimitry Andric   }
500b57cec5SDimitry Andric 
510b57cec5SDimitry Andric   StringRef getPassName() const override { return RUIP_NAME; }
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric   bool runOnMachineFunction(MachineFunction &MF) override;
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {
560b57cec5SDimitry Andric     AU.addRequired<PhysicalRegisterUsageInfo>();
570b57cec5SDimitry Andric     AU.setPreservesAll();
580b57cec5SDimitry Andric     MachineFunctionPass::getAnalysisUsage(AU);
590b57cec5SDimitry Andric   }
600b57cec5SDimitry Andric 
610b57cec5SDimitry Andric   static char ID;
620b57cec5SDimitry Andric 
630b57cec5SDimitry Andric private:
640b57cec5SDimitry Andric   static void setRegMask(MachineInstr &MI, ArrayRef<uint32_t> RegMask) {
650b57cec5SDimitry Andric     assert(RegMask.size() ==
660b57cec5SDimitry Andric            MachineOperand::getRegMaskSize(MI.getParent()->getParent()
670b57cec5SDimitry Andric                                           ->getRegInfo().getTargetRegisterInfo()
680b57cec5SDimitry Andric                                           ->getNumRegs())
690b57cec5SDimitry Andric            && "expected register mask size");
700b57cec5SDimitry Andric     for (MachineOperand &MO : MI.operands()) {
710b57cec5SDimitry Andric       if (MO.isRegMask())
720b57cec5SDimitry Andric         MO.setRegMask(RegMask.data());
730b57cec5SDimitry Andric     }
740b57cec5SDimitry Andric   }
750b57cec5SDimitry Andric };
760b57cec5SDimitry Andric 
770b57cec5SDimitry Andric } // end of anonymous namespace
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric INITIALIZE_PASS_BEGIN(RegUsageInfoPropagation, "reg-usage-propagation",
800b57cec5SDimitry Andric                       RUIP_NAME, false, false)
810b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(PhysicalRegisterUsageInfo)
820b57cec5SDimitry Andric INITIALIZE_PASS_END(RegUsageInfoPropagation, "reg-usage-propagation",
830b57cec5SDimitry Andric                     RUIP_NAME, false, false)
840b57cec5SDimitry Andric 
850b57cec5SDimitry Andric char RegUsageInfoPropagation::ID = 0;
860b57cec5SDimitry Andric 
870b57cec5SDimitry Andric // Assumes call instructions have a single reference to a function.
880b57cec5SDimitry Andric static const Function *findCalledFunction(const Module &M,
890b57cec5SDimitry Andric                                           const MachineInstr &MI) {
900b57cec5SDimitry Andric   for (const MachineOperand &MO : MI.operands()) {
910b57cec5SDimitry Andric     if (MO.isGlobal())
920b57cec5SDimitry Andric       return dyn_cast<const Function>(MO.getGlobal());
930b57cec5SDimitry Andric 
940b57cec5SDimitry Andric     if (MO.isSymbol())
950b57cec5SDimitry Andric       return M.getFunction(MO.getSymbolName());
960b57cec5SDimitry Andric   }
970b57cec5SDimitry Andric 
980b57cec5SDimitry Andric   return nullptr;
990b57cec5SDimitry Andric }
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric bool RegUsageInfoPropagation::runOnMachineFunction(MachineFunction &MF) {
1020b57cec5SDimitry Andric   const Module &M = *MF.getFunction().getParent();
1030b57cec5SDimitry Andric   PhysicalRegisterUsageInfo *PRUI = &getAnalysis<PhysicalRegisterUsageInfo>();
1040b57cec5SDimitry Andric 
1050b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << " ++++++++++++++++++++ " << getPassName()
1060b57cec5SDimitry Andric                     << " ++++++++++++++++++++  \n");
1070b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "MachineFunction : " << MF.getName() << "\n");
1080b57cec5SDimitry Andric 
1090b57cec5SDimitry Andric   const MachineFrameInfo &MFI = MF.getFrameInfo();
1100b57cec5SDimitry Andric   if (!MFI.hasCalls() && !MFI.hasTailCall())
1110b57cec5SDimitry Andric     return false;
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric   bool Changed = false;
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric   for (MachineBasicBlock &MBB : MF) {
1160b57cec5SDimitry Andric     for (MachineInstr &MI : MBB) {
1170b57cec5SDimitry Andric       if (!MI.isCall())
1180b57cec5SDimitry Andric         continue;
1190b57cec5SDimitry Andric       LLVM_DEBUG(
1200b57cec5SDimitry Andric           dbgs()
121*5ffd83dbSDimitry Andric           << "Call Instruction Before Register Usage Info Propagation : \n"
122*5ffd83dbSDimitry Andric           << MI << "\n");
1230b57cec5SDimitry Andric 
1240b57cec5SDimitry Andric       auto UpdateRegMask = [&](const Function &F) {
1250b57cec5SDimitry Andric         const ArrayRef<uint32_t> RegMask = PRUI->getRegUsageInfo(F);
1260b57cec5SDimitry Andric         if (RegMask.empty())
1270b57cec5SDimitry Andric           return;
1280b57cec5SDimitry Andric         setRegMask(MI, RegMask);
1290b57cec5SDimitry Andric         Changed = true;
1300b57cec5SDimitry Andric       };
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric       if (const Function *F = findCalledFunction(M, MI)) {
1338bcb0991SDimitry Andric         if (F->isDefinitionExact()) {
1340b57cec5SDimitry Andric           UpdateRegMask(*F);
1350b57cec5SDimitry Andric         } else {
1368bcb0991SDimitry Andric           LLVM_DEBUG(dbgs() << "Function definition is not exact\n");
1378bcb0991SDimitry Andric         }
1388bcb0991SDimitry Andric       } else {
1390b57cec5SDimitry Andric         LLVM_DEBUG(dbgs() << "Failed to find call target function\n");
1400b57cec5SDimitry Andric       }
1410b57cec5SDimitry Andric 
1420b57cec5SDimitry Andric       LLVM_DEBUG(
143*5ffd83dbSDimitry Andric           dbgs()
144*5ffd83dbSDimitry Andric           << "Call Instruction After Register Usage Info Propagation : \n"
1450b57cec5SDimitry Andric           << MI << '\n');
1460b57cec5SDimitry Andric     }
1470b57cec5SDimitry Andric   }
1480b57cec5SDimitry Andric 
1490b57cec5SDimitry Andric   LLVM_DEBUG(
1500b57cec5SDimitry Andric       dbgs() << " +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
1510b57cec5SDimitry Andric                 "++++++ \n");
1520b57cec5SDimitry Andric   return Changed;
1530b57cec5SDimitry Andric }
1540b57cec5SDimitry Andric 
1550b57cec5SDimitry Andric FunctionPass *llvm::createRegUsageInfoPropPass() {
1560b57cec5SDimitry Andric   return new RegUsageInfoPropagation();
1570b57cec5SDimitry Andric }
158