[llvm] r328377 - [PM][FunctionAttrs] add NoUnwind attribute inference to PostOrderFunctionAttrs pass

Fedor Sergeev via llvm-commits llvm-commits at lists.llvm.org
Fri Mar 23 14:46:16 PDT 2018


Author: fedor.sergeev
Date: Fri Mar 23 14:46:16 2018
New Revision: 328377

URL: http://llvm.org/viewvc/llvm-project?rev=328377&view=rev
Log:
[PM][FunctionAttrs] add NoUnwind attribute inference to PostOrderFunctionAttrs pass

Summary:
This was motivated by absence of PrunEH functionality in new PM.
It was decided that a proper way to do PruneEH is to add NoUnwind inference
into PostOrderFunctionAttrs and then perform normal SimplifyCFG on top.

This change generalizes attribute handling implemented for (a removal of)
Convergent attribute, by introducing a generic builder-like class
   AttributeInferer

It registers all the attribute inference requests, storing per-attribute
predicates into a vector, and then goes through an SCC Node, scanning all
the instructions for not breaking attribute assumptions.

The main idea is that as soon all the instructions from all the functions
of SCC Node conform to attribute assumptions then we are free to infer
the attribute as set for all the functions of SCC Node.

It handles two distinct cases of attributes:
   - those that might break due to derefinement of the function code

     for these attributes we are allowed to apply inference only if all the
     functions are "exact definitions". Example - NoUnwind.

   - those that do not care about derefinement

     for these attributes we are allowed to apply inference as soon as we see
     any function definition. Example - removal of Convergent attribute.

Also in this commit:
* Converted all the FunctionAttrs tests to use FileCheck and added new-PM
  invocations to them

* FunctionAttrs/convergent.ll test demonstrates a difference in behavior between
   new and old PM implementations. Marked with FIXME.

* PruneEH tests were converted to new-PM as well, using function-attrs+simplify-cfg
  combo as intended

* some of "other" tests were updated since function-attrs now infers 'nounwind'
  even for old PM pipeline

* -disable-nounwind-inference hidden option added as a possible workaround for a supposedly
  rare case when nounwind being inferred by default presents a problem

Reviewers: chandlerc, jlebar

Reviewed By: jlebar

Subscribers: eraman, llvm-commits

Differential Revision: https://reviews.llvm.org/D44415

Modified:
    llvm/trunk/lib/Transforms/IPO/FunctionAttrs.cpp
    llvm/trunk/test/Other/cgscc-devirt-iteration.ll
    llvm/trunk/test/Transforms/FunctionAttrs/2008-09-03-Mutual.ll
    llvm/trunk/test/Transforms/FunctionAttrs/2008-09-03-ReadNone.ll
    llvm/trunk/test/Transforms/FunctionAttrs/2008-09-03-ReadOnly.ll
    llvm/trunk/test/Transforms/FunctionAttrs/2008-09-13-VolatileRead.ll
    llvm/trunk/test/Transforms/FunctionAttrs/2008-12-29-Constant.ll
    llvm/trunk/test/Transforms/FunctionAttrs/2009-01-02-LocalStores.ll
    llvm/trunk/test/Transforms/FunctionAttrs/2010-10-30-volatile.ll
    llvm/trunk/test/Transforms/FunctionAttrs/assume.ll
    llvm/trunk/test/Transforms/FunctionAttrs/atomic.ll
    llvm/trunk/test/Transforms/FunctionAttrs/comdat-ipo.ll
    llvm/trunk/test/Transforms/FunctionAttrs/convergent.ll
    llvm/trunk/test/Transforms/FunctionAttrs/int_sideeffect.ll
    llvm/trunk/test/Transforms/FunctionAttrs/nocapture.ll
    llvm/trunk/test/Transforms/FunctionAttrs/nonnull-global.ll
    llvm/trunk/test/Transforms/FunctionAttrs/nonnull.ll
    llvm/trunk/test/Transforms/FunctionAttrs/norecurse.ll
    llvm/trunk/test/Transforms/FunctionAttrs/operand-bundles-scc.ll
    llvm/trunk/test/Transforms/FunctionAttrs/optnone.ll
    llvm/trunk/test/Transforms/FunctionAttrs/out-of-bounds-iterator-bug.ll
    llvm/trunk/test/Transforms/FunctionAttrs/readnone.ll
    llvm/trunk/test/Transforms/FunctionAttrs/returned.ll
    llvm/trunk/test/Transforms/Inline/cgscc-update.ll
    llvm/trunk/test/Transforms/PruneEH/2008-06-02-Weak.ll
    llvm/trunk/test/Transforms/PruneEH/ipo-nounwind.ll
    llvm/trunk/test/Transforms/PruneEH/operand-bundles.ll
    llvm/trunk/test/Transforms/PruneEH/pr23971.ll
    llvm/trunk/test/Transforms/PruneEH/pr26263.ll
    llvm/trunk/test/Transforms/PruneEH/recursivetest.ll
    llvm/trunk/test/Transforms/PruneEH/seh-nounwind.ll
    llvm/trunk/test/Transforms/PruneEH/simpletest.ll

