diff --git a/include/llvm/CodeGen/LinkAllCodegenComponents.h b/include/llvm/CodeGen/LinkAllCodegenComponents.h index 59c0482efc3..bc06d43b8fc 100644 --- a/include/llvm/CodeGen/LinkAllCodegenComponents.h +++ b/include/llvm/CodeGen/LinkAllCodegenComponents.h @@ -34,6 +34,7 @@ namespace { (void) llvm::createDeadMachineInstructionElimPass(); (void) llvm::createFastRegisterAllocator(); + (void) llvm::createBasicRegisterAllocator(); (void) llvm::createLinearScanRegisterAllocator(); (void) llvm::createDefaultPBQPRegisterAllocator(); diff --git a/include/llvm/CodeGen/Passes.h b/include/llvm/CodeGen/Passes.h index 7e135617fa6..72dd3b85291 100644 --- a/include/llvm/CodeGen/Passes.h +++ b/include/llvm/CodeGen/Passes.h @@ -95,6 +95,11 @@ namespace llvm { /// FunctionPass *createFastRegisterAllocator(); + /// BasicRegisterAllocation Pass - This pass implements a degenerate global + /// register allocator using the basic regalloc framework. + /// + FunctionPass *createBasicRegisterAllocator(); + /// LinearScanRegisterAllocation Pass - This pass implements the linear scan /// register allocation algorithm, a global register allocator. /// diff --git a/lib/CodeGen/CMakeLists.txt b/lib/CodeGen/CMakeLists.txt index dbf5dca3f22..effd03c3511 100644 --- a/lib/CodeGen/CMakeLists.txt +++ b/lib/CodeGen/CMakeLists.txt @@ -21,6 +21,7 @@ add_llvm_library(LLVMCodeGen LatencyPriorityQueue.cpp LiveInterval.cpp LiveIntervalAnalysis.cpp + LiveIntervalUnion.cpp LiveStackAnalysis.cpp LiveVariables.cpp LiveRangeEdit.cpp @@ -55,6 +56,7 @@ add_llvm_library(LLVMCodeGen ProcessImplicitDefs.cpp PrologEpilogInserter.cpp PseudoSourceValue.cpp + RegAllocBasic.cpp RegAllocFast.cpp RegAllocLinearScan.cpp RegAllocPBQP.cpp diff --git a/lib/CodeGen/LiveIntervalUnion.cpp b/lib/CodeGen/LiveIntervalUnion.cpp new file mode 100644 index 00000000000..b22f466367e --- /dev/null +++ b/lib/CodeGen/LiveIntervalUnion.cpp @@ -0,0 +1,167 @@ +//===-- LiveIntervalUnion.cpp - Live interval union data structure --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// LiveIntervalUnion represents a coalesced set of live intervals. This may be +// used during coalescing to represent a congruence class, or during register +// allocation to model liveness of a physical register. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "regalloc" +#include "LiveIntervalUnion.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include +using namespace llvm; + +// Merge a LiveInterval's segments. Guarantee no overlaps. +void LiveIntervalUnion::unify(LiveInterval &lvr) { + // Add this live virtual register to the union + LiveVirtRegs::iterator pos = std::upper_bound(lvrs_.begin(), lvrs_.end(), + &lvr, less_ptr()); + assert(pos == lvrs_.end() || *pos != &lvr && "duplicate LVR insertion"); + lvrs_.insert(pos, &lvr); + // Insert each of the virtual register's live segments into the map + SegmentIter segPos = segments_.begin(); + for (LiveInterval::iterator lvrI = lvr.begin(), lvrEnd = lvr.end(); + lvrI != lvrEnd; ++lvrI ) { + LiveSegment segment(lvrI->start, lvrI->end, lvr); + segPos = segments_.insert(segPos, segment); + assert(*segPos == segment && "need equal val for equal key"); + } +} + +namespace { + +// Keep LVRs sorted for fast membership test and extraction. +struct LessReg + : public std::binary_function { + bool operator()(const LiveInterval *left, const LiveInterval *right) const { + return left->reg < right->reg; + } +}; + +// Low-level helper to find the first segment in the range [segI,segEnd) that +// intersects with a live virtual register segment, or segI.start >= lvr.end +// +// This logic is tied to the underlying LiveSegments data structure. For now, we +// use a binary search within the vector to find the nearest starting position, +// then reverse iterate to find the first overlap. +// +// Upon entry we have segI.start < lvrSeg.end +// seg |--... +// \ . +// lvr ...-| +// +// After binary search, we have segI.start >= lvrSeg.start: +// seg |--... +// / +// lvr |--... +// +// Assuming intervals are disjoint, if an intersection exists, it must be the +// segment found or immediately behind it. We continue reverse iterating to +// return the first overlap. +// +// FIXME: support extract(), handle tombstones of extracted lvrs. +typedef LiveIntervalUnion::SegmentIter SegmentIter; +SegmentIter upperBound(SegmentIter segBegin, + SegmentIter segEnd, + const LiveRange &lvrSeg) { + assert(lvrSeg.end > segBegin->start && "segment iterator precondition"); + // get the next LIU segment such that setg.start is not less than + // lvrSeg.start + SegmentIter segI = std::upper_bound(segBegin, segEnd, lvrSeg.start); + while (segI != segBegin) { + --segI; + if (lvrSeg.start >= segI->end) + return ++segI; + } + return segI; +} +} // end anonymous namespace + +// Private interface accessed by Query. +// +// Find a pair of segments that intersect, one in the live virtual register +// (LiveInterval), and the other in this LiveIntervalUnion. The caller (Query) +// is responsible for advancing the LiveIntervalUnion segments to find a +// "notable" intersection, which requires query-specific logic. +// +// This design assumes only a fast mechanism for intersecting a single live +// virtual register segment with a set of LiveIntervalUnion segments. This may +// be ok since most LVRs have very few segments. If we had a data +// structure that optimizd MxN intersection of segments, then we would bypass +// the loop that advances within the LiveInterval. +// +// If no intersection exists, set lvrI = lvrEnd, and set segI to the first +// segment whose start point is greater than LiveInterval's end point. +// +// Assumes that segments are sorted by start position in both +// LiveInterval and LiveSegments. +void LiveIntervalUnion::Query::findIntersection(InterferenceResult &ir) const { + LiveInterval::iterator lvrEnd = lvr_.end(); + SegmentIter liuEnd = liu_.end(); + while (ir.liuSegI_ != liuEnd) { + // Slowly advance the live virtual reg iterator until we surpass the next + // segment in this union. If this is ever used for coalescing of fixed + // registers and we have a LiveInterval with thousands of segments, then use + // upper bound instead. + while (ir.lvrSegI_ != lvrEnd && ir.lvrSegI_->end <= ir.liuSegI_->start) + ++ir.lvrSegI_; + if (ir.lvrSegI_ == lvrEnd) + break; + // lvrSegI_ may have advanced far beyond liuSegI_, + // do a fast intersection test to "catch up" + ir.liuSegI_ = upperBound(ir.liuSegI_, liuEnd, *ir.lvrSegI_); + // Check if no liuSegI_ exists with lvrSegI_->start < liuSegI_.end + if (ir.liuSegI_ == liuEnd) + break; + if (ir.liuSegI_->start < ir.lvrSegI_->end) { + assert(overlap(*ir.lvrSegI_, *ir.liuSegI_) && "upperBound postcondition"); + break; + } + } + if (ir.liuSegI_ == liuEnd) + ir.lvrSegI_ = lvrEnd; +} + +// Find the first intersection, and cache interference info +// (retain segment iterators into both lvr_ and liu_). +LiveIntervalUnion::InterferenceResult +LiveIntervalUnion::Query::firstInterference() { + if (firstInterference_ != LiveIntervalUnion::InterferenceResult()) { + return firstInterference_; + } + firstInterference_ = InterferenceResult(lvr_.begin(), liu_.begin()); + findIntersection(firstInterference_); + return firstInterference_; +} + +// Treat the result as an iterator and advance to the next interfering pair +// of segments. This is a plain iterator with no filter. +bool LiveIntervalUnion::Query::nextInterference(InterferenceResult &ir) const { + assert(isInterference(ir) && "iteration past end of interferences"); + // Advance either the lvr or liu segment to ensure that we visit all unique + // overlapping pairs. + if (ir.lvrSegI_->end < ir.liuSegI_->end) { + if (++ir.lvrSegI_ == lvr_.end()) + return false; + } + else { + if (++ir.liuSegI_ == liu_.end()) { + ir.lvrSegI_ = lvr_.end(); + return false; + } + } + if (overlap(*ir.lvrSegI_, *ir.liuSegI_)) + return true; + // find the next intersection + findIntersection(ir); + return isInterference(ir); +} diff --git a/lib/CodeGen/LiveIntervalUnion.h b/lib/CodeGen/LiveIntervalUnion.h new file mode 100644 index 00000000000..3953c5930ad --- /dev/null +++ b/lib/CodeGen/LiveIntervalUnion.h @@ -0,0 +1,193 @@ +//===-- LiveIntervalUnion.h - Live interval union data struct --*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// LiveIntervalUnion is a union of live segments across multiple live virtual +// registers. This may be used during coalescing to represent a congruence +// class, or during register allocation to model liveness of a physical +// register. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_LIVEINTERVALUNION +#define LLVM_CODEGEN_LIVEINTERVALUNION + +#include "llvm/CodeGen/LiveInterval.h" +#include +#include + +namespace llvm { + +// A LiveSegment is a copy of a LiveRange object used within +// LiveIntervalUnion. LiveSegment additionally contains a pointer to its +// original live virtual register (LiveInterval). This allows quick lookup of +// the live virtual register as we iterate over live segments in a union. Note +// that LiveRange is misnamed and actually represents only a single contiguous +// interval within a virtual register's liveness. To limit confusion, in this +// file we refer it as a live segment. +struct LiveSegment { + SlotIndex start; + SlotIndex end; + LiveInterval *liveVirtReg; + + LiveSegment(SlotIndex s, SlotIndex e, LiveInterval &lvr) + : start(s), end(e), liveVirtReg(&lvr) {} + + bool operator==(const LiveSegment &ls) const { + return start == ls.start && end == ls.end && liveVirtReg == ls.liveVirtReg; + } + + bool operator!=(const LiveSegment &ls) const { + return !operator==(ls); + } + + bool operator<(const LiveSegment &ls) const { + return start < ls.start || (start == ls.start && end < ls.end); + } +}; + +/// Compare a live virtual register segment to a LiveIntervalUnion segment. +inline bool overlap(const LiveRange &lvrSeg, const LiveSegment &liuSeg) { + return lvrSeg.start < liuSeg.end && liuSeg.start < lvrSeg.end; +} + +inline bool operator<(SlotIndex V, const LiveSegment &ls) { + return V < ls.start; +} + +inline bool operator<(const LiveSegment &ls, SlotIndex V) { + return ls.start < V; +} + +/// Union of live intervals that are strong candidates for coalescing into a +/// single register (either physical or virtual depending on the context). We +/// expect the constituent live intervals to be disjoint, although we may +/// eventually make exceptions to handle value-based interference. +class LiveIntervalUnion { + // A set of live virtual register segments that supports fast insertion, + // intersection, and removal. + // + // FIXME: std::set is a placeholder until we decide how to + // efficiently represent it. Probably need to roll our own B-tree. + typedef std::set LiveSegments; + + // A set of live virtual registers. Elements have type LiveInterval, where + // each element represents the liveness of a single live virtual register. + // This is traditionally known as a live range, but we refer is as a live + // virtual register to avoid confusing it with the misnamed LiveRange + // class. + typedef std::vector LiveVirtRegs; + +public: + // SegmentIter can advance to the next segment ordered by starting position + // which may belong to a different live virtual register. We also must be able + // to reach the current segment's containing virtual register. + typedef LiveSegments::iterator SegmentIter; + + class InterferenceResult; + class Query; + +private: + unsigned repReg_; // representative register number + LiveSegments segments_; // union of virtual reg segements + LiveVirtRegs lvrs_; // set of live virtual regs in the union + +public: + // default ctor avoids placement new + LiveIntervalUnion() : repReg_(0) {} + + void init(unsigned repReg) { repReg_ = repReg; } + + SegmentIter begin() { return segments_.begin(); } + SegmentIter end() { return segments_.end(); } + + /// FIXME: !!!!!!!!!!! Keeps a non-const ref + void unify(LiveInterval &lvr); + + // FIXME: needed by RegAllocGreedy + //void extract(const LiveInterval &li); + + /// Cache a single interference test result in the form of two intersecting + /// segments. This allows efficiently iterating over the interferences. The + /// iteration logic is handled by LiveIntervalUnion::Query which may + /// filter interferences depending on the type of query. + class InterferenceResult { + friend class Query; + + LiveInterval::iterator lvrSegI_; // current position in _lvr + SegmentIter liuSegI_; // current position in _liu + + // Internal ctor. + InterferenceResult(LiveInterval::iterator lvrSegI, SegmentIter liuSegI) + : lvrSegI_(lvrSegI), liuSegI_(liuSegI) {} + + public: + // Public default ctor. + InterferenceResult(): lvrSegI_(), liuSegI_() {} + + // Note: this interface provides raw access to the iterators because the + // result has no way to tell if it's valid to dereference them. + + // Access the lvr segment. + const LiveInterval::iterator &lvrSegPos() const { return lvrSegI_; } + + // Access the liu segment. + const SegmentIter &liuSeg() const { return liuSegI_; } + + bool operator==(const InterferenceResult &ir) const { + return lvrSegI_ == ir.lvrSegI_ && liuSegI_ == ir.liuSegI_; + } + bool operator!=(const InterferenceResult &ir) const { + return !operator==(ir); + } + }; + + /// Query interferences between a single live virtual register and a live + /// interval union. + class Query { + LiveIntervalUnion &liu_; + LiveInterval &lvr_; + InterferenceResult firstInterference_; + // TBD: interfering vregs + + public: + Query(LiveInterval &lvr, LiveIntervalUnion &liu): liu_(liu), lvr_(lvr) {} + + LiveInterval &lvr() const { return lvr_; } + + bool isInterference(const InterferenceResult &ir) const { + if (ir.lvrSegI_ != lvr_.end()) { + assert(overlap(*ir.lvrSegI_, *ir.liuSegI_) && + "invalid segment iterators"); + return true; + } + return false; + } + + // Does this live virtual register interfere with the union. + bool checkInterference() { return isInterference(firstInterference()); } + + // First pair of interfering segments, or a noninterfering result. + InterferenceResult firstInterference(); + + // Treat the result as an iterator and advance to the next interfering pair + // of segments. Visiting each unique interfering pairs means that the same + // lvr or liu segment may be visited multiple times. + bool nextInterference(InterferenceResult &ir) const; + + // TBD: bool collectInterferingVirtRegs(unsigned maxInterference) + + private: + // Private interface for queries + void findIntersection(InterferenceResult &ir) const; + }; +}; + +} // end namespace llvm + +#endif // !defined(LLVM_CODEGEN_LIVEINTERVALUNION) diff --git a/lib/CodeGen/RegAllocBase.h b/lib/CodeGen/RegAllocBase.h new file mode 100644 index 00000000000..a972fbf1108 --- /dev/null +++ b/lib/CodeGen/RegAllocBase.h @@ -0,0 +1,179 @@ +//===-- RegAllocBase.h - basic regalloc interface and driver --*- C++ -*---===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the RegAllocBase class, which is the skeleton of a basic +// register allocation algorithm and interface for extending it. It provides the +// building blocks on which to construct other experimental allocators and test +// the validity of two principles: +// +// - If virtual and physical register liveness is modeled using intervals, then +// on-the-fly interference checking is cheap. Furthermore, interferences can be +// lazily cached and reused. +// +// - Register allocation complexity, and generated code performance is +// determined by the effectiveness of live range splitting rather than optimal +// coloring. +// +// Following the first principle, interfering checking revolves around the +// LiveIntervalUnion data structure. +// +// To fulfill the second principle, the basic allocator provides a driver for +// incremental splitting. It essentially punts on the problem of register +// coloring, instead driving the assignment of virtual to physical registers by +// the cost of splitting. The basic allocator allows for heuristic reassignment +// of registers, if a more sophisticated allocator chooses to do that. +// +// This framework provides a way to engineer the compile time vs. code +// quality trade-off without relying a particular theoretical solver. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_REGALLOCBASE +#define LLVM_CODEGEN_REGALLOCBASE + +#include "LiveIntervalUnion.h" +#include "VirtRegMap.h" +#include "llvm/CodeGen/LiveIntervalAnalysis.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/ADT/OwningPtr.h" +#include +#include + +namespace llvm { + +class VirtRegMap; + +/// RegAllocBase provides the register allocation driver and interface that can +/// be extended to add interesting heuristics. +/// +/// More sophisticated allocators must override the selectOrSplit() method to +/// implement live range splitting and must specify a comparator to determine +/// register assignment priority. LessSpillWeightPriority is provided as a +/// standard comparator. +class RegAllocBase { +protected: + typedef SmallVector LiveVirtRegs; + typedef LiveVirtRegs::iterator LVRIter; + + // Array of LiveIntervalUnions indexed by physical register. + class LIUArray { + unsigned nRegs_; + OwningArrayPtr array_; + public: + LIUArray(): nRegs_(0) {} + + unsigned numRegs() const { return nRegs_; } + + void init(unsigned nRegs); + + void clear(); + + LiveIntervalUnion& operator[](unsigned physReg) { + assert(physReg < nRegs_ && "physReg out of bounds"); + return array_[physReg]; + } + }; + + const TargetRegisterInfo *tri_; + VirtRegMap *vrm_; + LiveIntervals *lis_; + LIUArray physReg2liu_; + + RegAllocBase(): tri_(0), vrm_(0), lis_(0) {} + + // A RegAlloc pass should call this before allocatePhysRegs. + void init(const TargetRegisterInfo &tri, VirtRegMap &vrm, LiveIntervals &lis); + + // The top-level driver. Specialize with the comparator that determines the + // priority of assigning live virtual registers. The output is a VirtRegMap + // that us updated with physical register assignments. + template + void allocatePhysRegs(LICompare liCompare); + + // A RegAlloc pass should override this to provide the allocation heuristics. + // Each call must guarantee forward progess by returning an available + // PhysReg or new set of split LiveVirtRegs. It is up to the splitter to + // converge quickly toward fully spilled live ranges. + virtual unsigned selectOrSplit(LiveInterval &lvr, + LiveVirtRegs &splitLVRs) = 0; + + // A RegAlloc pass should call this when PassManager releases its memory. + virtual void releaseMemory(); + + // Helper for checking interference between a live virtual register and a + // physical register, including all its register aliases. + bool checkPhysRegInterference(LiveIntervalUnion::Query &query, unsigned preg); + +private: + template + void seedLiveVirtRegs(PQ &lvrQ); +}; + +// Heuristic that determines the priority of assigning virtual to physical +// registers. The main impact of the heuristic is expected to be compile time. +// The default is to simply compare spill weights. +struct LessSpillWeightPriority + : public std::binary_function { + bool operator()(const LiveInterval *left, const LiveInterval *right) const { + return left->weight < right->weight; + } +}; + +// Visit all the live virtual registers. If they are already assigned to a +// physical register, unify them with the corresponding LiveIntervalUnion, +// otherwise push them on the priority queue for later assignment. +template +void RegAllocBase::seedLiveVirtRegs(PQ &lvrQ) { + for (LiveIntervals::iterator liItr = lis_->begin(), liEnd = lis_->end(); + liItr != liEnd; ++liItr) { + unsigned reg = liItr->first; + LiveInterval &li = *liItr->second; + if (TargetRegisterInfo::isPhysicalRegister(reg)) { + physReg2liu_[reg].unify(li); + } + else { + lvrQ.push(&li); + } + } +} + +// Top-level driver to manage the queue of unassigned LiveVirtRegs and call the +// selectOrSplit implementation. +template +void RegAllocBase::allocatePhysRegs(LICompare liCompare) { + typedef std::priority_queue + , LICompare> LiveVirtRegQueue; + + LiveVirtRegQueue lvrQ(liCompare); + seedLiveVirtRegs(lvrQ); + while (!lvrQ.empty()) { + LiveInterval *lvr = lvrQ.top(); + lvrQ.pop(); + LiveVirtRegs splitLVRs; + unsigned availablePhysReg = selectOrSplit(*lvr, splitLVRs); + if (availablePhysReg) { + assert(splitLVRs.empty() && "inconsistent splitting"); + assert(!vrm_->hasPhys(lvr->reg) && "duplicate vreg in interval unions"); + vrm_->assignVirt2Phys(lvr->reg, availablePhysReg); + physReg2liu_[availablePhysReg].unify(*lvr); + } + else { + for (LVRIter lvrI = splitLVRs.begin(), lvrEnd = splitLVRs.end(); + lvrI != lvrEnd; ++lvrI ) { + assert(TargetRegisterInfo::isVirtualRegister((*lvrI)->reg) && + "expect split value in virtual register"); + lvrQ.push(*lvrI); + } + } + } +} + +} // end namespace llvm + +#endif // !defined(LLVM_CODEGEN_REGALLOCBASE) diff --git a/lib/CodeGen/RegAllocBasic.cpp b/lib/CodeGen/RegAllocBasic.cpp new file mode 100644 index 00000000000..ce5f9cfce85 --- /dev/null +++ b/lib/CodeGen/RegAllocBasic.cpp @@ -0,0 +1,259 @@ +//===-- RegAllocBasic.cpp - basic register allocator ----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the RABasic function pass, which provides a minimal +// implementation of the basic register allocator. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "regalloc" +#include "RegAllocBase.h" +#include "RenderMachineFunction.h" +#include "Spiller.h" +#include "VirtRegRewriter.h" +#include "llvm/Function.h" +#include "llvm/PassAnalysisSupport.h" +#include "llvm/CodeGen/CalcSpillWeights.h" +#include "llvm/CodeGen/LiveStackAnalysis.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/RegAllocRegistry.h" +#include "llvm/CodeGen/RegisterCoalescer.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +static RegisterRegAlloc basicRegAlloc("basic", "basic register allocator", + createBasicRegisterAllocator); + +namespace { + +/// RABasic provides a minimal implementation of the basic register allocation +/// algorithm. It prioritizes live virtual registers by spill weight and spills +/// whenever a register is unavailable. This is not practical in production but +/// provides a useful baseline both for measuring other allocators and comparing +/// the speed of the basic algorithm against other styles of allocators. +class RABasic : public MachineFunctionPass, public RegAllocBase +{ + // context + MachineFunction *mf_; + const TargetMachine *tm_; + MachineRegisterInfo *mri_; + + // analyses + LiveStacks *ls_; + RenderMachineFunction *rmf_; + + // state + std::auto_ptr spiller_; + +public: + RABasic(); + + /// Return the pass name. + virtual const char* getPassName() const { + return "Basic Register Allocator"; + } + + /// RABasic analysis usage. + virtual void getAnalysisUsage(AnalysisUsage &au) const; + + virtual void releaseMemory(); + + virtual unsigned selectOrSplit(LiveInterval &lvr, LiveVirtRegs &splitLVRs); + + /// Perform register allocation. + virtual bool runOnMachineFunction(MachineFunction &mf); + + static char ID; +}; + +char RABasic::ID = 0; + +} // end anonymous namespace + +// We should not need to publish the initializer as long as no other passes +// require RABasic. +#if 0 // disable INITIALIZE_PASS +INITIALIZE_PASS_BEGIN(RABasic, "basic-regalloc", + "Basic Register Allocator", false, false) +INITIALIZE_PASS_DEPENDENCY(LiveIntervals) +INITIALIZE_PASS_DEPENDENCY(StrongPHIElimination) +INITIALIZE_AG_DEPENDENCY(RegisterCoalescer) +INITIALIZE_PASS_DEPENDENCY(CalculateSpillWeights) +INITIALIZE_PASS_DEPENDENCY(LiveStacks) +INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo) +INITIALIZE_PASS_DEPENDENCY(VirtRegMap) +#ifndef NDEBUG +INITIALIZE_PASS_DEPENDENCY(RenderMachineFunction) +#endif +INITIALIZE_PASS_END(RABasic, "basic-regalloc", + "Basic Register Allocator", false, false) +#endif // INITIALIZE_PASS + +RABasic::RABasic(): MachineFunctionPass(ID) { + initializeLiveIntervalsPass(*PassRegistry::getPassRegistry()); + initializeSlotIndexesPass(*PassRegistry::getPassRegistry()); + initializeStrongPHIEliminationPass(*PassRegistry::getPassRegistry()); + initializeRegisterCoalescerAnalysisGroup(*PassRegistry::getPassRegistry()); + initializeCalculateSpillWeightsPass(*PassRegistry::getPassRegistry()); + initializeLiveStacksPass(*PassRegistry::getPassRegistry()); + initializeMachineLoopInfoPass(*PassRegistry::getPassRegistry()); + initializeVirtRegMapPass(*PassRegistry::getPassRegistry()); + initializeRenderMachineFunctionPass(*PassRegistry::getPassRegistry()); +} + +void RABasic::getAnalysisUsage(AnalysisUsage &au) const { + au.setPreservesCFG(); + au.addRequired(); + au.addPreserved(); + if (StrongPHIElim) + au.addRequiredID(StrongPHIEliminationID); + au.addRequiredTransitive(); + au.addRequired(); + au.addRequired(); + au.addPreserved(); + au.addRequired(); + au.addPreserved(); + au.addRequired(); + au.addPreserved(); + DEBUG(au.addRequired()); + MachineFunctionPass::getAnalysisUsage(au); +} + +void RABasic::releaseMemory() { + spiller_.reset(0); + RegAllocBase::releaseMemory(); +} + +//===----------------------------------------------------------------------===// +// RegAllocBase Implementation +//===----------------------------------------------------------------------===// + +// Instantiate a LiveIntervalUnion for each physical register. +void RegAllocBase::LIUArray::init(unsigned nRegs) { + array_.reset(new LiveIntervalUnion[nRegs]); + nRegs_ = nRegs; + for (unsigned pr = 0; pr < nRegs; ++pr) { + array_[pr].init(pr); + } +} + +void RegAllocBase::init(const TargetRegisterInfo &tri, VirtRegMap &vrm, + LiveIntervals &lis) { + tri_ = &tri; + vrm_ = &vrm; + lis_ = &lis; + physReg2liu_.init(tri_->getNumRegs()); +} + +void RegAllocBase::LIUArray::clear() { + nRegs_ = 0; + array_.reset(0); +} + +void RegAllocBase::releaseMemory() { + physReg2liu_.clear(); +} + +// Check if this live virtual reg interferes with a physical register. If not, +// then check for interference on each register that aliases with the physical +// register. +bool RegAllocBase::checkPhysRegInterference(LiveIntervalUnion::Query &query, + unsigned preg) { + if (query.checkInterference()) + return true; + for (const unsigned *asI = tri_->getAliasSet(preg); *asI; ++asI) { + // We assume it's very unlikely for a register in the alias set to also be + // in the original register class. So we don't bother caching the + // interference. + LiveIntervalUnion::Query subQuery(query.lvr(), physReg2liu_[*asI] ); + if (subQuery.checkInterference()) + return true; + } + return false; +} + +//===----------------------------------------------------------------------===// +// RABasic Implementation +//===----------------------------------------------------------------------===// + +// Driver for the register assignment and splitting heuristics. +// Manages iteration over the LiveIntervalUnions. +// +// Minimal implementation of register assignment and splitting--spills whenever +// we run out of registers. +// +// selectOrSplit can only be called once per live virtual register. We then do a +// single interference test for each register the correct class until we find an +// available register. So, the number of interference tests in the worst case is +// |vregs| * |machineregs|. And since the number of interference tests is +// minimal, there is no value in caching them. +unsigned RABasic::selectOrSplit(LiveInterval &lvr, LiveVirtRegs &splitLVRs) { + // Check for an available reg in this class. + const TargetRegisterClass *trc = mri_->getRegClass(lvr.reg); + for (TargetRegisterClass::iterator trcI = trc->allocation_order_begin(*mf_), + trcEnd = trc->allocation_order_end(*mf_); + trcI != trcEnd; ++trcI) { + unsigned preg = *trcI; + LiveIntervalUnion::Query query(lvr, physReg2liu_[preg]); + if (!checkPhysRegInterference(query, preg)) { + DEBUG(dbgs() << "\tallocating: " << tri_->getName(preg) << lvr << '\n'); + return preg; + } + } + DEBUG(dbgs() << "\tspilling: " << lvr << '\n'); + SmallVector spillIs; // ignored + spiller_->spill(&lvr, splitLVRs, spillIs); + + // FIXME: update LiveStacks + return 0; +} + +bool RABasic::runOnMachineFunction(MachineFunction &mf) { + DEBUG(dbgs() << "********** BASIC REGISTER ALLOCATION **********\n" + << "********** Function: " + << ((Value*)mf.getFunction())->getName() << '\n'); + + mf_ = &mf; + tm_ = &mf.getTarget(); + mri_ = &mf.getRegInfo(); + + DEBUG(rmf_ = &getAnalysis()); + + RegAllocBase::init(*tm_->getRegisterInfo(), getAnalysis(), + getAnalysis()); + + spiller_.reset(createSpiller(*this, *mf_, *vrm_)); + + allocatePhysRegs(LessSpillWeightPriority()); + + // Diagnostic output before rewriting + DEBUG(dbgs() << "Post alloc VirtRegMap:\n" << *vrm_ << "\n"); + + // optional HTML output + DEBUG(rmf_->renderMachineFunction("After basic register allocation.", vrm_)); + + // Run rewriter + std::auto_ptr rewriter(createVirtRegRewriter()); + rewriter->runOnMachineFunction(*mf_, *vrm_, lis_); + + return true; +} + +FunctionPass* llvm::createBasicRegisterAllocator() +{ + return new RABasic(); +} diff --git a/lib/CodeGen/SplitKit.h b/lib/CodeGen/SplitKit.h index 80fc23642a8..d9f16dc9155 100644 --- a/lib/CodeGen/SplitKit.h +++ b/lib/CodeGen/SplitKit.h @@ -1,4 +1,4 @@ -//===---------- SplitKit.cpp - Toolkit for splitting live ranges ----------===// +//===-------- SplitKit.cpp - Toolkit for splitting live ranges --*- C++ -*-===// // // The LLVM Compiler Infrastructure //