GVN: tolerate an instruction being replaced without existing in the leaderboard
authorTim Northover <tnorthover@apple.com>
Tue, 14 Jul 2015 21:03:18 +0000 (21:03 +0000)
committerTim Northover <tnorthover@apple.com>
Tue, 14 Jul 2015 21:03:18 +0000 (21:03 +0000)
Sometimes an incidentally created instruction can duplicate a Value used
elsewhere. It then often doesn't end up in the leader table. If it's later
removed, we attempt to remove it from the leader table and segfault.

Instead we should just ignore the removal request, which won't cause any
problems. The reverse situation, where the original instruction is replaced by
the new one (which you might think could leave the leader table empty) cannot
occur, because the incidental instruction will never be found in the first
place.

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

lib/Transforms/Scalar/GVN.cpp
test/Transforms/GVN/pre-new-inst.ll [new file with mode: 0644]

index 2c47a8ab78385a6dfa874f053d8c1faeb1b39bb3..b1a0db356a1e0a2ffb6807d946b7026f9eb952a8 100644 (file)
@@ -656,11 +656,14 @@ namespace {
       LeaderTableEntry* Prev = nullptr;
       LeaderTableEntry* Curr = &LeaderTable[N];
 
-      while (Curr->Val != I || Curr->BB != BB) {
+      while (Curr && (Curr->Val != I || Curr->BB != BB)) {
         Prev = Curr;
         Curr = Curr->Next;
       }
 
+      if (!Curr)
+        return;
+
       if (Prev) {
         Prev->Next = Curr->Next;
       } else {
diff --git a/test/Transforms/GVN/pre-new-inst.ll b/test/Transforms/GVN/pre-new-inst.ll
new file mode 100644 (file)
index 0000000..238b8a6
--- /dev/null
@@ -0,0 +1,29 @@
+; RUN: opt -basicaa -gvn -S %s | FileCheck %s
+
+%MyStruct = type { i32, i32 }
+define i8 @foo(i64 %in, i8* %arr) {
+  %addr = alloca %MyStruct
+  %dead = trunc i64 %in to i32
+  br i1 undef, label %next, label %tmp
+
+tmp:
+  call void @bar()
+  br label %next
+
+next:
+  %addr64 = bitcast %MyStruct* %addr to i64*
+  store i64 %in, i64* %addr64
+  br label %final
+
+final:
+  %addr32 = getelementptr %MyStruct, %MyStruct* %addr, i32 0, i32 0
+  %idx32 = load i32, i32* %addr32
+
+; CHECK: %resptr = getelementptr i8, i8* %arr, i32 %dead
+  %resptr = getelementptr i8, i8* %arr, i32 %idx32
+  %res = load i8, i8* %resptr
+
+  ret i8 %res
+}
+
+declare void @bar()