Index: include/llvm/CodeGen/Passes.h =================================================================== --- include/llvm/CodeGen/Passes.h +++ include/llvm/CodeGen/Passes.h @@ -365,6 +365,11 @@ /// 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 Index: lib/CodeGen/CMakeLists.txt =================================================================== --- lib/CodeGen/CMakeLists.txt +++ lib/CodeGen/CMakeLists.txt @@ -103,6 +103,7 @@ RenameIndependentSubregs.cpp RegisterUsageInfo.cpp RegUsageInfoCollector.cpp + RegUsageInfoPropagate.cpp SafeStack.cpp ScheduleDAG.cpp ScheduleDAGInstrs.cpp Index: lib/CodeGen/RegUsageInfoPropagate.cpp =================================================================== --- /dev/null +++ lib/CodeGen/RegUsageInfoPropagate.cpp @@ -0,0 +1,134 @@ +//=- 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 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 "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 "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", + "Register Usage Information Propagation", false, false) +INITIALIZE_PASS_DEPENDENCY(PhysicalRegisterUsageInfo) +INITIALIZE_PASS_END(RegUsageInfoPropagationPass, "RegUsageInfoPropagationPass", + "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 *M = 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 Instruction Before Register Usage Info Propagation : \n"); + DEBUG(dbgs() << MI << "\n"); + + auto UpdateRegMask = [&](StringRef FuncName) { + const auto *RegMask = PRUI->getRegUsageInfo(M->getFunction(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 Instruction After Register Usage Info Propagation : \n"); + DEBUG(dbgs() << MI << "\n"); + } + } + } + + DEBUG(dbgs() << " +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" + "++++++ \n"); + return Changed; +} Index: lib/CodeGen/TargetPassConfig.cpp =================================================================== --- lib/CodeGen/TargetPassConfig.cpp +++ lib/CodeGen/TargetPassConfig.cpp @@ -538,6 +538,9 @@ 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")) { Index: test/CodeGen/Generic/ipra-transform.ll =================================================================== --- /dev/null +++ test/CodeGen/Generic/ipra-transform.ll @@ -0,0 +1,28 @@ + +; 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 { +; NOIPRA-LABEL: foo: +; NOIPRA: pushq %r10 +; NOIPRA-NEXT: pushq %r9 +; NOIPRA-NEXT: pushq %r8 +; NOIPRA: callq bar1 +; 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}