summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/CodeGen')
-rw-r--r--llvm/lib/CodeGen/CMakeLists.txt2
-rw-r--r--llvm/lib/CodeGen/RegUsageInfoCollector.cpp131
-rw-r--r--llvm/lib/CodeGen/RegisterUsageInfo.cpp92
-rw-r--r--llvm/lib/CodeGen/TargetPassConfig.cpp15
4 files changed, 240 insertions, 0 deletions
diff --git a/llvm/lib/CodeGen/CMakeLists.txt b/llvm/lib/CodeGen/CMakeLists.txt
index 34f74e2921e..58f620d511d 100644
--- a/llvm/lib/CodeGen/CMakeLists.txt
+++ b/llvm/lib/CodeGen/CMakeLists.txt
@@ -101,6 +101,8 @@ add_llvm_library(LLVMCodeGen
RegisterPressure.cpp
RegisterScavenging.cpp
RenameIndependentSubregs.cpp
+ RegisterUsageInfo.cpp
+ RegUsageInfoCollector.cpp
SafeStack.cpp
ScheduleDAG.cpp
ScheduleDAGInstrs.cpp
diff --git a/llvm/lib/CodeGen/RegUsageInfoCollector.cpp b/llvm/lib/CodeGen/RegUsageInfoCollector.cpp
new file mode 100644
index 00000000000..aac52000893
--- /dev/null
+++ b/llvm/lib/CodeGen/RegUsageInfoCollector.cpp
@@ -0,0 +1,131 @@
+//===- RegUsageInfoCollector.cpp - Register Usage Informartion Collector --===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// This pass is required to take advantage of the interprocedural register
+/// allocation infrastructure.
+///
+/// This pass is simple MachineFunction pass which collects register usage
+/// details by iterating through each physical registers and checking
+/// MRI::isPhysRegUsed() then creates a RegMask based on this details.
+/// The pass then stores this RegMask in PhysicalRegisterUsageInfo.cpp
+///
+//===----------------------------------------------------------------------===//
+
+#include "llvm/CodeGen/MachineBasicBlock.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/CodeGen/MachineOperand.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/CodeGen/RegisterUsageInfo.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "ip-regalloc"
+
+namespace llvm {
+void initializeRegUsageInfoCollectorPass(PassRegistry &);
+}
+
+namespace {
+class RegUsageInfoCollector : public MachineFunctionPass {
+public:
+ RegUsageInfoCollector() : MachineFunctionPass(ID) {
+ PassRegistry &Registry = *PassRegistry::getPassRegistry();
+ initializeRegUsageInfoCollectorPass(Registry);
+ }
+
+ const char *getPassName() const override {
+ return "Register Usage Information Collector Pass";
+ }
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override;
+
+ bool runOnMachineFunction(MachineFunction &MF) override;
+
+ static char ID;
+
+private:
+ void markRegClobbered(const TargetRegisterInfo *TRI, uint32_t *RegMask,
+ unsigned PReg);
+};
+} // end of anonymous namespace
+
+char RegUsageInfoCollector::ID = 0;
+
+INITIALIZE_PASS_BEGIN(RegUsageInfoCollector, "RegUsageInfoCollector",
+ "Register Usage Information Collector", false, false)
+INITIALIZE_PASS_DEPENDENCY(PhysicalRegisterUsageInfo)
+INITIALIZE_PASS_END(RegUsageInfoCollector, "RegUsageInfoCollector",
+ "Register Usage Information Collector", false, false)
+
+FunctionPass *llvm::createRegUsageInfoCollector() {
+ return new RegUsageInfoCollector();
+}
+
+void RegUsageInfoCollector::markRegClobbered(const TargetRegisterInfo *TRI,
+ uint32_t *RegMask, unsigned PReg) {
+ // If PReg is clobbered then all of its alias are also clobbered.
+ for (MCRegAliasIterator AI(PReg, TRI, true); AI.isValid(); ++AI)
+ RegMask[*AI / 32] &= ~(1u << *AI % 32);
+}
+
+void RegUsageInfoCollector::getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.addRequired<PhysicalRegisterUsageInfo>();
+ AU.setPreservesAll();
+ MachineFunctionPass::getAnalysisUsage(AU);
+}
+
+bool RegUsageInfoCollector::runOnMachineFunction(MachineFunction &MF) {
+ MachineRegisterInfo *MRI = &MF.getRegInfo();
+ TargetRegisterInfo *TRI =
+ (TargetRegisterInfo *)MF.getSubtarget().getRegisterInfo();
+ const TargetMachine &TM = MF.getTarget();
+
+ DEBUG(dbgs() << " -------------------- " << getPassName()
+ << " -------------------- \n");
+ DEBUG(dbgs() << "Function Name : " << MF.getName() << "\n");
+
+ std::vector<uint32_t> RegMask;
+
+ // Compute the size of the bit vector to represent all the registers.
+ // The bit vector is broken into 32-bit chunks, thus takes the ceil of
+ // the number of registers divided by 32 for the size.
+ unsigned regMaskSize = (TRI->getNumRegs() + 31) / 32;
+ RegMask.resize(regMaskSize, 0xFFFFFFFF);
+
+ PhysicalRegisterUsageInfo *PRUI = &getAnalysis<PhysicalRegisterUsageInfo>();
+
+ PRUI->setTargetMachine(&TM);
+
+ DEBUG(dbgs() << "Clobbered Registers: ");
+ for (unsigned PReg = 1, PRegE = TRI->getNumRegs(); PReg < PRegE; ++PReg) {
+ if (!MRI->reg_nodbg_empty(PReg) && MRI->isPhysRegUsed(PReg))
+ markRegClobbered(TRI, &RegMask[0], PReg);
+ }
+
+ const uint32_t *CallPreservedMask =
+ TRI->getCallPreservedMask(MF, MF.getFunction()->getCallingConv());
+ // Set callee saved register as preserved.
+ for (unsigned index = 0; index < regMaskSize; index++) {
+ RegMask[index] = RegMask[index] | CallPreservedMask[index];
+ }
+ for (unsigned PReg = 1, PRegE = TRI->getNumRegs(); PReg < PRegE; ++PReg) {
+ if (MachineOperand::clobbersPhysReg(&(RegMask[0]), PReg))
+ DEBUG(dbgs() << TRI->getName(PReg) << " ");
+ }
+
+ DEBUG(dbgs() << " \n----------------------------------------\n");
+
+ PRUI->storeUpdateRegUsageInfo(MF.getFunction(), std::move(RegMask));
+
+ return false;
+}
diff --git a/llvm/lib/CodeGen/RegisterUsageInfo.cpp b/llvm/lib/CodeGen/RegisterUsageInfo.cpp
new file mode 100644
index 00000000000..9eeb3b9d8cc
--- /dev/null
+++ b/llvm/lib/CodeGen/RegisterUsageInfo.cpp
@@ -0,0 +1,92 @@
+//===- RegisterUsageInfo.cpp - Register Usage Informartion Storage --------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// This pass is required to take advantage of the interprocedural register
+/// allocation infrastructure.
+///
+//===----------------------------------------------------------------------===//
+
+#include "llvm/CodeGen/RegisterUsageInfo.h"
+#include "llvm/CodeGen/MachineOperand.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "ip-regalloc"
+
+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 Informartion Stroage", false, true)
+
+char PhysicalRegisterUsageInfo::ID = 0;
+
+void PhysicalRegisterUsageInfo::anchor() {}
+
+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, std::vector<uint32_t> RegMask) {
+ assert(FP != nullptr && "Function * can't be nullptr.");
+ RegMasks[FP] = std::move(RegMask);
+}
+
+const std::vector<uint32_t> *
+PhysicalRegisterUsageInfo::getRegUsageInfo(const Function *FP) {
+ if (RegMasks.find(FP) != RegMasks.end())
+ return &(RegMasks.find(FP)->second);
+ return nullptr;
+}
+
+void PhysicalRegisterUsageInfo::print(raw_ostream &OS, const Module *M) const {
+ const TargetRegisterInfo *TRI;
+
+ typedef std::pair<const Function *, std::vector<uint32_t>> FuncPtrRegMaskPair;
+
+ 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.
+ std::sort(
+ FPRMPairVector.begin(), FPRMPairVector.end(),
+ [](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: ";
+ 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 << TRI->getName(PReg) << " ";
+ }
+ OS << "\n";
+ }
+}
diff --git a/llvm/lib/CodeGen/TargetPassConfig.cpp b/llvm/lib/CodeGen/TargetPassConfig.cpp
index e7e41d570f6..3e7261a895f 100644
--- a/llvm/lib/CodeGen/TargetPassConfig.cpp
+++ b/llvm/lib/CodeGen/TargetPassConfig.cpp
@@ -16,11 +16,13 @@
#include "llvm/Analysis/BasicAliasAnalysis.h"
#include "llvm/Analysis/CFLAliasAnalysis.h"
+#include "llvm/Analysis/CallGraphSCCPass.h"
#include "llvm/Analysis/Passes.h"
#include "llvm/Analysis/ScopedNoAliasAA.h"
#include "llvm/Analysis/TypeBasedAliasAnalysis.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/RegAllocRegistry.h"
+#include "llvm/CodeGen/RegisterUsageInfo.h"
#include "llvm/IR/IRPrintingPasses.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Verifier.h"
@@ -112,6 +114,10 @@ static cl::opt<bool> UseCFLAA("use-cfl-aa-in-codegen",
cl::init(false), cl::Hidden,
cl::desc("Enable the new, experimental CFL alias analysis in CodeGen"));
+cl::opt<bool> UseIPRA("enable-ipra", cl::init(false), cl::Hidden,
+ cl::desc("Enable interprocedural register allocation "
+ "to reduce load/store at procedure calls."));
+
/// Allow standard passes to be disabled by command line options. This supports
/// simple binary flags that either suppress the pass or do nothing.
/// i.e. -disable-mypass=false has no effect.
@@ -492,6 +498,10 @@ void TargetPassConfig::addCodeGenPrepare() {
void TargetPassConfig::addISelPrepare() {
addPreISel();
+ // Force codegen to run according to the callgraph.
+ if (UseIPRA)
+ addPass(new DummyCGSCCPass);
+
// Add both the safe stack and the stack protection passes: each of them will
// only protect functions that have corresponding attributes.
addPass(createSafeStackPass(TM));
@@ -613,6 +623,11 @@ void TargetPassConfig::addMachinePasses() {
addPreEmitPass();
+ if (UseIPRA)
+ // Collect register usage information and produce a register mask of
+ // clobbered registers, to be used to optimize call sites.
+ addPass(createRegUsageInfoCollector());
+
addPass(&FuncletLayoutID, false);
addPass(&StackMapLivenessID, false);
OpenPOWER on IntegriCloud