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