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