Modified: llvm/trunk/lib/Transforms/IPO/FunctionAttrs.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/FunctionAttrs.cpp?rev=328377&r1=328376&r2=328377&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/FunctionAttrs.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/FunctionAttrs.cpp Fri Mar 23 14:46:16 2018
@@ -74,6 +74,7 @@ STATISTIC(NumReadOnlyArg, "Number of arg
 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:
@@ -83,6 +84,10 @@ static cl::opt<bool> EnableNonnullArgPro
     cl::desc("Try to propagate nonnull argument attributes from callsites to "
              "caller functions."));
 
+static cl::opt<bool> DisableNoUnwindInference(
+    "disable-nounwind-inference", cl::Hidden,
+    cl::desc("Stop inferring nounwind attribute during function-attrs pass"));
+
 namespace {
 
 using SCCNodeSet = SmallSetVector<Function *, 8>;
@@ -1037,49 +1042,213 @@ static bool addNonNullAttrs(const SCCNod
   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 {
+public:
+  /// Describes a request for inference of a single attribute.
+  struct InferenceDescriptor {
+
+    /// 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;
+
+    /// Attribute we derive.
+    Attribute::AttrKind AKind;
+
+    /// If true, only "exact" definitions can be used to infer this attribute.
+    /// See GlobalValue::isDefinitionExact.
+    bool RequiresExactDefinition;
+
+    InferenceDescriptor(Attribute::AttrKind AK,
+                        std::function<bool(const Function &)> SkipFunc,
+                        std::function<bool(Instruction &)> InstrScan,
+                        std::function<void(Function &)> SetAttr,
+                        bool ReqExactDef)
+        : SkipFunction(SkipFunc), InstrBreaksAttribute(InstrScan),
+          SetAttribute(SetAttr), AKind(AK),
+          RequiresExactDefinition(ReqExactDef) {}
+  };
+
+private:
+  SmallVector<InferenceDescriptor, 4> InferenceDescriptors;
+
+public:
+  void registerAttrInference(InferenceDescriptor AttrInference) {
+    InferenceDescriptors.push_back(AttrInference);
+  }
+
+  bool run(const SCCNodeSet &SCCNodes);
+};
+
+/// Perform all the requested attribute inference actions according to the
+/// attribute predicates stored before.
+bool AttributeInferer::run(const SCCNodeSet &SCCNodes) {
+  SmallVector<InferenceDescriptor, 4> InferInSCC = InferenceDescriptors;
+  // Go through all the functions in SCC and check corresponding attribute
+  // assumptions for each of them. Attributes that are invalid for this SCC
+  // will be removed from InferInSCC.
   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 (InferInSCC.empty())
+      return false;
 
-    // Can't remove convergent if any of our functions has a convergent call to a
-    // function not in the SCC.
-    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)
+    // Check if our attributes ever need scanning/can be scanned.
+    llvm::erase_if(InferInSCC, [F](const InferenceDescriptor &ID) {
+      if (ID.SkipFunction(*F))
         return false;
+
+      // Remove from further inference (invalidate) when visiting a function
+      // that has no instructions to scan/has an unsuitable definition.
+      return F->isDeclaration() ||
+             (ID.RequiresExactDefinition && !F->hasExactDefinition());
+    });
+
+    // For each attribute still in InferInSCC that doesn't explicitly skip F,
+    // set up the F instructions scan to verify assumptions of the attribute.
+    SmallVector<InferenceDescriptor, 4> InferInThisFunc;
+    llvm::copy_if(
+        InferInSCC, std::back_inserter(InferInThisFunc),
+        [F](const InferenceDescriptor &ID) { return !ID.SkipFunction(*F); });
+
+    if (InferInThisFunc.empty())
+      continue;
+
+    // Start instruction scan.
+    for (Instruction &I : instructions(*F)) {
+      llvm::erase_if(InferInThisFunc, [&](const InferenceDescriptor &ID) {
+        if (!ID.InstrBreaksAttribute(I))
+          return false;
+        // Remove attribute from further inference on any other functions
+        // because attribute assumptions have just been violated.
+        llvm::erase_if(InferInSCC, [&ID](const InferenceDescriptor &D) {
+          return D.AKind == ID.AKind;
+        });
+        // Remove attribute from the rest of current instruction scan.
+        return true;
+      });
+
+      if (InferInThisFunc.empty())
+        break;
     }
   }
 
-  // If the SCC doesn't have any convergent functions, we have nothing to do.
-  if (!HasConvergentFn) return false;
+  if (InferInSCC.empty())
+    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;
+  bool Changed = false;
+  for (Function *F : SCCNodes)
+    // At this point InferInSCC contains only functions that were either:
+    //   - explicitly skipped from scan/inference, or
+    //   - verified to have no instructions that break attribute assumptions.
+    // Hence we just go and force the attribute for all non-skipped functions.
+    for (auto &ID : InferInSCC) {
+      if (ID.SkipFunction(*F))
+        continue;
+      Changed = true;
+      ID.SetAttribute(*F);
+    }
+  return Changed;
+}
 
