When inlining through an 'nounwind' call, mark inlined
calls 'nounwind'.  It is important for correct C++
exception handling that nounwind markings do not get
lost, so this transformation is actually needed for
correctness.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@45218 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Transforms/IPO/PruneEH.cpp b/lib/Transforms/IPO/PruneEH.cpp
index 69bb1f6..529f98e 100644
--- a/lib/Transforms/IPO/PruneEH.cpp
+++ b/lib/Transforms/IPO/PruneEH.cpp
@@ -122,17 +122,15 @@
   // If the SCC doesn't unwind or doesn't throw, note this fact.
   if (!SCCMightUnwind || !SCCMightReturn)
     for (unsigned i = 0, e = SCC.size(); i != e; ++i) {
-      const ParamAttrsList *PAL = SCC[i]->getFunction()->getParamAttrs();
-      uint16_t RAttributes = PAL ? PAL->getParamAttrs(0) : 0;
+      uint16_t NewAttributes = ParamAttr::None;
 
       if (!SCCMightUnwind)
-        RAttributes |= ParamAttr::NoUnwind;
+        NewAttributes |= ParamAttr::NoUnwind;
       if (!SCCMightReturn)
-        RAttributes |= ParamAttr::NoReturn;
+        NewAttributes |= ParamAttr::NoReturn;
 
-      ParamAttrsVector modVec;
-      modVec.push_back(ParamAttrsWithIndex::get(0, RAttributes));
-      PAL = ParamAttrsList::getModified(PAL, modVec);
+      const ParamAttrsList *PAL = SCC[i]->getFunction()->getParamAttrs();
+      PAL = ParamAttrsList::includeAttrs(PAL, 0, NewAttributes);
       SCC[i]->getFunction()->setParamAttrs(PAL);
     }
 
diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp
index 166b484..d7c4923 100644
--- a/lib/Transforms/Scalar/InstructionCombining.cpp
+++ b/lib/Transforms/Scalar/InstructionCombining.cpp
@@ -8026,16 +8026,9 @@
       }
   }
 
-  if (isa<InlineAsm>(Callee) && !CS.paramHasAttr(0, ParamAttr::NoUnwind)) {
+  if (isa<InlineAsm>(Callee) && !CS.doesNotThrow()) {
     // Inline asm calls cannot throw - mark them 'nounwind'.
-    const ParamAttrsList *PAL = CS.getParamAttrs();
-    uint16_t RAttributes = PAL ? PAL->getParamAttrs(0) : 0;
-    RAttributes |= ParamAttr::NoUnwind;
-
-    ParamAttrsVector modVec;
-    modVec.push_back(ParamAttrsWithIndex::get(0, RAttributes));
-    PAL = ParamAttrsList::getModified(PAL, modVec);
-    CS.setParamAttrs(PAL);
+    CS.setDoesNotThrow();
     Changed = true;
   }
 
diff --git a/lib/Transforms/Utils/InlineFunction.cpp b/lib/Transforms/Utils/InlineFunction.cpp
index a2b834b..dba0e69 100644
--- a/lib/Transforms/Utils/InlineFunction.cpp
+++ b/lib/Transforms/Utils/InlineFunction.cpp
@@ -194,6 +194,10 @@
   bool MustClearTailCallFlags =
     isa<CallInst>(TheCall) && !cast<CallInst>(TheCall)->isTailCall();
 
+  // If the call to the callee cannot throw, set the 'nounwind' flag on any
+  // calls that we inline.
+  bool MarkNoUnwind = CS.doesNotThrow();
+
   BasicBlock *OrigBB = TheCall->getParent();
   Function *Caller = OrigBB->getParent();
 
@@ -207,7 +211,7 @@
   std::vector<ReturnInst*> Returns;
   ClonedCodeInfo InlinedFunctionInfo;
   Function::iterator FirstNewBlock;
-  
+
   { // Scope to destroy ValueMap after cloning.
     DenseMap<const Value*, Value*> ValueMap;
 
@@ -323,15 +327,33 @@
 
   // If we are inlining tail call instruction through a call site that isn't 
   // marked 'tail', we must remove the tail marker for any calls in the inlined
-  // code.
-  if (MustClearTailCallFlags && InlinedFunctionInfo.ContainsCalls) {
+  // code.  Also, calls inlined through a 'nounwind' call site should be marked
+  // 'nounwind'.
+  if (InlinedFunctionInfo.ContainsCalls &&
+      (MustClearTailCallFlags || MarkNoUnwind)) {
     for (Function::iterator BB = FirstNewBlock, E = Caller->end();
          BB != E; ++BB)
       for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I)
-        if (CallInst *CI = dyn_cast<CallInst>(I))
-          CI->setTailCall(false);
+        if (CallInst *CI = dyn_cast<CallInst>(I)) {
+          if (MustClearTailCallFlags)
+            CI->setTailCall(false);
+          if (MarkNoUnwind)
+            CI->setDoesNotThrow();
+        }
   }
 
+  // If we are inlining through a 'nounwind' call site then any inlined 'unwind'
+  // instructions are unreachable.
+  if (InlinedFunctionInfo.ContainsUnwinds && MarkNoUnwind)
+    for (Function::iterator BB = FirstNewBlock, E = Caller->end();
+         BB != E; ++BB) {
+      TerminatorInst *Term = BB->getTerminator();
+      if (isa<UnwindInst>(Term)) {
+        new UnreachableInst(Term);
+        BB->getInstList().erase(Term);
+      }
+    }
+
   // If we are inlining for an invoke instruction, we must make sure to rewrite
   // any inlined 'unwind' instructions into branches to the invoke exception
   // destination, and call instructions into invoke instructions.