diff options
author | Chris Lattner <sabre@nondot.org> | 2004-08-14 20:57:17 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2004-08-14 20:57:17 +0000 |
commit | 77a2a9d9dae5dbe551cec102e37ea02f45da44ed (patch) | |
tree | 32d758a7a3ff09f5c96e27c9993d2633fa70da3f /lib/Transforms | |
parent | 9a8e0087514e4b8de20b555ace77e3b191fa1ade (diff) | |
download | external_llvm-77a2a9d9dae5dbe551cec102e37ea02f45da44ed.zip external_llvm-77a2a9d9dae5dbe551cec102e37ea02f45da44ed.tar.gz external_llvm-77a2a9d9dae5dbe551cec102e37ea02f45da44ed.tar.bz2 |
Implement test/Regression/Transforms/GlobalConstifier/phi-select.llx
This allows more globals to be marked constant, particularly global arrays.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@15735 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms')
-rw-r--r-- | lib/Transforms/IPO/GlobalOpt.cpp | 22 |
1 files changed, 16 insertions, 6 deletions
diff --git a/lib/Transforms/IPO/GlobalOpt.cpp b/lib/Transforms/IPO/GlobalOpt.cpp index 97518a3..f9be0ad 100644 --- a/lib/Transforms/IPO/GlobalOpt.cpp +++ b/lib/Transforms/IPO/GlobalOpt.cpp @@ -25,6 +25,7 @@ #include "llvm/Pass.h" #include "Support/Debug.h" #include "Support/Statistic.h" +#include <set> using namespace llvm; namespace { @@ -52,16 +53,23 @@ static bool ContainingFunctionIsTriviallyDead(Instruction *I) { /// isStoredThrough - Return false if the specified pointer is provably never /// stored through. If we can't tell, we must conservatively assume it might. /// -static bool isStoredThrough(Value *V) { +static bool isStoredThrough(Value *V, std::set<PHINode*> &PHIUsers) { for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); UI != E; ++UI) if (ConstantExpr *CE = dyn_cast<ConstantExpr>(*UI)) { - if (isStoredThrough(CE)) + if (isStoredThrough(CE, PHIUsers)) return true; } else if (Instruction *I = dyn_cast<Instruction>(*UI)) { if (!ContainingFunctionIsTriviallyDead(I)) { - if (I->getOpcode() == Instruction::GetElementPtr) { - if (isStoredThrough(I)) return true; - } else if (!isa<LoadInst>(*UI) && !isa<SetCondInst>(*UI)) { + if (I->getOpcode() == Instruction::GetElementPtr || + I->getOpcode() == Instruction::Select) { + if (isStoredThrough(I, PHIUsers)) return true; + } else if (PHINode *PN = dyn_cast<PHINode>(I)) { + // PHI nodes we can check just like select or GEP instructions, but we + // have to be careful about infinite recursion. + if (PHIUsers.insert(PN).second) // Not already visited. + if (isStoredThrough(I, PHIUsers)) return true; + + } else if (!isa<LoadInst>(I) && !isa<SetCondInst>(I)) { return true; // Any other non-load instruction might store! } } @@ -75,14 +83,16 @@ static bool isStoredThrough(Value *V) { bool Constifier::run(Module &M) { bool Changed = false; + std::set<PHINode*> PHIUsers; for (Module::giterator GV = M.gbegin(), E = M.gend(); GV != E; ++GV) if (!GV->isConstant() && GV->hasInternalLinkage() && GV->hasInitializer()) { - if (!isStoredThrough(GV)) { + if (!isStoredThrough(GV, PHIUsers)) { DEBUG(std::cerr << "MARKING CONSTANT: " << *GV << "\n"); GV->setConstant(true); ++NumMarked; Changed = true; } + PHIUsers.clear(); } return Changed; } |