//
//===----------------------------------------------------------------------===//
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/IndexedMap.h"
#include "llvm/ADT/IntervalMap.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/CodeGen/SlotIndexes.h"
class LiveIntervals;
class LiveRangeEdit;
class MachineInstr;
-class MachineLoop;
class MachineLoopInfo;
class MachineRegisterInfo;
class TargetInstrInfo;
class SplitAnalysis {
public:
const MachineFunction &MF;
+ const VirtRegMap &VRM;
const LiveIntervals &LIS;
const MachineLoopInfo &Loops;
const TargetInstrInfo &TII;
- // Instructions using the the current register.
- typedef SmallPtrSet<const MachineInstr*, 16> InstrPtrSet;
- InstrPtrSet UsingInstrs;
-
// Sorted slot indexes of using instructions.
SmallVector<SlotIndex, 8> UseSlots;
- // The number of instructions using CurLI in each basic block.
- typedef DenseMap<const MachineBasicBlock*, unsigned> BlockCountMap;
- BlockCountMap UsingBlocks;
-
- // The number of basic block using CurLI in each loop.
- typedef DenseMap<const MachineLoop*, unsigned> LoopCountMap;
- LoopCountMap UsingLoops;
-
/// Additional information about basic blocks where the current variable is
/// live. Such a block will look like one of these templates:
///
SlotIndex LastUse; ///< Last instr using current reg.
SlotIndex Kill; ///< Interval end point inside block.
SlotIndex Def; ///< Interval start point inside block.
- /// Last possible point for splitting live ranges.
- SlotIndex LastSplitPoint;
- bool Uses; ///< Current reg has uses or defs in block.
bool LiveThrough; ///< Live in whole block (Templ 5. or 6. above).
bool LiveIn; ///< Current reg is live in.
bool LiveOut; ///< Current reg is live out.
-
- // Per-interference pattern scratch data.
- bool OverlapEntry; ///< Interference overlaps entering interval.
- bool OverlapExit; ///< Interference overlaps exiting interval.
};
- /// Basic blocks where var is live. This array is parallel to
- /// SpillConstraints.
- SmallVector<BlockInfo, 8> LiveBlocks;
-
private:
// Current live interval.
const LiveInterval *CurLI;
+ /// LastSplitPoint - Last legal split point in each basic block in the current
+ /// function. The first entry is the first terminator, the second entry is the
+ /// last valid split point for a variable that is live in to a landing pad
+ /// successor.
+ SmallVector<std::pair<SlotIndex, SlotIndex>, 8> LastSplitPoint;
+
+ /// UseBlocks - Blocks where CurLI has uses.
+ SmallVector<BlockInfo, 8> UseBlocks;
+
+ /// ThroughBlocks - Block numbers where CurLI is live through without uses.
+ BitVector ThroughBlocks;
+
+ /// NumThroughBlocks - Number of live-through blocks.
+ unsigned NumThroughBlocks;
+
+ SlotIndex computeLastSplitPoint(unsigned Num);
+
// Sumarize statistics by counting instructions using CurLI.
void analyzeUses();
/// calcLiveBlockInfo - Compute per-block information about CurLI.
- void calcLiveBlockInfo();
-
- /// canAnalyzeBranch - Return true if MBB ends in a branch that can be
- /// analyzed.
- bool canAnalyzeBranch(const MachineBasicBlock *MBB);
+ bool calcLiveBlockInfo();
public:
- SplitAnalysis(const MachineFunction &mf, const LiveIntervals &lis,
+ SplitAnalysis(const VirtRegMap &vrm, const LiveIntervals &lis,
const MachineLoopInfo &mli);
/// analyze - set CurLI to the specified interval, and analyze how it may be
/// new interval.
void clear();
- /// hasUses - Return true if MBB has any uses of CurLI.
- bool hasUses(const MachineBasicBlock *MBB) const {
- return UsingBlocks.lookup(MBB);
+ /// getParent - Return the last analyzed interval.
+ const LiveInterval &getParent() const { return *CurLI; }
+
+ /// getLastSplitPoint - Return that base index of the last valid split point
+ /// in the basic block numbered Num.
+ SlotIndex getLastSplitPoint(unsigned Num) {
+ // Inline the common simple case.
+ if (LastSplitPoint[Num].first.isValid() &&
+ !LastSplitPoint[Num].second.isValid())
+ return LastSplitPoint[Num].first;
+ return computeLastSplitPoint(Num);
}
- typedef SmallPtrSet<const MachineBasicBlock*, 16> BlockPtrSet;
- typedef SmallPtrSet<const MachineLoop*, 16> LoopPtrSet;
-
- // Print a set of blocks with use counts.
- void print(const BlockPtrSet&, raw_ostream&) const;
-
- // Sets of basic blocks surrounding a machine loop.
- struct LoopBlocks {
- BlockPtrSet Loop; // Blocks in the loop.
- BlockPtrSet Preds; // Loop predecessor blocks.
- BlockPtrSet Exits; // Loop exit blocks.
-
- void clear() {
- Loop.clear();
- Preds.clear();
- Exits.clear();
- }
- };
-
- // Print loop blocks with use counts.
- void print(const LoopBlocks&, raw_ostream&) const;
-
- // Calculate the block sets surrounding the loop.
- void getLoopBlocks(const MachineLoop *Loop, LoopBlocks &Blocks);
-
- /// 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 LoopBlocks&);
+ /// isOriginalEndpoint - Return true if the original live range was killed or
+ /// (re-)defined at Idx. Idx should be the 'def' slot for a normal kill/def,
+ /// and 'use' for an early-clobber def.
+ /// This can be used to recognize code inserted by earlier live range
+ /// splitting.
+ bool isOriginalEndpoint(SlotIndex Idx) const;
- /// getCriticalExits - It may be necessary to partially break critical edges
- /// leaving the loop if an exit block has phi uses of CurLI. Collect the exit
- /// blocks that need special treatment into CriticalExits.
- void getCriticalExits(const LoopBlocks &Blocks, BlockPtrSet &CriticalExits);
+ /// getUseBlocks - Return an array of BlockInfo objects for the basic blocks
+ /// where CurLI has uses.
+ ArrayRef<BlockInfo> getUseBlocks() { return UseBlocks; }
- /// canSplitCriticalExits - Return true if it is possible to insert new exit
- /// blocks before the blocks in CriticalExits.
- bool canSplitCriticalExits(const LoopBlocks &Blocks,
- BlockPtrSet &CriticalExits);
+ /// getNumThroughBlocks - Return the number of through blocks.
+ unsigned getNumThroughBlocks() const { return NumThroughBlocks; }
- /// getCriticalPreds - Get the set of loop predecessors with critical edges to
- /// blocks outside the loop that have CurLI live in. We don't have to break
- /// these edges, but they do require special treatment.
- void getCriticalPreds(const LoopBlocks &Blocks, BlockPtrSet &CriticalPreds);
+ /// isThroughBlock - Return true if CurLI is live through MBB without uses.
+ bool isThroughBlock(unsigned MBB) const { return ThroughBlocks.test(MBB); }
- /// getSplitLoops - Get the set of loops that have CurLI uses and would be
- /// profitable to split.
- void getSplitLoops(LoopPtrSet&);
+ /// getThroughBlocks - Return the set of through blocks.
+ const BitVector &getThroughBlocks() const { return ThroughBlocks; }
- /// getBestSplitLoop - Return the loop where CurLI may best be split to a
- /// separate register, or NULL.
- const MachineLoop *getBestSplitLoop();
-
- /// isBypassLoop - Return true if CurLI is live through Loop and has no uses
- /// inside the loop. Bypass loops are candidates for splitting because it can
- /// prevent interference inside the loop.
- bool isBypassLoop(const MachineLoop *Loop);
-
- /// getBypassLoops - Get all the maximal bypass loops. These are the bypass
- /// loops whose parent is not a bypass loop.
- void getBypassLoops(LoopPtrSet&);
+ typedef SmallPtrSet<const MachineBasicBlock*, 16> BlockPtrSet;
/// getMultiUseBlocks - Add basic blocks to Blocks that may benefit from
/// having CurLI split to a new live interval. Return true if Blocks can be
/// passed to SplitEditor::splitSingleBlocks.
bool getMultiUseBlocks(BlockPtrSet &Blocks);
-
- /// getBlockForInsideSplit - If CurLI is contained inside a single basic
- /// block, and it would pay to subdivide the interval inside that block,
- /// return it. Otherwise return NULL. The returned block can be passed to
- /// SplitEditor::splitInsideBlock.
- const MachineBasicBlock *getBlockForInsideSplit();
-};
-
-
-/// LiveIntervalMap - Map values from a large LiveInterval into a small
-/// interval that is a subset. Insert phi-def values as needed. This class is
-/// used by SplitEditor to create new smaller LiveIntervals.
-///
-/// ParentLI is the larger interval, LI is the subset interval. Every value
-/// in LI corresponds to exactly one value in ParentLI, and the live range
-/// of the value is contained within the live range of the ParentLI value.
-/// Values in ParentLI may map to any number of OpenLI values, including 0.
-class LiveIntervalMap {
- LiveIntervals &LIS;
- MachineDominatorTree &MDT;
-
- // The parent interval is never changed.
- const LiveInterval &ParentLI;
-
- // The child interval's values are fully contained inside ParentLI values.
- LiveInterval *LI;
-
- typedef DenseMap<const VNInfo*, VNInfo*> ValueMap;
-
- // Map ParentLI values to simple values in LI that are defined at the same
- // SlotIndex, or NULL for ParentLI values that have complex LI defs.
- // Note there is a difference between values mapping to NULL (complex), and
- // values not present (unknown/unmapped).
- ValueMap Values;
-
- typedef std::pair<VNInfo*, MachineDomTreeNode*> LiveOutPair;
- typedef DenseMap<MachineBasicBlock*,LiveOutPair> LiveOutMap;
-
- // LiveOutCache - Map each basic block where LI is live out to the live-out
- // value and its defining block. One of these conditions shall be true:
- //
- // 1. !LiveOutCache.count(MBB)
- // 2. LiveOutCache[MBB].second.getNode() == MBB
- // 3. forall P in preds(MBB): LiveOutCache[P] == LiveOutCache[MBB]
- //
- // This is only a cache, the values can be computed as:
- //
- // VNI = LI->getVNInfoAt(LIS.getMBBEndIdx(MBB))
- // Node = mbt_[LIS.getMBBFromIndex(VNI->def)]
- //
- // The cache is also used as a visiteed set by mapValue().
- LiveOutMap LiveOutCache;
-
- // Dump the live-out cache to dbgs().
- void dumpCache();
-
-public:
- LiveIntervalMap(LiveIntervals &lis,
- MachineDominatorTree &mdt,
- const LiveInterval &parentli)
- : LIS(lis), MDT(mdt), ParentLI(parentli), LI(0) {}
-
- /// reset - clear all data structures and start a new live interval.
- void reset(LiveInterval *);
-
- /// getLI - return the current live interval.
- LiveInterval *getLI() const { return LI; }
-
- /// defValue - define a value in LI from the ParentLI value VNI and Idx.
- /// Idx does not have to be ParentVNI->def, but it must be contained within
- /// ParentVNI's live range in ParentLI.
- /// Return the new LI value.
- VNInfo *defValue(const VNInfo *ParentVNI, SlotIndex Idx);
-
- /// mapValue - map ParentVNI to the corresponding LI value at Idx. It is
- /// assumed that ParentVNI is live at Idx.
- /// If ParentVNI has not been defined by defValue, it is assumed that
- /// ParentVNI->def dominates Idx.
- /// If ParentVNI has been defined by defValue one or more times, a value that
- /// dominates Idx will be returned. This may require creating extra phi-def
- /// values and adding live ranges to LI.
- /// If simple is not NULL, *simple will indicate if ParentVNI is a simply
- /// mapped value.
- VNInfo *mapValue(const VNInfo *ParentVNI, SlotIndex Idx, bool *simple = 0);
-
- // extendTo - Find the last LI value defined in MBB at or before Idx. The
- // parentli is assumed to be live at Idx. Extend the live range to include
- // Idx. Return the found VNInfo, or NULL.
- VNInfo *extendTo(const MachineBasicBlock *MBB, SlotIndex Idx);
-
- /// isMapped - Return true is ParentVNI is a known mapped value. It may be a
- /// simple 1-1 mapping or a complex mapping to later defs.
- bool isMapped(const VNInfo *ParentVNI) const {
- return Values.count(ParentVNI);
- }
-
- /// isComplexMapped - Return true if ParentVNI has received new definitions
- /// with defValue.
- bool isComplexMapped(const VNInfo *ParentVNI) const;
-
- /// markComplexMapped - Mark ParentVNI as complex mapped regardless of the
- /// number of definitions.
- void markComplexMapped(const VNInfo *ParentVNI) { Values[ParentVNI] = 0; }
-
- // addSimpleRange - Add a simple range from ParentLI to LI.
- // ParentVNI must be live in the [Start;End) interval.
- void addSimpleRange(SlotIndex Start, SlotIndex End, const VNInfo *ParentVNI);
-
- /// addRange - Add live ranges to LI where [Start;End) intersects ParentLI.
- /// All needed values whose def is not inside [Start;End) must be defined
- /// beforehand so mapValue will work.
- void addRange(SlotIndex Start, SlotIndex End);
};
/// - Rewrite instructions with finish().
///
class SplitEditor {
- SplitAnalysis &sa_;
+ SplitAnalysis &SA;
LiveIntervals &LIS;
VirtRegMap &VRM;
MachineRegisterInfo &MRI;
const TargetRegisterInfo &TRI;
/// Edit - The current parent register and new intervals created.
- LiveRangeEdit &Edit;
+ LiveRangeEdit *Edit;
/// Index into Edit of the currently open interval.
/// The index 0 is used for the complement, so the first interval started by
/// Idx.
RegAssignMap RegAssign;
- /// LIMappers - One LiveIntervalMap or each interval in Edit.
- SmallVector<LiveIntervalMap, 4> LIMappers;
+ typedef DenseMap<std::pair<unsigned, unsigned>, VNInfo*> ValueMap;
+
+ /// Values - keep track of the mapping from parent values to values in the new
+ /// intervals. Given a pair (RegIdx, ParentVNI->id), Values contains:
+ ///
+ /// 1. No entry - the value is not mapped to Edit.get(RegIdx).
+ /// 2. Null - the value is mapped to multiple values in Edit.get(RegIdx).
+ /// Each value is represented by a minimal live range at its def.
+ /// 3. A non-null VNInfo - the value is mapped to a single new value.
+ /// The new value has no live ranges anywhere.
+ ValueMap Values;
+
+ typedef std::pair<VNInfo*, MachineDomTreeNode*> LiveOutPair;
+ typedef IndexedMap<LiveOutPair, MBB2NumberFunctor> LiveOutMap;
+
+ // LiveOutCache - Map each basic block where a new register is live out to the
+ // live-out value and its defining block.
+ // One of these conditions shall be true:
+ //
+ // 1. !LiveOutCache.count(MBB)
+ // 2. LiveOutCache[MBB].second.getNode() == MBB
+ // 3. forall P in preds(MBB): LiveOutCache[P] == LiveOutCache[MBB]
+ //
+ // This is only a cache, the values can be computed as:
+ //
+ // VNI = Edit.get(RegIdx)->getVNInfoAt(LIS.getMBBEndIdx(MBB))
+ // Node = mbt_[LIS.getMBBFromIndex(VNI->def)]
+ //
+ // The cache is also used as a visited set by extendRange(). It can be shared
+ // by all the new registers because at most one is live out of each block.
+ LiveOutMap LiveOutCache;
+
+ // LiveOutSeen - Indexed by MBB->getNumber(), a bit is set for each valid
+ // entry in LiveOutCache.
+ BitVector LiveOutSeen;
+
+ /// LiveInBlock - Info for updateSSA() about a block where a register is
+ /// live-in.
+ /// The updateSSA caller provides DomNode and Kill inside MBB, updateSSA()
+ /// adds the computed live-in value.
+ struct LiveInBlock {
+ // Dominator tree node for the block.
+ // Cleared by updateSSA when the final value has been determined.
+ MachineDomTreeNode *DomNode;
+
+ // Live-in value filled in by updateSSA once it is known.
+ VNInfo *Value;
+
+ // Position in block where the live-in range ends, or SlotIndex() if the
+ // range passes through the block.
+ SlotIndex Kill;
+
+ LiveInBlock(MachineDomTreeNode *node) : DomNode(node), Value(0) {}
+ };
+
+ /// LiveInBlocks - List of live-in blocks used by findReachingDefs() and
+ /// updateSSA(). This list is usually empty, it exists here to avoid frequent
+ /// reallocations.
+ SmallVector<LiveInBlock, 16> LiveInBlocks;
+
+ /// defValue - define a value in RegIdx from ParentVNI at Idx.
+ /// Idx does not have to be ParentVNI->def, but it must be contained within
+ /// ParentVNI's live range in ParentLI. The new value is added to the value
+ /// map.
+ /// Return the new LI value.
+ VNInfo *defValue(unsigned RegIdx, const VNInfo *ParentVNI, SlotIndex Idx);
+
+ /// markComplexMapped - Mark ParentVNI as complex mapped in RegIdx regardless
+ /// of the number of defs.
+ void markComplexMapped(unsigned RegIdx, const VNInfo *ParentVNI);
/// defFromParent - Define Reg from ParentVNI at UseIdx using either
/// rematerialization or a COPY from parent. Return the new value.
MachineBasicBlock &MBB,
MachineBasicBlock::iterator I);
+ /// extendRange - Extend the live range of Edit.get(RegIdx) so it reaches Idx.
+ /// Insert PHIDefs as needed to preserve SSA form.
+ void extendRange(unsigned RegIdx, SlotIndex Idx);
+
+ /// findReachingDefs - Starting from MBB, add blocks to LiveInBlocks until all
+ /// reaching defs for LI are found.
+ /// @param LI Live interval whose value is needed.
+ /// @param MBB Block where LI should be live-in.
+ /// @param Kill Kill point in MBB.
+ /// @return Unique value seen, or NULL.
+ VNInfo *findReachingDefs(LiveInterval *LI, MachineBasicBlock *MBB,
+ SlotIndex Kill);
+
+ /// updateSSA - Compute and insert PHIDefs such that all blocks in
+ // LiveInBlocks get a known live-in value. Add live ranges to the blocks.
+ void updateSSA();
+
+ /// transferValues - Transfer values to the new ranges.
+ /// Return true if any ranges were skipped.
+ bool transferValues();
+
+ /// extendPHIKillRanges - Extend the ranges of all values killed by original
+ /// parent PHIDefs.
+ void extendPHIKillRanges();
+
/// rewriteAssigned - Rewrite all uses of Edit.getReg() to assigned registers.
- void rewriteAssigned();
+ void rewriteAssigned(bool ExtendRanges);
- /// rewriteComponents - Rewrite all uses of Intv[0] according to the eq
- /// classes in ConEQ.
- /// This must be done when Intvs[0] is styill live at all uses, before calling
- /// ConEq.Distribute().
- void rewriteComponents(const SmallVectorImpl<LiveInterval*> &Intvs,
- const ConnectedVNInfoEqClasses &ConEq);
+ /// deleteRematVictims - Delete defs that are dead after rematerializing.
+ void deleteRematVictims();
public:
/// Create a new SplitEditor for editing the LiveInterval analyzed by SA.
/// Newly created intervals will be appended to newIntervals.
SplitEditor(SplitAnalysis &SA, LiveIntervals&, VirtRegMap&,
- MachineDominatorTree&, LiveRangeEdit&);
+ MachineDominatorTree&);
- /// getAnalysis - Get the corresponding analysis.
- SplitAnalysis &getAnalysis() { return sa_; }
+ /// reset - Prepare for a new split.
+ void reset(LiveRangeEdit&);
/// Create a new virtual register and live interval.
- void openIntv();
+ /// Return the interval index, starting from 1. Interval index 0 is the
+ /// implicit complement interval.
+ unsigned openIntv();
+
+ /// currentIntv - Return the current interval index.
+ unsigned currentIntv() const { return OpenIdx; }
+
+ /// selectIntv - Select a previously opened interval index.
+ void selectIntv(unsigned Idx);
/// enterIntvBefore - Enter the open interval before the instruction at Idx.
/// If the parent interval is not live before Idx, a COPY is not inserted.
///
void overlapIntv(SlotIndex Start, SlotIndex End);
- /// closeIntv - Indicate that we are done editing the currently open
- /// LiveInterval, and ranges can be trimmed.
- void closeIntv();
-
/// finish - after all the new live ranges have been created, compute the
/// remaining live range, and rewrite instructions to use the new registers.
void finish();
// ===--- High level methods ---===
- /// splitAroundLoop - Split CurLI into a separate live interval inside
- /// the loop.
- void splitAroundLoop(const MachineLoop*);
+ /// splitSingleBlock - Split CurLI into a separate live interval around the
+ /// uses in a single block. This is intended to be used as part of a larger
+ /// split, and doesn't call finish().
+ void splitSingleBlock(const SplitAnalysis::BlockInfo &BI);
/// splitSingleBlocks - Split CurLI into a separate live interval inside each
/// basic block in Blocks.
void splitSingleBlocks(const SplitAnalysis::BlockPtrSet &Blocks);
-
- /// splitInsideBlock - Split CurLI into multiple intervals inside MBB.
- void splitInsideBlock(const MachineBasicBlock *);
};
}