mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-29 10:25:12 +00:00
Make DeleteDeadInstruction be a static function, move some code around.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@120471 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -66,8 +66,6 @@ namespace {
|
|||||||
bool handleEndBlock(BasicBlock &BB);
|
bool handleEndBlock(BasicBlock &BB);
|
||||||
void RemoveAccessedObjects(const AliasAnalysis::Location &LoadedLoc,
|
void RemoveAccessedObjects(const AliasAnalysis::Location &LoadedLoc,
|
||||||
SmallPtrSet<Value*, 16> &DeadStackObjects);
|
SmallPtrSet<Value*, 16> &DeadStackObjects);
|
||||||
void DeleteDeadInstruction(Instruction *I,
|
|
||||||
SmallPtrSet<Value*, 16> *deadPointers = 0);
|
|
||||||
|
|
||||||
|
|
||||||
// getAnalysisUsage - We require post dominance frontiers (aka Control
|
// getAnalysisUsage - We require post dominance frontiers (aka Control
|
||||||
@@ -93,6 +91,53 @@ INITIALIZE_PASS_END(DSE, "dse", "Dead Store Elimination", false, false)
|
|||||||
|
|
||||||
FunctionPass *llvm::createDeadStoreEliminationPass() { return new DSE(); }
|
FunctionPass *llvm::createDeadStoreEliminationPass() { return new DSE(); }
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// Helper functions
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
/// DeleteDeadInstruction - Delete this instruction. Before we do, go through
|
||||||
|
/// and zero out all the operands of this instruction. If any of them become
|
||||||
|
/// dead, delete them and the computation tree that feeds them.
|
||||||
|
///
|
||||||
|
/// If ValueSet is non-null, remove any deleted instructions from it as well.
|
||||||
|
///
|
||||||
|
static void DeleteDeadInstruction(Instruction *I,
|
||||||
|
MemoryDependenceAnalysis &MD,
|
||||||
|
SmallPtrSet<Value*, 16> *ValueSet = 0) {
|
||||||
|
SmallVector<Instruction*, 32> NowDeadInsts;
|
||||||
|
|
||||||
|
NowDeadInsts.push_back(I);
|
||||||
|
--NumFastOther;
|
||||||
|
|
||||||
|
// Before we touch this instruction, remove it from memdep!
|
||||||
|
do {
|
||||||
|
Instruction *DeadInst = NowDeadInsts.pop_back_val();
|
||||||
|
++NumFastOther;
|
||||||
|
|
||||||
|
// This instruction is dead, zap it, in stages. Start by removing it from
|
||||||
|
// MemDep, which needs to know the operands and needs it to be in the
|
||||||
|
// function.
|
||||||
|
MD.removeInstruction(DeadInst);
|
||||||
|
|
||||||
|
for (unsigned op = 0, e = DeadInst->getNumOperands(); op != e; ++op) {
|
||||||
|
Value *Op = DeadInst->getOperand(op);
|
||||||
|
DeadInst->setOperand(op, 0);
|
||||||
|
|
||||||
|
// If this operand just became dead, add it to the NowDeadInsts list.
|
||||||
|
if (!Op->use_empty()) continue;
|
||||||
|
|
||||||
|
if (Instruction *OpI = dyn_cast<Instruction>(Op))
|
||||||
|
if (isInstructionTriviallyDead(OpI))
|
||||||
|
NowDeadInsts.push_back(OpI);
|
||||||
|
}
|
||||||
|
|
||||||
|
DeadInst->eraseFromParent();
|
||||||
|
|
||||||
|
if (ValueSet) ValueSet->erase(DeadInst);
|
||||||
|
} while (!NowDeadInsts.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// hasMemoryWrite - Does this instruction write some memory? This only returns
|
/// hasMemoryWrite - Does this instruction write some memory? This only returns
|
||||||
/// true for things that we can analyze with other helpers below.
|
/// true for things that we can analyze with other helpers below.
|
||||||
static bool hasMemoryWrite(Instruction *I) {
|
static bool hasMemoryWrite(Instruction *I) {
|
||||||
@@ -177,21 +222,18 @@ static bool isRemovable(Instruction *I) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// getPointerOperand - Return the pointer that is being written to.
|
/// getStoredPointerOperand - Return the pointer that is being written to.
|
||||||
static Value *getPointerOperand(Instruction *I) {
|
static Value *getStoredPointerOperand(Instruction *I) {
|
||||||
assert(hasMemoryWrite(I));
|
|
||||||
if (StoreInst *SI = dyn_cast<StoreInst>(I))
|
if (StoreInst *SI = dyn_cast<StoreInst>(I))
|
||||||
return SI->getPointerOperand();
|
return SI->getPointerOperand();
|
||||||
if (MemIntrinsic *MI = dyn_cast<MemIntrinsic>(I))
|
if (MemIntrinsic *MI = dyn_cast<MemIntrinsic>(I))
|
||||||
return MI->getArgOperand(0);
|
return MI->getDest();
|
||||||
|
|
||||||
IntrinsicInst *II = cast<IntrinsicInst>(I);
|
IntrinsicInst *II = cast<IntrinsicInst>(I);
|
||||||
switch (II->getIntrinsicID()) {
|
switch (II->getIntrinsicID()) {
|
||||||
default: assert(false && "Unexpected intrinsic!");
|
default: assert(false && "Unexpected intrinsic!");
|
||||||
case Intrinsic::init_trampoline:
|
case Intrinsic::init_trampoline:
|
||||||
return II->getArgOperand(0);
|
return II->getArgOperand(0);
|
||||||
case Intrinsic::lifetime_end:
|
|
||||||
return II->getArgOperand(1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -243,6 +285,11 @@ static bool isCompleteOverwrite(const AliasAnalysis::Location &Later,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// DSE Pass
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
bool DSE::runOnBasicBlock(BasicBlock &BB) {
|
bool DSE::runOnBasicBlock(BasicBlock &BB) {
|
||||||
bool MadeChange = false;
|
bool MadeChange = false;
|
||||||
|
|
||||||
@@ -280,7 +327,7 @@ bool DSE::runOnBasicBlock(BasicBlock &BB) {
|
|||||||
// in case we need it.
|
// in case we need it.
|
||||||
WeakVH NextInst(BBI);
|
WeakVH NextInst(BBI);
|
||||||
|
|
||||||
DeleteDeadInstruction(SI);
|
DeleteDeadInstruction(SI, *MD);
|
||||||
|
|
||||||
if (NextInst == 0) // Next instruction deleted.
|
if (NextInst == 0) // Next instruction deleted.
|
||||||
BBI = BB.begin();
|
BBI = BB.begin();
|
||||||
@@ -318,7 +365,7 @@ bool DSE::runOnBasicBlock(BasicBlock &BB) {
|
|||||||
// store to 'Loc' then we can remove it.
|
// store to 'Loc' then we can remove it.
|
||||||
if (isRemovable(DepWrite) && isCompleteOverwrite(Loc, DepLoc, *AA)) {
|
if (isRemovable(DepWrite) && isCompleteOverwrite(Loc, DepLoc, *AA)) {
|
||||||
// Delete the store and now-dead instructions that feed it.
|
// Delete the store and now-dead instructions that feed it.
|
||||||
DeleteDeadInstruction(DepWrite);
|
DeleteDeadInstruction(DepWrite, *MD);
|
||||||
++NumFastStores;
|
++NumFastStores;
|
||||||
MadeChange = true;
|
MadeChange = true;
|
||||||
|
|
||||||
@@ -367,7 +414,8 @@ bool DSE::HandleFree(CallInst *F) {
|
|||||||
if (!hasMemoryWrite(Dependency) || !isRemovable(Dependency))
|
if (!hasMemoryWrite(Dependency) || !isRemovable(Dependency))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Value *DepPointer = getPointerOperand(Dependency)->getUnderlyingObject();
|
Value *DepPointer =
|
||||||
|
getStoredPointerOperand(Dependency)->getUnderlyingObject();
|
||||||
|
|
||||||
// Check for aliasing.
|
// Check for aliasing.
|
||||||
if (AA->alias(F->getArgOperand(0), 1, DepPointer, 1) !=
|
if (AA->alias(F->getArgOperand(0), 1, DepPointer, 1) !=
|
||||||
@@ -375,7 +423,7 @@ bool DSE::HandleFree(CallInst *F) {
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
// DCE instructions only used to calculate that store
|
// DCE instructions only used to calculate that store
|
||||||
DeleteDeadInstruction(Dependency);
|
DeleteDeadInstruction(Dependency, *MD);
|
||||||
++NumFastStores;
|
++NumFastStores;
|
||||||
|
|
||||||
// Inst's old Dependency is now deleted. Compute the next dependency,
|
// Inst's old Dependency is now deleted. Compute the next dependency,
|
||||||
@@ -422,14 +470,13 @@ bool DSE::handleEndBlock(BasicBlock &BB) {
|
|||||||
// If we find a store, check to see if it points into a dead stack value.
|
// If we find a store, check to see if it points into a dead stack value.
|
||||||
if (hasMemoryWrite(BBI) && isRemovable(BBI)) {
|
if (hasMemoryWrite(BBI) && isRemovable(BBI)) {
|
||||||
// See through pointer-to-pointer bitcasts
|
// See through pointer-to-pointer bitcasts
|
||||||
Value *Pointer = getPointerOperand(BBI)->getUnderlyingObject();
|
Value *Pointer = getStoredPointerOperand(BBI)->getUnderlyingObject();
|
||||||
|
|
||||||
// Alloca'd pointers or byval arguments (which are functionally like
|
// Stores to stack values are valid candidates for removal.
|
||||||
// alloca's) are valid candidates for removal.
|
|
||||||
if (DeadStackObjects.count(Pointer)) {
|
if (DeadStackObjects.count(Pointer)) {
|
||||||
// DCE instructions only used to calculate that store.
|
// DCE instructions only used to calculate that store.
|
||||||
Instruction *Dead = BBI++;
|
Instruction *Dead = BBI++;
|
||||||
DeleteDeadInstruction(Dead, &DeadStackObjects);
|
DeleteDeadInstruction(Dead, *MD, &DeadStackObjects);
|
||||||
++NumFastStores;
|
++NumFastStores;
|
||||||
MadeChange = true;
|
MadeChange = true;
|
||||||
continue;
|
continue;
|
||||||
@@ -439,7 +486,7 @@ bool DSE::handleEndBlock(BasicBlock &BB) {
|
|||||||
// Remove any dead non-memory-mutating instructions.
|
// Remove any dead non-memory-mutating instructions.
|
||||||
if (isInstructionTriviallyDead(BBI)) {
|
if (isInstructionTriviallyDead(BBI)) {
|
||||||
Instruction *Inst = BBI++;
|
Instruction *Inst = BBI++;
|
||||||
DeleteDeadInstruction(Inst, &DeadStackObjects);
|
DeleteDeadInstruction(Inst, *MD, &DeadStackObjects);
|
||||||
++NumFastOther;
|
++NumFastOther;
|
||||||
MadeChange = true;
|
MadeChange = true;
|
||||||
continue;
|
continue;
|
||||||
@@ -553,45 +600,3 @@ void DSE::RemoveAccessedObjects(const AliasAnalysis::Location &LoadedLoc,
|
|||||||
DeadStackObjects.erase(*I);
|
DeadStackObjects.erase(*I);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// DeleteDeadInstruction - Delete this instruction. Before we do, go through
|
|
||||||
/// and zero out all the operands of this instruction. If any of them become
|
|
||||||
/// dead, delete them and the computation tree that feeds them.
|
|
||||||
///
|
|
||||||
/// If ValueSet is non-null, remove any deleted instructions from it as well.
|
|
||||||
///
|
|
||||||
void DSE::DeleteDeadInstruction(Instruction *I,
|
|
||||||
SmallPtrSet<Value*, 16> *ValueSet) {
|
|
||||||
SmallVector<Instruction*, 32> NowDeadInsts;
|
|
||||||
|
|
||||||
NowDeadInsts.push_back(I);
|
|
||||||
--NumFastOther;
|
|
||||||
|
|
||||||
// Before we touch this instruction, remove it from memdep!
|
|
||||||
do {
|
|
||||||
Instruction *DeadInst = NowDeadInsts.pop_back_val();
|
|
||||||
|
|
||||||
++NumFastOther;
|
|
||||||
|
|
||||||
// This instruction is dead, zap it, in stages. Start by removing it from
|
|
||||||
// MemDep, which needs to know the operands and needs it to be in the
|
|
||||||
// function.
|
|
||||||
MD->removeInstruction(DeadInst);
|
|
||||||
|
|
||||||
for (unsigned op = 0, e = DeadInst->getNumOperands(); op != e; ++op) {
|
|
||||||
Value *Op = DeadInst->getOperand(op);
|
|
||||||
DeadInst->setOperand(op, 0);
|
|
||||||
|
|
||||||
// If this operand just became dead, add it to the NowDeadInsts list.
|
|
||||||
if (!Op->use_empty()) continue;
|
|
||||||
|
|
||||||
if (Instruction *OpI = dyn_cast<Instruction>(Op))
|
|
||||||
if (isInstructionTriviallyDead(OpI))
|
|
||||||
NowDeadInsts.push_back(OpI);
|
|
||||||
}
|
|
||||||
|
|
||||||
DeadInst->eraseFromParent();
|
|
||||||
|
|
||||||
if (ValueSet) ValueSet->erase(DeadInst);
|
|
||||||
} while (!NowDeadInsts.empty());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user