mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-29 13:29:28 +00:00
The old naming scheme (load/use/def/store) can be traced back to an old linear scan article, but the names don't match how slots are actually used. The load and store slots are not needed after the deferred spill code insertion framework was deleted. The use and def slots don't make any sense because we are using half-open intervals as is customary in C code, but the names suggest closed intervals. In reality, these slots were used to distinguish early-clobber defs from normal defs. The new naming scheme also has 4 slots, but the names match how the slots are really used. This is a purely mechanical renaming, but some of the code makes a lot more sense now. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@144503 91177308-0d34-0410-b5e6-96231b3b80d8
828 lines
28 KiB
C++
828 lines
28 KiB
C++
//===-- llvm/CodeGen/Splitter.cpp - Splitter -----------------------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#define DEBUG_TYPE "loopsplitter"
|
|
|
|
#include "Splitter.h"
|
|
|
|
#include "llvm/Module.h"
|
|
#include "llvm/CodeGen/CalcSpillWeights.h"
|
|
#include "llvm/CodeGen/LiveIntervalAnalysis.h"
|
|
#include "llvm/CodeGen/LiveStackAnalysis.h"
|
|
#include "llvm/CodeGen/MachineDominators.h"
|
|
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
|
#include "llvm/CodeGen/MachineFunction.h"
|
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
|
#include "llvm/CodeGen/Passes.h"
|
|
#include "llvm/CodeGen/SlotIndexes.h"
|
|
#include "llvm/Support/Debug.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
#include "llvm/Target/TargetMachine.h"
|
|
#include "llvm/Target/TargetInstrInfo.h"
|
|
|
|
using namespace llvm;
|
|
|
|
char LoopSplitter::ID = 0;
|
|
INITIALIZE_PASS_BEGIN(LoopSplitter, "loop-splitting",
|
|
"Split virtual regists across loop boundaries.", false, false)
|
|
INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)
|
|
INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo)
|
|
INITIALIZE_PASS_DEPENDENCY(SlotIndexes)
|
|
INITIALIZE_PASS_DEPENDENCY(LiveIntervals)
|
|
INITIALIZE_PASS_END(LoopSplitter, "loop-splitting",
|
|
"Split virtual regists across loop boundaries.", false, false)
|
|
|
|
namespace llvm {
|
|
|
|
class StartSlotComparator {
|
|
public:
|
|
StartSlotComparator(LiveIntervals &lis) : lis(lis) {}
|
|
bool operator()(const MachineBasicBlock *mbb1,
|
|
const MachineBasicBlock *mbb2) const {
|
|
return lis.getMBBStartIdx(mbb1) < lis.getMBBStartIdx(mbb2);
|
|
}
|
|
private:
|
|
LiveIntervals &lis;
|
|
};
|
|
|
|
class LoopSplit {
|
|
public:
|
|
LoopSplit(LoopSplitter &ls, LiveInterval &li, MachineLoop &loop)
|
|
: ls(ls), li(li), loop(loop), valid(true), inSplit(false), newLI(0) {
|
|
assert(TargetRegisterInfo::isVirtualRegister(li.reg) &&
|
|
"Cannot split physical registers.");
|
|
}
|
|
|
|
LiveInterval& getLI() const { return li; }
|
|
|
|
MachineLoop& getLoop() const { return loop; }
|
|
|
|
bool isValid() const { return valid; }
|
|
|
|
bool isWorthwhile() const { return valid && (inSplit || !outSplits.empty()); }
|
|
|
|
void invalidate() { valid = false; }
|
|
|
|
void splitIncoming() { inSplit = true; }
|
|
|
|
void splitOutgoing(MachineLoop::Edge &edge) { outSplits.insert(edge); }
|
|
|
|
void addLoopInstr(MachineInstr *i) { loopInstrs.push_back(i); }
|
|
|
|
void apply() {
|
|
assert(valid && "Attempt to apply invalid split.");
|
|
applyIncoming();
|
|
applyOutgoing();
|
|
copyRanges();
|
|
renameInside();
|
|
}
|
|
|
|
private:
|
|
LoopSplitter &ls;
|
|
LiveInterval &li;
|
|
MachineLoop &loop;
|
|
bool valid, inSplit;
|
|
std::set<MachineLoop::Edge> outSplits;
|
|
std::vector<MachineInstr*> loopInstrs;
|
|
|
|
LiveInterval *newLI;
|
|
std::map<VNInfo*, VNInfo*> vniMap;
|
|
|
|
LiveInterval* getNewLI() {
|
|
if (newLI == 0) {
|
|
const TargetRegisterClass *trc = ls.mri->getRegClass(li.reg);
|
|
unsigned vreg = ls.mri->createVirtualRegister(trc);
|
|
newLI = &ls.lis->getOrCreateInterval(vreg);
|
|
}
|
|
return newLI;
|
|
}
|
|
|
|
VNInfo* getNewVNI(VNInfo *oldVNI) {
|
|
VNInfo *newVNI = vniMap[oldVNI];
|
|
|
|
if (newVNI == 0) {
|
|
newVNI = getNewLI()->createValueCopy(oldVNI,
|
|
ls.lis->getVNInfoAllocator());
|
|
vniMap[oldVNI] = newVNI;
|
|
}
|
|
|
|
return newVNI;
|
|
}
|
|
|
|
void applyIncoming() {
|
|
if (!inSplit) {
|
|
return;
|
|
}
|
|
|
|
MachineBasicBlock *preHeader = loop.getLoopPreheader();
|
|
if (preHeader == 0) {
|
|
assert(ls.canInsertPreHeader(loop) &&
|
|
"Can't insert required preheader.");
|
|
preHeader = &ls.insertPreHeader(loop);
|
|
}
|
|
|
|
LiveRange *preHeaderRange =
|
|
ls.lis->findExitingRange(li, preHeader);
|
|
assert(preHeaderRange != 0 && "Range not live into preheader.");
|
|
|
|
// Insert the new copy.
|
|
MachineInstr *copy = BuildMI(*preHeader,
|
|
preHeader->getFirstTerminator(),
|
|
DebugLoc(),
|
|
ls.tii->get(TargetOpcode::COPY))
|
|
.addReg(getNewLI()->reg, RegState::Define)
|
|
.addReg(li.reg, RegState::Kill);
|
|
|
|
ls.lis->InsertMachineInstrInMaps(copy);
|
|
|
|
SlotIndex copyDefIdx = ls.lis->getInstructionIndex(copy).getRegSlot();
|
|
|
|
VNInfo *newVal = getNewVNI(preHeaderRange->valno);
|
|
newVal->def = copyDefIdx;
|
|
newVal->setCopy(copy);
|
|
li.removeRange(copyDefIdx, ls.lis->getMBBEndIdx(preHeader), true);
|
|
|
|
getNewLI()->addRange(LiveRange(copyDefIdx,
|
|
ls.lis->getMBBEndIdx(preHeader),
|
|
newVal));
|
|
}
|
|
|
|
void applyOutgoing() {
|
|
|
|
for (std::set<MachineLoop::Edge>::iterator osItr = outSplits.begin(),
|
|
osEnd = outSplits.end();
|
|
osItr != osEnd; ++osItr) {
|
|
MachineLoop::Edge edge = *osItr;
|
|
MachineBasicBlock *outBlock = edge.second;
|
|
if (ls.isCriticalEdge(edge)) {
|
|
assert(ls.canSplitEdge(edge) && "Unsplitable critical edge.");
|
|
outBlock = &ls.splitEdge(edge, loop);
|
|
}
|
|
LiveRange *outRange = ls.lis->findEnteringRange(li, outBlock);
|
|
assert(outRange != 0 && "No exiting range?");
|
|
|
|
MachineInstr *copy = BuildMI(*outBlock, outBlock->begin(),
|
|
DebugLoc(),
|
|
ls.tii->get(TargetOpcode::COPY))
|
|
.addReg(li.reg, RegState::Define)
|
|
.addReg(getNewLI()->reg, RegState::Kill);
|
|
|
|
ls.lis->InsertMachineInstrInMaps(copy);
|
|
|
|
SlotIndex copyDefIdx = ls.lis->getInstructionIndex(copy).getRegSlot();
|
|
|
|
// Blow away output range definition.
|
|
outRange->valno->def = ls.lis->getInvalidIndex();
|
|
li.removeRange(ls.lis->getMBBStartIdx(outBlock), copyDefIdx);
|
|
|
|
SlotIndex newDefIdx = ls.lis->getMBBStartIdx(outBlock);
|
|
assert(ls.lis->getInstructionFromIndex(newDefIdx) == 0 &&
|
|
"PHI def index points at actual instruction.");
|
|
VNInfo *newVal =
|
|
getNewLI()->getNextValue(newDefIdx, 0, ls.lis->getVNInfoAllocator());
|
|
|
|
getNewLI()->addRange(LiveRange(ls.lis->getMBBStartIdx(outBlock),
|
|
copyDefIdx, newVal));
|
|
|
|
}
|
|
}
|
|
|
|
void copyRange(LiveRange &lr) {
|
|
std::pair<bool, LoopSplitter::SlotPair> lsr =
|
|
ls.getLoopSubRange(lr, loop);
|
|
|
|
if (!lsr.first)
|
|
return;
|
|
|
|
LiveRange loopRange(lsr.second.first, lsr.second.second,
|
|
getNewVNI(lr.valno));
|
|
|
|
li.removeRange(loopRange.start, loopRange.end, true);
|
|
|
|
getNewLI()->addRange(loopRange);
|
|
}
|
|
|
|
void copyRanges() {
|
|
for (std::vector<MachineInstr*>::iterator iItr = loopInstrs.begin(),
|
|
iEnd = loopInstrs.end();
|
|
iItr != iEnd; ++iItr) {
|
|
MachineInstr &instr = **iItr;
|
|
SlotIndex instrIdx = ls.lis->getInstructionIndex(&instr);
|
|
if (instr.modifiesRegister(li.reg, 0)) {
|
|
LiveRange *defRange =
|
|
li.getLiveRangeContaining(instrIdx.getRegSlot());
|
|
if (defRange != 0) // May have caught this already.
|
|
copyRange(*defRange);
|
|
}
|
|
if (instr.readsRegister(li.reg, 0)) {
|
|
LiveRange *useRange =
|
|
li.getLiveRangeContaining(instrIdx.getRegSlot(true));
|
|
if (useRange != 0) { // May have caught this already.
|
|
copyRange(*useRange);
|
|
}
|
|
}
|
|
}
|
|
|
|
for (MachineLoop::block_iterator bbItr = loop.block_begin(),
|
|
bbEnd = loop.block_end();
|
|
bbItr != bbEnd; ++bbItr) {
|
|
MachineBasicBlock &loopBlock = **bbItr;
|
|
LiveRange *enteringRange =
|
|
ls.lis->findEnteringRange(li, &loopBlock);
|
|
if (enteringRange != 0) {
|
|
copyRange(*enteringRange);
|
|
}
|
|
}
|
|
}
|
|
|
|
void renameInside() {
|
|
for (std::vector<MachineInstr*>::iterator iItr = loopInstrs.begin(),
|
|
iEnd = loopInstrs.end();
|
|
iItr != iEnd; ++iItr) {
|
|
MachineInstr &instr = **iItr;
|
|
for (unsigned i = 0; i < instr.getNumOperands(); ++i) {
|
|
MachineOperand &mop = instr.getOperand(i);
|
|
if (mop.isReg() && mop.getReg() == li.reg) {
|
|
mop.setReg(getNewLI()->reg);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
};
|
|
|
|
void LoopSplitter::getAnalysisUsage(AnalysisUsage &au) const {
|
|
au.addRequired<MachineDominatorTree>();
|
|
au.addPreserved<MachineDominatorTree>();
|
|
au.addRequired<MachineLoopInfo>();
|
|
au.addPreserved<MachineLoopInfo>();
|
|
au.addPreservedID(RegisterCoalescerPassID);
|
|
au.addPreserved<CalculateSpillWeights>();
|
|
au.addPreserved<LiveStacks>();
|
|
au.addRequired<SlotIndexes>();
|
|
au.addPreserved<SlotIndexes>();
|
|
au.addRequired<LiveIntervals>();
|
|
au.addPreserved<LiveIntervals>();
|
|
MachineFunctionPass::getAnalysisUsage(au);
|
|
}
|
|
|
|
bool LoopSplitter::runOnMachineFunction(MachineFunction &fn) {
|
|
|
|
mf = &fn;
|
|
mri = &mf->getRegInfo();
|
|
tii = mf->getTarget().getInstrInfo();
|
|
tri = mf->getTarget().getRegisterInfo();
|
|
sis = &getAnalysis<SlotIndexes>();
|
|
lis = &getAnalysis<LiveIntervals>();
|
|
mli = &getAnalysis<MachineLoopInfo>();
|
|
mdt = &getAnalysis<MachineDominatorTree>();
|
|
|
|
fqn = mf->getFunction()->getParent()->getModuleIdentifier() + "." +
|
|
mf->getFunction()->getName().str();
|
|
|
|
dbgs() << "Splitting " << mf->getFunction()->getName() << ".";
|
|
|
|
dumpOddTerminators();
|
|
|
|
// dbgs() << "----------------------------------------\n";
|
|
// lis->dump();
|
|
// dbgs() << "----------------------------------------\n";
|
|
|
|
// std::deque<MachineLoop*> loops;
|
|
// std::copy(mli->begin(), mli->end(), std::back_inserter(loops));
|
|
// dbgs() << "Loops:\n";
|
|
// while (!loops.empty()) {
|
|
// MachineLoop &loop = *loops.front();
|
|
// loops.pop_front();
|
|
// std::copy(loop.begin(), loop.end(), std::back_inserter(loops));
|
|
|
|
// dumpLoopInfo(loop);
|
|
// }
|
|
|
|
//lis->dump();
|
|
//exit(0);
|
|
|
|
// Setup initial intervals.
|
|
for (LiveIntervals::iterator liItr = lis->begin(), liEnd = lis->end();
|
|
liItr != liEnd; ++liItr) {
|
|
LiveInterval *li = liItr->second;
|
|
|
|
if (TargetRegisterInfo::isVirtualRegister(li->reg) &&
|
|
!lis->intervalIsInOneMBB(*li)) {
|
|
intervals.push_back(li);
|
|
}
|
|
}
|
|
|
|
processIntervals();
|
|
|
|
intervals.clear();
|
|
|
|
// dbgs() << "----------------------------------------\n";
|
|
// lis->dump();
|
|
// dbgs() << "----------------------------------------\n";
|
|
|
|
dumpOddTerminators();
|
|
|
|
//exit(1);
|
|
|
|
return false;
|
|
}
|
|
|
|
void LoopSplitter::releaseMemory() {
|
|
fqn.clear();
|
|
intervals.clear();
|
|
loopRangeMap.clear();
|
|
}
|
|
|
|
void LoopSplitter::dumpOddTerminators() {
|
|
for (MachineFunction::iterator bbItr = mf->begin(), bbEnd = mf->end();
|
|
bbItr != bbEnd; ++bbItr) {
|
|
MachineBasicBlock *mbb = &*bbItr;
|
|
MachineBasicBlock *a = 0, *b = 0;
|
|
SmallVector<MachineOperand, 4> c;
|
|
if (tii->AnalyzeBranch(*mbb, a, b, c)) {
|
|
dbgs() << "MBB#" << mbb->getNumber() << " has multiway terminator.\n";
|
|
dbgs() << " Terminators:\n";
|
|
for (MachineBasicBlock::iterator iItr = mbb->begin(), iEnd = mbb->end();
|
|
iItr != iEnd; ++iItr) {
|
|
MachineInstr *instr= &*iItr;
|
|
dbgs() << " " << *instr << "";
|
|
}
|
|
dbgs() << "\n Listed successors: [ ";
|
|
for (MachineBasicBlock::succ_iterator sItr = mbb->succ_begin(), sEnd = mbb->succ_end();
|
|
sItr != sEnd; ++sItr) {
|
|
MachineBasicBlock *succMBB = *sItr;
|
|
dbgs() << succMBB->getNumber() << " ";
|
|
}
|
|
dbgs() << "]\n\n";
|
|
}
|
|
}
|
|
}
|
|
|
|
void LoopSplitter::dumpLoopInfo(MachineLoop &loop) {
|
|
MachineBasicBlock &headerBlock = *loop.getHeader();
|
|
typedef SmallVector<MachineLoop::Edge, 8> ExitEdgesList;
|
|
ExitEdgesList exitEdges;
|
|
loop.getExitEdges(exitEdges);
|
|
|
|
dbgs() << " Header: BB#" << headerBlock.getNumber() << ", Contains: [ ";
|
|
for (std::vector<MachineBasicBlock*>::const_iterator
|
|
subBlockItr = loop.getBlocks().begin(),
|
|
subBlockEnd = loop.getBlocks().end();
|
|
subBlockItr != subBlockEnd; ++subBlockItr) {
|
|
MachineBasicBlock &subBlock = **subBlockItr;
|
|
dbgs() << "BB#" << subBlock.getNumber() << " ";
|
|
}
|
|
dbgs() << "], Exit edges: [ ";
|
|
for (ExitEdgesList::iterator exitEdgeItr = exitEdges.begin(),
|
|
exitEdgeEnd = exitEdges.end();
|
|
exitEdgeItr != exitEdgeEnd; ++exitEdgeItr) {
|
|
MachineLoop::Edge &exitEdge = *exitEdgeItr;
|
|
dbgs() << "(MBB#" << exitEdge.first->getNumber()
|
|
<< ", MBB#" << exitEdge.second->getNumber() << ") ";
|
|
}
|
|
dbgs() << "], Sub-Loop Headers: [ ";
|
|
for (MachineLoop::iterator subLoopItr = loop.begin(),
|
|
subLoopEnd = loop.end();
|
|
subLoopItr != subLoopEnd; ++subLoopItr) {
|
|
MachineLoop &subLoop = **subLoopItr;
|
|
MachineBasicBlock &subLoopBlock = *subLoop.getHeader();
|
|
dbgs() << "BB#" << subLoopBlock.getNumber() << " ";
|
|
}
|
|
dbgs() << "]\n";
|
|
}
|
|
|
|
void LoopSplitter::updateTerminators(MachineBasicBlock &mbb) {
|
|
mbb.updateTerminator();
|
|
|
|
for (MachineBasicBlock::iterator miItr = mbb.begin(), miEnd = mbb.end();
|
|
miItr != miEnd; ++miItr) {
|
|
if (lis->isNotInMIMap(miItr)) {
|
|
lis->InsertMachineInstrInMaps(miItr);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool LoopSplitter::canInsertPreHeader(MachineLoop &loop) {
|
|
MachineBasicBlock *header = loop.getHeader();
|
|
MachineBasicBlock *a = 0, *b = 0;
|
|
SmallVector<MachineOperand, 4> c;
|
|
|
|
for (MachineBasicBlock::pred_iterator pbItr = header->pred_begin(),
|
|
pbEnd = header->pred_end();
|
|
pbItr != pbEnd; ++pbItr) {
|
|
MachineBasicBlock *predBlock = *pbItr;
|
|
if (!!tii->AnalyzeBranch(*predBlock, a, b, c)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
MachineFunction::iterator headerItr(header);
|
|
if (headerItr == mf->begin())
|
|
return true;
|
|
MachineBasicBlock *headerLayoutPred = llvm::prior(headerItr);
|
|
assert(headerLayoutPred != 0 && "Header should have layout pred.");
|
|
|
|
return (!tii->AnalyzeBranch(*headerLayoutPred, a, b, c));
|
|
}
|
|
|
|
MachineBasicBlock& LoopSplitter::insertPreHeader(MachineLoop &loop) {
|
|
assert(loop.getLoopPreheader() == 0 && "Loop already has preheader.");
|
|
|
|
MachineBasicBlock &header = *loop.getHeader();
|
|
|
|
// Save the preds - we'll need to update them once we insert the preheader.
|
|
typedef std::set<MachineBasicBlock*> HeaderPreds;
|
|
HeaderPreds headerPreds;
|
|
|
|
for (MachineBasicBlock::pred_iterator predItr = header.pred_begin(),
|
|
predEnd = header.pred_end();
|
|
predItr != predEnd; ++predItr) {
|
|
if (!loop.contains(*predItr))
|
|
headerPreds.insert(*predItr);
|
|
}
|
|
|
|
assert(!headerPreds.empty() && "No predecessors for header?");
|
|
|
|
//dbgs() << fqn << " MBB#" << header.getNumber() << " inserting preheader...";
|
|
|
|
MachineBasicBlock *preHeader =
|
|
mf->CreateMachineBasicBlock(header.getBasicBlock());
|
|
|
|
assert(preHeader != 0 && "Failed to create pre-header.");
|
|
|
|
mf->insert(header, preHeader);
|
|
|
|
for (HeaderPreds::iterator hpItr = headerPreds.begin(),
|
|
hpEnd = headerPreds.end();
|
|
hpItr != hpEnd; ++hpItr) {
|
|
assert(*hpItr != 0 && "How'd a null predecessor get into this set?");
|
|
MachineBasicBlock &hp = **hpItr;
|
|
hp.ReplaceUsesOfBlockWith(&header, preHeader);
|
|
}
|
|
preHeader->addSuccessor(&header);
|
|
|
|
MachineBasicBlock *oldLayoutPred =
|
|
llvm::prior(MachineFunction::iterator(preHeader));
|
|
if (oldLayoutPred != 0) {
|
|
updateTerminators(*oldLayoutPred);
|
|
}
|
|
|
|
lis->InsertMBBInMaps(preHeader);
|
|
|
|
if (MachineLoop *parentLoop = loop.getParentLoop()) {
|
|
assert(parentLoop->getHeader() != loop.getHeader() &&
|
|
"Parent loop has same header?");
|
|
parentLoop->addBasicBlockToLoop(preHeader, mli->getBase());
|
|
|
|
// Invalidate all parent loop ranges.
|
|
while (parentLoop != 0) {
|
|
loopRangeMap.erase(parentLoop);
|
|
parentLoop = parentLoop->getParentLoop();
|
|
}
|
|
}
|
|
|
|
for (LiveIntervals::iterator liItr = lis->begin(),
|
|
liEnd = lis->end();
|
|
liItr != liEnd; ++liItr) {
|
|
LiveInterval &li = *liItr->second;
|
|
|
|
// Is this safe for physregs?
|
|
// TargetRegisterInfo::isPhysicalRegister(li.reg) ||
|
|
if (!lis->isLiveInToMBB(li, &header))
|
|
continue;
|
|
|
|
if (lis->isLiveInToMBB(li, preHeader)) {
|
|
assert(lis->isLiveOutOfMBB(li, preHeader) &&
|
|
"Range terminates in newly added preheader?");
|
|
continue;
|
|
}
|
|
|
|
bool insertRange = false;
|
|
|
|
for (MachineBasicBlock::pred_iterator predItr = preHeader->pred_begin(),
|
|
predEnd = preHeader->pred_end();
|
|
predItr != predEnd; ++predItr) {
|
|
MachineBasicBlock *predMBB = *predItr;
|
|
if (lis->isLiveOutOfMBB(li, predMBB)) {
|
|
insertRange = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!insertRange)
|
|
continue;
|
|
|
|
SlotIndex newDefIdx = lis->getMBBStartIdx(preHeader);
|
|
assert(lis->getInstructionFromIndex(newDefIdx) == 0 &&
|
|
"PHI def index points at actual instruction.");
|
|
VNInfo *newVal = li.getNextValue(newDefIdx, 0, lis->getVNInfoAllocator());
|
|
li.addRange(LiveRange(lis->getMBBStartIdx(preHeader),
|
|
lis->getMBBEndIdx(preHeader),
|
|
newVal));
|
|
}
|
|
|
|
|
|
//dbgs() << "Dumping SlotIndexes:\n";
|
|
//sis->dump();
|
|
|
|
//dbgs() << "done. (Added MBB#" << preHeader->getNumber() << ")\n";
|
|
|
|
return *preHeader;
|
|
}
|
|
|
|
bool LoopSplitter::isCriticalEdge(MachineLoop::Edge &edge) {
|
|
assert(edge.first->succ_size() > 1 && "Non-sensical edge.");
|
|
if (edge.second->pred_size() > 1)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
bool LoopSplitter::canSplitEdge(MachineLoop::Edge &edge) {
|
|
MachineFunction::iterator outBlockItr(edge.second);
|
|
if (outBlockItr == mf->begin())
|
|
return true;
|
|
MachineBasicBlock *outBlockLayoutPred = llvm::prior(outBlockItr);
|
|
assert(outBlockLayoutPred != 0 && "Should have a layout pred if out!=begin.");
|
|
MachineBasicBlock *a = 0, *b = 0;
|
|
SmallVector<MachineOperand, 4> c;
|
|
return (!tii->AnalyzeBranch(*outBlockLayoutPred, a, b, c) &&
|
|
!tii->AnalyzeBranch(*edge.first, a, b, c));
|
|
}
|
|
|
|
MachineBasicBlock& LoopSplitter::splitEdge(MachineLoop::Edge &edge,
|
|
MachineLoop &loop) {
|
|
|
|
MachineBasicBlock &inBlock = *edge.first;
|
|
MachineBasicBlock &outBlock = *edge.second;
|
|
|
|
assert((inBlock.succ_size() > 1) && (outBlock.pred_size() > 1) &&
|
|
"Splitting non-critical edge?");
|
|
|
|
//dbgs() << fqn << " Splitting edge (MBB#" << inBlock.getNumber()
|
|
// << " -> MBB#" << outBlock.getNumber() << ")...";
|
|
|
|
MachineBasicBlock *splitBlock =
|
|
mf->CreateMachineBasicBlock();
|
|
|
|
assert(splitBlock != 0 && "Failed to create split block.");
|
|
|
|
mf->insert(&outBlock, splitBlock);
|
|
|
|
inBlock.ReplaceUsesOfBlockWith(&outBlock, splitBlock);
|
|
splitBlock->addSuccessor(&outBlock);
|
|
|
|
MachineBasicBlock *oldLayoutPred =
|
|
llvm::prior(MachineFunction::iterator(splitBlock));
|
|
if (oldLayoutPred != 0) {
|
|
updateTerminators(*oldLayoutPred);
|
|
}
|
|
|
|
lis->InsertMBBInMaps(splitBlock);
|
|
|
|
loopRangeMap.erase(&loop);
|
|
|
|
MachineLoop *splitParentLoop = loop.getParentLoop();
|
|
while (splitParentLoop != 0 &&
|
|
!splitParentLoop->contains(&outBlock)) {
|
|
splitParentLoop = splitParentLoop->getParentLoop();
|
|
}
|
|
|
|
if (splitParentLoop != 0) {
|
|
assert(splitParentLoop->contains(&loop) &&
|
|
"Split-block parent doesn't contain original loop?");
|
|
splitParentLoop->addBasicBlockToLoop(splitBlock, mli->getBase());
|
|
|
|
// Invalidate all parent loop ranges.
|
|
while (splitParentLoop != 0) {
|
|
loopRangeMap.erase(splitParentLoop);
|
|
splitParentLoop = splitParentLoop->getParentLoop();
|
|
}
|
|
}
|
|
|
|
|
|
for (LiveIntervals::iterator liItr = lis->begin(),
|
|
liEnd = lis->end();
|
|
liItr != liEnd; ++liItr) {
|
|
LiveInterval &li = *liItr->second;
|
|
bool intersects = lis->isLiveOutOfMBB(li, &inBlock) &&
|
|
lis->isLiveInToMBB(li, &outBlock);
|
|
if (lis->isLiveInToMBB(li, splitBlock)) {
|
|
if (!intersects) {
|
|
li.removeRange(lis->getMBBStartIdx(splitBlock),
|
|
lis->getMBBEndIdx(splitBlock), true);
|
|
}
|
|
} else if (intersects) {
|
|
SlotIndex newDefIdx = lis->getMBBStartIdx(splitBlock);
|
|
assert(lis->getInstructionFromIndex(newDefIdx) == 0 &&
|
|
"PHI def index points at actual instruction.");
|
|
VNInfo *newVal = li.getNextValue(newDefIdx, 0,
|
|
lis->getVNInfoAllocator());
|
|
li.addRange(LiveRange(lis->getMBBStartIdx(splitBlock),
|
|
lis->getMBBEndIdx(splitBlock),
|
|
newVal));
|
|
}
|
|
}
|
|
|
|
//dbgs() << "done. (Added MBB#" << splitBlock->getNumber() << ")\n";
|
|
|
|
return *splitBlock;
|
|
}
|
|
|
|
LoopSplitter::LoopRanges& LoopSplitter::getLoopRanges(MachineLoop &loop) {
|
|
typedef std::set<MachineBasicBlock*, StartSlotComparator> LoopMBBSet;
|
|
LoopRangeMap::iterator lrItr = loopRangeMap.find(&loop);
|
|
if (lrItr == loopRangeMap.end()) {
|
|
LoopMBBSet loopMBBs((StartSlotComparator(*lis)));
|
|
std::copy(loop.block_begin(), loop.block_end(),
|
|
std::inserter(loopMBBs, loopMBBs.begin()));
|
|
|
|
assert(!loopMBBs.empty() && "No blocks in loop?");
|
|
|
|
LoopRanges &loopRanges = loopRangeMap[&loop];
|
|
assert(loopRanges.empty() && "Loop encountered but not processed?");
|
|
SlotIndex oldEnd = lis->getMBBEndIdx(*loopMBBs.begin());
|
|
loopRanges.push_back(
|
|
std::make_pair(lis->getMBBStartIdx(*loopMBBs.begin()),
|
|
lis->getInvalidIndex()));
|
|
for (LoopMBBSet::iterator curBlockItr = llvm::next(loopMBBs.begin()),
|
|
curBlockEnd = loopMBBs.end();
|
|
curBlockItr != curBlockEnd; ++curBlockItr) {
|
|
SlotIndex newStart = lis->getMBBStartIdx(*curBlockItr);
|
|
if (newStart != oldEnd) {
|
|
loopRanges.back().second = oldEnd;
|
|
loopRanges.push_back(std::make_pair(newStart,
|
|
lis->getInvalidIndex()));
|
|
}
|
|
oldEnd = lis->getMBBEndIdx(*curBlockItr);
|
|
}
|
|
|
|
loopRanges.back().second =
|
|
lis->getMBBEndIdx(*llvm::prior(loopMBBs.end()));
|
|
|
|
return loopRanges;
|
|
}
|
|
return lrItr->second;
|
|
}
|
|
|
|
std::pair<bool, LoopSplitter::SlotPair> LoopSplitter::getLoopSubRange(
|
|
const LiveRange &lr,
|
|
MachineLoop &loop) {
|
|
LoopRanges &loopRanges = getLoopRanges(loop);
|
|
LoopRanges::iterator lrItr = loopRanges.begin(),
|
|
lrEnd = loopRanges.end();
|
|
while (lrItr != lrEnd && lr.start >= lrItr->second) {
|
|
++lrItr;
|
|
}
|
|
|
|
if (lrItr == lrEnd) {
|
|
SlotIndex invalid = lis->getInvalidIndex();
|
|
return std::make_pair(false, SlotPair(invalid, invalid));
|
|
}
|
|
|
|
SlotIndex srStart(lr.start < lrItr->first ? lrItr->first : lr.start);
|
|
SlotIndex srEnd(lr.end > lrItr->second ? lrItr->second : lr.end);
|
|
|
|
return std::make_pair(true, SlotPair(srStart, srEnd));
|
|
}
|
|
|
|
void LoopSplitter::dumpLoopRanges(MachineLoop &loop) {
|
|
LoopRanges &loopRanges = getLoopRanges(loop);
|
|
dbgs() << "For loop MBB#" << loop.getHeader()->getNumber() << ", subranges are: [ ";
|
|
for (LoopRanges::iterator lrItr = loopRanges.begin(), lrEnd = loopRanges.end();
|
|
lrItr != lrEnd; ++lrItr) {
|
|
dbgs() << "[" << lrItr->first << ", " << lrItr->second << ") ";
|
|
}
|
|
dbgs() << "]\n";
|
|
}
|
|
|
|
void LoopSplitter::processHeader(LoopSplit &split) {
|
|
MachineBasicBlock &header = *split.getLoop().getHeader();
|
|
//dbgs() << " Processing loop header BB#" << header.getNumber() << "\n";
|
|
|
|
if (!lis->isLiveInToMBB(split.getLI(), &header))
|
|
return; // Not live in, but nothing wrong so far.
|
|
|
|
MachineBasicBlock *preHeader = split.getLoop().getLoopPreheader();
|
|
if (!preHeader) {
|
|
|
|
if (!canInsertPreHeader(split.getLoop())) {
|
|
split.invalidate();
|
|
return; // Couldn't insert a pre-header. Bail on this interval.
|
|
}
|
|
|
|
for (MachineBasicBlock::pred_iterator predItr = header.pred_begin(),
|
|
predEnd = header.pred_end();
|
|
predItr != predEnd; ++predItr) {
|
|
if (lis->isLiveOutOfMBB(split.getLI(), *predItr)) {
|
|
split.splitIncoming();
|
|
break;
|
|
}
|
|
}
|
|
} else if (lis->isLiveOutOfMBB(split.getLI(), preHeader)) {
|
|
split.splitIncoming();
|
|
}
|
|
}
|
|
|
|
void LoopSplitter::processLoopExits(LoopSplit &split) {
|
|
typedef SmallVector<MachineLoop::Edge, 8> ExitEdgesList;
|
|
ExitEdgesList exitEdges;
|
|
split.getLoop().getExitEdges(exitEdges);
|
|
|
|
//dbgs() << " Processing loop exits:\n";
|
|
|
|
for (ExitEdgesList::iterator exitEdgeItr = exitEdges.begin(),
|
|
exitEdgeEnd = exitEdges.end();
|
|
exitEdgeItr != exitEdgeEnd; ++exitEdgeItr) {
|
|
MachineLoop::Edge exitEdge = *exitEdgeItr;
|
|
|
|
LiveRange *outRange =
|
|
split.getLI().getLiveRangeContaining(lis->getMBBStartIdx(exitEdge.second));
|
|
|
|
if (outRange != 0) {
|
|
if (isCriticalEdge(exitEdge) && !canSplitEdge(exitEdge)) {
|
|
split.invalidate();
|
|
return;
|
|
}
|
|
|
|
split.splitOutgoing(exitEdge);
|
|
}
|
|
}
|
|
}
|
|
|
|
void LoopSplitter::processLoopUses(LoopSplit &split) {
|
|
std::set<MachineInstr*> processed;
|
|
|
|
for (MachineRegisterInfo::reg_iterator
|
|
rItr = mri->reg_begin(split.getLI().reg),
|
|
rEnd = mri->reg_end();
|
|
rItr != rEnd; ++rItr) {
|
|
MachineInstr &instr = *rItr;
|
|
if (split.getLoop().contains(&instr) && processed.count(&instr) == 0) {
|
|
split.addLoopInstr(&instr);
|
|
processed.insert(&instr);
|
|
}
|
|
}
|
|
|
|
//dbgs() << " Rewriting reg" << li.reg << " to reg" << newLI->reg
|
|
// << " in blocks [ ";
|
|
//dbgs() << "]\n";
|
|
}
|
|
|
|
bool LoopSplitter::splitOverLoop(LiveInterval &li, MachineLoop &loop) {
|
|
assert(TargetRegisterInfo::isVirtualRegister(li.reg) &&
|
|
"Attempt to split physical register.");
|
|
|
|
LoopSplit split(*this, li, loop);
|
|
processHeader(split);
|
|
if (split.isValid())
|
|
processLoopExits(split);
|
|
if (split.isValid())
|
|
processLoopUses(split);
|
|
if (split.isValid() /* && split.isWorthwhile() */) {
|
|
split.apply();
|
|
DEBUG(dbgs() << "Success.\n");
|
|
return true;
|
|
}
|
|
DEBUG(dbgs() << "Failed.\n");
|
|
return false;
|
|
}
|
|
|
|
void LoopSplitter::processInterval(LiveInterval &li) {
|
|
std::deque<MachineLoop*> loops;
|
|
std::copy(mli->begin(), mli->end(), std::back_inserter(loops));
|
|
|
|
while (!loops.empty()) {
|
|
MachineLoop &loop = *loops.front();
|
|
loops.pop_front();
|
|
DEBUG(
|
|
dbgs() << fqn << " reg" << li.reg << " " << li.weight << " BB#"
|
|
<< loop.getHeader()->getNumber() << " ";
|
|
);
|
|
if (!splitOverLoop(li, loop)) {
|
|
// Couldn't split over outer loop, schedule sub-loops to be checked.
|
|
std::copy(loop.begin(), loop.end(), std::back_inserter(loops));
|
|
}
|
|
}
|
|
}
|
|
|
|
void LoopSplitter::processIntervals() {
|
|
while (!intervals.empty()) {
|
|
LiveInterval &li = *intervals.front();
|
|
intervals.pop_front();
|
|
|
|
assert(!lis->intervalIsInOneMBB(li) &&
|
|
"Single interval in process worklist.");
|
|
|
|
processInterval(li);
|
|
}
|
|
}
|
|
|
|
}
|