fix pasto
[oota-llvm.git] / lib / Transforms / IPO / GlobalOpt.cpp
index ea8080e35e89590cde78b2f88efec3eb7d555cf1..fd71dfb826148bcd968f8fda23dfdb86ff5f63ac 100644 (file)
@@ -21,6 +21,7 @@
 #include "llvm/Instructions.h"
 #include "llvm/IntrinsicInst.h"
 #include "llvm/Module.h"
+#include "llvm/ParameterAttributes.h"
 #include "llvm/Pass.h"
 #include "llvm/Analysis/ConstantFolding.h"
 #include "llvm/Target/TargetData.h"
@@ -46,6 +47,7 @@ STATISTIC(NumLocalized , "Number of globals localized");
 STATISTIC(NumShrunkToBool  , "Number of global vars shrunk to booleans");
 STATISTIC(NumFastCallFns   , "Number of functions converted to fastcc");
 STATISTIC(NumCtorsEvaluated, "Number of static ctors evaluated");
+STATISTIC(NumNestRemoved   , "Number of nest attributes removed");
 
 namespace {
   struct VISIBILITY_HIDDEN GlobalOpt : public ModulePass {
@@ -163,12 +165,15 @@ static bool AnalyzeGlobal(Value *V, GlobalStatus &GS,
         else if (GS.AccessingFunction != F)
           GS.HasMultipleAccessingFunctions = true;
       }
-      if (isa<LoadInst>(I)) {
+      if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
         GS.isLoaded = true;
+        if (LI->isVolatile()) return true;  // Don't hack on volatile loads.
       } else if (StoreInst *SI = dyn_cast<StoreInst>(I)) {
         // Don't allow a store OF the address, only stores TO the address.
         if (SI->getOperand(0) == V) return true;
 
+        if (SI->isVolatile()) return true;  // Don't hack on volatile stores.
+
         // If this is a direct store to the global (i.e., the global is a scalar
         // value, not an aggregate), keep more specific information about
         // stores.
@@ -1587,6 +1592,35 @@ static void ChangeCalleesToFastCall(Function *F) {
   }
 }
 
+static const ParamAttrsList *StripNest(const ParamAttrsList *Attrs) {
+  if (Attrs) {
+    for (unsigned i = 0, e = Attrs->size(); i != e; ++i) {
+      uint16_t A = Attrs->getParamAttrsAtIndex(i);
+      if (A & ParamAttr::Nest) {
+        Attrs = ParamAttrsList::excludeAttrs(Attrs, Attrs->getParamIndex(i),
+                                             ParamAttr::Nest);
+        // There can be only one.
+        break;
+      }
+    }
+  }
+
+  return Attrs;
+}
+
+static void RemoveNestAttribute(Function *F) {
+  F->setParamAttrs(StripNest(F->getParamAttrs()));
+  for (Value::use_iterator UI = F->use_begin(), E = F->use_end(); UI != E;++UI){
+    Instruction *User = cast<Instruction>(*UI);
+    if (CallInst *CI = dyn_cast<CallInst>(User)) {
+      CI->setParamAttrs(StripNest(CI->getParamAttrs()));
+    } else {
+      InvokeInst *II = cast<InvokeInst>(User);
+      II->setParamAttrs(StripNest(II->getParamAttrs()));
+    }
+  }
+}
+
 bool GlobalOpt::OptimizeFunctions(Module &M) {
   bool Changed = false;
   // Optimize functions.
@@ -1598,16 +1632,27 @@ bool GlobalOpt::OptimizeFunctions(Module &M) {
       M.getFunctionList().erase(F);
       Changed = true;
       ++NumFnDeleted;
-    } else if (F->hasInternalLinkage() &&
-               F->getCallingConv() == CallingConv::C &&  !F->isVarArg() &&
-               OnlyCalledDirectly(F)) {
-      // If this function has C calling conventions, is not a varargs
-      // function, and is only called directly, promote it to use the Fast
-      // calling convention.
-      F->setCallingConv(CallingConv::Fast);
-      ChangeCalleesToFastCall(F);
-      ++NumFastCallFns;
-      Changed = true;
+    } else if (F->hasInternalLinkage()) {
+      if (F->getCallingConv() == CallingConv::C && !F->isVarArg() &&
+          OnlyCalledDirectly(F)) {
+        // If this function has C calling conventions, is not a varargs
+        // function, and is only called directly, promote it to use the Fast
+        // calling convention.
+        F->setCallingConv(CallingConv::Fast);
+        ChangeCalleesToFastCall(F);
+        ++NumFastCallFns;
+        Changed = true;
+      }
+
+      if (F->getParamAttrs() &&
+          F->getParamAttrs()->hasAttrSomewhere(ParamAttr::Nest) &&
+          OnlyCalledDirectly(F)) {
+        // The function is not used by a trampoline intrinsic, so it is safe
+        // to remove the 'nest' attribute.
+        RemoveNestAttribute(F);
+        ++NumNestRemoved;
+        Changed = true;
+      }
     }
   }
   return Changed;