[llvm-commits] [llvm] r114626 - in /llvm/trunk: include/llvm/CodeGen/LinkAllCodegenComponents.h include/llvm/CodeGen/Passes.h include/llvm/CodeGen/RegAllocPBQP.h lib/CodeGen/RegAllocPBQP.cpp

Lang Hames lhames at gmail.com
Wed Sep 22 21:28:55 PDT 2010


Author: lhames
Date: Wed Sep 22 23:28:54 2010
New Revision: 114626

URL: http://llvm.org/viewvc/llvm-project?rev=114626&view=rev
Log:
Moved the PBQP allocator class out of the header and back in to the cpp file to hide the gory details.
Allocator instances can now be created by calling createPBQPRegisterAllocator.

Tidied up use of CoalescerPair as per Jakob's suggestions.

Made the new PBQPBuilder based construction process the default. The internal construction process
remains in-place and available via -pbqp-builder=false for now. It will be removed shortly if the new
process doesn't cause any regressions.


Modified:
    llvm/trunk/include/llvm/CodeGen/LinkAllCodegenComponents.h
    llvm/trunk/include/llvm/CodeGen/Passes.h
    llvm/trunk/include/llvm/CodeGen/RegAllocPBQP.h
    llvm/trunk/lib/CodeGen/RegAllocPBQP.cpp

Modified: llvm/trunk/include/llvm/CodeGen/LinkAllCodegenComponents.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/LinkAllCodegenComponents.h?rev=114626&r1=114625&r2=114626&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/LinkAllCodegenComponents.h (original)
+++ llvm/trunk/include/llvm/CodeGen/LinkAllCodegenComponents.h Wed Sep 22 23:28:54 2010
@@ -35,7 +35,7 @@
 
       (void) llvm::createFastRegisterAllocator();
       (void) llvm::createLinearScanRegisterAllocator();
-      (void) llvm::createPBQPRegisterAllocator();
+      (void) llvm::createDefaultPBQPRegisterAllocator();
 
       (void) llvm::createSimpleRegisterCoalescer();
       

Modified: llvm/trunk/include/llvm/CodeGen/Passes.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/Passes.h?rev=114626&r1=114625&r2=114626&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/Passes.h (original)
+++ llvm/trunk/include/llvm/CodeGen/Passes.h Wed Sep 22 23:28:54 2010
@@ -103,7 +103,7 @@
   /// PBQPRegisterAllocation Pass - This pass implements the Partitioned Boolean
   /// Quadratic Prograaming (PBQP) based register allocator.
   ///
-  FunctionPass *createPBQPRegisterAllocator();
+  FunctionPass *createDefaultPBQPRegisterAllocator();
 
   /// SimpleRegisterCoalescing Pass - Coalesce all copies possible.  Can run
   /// independently of the register allocator.

Modified: llvm/trunk/include/llvm/CodeGen/RegAllocPBQP.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/RegAllocPBQP.h?rev=114626&r1=114625&r2=114626&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/RegAllocPBQP.h (original)
+++ llvm/trunk/include/llvm/CodeGen/RegAllocPBQP.h Wed Sep 22 23:28:54 2010
@@ -160,125 +160,7 @@
                             PBQP::PBQPNum benefit);
   };
 
