mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-13 04:30:23 +00:00
Add a stack slot coloring pass. Not yet enabled.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@51934 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
d8a46e3a74
commit
3f32d65912
@ -35,6 +35,7 @@ namespace llvm {
|
||||
/// merge point), it contains ~0u,x. If the value number is not in use, it
|
||||
/// contains ~1u,x to indicate that the value # is not used.
|
||||
/// def - Instruction # of the definition.
|
||||
/// - or reg # of the definition if it's a stack slot liveinterval.
|
||||
/// copy - Copy iff val# is defined by a copy; zero otherwise.
|
||||
/// hasPHIKill - One or more of the kills are PHI nodes.
|
||||
/// kills - Instruction # of the kills.
|
||||
@ -100,15 +101,16 @@ namespace llvm {
|
||||
typedef SmallVector<LiveRange,4> Ranges;
|
||||
typedef SmallVector<VNInfo*,4> VNInfoList;
|
||||
|
||||
unsigned reg; // the register of this interval
|
||||
bool isSS; // True if this represents a stack slot
|
||||
unsigned reg; // the register or stack slot of this interval
|
||||
unsigned preference; // preferred register to allocate for this interval
|
||||
float weight; // weight of this interval
|
||||
Ranges ranges; // the ranges in which this register is live
|
||||
VNInfoList valnos; // value#'s
|
||||
|
||||
public:
|
||||
LiveInterval(unsigned Reg, float Weight)
|
||||
: reg(Reg), preference(0), weight(Weight) {
|
||||
LiveInterval(unsigned Reg, float Weight, bool IsSS = false)
|
||||
: isSS(IsSS), reg(Reg), preference(0), weight(Weight) {
|
||||
}
|
||||
|
||||
typedef Ranges::iterator iterator;
|
||||
@ -139,6 +141,17 @@ namespace llvm {
|
||||
return I;
|
||||
}
|
||||
|
||||
/// isStackSlot - Return true if this is a stack slot interval.
|
||||
///
|
||||
bool isStackSlot() const { return isSS; }
|
||||
|
||||
/// getStackSlotIndex - Return stack slot index if this is a stack slot
|
||||
/// interval.
|
||||
int getStackSlotIndex() const {
|
||||
assert(isStackSlot() && "Interval is not a stack slot interval!");
|
||||
return reg;
|
||||
}
|
||||
|
||||
bool containsOneValue() const { return valnos.size() == 1; }
|
||||
|
||||
unsigned getNumValNums() const { return (unsigned)valnos.size(); }
|
||||
@ -313,6 +326,11 @@ namespace llvm {
|
||||
/// FindLiveRangeContaining - Return an iterator to the live range that
|
||||
/// contains the specified index, or end() if there is none.
|
||||
iterator FindLiveRangeContaining(unsigned Idx);
|
||||
|
||||
/// findDefinedVNInfo - Find the VNInfo that's defined at the specified
|
||||
/// index (register interval) or defined by the specified register (stack
|
||||
/// inteval).
|
||||
VNInfo *findDefinedVNInfo(unsigned DefIdxOrReg) const;
|
||||
|
||||
/// overlaps - Return true if the intersection of the two live intervals is
|
||||
/// not empty.
|
||||
|
71
include/llvm/CodeGen/LiveStackAnalysis.h
Normal file
71
include/llvm/CodeGen/LiveStackAnalysis.h
Normal file
@ -0,0 +1,71 @@
|
||||
//===-- LiveStackAnalysis.h - Live Stack Slot Analysis ----------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements the live stack slot analysis pass. It is analogous to
|
||||
// live interval analysis except it's analyzing liveness of stack slots rather
|
||||
// than registers.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CODEGEN_LIVESTACK_ANALYSIS_H
|
||||
#define LLVM_CODEGEN_LIVESTACK_ANALYSIS_H
|
||||
|
||||
#include "llvm/CodeGen/MachineFunctionPass.h"
|
||||
#include "llvm/CodeGen/LiveInterval.h"
|
||||
#include "llvm/Support/Allocator.h"
|
||||
#include <map>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class LiveStacks : public MachineFunctionPass {
|
||||
/// Special pool allocator for VNInfo's (LiveInterval val#).
|
||||
///
|
||||
BumpPtrAllocator VNInfoAllocator;
|
||||
|
||||
/// s2iMap - Stack slot indices to live interval mapping.
|
||||
///
|
||||
typedef std::map<int, LiveInterval> SS2IntervalMap;
|
||||
SS2IntervalMap s2iMap;
|
||||
|
||||
public:
|
||||
static char ID; // Pass identification, replacement for typeid
|
||||
LiveStacks() : MachineFunctionPass((intptr_t)&ID) {}
|
||||
|
||||
typedef SS2IntervalMap::iterator iterator;
|
||||
typedef SS2IntervalMap::const_iterator const_iterator;
|
||||
const_iterator begin() const { return s2iMap.begin(); }
|
||||
const_iterator end() const { return s2iMap.end(); }
|
||||
iterator begin() { return s2iMap.begin(); }
|
||||
iterator end() { return s2iMap.end(); }
|
||||
unsigned getNumIntervals() const { return (unsigned)s2iMap.size(); }
|
||||
|
||||
LiveInterval &getOrCreateInterval(int Slot) {
|
||||
SS2IntervalMap::iterator I = s2iMap.find(Slot);
|
||||
if (I == s2iMap.end())
|
||||
I = s2iMap.insert(I,std::make_pair(Slot,LiveInterval(Slot,0.0F,true)));
|
||||
return I->second;
|
||||
}
|
||||
|
||||
BumpPtrAllocator& getVNInfoAllocator() { return VNInfoAllocator; }
|
||||
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
|
||||
virtual void releaseMemory();
|
||||
|
||||
/// runOnMachineFunction - pass entry point
|
||||
virtual bool runOnMachineFunction(MachineFunction&);
|
||||
|
||||
/// print - Implement the dump method.
|
||||
virtual void print(std::ostream &O, const Module* = 0) const;
|
||||
void print(std::ostream *O, const Module* M = 0) const {
|
||||
if (O) print(*O, M);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* LLVM_CODEGEN_LIVESTACK_ANALYSIS_H */
|
@ -195,6 +195,13 @@ public:
|
||||
///
|
||||
int getObjectIndexEnd() const { return (int)Objects.size()-NumFixedObjects; }
|
||||
|
||||
/// getNumFixedObjects() - Return the number of fixed objects.
|
||||
unsigned getNumFixedObjects() const { return NumFixedObjects; }
|
||||
|
||||
/// getNumObjects() - Return the number of objects.
|
||||
///
|
||||
unsigned getNumObjects() const { return Objects.size(); }
|
||||
|
||||
/// getObjectSize - Return the size of the specified object
|
||||
///
|
||||
int64_t getObjectSize(int ObjectIdx) const {
|
||||
@ -203,6 +210,13 @@ public:
|
||||
return Objects[ObjectIdx+NumFixedObjects].Size;
|
||||
}
|
||||
|
||||
// setObjectSize - Change the size of the specified stack object...
|
||||
void setObjectSize(int ObjectIdx, int64_t Size) {
|
||||
assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() &&
|
||||
"Invalid Object Idx!");
|
||||
Objects[ObjectIdx+NumFixedObjects].Size = Size;
|
||||
}
|
||||
|
||||
/// getObjectAlignment - Return the alignment of the specified stack object...
|
||||
unsigned getObjectAlignment(int ObjectIdx) const {
|
||||
assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() &&
|
||||
@ -324,12 +338,8 @@ public:
|
||||
/// RemoveStackObject - Remove or mark dead a statically sized stack object.
|
||||
///
|
||||
void RemoveStackObject(int ObjectIdx) {
|
||||
if (ObjectIdx == (int)(Objects.size()-NumFixedObjects-1))
|
||||
// Last object, simply pop it off the list.
|
||||
Objects.pop_back();
|
||||
else
|
||||
// Mark it dead.
|
||||
Objects[ObjectIdx+NumFixedObjects].Size = ~0ULL;
|
||||
// Mark it dead.
|
||||
Objects[ObjectIdx+NumFixedObjects].Size = ~0ULL;
|
||||
}
|
||||
|
||||
/// CreateVariableSizedObject - Notify the MachineFrameInfo object that a
|
||||
|
@ -172,6 +172,9 @@ namespace llvm {
|
||||
/// createMachineSinkingPass - This pass performs sinking on machine
|
||||
/// instructions.
|
||||
FunctionPass *createMachineSinkingPass();
|
||||
|
||||
/// createStackSlotColoringPass - This pass performs stack slot coloring.
|
||||
FunctionPass *createStackSlotColoringPass();
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
|
@ -38,12 +38,13 @@ static cl::opt<bool>
|
||||
EnableSinking("enable-sinking", cl::init(false), cl::Hidden,
|
||||
cl::desc("Perform sinking on machine code"));
|
||||
static cl::opt<bool>
|
||||
AlignLoops("align-loops", cl::init(true), cl::Hidden,
|
||||
cl::desc("Align loop headers"));
|
||||
EnableStackColoring("stack-coloring",
|
||||
cl::init(true), cl::Hidden,
|
||||
cl::desc("Perform stack slot coloring"));
|
||||
static cl::opt<bool>
|
||||
PerformLICM("machine-licm",
|
||||
cl::init(false), cl::Hidden,
|
||||
cl::desc("Perform loop-invariant code motion on machine code"));
|
||||
EnableLICM("machine-licm",
|
||||
cl::init(false), cl::Hidden,
|
||||
cl::desc("Perform loop-invariant code motion on machine code"));
|
||||
|
||||
// When this works it will be on by default.
|
||||
static cl::opt<bool>
|
||||
@ -88,7 +89,7 @@ LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &PM,
|
||||
if (PrintMachineCode)
|
||||
PM.add(createMachineFunctionPrinterPass(cerr));
|
||||
|
||||
if (PerformLICM)
|
||||
if (EnableLICM)
|
||||
PM.add(createMachineLICMPass());
|
||||
|
||||
if (EnableSinking)
|
||||
@ -101,21 +102,28 @@ LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &PM,
|
||||
// Perform register allocation to convert to a concrete x86 representation
|
||||
PM.add(createRegisterAllocator());
|
||||
|
||||
if (PrintMachineCode)
|
||||
// Perform stack slot coloring.
|
||||
if (EnableStackColoring)
|
||||
PM.add(createStackSlotColoringPass());
|
||||
|
||||
if (PrintMachineCode) // Print the register-allocated code
|
||||
PM.add(createMachineFunctionPrinterPass(cerr));
|
||||
|
||||
|
||||
// Run post-ra passes.
|
||||
if (addPostRegAlloc(PM, Fast) && PrintMachineCode)
|
||||
PM.add(createMachineFunctionPrinterPass(cerr));
|
||||
|
||||
PM.add(createLowerSubregsPass());
|
||||
|
||||
if (PrintMachineCode) // Print the subreg lowered code
|
||||
PM.add(createMachineFunctionPrinterPass(cerr));
|
||||
|
||||
// Run post-ra passes.
|
||||
if (addPostRegAlloc(PM, Fast) && PrintMachineCode)
|
||||
PM.add(createMachineFunctionPrinterPass(cerr));
|
||||
|
||||
// Insert prolog/epilog code. Eliminate abstract frame index references...
|
||||
PM.add(createPrologEpilogCodeInserter());
|
||||
|
||||
if (PrintMachineCode)
|
||||
PM.add(createMachineFunctionPrinterPass(cerr));
|
||||
|
||||
// Second pass scheduler.
|
||||
if (!Fast && !DisablePostRAScheduler)
|
||||
PM.add(createPostRAScheduler());
|
||||
@ -140,7 +148,7 @@ LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &PM,
|
||||
if (addPreEmitPass(PM, Fast) && PrintMachineCode)
|
||||
PM.add(createMachineFunctionPrinterPass(cerr));
|
||||
|
||||
if (AlignLoops && !Fast && !OptimizeForSize)
|
||||
if (!Fast && !OptimizeForSize)
|
||||
PM.add(createLoopAlignerPass());
|
||||
|
||||
switch (FileType) {
|
||||
@ -218,7 +226,7 @@ bool LLVMTargetMachine::addPassesToEmitMachineCode(PassManagerBase &PM,
|
||||
if (PrintMachineCode)
|
||||
PM.add(createMachineFunctionPrinterPass(cerr));
|
||||
|
||||
if (PerformLICM)
|
||||
if (EnableLICM)
|
||||
PM.add(createMachineLICMPass());
|
||||
|
||||
if (EnableSinking)
|
||||
@ -228,25 +236,32 @@ bool LLVMTargetMachine::addPassesToEmitMachineCode(PassManagerBase &PM,
|
||||
if (addPreRegAlloc(PM, Fast) && PrintMachineCode)
|
||||
PM.add(createMachineFunctionPrinterPass(cerr));
|
||||
|
||||
// Perform register allocation to convert to a concrete x86 representation
|
||||
// Perform register allocation.
|
||||
PM.add(createRegisterAllocator());
|
||||
|
||||
|
||||
// Perform stack slot coloring.
|
||||
if (EnableStackColoring)
|
||||
PM.add(createStackSlotColoringPass());
|
||||
|
||||
if (PrintMachineCode)
|
||||
PM.add(createMachineFunctionPrinterPass(cerr));
|
||||
|
||||
// Run post-ra passes.
|
||||
if (addPostRegAlloc(PM, Fast) && PrintMachineCode)
|
||||
PM.add(createMachineFunctionPrinterPass(cerr));
|
||||
|
||||
if (PrintMachineCode) // Print the register-allocated code
|
||||
PM.add(createMachineFunctionPrinterPass(cerr));
|
||||
|
||||
PM.add(createLowerSubregsPass());
|
||||
|
||||
if (PrintMachineCode) // Print the subreg lowered code
|
||||
PM.add(createMachineFunctionPrinterPass(cerr));
|
||||
|
||||
// Run post-ra passes.
|
||||
if (addPostRegAlloc(PM, Fast) && PrintMachineCode)
|
||||
PM.add(createMachineFunctionPrinterPass(cerr));
|
||||
|
||||
// Insert prolog/epilog code. Eliminate abstract frame index references...
|
||||
PM.add(createPrologEpilogCodeInserter());
|
||||
|
||||
if (PrintMachineCode) // Print the register-allocated code
|
||||
if (PrintMachineCode)
|
||||
PM.add(createMachineFunctionPrinterPass(cerr));
|
||||
|
||||
// Second pass scheduler.
|
||||
@ -258,6 +273,7 @@ bool LLVMTargetMachine::addPassesToEmitMachineCode(PassManagerBase &PM,
|
||||
PM.add(createBranchFoldingPass(getEnableTailMergeDefault()));
|
||||
|
||||
PM.add(createGCMachineCodeAnalysisPass());
|
||||
|
||||
if (PrintMachineCode)
|
||||
PM.add(createMachineFunctionPrinterPass(cerr));
|
||||
|
||||
|
@ -358,6 +358,20 @@ LiveInterval::FindLiveRangeContaining(unsigned Idx) {
|
||||
return end();
|
||||
}
|
||||
|
||||
/// findDefinedVNInfo - Find the VNInfo that's defined at the specified index
|
||||
/// (register interval) or defined by the specified register (stack inteval).
|
||||
VNInfo *LiveInterval::findDefinedVNInfo(unsigned DefIdxOrReg) const {
|
||||
VNInfo *VNI = NULL;
|
||||
for (LiveInterval::const_vni_iterator i = vni_begin(), e = vni_end();
|
||||
i != e; ++i)
|
||||
if ((*i)->def == DefIdxOrReg) {
|
||||
VNI = *i;
|
||||
break;
|
||||
}
|
||||
return VNI;
|
||||
}
|
||||
|
||||
|
||||
/// join - Join two live intervals (this, and other) together. This applies
|
||||
/// mappings to the value numbers in the LHS/RHS intervals as specified. If
|
||||
/// the intervals are not joinable, this aborts.
|
||||
@ -664,7 +678,9 @@ void LiveRange::dump() const {
|
||||
|
||||
void LiveInterval::print(std::ostream &OS,
|
||||
const TargetRegisterInfo *TRI) const {
|
||||
if (TRI && TargetRegisterInfo::isPhysicalRegister(reg))
|
||||
if (isSS)
|
||||
OS << "SS#" << reg;
|
||||
else if (TRI && TargetRegisterInfo::isPhysicalRegister(reg))
|
||||
OS << TRI->getName(reg);
|
||||
else
|
||||
OS << "%reg" << reg;
|
||||
@ -672,7 +688,7 @@ void LiveInterval::print(std::ostream &OS,
|
||||
OS << ',' << weight;
|
||||
|
||||
if (empty())
|
||||
OS << "EMPTY";
|
||||
OS << " EMPTY";
|
||||
else {
|
||||
OS << " = ";
|
||||
for (LiveInterval::Ranges::const_iterator I = ranges.begin(),
|
||||
|
@ -65,6 +65,7 @@ void LiveIntervals::getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
}
|
||||
|
||||
void LiveIntervals::releaseMemory() {
|
||||
MBB2IdxMap.clear();
|
||||
Idx2MBBMap.clear();
|
||||
mi2iMap_.clear();
|
||||
i2miMap_.clear();
|
||||
@ -229,8 +230,8 @@ bool LiveIntervals::runOnMachineFunction(MachineFunction &fn) {
|
||||
void LiveIntervals::print(std::ostream &O, const Module* ) const {
|
||||
O << "********** INTERVALS **********\n";
|
||||
for (const_iterator I = begin(), E = end(); I != E; ++I) {
|
||||
I->second.print(DOUT, tri_);
|
||||
DOUT << "\n";
|
||||
I->second.print(O, tri_);
|
||||
O << "\n";
|
||||
}
|
||||
|
||||
O << "********** MACHINEINSTRS **********\n";
|
||||
@ -1160,17 +1161,6 @@ bool LiveIntervals::anyKillInMBBAfterIdx(const LiveInterval &li,
|
||||
return false;
|
||||
}
|
||||
|
||||
static const VNInfo *findDefinedVNInfo(const LiveInterval &li, unsigned DefIdx) {
|
||||
const VNInfo *VNI = NULL;
|
||||
for (LiveInterval::const_vni_iterator i = li.vni_begin(),
|
||||
e = li.vni_end(); i != e; ++i)
|
||||
if ((*i)->def == DefIdx) {
|
||||
VNI = *i;
|
||||
break;
|
||||
}
|
||||
return VNI;
|
||||
}
|
||||
|
||||
/// RewriteInfo - Keep track of machine instrs that will be rewritten
|
||||
/// during spilling.
|
||||
namespace {
|
||||
@ -1318,7 +1308,7 @@ rewriteInstructionsForSpills(const LiveInterval &li, bool TrySplit,
|
||||
HasKill = anyKillInMBBAfterIdx(li, I->valno, MBB, getDefIndex(index));
|
||||
else {
|
||||
// If this is a two-address code, then this index starts a new VNInfo.
|
||||
const VNInfo *VNI = findDefinedVNInfo(li, getDefIndex(index));
|
||||
const VNInfo *VNI = li.findDefinedVNInfo(getDefIndex(index));
|
||||
if (VNI)
|
||||
HasKill = anyKillInMBBAfterIdx(li, VNI, MBB, getDefIndex(index));
|
||||
}
|
||||
|
50
lib/CodeGen/LiveStackAnalysis.cpp
Normal file
50
lib/CodeGen/LiveStackAnalysis.cpp
Normal file
@ -0,0 +1,50 @@
|
||||
//===-- LiveStackAnalysis.cpp - Live Stack Slot Analysis ------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements the live stack slot analysis pass. It is analogous to
|
||||
// live interval analysis except it's analyzing liveness of stack slots rather
|
||||
// than registers.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#define DEBUG_TYPE "livestacks"
|
||||
#include "llvm/CodeGen/LiveStackAnalysis.h"
|
||||
#include "llvm/CodeGen/Passes.h"
|
||||
#include "llvm/Target/TargetRegisterInfo.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
using namespace llvm;
|
||||
|
||||
char LiveStacks::ID = 0;
|
||||
static RegisterPass<LiveStacks> X("livestacks", "Live Stack Slot Analysis");
|
||||
|
||||
void LiveStacks::getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.setPreservesAll();
|
||||
}
|
||||
|
||||
void LiveStacks::releaseMemory() {
|
||||
// Release VNInfo memroy regions after all VNInfo objects are dtor'd.
|
||||
VNInfoAllocator.Reset();
|
||||
s2iMap.clear();
|
||||
}
|
||||
|
||||
bool LiveStacks::runOnMachineFunction(MachineFunction &) {
|
||||
// FIXME: No analysis is being done right now. We are relying on the
|
||||
// register allocators to provide the information.
|
||||
return false;
|
||||
}
|
||||
|
||||
/// print - Implement the dump method.
|
||||
void LiveStacks::print(std::ostream &O, const Module* ) const {
|
||||
O << "********** INTERVALS **********\n";
|
||||
for (const_iterator I = begin(), E = end(); I != E; ++I) {
|
||||
I->second.print(O);
|
||||
O << "\n";
|
||||
}
|
||||
}
|
@ -12,10 +12,11 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#define DEBUG_TYPE "regalloc"
|
||||
#include "llvm/CodeGen/LiveIntervalAnalysis.h"
|
||||
#include "PhysRegTracker.h"
|
||||
#include "VirtRegMap.h"
|
||||
#include "llvm/Function.h"
|
||||
#include "llvm/CodeGen/LiveIntervalAnalysis.h"
|
||||
#include "llvm/CodeGen/LiveStackAnalysis.h"
|
||||
#include "llvm/CodeGen/MachineFunctionPass.h"
|
||||
#include "llvm/CodeGen/MachineInstr.h"
|
||||
#include "llvm/CodeGen/MachineLoopInfo.h"
|
||||
@ -67,6 +68,7 @@ namespace {
|
||||
MachineRegisterInfo *reginfo_;
|
||||
BitVector allocatableRegs_;
|
||||
LiveIntervals* li_;
|
||||
LiveStacks* ls_;
|
||||
const MachineLoopInfo *loopInfo;
|
||||
|
||||
/// handled_ - Intervals are added to the handled_ set in the order of their
|
||||
@ -103,6 +105,8 @@ namespace {
|
||||
// Make sure PassManager knows which analyses to make available
|
||||
// to coalescing and which analyses coalescing invalidates.
|
||||
AU.addRequiredTransitive<RegisterCoalescer>();
|
||||
AU.addRequired<LiveStacks>();
|
||||
AU.addPreserved<LiveStacks>();
|
||||
AU.addRequired<MachineLoopInfo>();
|
||||
AU.addPreserved<MachineLoopInfo>();
|
||||
AU.addPreservedID(MachineDominatorsID);
|
||||
@ -171,6 +175,9 @@ namespace {
|
||||
char RALinScan::ID = 0;
|
||||
}
|
||||
|
||||
static RegisterPass<RALinScan>
|
||||
X("linearscan-regalloc", "Linear Scan Register Allocator");
|
||||
|
||||
void RALinScan::ComputeRelatedRegClasses() {
|
||||
const TargetRegisterInfo &TRI = *tri_;
|
||||
|
||||
@ -258,6 +265,7 @@ bool RALinScan::runOnMachineFunction(MachineFunction &fn) {
|
||||
reginfo_ = &mf_->getRegInfo();
|
||||
allocatableRegs_ = tri_->getAllocatableSet(fn);
|
||||
li_ = &getAnalysis<LiveIntervals>();
|
||||
ls_ = &getAnalysis<LiveStacks>();
|
||||
loopInfo = &getAnalysis<MachineLoopInfo>();
|
||||
|
||||
// We don't run the coalescer here because we have no reason to
|
||||
@ -504,6 +512,26 @@ static void RevertVectorIteratorsTo(RALinScan::IntervalPtrs &V, unsigned Point){
|
||||
}
|
||||
}
|
||||
|
||||
/// addStackInterval - Create a LiveInterval for stack if the specified live
|
||||
/// interval has been spilled.
|
||||
static void addStackInterval(LiveInterval *cur, LiveStacks *ls_,
|
||||
LiveIntervals *li_, VirtRegMap &vrm_) {
|
||||
int SS = vrm_.getStackSlot(cur->reg);
|
||||
if (SS == VirtRegMap::NO_STACK_SLOT)
|
||||
return;
|
||||
LiveInterval &SI = ls_->getOrCreateInterval(SS);
|
||||
VNInfo *VNI;
|
||||
if (SI.getNumValNums())
|
||||
VNI = SI.getValNumInfo(0);
|
||||
else
|
||||
VNI = SI.getNextValue(~0U, 0, ls_->getVNInfoAllocator());
|
||||
|
||||
LiveInterval &RI = li_->getInterval(cur->reg);
|
||||
// FIXME: This may be overly conservative.
|
||||
SI.MergeRangesInAsValue(RI, VNI);
|
||||
SI.weight += RI.weight;
|
||||
}
|
||||
|
||||
/// assignRegOrStackSlotAtInterval - assign a register if one is available, or
|
||||
/// spill.
|
||||
void RALinScan::assignRegOrStackSlotAtInterval(LiveInterval* cur)
|
||||
@ -717,6 +745,7 @@ void RALinScan::assignRegOrStackSlotAtInterval(LiveInterval* cur)
|
||||
DOUT << "\t\t\tspilling(c): " << *cur << '\n';
|
||||
std::vector<LiveInterval*> added =
|
||||
li_->addIntervalsForSpills(*cur, loopInfo, *vrm_);
|
||||
addStackInterval(cur, ls_, li_, *vrm_);
|
||||
if (added.empty())
|
||||
return; // Early exit if all spills were folded.
|
||||
|
||||
@ -769,6 +798,7 @@ void RALinScan::assignRegOrStackSlotAtInterval(LiveInterval* cur)
|
||||
earliestStart = std::min(earliestStart, i->first->beginNumber());
|
||||
std::vector<LiveInterval*> newIs =
|
||||
li_->addIntervalsForSpills(*i->first, loopInfo, *vrm_);
|
||||
addStackInterval(i->first, ls_, li_, *vrm_);
|
||||
std::copy(newIs.begin(), newIs.end(), std::back_inserter(added));
|
||||
spilled.insert(reg);
|
||||
}
|
||||
@ -782,6 +812,7 @@ void RALinScan::assignRegOrStackSlotAtInterval(LiveInterval* cur)
|
||||
earliestStart = std::min(earliestStart, i->first->beginNumber());
|
||||
std::vector<LiveInterval*> newIs =
|
||||
li_->addIntervalsForSpills(*i->first, loopInfo, *vrm_);
|
||||
addStackInterval(i->first, ls_, li_, *vrm_);
|
||||
std::copy(newIs.begin(), newIs.end(), std::back_inserter(added));
|
||||
spilled.insert(reg);
|
||||
}
|
||||
|
271
lib/CodeGen/StackSlotColoring.cpp
Normal file
271
lib/CodeGen/StackSlotColoring.cpp
Normal file
@ -0,0 +1,271 @@
|
||||
//===-- StackSlotColoring.cpp - Sinking for machine instructions ----------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements the stack slot coloring pass.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#define DEBUG_TYPE "stackcoloring"
|
||||
#include "llvm/CodeGen/LiveStackAnalysis.h"
|
||||
#include "llvm/CodeGen/MachineFrameInfo.h"
|
||||
#include "llvm/CodeGen/Passes.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/ADT/BitVector.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include <vector>
|
||||
using namespace llvm;
|
||||
|
||||
static cl::opt<bool>
|
||||
DisableSharing("no-stack-slot-sharing",
|
||||
cl::init(false), cl::Hidden,
|
||||
cl::desc("Surpress slot sharing during stack coloring"));
|
||||
|
||||
static cl::opt<int>
|
||||
DeleteLimit("slot-delete-limit", cl::init(-1), cl::Hidden,
|
||||
cl::desc("Stack coloring slot deletion limit"));
|
||||
|
||||
STATISTIC(NumEliminated, "Number of stack slots eliminated due to coloring");
|
||||
|
||||
namespace {
|
||||
class VISIBILITY_HIDDEN StackSlotColoring : public MachineFunctionPass {
|
||||
LiveStacks* LS;
|
||||
MachineFrameInfo *MFI;
|
||||
|
||||
// SSIntervals - Spill slot intervals.
|
||||
std::vector<LiveInterval*> SSIntervals;
|
||||
|
||||
// OrigAlignments - Alignments of stack objects before coloring.
|
||||
SmallVector<unsigned, 16> OrigAlignments;
|
||||
|
||||
// OrigSizes - Sizess of stack objects before coloring.
|
||||
SmallVector<unsigned, 16> OrigSizes;
|
||||
|
||||
// AllColors - If index is set, it's a spill slot, i.e. color.
|
||||
// FIXME: This assumes PEI locate spill slot with smaller indices
|
||||
// closest to stack pointer / frame pointer. Therefore, smaller
|
||||
// index == better color.
|
||||
BitVector AllColors;
|
||||
|
||||
// NextColor - Next "color" that's not yet used.
|
||||
int NextColor;
|
||||
|
||||
// UsedColors - "Colors" that have been assigned.
|
||||
BitVector UsedColors;
|
||||
|
||||
// Assignments - Color to intervals mapping.
|
||||
SmallVector<SmallVector<LiveInterval*,4>,16> Assignments;
|
||||
|
||||
public:
|
||||
static char ID; // Pass identification
|
||||
StackSlotColoring() : MachineFunctionPass((intptr_t)&ID), NextColor(-1) {}
|
||||
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.addRequired<LiveStacks>();
|
||||
MachineFunctionPass::getAnalysisUsage(AU);
|
||||
}
|
||||
|
||||
virtual bool runOnMachineFunction(MachineFunction &MF);
|
||||
virtual const char* getPassName() const {
|
||||
return "Stack Slot Coloring";
|
||||
}
|
||||
|
||||
private:
|
||||
bool InitializeSlots();
|
||||
bool OverlapWithAssignments(LiveInterval *li, int Color) const;
|
||||
int ColorSlot(LiveInterval *li);
|
||||
bool ColorSlots(MachineFunction &MF);
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
char StackSlotColoring::ID = 0;
|
||||
|
||||
static RegisterPass<StackSlotColoring>
|
||||
X("stack-slot-coloring", "Stack Slot Coloring");
|
||||
|
||||
FunctionPass *llvm::createStackSlotColoringPass() {
|
||||
return new StackSlotColoring();
|
||||
}
|
||||
|
||||
namespace {
|
||||
// IntervalSorter - Comparison predicate that sort live intervals by
|
||||
// their weight.
|
||||
struct IntervalSorter {
|
||||
bool operator()(LiveInterval* LHS, LiveInterval* RHS) const {
|
||||
return LHS->weight > RHS->weight;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// InitializeSlots - Process all spill stack slot liveintervals and add them
|
||||
/// to a sorted (by weight) list.
|
||||
bool StackSlotColoring::InitializeSlots() {
|
||||
if (LS->getNumIntervals() < 2)
|
||||
return false;
|
||||
|
||||
int LastFI = MFI->getObjectIndexEnd();
|
||||
OrigAlignments.resize(LastFI);
|
||||
OrigSizes.resize(LastFI);
|
||||
AllColors.resize(LastFI);
|
||||
UsedColors.resize(LastFI);
|
||||
Assignments.resize(LastFI);
|
||||
|
||||
// Gather all spill slots into a list.
|
||||
for (LiveStacks::iterator i = LS->begin(), e = LS->end(); i != e; ++i) {
|
||||
LiveInterval &li = i->second;
|
||||
int FI = li.getStackSlotIndex();
|
||||
if (MFI->isDeadObjectIndex(FI))
|
||||
continue;
|
||||
SSIntervals.push_back(&li);
|
||||
OrigAlignments[FI] = MFI->getObjectAlignment(FI);
|
||||
OrigSizes[FI] = MFI->getObjectSize(FI);
|
||||
AllColors.set(FI);
|
||||
}
|
||||
|
||||
// Sort them by weight.
|
||||
std::stable_sort(SSIntervals.begin(), SSIntervals.end(), IntervalSorter());
|
||||
|
||||
// Get first "color".
|
||||
NextColor = AllColors.find_first();
|
||||
return true;
|
||||
}
|
||||
|
||||
/// OverlapWithAssignments - Return true if LiveInterval overlaps with any
|
||||
/// LiveIntervals that have already been assigned to the specified color.
|
||||
bool
|
||||
StackSlotColoring::OverlapWithAssignments(LiveInterval *li, int Color) const {
|
||||
const SmallVector<LiveInterval*,4> &OtherLIs = Assignments[Color];
|
||||
for (unsigned i = 0, e = OtherLIs.size(); i != e; ++i) {
|
||||
LiveInterval *OtherLI = OtherLIs[i];
|
||||
if (OtherLI->overlaps(*li))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// ColorSlot - Assign a "color" (stack slot) to the specified stack slot.
|
||||
///
|
||||
int StackSlotColoring::ColorSlot(LiveInterval *li) {
|
||||
int Color = -1;
|
||||
bool Share = false;
|
||||
if (!DisableSharing &&
|
||||
(DeleteLimit == -1 || (int)NumEliminated < DeleteLimit)) {
|
||||
// Check if it's possible to reuse any of the used colors.
|
||||
Color = UsedColors.find_first();
|
||||
while (Color != -1) {
|
||||
if (!OverlapWithAssignments(li, Color)) {
|
||||
Share = true;
|
||||
++NumEliminated;
|
||||
break;
|
||||
}
|
||||
Color = UsedColors.find_next(Color);
|
||||
}
|
||||
}
|
||||
|
||||
// Assign it to the first available color (assumed to be the best) if it's
|
||||
// not possible to share a used color with other objects.
|
||||
if (!Share) {
|
||||
assert(NextColor != -1 && "No more spill slots?");
|
||||
Color = NextColor;
|
||||
UsedColors.set(Color);
|
||||
NextColor = AllColors.find_next(NextColor);
|
||||
}
|
||||
|
||||
// Record the assignment.
|
||||
Assignments[Color].push_back(li);
|
||||
int FI = li->getStackSlotIndex();
|
||||
DOUT << "Assigning fi #" << FI << " to fi #" << Color << "\n";
|
||||
|
||||
// Change size and alignment of the allocated slot. If there are multiple
|
||||
// objects sharing the same slot, then make sure the size and alignment
|
||||
// are large enough for all.
|
||||
unsigned Align = OrigAlignments[FI];
|
||||
if (!Share || Align > MFI->getObjectAlignment(Color))
|
||||
MFI->setObjectAlignment(Color, Align);
|
||||
int64_t Size = OrigSizes[FI];
|
||||
if (!Share || Size > MFI->getObjectSize(Color))
|
||||
MFI->setObjectSize(Color, Size);
|
||||
return Color;
|
||||
}
|
||||
|
||||
/// Colorslots - Color all spill stack slots and rewrite all frameindex machine
|
||||
/// operands in the function.
|
||||
bool StackSlotColoring::ColorSlots(MachineFunction &MF) {
|
||||
unsigned NumObjs = MFI->getObjectIndexEnd();
|
||||
std::vector<int> SlotMapping(NumObjs, -1);
|
||||
SlotMapping.resize(NumObjs, -1);
|
||||
|
||||
bool Changed = false;
|
||||
for (unsigned i = 0, e = SSIntervals.size(); i != e; ++i) {
|
||||
LiveInterval *li = SSIntervals[i];
|
||||
int SS = li->getStackSlotIndex();
|
||||
int NewSS = ColorSlot(li);
|
||||
SlotMapping[SS] = NewSS;
|
||||
Changed |= (SS != NewSS);
|
||||
}
|
||||
|
||||
if (!Changed)
|
||||
return false;
|
||||
|
||||
// Rewrite all MO_FrameIndex operands.
|
||||
// FIXME: Need the equivalent of MachineRegisterInfo for frameindex operands.
|
||||
for (MachineFunction::iterator MBB = MF.begin(), E = MF.end();
|
||||
MBB != E; ++MBB) {
|
||||
for (MachineBasicBlock::iterator MII = MBB->begin(), EE = MBB->end();
|
||||
MII != EE; ++MII) {
|
||||
MachineInstr &MI = *MII;
|
||||
for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
|
||||
MachineOperand &MO = MI.getOperand(i);
|
||||
if (!MO.isFrameIndex())
|
||||
continue;
|
||||
int FI = MO.getIndex();
|
||||
if (FI < 0)
|
||||
continue;
|
||||
FI = SlotMapping[FI];
|
||||
if (FI == -1)
|
||||
continue;
|
||||
MO.setIndex(FI);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Delete unused stack slots.
|
||||
while (NextColor != -1) {
|
||||
DOUT << "Removing unused stack object fi #" << NextColor << "\n";
|
||||
MFI->RemoveStackObject(NextColor);
|
||||
NextColor = AllColors.find_next(NextColor);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool StackSlotColoring::runOnMachineFunction(MachineFunction &MF) {
|
||||
DOUT << "******** Stack Slot Coloring ********\n";
|
||||
|
||||
MFI = MF.getFrameInfo();
|
||||
LS = &getAnalysis<LiveStacks>();
|
||||
|
||||
bool Changed = false;
|
||||
if (InitializeSlots())
|
||||
Changed = ColorSlots(MF);
|
||||
|
||||
NextColor = -1;
|
||||
SSIntervals.clear();
|
||||
OrigAlignments.clear();
|
||||
OrigSizes.clear();
|
||||
AllColors.clear();
|
||||
UsedColors.clear();
|
||||
for (unsigned i = 0, e = Assignments.size(); i != e; ++i)
|
||||
Assignments[i].clear();
|
||||
Assignments.clear();
|
||||
|
||||
return Changed;
|
||||
}
|
Loading…
Reference in New Issue
Block a user