Run proper recursive dead code elimination during coalescing.

Dead copies cause problems because they are trivial to coalesce, but
removing them gived the live range a dangling end point. This patch
enables full dead code elimination which trims live ranges to their uses
so end points don't dangle.

DCE may erase multiple instructions. Put the pointers in an ErasedInstrs
set so we never risk visiting erased instructions in the work list.

There isn't supposed to be any dead copies entering RegisterCoalescer,
but they do slip by as evidenced by test/CodeGen/X86/coalescer-dce.ll.

llvm-svn: 157101
This commit is contained in:
Jakob Stoklund Olesen 2012-05-19 05:25:50 +00:00
parent 6a5bbcc25c
commit 1cb1222e6c
2 changed files with 64 additions and 22 deletions

View File

@ -681,7 +681,10 @@ void ConnectedVNInfoEqClasses::Distribute(LiveInterval *LIV[],
SlotIndex Idx = LIS.getInstructionIndex(MI); SlotIndex Idx = LIS.getInstructionIndex(MI);
Idx = Idx.getRegSlot(MO.isUse()); Idx = Idx.getRegSlot(MO.isUse());
const VNInfo *VNI = LI.getVNInfoAt(Idx); 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); MO.setReg(LIV[getEqClass(VNI)]->reg);
} }

View File

