[llvm-commits] [llvm] r38517 - in /llvm/trunk: include/llvm/LinkAllPasses.h include/llvm/Transforms/Scalar.h lib/Transforms/Scalar/FastDSE.cpp
Owen Anderson
resistor at mac.com
Tue Jul 10 17:46:18 PDT 2007
Author: resistor
Date: Tue Jul 10 19:46:18 2007
New Revision: 38517
URL: http://llvm.org/viewvc/llvm-project?rev=38517&view=rev
Log:
Add FastDSE, a new algorithm for doing dead store elimination. This algorithm is not as accurate
as the current DSE, but it only a linear scan over each block, rather than quadratic. Eventually
(once it has been improved somewhat), this will replace the current DSE.
NOTE: This has not yet been extensively tested.
Added:
llvm/trunk/lib/Transforms/Scalar/FastDSE.cpp
Modified:
llvm/trunk/include/llvm/LinkAllPasses.h
llvm/trunk/include/llvm/Transforms/Scalar.h
Modified: llvm/trunk/include/llvm/LinkAllPasses.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/LinkAllPasses.h?rev=38517&r1=38516&r2=38517&view=diff
==============================================================================
--- llvm/trunk/include/llvm/LinkAllPasses.h (original)
+++ llvm/trunk/include/llvm/LinkAllPasses.h Tue Jul 10 19:46:18 2007
@@ -61,6 +61,7 @@
(void) llvm::createDeadStoreEliminationPass();
(void) llvm::createDeadTypeEliminationPass();
(void) llvm::createEdgeProfilerPass();
+ (void) llvm::createFastDeadStoreEliminationPass();
(void) llvm::createFunctionInliningPass();
(void) llvm::createFunctionProfilerPass();
(void) llvm::createGCSEPass();
Modified: llvm/trunk/include/llvm/Transforms/Scalar.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Scalar.h?rev=38517&r1=38516&r2=38517&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Transforms/Scalar.h (original)
+++ llvm/trunk/include/llvm/Transforms/Scalar.h Tue Jul 10 19:46:18 2007
@@ -325,6 +325,13 @@
//===----------------------------------------------------------------------===//
//
+// FastDeadStoreElimination - This pass deletes stores that are post-dominated by
+// must-aliased stores and are not loaded used between the stores.
+//
+FunctionPass *createFastDeadStoreEliminationPass();
+
+//===----------------------------------------------------------------------===//
+//
// CodeGenPrepare - This pass prepares a function for instruction selection.
//
FunctionPass *createCodeGenPreparePass(const TargetLowering *TLI = 0);
Added: llvm/trunk/lib/Transforms/Scalar/FastDSE.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/FastDSE.cpp?rev=38517&view=auto
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/FastDSE.cpp (added)
+++ llvm/trunk/lib/Transforms/Scalar/FastDSE.cpp Tue Jul 10 19:46:18 2007
@@ -0,0 +1,130 @@
+//===- DeadStoreElimination.cpp - Dead Store Elimination ------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements a trivial dead store elimination that only considers
+// basic-block local redundant stores.
+//
+// FIXME: This should eventually be extended to be a post-dominator tree
+// traversal. Doing so would be pretty trivial.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "fdse"
+#include "llvm/Transforms/Scalar.h"
+#include "llvm/Function.h"
+#include "llvm/Instructions.h"
+#include "llvm/Pass.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/Analysis/MemoryDependenceAnalysis.h"
+#include "llvm/Transforms/Utils/Local.h"
+#include "llvm/Support/Compiler.h"
+using namespace llvm;
+
+STATISTIC(NumFastStores, "Number of stores deleted");
+STATISTIC(NumFastOther , "Number of other instrs removed");
+
+namespace {
+ struct VISIBILITY_HIDDEN FDSE : public FunctionPass {
+ static char ID; // Pass identification, replacement for typeid
+ FDSE() : FunctionPass((intptr_t)&ID) {}
+
+ virtual bool runOnFunction(Function &F) {
+ bool Changed = false;
+ for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I)
+ Changed |= runOnBasicBlock(*I);
+ return Changed;
+ }
+
+ bool runOnBasicBlock(BasicBlock &BB);
+ void DeleteDeadInstructionChains(Instruction *I,
+ SetVector<Instruction*> &DeadInsts);
+
+ // getAnalysisUsage - We require post dominance frontiers (aka Control
+ // Dependence Graph)
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.setPreservesCFG();
+ AU.addRequired<MemoryDependenceAnalysis>();
+ AU.addPreserved<MemoryDependenceAnalysis>();
+ }
+ };
+ char FDSE::ID = 0;
+ RegisterPass<FDSE> X("fdse", "Fast Dead Store Elimination");
+}
+
+FunctionPass *llvm::createFastDeadStoreEliminationPass() { return new FDSE(); }
+
+bool FDSE::runOnBasicBlock(BasicBlock &BB) {
+ MemoryDependenceAnalysis& MD = getAnalysis<MemoryDependenceAnalysis>();
+
+ DenseMap<Value*, StoreInst*> lastStore;
+ SetVector<Instruction*> possiblyDead;
+
+ bool MadeChange = false;
+
+ // Do a top-down walk on the BB
+ for (BasicBlock::iterator BBI = BB.begin(), BBE = BB.end(); BBI != BBE; ++BBI) {
+ // If we find a store...
+ if (StoreInst* S = dyn_cast<StoreInst>(BBI)) {
+
+ // ... to a pointer that has been stored to before...
+ if (lastStore.count(S->getPointerOperand())) {
+ StoreInst* last = lastStore[S->getPointerOperand()];
+
+ // ... and no other memory dependencies are between them....
+ if (MD.getDependency(S) == last) {
+ // Remove it!
+ MD.removeInstruction(last);
+
+ // DCE instructions only used to calculate that store
+ if (Instruction* D = dyn_cast<Instruction>(last->getOperand(0)))
+ possiblyDead.insert(D);
+
+ last->eraseFromParent();
+ NumFastStores++;
+ MadeChange = true;
+ }
+ }
+
+ // Update our most-recent-store map
+ lastStore.insert(std::make_pair(S->getPointerOperand(), S));
+ }
+ }
+
+ // Do a trivial DCE
+ while (!possiblyDead.empty()) {
+ Instruction *I = possiblyDead.back();
+ possiblyDead.pop_back();
+ DeleteDeadInstructionChains(I, possiblyDead);
+ }
+
+ return MadeChange;
+}
+
+void FDSE::DeleteDeadInstructionChains(Instruction *I,
+ SetVector<Instruction*> &DeadInsts) {
+ // Instruction must be dead.
+ if (!I->use_empty() || !isInstructionTriviallyDead(I)) return;
+
+ // Let the memory dependence know
+ getAnalysis<MemoryDependenceAnalysis>().removeInstruction(I);
+
+ // See if this made any operands dead. We do it this way in case the
+ // instruction uses the same operand twice. We don't want to delete a
+ // value then reference it.
+ for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) {
+ if (Instruction *Op = dyn_cast<Instruction>(I->getOperand(i)))
+ DeadInsts.insert(Op); // Attempt to nuke it later.
+ I->setOperand(i, 0); // Drop from the operand list.
+ }
+
+ I->eraseFromParent();
+ ++NumFastOther;
+}
More information about the llvm-commits
mailing list