13ca95b02SDimitry Andric //=--- RegUsageInfoPropagate.cpp - Register Usage Informartion Propagation --=//
23ca95b02SDimitry Andric //
33ca95b02SDimitry Andric // The LLVM Compiler Infrastructure
43ca95b02SDimitry Andric //
53ca95b02SDimitry Andric // This file is distributed under the University of Illinois Open Source
63ca95b02SDimitry Andric // License. See LICENSE.TXT for details.
73ca95b02SDimitry Andric //
83ca95b02SDimitry Andric //===----------------------------------------------------------------------===//
93ca95b02SDimitry Andric ///
103ca95b02SDimitry Andric /// This pass is required to take advantage of the interprocedural register
113ca95b02SDimitry Andric /// allocation infrastructure.
123ca95b02SDimitry Andric ///
133ca95b02SDimitry Andric /// This pass iterates through MachineInstrs in a given MachineFunction and at
143ca95b02SDimitry Andric /// each callsite queries RegisterUsageInfo for RegMask (calculated based on
153ca95b02SDimitry Andric /// actual register allocation) of the callee function, if the RegMask detail
163ca95b02SDimitry Andric /// is available then this pass will update the RegMask of the call instruction.
173ca95b02SDimitry Andric /// This updated RegMask will be used by the register allocator while allocating
183ca95b02SDimitry Andric /// the current MachineFunction.
193ca95b02SDimitry Andric ///
203ca95b02SDimitry Andric //===----------------------------------------------------------------------===//
213ca95b02SDimitry Andric
223ca95b02SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
233ca95b02SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
242cab237bSDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
253ca95b02SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
263ca95b02SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
273ca95b02SDimitry Andric #include "llvm/CodeGen/Passes.h"
283ca95b02SDimitry Andric #include "llvm/CodeGen/RegisterUsageInfo.h"
293ca95b02SDimitry Andric #include "llvm/IR/Module.h"
303ca95b02SDimitry Andric #include "llvm/PassAnalysisSupport.h"
313ca95b02SDimitry Andric #include "llvm/Support/Debug.h"
323ca95b02SDimitry Andric #include "llvm/Support/raw_ostream.h"
333ca95b02SDimitry Andric #include "llvm/Target/TargetMachine.h"
343ca95b02SDimitry Andric #include <map>
353ca95b02SDimitry Andric #include <string>
363ca95b02SDimitry Andric
373ca95b02SDimitry Andric using namespace llvm;
383ca95b02SDimitry Andric
393ca95b02SDimitry Andric #define DEBUG_TYPE "ip-regalloc"
403ca95b02SDimitry Andric
413ca95b02SDimitry Andric #define RUIP_NAME "Register Usage Information Propagation"
423ca95b02SDimitry Andric
433ca95b02SDimitry Andric namespace {
443ca95b02SDimitry Andric
45*4ba319b5SDimitry Andric class RegUsageInfoPropagation : public MachineFunctionPass {
463ca95b02SDimitry Andric public:
RegUsageInfoPropagation()47*4ba319b5SDimitry Andric RegUsageInfoPropagation() : MachineFunctionPass(ID) {
483ca95b02SDimitry Andric PassRegistry &Registry = *PassRegistry::getPassRegistry();
49*4ba319b5SDimitry Andric initializeRegUsageInfoPropagationPass(Registry);
503ca95b02SDimitry Andric }
513ca95b02SDimitry Andric
getPassName() const52d88c1a5aSDimitry Andric StringRef getPassName() const override { return RUIP_NAME; }
533ca95b02SDimitry Andric
543ca95b02SDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override;
553ca95b02SDimitry Andric
getAnalysisUsage(AnalysisUsage & AU) const56*4ba319b5SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override {
573ca95b02SDimitry Andric AU.addRequired<PhysicalRegisterUsageInfo>();
583ca95b02SDimitry Andric AU.setPreservesAll();
593ca95b02SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU);
603ca95b02SDimitry Andric }
613ca95b02SDimitry Andric
62*4ba319b5SDimitry Andric static char ID;
63*4ba319b5SDimitry Andric
64*4ba319b5SDimitry Andric private:
setRegMask(MachineInstr & MI,ArrayRef<uint32_t> RegMask)65*4ba319b5SDimitry Andric static void setRegMask(MachineInstr &MI, ArrayRef<uint32_t> RegMask) {
66*4ba319b5SDimitry Andric assert(RegMask.size() ==
67*4ba319b5SDimitry Andric MachineOperand::getRegMaskSize(MI.getParent()->getParent()
68*4ba319b5SDimitry Andric ->getRegInfo().getTargetRegisterInfo()
69*4ba319b5SDimitry Andric ->getNumRegs())
70*4ba319b5SDimitry Andric && "expected register mask size");
712cab237bSDimitry Andric for (MachineOperand &MO : MI.operands()) {
72*4ba319b5SDimitry Andric if (MO.isRegMask())
73*4ba319b5SDimitry Andric MO.setRegMask(RegMask.data());
74*4ba319b5SDimitry Andric }
75*4ba319b5SDimitry Andric }
76*4ba319b5SDimitry Andric };
77*4ba319b5SDimitry Andric
78*4ba319b5SDimitry Andric } // end of anonymous namespace
79*4ba319b5SDimitry Andric
80*4ba319b5SDimitry Andric INITIALIZE_PASS_BEGIN(RegUsageInfoPropagation, "reg-usage-propagation",
81*4ba319b5SDimitry Andric RUIP_NAME, false, false)
82*4ba319b5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(PhysicalRegisterUsageInfo)
83*4ba319b5SDimitry Andric INITIALIZE_PASS_END(RegUsageInfoPropagation, "reg-usage-propagation",
84*4ba319b5SDimitry Andric RUIP_NAME, false, false)
85*4ba319b5SDimitry Andric
86*4ba319b5SDimitry Andric char RegUsageInfoPropagation::ID = 0;
87*4ba319b5SDimitry Andric
88*4ba319b5SDimitry Andric // Assumes call instructions have a single reference to a function.
findCalledFunction(const Module & M,const MachineInstr & MI)89*4ba319b5SDimitry Andric static const Function *findCalledFunction(const Module &M,
90*4ba319b5SDimitry Andric const MachineInstr &MI) {
91*4ba319b5SDimitry Andric for (const MachineOperand &MO : MI.operands()) {
922cab237bSDimitry Andric if (MO.isGlobal())
93*4ba319b5SDimitry Andric return dyn_cast<const Function>(MO.getGlobal());
942cab237bSDimitry Andric
952cab237bSDimitry Andric if (MO.isSymbol())
962cab237bSDimitry Andric return M.getFunction(MO.getSymbolName());
972cab237bSDimitry Andric }
982cab237bSDimitry Andric
992cab237bSDimitry Andric return nullptr;
1002cab237bSDimitry Andric }
1012cab237bSDimitry Andric
runOnMachineFunction(MachineFunction & MF)102*4ba319b5SDimitry Andric bool RegUsageInfoPropagation::runOnMachineFunction(MachineFunction &MF) {
103*4ba319b5SDimitry Andric const Module &M = *MF.getFunction().getParent();
1043ca95b02SDimitry Andric PhysicalRegisterUsageInfo *PRUI = &getAnalysis<PhysicalRegisterUsageInfo>();
1053ca95b02SDimitry Andric
106*4ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << " ++++++++++++++++++++ " << getPassName()
1073ca95b02SDimitry Andric << " ++++++++++++++++++++ \n");
108*4ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "MachineFunction : " << MF.getName() << "\n");
1093ca95b02SDimitry Andric
1102cab237bSDimitry Andric const MachineFrameInfo &MFI = MF.getFrameInfo();
1112cab237bSDimitry Andric if (!MFI.hasCalls() && !MFI.hasTailCall())
1122cab237bSDimitry Andric return false;
1132cab237bSDimitry Andric
1143ca95b02SDimitry Andric bool Changed = false;
1153ca95b02SDimitry Andric
1163ca95b02SDimitry Andric for (MachineBasicBlock &MBB : MF) {
1173ca95b02SDimitry Andric for (MachineInstr &MI : MBB) {
1183ca95b02SDimitry Andric if (!MI.isCall())
1193ca95b02SDimitry Andric continue;
120*4ba319b5SDimitry Andric LLVM_DEBUG(
121*4ba319b5SDimitry Andric dbgs()
1223ca95b02SDimitry Andric << "Call Instruction Before Register Usage Info Propagation : \n");
123*4ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << MI << "\n");
1243ca95b02SDimitry Andric
125*4ba319b5SDimitry Andric auto UpdateRegMask = [&](const Function &F) {
126*4ba319b5SDimitry Andric const ArrayRef<uint32_t> RegMask = PRUI->getRegUsageInfo(F);
127*4ba319b5SDimitry Andric if (RegMask.empty())
1283ca95b02SDimitry Andric return;
129*4ba319b5SDimitry Andric setRegMask(MI, RegMask);
1303ca95b02SDimitry Andric Changed = true;
1313ca95b02SDimitry Andric };
1323ca95b02SDimitry Andric
133*4ba319b5SDimitry Andric if (const Function *F = findCalledFunction(M, MI)) {
134*4ba319b5SDimitry Andric UpdateRegMask(*F);
1352cab237bSDimitry Andric } else {
136*4ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "Failed to find call target function\n");
1372cab237bSDimitry Andric }
1383ca95b02SDimitry Andric
139*4ba319b5SDimitry Andric LLVM_DEBUG(
140*4ba319b5SDimitry Andric dbgs() << "Call Instruction After Register Usage Info Propagation : "
1412cab237bSDimitry Andric << MI << '\n');
1423ca95b02SDimitry Andric }
1433ca95b02SDimitry Andric }
1443ca95b02SDimitry Andric
145*4ba319b5SDimitry Andric LLVM_DEBUG(
146*4ba319b5SDimitry Andric dbgs() << " +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
1473ca95b02SDimitry Andric "++++++ \n");
1483ca95b02SDimitry Andric return Changed;
1493ca95b02SDimitry Andric }
150*4ba319b5SDimitry Andric
createRegUsageInfoPropPass()151*4ba319b5SDimitry Andric FunctionPass *llvm::createRegUsageInfoPropPass() {
152*4ba319b5SDimitry Andric return new RegUsageInfoPropagation();
153*4ba319b5SDimitry Andric }
154