mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-26 07:29:55 +00:00
This patch will sometimes choose live range split points next to interference instead of always splitting next to a register point. That means spill code can now appear almost anywhere, and it was necessary to fix code that didn't expect that. The difficult places were: - Between a CALL returning a value on the x87 stack and the corresponding FpPOP_RETVAL (was FpGET_ST0). Probably also near x87 inline assembly, but that didn't actually show up in testing. - Between a CALL popping arguments off the stack and the corresponding ADJCALLSTACKUP. Both are fixed now. The only place spill code can't appear is after terminators, see SplitAnalysis::getLastSplitPoint. Original commit message: Rewrite RAGreedy::splitAroundRegion, now with cool ASCII art. This function has to deal with a lot of special cases, and the old version got it wrong sometimes. In particular, it would sometimes leave multiple uses in the stack interval in a single block. That causes bad code with multiple reloads in the same basic block. The new version handles block entry and exit in a single pass. It first eliminates all the easy cases, and then goes on to create a local interval for the blocks with difficult interference. Previously, we would only create the local interval for completely isolated blocks. It can happen that the stack interval becomes completely empty because we could allocate a register in all edge bundles, and the new local intervals deal with the interference. The empty stack interval is harmless, but we need to remove a SplitKit assertion that checks for empty intervals. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134125 91177308-0d34-0410-b5e6-96231b3b80d8
434 lines
16 KiB
C++
434 lines
16 KiB
C++
//===-------- SplitKit.h - Toolkit for splitting live ranges ----*- C++ -*-===//
|
|
//
|
|
// 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.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_CODEGEN_SPLITKIT_H
|
|
#define LLVM_CODEGEN_SPLITKIT_H
|
|
|
|
#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"
|
|
|
|
namespace llvm {
|
|
|
|
class ConnectedVNInfoEqClasses;
|
|
class LiveInterval;
|
|
class LiveIntervals;
|
|
class LiveRangeEdit;
|
|
class MachineInstr;
|
|
class MachineLoopInfo;
|
|
class MachineRegisterInfo;
|
|
class TargetInstrInfo;
|
|
class TargetRegisterInfo;
|
|
class VirtRegMap;
|
|
class VNInfo;
|
|
class raw_ostream;
|
|
|
|
/// At some point we should just include MachineDominators.h:
|
|
class MachineDominatorTree;
|
|
template <class NodeT> class DomTreeNodeBase;
|
|
typedef DomTreeNodeBase<MachineBasicBlock> MachineDomTreeNode;
|
|
|
|
|
|
/// SplitAnalysis - Analyze a LiveInterval, looking for live range splitting
|
|
/// opportunities.
|
|
class SplitAnalysis {
|
|
public:
|
|
const MachineFunction &MF;
|
|
const VirtRegMap &VRM;
|
|
const LiveIntervals &LIS;
|
|
const MachineLoopInfo &Loops;
|
|
const TargetInstrInfo &TII;
|
|
|
|
// Sorted slot indexes of using instructions.
|
|
SmallVector<SlotIndex, 8> UseSlots;
|
|
|
|
/// Additional information about basic blocks where the current variable is
|
|
/// live. Such a block will look like one of these templates:
|
|
///
|
|
/// 1. | o---x | Internal to block. Variable is only live in this block.
|
|
/// 2. |---x | Live-in, kill.
|
|
/// 3. | o---| Def, live-out.
|
|
/// 4. |---x o---| Live-in, kill, def, live-out. Counted by NumGapBlocks.
|
|
/// 5. |---o---o---| Live-through with uses or defs.
|
|
/// 6. |-----------| Live-through without uses. Counted by NumThroughBlocks.
|
|
///
|
|
/// Two BlockInfo entries are created for template 4. One for the live-in
|
|
/// segment, and one for the live-out segment. These entries look as if the
|
|
/// block were split in the middle where the live range isn't live.
|
|
///
|
|
/// Live-through blocks without any uses don't get BlockInfo entries. They
|
|
/// are simply listed in ThroughBlocks instead.
|
|
///
|
|
struct BlockInfo {
|
|
MachineBasicBlock *MBB;
|
|
SlotIndex FirstUse; ///< First instr using current reg.
|
|
SlotIndex LastUse; ///< Last instr using current reg.
|
|
bool LiveThrough; ///< Live in whole block (Templ 5. above).
|
|
bool LiveIn; ///< Current reg is live in.
|
|
bool LiveOut; ///< Current reg is live out.
|
|
|
|
/// isOneInstr - Returns true when this BlockInfo describes a single
|
|
/// instruction.
|
|
bool isOneInstr() const {
|
|
return SlotIndex::isSameInstr(FirstUse, LastUse);
|
|
}
|
|
};
|
|
|
|
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;
|
|
|
|
/// NumGapBlocks - Number of duplicate entries in UseBlocks for blocks where
|
|
/// the live range has a gap.
|
|
unsigned NumGapBlocks;
|
|
|
|
/// ThroughBlocks - Block numbers where CurLI is live through without uses.
|
|
BitVector ThroughBlocks;
|
|
|
|
/// NumThroughBlocks - Number of live-through blocks.
|
|
unsigned NumThroughBlocks;
|
|
|
|
/// DidRepairRange - analyze was forced to shrinkToUses().
|
|
bool DidRepairRange;
|
|
|
|
SlotIndex computeLastSplitPoint(unsigned Num);
|
|
|
|
// Sumarize statistics by counting instructions using CurLI.
|
|
void analyzeUses();
|
|
|
|
/// calcLiveBlockInfo - Compute per-block information about CurLI.
|
|
bool calcLiveBlockInfo();
|
|
|
|
public:
|
|
SplitAnalysis(const VirtRegMap &vrm, 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);
|
|
|
|
/// didRepairRange() - Returns true if CurLI was invalid and has been repaired
|
|
/// by analyze(). This really shouldn't happen, but sometimes the coalescer
|
|
/// can create live ranges that end in mid-air.
|
|
bool didRepairRange() const { return DidRepairRange; }
|
|
|
|
/// clear - clear all data structures so SplitAnalysis is ready to analyze a
|
|
/// new interval.
|
|
void clear();
|
|
|
|
/// 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);
|
|
}
|
|
|
|
/// 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;
|
|
|
|
/// getUseBlocks - Return an array of BlockInfo objects for the basic blocks
|
|
/// where CurLI has uses.
|
|
ArrayRef<BlockInfo> getUseBlocks() const { return UseBlocks; }
|
|
|
|
/// getNumThroughBlocks - Return the number of through blocks.
|
|
unsigned getNumThroughBlocks() const { return NumThroughBlocks; }
|
|
|
|
/// isThroughBlock - Return true if CurLI is live through MBB without uses.
|
|
bool isThroughBlock(unsigned MBB) const { return ThroughBlocks.test(MBB); }
|
|
|
|
/// getThroughBlocks - Return the set of through blocks.
|
|
const BitVector &getThroughBlocks() const { return ThroughBlocks; }
|
|
|
|
/// getNumLiveBlocks - Return the number of blocks where CurLI is live.
|
|
unsigned getNumLiveBlocks() const {
|
|
return getUseBlocks().size() - NumGapBlocks + getNumThroughBlocks();
|
|
}
|
|
|
|
/// countLiveBlocks - Return the number of blocks where li is live. This is
|
|
/// guaranteed to return the same number as getNumLiveBlocks() after calling
|
|
/// analyze(li).
|
|
unsigned countLiveBlocks(const LiveInterval *li) const;
|
|
|
|
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);
|
|
};
|
|
|
|
|
|
/// SplitEditor - Edit machine code and LiveIntervals for live range
|
|
/// splitting.
|
|
///
|
|
/// - Create a SplitEditor from a SplitAnalysis.
|
|
/// - Start a new live interval with openIntv.
|
|
/// - Mark the places where the new interval is entered using enterIntv*
|
|
/// - Mark the ranges where the new interval is used with useIntv*
|
|
/// - Mark the places where the interval is exited with exitIntv*.
|
|
/// - Finish the current interval with closeIntv and repeat from 2.
|
|
/// - Rewrite instructions with finish().
|
|
///
|
|
class SplitEditor {
|
|
SplitAnalysis &SA;
|
|
LiveIntervals &LIS;
|
|
VirtRegMap &VRM;
|
|
MachineRegisterInfo &MRI;
|
|
MachineDominatorTree &MDT;
|
|
const TargetInstrInfo &TII;
|
|
const TargetRegisterInfo &TRI;
|
|
|
|
/// Edit - The current parent register and new intervals created.
|
|
LiveRangeEdit *Edit;
|
|
|
|
/// Index into Edit of the currently open interval.
|
|
/// The index 0 is used for the complement, so the first interval started by
|
|
/// openIntv will be 1.
|
|
unsigned OpenIdx;
|
|
|
|
typedef IntervalMap<SlotIndex, unsigned> RegAssignMap;
|
|
|
|
/// Allocator for the interval map. This will eventually be shared with
|
|
/// SlotIndexes and LiveIntervals.
|
|
RegAssignMap::Allocator Allocator;
|
|
|
|
/// RegAssign - Map of the assigned register indexes.
|
|
/// Edit.get(RegAssign.lookup(Idx)) is the register that should be live at
|
|
/// Idx.
|
|
RegAssignMap RegAssign;
|
|
|
|
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.
|
|
VNInfo *defFromParent(unsigned RegIdx,
|
|
VNInfo *ParentVNI,
|
|
SlotIndex UseIdx,
|
|
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(bool ExtendRanges);
|
|
|
|
/// 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&);
|
|
|
|
/// reset - Prepare for a new split.
|
|
void reset(LiveRangeEdit&);
|
|
|
|
/// Create a new virtual register and live interval.
|
|
/// 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.
|
|
/// Return the beginning of the new live range.
|
|
SlotIndex enterIntvBefore(SlotIndex Idx);
|
|
|
|
/// enterIntvAfter - Enter the open interval after the instruction at Idx.
|
|
/// Return the beginning of the new live range.
|
|
SlotIndex enterIntvAfter(SlotIndex Idx);
|
|
|
|
/// enterIntvAtEnd - Enter the open interval at the end of MBB.
|
|
/// Use the open interval from he inserted copy to the MBB end.
|
|
/// Return the beginning of the new live range.
|
|
SlotIndex enterIntvAtEnd(MachineBasicBlock &MBB);
|
|
|
|
/// useIntv - indicate that all instructions in MBB should use OpenLI.
|
|
void useIntv(const MachineBasicBlock &MBB);
|
|
|
|
/// useIntv - indicate that all instructions in range should use OpenLI.
|
|
void useIntv(SlotIndex Start, SlotIndex End);
|
|
|
|
/// leaveIntvAfter - Leave the open interval after the instruction at Idx.
|
|
/// Return the end of the live range.
|
|
SlotIndex leaveIntvAfter(SlotIndex Idx);
|
|
|
|
/// leaveIntvBefore - Leave the open interval before the instruction at Idx.
|
|
/// Return the end of the live range.
|
|
SlotIndex leaveIntvBefore(SlotIndex Idx);
|
|
|
|
/// leaveIntvAtTop - Leave the interval at the top of MBB.
|
|
/// Add liveness from the MBB top to the copy.
|
|
/// Return the end of the live range.
|
|
SlotIndex leaveIntvAtTop(MachineBasicBlock &MBB);
|
|
|
|
/// overlapIntv - Indicate that all instructions in range should use the open
|
|
/// interval, but also let the complement interval be live.
|
|
///
|
|
/// This doubles the register pressure, but is sometimes required to deal with
|
|
/// register uses after the last valid split point.
|
|
///
|
|
/// The Start index should be a return value from a leaveIntv* call, and End
|
|
/// should be in the same basic block. The parent interval must have the same
|
|
/// value across the range.
|
|
///
|
|
void overlapIntv(SlotIndex Start, SlotIndex End);
|
|
|
|
/// finish - after all the new live ranges have been created, compute the
|
|
/// remaining live range, and rewrite instructions to use the new registers.
|
|
/// @param LRMap When not null, this vector will map each live range in Edit
|
|
/// back to the indices returned by openIntv.
|
|
/// There may be extra indices created by dead code elimination.
|
|
void finish(SmallVectorImpl<unsigned> *LRMap = 0);
|
|
|
|
/// dump - print the current interval maping to dbgs().
|
|
void dump() const;
|
|
|
|
// ===--- High level methods ---===
|
|
|
|
/// 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);
|
|
};
|
|
|
|
}
|
|
|
|
#endif
|