-    DEBUG(dbgs() << "Removing convergent attr from fn " << F->getName()
-                 << "\n");
-    F->setNotConvergent();
+} // 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) {
+  if (!I.mayThrow())
+    return false;
+  if (const auto *CI = dyn_cast<CallInst>(&I)) {
+    if (Function *Callee = CI->getCalledFunction()) {
+      // I is a may-throw call to a function inside our SCC. This doesn't
+      // invalidate our current working assumption that the SCC is no-throw; we
+      // just have to scan that other function.
+      if (SCCNodes.count(Callee) > 0)
+        return false;
+    }
   }
   return true;
 }
 
+/// 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(AttributeInferer::InferenceDescriptor{
+      Attribute::Convergent,
+      // 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();
+      },
+      /* RequiresExactDefinition= */ false});
+
+  if (!DisableNoUnwindInference)
+    // 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(AttributeInferer::InferenceDescriptor{
+        Attribute::NoUnwind,
+        // 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;
+        },
+        /* RequiresExactDefinition= */ true});
+
+  // Perform all the requested attribute inference actions.
+  return AI.run(SCCNodes);
+}
+
 static bool setDoesNotRecurse(Function &F) {
   if (F.doesNotRecurse())
     return false;
@@ -1168,7 +1337,7 @@ PreservedAnalyses PostOrderFunctionAttrs
   if (!HasUnknownCall) {
     Changed |= addNoAliasAttrs(SCCNodes);
     Changed |= addNonNullAttrs(SCCNodes);
-    Changed |= removeConvergentAttrs(SCCNodes);
+    Changed |= inferAttrsFromFunctionBodies(SCCNodes);
     Changed |= addNoRecurseAttrs(SCCNodes);
   }
 
@@ -1246,7 +1415,7 @@ static bool runImpl(CallGraphSCC &SCC, A
   if (!ExternalNode) {
     Changed |= addNoAliasAttrs(SCCNodes);
     Changed |= addNonNullAttrs(SCCNodes);
-    Changed |= removeConvergentAttrs(SCCNodes);
+    Changed |= inferAttrsFromFunctionBodies(SCCNodes);
     Changed |= addNoRecurseAttrs(SCCNodes);
   }
 

Modified: llvm/trunk/test/Other/cgscc-devirt-iteration.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Other/cgscc-devirt-iteration.ll?rev=328377&r1=328376&r2=328377&view=diff
==============================================================================
--- llvm/trunk/test/Other/cgscc-devirt-iteration.ll (original)
+++ llvm/trunk/test/Other/cgscc-devirt-iteration.ll Fri Mar 23 14:46:16 2018
@@ -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 @@ declare void @unknown()
 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 @@ entry:
 
 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 @@ define void @test2_b() {
 ; 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 @@ entry:
 }
 
 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 @@ define void @test3(i8* %src, i8* %dest,
 ; 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

Modified: llvm/trunk/test/Transforms/FunctionAttrs/2008-09-03-Mutual.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/2008-09-03-Mutual.ll?rev=328377&r1=328376&r2=328377&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/2008-09-03-Mutual.ll (original)
+++ llvm/trunk/test/Transforms/FunctionAttrs/2008-09-03-Mutual.ll Fri Mar 23 14:46:16 2018
@@ -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

Modified: llvm/trunk/test/Transforms/FunctionAttrs/2008-09-03-ReadNone.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/2008-09-03-ReadNone.ll?rev=328377&r1=328376&r2=328377&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/2008-09-03-ReadNone.ll (original)
+++ llvm/trunk/test/Transforms/FunctionAttrs/2008-09-03-ReadNone.ll Fri Mar 23 14:46:16 2018
@@ -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 }

Modified: llvm/trunk/test/Transforms/FunctionAttrs/2008-09-03-ReadOnly.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/2008-09-03-ReadOnly.ll?rev=328377&r1=328376&r2=328377&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/2008-09-03-ReadOnly.ll (original)
+++ llvm/trunk/test/Transforms/FunctionAttrs/2008-09-03-ReadOnly.ll Fri Mar 23 14:46:16 2018
@@ -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() {

Modified: llvm/trunk/test/Transforms/FunctionAttrs/2008-09-13-VolatileRead.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/2008-09-13-VolatileRead.ll?rev=328377&r1=328376&r2=328377&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/2008-09-13-VolatileRead.ll (original)
+++ llvm/trunk/test/Transforms/FunctionAttrs/2008-09-13-VolatileRead.ll Fri Mar 23 14:46:16 2018
@@ -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 @@ define i32 @f() {
 	%t = load volatile i32, i32* @g		; <i32> [#uses=1]
 	ret i32 %t
 }
+
+; CHECK-NOT: attributes #{{.*}} read

Modified: llvm/trunk/test/Transforms/FunctionAttrs/2008-12-29-Constant.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/2008-12-29-Constant.ll?rev=328377&r1=328376&r2=328377&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/2008-12-29-Constant.ll (original)
+++ llvm/trunk/test/Transforms/FunctionAttrs/2008-12-29-Constant.ll Fri Mar 23 14:46:16 2018
@@ -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

Modified: llvm/trunk/test/Transforms/FunctionAttrs/2009-01-02-LocalStores.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/2009-01-02-LocalStores.ll?rev=328377&r1=328376&r2=328377&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/2009-01-02-LocalStores.ll (original)
+++ llvm/trunk/test/Transforms/FunctionAttrs/2009-01-02-LocalStores.ll Fri Mar 23 14:46:16 2018
@@ -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) {

Modified: llvm/trunk/test/Transforms/FunctionAttrs/2010-10-30-volatile.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/2010-10-30-volatile.ll?rev=328377&r1=328376&r2=328377&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/2010-10-30-volatile.ll (original)
+++ llvm/trunk/test/Transforms/FunctionAttrs/2010-10-30-volatile.ll Fri Mar 23 14:46:16 2018
@@ -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 }

Modified: llvm/trunk/test/Transforms/FunctionAttrs/assume.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/assume.ll?rev=328377&r1=328376&r2=328377&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/assume.ll (original)
+++ llvm/trunk/test/Transforms/FunctionAttrs/assume.ll Fri Mar 23 14:46:16 2018
@@ -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)

Modified: llvm/trunk/test/Transforms/FunctionAttrs/atomic.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/atomic.ll?rev=328377&r1=328376&r2=328377&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/atomic.ll (original)
+++ llvm/trunk/test/Transforms/FunctionAttrs/atomic.ll Fri Mar 23 14:46:16 2018
@@ -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 @@ entry:
   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 }

Modified: llvm/trunk/test/Transforms/FunctionAttrs/comdat-ipo.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/comdat-ipo.ll?rev=328377&r1=328376&r2=328377&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/comdat-ipo.ll (original)
+++ llvm/trunk/test/Transforms/FunctionAttrs/comdat-ipo.ll Fri Mar 23 14:46:16 2018
@@ -1,4 +1,5 @@
 ; RUN: opt < %s -functionattrs -S | FileCheck %s
+; RUN: opt < %s -passes=function-attrs -S | FileCheck %s
 
 ; See PR26774
 

Modified: llvm/trunk/test/Transforms/FunctionAttrs/convergent.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/convergent.ll?rev=328377&r1=328376&r2=328377&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/convergent.ll (original)
+++ llvm/trunk/test/Transforms/FunctionAttrs/convergent.ll Fri Mar 23 14:46:16 2018
@@ -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 @@ define i32 @indirect_convergent_call(i32
 ; "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

Modified: llvm/trunk/test/Transforms/FunctionAttrs/int_sideeffect.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/int_sideeffect.ll?rev=328377&r1=328376&r2=328377&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/int_sideeffect.ll (original)
+++ llvm/trunk/test/Transforms/FunctionAttrs/int_sideeffect.ll Fri Mar 23 14:46:16 2018
@@ -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
 

Modified: llvm/trunk/test/Transforms/FunctionAttrs/nocapture.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/nocapture.ll?rev=328377&r1=328376&r2=328377&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/nocapture.ll (original)
+++ llvm/trunk/test/Transforms/FunctionAttrs/nocapture.ll Fri Mar 23 14:46:16 2018
@@ -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)

Modified: llvm/trunk/test/Transforms/FunctionAttrs/nonnull-global.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/nonnull-global.ll?rev=328377&r1=328376&r2=328377&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/nonnull-global.ll (original)
+++ llvm/trunk/test/Transforms/FunctionAttrs/nonnull-global.ll Fri Mar 23 14:46:16 2018
@@ -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
 

Modified: llvm/trunk/test/Transforms/FunctionAttrs/nonnull.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/nonnull.ll?rev=328377&r1=328376&r2=328377&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/nonnull.ll (original)
+++ llvm/trunk/test/Transforms/FunctionAttrs/nonnull.ll Fri Mar 23 14:46:16 2018
@@ -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)

