diff options
Diffstat (limited to 'lib/CodeGen/SplitKit.cpp')
-rw-r--r-- | lib/CodeGen/SplitKit.cpp | 148 |
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; +} + |