Index: lib/Transforms/IPO/FunctionAttrs.cpp
===================================================================
--- lib/Transforms/IPO/FunctionAttrs.cpp
+++ lib/Transforms/IPO/FunctionAttrs.cpp
@@ -17,6 +17,7 @@
 #include "llvm/ADT/SCCIterator.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallBitVector.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/SmallVector.h"
@@ -74,6 +75,7 @@
 STATISTIC(NumNoAlias, "Number of function returns marked noalias");
 STATISTIC(NumNonNullReturn, "Number of function returns marked nonnull");
 STATISTIC(NumNoRecurse, "Number of functions marked as norecurse");
+STATISTIC(NumNoUnwind, "Number of functions marked as nounwind");
 
 // FIXME: This is disabled by default to avoid exposing security vulnerabilities
 // in C/C++ code compiled by clang:
@@ -1037,49 +1039,208 @@
   return MadeChange;
 }
 
-/// Remove the convergent attribute from all functions in the SCC if every
-/// callsite within the SCC is not convergent (except for calls to functions
-/// within the SCC).  Returns true if changes were made.
-static bool removeConvergentAttrs(const SCCNodeSet &SCCNodes) {
-  // For every function in SCC, ensure that either
-  //  * it is not convergent, or
-  //  * we can remove its convergent attribute.
-  bool HasConvergentFn = false;
+namespace {
+
+/// Collects a set of attribute inference requests and performs them all in one
+/// go on a single SCC Node. Inference involves scanning function bodies
+/// looking for instructions that violate attribute assumptions.
+/// As soon as all the bodies are fine we are free to set the attribute.
+/// Customization of inference for individual attributes is performed by
+/// providing a handful of predicates for each attribute.
+class AttributeInferer {
+
+  struct InferenceDescriptor {
+    /// Only "exact" definitions can be used to infer this attribute.
+    bool RequiresExactDefinition;
+
+    /// Returns true if this function does not have to be handled.
+    /// General intent for this predicate is to provide an optimization
+    /// for functions that do not need this attribute inference at all
+    /// (say, for functions that already have the attribute).
+    std::function<bool(const Function &)> SkipFunction;
+
+    /// Returns true if this instruction violates attribute assumptions.
+    std::function<bool(Instruction &)> InstrBreaksAttribute;
+
+    /// Sets the inferred attribute for this function.
+    std::function<void(Function &)> SetAttribute;
+  };
+
+  SmallVector<InferenceDescriptor, 4> InferencePredicates;
+
+public:
+  void registerAttrInference(InferenceDescriptor Predicates) {
+    InferencePredicates.push_back(Predicates);
+  }
+
+  bool run(const SCCNodeSet &SCCNodes) const;
+};
+
+/// Perform all the requested attribute inference actions according to the
+/// attribute predicates stored before.
+bool AttributeInferer::run(const SCCNodeSet &SCCNodes) const {
+  unsigned AttrCount = InferencePredicates.size();
+
+  /// true for attributes whose assumptions were not invalidated
+  SmallBitVector ValidAttrs(AttrCount, true);
+
+  /// true for "valid" attributes that went through at least one instruction
+  /// scan
+  SmallBitVector SuccessfullyScanned(AttrCount, false);
+
+  // Go through all the functions in SCC and check corresponding attribute
+  // assumptions for each of them.
   for (Function *F : SCCNodes) {
-    if (!F->isConvergent()) continue;
-    HasConvergentFn = true;
 
-    // Can't remove convergent from function declarations.
-    if (F->isDeclaration()) return false;
+    // No attributes whose assumptions are still valid - done.
+    if (ValidAttrs.count() == 0)
+      return false;
+
+    // Check if our attributes ever need scanning/can be scanned.
+    SmallBitVector ScanAttrsHere = ValidAttrs;
+    for (unsigned A = 0; A < AttrCount; A++) {
+      if (!ScanAttrsHere[A])
+        continue;
+      auto &IP = InferencePredicates[A];
+
+      // This function is explicitly skipped from inference w/o breaking the main
+      // per-Function loop. Perhaps it already has the attribute.
+      if (IP.SkipFunction(*F))
+        ScanAttrsHere[A] = false;
+      else if (F->isDeclaration() ||
+	       (IP.RequiresExactDefinition && !F->hasExactDefinition())) {
+	// No instructions to scan, can't handle this attribute.
+	ScanAttrsHere[A] = false;
+	ValidAttrs[A] = false;
+      }
+    }
 
-    // Can't remove convergent if any of our functions has a convergent call to a
-    // function not in the SCC.
+    // Nothing to scan in this func.
+    if (ScanAttrsHere.count() == 0)
+      continue;
+
+    // Start instruction scan.
     for (Instruction &I : instructions(*F)) {
-      CallSite CS(&I);
-      // Bail if CS is a convergent call to a function not in the SCC.
-      if (CS && CS.isConvergent() &&
-          SCCNodes.count(CS.getCalledFunction()) == 0)
-        return false;
+      for (unsigned A = 0; A < AttrCount; A++) {
+        if (!ScanAttrsHere[A])
+          continue;
+
+        auto &IP = InferencePredicates[A];
+        if (IP.InstrBreaksAttribute(I)) {
+          ScanAttrsHere[A] = false;
+          ValidAttrs[A] = false;
+        }
+      }
+
+      if (ScanAttrsHere.count() == 0)
+        break;
     }
+    SuccessfullyScanned |= ScanAttrsHere;
   }
 
-  // If the SCC doesn't have any convergent functions, we have nothing to do.
-  if (!HasConvergentFn) return false;
+  // If the SCC doesn't have functions that were successfully scanned then we
+  // have nothing to do.
+  if (SuccessfullyScanned.count() == 0)
+    return false;
 
-  // If we got here, all of the calls the SCC makes to functions not in the SCC
-  // are non-convergent.  Therefore all of the SCC's functions can also be made
-  // non-convergent.  We'll remove the attr from the callsites in
-  // InstCombineCalls.
-  for (Function *F : SCCNodes) {
-    if (!F->isConvergent()) continue;
+  // If we got here, all of the SCC's functions adhere to the attribute
+  // assumptions being checked above, so we go and set all the attributes that
+  // are still valid.
+  for (Function *F : SCCNodes)
+    for (unsigned A = 0; A < AttrCount; A++) {
+      if (!SuccessfullyScanned[A])
+        continue;
 
-    DEBUG(dbgs() << "Removing convergent attr from fn " << F->getName()
-                 << "\n");
-    F->setNotConvergent();
-  }
+      auto &IP = InferencePredicates[A];
+      if (IP.SkipFunction(*F))
+        continue;
+
+      IP.SetAttribute(*F);
+    }
   return true;
 }
 
+} // end anonymous namespace
+
+/// helper for non-Convergent inference predicate InstrBreaksAttribute
+static bool InstrBreaksNonConvergent(Instruction &I,
+                                      const SCCNodeSet &SCCNodes) {
+  const CallSite CS(&I);
+  // Breaks non-convergent assumption if CS is a convergent call to a function
+  // not in the SCC.
+  return CS && CS.isConvergent() && SCCNodes.count(CS.getCalledFunction()) == 0;
+}
+
+/// helper for NoUnwind inference predicate InstrBreaksAttribute
+static bool InstrBreaksNonThrowing(Instruction &I,
+                                    const SCCNodeSet &SCCNodes) {
+  bool InstMightUnwind = I.mayThrow();
+  if (InstMightUnwind) {
+    if (const auto *CI = dyn_cast<CallInst>(&I)) {
+      if (Function *Callee = CI->getCalledFunction()) {
+        // If the callee is outside our current SCC then we may throw
+        // because it might.  If it is inside, do nothing.
+        if (SCCNodes.count(Callee) > 0)
+          InstMightUnwind = false;
+      }
+    }
+  }
+  return InstMightUnwind;
+}
+
+/// Infer attributes from all functions in the SCC by scanning every
+/// instruction for compliance to the attribute assumptions. Currently it
+/// does:
+///   - removal of Convergent attribute
+///   - addition of NoUnwind attribute
+///
+/// Returns true if any changes to function attributes were made.
+static bool inferAttrsFromFunctionBodies(const SCCNodeSet &SCCNodes) {
+
+  AttributeInferer AI;
+
+  // Request to remove the convergent attribute from all functions in the SCC
+  // if every callsite within the SCC is not convergent (except for calls
+  // to functions within the SCC).
+  // Note: Removal of the attr from the callsites will happen in
+  // InstCombineCalls separately.
+  AI.registerAttrInference(
+      {  /* RequiresExactDefinition= */ false,
+       // Skip non-convergent functions.
+       [](const Function &F) { return !F.isConvergent(); },
+       // Instructions that break non-convergent assumption.
+       [SCCNodes](Instruction &I) {
+         return InstrBreaksNonConvergent(I, SCCNodes);
+       },
+       [](Function &F) {
+         DEBUG(dbgs() << "Removing convergent attr from fn " << F.getName()
+                      << "\n");
+         F.setNotConvergent();
+       }});
+
+  // Request to infer nounwind attribute for all the functions in the SCC if
+  // every callsite within the SCC is not throwing (except for calls to
+  // functions within the SCC). Note that nounwind attribute suffers from
+  // derefinement - results may change depending on how functions are
+  // optimized. Thus it can be inferred only from exact definitions.
+  AI.registerAttrInference(
+      {/* RequiresExactDefinition= */ true,
+       // Skip non-throwing functions.
+       [](const Function &F) { return F.doesNotThrow(); },
+       // Instructions that break non-throwing assumption.
+       [SCCNodes](Instruction &I) {
+	 return InstrBreaksNonThrowing(I, SCCNodes);
+       },
+       [](Function &F) {
+	 DEBUG(dbgs() << "Adding nounwind attr to fn " << F.getName() << "\n");
+	 F.setDoesNotThrow();
+	 ++NumNoUnwind;
+       }});
+
+  // Perform all the requested attribute inference actions.
+  return AI.run(SCCNodes);
+}
+
 static bool setDoesNotRecurse(Function &F) {
   if (F.doesNotRecurse())
     return false;
@@ -1168,7 +1329,7 @@
   if (!HasUnknownCall) {
     Changed |= addNoAliasAttrs(SCCNodes);
     Changed |= addNonNullAttrs(SCCNodes);
-    Changed |= removeConvergentAttrs(SCCNodes);
+    Changed |= inferAttrsFromFunctionBodies(SCCNodes);
     Changed |= addNoRecurseAttrs(SCCNodes);
   }
 
@@ -1246,7 +1407,7 @@
   if (!ExternalNode) {
     Changed |= addNoAliasAttrs(SCCNodes);
     Changed |= addNonNullAttrs(SCCNodes);
-    Changed |= removeConvergentAttrs(SCCNodes);
+    Changed |= inferAttrsFromFunctionBodies(SCCNodes);
     Changed |= addNoRecurseAttrs(SCCNodes);
   }
 
Index: test/Other/cgscc-devirt-iteration.ll
===================================================================
--- test/Other/cgscc-devirt-iteration.ll
+++ test/Other/cgscc-devirt-iteration.ll
@@ -13,11 +13,11 @@
 
 declare void @readnone() readnone
 ; CHECK: Function Attrs: readnone
-; CHECK: declare void @readnone()
+; CHECK-NEXT: declare void @readnone()
 
 declare void @unknown()
 ; CHECK-NOT: Function Attrs
-; CHECK: declare void @unknown()
+; CHECK-LABEL: declare void @unknown(){{ *$}}
 
 ; The @test1 function checks that when we refine an indirect call to a direct
 ; call we revisit the SCC passes to reflect the more precise information. This
@@ -26,7 +26,7 @@
 define void @test1() {
 ; BEFORE-NOT: Function Attrs
 ; AFTER: Function Attrs: readnone
-; CHECK: define void @test1()
+; CHECK-LABEL: define void @test1()
 entry:
   %fptr = alloca void ()*
   store void ()* @readnone, void ()** %fptr
@@ -49,7 +49,7 @@
 
 declare void @readnone_with_arg(void ()**) readnone
 ; CHECK: Function Attrs: readnone
-; CHECK: declare void @readnone_with_arg(void ()**)
+; CHECK-LABEL: declare void @readnone_with_arg(void ()**)
 
 define void @test2_a(void ()** %ignore) {
 ; BEFORE-NOT: Function Attrs
@@ -76,7 +76,7 @@
 ; BEFORE-NOT: Function Attrs
 ; AFTER1: Function Attrs: readonly
 ; AFTER2: Function Attrs: readnone
-; CHECK: define void @test2_b()
+; CHECK-LABEL: define void @test2_b()
 entry:
   %f2ptr = alloca void ()*
   store void ()* @readnone, void ()** %f2ptr
@@ -96,17 +96,20 @@
 }
 
 declare i8* @memcpy(i8*, i8*, i64)
-; CHECK: declare i8* @memcpy(
+; CHECK-LABEL: declare i8* @memcpy(
 
 ; The @test3 function checks that when we refine an indirect call to an
 ; intrinsic we still revisit the SCC pass. This also covers cases where the
 ; value handle itself doesn't persist due to the nature of how instcombine
 ; creates the memcpy intrinsic call, and we rely on the count of indirect calls
 ; decreasing and the count of direct calls increasing.
-define void @test3(i8* %src, i8* %dest, i64 %size) {
-; CHECK-NOT: Function Attrs
-; BEFORE: define void @test3(i8* %src, i8* %dest, i64 %size)
-; AFTER: define void @test3(i8* nocapture readonly %src, i8* nocapture %dest, i64 %size)
+; Adding 'noinline' attribute to force attributes for improved matching.
+define void @test3(i8* %src, i8* %dest, i64 %size) noinline {
+; CHECK: Function Attrs
+; CHECK-NOT: read
+; CHECK-SAME: noinline
+; BEFORE-LABEL: define void @test3(i8* %src, i8* %dest, i64 %size)
+; AFTER-LABEL: define void @test3(i8* nocapture readonly %src, i8* nocapture %dest, i64 %size)
   %fptr = alloca i8* (i8*, i8*, i64)*
   store i8* (i8*, i8*, i64)* @memcpy, i8* (i8*, i8*, i64)** %fptr
   %f = load i8* (i8*, i8*, i64)*, i8* (i8*, i8*, i64)** %fptr
@@ -118,7 +121,7 @@
 ; A boring function that just keeps our declarations around.
 define void @keep(i8** %sink) {
 ; CHECK-NOT: Function Attrs
-; CHECK: define void @keep(
+; CHECK-LABEL: define void @keep(
 entry:
   store volatile i8* bitcast (void ()* @readnone to i8*), i8** %sink
   store volatile i8* bitcast (void ()* @unknown to i8*), i8** %sink
Index: test/Transforms/FunctionAttrs/2008-09-03-Mutual.ll
===================================================================
--- test/Transforms/FunctionAttrs/2008-09-03-Mutual.ll
+++ test/Transforms/FunctionAttrs/2008-09-03-Mutual.ll
@@ -1,10 +1,17 @@
-; RUN: opt < %s -functionattrs -S | grep readnone
+; RUN: opt < %s -functionattrs -S | FileCheck %s
+; RUN: opt < %s -passes=function-attrs -S | FileCheck %s
 
+; CHECK: Function Attrs
+; CHECK-SAME: readnone
+; CHECK-NEXT: define i32 @a
 define i32 @a() {
 	%tmp = call i32 @b( )		; <i32> [#uses=1]
 	ret i32 %tmp
 }
 
+; CHECK: Function Attrs
+; CHECK-SAME: readnone
+; CHECK-NEXT: define i32 @b
 define i32 @b() {
 	%tmp = call i32 @a( )		; <i32> [#uses=1]
 	ret i32 %tmp
Index: test/Transforms/FunctionAttrs/2008-09-03-ReadNone.ll
===================================================================
--- test/Transforms/FunctionAttrs/2008-09-03-ReadNone.ll
+++ test/Transforms/FunctionAttrs/2008-09-03-ReadNone.ll
@@ -1,25 +1,32 @@
 ; RUN: opt < %s -basicaa -functionattrs -S | FileCheck %s
+; RUN: opt < %s -aa-pipeline=basic-aa -passes=function-attrs -S | FileCheck %s
+
 @x = global i32 0
 
-; CHECK: declare i32 @e() #0
+; CHECK: Function Attrs
+; CHECK-SAME: readnone
+; CHECK-NEXT: declare i32 @e
 declare i32 @e() readnone
 
-; CHECK: define i32 @f() #0
+; CHECK: Function Attrs
+; CHECK-SAME: readnone
+; CHECK-NEXT: define i32 @f
 define i32 @f() {
 	%tmp = call i32 @e( )		; <i32> [#uses=1]
 	ret i32 %tmp
 }
 
-; CHECK: define i32 @g() #1
+; CHECK: Function Attrs
+; CHECK-SAME: readnone
+; CHECK-NEXT: define i32 @g
 define i32 @g() readonly {
 	ret i32 0
 }
 
-; CHECK: define i32 @h() #1
+; CHECK: Function Attrs
+; CHECK-SAME: readnone
+; CHECK-NEXT: define i32 @h
 define i32 @h() readnone {
 	%tmp = load i32, i32* @x		; <i32> [#uses=1]
 	ret i32 %tmp
 }
-
-; CHECK: attributes #0 = { readnone }
-; CHECK: attributes #1 = { norecurse readnone }
Index: test/Transforms/FunctionAttrs/2008-09-03-ReadOnly.ll
===================================================================
--- test/Transforms/FunctionAttrs/2008-09-03-ReadOnly.ll
+++ test/Transforms/FunctionAttrs/2008-09-03-ReadOnly.ll
@@ -1,4 +1,5 @@
 ; RUN: opt < %s -basicaa -functionattrs -S | FileCheck %s
+; RUN: opt < %s -aa-pipeline=basic-aa -passes=function-attrs -S | FileCheck %s
 
 ; CHECK: define i32 @f() #0
 define i32 @f() {
Index: test/Transforms/FunctionAttrs/2008-09-13-VolatileRead.ll
===================================================================
--- test/Transforms/FunctionAttrs/2008-09-13-VolatileRead.ll
+++ test/Transforms/FunctionAttrs/2008-09-13-VolatileRead.ll
@@ -1,4 +1,5 @@
-; RUN: opt < %s -functionattrs -S | not grep read
+; RUN: opt < %s -functionattrs -S | FileCheck %s
+; RUN: opt < %s -passes=function-attrs -S | FileCheck %s
 ; PR2792
 
 @g = global i32 0		; <i32*> [#uses=1]
@@ -7,3 +8,5 @@
 	%t = load volatile i32, i32* @g		; <i32> [#uses=1]
 	ret i32 %t
 }
+
+; CHECK-NOT: attributes #{{.*}} read
Index: test/Transforms/FunctionAttrs/2008-12-29-Constant.ll
===================================================================
--- test/Transforms/FunctionAttrs/2008-12-29-Constant.ll
+++ test/Transforms/FunctionAttrs/2008-12-29-Constant.ll
@@ -1,8 +1,12 @@
-; RUN: opt < %s -basicaa -functionattrs -S | grep readnone
+; RUN: opt < %s -basicaa -functionattrs -S | FileCheck %s
+; RUN: opt < %s -aa-pipeline=basic-aa -passes=function-attrs -S | FileCheck %s
 
 @s = external constant i8		; <i8*> [#uses=1]
 
+; CHECK: define i8 @f() #0
 define i8 @f() {
 	%tmp = load i8, i8* @s		; <i8> [#uses=1]
 	ret i8 %tmp
 }
+
+; CHECK: attributes #0 = { {{.*}} readnone
Index: test/Transforms/FunctionAttrs/2009-01-02-LocalStores.ll
===================================================================
--- test/Transforms/FunctionAttrs/2009-01-02-LocalStores.ll
+++ test/Transforms/FunctionAttrs/2009-01-02-LocalStores.ll
@@ -1,4 +1,5 @@
 ; RUN: opt < %s -functionattrs -S | FileCheck %s
+; RUN: opt < %s -passes=function-attrs -S | FileCheck %s
 
 ; CHECK: define i32* @a(i32** nocapture readonly %p)
 define i32* @a(i32** %p) {
Index: test/Transforms/FunctionAttrs/2010-10-30-volatile.ll
===================================================================
--- test/Transforms/FunctionAttrs/2010-10-30-volatile.ll
+++ test/Transforms/FunctionAttrs/2010-10-30-volatile.ll
@@ -1,12 +1,14 @@
 ; RUN: opt < %s -functionattrs -S | FileCheck %s
+; RUN: opt < %s -passes=function-attrs -S | FileCheck %s
 ; PR8279
 
 @g = constant i32 1
 
+; CHECK: Function Attrs
+; CHECK-SAME: norecurse
+; CHECK-NOT: readonly
+; CHECK-NEXT: void @foo()
 define void @foo() {
-; CHECK: void @foo() #0 {
   %tmp = load volatile i32, i32* @g
   ret void
 }
-
-; CHECK: attributes #0 = { norecurse }
Index: test/Transforms/FunctionAttrs/assume.ll
===================================================================
--- test/Transforms/FunctionAttrs/assume.ll
+++ test/Transforms/FunctionAttrs/assume.ll
@@ -1,4 +1,5 @@
 ; RUN: opt -S -o - -functionattrs %s | FileCheck %s
+; RUN: opt -S -o - -passes=function-attrs %s | FileCheck %s
 
 ; CHECK-NOT: readnone
 declare void @llvm.assume(i1)
Index: test/Transforms/FunctionAttrs/atomic.ll
===================================================================
--- test/Transforms/FunctionAttrs/atomic.ll
+++ test/Transforms/FunctionAttrs/atomic.ll
@@ -1,4 +1,5 @@
 ; RUN: opt -basicaa -functionattrs -S < %s | FileCheck %s
+; RUN: opt -aa-pipeline=basic-aa -passes=function-attrs -S < %s | FileCheck %s
 
 ; Atomic load/store to local doesn't affect whether a function is
 ; readnone/readonly.
@@ -19,5 +20,5 @@
   ret i32 %r
 }
 
-; CHECK: attributes #0 = { norecurse readnone ssp uwtable }
-; CHECK: attributes #1 = { norecurse ssp uwtable }
+; CHECK: attributes #0 = { norecurse nounwind readnone ssp uwtable }
+; CHECK: attributes #1 = { norecurse nounwind ssp uwtable }
Index: test/Transforms/FunctionAttrs/comdat-ipo.ll
===================================================================
--- test/Transforms/FunctionAttrs/comdat-ipo.ll
+++ test/Transforms/FunctionAttrs/comdat-ipo.ll
@@ -1,4 +1,5 @@
 ; RUN: opt < %s -functionattrs -S | FileCheck %s
+; RUN: opt < %s -passes=function-attrs -S | FileCheck %s
 
 ; See PR26774
 
Index: test/Transforms/FunctionAttrs/convergent.ll
===================================================================
--- test/Transforms/FunctionAttrs/convergent.ll
+++ test/Transforms/FunctionAttrs/convergent.ll
@@ -1,4 +1,8 @@
-; RUN: opt -functionattrs -S < %s | FileCheck %s
+; FIXME: convert CHECK-INDIRECT into CHECK (and remove -check-prefixes) as soon
+; FIXME: as new-pass-manager's handling of indirect_non_convergent_call is fixed
+;
+; RUN: opt -functionattrs -S < %s | FileCheck %s --check-prefixes=CHECK,CHECK-INDIRECT
+; RUN: opt -passes=function-attrs -S < %s | FileCheck %s
 
 ; CHECK: Function Attrs
 ; CHECK-NOT: convergent
@@ -50,8 +54,8 @@
 ; "Function Attrs" comment in the output.
 ;
 ; CHECK: Function Attrs
-; CHECK-NOT: convergent
-; CHECK-NEXT: define i32 @indirect_non_convergent_call(
+; CHECK-INDIRECT-NOT: convergent
+; CHECK-INDIRECT-NEXT: define i32 @indirect_non_convergent_call(
 define i32 @indirect_non_convergent_call(i32 ()* %f) convergent norecurse {
    %a = call i32 %f()
    ret i32 %a
Index: test/Transforms/FunctionAttrs/int_sideeffect.ll
===================================================================
--- test/Transforms/FunctionAttrs/int_sideeffect.ll
+++ test/Transforms/FunctionAttrs/int_sideeffect.ll
@@ -1,17 +1,25 @@
 ; RUN: opt -S < %s -functionattrs | FileCheck %s
+; RUN: opt -S < %s -passes=function-attrs | FileCheck %s
 
+; CHECK: Function Attrs
+; CHECK-SAME: inaccessiblememonly
+; CHECK-NEXT: declare void @llvm.sideeffect()
 declare void @llvm.sideeffect()
 
 ; Don't add readnone or similar attributes when an @llvm.sideeffect() intrinsic
 ; is present.
 
-; CHECK: define void @test() {
+; CHECK: Function Attrs
+; CHECK-NOT: readnone
+; CHECK: define void @test()
 define void @test() {
     call void @llvm.sideeffect()
     ret void
 }
 
-; CHECK: define void @loop() {
+; CHECK: Function Attrs
+; CHECK-NOT: readnone
+; CHECK: define void @loop()
 define void @loop() {
     br label %loop
 
Index: test/Transforms/FunctionAttrs/nocapture.ll
===================================================================
--- test/Transforms/FunctionAttrs/nocapture.ll
+++ test/Transforms/FunctionAttrs/nocapture.ll
@@ -1,4 +1,6 @@
 ; RUN: opt < %s -functionattrs -S | FileCheck %s
+; RUN: opt < %s -passes=function-attrs -S | FileCheck %s
+
 @g = global i32* null		; <i32**> [#uses=1]
 
 ; CHECK: define i32* @c1(i32* readnone returned %q)
Index: test/Transforms/FunctionAttrs/nonnull-global.ll
===================================================================
--- test/Transforms/FunctionAttrs/nonnull-global.ll
+++ test/Transforms/FunctionAttrs/nonnull-global.ll
@@ -1,4 +1,5 @@
 ; RUN: opt -S -functionattrs %s | FileCheck %s
+; RUN: opt -S -passes=function-attrs %s | FileCheck %s
 
 @a = external global i8, !absolute_symbol !0
 
Index: test/Transforms/FunctionAttrs/nonnull.ll
===================================================================
--- test/Transforms/FunctionAttrs/nonnull.ll
+++ test/Transforms/FunctionAttrs/nonnull.ll
@@ -1,4 +1,6 @@
 ; RUN: opt -S -functionattrs -enable-nonnull-arg-prop %s | FileCheck %s
+; RUN: opt -S -passes=function-attrs -enable-nonnull-arg-prop %s | FileCheck %s
+
 declare nonnull i8* @ret_nonnull()
 
 ; Return a pointer trivially nonnull (call return attribute)
Index: test/Transforms/FunctionAttrs/norecurse.ll
===================================================================
--- test/Transforms/FunctionAttrs/norecurse.ll
+++ test/Transforms/FunctionAttrs/norecurse.ll
@@ -1,53 +1,82 @@
 ; RUN: opt < %s -basicaa -functionattrs -rpo-functionattrs -S | FileCheck %s
 ; RUN: opt < %s -aa-pipeline=basic-aa -passes='cgscc(function-attrs),rpo-functionattrs' -S | FileCheck %s
 
-; CHECK: define i32 @leaf() #0
+; CHECK: Function Attrs
+; CHECK-SAME: norecurse nounwind readnone
+; CHECK-NEXT: define i32 @leaf()
 define i32 @leaf() {
   ret i32 1
 }
 
-; CHECK: define i32 @self_rec() #1
+; CHECK: Function Attrs
+; CHECK-SAME: readnone
+; CHECK-NOT: norecurse
+; CHECK-NEXT: define i32 @self_rec()
 define i32 @self_rec() {
   %a = call i32 @self_rec()
   ret i32 4
 }
 
-; CHECK: define i32 @indirect_rec() #1
+; CHECK: Function Attrs
+; CHECK-SAME: readnone
+; CHECK-NOT: norecurse
+; CHECK-NEXT: define i32 @indirect_rec()
 define i32 @indirect_rec() {
   %a = call i32 @indirect_rec2()
   ret i32 %a
 }
-; CHECK: define i32 @indirect_rec2() #1
+; CHECK: Function Attrs
+; CHECK-SAME: readnone
+; CHECK-NOT: norecurse
+; CHECK-NEXT: define i32 @indirect_rec2()
 define i32 @indirect_rec2() {
   %a = call i32 @indirect_rec()
   ret i32 %a
 }
 
-; CHECK: define i32 @extern() #1
+; CHECK: Function Attrs
+; CHECK-SAME: readnone
+; CHECK-NOT: norecurse
+; CHECK-NEXT: define i32 @extern()
 define i32 @extern() {
   %a = call i32 @k()
   ret i32 %a
 }
+
+; CHECK: Function Attrs
+; CHECK-NEXT: declare i32 @k()
 declare i32 @k() readnone
 
-; CHECK: define void @intrinsic(i8* nocapture %dest, i8* nocapture readonly %src, i32 %len) {
+; CHECK: Function Attrs
+; CHECK-SAME: nounwind
+; CHECK-NOT: norecurse
+; CHECK-NEXT: define void @intrinsic(i8* nocapture %dest, i8* nocapture readonly %src, i32 %len)
 define void @intrinsic(i8* %dest, i8* %src, i32 %len) {
   call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* %src, i32 %len, i1 false)
   ret void
 }
+
+; CHECK: Function Attrs
+; CHECK-NEXT: declare void @llvm.memcpy.p0i8.p0i8.i32
 declare void @llvm.memcpy.p0i8.p0i8.i32(i8*, i8*, i32, i1)
 
-; CHECK: define internal i32 @called_by_norecurse() #0
+; CHECK: Function Attrs
+; CHECK-SAME: norecurse readnone
+; CHECK-NEXT: define internal i32 @called_by_norecurse()
 define internal i32 @called_by_norecurse() {
   %a = call i32 @k()
   ret i32 %a
 }
+; CHECK: Function Attrs
+; CHECK-NEXT: define void @m()
 define void @m() norecurse {
   %a = call i32 @called_by_norecurse()
   ret void
 }
 
-; CHECK: define internal i32 @called_by_norecurse_indirectly() #0
+; CHECK: Function Attrs
+; CHECK-SAME: norecurse readnone
+; CHECK-NEXT: define internal i32 @called_by_norecurse_indirectly()
 define internal i32 @called_by_norecurse_indirectly() {
   %a = call i32 @k()
   ret i32 %a
@@ -60,6 +89,3 @@
   call void @o()
   ret void
 }
-
-; CHECK: attributes #0 = { norecurse readnone }
-; CHECK: attributes #1 = { readnone }
Index: test/Transforms/FunctionAttrs/operand-bundles-scc.ll
===================================================================
--- test/Transforms/FunctionAttrs/operand-bundles-scc.ll
+++ test/Transforms/FunctionAttrs/operand-bundles-scc.ll
@@ -1,13 +1,17 @@
 ; RUN: opt -S -functionattrs < %s | FileCheck %s
+; RUN: opt -S -passes=function-attrs < %s | FileCheck %s
 
 define void @f() {
-; CHECK-LABEL:  define void @f() {
+; CHECK-LABEL:  define void @f() #0 {
  call void @g() [ "unknown"() ]
  ret void
 }
 
 define void @g() {
-; CHECK-LABEL:  define void @g() {
+; CHECK-LABEL:  define void @g() #0 {
  call void @f()
  ret void
 }
+
+
+; CHECK: attributes #0 = { nounwind }
Index: test/Transforms/FunctionAttrs/optnone.ll
===================================================================
--- test/Transforms/FunctionAttrs/optnone.ll
+++ test/Transforms/FunctionAttrs/optnone.ll
@@ -1,4 +1,5 @@
 ; RUN: opt < %s -functionattrs -S | FileCheck %s
+; RUN: opt < %s -passes=function-attrs -S | FileCheck %s
 
 @x = global i32 0
 
@@ -19,6 +20,6 @@
 ; CHECK: (i8*) #1
 
 ; CHECK-LABEL: attributes #0
-; CHECK: = { norecurse readnone }
+; CHECK: = { norecurse nounwind readnone }
 ; CHECK-LABEL: attributes #1
 ; CHECK: = { noinline optnone }
Index: test/Transforms/FunctionAttrs/out-of-bounds-iterator-bug.ll
===================================================================
--- test/Transforms/FunctionAttrs/out-of-bounds-iterator-bug.ll
+++ test/Transforms/FunctionAttrs/out-of-bounds-iterator-bug.ll
@@ -1,4 +1,5 @@
 ; RUN: opt -functionattrs -S < %s | FileCheck %s
+; RUN: opt -passes=function-attrs -S < %s | FileCheck %s
 
 ; This checks for an iterator wraparound bug in FunctionAttrs.  The previous
 ; "incorrect" behavior was inferring readonly for the %x argument in @caller.
Index: test/Transforms/FunctionAttrs/readnone.ll
===================================================================
--- test/Transforms/FunctionAttrs/readnone.ll
+++ test/Transforms/FunctionAttrs/readnone.ll
@@ -1,4 +1,5 @@
 ; RUN: opt < %s -functionattrs -S | FileCheck %s
+; RUN: opt < %s -passes=function-attrs -S | FileCheck %s
 
 ; CHECK: define void @bar(i8* nocapture readnone)
 define void @bar(i8* readonly) {
Index: test/Transforms/FunctionAttrs/returned.ll
===================================================================
--- test/Transforms/FunctionAttrs/returned.ll
+++ test/Transforms/FunctionAttrs/returned.ll
@@ -1,4 +1,5 @@
 ; RUN: opt < %s -functionattrs -S | FileCheck %s
+; RUN: opt < %s -passes=function-attrs -S | FileCheck %s
 
 ; CHECK: define i32 @test1(i32 %p, i32 %q)
 define i32 @test1(i32 %p, i32 %q) {
Index: test/Transforms/Inline/cgscc-update.ll
===================================================================
--- test/Transforms/Inline/cgscc-update.ll
+++ test/Transforms/Inline/cgscc-update.ll
@@ -10,9 +10,9 @@
 declare void @unknown()
 
 ; Sanity check: this should get annotated as readnone.
-; CHECK: Function Attrs: readnone
+; CHECK: Function Attrs: nounwind readnone
 ; CHECK-NEXT: declare void @readnone()
-declare void @readnone() readnone
+declare void @readnone() readnone nounwind
 
 ; The 'test1_' prefixed functions are designed to trigger forming a new direct
 ; call in the inlined body of the function. After that, we form a new SCC and
@@ -27,7 +27,7 @@
 }
 
 ; This function should have had 'readnone' deduced for its SCC.
-; CHECK: Function Attrs: noinline readnone
+; CHECK: Function Attrs: noinline nounwind readnone
 ; CHECK-NEXT: define void @test1_g()
 define void @test1_g() noinline {
 entry:
@@ -36,7 +36,7 @@
 }
 
 ; This function should have had 'readnone' deduced for its SCC.
-; CHECK: Function Attrs: noinline readnone
+; CHECK: Function Attrs: noinline nounwind readnone
 ; CHECK-NEXT: define void @test1_h()
 define void @test1_h() noinline {
 entry:
@@ -59,7 +59,7 @@
 }
 
 ; This function should have had 'readnone' deduced for its SCC.
-; CHECK: Function Attrs: noinline readnone
+; CHECK: Function Attrs: noinline nounwind readnone
 ; CHECK-NEXT: define void @test2_g()
 define void @test2_g() noinline {
 entry:
@@ -69,7 +69,7 @@
 }
 
 ; This function should have had 'readnone' deduced for its SCC.
-; CHECK: Function Attrs: noinline readnone
+; CHECK: Function Attrs: noinline nounwind readnone
 ; CHECK-NEXT: define void @test2_h()
 define void @test2_h() noinline {
 entry:
@@ -152,7 +152,7 @@
 ; form a new SCC and should use that can deduce precise function attrs.
 
 ; This function should have had 'readnone' deduced for its SCC.
-; CHECK: Function Attrs: noinline readnone
+; CHECK: Function Attrs: noinline nounwind readnone
 ; CHECK-NEXT: define void @test4_f1()
 define void @test4_f1() noinline {
 entry:
@@ -175,7 +175,7 @@
 }
 
 ; This function should have had 'readnone' deduced for its SCC.
-; CHECK: Function Attrs: noinline readnone
+; CHECK: Function Attrs: noinline nounwind readnone
 ; CHECK-NEXT: define void @test4_h()
 define void @test4_h() noinline {
 entry:
Index: test/Transforms/PruneEH/2008-06-02-Weak.ll
===================================================================
--- test/Transforms/PruneEH/2008-06-02-Weak.ll
+++ test/Transforms/PruneEH/2008-06-02-Weak.ll
@@ -1,12 +1,20 @@
-; RUN: opt < %s -prune-eh -S | not grep nounwind
+; RUN: opt < %s -prune-eh -S | FileCheck %s
+; RUN: opt < %s -passes='function-attrs,function(simplify-cfg)' -S | FileCheck %s
 
+; We should not infer 'nounwind' for/from a weak function,
+; since it can be overriden by throwing implementation.
+;
+; CHECK-LABEL: define weak void @f()
 define weak void @f() {
 entry:
         ret void
 }
 
+; CHECK-LABEL: define void @g()
 define void @g() {
 entry:
 	call void @f()
 	ret void
 }
+
+; CHECK-NOT: {{^}}attributes #{{[0-9].*}} nounwind
Index: test/Transforms/PruneEH/ipo-nounwind.ll
===================================================================
--- test/Transforms/PruneEH/ipo-nounwind.ll
+++ test/Transforms/PruneEH/ipo-nounwind.ll
@@ -1,4 +1,5 @@
 ; RUN: opt -S -prune-eh < %s | FileCheck %s
+; RUN: opt -S -passes='function-attrs,function(simplify-cfg)' < %s | FileCheck %s
 
 declare void @may_throw()
 
Index: test/Transforms/PruneEH/operand-bundles.ll
===================================================================
--- test/Transforms/PruneEH/operand-bundles.ll
+++ test/Transforms/PruneEH/operand-bundles.ll
@@ -1,4 +1,5 @@
 ; RUN: opt < %s -prune-eh -S | FileCheck %s
+; RUN: opt < %s -passes='function-attrs,function(simplify-cfg)' -S | FileCheck %s
 
 declare void @nounwind() nounwind
 
Index: test/Transforms/PruneEH/pr23971.ll
===================================================================
--- test/Transforms/PruneEH/pr23971.ll
+++ test/Transforms/PruneEH/pr23971.ll
@@ -1,4 +1,5 @@
 ; RUN: opt -S -prune-eh < %s | FileCheck %s
+; RUN: opt -S -passes='function-attrs,function(simplify-cfg)' < %s | FileCheck %s
 
 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
 target triple = "x86_64-unknown-linux-gnu"
Index: test/Transforms/PruneEH/pr26263.ll
===================================================================
--- test/Transforms/PruneEH/pr26263.ll
+++ test/Transforms/PruneEH/pr26263.ll
@@ -1,4 +1,10 @@
-; RUN: opt -prune-eh -S < %s | FileCheck %s
+; PruneEH is less powerful than simplify-cfg in terms of cfg simplification,
+; so it leaves some of the unreachable stuff hanging around.
+; Checking it with CHECK-OLD.
+;
+; RUN: opt -prune-eh -S < %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-OLD
+; RUN: opt -passes='function-attrs,function(simplify-cfg)' -S < %s | FileCheck %s  --check-prefix=CHECK --check-prefix=CHECK-NEW
+
 target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
 target triple = "i386-pc-windows-msvc"
 
@@ -20,12 +26,15 @@
 }
 
 ; CHECK-LABEL: define void @test1(
-; CHECK: call void @neverthrows()
+; CHECK:       call void @neverthrows()
+; CHECK-NEW-NEXT: ret void
+; CHECK-NEW-NEXT: }
+; CHECK-OLD:	  ret void
 
-; CHECK: %[[cp:.*]] = cleanuppad within none []
-; CHECK-NEXT: unreachable
+; CHECK-OLD: %[[cp:.*]] = cleanuppad within none []
+; CHECK-OLD-NEXT: unreachable
 
-; CHECK: cleanupret from %[[cp]] unwind to caller
+; CHECK-OLD: cleanupret from %[[cp]] unwind to caller
 
 define void @test2() personality i32 (...)* @__CxxFrameHandler3 {
   invoke void @neverthrows()
@@ -46,11 +55,16 @@
 }
 
 ; CHECK-LABEL: define void @test2(
-; CHECK: call void @neverthrows()
+; CHECK:       call void @neverthrows()
+; CHECK-NEW-NEXT: ret void
+; CHECK-NEW-NEXT: }
+; CHECK-OLD:      ret void
+
+; CHECK-OLD: %[[cs:.*]] = catchswitch within none [label
 
-; CHECK: %[[cs:.*]] = catchswitch within none [label
+; CHECK-OLD: catchpad within %[[cs]] []
+; CHECK-OLD-NEXT: unreachable
 
-; CHECK: catchpad within %[[cs]] []
-; CHECK-NEXT: unreachable
+; CHECK-OLD:ret void
 
 declare i32 @__CxxFrameHandler3(...)
Index: test/Transforms/PruneEH/recursivetest.ll
===================================================================
--- test/Transforms/PruneEH/recursivetest.ll
+++ test/Transforms/PruneEH/recursivetest.ll
@@ -1,6 +1,9 @@
-; RUN: opt < %s -prune-eh -S | not grep invoke
+; RUN: opt < %s -prune-eh -S | FileCheck %s
+; RUN: opt < %s -passes='function-attrs,function(simplify-cfg)' -S | FileCheck %s
 
+; CHECK-LABEL: define internal i32 @foo()
 define internal i32 @foo() personality i32 (...)* @__gxx_personality_v0 {
+; CHECK-NOT: invoke i32 @foo()
 	invoke i32 @foo( )
 			to label %Normal unwind label %Except		; <i32>:1 [#uses=0]
 Normal:		; preds = %0
@@ -11,7 +14,9 @@
 	ret i32 123
 }
 
+; CHECK-LABEL: define i32 @caller()
 define i32 @caller() personality i32 (...)* @__gxx_personality_v0 {
+; CHECK-NOT: invoke i32 @foo()
 	invoke i32 @foo( )
 			to label %Normal unwind label %Except		; <i32>:1 [#uses=0]
 Normal:		; preds = %0
Index: test/Transforms/PruneEH/seh-nounwind.ll
===================================================================
--- test/Transforms/PruneEH/seh-nounwind.ll
+++ test/Transforms/PruneEH/seh-nounwind.ll
@@ -1,4 +1,5 @@
 ; RUN: opt -S -prune-eh < %s | FileCheck %s
+; RUN: opt -S -passes='function-attrs,function(simplify-cfg)' < %s | FileCheck %s
 
 ; Don't remove invokes of nounwind functions if the personality handles async
 ; exceptions. The @div function in this test can fault, even though it can't
Index: test/Transforms/PruneEH/simpletest.ll
===================================================================
--- test/Transforms/PruneEH/simpletest.ll
+++ test/Transforms/PruneEH/simpletest.ll
@@ -1,4 +1,5 @@
-; RUN: opt < %s -prune-eh -S | not grep invoke
+; RUN: opt < %s -prune-eh -S | FileCheck %s
+; RUN: opt < %s -passes='function-attrs,function(simplify-cfg)' -S | FileCheck %s
 
 declare void @nounwind() nounwind
 
@@ -7,7 +8,9 @@
 	ret void
 }
 
+; CHECK-LABEL: define i32 @caller()
 define i32 @caller() personality i32 (...)* @__gxx_personality_v0 {
+; CHECK-NOT: invoke void @foo
 	invoke void @foo( )
 			to label %Normal unwind label %Except