Fix PR3141 by ensuring that MemoryDependenceAnalysis::removeInstruction
authorChris Lattner <sabre@nondot.org>
Fri, 28 Nov 2008 22:51:08 +0000 (22:51 +0000)
committerChris Lattner <sabre@nondot.org>
Fri, 28 Nov 2008 22:51:08 +0000 (22:51 +0000)
properly updates the reverse dependency map when it installs updated
dependencies for instructions that depend on the removed instruction.

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

lib/Analysis/MemoryDependenceAnalysis.cpp
test/Transforms/DeadStoreElimination/2008-11-28-MemDepUpdate.ll [new file with mode: 0644]

index 27c43c735e979860bc2c06984031d7900a6457fe..9c269053c129f36b1fadb31796334256c823b2e2 100644 (file)
@@ -545,6 +545,7 @@ void MemoryDependenceAnalysis::removeInstruction(Instruction *RemInst) {
     if (IsConfirmed) {
       // If we have a confirmed non-local flag, use it.
       if (LocalDepInst == NonLocal || LocalDepInst == None) {
+        // The only time this dependency is confirmed is if it is non-local.
         NewDependency = LocalDepInst;
         NewDependencyConfirmed = true;
       } else {
@@ -565,18 +566,34 @@ void MemoryDependenceAnalysis::removeInstruction(Instruction *RemInst) {
   if (NewDependency == 0)
     NewDependency = next(BasicBlock::iterator(RemInst));
   
-  SmallPtrSet<Instruction*, 4>& set = reverseDep[RemInst];
-  for (SmallPtrSet<Instruction*, 4>::iterator I = set.begin(), E = set.end();
-       I != E; ++I) {
-    // Insert the new dependencies
-    // Mark it as unconfirmed as long as it is not the non-local flag
-    depGraphLocal[*I] = std::make_pair(NewDependency, NewDependencyConfirmed);
+  // Loop over all of the things that depend on the instruction we're removing.
+  // 
+  reverseDepMapType::iterator ReverseDepIt = reverseDep.find(RemInst);
+  if (ReverseDepIt != reverseDep.end()) {
+    SmallPtrSet<Instruction*, 4> &ReverseDeps = ReverseDepIt->second;
+    for (SmallPtrSet<Instruction*, 4>::iterator I = ReverseDeps.begin(),
+         E = ReverseDeps.end(); I != E; ++I) {
+      Instruction *InstDependingOnRemInst = *I;
+      
+      // If we thought the instruction depended on itself (possible for
+      // unconfirmed dependencies) ignore the update.
+      if (InstDependingOnRemInst == RemInst) continue;
+      
+      // Insert the new dependencies.
+      depGraphLocal[InstDependingOnRemInst] =
+        std::make_pair(NewDependency, NewDependencyConfirmed);
+      
+      // If our NewDependency is an instruction, make sure to remember that new
+      // things depend on it.
+      if (NewDependency != NonLocal && NewDependency != None)
+        reverseDep[NewDependency].insert(InstDependingOnRemInst);
+    }
+    reverseDep.erase(RemInst);
   }
   
-  reverseDep.erase(RemInst);
-  
-  if (reverseDepNonLocal.count(RemInst)) {
-    SmallPtrSet<Instruction*, 4>& set = reverseDepNonLocal[RemInst];
+  ReverseDepIt = reverseDepNonLocal.find(RemInst);
+  if (ReverseDepIt != reverseDepNonLocal.end()) {
+    SmallPtrSet<Instruction*, 4>& set = ReverseDepIt->second;
     for (SmallPtrSet<Instruction*, 4>::iterator I = set.begin(), E = set.end();
          I != E; ++I)
       for (DenseMap<BasicBlock*, Value*>::iterator DI =
@@ -584,10 +601,9 @@ void MemoryDependenceAnalysis::removeInstruction(Instruction *RemInst) {
            DI != DE; ++DI)
         if (DI->second == RemInst)
           DI->second = Dirty;
-    
+    reverseDepNonLocal.erase(RemInst);
   }
   
-  reverseDepNonLocal.erase(RemInst);
   depGraphNonLocal.erase(RemInst);
 
   getAnalysis<AliasAnalysis>().deleteValue(RemInst);
diff --git a/test/Transforms/DeadStoreElimination/2008-11-28-MemDepUpdate.ll b/test/Transforms/DeadStoreElimination/2008-11-28-MemDepUpdate.ll
new file mode 100644 (file)
index 0000000..0f3350d
--- /dev/null
@@ -0,0 +1,16 @@
+; RUN: llvm-as < %s | opt -dse | llvm-dis
+; PR3141
+       %struct.ada__tags__dispatch_table = type { [1 x i32] }
+       %struct.f393a00_1__object = type { %struct.ada__tags__dispatch_table*, i8 }
+       %struct.f393a00_2__windmill = type { %struct.f393a00_1__object, i16 }
+
+define void @f393a00_2__swap(%struct.f393a00_2__windmill* %a, %struct.f393a00_2__windmill* %b) {
+entry:
+       %t = alloca %struct.f393a00_2__windmill         ; <%struct.f393a00_2__windmill*> [#uses=1]
+       %0 = getelementptr %struct.f393a00_2__windmill* %t, i32 0, i32 0, i32 0         ; <%struct.ada__tags__dispatch_table**> [#uses=1]
+       %1 = load %struct.ada__tags__dispatch_table** null, align 4             ; <%struct.ada__tags__dispatch_table*> [#uses=1]
+       %2 = load %struct.ada__tags__dispatch_table** %0, align 8               ; <%struct.ada__tags__dispatch_table*> [#uses=1]
+       store %struct.ada__tags__dispatch_table* %2, %struct.ada__tags__dispatch_table** null, align 4
+       store %struct.ada__tags__dispatch_table* %1, %struct.ada__tags__dispatch_table** null, align 4
+       ret void
+}