Improve performance of calculateDbgValueHistory.
authorAdrian Prantl <aprantl@apple.com>
Wed, 6 Aug 2014 18:41:24 +0000 (18:41 +0000)
committerAdrian Prantl <aprantl@apple.com>
Wed, 6 Aug 2014 18:41:24 +0000 (18:41 +0000)
In r210492 the logic of calculateDbgValueHistory was changed to end
register variable live ranges at the end of MBB conditionally on
the fact that the register was or not clobbered by the function body.

This requires an initial scan of all the operands of the function
to collect all clobbered registers. In a second pass over all
instructions, we compare this set with the set of clobbered
registers for the current MachineInstruction. This modification
incurred a compilation time regression on some benchmarks: the
debug info emission phase takes ~10% more time.

While a small performance hit is unavoidable due to the initial
scan requirement, we can improve the situation by avoiding to
create too many temporary sets and just use lambdas to work directly
on the result of the initial scan.

Fixes <rdar://problem/17884104>

Patch by Frederic Riss!

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@214987 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.cpp

index 143b0135c8c8432c3b233ac355765683fb762cb4..998c396924bc38d5872653019485f7f0c09ec59b 100644 (file)
@@ -112,15 +112,23 @@ static void clobberRegisterUses(RegDescribedVarsMap &RegVars, unsigned RegNo,
   RegVars.erase(I);
 }
 
-// \brief Collect all registers clobbered by @MI and insert them to @Regs.
-static void collectClobberedRegisters(const MachineInstr &MI,
+// \brief Collect all registers clobbered by @MI and apply the functor
+// @Func to their RegNo.
+// @Func should be a functor with a void(unsigned) signature. We're
+// not using std::function here for performance reasons. It has a
+// small but measurable impact. By using a functor instead of a
+// std::set& here, we can avoid the overhead of constructing
+// temporaries in calculateDbgValueHistory, which has a significant
+// performance impact.
+template<typename Callable>
+static void applyToClobberedRegisters(const MachineInstr &MI,
                                       const TargetRegisterInfo *TRI,
-                                      std::set<unsigned> &Regs) {
+                                      Callable Func) {
   for (const MachineOperand &MO : MI.operands()) {
     if (!MO.isReg() || !MO.isDef() || !MO.getReg())
       continue;
     for (MCRegAliasIterator AI(MO.getReg(), TRI, true); AI.isValid(); ++AI)
-      Regs.insert(*AI);
+      Func(*AI);
   }
 }
 
@@ -146,7 +154,7 @@ static const MachineInstr *getFirstEpilogueInst(const MachineBasicBlock &MBB) {
 }
 
 // \brief Collect registers that are modified in the function body (their
-// contents is changed only in the prologue and epilogue).
+// contents is changed outside of the prologue and epilogue).
 static void collectChangingRegs(const MachineFunction *MF,
                                 const TargetRegisterInfo *TRI,
                                 std::set<unsigned> &Regs) {
@@ -157,7 +165,7 @@ static void collectChangingRegs(const MachineFunction *MF,
       if (&MI == FirstEpilogueInst)
         break;
       if (!MI.getFlag(MachineInstr::FrameSetup))
-        collectClobberedRegisters(MI, TRI, Regs);
+        applyToClobberedRegisters(MI, TRI, [&](unsigned r) { Regs.insert(r); });
     }
   }
 }
@@ -174,12 +182,10 @@ void calculateDbgValueHistory(const MachineFunction *MF,
       if (!MI.isDebugValue()) {
         // Not a DBG_VALUE instruction. It may clobber registers which describe
         // some variables.
-        std::set<unsigned> MIClobberedRegs;
-        collectClobberedRegisters(MI, TRI, MIClobberedRegs);
-        for (unsigned RegNo : MIClobberedRegs) {
+        applyToClobberedRegisters(MI, TRI, [&](unsigned RegNo) {
           if (ChangingRegs.count(RegNo))
             clobberRegisterUses(RegVars, RegNo, Result, MI);
-        }
+        });
         continue;
       }