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