2010-12-08 03:26:16 +00:00
|
|
|
//===-- RegAllocGreedy.cpp - greedy 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 RAGreedy function pass for register allocation in
|
|
|
|
// optimized builds.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2010-12-10 22:21:05 +00:00
|
|
|
#include "AllocationOrder.h"
|
2011-04-02 06:03:35 +00:00
|
|
|
#include "InterferenceCache.h"
|
2011-04-05 21:40:37 +00:00
|
|
|
#include "LiveDebugVariables.h"
|
2010-12-08 03:26:16 +00:00
|
|
|
#include "RegAllocBase.h"
|
2011-01-18 21:13:27 +00:00
|
|
|
#include "SpillPlacement.h"
|
2012-12-03 16:50:05 +00:00
|
|
|
#include "Spiller.h"
|
2010-12-15 23:46:13 +00:00
|
|
|
#include "SplitKit.h"
|
2011-02-17 22:53:48 +00:00
|
|
|
#include "llvm/ADT/Statistic.h"
|
2010-12-08 03:26:16 +00:00
|
|
|
#include "llvm/Analysis/AliasAnalysis.h"
|
|
|
|
#include "llvm/CodeGen/CalcSpillWeights.h"
|
2011-01-18 21:13:27 +00:00
|
|
|
#include "llvm/CodeGen/EdgeBundles.h"
|
2010-12-08 03:26:16 +00:00
|
|
|
#include "llvm/CodeGen/LiveIntervalAnalysis.h"
|
2012-04-02 22:44:18 +00:00
|
|
|
#include "llvm/CodeGen/LiveRangeEdit.h"
|
2012-11-28 19:13:06 +00:00
|
|
|
#include "llvm/CodeGen/LiveRegMatrix.h"
|
2010-12-08 03:26:16 +00:00
|
|
|
#include "llvm/CodeGen/LiveStackAnalysis.h"
|
2013-06-17 19:00:36 +00:00
|
|
|
#include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
|
2010-12-17 23:16:32 +00:00
|
|
|
#include "llvm/CodeGen/MachineDominators.h"
|
2010-12-08 03:26:16 +00:00
|
|
|
#include "llvm/CodeGen/MachineFunctionPass.h"
|
|
|
|
#include "llvm/CodeGen/MachineLoopInfo.h"
|
|
|
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
2016-04-13 03:08:27 +00:00
|
|
|
#include "llvm/CodeGen/Passes.h"
|
2010-12-08 03:26:16 +00:00
|
|
|
#include "llvm/CodeGen/RegAllocRegistry.h"
|
2014-01-02 22:47:22 +00:00
|
|
|
#include "llvm/CodeGen/RegisterClassInfo.h"
|
2012-12-03 16:50:05 +00:00
|
|
|
#include "llvm/CodeGen/VirtRegMap.h"
|
2014-04-04 02:05:21 +00:00
|
|
|
#include "llvm/IR/LLVMContext.h"
|
2012-12-03 16:50:05 +00:00
|
|
|
#include "llvm/PassAnalysisSupport.h"
|
2014-04-08 19:18:56 +00:00
|
|
|
#include "llvm/Support/BranchProbability.h"
|
2011-07-26 23:41:46 +00:00
|
|
|
#include "llvm/Support/CommandLine.h"
|
2010-12-08 03:26:16 +00:00
|
|
|
#include "llvm/Support/Debug.h"
|
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
2010-12-11 00:19:56 +00:00
|
|
|
#include "llvm/Support/Timer.h"
|
2012-12-03 16:50:05 +00:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2016-04-13 03:08:27 +00:00
|
|
|
#include "llvm/Target/TargetInstrInfo.h"
|
2014-07-02 18:32:04 +00:00
|
|
|
#include "llvm/Target/TargetSubtargetInfo.h"
|
2011-02-22 23:01:52 +00:00
|
|
|
#include <queue>
|
|
|
|
|
2010-12-08 03:26:16 +00:00
|
|
|
using namespace llvm;
|
|
|
|
|
2014-04-22 02:02:50 +00:00
|
|
|
#define DEBUG_TYPE "regalloc"
|
|
|
|
|
2011-02-17 22:53:48 +00:00
|
|
|
STATISTIC(NumGlobalSplits, "Number of split global live ranges");
|
|
|
|
STATISTIC(NumLocalSplits, "Number of split local live ranges");
|
|
|
|
STATISTIC(NumEvicted, "Number of interferences evicted");
|
|
|
|
|
2016-04-13 03:08:27 +00:00
|
|
|
static cl::opt<SplitEditor::ComplementSpillMode> SplitSpillMode(
|
|
|
|
"split-spill-mode", cl::Hidden,
|
|
|
|
cl::desc("Spill mode for splitting live ranges"),
|
|
|
|
cl::values(clEnumValN(SplitEditor::SM_Partition, "default", "Default"),
|
|
|
|
clEnumValN(SplitEditor::SM_Size, "size", "Optimize for size"),
|
|
|
|
clEnumValN(SplitEditor::SM_Speed, "speed", "Optimize for speed"),
|
|
|
|
clEnumValEnd),
|
|
|
|
cl::init(SplitEditor::SM_Speed));
|
Add an interface for SplitKit complement spill modes.
SplitKit always computes a complement live range to cover the places
where the original live range was live, but no explicit region has been
allocated.
Currently, the complement live range is created to be as small as
possible - it never overlaps any of the regions. This minimizes
register pressure, but if the complement is going to be spilled anyway,
that is not very important. The spiller will eliminate redundant
spills, and hoist others by making the spill slot live range overlap
some of the regions created by splitting. Stack slots are cheap.
This patch adds the interface to enable spill modes in SplitKit. In
spill mode, SplitKit will assume that the complement is going to spill,
so it will allow it to overlap regions in order to avoid back-copies.
By doing some of the spiller's work early, the complement live range
becomes simpler. In some cases, it can become much simpler because no
extra PHI-defs are required. This will speed up both splitting and
spilling.
This is only the interface to enable spill modes, no implementation yet.
llvm-svn: 139500
2011-09-12 16:49:21 +00:00
|
|
|
|
2014-02-05 22:13:59 +00:00
|
|
|
static cl::opt<unsigned>
|
|
|
|
LastChanceRecoloringMaxDepth("lcr-max-depth", cl::Hidden,
|
|
|
|
cl::desc("Last chance recoloring max depth"),
|
|
|
|
cl::init(5));
|
|
|
|
|
|
|
|
static cl::opt<unsigned> LastChanceRecoloringMaxInterference(
|
|
|
|
"lcr-max-interf", cl::Hidden,
|
|
|
|
cl::desc("Last chance recoloring maximum number of considered"
|
|
|
|
" interference at a time"),
|
|
|
|
cl::init(8));
|
|
|
|
|
2014-04-11 21:39:44 +00:00
|
|
|
static cl::opt<bool>
|
2014-04-11 21:51:09 +00:00
|
|
|
ExhaustiveSearch("exhaustive-register-search", cl::NotHidden,
|
2014-04-11 21:39:44 +00:00
|
|
|
cl::desc("Exhaustive Search for registers bypassing the depth "
|
|
|
|
"and interference cutoffs of last chance recoloring"));
|
|
|
|
|
2014-07-01 14:08:37 +00:00
|
|
|
static cl::opt<bool> EnableLocalReassignment(
|
|
|
|
"enable-local-reassign", cl::Hidden,
|
|
|
|
cl::desc("Local reassignment can yield better allocation decisions, but "
|
|
|
|
"may be compile time intensive"),
|
2014-07-02 18:32:04 +00:00
|
|
|
cl::init(false));
|
2014-07-01 14:08:37 +00:00
|
|
|
|
2015-07-17 23:04:06 +00:00
|
|
|
static cl::opt<bool> EnableDeferredSpilling(
|
|
|
|
"enable-deferred-spilling", cl::Hidden,
|
|
|
|
cl::desc("Instead of spilling a variable right away, defer the actual "
|
|
|
|
"code insertion to the end of the allocation. That way the "
|
|
|
|
"allocator might still find a suitable coloring for this "
|
|
|
|
"variable because of other evicted variables."),
|
|
|
|
cl::init(false));
|
|
|
|
|
2014-03-25 00:16:25 +00:00
|
|
|
// FIXME: Find a good default for this flag and remove the flag.
|
|
|
|
static cl::opt<unsigned>
|
|
|
|
CSRFirstTimeCost("regalloc-csr-first-time-cost",
|
|
|
|
cl::desc("Cost for first time use of callee-saved register."),
|
|
|
|
cl::init(0), cl::Hidden);
|
|
|
|
|
2010-12-08 03:26:16 +00:00
|
|
|
static RegisterRegAlloc greedyRegAlloc("greedy", "greedy register allocator",
|
|
|
|
createGreedyRegisterAllocator);
|
|
|
|
|
|
|
|
namespace {
|
2011-03-09 00:57:29 +00:00
|
|
|
class RAGreedy : public MachineFunctionPass,
|
|
|
|
public RegAllocBase,
|
|
|
|
private LiveRangeEdit::Delegate {
|
2014-02-05 22:13:59 +00:00
|
|
|
// Convenient shortcuts.
|
|
|
|
typedef std::priority_queue<std::pair<unsigned, unsigned> > PQueue;
|
|
|
|
typedef SmallPtrSet<LiveInterval *, 4> SmallLISet;
|
|
|
|
typedef SmallSet<unsigned, 16> SmallVirtRegSet;
|
2011-03-09 00:57:29 +00:00
|
|
|
|
2010-12-08 03:26:16 +00:00
|
|
|
// context
|
|
|
|
MachineFunction *MF;
|
|
|
|
|
2014-01-02 22:47:22 +00:00
|
|
|
// Shortcuts to some useful interface.
|
|
|
|
const TargetInstrInfo *TII;
|
|
|
|
const TargetRegisterInfo *TRI;
|
|
|
|
RegisterClassInfo RCI;
|
|
|
|
|
2010-12-08 03:26:16 +00:00
|
|
|
// analyses
|
2011-01-18 21:13:27 +00:00
|
|
|
SlotIndexes *Indexes;
|
2013-06-17 19:00:36 +00:00
|
|
|
MachineBlockFrequencyInfo *MBFI;
|
2010-12-17 23:16:32 +00:00
|
|
|
MachineDominatorTree *DomTree;
|
2010-12-15 23:46:13 +00:00
|
|
|
MachineLoopInfo *Loops;
|
2011-01-18 21:13:27 +00:00
|
|
|
EdgeBundles *Bundles;
|
|
|
|
SpillPlacement *SpillPlacer;
|
2011-05-06 18:00:02 +00:00
|
|
|
LiveDebugVariables *DebugVars;
|
2016-07-08 21:08:09 +00:00
|
|
|
AliasAnalysis *AA;
|
2010-12-17 23:16:32 +00:00
|
|
|
|
2010-12-08 03:26:16 +00:00
|
|
|
// state
|
2014-03-06 05:51:42 +00:00
|
|
|
std::unique_ptr<Spiller> SpillerInstance;
|
2014-02-05 22:13:59 +00:00
|
|
|
PQueue Queue;
|
2011-07-02 01:37:09 +00:00
|
|
|
unsigned NextCascade;
|
2011-03-01 21:10:07 +00:00
|
|
|
|
|
|
|
// Live ranges pass through a number of stages as we try to allocate them.
|
|
|
|
// Some of the stages may also create new live ranges:
|
|
|
|
//
|
|
|
|
// - Region splitting.
|
|
|
|
// - Per-block splitting.
|
|
|
|
// - Local splitting.
|
|
|
|
// - Spilling.
|
|
|
|
//
|
|
|
|
// Ranges produced by one of the stages skip the previous stages when they are
|
|
|
|
// dequeued. This improves performance because we can skip interference checks
|
|
|
|
// that are unlikely to give any results. It also guarantees that the live
|
|
|
|
// range splitting algorithm terminates, something that is otherwise hard to
|
|
|
|
// ensure.
|
|
|
|
enum LiveRangeStage {
|
2011-07-25 15:25:41 +00:00
|
|
|
/// Newly created live range that has never been queued.
|
|
|
|
RS_New,
|
|
|
|
|
|
|
|
/// Only attempt assignment and eviction. Then requeue as RS_Split.
|
|
|
|
RS_Assign,
|
|
|
|
|
|
|
|
/// Attempt live range splitting if assignment is impossible.
|
|
|
|
RS_Split,
|
|
|
|
|
2011-07-25 15:25:43 +00:00
|
|
|
/// Attempt more aggressive live range splitting that is guaranteed to make
|
|
|
|
/// progress. This is used for split products that may not be making
|
|
|
|
/// progress.
|
|
|
|
RS_Split2,
|
|
|
|
|
2011-07-25 15:25:41 +00:00
|
|
|
/// Live range will be spilled. No more splitting will be attempted.
|
|
|
|
RS_Spill,
|
|
|
|
|
2015-07-17 23:04:06 +00:00
|
|
|
|
|
|
|
/// Live range is in memory. Because of other evictions, it might get moved
|
|
|
|
/// in a register in the end.
|
|
|
|
RS_Memory,
|
|
|
|
|
2011-07-25 15:25:41 +00:00
|
|
|
/// There is nothing more we can do to this live range. Abort compilation
|
|
|
|
/// if it can't be assigned.
|
|
|
|
RS_Done
|
2011-03-01 21:10:07 +00:00
|
|
|
};
|
|
|
|
|
2014-04-04 02:05:21 +00:00
|
|
|
// Enum CutOffStage to keep a track whether the register allocation failed
|
|
|
|
// because of the cutoffs encountered in last chance recoloring.
|
|
|
|
// Note: This is used as bitmask. New value should be next power of 2.
|
|
|
|
enum CutOffStage {
|
|
|
|
// No cutoffs encountered
|
|
|
|
CO_None = 0,
|
|
|
|
|
|
|
|
// lcr-max-depth cutoff encountered
|
|
|
|
CO_Depth = 1,
|
|
|
|
|
|
|
|
// lcr-max-interf cutoff encountered
|
|
|
|
CO_Interf = 2
|
|
|
|
};
|
|
|
|
|
|
|
|
uint8_t CutOffInfo;
|
|
|
|
|
2013-09-10 23:18:14 +00:00
|
|
|
#ifndef NDEBUG
|
2011-05-25 23:58:36 +00:00
|
|
|
static const char *const StageName[];
|
2013-09-10 23:18:14 +00:00
|
|
|
#endif
|
2011-05-25 23:58:36 +00:00
|
|
|
|
2011-07-02 01:37:09 +00:00
|
|
|
// RegInfo - Keep additional information about each live range.
|
|
|
|
struct RegInfo {
|
|
|
|
LiveRangeStage Stage;
|
|
|
|
|
|
|
|
// Cascade - Eviction loop prevention. See canEvictInterference().
|
|
|
|
unsigned Cascade;
|
|
|
|
|
|
|
|
RegInfo() : Stage(RS_New), Cascade(0) {}
|
|
|
|
};
|
|
|
|
|
|
|
|
IndexedMap<RegInfo, VirtReg2IndexFunctor> ExtraRegInfo;
|
2011-03-01 21:10:07 +00:00
|
|
|
|
|
|
|
LiveRangeStage getStage(const LiveInterval &VirtReg) const {
|
2011-07-02 01:37:09 +00:00
|
|
|
return ExtraRegInfo[VirtReg.reg].Stage;
|
|
|
|
}
|
|
|
|
|
|
|
|
void setStage(const LiveInterval &VirtReg, LiveRangeStage Stage) {
|
|
|
|
ExtraRegInfo.resize(MRI->getNumVirtRegs());
|
|
|
|
ExtraRegInfo[VirtReg.reg].Stage = Stage;
|
2011-03-01 21:10:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template<typename Iterator>
|
|
|
|
void setStage(Iterator Begin, Iterator End, LiveRangeStage NewStage) {
|
2011-07-02 01:37:09 +00:00
|
|
|
ExtraRegInfo.resize(MRI->getNumVirtRegs());
|
2011-03-30 02:52:39 +00:00
|
|
|
for (;Begin != End; ++Begin) {
|
2013-08-14 23:50:04 +00:00
|
|
|
unsigned Reg = *Begin;
|
2011-07-02 01:37:09 +00:00
|
|
|
if (ExtraRegInfo[Reg].Stage == RS_New)
|
|
|
|
ExtraRegInfo[Reg].Stage = NewStage;
|
2011-03-30 02:52:39 +00:00
|
|
|
}
|
2011-03-01 21:10:07 +00:00
|
|
|
}
|
2010-12-08 03:26:16 +00:00
|
|
|
|
2011-07-08 20:46:18 +00:00
|
|
|
/// Cost of evicting interference.
|
|
|
|
struct EvictionCost {
|
|
|
|
unsigned BrokenHints; ///< Total number of broken hints.
|
|
|
|
float MaxWeight; ///< Maximum spill weight evicted.
|
|
|
|
|
2013-11-22 19:07:38 +00:00
|
|
|
EvictionCost(): BrokenHints(0), MaxWeight(0) {}
|
2011-07-08 20:46:18 +00:00
|
|
|
|
2013-07-25 18:35:14 +00:00
|
|
|
bool isMax() const { return BrokenHints == ~0u; }
|
|
|
|
|
2013-11-22 19:07:38 +00:00
|
|
|
void setMax() { BrokenHints = ~0u; }
|
|
|
|
|
|
|
|
void setBrokenHints(unsigned NHints) { BrokenHints = NHints; }
|
|
|
|
|
2011-07-08 20:46:18 +00:00
|
|
|
bool operator<(const EvictionCost &O) const {
|
2014-03-03 19:58:30 +00:00
|
|
|
return std::tie(BrokenHints, MaxWeight) <
|
|
|
|
std::tie(O.BrokenHints, O.MaxWeight);
|
2011-07-08 20:46:18 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2011-01-18 21:13:27 +00:00
|
|
|
// splitting state.
|
2014-03-06 05:51:42 +00:00
|
|
|
std::unique_ptr<SplitAnalysis> SA;
|
|
|
|
std::unique_ptr<SplitEditor> SE;
|
2011-01-18 21:13:27 +00:00
|
|
|
|
2011-04-02 06:03:38 +00:00
|
|
|
/// Cached per-block interference maps
|
|
|
|
InterferenceCache IntfCache;
|
|
|
|
|
2011-04-07 17:27:46 +00:00
|
|
|
/// All basic blocks where the current register has uses.
|
2011-03-05 01:10:31 +00:00
|
|
|
SmallVector<SpillPlacement::BlockConstraint, 8> SplitConstraints;
|
2011-01-18 21:13:27 +00:00
|
|
|
|
2011-03-05 01:10:31 +00:00
|
|
|
/// Global live range splitting candidate info.
|
|
|
|
struct GlobalSplitCandidate {
|
2011-07-26 23:41:46 +00:00
|
|
|
// Register intended for assignment, or 0.
|
2011-03-05 01:10:31 +00:00
|
|
|
unsigned PhysReg;
|
2011-07-26 23:41:46 +00:00
|
|
|
|
|
|
|
// SplitKit interval index for this candidate.
|
|
|
|
unsigned IntvIdx;
|
|
|
|
|
|
|
|
// Interference for PhysReg.
|
2011-07-14 00:17:10 +00:00
|
|
|
InterferenceCache::Cursor Intf;
|
2011-07-26 23:41:46 +00:00
|
|
|
|
|
|
|
// Bundles where this candidate should be live.
|
2011-03-05 01:10:31 +00:00
|
|
|
BitVector LiveBundles;
|
2011-04-12 21:30:53 +00:00
|
|
|
SmallVector<unsigned, 8> ActiveBlocks;
|
|
|
|
|
2011-07-14 00:17:10 +00:00
|
|
|
void reset(InterferenceCache &Cache, unsigned Reg) {
|
2011-04-12 21:30:53 +00:00
|
|
|
PhysReg = Reg;
|
2011-07-26 23:41:46 +00:00
|
|
|
IntvIdx = 0;
|
2011-07-14 00:17:10 +00:00
|
|
|
Intf.setPhysReg(Cache, Reg);
|
2011-04-12 21:30:53 +00:00
|
|
|
LiveBundles.clear();
|
|
|
|
ActiveBlocks.clear();
|
|
|
|
}
|
2011-07-26 23:41:46 +00:00
|
|
|
|
|
|
|
// Set B[i] = C for every live bundle where B[i] was NoCand.
|
|
|
|
unsigned getBundles(SmallVectorImpl<unsigned> &B, unsigned C) {
|
|
|
|
unsigned Count = 0;
|
|
|
|
for (int i = LiveBundles.find_first(); i >= 0;
|
|
|
|
i = LiveBundles.find_next(i))
|
|
|
|
if (B[i] == NoCand) {
|
|
|
|
B[i] = C;
|
|
|
|
Count++;
|
|
|
|
}
|
|
|
|
return Count;
|
|
|
|
}
|
2011-03-05 01:10:31 +00:00
|
|
|
};
|
|
|
|
|
2013-11-19 23:51:32 +00:00
|
|
|
/// Candidate info for each PhysReg in AllocationOrder.
|
2011-03-05 01:10:31 +00:00
|
|
|
/// This vector never shrinks, but grows to the size of the largest register
|
|
|
|
/// class.
|
|
|
|
SmallVector<GlobalSplitCandidate, 32> GlobalCand;
|
|
|
|
|
2014-03-02 03:20:38 +00:00
|
|
|
enum : unsigned { NoCand = ~0u };
|
2011-07-26 23:41:46 +00:00
|
|
|
|
|
|
|
/// Candidate map. Each edge bundle is assigned to a GlobalCand entry, or to
|
|
|
|
/// NoCand which indicates the stack interval.
|
|
|
|
SmallVector<unsigned, 32> BundleCand;
|
|
|
|
|
2014-04-08 19:18:56 +00:00
|
|
|
/// Callee-save register cost, calculated once per machine function.
|
|
|
|
BlockFrequency CSRCost;
|
|
|
|
|
2014-07-02 18:32:04 +00:00
|
|
|
/// Run or not the local reassignment heuristic. This information is
|
|
|
|
/// obtained from the TargetSubtargetInfo.
|
|
|
|
bool EnableLocalReassign;
|
|
|
|
|
[RegAllocGreedy] Introduce a late pass to repair broken hints.
A broken hint is a copy where both ends are assigned different colors. When a
variable gets evicted in the neighborhood of such copies, it is likely we can
reconcile some of them.
** Context **
Copies are inserted during the register allocation via splitting. These split
points are required to relax the constraints on the allocation problem. When
such a point is inserted, both ends of the copy would not share the same color
with respect to the current allocation problem. When variables get evicted,
the allocation problem becomes different and some split point may not be
required anymore. However, the related variables may already have been colored.
This usually shows up in the assembly with pattern like this:
def A
...
save A to B
def A
use A
restore A from B
...
use B
Whereas we could simply have done:
def B
...
def A
use A
...
use B
** Proposed Solution **
A variable having a broken hint is marked for late recoloring if and only if
selecting a register for it evict another variable. Indeed, if no eviction
happens this is pointless to look for recoloring opportunities as it means the
situation was the same as the initial allocation problem where we had to break
the hint.
Finally, when everything has been allocated, we look for recoloring
opportunities for all the identified candidates.
The recoloring is performed very late to rely on accurate copy cost (all
involved variables are allocated).
The recoloring is simple unlike the last change recoloring. It propagates the
color of the broken hint to all its copy-related variables. If the color is
available for them, the recoloring uses it, otherwise it gives up on that hint
even if a more complex coloring would have worked.
The recoloring happens only if it is profitable. The profitability is evaluated
using the expected frequency of the copies of the currently recolored variable
with a) its current color and b) with the target color. If a) is greater or
equal than b), then it is profitable and the recoloring happen.
** Example **
Consider the following example:
BB1:
a =
b =
BB2:
...
= b
= a
Let us assume b gets split:
BB1:
a =
b =
BB2:
c = b
...
d = c
= d
= a
Because of how the allocation work, b, c, and d may be assigned different
colors. Now, if a gets evicted to make room for c, assuming b and d were
assigned to something different than a.
We end up with:
BB1:
a =
st a, SpillSlot
b =
BB2:
c = b
...
d = c
= d
e = ld SpillSlot
= e
This is likely that we can assign the same register for b, c, and d,
getting rid of 2 copies.
** Performances **
Both ARM64 and x86_64 show performance improvements of up to 3% for the
llvm-testsuite + externals with Os and O3. There are a few regressions too that
comes from the (in)accuracy of the block frequency estimate.
<rdar://problem/18312047>
llvm-svn: 225422
2015-01-08 01:16:39 +00:00
|
|
|
/// Set of broken hints that may be reconciled later because of eviction.
|
|
|
|
SmallSetVector<LiveInterval *, 8> SetOfBrokenHints;
|
|
|
|
|
2010-12-08 03:26:16 +00:00
|
|
|
public:
|
|
|
|
RAGreedy();
|
|
|
|
|
|
|
|
/// Return the pass name.
|
2014-03-07 09:26:03 +00:00
|
|
|
const char* getPassName() const override {
|
2010-12-11 00:19:56 +00:00
|
|
|
return "Greedy Register Allocator";
|
2010-12-08 03:26:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// RAGreedy analysis usage.
|
2014-03-07 09:26:03 +00:00
|
|
|
void getAnalysisUsage(AnalysisUsage &AU) const override;
|
|
|
|
void releaseMemory() override;
|
|
|
|
Spiller &spiller() override { return *SpillerInstance; }
|
|
|
|
void enqueue(LiveInterval *LI) override;
|
|
|
|
LiveInterval *dequeue() override;
|
|
|
|
unsigned selectOrSplit(LiveInterval&, SmallVectorImpl<unsigned>&) override;
|
[RegAllocGreedy] Introduce a late pass to repair broken hints.
A broken hint is a copy where both ends are assigned different colors. When a
variable gets evicted in the neighborhood of such copies, it is likely we can
reconcile some of them.
** Context **
Copies are inserted during the register allocation via splitting. These split
points are required to relax the constraints on the allocation problem. When
such a point is inserted, both ends of the copy would not share the same color
with respect to the current allocation problem. When variables get evicted,
the allocation problem becomes different and some split point may not be
required anymore. However, the related variables may already have been colored.
This usually shows up in the assembly with pattern like this:
def A
...
save A to B
def A
use A
restore A from B
...
use B
Whereas we could simply have done:
def B
...
def A
use A
...
use B
** Proposed Solution **
A variable having a broken hint is marked for late recoloring if and only if
selecting a register for it evict another variable. Indeed, if no eviction
happens this is pointless to look for recoloring opportunities as it means the
situation was the same as the initial allocation problem where we had to break
the hint.
Finally, when everything has been allocated, we look for recoloring
opportunities for all the identified candidates.
The recoloring is performed very late to rely on accurate copy cost (all
involved variables are allocated).
The recoloring is simple unlike the last change recoloring. It propagates the
color of the broken hint to all its copy-related variables. If the color is
available for them, the recoloring uses it, otherwise it gives up on that hint
even if a more complex coloring would have worked.
The recoloring happens only if it is profitable. The profitability is evaluated
using the expected frequency of the copies of the currently recolored variable
with a) its current color and b) with the target color. If a) is greater or
equal than b), then it is profitable and the recoloring happen.
** Example **
Consider the following example:
BB1:
a =
b =
BB2:
...
= b
= a
Let us assume b gets split:
BB1:
a =
b =
BB2:
c = b
...
d = c
= d
= a
Because of how the allocation work, b, c, and d may be assigned different
colors. Now, if a gets evicted to make room for c, assuming b and d were
assigned to something different than a.
We end up with:
BB1:
a =
st a, SpillSlot
b =
BB2:
c = b
...
d = c
= d
e = ld SpillSlot
= e
This is likely that we can assign the same register for b, c, and d,
getting rid of 2 copies.
** Performances **
Both ARM64 and x86_64 show performance improvements of up to 3% for the
llvm-testsuite + externals with Os and O3. There are a few regressions too that
comes from the (in)accuracy of the block frequency estimate.
<rdar://problem/18312047>
llvm-svn: 225422
2015-01-08 01:16:39 +00:00
|
|
|
void aboutToRemoveInterval(LiveInterval &) override;
|
2010-12-08 03:26:16 +00:00
|
|
|
|
|
|
|
/// Perform register allocation.
|
2014-03-07 09:26:03 +00:00
|
|
|
bool runOnMachineFunction(MachineFunction &mf) override;
|
2010-12-08 03:26:16 +00:00
|
|
|
|
|
|
|
static char ID;
|
2010-12-09 18:15:21 +00:00
|
|
|
|
|
|
|
private:
|
2014-02-05 22:13:59 +00:00
|
|
|
unsigned selectOrSplitImpl(LiveInterval &, SmallVectorImpl<unsigned> &,
|
|
|
|
SmallVirtRegSet &, unsigned = 0);
|
|
|
|
|
2014-03-07 09:26:03 +00:00
|
|
|
bool LRE_CanEraseVirtReg(unsigned) override;
|
|
|
|
void LRE_WillShrinkVirtReg(unsigned) override;
|
|
|
|
void LRE_DidCloneVirtReg(unsigned, unsigned) override;
|
2014-02-05 22:13:59 +00:00
|
|
|
void enqueue(PQueue &CurQueue, LiveInterval *LI);
|
|
|
|
LiveInterval *dequeue(PQueue &CurQueue);
|
2011-03-09 00:57:29 +00:00
|
|
|
|
2013-07-16 18:26:18 +00:00
|
|
|
BlockFrequency calcSpillCost();
|
|
|
|
bool addSplitConstraints(InterferenceCache::Cursor, BlockFrequency&);
|
2011-04-09 02:59:09 +00:00
|
|
|
void addThroughConstraints(InterferenceCache::Cursor, ArrayRef<unsigned>);
|
2011-07-14 00:17:10 +00:00
|
|
|
void growRegion(GlobalSplitCandidate &Cand);
|
2013-07-16 18:26:18 +00:00
|
|
|
BlockFrequency calcGlobalSplitCost(GlobalSplitCandidate&);
|
2011-07-23 03:41:57 +00:00
|
|
|
bool calcCompactRegion(GlobalSplitCandidate&);
|
2011-07-26 23:41:46 +00:00
|
|
|
void splitAroundRegion(LiveRangeEdit&, ArrayRef<unsigned>);
|
2011-02-17 19:13:53 +00:00
|
|
|
void calcGapWeights(unsigned, SmallVectorImpl<float>&);
|
2013-07-25 18:35:19 +00:00
|
|
|
unsigned canReassign(LiveInterval &VirtReg, unsigned PhysReg);
|
2011-07-08 20:46:18 +00:00
|
|
|
bool shouldEvict(LiveInterval &A, bool, LiveInterval &B, bool);
|
|
|
|
bool canEvictInterference(LiveInterval&, unsigned, bool, EvictionCost&);
|
|
|
|
void evictInterference(LiveInterval&, unsigned,
|
2013-08-14 23:50:04 +00:00
|
|
|
SmallVectorImpl<unsigned>&);
|
2014-02-05 22:13:59 +00:00
|
|
|
bool mayRecolorAllInterferences(unsigned PhysReg, LiveInterval &VirtReg,
|
|
|
|
SmallLISet &RecoloringCandidates,
|
|
|
|
const SmallVirtRegSet &FixedRegisters);
|
2010-12-14 00:37:44 +00:00
|
|
|
|
2011-04-20 18:19:48 +00:00
|
|
|
unsigned tryAssign(LiveInterval&, AllocationOrder&,
|
2013-08-14 23:50:04 +00:00
|
|
|
SmallVectorImpl<unsigned>&);
|
2011-02-23 00:29:52 +00:00
|
|
|
unsigned tryEvict(LiveInterval&, AllocationOrder&,
|
2013-08-14 23:50:04 +00:00
|
|
|
SmallVectorImpl<unsigned>&, unsigned = ~0u);
|
2011-01-18 21:13:27 +00:00
|
|
|
unsigned tryRegionSplit(LiveInterval&, AllocationOrder&,
|
2013-08-14 23:50:04 +00:00
|
|
|
SmallVectorImpl<unsigned>&);
|
2014-03-24 23:23:42 +00:00
|
|
|
/// Calculate cost of region splitting.
|
|
|
|
unsigned calculateRegionSplitCost(LiveInterval &VirtReg,
|
|
|
|
AllocationOrder &Order,
|
|
|
|
BlockFrequency &BestCost,
|
2014-03-25 00:16:25 +00:00
|
|
|
unsigned &NumCands, bool IgnoreCSR);
|
2014-03-24 23:23:42 +00:00
|
|
|
/// Perform region splitting.
|
|
|
|
unsigned doRegionSplit(LiveInterval &VirtReg, unsigned BestCand,
|
|
|
|
bool HasCompact,
|
|
|
|
SmallVectorImpl<unsigned> &NewVRegs);
|
2014-03-27 21:21:57 +00:00
|
|
|
/// Check other options before using a callee-saved register for the first
|
|
|
|
/// time.
|
|
|
|
unsigned tryAssignCSRFirstTime(LiveInterval &VirtReg, AllocationOrder &Order,
|
|
|
|
unsigned PhysReg, unsigned &CostPerUseLimit,
|
|
|
|
SmallVectorImpl<unsigned> &NewVRegs);
|
2014-04-08 19:18:56 +00:00
|
|
|
void initializeCSRCost();
|
2011-08-05 23:04:18 +00:00
|
|
|
unsigned tryBlockSplit(LiveInterval&, AllocationOrder&,
|
2013-08-14 23:50:04 +00:00
|
|
|
SmallVectorImpl<unsigned>&);
|
2012-05-23 22:37:27 +00:00
|
|
|
unsigned tryInstructionSplit(LiveInterval&, AllocationOrder&,
|
2013-08-14 23:50:04 +00:00
|
|
|
SmallVectorImpl<unsigned>&);
|
2011-02-17 19:13:53 +00:00
|
|
|
unsigned tryLocalSplit(LiveInterval&, AllocationOrder&,
|
2013-08-14 23:50:04 +00:00
|
|
|
SmallVectorImpl<unsigned>&);
|
2010-12-14 00:37:44 +00:00
|
|
|
unsigned trySplit(LiveInterval&, AllocationOrder&,
|
2013-08-14 23:50:04 +00:00
|
|
|
SmallVectorImpl<unsigned>&);
|
2014-02-05 22:13:59 +00:00
|
|
|
unsigned tryLastChanceRecoloring(LiveInterval &, AllocationOrder &,
|
|
|
|
SmallVectorImpl<unsigned> &,
|
|
|
|
SmallVirtRegSet &, unsigned);
|
|
|
|
bool tryRecoloringCandidates(PQueue &, SmallVectorImpl<unsigned> &,
|
|
|
|
SmallVirtRegSet &, unsigned);
|
[RegAllocGreedy] Introduce a late pass to repair broken hints.
A broken hint is a copy where both ends are assigned different colors. When a
variable gets evicted in the neighborhood of such copies, it is likely we can
reconcile some of them.
** Context **
Copies are inserted during the register allocation via splitting. These split
points are required to relax the constraints on the allocation problem. When
such a point is inserted, both ends of the copy would not share the same color
with respect to the current allocation problem. When variables get evicted,
the allocation problem becomes different and some split point may not be
required anymore. However, the related variables may already have been colored.
This usually shows up in the assembly with pattern like this:
def A
...
save A to B
def A
use A
restore A from B
...
use B
Whereas we could simply have done:
def B
...
def A
use A
...
use B
** Proposed Solution **
A variable having a broken hint is marked for late recoloring if and only if
selecting a register for it evict another variable. Indeed, if no eviction
happens this is pointless to look for recoloring opportunities as it means the
situation was the same as the initial allocation problem where we had to break
the hint.
Finally, when everything has been allocated, we look for recoloring
opportunities for all the identified candidates.
The recoloring is performed very late to rely on accurate copy cost (all
involved variables are allocated).
The recoloring is simple unlike the last change recoloring. It propagates the
color of the broken hint to all its copy-related variables. If the color is
available for them, the recoloring uses it, otherwise it gives up on that hint
even if a more complex coloring would have worked.
The recoloring happens only if it is profitable. The profitability is evaluated
using the expected frequency of the copies of the currently recolored variable
with a) its current color and b) with the target color. If a) is greater or
equal than b), then it is profitable and the recoloring happen.
** Example **
Consider the following example:
BB1:
a =
b =
BB2:
...
= b
= a
Let us assume b gets split:
BB1:
a =
b =
BB2:
c = b
...
d = c
= d
= a
Because of how the allocation work, b, c, and d may be assigned different
colors. Now, if a gets evicted to make room for c, assuming b and d were
assigned to something different than a.
We end up with:
BB1:
a =
st a, SpillSlot
b =
BB2:
c = b
...
d = c
= d
e = ld SpillSlot
= e
This is likely that we can assign the same register for b, c, and d,
getting rid of 2 copies.
** Performances **
Both ARM64 and x86_64 show performance improvements of up to 3% for the
llvm-testsuite + externals with Os and O3. There are a few regressions too that
comes from the (in)accuracy of the block frequency estimate.
<rdar://problem/18312047>
llvm-svn: 225422
2015-01-08 01:16:39 +00:00
|
|
|
void tryHintRecoloring(LiveInterval &);
|
|
|
|
void tryHintsRecoloring();
|
|
|
|
|
|
|
|
/// Model the information carried by one end of a copy.
|
|
|
|
struct HintInfo {
|
|
|
|
/// The frequency of the copy.
|
|
|
|
BlockFrequency Freq;
|
|
|
|
/// The virtual register or physical register.
|
|
|
|
unsigned Reg;
|
|
|
|
/// Its currently assigned register.
|
|
|
|
/// In case of a physical register Reg == PhysReg.
|
|
|
|
unsigned PhysReg;
|
|
|
|
HintInfo(BlockFrequency Freq, unsigned Reg, unsigned PhysReg)
|
|
|
|
: Freq(Freq), Reg(Reg), PhysReg(PhysReg) {}
|
|
|
|
};
|
|
|
|
typedef SmallVector<HintInfo, 4> HintsInfo;
|
|
|
|
BlockFrequency getBrokenHintFreq(const HintsInfo &, unsigned);
|
|
|
|
void collectHintInfo(unsigned, HintsInfo &);
|
2015-07-14 17:38:17 +00:00
|
|
|
|
|
|
|
bool isUnusedCalleeSavedReg(unsigned PhysReg) const;
|
2010-12-08 03:26:16 +00:00
|
|
|
};
|
|
|
|
} // end anonymous namespace
|
|
|
|
|
|
|
|
char RAGreedy::ID = 0;
|
|
|
|
|
2011-05-25 23:58:36 +00:00
|
|
|
#ifndef NDEBUG
|
|
|
|
const char *const RAGreedy::StageName[] = {
|
2011-07-25 15:25:41 +00:00
|
|
|
"RS_New",
|
|
|
|
"RS_Assign",
|
|
|
|
"RS_Split",
|
2011-07-25 15:25:43 +00:00
|
|
|
"RS_Split2",
|
2011-07-25 15:25:41 +00:00
|
|
|
"RS_Spill",
|
2015-07-17 23:04:06 +00:00
|
|
|
"RS_Memory",
|
2011-07-25 15:25:41 +00:00
|
|
|
"RS_Done"
|
2011-05-25 23:58:36 +00:00
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
2011-04-22 22:47:40 +00:00
|
|
|
// Hysteresis to use when comparing floats.
|
|
|
|
// This helps stabilize decisions based on float comparisons.
|
2014-02-04 06:29:38 +00:00
|
|
|
const float Hysteresis = (2007 / 2048.0f); // 0.97998046875
|
2011-04-22 22:47:40 +00:00
|
|
|
|
|
|
|
|
2010-12-08 03:26:16 +00:00
|
|
|
FunctionPass* llvm::createGreedyRegisterAllocator() {
|
|
|
|
return new RAGreedy();
|
|
|
|
}
|
|
|
|
|
2011-07-02 01:37:09 +00:00
|
|
|
RAGreedy::RAGreedy(): MachineFunctionPass(ID) {
|
2011-04-05 21:40:37 +00:00
|
|
|
initializeLiveDebugVariablesPass(*PassRegistry::getPassRegistry());
|
2011-01-18 21:13:27 +00:00
|
|
|
initializeSlotIndexesPass(*PassRegistry::getPassRegistry());
|
2010-12-08 03:26:16 +00:00
|
|
|
initializeLiveIntervalsPass(*PassRegistry::getPassRegistry());
|
|
|
|
initializeSlotIndexesPass(*PassRegistry::getPassRegistry());
|
2011-06-26 22:34:10 +00:00
|
|
|
initializeRegisterCoalescerPass(*PassRegistry::getPassRegistry());
|
2012-01-17 06:55:03 +00:00
|
|
|
initializeMachineSchedulerPass(*PassRegistry::getPassRegistry());
|
2010-12-08 03:26:16 +00:00
|
|
|
initializeLiveStacksPass(*PassRegistry::getPassRegistry());
|
|
|
|
initializeMachineDominatorTreePass(*PassRegistry::getPassRegistry());
|
|
|
|
initializeMachineLoopInfoPass(*PassRegistry::getPassRegistry());
|
|
|
|
initializeVirtRegMapPass(*PassRegistry::getPassRegistry());
|
2012-06-20 22:52:26 +00:00
|
|
|
initializeLiveRegMatrixPass(*PassRegistry::getPassRegistry());
|
2011-01-18 21:13:27 +00:00
|
|
|
initializeEdgeBundlesPass(*PassRegistry::getPassRegistry());
|
|
|
|
initializeSpillPlacementPass(*PassRegistry::getPassRegistry());
|
2010-12-08 03:26:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void RAGreedy::getAnalysisUsage(AnalysisUsage &AU) const {
|
|
|
|
AU.setPreservesCFG();
|
2013-06-17 19:00:36 +00:00
|
|
|
AU.addRequired<MachineBlockFrequencyInfo>();
|
|
|
|
AU.addPreserved<MachineBlockFrequencyInfo>();
|
[PM/AA] Rebuild LLVM's alias analysis infrastructure in a way compatible
with the new pass manager, and no longer relying on analysis groups.
This builds essentially a ground-up new AA infrastructure stack for
LLVM. The core ideas are the same that are used throughout the new pass
manager: type erased polymorphism and direct composition. The design is
as follows:
- FunctionAAResults is a type-erasing alias analysis results aggregation
interface to walk a single query across a range of results from
different alias analyses. Currently this is function-specific as we
always assume that aliasing queries are *within* a function.
- AAResultBase is a CRTP utility providing stub implementations of
various parts of the alias analysis result concept, notably in several
cases in terms of other more general parts of the interface. This can
be used to implement only a narrow part of the interface rather than
the entire interface. This isn't really ideal, this logic should be
hoisted into FunctionAAResults as currently it will cause
a significant amount of redundant work, but it faithfully models the
behavior of the prior infrastructure.
- All the alias analysis passes are ported to be wrapper passes for the
legacy PM and new-style analysis passes for the new PM with a shared
result object. In some cases (most notably CFL), this is an extremely
naive approach that we should revisit when we can specialize for the
new pass manager.
- BasicAA has been restructured to reflect that it is much more
fundamentally a function analysis because it uses dominator trees and
loop info that need to be constructed for each function.
All of the references to getting alias analysis results have been
updated to use the new aggregation interface. All the preservation and
other pass management code has been updated accordingly.
The way the FunctionAAResultsWrapperPass works is to detect the
available alias analyses when run, and add them to the results object.
This means that we should be able to continue to respect when various
passes are added to the pipeline, for example adding CFL or adding TBAA
passes should just cause their results to be available and to get folded
into this. The exception to this rule is BasicAA which really needs to
be a function pass due to using dominator trees and loop info. As
a consequence, the FunctionAAResultsWrapperPass directly depends on
BasicAA and always includes it in the aggregation.
This has significant implications for preserving analyses. Generally,
most passes shouldn't bother preserving FunctionAAResultsWrapperPass
because rebuilding the results just updates the set of known AA passes.
The exception to this rule are LoopPass instances which need to preserve
all the function analyses that the loop pass manager will end up
needing. This means preserving both BasicAAWrapperPass and the
aggregating FunctionAAResultsWrapperPass.
Now, when preserving an alias analysis, you do so by directly preserving
that analysis. This is only necessary for non-immutable-pass-provided
alias analyses though, and there are only three of interest: BasicAA,
GlobalsAA (formerly GlobalsModRef), and SCEVAA. Usually BasicAA is
preserved when needed because it (like DominatorTree and LoopInfo) is
marked as a CFG-only pass. I've expanded GlobalsAA into the preserved
set everywhere we previously were preserving all of AliasAnalysis, and
I've added SCEVAA in the intersection of that with where we preserve
SCEV itself.
One significant challenge to all of this is that the CGSCC passes were
actually using the alias analysis implementations by taking advantage of
a pretty amazing set of loop holes in the old pass manager's analysis
management code which allowed analysis groups to slide through in many
cases. Moving away from analysis groups makes this problem much more
obvious. To fix it, I've leveraged the flexibility the design of the new
PM components provides to just directly construct the relevant alias
analyses for the relevant functions in the IPO passes that need them.
This is a bit hacky, but should go away with the new pass manager, and
is already in many ways cleaner than the prior state.
Another significant challenge is that various facilities of the old
alias analysis infrastructure just don't fit any more. The most
significant of these is the alias analysis 'counter' pass. That pass
relied on the ability to snoop on AA queries at different points in the
analysis group chain. Instead, I'm planning to build printing
functionality directly into the aggregation layer. I've not included
that in this patch merely to keep it smaller.
Note that all of this needs a nearly complete rewrite of the AA
documentation. I'm planning to do that, but I'd like to make sure the
new design settles, and to flesh out a bit more of what it looks like in
the new pass manager first.
Differential Revision: http://reviews.llvm.org/D12080
llvm-svn: 247167
2015-09-09 17:55:00 +00:00
|
|
|
AU.addRequired<AAResultsWrapperPass>();
|
|
|
|
AU.addPreserved<AAResultsWrapperPass>();
|
2010-12-08 03:26:16 +00:00
|
|
|
AU.addRequired<LiveIntervals>();
|
2012-06-08 23:44:45 +00:00
|
|
|
AU.addPreserved<LiveIntervals>();
|
2011-01-18 21:13:27 +00:00
|
|
|
AU.addRequired<SlotIndexes>();
|
2010-12-08 03:26:16 +00:00
|
|
|
AU.addPreserved<SlotIndexes>();
|
2011-04-05 21:40:37 +00:00
|
|
|
AU.addRequired<LiveDebugVariables>();
|
|
|
|
AU.addPreserved<LiveDebugVariables>();
|
2010-12-08 03:26:16 +00:00
|
|
|
AU.addRequired<LiveStacks>();
|
|
|
|
AU.addPreserved<LiveStacks>();
|
2010-12-17 23:16:32 +00:00
|
|
|
AU.addRequired<MachineDominatorTree>();
|
|
|
|
AU.addPreserved<MachineDominatorTree>();
|
2010-12-08 03:26:16 +00:00
|
|
|
AU.addRequired<MachineLoopInfo>();
|
|
|
|
AU.addPreserved<MachineLoopInfo>();
|
|
|
|
AU.addRequired<VirtRegMap>();
|
|
|
|
AU.addPreserved<VirtRegMap>();
|
2012-06-20 22:52:26 +00:00
|
|
|
AU.addRequired<LiveRegMatrix>();
|
|
|
|
AU.addPreserved<LiveRegMatrix>();
|
2011-01-18 21:13:27 +00:00
|
|
|
AU.addRequired<EdgeBundles>();
|
|
|
|
AU.addRequired<SpillPlacement>();
|
2010-12-08 03:26:16 +00:00
|
|
|
MachineFunctionPass::getAnalysisUsage(AU);
|
|
|
|
}
|
|
|
|
|
2011-03-09 00:57:29 +00:00
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// LiveRangeEdit delegate methods
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2011-03-13 01:23:11 +00:00
|
|
|
bool RAGreedy::LRE_CanEraseVirtReg(unsigned VirtReg) {
|
2012-06-20 22:52:26 +00:00
|
|
|
if (VRM->hasPhys(VirtReg)) {
|
[RegAllocGreedy] Introduce a late pass to repair broken hints.
A broken hint is a copy where both ends are assigned different colors. When a
variable gets evicted in the neighborhood of such copies, it is likely we can
reconcile some of them.
** Context **
Copies are inserted during the register allocation via splitting. These split
points are required to relax the constraints on the allocation problem. When
such a point is inserted, both ends of the copy would not share the same color
with respect to the current allocation problem. When variables get evicted,
the allocation problem becomes different and some split point may not be
required anymore. However, the related variables may already have been colored.
This usually shows up in the assembly with pattern like this:
def A
...
save A to B
def A
use A
restore A from B
...
use B
Whereas we could simply have done:
def B
...
def A
use A
...
use B
** Proposed Solution **
A variable having a broken hint is marked for late recoloring if and only if
selecting a register for it evict another variable. Indeed, if no eviction
happens this is pointless to look for recoloring opportunities as it means the
situation was the same as the initial allocation problem where we had to break
the hint.
Finally, when everything has been allocated, we look for recoloring
opportunities for all the identified candidates.
The recoloring is performed very late to rely on accurate copy cost (all
involved variables are allocated).
The recoloring is simple unlike the last change recoloring. It propagates the
color of the broken hint to all its copy-related variables. If the color is
available for them, the recoloring uses it, otherwise it gives up on that hint
even if a more complex coloring would have worked.
The recoloring happens only if it is profitable. The profitability is evaluated
using the expected frequency of the copies of the currently recolored variable
with a) its current color and b) with the target color. If a) is greater or
equal than b), then it is profitable and the recoloring happen.
** Example **
Consider the following example:
BB1:
a =
b =
BB2:
...
= b
= a
Let us assume b gets split:
BB1:
a =
b =
BB2:
c = b
...
d = c
= d
= a
Because of how the allocation work, b, c, and d may be assigned different
colors. Now, if a gets evicted to make room for c, assuming b and d were
assigned to something different than a.
We end up with:
BB1:
a =
st a, SpillSlot
b =
BB2:
c = b
...
d = c
= d
e = ld SpillSlot
= e
This is likely that we can assign the same register for b, c, and d,
getting rid of 2 copies.
** Performances **
Both ARM64 and x86_64 show performance improvements of up to 3% for the
llvm-testsuite + externals with Os and O3. There are a few regressions too that
comes from the (in)accuracy of the block frequency estimate.
<rdar://problem/18312047>
llvm-svn: 225422
2015-01-08 01:16:39 +00:00
|
|
|
LiveInterval &LI = LIS->getInterval(VirtReg);
|
|
|
|
Matrix->unassign(LI);
|
|
|
|
aboutToRemoveInterval(LI);
|
2011-03-13 01:23:11 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
// Unassigned virtreg is probably in the priority queue.
|
|
|
|
// RegAllocBase will erase it after dequeueing.
|
|
|
|
return false;
|
|
|
|
}
|
2011-03-09 00:57:29 +00:00
|
|
|
|
2011-03-16 22:56:16 +00:00
|
|
|
void RAGreedy::LRE_WillShrinkVirtReg(unsigned VirtReg) {
|
2012-06-20 22:52:26 +00:00
|
|
|
if (!VRM->hasPhys(VirtReg))
|
2011-03-16 22:56:16 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
// Register is assigned, put it back on the queue for reassignment.
|
|
|
|
LiveInterval &LI = LIS->getInterval(VirtReg);
|
2012-06-20 22:52:26 +00:00
|
|
|
Matrix->unassign(LI);
|
2011-03-16 22:56:16 +00:00
|
|
|
enqueue(&LI);
|
|
|
|
}
|
|
|
|
|
2011-03-30 02:52:39 +00:00
|
|
|
void RAGreedy::LRE_DidCloneVirtReg(unsigned New, unsigned Old) {
|
2011-09-14 17:34:37 +00:00
|
|
|
// Cloning a register we haven't even heard about yet? Just ignore it.
|
|
|
|
if (!ExtraRegInfo.inBounds(Old))
|
|
|
|
return;
|
|
|
|
|
2011-03-30 02:52:39 +00:00
|
|
|
// LRE may clone a virtual register because dead code elimination causes it to
|
2011-07-26 00:54:56 +00:00
|
|
|
// be split into connected components. The new components are much smaller
|
|
|
|
// than the original, so they should get a new chance at being assigned.
|
2011-03-30 02:52:39 +00:00
|
|
|
// same stage as the parent.
|
2011-07-26 00:54:56 +00:00
|
|
|
ExtraRegInfo[Old].Stage = RS_Assign;
|
2011-07-02 01:37:09 +00:00
|
|
|
ExtraRegInfo.grow(New);
|
|
|
|
ExtraRegInfo[New] = ExtraRegInfo[Old];
|
2011-03-30 02:52:39 +00:00
|
|
|
}
|
|
|
|
|
2010-12-08 03:26:16 +00:00
|
|
|
void RAGreedy::releaseMemory() {
|
2014-07-19 01:05:11 +00:00
|
|
|
SpillerInstance.reset();
|
2011-07-02 01:37:09 +00:00
|
|
|
ExtraRegInfo.clear();
|
2011-04-12 21:30:53 +00:00
|
|
|
GlobalCand.clear();
|
2010-12-08 03:26:16 +00:00
|
|
|
}
|
|
|
|
|
2014-02-05 22:13:59 +00:00
|
|
|
void RAGreedy::enqueue(LiveInterval *LI) { enqueue(Queue, LI); }
|
|
|
|
|
|
|
|
void RAGreedy::enqueue(PQueue &CurQueue, LiveInterval *LI) {
|
2011-02-22 23:01:52 +00:00
|
|
|
// Prioritize live ranges by size, assigning larger ranges first.
|
|
|
|
// The queue holds (size, reg) pairs.
|
2011-02-24 23:21:36 +00:00
|
|
|
const unsigned Size = LI->getSize();
|
|
|
|
const unsigned Reg = LI->reg;
|
2011-02-22 23:01:52 +00:00
|
|
|
assert(TargetRegisterInfo::isVirtualRegister(Reg) &&
|
|
|
|
"Can only enqueue virtual registers");
|
2011-02-24 23:21:36 +00:00
|
|
|
unsigned Prio;
|
2010-12-08 22:57:16 +00:00
|
|
|
|
2011-07-02 01:37:09 +00:00
|
|
|
ExtraRegInfo.grow(Reg);
|
|
|
|
if (ExtraRegInfo[Reg].Stage == RS_New)
|
2011-07-25 15:25:41 +00:00
|
|
|
ExtraRegInfo[Reg].Stage = RS_Assign;
|
2011-03-30 02:52:39 +00:00
|
|
|
|
Reverse order of RS_Split live ranges under -compact-regions.
There are two conflicting strategies in play:
- Under high register pressure, we want to assign large live ranges
first. Smaller live ranges are easier to place afterwards.
- Live range splitting is guided by interference, so splitting should be
deferred until interference is as realistic as possible.
With the recent changes to the live range stages, and with compact
regions enabled, it is less traumatic to split a live range too early.
If some of the split products were too big, they can often be split
again.
By reversing the RS_Split order, we get this queue order:
1. Normal live ranges, large to small.
2. RS_Split live ranges, large to small.
The large-to-small order improves RAGreedy's puzzle solving skills under
high register pressure. It may cause a bit more iterated splitting, but
we handle that better now.
With this change, -compact-regions is mostly an improvement on SPEC.
llvm-svn: 136388
2011-07-28 20:48:23 +00:00
|
|
|
if (ExtraRegInfo[Reg].Stage == RS_Split) {
|
2011-03-27 22:49:21 +00:00
|
|
|
// Unsplit ranges that couldn't be allocated immediately are deferred until
|
2011-09-12 16:54:42 +00:00
|
|
|
// everything else has been allocated.
|
|
|
|
Prio = Size;
|
2015-07-17 23:04:06 +00:00
|
|
|
} else if (ExtraRegInfo[Reg].Stage == RS_Memory) {
|
|
|
|
// Memory operand should be considered last.
|
|
|
|
// Change the priority such that Memory operand are assigned in
|
|
|
|
// the reverse order that they came in.
|
|
|
|
// TODO: Make this a member variable and probably do something about hints.
|
|
|
|
static unsigned MemOp = 0;
|
|
|
|
Prio = MemOp++;
|
Reverse order of RS_Split live ranges under -compact-regions.
There are two conflicting strategies in play:
- Under high register pressure, we want to assign large live ranges
first. Smaller live ranges are easier to place afterwards.
- Live range splitting is guided by interference, so splitting should be
deferred until interference is as realistic as possible.
With the recent changes to the live range stages, and with compact
regions enabled, it is less traumatic to split a live range too early.
If some of the split products were too big, they can often be split
again.
By reversing the RS_Split order, we get this queue order:
1. Normal live ranges, large to small.
2. RS_Split live ranges, large to small.
The large-to-small order improves RAGreedy's puzzle solving skills under
high register pressure. It may cause a bit more iterated splitting, but
we handle that better now.
With this change, -compact-regions is mostly an improvement on SPEC.
llvm-svn: 136388
2011-07-28 20:48:23 +00:00
|
|
|
} else {
|
2014-02-26 22:07:26 +00:00
|
|
|
// Giant live ranges fall back to the global assignment heuristic, which
|
|
|
|
// prevents excessive spilling in pathological cases.
|
|
|
|
bool ReverseLocal = TRI->reverseLocalAssignment();
|
2015-03-31 19:57:53 +00:00
|
|
|
const TargetRegisterClass &RC = *MRI->getRegClass(Reg);
|
2014-10-03 12:20:53 +00:00
|
|
|
bool ForceGlobal = !ReverseLocal &&
|
2015-03-31 19:57:53 +00:00
|
|
|
(Size / SlotIndex::InstrDist) > (2 * RC.getNumRegs());
|
2014-02-26 22:07:26 +00:00
|
|
|
|
|
|
|
if (ExtraRegInfo[Reg].Stage == RS_Assign && !ForceGlobal && !LI->empty() &&
|
2013-07-25 18:35:14 +00:00
|
|
|
LIS->intervalIsInOneMBB(*LI)) {
|
|
|
|
// Allocate original local ranges in linear instruction order. Since they
|
|
|
|
// are singly defined, this produces optimal coloring in the absence of
|
|
|
|
// global interference and other constraints.
|
2014-02-26 22:07:26 +00:00
|
|
|
if (!ReverseLocal)
|
2013-12-11 03:40:15 +00:00
|
|
|
Prio = LI->beginIndex().getInstrDistance(Indexes->getLastIndex());
|
|
|
|
else {
|
|
|
|
// Allocating bottom up may allow many short LRGs to be assigned first
|
|
|
|
// to one of the cheap registers. This could be much faster for very
|
|
|
|
// large blocks on targets with many physical registers.
|
2015-03-31 19:57:49 +00:00
|
|
|
Prio = Indexes->getZeroIndex().getInstrDistance(LI->endIndex());
|
2013-12-11 03:40:15 +00:00
|
|
|
}
|
2015-03-31 19:57:53 +00:00
|
|
|
Prio |= RC.AllocationPriority << 24;
|
|
|
|
} else {
|
2013-07-25 18:35:14 +00:00
|
|
|
// Allocate global and split ranges in long->short order. Long ranges that
|
|
|
|
// don't fit should be spilled (or split) ASAP so they don't create
|
|
|
|
// interference. Mark a bit to prioritize global above local ranges.
|
|
|
|
Prio = (1u << 29) + Size;
|
|
|
|
}
|
|
|
|
// Mark a higher bit to prioritize global and local above RS_Split.
|
|
|
|
Prio |= (1u << 31);
|
2011-02-23 00:56:56 +00:00
|
|
|
|
2011-03-27 22:49:21 +00:00
|
|
|
// Boost ranges that have a physical register hint.
|
2012-12-03 23:23:50 +00:00
|
|
|
if (VRM->hasKnownPreference(Reg))
|
2011-03-27 22:49:21 +00:00
|
|
|
Prio |= (1u << 30);
|
|
|
|
}
|
2013-07-25 18:35:22 +00:00
|
|
|
// The virtual register number is a tie breaker for same-sized ranges.
|
|
|
|
// Give lower vreg numbers higher priority to assign them first.
|
2014-02-05 22:13:59 +00:00
|
|
|
CurQueue.push(std::make_pair(Prio, ~Reg));
|
2010-12-08 22:57:16 +00:00
|
|
|
}
|
|
|
|
|
2014-02-05 22:13:59 +00:00
|
|
|
LiveInterval *RAGreedy::dequeue() { return dequeue(Queue); }
|
|
|
|
|
|
|
|
LiveInterval *RAGreedy::dequeue(PQueue &CurQueue) {
|
|
|
|
if (CurQueue.empty())
|
2014-04-14 00:51:57 +00:00
|
|
|
return nullptr;
|
2014-02-05 22:13:59 +00:00
|
|
|
LiveInterval *LI = &LIS->getInterval(~CurQueue.top().second);
|
|
|
|
CurQueue.pop();
|
2011-02-22 23:01:52 +00:00
|
|
|
return LI;
|
|
|
|
}
|
2010-12-22 22:01:30 +00:00
|
|
|
|
2011-04-20 18:19:48 +00:00
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Direct Assignment
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
/// tryAssign - Try to assign VirtReg to an available register.
|
|
|
|
unsigned RAGreedy::tryAssign(LiveInterval &VirtReg,
|
|
|
|
AllocationOrder &Order,
|
2013-08-14 23:50:04 +00:00
|
|
|
SmallVectorImpl<unsigned> &NewVRegs) {
|
2011-04-20 18:19:48 +00:00
|
|
|
Order.rewind();
|
|
|
|
unsigned PhysReg;
|
2012-06-20 22:52:26 +00:00
|
|
|
while ((PhysReg = Order.next()))
|
|
|
|
if (!Matrix->checkInterference(VirtReg, PhysReg))
|
2011-04-20 18:19:48 +00:00
|
|
|
break;
|
2012-12-04 22:25:16 +00:00
|
|
|
if (!PhysReg || Order.isHint())
|
2011-04-20 18:19:48 +00:00
|
|
|
return PhysReg;
|
|
|
|
|
2011-07-08 20:46:18 +00:00
|
|
|
// PhysReg is available, but there may be a better choice.
|
|
|
|
|
|
|
|
// If we missed a simple hint, try to cheaply evict interference from the
|
|
|
|
// preferred register.
|
|
|
|
if (unsigned Hint = MRI->getSimpleHint(VirtReg.reg))
|
2012-06-20 22:52:26 +00:00
|
|
|
if (Order.isHint(Hint)) {
|
2011-07-08 20:46:18 +00:00
|
|
|
DEBUG(dbgs() << "missed hint " << PrintReg(Hint, TRI) << '\n');
|
2013-11-22 19:07:38 +00:00
|
|
|
EvictionCost MaxCost;
|
|
|
|
MaxCost.setBrokenHints(1);
|
2011-07-08 20:46:18 +00:00
|
|
|
if (canEvictInterference(VirtReg, Hint, true, MaxCost)) {
|
|
|
|
evictInterference(VirtReg, Hint, NewVRegs);
|
|
|
|
return Hint;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Try to evict interference from a cheaper alternative.
|
2011-04-20 18:19:48 +00:00
|
|
|
unsigned Cost = TRI->getCostPerUse(PhysReg);
|
|
|
|
|
|
|
|
// Most registers have 0 additional cost.
|
|
|
|
if (!Cost)
|
|
|
|
return PhysReg;
|
|
|
|
|
|
|
|
DEBUG(dbgs() << PrintReg(PhysReg, TRI) << " is available at cost " << Cost
|
|
|
|
<< '\n');
|
|
|
|
unsigned CheapReg = tryEvict(VirtReg, Order, NewVRegs, Cost);
|
|
|
|
return CheapReg ? CheapReg : PhysReg;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-02-23 00:29:52 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Interference eviction
|
|
|
|
//===----------------------------------------------------------------------===//
|
2011-02-09 01:14:03 +00:00
|
|
|
|
2013-07-25 18:35:19 +00:00
|
|
|
unsigned RAGreedy::canReassign(LiveInterval &VirtReg, unsigned PrevReg) {
|
2015-07-15 22:16:00 +00:00
|
|
|
AllocationOrder Order(VirtReg.reg, *VRM, RegClassInfo, Matrix);
|
2013-07-25 18:35:19 +00:00
|
|
|
unsigned PhysReg;
|
|
|
|
while ((PhysReg = Order.next())) {
|
|
|
|
if (PhysReg == PrevReg)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
MCRegUnitIterator Units(PhysReg, TRI);
|
|
|
|
for (; Units.isValid(); ++Units) {
|
|
|
|
// Instantiate a "subquery", not to be confused with the Queries array.
|
|
|
|
LiveIntervalUnion::Query subQ(&VirtReg, &Matrix->getLiveUnions()[*Units]);
|
|
|
|
if (subQ.checkInterference())
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// If no units have interference, break out with the current PhysReg.
|
|
|
|
if (!Units.isValid())
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (PhysReg)
|
|
|
|
DEBUG(dbgs() << "can reassign: " << VirtReg << " from "
|
|
|
|
<< PrintReg(PrevReg, TRI) << " to " << PrintReg(PhysReg, TRI)
|
|
|
|
<< '\n');
|
|
|
|
return PhysReg;
|
|
|
|
}
|
|
|
|
|
2011-07-08 20:46:18 +00:00
|
|
|
/// shouldEvict - determine if A should evict the assigned live range B. The
|
|
|
|
/// eviction policy defined by this function together with the allocation order
|
|
|
|
/// defined by enqueue() decides which registers ultimately end up being split
|
|
|
|
/// and spilled.
|
2011-05-25 23:58:36 +00:00
|
|
|
///
|
2011-07-02 01:37:09 +00:00
|
|
|
/// Cascade numbers are used to prevent infinite loops if this function is a
|
|
|
|
/// cyclic relation.
|
2011-07-08 20:46:18 +00:00
|
|
|
///
|
|
|
|
/// @param A The live range to be assigned.
|
|
|
|
/// @param IsHint True when A is about to be assigned to its preferred
|
|
|
|
/// register.
|
|
|
|
/// @param B The live range to be evicted.
|
|
|
|
/// @param BreaksHint True when B is already assigned to its preferred register.
|
|
|
|
bool RAGreedy::shouldEvict(LiveInterval &A, bool IsHint,
|
|
|
|
LiveInterval &B, bool BreaksHint) {
|
2011-07-25 15:25:43 +00:00
|
|
|
bool CanSplit = getStage(B) < RS_Spill;
|
2011-07-08 20:46:18 +00:00
|
|
|
|
|
|
|
// Be fairly aggressive about following hints as long as the evictee can be
|
|
|
|
// split.
|
|
|
|
if (CanSplit && IsHint && !BreaksHint)
|
|
|
|
return true;
|
|
|
|
|
2013-11-22 19:07:42 +00:00
|
|
|
if (A.weight > B.weight) {
|
|
|
|
DEBUG(dbgs() << "should evict: " << B << " w= " << B.weight << '\n');
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
2011-05-25 23:58:36 +00:00
|
|
|
}
|
|
|
|
|
2011-07-08 20:46:18 +00:00
|
|
|
/// canEvictInterference - Return true if all interferences between VirtReg and
|
2014-02-25 19:47:15 +00:00
|
|
|
/// PhysReg can be evicted.
|
2011-07-08 20:46:18 +00:00
|
|
|
///
|
|
|
|
/// @param VirtReg Live range that is about to be assigned.
|
|
|
|
/// @param PhysReg Desired register for assignment.
|
2012-09-12 16:59:47 +00:00
|
|
|
/// @param IsHint True when PhysReg is VirtReg's preferred register.
|
2011-07-08 20:46:18 +00:00
|
|
|
/// @param MaxCost Only look for cheaper candidates and update with new cost
|
|
|
|
/// when returning true.
|
|
|
|
/// @returns True when interference can be evicted cheaper than MaxCost.
|
2011-02-23 00:29:52 +00:00
|
|
|
bool RAGreedy::canEvictInterference(LiveInterval &VirtReg, unsigned PhysReg,
|
2011-07-08 20:46:18 +00:00
|
|
|
bool IsHint, EvictionCost &MaxCost) {
|
2012-06-20 22:52:26 +00:00
|
|
|
// It is only possible to evict virtual register interference.
|
|
|
|
if (Matrix->checkInterference(VirtReg, PhysReg) > LiveRegMatrix::IK_VirtReg)
|
|
|
|
return false;
|
|
|
|
|
2013-07-25 18:35:14 +00:00
|
|
|
bool IsLocal = LIS->intervalIsInOneMBB(VirtReg);
|
|
|
|
|
2011-07-02 01:37:09 +00:00
|
|
|
// Find VirtReg's cascade number. This will be unassigned if VirtReg was never
|
|
|
|
// involved in an eviction before. If a cascade number was assigned, deny
|
|
|
|
// evicting anything with the same or a newer cascade number. This prevents
|
|
|
|
// infinite eviction loops.
|
|
|
|
//
|
|
|
|
// This works out so a register without a cascade number is allowed to evict
|
|
|
|
// anything, and it can be evicted by anything.
|
|
|
|
unsigned Cascade = ExtraRegInfo[VirtReg.reg].Cascade;
|
|
|
|
if (!Cascade)
|
|
|
|
Cascade = NextCascade;
|
|
|
|
|
2011-07-08 20:46:18 +00:00
|
|
|
EvictionCost Cost;
|
2012-06-20 22:52:26 +00:00
|
|
|
for (MCRegUnitIterator Units(PhysReg, TRI); Units.isValid(); ++Units) {
|
|
|
|
LiveIntervalUnion::Query &Q = Matrix->query(VirtReg, *Units);
|
2011-04-11 21:47:01 +00:00
|
|
|
// If there is 10 or more interferences, chances are one is heavier.
|
2011-07-08 20:46:18 +00:00
|
|
|
if (Q.collectInterferingVRegs(10) >= 10)
|
2011-02-23 00:29:52 +00:00
|
|
|
return false;
|
|
|
|
|
2011-04-11 21:47:01 +00:00
|
|
|
// Check if any interfering live range is heavier than MaxWeight.
|
|
|
|
for (unsigned i = Q.interferingVRegs().size(); i; --i) {
|
|
|
|
LiveInterval *Intf = Q.interferingVRegs()[i - 1];
|
2012-06-20 22:52:26 +00:00
|
|
|
assert(TargetRegisterInfo::isVirtualRegister(Intf->reg) &&
|
|
|
|
"Only expecting virtual register interference from query");
|
2011-07-08 20:46:18 +00:00
|
|
|
// Never evict spill products. They cannot split or spill.
|
2011-07-25 15:25:41 +00:00
|
|
|
if (getStage(*Intf) == RS_Done)
|
2011-07-02 01:37:09 +00:00
|
|
|
return false;
|
2011-07-08 20:46:18 +00:00
|
|
|
// Once a live range becomes small enough, it is urgent that we find a
|
|
|
|
// register for it. This is indicated by an infinite spill weight. These
|
|
|
|
// urgent live ranges get to evict almost anything.
|
2012-05-30 21:46:58 +00:00
|
|
|
//
|
|
|
|
// Also allow urgent evictions of unspillable ranges from a strictly
|
|
|
|
// larger allocation order.
|
|
|
|
bool Urgent = !VirtReg.isSpillable() &&
|
|
|
|
(Intf->isSpillable() ||
|
|
|
|
RegClassInfo.getNumAllocatableRegs(MRI->getRegClass(VirtReg.reg)) <
|
|
|
|
RegClassInfo.getNumAllocatableRegs(MRI->getRegClass(Intf->reg)));
|
2011-07-08 20:46:18 +00:00
|
|
|
// Only evict older cascades or live ranges without a cascade.
|
|
|
|
unsigned IntfCascade = ExtraRegInfo[Intf->reg].Cascade;
|
|
|
|
if (Cascade <= IntfCascade) {
|
|
|
|
if (!Urgent)
|
|
|
|
return false;
|
|
|
|
// We permit breaking cascades for urgent evictions. It should be the
|
|
|
|
// last resort, though, so make it really expensive.
|
|
|
|
Cost.BrokenHints += 10;
|
|
|
|
}
|
|
|
|
// Would this break a satisfied hint?
|
|
|
|
bool BreaksHint = VRM->hasPreferredPhys(Intf->reg);
|
|
|
|
// Update eviction cost.
|
|
|
|
Cost.BrokenHints += BreaksHint;
|
|
|
|
Cost.MaxWeight = std::max(Cost.MaxWeight, Intf->weight);
|
|
|
|
// Abort if this would be too expensive.
|
|
|
|
if (!(Cost < MaxCost))
|
2011-05-25 23:58:36 +00:00
|
|
|
return false;
|
2013-07-25 18:35:14 +00:00
|
|
|
if (Urgent)
|
|
|
|
continue;
|
2013-11-29 23:49:38 +00:00
|
|
|
// Apply the eviction policy for non-urgent evictions.
|
|
|
|
if (!shouldEvict(VirtReg, IsHint, *Intf, BreaksHint))
|
|
|
|
return false;
|
2013-07-25 18:35:14 +00:00
|
|
|
// If !MaxCost.isMax(), then we're just looking for a cheap register.
|
|
|
|
// Evicting another local live range in this case could lead to suboptimal
|
|
|
|
// coloring.
|
2013-07-25 18:35:19 +00:00
|
|
|
if (!MaxCost.isMax() && IsLocal && LIS->intervalIsInOneMBB(*Intf) &&
|
2014-07-02 18:32:04 +00:00
|
|
|
(!EnableLocalReassign || !canReassign(*Intf, PhysReg))) {
|
2013-07-25 18:35:14 +00:00
|
|
|
return false;
|
2013-07-25 18:35:19 +00:00
|
|
|
}
|
2011-02-09 01:14:03 +00:00
|
|
|
}
|
|
|
|
}
|
2011-07-08 20:46:18 +00:00
|
|
|
MaxCost = Cost;
|
2011-02-23 00:29:52 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2011-07-08 20:46:18 +00:00
|
|
|
/// evictInterference - Evict any interferring registers that prevent VirtReg
|
|
|
|
/// from being assigned to Physreg. This assumes that canEvictInterference
|
|
|
|
/// returned true.
|
|
|
|
void RAGreedy::evictInterference(LiveInterval &VirtReg, unsigned PhysReg,
|
2013-08-14 23:50:04 +00:00
|
|
|
SmallVectorImpl<unsigned> &NewVRegs) {
|
2011-07-08 20:46:18 +00:00
|
|
|
// Make sure that VirtReg has a cascade number, and assign that cascade
|
|
|
|
// number to every evicted register. These live ranges than then only be
|
|
|
|
// evicted by a newer cascade, preventing infinite loops.
|
|
|
|
unsigned Cascade = ExtraRegInfo[VirtReg.reg].Cascade;
|
|
|
|
if (!Cascade)
|
|
|
|
Cascade = ExtraRegInfo[VirtReg.reg].Cascade = NextCascade++;
|
|
|
|
|
|
|
|
DEBUG(dbgs() << "evicting " << PrintReg(PhysReg, TRI)
|
|
|
|
<< " interference: Cascade " << Cascade << '\n');
|
2012-06-20 22:52:26 +00:00
|
|
|
|
|
|
|
// Collect all interfering virtregs first.
|
|
|
|
SmallVector<LiveInterval*, 8> Intfs;
|
|
|
|
for (MCRegUnitIterator Units(PhysReg, TRI); Units.isValid(); ++Units) {
|
|
|
|
LiveIntervalUnion::Query &Q = Matrix->query(VirtReg, *Units);
|
2011-07-08 20:46:18 +00:00
|
|
|
assert(Q.seenAllInterferences() && "Didn't check all interfererences.");
|
2012-06-20 22:52:26 +00:00
|
|
|
ArrayRef<LiveInterval*> IVR = Q.interferingVRegs();
|
|
|
|
Intfs.append(IVR.begin(), IVR.end());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Evict them second. This will invalidate the queries.
|
|
|
|
for (unsigned i = 0, e = Intfs.size(); i != e; ++i) {
|
|
|
|
LiveInterval *Intf = Intfs[i];
|
|
|
|
// The same VirtReg may be present in multiple RegUnits. Skip duplicates.
|
|
|
|
if (!VRM->hasPhys(Intf->reg))
|
|
|
|
continue;
|
|
|
|
Matrix->unassign(*Intf);
|
|
|
|
assert((ExtraRegInfo[Intf->reg].Cascade < Cascade ||
|
|
|
|
VirtReg.isSpillable() < Intf->isSpillable()) &&
|
|
|
|
"Cannot decrease cascade number, illegal eviction");
|
|
|
|
ExtraRegInfo[Intf->reg].Cascade = Cascade;
|
|
|
|
++NumEvicted;
|
2013-08-14 23:50:04 +00:00
|
|
|
NewVRegs.push_back(Intf->reg);
|
2011-07-08 20:46:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-14 17:38:17 +00:00
|
|
|
/// Returns true if the given \p PhysReg is a callee saved register and has not
|
|
|
|
/// been used for allocation yet.
|
|
|
|
bool RAGreedy::isUnusedCalleeSavedReg(unsigned PhysReg) const {
|
|
|
|
unsigned CSR = RegClassInfo.getLastCalleeSavedAlias(PhysReg);
|
|
|
|
if (CSR == 0)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return !Matrix->isPhysRegUsed(PhysReg);
|
|
|
|
}
|
|
|
|
|
2011-02-23 00:29:52 +00:00
|
|
|
/// tryEvict - Try to evict all interferences for a physreg.
|
2011-06-01 18:45:02 +00:00
|
|
|
/// @param VirtReg Currently unassigned virtual register.
|
|
|
|
/// @param Order Physregs to try.
|
|
|
|
/// @return Physreg to assign VirtReg, or 0.
|
2011-02-23 00:29:52 +00:00
|
|
|
unsigned RAGreedy::tryEvict(LiveInterval &VirtReg,
|
|
|
|
AllocationOrder &Order,
|
2013-08-14 23:50:04 +00:00
|
|
|
SmallVectorImpl<unsigned> &NewVRegs,
|
2011-04-20 18:19:48 +00:00
|
|
|
unsigned CostPerUseLimit) {
|
2011-02-23 00:29:52 +00:00
|
|
|
NamedRegionTimer T("Evict", TimerGroupName, TimePassesIsEnabled);
|
|
|
|
|
2011-07-08 20:46:18 +00:00
|
|
|
// Keep track of the cheapest interference seen so far.
|
2013-11-22 19:07:38 +00:00
|
|
|
EvictionCost BestCost;
|
|
|
|
BestCost.setMax();
|
2011-02-23 00:29:52 +00:00
|
|
|
unsigned BestPhys = 0;
|
2013-01-12 00:57:44 +00:00
|
|
|
unsigned OrderLimit = Order.getOrder().size();
|
2011-02-23 00:29:52 +00:00
|
|
|
|
2011-07-08 20:46:18 +00:00
|
|
|
// When we are just looking for a reduced cost per use, don't break any
|
|
|
|
// hints, and only evict smaller spill weights.
|
|
|
|
if (CostPerUseLimit < ~0u) {
|
|
|
|
BestCost.BrokenHints = 0;
|
|
|
|
BestCost.MaxWeight = VirtReg.weight;
|
2013-01-12 00:57:44 +00:00
|
|
|
|
|
|
|
// Check of any registers in RC are below CostPerUseLimit.
|
|
|
|
const TargetRegisterClass *RC = MRI->getRegClass(VirtReg.reg);
|
|
|
|
unsigned MinCost = RegClassInfo.getMinCost(RC);
|
|
|
|
if (MinCost >= CostPerUseLimit) {
|
2014-11-17 05:50:14 +00:00
|
|
|
DEBUG(dbgs() << TRI->getRegClassName(RC) << " minimum cost = " << MinCost
|
2013-01-12 00:57:44 +00:00
|
|
|
<< ", no cheaper registers to be found.\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// It is normal for register classes to have a long tail of registers with
|
|
|
|
// the same cost. We don't need to look at them if they're too expensive.
|
|
|
|
if (TRI->getCostPerUse(Order.getOrder().back()) >= CostPerUseLimit) {
|
|
|
|
OrderLimit = RegClassInfo.getLastCostChange(RC);
|
|
|
|
DEBUG(dbgs() << "Only trying the first " << OrderLimit << " regs.\n");
|
|
|
|
}
|
2011-07-08 20:46:18 +00:00
|
|
|
}
|
|
|
|
|
2011-02-23 00:29:52 +00:00
|
|
|
Order.rewind();
|
2013-12-05 21:18:40 +00:00
|
|
|
while (unsigned PhysReg = Order.next(OrderLimit)) {
|
2011-04-20 18:19:48 +00:00
|
|
|
if (TRI->getCostPerUse(PhysReg) >= CostPerUseLimit)
|
|
|
|
continue;
|
2011-07-08 20:46:18 +00:00
|
|
|
// The first use of a callee-saved register in a function has cost 1.
|
|
|
|
// Don't start using a CSR when the CostPerUseLimit is low.
|
2015-07-14 17:38:17 +00:00
|
|
|
if (CostPerUseLimit == 1 && isUnusedCalleeSavedReg(PhysReg)) {
|
|
|
|
DEBUG(dbgs() << PrintReg(PhysReg, TRI) << " would clobber CSR "
|
|
|
|
<< PrintReg(RegClassInfo.getLastCalleeSavedAlias(PhysReg), TRI)
|
|
|
|
<< '\n');
|
|
|
|
continue;
|
|
|
|
}
|
2011-07-08 20:46:18 +00:00
|
|
|
|
|
|
|
if (!canEvictInterference(VirtReg, PhysReg, false, BestCost))
|
2011-02-23 00:29:52 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
// Best so far.
|
|
|
|
BestPhys = PhysReg;
|
2011-07-08 20:46:18 +00:00
|
|
|
|
2011-02-25 01:04:22 +00:00
|
|
|
// Stop if the hint can be used.
|
2012-12-04 22:25:16 +00:00
|
|
|
if (Order.isHint())
|
2011-02-25 01:04:22 +00:00
|
|
|
break;
|
2011-02-09 01:14:03 +00:00
|
|
|
}
|
|
|
|
|
2011-02-23 00:29:52 +00:00
|
|
|
if (!BestPhys)
|
|
|
|
return 0;
|
|
|
|
|
2011-07-08 20:46:18 +00:00
|
|
|
evictInterference(VirtReg, BestPhys, NewVRegs);
|
2011-02-23 00:29:52 +00:00
|
|
|
return BestPhys;
|
2010-12-09 18:15:21 +00:00
|
|
|
}
|
|
|
|
|
2010-12-22 22:01:30 +00:00
|
|
|
|
2011-01-18 21:13:27 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Region Splitting
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2011-04-06 21:32:38 +00:00
|
|
|
/// addSplitConstraints - Fill out the SplitConstraints vector based on the
|
|
|
|
/// interference pattern in Physreg and its aliases. Add the constraints to
|
|
|
|
/// SpillPlacement and return the static cost of this split in Cost, assuming
|
|
|
|
/// that all preferences in SplitConstraints are met.
|
2011-04-09 02:59:09 +00:00
|
|
|
/// Return false if there are no bundles with positive bias.
|
|
|
|
bool RAGreedy::addSplitConstraints(InterferenceCache::Cursor Intf,
|
2013-07-16 18:26:18 +00:00
|
|
|
BlockFrequency &Cost) {
|
2011-04-06 03:57:00 +00:00
|
|
|
ArrayRef<SplitAnalysis::BlockInfo> UseBlocks = SA->getUseBlocks();
|
2011-04-02 06:03:38 +00:00
|
|
|
|
2011-01-18 21:13:27 +00:00
|
|
|
// Reset interference dependent info.
|
2011-04-06 03:57:00 +00:00
|
|
|
SplitConstraints.resize(UseBlocks.size());
|
2013-07-16 18:26:18 +00:00
|
|
|
BlockFrequency StaticCost = 0;
|
2011-04-06 03:57:00 +00:00
|
|
|
for (unsigned i = 0; i != UseBlocks.size(); ++i) {
|
|
|
|
const SplitAnalysis::BlockInfo &BI = UseBlocks[i];
|
2011-03-05 01:10:31 +00:00
|
|
|
SpillPlacement::BlockConstraint &BC = SplitConstraints[i];
|
|
|
|
|
2011-02-09 22:50:26 +00:00
|
|
|
BC.Number = BI.MBB->getNumber();
|
2011-04-02 06:03:38 +00:00
|
|
|
Intf.moveToBlock(BC.Number);
|
2011-04-06 03:57:00 +00:00
|
|
|
BC.Entry = BI.LiveIn ? SpillPlacement::PrefReg : SpillPlacement::DontCare;
|
|
|
|
BC.Exit = BI.LiveOut ? SpillPlacement::PrefReg : SpillPlacement::DontCare;
|
2013-05-15 07:36:59 +00:00
|
|
|
BC.ChangesValue = BI.FirstDef.isValid();
|
2011-01-18 21:13:27 +00:00
|
|
|
|
2011-04-02 06:03:38 +00:00
|
|
|
if (!Intf.hasInterference())
|
|
|
|
continue;
|
|
|
|
|
2011-03-05 01:10:31 +00:00
|
|
|
// Number of spill code instructions to insert.
|
|
|
|
unsigned Ins = 0;
|
|
|
|
|
|
|
|
// Interference for the live-in value.
|
2011-04-02 06:03:38 +00:00
|
|
|
if (BI.LiveIn) {
|
2016-02-18 22:09:30 +00:00
|
|
|
if (Intf.first() <= Indexes->getMBBStartIdx(BC.Number)) {
|
|
|
|
BC.Entry = SpillPlacement::MustSpill;
|
2011-03-05 01:10:31 +00:00
|
|
|
++Ins;
|
2016-02-18 22:09:30 +00:00
|
|
|
} else if (Intf.first() < BI.FirstInstr) {
|
|
|
|
BC.Entry = SpillPlacement::PrefSpill;
|
|
|
|
++Ins;
|
|
|
|
} else if (Intf.first() < BI.LastInstr) {
|
|
|
|
++Ins;
|
|
|
|
}
|
2011-02-08 23:02:58 +00:00
|
|
|
}
|
2011-01-18 21:13:27 +00:00
|
|
|
|
2011-03-05 01:10:31 +00:00
|
|
|
// Interference for the live-out value.
|
2011-04-02 06:03:38 +00:00
|
|
|
if (BI.LiveOut) {
|
2016-02-18 22:09:30 +00:00
|
|
|
if (Intf.last() >= SA->getLastSplitPoint(BC.Number)) {
|
|
|
|
BC.Exit = SpillPlacement::MustSpill;
|
|
|
|
++Ins;
|
|
|
|
} else if (Intf.last() > BI.LastInstr) {
|
|
|
|
BC.Exit = SpillPlacement::PrefSpill;
|
2011-03-05 01:10:31 +00:00
|
|
|
++Ins;
|
2016-02-18 22:09:30 +00:00
|
|
|
} else if (Intf.last() > BI.FirstInstr) {
|
|
|
|
++Ins;
|
|
|
|
}
|
2011-01-18 21:13:27 +00:00
|
|
|
}
|
|
|
|
|
2011-03-05 01:10:31 +00:00
|
|
|
// Accumulate the total frequency of inserted spill code.
|
2013-07-16 18:26:18 +00:00
|
|
|
while (Ins--)
|
|
|
|
StaticCost += SpillPlacer->getBlockFrequency(BC.Number);
|
2011-01-18 21:13:27 +00:00
|
|
|
}
|
2011-04-09 02:59:09 +00:00
|
|
|
Cost = StaticCost;
|
2011-04-06 03:57:00 +00:00
|
|
|
|
2011-04-06 21:32:38 +00:00
|
|
|
// Add constraints for use-blocks. Note that these are the only constraints
|
|
|
|
// that may add a positive bias, it is downhill from here.
|
|
|
|
SpillPlacer->addConstraints(SplitConstraints);
|
2011-04-09 02:59:09 +00:00
|
|
|
return SpillPlacer->scanActiveBundles();
|
|
|
|
}
|
2011-04-06 03:57:00 +00:00
|
|
|
|
|
|
|
|
2011-04-09 02:59:09 +00:00
|
|
|
/// addThroughConstraints - Add constraints and links to SpillPlacer from the
|
|
|
|
/// live-through blocks in Blocks.
|
|
|
|
void RAGreedy::addThroughConstraints(InterferenceCache::Cursor Intf,
|
|
|
|
ArrayRef<unsigned> Blocks) {
|
2011-04-06 21:32:38 +00:00
|
|
|
const unsigned GroupSize = 8;
|
|
|
|
SpillPlacement::BlockConstraint BCS[GroupSize];
|
2011-04-09 02:59:09 +00:00
|
|
|
unsigned TBS[GroupSize];
|
|
|
|
unsigned B = 0, T = 0;
|
2011-04-06 03:57:00 +00:00
|
|
|
|
2011-04-09 02:59:09 +00:00
|
|
|
for (unsigned i = 0; i != Blocks.size(); ++i) {
|
|
|
|
unsigned Number = Blocks[i];
|
2011-04-06 21:32:38 +00:00
|
|
|
Intf.moveToBlock(Number);
|
|
|
|
|
2011-04-07 17:27:46 +00:00
|
|
|
if (!Intf.hasInterference()) {
|
2011-04-09 02:59:09 +00:00
|
|
|
assert(T < GroupSize && "Array overflow");
|
|
|
|
TBS[T] = Number;
|
|
|
|
if (++T == GroupSize) {
|
2011-07-18 12:00:32 +00:00
|
|
|
SpillPlacer->addLinks(makeArrayRef(TBS, T));
|
2011-04-09 02:59:09 +00:00
|
|
|
T = 0;
|
|
|
|
}
|
2011-04-07 17:27:46 +00:00
|
|
|
continue;
|
2011-04-06 21:32:38 +00:00
|
|
|
}
|
|
|
|
|
2011-04-09 02:59:09 +00:00
|
|
|
assert(B < GroupSize && "Array overflow");
|
|
|
|
BCS[B].Number = Number;
|
|
|
|
|
2011-04-07 17:27:46 +00:00
|
|
|
// Interference for the live-in value.
|
|
|
|
if (Intf.first() <= Indexes->getMBBStartIdx(Number))
|
|
|
|
BCS[B].Entry = SpillPlacement::MustSpill;
|
|
|
|
else
|
|
|
|
BCS[B].Entry = SpillPlacement::PrefSpill;
|
|
|
|
|
|
|
|
// Interference for the live-out value.
|
|
|
|
if (Intf.last() >= SA->getLastSplitPoint(Number))
|
|
|
|
BCS[B].Exit = SpillPlacement::MustSpill;
|
|
|
|
else
|
|
|
|
BCS[B].Exit = SpillPlacement::PrefSpill;
|
|
|
|
|
2011-04-06 21:32:38 +00:00
|
|
|
if (++B == GroupSize) {
|
2014-08-27 05:25:25 +00:00
|
|
|
SpillPlacer->addConstraints(makeArrayRef(BCS, B));
|
2011-04-06 21:32:38 +00:00
|
|
|
B = 0;
|
|
|
|
}
|
2011-04-06 03:57:00 +00:00
|
|
|
}
|
|
|
|
|
2014-08-27 05:25:25 +00:00
|
|
|
SpillPlacer->addConstraints(makeArrayRef(BCS, B));
|
2011-07-18 12:00:32 +00:00
|
|
|
SpillPlacer->addLinks(makeArrayRef(TBS, T));
|
2011-01-18 21:13:27 +00:00
|
|
|
}
|
|
|
|
|
2011-07-14 00:17:10 +00:00
|
|
|
void RAGreedy::growRegion(GlobalSplitCandidate &Cand) {
|
2011-04-12 21:30:53 +00:00
|
|
|
// Keep track of through blocks that have not been added to SpillPlacer.
|
|
|
|
BitVector Todo = SA->getThroughBlocks();
|
|
|
|
SmallVectorImpl<unsigned> &ActiveBlocks = Cand.ActiveBlocks;
|
|
|
|
unsigned AddedTo = 0;
|
2011-04-09 02:59:09 +00:00
|
|
|
#ifndef NDEBUG
|
|
|
|
unsigned Visited = 0;
|
|
|
|
#endif
|
2011-04-12 21:30:53 +00:00
|
|
|
|
2011-04-09 02:59:09 +00:00
|
|
|
for (;;) {
|
|
|
|
ArrayRef<unsigned> NewBundles = SpillPlacer->getRecentPositive();
|
|
|
|
// Find new through blocks in the periphery of PrefRegBundles.
|
|
|
|
for (int i = 0, e = NewBundles.size(); i != e; ++i) {
|
|
|
|
unsigned Bundle = NewBundles[i];
|
|
|
|
// Look at all blocks connected to Bundle in the full graph.
|
|
|
|
ArrayRef<unsigned> Blocks = Bundles->getBlocks(Bundle);
|
|
|
|
for (ArrayRef<unsigned>::iterator I = Blocks.begin(), E = Blocks.end();
|
|
|
|
I != E; ++I) {
|
|
|
|
unsigned Block = *I;
|
2011-04-12 21:30:53 +00:00
|
|
|
if (!Todo.test(Block))
|
2011-04-09 02:59:09 +00:00
|
|
|
continue;
|
2011-04-12 21:30:53 +00:00
|
|
|
Todo.reset(Block);
|
2011-04-09 02:59:09 +00:00
|
|
|
// This is a new through block. Add it to SpillPlacer later.
|
2011-04-12 21:30:53 +00:00
|
|
|
ActiveBlocks.push_back(Block);
|
2011-04-09 02:59:09 +00:00
|
|
|
#ifndef NDEBUG
|
|
|
|
++Visited;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Any new blocks to add?
|
2011-07-05 18:46:42 +00:00
|
|
|
if (ActiveBlocks.size() == AddedTo)
|
|
|
|
break;
|
2011-07-23 03:22:33 +00:00
|
|
|
|
|
|
|
// Compute through constraints from the interference, or assume that all
|
|
|
|
// through blocks prefer spilling when forming compact regions.
|
2014-08-27 05:25:25 +00:00
|
|
|
auto NewBlocks = makeArrayRef(ActiveBlocks).slice(AddedTo);
|
2011-07-23 03:22:33 +00:00
|
|
|
if (Cand.PhysReg)
|
|
|
|
addThroughConstraints(Cand.Intf, NewBlocks);
|
|
|
|
else
|
2011-08-03 23:09:38 +00:00
|
|
|
// Provide a strong negative bias on through blocks to prevent unwanted
|
|
|
|
// liveness on loop backedges.
|
|
|
|
SpillPlacer->addPrefSpill(NewBlocks, /* Strong= */ true);
|
2011-07-05 18:46:42 +00:00
|
|
|
AddedTo = ActiveBlocks.size();
|
|
|
|
|
2011-04-09 02:59:09 +00:00
|
|
|
// Perhaps iterating can enable more bundles?
|
|
|
|
SpillPlacer->iterate();
|
|
|
|
}
|
|
|
|
DEBUG(dbgs() << ", v=" << Visited);
|
|
|
|
}
|
2011-03-05 01:10:31 +00:00
|
|
|
|
2011-07-23 03:41:57 +00:00
|
|
|
/// calcCompactRegion - Compute the set of edge bundles that should be live
|
|
|
|
/// when splitting the current live range into compact regions. Compact
|
|
|
|
/// regions can be computed without looking at interference. They are the
|
|
|
|
/// regions formed by removing all the live-through blocks from the live range.
|
|
|
|
///
|
|
|
|
/// Returns false if the current live range is already compact, or if the
|
|
|
|
/// compact regions would form single block regions anyway.
|
|
|
|
bool RAGreedy::calcCompactRegion(GlobalSplitCandidate &Cand) {
|
|
|
|
// Without any through blocks, the live range is already compact.
|
|
|
|
if (!SA->getNumThroughBlocks())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Compact regions don't correspond to any physreg.
|
|
|
|
Cand.reset(IntfCache, 0);
|
|
|
|
|
|
|
|
DEBUG(dbgs() << "Compact region bundles");
|
|
|
|
|
|
|
|
// Use the spill placer to determine the live bundles. GrowRegion pretends
|
|
|
|
// that all the through blocks have interference when PhysReg is unset.
|
|
|
|
SpillPlacer->prepare(Cand.LiveBundles);
|
|
|
|
|
|
|
|
// The static split cost will be zero since Cand.Intf reports no interference.
|
2013-07-16 18:26:18 +00:00
|
|
|
BlockFrequency Cost;
|
2011-07-23 03:41:57 +00:00
|
|
|
if (!addSplitConstraints(Cand.Intf, Cost)) {
|
|
|
|
DEBUG(dbgs() << ", none.\n");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
growRegion(Cand);
|
|
|
|
SpillPlacer->finish();
|
|
|
|
|
|
|
|
if (!Cand.LiveBundles.any()) {
|
|
|
|
DEBUG(dbgs() << ", none.\n");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
DEBUG({
|
|
|
|
for (int i = Cand.LiveBundles.find_first(); i>=0;
|
|
|
|
i = Cand.LiveBundles.find_next(i))
|
|
|
|
dbgs() << " EB#" << i;
|
|
|
|
dbgs() << ".\n";
|
|
|
|
});
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2011-04-22 22:47:40 +00:00
|
|
|
/// calcSpillCost - Compute how expensive it would be to split the live range in
|
|
|
|
/// SA around all use blocks instead of forming bundle regions.
|
2013-07-16 18:26:18 +00:00
|
|
|
BlockFrequency RAGreedy::calcSpillCost() {
|
|
|
|
BlockFrequency Cost = 0;
|
2011-04-22 22:47:40 +00:00
|
|
|
ArrayRef<SplitAnalysis::BlockInfo> UseBlocks = SA->getUseBlocks();
|
|
|
|
for (unsigned i = 0; i != UseBlocks.size(); ++i) {
|
|
|
|
const SplitAnalysis::BlockInfo &BI = UseBlocks[i];
|
|
|
|
unsigned Number = BI.MBB->getNumber();
|
|
|
|
// We normally only need one spill instruction - a load or a store.
|
|
|
|
Cost += SpillPlacer->getBlockFrequency(Number);
|
|
|
|
|
|
|
|
// Unless the value is redefined in the block.
|
2011-08-02 23:04:08 +00:00
|
|
|
if (BI.LiveIn && BI.LiveOut && BI.FirstDef)
|
|
|
|
Cost += SpillPlacer->getBlockFrequency(Number);
|
2011-04-22 22:47:40 +00:00
|
|
|
}
|
|
|
|
return Cost;
|
|
|
|
}
|
|
|
|
|
2011-01-18 21:13:27 +00:00
|
|
|
/// calcGlobalSplitCost - Return the global split cost of following the split
|
|
|
|
/// pattern in LiveBundles. This cost should be added to the local cost of the
|
2011-03-05 01:10:31 +00:00
|
|
|
/// interference pattern in SplitConstraints.
|
2011-01-18 21:13:27 +00:00
|
|
|
///
|
2013-07-16 18:26:18 +00:00
|
|
|
BlockFrequency RAGreedy::calcGlobalSplitCost(GlobalSplitCandidate &Cand) {
|
|
|
|
BlockFrequency GlobalCost = 0;
|
2011-04-12 21:30:53 +00:00
|
|
|
const BitVector &LiveBundles = Cand.LiveBundles;
|
2011-04-06 03:57:00 +00:00
|
|
|
ArrayRef<SplitAnalysis::BlockInfo> UseBlocks = SA->getUseBlocks();
|
|
|
|
for (unsigned i = 0; i != UseBlocks.size(); ++i) {
|
|
|
|
const SplitAnalysis::BlockInfo &BI = UseBlocks[i];
|
2011-03-05 01:10:31 +00:00
|
|
|
SpillPlacement::BlockConstraint &BC = SplitConstraints[i];
|
2011-03-05 03:28:51 +00:00
|
|
|
bool RegIn = LiveBundles[Bundles->getBundle(BC.Number, 0)];
|
|
|
|
bool RegOut = LiveBundles[Bundles->getBundle(BC.Number, 1)];
|
|
|
|
unsigned Ins = 0;
|
|
|
|
|
2011-04-06 03:57:00 +00:00
|
|
|
if (BI.LiveIn)
|
|
|
|
Ins += RegIn != (BC.Entry == SpillPlacement::PrefReg);
|
|
|
|
if (BI.LiveOut)
|
|
|
|
Ins += RegOut != (BC.Exit == SpillPlacement::PrefReg);
|
2013-07-16 18:26:18 +00:00
|
|
|
while (Ins--)
|
|
|
|
GlobalCost += SpillPlacer->getBlockFrequency(BC.Number);
|
2011-01-18 21:13:27 +00:00
|
|
|
}
|
2011-04-06 03:57:00 +00:00
|
|
|
|
2011-04-12 21:30:53 +00:00
|
|
|
for (unsigned i = 0, e = Cand.ActiveBlocks.size(); i != e; ++i) {
|
|
|
|
unsigned Number = Cand.ActiveBlocks[i];
|
2011-04-06 03:57:00 +00:00
|
|
|
bool RegIn = LiveBundles[Bundles->getBundle(Number, 0)];
|
|
|
|
bool RegOut = LiveBundles[Bundles->getBundle(Number, 1)];
|
2011-04-06 21:32:41 +00:00
|
|
|
if (!RegIn && !RegOut)
|
|
|
|
continue;
|
|
|
|
if (RegIn && RegOut) {
|
|
|
|
// We need double spill code if this block has interference.
|
2011-07-14 00:17:10 +00:00
|
|
|
Cand.Intf.moveToBlock(Number);
|
2013-07-16 18:26:18 +00:00
|
|
|
if (Cand.Intf.hasInterference()) {
|
|
|
|
GlobalCost += SpillPlacer->getBlockFrequency(Number);
|
|
|
|
GlobalCost += SpillPlacer->getBlockFrequency(Number);
|
|
|
|
}
|
2011-04-06 21:32:41 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
// live-in / stack-out or stack-in live-out.
|
|
|
|
GlobalCost += SpillPlacer->getBlockFrequency(Number);
|
2011-04-06 03:57:00 +00:00
|
|
|
}
|
2011-01-18 21:13:27 +00:00
|
|
|
return GlobalCost;
|
|
|
|
}
|
|
|
|
|
2011-07-26 23:41:46 +00:00
|
|
|
/// splitAroundRegion - Split the current live range around the regions
|
|
|
|
/// determined by BundleCand and GlobalCand.
|
2011-01-19 22:11:48 +00:00
|
|
|
///
|
2011-07-26 23:41:46 +00:00
|
|
|
/// Before calling this function, GlobalCand and BundleCand must be initialized
|
|
|
|
/// so each bundle is assigned to a valid candidate, or NoCand for the
|
|
|
|
/// stack-bound bundles. The shared SA/SE SplitAnalysis and SplitEditor
|
|
|
|
/// objects must be initialized for the current live range, and intervals
|
|
|
|
/// created for the used candidates.
|
2011-01-19 22:11:48 +00:00
|
|
|
///
|
2011-07-26 23:41:46 +00:00
|
|
|
/// @param LREdit The LiveRangeEdit object handling the current split.
|
|
|
|
/// @param UsedCands List of used GlobalCand entries. Every BundleCand value
|
|
|
|
/// must appear in this list.
|
|
|
|
void RAGreedy::splitAroundRegion(LiveRangeEdit &LREdit,
|
|
|
|
ArrayRef<unsigned> UsedCands) {
|
|
|
|
// These are the intervals created for new global ranges. We may create more
|
|
|
|
// intervals for local ranges.
|
|
|
|
const unsigned NumGlobalIntvs = LREdit.size();
|
|
|
|
DEBUG(dbgs() << "splitAroundRegion with " << NumGlobalIntvs << " globals.\n");
|
|
|
|
assert(NumGlobalIntvs && "No global intervals configured");
|
2011-01-19 22:11:48 +00:00
|
|
|
|
2011-08-05 22:20:45 +00:00
|
|
|
// Isolate even single instructions when dealing with a proper sub-class.
|
2011-08-06 18:20:24 +00:00
|
|
|
// That guarantees register class inflation for the stack interval because it
|
2011-08-05 22:20:45 +00:00
|
|
|
// is all copies.
|
|
|
|
unsigned Reg = SA->getParent().reg;
|
|
|
|
bool SingleInstrs = RegClassInfo.isProperSubClass(MRI->getRegClass(Reg));
|
|
|
|
|
Reapply r134047 now that the world is ready for it.
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.
llvm-svn: 134125
2011-06-30 01:30:39 +00:00
|
|
|
// First handle all the blocks with uses.
|
2011-04-06 03:57:00 +00:00
|
|
|
ArrayRef<SplitAnalysis::BlockInfo> UseBlocks = SA->getUseBlocks();
|
|
|
|
for (unsigned i = 0; i != UseBlocks.size(); ++i) {
|
|
|
|
const SplitAnalysis::BlockInfo &BI = UseBlocks[i];
|
2011-07-26 23:41:46 +00:00
|
|
|
unsigned Number = BI.MBB->getNumber();
|
|
|
|
unsigned IntvIn = 0, IntvOut = 0;
|
|
|
|
SlotIndex IntfIn, IntfOut;
|
|
|
|
if (BI.LiveIn) {
|
|
|
|
unsigned CandIn = BundleCand[Bundles->getBundle(Number, 0)];
|
|
|
|
if (CandIn != NoCand) {
|
|
|
|
GlobalSplitCandidate &Cand = GlobalCand[CandIn];
|
|
|
|
IntvIn = Cand.IntvIdx;
|
|
|
|
Cand.Intf.moveToBlock(Number);
|
|
|
|
IntfIn = Cand.Intf.first();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (BI.LiveOut) {
|
|
|
|
unsigned CandOut = BundleCand[Bundles->getBundle(Number, 1)];
|
|
|
|
if (CandOut != NoCand) {
|
|
|
|
GlobalSplitCandidate &Cand = GlobalCand[CandOut];
|
|
|
|
IntvOut = Cand.IntvIdx;
|
|
|
|
Cand.Intf.moveToBlock(Number);
|
|
|
|
IntfOut = Cand.Intf.last();
|
|
|
|
}
|
|
|
|
}
|
2011-01-19 22:11:48 +00:00
|
|
|
|
2011-04-12 19:32:53 +00:00
|
|
|
// Create separate intervals for isolated blocks with multiple uses.
|
2011-07-26 23:41:46 +00:00
|
|
|
if (!IntvIn && !IntvOut) {
|
2011-04-12 19:32:53 +00:00
|
|
|
DEBUG(dbgs() << "BB#" << BI.MBB->getNumber() << " isolated.\n");
|
2011-08-05 22:20:45 +00:00
|
|
|
if (SA->shouldSplitSingleBlock(BI, SingleInstrs))
|
Reapply r134047 now that the world is ready for it.
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.
llvm-svn: 134125
2011-06-30 01:30:39 +00:00
|
|
|
SE->splitSingleBlock(BI);
|
2011-04-12 19:32:53 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2011-07-26 23:41:46 +00:00
|
|
|
if (IntvIn && IntvOut)
|
|
|
|
SE->splitLiveThroughBlock(Number, IntvIn, IntfIn, IntvOut, IntfOut);
|
|
|
|
else if (IntvIn)
|
|
|
|
SE->splitRegInBlock(BI, IntvIn, IntfIn);
|
2011-07-15 21:47:57 +00:00
|
|
|
else
|
2011-07-26 23:41:46 +00:00
|
|
|
SE->splitRegOutBlock(BI, IntvOut, IntfOut);
|
2011-01-19 22:11:48 +00:00
|
|
|
}
|
|
|
|
|
2011-07-26 23:41:46 +00:00
|
|
|
// Handle live-through blocks. The relevant live-through blocks are stored in
|
|
|
|
// the ActiveBlocks list with each candidate. We need to filter out
|
|
|
|
// duplicates.
|
|
|
|
BitVector Todo = SA->getThroughBlocks();
|
|
|
|
for (unsigned c = 0; c != UsedCands.size(); ++c) {
|
|
|
|
ArrayRef<unsigned> Blocks = GlobalCand[UsedCands[c]].ActiveBlocks;
|
|
|
|
for (unsigned i = 0, e = Blocks.size(); i != e; ++i) {
|
|
|
|
unsigned Number = Blocks[i];
|
|
|
|
if (!Todo.test(Number))
|
|
|
|
continue;
|
|
|
|
Todo.reset(Number);
|
|
|
|
|
|
|
|
unsigned IntvIn = 0, IntvOut = 0;
|
|
|
|
SlotIndex IntfIn, IntfOut;
|
|
|
|
|
|
|
|
unsigned CandIn = BundleCand[Bundles->getBundle(Number, 0)];
|
|
|
|
if (CandIn != NoCand) {
|
|
|
|
GlobalSplitCandidate &Cand = GlobalCand[CandIn];
|
|
|
|
IntvIn = Cand.IntvIdx;
|
|
|
|
Cand.Intf.moveToBlock(Number);
|
|
|
|
IntfIn = Cand.Intf.first();
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned CandOut = BundleCand[Bundles->getBundle(Number, 1)];
|
|
|
|
if (CandOut != NoCand) {
|
|
|
|
GlobalSplitCandidate &Cand = GlobalCand[CandOut];
|
|
|
|
IntvOut = Cand.IntvIdx;
|
|
|
|
Cand.Intf.moveToBlock(Number);
|
|
|
|
IntfOut = Cand.Intf.last();
|
|
|
|
}
|
|
|
|
if (!IntvIn && !IntvOut)
|
|
|
|
continue;
|
|
|
|
SE->splitLiveThroughBlock(Number, IntvIn, IntfIn, IntvOut, IntfOut);
|
|
|
|
}
|
2011-04-06 03:57:00 +00:00
|
|
|
}
|
|
|
|
|
2011-02-17 22:53:48 +00:00
|
|
|
++NumGlobalSplits;
|
2011-01-19 22:11:48 +00:00
|
|
|
|
2011-04-21 18:38:15 +00:00
|
|
|
SmallVector<unsigned, 8> IntvMap;
|
|
|
|
SE->finish(&IntvMap);
|
2013-08-14 23:50:04 +00:00
|
|
|
DebugVars->splitRegister(Reg, LREdit.regs(), *LIS);
|
2011-05-06 18:00:02 +00:00
|
|
|
|
2011-07-02 01:37:09 +00:00
|
|
|
ExtraRegInfo.resize(MRI->getNumVirtRegs());
|
2011-05-28 02:32:57 +00:00
|
|
|
unsigned OrigBlocks = SA->getNumLiveBlocks();
|
2011-04-21 18:38:15 +00:00
|
|
|
|
|
|
|
// Sort out the new intervals created by splitting. We get four kinds:
|
|
|
|
// - Remainder intervals should not be split again.
|
|
|
|
// - Candidate intervals can be assigned to Cand.PhysReg.
|
|
|
|
// - Block-local splits are candidates for local splitting.
|
|
|
|
// - DCE leftovers should go back on the queue.
|
|
|
|
for (unsigned i = 0, e = LREdit.size(); i != e; ++i) {
|
2013-08-14 23:50:04 +00:00
|
|
|
LiveInterval &Reg = LIS->getInterval(LREdit.get(i));
|
2011-04-21 18:38:15 +00:00
|
|
|
|
|
|
|
// Ignore old intervals from DCE.
|
2011-07-02 01:37:09 +00:00
|
|
|
if (getStage(Reg) != RS_New)
|
2011-04-21 18:38:15 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
// Remainder interval. Don't try splitting again, spill if it doesn't
|
|
|
|
// allocate.
|
|
|
|
if (IntvMap[i] == 0) {
|
2011-07-25 15:25:41 +00:00
|
|
|
setStage(Reg, RS_Spill);
|
2011-04-21 18:38:15 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2011-07-26 23:41:46 +00:00
|
|
|
// Global intervals. Allow repeated splitting as long as the number of live
|
|
|
|
// blocks is strictly decreasing.
|
|
|
|
if (IntvMap[i] < NumGlobalIntvs) {
|
2011-07-02 01:37:09 +00:00
|
|
|
if (SA->countLiveBlocks(&Reg) >= OrigBlocks) {
|
2011-04-26 22:33:12 +00:00
|
|
|
DEBUG(dbgs() << "Main interval covers the same " << OrigBlocks
|
|
|
|
<< " blocks as original.\n");
|
|
|
|
// Don't allow repeated splitting as a safe guard against looping.
|
2011-07-25 15:25:43 +00:00
|
|
|
setStage(Reg, RS_Split2);
|
2011-04-26 22:33:12 +00:00
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Other intervals are treated as new. This includes local intervals created
|
|
|
|
// for blocks with multiple uses, and anything created by DCE.
|
2011-04-21 18:38:15 +00:00
|
|
|
}
|
|
|
|
|
2011-03-27 22:49:21 +00:00
|
|
|
if (VerifyEnabled)
|
2011-01-19 22:11:48 +00:00
|
|
|
MF->verify(this, "After splitting live range around region");
|
|
|
|
}
|
|
|
|
|
2011-01-18 21:13:27 +00:00
|
|
|
unsigned RAGreedy::tryRegionSplit(LiveInterval &VirtReg, AllocationOrder &Order,
|
2013-08-14 23:50:04 +00:00
|
|
|
SmallVectorImpl<unsigned> &NewVRegs) {
|
2011-07-14 00:17:10 +00:00
|
|
|
unsigned NumCands = 0;
|
2013-07-16 18:26:18 +00:00
|
|
|
BlockFrequency BestCost;
|
2011-07-26 23:41:46 +00:00
|
|
|
|
|
|
|
// Check if we can split this live range around a compact region.
|
2011-09-12 16:54:42 +00:00
|
|
|
bool HasCompact = calcCompactRegion(GlobalCand.front());
|
2011-07-26 23:41:46 +00:00
|
|
|
if (HasCompact) {
|
|
|
|
// Yes, keep GlobalCand[0] as the compact region candidate.
|
|
|
|
NumCands = 1;
|
2013-07-16 18:26:18 +00:00
|
|
|
BestCost = BlockFrequency::getMaxFrequency();
|
2011-07-26 23:41:46 +00:00
|
|
|
} else {
|
|
|
|
// No benefit from the compact region, our fallback will be per-block
|
|
|
|
// splitting. Make sure we find a solution that is cheaper than spilling.
|
2013-07-16 18:26:18 +00:00
|
|
|
BestCost = calcSpillCost();
|
2013-12-14 00:25:45 +00:00
|
|
|
DEBUG(dbgs() << "Cost of isolating all blocks = ";
|
|
|
|
MBFI->printBlockFreq(dbgs(), BestCost) << '\n');
|
2011-07-26 23:41:46 +00:00
|
|
|
}
|
2011-03-05 01:10:31 +00:00
|
|
|
|
2014-03-24 23:23:42 +00:00
|
|
|
unsigned BestCand =
|
2014-03-25 00:16:25 +00:00
|
|
|
calculateRegionSplitCost(VirtReg, Order, BestCost, NumCands,
|
|
|
|
false/*IgnoreCSR*/);
|
2014-03-24 23:23:42 +00:00
|
|
|
|
|
|
|
// No solutions found, fall back to single block splitting.
|
|
|
|
if (!HasCompact && BestCand == NoCand)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return doRegionSplit(VirtReg, BestCand, HasCompact, NewVRegs);
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned RAGreedy::calculateRegionSplitCost(LiveInterval &VirtReg,
|
|
|
|
AllocationOrder &Order,
|
|
|
|
BlockFrequency &BestCost,
|
2014-03-25 00:16:25 +00:00
|
|
|
unsigned &NumCands,
|
|
|
|
bool IgnoreCSR) {
|
2014-03-24 23:23:42 +00:00
|
|
|
unsigned BestCand = NoCand;
|
2011-01-18 21:13:27 +00:00
|
|
|
Order.rewind();
|
2011-07-14 00:17:10 +00:00
|
|
|
while (unsigned PhysReg = Order.next()) {
|
2015-07-14 17:38:17 +00:00
|
|
|
if (IgnoreCSR && isUnusedCalleeSavedReg(PhysReg))
|
|
|
|
continue;
|
2014-03-25 00:16:25 +00:00
|
|
|
|
2011-07-14 05:35:11 +00:00
|
|
|
// Discard bad candidates before we run out of interference cache cursors.
|
|
|
|
// This will only affect register classes with a lot of registers (>32).
|
|
|
|
if (NumCands == IntfCache.getMaxCursors()) {
|
|
|
|
unsigned WorstCount = ~0u;
|
|
|
|
unsigned Worst = 0;
|
|
|
|
for (unsigned i = 0; i != NumCands; ++i) {
|
2011-07-26 23:41:46 +00:00
|
|
|
if (i == BestCand || !GlobalCand[i].PhysReg)
|
2011-07-14 05:35:11 +00:00
|
|
|
continue;
|
|
|
|
unsigned Count = GlobalCand[i].LiveBundles.count();
|
2016-02-18 22:09:30 +00:00
|
|
|
if (Count < WorstCount) {
|
|
|
|
Worst = i;
|
|
|
|
WorstCount = Count;
|
|
|
|
}
|
2011-07-14 05:35:11 +00:00
|
|
|
}
|
|
|
|
--NumCands;
|
|
|
|
GlobalCand[Worst] = GlobalCand[NumCands];
|
2011-11-01 00:02:31 +00:00
|
|
|
if (BestCand == NumCands)
|
|
|
|
BestCand = Worst;
|
2011-07-14 05:35:11 +00:00
|
|
|
}
|
|
|
|
|
2011-07-14 00:17:10 +00:00
|
|
|
if (GlobalCand.size() <= NumCands)
|
|
|
|
GlobalCand.resize(NumCands+1);
|
|
|
|
GlobalSplitCandidate &Cand = GlobalCand[NumCands];
|
|
|
|
Cand.reset(IntfCache, PhysReg);
|
2011-03-05 01:10:31 +00:00
|
|
|
|
2011-07-14 00:17:10 +00:00
|
|
|
SpillPlacer->prepare(Cand.LiveBundles);
|
2013-07-16 18:26:18 +00:00
|
|
|
BlockFrequency Cost;
|
2011-07-14 00:17:10 +00:00
|
|
|
if (!addSplitConstraints(Cand.Intf, Cost)) {
|
2011-04-09 02:59:09 +00:00
|
|
|
DEBUG(dbgs() << PrintReg(PhysReg, TRI) << "\tno positive bundles\n");
|
2011-04-06 21:32:38 +00:00
|
|
|
continue;
|
|
|
|
}
|
2013-12-14 00:25:45 +00:00
|
|
|
DEBUG(dbgs() << PrintReg(PhysReg, TRI) << "\tstatic = ";
|
|
|
|
MBFI->printBlockFreq(dbgs(), Cost));
|
2011-04-22 22:47:40 +00:00
|
|
|
if (Cost >= BestCost) {
|
|
|
|
DEBUG({
|
|
|
|
if (BestCand == NoCand)
|
|
|
|
dbgs() << " worse than no bundles\n";
|
|
|
|
else
|
|
|
|
dbgs() << " worse than "
|
|
|
|
<< PrintReg(GlobalCand[BestCand].PhysReg, TRI) << '\n';
|
|
|
|
});
|
2011-01-18 21:13:27 +00:00
|
|
|
continue;
|
2011-03-05 03:28:51 +00:00
|
|
|
}
|
2011-07-14 00:17:10 +00:00
|
|
|
growRegion(Cand);
|
2011-01-19 22:11:48 +00:00
|
|
|
|
2011-04-06 19:13:57 +00:00
|
|
|
SpillPlacer->finish();
|
|
|
|
|
2011-01-19 22:11:48 +00:00
|
|
|
// No live bundles, defer to splitSingleBlocks().
|
2011-07-14 00:17:10 +00:00
|
|
|
if (!Cand.LiveBundles.any()) {
|
2011-03-05 03:28:51 +00:00
|
|
|
DEBUG(dbgs() << " no bundles.\n");
|
2011-01-19 22:11:48 +00:00
|
|
|
continue;
|
2011-03-05 03:28:51 +00:00
|
|
|
}
|
2011-01-19 22:11:48 +00:00
|
|
|
|
2011-07-14 00:17:10 +00:00
|
|
|
Cost += calcGlobalSplitCost(Cand);
|
2011-03-05 03:28:51 +00:00
|
|
|
DEBUG({
|
2013-12-14 00:25:45 +00:00
|
|
|
dbgs() << ", total = "; MBFI->printBlockFreq(dbgs(), Cost)
|
|
|
|
<< " with bundles";
|
2011-07-14 00:17:10 +00:00
|
|
|
for (int i = Cand.LiveBundles.find_first(); i>=0;
|
|
|
|
i = Cand.LiveBundles.find_next(i))
|
2011-03-05 03:28:51 +00:00
|
|
|
dbgs() << " EB#" << i;
|
|
|
|
dbgs() << ".\n";
|
|
|
|
});
|
2011-04-22 22:47:40 +00:00
|
|
|
if (Cost < BestCost) {
|
2011-07-14 00:17:10 +00:00
|
|
|
BestCand = NumCands;
|
2013-07-16 18:26:18 +00:00
|
|
|
BestCost = Cost;
|
2011-01-18 21:13:27 +00:00
|
|
|
}
|
2011-07-14 00:17:10 +00:00
|
|
|
++NumCands;
|
2011-01-18 21:13:27 +00:00
|
|
|
}
|
2014-03-24 23:23:42 +00:00
|
|
|
return BestCand;
|
|
|
|
}
|
2011-01-19 22:11:48 +00:00
|
|
|
|
2014-03-24 23:23:42 +00:00
|
|
|
unsigned RAGreedy::doRegionSplit(LiveInterval &VirtReg, unsigned BestCand,
|
|
|
|
bool HasCompact,
|
|
|
|
SmallVectorImpl<unsigned> &NewVRegs) {
|
|
|
|
SmallVector<unsigned, 8> UsedCands;
|
2011-07-26 23:41:46 +00:00
|
|
|
// Prepare split editor.
|
2016-04-13 03:08:27 +00:00
|
|
|
LiveRangeEdit LREdit(&VirtReg, NewVRegs, *MF, *LIS, VRM, this, &DeadRemats);
|
Add an interface for SplitKit complement spill modes.
SplitKit always computes a complement live range to cover the places
where the original live range was live, but no explicit region has been
allocated.
Currently, the complement live range is created to be as small as
possible - it never overlaps any of the regions. This minimizes
register pressure, but if the complement is going to be spilled anyway,
that is not very important. The spiller will eliminate redundant
spills, and hoist others by making the spill slot live range overlap
some of the regions created by splitting. Stack slots are cheap.
This patch adds the interface to enable spill modes in SplitKit. In
spill mode, SplitKit will assume that the complement is going to spill,
so it will allow it to overlap regions in order to avoid back-copies.
By doing some of the spiller's work early, the complement live range
becomes simpler. In some cases, it can become much simpler because no
extra PHI-defs are required. This will speed up both splitting and
spilling.
This is only the interface to enable spill modes, no implementation yet.
llvm-svn: 139500
2011-09-12 16:49:21 +00:00
|
|
|
SE->reset(LREdit, SplitSpillMode);
|
2011-07-26 23:41:46 +00:00
|
|
|
|
|
|
|
// Assign all edge bundles to the preferred candidate, or NoCand.
|
|
|
|
BundleCand.assign(Bundles->getNumBundles(), NoCand);
|
|
|
|
|
|
|
|
// Assign bundles for the best candidate region.
|
|
|
|
if (BestCand != NoCand) {
|
|
|
|
GlobalSplitCandidate &Cand = GlobalCand[BestCand];
|
|
|
|
if (unsigned B = Cand.getBundles(BundleCand, BestCand)) {
|
|
|
|
UsedCands.push_back(BestCand);
|
|
|
|
Cand.IntvIdx = SE->openIntv();
|
|
|
|
DEBUG(dbgs() << "Split for " << PrintReg(Cand.PhysReg, TRI) << " in "
|
|
|
|
<< B << " bundles, intv " << Cand.IntvIdx << ".\n");
|
2011-08-03 23:07:27 +00:00
|
|
|
(void)B;
|
2011-07-26 23:41:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Assign bundles for the compact region.
|
|
|
|
if (HasCompact) {
|
|
|
|
GlobalSplitCandidate &Cand = GlobalCand.front();
|
|
|
|
assert(!Cand.PhysReg && "Compact region has no physreg");
|
|
|
|
if (unsigned B = Cand.getBundles(BundleCand, 0)) {
|
|
|
|
UsedCands.push_back(0);
|
|
|
|
Cand.IntvIdx = SE->openIntv();
|
|
|
|
DEBUG(dbgs() << "Split for compact region in " << B << " bundles, intv "
|
|
|
|
<< Cand.IntvIdx << ".\n");
|
2011-08-03 23:07:27 +00:00
|
|
|
(void)B;
|
2011-07-26 23:41:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
splitAroundRegion(LREdit, UsedCands);
|
2011-01-18 21:13:27 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-01-19 22:11:48 +00:00
|
|
|
|
2011-08-05 23:04:18 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Per-Block Splitting
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
/// tryBlockSplit - Split a global live range around every block with uses. This
|
|
|
|
/// creates a lot of local live ranges, that will be split by tryLocalSplit if
|
|
|
|
/// they don't allocate.
|
|
|
|
unsigned RAGreedy::tryBlockSplit(LiveInterval &VirtReg, AllocationOrder &Order,
|
2013-08-14 23:50:04 +00:00
|
|
|
SmallVectorImpl<unsigned> &NewVRegs) {
|
2011-08-05 23:04:18 +00:00
|
|
|
assert(&SA->getParent() == &VirtReg && "Live range wasn't analyzed");
|
|
|
|
unsigned Reg = VirtReg.reg;
|
|
|
|
bool SingleInstrs = RegClassInfo.isProperSubClass(MRI->getRegClass(Reg));
|
2016-04-13 03:08:27 +00:00
|
|
|
LiveRangeEdit LREdit(&VirtReg, NewVRegs, *MF, *LIS, VRM, this, &DeadRemats);
|
Add an interface for SplitKit complement spill modes.
SplitKit always computes a complement live range to cover the places
where the original live range was live, but no explicit region has been
allocated.
Currently, the complement live range is created to be as small as
possible - it never overlaps any of the regions. This minimizes
register pressure, but if the complement is going to be spilled anyway,
that is not very important. The spiller will eliminate redundant
spills, and hoist others by making the spill slot live range overlap
some of the regions created by splitting. Stack slots are cheap.
This patch adds the interface to enable spill modes in SplitKit. In
spill mode, SplitKit will assume that the complement is going to spill,
so it will allow it to overlap regions in order to avoid back-copies.
By doing some of the spiller's work early, the complement live range
becomes simpler. In some cases, it can become much simpler because no
extra PHI-defs are required. This will speed up both splitting and
spilling.
This is only the interface to enable spill modes, no implementation yet.
llvm-svn: 139500
2011-09-12 16:49:21 +00:00
|
|
|
SE->reset(LREdit, SplitSpillMode);
|
2011-08-05 23:04:18 +00:00
|
|
|
ArrayRef<SplitAnalysis::BlockInfo> UseBlocks = SA->getUseBlocks();
|
|
|
|
for (unsigned i = 0; i != UseBlocks.size(); ++i) {
|
|
|
|
const SplitAnalysis::BlockInfo &BI = UseBlocks[i];
|
|
|
|
if (SA->shouldSplitSingleBlock(BI, SingleInstrs))
|
|
|
|
SE->splitSingleBlock(BI);
|
|
|
|
}
|
|
|
|
// No blocks were split.
|
|
|
|
if (LREdit.empty())
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
// We did split for some blocks.
|
2011-08-05 23:50:31 +00:00
|
|
|
SmallVector<unsigned, 8> IntvMap;
|
|
|
|
SE->finish(&IntvMap);
|
2011-08-05 23:10:40 +00:00
|
|
|
|
|
|
|
// Tell LiveDebugVariables about the new ranges.
|
2013-08-14 23:50:04 +00:00
|
|
|
DebugVars->splitRegister(Reg, LREdit.regs(), *LIS);
|
2011-08-05 23:10:40 +00:00
|
|
|
|
2011-08-05 23:50:31 +00:00
|
|
|
ExtraRegInfo.resize(MRI->getNumVirtRegs());
|
|
|
|
|
|
|
|
// Sort out the new intervals created by splitting. The remainder interval
|
|
|
|
// goes straight to spilling, the new local ranges get to stay RS_New.
|
|
|
|
for (unsigned i = 0, e = LREdit.size(); i != e; ++i) {
|
2013-08-14 23:50:04 +00:00
|
|
|
LiveInterval &LI = LIS->getInterval(LREdit.get(i));
|
2011-08-05 23:50:31 +00:00
|
|
|
if (getStage(LI) == RS_New && IntvMap[i] == 0)
|
|
|
|
setStage(LI, RS_Spill);
|
|
|
|
}
|
|
|
|
|
2011-08-05 23:04:18 +00:00
|
|
|
if (VerifyEnabled)
|
|
|
|
MF->verify(this, "After splitting live range around basic blocks");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-05-23 22:37:27 +00:00
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Per-Instruction Splitting
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2014-01-02 22:47:22 +00:00
|
|
|
/// Get the number of allocatable registers that match the constraints of \p Reg
|
|
|
|
/// on \p MI and that are also in \p SuperRC.
|
|
|
|
static unsigned getNumAllocatableRegsForConstraints(
|
|
|
|
const MachineInstr *MI, unsigned Reg, const TargetRegisterClass *SuperRC,
|
|
|
|
const TargetInstrInfo *TII, const TargetRegisterInfo *TRI,
|
|
|
|
const RegisterClassInfo &RCI) {
|
|
|
|
assert(SuperRC && "Invalid register class");
|
|
|
|
|
|
|
|
const TargetRegisterClass *ConstrainedRC =
|
|
|
|
MI->getRegClassConstraintEffectForVReg(Reg, SuperRC, TII, TRI,
|
|
|
|
/* ExploreBundle */ true);
|
|
|
|
if (!ConstrainedRC)
|
|
|
|
return 0;
|
|
|
|
return RCI.getNumAllocatableRegs(ConstrainedRC);
|
|
|
|
}
|
|
|
|
|
2012-05-23 22:37:27 +00:00
|
|
|
/// tryInstructionSplit - Split a live range around individual instructions.
|
|
|
|
/// This is normally not worthwhile since the spiller is doing essentially the
|
|
|
|
/// same thing. However, when the live range is in a constrained register
|
|
|
|
/// class, it may help to insert copies such that parts of the live range can
|
|
|
|
/// be moved to a larger register class.
|
|
|
|
///
|
|
|
|
/// This is similar to spilling to a larger register class.
|
|
|
|
unsigned
|
|
|
|
RAGreedy::tryInstructionSplit(LiveInterval &VirtReg, AllocationOrder &Order,
|
2013-08-14 23:50:04 +00:00
|
|
|
SmallVectorImpl<unsigned> &NewVRegs) {
|
2014-01-02 22:47:22 +00:00
|
|
|
const TargetRegisterClass *CurRC = MRI->getRegClass(VirtReg.reg);
|
2012-05-23 22:37:27 +00:00
|
|
|
// There is no point to this if there are no larger sub-classes.
|
2014-01-02 22:47:22 +00:00
|
|
|
if (!RegClassInfo.isProperSubClass(CurRC))
|
2012-05-23 22:37:27 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
// Always enable split spill mode, since we're effectively spilling to a
|
|
|
|
// register.
|
2016-04-13 03:08:27 +00:00
|
|
|
LiveRangeEdit LREdit(&VirtReg, NewVRegs, *MF, *LIS, VRM, this, &DeadRemats);
|
2012-05-23 22:37:27 +00:00
|
|
|
SE->reset(LREdit, SplitEditor::SM_Size);
|
|
|
|
|
|
|
|
ArrayRef<SlotIndex> Uses = SA->getUseSlots();
|
|
|
|
if (Uses.size() <= 1)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
DEBUG(dbgs() << "Split around " << Uses.size() << " individual instrs.\n");
|
|
|
|
|
2015-03-10 23:46:01 +00:00
|
|
|
const TargetRegisterClass *SuperRC =
|
|
|
|
TRI->getLargestLegalSuperClass(CurRC, *MF);
|
2014-01-02 22:47:22 +00:00
|
|
|
unsigned SuperRCNumAllocatableRegs = RCI.getNumAllocatableRegs(SuperRC);
|
|
|
|
// Split around every non-copy instruction if this split will relax
|
|
|
|
// the constraints on the virtual register.
|
|
|
|
// Otherwise, splitting just inserts uncoalescable copies that do not help
|
|
|
|
// the allocation.
|
2012-05-23 22:37:27 +00:00
|
|
|
for (unsigned i = 0; i != Uses.size(); ++i) {
|
|
|
|
if (const MachineInstr *MI = Indexes->getInstructionFromIndex(Uses[i]))
|
2014-01-02 22:47:22 +00:00
|
|
|
if (MI->isFullCopy() ||
|
|
|
|
SuperRCNumAllocatableRegs ==
|
|
|
|
getNumAllocatableRegsForConstraints(MI, VirtReg.reg, SuperRC, TII,
|
|
|
|
TRI, RCI)) {
|
2012-05-23 22:37:27 +00:00
|
|
|
DEBUG(dbgs() << " skip:\t" << Uses[i] << '\t' << *MI);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
SE->openIntv();
|
|
|
|
SlotIndex SegStart = SE->enterIntvBefore(Uses[i]);
|
|
|
|
SlotIndex SegStop = SE->leaveIntvAfter(Uses[i]);
|
|
|
|
SE->useIntv(SegStart, SegStop);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (LREdit.empty()) {
|
|
|
|
DEBUG(dbgs() << "All uses were copies.\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
SmallVector<unsigned, 8> IntvMap;
|
|
|
|
SE->finish(&IntvMap);
|
2013-08-14 23:50:04 +00:00
|
|
|
DebugVars->splitRegister(VirtReg.reg, LREdit.regs(), *LIS);
|
2012-05-23 22:37:27 +00:00
|
|
|
ExtraRegInfo.resize(MRI->getNumVirtRegs());
|
|
|
|
|
|
|
|
// Assign all new registers to RS_Spill. This was the last chance.
|
|
|
|
setStage(LREdit.begin(), LREdit.end(), RS_Spill);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-02-17 19:13:53 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Local Splitting
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
|
|
|
|
/// calcGapWeights - Compute the maximum spill weight that needs to be evicted
|
|
|
|
/// in order to use PhysReg between two entries in SA->UseSlots.
|
|
|
|
///
|
|
|
|
/// GapWeight[i] represents the gap between UseSlots[i] and UseSlots[i+1].
|
|
|
|
///
|
|
|
|
void RAGreedy::calcGapWeights(unsigned PhysReg,
|
|
|
|
SmallVectorImpl<float> &GapWeight) {
|
2011-04-06 03:57:00 +00:00
|
|
|
assert(SA->getUseBlocks().size() == 1 && "Not a local interval");
|
|
|
|
const SplitAnalysis::BlockInfo &BI = SA->getUseBlocks().front();
|
2012-01-12 17:53:44 +00:00
|
|
|
ArrayRef<SlotIndex> Uses = SA->getUseSlots();
|
2011-02-17 19:13:53 +00:00
|
|
|
const unsigned NumGaps = Uses.size()-1;
|
|
|
|
|
|
|
|
// Start and end points for the interference check.
|
2011-08-02 22:54:14 +00:00
|
|
|
SlotIndex StartIdx =
|
|
|
|
BI.LiveIn ? BI.FirstInstr.getBaseIndex() : BI.FirstInstr;
|
|
|
|
SlotIndex StopIdx =
|
|
|
|
BI.LiveOut ? BI.LastInstr.getBoundaryIndex() : BI.LastInstr;
|
2011-02-17 19:13:53 +00:00
|
|
|
|
|
|
|
GapWeight.assign(NumGaps, 0.0f);
|
|
|
|
|
|
|
|
// Add interference from each overlapping register.
|
2012-06-20 22:52:26 +00:00
|
|
|
for (MCRegUnitIterator Units(PhysReg, TRI); Units.isValid(); ++Units) {
|
|
|
|
if (!Matrix->query(const_cast<LiveInterval&>(SA->getParent()), *Units)
|
|
|
|
.checkInterference())
|
2011-02-17 19:13:53 +00:00
|
|
|
continue;
|
|
|
|
|
2011-08-02 22:54:14 +00:00
|
|
|
// We know that VirtReg is a continuous interval from FirstInstr to
|
|
|
|
// LastInstr, so we don't need InterferenceQuery.
|
2011-02-17 19:13:53 +00:00
|
|
|
//
|
|
|
|
// Interference that overlaps an instruction is counted in both gaps
|
|
|
|
// surrounding the instruction. The exception is interference before
|
|
|
|
// StartIdx and after StopIdx.
|
|
|
|
//
|
2012-06-20 22:52:26 +00:00
|
|
|
LiveIntervalUnion::SegmentIter IntI =
|
|
|
|
Matrix->getLiveUnions()[*Units] .find(StartIdx);
|
2011-02-17 19:13:53 +00:00
|
|
|
for (unsigned Gap = 0; IntI.valid() && IntI.start() < StopIdx; ++IntI) {
|
|
|
|
// Skip the gaps before IntI.
|
|
|
|
while (Uses[Gap+1].getBoundaryIndex() < IntI.start())
|
|
|
|
if (++Gap == NumGaps)
|
|
|
|
break;
|
|
|
|
if (Gap == NumGaps)
|
|
|
|
break;
|
|
|
|
|
|
|
|
// Update the gaps covered by IntI.
|
|
|
|
const float weight = IntI.value()->weight;
|
|
|
|
for (; Gap != NumGaps; ++Gap) {
|
|
|
|
GapWeight[Gap] = std::max(GapWeight[Gap], weight);
|
|
|
|
if (Uses[Gap+1].getBaseIndex() >= IntI.stop())
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (Gap == NumGaps)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2012-06-20 22:52:26 +00:00
|
|
|
|
|
|
|
// Add fixed interference.
|
|
|
|
for (MCRegUnitIterator Units(PhysReg, TRI); Units.isValid(); ++Units) {
|
2013-10-10 21:29:02 +00:00
|
|
|
const LiveRange &LR = LIS->getRegUnit(*Units);
|
|
|
|
LiveRange::const_iterator I = LR.find(StartIdx);
|
|
|
|
LiveRange::const_iterator E = LR.end();
|
2012-06-20 22:52:26 +00:00
|
|
|
|
|
|
|
// Same loop as above. Mark any overlapped gaps as HUGE_VALF.
|
|
|
|
for (unsigned Gap = 0; I != E && I->start < StopIdx; ++I) {
|
|
|
|
while (Uses[Gap+1].getBoundaryIndex() < I->start)
|
|
|
|
if (++Gap == NumGaps)
|
|
|
|
break;
|
|
|
|
if (Gap == NumGaps)
|
|
|
|
break;
|
|
|
|
|
|
|
|
for (; Gap != NumGaps; ++Gap) {
|
2013-11-13 00:15:44 +00:00
|
|
|
GapWeight[Gap] = llvm::huge_valf;
|
2012-06-20 22:52:26 +00:00
|
|
|
if (Uses[Gap+1].getBaseIndex() >= I->end)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (Gap == NumGaps)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2011-02-17 19:13:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// tryLocalSplit - Try to split VirtReg into smaller intervals inside its only
|
|
|
|
/// basic block.
|
|
|
|
///
|
|
|
|
unsigned RAGreedy::tryLocalSplit(LiveInterval &VirtReg, AllocationOrder &Order,
|
2013-08-14 23:50:04 +00:00
|
|
|
SmallVectorImpl<unsigned> &NewVRegs) {
|
2011-04-06 03:57:00 +00:00
|
|
|
assert(SA->getUseBlocks().size() == 1 && "Not a local interval");
|
|
|
|
const SplitAnalysis::BlockInfo &BI = SA->getUseBlocks().front();
|
2011-02-17 19:13:53 +00:00
|
|
|
|
|
|
|
// Note that it is possible to have an interval that is live-in or live-out
|
|
|
|
// while only covering a single block - A phi-def can use undef values from
|
|
|
|
// predecessors, and the block could be a single-block loop.
|
|
|
|
// We don't bother doing anything clever about such a case, we simply assume
|
2011-08-02 22:54:14 +00:00
|
|
|
// that the interval is continuous from FirstInstr to LastInstr. We should
|
|
|
|
// make sure that we don't do anything illegal to such an interval, though.
|
2011-02-17 19:13:53 +00:00
|
|
|
|
2012-01-12 17:53:44 +00:00
|
|
|
ArrayRef<SlotIndex> Uses = SA->getUseSlots();
|
2011-02-17 19:13:53 +00:00
|
|
|
if (Uses.size() <= 2)
|
|
|
|
return 0;
|
|
|
|
const unsigned NumGaps = Uses.size()-1;
|
|
|
|
|
|
|
|
DEBUG({
|
|
|
|
dbgs() << "tryLocalSplit: ";
|
|
|
|
for (unsigned i = 0, e = Uses.size(); i != e; ++i)
|
2012-01-12 17:53:44 +00:00
|
|
|
dbgs() << ' ' << Uses[i];
|
2011-02-17 19:13:53 +00:00
|
|
|
dbgs() << '\n';
|
|
|
|
});
|
|
|
|
|
2012-02-11 00:42:18 +00:00
|
|
|
// If VirtReg is live across any register mask operands, compute a list of
|
|
|
|
// gaps with register masks.
|
|
|
|
SmallVector<unsigned, 8> RegMaskGaps;
|
2012-06-20 22:52:26 +00:00
|
|
|
if (Matrix->checkRegMaskInterference(VirtReg)) {
|
2012-02-11 00:42:18 +00:00
|
|
|
// Get regmask slots for the whole block.
|
|
|
|
ArrayRef<SlotIndex> RMS = LIS->getRegMaskSlotsInBlock(BI.MBB->getNumber());
|
2012-02-14 23:51:27 +00:00
|
|
|
DEBUG(dbgs() << RMS.size() << " regmasks in block:");
|
2012-02-11 00:42:18 +00:00
|
|
|
// Constrain to VirtReg's live range.
|
2012-02-14 23:51:27 +00:00
|
|
|
unsigned ri = std::lower_bound(RMS.begin(), RMS.end(),
|
|
|
|
Uses.front().getRegSlot()) - RMS.begin();
|
2012-02-11 00:42:18 +00:00
|
|
|
unsigned re = RMS.size();
|
|
|
|
for (unsigned i = 0; i != NumGaps && ri != re; ++i) {
|
2012-02-14 23:51:27 +00:00
|
|
|
// Look for Uses[i] <= RMS <= Uses[i+1].
|
|
|
|
assert(!SlotIndex::isEarlierInstr(RMS[ri], Uses[i]));
|
|
|
|
if (SlotIndex::isEarlierInstr(Uses[i+1], RMS[ri]))
|
2012-02-11 00:42:18 +00:00
|
|
|
continue;
|
2012-02-14 23:51:27 +00:00
|
|
|
// Skip a regmask on the same instruction as the last use. It doesn't
|
|
|
|
// overlap the live range.
|
|
|
|
if (SlotIndex::isSameInstr(Uses[i+1], RMS[ri]) && i+1 == NumGaps)
|
|
|
|
break;
|
|
|
|
DEBUG(dbgs() << ' ' << RMS[ri] << ':' << Uses[i] << '-' << Uses[i+1]);
|
2012-02-11 00:42:18 +00:00
|
|
|
RegMaskGaps.push_back(i);
|
2012-02-14 23:51:27 +00:00
|
|
|
// Advance ri to the next gap. A regmask on one of the uses counts in
|
|
|
|
// both gaps.
|
|
|
|
while (ri != re && SlotIndex::isEarlierInstr(RMS[ri], Uses[i+1]))
|
|
|
|
++ri;
|
2012-02-11 00:42:18 +00:00
|
|
|
}
|
2012-02-14 23:51:27 +00:00
|
|
|
DEBUG(dbgs() << '\n');
|
2012-02-11 00:42:18 +00:00
|
|
|
}
|
|
|
|
|
2011-06-06 23:55:20 +00:00
|
|
|
// Since we allow local split results to be split again, there is a risk of
|
|
|
|
// creating infinite loops. It is tempting to require that the new live
|
|
|
|
// ranges have less instructions than the original. That would guarantee
|
|
|
|
// convergence, but it is too strict. A live range with 3 instructions can be
|
|
|
|
// split 2+3 (including the COPY), and we want to allow that.
|
|
|
|
//
|
|
|
|
// Instead we use these rules:
|
|
|
|
//
|
2011-07-25 15:25:43 +00:00
|
|
|
// 1. Allow any split for ranges with getStage() < RS_Split2. (Except for the
|
2011-06-06 23:55:20 +00:00
|
|
|
// noop split, of course).
|
2011-07-25 15:25:43 +00:00
|
|
|
// 2. Require progress be made for ranges with getStage() == RS_Split2. All
|
2011-06-06 23:55:20 +00:00
|
|
|
// the new ranges must have fewer instructions than before the split.
|
2011-07-25 15:25:43 +00:00
|
|
|
// 3. New ranges with the same number of instructions are marked RS_Split2,
|
2011-06-06 23:55:20 +00:00
|
|
|
// smaller ranges are marked RS_New.
|
|
|
|
//
|
|
|
|
// These rules allow a 3 -> 2+3 split once, which we need. They also prevent
|
|
|
|
// excessive splitting and infinite loops.
|
|
|
|
//
|
2011-07-25 15:25:43 +00:00
|
|
|
bool ProgressRequired = getStage(VirtReg) >= RS_Split2;
|
2011-02-17 19:13:53 +00:00
|
|
|
|
2011-06-06 23:55:20 +00:00
|
|
|
// Best split candidate.
|
2011-02-17 19:13:53 +00:00
|
|
|
unsigned BestBefore = NumGaps;
|
|
|
|
unsigned BestAfter = 0;
|
|
|
|
float BestDiff = 0;
|
|
|
|
|
2013-07-16 18:26:18 +00:00
|
|
|
const float blockFreq =
|
|
|
|
SpillPlacer->getBlockFrequency(BI.MBB->getNumber()).getFrequency() *
|
2013-12-14 02:37:38 +00:00
|
|
|
(1.0f / MBFI->getEntryFreq());
|
2011-02-17 19:13:53 +00:00
|
|
|
SmallVector<float, 8> GapWeight;
|
|
|
|
|
|
|
|
Order.rewind();
|
|
|
|
while (unsigned PhysReg = Order.next()) {
|
|
|
|
// Keep track of the largest spill weight that would need to be evicted in
|
|
|
|
// order to make use of PhysReg between UseSlots[i] and UseSlots[i+1].
|
|
|
|
calcGapWeights(PhysReg, GapWeight);
|
|
|
|
|
2012-02-11 00:42:18 +00:00
|
|
|
// Remove any gaps with regmask clobbers.
|
2012-06-20 22:52:26 +00:00
|
|
|
if (Matrix->checkRegMaskInterference(VirtReg, PhysReg))
|
2012-02-11 00:42:18 +00:00
|
|
|
for (unsigned i = 0, e = RegMaskGaps.size(); i != e; ++i)
|
2013-11-13 00:15:44 +00:00
|
|
|
GapWeight[RegMaskGaps[i]] = llvm::huge_valf;
|
2012-02-11 00:42:18 +00:00
|
|
|
|
2011-02-17 19:13:53 +00:00
|
|
|
// Try to find the best sequence of gaps to close.
|
|
|
|
// The new spill weight must be larger than any gap interference.
|
|
|
|
|
|
|
|
// We will split before Uses[SplitBefore] and after Uses[SplitAfter].
|
2011-06-06 23:55:20 +00:00
|
|
|
unsigned SplitBefore = 0, SplitAfter = 1;
|
2011-02-17 19:13:53 +00:00
|
|
|
|
|
|
|
// MaxGap should always be max(GapWeight[SplitBefore..SplitAfter-1]).
|
|
|
|
// It is the spill weight that needs to be evicted.
|
|
|
|
float MaxGap = GapWeight[0];
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
// Live before/after split?
|
|
|
|
const bool LiveBefore = SplitBefore != 0 || BI.LiveIn;
|
|
|
|
const bool LiveAfter = SplitAfter != NumGaps || BI.LiveOut;
|
|
|
|
|
|
|
|
DEBUG(dbgs() << PrintReg(PhysReg, TRI) << ' '
|
|
|
|
<< Uses[SplitBefore] << '-' << Uses[SplitAfter]
|
|
|
|
<< " i=" << MaxGap);
|
|
|
|
|
|
|
|
// Stop before the interval gets so big we wouldn't be making progress.
|
|
|
|
if (!LiveBefore && !LiveAfter) {
|
|
|
|
DEBUG(dbgs() << " all\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// Should the interval be extended or shrunk?
|
|
|
|
bool Shrink = true;
|
|
|
|
|
2011-06-06 23:55:20 +00:00
|
|
|
// How many gaps would the new range have?
|
|
|
|
unsigned NewGaps = LiveBefore + SplitAfter - SplitBefore + LiveAfter;
|
|
|
|
|
|
|
|
// Legally, without causing looping?
|
|
|
|
bool Legal = !ProgressRequired || NewGaps < NumGaps;
|
|
|
|
|
2013-11-13 00:15:44 +00:00
|
|
|
if (Legal && MaxGap < llvm::huge_valf) {
|
2011-06-06 23:55:20 +00:00
|
|
|
// Estimate the new spill weight. Each instruction reads or writes the
|
|
|
|
// register. Conservatively assume there are no read-modify-write
|
|
|
|
// instructions.
|
2011-02-17 19:13:53 +00:00
|
|
|
//
|
2011-06-06 23:55:20 +00:00
|
|
|
// Try to guess the size of the new interval.
|
[PBQP] Tweak spill costs and coalescing benefits
This patch improves how the different costs (register, interference, spill
and coalescing) relates together. The assumption is now that:
- coalescing (or any other "side effect" of reg alloc) is negative, and
instead of being derived from a spill cost, they use the block
frequency info.
- spill costs are in the [MinSpillCost:+inf( range
- register or interference costs are in [0.0:MinSpillCost( or +inf
The current MinSpillCost is set to 10.0, which is a random value high
enough that the current constraint builders do not need to worry about
when settings costs. It would however be worth adding a normalization
step for register and interference costs as the last step in the
constraint builder chain to ensure they are not greater than SpillMinCost
(unless this has some sense for some architectures). This would work well
with the current builder pipeline, where all costs are tweaked relatively
to each others, but could grow above MinSpillCost if the pipeline is
deep enough.
The current heuristic is tuned to depend rather on the number of uses of
a live interval rather than a density of uses, as used by the greedy
allocator. This heuristic provides a few percent improvement on a number
of benchmarks (eembc, spec, ...) and will definitely need to change once
spill placement is implemented: the current spill placement is really
ineficient, so making the cost proportionnal to the number of use is a
clear win.
llvm-svn: 221292
2014-11-04 20:51:24 +00:00
|
|
|
const float EstWeight = normalizeSpillWeight(
|
|
|
|
blockFreq * (NewGaps + 1),
|
|
|
|
Uses[SplitBefore].distance(Uses[SplitAfter]) +
|
|
|
|
(LiveBefore + LiveAfter) * SlotIndex::InstrDist,
|
|
|
|
1);
|
2011-02-17 19:13:53 +00:00
|
|
|
// Would this split be possible to allocate?
|
|
|
|
// Never allocate all gaps, we wouldn't be making progress.
|
2011-04-30 05:07:46 +00:00
|
|
|
DEBUG(dbgs() << " w=" << EstWeight);
|
|
|
|
if (EstWeight * Hysteresis >= MaxGap) {
|
2011-02-17 19:13:53 +00:00
|
|
|
Shrink = false;
|
2011-04-30 05:07:46 +00:00
|
|
|
float Diff = EstWeight - MaxGap;
|
2011-02-17 19:13:53 +00:00
|
|
|
if (Diff > BestDiff) {
|
|
|
|
DEBUG(dbgs() << " (best)");
|
2011-04-30 05:07:46 +00:00
|
|
|
BestDiff = Hysteresis * Diff;
|
2011-02-17 19:13:53 +00:00
|
|
|
BestBefore = SplitBefore;
|
|
|
|
BestAfter = SplitAfter;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Try to shrink.
|
|
|
|
if (Shrink) {
|
2011-06-06 23:55:20 +00:00
|
|
|
if (++SplitBefore < SplitAfter) {
|
2011-02-17 19:13:53 +00:00
|
|
|
DEBUG(dbgs() << " shrink\n");
|
|
|
|
// Recompute the max when necessary.
|
|
|
|
if (GapWeight[SplitBefore - 1] >= MaxGap) {
|
|
|
|
MaxGap = GapWeight[SplitBefore];
|
|
|
|
for (unsigned i = SplitBefore + 1; i != SplitAfter; ++i)
|
|
|
|
MaxGap = std::max(MaxGap, GapWeight[i]);
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
MaxGap = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Try to extend the interval.
|
|
|
|
if (SplitAfter >= NumGaps) {
|
|
|
|
DEBUG(dbgs() << " end\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
DEBUG(dbgs() << " extend\n");
|
2011-06-06 23:55:20 +00:00
|
|
|
MaxGap = std::max(MaxGap, GapWeight[SplitAfter++]);
|
2011-02-17 19:13:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Didn't find any candidates?
|
|
|
|
if (BestBefore == NumGaps)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
DEBUG(dbgs() << "Best local split range: " << Uses[BestBefore]
|
|
|
|
<< '-' << Uses[BestAfter] << ", " << BestDiff
|
|
|
|
<< ", " << (BestAfter - BestBefore + 1) << " instrs\n");
|
|
|
|
|
2016-04-13 03:08:27 +00:00
|
|
|
LiveRangeEdit LREdit(&VirtReg, NewVRegs, *MF, *LIS, VRM, this, &DeadRemats);
|
2011-03-03 01:29:13 +00:00
|
|
|
SE->reset(LREdit);
|
|
|
|
|
|
|
|
SE->openIntv();
|
|
|
|
SlotIndex SegStart = SE->enterIntvBefore(Uses[BestBefore]);
|
|
|
|
SlotIndex SegStop = SE->leaveIntvAfter(Uses[BestAfter]);
|
|
|
|
SE->useIntv(SegStart, SegStop);
|
2011-06-06 23:55:20 +00:00
|
|
|
SmallVector<unsigned, 8> IntvMap;
|
|
|
|
SE->finish(&IntvMap);
|
2013-08-14 23:50:04 +00:00
|
|
|
DebugVars->splitRegister(VirtReg.reg, LREdit.regs(), *LIS);
|
2011-06-06 23:55:20 +00:00
|
|
|
|
|
|
|
// If the new range has the same number of instructions as before, mark it as
|
2011-07-25 15:25:43 +00:00
|
|
|
// RS_Split2 so the next split will be forced to make progress. Otherwise,
|
2011-06-06 23:55:20 +00:00
|
|
|
// leave the new intervals as RS_New so they can compete.
|
|
|
|
bool LiveBefore = BestBefore != 0 || BI.LiveIn;
|
|
|
|
bool LiveAfter = BestAfter != NumGaps || BI.LiveOut;
|
|
|
|
unsigned NewGaps = LiveBefore + BestAfter - BestBefore + LiveAfter;
|
|
|
|
if (NewGaps >= NumGaps) {
|
|
|
|
DEBUG(dbgs() << "Tagging non-progress ranges: ");
|
|
|
|
assert(!ProgressRequired && "Didn't make progress when it was required.");
|
|
|
|
for (unsigned i = 0, e = IntvMap.size(); i != e; ++i)
|
|
|
|
if (IntvMap[i] == 1) {
|
2013-08-14 23:50:04 +00:00
|
|
|
setStage(LIS->getInterval(LREdit.get(i)), RS_Split2);
|
|
|
|
DEBUG(dbgs() << PrintReg(LREdit.get(i)));
|
2011-06-06 23:55:20 +00:00
|
|
|
}
|
|
|
|
DEBUG(dbgs() << '\n');
|
|
|
|
}
|
2011-02-17 22:53:48 +00:00
|
|
|
++NumLocalSplits;
|
2011-02-17 19:13:53 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-01-19 22:11:48 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Live Range Splitting
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
/// trySplit - Try to split VirtReg or one of its interferences, making it
|
|
|
|
/// assignable.
|
|
|
|
/// @return Physreg when VirtReg may be assigned and/or new NewVRegs.
|
|
|
|
unsigned RAGreedy::trySplit(LiveInterval &VirtReg, AllocationOrder &Order,
|
2013-08-14 23:50:04 +00:00
|
|
|
SmallVectorImpl<unsigned>&NewVRegs) {
|
2011-08-05 23:50:33 +00:00
|
|
|
// Ranges must be Split2 or less.
|
|
|
|
if (getStage(VirtReg) >= RS_Spill)
|
|
|
|
return 0;
|
|
|
|
|
2011-02-17 19:13:53 +00:00
|
|
|
// Local intervals are handled separately.
|
2011-02-19 00:38:40 +00:00
|
|
|
if (LIS->intervalIsInOneMBB(VirtReg)) {
|
|
|
|
NamedRegionTimer T("Local Splitting", TimerGroupName, TimePassesIsEnabled);
|
2011-03-01 21:10:07 +00:00
|
|
|
SA->analyze(&VirtReg);
|
2012-05-23 22:37:27 +00:00
|
|
|
unsigned PhysReg = tryLocalSplit(VirtReg, Order, NewVRegs);
|
|
|
|
if (PhysReg || !NewVRegs.empty())
|
|
|
|
return PhysReg;
|
|
|
|
return tryInstructionSplit(VirtReg, Order, NewVRegs);
|
2011-02-19 00:38:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NamedRegionTimer T("Global Splitting", TimerGroupName, TimePassesIsEnabled);
|
2011-01-19 22:11:48 +00:00
|
|
|
|
2011-03-01 21:10:07 +00:00
|
|
|
SA->analyze(&VirtReg);
|
|
|
|
|
2011-05-03 20:42:13 +00:00
|
|
|
// FIXME: SplitAnalysis may repair broken live ranges coming from the
|
|
|
|
// coalescer. That may cause the range to become allocatable which means that
|
|
|
|
// tryRegionSplit won't be making progress. This check should be replaced with
|
|
|
|
// an assertion when the coalescer is fixed.
|
|
|
|
if (SA->didRepairRange()) {
|
|
|
|
// VirtReg has changed, so all cached queries are invalid.
|
2012-06-20 22:52:26 +00:00
|
|
|
Matrix->invalidateVirtRegs();
|
2011-05-03 20:42:13 +00:00
|
|
|
if (unsigned PhysReg = tryAssign(VirtReg, Order, NewVRegs))
|
|
|
|
return PhysReg;
|
|
|
|
}
|
|
|
|
|
2011-07-25 15:25:43 +00:00
|
|
|
// First try to split around a region spanning multiple blocks. RS_Split2
|
|
|
|
// ranges already made dubious progress with region splitting, so they go
|
|
|
|
// straight to single block splitting.
|
|
|
|
if (getStage(VirtReg) < RS_Split2) {
|
|
|
|
unsigned PhysReg = tryRegionSplit(VirtReg, Order, NewVRegs);
|
|
|
|
if (PhysReg || !NewVRegs.empty())
|
|
|
|
return PhysReg;
|
|
|
|
}
|
2011-01-19 22:11:48 +00:00
|
|
|
|
2011-08-05 23:04:18 +00:00
|
|
|
// Then isolate blocks.
|
|
|
|
return tryBlockSplit(VirtReg, Order, NewVRegs);
|
2011-01-19 22:11:48 +00:00
|
|
|
}
|
|
|
|
|
2014-02-05 22:13:59 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Last Chance Recoloring
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
/// mayRecolorAllInterferences - Check if the virtual registers that
|
|
|
|
/// interfere with \p VirtReg on \p PhysReg (or one of its aliases) may be
|
|
|
|
/// recolored to free \p PhysReg.
|
|
|
|
/// When true is returned, \p RecoloringCandidates has been augmented with all
|
|
|
|
/// the live intervals that need to be recolored in order to free \p PhysReg
|
|
|
|
/// for \p VirtReg.
|
|
|
|
/// \p FixedRegisters contains all the virtual registers that cannot be
|
|
|
|
/// recolored.
|
|
|
|
bool
|
|
|
|
RAGreedy::mayRecolorAllInterferences(unsigned PhysReg, LiveInterval &VirtReg,
|
|
|
|
SmallLISet &RecoloringCandidates,
|
|
|
|
const SmallVirtRegSet &FixedRegisters) {
|
|
|
|
const TargetRegisterClass *CurRC = MRI->getRegClass(VirtReg.reg);
|
|
|
|
|
|
|
|
for (MCRegUnitIterator Units(PhysReg, TRI); Units.isValid(); ++Units) {
|
|
|
|
LiveIntervalUnion::Query &Q = Matrix->query(VirtReg, *Units);
|
|
|
|
// If there is LastChanceRecoloringMaxInterference or more interferences,
|
|
|
|
// chances are one would not be recolorable.
|
|
|
|
if (Q.collectInterferingVRegs(LastChanceRecoloringMaxInterference) >=
|
2014-04-11 21:39:44 +00:00
|
|
|
LastChanceRecoloringMaxInterference && !ExhaustiveSearch) {
|
2014-02-05 22:13:59 +00:00
|
|
|
DEBUG(dbgs() << "Early abort: too many interferences.\n");
|
2014-04-04 02:05:21 +00:00
|
|
|
CutOffInfo |= CO_Interf;
|
2014-02-05 22:13:59 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
for (unsigned i = Q.interferingVRegs().size(); i; --i) {
|
|
|
|
LiveInterval *Intf = Q.interferingVRegs()[i - 1];
|
|
|
|
// If Intf is done and sit on the same register class as VirtReg,
|
|
|
|
// it would not be recolorable as it is in the same state as VirtReg.
|
|
|
|
if ((getStage(*Intf) == RS_Done &&
|
|
|
|
MRI->getRegClass(Intf->reg) == CurRC) ||
|
|
|
|
FixedRegisters.count(Intf->reg)) {
|
|
|
|
DEBUG(dbgs() << "Early abort: the inteference is not recolorable.\n");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
RecoloringCandidates.insert(Intf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// tryLastChanceRecoloring - Try to assign a color to \p VirtReg by recoloring
|
|
|
|
/// its interferences.
|
|
|
|
/// Last chance recoloring chooses a color for \p VirtReg and recolors every
|
|
|
|
/// virtual register that was using it. The recoloring process may recursively
|
|
|
|
/// use the last chance recoloring. Therefore, when a virtual register has been
|
|
|
|
/// assigned a color by this mechanism, it is marked as Fixed, i.e., it cannot
|
|
|
|
/// be last-chance-recolored again during this recoloring "session".
|
|
|
|
/// E.g.,
|
|
|
|
/// Let
|
|
|
|
/// vA can use {R1, R2 }
|
|
|
|
/// vB can use { R2, R3}
|
|
|
|
/// vC can use {R1 }
|
|
|
|
/// Where vA, vB, and vC cannot be split anymore (they are reloads for
|
|
|
|
/// instance) and they all interfere.
|
|
|
|
///
|
|
|
|
/// vA is assigned R1
|
|
|
|
/// vB is assigned R2
|
|
|
|
/// vC tries to evict vA but vA is already done.
|
|
|
|
/// Regular register allocation fails.
|
|
|
|
///
|
|
|
|
/// Last chance recoloring kicks in:
|
|
|
|
/// vC does as if vA was evicted => vC uses R1.
|
|
|
|
/// vC is marked as fixed.
|
|
|
|
/// vA needs to find a color.
|
|
|
|
/// None are available.
|
|
|
|
/// vA cannot evict vC: vC is a fixed virtual register now.
|
|
|
|
/// vA does as if vB was evicted => vA uses R2.
|
|
|
|
/// vB needs to find a color.
|
|
|
|
/// R3 is available.
|
|
|
|
/// Recoloring => vC = R1, vA = R2, vB = R3
|
|
|
|
///
|
2014-02-25 04:21:15 +00:00
|
|
|
/// \p Order defines the preferred allocation order for \p VirtReg.
|
2014-02-05 22:13:59 +00:00
|
|
|
/// \p NewRegs will contain any new virtual register that have been created
|
|
|
|
/// (split, spill) during the process and that must be assigned.
|
|
|
|
/// \p FixedRegisters contains all the virtual registers that cannot be
|
|
|
|
/// recolored.
|
|
|
|
/// \p Depth gives the current depth of the last chance recoloring.
|
|
|
|
/// \return a physical register that can be used for VirtReg or ~0u if none
|
|
|
|
/// exists.
|
|
|
|
unsigned RAGreedy::tryLastChanceRecoloring(LiveInterval &VirtReg,
|
|
|
|
AllocationOrder &Order,
|
|
|
|
SmallVectorImpl<unsigned> &NewVRegs,
|
|
|
|
SmallVirtRegSet &FixedRegisters,
|
|
|
|
unsigned Depth) {
|
|
|
|
DEBUG(dbgs() << "Try last chance recoloring for " << VirtReg << '\n');
|
|
|
|
// Ranges must be Done.
|
2014-02-13 05:17:37 +00:00
|
|
|
assert((getStage(VirtReg) >= RS_Done || !VirtReg.isSpillable()) &&
|
2014-02-05 22:13:59 +00:00
|
|
|
"Last chance recoloring should really be last chance");
|
|
|
|
// Set the max depth to LastChanceRecoloringMaxDepth.
|
|
|
|
// We may want to reconsider that if we end up with a too large search space
|
|
|
|
// for target with hundreds of registers.
|
|
|
|
// Indeed, in that case we may want to cut the search space earlier.
|
2014-04-11 21:39:44 +00:00
|
|
|
if (Depth >= LastChanceRecoloringMaxDepth && !ExhaustiveSearch) {
|
2014-02-05 22:13:59 +00:00
|
|
|
DEBUG(dbgs() << "Abort because max depth has been reached.\n");
|
2014-04-04 02:05:21 +00:00
|
|
|
CutOffInfo |= CO_Depth;
|
2014-02-05 22:13:59 +00:00
|
|
|
return ~0u;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set of Live intervals that will need to be recolored.
|
|
|
|
SmallLISet RecoloringCandidates;
|
|
|
|
// Record the original mapping virtual register to physical register in case
|
|
|
|
// the recoloring fails.
|
|
|
|
DenseMap<unsigned, unsigned> VirtRegToPhysReg;
|
|
|
|
// Mark VirtReg as fixed, i.e., it will not be recolored pass this point in
|
|
|
|
// this recoloring "session".
|
|
|
|
FixedRegisters.insert(VirtReg.reg);
|
|
|
|
|
|
|
|
Order.rewind();
|
|
|
|
while (unsigned PhysReg = Order.next()) {
|
|
|
|
DEBUG(dbgs() << "Try to assign: " << VirtReg << " to "
|
|
|
|
<< PrintReg(PhysReg, TRI) << '\n');
|
|
|
|
RecoloringCandidates.clear();
|
|
|
|
VirtRegToPhysReg.clear();
|
|
|
|
|
|
|
|
// It is only possible to recolor virtual register interference.
|
|
|
|
if (Matrix->checkInterference(VirtReg, PhysReg) >
|
|
|
|
LiveRegMatrix::IK_VirtReg) {
|
|
|
|
DEBUG(dbgs() << "Some inteferences are not with virtual registers.\n");
|
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Early give up on this PhysReg if it is obvious we cannot recolor all
|
|
|
|
// the interferences.
|
|
|
|
if (!mayRecolorAllInterferences(PhysReg, VirtReg, RecoloringCandidates,
|
|
|
|
FixedRegisters)) {
|
|
|
|
DEBUG(dbgs() << "Some inteferences cannot be recolored.\n");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// RecoloringCandidates contains all the virtual registers that interfer
|
|
|
|
// with VirtReg on PhysReg (or one of its aliases).
|
|
|
|
// Enqueue them for recoloring and perform the actual recoloring.
|
|
|
|
PQueue RecoloringQueue;
|
|
|
|
for (SmallLISet::iterator It = RecoloringCandidates.begin(),
|
|
|
|
EndIt = RecoloringCandidates.end();
|
|
|
|
It != EndIt; ++It) {
|
|
|
|
unsigned ItVirtReg = (*It)->reg;
|
|
|
|
enqueue(RecoloringQueue, *It);
|
|
|
|
assert(VRM->hasPhys(ItVirtReg) &&
|
|
|
|
"Interferences are supposed to be with allocated vairables");
|
|
|
|
|
|
|
|
// Record the current allocation.
|
|
|
|
VirtRegToPhysReg[ItVirtReg] = VRM->getPhys(ItVirtReg);
|
|
|
|
// unset the related struct.
|
|
|
|
Matrix->unassign(**It);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Do as if VirtReg was assigned to PhysReg so that the underlying
|
|
|
|
// recoloring has the right information about the interferes and
|
|
|
|
// available colors.
|
|
|
|
Matrix->assign(VirtReg, PhysReg);
|
|
|
|
|
|
|
|
// Save the current recoloring state.
|
|
|
|
// If we cannot recolor all the interferences, we will have to start again
|
|
|
|
// at this point for the next physical register.
|
|
|
|
SmallVirtRegSet SaveFixedRegisters(FixedRegisters);
|
|
|
|
if (tryRecoloringCandidates(RecoloringQueue, NewVRegs, FixedRegisters,
|
|
|
|
Depth)) {
|
|
|
|
// Do not mess up with the global assignment process.
|
|
|
|
// I.e., VirtReg must be unassigned.
|
|
|
|
Matrix->unassign(VirtReg);
|
|
|
|
return PhysReg;
|
|
|
|
}
|
|
|
|
|
|
|
|
DEBUG(dbgs() << "Fail to assign: " << VirtReg << " to "
|
|
|
|
<< PrintReg(PhysReg, TRI) << '\n');
|
|
|
|
|
|
|
|
// The recoloring attempt failed, undo the changes.
|
|
|
|
FixedRegisters = SaveFixedRegisters;
|
|
|
|
Matrix->unassign(VirtReg);
|
|
|
|
|
|
|
|
for (SmallLISet::iterator It = RecoloringCandidates.begin(),
|
|
|
|
EndIt = RecoloringCandidates.end();
|
|
|
|
It != EndIt; ++It) {
|
|
|
|
unsigned ItVirtReg = (*It)->reg;
|
|
|
|
if (VRM->hasPhys(ItVirtReg))
|
|
|
|
Matrix->unassign(**It);
|
2015-07-14 17:38:17 +00:00
|
|
|
unsigned ItPhysReg = VirtRegToPhysReg[ItVirtReg];
|
|
|
|
Matrix->assign(**It, ItPhysReg);
|
2014-02-05 22:13:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Last chance recoloring did not worked either, give up.
|
|
|
|
return ~0u;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// tryRecoloringCandidates - Try to assign a new color to every register
|
|
|
|
/// in \RecoloringQueue.
|
|
|
|
/// \p NewRegs will contain any new virtual register created during the
|
|
|
|
/// recoloring process.
|
|
|
|
/// \p FixedRegisters[in/out] contains all the registers that have been
|
|
|
|
/// recolored.
|
|
|
|
/// \return true if all virtual registers in RecoloringQueue were successfully
|
|
|
|
/// recolored, false otherwise.
|
|
|
|
bool RAGreedy::tryRecoloringCandidates(PQueue &RecoloringQueue,
|
|
|
|
SmallVectorImpl<unsigned> &NewVRegs,
|
|
|
|
SmallVirtRegSet &FixedRegisters,
|
|
|
|
unsigned Depth) {
|
|
|
|
while (!RecoloringQueue.empty()) {
|
|
|
|
LiveInterval *LI = dequeue(RecoloringQueue);
|
|
|
|
DEBUG(dbgs() << "Try to recolor: " << *LI << '\n');
|
|
|
|
unsigned PhysReg;
|
|
|
|
PhysReg = selectOrSplitImpl(*LI, NewVRegs, FixedRegisters, Depth + 1);
|
|
|
|
if (PhysReg == ~0u || !PhysReg)
|
|
|
|
return false;
|
|
|
|
DEBUG(dbgs() << "Recoloring of " << *LI
|
|
|
|
<< " succeeded with: " << PrintReg(PhysReg, TRI) << '\n');
|
|
|
|
Matrix->assign(*LI, PhysReg);
|
|
|
|
FixedRegisters.insert(LI->reg);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
2011-01-19 22:11:48 +00:00
|
|
|
|
2010-12-22 22:01:30 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Main Entry Point
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
unsigned RAGreedy::selectOrSplit(LiveInterval &VirtReg,
|
2013-08-14 23:50:04 +00:00
|
|
|
SmallVectorImpl<unsigned> &NewVRegs) {
|
2014-04-04 02:05:21 +00:00
|
|
|
CutOffInfo = CO_None;
|
|
|
|
LLVMContext &Ctx = MF->getFunction()->getContext();
|
2014-02-05 22:13:59 +00:00
|
|
|
SmallVirtRegSet FixedRegisters;
|
2014-04-04 02:05:21 +00:00
|
|
|
unsigned Reg = selectOrSplitImpl(VirtReg, NewVRegs, FixedRegisters);
|
|
|
|
if (Reg == ~0U && (CutOffInfo != CO_None)) {
|
|
|
|
uint8_t CutOffEncountered = CutOffInfo & (CO_Depth | CO_Interf);
|
|
|
|
if (CutOffEncountered == CO_Depth)
|
2014-04-11 21:39:44 +00:00
|
|
|
Ctx.emitError("register allocation failed: maximum depth for recoloring "
|
|
|
|
"reached. Use -fexhaustive-register-search to skip "
|
|
|
|
"cutoffs");
|
2014-04-04 02:05:21 +00:00
|
|
|
else if (CutOffEncountered == CO_Interf)
|
|
|
|
Ctx.emitError("register allocation failed: maximum interference for "
|
2014-04-11 21:39:44 +00:00
|
|
|
"recoloring reached. Use -fexhaustive-register-search "
|
|
|
|
"to skip cutoffs");
|
2014-04-04 02:05:21 +00:00
|
|
|
else if (CutOffEncountered == (CO_Depth | CO_Interf))
|
|
|
|
Ctx.emitError("register allocation failed: maximum interference and "
|
2014-04-11 21:39:44 +00:00
|
|
|
"depth for recoloring reached. Use "
|
|
|
|
"-fexhaustive-register-search to skip cutoffs");
|
2014-04-04 02:05:21 +00:00
|
|
|
}
|
|
|
|
return Reg;
|
2014-02-05 22:13:59 +00:00
|
|
|
}
|
|
|
|
|
2014-03-27 21:21:57 +00:00
|
|
|
/// Using a CSR for the first time has a cost because it causes push|pop
|
|
|
|
/// to be added to prologue|epilogue. Splitting a cold section of the live
|
|
|
|
/// range can have lower cost than using the CSR for the first time;
|
|
|
|
/// Spilling a live range in the cold path can have lower cost than using
|
|
|
|
/// the CSR for the first time. Returns the physical register if we decide
|
|
|
|
/// to use the CSR; otherwise return 0.
|
|
|
|
unsigned RAGreedy::tryAssignCSRFirstTime(LiveInterval &VirtReg,
|
|
|
|
AllocationOrder &Order,
|
|
|
|
unsigned PhysReg,
|
|
|
|
unsigned &CostPerUseLimit,
|
|
|
|
SmallVectorImpl<unsigned> &NewVRegs) {
|
|
|
|
if (getStage(VirtReg) == RS_Spill && VirtReg.isSpillable()) {
|
|
|
|
// We choose spill over using the CSR for the first time if the spill cost
|
|
|
|
// is lower than CSRCost.
|
|
|
|
SA->analyze(&VirtReg);
|
|
|
|
if (calcSpillCost() >= CSRCost)
|
|
|
|
return PhysReg;
|
|
|
|
|
|
|
|
// We are going to spill, set CostPerUseLimit to 1 to make sure that
|
|
|
|
// we will not use a callee-saved register in tryEvict.
|
|
|
|
CostPerUseLimit = 1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (getStage(VirtReg) < RS_Split) {
|
|
|
|
// We choose pre-splitting over using the CSR for the first time if
|
|
|
|
// the cost of splitting is lower than CSRCost.
|
|
|
|
SA->analyze(&VirtReg);
|
|
|
|
unsigned NumCands = 0;
|
2014-04-08 19:18:56 +00:00
|
|
|
BlockFrequency BestCost = CSRCost; // Don't modify CSRCost.
|
|
|
|
unsigned BestCand = calculateRegionSplitCost(VirtReg, Order, BestCost,
|
|
|
|
NumCands, true /*IgnoreCSR*/);
|
2014-03-27 21:21:57 +00:00
|
|
|
if (BestCand == NoCand)
|
|
|
|
// Use the CSR if we can't find a region split below CSRCost.
|
|
|
|
return PhysReg;
|
|
|
|
|
|
|
|
// Perform the actual pre-splitting.
|
|
|
|
doRegionSplit(VirtReg, BestCand, false/*HasCompact*/, NewVRegs);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return PhysReg;
|
|
|
|
}
|
|
|
|
|
[RegAllocGreedy] Introduce a late pass to repair broken hints.
A broken hint is a copy where both ends are assigned different colors. When a
variable gets evicted in the neighborhood of such copies, it is likely we can
reconcile some of them.
** Context **
Copies are inserted during the register allocation via splitting. These split
points are required to relax the constraints on the allocation problem. When
such a point is inserted, both ends of the copy would not share the same color
with respect to the current allocation problem. When variables get evicted,
the allocation problem becomes different and some split point may not be
required anymore. However, the related variables may already have been colored.
This usually shows up in the assembly with pattern like this:
def A
...
save A to B
def A
use A
restore A from B
...
use B
Whereas we could simply have done:
def B
...
def A
use A
...
use B
** Proposed Solution **
A variable having a broken hint is marked for late recoloring if and only if
selecting a register for it evict another variable. Indeed, if no eviction
happens this is pointless to look for recoloring opportunities as it means the
situation was the same as the initial allocation problem where we had to break
the hint.
Finally, when everything has been allocated, we look for recoloring
opportunities for all the identified candidates.
The recoloring is performed very late to rely on accurate copy cost (all
involved variables are allocated).
The recoloring is simple unlike the last change recoloring. It propagates the
color of the broken hint to all its copy-related variables. If the color is
available for them, the recoloring uses it, otherwise it gives up on that hint
even if a more complex coloring would have worked.
The recoloring happens only if it is profitable. The profitability is evaluated
using the expected frequency of the copies of the currently recolored variable
with a) its current color and b) with the target color. If a) is greater or
equal than b), then it is profitable and the recoloring happen.
** Example **
Consider the following example:
BB1:
a =
b =
BB2:
...
= b
= a
Let us assume b gets split:
BB1:
a =
b =
BB2:
c = b
...
d = c
= d
= a
Because of how the allocation work, b, c, and d may be assigned different
colors. Now, if a gets evicted to make room for c, assuming b and d were
assigned to something different than a.
We end up with:
BB1:
a =
st a, SpillSlot
b =
BB2:
c = b
...
d = c
= d
e = ld SpillSlot
= e
This is likely that we can assign the same register for b, c, and d,
getting rid of 2 copies.
** Performances **
Both ARM64 and x86_64 show performance improvements of up to 3% for the
llvm-testsuite + externals with Os and O3. There are a few regressions too that
comes from the (in)accuracy of the block frequency estimate.
<rdar://problem/18312047>
llvm-svn: 225422
2015-01-08 01:16:39 +00:00
|
|
|
void RAGreedy::aboutToRemoveInterval(LiveInterval &LI) {
|
|
|
|
// Do not keep invalid information around.
|
|
|
|
SetOfBrokenHints.remove(&LI);
|
|
|
|
}
|
|
|
|
|
2014-04-08 19:18:56 +00:00
|
|
|
void RAGreedy::initializeCSRCost() {
|
|
|
|
// We use the larger one out of the command-line option and the value report
|
|
|
|
// by TRI.
|
|
|
|
CSRCost = BlockFrequency(
|
|
|
|
std::max((unsigned)CSRFirstTimeCost, TRI->getCSRFirstUseCost()));
|
|
|
|
if (!CSRCost.getFrequency())
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Raw cost is relative to Entry == 2^14; scale it appropriately.
|
|
|
|
uint64_t ActualEntry = MBFI->getEntryFreq();
|
|
|
|
if (!ActualEntry) {
|
|
|
|
CSRCost = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
uint64_t FixedEntry = 1 << 14;
|
|
|
|
if (ActualEntry < FixedEntry)
|
|
|
|
CSRCost *= BranchProbability(ActualEntry, FixedEntry);
|
|
|
|
else if (ActualEntry <= UINT32_MAX)
|
|
|
|
// Invert the fraction and divide.
|
|
|
|
CSRCost /= BranchProbability(FixedEntry, ActualEntry);
|
|
|
|
else
|
|
|
|
// Can't use BranchProbability in general, since it takes 32-bit numbers.
|
|
|
|
CSRCost = CSRCost.getFrequency() * (ActualEntry / FixedEntry);
|
|
|
|
}
|
|
|
|
|
[RegAllocGreedy] Introduce a late pass to repair broken hints.
A broken hint is a copy where both ends are assigned different colors. When a
variable gets evicted in the neighborhood of such copies, it is likely we can
reconcile some of them.
** Context **
Copies are inserted during the register allocation via splitting. These split
points are required to relax the constraints on the allocation problem. When
such a point is inserted, both ends of the copy would not share the same color
with respect to the current allocation problem. When variables get evicted,
the allocation problem becomes different and some split point may not be
required anymore. However, the related variables may already have been colored.
This usually shows up in the assembly with pattern like this:
def A
...
save A to B
def A
use A
restore A from B
...
use B
Whereas we could simply have done:
def B
...
def A
use A
...
use B
** Proposed Solution **
A variable having a broken hint is marked for late recoloring if and only if
selecting a register for it evict another variable. Indeed, if no eviction
happens this is pointless to look for recoloring opportunities as it means the
situation was the same as the initial allocation problem where we had to break
the hint.
Finally, when everything has been allocated, we look for recoloring
opportunities for all the identified candidates.
The recoloring is performed very late to rely on accurate copy cost (all
involved variables are allocated).
The recoloring is simple unlike the last change recoloring. It propagates the
color of the broken hint to all its copy-related variables. If the color is
available for them, the recoloring uses it, otherwise it gives up on that hint
even if a more complex coloring would have worked.
The recoloring happens only if it is profitable. The profitability is evaluated
using the expected frequency of the copies of the currently recolored variable
with a) its current color and b) with the target color. If a) is greater or
equal than b), then it is profitable and the recoloring happen.
** Example **
Consider the following example:
BB1:
a =
b =
BB2:
...
= b
= a
Let us assume b gets split:
BB1:
a =
b =
BB2:
c = b
...
d = c
= d
= a
Because of how the allocation work, b, c, and d may be assigned different
colors. Now, if a gets evicted to make room for c, assuming b and d were
assigned to something different than a.
We end up with:
BB1:
a =
st a, SpillSlot
b =
BB2:
c = b
...
d = c
= d
e = ld SpillSlot
= e
This is likely that we can assign the same register for b, c, and d,
getting rid of 2 copies.
** Performances **
Both ARM64 and x86_64 show performance improvements of up to 3% for the
llvm-testsuite + externals with Os and O3. There are a few regressions too that
comes from the (in)accuracy of the block frequency estimate.
<rdar://problem/18312047>
llvm-svn: 225422
2015-01-08 01:16:39 +00:00
|
|
|
/// \brief Collect the hint info for \p Reg.
|
|
|
|
/// The results are stored into \p Out.
|
|
|
|
/// \p Out is not cleared before being populated.
|
|
|
|
void RAGreedy::collectHintInfo(unsigned Reg, HintsInfo &Out) {
|
|
|
|
for (const MachineInstr &Instr : MRI->reg_nodbg_instructions(Reg)) {
|
|
|
|
if (!Instr.isFullCopy())
|
|
|
|
continue;
|
|
|
|
// Look for the other end of the copy.
|
|
|
|
unsigned OtherReg = Instr.getOperand(0).getReg();
|
|
|
|
if (OtherReg == Reg) {
|
|
|
|
OtherReg = Instr.getOperand(1).getReg();
|
|
|
|
if (OtherReg == Reg)
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
// Get the current assignment.
|
|
|
|
unsigned OtherPhysReg = TargetRegisterInfo::isPhysicalRegister(OtherReg)
|
|
|
|
? OtherReg
|
|
|
|
: VRM->getPhys(OtherReg);
|
|
|
|
// Push the collected information.
|
|
|
|
Out.push_back(HintInfo(MBFI->getBlockFreq(Instr.getParent()), OtherReg,
|
|
|
|
OtherPhysReg));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Using the given \p List, compute the cost of the broken hints if
|
|
|
|
/// \p PhysReg was used.
|
|
|
|
/// \return The cost of \p List for \p PhysReg.
|
|
|
|
BlockFrequency RAGreedy::getBrokenHintFreq(const HintsInfo &List,
|
|
|
|
unsigned PhysReg) {
|
|
|
|
BlockFrequency Cost = 0;
|
|
|
|
for (const HintInfo &Info : List) {
|
|
|
|
if (Info.PhysReg != PhysReg)
|
|
|
|
Cost += Info.Freq;
|
|
|
|
}
|
|
|
|
return Cost;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Using the register assigned to \p VirtReg, try to recolor
|
|
|
|
/// all the live ranges that are copy-related with \p VirtReg.
|
|
|
|
/// The recoloring is then propagated to all the live-ranges that have
|
|
|
|
/// been recolored and so on, until no more copies can be coalesced or
|
|
|
|
/// it is not profitable.
|
|
|
|
/// For a given live range, profitability is determined by the sum of the
|
|
|
|
/// frequencies of the non-identity copies it would introduce with the old
|
|
|
|
/// and new register.
|
|
|
|
void RAGreedy::tryHintRecoloring(LiveInterval &VirtReg) {
|
|
|
|
// We have a broken hint, check if it is possible to fix it by
|
|
|
|
// reusing PhysReg for the copy-related live-ranges. Indeed, we evicted
|
|
|
|
// some register and PhysReg may be available for the other live-ranges.
|
|
|
|
SmallSet<unsigned, 4> Visited;
|
|
|
|
SmallVector<unsigned, 2> RecoloringCandidates;
|
|
|
|
HintsInfo Info;
|
|
|
|
unsigned Reg = VirtReg.reg;
|
|
|
|
unsigned PhysReg = VRM->getPhys(Reg);
|
|
|
|
// Start the recoloring algorithm from the input live-interval, then
|
|
|
|
// it will propagate to the ones that are copy-related with it.
|
|
|
|
Visited.insert(Reg);
|
|
|
|
RecoloringCandidates.push_back(Reg);
|
|
|
|
|
|
|
|
DEBUG(dbgs() << "Trying to reconcile hints for: " << PrintReg(Reg, TRI) << '('
|
|
|
|
<< PrintReg(PhysReg, TRI) << ")\n");
|
|
|
|
|
|
|
|
do {
|
|
|
|
Reg = RecoloringCandidates.pop_back_val();
|
|
|
|
|
|
|
|
// We cannot recolor physcal register.
|
|
|
|
if (TargetRegisterInfo::isPhysicalRegister(Reg))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
assert(VRM->hasPhys(Reg) && "We have unallocated variable!!");
|
|
|
|
|
|
|
|
// Get the live interval mapped with this virtual register to be able
|
|
|
|
// to check for the interference with the new color.
|
|
|
|
LiveInterval &LI = LIS->getInterval(Reg);
|
|
|
|
unsigned CurrPhys = VRM->getPhys(Reg);
|
|
|
|
// Check that the new color matches the register class constraints and
|
|
|
|
// that it is free for this live range.
|
|
|
|
if (CurrPhys != PhysReg && (!MRI->getRegClass(Reg)->contains(PhysReg) ||
|
|
|
|
Matrix->checkInterference(LI, PhysReg)))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
DEBUG(dbgs() << PrintReg(Reg, TRI) << '(' << PrintReg(CurrPhys, TRI)
|
|
|
|
<< ") is recolorable.\n");
|
|
|
|
|
|
|
|
// Gather the hint info.
|
|
|
|
Info.clear();
|
|
|
|
collectHintInfo(Reg, Info);
|
|
|
|
// Check if recoloring the live-range will increase the cost of the
|
|
|
|
// non-identity copies.
|
|
|
|
if (CurrPhys != PhysReg) {
|
|
|
|
DEBUG(dbgs() << "Checking profitability:\n");
|
|
|
|
BlockFrequency OldCopiesCost = getBrokenHintFreq(Info, CurrPhys);
|
|
|
|
BlockFrequency NewCopiesCost = getBrokenHintFreq(Info, PhysReg);
|
|
|
|
DEBUG(dbgs() << "Old Cost: " << OldCopiesCost.getFrequency()
|
|
|
|
<< "\nNew Cost: " << NewCopiesCost.getFrequency() << '\n');
|
|
|
|
if (OldCopiesCost < NewCopiesCost) {
|
|
|
|
DEBUG(dbgs() << "=> Not profitable.\n");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
// At this point, the cost is either cheaper or equal. If it is
|
|
|
|
// equal, we consider this is profitable because it may expose
|
|
|
|
// more recoloring opportunities.
|
|
|
|
DEBUG(dbgs() << "=> Profitable.\n");
|
|
|
|
// Recolor the live-range.
|
|
|
|
Matrix->unassign(LI);
|
|
|
|
Matrix->assign(LI, PhysReg);
|
|
|
|
}
|
|
|
|
// Push all copy-related live-ranges to keep reconciling the broken
|
|
|
|
// hints.
|
|
|
|
for (const HintInfo &HI : Info) {
|
|
|
|
if (Visited.insert(HI.Reg).second)
|
|
|
|
RecoloringCandidates.push_back(HI.Reg);
|
|
|
|
}
|
|
|
|
} while (!RecoloringCandidates.empty());
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Try to recolor broken hints.
|
|
|
|
/// Broken hints may be repaired by recoloring when an evicted variable
|
|
|
|
/// freed up a register for a larger live-range.
|
|
|
|
/// Consider the following example:
|
|
|
|
/// BB1:
|
|
|
|
/// a =
|
|
|
|
/// b =
|
|
|
|
/// BB2:
|
|
|
|
/// ...
|
|
|
|
/// = b
|
|
|
|
/// = a
|
|
|
|
/// Let us assume b gets split:
|
|
|
|
/// BB1:
|
|
|
|
/// a =
|
|
|
|
/// b =
|
|
|
|
/// BB2:
|
|
|
|
/// c = b
|
|
|
|
/// ...
|
|
|
|
/// d = c
|
|
|
|
/// = d
|
|
|
|
/// = a
|
|
|
|
/// Because of how the allocation work, b, c, and d may be assigned different
|
|
|
|
/// colors. Now, if a gets evicted later:
|
|
|
|
/// BB1:
|
|
|
|
/// a =
|
|
|
|
/// st a, SpillSlot
|
|
|
|
/// b =
|
|
|
|
/// BB2:
|
|
|
|
/// c = b
|
|
|
|
/// ...
|
|
|
|
/// d = c
|
|
|
|
/// = d
|
|
|
|
/// e = ld SpillSlot
|
|
|
|
/// = e
|
|
|
|
/// This is likely that we can assign the same register for b, c, and d,
|
|
|
|
/// getting rid of 2 copies.
|
|
|
|
void RAGreedy::tryHintsRecoloring() {
|
|
|
|
for (LiveInterval *LI : SetOfBrokenHints) {
|
|
|
|
assert(TargetRegisterInfo::isVirtualRegister(LI->reg) &&
|
|
|
|
"Recoloring is possible only for virtual registers");
|
|
|
|
// Some dead defs may be around (e.g., because of debug uses).
|
|
|
|
// Ignore those.
|
|
|
|
if (!VRM->hasPhys(LI->reg))
|
|
|
|
continue;
|
|
|
|
tryHintRecoloring(*LI);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-02-05 22:13:59 +00:00
|
|
|
unsigned RAGreedy::selectOrSplitImpl(LiveInterval &VirtReg,
|
|
|
|
SmallVectorImpl<unsigned> &NewVRegs,
|
|
|
|
SmallVirtRegSet &FixedRegisters,
|
|
|
|
unsigned Depth) {
|
2014-03-25 00:16:25 +00:00
|
|
|
unsigned CostPerUseLimit = ~0u;
|
2010-12-22 22:01:30 +00:00
|
|
|
// First try assigning a free register.
|
2015-07-15 22:16:00 +00:00
|
|
|
AllocationOrder Order(VirtReg.reg, *VRM, RegClassInfo, Matrix);
|
2014-03-25 00:16:25 +00:00
|
|
|
if (unsigned PhysReg = tryAssign(VirtReg, Order, NewVRegs)) {
|
2014-03-27 21:21:57 +00:00
|
|
|
// When NewVRegs is not empty, we may have made decisions such as evicting
|
|
|
|
// a virtual register, go with the earlier decisions and use the physical
|
|
|
|
// register.
|
2015-07-14 17:38:17 +00:00
|
|
|
if (CSRCost.getFrequency() && isUnusedCalleeSavedReg(PhysReg) &&
|
|
|
|
NewVRegs.empty()) {
|
2014-03-27 21:21:57 +00:00
|
|
|
unsigned CSRReg = tryAssignCSRFirstTime(VirtReg, Order, PhysReg,
|
|
|
|
CostPerUseLimit, NewVRegs);
|
|
|
|
if (CSRReg || !NewVRegs.empty())
|
|
|
|
// Return now if we decide to use a CSR or create new vregs due to
|
|
|
|
// pre-splitting.
|
|
|
|
return CSRReg;
|
2014-03-25 00:16:25 +00:00
|
|
|
} else
|
|
|
|
return PhysReg;
|
|
|
|
}
|
2010-12-09 18:15:21 +00:00
|
|
|
|
2011-05-25 23:58:36 +00:00
|
|
|
LiveRangeStage Stage = getStage(VirtReg);
|
2011-07-02 01:37:09 +00:00
|
|
|
DEBUG(dbgs() << StageName[Stage]
|
|
|
|
<< " Cascade " << ExtraRegInfo[VirtReg.reg].Cascade << '\n');
|
2011-05-25 23:58:36 +00:00
|
|
|
|
2011-06-01 18:45:02 +00:00
|
|
|
// Try to evict a less worthy live range, but only for ranges from the primary
|
2011-07-25 15:25:41 +00:00
|
|
|
// queue. The RS_Split ranges already failed to do this, and they should not
|
2011-06-01 18:45:02 +00:00
|
|
|
// get a second chance until they have been split.
|
2011-07-25 15:25:41 +00:00
|
|
|
if (Stage != RS_Split)
|
[RegAllocGreedy] Introduce a late pass to repair broken hints.
A broken hint is a copy where both ends are assigned different colors. When a
variable gets evicted in the neighborhood of such copies, it is likely we can
reconcile some of them.
** Context **
Copies are inserted during the register allocation via splitting. These split
points are required to relax the constraints on the allocation problem. When
such a point is inserted, both ends of the copy would not share the same color
with respect to the current allocation problem. When variables get evicted,
the allocation problem becomes different and some split point may not be
required anymore. However, the related variables may already have been colored.
This usually shows up in the assembly with pattern like this:
def A
...
save A to B
def A
use A
restore A from B
...
use B
Whereas we could simply have done:
def B
...
def A
use A
...
use B
** Proposed Solution **
A variable having a broken hint is marked for late recoloring if and only if
selecting a register for it evict another variable. Indeed, if no eviction
happens this is pointless to look for recoloring opportunities as it means the
situation was the same as the initial allocation problem where we had to break
the hint.
Finally, when everything has been allocated, we look for recoloring
opportunities for all the identified candidates.
The recoloring is performed very late to rely on accurate copy cost (all
involved variables are allocated).
The recoloring is simple unlike the last change recoloring. It propagates the
color of the broken hint to all its copy-related variables. If the color is
available for them, the recoloring uses it, otherwise it gives up on that hint
even if a more complex coloring would have worked.
The recoloring happens only if it is profitable. The profitability is evaluated
using the expected frequency of the copies of the currently recolored variable
with a) its current color and b) with the target color. If a) is greater or
equal than b), then it is profitable and the recoloring happen.
** Example **
Consider the following example:
BB1:
a =
b =
BB2:
...
= b
= a
Let us assume b gets split:
BB1:
a =
b =
BB2:
c = b
...
d = c
= d
= a
Because of how the allocation work, b, c, and d may be assigned different
colors. Now, if a gets evicted to make room for c, assuming b and d were
assigned to something different than a.
We end up with:
BB1:
a =
st a, SpillSlot
b =
BB2:
c = b
...
d = c
= d
e = ld SpillSlot
= e
This is likely that we can assign the same register for b, c, and d,
getting rid of 2 copies.
** Performances **
Both ARM64 and x86_64 show performance improvements of up to 3% for the
llvm-testsuite + externals with Os and O3. There are a few regressions too that
comes from the (in)accuracy of the block frequency estimate.
<rdar://problem/18312047>
llvm-svn: 225422
2015-01-08 01:16:39 +00:00
|
|
|
if (unsigned PhysReg =
|
|
|
|
tryEvict(VirtReg, Order, NewVRegs, CostPerUseLimit)) {
|
|
|
|
unsigned Hint = MRI->getSimpleHint(VirtReg.reg);
|
|
|
|
// If VirtReg has a hint and that hint is broken record this
|
|
|
|
// virtual register as a recoloring candidate for broken hint.
|
|
|
|
// Indeed, since we evicted a variable in its neighborhood it is
|
|
|
|
// likely we can at least partially recolor some of the
|
|
|
|
// copy-related live-ranges.
|
|
|
|
if (Hint && Hint != PhysReg)
|
|
|
|
SetOfBrokenHints.insert(&VirtReg);
|
2011-06-01 18:45:02 +00:00
|
|
|
return PhysReg;
|
[RegAllocGreedy] Introduce a late pass to repair broken hints.
A broken hint is a copy where both ends are assigned different colors. When a
variable gets evicted in the neighborhood of such copies, it is likely we can
reconcile some of them.
** Context **
Copies are inserted during the register allocation via splitting. These split
points are required to relax the constraints on the allocation problem. When
such a point is inserted, both ends of the copy would not share the same color
with respect to the current allocation problem. When variables get evicted,
the allocation problem becomes different and some split point may not be
required anymore. However, the related variables may already have been colored.
This usually shows up in the assembly with pattern like this:
def A
...
save A to B
def A
use A
restore A from B
...
use B
Whereas we could simply have done:
def B
...
def A
use A
...
use B
** Proposed Solution **
A variable having a broken hint is marked for late recoloring if and only if
selecting a register for it evict another variable. Indeed, if no eviction
happens this is pointless to look for recoloring opportunities as it means the
situation was the same as the initial allocation problem where we had to break
the hint.
Finally, when everything has been allocated, we look for recoloring
opportunities for all the identified candidates.
The recoloring is performed very late to rely on accurate copy cost (all
involved variables are allocated).
The recoloring is simple unlike the last change recoloring. It propagates the
color of the broken hint to all its copy-related variables. If the color is
available for them, the recoloring uses it, otherwise it gives up on that hint
even if a more complex coloring would have worked.
The recoloring happens only if it is profitable. The profitability is evaluated
using the expected frequency of the copies of the currently recolored variable
with a) its current color and b) with the target color. If a) is greater or
equal than b), then it is profitable and the recoloring happen.
** Example **
Consider the following example:
BB1:
a =
b =
BB2:
...
= b
= a
Let us assume b gets split:
BB1:
a =
b =
BB2:
c = b
...
d = c
= d
= a
Because of how the allocation work, b, c, and d may be assigned different
colors. Now, if a gets evicted to make room for c, assuming b and d were
assigned to something different than a.
We end up with:
BB1:
a =
st a, SpillSlot
b =
BB2:
c = b
...
d = c
= d
e = ld SpillSlot
= e
This is likely that we can assign the same register for b, c, and d,
getting rid of 2 copies.
** Performances **
Both ARM64 and x86_64 show performance improvements of up to 3% for the
llvm-testsuite + externals with Os and O3. There are a few regressions too that
comes from the (in)accuracy of the block frequency estimate.
<rdar://problem/18312047>
llvm-svn: 225422
2015-01-08 01:16:39 +00:00
|
|
|
}
|
2010-12-09 18:15:21 +00:00
|
|
|
|
2011-01-19 22:11:48 +00:00
|
|
|
assert(NewVRegs.empty() && "Cannot append to existing NewVRegs");
|
|
|
|
|
2011-02-24 23:21:36 +00:00
|
|
|
// The first time we see a live range, don't try to split or spill.
|
|
|
|
// Wait until the second time, when all smaller ranges have been allocated.
|
|
|
|
// This gives a better picture of the interference to split around.
|
2011-07-25 15:25:41 +00:00
|
|
|
if (Stage < RS_Split) {
|
|
|
|
setStage(VirtReg, RS_Split);
|
2011-03-19 23:02:47 +00:00
|
|
|
DEBUG(dbgs() << "wait for second round\n");
|
2013-08-14 23:50:04 +00:00
|
|
|
NewVRegs.push_back(VirtReg.reg);
|
2011-02-24 23:21:36 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-05-06 21:58:30 +00:00
|
|
|
// If we couldn't allocate a register from spilling, there is probably some
|
|
|
|
// invalid inline assembly. The base class wil report it.
|
2011-07-25 15:25:41 +00:00
|
|
|
if (Stage >= RS_Done || !VirtReg.isSpillable())
|
2014-02-05 22:13:59 +00:00
|
|
|
return tryLastChanceRecoloring(VirtReg, Order, NewVRegs, FixedRegisters,
|
|
|
|
Depth);
|
2011-03-01 21:10:07 +00:00
|
|
|
|
2010-12-14 00:37:49 +00:00
|
|
|
// Try splitting VirtReg or interferences.
|
2011-01-19 22:11:48 +00:00
|
|
|
unsigned PhysReg = trySplit(VirtReg, Order, NewVRegs);
|
|
|
|
if (PhysReg || !NewVRegs.empty())
|
2010-12-14 00:37:44 +00:00
|
|
|
return PhysReg;
|
|
|
|
|
2010-12-22 22:01:30 +00:00
|
|
|
// Finally spill VirtReg itself.
|
2015-07-17 23:04:06 +00:00
|
|
|
if (EnableDeferredSpilling && getStage(VirtReg) < RS_Memory) {
|
|
|
|
// TODO: This is experimental and in particular, we do not model
|
|
|
|
// the live range splitting done by spilling correctly.
|
|
|
|
// We would need a deep integration with the spiller to do the
|
|
|
|
// right thing here. Anyway, that is still good for early testing.
|
|
|
|
setStage(VirtReg, RS_Memory);
|
|
|
|
DEBUG(dbgs() << "Do as if this register is in memory\n");
|
|
|
|
NewVRegs.push_back(VirtReg.reg);
|
|
|
|
} else {
|
|
|
|
NamedRegionTimer T("Spiller", TimerGroupName, TimePassesIsEnabled);
|
2016-04-13 03:08:27 +00:00
|
|
|
LiveRangeEdit LRE(&VirtReg, NewVRegs, *MF, *LIS, VRM, this, &DeadRemats);
|
2015-07-17 23:04:06 +00:00
|
|
|
spiller().spill(LRE);
|
|
|
|
setStage(NewVRegs.begin(), NewVRegs.end(), RS_Done);
|
2010-12-08 03:26:16 +00:00
|
|
|
|
2015-07-17 23:04:06 +00:00
|
|
|
if (VerifyEnabled)
|
|
|
|
MF->verify(this, "After spilling");
|
|
|
|
}
|
2011-03-16 22:56:08 +00:00
|
|
|
|
2010-12-08 03:26:16 +00:00
|
|
|
// The live virtual register requesting allocation was spilled, so tell
|
|
|
|
// the caller not to allocate anything during this round.
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool RAGreedy::runOnMachineFunction(MachineFunction &mf) {
|
|
|
|
DEBUG(dbgs() << "********** GREEDY REGISTER ALLOCATION **********\n"
|
2012-08-22 17:18:53 +00:00
|
|
|
<< "********** Function: " << mf.getName() << '\n');
|
2010-12-08 03:26:16 +00:00
|
|
|
|
|
|
|
MF = &mf;
|
2014-10-14 07:22:00 +00:00
|
|
|
TRI = MF->getSubtarget().getRegisterInfo();
|
|
|
|
TII = MF->getSubtarget().getInstrInfo();
|
2014-01-02 22:47:22 +00:00
|
|
|
RCI.runOnMachineFunction(mf);
|
2014-07-02 18:32:04 +00:00
|
|
|
|
|
|
|
EnableLocalReassign = EnableLocalReassignment ||
|
2014-10-14 07:22:00 +00:00
|
|
|
MF->getSubtarget().enableRALocalReassignment(
|
|
|
|
MF->getTarget().getOptLevel());
|
2014-07-02 18:32:04 +00:00
|
|
|
|
2010-12-17 23:16:35 +00:00
|
|
|
if (VerifyEnabled)
|
2010-12-18 00:06:56 +00:00
|
|
|
MF->verify(this, "Before greedy register allocator");
|
2010-12-17 23:16:35 +00:00
|
|
|
|
2012-06-20 22:52:29 +00:00
|
|
|
RegAllocBase::init(getAnalysis<VirtRegMap>(),
|
|
|
|
getAnalysis<LiveIntervals>(),
|
|
|
|
getAnalysis<LiveRegMatrix>());
|
2011-01-18 21:13:27 +00:00
|
|
|
Indexes = &getAnalysis<SlotIndexes>();
|
2013-06-17 19:00:36 +00:00
|
|
|
MBFI = &getAnalysis<MachineBlockFrequencyInfo>();
|
2010-12-17 23:16:32 +00:00
|
|
|
DomTree = &getAnalysis<MachineDominatorTree>();
|
2010-12-10 22:54:44 +00:00
|
|
|
SpillerInstance.reset(createInlineSpiller(*this, *MF, *VRM));
|
2010-12-15 23:46:13 +00:00
|
|
|
Loops = &getAnalysis<MachineLoopInfo>();
|
2011-01-18 21:13:27 +00:00
|
|
|
Bundles = &getAnalysis<EdgeBundles>();
|
|
|
|
SpillPlacer = &getAnalysis<SpillPlacement>();
|
2011-05-06 18:00:02 +00:00
|
|
|
DebugVars = &getAnalysis<LiveDebugVariables>();
|
2016-07-08 21:08:09 +00:00
|
|
|
AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
|
2011-01-18 21:13:27 +00:00
|
|
|
|
2014-04-08 19:18:56 +00:00
|
|
|
initializeCSRCost();
|
|
|
|
|
2015-08-10 11:59:44 +00:00
|
|
|
calculateSpillWeightsAndHints(*LIS, mf, VRM, *Loops, *MBFI);
|
2013-11-10 17:46:31 +00:00
|
|
|
|
2013-07-25 07:26:26 +00:00
|
|
|
DEBUG(LIS->dump());
|
|
|
|
|
2011-02-19 00:53:42 +00:00
|
|
|
SA.reset(new SplitAnalysis(*VRM, *LIS, *Loops));
|
2016-07-08 21:08:09 +00:00
|
|
|
SE.reset(new SplitEditor(*SA, *AA, *LIS, *VRM, *DomTree, *MBFI));
|
2011-07-02 01:37:09 +00:00
|
|
|
ExtraRegInfo.clear();
|
|
|
|
ExtraRegInfo.resize(MRI->getNumVirtRegs());
|
|
|
|
NextCascade = 1;
|
2012-06-20 22:52:26 +00:00
|
|
|
IntfCache.init(MF, Matrix->getLiveUnions(), Indexes, LIS, TRI);
|
2011-07-26 23:41:46 +00:00
|
|
|
GlobalCand.resize(32); // This will grow as needed.
|
[RegAllocGreedy] Introduce a late pass to repair broken hints.
A broken hint is a copy where both ends are assigned different colors. When a
variable gets evicted in the neighborhood of such copies, it is likely we can
reconcile some of them.
** Context **
Copies are inserted during the register allocation via splitting. These split
points are required to relax the constraints on the allocation problem. When
such a point is inserted, both ends of the copy would not share the same color
with respect to the current allocation problem. When variables get evicted,
the allocation problem becomes different and some split point may not be
required anymore. However, the related variables may already have been colored.
This usually shows up in the assembly with pattern like this:
def A
...
save A to B
def A
use A
restore A from B
...
use B
Whereas we could simply have done:
def B
...
def A
use A
...
use B
** Proposed Solution **
A variable having a broken hint is marked for late recoloring if and only if
selecting a register for it evict another variable. Indeed, if no eviction
happens this is pointless to look for recoloring opportunities as it means the
situation was the same as the initial allocation problem where we had to break
the hint.
Finally, when everything has been allocated, we look for recoloring
opportunities for all the identified candidates.
The recoloring is performed very late to rely on accurate copy cost (all
involved variables are allocated).
The recoloring is simple unlike the last change recoloring. It propagates the
color of the broken hint to all its copy-related variables. If the color is
available for them, the recoloring uses it, otherwise it gives up on that hint
even if a more complex coloring would have worked.
The recoloring happens only if it is profitable. The profitability is evaluated
using the expected frequency of the copies of the currently recolored variable
with a) its current color and b) with the target color. If a) is greater or
equal than b), then it is profitable and the recoloring happen.
** Example **
Consider the following example:
BB1:
a =
b =
BB2:
...
= b
= a
Let us assume b gets split:
BB1:
a =
b =
BB2:
c = b
...
d = c
= d
= a
Because of how the allocation work, b, c, and d may be assigned different
colors. Now, if a gets evicted to make room for c, assuming b and d were
assigned to something different than a.
We end up with:
BB1:
a =
st a, SpillSlot
b =
BB2:
c = b
...
d = c
= d
e = ld SpillSlot
= e
This is likely that we can assign the same register for b, c, and d,
getting rid of 2 copies.
** Performances **
Both ARM64 and x86_64 show performance improvements of up to 3% for the
llvm-testsuite + externals with Os and O3. There are a few regressions too that
comes from the (in)accuracy of the block frequency estimate.
<rdar://problem/18312047>
llvm-svn: 225422
2015-01-08 01:16:39 +00:00
|
|
|
SetOfBrokenHints.clear();
|
2010-12-15 23:46:13 +00:00
|
|
|
|
2010-12-08 03:26:16 +00:00
|
|
|
allocatePhysRegs();
|
[RegAllocGreedy] Introduce a late pass to repair broken hints.
A broken hint is a copy where both ends are assigned different colors. When a
variable gets evicted in the neighborhood of such copies, it is likely we can
reconcile some of them.
** Context **
Copies are inserted during the register allocation via splitting. These split
points are required to relax the constraints on the allocation problem. When
such a point is inserted, both ends of the copy would not share the same color
with respect to the current allocation problem. When variables get evicted,
the allocation problem becomes different and some split point may not be
required anymore. However, the related variables may already have been colored.
This usually shows up in the assembly with pattern like this:
def A
...
save A to B
def A
use A
restore A from B
...
use B
Whereas we could simply have done:
def B
...
def A
use A
...
use B
** Proposed Solution **
A variable having a broken hint is marked for late recoloring if and only if
selecting a register for it evict another variable. Indeed, if no eviction
happens this is pointless to look for recoloring opportunities as it means the
situation was the same as the initial allocation problem where we had to break
the hint.
Finally, when everything has been allocated, we look for recoloring
opportunities for all the identified candidates.
The recoloring is performed very late to rely on accurate copy cost (all
involved variables are allocated).
The recoloring is simple unlike the last change recoloring. It propagates the
color of the broken hint to all its copy-related variables. If the color is
available for them, the recoloring uses it, otherwise it gives up on that hint
even if a more complex coloring would have worked.
The recoloring happens only if it is profitable. The profitability is evaluated
using the expected frequency of the copies of the currently recolored variable
with a) its current color and b) with the target color. If a) is greater or
equal than b), then it is profitable and the recoloring happen.
** Example **
Consider the following example:
BB1:
a =
b =
BB2:
...
= b
= a
Let us assume b gets split:
BB1:
a =
b =
BB2:
c = b
...
d = c
= d
= a
Because of how the allocation work, b, c, and d may be assigned different
colors. Now, if a gets evicted to make room for c, assuming b and d were
assigned to something different than a.
We end up with:
BB1:
a =
st a, SpillSlot
b =
BB2:
c = b
...
d = c
= d
e = ld SpillSlot
= e
This is likely that we can assign the same register for b, c, and d,
getting rid of 2 copies.
** Performances **
Both ARM64 and x86_64 show performance improvements of up to 3% for the
llvm-testsuite + externals with Os and O3. There are a few regressions too that
comes from the (in)accuracy of the block frequency estimate.
<rdar://problem/18312047>
llvm-svn: 225422
2015-01-08 01:16:39 +00:00
|
|
|
tryHintsRecoloring();
|
2016-04-13 03:08:27 +00:00
|
|
|
postOptimization();
|
|
|
|
|
2010-12-08 03:26:16 +00:00
|
|
|
releaseMemory();
|
|
|
|
return true;
|
|
|
|
}
|