-  ///
-  /// PBQP based allocators solve the register allocation problem by mapping
-  /// register allocation problems to Partitioned Boolean Quadratic
-  /// Programming problems.
-  class RegAllocPBQP : public MachineFunctionPass {
-  public:
-
-    static char ID;
-
-    /// Construct a PBQP register allocator.
-    RegAllocPBQP(std::auto_ptr<PBQPBuilder> b) : MachineFunctionPass(ID), builder(b) {}
-
-    /// Return the pass name.
-    virtual const char* getPassName() const {
-      return "PBQP Register Allocator";
-    }
-
-    /// PBQP analysis usage.
-    virtual void getAnalysisUsage(AnalysisUsage &au) const;
-
-    /// Perform register allocation
-    virtual bool runOnMachineFunction(MachineFunction &MF);
-
-  private:
-
-    typedef std::map<const LiveInterval*, unsigned> LI2NodeMap;
-    typedef std::vector<const LiveInterval*> Node2LIMap;
-    typedef std::vector<unsigned> AllowedSet;
-    typedef std::vector<AllowedSet> AllowedSetMap;
-    typedef std::pair<unsigned, unsigned> RegPair;
-    typedef std::map<RegPair, PBQP::PBQPNum> CoalesceMap;
-    typedef std::vector<PBQP::Graph::NodeItr> NodeVector;
-    typedef std::set<unsigned> RegSet;
-
-
-    std::auto_ptr<PBQPBuilder> builder;
-
-    MachineFunction *mf;
-    const TargetMachine *tm;
-    const TargetRegisterInfo *tri;
-    const TargetInstrInfo *tii;
-    const MachineLoopInfo *loopInfo;
-    MachineRegisterInfo *mri;
-    RenderMachineFunction *rmf;
-
-    LiveIntervals *lis;
-    LiveStacks *lss;
-    VirtRegMap *vrm;
-
-    LI2NodeMap li2Node;
-    Node2LIMap node2LI;
-    AllowedSetMap allowedSets;
-    RegSet vregsToAlloc, emptyIntervalVRegs;
-    NodeVector problemNodes;
-
-
-    /// Builds a PBQP cost vector.
-    template <typename RegContainer>
-    PBQP::Vector buildCostVector(unsigned vReg,
-                                 const RegContainer &allowed,
-                                 const CoalesceMap &cealesces,
-                                 PBQP::PBQPNum spillCost) const;
-
-    /// \brief Builds a PBQP interference matrix.
-    ///
-    /// @return Either a pointer to a non-zero PBQP matrix representing the
-    ///         allocation option costs, or a null pointer for a zero matrix.
-    ///
-    /// Expects allowed sets for two interfering LiveIntervals. These allowed
-    /// sets should contain only allocable registers from the LiveInterval's
-    /// register class, with any interfering pre-colored registers removed.
-    template <typename RegContainer>
-    PBQP::Matrix* buildInterferenceMatrix(const RegContainer &allowed1,
-                                          const RegContainer &allowed2) const;
-
-    ///
-    /// Expects allowed sets for two potentially coalescable LiveIntervals,
-    /// and an estimated benefit due to coalescing. The allowed sets should
-    /// contain only allocable registers from the LiveInterval's register
-    /// classes, with any interfering pre-colored registers removed.
-    template <typename RegContainer>
-    PBQP::Matrix* buildCoalescingMatrix(const RegContainer &allowed1,
-                                        const RegContainer &allowed2,
-                                        PBQP::PBQPNum cBenefit) const;
-
-    /// \brief Finds coalescing opportunities and returns them as a map.
-    ///
-    /// Any entries in the map are guaranteed coalescable, even if their
-    /// corresponding live intervals overlap.
-    CoalesceMap findCoalesces();
-
-    /// \brief Finds the initial set of vreg intervals to allocate.
-    void findVRegIntervalsToAlloc();
-
-    /// \brief Constructs a PBQP problem representation of the register
-    /// allocation problem for this function.
-    ///
-    /// @return a PBQP solver object for the register allocation problem.
-    PBQP::Graph constructPBQPProblem();
-
-    /// \brief Adds a stack interval if the given live interval has been
-    /// spilled. Used to support stack slot coloring.
-    void addStackInterval(const LiveInterval *spilled,MachineRegisterInfo* mri);
-
-    /// \brief Given a solved PBQP problem maps this solution back to a register
-    /// assignment.
-    bool mapPBQPToRegAlloc(const PBQP::Solution &solution);
-
-    /// \brief Given a solved PBQP problem maps this solution back to a register
-    /// assignment.
-    bool mapPBQPToRegAlloc2(const PBQPRAProblem &problem,
-                            const PBQP::Solution &solution);
-
-    /// \brief Postprocessing before final spilling. Sets basic block "live in"
-    /// variables.
-    void finalizeAlloc() const;
-
-  };
-
+  FunctionPass* createPBQPRegisterAllocator(std::auto_ptr<PBQPBuilder> builder);
 }
 
 #endif /* LLVM_CODEGEN_REGALLOCPBQP_H */

