108bbd35aSDimitry Andric //===- RegisterUsageInfo.cpp - Register Usage Information Storage ---------===//
201095a5dSDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
601095a5dSDimitry Andric //
701095a5dSDimitry Andric //===----------------------------------------------------------------------===//
801095a5dSDimitry Andric ///
901095a5dSDimitry Andric /// This pass is required to take advantage of the interprocedural register
1001095a5dSDimitry Andric /// allocation infrastructure.
1101095a5dSDimitry Andric ///
1201095a5dSDimitry Andric //===----------------------------------------------------------------------===//
1301095a5dSDimitry Andric
1401095a5dSDimitry Andric #include "llvm/CodeGen/RegisterUsageInfo.h"
15044eb2f6SDimitry Andric #include "llvm/ADT/SmallVector.h"
1601095a5dSDimitry Andric #include "llvm/CodeGen/MachineOperand.h"
17044eb2f6SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
18044eb2f6SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
197ab83427SDimitry Andric #include "llvm/IR/Function.h"
2001095a5dSDimitry Andric #include "llvm/IR/Module.h"
217ab83427SDimitry Andric #include "llvm/Pass.h"
227ab83427SDimitry Andric #include "llvm/Support/CommandLine.h"
2301095a5dSDimitry Andric #include "llvm/Support/raw_ostream.h"
247ab83427SDimitry Andric #include "llvm/Target/TargetMachine.h"
257ab83427SDimitry Andric #include <cstdint>
267ab83427SDimitry Andric #include <utility>
277ab83427SDimitry Andric #include <vector>
2801095a5dSDimitry Andric
2901095a5dSDimitry Andric using namespace llvm;
3001095a5dSDimitry Andric
31b915e9e0SDimitry Andric static cl::opt<bool> DumpRegUsage(
3201095a5dSDimitry Andric "print-regusage", cl::init(false), cl::Hidden,
3301095a5dSDimitry Andric cl::desc("print register usage details collected for analysis."));
3401095a5dSDimitry Andric
3501095a5dSDimitry Andric INITIALIZE_PASS(PhysicalRegisterUsageInfo, "reg-usage-info",
3608bbd35aSDimitry Andric "Register Usage Information Storage", false, true)
3701095a5dSDimitry Andric
3801095a5dSDimitry Andric char PhysicalRegisterUsageInfo::ID = 0;
3901095a5dSDimitry Andric
setTargetMachine(const LLVMTargetMachine & TM)40d8e91e46SDimitry Andric void PhysicalRegisterUsageInfo::setTargetMachine(const LLVMTargetMachine &TM) {
41eb11fae6SDimitry Andric this->TM = &TM;
42eb11fae6SDimitry Andric }
4301095a5dSDimitry Andric
doInitialization(Module & M)4401095a5dSDimitry Andric bool PhysicalRegisterUsageInfo::doInitialization(Module &M) {
4501095a5dSDimitry Andric RegMasks.grow(M.size());
4601095a5dSDimitry Andric return false;
4701095a5dSDimitry Andric }
4801095a5dSDimitry Andric
doFinalization(Module & M)4901095a5dSDimitry Andric bool PhysicalRegisterUsageInfo::doFinalization(Module &M) {
5001095a5dSDimitry Andric if (DumpRegUsage)
5101095a5dSDimitry Andric print(errs());
5201095a5dSDimitry Andric
5301095a5dSDimitry Andric RegMasks.shrink_and_clear();
5401095a5dSDimitry Andric return false;
5501095a5dSDimitry Andric }
5601095a5dSDimitry Andric
storeUpdateRegUsageInfo(const Function & FP,ArrayRef<uint32_t> RegMask)5701095a5dSDimitry Andric void PhysicalRegisterUsageInfo::storeUpdateRegUsageInfo(
58eb11fae6SDimitry Andric const Function &FP, ArrayRef<uint32_t> RegMask) {
59eb11fae6SDimitry Andric RegMasks[&FP] = RegMask;
6001095a5dSDimitry Andric }
6101095a5dSDimitry Andric
62eb11fae6SDimitry Andric ArrayRef<uint32_t>
getRegUsageInfo(const Function & FP)63eb11fae6SDimitry Andric PhysicalRegisterUsageInfo::getRegUsageInfo(const Function &FP) {
64eb11fae6SDimitry Andric auto It = RegMasks.find(&FP);
6501095a5dSDimitry Andric if (It != RegMasks.end())
66e3b55780SDimitry Andric return ArrayRef<uint32_t>(It->second);
67eb11fae6SDimitry Andric return ArrayRef<uint32_t>();
6801095a5dSDimitry Andric }
6901095a5dSDimitry Andric
print(raw_ostream & OS,const Module * M) const7001095a5dSDimitry Andric void PhysicalRegisterUsageInfo::print(raw_ostream &OS, const Module *M) const {
717ab83427SDimitry Andric using FuncPtrRegMaskPair = std::pair<const Function *, std::vector<uint32_t>>;
7201095a5dSDimitry Andric
7301095a5dSDimitry Andric SmallVector<const FuncPtrRegMaskPair *, 64> FPRMPairVector;
7401095a5dSDimitry Andric
7501095a5dSDimitry Andric // Create a vector of pointer to RegMasks entries
7601095a5dSDimitry Andric for (const auto &RegMask : RegMasks)
7701095a5dSDimitry Andric FPRMPairVector.push_back(&RegMask);
7801095a5dSDimitry Andric
7901095a5dSDimitry Andric // sort the vector to print analysis in alphabatic order of function name.
80eb11fae6SDimitry Andric llvm::sort(
81d8e91e46SDimitry Andric FPRMPairVector,
8201095a5dSDimitry Andric [](const FuncPtrRegMaskPair *A, const FuncPtrRegMaskPair *B) -> bool {
8301095a5dSDimitry Andric return A->first->getName() < B->first->getName();
8401095a5dSDimitry Andric });
8501095a5dSDimitry Andric
8601095a5dSDimitry Andric for (const FuncPtrRegMaskPair *FPRMPair : FPRMPairVector) {
8701095a5dSDimitry Andric OS << FPRMPair->first->getName() << " "
8801095a5dSDimitry Andric << "Clobbered Registers: ";
89eb11fae6SDimitry Andric const TargetRegisterInfo *TRI
90eb11fae6SDimitry Andric = TM->getSubtarget<TargetSubtargetInfo>(*(FPRMPair->first))
9101095a5dSDimitry Andric .getRegisterInfo();
9201095a5dSDimitry Andric
9301095a5dSDimitry Andric for (unsigned PReg = 1, PRegE = TRI->getNumRegs(); PReg < PRegE; ++PReg) {
9401095a5dSDimitry Andric if (MachineOperand::clobbersPhysReg(&(FPRMPair->second[0]), PReg))
95044eb2f6SDimitry Andric OS << printReg(PReg, TRI) << " ";
9601095a5dSDimitry Andric }
9701095a5dSDimitry Andric OS << "\n";
9801095a5dSDimitry Andric }
9901095a5dSDimitry Andric }
100