[llvm-commits] [llvm] r156561 - in /llvm/trunk/lib/CodeGen: RegisterPressure.cpp RegisterPressure.h

Andrew Trick atrick at apple.com
Thu May 10 12:11:52 PDT 2012


Author: atrick
Date: Thu May 10 14:11:52 2012
New Revision: 156561

URL: http://llvm.org/viewvc/llvm-project?rev=156561&view=rev
Log:
RegPressure: API for speculatively checking instruction pressure.

Added getMaxExcessUpward/DownwardPressure. They somewhat abuse the
tracker by speculatively handling an instruction out of order. But it
is convenient for now. In the future, we will cache each instruction's
pressure contribution to make this efficient.

Modified:
    llvm/trunk/lib/CodeGen/RegisterPressure.cpp
    llvm/trunk/lib/CodeGen/RegisterPressure.h

Modified: llvm/trunk/lib/CodeGen/RegisterPressure.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/RegisterPressure.cpp?rev=156561&r1=156560&r2=156561&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/RegisterPressure.cpp (original)
+++ llvm/trunk/lib/CodeGen/RegisterPressure.cpp Thu May 10 14:11:52 2012
@@ -30,8 +30,10 @@
   for (const int *PSet = TRI->getRegClassPressureSets(RC);
        *PSet != -1; ++PSet) {
     CurrSetPressure[*PSet] += Weight;
-    if (CurrSetPressure[*PSet] > MaxSetPressure[*PSet])
+    if (&CurrSetPressure != &MaxSetPressure
+        && CurrSetPressure[*PSet] > MaxSetPressure[*PSet]) {
       MaxSetPressure[*PSet] = CurrSetPressure[*PSet];
+    }
   }
 }
 
@@ -543,3 +545,180 @@
   while (CurrPos != MBB->end() && CurrPos->isDebugValue());
   return true;
 }
