aboutsummaryrefslogtreecommitdiff
path: root/lib/Transforms
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2005-02-27 18:58:52 +0000
committerChris Lattner <sabre@nondot.org>2005-02-27 18:58:52 +0000
commit35c81b0b120f87373584f2e238e4d77f9d2ae88f (patch)
tree103afc90c327fd48e4bbdf9b8974fe80cf52b5f5 /lib/Transforms
parentb503cc43631ecc62b4225235dc4aa2768727a5ef (diff)
Teach globalopt how memset/cpy/move affect memory, to allow better optimization.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@20352 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms')
-rw-r--r--lib/Transforms/IPO/GlobalOpt.cpp65
1 files changed, 40 insertions, 25 deletions
diff --git a/lib/Transforms/IPO/GlobalOpt.cpp b/lib/Transforms/IPO/GlobalOpt.cpp
index 4c87400729..754adc3949 100644
--- a/lib/Transforms/IPO/GlobalOpt.cpp
+++ b/lib/Transforms/IPO/GlobalOpt.cpp
@@ -18,6 +18,7 @@
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Instructions.h"
+#include "llvm/IntrinsicInst.h"
#include "llvm/Module.h"
#include "llvm/Pass.h"
#include "llvm/Support/Debug.h"
@@ -194,7 +195,7 @@ static bool AnalyzeGlobal(Value *V, GlobalStatus &GS,
} else {
GS.StoredType = GlobalStatus::isStored;
}
- } else if (I->getOpcode() == Instruction::GetElementPtr) {
+ } else if (isa<GetElementPtrInst>(I)) {
if (AnalyzeGlobal(I, GS, PHIUsers)) return true;
// If the first two indices are constants, this can be SRA'd.
@@ -212,7 +213,7 @@ static bool AnalyzeGlobal(Value *V, GlobalStatus &GS,
} else {
GS.isNotSuitableForSRA = true;
}
- } else if (I->getOpcode() == Instruction::Select) {
+ } else if (isa<SelectInst>(I)) {
if (AnalyzeGlobal(I, GS, PHIUsers)) return true;
GS.isNotSuitableForSRA = true;
} else if (PHINode *PN = dyn_cast<PHINode>(I)) {
@@ -223,6 +224,16 @@ static bool AnalyzeGlobal(Value *V, GlobalStatus &GS,
GS.isNotSuitableForSRA = true;
} else if (isa<SetCondInst>(I)) {
GS.isNotSuitableForSRA = true;
+ } else if (isa<MemCpyInst>(I) || isa<MemMoveInst>(I)) {
+ if (I->getOperand(1) == V)
+ GS.StoredType = GlobalStatus::isStored;
+ if (I->getOperand(2) == V)
+ GS.isLoaded = true;
+ GS.isNotSuitableForSRA = true;
+ } else if (isa<MemSetInst>(I)) {
+ assert(I->getOperand(1) == V && "Memset only takes one pointer!");
+ GS.StoredType = GlobalStatus::isStored;
+ GS.isNotSuitableForSRA = true;
} else {
return true; // Any other non-load instruction might take address!
}
@@ -270,6 +281,7 @@ static Constant *getAggregateConstantElement(Constant *Agg, Constant *Idx) {
}
static Constant *TraverseGEPInitializer(User *GEP, Constant *Init) {
+ if (Init == 0) return 0;
if (GEP->getNumOperands() == 1 ||
!isa<Constant>(GEP->getOperand(1)) ||
!cast<Constant>(GEP->getOperand(1))->isNullValue())
@@ -294,47 +306,50 @@ static bool CleanupConstantGlobalUsers(Value *V, Constant *Init) {
User *U = *UI++;
if (LoadInst *LI = dyn_cast<LoadInst>(U)) {
- // Replace the load with the initializer.
- LI->replaceAllUsesWith(Init);
- LI->eraseFromParent();
- Changed = true;
+ if (Init) {
+ // Replace the load with the initializer.
+ LI->replaceAllUsesWith(Init);
+ LI->eraseFromParent();
+ Changed = true;
+ }
} else if (StoreInst *SI = dyn_cast<StoreInst>(U)) {
// Store must be unreachable or storing Init into the global.
SI->eraseFromParent();
Changed = true;
} else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(U)) {
if (CE->getOpcode() == Instruction::GetElementPtr) {
- if (Constant *SubInit = TraverseGEPInitializer(CE, Init))
- Changed |= CleanupConstantGlobalUsers(CE, SubInit);
- if (CE->use_empty()) {
- CE->destroyConstant();
- Changed = true;
- }
+ Constant *SubInit = TraverseGEPInitializer(CE, Init);
+ Changed |= CleanupConstantGlobalUsers(CE, SubInit);
+ } else if (CE->getOpcode() == Instruction::Cast &&
+ isa<PointerType>(CE->getType())) {
+ // Pointer cast, delete any stores and memsets to the global.
+ Changed |= CleanupConstantGlobalUsers(CE, 0);
}
- } else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(U)) {
- if (Constant *SubInit = TraverseGEPInitializer(GEP, Init))
- Changed |= CleanupConstantGlobalUsers(GEP, SubInit);
- else {
- // If this GEP has variable indexes, we should still be able to delete
- // any stores through it.
- for (Value::use_iterator GUI = GEP->use_begin(), E = GEP->use_end();
- GUI != E;)
- if (StoreInst *SI = dyn_cast<StoreInst>(*GUI++)) {
- SI->eraseFromParent();
- Changed = true;
- }
+
+ if (CE->use_empty()) {
+ CE->destroyConstant();
+ Changed = true;
}
+ } else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(U)) {
+ Constant *SubInit = TraverseGEPInitializer(GEP, Init);
+ Changed |= CleanupConstantGlobalUsers(GEP, SubInit);
if (GEP->use_empty()) {
GEP->eraseFromParent();
Changed = true;
}
+ } else if (MemIntrinsic *MI = dyn_cast<MemIntrinsic>(U)) { // memset/cpy/mv
+ if (MI->getRawDest() == V) {
+ MI->eraseFromParent();
+ Changed = true;
+ }
+
} else if (Constant *C = dyn_cast<Constant>(U)) {
// If we have a chain of dead constantexprs or other things dangling from
// us, and if they are all dead, nuke them without remorse.
if (ConstantIsDead(C)) {
C->destroyConstant();
- // This could have incalidated UI, start over from scratch.x
+ // This could have invalidated UI, start over from scratch.
CleanupConstantGlobalUsers(V, Init);
return true;
}