From 39d1fb33203d0c9950c7588fa85c3831db6351f6 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sun, 2 Jan 2011 23:19:45 +0000 Subject: [PATCH] add DEBUG and -stats output to earlycse. Teach it to CSE the rest of the non-side-effecting instructions. llvm-svn: 122716 --- lib/Transforms/Scalar/EarlyCSE.cpp | 38 ++++++++++++++++++-- lib/Transforms/Scalar/LoopIdiomRecognize.cpp | 7 ++-- test/Transforms/EarlyCSE/basic.ll | 15 ++++++-- 3 files changed, 52 insertions(+), 8 deletions(-) diff --git a/lib/Transforms/Scalar/EarlyCSE.cpp b/lib/Transforms/Scalar/EarlyCSE.cpp index a43d4254c3a..862e37ca28e 100644 --- a/lib/Transforms/Scalar/EarlyCSE.cpp +++ b/lib/Transforms/Scalar/EarlyCSE.cpp @@ -14,15 +14,21 @@ #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(Inst); + return isa(Inst) || isa(Inst) || + isa(Inst) || isa(Inst) || + isa(Inst) || isa(Inst) || + isa(Inst) || isa(Inst) || + isa(Inst) || isa(Inst); } static InstValue get(Instruction *I) { @@ -73,8 +83,24 @@ unsigned DenseMapInfo::getHashValue(InstValue Val) { unsigned Res = 0; if (CastInst *CI = dyn_cast(Inst)) Res = getHash(CI->getOperand(0)) ^ getHash(CI->getType()); - else - assert(0 && "Unhandled instruction kind"); + else if (BinaryOperator *BO = dyn_cast(Inst)) + Res = getHash(BO->getOperand(0)) ^ (getHash(BO->getOperand(1)) << 1); + else if (GetElementPtrInst *GEP = dyn_cast(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(Inst)) { + Res = getHash(CI->getOperand(0)) ^ (getHash(CI->getOperand(1)) << 1) ^ + CI->getPredicate(); + } else { + assert((isa(Inst) || isa(Inst) || + isa(Inst) || isa(Inst) || + isa(Inst) || isa(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; } diff --git a/lib/Transforms/Scalar/LoopIdiomRecognize.cpp b/lib/Transforms/Scalar/LoopIdiomRecognize.cpp index 49368cb7f7e..086afb14b29 100644 --- a/lib/Transforms/Scalar/LoopIdiomRecognize.cpp +++ b/lib/Transforms/Scalar/LoopIdiomRecognize.cpp @@ -31,7 +31,10 @@ // 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"); diff --git a/test/Transforms/EarlyCSE/basic.ll b/test/Transforms/EarlyCSE/basic.ll index d42f503fc64..6cfd0a9df98 100644 --- a/test/Transforms/EarlyCSE/basic.ll +++ b/test/Transforms/EarlyCSE/basic.ll @@ -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 }