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,135 @@ +//=- 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 *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/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) Index: test/CodeGen/Generic/ip-regalloc-simple.ll =================================================================== --- /dev/null +++ test/CodeGen/Generic/ip-regalloc-simple.ll @@ -0,0 +1,28 @@ +;;;;; ip-regallco-simple.ll +; 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}