[llvm-commits] [llvm] r122715 - in /llvm/trunk: lib/Transforms/Scalar/EarlyCSE.cpp test/Transforms/EarlyCSE/ test/Transforms/EarlyCSE/basic.ll test/Transforms/EarlyCSE/dg.exp

Chris Lattner sabre at nondot.org
Sun Jan 2 15:04:14 PST 2011


Author: lattner
Date: Sun Jan  2 17:04:14 2011
New Revision: 122715

URL: http://llvm.org/viewvc/llvm-project?rev=122715&view=rev
Log:
Enhance earlycse to do CSE of casts, instsimplify and die.
Add a testcase.


Added:
    llvm/trunk/test/Transforms/EarlyCSE/
    llvm/trunk/test/Transforms/EarlyCSE/basic.ll
    llvm/trunk/test/Transforms/EarlyCSE/dg.exp
Modified:
    llvm/trunk/lib/Transforms/Scalar/EarlyCSE.cpp

Modified: llvm/trunk/lib/Transforms/Scalar/EarlyCSE.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/EarlyCSE.cpp?rev=122715&r1=122714&r2=122715&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/EarlyCSE.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/EarlyCSE.cpp Sun Jan  2 17:04:14 2011
@@ -14,11 +14,84 @@
 
 #define DEBUG_TYPE "early-cse"
 #include "llvm/Transforms/Scalar.h"
-#include "llvm/Analysis/Dominators.h"
 #include "llvm/Pass.h"
