fix an IPSCCP bug I introduced when I changed IPSCCP to start working on
authorChris Lattner <sabre@nondot.org>
Tue, 3 Nov 2009 19:24:51 +0000 (19:24 +0000)
committerChris Lattner <sabre@nondot.org>
Tue, 3 Nov 2009 19:24:51 +0000 (19:24 +0000)
functions that don't have local linkage.  Basically, we need to be more
careful about propagating argument information to functions whose results
we aren't tracking.  This fixes a miscompilation of
LLVMCConfigurationEmitter.cpp when built with an llvm-gcc that has ipsccp
enabled.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@85923 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/Scalar/SCCP.cpp
test/Transforms/SCCP/ipsccp-basic.ll

index 2ee4bbc95b17f54f54928ef4d63b625b2f63871b..15b5bb5bc41f76d168746c4cb88ef6bfc9a7a4ba 100644 (file)
@@ -174,6 +174,9 @@ class SCCPSolver : public InstVisitor<SCCPSolver> {
   /// that return multiple values.
   DenseMap<std::pair<Function*, unsigned>, LatticeVal> TrackedMultipleRetVals;
 
+  /// TrackingIncomingArguments - This is the set of functions that are 
+  SmallPtrSet<Function*, 16> TrackingIncomingArguments;
+  
   /// The reason for two worklists is that overdefined is the lowest state
   /// on the lattice, and moving things to overdefined as fast as possible
   /// makes SCCP converge much faster.
@@ -235,6 +238,10 @@ public:
       TrackedRetVals.insert(std::make_pair(F, LatticeVal()));
   }
 
+  void AddArgumentTrackedFunction(Function *F) {
+    TrackingIncomingArguments.insert(F);
+  }
+  
   /// Solve - Solve for constants and executable blocks.
   ///
   void Solve();
@@ -1190,6 +1197,27 @@ CallOverdefined:
     return markOverdefined(I);
   }
 
+  // If this is a local function that doesn't have its address taken, mark its
+  // entry block executable and merge in the actual arguments to the call into
+  // the formal arguments of the function.
+  if (!TrackingIncomingArguments.empty() && TrackingIncomingArguments.count(F)){
+    MarkBlockExecutable(F->begin());
+    
+    // Propagate information from this call site into the callee.
+    CallSite::arg_iterator CAI = CS.arg_begin();
+    for (Function::arg_iterator AI = F->arg_begin(), E = F->arg_end();
+         AI != E; ++AI, ++CAI) {
+      // If this argument is byval, and if the function is not readonly, there
+      // will be an implicit copy formed of the input aggregate.
+      if (AI->hasByValAttr() && !F->onlyReadsMemory()) {
+        markOverdefined(AI);
+        continue;
+      }
+      
+      mergeInValue(AI, getValueState(*CAI));
+    }
+  }
+  
   // If this is a single/zero retval case, see if we're tracking the function.
   DenseMap<Function*, LatticeVal>::iterator TFRVI = TrackedRetVals.find(F);
   if (TFRVI != TrackedRetVals.end()) {
@@ -1228,24 +1256,6 @@ CallOverdefined:
     // common path above.
     goto CallOverdefined;
   }
-  
-  // Finally, if this is the first call to the function hit, mark its entry
-  // block executable.
-  MarkBlockExecutable(F->begin());
-  
-  // Propagate information from this call site into the callee.
-  CallSite::arg_iterator CAI = CS.arg_begin();
-  for (Function::arg_iterator AI = F->arg_begin(), E = F->arg_end();
-       AI != E; ++AI, ++CAI) {
-    // If this argument is byval, and if the function is not readonly, there
-    // will be an implicit copy formed of the input aggregate.
-    if (AI->hasByValAttr() && !F->onlyReadsMemory()) {
-      markOverdefined(AI);
-      continue;
-    }
-    
-    mergeInValue(AI, getValueState(*CAI));
-  }
 }
 
 void SCCPSolver::Solve() {
@@ -1656,8 +1666,10 @@ bool IPSCCP::runOnModule(Module &M) {
     // If this function only has direct calls that we can see, we can track its
     // arguments and return value aggressively, and can assume it is not called
     // unless we see evidence to the contrary.
-    if (F->hasLocalLinkage() && !AddressIsTaken(F))
+    if (F->hasLocalLinkage() && !AddressIsTaken(F)) {
+      Solver.AddArgumentTrackedFunction(F);
       continue;
+    }
 
     // Assume the function is called.
     Solver.MarkBlockExecutable(F->begin());
index ec349e91d242d58c21516b0b1124f647c5f83fd0..2442c56e0195d788d84608a0e68fd06267b9fc23 100644 (file)
@@ -174,4 +174,24 @@ define i32 @test7b() {
 ; CHECK-NEXT: ret i32 36
 }
 
+;;======================== test8
+
+
+define internal {} @test8a(i32 %A, i32* %P) {
+  store i32 %A, i32* %P
+  ret {} {}
+; CHECK: @test8a
+; CHECK-NEXT: store i32 5, 
+; CHECK-NEXT: ret 
+}
+
+define void @test8b(i32* %P) {
+    %X = call {} @test8a(i32 5, i32* %P)
+    ret void
+; CHECK: define void @test8b
+; CHECK-NEXT: call {} @test8a
+; CHECK-NEXT: ret void
+}
+
+