| //===- RegisterUsageInfo.cpp - Register Usage Information Storage ---------===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| /// | |
| /// This pass is required to take advantage of the interprocedural register | |
| /// allocation infrastructure. | |
| /// | |
| //===----------------------------------------------------------------------===// | |
| #include "llvm/CodeGen/RegisterUsageInfo.h" | |
| #include "llvm/ADT/SmallVector.h" | |
| #include "llvm/CodeGen/MachineOperand.h" | |
| #include "llvm/CodeGen/TargetRegisterInfo.h" | |
| #include "llvm/CodeGen/TargetSubtargetInfo.h" | |
| #include "llvm/IR/Function.h" | |
| #include "llvm/IR/Module.h" | |
| #include "llvm/Pass.h" | |
| #include "llvm/Support/CommandLine.h" | |
| #include "llvm/Support/raw_ostream.h" | |
| #include "llvm/Target/TargetMachine.h" | |
| #include <algorithm> | |
| #include <cassert> | |
| #include <cstdint> | |
| #include <utility> | |
| #include <vector> | |
| using namespace llvm; | |
| static cl::opt<bool> DumpRegUsage( | |
| "print-regusage", cl::init(false), cl::Hidden, | |
| cl::desc("print register usage details collected for analysis.")); | |
| INITIALIZE_PASS(PhysicalRegisterUsageInfo, "reg-usage-info", | |
| "Register Usage Information Storage", false, true) | |
| char PhysicalRegisterUsageInfo::ID = 0; | |
| void PhysicalRegisterUsageInfo::setTargetMachine(const LLVMTargetMachine &TM) { | |
| this->TM = &TM; | |
| } | |
| bool PhysicalRegisterUsageInfo::doInitialization(Module &M) { | |
| RegMasks.grow(M.size()); | |
| return false; | |
| } | |
| bool PhysicalRegisterUsageInfo::doFinalization(Module &M) { | |
| if (DumpRegUsage) | |
| print(errs()); | |
| RegMasks.shrink_and_clear(); | |
| return false; | |
| } | |
| void PhysicalRegisterUsageInfo::storeUpdateRegUsageInfo( | |
| const Function &FP, ArrayRef<uint32_t> RegMask) { | |
| RegMasks[&FP] = RegMask; | |
| } | |
| ArrayRef<uint32_t> | |
| PhysicalRegisterUsageInfo::getRegUsageInfo(const Function &FP) { | |
| auto It = RegMasks.find(&FP); | |
| if (It != RegMasks.end()) | |
| return makeArrayRef<uint32_t>(It->second); | |
| return ArrayRef<uint32_t>(); | |
| } | |
| void PhysicalRegisterUsageInfo::print(raw_ostream &OS, const Module *M) const { | |
| using FuncPtrRegMaskPair = std::pair<const Function *, std::vector<uint32_t>>; | |
| SmallVector<const FuncPtrRegMaskPair *, 64> FPRMPairVector; | |
| // Create a vector of pointer to RegMasks entries | |
| for (const auto &RegMask : RegMasks) | |
| FPRMPairVector.push_back(&RegMask); | |
| // sort the vector to print analysis in alphabatic order of function name. | |
| llvm::sort( | |
| FPRMPairVector, | |
| [](const FuncPtrRegMaskPair *A, const FuncPtrRegMaskPair *B) -> bool { | |
| return A->first->getName() < B->first->getName(); | |
| }); | |
| for (const FuncPtrRegMaskPair *FPRMPair : FPRMPairVector) { | |
| OS << FPRMPair->first->getName() << " " | |
| << "Clobbered Registers: "; | |
| const TargetRegisterInfo *TRI | |
| = TM->getSubtarget<TargetSubtargetInfo>(*(FPRMPair->first)) | |
| .getRegisterInfo(); | |
| for (unsigned PReg = 1, PRegE = TRI->getNumRegs(); PReg < PRegE; ++PReg) { | |
| if (MachineOperand::clobbersPhysReg(&(FPRMPair->second[0]), PReg)) | |
| OS << printReg(PReg, TRI) << " "; | |
| } | |
| OS << "\n"; | |
| } | |
| } |