Modified: llvm/trunk/lib/CodeGen/RegAllocPBQP.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/RegAllocPBQP.cpp?rev=114626&r1=114625&r2=114626&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/RegAllocPBQP.cpp (original)
+++ llvm/trunk/lib/CodeGen/RegAllocPBQP.cpp Wed Sep 22 23:28:54 2010
@@ -56,11 +56,11 @@
 #include <set>
 #include <vector>
 
-namespace llvm {
+using namespace llvm;
 
 static RegisterRegAlloc
 registerPBQPRepAlloc("pbqp", "PBQP register allocator",
-                       llvm::createPBQPRegisterAllocator);
+                       createDefaultPBQPRegisterAllocator);
 
 static cl::opt<bool>
 pbqpCoalescing("pbqp-coalescing",
@@ -69,17 +69,149 @@
 
 static cl::opt<bool>
 pbqpBuilder("pbqp-builder",
-                cl::desc("Use new builder system."),
-                cl::init(false), cl::Hidden);
+             cl::desc("Use new builder system."),
+             cl::init(true), cl::Hidden);
 
 
 static cl::opt<bool>
 pbqpPreSplitting("pbqp-pre-splitting",
-                 cl::desc("Pre-splite before PBQP register allocation."),
+                 cl::desc("Pre-split before PBQP register allocation."),
                  cl::init(false), cl::Hidden);
 
+namespace {
+
+///
+/// PBQP based allocators solve the register allocation problem by mapping
+/// register allocation problems to Partitioned Boolean Quadratic
+/// Programming problems.
+class RegAllocPBQP : public MachineFunctionPass {
+public:
+
+  static char ID;
+
+  /// Construct a PBQP register allocator.
+  RegAllocPBQP(std::auto_ptr<PBQPBuilder> b) : MachineFunctionPass(ID), builder(b) {}
+
+  /// Return the pass name.
+  virtual const char* getPassName() const {
+    return "PBQP Register Allocator";
+  }
+
+  /// PBQP analysis usage.
+  virtual void getAnalysisUsage(AnalysisUsage &au) const;
+
+  /// Perform register allocation
+  virtual bool runOnMachineFunction(MachineFunction &MF);
+
+private:
+
+  typedef std::map<const LiveInterval*, unsigned> LI2NodeMap;
+  typedef std::vector<const LiveInterval*> Node2LIMap;
+  typedef std::vector<unsigned> AllowedSet;
+  typedef std::vector<AllowedSet> AllowedSetMap;
+  typedef std::pair<unsigned, unsigned> RegPair;
+  typedef std::map<RegPair, PBQP::PBQPNum> CoalesceMap;
+  typedef std::vector<PBQP::Graph::NodeItr> NodeVector;
+  typedef std::set<unsigned> RegSet;
+
+
+  std::auto_ptr<PBQPBuilder> builder;
+
+  MachineFunction *mf;
+  const TargetMachine *tm;
+  const TargetRegisterInfo *tri;
+  const TargetInstrInfo *tii;
+  const MachineLoopInfo *loopInfo;
+  MachineRegisterInfo *mri;
+  RenderMachineFunction *rmf;
+
+  LiveIntervals *lis;
+  LiveStacks *lss;
+  VirtRegMap *vrm;
+
+  LI2NodeMap li2Node;
+  Node2LIMap node2LI;
+  AllowedSetMap allowedSets;
+  RegSet vregsToAlloc, emptyIntervalVRegs;
+  NodeVector problemNodes;
+
+
+  /// Builds a PBQP cost vector.
+  template <typename RegContainer>
+  PBQP::Vector buildCostVector(unsigned vReg,
+                               const RegContainer &allowed,
+                               const CoalesceMap &cealesces,
+                               PBQP::PBQPNum spillCost) const;
+
+  /// \brief Builds a PBQP interference matrix.
+  ///
+  /// @return Either a pointer to a non-zero PBQP matrix representing the
+  ///         allocation option costs, or a null pointer for a zero matrix.
+  ///
+  /// Expects allowed sets for two interfering LiveIntervals. These allowed
+  /// sets should contain only allocable registers from the LiveInterval's
+  /// register class, with any interfering pre-colored registers removed.
+  template <typename RegContainer>
+  PBQP::Matrix* buildInterferenceMatrix(const RegContainer &allowed1,
+                                        const RegContainer &allowed2) const;
+
+  ///
+  /// Expects allowed sets for two potentially coalescable LiveIntervals,
+  /// and an estimated benefit due to coalescing. The allowed sets should
+  /// contain only allocable registers from the LiveInterval's register
+  /// classes, with any interfering pre-colored registers removed.
+  template <typename RegContainer>
+  PBQP::Matrix* buildCoalescingMatrix(const RegContainer &allowed1,
+                                      const RegContainer &allowed2,
+                                      PBQP::PBQPNum cBenefit) const;
+
+  /// \brief Finds coalescing opportunities and returns them as a map.
+  ///
+  /// Any entries in the map are guaranteed coalescable, even if their
+  /// corresponding live intervals overlap.
+  CoalesceMap findCoalesces();
+
+  /// \brief Finds the initial set of vreg intervals to allocate.
+  void findVRegIntervalsToAlloc();
+
+  /// \brief Constructs a PBQP problem representation of the register
+  /// allocation problem for this function.
+  ///
+  /// Old Construction Process - this functionality has been subsumed
+  /// by PBQPBuilder. This function will only be hanging around for a little
+  /// while until the new system has been fully tested.
+  /// 
+  /// @return a PBQP solver object for the register allocation problem.
+  PBQP::Graph constructPBQPProblemOld();
+
+  /// \brief Adds a stack interval if the given live interval has been
+  /// spilled. Used to support stack slot coloring.
+  void addStackInterval(const LiveInterval *spilled,MachineRegisterInfo* mri);
+
+  /// \brief Given a solved PBQP problem maps this solution back to a register
+  /// assignment.
+  ///
+  /// Old Construction Process - this functionality has been subsumed
+  /// by PBQPBuilder. This function will only be hanging around for a little
+  /// while until the new system has been fully tested.
+  /// 
+  bool mapPBQPToRegAllocOld(const PBQP::Solution &solution);
+
+  /// \brief Given a solved PBQP problem maps this solution back to a register
+  /// assignment.
+  bool mapPBQPToRegAlloc(const PBQPRAProblem &problem,
+                         const PBQP::Solution &solution);
+
+  /// \brief Postprocessing before final spilling. Sets basic block "live in"
+  /// variables.
+  void finalizeAlloc() const;
+
+};
+
 char RegAllocPBQP::ID = 0;
 
+} // End anonymous namespace.
+
 unsigned PBQPRAProblem::getVRegForNode(PBQP::Graph::ConstNodeItr node) const {
   Node2VReg::const_iterator vregItr = node2VReg.find(node);
   assert(vregItr != node2VReg.end() && "No vreg for node.");
@@ -277,58 +409,54 @@
          miItr != miEnd; ++miItr) {
       const MachineInstr *mi = &*miItr;
 
-      if (!mi->isCopy() && !mi->isSubregToReg())
-        continue; // Not coalescable.
-
       if (!cp.setRegisters(mi))
         continue; // Not coalescable.
 
       if (cp.getSrcReg() == cp.getDstReg())
         continue; // Already coalesced.
 
-      if (cp.isCoalescable(mi)) {
-
-        unsigned dst = cp.getDstReg(),
-                 src = cp.getSrcReg();
-
+      unsigned dst = cp.getDstReg(),
+               src = cp.getSrcReg();
 
+      const float copyFactor = 0.5; // Cost of copy relative to load. Current
+      // value plucked randomly out of the air.
+                                      
+      PBQP::PBQPNum cBenefit =
+        copyFactor * LiveIntervals::getSpillWeight(false, true,
+                                                   loopInfo->getLoopDepth(mbb));
 
-        PBQP::PBQPNum cBenefit =
-          std::pow(10.0f, (float)loopInfo->getLoopDepth(mbb));
-
-        if (cp.isPhys()) {
-          if (!lis->isAllocatable(dst))
-            continue;
+      if (cp.isPhys()) {
+        if (!lis->isAllocatable(dst))
+          continue;
 
-          const PBQPRAProblem::AllowedSet &allowed = p->getAllowedSet(src);
-          unsigned pregOpt = 0;  
-          while (pregOpt < allowed.size() && allowed[pregOpt] != dst)
-            ++pregOpt;
-          if (pregOpt < allowed.size()) {
-            ++pregOpt; // +1 to account for spill option.
-            PBQP::Graph::NodeItr node = p->getNodeForVReg(src);
-            addPhysRegCoalesce(g.getNodeCosts(node), pregOpt, cBenefit);
-          }
+        const PBQPRAProblem::AllowedSet &allowed = p->getAllowedSet(src);
+        unsigned pregOpt = 0;  
+        while (pregOpt < allowed.size() && allowed[pregOpt] != dst)
+          ++pregOpt;
+        if (pregOpt < allowed.size()) {
+          ++pregOpt; // +1 to account for spill option.
+          PBQP::Graph::NodeItr node = p->getNodeForVReg(src);
+          addPhysRegCoalesce(g.getNodeCosts(node), pregOpt, cBenefit);
+        }
+      } else {
+        const PBQPRAProblem::AllowedSet *allowed1 = &p->getAllowedSet(dst);
+        const PBQPRAProblem::AllowedSet *allowed2 = &p->getAllowedSet(src);
+        PBQP::Graph::NodeItr node1 = p->getNodeForVReg(dst);
+        PBQP::Graph::NodeItr node2 = p->getNodeForVReg(src);
+        PBQP::Graph::EdgeItr edge = g.findEdge(node1, node2);
+        if (edge == g.edgesEnd()) {
+          edge = g.addEdge(node1, node2, PBQP::Matrix(allowed1->size() + 1,
+                                                      allowed2->size() + 1,
+                                                      0));
         } else {
-          const PBQPRAProblem::AllowedSet *allowed1 = &p->getAllowedSet(dst);
-          const PBQPRAProblem::AllowedSet *allowed2 = &p->getAllowedSet(src);
-          PBQP::Graph::NodeItr node1 = p->getNodeForVReg(dst);
-          PBQP::Graph::NodeItr node2 = p->getNodeForVReg(src);
-          PBQP::Graph::EdgeItr edge = g.findEdge(node1, node2);
-          if (edge == g.edgesEnd()) {
-            edge = g.addEdge(node1, node2, PBQP::Matrix(allowed1->size() + 1,
-                                                        allowed2->size() + 1,
-                                                        0));
-          } else {
-            if (g.getEdgeNode1(edge) == node2) {
-              std::swap(node1, node2);
-              std::swap(allowed1, allowed2);
-            }
+          if (g.getEdgeNode1(edge) == node2) {
+            std::swap(node1, node2);
+            std::swap(allowed1, allowed2);
           }
-            
-          addVirtRegCoalesce(g.getEdgeCosts(edge), *allowed1, *allowed2,
-                             cBenefit);
         }
+            
+        addVirtRegCoalesce(g.getEdgeCosts(edge), *allowed1, *allowed2,
+                           cBenefit);
       }
     }
   }
@@ -336,7 +464,6 @@
   return p;
 }
 
-
 void PBQPBuilderWithCoalescing::addPhysRegCoalesce(PBQP::Vector &costVec,
                                                    unsigned pregOption,
                                                    PBQP::PBQPNum benefit) {
@@ -707,7 +834,7 @@
   }
 }
 
-PBQP::Graph RegAllocPBQP::constructPBQPProblem() {
+PBQP::Graph RegAllocPBQP::constructPBQPProblemOld() {
 
   typedef std::vector<const LiveInterval*> LIVector;
   typedef std::vector<unsigned> RegVector;
@@ -893,7 +1020,7 @@
   stackInterval.MergeRangesInAsValue(rhsInterval, vni);
 }
 
-bool RegAllocPBQP::mapPBQPToRegAlloc(const PBQP::Solution &solution) {
+bool RegAllocPBQP::mapPBQPToRegAllocOld(const PBQP::Solution &solution) {
 
   // Set to true if we have any spills
   bool anotherRoundNeeded = false;
@@ -964,8 +1091,8 @@
   return !anotherRoundNeeded;
 }
 
-bool RegAllocPBQP::mapPBQPToRegAlloc2(const PBQPRAProblem &problem,
-                                      const PBQP::Solution &solution) {
+bool RegAllocPBQP::mapPBQPToRegAlloc(const PBQPRAProblem &problem,
+                                     const PBQP::Solution &solution) {
   // Set to true if we have any spills
   bool anotherRoundNeeded = false;
 
@@ -1132,11 +1259,11 @@
       while (!pbqpAllocComplete) {
         DEBUG(dbgs() << "  PBQP Regalloc round " << round << ":\n");
 
-        PBQP::Graph problem = constructPBQPProblem();
+        PBQP::Graph problem = constructPBQPProblemOld();
         PBQP::Solution solution =
           PBQP::HeuristicSolver<PBQP::Heuristics::Briggs>::solve(problem);
 
-        pbqpAllocComplete = mapPBQPToRegAlloc(solution);
+        pbqpAllocComplete = mapPBQPToRegAllocOld(solution);
 
         ++round;
       }
@@ -1150,7 +1277,7 @@
           PBQP::HeuristicSolver<PBQP::Heuristics::Briggs>::solve(
             problem->getGraph());
 
-        pbqpAllocComplete = mapPBQPToRegAlloc2(*problem, solution);
+        pbqpAllocComplete = mapPBQPToRegAlloc(*problem, solution);
 
         ++round;
       }
@@ -1179,15 +1306,18 @@
   return true;
 }
 
-FunctionPass* createPBQPRegisterAllocator() {
-  if (pbqpCoalescing) {
-    return new RegAllocPBQP(
-                 std::auto_ptr<PBQPBuilder>(new PBQPBuilderWithCoalescing()));
-  } // else
-  return new RegAllocPBQP(
-                 std::auto_ptr<PBQPBuilder>(new PBQPBuilder()));
+FunctionPass* llvm::createPBQPRegisterAllocator(
+                                           std::auto_ptr<PBQPBuilder> builder) {
+  return new RegAllocPBQP(builder);
 }
 
+FunctionPass* llvm::createDefaultPBQPRegisterAllocator() {
+  if (pbqpCoalescing) {
+    return createPBQPRegisterAllocator(
+             std::auto_ptr<PBQPBuilder>(new PBQPBuilderWithCoalescing()));
+  } // else
+  return createPBQPRegisterAllocator(
+           std::auto_ptr<PBQPBuilder>(new PBQPBuilder()));
 }
 
 #undef DEBUG_TYPE





More information about the llvm-commits mailing list