Adding dllimport, dllexport and external weak linkage types.
[oota-llvm.git] / lib / Transforms / IPO / GlobalOpt.cpp
index 6170bfcac641a144168f5bf148163673ff43cde6..609bd94aa1a6969b211414afdbd1aa8032c7d117 100644 (file)
@@ -27,8 +27,9 @@
 #include "llvm/Transforms/Utils/Local.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/ADT/StringExtras.h"
-#include <set>
 #include <algorithm>
+#include <iostream>
+#include <set>
 using namespace llvm;
 
 namespace {
@@ -59,10 +60,10 @@ namespace {
     bool OptimizeFunctions(Module &M);
     bool OptimizeGlobalVars(Module &M);
     bool OptimizeGlobalCtorsList(GlobalVariable *&GCL);
-    bool ProcessInternalGlobal(GlobalVariable *GV, Module::global_iterator &GVI);
+    bool ProcessInternalGlobal(GlobalVariable *GV,Module::global_iterator &GVI);
   };
 
-  RegisterOpt<GlobalOpt> X("globalopt", "Global Variable Optimizer");
+  RegisterPass<GlobalOpt> X("globalopt", "Global Variable Optimizer");
 }
 
 ModulePass *llvm::createGlobalOptimizerPass() { return new GlobalOpt(); }
@@ -337,7 +338,7 @@ static bool CleanupConstantGlobalUsers(Value *V, Constant *Init) {
       Constant *SubInit = 0;
       ConstantExpr *CE = 
         dyn_cast_or_null<ConstantExpr>(ConstantFoldInstruction(GEP));
-      if (CE && CE->getOpcode() == Instruction::GetElementPtr)
+      if (Init && CE && CE->getOpcode() == Instruction::GetElementPtr)
         SubInit = ConstantFoldLoadThroughGEPConstantExpr(Init, CE);
       Changed |= CleanupConstantGlobalUsers(GEP, SubInit);
 
@@ -678,7 +679,7 @@ static GlobalVariable *OptimizeGlobalAddressOfMalloc(GlobalVariable *GV,
                                  (unsigned)NElements->getRawValue());
     MallocInst *NewMI =
       new MallocInst(NewTy, Constant::getNullValue(Type::UIntTy),
-                     MI->getName(), MI);
+                     MI->getAlignment(), MI->getName(), MI);
     std::vector<Value*> Indices;
     Indices.push_back(Constant::getNullValue(Type::IntTy));
     Indices.push_back(Indices[0]);
