mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-10-31 08:16:47 +00:00 
			
		
		
		
	add DEBUG and -stats output to earlycse.
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
This commit is contained in:
		| @@ -14,15 +14,21 @@ | |||||||
|  |  | ||||||
| #define DEBUG_TYPE "early-cse" | #define DEBUG_TYPE "early-cse" | ||||||
| #include "llvm/Transforms/Scalar.h" | #include "llvm/Transforms/Scalar.h" | ||||||
|  | #include "llvm/Instructions.h" | ||||||
| #include "llvm/Pass.h" | #include "llvm/Pass.h" | ||||||
| #include "llvm/Analysis/Dominators.h" | #include "llvm/Analysis/Dominators.h" | ||||||
| #include "llvm/Analysis/InstructionSimplify.h" | #include "llvm/Analysis/InstructionSimplify.h" | ||||||
| #include "llvm/Analysis/InstructionSimplify.h" | #include "llvm/Analysis/InstructionSimplify.h" | ||||||
| #include "llvm/Target/TargetData.h" | #include "llvm/Target/TargetData.h" | ||||||
| #include "llvm/Transforms/Utils/Local.h" | #include "llvm/Transforms/Utils/Local.h" | ||||||
|  | #include "llvm/Support/Debug.h" | ||||||
| #include "llvm/ADT/ScopedHashTable.h" | #include "llvm/ADT/ScopedHashTable.h" | ||||||
|  | #include "llvm/ADT/Statistic.h" | ||||||
| using namespace llvm; | using namespace llvm; | ||||||
|  |  | ||||||
|  | STATISTIC(NumSimplify, "Number of insts simplified or DCE'd"); | ||||||
|  | STATISTIC(NumCSE, "Number of insts CSE'd"); | ||||||
|  |  | ||||||
| namespace { | namespace { | ||||||
|   /// InstValue - Instances of this struct represent available values in the |   /// InstValue - Instances of this struct represent available values in the | ||||||
|   /// scoped hash table. |   /// scoped hash table. | ||||||
| @@ -35,7 +41,11 @@ namespace { | |||||||
|     } |     } | ||||||
|      |      | ||||||
|     static bool canHandle(Instruction *Inst) { |     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) { |     static InstValue get(Instruction *I) { | ||||||
| @@ -73,8 +83,24 @@ unsigned DenseMapInfo<InstValue>::getHashValue(InstValue Val) { | |||||||
|   unsigned Res = 0; |   unsigned Res = 0; | ||||||
|   if (CastInst *CI = dyn_cast<CastInst>(Inst)) |   if (CastInst *CI = dyn_cast<CastInst>(Inst)) | ||||||
|     Res = getHash(CI->getOperand(0)) ^ getHash(CI->getType()); |     Res = getHash(CI->getOperand(0)) ^ getHash(CI->getType()); | ||||||
|   else |   else if (BinaryOperator *BO = dyn_cast<BinaryOperator>(Inst)) | ||||||
|     assert(0 && "Unhandled instruction kind"); |     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(); |   return (Res << 1) ^ Inst->getOpcode(); | ||||||
| } | } | ||||||
| @@ -152,17 +178,21 @@ bool EarlyCSE::processNode(DomTreeNode *Node) { | |||||||
|      |      | ||||||
|     // Dead instructions should just be removed. |     // Dead instructions should just be removed. | ||||||
|     if (isInstructionTriviallyDead(Inst)) { |     if (isInstructionTriviallyDead(Inst)) { | ||||||
|  |       DEBUG(dbgs() << "EarlyCSE DCE: " << *Inst << '\n'); | ||||||
|       Inst->eraseFromParent(); |       Inst->eraseFromParent(); | ||||||
|       Changed = true; |       Changed = true; | ||||||
|  |       ++NumSimplify; | ||||||
|       continue; |       continue; | ||||||
|     } |     } | ||||||
|      |      | ||||||
|     // If the instruction can be simplified (e.g. X+0 = X) then replace it with |     // If the instruction can be simplified (e.g. X+0 = X) then replace it with | ||||||
|     // its simpler value. |     // its simpler value. | ||||||
|     if (Value *V = SimplifyInstruction(Inst, TD, DT)) { |     if (Value *V = SimplifyInstruction(Inst, TD, DT)) { | ||||||
|  |       DEBUG(dbgs() << "EarlyCSE Simplify: " << *Inst << "  to: " << *V << '\n'); | ||||||
|       Inst->replaceAllUsesWith(V); |       Inst->replaceAllUsesWith(V); | ||||||
|       Inst->eraseFromParent(); |       Inst->eraseFromParent(); | ||||||
|       Changed = true; |       Changed = true; | ||||||
|  |       ++NumSimplify; | ||||||
|       continue; |       continue; | ||||||
|     } |     } | ||||||
|      |      | ||||||
| @@ -172,9 +202,11 @@ bool EarlyCSE::processNode(DomTreeNode *Node) { | |||||||
|      |      | ||||||
|     // See if the instruction has an available value.  If so, use it. |     // See if the instruction has an available value.  If so, use it. | ||||||
|     if (Instruction *V = AvailableValues->lookup(InstValue::get(Inst))) { |     if (Instruction *V = AvailableValues->lookup(InstValue::get(Inst))) { | ||||||
|  |       DEBUG(dbgs() << "EarlyCSE CSE: " << *Inst << "  to: " << *V << '\n'); | ||||||
|       Inst->replaceAllUsesWith(V); |       Inst->replaceAllUsesWith(V); | ||||||
|       Inst->eraseFromParent(); |       Inst->eraseFromParent(); | ||||||
|       Changed = true; |       Changed = true; | ||||||
|  |       ++NumCSE; | ||||||
|       continue; |       continue; | ||||||
|     } |     } | ||||||
|      |      | ||||||
|   | |||||||
| @@ -32,6 +32,9 @@ | |||||||
| //     for (i) { __real__(*P) = 0;  __imag__(*P) = 0; } | //     for (i) { __real__(*P) = 0;  __imag__(*P) = 0; } | ||||||
| // this is also "Example 2" from http://blog.regehr.org/archives/320 | // 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" | #define DEBUG_TYPE "loop-idiom" | ||||||
| @@ -49,8 +52,6 @@ | |||||||
| #include "llvm/ADT/Statistic.h" | #include "llvm/ADT/Statistic.h" | ||||||
| using namespace llvm; | 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(NumMemSet, "Number of memset's formed from loop stores"); | ||||||
| STATISTIC(NumMemCpy, "Number of memcpy's formed from loop load+stores"); | STATISTIC(NumMemCpy, "Number of memcpy's formed from loop load+stores"); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -6,16 +6,27 @@ define void @test1(i8 %V, i32 *%P) { | |||||||
|   %A = bitcast i64 42 to double  ;; dead |   %A = bitcast i64 42 to double  ;; dead | ||||||
|   %B = add i32 4, 19             ;; constant folds |   %B = add i32 4, 19             ;; constant folds | ||||||
|   store i32 %B, i32* %P |   store i32 %B, i32* %P | ||||||
|    |  | ||||||
|   ; CHECK-NEXT: store i32 23, i32* %P |   ; CHECK-NEXT: store i32 23, i32* %P | ||||||
|    |    | ||||||
|   %C = zext i8 %V to i32 |   %C = zext i8 %V to i32 | ||||||
|   %D = zext i8 %V to i32  ;; CSE |   %D = zext i8 %V to i32  ;; CSE | ||||||
|   volatile store i32 %C, i32* %P |   volatile store i32 %C, i32* %P | ||||||
|   volatile store i32 %D, i32* %P |   volatile store i32 %D, i32* %P | ||||||
|    |  | ||||||
|   ; CHECK-NEXT: %C = zext i8 %V to i32 |   ; CHECK-NEXT: %C = zext i8 %V to i32 | ||||||
|   ; CHECK-NEXT: volatile store i32 %C |   ; CHECK-NEXT: volatile store i32 %C | ||||||
|   ; 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 |   ret void | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user