+#include "llvm/Analysis/Dominators.h"
+#include "llvm/Analysis/InstructionSimplify.h"
+#include "llvm/Analysis/InstructionSimplify.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/Transforms/Utils/Local.h"
+#include "llvm/ADT/ScopedHashTable.h"
 using namespace llvm;
 
 namespace {
+  /// InstValue - Instances of this struct represent available values in the
+  /// scoped hash table.
+  struct InstValue {
+    Instruction *Inst;
+    
+    bool isSentinel() const {
+      return Inst == DenseMapInfo<Instruction*>::getEmptyKey() ||
+             Inst == DenseMapInfo<Instruction*>::getTombstoneKey();
+    }
+    
+    static bool canHandle(Instruction *Inst) {
+      return isa<CastInst>(Inst);
+    }
+    
+    static InstValue get(Instruction *I) {
+      InstValue X; X.Inst = I;
+      assert((X.isSentinel() || canHandle(I)) && "Inst can't be handled!");
+      return X;
+    }
+  };
+}
+
+namespace llvm {
+// InstValue is POD.
+template<> struct isPodLike<InstValue> {
+  static const bool value = true;
+};
+
+template<> struct DenseMapInfo<InstValue> {
+  static inline InstValue getEmptyKey() {
+    return InstValue::get(DenseMapInfo<Instruction*>::getEmptyKey());
+  }
+  static inline InstValue getTombstoneKey() {
+    return InstValue::get(DenseMapInfo<Instruction*>::getTombstoneKey());
+  }
+  static unsigned getHashValue(InstValue Val);
+  static bool isEqual(InstValue LHS, InstValue RHS);
+};
+}
+
+unsigned getHash(const void *V) {
+  return DenseMapInfo<const void*>::getHashValue(V);
+}
+
+unsigned DenseMapInfo<InstValue>::getHashValue(InstValue Val) {
+  Instruction *Inst = Val.Inst;
+  unsigned Res = 0;
+  if (CastInst *CI = dyn_cast<CastInst>(Inst))
+    Res = getHash(CI->getOperand(0)) ^ getHash(CI->getType());
+  else
+    assert(0 && "Unhandled instruction kind");
+  
+  return (Res << 1) ^ Inst->getOpcode();
+}
+
+bool DenseMapInfo<InstValue>::isEqual(InstValue LHS, InstValue RHS) {
+  Instruction *LHSI = LHS.Inst, *RHSI = RHS.Inst;
+
+  if (LHS.isSentinel() || RHS.isSentinel())
+    return LHSI == RHSI;
+  
+  if (LHSI->getOpcode() != RHSI->getOpcode()) return false;
+  return LHSI->isIdenticalTo(RHSI);
+}
+
+
+namespace {
+  
 /// EarlyCSE - This pass does a simple depth-first walk over the dominator
 /// tree, eliminating trivially redundant instructions and using instsimplify
 /// to canonicalize things as it goes.  It is intended to be fast and catch
@@ -27,6 +100,10 @@
 /// cases.
 class EarlyCSE : public FunctionPass {
 public:
+  const TargetData *TD;
+  DominatorTree *DT;
+  ScopedHashTable<InstValue, Instruction*> *AvailableValues;
+  
   static char ID;
   explicit EarlyCSE()
       : FunctionPass(ID) {
@@ -36,6 +113,9 @@
   bool runOnFunction(Function &F);
 
 private:
+  
+  bool processNode(DomTreeNode *Node);
+  
   // This transformation requires dominator postdominator info
   virtual void getAnalysisUsage(AnalysisUsage &AU) const {
     AU.addRequired<DominatorTree>();
@@ -55,8 +135,65 @@
 INITIALIZE_PASS_DEPENDENCY(DominatorTree)
 INITIALIZE_PASS_END(EarlyCSE, "early-cse", "Early CSE", false, false)
 
+// FIXME: Should bump pointer allocate entries in scoped hash table.
+
+bool EarlyCSE::processNode(DomTreeNode *Node) {
+  // Define a scope in the scoped hash table.
+  ScopedHashTableScope<InstValue, Instruction*> Scope(*AvailableValues);
+  
+  BasicBlock *BB = Node->getBlock();
+  
+  bool Changed = false;
+
+  // See if any instructions in the block can be eliminated.  If so, do it.  If
+  // not, add them to AvailableValues.
+  for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ) {
+    Instruction *Inst = I++;
+    
+    // Dead instructions should just be removed.
+    if (isInstructionTriviallyDead(Inst)) {
+      Inst->eraseFromParent();
+      Changed = true;
+      continue;
+    }
+    
+    // If the instruction can be simplified (e.g. X+0 = X) then replace it with
+    // its simpler value.
+    if (Value *V = SimplifyInstruction(Inst, TD, DT)) {
+      Inst->replaceAllUsesWith(V);
+      Inst->eraseFromParent();
+      Changed = true;
+      continue;
+    }
+    
+    // If this instruction is something that we can't value number, ignore it.
+    if (!InstValue::canHandle(Inst))
+      continue;
+    
+    // See if the instruction has an available value.  If so, use it.
+    if (Instruction *V = AvailableValues->lookup(InstValue::get(Inst))) {
+      Inst->replaceAllUsesWith(V);
+      Inst->eraseFromParent();
+      Changed = true;
+      continue;
+    }
+    
+    // Otherwise, just remember that this value is available.
+    AvailableValues->insert(InstValue::get(Inst), Inst);
+  }
+  
+  
+  for (DomTreeNode::iterator I = Node->begin(), E = Node->end(); I != E; ++I)
+    Changed |= processNode(*I);
+  return Changed;
+}
+
+
 bool EarlyCSE::runOnFunction(Function &F) {
-  DominatorTree &DT = getAnalysis<DominatorTree>();
-  (void)DT;
-  return false;
+  TD = getAnalysisIfAvailable<TargetData>();
+  DT = &getAnalysis<DominatorTree>();
+  ScopedHashTable<InstValue, Instruction*> AVTable;
+  AvailableValues = &AVTable;
+  return processNode(DT->getRootNode());
 }
+

Added: llvm/trunk/test/Transforms/EarlyCSE/basic.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/EarlyCSE/basic.ll?rev=122715&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/EarlyCSE/basic.ll (added)
+++ llvm/trunk/test/Transforms/EarlyCSE/basic.ll Sun Jan  2 17:04:14 2011
@@ -0,0 +1,21 @@
+; RUN: opt < %s -S -early-cse | FileCheck %s
+
+
+; CHECK: @test1
+define void @test1(i8 %V, i32 *%P) {
+  %A = bitcast i64 42 to double  ;; dead
+  %B = add i32 4, 19             ;; constant folds
+  store i32 %B, i32* %P
+  
+  ; CHECK-NEXT: store i32 23, i32* %P
+  
+  %C = zext i8 %V to i32
+  %D = zext i8 %V to i32  ;; CSE
+  volatile store i32 %C, i32* %P
+  volatile store i32 %D, i32* %P
+  
+  ; CHECK-NEXT: %C = zext i8 %V to i32
+  ; CHECK-NEXT: volatile store i32 %C
+  ; CHECK-NEXT: volatile store i32 %C
+  ret void
+}

Added: llvm/trunk/test/Transforms/EarlyCSE/dg.exp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/EarlyCSE/dg.exp?rev=122715&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/EarlyCSE/dg.exp (added)
+++ llvm/trunk/test/Transforms/EarlyCSE/dg.exp Sun Jan  2 17:04:14 2011
@@ -0,0 +1,3 @@
+load_lib llvm.exp
+
+RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.ll]]





More information about the llvm-commits mailing list