diff options
-rw-r--r-- | lib/Transforms/IPO/GlobalOpt.cpp | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/lib/Transforms/IPO/GlobalOpt.cpp b/lib/Transforms/IPO/GlobalOpt.cpp new file mode 100644 index 0000000000..8f6cbbdfda --- /dev/null +++ b/lib/Transforms/IPO/GlobalOpt.cpp @@ -0,0 +1,82 @@ +//===- GlobalConstifier.cpp - Mark read-only globals constant -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass loops over the non-constant internal global variables in the +// program. If it can prove that they are never written to, it marks them +// constant. +// +// NOTE: this should eventually use the alias analysis interfaces to do the +// transformation, but for now we just stick with a simple solution. DSA in +// particular could give a much more accurate answer to the mod/ref query, but +// it's not quite ready for this. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Transforms/IPO.h" +#include "llvm/Constants.h" +#include "llvm/iMemory.h" +#include "llvm/Module.h" +#include "llvm/Pass.h" +#include "Support/Debug.h" +#include "Support/Statistic.h" +using namespace llvm; + +namespace { + Statistic<> NumMarked("constify", "Number of globals marked constant"); + + struct Constifier : public Pass { + bool run(Module &M); + }; + + RegisterOpt<Constifier> X("constify", "Global Constifier"); +} + +Pass *llvm::createGlobalConstifierPass() { return new Constifier(); } + +/// 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) { + for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); UI != E; ++UI) + if (Constant *C = dyn_cast<Constant>(*UI)) { + if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) { + if (isStoredThrough(CE)) + return true; + } else if (ConstantPointerRef *CPR = dyn_cast<ConstantPointerRef>(C)) { + if (isStoredThrough(CPR)) return true; + } else { + // Must be an element of a constant array or something. + return true; + } + } else if (Instruction *I = dyn_cast<Instruction>(*UI)) { + if (I->getOpcode() == Instruction::GetElementPtr) { + if (isStoredThrough(I)) return true; + } else if (!isa<LoadInst>(*UI)) + return true; // Any other non-load instruction might store! + } else { + // Otherwise must be a global or some other user. + return true; + } + + return false; +} + +bool Constifier::run(Module &M) { + bool Changed = false; + for (Module::giterator GV = M.gbegin(), E = M.gend(); GV != E; ++GV) + if (!GV->isConstant() && GV->hasInternalLinkage() && GV->hasInitializer()) { + if (!isStoredThrough(GV)) { + DEBUG(std::cerr << "MARKING CONSTANT: " << *GV << "\n"); + GV->setConstant(true); + ++NumMarked; + Changed = true; + } + } + return Changed; +} |