Newer
Older
VNInfo* AfterValNo = UpdateRegisterInterval(ValNo,
LIs->getUseIndex(BarrierIdx)+1,
LIs->getDefIndex(RestoreIdx));
// Attempt to renumber the new valno into a new vreg.
RenumberValno(AfterValNo);
Owen Anderson
committed
/// RenumberValno - Split the given valno out into a new vreg, allowing it to
/// be allocated to a different register. This function creates a new vreg,
/// copies the valno and its live ranges over to the new vreg's interval,
/// removes them from the old interval, and rewrites all uses and defs of
/// the original reg to the new vreg within those ranges.
void PreAllocSplitting::RenumberValno(VNInfo* VN) {
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
SmallVector<VNInfo*, 4> Stack;
SmallVector<VNInfo*, 4> VNsToCopy;
Stack.push_back(VN);
// Walk through and copy the valno we care about, and any other valnos
// that are two-address redefinitions of the one we care about. These
// will need to be rewritten as well. We also check for safety of the
// renumbering here, by making sure that none of the valno involved has
// phi kills.
while (!Stack.empty()) {
VNInfo* OldVN = Stack.back();
Stack.pop_back();
// Bail out if we ever encounter a valno that has a PHI kill. We can't
// renumber these.
if (OldVN->hasPHIKill) return;
VNsToCopy.push_back(OldVN);
// Locate two-address redefinitions
for (SmallVector<unsigned, 4>::iterator KI = OldVN->kills.begin(),
KE = OldVN->kills.end(); KI != KE; ++KI) {
MachineInstr* MI = LIs->getInstructionFromIndex(*KI);
//if (!MI) continue;
unsigned DefIdx = MI->findRegisterDefOperandIdx(CurrLI->reg);
if (DefIdx == ~0U) continue;
if (MI->isRegReDefinedByTwoAddr(DefIdx)) {
VNInfo* NextVN =
CurrLI->findDefinedVNInfo(LiveIntervals::getDefIndex(*KI));
Stack.push_back(NextVN);
}
}
}
Owen Anderson
committed
// Create the new vreg
unsigned NewVReg = MRI->createVirtualRegister(MRI->getRegClass(CurrLI->reg));
// Create the new live interval
Owen Anderson
committed
LiveInterval& NewLI = LIs->getOrCreateInterval(NewVReg);
for (SmallVector<VNInfo*, 4>::iterator OI = VNsToCopy.begin(), OE =
VNsToCopy.end(); OI != OE; ++OI) {
VNInfo* OldVN = *OI;
// Copy the valno over
VNInfo* NewVN = NewLI.getNextValue(OldVN->def, OldVN->copy,
LIs->getVNInfoAllocator());
NewLI.copyValNumInfo(NewVN, OldVN);
NewLI.MergeValueInAsValue(*CurrLI, OldVN, NewVN);
// Remove the valno from the old interval
CurrLI->removeValNo(OldVN);
}
Owen Anderson
committed
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
// Rewrite defs and uses. This is done in two stages to avoid invalidating
// the reg_iterator.
SmallVector<std::pair<MachineInstr*, unsigned>, 8> OpsToChange;
for (MachineRegisterInfo::reg_iterator I = MRI->reg_begin(CurrLI->reg),
E = MRI->reg_end(); I != E; ++I) {
MachineOperand& MO = I.getOperand();
unsigned InstrIdx = LIs->getInstructionIndex(&*I);
if ((MO.isUse() && NewLI.liveAt(LiveIntervals::getUseIndex(InstrIdx))) ||
(MO.isDef() && NewLI.liveAt(LiveIntervals::getDefIndex(InstrIdx))))
OpsToChange.push_back(std::make_pair(&*I, I.getOperandNo()));
}
for (SmallVector<std::pair<MachineInstr*, unsigned>, 8>::iterator I =
OpsToChange.begin(), E = OpsToChange.end(); I != E; ++I) {
MachineInstr* Inst = I->first;
unsigned OpIdx = I->second;
MachineOperand& MO = Inst->getOperand(OpIdx);
MO.setReg(NewVReg);
}
NumRenumbers++;
Owen Anderson
committed
}
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
bool PreAllocSplitting::Rematerialize(unsigned vreg, VNInfo* ValNo,
MachineInstr* DefMI,
MachineBasicBlock::iterator RestorePt,
unsigned RestoreIdx,
SmallPtrSet<MachineInstr*, 4>& RefsInMBB) {
MachineBasicBlock& MBB = *RestorePt->getParent();
MachineBasicBlock::iterator KillPt = BarrierMBB->end();
unsigned KillIdx = 0;
if (ValNo->def == ~0U || DefMI->getParent() == BarrierMBB)
KillPt = findSpillPoint(BarrierMBB, Barrier, NULL, RefsInMBB, KillIdx);
else
KillPt = findNextEmptySlot(DefMI->getParent(), DefMI, KillIdx);
if (KillPt == DefMI->getParent()->end())
return false;
TII->reMaterialize(MBB, RestorePt, vreg, DefMI);
LIs->InsertMachineInstrInMaps(prior(RestorePt), RestoreIdx);
if (KillPt->getParent() == BarrierMBB) {
UpdateRegisterInterval(ValNo, LIs->getUseIndex(KillIdx)+1,
LIs->getDefIndex(RestoreIdx));
++NumSplits;
++NumRemats;
return true;
}
RepairLiveInterval(CurrLI, ValNo, DefMI, RestoreIdx);
++NumSplits;
++NumRemats;
Owen Anderson
committed
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
return true;
}
MachineInstr* PreAllocSplitting::FoldSpill(unsigned vreg,
const TargetRegisterClass* RC,
MachineInstr* DefMI,
MachineInstr* Barrier,
MachineBasicBlock* MBB,
int& SS,
SmallPtrSet<MachineInstr*, 4>& RefsInMBB) {
MachineBasicBlock::iterator Pt = MBB->begin();
// Go top down if RefsInMBB is empty.
if (RefsInMBB.empty())
return 0;
MachineBasicBlock::iterator FoldPt = Barrier;
while (&*FoldPt != DefMI && FoldPt != MBB->begin() &&
!RefsInMBB.count(FoldPt))
--FoldPt;
int OpIdx = FoldPt->findRegisterDefOperandIdx(vreg, false);
if (OpIdx == -1)
return 0;
SmallVector<unsigned, 1> Ops;
Ops.push_back(OpIdx);
if (!TII->canFoldMemoryOperand(FoldPt, Ops))
return 0;
DenseMap<unsigned, int>::iterator I = IntervalSSMap.find(vreg);
if (I != IntervalSSMap.end()) {
SS = I->second;
} else {
SS = MFI->CreateStackObject(RC->getSize(), RC->getAlignment());
}
MachineInstr* FMI = TII->foldMemoryOperand(*MBB->getParent(),
FoldPt, Ops, SS);
if (FMI) {
LIs->ReplaceMachineInstrInMaps(FoldPt, FMI);
FMI = MBB->insert(MBB->erase(FoldPt), FMI);
++NumFolds;
IntervalSSMap[vreg] = SS;
CurrSLI = &LSs->getOrCreateInterval(SS);
if (CurrSLI->hasAtLeastOneValue())
CurrSValNo = CurrSLI->getValNumInfo(0);
else
CurrSValNo = CurrSLI->getNextValue(~0U, 0, LSs->getVNInfoAllocator());
}
Owen Anderson
committed
return FMI;
Evan Cheng
committed
/// SplitRegLiveInterval - Split (spill and restore) the given live interval
/// so it would not cross the barrier that's being processed. Shrink wrap
/// (minimize) the live interval to the last uses.
bool PreAllocSplitting::SplitRegLiveInterval(LiveInterval *LI) {
CurrLI = LI;
// Find live range where current interval cross the barrier.
LiveInterval::iterator LR =
CurrLI->FindLiveRangeContaining(LIs->getUseIndex(BarrierIdx));
VNInfo *ValNo = LR->valno;
if (ValNo->def == ~1U) {
// Defined by a dead def? How can this be?
assert(0 && "Val# is defined by a dead def?");
abort();
}
Evan Cheng
committed
MachineInstr *DefMI = (ValNo->def != ~0U)
? LIs->getInstructionFromIndex(ValNo->def) : NULL;
Owen Anderson
committed
// If this would create a new join point, do not split.
if (DefMI && createsNewJoin(LR, DefMI->getParent(), Barrier->getParent()))
return false;
Evan Cheng
committed
// Find all references in the barrier mbb.
SmallPtrSet<MachineInstr*, 4> RefsInMBB;
for (MachineRegisterInfo::reg_iterator I = MRI->reg_begin(CurrLI->reg),
E = MRI->reg_end(); I != E; ++I) {
MachineInstr *RefMI = &*I;
if (RefMI->getParent() == BarrierMBB)
RefsInMBB.insert(RefMI);
}
// Find a point to restore the value after the barrier.
unsigned RestoreIndex;
MachineBasicBlock::iterator RestorePt =
Evan Cheng
committed
findRestorePoint(BarrierMBB, Barrier, LR->end, RefsInMBB, RestoreIndex);
Evan Cheng
committed
if (RestorePt == BarrierMBB->end())
return false;
if (DefMI && LIs->isReMaterializable(*LI, ValNo, DefMI))
if (Rematerialize(LI->reg, ValNo, DefMI, RestorePt,
RestoreIndex, RefsInMBB))
return true;
Evan Cheng
committed
// Add a spill either before the barrier or after the definition.
Evan Cheng
committed
MachineBasicBlock *DefMBB = DefMI ? DefMI->getParent() : NULL;
Evan Cheng
committed
const TargetRegisterClass *RC = MRI->getRegClass(CurrLI->reg);
unsigned SpillIndex = 0;
Evan Cheng
committed
MachineInstr *SpillMI = NULL;
Evan Cheng
committed
if (ValNo->def == ~0U) {
Evan Cheng
committed
// If it's defined by a phi, we must split just before the barrier.
Owen Anderson
committed
if ((SpillMI = FoldSpill(LI->reg, RC, 0, Barrier,
BarrierMBB, SS, RefsInMBB))) {
SpillIndex = LIs->getInstructionIndex(SpillMI);
} else {
MachineBasicBlock::iterator SpillPt =
findSpillPoint(BarrierMBB, Barrier, NULL, RefsInMBB, SpillIndex);
if (SpillPt == BarrierMBB->begin())
return false; // No gap to insert spill.
// Add spill.
SS = CreateSpillStackSlot(CurrLI->reg, RC);
TII->storeRegToStackSlot(*BarrierMBB, SpillPt, CurrLI->reg, true, SS, RC);
SpillMI = prior(SpillPt);
LIs->InsertMachineInstrInMaps(SpillMI, SpillIndex);
}
Evan Cheng
committed
} else if (!IsAvailableInStack(DefMBB, CurrLI->reg, ValNo->def,
RestoreIndex, SpillIndex, SS)) {
Evan Cheng
committed
// If it's already split, just restore the value. There is no need to spill
// the def again.
if (!DefMI)
return false; // Def is dead. Do nothing.
Owen Anderson
committed
if ((SpillMI = FoldSpill(LI->reg, RC, DefMI, Barrier,
BarrierMBB, SS, RefsInMBB))) {
SpillIndex = LIs->getInstructionIndex(SpillMI);
Evan Cheng
committed
} else {
Owen Anderson
committed
// Check if it's possible to insert a spill after the def MI.
MachineBasicBlock::iterator SpillPt;
if (DefMBB == BarrierMBB) {
// Add spill after the def and the last use before the barrier.
SpillPt = findSpillPoint(BarrierMBB, Barrier, DefMI,
RefsInMBB, SpillIndex);
if (SpillPt == DefMBB->begin())
return false; // No gap to insert spill.
} else {
SpillPt = findNextEmptySlot(DefMBB, DefMI, SpillIndex);
if (SpillPt == DefMBB->end())
return false; // No gap to insert spill.
}
// Add spill. The store instruction kills the register if def is before
// the barrier in the barrier block.
SS = CreateSpillStackSlot(CurrLI->reg, RC);
TII->storeRegToStackSlot(*DefMBB, SpillPt, CurrLI->reg,
DefMBB == BarrierMBB, SS, RC);
SpillMI = prior(SpillPt);
LIs->InsertMachineInstrInMaps(SpillMI, SpillIndex);
Evan Cheng
committed
}
Evan Cheng
committed
}
Evan Cheng
committed
// Remember def instruction index to spill index mapping.
if (DefMI && SpillMI)
Def2SpillMap[ValNo->def] = SpillIndex;
Evan Cheng
committed
// Add restore.
TII->loadRegFromStackSlot(*BarrierMBB, RestorePt, CurrLI->reg, SS, RC);
MachineInstr *LoadMI = prior(RestorePt);
LIs->InsertMachineInstrInMaps(LoadMI, RestoreIndex);
// If live interval is spilled in the same block as the barrier, just
// create a hole in the interval.
if (!DefMBB ||
Evan Cheng
committed
(SpillMI && SpillMI->getParent() == BarrierMBB)) {
// Update spill stack slot live interval.
UpdateSpillSlotInterval(ValNo, LIs->getUseIndex(SpillIndex)+1,
LIs->getDefIndex(RestoreIndex));
Evan Cheng
committed
UpdateRegisterInterval(ValNo, LIs->getUseIndex(SpillIndex)+1,
LIs->getDefIndex(RestoreIndex));
++NumSplits;
Evan Cheng
committed
return true;
}
// Update spill stack slot live interval.
Evan Cheng
committed
UpdateSpillSlotInterval(ValNo, LIs->getUseIndex(SpillIndex)+1,
LIs->getDefIndex(RestoreIndex));
RepairLiveInterval(CurrLI, ValNo, DefMI, RestoreIndex);
++NumSplits;
Evan Cheng
committed
return true;
}
/// SplitRegLiveIntervals - Split all register live intervals that cross the
/// barrier that's being processed.
bool
PreAllocSplitting::SplitRegLiveIntervals(const TargetRegisterClass **RCs) {
// First find all the virtual registers whose live intervals are intercepted
// by the current barrier.
SmallVector<LiveInterval*, 8> Intervals;
for (const TargetRegisterClass **RC = RCs; *RC; ++RC) {
if (TII->IgnoreRegisterClassBarriers(*RC))
continue;
Evan Cheng
committed
std::vector<unsigned> &VRs = MRI->getRegClassVirtRegs(*RC);
for (unsigned i = 0, e = VRs.size(); i != e; ++i) {
unsigned Reg = VRs[i];
if (!LIs->hasInterval(Reg))
continue;
LiveInterval *LI = &LIs->getInterval(Reg);
if (LI->liveAt(BarrierIdx) && !Barrier->readsRegister(Reg))
// Virtual register live interval is intercepted by the barrier. We
// should split and shrink wrap its interval if possible.
Intervals.push_back(LI);
}
}
// Process the affected live intervals.
bool Change = false;
while (!Intervals.empty()) {
if (PreSplitLimit != -1 && (int)NumSplits == PreSplitLimit)
break;
Evan Cheng
committed
LiveInterval *LI = Intervals.back();
Intervals.pop_back();
Change |= SplitRegLiveInterval(LI);
}
return Change;
}
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
bool PreAllocSplitting::createsNewJoin(LiveRange* LR,
MachineBasicBlock* DefMBB,
MachineBasicBlock* BarrierMBB) {
if (DefMBB == BarrierMBB)
return false;
if (LR->valno->hasPHIKill)
return false;
unsigned MBBEnd = LIs->getMBBEndIdx(BarrierMBB);
if (LR->end < MBBEnd)
return false;
MachineLoopInfo& MLI = getAnalysis<MachineLoopInfo>();
if (MLI.getLoopFor(DefMBB) != MLI.getLoopFor(BarrierMBB))
return true;
MachineDominatorTree& MDT = getAnalysis<MachineDominatorTree>();
SmallPtrSet<MachineBasicBlock*, 4> Visited;
typedef std::pair<MachineBasicBlock*,
MachineBasicBlock::succ_iterator> ItPair;
SmallVector<ItPair, 4> Stack;
Stack.push_back(std::make_pair(BarrierMBB, BarrierMBB->succ_begin()));
while (!Stack.empty()) {
ItPair P = Stack.back();
Stack.pop_back();
MachineBasicBlock* PredMBB = P.first;
MachineBasicBlock::succ_iterator S = P.second;
if (S == PredMBB->succ_end())
continue;
else if (Visited.count(*S)) {
Stack.push_back(std::make_pair(PredMBB, ++S));
continue;
} else
Owen Anderson
committed
Stack.push_back(std::make_pair(PredMBB, S+1));
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
MachineBasicBlock* MBB = *S;
Visited.insert(MBB);
if (MBB == BarrierMBB)
return true;
MachineDomTreeNode* DefMDTN = MDT.getNode(DefMBB);
MachineDomTreeNode* BarrierMDTN = MDT.getNode(BarrierMBB);
MachineDomTreeNode* MDTN = MDT.getNode(MBB)->getIDom();
while (MDTN) {
if (MDTN == DefMDTN)
return true;
else if (MDTN == BarrierMDTN)
break;
MDTN = MDTN->getIDom();
}
MBBEnd = LIs->getMBBEndIdx(MBB);
if (LR->end > MBBEnd)
Stack.push_back(std::make_pair(MBB, MBB->succ_begin()));
}
return false;
}
bool PreAllocSplitting::runOnMachineFunction(MachineFunction &MF) {
CurrMF = &MF;
TM = &MF.getTarget();
TII = TM->getInstrInfo();
MFI = MF.getFrameInfo();
MRI = &MF.getRegInfo();
LIs = &getAnalysis<LiveIntervals>();
LSs = &getAnalysis<LiveStacks>();
Evan Cheng
committed
bool MadeChange = false;
// Make sure blocks are numbered in order.
MF.RenumberBlocks();
Evan Cheng
committed
MachineBasicBlock *Entry = MF.begin();
SmallPtrSet<MachineBasicBlock*,16> Visited;
for (df_ext_iterator<MachineBasicBlock*, SmallPtrSet<MachineBasicBlock*,16> >
DFI = df_ext_begin(Entry, Visited), E = df_ext_end(Entry, Visited);
DFI != E; ++DFI) {
BarrierMBB = *DFI;
for (MachineBasicBlock::iterator I = BarrierMBB->begin(),
E = BarrierMBB->end(); I != E; ++I) {
Barrier = &*I;
const TargetRegisterClass **BarrierRCs =
Barrier->getDesc().getRegClassBarriers();
if (!BarrierRCs)
continue;
BarrierIdx = LIs->getInstructionIndex(Barrier);
MadeChange |= SplitRegLiveIntervals(BarrierRCs);
}
}
Evan Cheng
committed
return MadeChange;