+
+// Find the max change in excess pressure across all sets.
+static int computeMaxPressureDelta(ArrayRef<unsigned> OldPressureVec,
+                                   ArrayRef<unsigned> NewPressureVec,
+                                   unsigned &PSetID,
+                                   const TargetRegisterInfo *TRI) {
+  int ExcessUnits = 0;
+  for (unsigned i = 0, e = OldPressureVec.size(); i < e; ++i) {
+    unsigned POld = OldPressureVec[i];
+    unsigned PNew = NewPressureVec[i];
+    int PDiff = (int)PNew - (int)POld;
+    if (!PDiff) // No change in this set in the common case.
+      continue;
+    // Only consider change beyond the limit.
+    unsigned Limit = TRI->getRegPressureSetLimit(i);
+    if (Limit > POld) {
+      if (Limit > PNew)
+        PDiff = 0;          // Under the limit
+      else
+        PDiff = PNew - Limit; // Just exceeded limit.
+    }
+    else if (Limit > PNew)
+      PDiff = Limit - POld; // Just obeyed limit.
+
+    if (std::abs(PDiff) > std::abs(ExcessUnits)) {
+      ExcessUnits = PDiff;
+      PSetID = i;
+    }
+  }
+  return ExcessUnits;
+}
+
+/// Consider the pressure increase caused by traversing this instruction
+/// bottom-up. Find the pressure set with the most change beyond its pressure
+/// limit based on the tracker's current pressure, and return the change in
+/// number of register units of that pressure set introduced by this
+/// instruction.
+///
+/// This assumes that the current LiveOut set is sufficient.
+///
+/// FIXME: This is expensive for an on-the-fly query. We need to cache the
+/// result per-SUnit with enough information to adjust for the current
+/// scheduling position. But this works as a proof of concept.
+void RegPressureTracker::
+getMaxUpwardPressureDelta(const MachineInstr *MI, RegPressureDelta &Delta) {
+  // Account for register pressure similar to RegPressureTracker::recede().
+  PhysRegOperands PhysRegOpers;
+  VirtRegOperands VirtRegOpers;
+  collectOperands(MI, PhysRegOpers, VirtRegOpers, TRI, RCI);
+
+  // Snapshot Pressure.
+  std::vector<unsigned> SavedPressure = CurrSetPressure;
+  std::vector<unsigned> SavedMaxPressure = P.MaxSetPressure;
+
+  // Boost max pressure for all dead defs together.
+  // Since CurrSetPressure and MaxSetPressure
+  increasePhysRegPressure(PhysRegOpers.DeadDefs);
+  increaseVirtRegPressure(VirtRegOpers.DeadDefs);
+  decreasePhysRegPressure(PhysRegOpers.DeadDefs);
+  decreaseVirtRegPressure(VirtRegOpers.DeadDefs);
+
+  // Kill liveness at live defs.
+  // TODO: consider earlyclobbers?
+  for (unsigned i = 0; i < PhysRegOpers.Defs.size(); ++i) {
+    unsigned Reg = PhysRegOpers.Defs[i];
+    if (LivePhysRegs.erase(Reg))
+      decreasePhysRegPressure(Reg);
+    else
+      discoverPhysLiveOut(Reg);
+  }
+  for (unsigned i = 0; i < VirtRegOpers.Defs.size(); ++i) {
+    unsigned Reg = VirtRegOpers.Defs[i];
+    if (LiveVirtRegs.erase(Reg))
+      decreaseVirtRegPressure(Reg);
+    else
+      discoverVirtLiveOut(Reg);
+  }
+
+  // Generate liveness for uses.
+  for (unsigned i = 0, e = PhysRegOpers.Uses.size(); i < e; ++i) {
+    unsigned Reg = PhysRegOpers.Uses[i];
+    if (!hasRegAlias(Reg, LivePhysRegs, TRI)) {
+      increasePhysRegPressure(Reg);
+      LivePhysRegs.insert(Reg);
+    }
+  }
+  for (unsigned i = 0, e = VirtRegOpers.Uses.size(); i < e; ++i) {
+    unsigned Reg = VirtRegOpers.Uses[i];
+    if (!LiveVirtRegs.count(Reg)) {
+      increaseVirtRegPressure(Reg);
+    }
+  }
+  Delta.ExcessUnits =
+    computeMaxPressureDelta(SavedPressure, CurrSetPressure,
+                            Delta.ExcessSetID, TRI);
+  Delta.MaxUnitIncrease =
+    computeMaxPressureDelta(SavedMaxPressure, P.MaxSetPressure,
+                            Delta.MaxSetID, TRI);
+  assert(Delta.MaxUnitIncrease >= 0 && "cannot increase max pressure");
+
+  // Restore the tracker's state.
+  P.MaxSetPressure.swap(SavedMaxPressure);
+  CurrSetPressure.swap(SavedPressure);
+}
+
+/// Helper to find a vreg use between two indices [PriorUseIdx, NextUseIdx).
+static bool findUseBetween(unsigned Reg,
+                           SlotIndex PriorUseIdx, SlotIndex NextUseIdx,
+                           const MachineRegisterInfo *MRI,
+                           const LiveIntervals *LIS) {
+  for (MachineRegisterInfo::use_nodbg_iterator
+         UI = MRI->use_nodbg_begin(Reg), UE = MRI->use_nodbg_end();
+         UI != UE; UI.skipInstruction()) {
+      const MachineInstr* MI = &*UI;
+      SlotIndex InstSlot = LIS->getInstructionIndex(MI).getRegSlot();
+      if (InstSlot >= PriorUseIdx && InstSlot < NextUseIdx)
+        return true;
+  }
+  return false;
+}
+
+/// Consider the pressure increase caused by traversing this instruction
+/// top-down. Find the register class with the most change in its pressure limit
+/// based on the tracker's current pressure, and return the number of excess
+/// register units of that pressure set introduced by this instruction.
+///
+/// This assumes that the current LiveIn set is sufficient.
+void RegPressureTracker::
+getMaxDownwardPressureDelta(const MachineInstr *MI, RegPressureDelta &Delta) {
+  // Account for register pressure similar to RegPressureTracker::recede().
+  PhysRegOperands PhysRegOpers;
+  VirtRegOperands VirtRegOpers;
+  collectOperands(MI, PhysRegOpers, VirtRegOpers, TRI, RCI);
+
+  // Snapshot Pressure.
+  std::vector<unsigned> SavedPressure = CurrSetPressure;
+  std::vector<unsigned> SavedMaxPressure = P.MaxSetPressure;
+
+  // Kill liveness at last uses. Assume allocatable physregs are single-use
+  // rather than checking LiveIntervals.
+  decreasePhysRegPressure(PhysRegOpers.Uses);
+  if (RequireIntervals) {
+    SlotIndex SlotIdx = LIS->getInstructionIndex(MI).getRegSlot();
+    for (unsigned i = 0, e = VirtRegOpers.Uses.size(); i < e; ++i) {
+      unsigned Reg = VirtRegOpers.Uses[i];
+      const LiveInterval *LI = &LIS->getInterval(Reg);
+      // FIXME: allow the caller to pass in the list of vreg uses that remain to
+      // be top-scheduled to avoid searching uses at each query.
+      SlotIndex CurrIdx = LIS->getInstructionIndex(CurrPos).getRegSlot();
+      if (LI->killedAt(SlotIdx)
+          && !findUseBetween(Reg, CurrIdx, SlotIdx, MRI, LIS)) {
+        decreaseVirtRegPressure(Reg);
+      }
+    }
+  }
+
+  // Generate liveness for defs.
+  increasePhysRegPressure(PhysRegOpers.Defs);
+  increaseVirtRegPressure(VirtRegOpers.Defs);
+
+  // Boost pressure for all dead defs together.
+  increasePhysRegPressure(PhysRegOpers.DeadDefs);
+  increaseVirtRegPressure(VirtRegOpers.DeadDefs);
+  decreasePhysRegPressure(PhysRegOpers.DeadDefs);
+  decreaseVirtRegPressure(VirtRegOpers.DeadDefs);
+
+  Delta.ExcessUnits =
+    computeMaxPressureDelta(SavedPressure, CurrSetPressure,
+                            Delta.ExcessSetID, TRI);
+  Delta.MaxUnitIncrease =
+    computeMaxPressureDelta(SavedMaxPressure, P.MaxSetPressure,
+                            Delta.MaxSetID, TRI);
+
+  // Restore the tracker's state.
+  P.MaxSetPressure.swap(SavedMaxPressure);
+  CurrSetPressure.swap(SavedPressure);
+}

