forked from OSchip/llvm-project
[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:
parent
931df67ae6
commit
4beea66232
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue