[llvm-commits] [llvm] r108842 - in /llvm/trunk/lib/CodeGen: CMakeLists.txt InlineSpiller.cpp SplitKit.cpp SplitKit.h

Jakob Stoklund Olesen stoklund at 2pi.dk
Tue Jul 20 08:41:07 PDT 2010


Author: stoklund
Date: Tue Jul 20 10:41:07 2010
New Revision: 108842

URL: http://llvm.org/viewvc/llvm-project?rev=108842&view=rev
Log:
Beginning SplitKit - utility classes for live range splitting.

This is a work in progress. So far we have some basic loop analysis to help
determine where it is useful to split a live range around a loop.

The actual loop splitting code from Splitter.cpp is also going to move in here.

Added:
    llvm/trunk/lib/CodeGen/SplitKit.cpp
    llvm/trunk/lib/CodeGen/SplitKit.h
Modified:
    llvm/trunk/lib/CodeGen/CMakeLists.txt
    llvm/trunk/lib/CodeGen/InlineSpiller.cpp

Modified: llvm/trunk/lib/CodeGen/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/CMakeLists.txt?rev=108842&r1=108841&r2=108842&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/CMakeLists.txt (original)
+++ llvm/trunk/lib/CodeGen/CMakeLists.txt Tue Jul 20 10:41:07 2010
@@ -68,6 +68,7 @@
   SjLjEHPrepare.cpp
   SlotIndexes.cpp
   Spiller.cpp
+  SplitKit.cpp
   Splitter.cpp
   StackProtector.cpp
   StackSlotColoring.cpp

Modified: llvm/trunk/lib/CodeGen/InlineSpiller.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/InlineSpiller.cpp?rev=108842&r1=108841&r2=108842&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/InlineSpiller.cpp (original)
+++ llvm/trunk/lib/CodeGen/InlineSpiller.cpp Tue Jul 20 10:41:07 2010
@@ -14,6 +14,7 @@
 
 #define DEBUG_TYPE "spiller"
 #include "Spiller.h"
+#include "SplitKit.h"
 #include "VirtRegMap.h"
 #include "llvm/CodeGen/LiveIntervalAnalysis.h"
 #include "llvm/CodeGen/MachineFrameInfo.h"
@@ -39,6 +40,8 @@
   const TargetRegisterInfo &tri_;
   const BitVector reserved_;
 
+  SplitAnalysis splitAnalysis_;
+
   // Variables that are valid during spill(), but used by multiple methods.
   LiveInterval *li_;
   std::vector<LiveInterval*> *newIntervals_;
@@ -62,7 +65,8 @@
       mri_(mf->getRegInfo()),
       tii_(*mf->getTarget().getInstrInfo()),
       tri_(*mf->getTarget().getRegisterInfo()),
-      reserved_(tri_.getReservedRegs(mf_)) {}
+      reserved_(tri_.getReservedRegs(mf_)),
+      splitAnalysis_(mf, lis, mli) {}
 
   void spill(LiveInterval *li,
              std::vector<LiveInterval*> &newIntervals,
@@ -70,6 +74,8 @@
              SlotIndex *earliestIndex);
 
 private:
+  bool split();
+
   bool allUsesAvailableAt(const MachineInstr *OrigMI, SlotIndex OrigIdx,
                           SlotIndex UseIdx);
   bool reMaterializeFor(MachineBasicBlock::iterator MI);
@@ -91,6 +97,22 @@
 }
 }
 
