add DEBUG and -stats output to earlycse.
authorChris Lattner <sabre@nondot.org>
Sun, 2 Jan 2011 23:19:45 +0000 (23:19 +0000)
committerChris Lattner <sabre@nondot.org>
Sun, 2 Jan 2011 23:19:45 +0000 (23:19 +0000)
Teach it to CSE the rest of the non-side-effecting instructions.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@122716 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/Scalar/EarlyCSE.cpp
lib/Transforms/Scalar/LoopIdiomRecognize.cpp
test/Transforms/EarlyCSE/basic.ll

index a43d4254c3aa977bfb85d9f70803cd014caaf92b..862e37ca28e991ce020880b23126bc011fed7d5d 100644 (file)
 
 #define DEBUG_TYPE "early-cse"
 #include "llvm/Transforms/Scalar.h"
+#include "llvm/Instructions.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/Support/Debug.h"
 #include "llvm/ADT/ScopedHashTable.h"
+#include "llvm/ADT/Statistic.h"
 using namespace llvm;
 
+STATISTIC(NumSimplify, "Number of insts simplified or DCE'd");
+STATISTIC(NumCSE, "Number of insts CSE'd");
+
 namespace {
   /// InstValue - Instances of this struct represent available values in the
   /// scoped hash table.
@@ -35,7 +41,11 @@ namespace {
     }
     
     static bool canHandle(Instruction *Inst) {
-      return isa<CastInst>(Inst);
+      return isa<CastInst>(Inst) || isa<BinaryOperator>(Inst) ||
+             isa<GetElementPtrInst>(Inst) || isa<CmpInst>(Inst) ||
+             isa<SelectInst>(Inst) || isa<ExtractElementInst>(Inst) ||
+             isa<InsertElementInst>(Inst) || isa<ShuffleVectorInst>(Inst) ||
+             isa<ExtractValueInst>(Inst) || isa<InsertValueInst>(Inst);
     }
     
     static InstValue get(Instruction *I) {
@@ -73,8 +83,24 @@ unsigned DenseMapInfo<InstValue>::getHashValue(InstValue Val) {
   unsigned Res = 0;
   if (CastInst *CI = dyn_cast<CastInst>(Inst))
     Res = getHash(CI->getOperand(0)) ^ getHash(CI->getType());
-  else
-    assert(0 && "Unhandled instruction kind");
+  else if (BinaryOperator *BO = dyn_cast<BinaryOperator>(Inst))
+    Res = getHash(BO->getOperand(0)) ^ (getHash(BO->getOperand(1)) << 1);
+  else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Inst)) {
+    Res = getHash(CI->getOperand(0));
+    for (unsigned i = 1, e = GEP->getNumOperands(); i != e; ++i)
+      Res ^= getHash(CI->getOperand(i)) << i;
+  } else if (CmpInst *CI = dyn_cast<CmpInst>(Inst)) {
+      Res = getHash(CI->getOperand(0)) ^ (getHash(CI->getOperand(1)) << 1) ^
+         CI->getPredicate();
+  } else {
+    assert((isa<SelectInst>(Inst) || isa<ExtractElementInst>(Inst) ||
+            isa<InsertElementInst>(Inst) || isa<ShuffleVectorInst>(Inst) ||
+            isa<ExtractValueInst>(Inst) || isa<InsertValueInst>(Inst)) &&
+           "Unhandled instruction kind");
+    Res = getHash(CI->getType()) << 4;
+    for (unsigned i = 0, e = Inst->getNumOperands(); i != e; ++i)
+      Res ^= getHash(CI->getOperand(i)) << i;
+  }
   
   return (Res << 1) ^ Inst->getOpcode();
 }
@@ -152,17 +178,21 @@ bool EarlyCSE::processNode(DomTreeNode *Node) {
     
     // Dead instructions should just be removed.
     if (isInstructionTriviallyDead(Inst)) {
+      DEBUG(dbgs() << "EarlyCSE DCE: " << *Inst << '\n');
       Inst->eraseFromParent();
       Changed = true;
+      ++NumSimplify;
       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)) {
+      DEBUG(dbgs() << "EarlyCSE Simplify: " << *Inst << "  to: " << *V << '\n');
       Inst->replaceAllUsesWith(V);
       Inst->eraseFromParent();
       Changed = true;
+      ++NumSimplify;
       continue;
     }
     
@@ -172,9 +202,11 @@ bool EarlyCSE::processNode(DomTreeNode *Node) {
     
     // See if the instruction has an available value.  If so, use it.
     if (Instruction *V = AvailableValues->lookup(InstValue::get(Inst))) {
+      DEBUG(dbgs() << "EarlyCSE CSE: " << *Inst << "  to: " << *V << '\n');
       Inst->replaceAllUsesWith(V);
       Inst->eraseFromParent();
       Changed = true;
+      ++NumCSE;
       continue;
     }
     
index 49368cb7f7ecccd1098d5dfbdda65a7c3b3d34c7..086afb14b29996398f11e555f827cf8cd639dbeb 100644 (file)
 //   void foo(_Complex float *P)
 //     for (i) { __real__(*P) = 0;  __imag__(*P) = 0; }
 // this is also "Example 2" from http://blog.regehr.org/archives/320
-//  
+//
+// This could regognize common matrix multiplies and dot product idioms and
+// replace them with calls to BLAS (if linked in??).
+//
 //===----------------------------------------------------------------------===//
 
 #define DEBUG_TYPE "loop-idiom"
@@ -49,8 +52,6 @@
 #include "llvm/ADT/Statistic.h"
 using namespace llvm;
 
-// TODO: Recognize "N" size array multiplies: replace with call to blas or
-// something.
 STATISTIC(NumMemSet, "Number of memset's formed from loop stores");
 STATISTIC(NumMemCpy, "Number of memcpy's formed from loop load+stores");
 
index d42f503fc64b1ce9f513f1c5b46a13a2aeaeb700..6cfd0a9df98a59ce3b6281ae43b8562e9bc1f3ea 100644 (file)
@@ -6,16 +6,27 @@ 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
+  
+  %E = add i32 %C, %C
+  %F = add i32 %C, %C
+  volatile store i32 %E, i32* %P
+  volatile store i32 %F, i32* %P
+  ; CHECK-NEXT: %E = add i32 %C, %C
+  ; CHECK-NEXT: volatile store i32 %E
+  ; CHECK-NEXT: volatile store i32 %E
+
+  %G = add nuw i32 %C, %C         ;; not a CSE with E
+  volatile store i32 %G, i32* %P
+  ; CHECK-NEXT: %G = add nuw i32 %C, %C
+  ; CHECK-NEXT: volatile store i32 %G
   ret void
 }