Modified: llvm/trunk/test/Transforms/FunctionAttrs/norecurse.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/norecurse.ll?rev=328377&r1=328376&r2=328377&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/norecurse.ll (original)
+++ llvm/trunk/test/Transforms/FunctionAttrs/norecurse.ll Fri Mar 23 14:46:16 2018
@@ -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 @@ define void @p() norecurse {
   call void @o()
   ret void
 }
-
-; CHECK: attributes #0 = { norecurse readnone }
-; CHECK: attributes #1 = { readnone }

Modified: llvm/trunk/test/Transforms/FunctionAttrs/operand-bundles-scc.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/operand-bundles-scc.ll?rev=328377&r1=328376&r2=328377&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/operand-bundles-scc.ll (original)
+++ llvm/trunk/test/Transforms/FunctionAttrs/operand-bundles-scc.ll Fri Mar 23 14:46:16 2018
@@ -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 }

Modified: llvm/trunk/test/Transforms/FunctionAttrs/optnone.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/optnone.ll?rev=328377&r1=328376&r2=328377&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/optnone.ll (original)
+++ llvm/trunk/test/Transforms/FunctionAttrs/optnone.ll Fri Mar 23 14:46:16 2018
@@ -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 @@ declare i8 @strlen(i8*) noinline optnone
 ; CHECK: (i8*) #1
 
 ; CHECK-LABEL: attributes #0