@@ -799,7 +800,8 @@ static bool ValueIsOnlyUsedLocallyOrStoredToOneGlobal(Instruction *V,
 // OptimizeOnceStoredGlobal - Try to optimize globals based on the knowledge
 // that only one value (besides its initializer) is ever stored to the global.
 static bool OptimizeOnceStoredGlobal(GlobalVariable *GV, Value *StoredOnceVal,
-                                     Module::global_iterator &GVI, TargetData &TD) {
+                                     Module::global_iterator &GVI,
+                                     TargetData &TD) {
   if (CastInst *CI = dyn_cast<CastInst>(StoredOnceVal))
     StoredOnceVal = CI->getOperand(0);
   else if (GetElementPtrInst *GEPI =dyn_cast<GetElementPtrInst>(StoredOnceVal)){
@@ -950,6 +952,7 @@ bool GlobalOpt::ProcessInternalGlobal(GlobalVariable *GV,
       DEBUG(std::cerr << "LOCALIZING GLOBAL: " << *GV);
       Instruction* FirstI = GS.AccessingFunction->getEntryBlock().begin();
       const Type* ElemTy = GV->getType()->getElementType();
+      // FIXME: Pass Global's alignment when globals have alignment
       AllocaInst* Alloca = new AllocaInst(ElemTy, NULL, GV->getName(), FirstI);
       if (!isa<UndefValue>(GV->getInitializer()))
         new StoreInst(GV->getInitializer(), Alloca, FirstI);
@@ -1113,7 +1116,8 @@ bool GlobalOpt::OptimizeGlobalVars(Module &M) {
 /// FindGlobalCtors - Find the llvm.globalctors list, verifying that all
 /// initializers have an init priority of 65535.
 GlobalVariable *GlobalOpt::FindGlobalCtors(Module &M) {
-  for (Module::giterator I = M.global_begin(), E = M.global_end(); I != E; ++I)
+  for (Module::global_iterator I = M.global_begin(), E = M.global_end();
+       I != E; ++I)
     if (I->getName() == "llvm.global_ctors") {
       // Found it, verify it's an array of { int, void()* }.
       const ArrayType *ATy =dyn_cast<ArrayType>(I->getType()->getElementType());
@@ -1239,13 +1243,18 @@ static Constant *getVal(std::map<Value*, Constant*> &ComputedValues,
 /// we punt.  We basically just support direct accesses to globals and GEP's of
 /// globals.  This should be kept up to date with CommitValueTo.
 static bool isSimpleEnoughPointerToCommit(Constant *C) {
-  if (GlobalVariable *GV = dyn_cast<GlobalVariable>(C))
+  if (GlobalVariable *GV = dyn_cast<GlobalVariable>(C)) {
+    if (!GV->hasExternalLinkage() && !GV->hasInternalLinkage())
+      return false;  // do not allow weak/linkonce/dllimport/dllexport linkage.
     return !GV->isExternal();  // reject external globals.
+  }
   if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C))
     // Handle a constantexpr gep.
     if (CE->getOpcode() == Instruction::GetElementPtr &&
         isa<GlobalVariable>(CE->getOperand(0))) {
       GlobalVariable *GV = cast<GlobalVariable>(CE->getOperand(0));
+      if (!GV->hasExternalLinkage() && !GV->hasInternalLinkage())
+        return false;  // do not allow weak/linkonce/dllimport/dllexport linkage.
       return GV->hasInitializer() &&
              ConstantFoldLoadThroughGEPConstantExpr(GV->getInitializer(), CE);
     }
@@ -1442,24 +1451,36 @@ static bool EvaluateFunction(Function *F, Constant *&RetVal,
                                               AI->getName()));
       InstResult = AllocaTmps.back();     
     } else if (CallInst *CI = dyn_cast<CallInst>(CurInst)) {
+      // Cannot handle inline asm.
+      if (isa<InlineAsm>(CI->getOperand(0))) return false;
+
       // Resolve function pointers.
       Function *Callee = dyn_cast<Function>(getVal(Values, CI->getOperand(0)));
       if (!Callee) return false;  // Cannot resolve.
-      
-      if (Callee->isExternal() || Callee->getFunctionType()->isVarArg()) {
-        return false;  // TODO: Constant fold calls.
-      }
-      
+
       std::vector<Constant*> Formals;
       for (unsigned i = 1, e = CI->getNumOperands(); i != e; ++i)
         Formals.push_back(getVal(Values, CI->getOperand(i)));
-      Constant *RetVal;
       
-      // Execute the call, if successful, use the return value.
-      if (!EvaluateFunction(Callee, RetVal, Formals, CallStack,
-                            MutatedMemory, AllocaTmps))
-        return false;
-      InstResult = RetVal;
+      if (Callee->isExternal()) {
+        // If this is a function we can constant fold, do it.
+        if (Constant *C = ConstantFoldCall(Callee, Formals)) {
+          InstResult = C;
+        } else {
+          return false;
+        }
+      } else {
+        if (Callee->getFunctionType()->isVarArg())
+          return false;
+        
+        Constant *RetVal;
+        
+        // Execute the call, if successful, use the return value.
+        if (!EvaluateFunction(Callee, RetVal, Formals, CallStack,
+                              MutatedMemory, AllocaTmps))
+          return false;
+        InstResult = RetVal;
+      }
     } else if (TerminatorInst *TI = dyn_cast<TerminatorInst>(CurInst)) {
       BasicBlock *NewBB = 0;
       if (BranchInst *BI = dyn_cast<BranchInst>(CurInst)) {