@ -21,29 +21,30 @@
#include "llvm/Pass.h" #include "llvm/Pass.h"
#include "llvm/Value.h" #include "llvm/Value.h"
#include "llvm/CodeGen/LiveIntervalAnalysis.h" #include "llvm/ADT/OwningPtr.h"
#include "llvm/CodeGen/MachineInstr.h" #include "llvm/ADT/STLExtras.h"
#include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/ADT/SmallSet.h"
#include "llvm/Target/TargetInstrInfo.h" #include "llvm/ADT/Statistic.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/CodeGen/LiveIntervalAnalysis.h"
#include "llvm/Analysis/AliasAnalysis.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/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineLoopInfo.h" #include "llvm/CodeGen/MachineLoopInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/Passes.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/CommandLine.h"
#include "llvm/Support/Debug.h" #include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h" #include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/OwningPtr.h" #include "llvm/Target/TargetInstrInfo.h"
#include "llvm/ADT/SmallSet.h" #include "llvm/Target/TargetInstrInfo.h"
#include "llvm/ADT/Statistic.h" #include "llvm/Target/TargetMachine.h"
#include "llvm/ADT/STLExtras.h" #include "llvm/Target/TargetOptions.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include <algorithm> #include <algorithm>
#include <cmath> #include <cmath>
using namespace llvm; using namespace llvm;
@ -67,7 +68,8 @@ VerifyCoalescing("verify-coalescing",
cl::Hidden); cl::Hidden);
namespace { namespace {
class RegisterCoalescer : public MachineFunctionPass { class RegisterCoalescer : public MachineFunctionPass,
private LiveRangeEdit::Delegate {
MachineFunction* MF; MachineFunction* MF;
MachineRegisterInfo* MRI; MachineRegisterInfo* MRI;
const TargetMachine* TM; const TargetMachine* TM;
@ -83,10 +85,6 @@ namespace {
/// ///
SmallPtrSet<MachineInstr*, 32> JoinedCopies; SmallPtrSet<MachineInstr*, 32> JoinedCopies;
/// ReMatCopies - Keep track of copies eliminated due to remat.
///
SmallPtrSet<MachineInstr*, 32> ReMatCopies;
/// ReMatDefs - Keep track of definition instructions which have /// ReMatDefs - Keep track of definition instructions which have
/// been remat'ed. /// been remat'ed.
SmallPtrSet<MachineInstr*, 8> ReMatDefs; SmallPtrSet<MachineInstr*, 8> ReMatDefs;
@ -94,6 +92,19 @@ namespace {
/// WorkList - Copy instructions yet to be coalesced. /// WorkList - Copy instructions yet to be coalesced.
SmallVector<MachineInstr*, 8> WorkList; SmallVector<MachineInstr*, 8> WorkList;
/// ErasedInstrs - Set of instruction pointers that have been erased, and
/// that may be present in WorkList.
SmallPtrSet<MachineInstr*, 8> ErasedInstrs;
/// Dead instructions that are about to be deleted.
SmallVector<MachineInstr*, 8> DeadDefs;
/// Recursively eliminate dead defs in DeadDefs.
void eliminateDeadDefs();
/// LiveRangeEdit callback.
void LRE_WillEraseInstruction(MachineInstr *MI);
/// joinAllIntervals - join compatible live intervals /// joinAllIntervals - join compatible live intervals
void joinAllIntervals(); void joinAllIntervals();
@ -383,6 +394,17 @@ void RegisterCoalescer::markAsJoined(MachineInstr *CopyMI) {
I->setIsUndef(true); I->setIsUndef(true);
} }
void RegisterCoalescer::eliminateDeadDefs() {
SmallVector<LiveInterval*, 8> 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 /// adjustCopiesBackFrom - We found a non-trivially-coalescable copy with IntA
/// being the source and IntB being the dest, thus this defines a value number /// 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, /// 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(); CopyMI->eraseFromParent();
ReMatCopies.insert(CopyMI); ErasedInstrs.insert(CopyMI);
ReMatDefs.insert(DefMI); ReMatDefs.insert(DefMI);
DEBUG(dbgs() << "Remat: " << *NewMI); DEBUG(dbgs() << "Remat: " << *NewMI);
++NumReMats; ++NumReMats;
@ -1025,7 +1047,7 @@ bool RegisterCoalescer::canJoinPhys(CoalescerPair &CP) {
bool RegisterCoalescer::joinCopy(MachineInstr *CopyMI, bool &Again) { bool RegisterCoalescer::joinCopy(MachineInstr *CopyMI, bool &Again) {
Again = false; Again = false;
if (JoinedCopies.count(CopyMI) || ReMatCopies.count(CopyMI)) if (JoinedCopies.count(CopyMI))
return false; // Already done. return false; // Already done.
DEBUG(dbgs() << LIS->getInstructionIndex(CopyMI) << '\t' << *CopyMI); DEBUG(dbgs() << LIS->getInstructionIndex(CopyMI) << '\t' << *CopyMI);
@ -1036,6 +1058,16 @@ bool RegisterCoalescer::joinCopy(MachineInstr *CopyMI, bool &Again) {
return false; 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 they are already joined we continue.
if (CP.getSrcReg() == CP.getDstReg()) { if (CP.getSrcReg() == CP.getDstReg()) {
markAsJoined(CopyMI); markAsJoined(CopyMI);
@ -1542,6 +1574,12 @@ bool RegisterCoalescer::copyCoalesceWorkList(unsigned From) {
for (unsigned i = From, e = WorkList.size(); i != e; ++i) { for (unsigned i = From, e = WorkList.size(); i != e; ++i) {
if (!WorkList[i]) if (!WorkList[i])
continue; 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 Again = false;
bool Success = joinCopy(WorkList[i], Again); bool Success = joinCopy(WorkList[i], Again);
Progress |= Success; Progress |= Success;
@ -1609,9 +1647,10 @@ void RegisterCoalescer::joinAllIntervals() {
void RegisterCoalescer::releaseMemory() { void RegisterCoalescer::releaseMemory() {
JoinedCopies.clear(); JoinedCopies.clear();
ReMatCopies.clear(); ErasedInstrs.clear();
ReMatDefs.clear(); ReMatDefs.clear();
WorkList.clear(); WorkList.clear();
DeadDefs.clear();
} }
bool RegisterCoalescer::runOnMachineFunction(MachineFunction &fn) { bool RegisterCoalescer::runOnMachineFunction(MachineFunction &fn) {