Index: include/llvm/Analysis/CallGraphSCCPass.h =================================================================== --- include/llvm/Analysis/CallGraphSCCPass.h +++ include/llvm/Analysis/CallGraphSCCPass.h @@ -23,6 +23,7 @@ #include "llvm/Analysis/CallGraph.h" #include "llvm/Pass.h" +#include "llvm/PassSupport.h" namespace llvm { @@ -111,6 +112,20 @@ const CallGraph &getCallGraph() { return CG; } }; -} // End llvm namespace +class DummyCGSCCPass : public CallGraphSCCPass { +public: + static char ID; + DummyCGSCCPass() : CallGraphSCCPass(ID){ + PassRegistry &Registry = *PassRegistry::getPassRegistry(); + initializeDummyCGSCCPassPass(Registry); + }; + bool runOnSCC(CallGraphSCC &SCC) override { return false; } + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.setPreservesAll(); + } +}; +void initializeDummyCGSCCPassPass(PassRegistry &); +} // End llvm namespace + #endif Index: include/llvm/CodeGen/MachineOperand.h =================================================================== --- include/llvm/CodeGen/MachineOperand.h +++ include/llvm/CodeGen/MachineOperand.h @@ -534,6 +534,17 @@ Contents.MBB = MBB; } + /// setRegMask - Sets value of register mask operand referencing Mask. The + /// operand does not take ownership of the memory referenced by Mask, it must + /// remain valid for the lifetime of the operand. See CreateRegMask(). + /// + /// + /// Any physreg with a 0 bit in the mask is clobbered by the instruction. + void setRegMask(const uint32_t *RegMaskPtr) { + assert(isRegMask() && "Wrong MachineOperand mutator"); + Contents.RegMask = RegMaskPtr; + } + //===--------------------------------------------------------------------===// // Other methods. //===--------------------------------------------------------------------===// Index: include/llvm/CodeGen/Passes.h =================================================================== --- include/llvm/CodeGen/Passes.h +++ include/llvm/CodeGen/Passes.h @@ -361,6 +361,10 @@ /// independently of other lanes and splits them into separate virtual /// registers. extern char &RenameIndependentSubregsID; + + /// This pass is executed POST-RA to collect which physical registers are + /// used by given machine function. + FunctionPass *createRegUsageInfoCollector(); } // End llvm namespace /// Target machine pass initializer for passes with dependencies. Use with Index: include/llvm/CodeGen/RegisterUsageInfo.h =================================================================== --- /dev/null +++ include/llvm/CodeGen/RegisterUsageInfo.h @@ -0,0 +1,67 @@ +//==- RegisterUsageInfo.h - Register Usage Informartion Storage -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// This pass is required to take advantage of +/// the interprocedural-register-allocation infrastructure. +/// +/// This pass is simple immutable pass which keeps DenseMap of +/// GlobalVariable * for Function to RegMask (calculated based on actual +/// register allocation) and provides simple API to query this information. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_PHYSICALREGISTERUSAGEINFO_H +#define LLVM_CODEGEN_PHYSICALREGISTERUSAGEINFO_H + +#include "llvm/Pass.h" +#include "llvm/IR/Module.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/IR/GlobalVariable.h" + +namespace llvm { + +class PhysicalRegisterUsageInfo : public ImmutablePass { + virtual void anchor(); + +public: + static char ID; + + PhysicalRegisterUsageInfo() : ImmutablePass(ID) { + PassRegistry &Registry = *PassRegistry::getPassRegistry(); + initializePhysicalRegisterUsageInfoPass(Registry); + } + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.setPreservesAll(); + } + + bool doInitialization(Module &M) override { + RegMasks.grow(M.size()); + return false; + } + + bool doFinalization(Module &M) override { + RegMasks.shrink_and_clear(); + return false; + } + + void storeUpdateRegUsageInfo(const GlobalVariable* MFGlobalVar, + std::vector RegMasks); + + const std::vector *getRegUsageInfo(const GlobalVariable* MFGlobalVar); + +private: + /// A Dense map from GlobalVariable * for Function to RegMask. + /// In RegMask 0 means register used (clobbered) by function. + /// and 1 means content of register will be preserved around function call. + DenseMap> RegMasks; +}; +} + +#endif Index: include/llvm/InitializePasses.h =================================================================== --- include/llvm/InitializePasses.h +++ include/llvm/InitializePasses.h @@ -240,6 +240,7 @@ void initializePartiallyInlineLibCallsLegacyPassPass(PassRegistry &); void initializePEIPass(PassRegistry&); void initializePHIEliminationPass(PassRegistry&); +void initializePhysicalRegisterUsageInfoPass(PassRegistry &); void initializePartialInlinerPass(PassRegistry&); void initializePeepholeOptimizerPass(PassRegistry&); void initializePostDomOnlyPrinterPass(PassRegistry&); Index: lib/Analysis/CallGraphSCCPass.cpp =================================================================== --- lib/Analysis/CallGraphSCCPass.cpp +++ lib/Analysis/CallGraphSCCPass.cpp @@ -638,3 +638,8 @@ .getOptBisect() .shouldRunPass(this, SCC); } + +char DummyCGSCCPass::ID = 0; +INITIALIZE_PASS(DummyCGSCCPass, "DummyCGSCCPass", "DummyCGSCCPass", false, + false) + Index: lib/CodeGen/CMakeLists.txt =================================================================== --- lib/CodeGen/CMakeLists.txt +++ lib/CodeGen/CMakeLists.txt @@ -101,6 +101,8 @@ RegisterPressure.cpp RegisterScavenging.cpp RenameIndependentSubregs.cpp + RegisterUsageInfo.cpp + RegUsageInfoCollector.cpp SafeStack.cpp ScheduleDAG.cpp ScheduleDAGInstrs.cpp Index: lib/CodeGen/RegUsageInfoCollector.cpp =================================================================== --- /dev/null +++ lib/CodeGen/RegUsageInfoCollector.cpp @@ -0,0 +1,125 @@ +//===- 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/MachineRegisterInfo.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/RegisterUsageInfo.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" + +namespace llvm { +void initializeRegUsageInfoCollectorPass(PassRegistry &); +} + +namespace { +class RegUsageInfoCollector : public MachineFunctionPass { +public: + RegUsageInfoCollector() : MachineFunctionPass(ID) {} + + 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(); + AU.setPreservesAll(); + MachineFunctionPass::getAnalysisUsage(AU); +} + +bool RegUsageInfoCollector::runOnMachineFunction(MachineFunction &MF) { + MachineRegisterInfo *MRI = &MF.getRegInfo(); + TargetRegisterInfo *TRI = + (TargetRegisterInfo *)MF.getSubtarget().getRegisterInfo(); + + DEBUG(dbgs() << " -------------------- " << getPassName() + << " ----------------------- \n"); + DEBUG(dbgs() << "Function Name : " << MF.getName() << "\n"); + + std::vector 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(); + + for (unsigned PReg = 1, PRegE = TRI->getNumRegs(); PReg < PRegE; ++PReg) { + if (!MRI->reg_nodbg_empty(PReg) && MRI->isPhysRegUsed(PReg)) + markRegClobbered(TRI, &RegMask[0], PReg); + } + + DEBUG(dbgs() << " -----------------------------------------------------------" + "------------------ \n"); + + 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]; + } + + const Module *Mdl = MF.getFunction()->getParent(); + + PRUI->storeUpdateRegUsageInfo(Mdl->getNamedGlobal(MF.getName()), + std::move(RegMask)); + + return false; +} Index: lib/CodeGen/RegisterUsageInfo.cpp =================================================================== --- /dev/null +++ lib/CodeGen/RegisterUsageInfo.cpp @@ -0,0 +1,41 @@ +//===- 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/IR/Module.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" + +INITIALIZE_PASS(PhysicalRegisterUsageInfo, "reg-usage-info", + "Register Usage Informartion Stroage", false, true) + +char PhysicalRegisterUsageInfo::ID = 0; + +void PhysicalRegisterUsageInfo::anchor() {} + +void PhysicalRegisterUsageInfo::storeUpdateRegUsageInfo( + const GlobalVariable* MFGlobalVar, std::vector RegMask) { + RegMasks[MFGlobalVar] = std::move(RegMask); +} + +const std::vector * +PhysicalRegisterUsageInfo::getRegUsageInfo(const GlobalVariable* MFGlobalVar) { + if (RegMasks.find(MFGlobalVar) != RegMasks.end()) + return &(RegMasks.find(MFGlobalVar)->second); + return nullptr; +} Index: lib/CodeGen/TargetPassConfig.cpp =================================================================== --- lib/CodeGen/TargetPassConfig.cpp +++ lib/CodeGen/TargetPassConfig.cpp @@ -20,6 +20,7 @@ #include "llvm/Analysis/ScopedNoAliasAA.h" #include "llvm/Analysis/TypeBasedAliasAnalysis.h" #include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/RegisterUsageInfo.h" #include "llvm/CodeGen/RegAllocRegistry.h" #include "llvm/IR/IRPrintingPasses.h" #include "llvm/IR/LegacyPassManager.h" @@ -112,6 +113,11 @@ cl::init(false), cl::Hidden, cl::desc("Enable the new, experimental CFL alias analysis in CodeGen")); +cl::opt + UseIPRA("enable-ipra", cl::init(false), cl::Hidden, + cl::desc("Enable compile time 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. @@ -487,11 +493,37 @@ addPass(createRewriteSymbolsPass()); } +#include "llvm/Analysis/CallGraphSCCPass.h" +// namespace llvm { +// void initializeDummyCGSCCPassPass(PassRegistry &); +// } +// namespace { +// class DummyCGSCCPass : public CallGraphSCCPass { +// public: +// static char ID; +// DummyCGSCCPass() : CallGraphSCCPass(ID){}; +// bool runOnSCC(CallGraphSCC &SCC) override { return false; } +// void getAnalysisUsage(AnalysisUsage &AU) const override { +// AU.setPreservesAll(); +// } +// }; +// } + +// char DummyCGSCCPass::ID = 0; +// INITIALIZE_PASS(DummyCGSCCPass, "DummyCGSCCPass", "DummyCGSCCPass", false, +// false) + /// Add common passes that perform LLVM IR to IR transforms in preparation for /// instruction selection. void TargetPassConfig::addISelPrepare() { addPreISel(); + if (UseIPRA) { + // Force codegen to run according to the callgraph. + //initializeDummyCGSCCPassPass(*PassRegistry::getPassRegistry()); + 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)); @@ -612,7 +644,13 @@ addBlockPlacement(); 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); Index: lib/Target/X86/CMakeLists.txt =================================================================== --- lib/Target/X86/CMakeLists.txt +++ lib/Target/X86/CMakeLists.txt @@ -26,6 +26,7 @@ X86MachineFunctionInfo.cpp X86PadShortFunction.cpp X86RegisterInfo.cpp + X86RegUsageInfoPropagate.cpp X86SelectionDAGInfo.cpp X86ShuffleDecodeConstantPool.cpp X86Subtarget.cpp Index: lib/Target/X86/X86.h =================================================================== --- lib/Target/X86/X86.h +++ lib/Target/X86/X86.h @@ -83,6 +83,11 @@ /// the upper portions of registers, and to save code size. FunctionPass *createX86FixupBWInsts(); +/// Return a MachineFunction pass that identifies call sites +/// and propagates register usage information of callee to caller +/// if available with PysicalRegisterUsageInfo pass. +FunctionPass *createRegUsageInfoPropPass(); + void initializeFixupBWInstPassPass(PassRegistry &); } // End llvm namespace Index: lib/Target/X86/X86RegUsageInfoPropagate.cpp =================================================================== --- /dev/null +++ lib/Target/X86/X86RegUsageInfoPropagate.cpp @@ -0,0 +1,136 @@ +//=- X86RegUsageInfoPropagate.cpp - Register Usage Informartion Propagation -=// +// +// 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 iterates through MachineInstr in given MachineFunction and at each +/// callsite queries RegisterUsageInfo.cpp for RegMask (calculated based on +/// actual register allocation) of callee function, if such details found then +/// pass will update RegMask in call instruction. This updated RegMask will be +/// used by RegAllocators while allocating current MachineFunction. +/// +//===----------------------------------------------------------------------===// + +#include "X86.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/RegisterUsageInfo.h" +#include "llvm/IR/Module.h" +#include "llvm/PassAnalysisSupport.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetMachine.h" +#include +#include + +namespace llvm { +void initializeRegUsageInfoPropagationPassPass(PassRegistry &); +} + +using namespace llvm; + +#define DEBUG_TYPE "ip-regalloc" + +namespace { +class RegUsageInfoPropagationPass : public MachineFunctionPass { + +public: + RegUsageInfoPropagationPass() : MachineFunctionPass(ID) { + PassRegistry &Registry = *PassRegistry::getPassRegistry(); + initializeRegUsageInfoPropagationPassPass(Registry); + } + + const char *getPassName() const override { + return "X86 Register Usage Information Propagation"; + } + + bool runOnMachineFunction(MachineFunction &MF) override; + + void getAnalysisUsage(AnalysisUsage &AU) const override; + + static char ID; + +private: + static void setRegMask(MachineInstr &MI, const uint32_t *RegMask) { + for (MachineOperand &MO : MI.operands()) { + if (MO.isRegMask()) + MO.setRegMask(RegMask); + } + } +}; +} // end of anonymous namespace +char RegUsageInfoPropagationPass::ID = 0; + +INITIALIZE_PASS_BEGIN(RegUsageInfoPropagationPass, + "RegUsageInfoPropagationPass", + "X86 Register Usage Information Propagation", false, + false) +INITIALIZE_PASS_DEPENDENCY(PhysicalRegisterUsageInfo) +INITIALIZE_PASS_END(RegUsageInfoPropagationPass, "RegUsageInfoPropagationPass", + "X86 Register Usage Information Propagation", false, false) + +FunctionPass *llvm::createRegUsageInfoPropPass() { + return new RegUsageInfoPropagationPass(); +} + +void RegUsageInfoPropagationPass::getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired(); + AU.setPreservesAll(); + MachineFunctionPass::getAnalysisUsage(AU); +} + +bool RegUsageInfoPropagationPass::runOnMachineFunction(MachineFunction &MF) { + const Module *Mdl = MF.getFunction()->getParent(); + PhysicalRegisterUsageInfo *PRUI = &getAnalysis(); + + DEBUG(dbgs() << " ++++++++++++++++++++ " << getPassName() + << " ++++++++++++++++++++ \n"); + DEBUG(dbgs() << "MachineFunction : " << MF.getName() << "\n"); + + bool Changed = false; + + for (MachineBasicBlock &MBB : MF) { + for (MachineInstr &MI : MBB) { + // is it a call instr ? + if (MI.isCall()) { + DEBUG(dbgs() + << "Call Instrunction Before Register Usage Info Propagation : \n"); + DEBUG(dbgs() << MI << "\n"); + + auto UpdateRegMask = [&](StringRef FuncName) { + const auto *RegMask = + PRUI->getRegUsageInfo(Mdl->getNamedGlobal(FuncName)); + if (RegMask) { // else skip optimization + setRegMask(MI, &(*RegMask)[0]); + Changed = true; + } + }; + + MachineOperand &Operand = MI.getOperand(0); + if (Operand.isGlobal()) { + UpdateRegMask(Operand.getGlobal()->getName()); + } else if (Operand.isSymbol()) { + UpdateRegMask(Operand.getSymbolName()); + } + + DEBUG(dbgs() + << "Call Instrunction After Register Usage Info Propagation : \n"); + DEBUG(dbgs() << MI << "\n"); + } + } + } + + DEBUG(dbgs() << " +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" + "++++++ \n"); + return Changed; +} Index: lib/Target/X86/X86TargetMachine.cpp =================================================================== --- lib/Target/X86/X86TargetMachine.cpp +++ lib/Target/X86/X86TargetMachine.cpp @@ -28,7 +28,7 @@ static cl::opt EnableMachineCombinerPass("x86-machine-combiner", cl::desc("Enable the machine combiner pass"), cl::init(true), cl::Hidden); - +extern cl::opt UseIPRA; namespace llvm { void initializeWinEHStatePassPass(PassRegistry &); } @@ -279,6 +279,9 @@ // Install an instruction selector. addPass(createX86ISelDag(getX86TargetMachine(), getOptLevel())); + if (UseIPRA) + addPass(createRegUsageInfoPropPass()); + // For ELF, cleanup any local-dynamic TLS accesses. if (TM->getTargetTriple().isOSBinFormatELF() && getOptLevel() != CodeGenOpt::None)