OSDN Git Service

Fix PR 28933
authorDaniel Berlin <dberlin@dberlin.org>
Thu, 11 Aug 2016 20:32:43 +0000 (20:32 +0000)
committerDaniel Berlin <dberlin@dberlin.org>
Thu, 11 Aug 2016 20:32:43 +0000 (20:32 +0000)
Summary:
This fixes PR 28933 by making sure GVNHoist does not try to recreate memory
accesses when it has not actually moved them.

Reviewers: sebpop

Subscribers: llvm-commits, george.burgess.iv

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

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

lib/Transforms/Scalar/GVNHoist.cpp
test/Transforms/GVN/hoist-pr28933.ll [new file with mode: 0644]

index 63f0025..0d7364b 100644 (file)
@@ -740,10 +740,14 @@ private:
           if (!Repl || firstInBB(I, Repl))
             Repl = I;
 
+      // Keep track of whether we moved the instruction so we know whether we
+      // should move the MemoryAccess.
+      bool MoveAccess = true;
       if (Repl) {
         // Repl is already in HoistPt: it remains in place.
         assert(allOperandsAvailable(Repl, HoistPt) &&
                "instruction depends on operands that are not available");
+        MoveAccess = false;
       } else {
         // When we do not find Repl in HoistPt, select the first in the list
         // and move it to HoistPt.
@@ -771,14 +775,16 @@ private:
         DFSNumber[Repl] = DFSNumber[Last]++;
       }
 
-      MemoryAccess *NewMemAcc = nullptr;
-      if (MemoryAccess *MA = MSSA->getMemoryAccess(Repl)) {
-        if (MemoryUseOrDef *OldMemAcc = dyn_cast<MemoryUseOrDef>(MA)) {
+      MemoryAccess *NewMemAcc = MSSA->getMemoryAccess(Repl);
+
+      if (MoveAccess) {
+        if (MemoryUseOrDef *OldMemAcc =
+                dyn_cast_or_null<MemoryUseOrDef>(NewMemAcc)) {
           // The definition of this ld/st will not change: ld/st hoisting is
           // legal when the ld/st is not moved past its current definition.
           MemoryAccess *Def = OldMemAcc->getDefiningAccess();
-          NewMemAcc = MSSA->createMemoryAccessInBB(Repl, Def, HoistPt,
-                                                   MemorySSA::End);
+          NewMemAcc =
+              MSSA->createMemoryAccessInBB(Repl, Def, HoistPt, MemorySSA::End);
           OldMemAcc->replaceAllUsesWith(NewMemAcc);
           MSSA->removeMemoryAccess(OldMemAcc);
         }
diff --git a/test/Transforms/GVN/hoist-pr28933.ll b/test/Transforms/GVN/hoist-pr28933.ll
new file mode 100644 (file)
index 0000000..95df3f2
--- /dev/null
@@ -0,0 +1,21 @@
+; RUN: opt -S -gvn-hoist -verify-memoryssa < %s | FileCheck %s
+
+; Check that we end up with one load and one store, in the right order
+; CHECK-LABEL:  define void @test_it(
+; CHECK: store
+; CHECK-NEXT: load
+; CHECK-NOT: store
+; CHECK-NOT: load
+        
+%rec894.0.1.2.3.12 = type { i16 }
+
+@a = external global %rec894.0.1.2.3.12
+
+define void @test_it() {
+bb2:
+  store i16 undef, i16* getelementptr inbounds (%rec894.0.1.2.3.12, %rec894.0.1.2.3.12* @a, i16 0, i32 0), align 1
+  %_tmp61 = load i16, i16* getelementptr inbounds (%rec894.0.1.2.3.12, %rec894.0.1.2.3.12* @a, i16 0, i32 0), align 1
+  store i16 undef, i16* getelementptr inbounds (%rec894.0.1.2.3.12, %rec894.0.1.2.3.12* @a, i16 0, i32 0), align 1
+  %_tmp92 = load i16, i16* getelementptr inbounds (%rec894.0.1.2.3.12, %rec894.0.1.2.3.12* @a, i16 0, i32 0), align 1
+  ret void
+}