"llvm/lib/git@repo.hca.bsc.es:rferrer/llvm-epi-0.8.git" did not exist on "a4cfafe31a0d75a491d01096da85f0f3f012ef53"
Newer
Older
//===-------- InlineSpiller.cpp - Insert spills and restores inline -------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// The inline spiller modifies the machine function directly instead of
// inserting spills and restores in VirtRegMap.
//
//===----------------------------------------------------------------------===//
Jakob Stoklund Olesen
committed
#include "LiveRangeEdit.h"
#include "VirtRegMap.h"
#include "llvm/ADT/Statistic.h"
Jakob Stoklund Olesen
committed
#include "llvm/ADT/TinyPtrVector.h"
Jakob Stoklund Olesen
committed
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/CodeGen/LiveIntervalAnalysis.h"
#include "llvm/CodeGen/LiveStackAnalysis.h"
Jakob Stoklund Olesen
committed
#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
Jakob Stoklund Olesen
committed
#include "llvm/CodeGen/MachineLoopInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
STATISTIC(NumSpilledRanges, "Number of spilled live ranges");
STATISTIC(NumSnippets, "Number of spilled snippets");
STATISTIC(NumSpills, "Number of spills inserted");
STATISTIC(NumSpillsRemoved, "Number of spills removed");
STATISTIC(NumReloads, "Number of reloads inserted");
STATISTIC(NumReloadsRemoved, "Number of reloads removed");
STATISTIC(NumFolded, "Number of folded stack accesses");
STATISTIC(NumFoldedLoads, "Number of folded loads");
STATISTIC(NumRemats, "Number of rematerialized defs for spilling");
STATISTIC(NumOmitReloadSpill, "Number of omitted spills of reloads");
STATISTIC(NumHoists, "Number of hoisted spills");
static cl::opt<bool> DisableHoisting("disable-spill-hoist", cl::Hidden,
cl::desc("Disable inline spill hoisting"));
namespace {
class InlineSpiller : public Spiller {
MachineFunctionPass &Pass;
MachineFunction &MF;
LiveIntervals &LIS;
LiveStacks &LSS;
AliasAnalysis *AA;
Jakob Stoklund Olesen
committed
MachineDominatorTree &MDT;
MachineLoopInfo &Loops;
VirtRegMap &VRM;
MachineFrameInfo &MFI;
MachineRegisterInfo &MRI;
const TargetInstrInfo &TII;
const TargetRegisterInfo &TRI;
// Variables that are valid during spill(), but used by multiple methods.
LiveRangeEdit *Edit;
LiveInterval *StackInt;
int StackSlot;
Jakob Stoklund Olesen
committed
unsigned Original;
// All registers to spill to StackSlot, including the main register.
SmallVector<unsigned, 8> RegsToSpill;
// All COPY instructions to/from snippets.
// They are ignored since both operands refer to the same stack slot.
SmallPtrSet<MachineInstr*, 8> SnippetCopies;
Jakob Stoklund Olesen
committed
// Values that failed to remat at some point.
SmallPtrSet<VNInfo*, 8> UsedValues;
Jakob Stoklund Olesen
committed
Jakob Stoklund Olesen
committed
public:
Jakob Stoklund Olesen
committed
// Information about a value that was defined by a copy from a sibling
// register.
struct SibValueInfo {
// True when all reaching defs were reloads: No spill is necessary.
bool AllDefsAreReloads;
Jakob Stoklund Olesen
committed
// True when value is defined by an original PHI not from splitting.
bool DefByOrigPHI;
// True when the COPY defining this value killed its source.
bool KillsSource;
Jakob Stoklund Olesen
committed
// The preferred register to spill.
unsigned SpillReg;
// The value of SpillReg that should be spilled.
VNInfo *SpillVNI;
Jakob Stoklund Olesen
committed
// The block where SpillVNI should be spilled. Currently, this must be the
// block containing SpillVNI->def.
MachineBasicBlock *SpillMBB;
Jakob Stoklund Olesen
committed
// A defining instruction that is not a sibling copy or a reload, or NULL.
// This can be used as a template for rematerialization.
MachineInstr *DefMI;
Jakob Stoklund Olesen
committed
// List of values that depend on this one. These values are actually the
// same, but live range splitting has placed them in different registers,
// or SSA update needed to insert PHI-defs to preserve SSA form. This is
// copies of the current value and phi-kills. Usually only phi-kills cause
// more than one dependent value.
TinyPtrVector<VNInfo*> Deps;
Jakob Stoklund Olesen
committed
SibValueInfo(unsigned Reg, VNInfo *VNI)
: AllDefsAreReloads(true), DefByOrigPHI(false), KillsSource(false),
Jakob Stoklund Olesen
committed
SpillReg(Reg), SpillVNI(VNI), SpillMBB(0), DefMI(0) {}
// Returns true when a def has been found.
bool hasDef() const { return DefByOrigPHI || DefMI; }
Jakob Stoklund Olesen
committed
};
Jakob Stoklund Olesen
committed
private:
Jakob Stoklund Olesen
committed
// Values in RegsToSpill defined by sibling copies.
Jakob Stoklund Olesen
committed
typedef DenseMap<VNInfo*, SibValueInfo> SibValueMap;
SibValueMap SibValues;
// Dead defs generated during spilling.
SmallVector<MachineInstr*, 8> DeadDefs;
Jakob Stoklund Olesen
committed
~InlineSpiller() {}
public:
Jakob Stoklund Olesen
committed
InlineSpiller(MachineFunctionPass &pass,
MachineFunction &mf,
VirtRegMap &vrm)
: Pass(pass),
MF(mf),
LIS(pass.getAnalysis<LiveIntervals>()),
LSS(pass.getAnalysis<LiveStacks>()),
AA(&pass.getAnalysis<AliasAnalysis>()),
Jakob Stoklund Olesen
committed
MDT(pass.getAnalysis<MachineDominatorTree>()),
Loops(pass.getAnalysis<MachineLoopInfo>()),
VRM(vrm),
MFI(*mf.getFrameInfo()),
MRI(mf.getRegInfo()),
TII(*mf.getTarget().getInstrInfo()),
TRI(*mf.getTarget().getRegisterInfo()) {}
Jakob Stoklund Olesen
committed
void spill(LiveRangeEdit &);
Jakob Stoklund Olesen
committed
private:
bool isSnippet(const LiveInterval &SnipLI);
void collectRegsToSpill();
Jakob Stoklund Olesen
committed
bool isRegToSpill(unsigned Reg) {
return std::find(RegsToSpill.begin(),
RegsToSpill.end(), Reg) != RegsToSpill.end();
}
bool isSibling(unsigned Reg);
Jakob Stoklund Olesen
committed
MachineInstr *traceSiblingValue(unsigned, VNInfo*, VNInfo*);
Jakob Stoklund Olesen
committed
void propagateSiblingValue(SibValueMap::iterator, VNInfo *VNI = 0);
Jakob Stoklund Olesen
committed
void analyzeSiblingValues();
Jakob Stoklund Olesen
committed
bool hoistSpill(LiveInterval &SpillLI, MachineInstr *CopyMI);
Jakob Stoklund Olesen
committed
void eliminateRedundantSpills(LiveInterval &LI, VNInfo *VNI);
Jakob Stoklund Olesen
committed
Jakob Stoklund Olesen
committed
void markValueUsed(LiveInterval*, VNInfo*);
bool reMaterializeFor(LiveInterval&, MachineBasicBlock::iterator MI);
Jakob Stoklund Olesen
committed
void reMaterializeAll();
bool coalesceStackAccess(MachineInstr *MI, unsigned Reg);
bool foldMemoryOperand(MachineBasicBlock::iterator MI,
Jakob Stoklund Olesen
committed
const SmallVectorImpl<unsigned> &Ops,
MachineInstr *LoadMI = 0);
Jakob Stoklund Olesen
committed
void insertReload(LiveInterval &NewLI, SlotIndex,
MachineBasicBlock::iterator MI);
void insertSpill(LiveInterval &NewLI, const LiveInterval &OldLI,
Jakob Stoklund Olesen
committed
SlotIndex, MachineBasicBlock::iterator MI);
void spillAroundUses(unsigned Reg);
Jakob Stoklund Olesen
committed
void spillAll();
};
}
namespace llvm {
Jakob Stoklund Olesen
committed
Spiller *createInlineSpiller(MachineFunctionPass &pass,
MachineFunction &mf,
VirtRegMap &vrm) {
return new InlineSpiller(pass, mf, vrm);
//===----------------------------------------------------------------------===//
// Snippets
//===----------------------------------------------------------------------===//
Loading
Loading full blame...