From af068750a71780a2f1780f056af0c21208a408dd Mon Sep 17 00:00:00 2001
From: Duncan Sands <baldrick@free.fr>
Date: Wed, 11 Feb 2009 09:58:43 +0000
Subject: [PATCH] Make sure the SCC pass manager initializes any contained
 function pass managers.  Without this, simplify-libcalls would add nocapture
 attributes when run on its own, but not when run as part of -std-compile-opts
 or similar.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@64300 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/Analysis/IPA/CallGraphSCCPass.cpp         | 26 +++++++++++++------
 .../2009-02-11-NotInitialized.ll              | 12 +++++++++
 2 files changed, 30 insertions(+), 8 deletions(-)
 create mode 100644 test/Transforms/SimplifyLibCalls/2009-02-11-NotInitialized.ll

diff --git a/lib/Analysis/IPA/CallGraphSCCPass.cpp b/lib/Analysis/IPA/CallGraphSCCPass.cpp
index b8343cf4ce8..0a2f7c53977 100644
--- a/lib/Analysis/IPA/CallGraphSCCPass.cpp
+++ b/lib/Analysis/IPA/CallGraphSCCPass.cpp
@@ -40,8 +40,8 @@ public:
   /// whether any of the passes modifies the module, and if so, return true.
   bool runOnModule(Module &M);
 
-  bool doInitialization(CallGraph &CG);
-  bool doFinalization(CallGraph &CG);
+  bool doInitialization(CallGraph &CG, Module &M);
+  bool doFinalization(CallGraph &CG, Module &M);
 
   /// Pass Manager itself does not invalidate any analysis info.
   void getAnalysisUsage(AnalysisUsage &Info) const {
@@ -82,7 +82,7 @@ char CGPassManager::ID = 0;
 /// whether any of the passes modifies the module, and if so, return true.
 bool CGPassManager::runOnModule(Module &M) {
   CallGraph &CG = getAnalysis<CallGraph>();
-  bool Changed = doInitialization(CG);
+  bool Changed = doInitialization(CG, M);
 
   // Walk SCC
   for (scc_iterator<CallGraph*> I = scc_begin(&CG), E = scc_end(&CG);
@@ -126,28 +126,38 @@ bool CGPassManager::runOnModule(Module &M) {
       removeDeadPasses(P, "", ON_CG_MSG);
     }
   }
-  Changed |= doFinalization(CG);
+  Changed |= doFinalization(CG, M);
   return Changed;
 }
 
 /// Initialize CG
-bool CGPassManager::doInitialization(CallGraph &CG) {
+bool CGPassManager::doInitialization(CallGraph &CG, Module &M) {
   bool Changed = false;
   for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {  
     Pass *P = getContainedPass(Index);
-    if (CallGraphSCCPass *CGSP = dynamic_cast<CallGraphSCCPass *>(P)) 
+    if (CallGraphSCCPass *CGSP = dynamic_cast<CallGraphSCCPass *>(P)) {
       Changed |= CGSP->doInitialization(CG);
+    } else {
+      FPPassManager *FP = dynamic_cast<FPPassManager *>(P);
+      assert (FP && "Invalid CGPassManager member");
+      Changed |= FP->doInitialization(M);
+    }
   }
   return Changed;
 }
 
 /// Finalize CG
-bool CGPassManager::doFinalization(CallGraph &CG) {
+bool CGPassManager::doFinalization(CallGraph &CG, Module &M) {
   bool Changed = false;
   for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {  
     Pass *P = getContainedPass(Index);
-    if (CallGraphSCCPass *CGSP = dynamic_cast<CallGraphSCCPass *>(P)) 
+    if (CallGraphSCCPass *CGSP = dynamic_cast<CallGraphSCCPass *>(P)) {
       Changed |= CGSP->doFinalization(CG);
+    } else {
+      FPPassManager *FP = dynamic_cast<FPPassManager *>(P);
+      assert (FP && "Invalid CGPassManager member");
+      Changed |= FP->doFinalization(M);
+    }
   }
   return Changed;
 }
diff --git a/test/Transforms/SimplifyLibCalls/2009-02-11-NotInitialized.ll b/test/Transforms/SimplifyLibCalls/2009-02-11-NotInitialized.ll
new file mode 100644
index 00000000000..7d3a5c1b9ec
--- /dev/null
+++ b/test/Transforms/SimplifyLibCalls/2009-02-11-NotInitialized.ll
@@ -0,0 +1,12 @@
+; RUN: llvm-as < %s | opt -std-compile-opts | llvm-dis | grep nocapture | count 2
+; Check that nocapture attributes are added when run after an SCC pass.
+; PR3520
+
+define i32 @use(i8* %x) nounwind readonly {
+entry:
+	%0 = tail call i64 @strlen(i8* %x) nounwind readonly		; <i64> [#uses=1]
+	%1 = trunc i64 %0 to i32		; <i32> [#uses=1]
+	ret i32 %1
+}
+
+declare i64 @strlen(i8*) nounwind readonly