1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-24 19:52:54 +01:00

earlycse can do trivial with-a-block dead store

elimination as well.  This deletes 60 stores in 176.gcc
that largely come from bitfield code.

llvm-svn: 122736
This commit is contained in:
Chris Lattner 2011-01-03 04:17:24 +00:00
parent 60ec113434
commit c1ebe702b1
2 changed files with 48 additions and 6 deletions

View File

@ -30,6 +30,7 @@ STATISTIC(NumSimplify, "Number of instructions simplified or DCE'd");
STATISTIC(NumCSE, "Number of instructions CSE'd");
STATISTIC(NumCSELoad, "Number of load instructions CSE'd");
STATISTIC(NumCSECall, "Number of call instructions CSE'd");
STATISTIC(NumDSE, "Number of trivial dead stores removed");
static unsigned getHash(const void *V) {
return DenseMapInfo<const void*>::getHashValue(V);
@ -290,6 +291,12 @@ bool EarlyCSE::processNode(DomTreeNode *Node) {
if (BB->getSinglePredecessor() == 0)
++CurrentGeneration;
/// LastStore - Keep track of the last non-volatile store that we saw... for
/// as long as there in no instruction that reads memory. If we see a store
/// to the same location, we delete the dead store. This zaps trivial dead
/// stores which can occur in bitfield code among other things.
StoreInst *LastStore = 0;
bool Changed = false;
// See if any instructions in the block can be eliminated. If so, do it. If
@ -337,7 +344,10 @@ bool EarlyCSE::processNode(DomTreeNode *Node) {
// If this is a non-volatile load, process it.
if (LoadInst *LI = dyn_cast<LoadInst>(Inst)) {
// Ignore volatile loads.
if (LI->isVolatile()) continue;
if (LI->isVolatile()) {
LastStore = 0;
continue;
}
// If we have an available version of this load, and if it is the right
// generation, replace this instruction.
@ -356,9 +366,14 @@ bool EarlyCSE::processNode(DomTreeNode *Node) {
// Otherwise, remember that we have this instruction.
AvailableLoads->insert(Inst->getOperand(0),
std::pair<Value*, unsigned>(Inst, CurrentGeneration));
LastStore = 0;
continue;
}
// If this instruction may read from memory, forget LastStore.
if (Inst->mayReadFromMemory())
LastStore = 0;
// If this is a read-only call, process it.
if (CallValue::canHandle(Inst)) {
// If we have an available version of this call, and if it is the right
@ -386,14 +401,31 @@ bool EarlyCSE::processNode(DomTreeNode *Node) {
if (Inst->mayWriteToMemory()) {
++CurrentGeneration;
// Okay, we just invalidated anything we knew about loaded values. Try to
// salvage *something* by remembering that the stored value is a live
// version of the pointer. It is safe to forward from volatile stores to
// non-volatile loads, so we don't have to check for volatility of the
// store.
if (StoreInst *SI = dyn_cast<StoreInst>(Inst)) {
// We do a trivial form of DSE if there are two stores to the same
// location with no intervening loads. Delete the earlier store.
if (LastStore &&
LastStore->getPointerOperand() == SI->getPointerOperand()) {
DEBUG(dbgs() << "EarlyCSE DEAD STORE: " << *LastStore << " due to: "
<< *Inst << '\n');
LastStore->eraseFromParent();
Changed = true;
++NumDSE;
LastStore = 0;
continue;
}
// Okay, we just invalidated anything we knew about loaded values. Try
// to salvage *something* by remembering that the stored value is a live
// version of the pointer. It is safe to forward from volatile stores
// to non-volatile loads, so we don't have to check for volatility of
// the store.
AvailableLoads->insert(SI->getPointerOperand(),
std::pair<Value*, unsigned>(SI->getValueOperand(), CurrentGeneration));
// Remember that this was the last store we saw for DSE.
if (!SI->isVolatile())
LastStore = SI;
}
}
}

View File

@ -96,3 +96,13 @@ define i32 @test6(i32 *%P) {
ret i32 %V1
; CHECK: ret i32 42
}
;; Trivial dead store elimination.
; CHECK: @test7
define void @test7(i32 *%P) {
store i32 42, i32* %P
store i32 45, i32* %P
ret void
; CHECK-NEXT: store i32 45
; CHECK-NEXT: ret void
}