From 4beea6623250516c2f8fe72a1d1f91970510f31c Mon Sep 17 00:00:00 2001 From: Mehdi Amini Date: Wed, 13 Jul 2016 23:39:34 +0000 Subject: [PATCH] [IPRA] Set callee saved registers to none for local function when IPRA is enabled. IPRA try to optimize caller saved register by propagating register usage information from callee to caller so it is beneficial to have caller saved registers compare to callee saved registers when IPRA is enabled. Please find more detailed explanation here https://groups.google.com/d/msg/llvm-dev/XRzGhJ9wtZg/tjAJqb0eEgAJ. This change makes local function do not have any callee preserved register when IPRA is enabled. A simple test case is also added to verify this change. Patch by Vivek Pandya Differential Revision: http://reviews.llvm.org/D21561 llvm-svn: 275347 --- llvm/include/llvm/CodeGen/TargetPassConfig.h | 3 +++ llvm/include/llvm/Target/TargetFrameLowering.h | 14 ++++++++++++++ llvm/lib/CodeGen/RegUsageInfoCollector.cpp | 25 +++++++++++++++++++------ llvm/lib/CodeGen/TargetFrameLoweringImpl.cpp | 13 ++++++++++--- llvm/lib/CodeGen/TargetPassConfig.cpp | 1 - 5 files changed, 46 insertions(+), 10 deletions(-) diff --git a/llvm/include/llvm/CodeGen/TargetPassConfig.h b/llvm/include/llvm/CodeGen/TargetPassConfig.h index 9309655..785d7e0 100644 --- a/llvm/include/llvm/CodeGen/TargetPassConfig.h +++ b/llvm/include/llvm/CodeGen/TargetPassConfig.h @@ -16,8 +16,11 @@ #include "llvm/Pass.h" #include "llvm/Support/CodeGen.h" +#include "llvm/Support/CommandLine.h" #include +extern llvm::cl::opt UseIPRA; + namespace llvm { class PassConfigImpl; diff --git a/llvm/include/llvm/Target/TargetFrameLowering.h b/llvm/include/llvm/Target/TargetFrameLowering.h index fcf890f..98065ac 100644 --- a/llvm/include/llvm/Target/TargetFrameLowering.h +++ b/llvm/include/llvm/Target/TargetFrameLowering.h @@ -331,6 +331,20 @@ public: virtual bool canUseAsEpilogue(const MachineBasicBlock &MBB) const { return true; } + + /// Check if given function is safe for not having callee saved registers. + /// This is used when interprocedural register allocation is enabled. + static bool isSafeForNoCSROpt(const Function *F) { + if (!F->hasLocalLinkage() || F->hasAddressTaken() || + !F->hasFnAttribute(Attribute::NoRecurse)) + return false; + // Function should not be optimized as tail call. + for (const User *U : F->users()) + if (auto CS = ImmutableCallSite(U)) + if (CS.isTailCall()) + return false; + return true; + } }; } // End llvm namespace diff --git a/llvm/lib/CodeGen/RegUsageInfoCollector.cpp b/llvm/lib/CodeGen/RegUsageInfoCollector.cpp index 7c3713a..50b8854 100644 --- a/llvm/lib/CodeGen/RegUsageInfoCollector.cpp +++ b/llvm/lib/CodeGen/RegUsageInfoCollector.cpp @@ -17,6 +17,7 @@ /// //===----------------------------------------------------------------------===// +#include "llvm/ADT/Statistic.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstr.h" @@ -26,11 +27,15 @@ #include "llvm/CodeGen/RegisterUsageInfo.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetFrameLowering.h" using namespace llvm; #define DEBUG_TYPE "ip-regalloc" +STATISTIC(NumCSROpt, + "Number of functions optimized for callee saved registers"); + namespace llvm { void initializeRegUsageInfoCollectorPass(PassRegistry &); } @@ -101,6 +106,8 @@ bool RegUsageInfoCollector::runOnMachineFunction(MachineFunction &MF) { unsigned RegMaskSize = (TRI->getNumRegs() + 31) / 32; RegMask.resize(RegMaskSize, 0xFFFFFFFF); + const Function *F = MF.getFunction(); + PhysicalRegisterUsageInfo *PRUI = &getAnalysis(); PRUI->setTargetMachine(&TM); @@ -111,11 +118,17 @@ bool RegUsageInfoCollector::runOnMachineFunction(MachineFunction &MF) { if (MRI->isPhysRegModified(PReg, true)) markRegClobbered(TRI, &RegMask[0], PReg); - const uint32_t *CallPreservedMask = - TRI->getCallPreservedMask(MF, MF.getFunction()->getCallingConv()); - // Set callee saved register as preserved. - for (unsigned i = 0; i < RegMaskSize; ++i) - RegMask[i] = RegMask[i] | CallPreservedMask[i]; + if (!TargetFrameLowering::isSafeForNoCSROpt(F)) { + const uint32_t *CallPreservedMask = + TRI->getCallPreservedMask(MF, F->getCallingConv()); + // Set callee saved register as preserved. + for (unsigned i = 0; i < RegMaskSize; ++i) + RegMask[i] = RegMask[i] | CallPreservedMask[i]; + } else { + ++NumCSROpt; + DEBUG(dbgs() << MF.getName() + << " function optimized for not having CSR.\n"); + } for (unsigned PReg = 1, PRegE = TRI->getNumRegs(); PReg < PRegE; ++PReg) if (MachineOperand::clobbersPhysReg(&(RegMask[0]), PReg)) @@ -123,7 +136,7 @@ bool RegUsageInfoCollector::runOnMachineFunction(MachineFunction &MF) { DEBUG(dbgs() << " \n----------------------------------------\n"); - PRUI->storeUpdateRegUsageInfo(MF.getFunction(), std::move(RegMask)); + PRUI->storeUpdateRegUsageInfo(F, std::move(RegMask)); return false; } diff --git a/llvm/lib/CodeGen/TargetFrameLoweringImpl.cpp b/llvm/lib/CodeGen/TargetFrameLoweringImpl.cpp index 0a0e079..bb99166 100644 --- a/llvm/lib/CodeGen/TargetFrameLoweringImpl.cpp +++ b/llvm/lib/CodeGen/TargetFrameLoweringImpl.cpp @@ -12,13 +12,14 @@ //===----------------------------------------------------------------------===// #include "llvm/ADT/BitVector.h" -#include "llvm/Target/TargetFrameLowering.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/TargetPassConfig.h" #include "llvm/IR/CallingConv.h" #include "llvm/IR/Function.h" +#include "llvm/Target/TargetFrameLowering.h" #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Target/TargetSubtargetInfo.h" #include @@ -59,15 +60,21 @@ bool TargetFrameLowering::needsFrameIndexResolution( void TargetFrameLowering::determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, RegScavenger *RS) const { - // Get the callee saved register list... const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo(); - const MCPhysReg *CSRegs = TRI.getCalleeSavedRegs(&MF); // Resize before the early returns. Some backends expect that // SavedRegs.size() == TRI.getNumRegs() after this call even if there are no // saved registers. SavedRegs.resize(TRI.getNumRegs()); + // When interprocedural register allocation is enabled caller saved registers + // are preferred over callee saved registers. + if (UseIPRA && isSafeForNoCSROpt(MF.getFunction())) + return; + + // Get the callee saved register list... + const MCPhysReg *CSRegs = TRI.getCalleeSavedRegs(&MF); + // Early exit if there are no callee saved registers. if (!CSRegs || CSRegs[0] == 0) return; diff --git a/llvm/lib/CodeGen/TargetPassConfig.cpp b/llvm/lib/CodeGen/TargetPassConfig.cpp index 4bdfb04..dccdc52 100644 --- a/llvm/lib/CodeGen/TargetPassConfig.cpp +++ b/llvm/lib/CodeGen/TargetPassConfig.cpp @@ -28,7 +28,6 @@ #include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Verifier.h" #include "llvm/MC/MCAsmInfo.h" -#include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" -- 2.7.4