various cleanups and code simplification

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@120454 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2010-11-30 19:48:15 +00:00
parent e3c611085e
commit 83d6759403

View File

@ -400,104 +400,88 @@ bool DSE::handleEndBlock(BasicBlock &BB) {
bool MadeChange = false; bool MadeChange = false;
// Pointers alloca'd in this function are dead in the end block // Pointers alloca'd in this function are dead in the end block
SmallPtrSet<Value*, 64> deadPointers; SmallPtrSet<Value*, 64> DeadPointers;
// Find all of the alloca'd pointers in the entry block. // Find all of the alloca'd pointers in the entry block.
BasicBlock *Entry = BB.getParent()->begin(); BasicBlock *Entry = BB.getParent()->begin();
for (BasicBlock::iterator I = Entry->begin(), E = Entry->end(); I != E; ++I) for (BasicBlock::iterator I = Entry->begin(), E = Entry->end(); I != E; ++I)
if (AllocaInst *AI = dyn_cast<AllocaInst>(I)) if (AllocaInst *AI = dyn_cast<AllocaInst>(I))
deadPointers.insert(AI); DeadPointers.insert(AI);
// Treat byval arguments the same, stores to them are dead at the end of the // Treat byval arguments the same, stores to them are dead at the end of the
// function. // function.
for (Function::arg_iterator AI = BB.getParent()->arg_begin(), for (Function::arg_iterator AI = BB.getParent()->arg_begin(),
AE = BB.getParent()->arg_end(); AI != AE; ++AI) AE = BB.getParent()->arg_end(); AI != AE; ++AI)
if (AI->hasByValAttr()) if (AI->hasByValAttr())
deadPointers.insert(AI); DeadPointers.insert(AI);
// Scan the basic block backwards // Scan the basic block backwards
for (BasicBlock::iterator BBI = BB.end(); BBI != BB.begin(); ){ for (BasicBlock::iterator BBI = BB.end(); BBI != BB.begin(); ){
--BBI; --BBI;
// If we find a store whose pointer is dead. // If we find a store, check to see if it points into a dead stack value.
if (hasMemoryWrite(BBI)) { if (hasMemoryWrite(BBI) && isRemovable(BBI)) {
if (isRemovable(BBI)) { // See through pointer-to-pointer bitcasts
// See through pointer-to-pointer bitcasts Value *Pointer = getPointerOperand(BBI)->getUnderlyingObject();
Value *pointerOperand = getPointerOperand(BBI)->getUnderlyingObject();
// Alloca'd pointers or byval arguments (which are functionally like // Alloca'd pointers or byval arguments (which are functionally like
// alloca's) are valid candidates for removal. // alloca's) are valid candidates for removal.
if (deadPointers.count(pointerOperand)) { if (DeadPointers.count(Pointer)) {
// DCE instructions only used to calculate that store. // DCE instructions only used to calculate that store.
Instruction *Dead = BBI; Instruction *Dead = BBI++;
++BBI; DeleteDeadInstruction(Dead, &DeadPointers);
DeleteDeadInstruction(Dead, &deadPointers); ++NumFastStores;
++NumFastStores; MadeChange = true;
MadeChange = true;
continue;
}
}
// Because a memcpy or memmove is also a load, we can't skip it if we
// didn't remove it.
if (!isa<MemTransferInst>(BBI))
continue; continue;
}
} }
Value *killPointer = 0; // Remove any dead non-memory-mutating instructions.
uint64_t killPointerSize = AliasAnalysis::UnknownSize; if (isInstructionTriviallyDead(BBI)) {
Instruction *Inst = BBI++;
DeleteDeadInstruction(Inst, &DeadPointers);
++NumFastOther;
MadeChange = true;
continue;
}
if (AllocaInst *A = dyn_cast<AllocaInst>(BBI)) {
DeadPointers.erase(A);
continue;
}
Value *KillPointer = 0;
uint64_t KillPointerSize = AliasAnalysis::UnknownSize;
// If we encounter a use of the pointer, it is no longer considered dead // If we encounter a use of the pointer, it is no longer considered dead
if (LoadInst *L = dyn_cast<LoadInst>(BBI)) { if (LoadInst *L = dyn_cast<LoadInst>(BBI)) {
// However, if this load is unused and not volatile, we can go ahead and KillPointer = L->getPointerOperand();
// remove it, and not have to worry about it making our pointer undead!
if (L->use_empty() && !L->isVolatile()) {
++BBI;
DeleteDeadInstruction(L, &deadPointers);
++NumFastOther;
MadeChange = true;
continue;
}
killPointer = L->getPointerOperand();
} else if (VAArgInst *V = dyn_cast<VAArgInst>(BBI)) { } else if (VAArgInst *V = dyn_cast<VAArgInst>(BBI)) {
killPointer = V->getOperand(0); KillPointer = V->getOperand(0);
} else if (isa<MemTransferInst>(BBI) && } else if (MemTransferInst *MTI = dyn_cast<MemTransferInst>(BBI)) {
isa<ConstantInt>(cast<MemTransferInst>(BBI)->getLength())) { KillPointer = cast<MemTransferInst>(BBI)->getSource();
killPointer = cast<MemTransferInst>(BBI)->getSource(); if (ConstantInt *Len = dyn_cast<ConstantInt>(MTI->getLength()))
killPointerSize = cast<ConstantInt>( KillPointerSize = Len->getZExtValue();
cast<MemTransferInst>(BBI)->getLength())->getZExtValue();
} else if (AllocaInst *A = dyn_cast<AllocaInst>(BBI)) {
deadPointers.erase(A);
// Dead alloca's can be DCE'd when we reach them
if (A->use_empty()) {
++BBI;
DeleteDeadInstruction(A, &deadPointers);
++NumFastOther;
MadeChange = true;
}
continue;
} else if (CallSite CS = cast<Value>(BBI)) { } else if (CallSite CS = cast<Value>(BBI)) {
// If this call does not access memory, it can't // If this call does not access memory, it can't be loading any of our
// be undeadifying any of our pointers. // pointers.
if (AA->doesNotAccessMemory(CS)) if (AA->doesNotAccessMemory(CS))
continue; continue;
unsigned modRef = 0; unsigned NumModRef = 0;
unsigned other = 0; unsigned NumOther = 0;
// Remove any pointers made undead by the call from the dead set // Remove any pointers made undead by the call from the dead set
std::vector<Value*> dead; std::vector<Value*> dead;
for (SmallPtrSet<Value*, 64>::iterator I = deadPointers.begin(), for (SmallPtrSet<Value*, 64>::iterator I = DeadPointers.begin(),
E = deadPointers.end(); I != E; ++I) { E = DeadPointers.end(); I != E; ++I) {
// HACK: if we detect that our AA is imprecise, it's not // HACK: if we detect that our AA is imprecise, it's not
// worth it to scan the rest of the deadPointers set. Just // worth it to scan the rest of the deadPointers set. Just
// assume that the AA will return ModRef for everything, and // assume that the AA will return ModRef for everything, and
// go ahead and bail. // go ahead and bail.
if (modRef >= 16 && other == 0) { if (NumModRef >= 16 && NumOther == 0) {
deadPointers.clear(); DeadPointers.clear();
return MadeChange; return MadeChange;
} }
@ -506,9 +490,9 @@ bool DSE::handleEndBlock(BasicBlock &BB) {
AA->getModRefInfo(CS, *I, getPointerSize(*I, *AA)); AA->getModRefInfo(CS, *I, getPointerSize(*I, *AA));
if (A == AliasAnalysis::ModRef) if (A == AliasAnalysis::ModRef)
++modRef; ++NumModRef;
else else
++other; ++NumOther;
if (A == AliasAnalysis::ModRef || A == AliasAnalysis::Ref) if (A == AliasAnalysis::ModRef || A == AliasAnalysis::Ref)
dead.push_back(*I); dead.push_back(*I);
@ -516,27 +500,19 @@ bool DSE::handleEndBlock(BasicBlock &BB) {
for (std::vector<Value*>::iterator I = dead.begin(), E = dead.end(); for (std::vector<Value*>::iterator I = dead.begin(), E = dead.end();
I != E; ++I) I != E; ++I)
deadPointers.erase(*I); DeadPointers.erase(*I);
continue; continue;
} else if (isInstructionTriviallyDead(BBI)) { } else {
// For any non-memory-affecting non-terminators, DCE them as we reach them // Not a loading instruction.
Instruction *Inst = BBI;
++BBI;
DeleteDeadInstruction(Inst, &deadPointers);
++NumFastOther;
MadeChange = true;
continue; continue;
} }
if (!killPointer) KillPointer = KillPointer->getUnderlyingObject();
continue;
killPointer = killPointer->getUnderlyingObject();
// Deal with undead pointers // Deal with undead pointers
MadeChange |= RemoveUndeadPointers(killPointer, killPointerSize, BBI, MadeChange |= RemoveUndeadPointers(KillPointer, KillPointerSize, BBI,
deadPointers); DeadPointers);
} }
return MadeChange; return MadeChange;
@ -546,11 +522,11 @@ bool DSE::handleEndBlock(BasicBlock &BB) {
/// undead when scanning for dead stores to alloca's. /// undead when scanning for dead stores to alloca's.
bool DSE::RemoveUndeadPointers(Value *killPointer, uint64_t killPointerSize, bool DSE::RemoveUndeadPointers(Value *killPointer, uint64_t killPointerSize,
BasicBlock::iterator &BBI, BasicBlock::iterator &BBI,
SmallPtrSet<Value*, 64> &deadPointers) { SmallPtrSet<Value*, 64> &DeadPointers) {
// If the kill pointer can be easily reduced to an alloca, // If the kill pointer can be easily reduced to an alloca,
// don't bother doing extraneous AA queries. // don't bother doing extraneous AA queries.
if (deadPointers.count(killPointer)) { if (DeadPointers.count(killPointer)) {
deadPointers.erase(killPointer); DeadPointers.erase(killPointer);
return false; return false;
} }
@ -562,8 +538,8 @@ bool DSE::RemoveUndeadPointers(Value *killPointer, uint64_t killPointerSize,
SmallVector<Value*, 16> undead; SmallVector<Value*, 16> undead;
for (SmallPtrSet<Value*, 64>::iterator I = deadPointers.begin(), for (SmallPtrSet<Value*, 64>::iterator I = DeadPointers.begin(),
E = deadPointers.end(); I != E; ++I) { E = DeadPointers.end(); I != E; ++I) {
// See if this pointer could alias it // See if this pointer could alias it
AliasAnalysis::AliasResult A = AA->alias(*I, getPointerSize(*I, *AA), AliasAnalysis::AliasResult A = AA->alias(*I, getPointerSize(*I, *AA),
killPointer, killPointerSize); killPointer, killPointerSize);
@ -574,7 +550,7 @@ bool DSE::RemoveUndeadPointers(Value *killPointer, uint64_t killPointerSize,
// Remove it! // Remove it!
++BBI; ++BBI;
DeleteDeadInstruction(S, &deadPointers); DeleteDeadInstruction(S, &DeadPointers);
++NumFastStores; ++NumFastStores;
MadeChange = true; MadeChange = true;
@ -587,7 +563,7 @@ bool DSE::RemoveUndeadPointers(Value *killPointer, uint64_t killPointerSize,
for (SmallVector<Value*, 16>::iterator I = undead.begin(), E = undead.end(); for (SmallVector<Value*, 16>::iterator I = undead.begin(), E = undead.end();
I != E; ++I) I != E; ++I)
deadPointers.erase(*I); DeadPointers.erase(*I);
return MadeChange; return MadeChange;
} }