Modified: llvm/trunk/lib/CodeGen/RegisterPressure.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/RegisterPressure.h?rev=156561&r1=156560&r2=156561&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/RegisterPressure.h (original)
+++ llvm/trunk/lib/CodeGen/RegisterPressure.h Thu May 10 14:11:52 2012
@@ -23,6 +23,7 @@
 
 class LiveIntervals;
 class RegisterClassInfo;
+class MachineInstr;
 
 /// Base class for register pressure results.
 struct RegisterPressure {
@@ -79,6 +80,30 @@
   void openBottom(MachineBasicBlock::const_iterator PrevBottom);
 };
 
+/// Store the results of a change in pressure.
+///
+/// ExcessUnits is the value of the largest difference in register units beyond
+/// the target's pressure limits across the affected pressure sets, where
+/// largest is defined as the absolute value of the difference. Negative
+/// ExcessUnits indicates a reduction in pressure that had already exceeded the
+/// target's limits.
+///
+/// MaxUnitIncrease is the largest increase in register units required across
+/// the scheduled region across the affected pressure sets, regardless of the
+/// target's pressure limits.
+///
+/// If ExcessUnits == 0, then ExcessSetID is invalid.
+/// If MaxUnitIncrease == 0, then MaxSetID is invalid.
+struct RegPressureDelta {
+  int ExcessUnits;
+  unsigned ExcessSetID;
+  int MaxUnitIncrease;
+  unsigned MaxSetID;
+
+  RegPressureDelta():
+    ExcessUnits(0), ExcessSetID(~0U), MaxUnitIncrease(0), MaxSetID(~0U) {}
+};
+
 /// Track the current register pressure at some position in the instruction
 /// stream, and remember the high water mark within the region traversed. This
 /// does not automatically consider live-through ranges. The client may
@@ -151,6 +176,30 @@
   /// or if closeRegion() was explicitly invoked.
   RegisterPressure &getPressure() { return P; }
 
+  /// Consider the pressure increase caused by traversing this instruction
+  /// bottom-up. Find the pressure set with the most change beyond its pressure
+  /// limit based on the tracker's current pressure, and record the number of
+  /// excess register units of that pressure set introduced by this instruction.
+  void getMaxUpwardPressureDelta(const MachineInstr *MI,
+                                 RegPressureDelta &Delta);
+
+  /// Consider the pressure increase caused by traversing this instruction
+  /// top-down. Find the pressure set with the most change beyond its pressure
+  /// limit based on the tracker's current pressure, and record the number of
+  /// excess register units of that pressure set introduced by this instruction.
+  void getMaxDownwardPressureDelta(const MachineInstr *MI,
+                                   RegPressureDelta &Delta);
+
+  /// Find the pressure set with the most change beyond its pressure limit after
+  /// traversing this instruction either upward or downward depending on the
+  /// closed end of the current region.
+  void getMaxPressureDelta(const MachineInstr *MI, RegPressureDelta &Delta) {
+    if (isTopClosed())
+      return getMaxDownwardPressureDelta(MI, Delta);
+    assert(isBottomClosed() && "Uninitialized pressure tracker");
+    return getMaxUpwardPressureDelta(MI, Delta);
+  }
+
 protected:
   bool isTopClosed() const;
   bool isBottomClosed() const;





More information about the llvm-commits mailing list