#include "llvm/CodeGen/RegisterCoalescer.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetOptions.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/ADT/SmallSet.h"
const PassInfo *const llvm::SimpleRegisterCoalescingID = &X;
void SimpleRegisterCoalescing::getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.addRequired<LiveIntervals>();
AU.addPreserved<LiveIntervals>();
+ AU.addRequired<MachineLoopInfo>();
AU.addPreserved<MachineLoopInfo>();
AU.addPreservedID(MachineDominatorsID);
- AU.addPreservedID(PHIEliminationID);
+ if (StrongPHIElim)
+ AU.addPreservedID(StrongPHIEliminationID);
+ else
+ AU.addPreservedID(PHIEliminationID);
AU.addPreservedID(TwoAddressInstructionPassID);
- AU.addRequired<LiveIntervals>();
- AU.addRequired<MachineLoopInfo>();
MachineFunctionPass::getAnalysisUsage(AU);
}
if (ALR == IntA.end()) // Should never happen!
return false;
VNInfo *AValNo = ALR->valno;
+ // If it's re-defined by an early clobber somewhere in the live range, then
+ // it's not safe to eliminate the copy. FIXME: This is a temporary workaround.
+ // See PR3149:
+ // 172 %ECX<def> = MOV32rr %reg1039<kill>
+ // 180 INLINEASM <es:subl $5,$1
+ // sbbl $3,$0>, 10, %EAX<def>, 14, %ECX<earlyclobber,def>, 9, %EAX<kill>,
+ // 36, <fi#0>, 1, %reg0, 0, 9, %ECX<kill>, 36, <fi#1>, 1, %reg0, 0
+ // 188 %EAX<def> = MOV32rr %EAX<kill>
+ // 196 %ECX<def> = MOV32rr %ECX<kill>
+ // 204 %ECX<def> = MOV32rr %ECX<kill>
+ // 212 %EAX<def> = MOV32rr %EAX<kill>
+ // 220 %EAX<def> = MOV32rr %EAX
+ // 228 %reg1039<def> = MOV32rr %ECX<kill>
+ // The early clobber operand ties ECX input to the ECX def.
+ //
+ // The live interval of ECX is represented as this:
+ // %reg20,inf = [46,47:1)[174,230:0) 0@174-(230) 1@46-(47)
+ // The coalescer has no idea there was a def in the middle of [174,230].
+ if (AValNo->redefByEC)
+ return false;
// If AValNo is defined as a copy from IntB, we can potentially process this.
// Get the instruction that defines this value number.
unsigned DefIdx = li_->getDefIndex(CopyIdx);
const LiveRange *DLR= li_->getInterval(DstReg).getLiveRangeContaining(DefIdx);
DLR->valno->copy = NULL;
+ // Don't forget to update sub-register intervals.
+ if (TargetRegisterInfo::isPhysicalRegister(DstReg)) {
+ for (const unsigned* SR = tri_->getSubRegisters(DstReg); *SR; ++SR) {
+ if (!li_->hasInterval(*SR))
+ continue;
+ DLR = li_->getInterval(*SR).getLiveRangeContaining(DefIdx);
+ if (DLR && DLR->valno->copy == CopyMI)
+ DLR->valno->copy = NULL;
+ }
+ }
- MachineBasicBlock::iterator MII = CopyMI;
MachineBasicBlock *MBB = CopyMI->getParent();
+ MachineBasicBlock::iterator MII = next(MachineBasicBlock::iterator(CopyMI));
+ CopyMI->removeFromParent();
tii_->reMaterialize(*MBB, MII, DstReg, DefMI);
MachineInstr *NewMI = prior(MII);
- // CopyMI may have implicit instructions, transfer them over to the newly
+ // CopyMI may have implicit operands, transfer them over to the newly
// rematerialized instruction. And update implicit def interval valnos.
for (unsigned i = CopyMI->getDesc().getNumOperands(),
e = CopyMI->getNumOperands(); i != e; ++i) {
MachineOperand &MO = CopyMI->getOperand(i);
- if (MO.isRegister() && MO.isImplicit())
+ if (MO.isReg() && MO.isImplicit())
NewMI->addOperand(MO);
if (MO.isDef() && li_->hasInterval(MO.getReg())) {
unsigned Reg = MO.getReg();
}
li_->ReplaceMachineInstrInMaps(CopyMI, NewMI);
- CopyMI->eraseFromParent();
+ MBB->getParent()->DeleteMachineInstr(CopyMI);
ReMatCopies.insert(CopyMI);
+ ReMatDefs.insert(DefMI);
++NumReMats;
return true;
}
return false;
}
+/// RemoveDeadDef - If a def of a live interval is now determined dead, remove
+/// the val# it defines. If the live interval becomes empty, remove it as well.
+bool SimpleRegisterCoalescing::RemoveDeadDef(LiveInterval &li,
+ MachineInstr *DefMI) {
+ unsigned DefIdx = li_->getDefIndex(li_->getInstructionIndex(DefMI));
+ LiveInterval::iterator MLR = li.FindLiveRangeContaining(DefIdx);
+ if (DefIdx != MLR->valno->def)
+ return false;
+ li.removeValNo(MLR->valno);
+ return removeIntervalIfEmpty(li, li_, tri_);
+}
+
/// PropagateDeadness - Propagate the dead marker to the instruction which
/// defines the val#.
static void PropagateDeadness(LiveInterval &li, MachineInstr *CopyMI,
// Each use MI may have multiple uses of this register. Change them all.
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
MachineOperand &MO = MI->getOperand(i);
- if (MO.isRegister() && MO.getReg() == li.reg)
+ if (MO.isReg() && MO.getReg() == li.reg)
MO.setReg(DstReg);
}
JoinedCopies.insert(MI);
// optimize for it: if there is more than one value, we merge them all into
// the lowest numbered one, then handle the interval as if we were merging
// with one value number.
- VNInfo *LHSValNo;
+ VNInfo *LHSValNo = NULL;
if (EliminatedLHSVals.size() > 1) {
// Loop through all the equal value numbers merging them into the smallest
// one.
if (!(tii_->isMoveInstr(*MI, SrcReg, DstReg) && SrcReg == DstReg))
for (unsigned i = 0, NumOps = MI->getNumOperands(); i != NumOps; ++i) {
MachineOperand &Use = MI->getOperand(i);
- if (Use.isRegister() && Use.isUse() && Use.getReg() &&
+ if (Use.isReg() && Use.isUse() && Use.getReg() &&
tri_->regsOverlap(Use.getReg(), Reg)) {
UseIdx = e;
return &Use;
void SimpleRegisterCoalescing::releaseMemory() {
JoinedCopies.clear();
ReMatCopies.clear();
+ ReMatDefs.clear();
}
static bool isZeroLengthInterval(LiveInterval *li) {
// Join (coalesce) intervals if requested.
if (EnableJoining) {
joinIntervals();
- DOUT << "********** INTERVALS POST JOINING **********\n";
- for (LiveIntervals::iterator I = li_->begin(), E = li_->end(); I != E; ++I){
- I->second->print(DOUT, tri_);
- DOUT << "\n";
- }
+ DEBUG({
+ DOUT << "********** INTERVALS POST JOINING **********\n";
+ for (LiveIntervals::iterator I = li_->begin(), E = li_->end(); I != E; ++I){
+ I->second->print(DOUT, tri_);
+ DOUT << "\n";
+ }
+ });
}
// Perform a final pass over the instructions and compute spill weights
// and remove identity moves.
+ SmallVector<unsigned, 4> DeadDefs;
for (MachineFunction::iterator mbbi = mf_->begin(), mbbe = mf_->end();
mbbi != mbbe; ++mbbi) {
MachineBasicBlock* mbb = mbbi;
continue;
}
+ // Now check if this is a remat'ed def instruction which is now dead.
+ if (ReMatDefs.count(MI)) {
+ bool isDead = true;
+ for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
+ const MachineOperand &MO = MI->getOperand(i);
+ if (!MO.isReg())
+ continue;
+ unsigned Reg = MO.getReg();
+ if (TargetRegisterInfo::isVirtualRegister(Reg))
+ DeadDefs.push_back(Reg);
+ if (MO.isDead())
+ continue;
+ if (TargetRegisterInfo::isPhysicalRegister(Reg) ||
+ !mri_->use_empty(Reg)) {
+ isDead = false;
+ break;
+ }
+ }
+ if (isDead) {
+ while (!DeadDefs.empty()) {
+ unsigned DeadDef = DeadDefs.back();
+ DeadDefs.pop_back();
+ RemoveDeadDef(li_->getInterval(DeadDef), MI);
+ }
+ li_->RemoveMachineInstrFromMaps(mii);
+ mii = mbbi->erase(mii);
+ continue;
+ } else
+ DeadDefs.clear();
+ }
+
// If the move will be an identity move delete it
- bool isMove = tii_->isMoveInstr(*mii, SrcReg, DstReg);
+ bool isMove = tii_->isMoveInstr(*MI, SrcReg, DstReg);
if (isMove && SrcReg == DstReg) {
if (li_->hasInterval(SrcReg)) {
LiveInterval &RegInt = li_->getInterval(SrcReg);
// If def of this move instruction is dead, remove its live range
// from the dstination register's live interval.
- if (mii->registerDefIsDead(DstReg)) {
- if (!ShortenDeadCopySrcLiveRange(RegInt, mii))
- ShortenDeadCopyLiveRange(RegInt, mii);
+ if (MI->registerDefIsDead(DstReg)) {
+ if (!ShortenDeadCopySrcLiveRange(RegInt, MI))
+ ShortenDeadCopyLiveRange(RegInt, MI);
}
}
- li_->RemoveMachineInstrFromMaps(mii);
+ li_->RemoveMachineInstrFromMaps(MI);
mii = mbbi->erase(mii);
++numPeep;
} else if (!isMove || !TurnCopyIntoImpDef(mii, mbb, DstReg, SrcReg)) {
SmallSet<unsigned, 4> UniqueUses;
- for (unsigned i = 0, e = mii->getNumOperands(); i != e; ++i) {
- const MachineOperand &mop = mii->getOperand(i);
- if (mop.isRegister() && mop.getReg() &&
+ for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
+ const MachineOperand &mop = MI->getOperand(i);
+ if (mop.isReg() && mop.getReg() &&
TargetRegisterInfo::isVirtualRegister(mop.getReg())) {
unsigned reg = mop.getReg();
// Multiple uses of reg by the same instruction. It should not
LI.weight = HUGE_VALF;
else {
bool isLoad = false;
- if (li_->isReMaterializable(LI, isLoad)) {
+ SmallVector<LiveInterval*, 4> SpillIs;
+ if (li_->isReMaterializable(LI, SpillIs, isLoad)) {
// If all of the definitions of the interval are re-materializable,
// it is a preferred candidate for spilling. If non of the defs are
// loads, then it's potentially very cheap to re-materialize.