[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 <vivekvpandya@gmail.com>

Differential Revision: http://reviews.llvm.org/D21561

llvm-svn: 275347
This commit is contained in:
Mehdi Amini 2016-07-13 23:39:34 +00:00
parent 931df67ae6
commit 4beea66232
5 changed files with 46 additions and 10 deletions

View File

@ -16,8 +16,11 @@
#include "llvm/Pass.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/CommandLine.h"
#include <string>
extern llvm::cl::opt<bool> UseIPRA;
namespace llvm {
class PassConfigImpl;

View File

@ -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

View File

@ -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<PhysicalRegisterUsageInfo>();
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;
}

View File

@ -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 <cstdlib>
@ -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;

View File

@ -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"