+/// split - try splitting the current interval into pieces that may allocate
+/// separately. Return true if successful.
+bool InlineSpiller::split() {
+  // FIXME: Add intra-MBB splitting.
+  if (lis_.intervalIsInOneMBB(*li_))
+    return false;
+
+  splitAnalysis_.analyze(li_);
+
+  if (const MachineLoop *loop = splitAnalysis_.getBestSplitLoop()) {
+    if (splitAroundLoop(splitAnalysis_, loop))
+      return true;
+  }
+  return false;
+}
+
 /// allUsesAvailableAt - Return true if all registers used by OrigMI at
 /// OrigIdx are also available with the same value at UseIdx.
 bool InlineSpiller::allUsesAvailableAt(const MachineInstr *OrigMI,
@@ -338,6 +360,9 @@
   rc_ = mri_.getRegClass(li->reg);
   spillIs_ = &spillIs;
 
+  if (split())
+    return;
+
   reMaterializeAll();
 
   // Remat may handle everything.

Added: llvm/trunk/lib/CodeGen/SplitKit.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SplitKit.cpp?rev=108842&view=auto
==============================================================================
--- llvm/trunk/lib/CodeGen/SplitKit.cpp (added)
+++ llvm/trunk/lib/CodeGen/SplitKit.cpp Tue Jul 20 10:41:07 2010
@@ -0,0 +1,148 @@
+//===---------- SplitKit.cpp - Toolkit for splitting live ranges ----------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the SplitAnalysis class as well as mutator functions for
+// live range splitting.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "splitter"
+#include "SplitKit.h"
+#include "llvm/CodeGen/LiveIntervalAnalysis.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachineLoopInfo.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+
+
+//===----------------------------------------------------------------------===//
+//                                 Split Analysis
+//===----------------------------------------------------------------------===//
+
+SplitAnalysis::SplitAnalysis(const MachineFunction *mf,
+                             const LiveIntervals *lis,
+                             const MachineLoopInfo *mli)
+  : mf_(*mf),
+    lis_(*lis),
+    loops_(*mli),
+    curli_(0) {}
+
+void SplitAnalysis::clear() {
+  usingInstrs_.clear();
+  usingBlocks_.clear();
+  usingLoops_.clear();
+}
+
+/// analyseUses - Count instructions, basic blocks, and loops using curli.
+void SplitAnalysis::analyseUses() {
+  const MachineRegisterInfo &MRI = mf_.getRegInfo();
+  for (MachineRegisterInfo::reg_iterator I = MRI.reg_begin(curli_->reg);
+       MachineInstr *MI = I.skipInstruction();) {
+    if (MI->isDebugValue() || !usingInstrs_.insert(MI))
+      continue;
+    MachineBasicBlock *MBB = MI->getParent();
+    if (usingBlocks_[MBB]++)
+      continue;
+    if (MachineLoop *Loop = loops_.getLoopFor(MBB))
+      usingLoops_.insert(Loop);
+  }
+  DEBUG(dbgs() << "Counted "
+               << usingInstrs_.size() << " instrs, "
+               << usingBlocks_.size() << " blocks, "
+               << usingLoops_.size()  << " loops in "
+               << *curli_ << "\n");
+}
+
+SplitAnalysis::LoopPeripheralUse
+SplitAnalysis::analyzeLoopPeripheralUse(const MachineLoop *Loop) {
+  // Peripheral blocks.
+  SmallVector<MachineBasicBlock*, 16> Peri;
+  Loop->getExitBlocks(Peri);
+  if (MachineBasicBlock *PredBB = Loop->getLoopPredecessor())
+    Peri.push_back(PredBB);
+  array_pod_sort(Peri.begin(), Peri.end());
+  Peri.erase(std::unique(Peri.begin(), Peri.end()), Peri.end());
+
+  LoopPeripheralUse use = ContainedInLoop;
+  for (BlockCountMap::iterator I = usingBlocks_.begin(), E = usingBlocks_.end();
+       I != E; ++I) {
+    const MachineBasicBlock *MBB = I->first;
+    // Is this a peripheral block?
+    if (use < MultiPeripheral &&
+        std::binary_search(Peri.begin(), Peri.end(), MBB)) {
+      if (I->second > 1) use = MultiPeripheral;
+      else               use = SinglePeripheral;
+      continue;
+    }
+    // Is it a loop block?
+    if (Loop->contains(MBB))
+      continue;
+    // It must be an unrelated block.
+    return OutsideLoop;
+  }
+  return use;
+}
+
+void SplitAnalysis::analyze(const LiveInterval *li) {
+  clear();
+  curli_ = li;
+  analyseUses();
+}
+
+const MachineLoop *SplitAnalysis::getBestSplitLoop() {
+  LoopPtrSet Loops, SecondLoops;
+
+  // Find first-class and second class candidate loops.
+  // We prefer to split around loops where curli is used outside the periphery.
+  for (LoopPtrSet::const_iterator I = usingLoops_.begin(),
+       E = usingLoops_.end(); I != E; ++I)
+    switch(analyzeLoopPeripheralUse(*I)) {
+    case OutsideLoop:
+      Loops.insert(*I);
+      break;
+    case MultiPeripheral:
+      SecondLoops.insert(*I);
+      break;
+    default:
+      continue;
+    }
+
+  // If there are no first class loops available, look at second class loops.
+  if (Loops.empty())
+    Loops = SecondLoops;
+
+  if (Loops.empty())
+    return 0;
+
+  // Pick the earliest loop.
+  // FIXME: Are there other heuristics to consider?
+  // - avoid breaking critical edges.
+  // - avoid impossible loops.
+  const MachineLoop *Best = 0;
+  SlotIndex BestIdx;
+  for (LoopPtrSet::const_iterator I = Loops.begin(), E = Loops.end(); I != E;
+       ++I) {
+    SlotIndex Idx = lis_.getMBBStartIdx((*I)->getHeader());
+    if (!Best || Idx < BestIdx)
+      Best = *I, BestIdx = Idx;
+  }
+  return Best;
+}
+
+//===----------------------------------------------------------------------===//
+//                               Loop Splitting
+//===----------------------------------------------------------------------===//
+
+bool llvm::splitAroundLoop(SplitAnalysis &sa, const MachineLoop *loop) {
+  return false;
+}
+

Added: llvm/trunk/lib/CodeGen/SplitKit.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SplitKit.h?rev=108842&view=auto
==============================================================================
--- llvm/trunk/lib/CodeGen/SplitKit.h (added)
+++ llvm/trunk/lib/CodeGen/SplitKit.h Tue Jul 20 10:41:07 2010
@@ -0,0 +1,86 @@
+//===---------- SplitKit.cpp - Toolkit for splitting live ranges ----------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the SplitAnalysis class as well as mutator functions for
+// live range splitting.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/DenseMap.h"
+
+namespace llvm {
+
+class LiveInterval;
+class LiveIntervals;
+class MachineBasicBlock;
+class MachineInstr;
+class MachineFunction;
+class MachineFunctionPass;
+class MachineLoop;
+class MachineLoopInfo;
+
+class SplitAnalysis {
+  const MachineFunction &mf_;
+  const LiveIntervals &lis_;
+  const MachineLoopInfo &loops_;
+
+  // Current live interval.
+  const LiveInterval *curli_;
+
+  // Instructions using the the current register.
+  typedef SmallPtrSet<const MachineInstr*, 16> InstrPtrSet;
+  InstrPtrSet usingInstrs_;
+
+  // The number of instructions using curli in each basic block.
+  typedef DenseMap<const MachineBasicBlock*, unsigned> BlockCountMap;
+  BlockCountMap usingBlocks_;
+
+  // Loops where the curent interval is used.
+  typedef SmallPtrSet<const MachineLoop*, 16> LoopPtrSet;
+  LoopPtrSet usingLoops_;
+
+  // Sumarize statistics by counting instructions using curli_.
+  void analyseUses();
+
+public:
+  SplitAnalysis(const MachineFunction *mf, const LiveIntervals *lis,
+                const MachineLoopInfo *mli);
+
+  /// analyze - set curli to the specified interval, and analyze how it may be
+  /// split.
+  void analyze(const LiveInterval *li);
+
+  /// clear - clear all data structures so SplitAnalysis is ready to analyze a
+  /// new interval.
+  void clear();
+
+  /// LoopPeripheralUse - how is a variable used in and around a loop?
+  /// Peripheral blocks are the loop predecessors and exit blocks.
+  enum LoopPeripheralUse {
+    ContainedInLoop,  // All uses are inside the loop.
+    SinglePeripheral, // At most one instruction per peripheral block.
+    MultiPeripheral,  // Multiple instructions in some peripheral blocks.
+    OutsideLoop       // Uses outside loop periphery.
+  };
+
+  /// analyzeLoopPeripheralUse - Return an enum describing how curli_ is used in
+  /// and around the Loop.
+  LoopPeripheralUse analyzeLoopPeripheralUse(const MachineLoop*);
+
+  /// getBestSplitLoop - Return the loop where curli may best be split to a
+  /// separate register, or NULL.
+  const MachineLoop *getBestSplitLoop();
+};
+
+/// splitAroundLoop - Try to split curli into a separate live interval inside
+/// the loop. Retun true on success.
+bool splitAroundLoop(SplitAnalysis&, const MachineLoop*);
+
+}





More information about the llvm-commits mailing list