diff options
| author | Mehdi Amini <mehdi.amini@apple.com> | 2016-06-10 18:37:21 +0000 |
|---|---|---|
| committer | Mehdi Amini <mehdi.amini@apple.com> | 2016-06-10 18:37:21 +0000 |
| commit | 1d396832d3b4e916c3901fed5083ad44b68d288e (patch) | |
| tree | 5f67f8040601137231c42121d75a0e68ef347e61 | |
| parent | 4e9cef0491ce508904137eb857df9523f5647ff5 (diff) | |
| download | bcm5719-llvm-1d396832d3b4e916c3901fed5083ad44b68d288e.tar.gz bcm5719-llvm-1d396832d3b4e916c3901fed5083ad44b68d288e.zip | |
Interprocedural Register Allocation (IPRA): add a Transformation Pass
Adds a MachineFunctionPass that scans the body to find calls, and
update the register mask with the one saved by the
RegUsageInfoCollector analysis in PhysicalRegisterUsageInfo.
Patch by Vivek Pandya <vivekvpandya@gmail.com>
Differential Revision: http://reviews.llvm.org/D21180
llvm-svn: 272414
| -rw-r--r-- | llvm/include/llvm/CodeGen/Passes.h | 5 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/RegUsageInfoPropagate.cpp | 131 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/TargetPassConfig.cpp | 3 | ||||
| -rw-r--r-- | llvm/test/CodeGen/Generic/ipra-transform.ll | 32 |
5 files changed, 172 insertions, 0 deletions
diff --git a/llvm/include/llvm/CodeGen/Passes.h b/llvm/include/llvm/CodeGen/Passes.h index e2e8ed964df..cffbca311fb 100644 --- a/llvm/include/llvm/CodeGen/Passes.h +++ b/llvm/include/llvm/CodeGen/Passes.h @@ -365,6 +365,11 @@ namespace llvm { /// This pass is executed POST-RA to collect which physical registers are /// preserved by given machine function. FunctionPass *createRegUsageInfoCollector(); + + /// Return a MachineFunction pass that identifies call sites + /// and propagates register usage information of callee to caller + /// if available with PysicalRegisterUsageInfo pass. + FunctionPass *createRegUsageInfoPropPass(); } // End llvm namespace /// Target machine pass initializer for passes with dependencies. Use with diff --git a/llvm/lib/CodeGen/CMakeLists.txt b/llvm/lib/CodeGen/CMakeLists.txt index 58f620d511d..03314889c8e 100644 --- a/llvm/lib/CodeGen/CMakeLists.txt +++ b/llvm/lib/CodeGen/CMakeLists.txt @@ -103,6 +103,7 @@ add_llvm_library(LLVMCodeGen RenameIndependentSubregs.cpp RegisterUsageInfo.cpp RegUsageInfoCollector.cpp + RegUsageInfoPropagate.cpp SafeStack.cpp ScheduleDAG.cpp ScheduleDAGInstrs.cpp diff --git a/llvm/lib/CodeGen/RegUsageInfoPropagate.cpp b/llvm/lib/CodeGen/RegUsageInfoPropagate.cpp new file mode 100644 index 00000000000..759566147cc --- /dev/null +++ b/llvm/lib/CodeGen/RegUsageInfoPropagate.cpp @@ -0,0 +1,131 @@ +//=--- RegUsageInfoPropagate.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 MachineInstrs in a given MachineFunction and at +/// each callsite queries RegisterUsageInfo for RegMask (calculated based on +/// actual register allocation) of the callee function, if the RegMask detail +/// is available then this pass will update the RegMask of the call instruction. +/// This updated RegMask will be used by the register allocator while allocating +/// the current MachineFunction. +/// +//===----------------------------------------------------------------------===// + +#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 <map> +#include <string> + +namespace llvm { +void initializeRegUsageInfoPropagationPassPass(PassRegistry &); +} + +using namespace llvm; + +#define DEBUG_TYPE "ip-regalloc" + +#define RUIP_NAME "Register Usage Information Propagation" + +namespace { +class RegUsageInfoPropagationPass : public MachineFunctionPass { + +public: + RegUsageInfoPropagationPass() : MachineFunctionPass(ID) { + PassRegistry &Registry = *PassRegistry::getPassRegistry(); + initializeRegUsageInfoPropagationPassPass(Registry); + } + + const char *getPassName() const override { return RUIP_NAME; } + + 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, "reg-usage-propagation", + RUIP_NAME, false, false) +INITIALIZE_PASS_DEPENDENCY(PhysicalRegisterUsageInfo) +INITIALIZE_PASS_END(RegUsageInfoPropagationPass, "reg-usage-propagation", + RUIP_NAME, false, false) + +FunctionPass *llvm::createRegUsageInfoPropPass() { + return new RegUsageInfoPropagationPass(); +} + +void RegUsageInfoPropagationPass::getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired<PhysicalRegisterUsageInfo>(); + AU.setPreservesAll(); + MachineFunctionPass::getAnalysisUsage(AU); +} + +bool RegUsageInfoPropagationPass::runOnMachineFunction(MachineFunction &MF) { + const Module *M = MF.getFunction()->getParent(); + PhysicalRegisterUsageInfo *PRUI = &getAnalysis<PhysicalRegisterUsageInfo>(); + + DEBUG(dbgs() << " ++++++++++++++++++++ " << getPassName() + << " ++++++++++++++++++++ \n"); + DEBUG(dbgs() << "MachineFunction : " << MF.getName() << "\n"); + + bool Changed = false; + + for (MachineBasicBlock &MBB : MF) { + for (MachineInstr &MI : MBB) { + if (!MI.isCall()) + continue; + DEBUG(dbgs() + << "Call Instruction Before Register Usage Info Propagation : \n"); + DEBUG(dbgs() << MI << "\n"); + + auto UpdateRegMask = [&](const Function *F) { + const auto *RegMask = PRUI->getRegUsageInfo(F); + if (!RegMask) + return; + setRegMask(MI, &(*RegMask)[0]); + Changed = true; + }; + + MachineOperand &Operand = MI.getOperand(0); + if (Operand.isGlobal()) + UpdateRegMask(cast<Function>(Operand.getGlobal())); + else if (Operand.isSymbol()) + UpdateRegMask(M->getFunction(Operand.getSymbolName())); + + DEBUG(dbgs() + << "Call Instruction After Register Usage Info Propagation : \n"); + DEBUG(dbgs() << MI << "\n"); + } + } + + DEBUG(dbgs() << " +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" + "++++++ \n"); + return Changed; +} diff --git a/llvm/lib/CodeGen/TargetPassConfig.cpp b/llvm/lib/CodeGen/TargetPassConfig.cpp index 3e7261a895f..1b30cc8ee54 100644 --- a/llvm/lib/CodeGen/TargetPassConfig.cpp +++ b/llvm/lib/CodeGen/TargetPassConfig.cpp @@ -538,6 +538,9 @@ void TargetPassConfig::addISelPrepare() { void TargetPassConfig::addMachinePasses() { AddingMachinePasses = true; + if (UseIPRA) + addPass(createRegUsageInfoPropPass()); + // Insert a machine instr printer pass after the specified pass. if (!StringRef(PrintMachineInstrs.getValue()).equals("") && !StringRef(PrintMachineInstrs.getValue()).equals("option-unspecified")) { diff --git a/llvm/test/CodeGen/Generic/ipra-transform.ll b/llvm/test/CodeGen/Generic/ipra-transform.ll new file mode 100644 index 00000000000..362af881234 --- /dev/null +++ b/llvm/test/CodeGen/Generic/ipra-transform.ll @@ -0,0 +1,32 @@ + +; RUN: llc < %s | FileCheck %s -check-prefix=NOIPRA +; RUN: llc -enable-ipra < %s | FileCheck %s + + +target triple = "x86_64-unknown-unknown" +define void @bar1() { + ret void +} +define preserve_allcc void @foo()#0 { +; Due to preserve_allcc foo() will save some registers at start of foo() +; prefix NOIPRA will verify that. +; NOIPRA-LABEL: foo: +; NOIPRA: pushq %r10 +; NOIPRA-NEXT: pushq %r9 +; NOIPRA-NEXT: pushq %r8 +; NOIPRA: callq bar1 +; When IPRA is present above registers will not be saved and that is verified +; by prefix CHECK. +; CHECK: foo: +; CHECK-NOT: pushq %r10 +; CHECK-NOT: pushq %r9 +; CHECK-NOT: pushq %r8 +; CHECK: callq bar1 + call void @bar1() + call void @bar2() + ret void +} +define void @bar2() { + ret void +} +attributes #0 = {nounwind} |

