aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/SplitKit.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/SplitKit.cpp')
-rw-r--r--lib/CodeGen/SplitKit.cpp148
1 files changed, 148 insertions, 0 deletions
diff --git a/lib/CodeGen/SplitKit.cpp b/lib/CodeGen/SplitKit.cpp
new file mode 100644
index 0000000000..4fbca10319
--- /dev/null
+++ b/lib/CodeGen/SplitKit.cpp
@@ -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;
+}
+