1*0b57cec5SDimitry Andric //===- RegisterUsageInfo.cpp - Register Usage Information Storage ---------===//
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 //===----------------------------------------------------------------------===//
13*0b57cec5SDimitry Andric 
14*0b57cec5SDimitry Andric #include "llvm/CodeGen/RegisterUsageInfo.h"
15*0b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
16*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineOperand.h"
17*0b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
18*0b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
19*0b57cec5SDimitry Andric #include "llvm/IR/Function.h"
20*0b57cec5SDimitry Andric #include "llvm/IR/Module.h"
21*0b57cec5SDimitry Andric #include "llvm/Pass.h"
22*0b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
23*0b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
24*0b57cec5SDimitry Andric #include "llvm/Target/TargetMachine.h"
25*0b57cec5SDimitry Andric #include <cstdint>
26*0b57cec5SDimitry Andric #include <utility>
27*0b57cec5SDimitry Andric #include <vector>
28*0b57cec5SDimitry Andric 
29*0b57cec5SDimitry Andric using namespace llvm;
30*0b57cec5SDimitry Andric 
31*0b57cec5SDimitry Andric static cl::opt<bool> DumpRegUsage(
32*0b57cec5SDimitry Andric     "print-regusage", cl::init(false), cl::Hidden,
33*0b57cec5SDimitry Andric     cl::desc("print register usage details collected for analysis."));
34*0b57cec5SDimitry Andric 
35*0b57cec5SDimitry Andric INITIALIZE_PASS(PhysicalRegisterUsageInfo, "reg-usage-info",
36*0b57cec5SDimitry Andric                 "Register Usage Information Storage", false, true)
37*0b57cec5SDimitry Andric 
38*0b57cec5SDimitry Andric char PhysicalRegisterUsageInfo::ID = 0;
39*0b57cec5SDimitry Andric 
setTargetMachine(const LLVMTargetMachine & TM)40*0b57cec5SDimitry Andric void PhysicalRegisterUsageInfo::setTargetMachine(const LLVMTargetMachine &TM) {
41*0b57cec5SDimitry Andric   this->TM = &TM;
42*0b57cec5SDimitry Andric }
43*0b57cec5SDimitry Andric 
doInitialization(Module & M)44*0b57cec5SDimitry Andric bool PhysicalRegisterUsageInfo::doInitialization(Module &M) {
45*0b57cec5SDimitry Andric   RegMasks.grow(M.size());
46*0b57cec5SDimitry Andric   return false;
47*0b57cec5SDimitry Andric }
48*0b57cec5SDimitry Andric 
doFinalization(Module & M)49*0b57cec5SDimitry Andric bool PhysicalRegisterUsageInfo::doFinalization(Module &M) {
50*0b57cec5SDimitry Andric   if (DumpRegUsage)
51*0b57cec5SDimitry Andric     print(errs());
52*0b57cec5SDimitry Andric 
53*0b57cec5SDimitry Andric   RegMasks.shrink_and_clear();
54*0b57cec5SDimitry Andric   return false;
55*0b57cec5SDimitry Andric }
56*0b57cec5SDimitry Andric 
storeUpdateRegUsageInfo(const Function & FP,ArrayRef<uint32_t> RegMask)57*0b57cec5SDimitry Andric void PhysicalRegisterUsageInfo::storeUpdateRegUsageInfo(
58*0b57cec5SDimitry Andric     const Function &FP, ArrayRef<uint32_t> RegMask) {
59*0b57cec5SDimitry Andric   RegMasks[&FP] = RegMask;
60*0b57cec5SDimitry Andric }
61*0b57cec5SDimitry Andric 
62*0b57cec5SDimitry Andric ArrayRef<uint32_t>
getRegUsageInfo(const Function & FP)63*0b57cec5SDimitry Andric PhysicalRegisterUsageInfo::getRegUsageInfo(const Function &FP) {
64*0b57cec5SDimitry Andric   auto It = RegMasks.find(&FP);
65*0b57cec5SDimitry Andric   if (It != RegMasks.end())
66*0b57cec5SDimitry Andric     return ArrayRef<uint32_t>(It->second);
67*0b57cec5SDimitry Andric   return ArrayRef<uint32_t>();
68*0b57cec5SDimitry Andric }
69*0b57cec5SDimitry Andric 
print(raw_ostream & OS,const Module * M) const70*0b57cec5SDimitry Andric void PhysicalRegisterUsageInfo::print(raw_ostream &OS, const Module *M) const {
71*0b57cec5SDimitry Andric   using FuncPtrRegMaskPair = std::pair<const Function *, std::vector<uint32_t>>;
72*0b57cec5SDimitry Andric 
73*0b57cec5SDimitry Andric   SmallVector<const FuncPtrRegMaskPair *, 64> FPRMPairVector;
74*0b57cec5SDimitry Andric 
75*0b57cec5SDimitry Andric   // Create a vector of pointer to RegMasks entries
76*0b57cec5SDimitry Andric   for (const auto &RegMask : RegMasks)
77*0b57cec5SDimitry Andric     FPRMPairVector.push_back(&RegMask);
78*0b57cec5SDimitry Andric 
79*0b57cec5SDimitry Andric   // sort the vector to print analysis in alphabatic order of function name.
80*0b57cec5SDimitry Andric   llvm::sort(
81*0b57cec5SDimitry Andric       FPRMPairVector,
82*0b57cec5SDimitry Andric       [](const FuncPtrRegMaskPair *A, const FuncPtrRegMaskPair *B) -> bool {
83*0b57cec5SDimitry Andric         return A->first->getName() < B->first->getName();
84*0b57cec5SDimitry Andric       });
85*0b57cec5SDimitry Andric 
86*0b57cec5SDimitry Andric   for (const FuncPtrRegMaskPair *FPRMPair : FPRMPairVector) {
87*0b57cec5SDimitry Andric     OS << FPRMPair->first->getName() << " "
88*0b57cec5SDimitry Andric        << "Clobbered Registers: ";
89*0b57cec5SDimitry Andric     const TargetRegisterInfo *TRI
90*0b57cec5SDimitry Andric         = TM->getSubtarget<TargetSubtargetInfo>(*(FPRMPair->first))
91*0b57cec5SDimitry Andric           .getRegisterInfo();
92*0b57cec5SDimitry Andric 
93*0b57cec5SDimitry Andric     for (unsigned PReg = 1, PRegE = TRI->getNumRegs(); PReg < PRegE; ++PReg) {
94*0b57cec5SDimitry Andric       if (MachineOperand::clobbersPhysReg(&(FPRMPair->second[0]), PReg))
95*0b57cec5SDimitry Andric         OS << printReg(PReg, TRI) << " ";
96*0b57cec5SDimitry Andric     }
97*0b57cec5SDimitry Andric     OS << "\n";
98*0b57cec5SDimitry Andric   }
99*0b57cec5SDimitry Andric }
100*0b57cec5SDimitry Andric