-; CHECK: = { norecurse readnone }
+; CHECK: = { norecurse nounwind readnone }
 ; CHECK-LABEL: attributes #1
 ; CHECK: = { noinline optnone }

Modified: llvm/trunk/test/Transforms/FunctionAttrs/out-of-bounds-iterator-bug.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/out-of-bounds-iterator-bug.ll?rev=328377&r1=328376&r2=328377&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/out-of-bounds-iterator-bug.ll (original)
+++ llvm/trunk/test/Transforms/FunctionAttrs/out-of-bounds-iterator-bug.ll Fri Mar 23 14:46:16 2018
@@ -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.

Modified: llvm/trunk/test/Transforms/FunctionAttrs/readnone.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/readnone.ll?rev=328377&r1=328376&r2=328377&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/readnone.ll (original)
+++ llvm/trunk/test/Transforms/FunctionAttrs/readnone.ll Fri Mar 23 14:46:16 2018
@@ -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) {

Modified: llvm/trunk/test/Transforms/FunctionAttrs/returned.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/returned.ll?rev=328377&r1=328376&r2=328377&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/returned.ll (original)
+++ llvm/trunk/test/Transforms/FunctionAttrs/returned.ll Fri Mar 23 14:46:16 2018
@@ -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) {

Modified: llvm/trunk/test/Transforms/Inline/cgscc-update.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/cgscc-update.ll?rev=328377&r1=328376&r2=328377&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/Inline/cgscc-update.ll (original)
+++ llvm/trunk/test/Transforms/Inline/cgscc-update.ll Fri Mar 23 14:46:16 2018
@@ -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 @@ entry:
 }
 
 ; 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 @@ entry:
 }
 
 ; 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 @@ entry:
 }
 
 ; 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 @@ entry:
 }
 
 ; 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 @@ exit:
 ; 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 @@ entry:
 }
 
 ; 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:

