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(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); + + 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,40 @@ +//=- 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" + +using namespace llvm; + +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] = RegMask; +} + +std::vector PhysicalRegisterUsageInfo::getRegUsageInfo(StringRef MFName) { + if(RegMasks.find(MFName) != RegMasks.end()) + return RegMasks.find(MFName)->second; + else + return std::vector(); +} 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); // default all regs are not preserved + + 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(),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,46 @@ 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)); @@ -543,6 +584,7 @@ // Print the instruction selected machine code... printAndVerify("After Instruction Selection"); + // Expand pseudo-instructions emitted by ISel. addPass(&ExpandISelPseudosID); @@ -554,6 +596,11 @@ // to one another and simplify frame index references where possible. addPass(&LocalStackSlotAllocationID, false); } + + if(UseIPRA){ + // This immutable pass which is kind of function_name -> reg usage storage + addPass(new PhysicalRegisterUsageInfo); + } // Run pre-ra passes. addPreRegAlloc(); @@ -568,6 +615,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); @@ -612,7 +665,7 @@ addBlockPlacement(); addPreEmitPass(); - + 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 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) { } + + 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, 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(MachineFunction::iterator MBB = MF.begin(), MBE = MF.end(); MBB != MBE ; MBB++) { + MachineBasicBlock *mb = (MachineBasicBlock *)MBB; + for(MachineBasicBlock::iterator MIB = mb->begin(), MIE = mb->end(); MIB != MIE; MIB++) { + MachineInstr *mi = MIB; + //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"); + + MachineOperand &operand = mi->getOperand(0); + if(operand.isGlobal()) { + std::vector RegMask = PRUI->getRegUsageInfo(operand.getGlobal()->getName()); + if(!RegMask.empty()) { // else skip optimization + setRegMask(*mi,&RegMask[0]); + changed = true; + } + } else if (operand.isSymbol()) { + StringRef FunctionName = StringRef(operand.getSymbolName()); + std::vector RegMask = PRUI->getRegUsageInfo(FunctionName); + if(!RegMask.empty()) { // else skip optimization + setRegMask(*mi,&RegMask[0]); + changed = true; + } + } + + 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 &); @@ -310,6 +311,9 @@ addPass(createX86CallFrameOptimization()); addPass(createX86WinAllocaExpander()); + + if(UseIPRA) + addPass(createRegUsageInfoPropPass()); } void X86PassConfig::addPostRegAlloc() {