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