[IPRA] Set callee saved registers to none for local function when IPRA is enabled.
authorMehdi Amini <mehdi.amini@apple.com>
Wed, 13 Jul 2016 23:39:34 +0000 (23:39 +0000)
committerMehdi Amini <mehdi.amini@apple.com>
Wed, 13 Jul 2016 23:39:34 +0000 (23:39 +0000)
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

llvm/include/llvm/CodeGen/TargetPassConfig.h
llvm/include/llvm/Target/TargetFrameLowering.h
llvm/lib/CodeGen/RegUsageInfoCollector.cpp
llvm/lib/CodeGen/TargetFrameLoweringImpl.cpp
llvm/lib/CodeGen/TargetPassConfig.cpp

index 9309655..785d7e0 100644 (file)
 
 #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;
index fcf890f..98065ac 100644 (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
index 7c3713a..50b8854 100644 (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"
 #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;
 }
index 0a0e079..bb99166 100644 (file)
 //===----------------------------------------------------------------------===//
 
 #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;
index 4bdfb04..dccdc52 100644 (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"