}
static bool CanTurnIntoImplicitDef(MachineInstr *MI, unsigned Reg,
- const TargetInstrInfo *tii_) {
+ unsigned OpIdx, const TargetInstrInfo *tii_){
unsigned SrcReg, DstReg, SrcSubReg, DstSubReg;
if (tii_->isMoveInstr(*MI, SrcReg, DstReg, SrcSubReg, DstSubReg) &&
Reg == SrcReg)
return true;
- if ((MI->getOpcode() == TargetInstrInfo::INSERT_SUBREG ||
- MI->getOpcode() == TargetInstrInfo::SUBREG_TO_REG) &&
- MI->getOperand(2).getReg() == Reg)
+ if (OpIdx == 2 && MI->getOpcode() == TargetInstrInfo::SUBREG_TO_REG)
return true;
- if (MI->getOpcode() == TargetInstrInfo::EXTRACT_SUBREG &&
- MI->getOperand(1).getReg() == Reg)
+ if (OpIdx == 1 && MI->getOpcode() == TargetInstrInfo::EXTRACT_SUBREG)
return true;
return false;
}
if (MI->getOpcode() == TargetInstrInfo::IMPLICIT_DEF) {
unsigned Reg = MI->getOperand(0).getReg();
ImpDefRegs.insert(Reg);
+ if (TargetRegisterInfo::isPhysicalRegister(Reg)) {
+ for (const unsigned *SS = tri_->getSubRegisters(Reg); *SS; ++SS)
+ ImpDefRegs.insert(*SS);
+ }
ImpDefMIs.push_back(MI);
continue;
}
+ if (MI->getOpcode() == TargetInstrInfo::INSERT_SUBREG) {
+ MachineOperand &MO = MI->getOperand(2);
+ if (ImpDefRegs.count(MO.getReg())) {
+ // %reg1032<def> = INSERT_SUBREG %reg1032, undef, 2
+ // This is an identity copy, eliminate it now.
+ if (MO.isKill()) {
+ LiveVariables::VarInfo& vi = lv_->getVarInfo(MO.getReg());
+ vi.removeKill(MI);
+ }
+ MI->eraseFromParent();
+ continue;
+ }
+ }
+
bool ChangedToImpDef = false;
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
MachineOperand& MO = MI->getOperand(i);
if (!ImpDefRegs.count(Reg))
continue;
// Use is a copy, just turn it into an implicit_def.
- if (CanTurnIntoImplicitDef(MI, Reg, tii_)) {
+ if (CanTurnIntoImplicitDef(MI, Reg, i, tii_)) {
bool isKill = MO.isKill();
MI->setDesc(tii_->get(TargetInstrInfo::IMPLICIT_DEF));
for (int j = MI->getNumOperands() - 1, ee = 0; j > ee; --j)
MI->RemoveOperand(j);
- if (isKill)
+ if (isKill) {
ImpDefRegs.erase(Reg);
+ LiveVariables::VarInfo& vi = lv_->getVarInfo(Reg);
+ vi.removeKill(MI);
+ }
ChangedToImpDef = true;
break;
}
return false;
}
-
+#ifndef NDEBUG
static void printRegName(unsigned reg, const TargetRegisterInfo* tri_) {
if (TargetRegisterInfo::isPhysicalRegister(reg))
errs() << tri_->getName(reg);
else
errs() << "%reg" << reg;
}
+#endif
void LiveIntervals::handleVirtualRegisterDef(MachineBasicBlock *mbb,
MachineBasicBlock::iterator mi,
if (interval.empty()) {
// Get the Idx of the defining instructions.
MachineInstrIndex defIndex = getDefIndex(MIIdx);
- // Earlyclobbers move back one.
+ // Earlyclobbers move back one, so that they overlap the live range
+ // of inputs.
if (MO.isEarlyClobber())
defIndex = getUseIndex(MIIdx);
VNInfo *ValNo;
MachineInstrIndex killIdx;
if (vi.Kills[0] != mi)
killIdx = getNextSlot(getUseIndex(getInstructionIndex(vi.Kills[0])));
+ else if (MO.isEarlyClobber())
+ // Earlyclobbers that die in this instruction move up one extra, to
+ // compensate for having the starting point moved back one. This
+ // gets them to overlap the live range of other outputs.
+ killIdx = getNextSlot(getNextSlot(defIndex));
else
killIdx = getNextSlot(defIndex);
MachineInstr *Kill = vi.Kills[i];
MachineInstrIndex killIdx =
getNextSlot(getUseIndex(getInstructionIndex(Kill)));
- LiveRange LR(getMBBStartIdx(Kill->getParent()),
- killIdx, ValNo);
+ LiveRange LR(getMBBStartIdx(Kill->getParent()), killIdx, ValNo);
interval.addRange(LR);
ValNo->addKill(killIdx);
DEBUG(errs() << " +" << LR);
// range covering the def slot.
if (MO.isDead())
interval.addRange(
- LiveRange(RedefIndex, getNextSlot(RedefIndex), OldValNo));
+ LiveRange(RedefIndex, MO.isEarlyClobber() ?
+ getNextSlot(getNextSlot(RedefIndex)) :
+ getNextSlot(RedefIndex), OldValNo));
DEBUG({
errs() << " RESULT: ";
// If it is not used after definition, it is considered dead at
// the instruction defining it. Hence its interval is:
// [defSlot(def), defSlot(def)+1)
+ // For earlyclobbers, the defSlot was pushed back one; the extra
+ // advance below compensates.
if (MO.isDead()) {
DEBUG(errs() << " dead");
- end = getNextSlot(start);
+ if (MO.isEarlyClobber())
+ end = getNextSlot(getNextSlot(start));
+ else
+ end = getNextSlot(start);
goto exit;
}
bool
LiveIntervals::isProfitableToCoalesce(LiveInterval &DstInt, LiveInterval &SrcInt,
SmallVector<MachineInstr*,16> &IdentCopies,
- SmallVector<MachineInstr*,16> &OtherCopies,
- bool &HaveConflict) {
- HaveConflict = false;
-
+ SmallVector<MachineInstr*,16> &OtherCopies) {
+ bool HaveConflict = false;
unsigned NumIdent = 0;
- unsigned NumSources = 0;
for (MachineRegisterInfo::reg_iterator ri = mri_->reg_begin(SrcInt.reg),
re = mri_->reg_end(); ri != re; ++ri) {
MachineOperand &O = ri.getOperand();
if (!O.isDef())
continue;
- ++NumSources;
MachineInstr *MI = &*ri;
unsigned SrcReg, DstReg, SrcSubReg, DstSubReg;
if (!tii_->isMoveInstr(*MI, SrcReg, DstReg, SrcSubReg, DstSubReg))
- continue;
+ return false;
if (SrcReg != DstInt.reg) {
OtherCopies.push_back(MI);
HaveConflict |= DstInt.liveAt(getInstructionIndex(MI));
}
}
- return NumSources >= 5 && (((float)NumIdent) / NumSources) > 0.20F;
+ if (!HaveConflict)
+ return false; // Let coalescer handle it
+ return IdentCopies.size() > OtherCopies.size();
}
void LiveIntervals::performEarlyCoalescing() {
LiveInterval &SrcInt = getInterval(PHISrc);
SmallVector<MachineInstr*, 16> IdentCopies;
SmallVector<MachineInstr*, 16> OtherCopies;
- bool HaveConflict;
- if (!isProfitableToCoalesce(DstInt, SrcInt, IdentCopies, OtherCopies,
- HaveConflict))
+ if (!isProfitableToCoalesce(DstInt, SrcInt, IdentCopies, OtherCopies))
continue;
DEBUG(errs() << "PHI Join: " << *Join);
assert(DstInt.containsOneValue() && "PHI join should have just one val#!");
VNInfo *VNI = DstInt.getValNumInfo(0);
- VNInfo *NewVNI = HaveConflict
- ? 0 : SrcInt.getNextValue(VNI->def, 0, false, VNInfoAllocator);
+
+ // Change the non-identity copies to directly target the phi destination.
+ for (unsigned i = 0, e = OtherCopies.size(); i != e; ++i) {
+ MachineInstr *PHICopy = OtherCopies[i];
+ DEBUG(errs() << "Moving: " << *PHICopy);
+
+ MachineInstrIndex MIIndex = getInstructionIndex(PHICopy);
+ MachineInstrIndex DefIndex = getDefIndex(MIIndex);
+ LiveRange *SLR = SrcInt.getLiveRangeContaining(DefIndex);
+ MachineInstrIndex StartIndex = SLR->start;
+ MachineInstrIndex EndIndex = SLR->end;
+
+ // Delete val# defined by the now identity copy and add the range from
+ // beginning of the mbb to the end of the range.
+ SrcInt.removeValNo(SLR->valno);
+ DEBUG(errs() << " added range [" << StartIndex << ','
+ << EndIndex << "] to reg" << DstInt.reg << '\n');
+ if (DstInt.liveAt(StartIndex))
+ DstInt.removeRange(StartIndex, EndIndex);
+ VNInfo *NewVNI = DstInt.getNextValue(DefIndex, PHICopy, true,
+ VNInfoAllocator);
+ NewVNI->setHasPHIKill(true);
+ DstInt.addRange(LiveRange(StartIndex, EndIndex, NewVNI));
+ for (unsigned j = 0, ee = PHICopy->getNumOperands(); j != ee; ++j) {
+ MachineOperand &MO = PHICopy->getOperand(j);
+ if (!MO.isReg() || MO.getReg() != PHISrc)
+ continue;
+ MO.setReg(PHIDst);
+ }
+ }
+
// Now let's eliminate all the would-be identity copies.
for (unsigned i = 0, e = IdentCopies.size(); i != e; ++i) {
MachineInstr *PHICopy = IdentCopies[i];
DEBUG(errs() << "Coalescing: " << *PHICopy);
- MachineBasicBlock *PHIMBB = PHICopy->getParent();
MachineInstrIndex MIIndex = getInstructionIndex(PHICopy);
MachineInstrIndex DefIndex = getDefIndex(MIIndex);
LiveRange *SLR = SrcInt.getLiveRangeContaining(DefIndex);
- MachineInstrIndex StartIndex = HaveConflict
- ? SLR->start : getMBBStartIdx(PHIMBB);
+ MachineInstrIndex StartIndex = SLR->start;
MachineInstrIndex EndIndex = SLR->end;
// Delete val# defined by the now identity copy and add the range from
// beginning of the mbb to the end of the range.
SrcInt.removeValNo(SLR->valno);
- if (HaveConflict) {
- DEBUG(errs() << " added range [" << StartIndex << ','
- << EndIndex << "] to reg" << DstInt.reg << '\n');
- DstInt.addRange(LiveRange(StartIndex, EndIndex, VNI));
- // FIXME: Update uses of src to dst in this range?
- } else {
- DEBUG(errs() << " added range [" << StartIndex << ','
- << SLR->start << "] to reg" << SrcInt.reg << '\n');
- SrcInt.addRange(LiveRange(StartIndex, EndIndex, NewVNI));
- if (PHICopy->killsRegister(PHIDst))
- EndIndex = DefIndex;
- DstInt.removeRange(StartIndex, EndIndex);
- }
RemoveMachineInstrFromMaps(PHICopy);
PHICopy->eraseFromParent();
+ DEBUG(errs() << " added range [" << StartIndex << ','
+ << EndIndex << "] to reg" << DstInt.reg << '\n');
+ DstInt.addRange(LiveRange(StartIndex, EndIndex, VNI));
}
- if (HaveConflict) {
- // First unset the kill.
- for (unsigned i = 0, e = Join->getNumOperands(); i != e; ++i) {
- MachineOperand &O = Join->getOperand(i);
- if (!O.isReg() || O.getReg() != PHISrc)
- continue;
- if (O.isKill())
- O.setIsKill(false);
- }
- MachineInstrIndex MIIndex = getInstructionIndex(Join);
- MachineInstrIndex UseIndex = getUseIndex(MIIndex);
- MachineInstrIndex DefIndex = getDefIndex(MIIndex);
- LiveRange *SLR = SrcInt.getLiveRangeContaining(UseIndex);
- LiveRange *DLR = DstInt.getLiveRangeContaining(DefIndex);
- SrcInt.addRange(LiveRange(DLR->start, DLR->end, SLR->valno));
- } else {
- SrcInt.MergeValueInAsValue(DstInt, VNI, NewVNI);
-
- // Change all references of phi source to destination.
- for (MachineRegisterInfo::reg_iterator ri = mri_->reg_begin(PHIDst),
- re = mri_->reg_end(); ri != re; ) {
- MachineOperand &O = ri.getOperand();
- ++ri;
- O.setReg(PHISrc);
- }
- removeInterval(DstInt.reg);
- RemoveMachineInstrFromMaps(Join);
- Join->eraseFromParent();
- }
+ // Remove the phi join and update the phi block liveness.
+ MachineInstrIndex MIIndex = getInstructionIndex(Join);
+ MachineInstrIndex UseIndex = getUseIndex(MIIndex);
+ MachineInstrIndex DefIndex = getDefIndex(MIIndex);
+ LiveRange *SLR = SrcInt.getLiveRangeContaining(UseIndex);
+ LiveRange *DLR = DstInt.getLiveRangeContaining(DefIndex);
+ DLR->valno->setCopy(0);
+ DLR->valno->setIsDefAccurate(false);
+ DstInt.addRange(LiveRange(SLR->start, SLR->end, DLR->valno));
+ SrcInt.removeRange(SLR->start, SLR->end);
+ assert(SrcInt.empty());
+ removeInterval(PHISrc);
+ RemoveMachineInstrFromMaps(Join);
+ Join->eraseFromParent();
++numCoalescing;
}