Index: include/llvm/CodeGen/MachineOperand.h =================================================================== --- include/llvm/CodeGen/MachineOperand.h +++ include/llvm/CodeGen/MachineOperand.h @@ -534,6 +534,11 @@ Contents.MBB = MBB; } + 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 @@ -356,6 +356,10 @@ /// This pass splits the stack into a safe stack and an unsafe stack to /// protect against stack-based overflow vulnerabilities. FunctionPass *createSafeStackPass(const TargetMachine *TM = nullptr); + + /// This pass is executed POST-RA to collect which physical registers are + /// used by given machien function. + FunctionPass *createRegUsageInfoCollector(); } // End llvm namespace /// Target machine pass initializer for passes with dependencies. Use with Index: include/llvm/CodeGen/PhysicalRegisterUsageInfo.h =================================================================== --- /dev/null +++ include/llvm/CodeGen/PhysicalRegisterUsageInfo.h @@ -0,0 +1,55 @@ +//=- PhysicalRegisterUsageInfo.cpp - 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. +// +//===----------------------------------------------------------------------===// +// +// This pass is required to get Interprocedural Register Allocation effect. +// See other two passes at lib/Target/X86/X86RegUsageInfoPropagate.cpp and lib/CodeGen/RegUsageInfoCollector.cpp +// +// This pass is simple immutable pass which keeps StringMap of +// function name 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" + +namespace llvm{ + + class StringRef; + + 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(); + } + + void storeUpdateRegUsageInfo(StringRef MFName, std::vector RegMasks); + + const std::vector *getRegUsageInfo(StringRef MFName); + + private: + // A simple map from function name to RegMask + // In RegMask 0 means register used (clobbered) by funciton + // and 1 means content of register will be preserved around function call + StringMap> RegMasks; + }; +} + +#endif \ No newline at end of file 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/CodeGen/CMakeLists.txt =================================================================== --- lib/CodeGen/CMakeLists.txt +++ lib/CodeGen/CMakeLists.txt @@ -85,6 +85,7 @@ PeepholeOptimizer.cpp PHIElimination.cpp PHIEliminationUtils.cpp + PhysicalRegisterUsageInfo.cpp PostRAHazardRecognizer.cpp PostRASchedulerList.cpp PreISelIntrinsicLowering.cpp @@ -100,6 +101,7 @@ RegisterCoalescer.cpp RegisterPressure.cpp RegisterScavenging.cpp + RegUsageInfoCollector.cpp SafeStack.cpp ScheduleDAG.cpp ScheduleDAGInstrs.cpp Index: lib/CodeGen/PhysicalRegisterUsageInfo.cpp =================================================================== --- /dev/null +++ lib/CodeGen/PhysicalRegisterUsageInfo.cpp @@ -0,0 +1,44 @@ +//=- PhysicalRegisterUsageInfo.cpp - 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. +// +//===----------------------------------------------------------------------===// +// +// This pass is required to get Interprocedural Register Allocation effect. +// See other two passes at lib/Target/X86/X86RegUsageInfoPropagate.cpp and lib/CodeGen/RegUsageInfoCollector.cpp +// +// This pass is simple immutable pass which keeps StringMap of +// function name to RegMask (calculated based on actual register allocation) and +// provides simple API to query this information. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/PhysicalRegisterUsageInfo.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +#define DEBUG_TYPE "ipra" + +INITIALIZE_PASS(PhysicalRegisterUsageInfo, "reg-usage-info", + "Register Usage Informartion Stroage", false, true) + +char PhysicalRegisterUsageInfo::ID = 0; + +void PhysicalRegisterUsageInfo::anchor() { } + +void PhysicalRegisterUsageInfo::storeUpdateRegUsageInfo(StringRef MFName, + std::vector RegMask) { + RegMasks[MFName] = std::move(RegMask); +} + +const std::vector *PhysicalRegisterUsageInfo::getRegUsageInfo(StringRef MFName) { + if(RegMasks.find(MFName) != RegMasks.end()) + return &(RegMasks.find(MFName)->second); + else + return nullptr; +} Index: lib/CodeGen/RegUsageInfoCollector.cpp =================================================================== --- /dev/null +++ lib/CodeGen/RegUsageInfoCollector.cpp @@ -0,0 +1,102 @@ +//=- RegUsageInfoCollector.cpp - Register Usage Informartion Collector -*- C++ -*-=// +// +// 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 get Interprocedural Register Allocation effect. +// See other two passes at lib/Target/X86/X86RegUsageInfoPropagate.cpp and lib/CodeGen/PhysicalRegisterUsageInfo.cpp +// +// 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/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/PhysicalRegisterUsageInfo.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +#define DEBUG_TYPE "ipra" + +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; + }; +} + +char RegUsageInfoCollector::ID = 0; + +INITIALIZE_PASS_BEGIN(RegUsageInfoCollector, "RegUsageInfoCollector", + "Register Usage Information Collector Pass", false, false) +INITIALIZE_PASS_DEPENDENCY(PhysicalRegisterUsageInfo) +INITIALIZE_PASS_END(RegUsageInfoCollector, "RegUsageInfoCollector", + "Register Usage Information Collector Pass", false, false) + +FunctionPass *llvm::createRegUsageInfoCollector() { return new RegUsageInfoCollector(); } + +void RegUsageInfoCollector::getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired(); + AU.setPreservesAll(); + MachineFunctionPass::getAnalysisUsage(AU); +} + +bool RegUsageInfoCollector::runOnMachineFunction(MachineFunction &MF) { + bool changed = false; + MachineRegisterInfo *MRI = &MF.getRegInfo(); + TargetRegisterInfo *TRI = (TargetRegisterInfo *)MF.getSubtarget().getRegisterInfo(); + + DEBUG(dbgs() << " -------------------- Register Usage Collection Pass ----------------------- \n"); + DEBUG(dbgs() << "Function Name : " << MF.getName() << "\n"); + + std::vector RegMask; + unsigned regMaskSize = (TRI->getNumRegs() + 31) / 32; // size should be in multiple of 32. + RegMask.resize(regMaskSize, 0); + + PhysicalRegisterUsageInfo *PRUI = &getAnalysis(); + + for (unsigned PReg = 1; PReg < TRI->getNumRegs(); ++PReg) { + if (!MRI->reg_nodbg_empty(PReg)) { + if(MRI->isPhysRegUsed(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; + } + } + } + } + + DEBUG(dbgs() << " ----------------------------------------------------------------------------- \n"); + + // bitwise negation for RegMask because 0 means clobbred and 1 means preserved + for (unsigned index = 0; index < regMaskSize; index++ ) { + RegMask[index] = ~RegMask[index]; + } + + PRUI->storeUpdateRegUsageInfo(MF.getName(),std::move(RegMask)); + + return changed; +} Index: lib/CodeGen/TargetPassConfig.cpp =================================================================== --- lib/CodeGen/TargetPassConfig.cpp +++ lib/CodeGen/TargetPassConfig.cpp @@ -21,6 +21,7 @@ #include "llvm/Analysis/TypeBasedAliasAnalysis.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/RegAllocRegistry.h" +#include "llvm/CodeGen/PhysicalRegisterUsageInfo.h" #include "llvm/IR/IRPrintingPasses.h" #include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Verifier.h" @@ -112,6 +113,11 @@ cl::init(false), cl::Hidden, cl::desc("Enable the new, experimental CFL alias analysis in CodeGen")); +// Option to enable compile time interprocedural register allocation. +cl::opt UseIPRA("enable-ipra", + cl::init(false), + 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,45 @@ 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_BEGIN(DummyCGSCCPass, "DummyCGSCCPass", + "DummyCGSCCPass", false, false) + INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass) + INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass) + INITIALIZE_PASS_END(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)); @@ -568,6 +608,12 @@ // Run post-ra passes. addPostRegAlloc(); + if(UseIPRA){ + // this is MachineFunction pass which iterates through register + // to check if it is used or not and creates RegMask + addPass(createRegUsageInfoCollector()); + } + // Insert prolog/epilog code. Eliminate abstract frame index references... if (getOptLevel() != CodeGenOpt::None) addPass(&ShrinkWrapID); 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 site +/// 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,124 @@ +//=- X86RegUsageInfoPropagate.cpp - Target Specific Register Usage Informartion Propagation -*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// This pass is last required pass to get Interprocedural Register Allocation effect. +// See other two passes at lib/CodeGen/PhysicalRegisterUsageInfo.cpp and lib/CodeGen/RegUsageInfoCollector.cpp +// +// This pass iterates through MachineInstr in given MachineFunction and at each callsite quires PhysicalRegisterUsageInfo.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 RegAllocators while allocating current MachineFunction. +// +//===----------------------------------------------------------------------===// + +#include "X86.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/PhysicalRegisterUsageInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/PassAnalysisSupport.h" +#include +#include + +namespace llvm { + void initializeRegUsageInfoPropagationPassPass(PassRegistry &); +} + +using namespace llvm; + +#define DEBUG_TYPE "ipra" + + +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); + } + } + }; + +} +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) { + PhysicalRegisterUsageInfo *PRUI = &getAnalysis(); + + DEBUG(dbgs() << " ++++++++++++++++++++ Register Usage Info Propagation Pass ++++++++++++++++++++ \n"); + DEBUG(dbgs() << "MachineFunction : " << MF.getName() << "\n"); + + bool changed = false; + + for (auto &MBB : MF) { + for (auto &MI : MBB) { + //is it a call instr ? + if(MI.isCall()) { + DEBUG(dbgs() << "Call Instrunction Before Register Usage Info Propagation : \n"); + DEBUG(MI.print(dbgs())); + DEBUG(dbgs() << "\n"); + + auto updateRegMask = [&](StringRef FuncName) { + const auto *RegMask = PRUI->getRegUsageInfo(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(MI.print(dbgs())); + DEBUG(dbgs() << "\n"); + } + } + } + + DEBUG(dbgs() << " +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ \n"); + return changed; +} Index: lib/Target/X86/X86TargetMachine.cpp =================================================================== --- lib/Target/X86/X86TargetMachine.cpp +++ lib/Target/X86/X86TargetMachine.cpp @@ -28,6 +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 +280,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)