diff --git a/lib/CodeGen/LiveInterval.cpp b/lib/CodeGen/LiveInterval.cpp index aa44d3738ed..010ef48f5cd 100644 --- a/lib/CodeGen/LiveInterval.cpp +++ b/lib/CodeGen/LiveInterval.cpp @@ -681,7 +681,10 @@ void ConnectedVNInfoEqClasses::Distribute(LiveInterval *LIV[], SlotIndex Idx = LIS.getInstructionIndex(MI); Idx = Idx.getRegSlot(MO.isUse()); const VNInfo *VNI = LI.getVNInfoAt(Idx); - assert(VNI && "Interval not live at use."); + // FIXME: We should be able to assert(VNI) here, but the coalescer leaves + // dangling defs around. + if (!VNI) + continue; MO.setReg(LIV[getEqClass(VNI)]->reg); } diff --git a/lib/CodeGen/RegisterCoalescer.cpp b/lib/CodeGen/RegisterCoalescer.cpp index 8f4a10c8089..84fd590f268 100644 --- a/lib/CodeGen/RegisterCoalescer.cpp +++ b/lib/CodeGen/RegisterCoalescer.cpp @@ -21,29 +21,30 @@ #include "llvm/Pass.h" #include "llvm/Value.h" -#include "llvm/CodeGen/LiveIntervalAnalysis.h" -#include "llvm/CodeGen/MachineInstr.h" -#include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/Target/TargetInstrInfo.h" -#include "llvm/Target/TargetRegisterInfo.h" -#include "llvm/CodeGen/LiveIntervalAnalysis.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/Statistic.h" #include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/CodeGen/LiveIntervalAnalysis.h" +#include "llvm/CodeGen/LiveIntervalAnalysis.h" +#include "llvm/CodeGen/LiveRangeEdit.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineLoopInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/Passes.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/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/ADT/OwningPtr.h" -#include "llvm/ADT/SmallSet.h" -#include "llvm/ADT/Statistic.h" -#include "llvm/ADT/STLExtras.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Target/TargetRegisterInfo.h" #include #include using namespace llvm; @@ -67,7 +68,8 @@ VerifyCoalescing("verify-coalescing", cl::Hidden); namespace { - class RegisterCoalescer : public MachineFunctionPass { + class RegisterCoalescer : public MachineFunctionPass, + private LiveRangeEdit::Delegate { MachineFunction* MF; MachineRegisterInfo* MRI; const TargetMachine* TM; @@ -83,10 +85,6 @@ namespace { /// SmallPtrSet JoinedCopies; - /// ReMatCopies - Keep track of copies eliminated due to remat. - /// - SmallPtrSet ReMatCopies; - /// ReMatDefs - Keep track of definition instructions which have /// been remat'ed. SmallPtrSet ReMatDefs; @@ -94,6 +92,19 @@ namespace { /// WorkList - Copy instructions yet to be coalesced. SmallVector WorkList; + /// ErasedInstrs - Set of instruction pointers that have been erased, and + /// that may be present in WorkList. + SmallPtrSet ErasedInstrs; + + /// Dead instructions that are about to be deleted. + SmallVector DeadDefs; + + /// Recursively eliminate dead defs in DeadDefs. + void eliminateDeadDefs(); + + /// LiveRangeEdit callback. + void LRE_WillEraseInstruction(MachineInstr *MI); + /// joinAllIntervals - join compatible live intervals void joinAllIntervals(); @@ -383,6 +394,17 @@ void RegisterCoalescer::markAsJoined(MachineInstr *CopyMI) { I->setIsUndef(true); } +void RegisterCoalescer::eliminateDeadDefs() { + SmallVector NewRegs; + LiveRangeEdit(0, NewRegs, *MF, *LIS, 0, this).eliminateDeadDefs(DeadDefs); +} + +// Callback from eliminateDeadDefs(). +void RegisterCoalescer::LRE_WillEraseInstruction(MachineInstr *MI) { + // MI may be in WorkList. Make sure we don't visit it. + ErasedInstrs.insert(MI); +} + /// adjustCopiesBackFrom - We found a non-trivially-coalescable copy with IntA /// being the source and IntB being the dest, thus this defines a value number /// in IntB. If the source value number (in IntA) is defined by a copy from B, @@ -844,7 +866,7 @@ bool RegisterCoalescer::reMaterializeTrivialDef(LiveInterval &SrcInt, } CopyMI->eraseFromParent(); - ReMatCopies.insert(CopyMI); + ErasedInstrs.insert(CopyMI); ReMatDefs.insert(DefMI); DEBUG(dbgs() << "Remat: " << *NewMI); ++NumReMats; @@ -1025,7 +1047,7 @@ bool RegisterCoalescer::canJoinPhys(CoalescerPair &CP) { bool RegisterCoalescer::joinCopy(MachineInstr *CopyMI, bool &Again) { Again = false; - if (JoinedCopies.count(CopyMI) || ReMatCopies.count(CopyMI)) + if (JoinedCopies.count(CopyMI)) return false; // Already done. DEBUG(dbgs() << LIS->getInstructionIndex(CopyMI) << '\t' << *CopyMI); @@ -1036,6 +1058,16 @@ bool RegisterCoalescer::joinCopy(MachineInstr *CopyMI, bool &Again) { return false; } + // Dead code elimination. This really should be handled by MachineDCE, but + // sometimes dead copies slip through, and we can't generate invalid live + // ranges. + if (!CP.isPhys() && CopyMI->allDefsAreDead()) { + DEBUG(dbgs() << "\tCopy is dead.\n"); + DeadDefs.push_back(CopyMI); + eliminateDeadDefs(); + return true; + } + // If they are already joined we continue. if (CP.getSrcReg() == CP.getDstReg()) { markAsJoined(CopyMI); @@ -1542,6 +1574,12 @@ bool RegisterCoalescer::copyCoalesceWorkList(unsigned From) { for (unsigned i = From, e = WorkList.size(); i != e; ++i) { if (!WorkList[i]) continue; + // Skip instruction pointers that have already been erased, for example by + // dead code elimination. + if (ErasedInstrs.erase(WorkList[i])) { + WorkList[i] = 0; + continue; + } bool Again = false; bool Success = joinCopy(WorkList[i], Again); Progress |= Success; @@ -1609,9 +1647,10 @@ void RegisterCoalescer::joinAllIntervals() { void RegisterCoalescer::releaseMemory() { JoinedCopies.clear(); - ReMatCopies.clear(); + ErasedInstrs.clear(); ReMatDefs.clear(); WorkList.clear(); + DeadDefs.clear(); } bool RegisterCoalescer::runOnMachineFunction(MachineFunction &fn) {