Chris Lattner | 8d1da1a | 2004-02-25 21:34:36 +0000 | [diff] [blame] | 1 | //===- GlobalConstifier.cpp - Mark read-only globals constant -------------===// |
| 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file was developed by the LLVM research group and is distributed under |
| 6 | // the University of Illinois Open Source License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | // |
| 10 | // This pass loops over the non-constant internal global variables in the |
| 11 | // program. If it can prove that they are never written to, it marks them |
| 12 | // constant. |
| 13 | // |
| 14 | // NOTE: this should eventually use the alias analysis interfaces to do the |
| 15 | // transformation, but for now we just stick with a simple solution. DSA in |
| 16 | // particular could give a much more accurate answer to the mod/ref query, but |
| 17 | // it's not quite ready for this. |
| 18 | // |
| 19 | //===----------------------------------------------------------------------===// |
| 20 | |
| 21 | #include "llvm/Transforms/IPO.h" |
| 22 | #include "llvm/Constants.h" |
Chris Lattner | e82c217 | 2004-02-27 18:09:25 +0000 | [diff] [blame] | 23 | #include "llvm/Instructions.h" |
Chris Lattner | 8d1da1a | 2004-02-25 21:34:36 +0000 | [diff] [blame] | 24 | #include "llvm/Module.h" |
| 25 | #include "llvm/Pass.h" |
| 26 | #include "Support/Debug.h" |
| 27 | #include "Support/Statistic.h" |
| 28 | using namespace llvm; |
| 29 | |
| 30 | namespace { |
| 31 | Statistic<> NumMarked("constify", "Number of globals marked constant"); |
| 32 | |
| 33 | struct Constifier : public Pass { |
| 34 | bool run(Module &M); |
| 35 | }; |
| 36 | |
| 37 | RegisterOpt<Constifier> X("constify", "Global Constifier"); |
| 38 | } |
| 39 | |
| 40 | Pass *llvm::createGlobalConstifierPass() { return new Constifier(); } |
| 41 | |
| 42 | /// isStoredThrough - Return false if the specified pointer is provably never |
| 43 | /// stored through. If we can't tell, we must conservatively assume it might. |
| 44 | /// |
| 45 | static bool isStoredThrough(Value *V) { |
| 46 | for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); UI != E; ++UI) |
| 47 | if (Constant *C = dyn_cast<Constant>(*UI)) { |
| 48 | if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) { |
| 49 | if (isStoredThrough(CE)) |
| 50 | return true; |
| 51 | } else if (ConstantPointerRef *CPR = dyn_cast<ConstantPointerRef>(C)) { |
| 52 | if (isStoredThrough(CPR)) return true; |
| 53 | } else { |
| 54 | // Must be an element of a constant array or something. |
| 55 | return true; |
| 56 | } |
| 57 | } else if (Instruction *I = dyn_cast<Instruction>(*UI)) { |
| 58 | if (I->getOpcode() == Instruction::GetElementPtr) { |
| 59 | if (isStoredThrough(I)) return true; |
Chris Lattner | e82c217 | 2004-02-27 18:09:25 +0000 | [diff] [blame] | 60 | } else if (!isa<LoadInst>(*UI) && !isa<SetCondInst>(*UI)) |
Chris Lattner | 8d1da1a | 2004-02-25 21:34:36 +0000 | [diff] [blame] | 61 | return true; // Any other non-load instruction might store! |
| 62 | } else { |
| 63 | // Otherwise must be a global or some other user. |
| 64 | return true; |
| 65 | } |
| 66 | |
| 67 | return false; |
| 68 | } |
| 69 | |
| 70 | bool Constifier::run(Module &M) { |
| 71 | bool Changed = false; |
| 72 | for (Module::giterator GV = M.gbegin(), E = M.gend(); GV != E; ++GV) |
| 73 | if (!GV->isConstant() && GV->hasInternalLinkage() && GV->hasInitializer()) { |
| 74 | if (!isStoredThrough(GV)) { |
| 75 | DEBUG(std::cerr << "MARKING CONSTANT: " << *GV << "\n"); |
| 76 | GV->setConstant(true); |
| 77 | ++NumMarked; |
| 78 | Changed = true; |
| 79 | } |
| 80 | } |
| 81 | return Changed; |
| 82 | } |