Modified: llvm/trunk/test/Transforms/PruneEH/2008-06-02-Weak.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PruneEH/2008-06-02-Weak.ll?rev=328377&r1=328376&r2=328377&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/PruneEH/2008-06-02-Weak.ll (original)
+++ llvm/trunk/test/Transforms/PruneEH/2008-06-02-Weak.ll Fri Mar 23 14:46:16 2018
@@ -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

Modified: llvm/trunk/test/Transforms/PruneEH/ipo-nounwind.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PruneEH/ipo-nounwind.ll?rev=328377&r1=328376&r2=328377&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/PruneEH/ipo-nounwind.ll (original)
+++ llvm/trunk/test/Transforms/PruneEH/ipo-nounwind.ll Fri Mar 23 14:46:16 2018
@@ -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()
 

Modified: llvm/trunk/test/Transforms/PruneEH/operand-bundles.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PruneEH/operand-bundles.ll?rev=328377&r1=328376&r2=328377&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/PruneEH/operand-bundles.ll (original)
+++ llvm/trunk/test/Transforms/PruneEH/operand-bundles.ll Fri Mar 23 14:46:16 2018
@@ -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
 

Modified: llvm/trunk/test/Transforms/PruneEH/pr23971.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PruneEH/pr23971.ll?rev=328377&r1=328376&r2=328377&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/PruneEH/pr23971.ll (original)
+++ llvm/trunk/test/Transforms/PruneEH/pr23971.ll Fri Mar 23 14:46:16 2018
@@ -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"

Modified: llvm/trunk/test/Transforms/PruneEH/pr26263.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PruneEH/pr26263.ll?rev=328377&r1=328376&r2=328377&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/PruneEH/pr26263.ll (original)
+++ llvm/trunk/test/Transforms/PruneEH/pr26263.ll Fri Mar 23 14:46:16 2018
@@ -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 @@ cleanupret:
 }
 
 ; 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 @@ ret:
 }
 
 ; 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(...)

Modified: llvm/trunk/test/Transforms/PruneEH/recursivetest.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PruneEH/recursivetest.ll?rev=328377&r1=328376&r2=328377&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/PruneEH/recursivetest.ll (original)
+++ llvm/trunk/test/Transforms/PruneEH/recursivetest.ll Fri Mar 23 14:46:16 2018
@@ -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 @@ Except:		; preds = %0
 	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

Modified: llvm/trunk/test/Transforms/PruneEH/seh-nounwind.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PruneEH/seh-nounwind.ll?rev=328377&r1=328376&r2=328377&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/PruneEH/seh-nounwind.ll (original)
+++ llvm/trunk/test/Transforms/PruneEH/seh-nounwind.ll Fri Mar 23 14:46:16 2018
@@ -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

Modified: llvm/trunk/test/Transforms/PruneEH/simpletest.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PruneEH/simpletest.ll?rev=328377&r1=328376&r2=328377&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/PruneEH/simpletest.ll (original)
+++ llvm/trunk/test/Transforms/PruneEH/simpletest.ll Fri Mar 23 14:46:16 2018
@@ -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 @@ define internal void @foo() {
 	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
 




More information about the llvm-commits mailing list