aboutsummaryrefslogtreecommitdiff
path: root/test/Transforms/Util
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2016-07-23 20:41:05 +0000
committerDimitry Andric <dim@FreeBSD.org>2016-07-23 20:41:05 +0000
commit01095a5d43bbfde13731688ddcf6048ebb8b7721 (patch)
tree4def12e759965de927d963ac65840d663ef9d1ea /test/Transforms/Util
parentf0f4822ed4b66e3579e92a89f368f8fb860e218e (diff)
Vendor import of llvm release_39 branch r276489:vendor/llvm/llvm-release_39-r276489
Diffstat (limited to 'test/Transforms/Util')
-rw-r--r--test/Transforms/Util/MemorySSA/assume.ll19
-rw-r--r--test/Transforms/Util/MemorySSA/atomic-clobber.ll18
-rw-r--r--test/Transforms/Util/MemorySSA/cyclicphi.ll124
-rw-r--r--test/Transforms/Util/MemorySSA/forward-unreachable.ll23
-rw-r--r--test/Transforms/Util/MemorySSA/function-clobber.ll54
-rw-r--r--test/Transforms/Util/MemorySSA/function-mem-attrs.ll59
-rw-r--r--test/Transforms/Util/MemorySSA/livein.ll53
-rw-r--r--test/Transforms/Util/MemorySSA/load-invariant.ll25
-rw-r--r--test/Transforms/Util/MemorySSA/many-dom-backedge.ll77
-rw-r--r--test/Transforms/Util/MemorySSA/many-doms.ll67
-rw-r--r--test/Transforms/Util/MemorySSA/multi-edges.ll32
-rw-r--r--test/Transforms/Util/MemorySSA/multiple-backedges-hal.ll73
-rw-r--r--test/Transforms/Util/MemorySSA/multiple-locations.ll25
-rw-r--r--test/Transforms/Util/MemorySSA/no-disconnected.ll43
-rw-r--r--test/Transforms/Util/MemorySSA/optimize-use.ll37
-rw-r--r--test/Transforms/Util/MemorySSA/phi-translation.ll182
-rw-r--r--test/Transforms/Util/MemorySSA/volatile-clobber.ll22
-rw-r--r--test/Transforms/Util/simplify-dbg-declare-load.ll9
-rw-r--r--test/Transforms/Util/split-bit-piece.ll4
-rw-r--r--test/Transforms/Util/store-first-op.ll36
20 files changed, 976 insertions, 6 deletions
diff --git a/test/Transforms/Util/MemorySSA/assume.ll b/test/Transforms/Util/MemorySSA/assume.ll
new file mode 100644
index 000000000000..d771c78eb1cf
--- /dev/null
+++ b/test/Transforms/Util/MemorySSA/assume.ll
@@ -0,0 +1,19 @@
+; RUN: opt -basicaa -memoryssa -analyze < %s 2>&1 | FileCheck %s
+; RUN: opt -aa-pipeline=basic-aa -passes='print<memoryssa>,verify<memoryssa>' -disable-output < %s 2>&1 | FileCheck %s
+;
+; Ensures that assumes are treated as not reading or writing memory.
+
+declare void @llvm.assume(i1)
+
+define i32 @foo(i32* %a, i32* %b, i1 %c) {
+; CHECK: 1 = MemoryDef(liveOnEntry)
+; CHECK-NEXT: store i32 4
+ store i32 4, i32* %a, align 4
+; CHECK-NOT: MemoryDef
+; CHECK: call void @llvm.assume
+ call void @llvm.assume(i1 %c)
+; CHECK: MemoryUse(1)
+; CHECK-NEXT: %1 = load i32
+ %1 = load i32, i32* %a, align 4
+ ret i32 %1
+}
diff --git a/test/Transforms/Util/MemorySSA/atomic-clobber.ll b/test/Transforms/Util/MemorySSA/atomic-clobber.ll
new file mode 100644
index 000000000000..217d5f65d787
--- /dev/null
+++ b/test/Transforms/Util/MemorySSA/atomic-clobber.ll
@@ -0,0 +1,18 @@
+; RUN: opt -basicaa -print-memoryssa -verify-memoryssa -analyze < %s 2>&1 | FileCheck %s
+; RUN: opt -aa-pipeline=basic-aa -passes='print<memoryssa>,verify<memoryssa>' -disable-output < %s 2>&1 | FileCheck %s
+;
+; Ensures that atomic loads count as MemoryDefs
+
+define i32 @foo(i32* %a, i32* %b) {
+; CHECK: 1 = MemoryDef(liveOnEntry)
+; CHECK-NEXT: store i32 4
+ store i32 4, i32* %a, align 4
+; CHECK: 2 = MemoryDef(1)
+; CHECK-NEXT: %1 = load atomic i32
+ %1 = load atomic i32, i32* %b acquire, align 4
+; CHECK: MemoryUse(2)
+; CHECK-NEXT: %2 = load i32
+ %2 = load i32, i32* %a, align 4
+ %3 = add i32 %1, %2
+ ret i32 %3
+}
diff --git a/test/Transforms/Util/MemorySSA/cyclicphi.ll b/test/Transforms/Util/MemorySSA/cyclicphi.ll
new file mode 100644
index 000000000000..c9a5422e0a18
--- /dev/null
+++ b/test/Transforms/Util/MemorySSA/cyclicphi.ll
@@ -0,0 +1,124 @@
+; RUN: opt -basicaa -print-memoryssa -verify-memoryssa -analyze < %s 2>&1 | FileCheck %s
+; RUN: opt -aa-pipeline=basic-aa -passes='print<memoryssa>,verify<memoryssa>' -disable-output < %s 2>&1 | FileCheck %s
+
+%struct.hoge = type { i32, %struct.widget }
+%struct.widget = type { i64 }
+
+define hidden void @quux(%struct.hoge *%f) align 2 {
+ %tmp = getelementptr inbounds %struct.hoge, %struct.hoge* %f, i64 0, i32 1, i32 0
+ %tmp24 = getelementptr inbounds %struct.hoge, %struct.hoge* %f, i64 0, i32 1
+ %tmp25 = bitcast %struct.widget* %tmp24 to i64**
+ br label %bb26
+
+bb26: ; preds = %bb77, %0
+; CHECK: 3 = MemoryPhi({%0,liveOnEntry},{bb77,2})
+; CHECK-NEXT: br i1 undef, label %bb68, label %bb77
+ br i1 undef, label %bb68, label %bb77
+
+bb68: ; preds = %bb26
+; CHECK: MemoryUse(liveOnEntry)
+; CHECK-NEXT: %tmp69 = load i64, i64* null, align 8
+ %tmp69 = load i64, i64* null, align 8
+; CHECK: 1 = MemoryDef(3)
+; CHECK-NEXT: store i64 %tmp69, i64* %tmp, align 8
+ store i64 %tmp69, i64* %tmp, align 8
+ br label %bb77
+
+bb77: ; preds = %bb68, %bb26
+; CHECK: 2 = MemoryPhi({bb26,3},{bb68,1})
+; CHECK: MemoryUse(2)
+; CHECK-NEXT: %tmp78 = load i64*, i64** %tmp25, align 8
+ %tmp78 = load i64*, i64** %tmp25, align 8
+ %tmp79 = getelementptr inbounds i64, i64* %tmp78, i64 undef
+ br label %bb26
+}
+
+; CHECK-LABEL: define void @quux_skip
+define void @quux_skip(%struct.hoge* noalias %f, i64* noalias %g) align 2 {
+ %tmp = getelementptr inbounds %struct.hoge, %struct.hoge* %f, i64 0, i32 1, i32 0
+ %tmp24 = getelementptr inbounds %struct.hoge, %struct.hoge* %f, i64 0, i32 1
+ %tmp25 = bitcast %struct.widget* %tmp24 to i64**
+ br label %bb26
+
+bb26: ; preds = %bb77, %0
+; CHECK: 3 = MemoryPhi({%0,liveOnEntry},{bb77,2})
+; CHECK-NEXT: br i1 undef, label %bb68, label %bb77
+ br i1 undef, label %bb68, label %bb77
+
+bb68: ; preds = %bb26
+; CHECK: MemoryUse(3)
+; CHECK-NEXT: %tmp69 = load i64, i64* %g, align 8
+ %tmp69 = load i64, i64* %g, align 8
+; CHECK: 1 = MemoryDef(3)
+; CHECK-NEXT: store i64 %tmp69, i64* %g, align 8
+ store i64 %tmp69, i64* %g, align 8
+ br label %bb77
+
+bb77: ; preds = %bb68, %bb26
+; CHECK: 2 = MemoryPhi({bb26,3},{bb68,1})
+; FIXME: This should be MemoryUse(liveOnEntry)
+; CHECK: MemoryUse(3)
+; CHECK-NEXT: %tmp78 = load i64*, i64** %tmp25, align 8
+ %tmp78 = load i64*, i64** %tmp25, align 8
+ br label %bb26
+}
+
+; CHECK-LABEL: define void @quux_dominated
+define void @quux_dominated(%struct.hoge* noalias %f, i64* noalias %g) align 2 {
+ %tmp = getelementptr inbounds %struct.hoge, %struct.hoge* %f, i64 0, i32 1, i32 0
+ %tmp24 = getelementptr inbounds %struct.hoge, %struct.hoge* %f, i64 0, i32 1
+ %tmp25 = bitcast %struct.widget* %tmp24 to i64**
+ br label %bb26
+
+bb26: ; preds = %bb77, %0
+; CHECK: 4 = MemoryPhi({%0,liveOnEntry},{bb77,2})
+; CHECK: MemoryUse(4)
+; CHECK-NEXT: load i64*, i64** %tmp25, align 8
+ load i64*, i64** %tmp25, align 8
+ br i1 undef, label %bb68, label %bb77
+
+bb68: ; preds = %bb26
+; CHECK: MemoryUse(4)
+; CHECK-NEXT: %tmp69 = load i64, i64* %g, align 8
+ %tmp69 = load i64, i64* %g, align 8
+; CHECK: 1 = MemoryDef(4)
+; CHECK-NEXT: store i64 %tmp69, i64* %g, align 8
+ store i64 %tmp69, i64* %g, align 8
+ br label %bb77
+
+bb77: ; preds = %bb68, %bb26
+; CHECK: 3 = MemoryPhi({bb26,4},{bb68,1})
+; CHECK: 2 = MemoryDef(3)
+; CHECK-NEXT: store i64* null, i64** %tmp25, align 8
+ store i64* null, i64** %tmp25, align 8
+ br label %bb26
+}
+
+; CHECK-LABEL: define void @quux_nodominate
+define void @quux_nodominate(%struct.hoge* noalias %f, i64* noalias %g) align 2 {
+ %tmp = getelementptr inbounds %struct.hoge, %struct.hoge* %f, i64 0, i32 1, i32 0
+ %tmp24 = getelementptr inbounds %struct.hoge, %struct.hoge* %f, i64 0, i32 1
+ %tmp25 = bitcast %struct.widget* %tmp24 to i64**
+ br label %bb26
+
+bb26: ; preds = %bb77, %0
+; CHECK: 3 = MemoryPhi({%0,liveOnEntry},{bb77,2})
+; CHECK: MemoryUse(liveOnEntry)
+; CHECK-NEXT: load i64*, i64** %tmp25, align 8
+ load i64*, i64** %tmp25, align 8
+ br i1 undef, label %bb68, label %bb77
+
+bb68: ; preds = %bb26
+; CHECK: MemoryUse(3)
+; CHECK-NEXT: %tmp69 = load i64, i64* %g, align 8
+ %tmp69 = load i64, i64* %g, align 8
+; CHECK: 1 = MemoryDef(3)
+; CHECK-NEXT: store i64 %tmp69, i64* %g, align 8
+ store i64 %tmp69, i64* %g, align 8
+ br label %bb77
+
+bb77: ; preds = %bb68, %bb26
+; CHECK: 2 = MemoryPhi({bb26,3},{bb68,1})
+; CHECK-NEXT: br label %bb26
+ br label %bb26
+}
diff --git a/test/Transforms/Util/MemorySSA/forward-unreachable.ll b/test/Transforms/Util/MemorySSA/forward-unreachable.ll
new file mode 100644
index 000000000000..2bbf399daae4
--- /dev/null
+++ b/test/Transforms/Util/MemorySSA/forward-unreachable.ll
@@ -0,0 +1,23 @@
+; RUN: opt -aa-pipeline=basic-aa -passes='print<memoryssa>,verify<memoryssa>' -disable-output < %s 2>&1 | FileCheck %s
+target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
+
+define void @test() {
+entry:
+ br i1 undef, label %split1, label %split2
+
+split1:
+ store i16 undef, i16* undef, align 2
+ br label %merge
+split2:
+ br label %merge
+forwardunreachable:
+ br label %merge
+merge:
+; The forwardunreachable block still needs an entry in the phi node,
+; because it is reverse reachable, so the CFG still has it as a
+; predecessor of the block
+; CHECK: 3 = MemoryPhi({split1,1},{split2,liveOnEntry},{forwardunreachable,liveOnEntry})
+ store i16 undef, i16* undef, align 2
+ ret void
+}
+
diff --git a/test/Transforms/Util/MemorySSA/function-clobber.ll b/test/Transforms/Util/MemorySSA/function-clobber.ll
new file mode 100644
index 000000000000..a01893a5b954
--- /dev/null
+++ b/test/Transforms/Util/MemorySSA/function-clobber.ll
@@ -0,0 +1,54 @@
+; RUN: opt -basicaa -print-memoryssa -verify-memoryssa -analyze < %s 2>&1 | FileCheck %s
+; RUN: opt -aa-pipeline=basic-aa -passes='print<memoryssa>,verify<memoryssa>' -disable-output < %s 2>&1 | FileCheck %s
+;
+; Ensuring that external functions without attributes are MemoryDefs
+
+@g = external global i32
+declare void @modifyG()
+
+define i32 @foo() {
+; CHECK: MemoryUse(liveOnEntry)
+; CHECK-NEXT: %1 = load i32
+ %1 = load i32, i32* @g
+
+; CHECK: 1 = MemoryDef(liveOnEntry)
+; CHECK-NEXT: store i32 4
+ store i32 4, i32* @g, align 4
+
+; CHECK: 2 = MemoryDef(1)
+; CHECK-NEXT: call void @modifyG()
+ call void @modifyG()
+
+; CHECK: MemoryUse(2)
+; CHECK-NEXT: %2 = load i32
+ %2 = load i32, i32* @g
+ %3 = add i32 %2, %1
+ ret i32 %3
+}
+
+declare void @readEverything() readonly
+declare void @clobberEverything()
+
+; CHECK-LABEL: define void @bar
+define void @bar() {
+; CHECK: 1 = MemoryDef(liveOnEntry)
+; CHECK-NEXT: call void @clobberEverything()
+ call void @clobberEverything()
+ br i1 undef, label %if.end, label %if.then
+
+if.then:
+; CHECK: MemoryUse(1)
+; CHECK-NEXT: call void @readEverything()
+ call void @readEverything()
+; CHECK: 2 = MemoryDef(1)
+; CHECK-NEXT: call void @clobberEverything()
+ call void @clobberEverything()
+ br label %if.end
+
+if.end:
+; CHECK: 3 = MemoryPhi({%0,1},{if.then,2})
+; CHECK: MemoryUse(3)
+; CHECK-NEXT: call void @readEverything()
+ call void @readEverything()
+ ret void
+}
diff --git a/test/Transforms/Util/MemorySSA/function-mem-attrs.ll b/test/Transforms/Util/MemorySSA/function-mem-attrs.ll
new file mode 100644
index 000000000000..11383771a413
--- /dev/null
+++ b/test/Transforms/Util/MemorySSA/function-mem-attrs.ll
@@ -0,0 +1,59 @@
+; RUN: opt -basicaa -print-memoryssa -verify-memoryssa -analyze < %s 2>&1 | FileCheck %s
+; RUN: opt -aa-pipeline=basic-aa -passes='print<memoryssa>,verify<memoryssa>' -disable-output < %s 2>&1 | FileCheck %s
+;
+; Test that various function attributes give us sane results.
+
+@g = external global i32
+
+declare void @readonlyFunction() readonly
+declare void @noattrsFunction()
+
+define void @readonlyAttr() {
+; CHECK: 1 = MemoryDef(liveOnEntry)
+; CHECK-NEXT: store i32 0
+ store i32 0, i32* @g, align 4
+
+ %1 = alloca i32, align 4
+; CHECK: 2 = MemoryDef(1)
+; CHECK-NEXT: store i32 0
+ store i32 0, i32* %1, align 4
+
+; CHECK: MemoryUse(1)
+; CHECK-NEXT: call void @readonlyFunction()
+ call void @readonlyFunction()
+
+; CHECK: MemoryUse(1)
+; CHECK-NEXT: call void @noattrsFunction() #
+; Assume that #N is readonly
+ call void @noattrsFunction() readonly
+
+ ; Sanity check that noattrsFunction is otherwise a MemoryDef
+; CHECK: 3 = MemoryDef(2)
+; CHECK-NEXT: call void @noattrsFunction()
+ call void @noattrsFunction()
+ ret void
+}
+
+declare void @argMemOnly(i32*) argmemonly
+
+define void @inaccessableOnlyAttr() {
+ %1 = alloca i32, align 4
+; CHECK: 1 = MemoryDef(liveOnEntry)
+; CHECK-NEXT: store i32 0
+ store i32 0, i32* %1, align 4
+
+; CHECK: 2 = MemoryDef(1)
+; CHECK-NEXT: store i32 0
+ store i32 0, i32* @g, align 4
+
+; CHECK: MemoryUse(1)
+; CHECK-NEXT: call void @argMemOnly(i32* %1) #
+; Assume that #N is readonly
+ call void @argMemOnly(i32* %1) readonly
+
+; CHECK: 3 = MemoryDef(2)
+; CHECK-NEXT: call void @argMemOnly(i32* %1)
+ call void @argMemOnly(i32* %1)
+
+ ret void
+}
diff --git a/test/Transforms/Util/MemorySSA/livein.ll b/test/Transforms/Util/MemorySSA/livein.ll
new file mode 100644
index 000000000000..93072ea97daf
--- /dev/null
+++ b/test/Transforms/Util/MemorySSA/livein.ll
@@ -0,0 +1,53 @@
+; RUN: opt -basicaa -print-memoryssa -verify-memoryssa -analyze < %s 2>&1 | FileCheck %s
+; RUN: opt -aa-pipeline=basic-aa -passes='print<memoryssa>,verify<memoryssa>' -disable-output < %s 2>&1 | FileCheck %s
+define void @F(i8*) {
+ br i1 true, label %left, label %right
+left:
+; CHECK: 1 = MemoryDef(liveOnEntry)
+ store i8 16, i8* %0
+ br label %merge
+right:
+ br label %merge
+
+merge:
+; CHECK-NOT: 2 = MemoryPhi
+ret void
+}
+
+define void @F2(i8*) {
+ br i1 true, label %left, label %right
+left:
+; CHECK: 1 = MemoryDef(liveOnEntry)
+ store i8 16, i8* %0
+ br label %merge
+right:
+ br label %merge
+
+merge:
+; CHECK: 2 = MemoryPhi({left,1},{right,liveOnEntry})
+%c = load i8, i8* %0
+ret void
+}
+
+; Ensure we treat def-only blocks as though they have uses for phi placement.
+; CHECK-LABEL: define void @F3
+define void @F3() {
+ %a = alloca i8
+; CHECK: 1 = MemoryDef(liveOnEntry)
+; CHECK-NEXT: store i8 0, i8* %a
+ store i8 0, i8* %a
+ br i1 undef, label %if.then, label %if.end
+
+if.then:
+; CHECK: 2 = MemoryDef(1)
+; CHECK-NEXT: store i8 1, i8* %a
+ store i8 1, i8* %a
+ br label %if.end
+
+if.end:
+; CHECK: 4 = MemoryPhi({%0,1},{if.then,2})
+; CHECK: 3 = MemoryDef(4)
+; CHECK-NEXT: store i8 2, i8* %a
+ store i8 2, i8* %a
+ ret void
+}
diff --git a/test/Transforms/Util/MemorySSA/load-invariant.ll b/test/Transforms/Util/MemorySSA/load-invariant.ll
new file mode 100644
index 000000000000..e387ff4c5302
--- /dev/null
+++ b/test/Transforms/Util/MemorySSA/load-invariant.ll
@@ -0,0 +1,25 @@
+; XFAIL: *
+; RUN: opt -basicaa -print-memoryssa -verify-memoryssa -analyze < %s 2>&1 | FileCheck %s
+; RUN: opt -aa-pipeline=basic-aa -passes='print<memoryssa>' -verify-memoryssa -disable-output < %s 2>&1 | FileCheck %s
+;
+; Invariant loads should be considered live on entry, because, once the
+; location is known to be dereferenceable, the value can never change.
+;
+; Currently XFAILed because this optimization was held back from the initial
+; commit.
+
+@g = external global i32
+
+declare void @clobberAllTheThings()
+
+define i32 @foo() {
+; CHECK: 1 = MemoryDef(liveOnEntry)
+; CHECK-NEXT: call void @clobberAllTheThings()
+ call void @clobberAllTheThings()
+; CHECK: MemoryUse(liveOnEntry)
+; CHECK-NEXT: %1 = load i32
+ %1 = load i32, i32* @g, align 4, !invariant.load !0
+ ret i32 %1
+}
+
+!0 = !{}
diff --git a/test/Transforms/Util/MemorySSA/many-dom-backedge.ll b/test/Transforms/Util/MemorySSA/many-dom-backedge.ll
new file mode 100644
index 000000000000..3d76f4af2d61
--- /dev/null
+++ b/test/Transforms/Util/MemorySSA/many-dom-backedge.ll
@@ -0,0 +1,77 @@
+; RUN: opt -basicaa -print-memoryssa -verify-memoryssa -analyze < %s 2>&1 | FileCheck %s
+; RUN: opt -aa-pipeline=basic-aa -passes='print<memoryssa>,verify<memoryssa>' -disable-output < %s 2>&1 | FileCheck %s
+;
+; many-dom.ll, with an added back-edge back into the switch.
+; Because people love their gotos.
+
+declare i1 @getBool() readnone
+
+define i32 @foo(i32* %p) {
+entry:
+ br label %loopbegin
+
+loopbegin:
+; CHECK: 9 = MemoryPhi({entry,liveOnEntry},{sw.epilog,6})
+; CHECK-NEXT: %n =
+ %n = phi i32 [ 0, %entry ], [ %1, %sw.epilog ]
+ %m = alloca i32, align 4
+ switch i32 %n, label %sw.default [
+ i32 0, label %sw.bb
+ i32 1, label %sw.bb1
+ i32 2, label %sw.bb2
+ i32 3, label %sw.bb3
+ ]
+
+sw.bb:
+; CHECK: 1 = MemoryDef(9)
+; CHECK-NEXT: store i32 1
+ store i32 1, i32* %m, align 4
+ br label %sw.epilog
+
+sw.bb1:
+; CHECK: 2 = MemoryDef(9)
+; CHECK-NEXT: store i32 2
+ store i32 2, i32* %m, align 4
+ br label %sw.epilog
+
+sw.bb2:
+; CHECK: 3 = MemoryDef(9)
+; CHECK-NEXT: store i32 3
+ store i32 3, i32* %m, align 4
+ br label %sw.epilog
+
+sw.bb3:
+; CHECK: 10 = MemoryPhi({loopbegin,9},{sw.almostexit,6})
+; CHECK: 4 = MemoryDef(10)
+; CHECK-NEXT: store i32 4
+ store i32 4, i32* %m, align 4
+ br label %sw.epilog
+
+sw.default:
+; CHECK: 5 = MemoryDef(9)
+; CHECK-NEXT: store i32 5
+ store i32 5, i32* %m, align 4
+ br label %sw.epilog
+
+sw.epilog:
+; CHECK: 8 = MemoryPhi({sw.default,5},{sw.bb3,4},{sw.bb,1},{sw.bb1,2},{sw.bb2,3})
+; CHECK-NEXT: MemoryUse(8)
+; CHECK-NEXT: %0 =
+ %0 = load i32, i32* %m, align 4
+; CHECK: 6 = MemoryDef(8)
+; CHECK-NEXT: %1 =
+ %1 = load volatile i32, i32* %p, align 4
+ %2 = icmp eq i32 %0, %1
+ br i1 %2, label %sw.almostexit, label %loopbegin
+
+sw.almostexit:
+ %3 = icmp eq i32 0, %1
+ br i1 %3, label %exit, label %sw.bb3
+
+exit:
+; CHECK: 7 = MemoryDef(6)
+; CHECK-NEXT: %4 = load volatile i32
+ %4 = load volatile i32, i32* %p, align 4
+ %5 = add i32 %4, %1
+ ret i32 %5
+}
diff --git a/test/Transforms/Util/MemorySSA/many-doms.ll b/test/Transforms/Util/MemorySSA/many-doms.ll
new file mode 100644
index 000000000000..d2e6c6fa1e43
--- /dev/null
+++ b/test/Transforms/Util/MemorySSA/many-doms.ll
@@ -0,0 +1,67 @@
+; RUN: opt -basicaa -print-memoryssa -verify-memoryssa -analyze < %s 2>&1 | FileCheck %s
+; RUN: opt -aa-pipeline=basic-aa -passes='print<memoryssa>,verify<memoryssa>' -disable-output < %s 2>&1 | FileCheck %s
+;
+; Testing many dominators, specifically from a switch statement in C.
+
+declare i1 @getBool() readnone
+
+define i32 @foo(i32* %p) {
+entry:
+ br label %loopbegin
+
+loopbegin:
+; CHECK: 8 = MemoryPhi({entry,liveOnEntry},{sw.epilog,6})
+; CHECK-NEXT: %n =
+ %n = phi i32 [ 0, %entry ], [ %1, %sw.epilog ]
+ %m = alloca i32, align 4
+ switch i32 %n, label %sw.default [
+ i32 0, label %sw.bb
+ i32 1, label %sw.bb1
+ i32 2, label %sw.bb2
+ i32 3, label %sw.bb3
+ ]
+
+sw.bb:
+; CHECK: 1 = MemoryDef(8)
+; CHECK-NEXT: store i32 1
+ store i32 1, i32* %m, align 4
+ br label %sw.epilog
+
+sw.bb1:
+; CHECK: 2 = MemoryDef(8)
+; CHECK-NEXT: store i32 2
+ store i32 2, i32* %m, align 4
+ br label %sw.epilog
+
+sw.bb2:
+; CHECK: 3 = MemoryDef(8)
+; CHECK-NEXT: store i32 3
+ store i32 3, i32* %m, align 4
+ br label %sw.epilog
+
+sw.bb3:
+; CHECK: 4 = MemoryDef(8)
+; CHECK-NEXT: store i32 4
+ store i32 4, i32* %m, align 4
+ br label %sw.epilog
+
+sw.default:
+; CHECK: 5 = MemoryDef(8)
+; CHECK-NEXT: store i32 5
+ store i32 5, i32* %m, align 4
+ br label %sw.epilog
+
+sw.epilog:
+; CHECK: 7 = MemoryPhi({sw.default,5},{sw.bb,1},{sw.bb1,2},{sw.bb2,3},{sw.bb3,4})
+; CHECK-NEXT: MemoryUse(7)
+; CHECK-NEXT: %0 =
+ %0 = load i32, i32* %m, align 4
+; CHECK: 6 = MemoryDef(7)
+; CHECK-NEXT: %1 =
+ %1 = load volatile i32, i32* %p, align 4
+ %2 = icmp eq i32 %0, %1
+ br i1 %2, label %exit, label %loopbegin
+
+exit:
+ ret i32 %1
+}
diff --git a/test/Transforms/Util/MemorySSA/multi-edges.ll b/test/Transforms/Util/MemorySSA/multi-edges.ll
new file mode 100644
index 000000000000..c13fc016b2c7
--- /dev/null
+++ b/test/Transforms/Util/MemorySSA/multi-edges.ll
@@ -0,0 +1,32 @@
+; RUN: opt -basicaa -print-memoryssa -verify-memoryssa -analyze < %s 2>&1 | FileCheck %s
+; RUN: opt -aa-pipeline=basic-aa -passes='print<memoryssa>,verify<memoryssa>' -disable-output < %s 2>&1 | FileCheck %s
+;
+; Makes sure we have a sane model if both successors of some block is the same
+; block.
+
+define i32 @foo(i1 %a) {
+entry:
+ %0 = alloca i32, align 4
+; CHECK: 1 = MemoryDef(liveOnEntry)
+; CHECK-NEXT: store i32 4
+ store i32 4, i32* %0
+ br i1 %a, label %Loop.Body, label %Loop.End
+
+Loop.Body:
+; CHECK: 4 = MemoryPhi({entry,1},{Loop.End,3})
+; CHECK-NEXT: 2 = MemoryDef(4)
+; CHECK-NEXT: store i32 5
+ store i32 5, i32* %0, align 4
+ br i1 %a, label %Loop.End, label %Loop.End ; WhyDoWeEvenHaveThatLever.gif
+
+Loop.End:
+; CHECK: 3 = MemoryPhi({entry,1},{Loop.Body,2},{Loop.Body,2})
+; CHECK-NEXT: MemoryUse(3)
+; CHECK-NEXT: %1 = load
+ %1 = load i32, i32* %0, align 4
+ %2 = icmp eq i32 5, %1
+ br i1 %2, label %Ret, label %Loop.Body
+
+Ret:
+ ret i32 %1
+}
diff --git a/test/Transforms/Util/MemorySSA/multiple-backedges-hal.ll b/test/Transforms/Util/MemorySSA/multiple-backedges-hal.ll
new file mode 100644
index 000000000000..473b3685801c
--- /dev/null
+++ b/test/Transforms/Util/MemorySSA/multiple-backedges-hal.ll
@@ -0,0 +1,73 @@
+; RUN: opt -basicaa -print-memoryssa -verify-memoryssa -analyze < %s 2>&1 | FileCheck %s
+; RUN: opt -aa-pipeline=basic-aa -passes='print<memoryssa>,verify<memoryssa>' -disable-output < %s 2>&1 | FileCheck %s
+
+; hfinkel's case
+; [entry]
+; |
+; .....
+; (clobbering access - b)
+; |
+; .... ________________________________
+; \ / |
+; (x) |
+; ...... |
+; | |
+; | ______________________ |
+; \ / | |
+; (starting access) | |
+; ... | |
+; (clobbering access - a) | |
+; ... | |
+; | | | |
+; | |_______________________| |
+; | |
+; |_________________________________|
+;
+; More specifically, one access, with multiple clobbering accesses. One of
+; which strictly dominates the access, the other of which has a backedge
+
+; readnone so we don't have a 1:1 mapping of MemorySSA edges to Instructions.
+declare void @doThingWithoutReading() readnone
+declare i8 @getValue() readnone
+declare i1 @getBool() readnone
+
+define hidden void @testcase(i8* %Arg) {
+Entry:
+ call void @doThingWithoutReading()
+ %Val.Entry = call i8 @getValue()
+; CHECK: 1 = MemoryDef(liveOnEntry)
+; CHECK-NEXT: store i8 %Val.Entry
+ store i8 %Val.Entry, i8* %Arg
+ call void @doThingWithoutReading()
+ br label %OuterLoop
+
+OuterLoop:
+; CHECK: 5 = MemoryPhi({Entry,1},{InnerLoop.Tail,3})
+; CHECK-NEXT: %Val.Outer =
+ %Val.Outer = call i8 @getValue()
+; CHECK: 2 = MemoryDef(5)
+; CHECK-NEXT: store i8 %Val.Outer
+ store i8 %Val.Outer, i8* %Arg
+ call void @doThingWithoutReading()
+ br label %InnerLoop
+
+InnerLoop:
+; CHECK: 4 = MemoryPhi({OuterLoop,2},{InnerLoop,3})
+; CHECK-NEXT: ; MemoryUse(4)
+; CHECK-NEXT: %StartingAccess = load
+ %StartingAccess = load i8, i8* %Arg, align 4
+ %Val.Inner = call i8 @getValue()
+; CHECK: 3 = MemoryDef(4)
+; CHECK-NEXT: store i8 %Val.Inner
+ store i8 %Val.Inner, i8* %Arg
+ call void @doThingWithoutReading()
+ %KeepGoing = call i1 @getBool()
+ br i1 %KeepGoing, label %InnerLoop.Tail, label %InnerLoop
+
+InnerLoop.Tail:
+ %KeepGoing.Tail = call i1 @getBool()
+ br i1 %KeepGoing.Tail, label %End, label %OuterLoop
+
+End:
+ ret void
+}
diff --git a/test/Transforms/Util/MemorySSA/multiple-locations.ll b/test/Transforms/Util/MemorySSA/multiple-locations.ll
new file mode 100644
index 000000000000..9a3e87e4ab6d
--- /dev/null
+++ b/test/Transforms/Util/MemorySSA/multiple-locations.ll
@@ -0,0 +1,25 @@
+; RUN: opt -basicaa -print-memoryssa -verify-memoryssa -analyze < %s 2>&1 | FileCheck %s
+; RUN: opt -aa-pipeline=basic-aa -passes='print<memoryssa>,verify<memoryssa>' -disable-output < %s 2>&1 | FileCheck %s
+;
+; Checks that basicAA is doing some amount of disambiguation for us
+
+define i32 @foo(i1 %cond) {
+ %a = alloca i32, align 4
+ %b = alloca i32, align 4
+; CHECK: 1 = MemoryDef(liveOnEntry)
+; CHECK-NEXT: store i32 0
+ store i32 0, i32* %a, align 4
+; CHECK: 2 = MemoryDef(1)
+; CHECK-NEXT: store i32 1
+ store i32 1, i32* %b, align 4
+
+; CHECK: MemoryUse(1)
+; CHECK-NEXT: %1 = load i32
+ %1 = load i32, i32* %a, align 4
+; CHECK: MemoryUse(2)
+; CHECK-NEXT: %2 = load i32
+ %2 = load i32, i32* %b, align 4
+
+ %3 = add i32 %1, %2
+ ret i32 %3
+}
diff --git a/test/Transforms/Util/MemorySSA/no-disconnected.ll b/test/Transforms/Util/MemorySSA/no-disconnected.ll
new file mode 100644
index 000000000000..d1dcb15893ad
--- /dev/null
+++ b/test/Transforms/Util/MemorySSA/no-disconnected.ll
@@ -0,0 +1,43 @@
+; RUN: opt -basicaa -print-memoryssa -verify-memoryssa -analyze < %s 2>&1 | FileCheck %s
+; RUN: opt -aa-pipeline=basic-aa -passes='print<memoryssa>,verify<memoryssa>' -disable-output < %s 2>&1 | FileCheck %s
+;
+; This test ensures we don't end up with multiple reaching defs for a single
+; use/phi edge If we were to optimize defs, we would end up with 2=
+; MemoryDef(liveOnEntry) and 4 = MemoryDef(liveOnEntry) Both would mean both
+; 1,2, and 3,4 would reach the phi node. Because the phi node can only have one
+; entry on each edge, it would choose 2, 4 and disconnect 1 and 3 completely
+; from the SSA graph, even though they are not dead
+
+define void @sink_store(i32 %index, i32* %foo, i32* %bar) {
+entry:
+ %cmp = trunc i32 %index to i1
+ br i1 %cmp, label %if.then, label %if.else
+
+if.then: ; preds = %entry
+; CHECK: 1 = MemoryDef(liveOnEntry)
+; CHECK-NEXT: store i32 %index, i32* %foo, align 4
+ store i32 %index, i32* %foo, align 4
+; CHECK: 2 = MemoryDef(1)
+; CHECK-NEXT: store i32 %index, i32* %bar, align 4
+ store i32 %index, i32* %bar, align 4
+ br label %if.end
+
+if.else: ; preds = %entry
+; CHECK: 3 = MemoryDef(liveOnEntry)
+; CHECK-NEXT: store i32 %index, i32* %foo, align 4
+ store i32 %index, i32* %foo, align 4
+; CHECK: 4 = MemoryDef(3)
+; CHECK-NEXT: store i32 %index, i32* %bar, align 4
+ store i32 %index, i32* %bar, align 4
+ br label %if.end
+
+if.end: ; preds = %if.else, %if.then
+; CHECK: 5 = MemoryPhi({if.then,2},{if.else,4})
+; CHECK: MemoryUse(5)
+; CHECK-NEXT: %c = load i32, i32* %foo
+ %c = load i32, i32* %foo
+; CHECK: MemoryUse(5)
+; CHECK-NEXT: %d = load i32, i32* %bar
+ %d = load i32, i32* %bar
+ ret void
+}
diff --git a/test/Transforms/Util/MemorySSA/optimize-use.ll b/test/Transforms/Util/MemorySSA/optimize-use.ll
new file mode 100644
index 000000000000..8a8f2dd50959
--- /dev/null
+++ b/test/Transforms/Util/MemorySSA/optimize-use.ll
@@ -0,0 +1,37 @@
+; RUN: opt -basicaa -print-memoryssa -verify-memoryssa -analyze < %s 2>&1 | FileCheck %s
+; RUN: opt -aa-pipeline=basic-aa -passes='print<memoryssa>,verify<memoryssa>' -disable-output < %s 2>&1 | FileCheck %s
+
+; Function Attrs: ssp uwtable
+define i32 @main() {
+entry:
+; CHECK: 1 = MemoryDef(liveOnEntry)
+; CHECK-NEXT: %call = call noalias i8* @_Znwm(i64 4)
+ %call = call noalias i8* @_Znwm(i64 4)
+ %0 = bitcast i8* %call to i32*
+; CHECK: 2 = MemoryDef(1)
+; CHECK-NEXT: %call1 = call noalias i8* @_Znwm(i64 4)
+ %call1 = call noalias i8* @_Znwm(i64 4)
+ %1 = bitcast i8* %call1 to i32*
+; CHECK: 3 = MemoryDef(2)
+; CHECK-NEXT: store i32 5, i32* %0, align 4
+ store i32 5, i32* %0, align 4
+; CHECK: 4 = MemoryDef(3)
+; CHECK-NEXT: store i32 7, i32* %1, align 4
+ store i32 7, i32* %1, align 4
+; CHECK: MemoryUse(3)
+; CHECK-NEXT: %2 = load i32, i32* %0, align 4
+ %2 = load i32, i32* %0, align 4
+; CHECK: MemoryUse(4)
+; CHECK-NEXT: %3 = load i32, i32* %1, align 4
+ %3 = load i32, i32* %1, align 4
+; CHECK: MemoryUse(3)
+; CHECK-NEXT: %4 = load i32, i32* %0, align 4
+ %4 = load i32, i32* %0, align 4
+; CHECK: MemoryUse(4)
+; CHECK-NEXT: %5 = load i32, i32* %1, align 4
+ %5 = load i32, i32* %1, align 4
+ %add = add nsw i32 %3, %5
+ ret i32 %add
+}
+
+declare noalias i8* @_Znwm(i64)
diff --git a/test/Transforms/Util/MemorySSA/phi-translation.ll b/test/Transforms/Util/MemorySSA/phi-translation.ll
new file mode 100644
index 000000000000..30cd011a119c
--- /dev/null
+++ b/test/Transforms/Util/MemorySSA/phi-translation.ll
@@ -0,0 +1,182 @@
+; RUN: opt -basicaa -print-memoryssa -verify-memoryssa -analyze < %s 2>&1 | FileCheck %s
+; RUN: opt -aa-pipeline=basic-aa -passes='print<memoryssa>,verify<memoryssa>' -disable-output < %s 2>&1 | FileCheck %s
+
+; %ptr can't alias %local, so we should be able to optimize the use of %local to
+; point to the store to %local.
+; CHECK-LABEL: define void @check
+define void @check(i8* %ptr, i1 %bool) {
+entry:
+ %local = alloca i8, align 1
+; CHECK: 1 = MemoryDef(liveOnEntry)
+; CHECK-NEXT: store i8 0, i8* %local, align 1
+ store i8 0, i8* %local, align 1
+ br i1 %bool, label %if.then, label %if.end
+
+if.then:
+ %p2 = getelementptr inbounds i8, i8* %ptr, i32 1
+; CHECK: 2 = MemoryDef(1)
+; CHECK-NEXT: store i8 0, i8* %p2, align 1
+ store i8 0, i8* %p2, align 1
+ br label %if.end
+
+if.end:
+; CHECK: 3 = MemoryPhi({entry,1},{if.then,2})
+; CHECK: MemoryUse(1)
+; CHECK-NEXT: load i8, i8* %local, align 1
+ load i8, i8* %local, align 1
+ ret void
+}
+
+; CHECK-LABEL: define void @check2
+define void @check2(i1 %val1, i1 %val2, i1 %val3) {
+entry:
+ %local = alloca i8, align 1
+ %local2 = alloca i8, align 1
+
+; CHECK: 1 = MemoryDef(liveOnEntry)
+; CHECK-NEXT: store i8 0, i8* %local
+ store i8 0, i8* %local
+ br i1 %val1, label %if.then, label %phi.3
+
+if.then:
+; CHECK: 2 = MemoryDef(1)
+; CHECK-NEXT: store i8 2, i8* %local2
+ store i8 2, i8* %local2
+ br i1 %val2, label %phi.2, label %phi.3
+
+phi.3:
+; CHECK: 6 = MemoryPhi({entry,1},{if.then,2})
+; CHECK: 3 = MemoryDef(6)
+; CHECK-NEXT: store i8 3, i8* %local2
+ store i8 3, i8* %local2
+ br i1 %val3, label %phi.2, label %phi.1
+
+phi.2:
+; CHECK: 5 = MemoryPhi({if.then,2},{phi.3,3})
+; CHECK: 4 = MemoryDef(5)
+; CHECK-NEXT: store i8 4, i8* %local2
+ store i8 4, i8* %local2
+ br label %phi.1
+
+phi.1:
+; Order matters here; phi.2 needs to come before phi.3, because that's the order
+; they're visited in.
+; CHECK: 7 = MemoryPhi({phi.2,4},{phi.3,3})
+; CHECK: MemoryUse(1)
+; CHECK-NEXT: load i8, i8* %local
+ load i8, i8* %local
+ ret void
+}
+
+; CHECK-LABEL: define void @cross_phi
+define void @cross_phi(i8* noalias %p1, i8* noalias %p2) {
+; CHECK: 1 = MemoryDef(liveOnEntry)
+; CHECK-NEXT: store i8 0, i8* %p1
+ store i8 0, i8* %p1
+; CHECK: MemoryUse(1)
+; CHECK-NEXT: load i8, i8* %p1
+ load i8, i8* %p1
+ br i1 undef, label %a, label %b
+
+a:
+; CHECK: 2 = MemoryDef(1)
+; CHECK-NEXT: store i8 0, i8* %p2
+ store i8 0, i8* %p2
+ br i1 undef, label %c, label %d
+
+b:
+; CHECK: 3 = MemoryDef(1)
+; CHECK-NEXT: store i8 1, i8* %p2
+ store i8 1, i8* %p2
+ br i1 undef, label %c, label %d
+
+c:
+; CHECK: 6 = MemoryPhi({a,2},{b,3})
+; CHECK: 4 = MemoryDef(6)
+; CHECK-NEXT: store i8 2, i8* %p2
+ store i8 2, i8* %p2
+ br label %e
+
+d:
+; CHECK: 7 = MemoryPhi({a,2},{b,3})
+; CHECK: 5 = MemoryDef(7)
+; CHECK-NEXT: store i8 3, i8* %p2
+ store i8 3, i8* %p2
+ br label %e
+
+e:
+; 8 = MemoryPhi({c,4},{d,5})
+; CHECK: MemoryUse(1)
+; CHECK-NEXT: load i8, i8* %p1
+ load i8, i8* %p1
+ ret void
+}
+
+; CHECK-LABEL: define void @looped
+define void @looped(i8* noalias %p1, i8* noalias %p2) {
+; CHECK: 1 = MemoryDef(liveOnEntry)
+; CHECK-NEXT: store i8 0, i8* %p1
+ store i8 0, i8* %p1
+ br label %loop.1
+
+loop.1:
+; CHECK: 7 = MemoryPhi({%0,1},{loop.3,4})
+; CHECK: 2 = MemoryDef(7)
+; CHECK-NEXT: store i8 0, i8* %p2
+ store i8 0, i8* %p2
+ br i1 undef, label %loop.2, label %loop.3
+
+loop.2:
+; CHECK: 6 = MemoryPhi({loop.1,2},{loop.3,4})
+; CHECK: 3 = MemoryDef(6)
+; CHECK-NEXT: store i8 1, i8* %p2
+ store i8 1, i8* %p2
+ br label %loop.3
+
+loop.3:
+; CHECK: 5 = MemoryPhi({loop.1,2},{loop.2,3})
+; CHECK: 4 = MemoryDef(5)
+; CHECK-NEXT: store i8 2, i8* %p2
+ store i8 2, i8* %p2
+; FIXME: This should be MemoryUse(1)
+; CHECK: MemoryUse(5)
+; CHECK-NEXT: load i8, i8* %p1
+ load i8, i8* %p1
+ br i1 undef, label %loop.2, label %loop.1
+}
+
+; CHECK-LABEL: define void @looped_visitedonlyonce
+define void @looped_visitedonlyonce(i8* noalias %p1, i8* noalias %p2) {
+ br label %while.cond
+
+while.cond:
+; CHECK: 5 = MemoryPhi({%0,liveOnEntry},{if.end,3})
+; CHECK-NEXT: br i1 undef, label %if.then, label %if.end
+ br i1 undef, label %if.then, label %if.end
+
+if.then:
+; CHECK: 1 = MemoryDef(5)
+; CHECK-NEXT: store i8 0, i8* %p1
+ store i8 0, i8* %p1
+ br i1 undef, label %if.end, label %if.then2
+
+if.then2:
+; CHECK: 2 = MemoryDef(1)
+; CHECK-NEXT: store i8 1, i8* %p2
+ store i8 1, i8* %p2
+ br label %if.end
+
+if.end:
+; CHECK: 4 = MemoryPhi({while.cond,5},{if.then,1},{if.then2,2})
+; CHECK: MemoryUse(4)
+; CHECK-NEXT: load i8, i8* %p1
+ load i8, i8* %p1
+; CHECK: 3 = MemoryDef(4)
+; CHECK-NEXT: store i8 2, i8* %p2
+ store i8 2, i8* %p2
+; CHECK: MemoryUse(4)
+; CHECK-NEXT: load i8, i8* %p1
+ load i8, i8* %p1
+ br label %while.cond
+}
+
diff --git a/test/Transforms/Util/MemorySSA/volatile-clobber.ll b/test/Transforms/Util/MemorySSA/volatile-clobber.ll
new file mode 100644
index 000000000000..baad8d8c2d14
--- /dev/null
+++ b/test/Transforms/Util/MemorySSA/volatile-clobber.ll
@@ -0,0 +1,22 @@
+; RUN: opt -basicaa -print-memoryssa -verify-memoryssa -analyze < %s 2>&1 | FileCheck %s
+; RUN: opt -aa-pipeline=basic-aa -passes='print<memoryssa>,verify<memoryssa>' -disable-output < %s 2>&1 | FileCheck %s
+;
+; Ensures that volatile stores/loads count as MemoryDefs
+
+define i32 @foo() {
+ %1 = alloca i32, align 4
+; CHECK: 1 = MemoryDef(liveOnEntry)
+; CHECK-NEXT: store volatile i32 4
+ store volatile i32 4, i32* %1, align 4
+; CHECK: 2 = MemoryDef(1)
+; CHECK-NEXT: store volatile i32 8
+ store volatile i32 8, i32* %1, align 4
+; CHECK: 3 = MemoryDef(2)
+; CHECK-NEXT: %2 = load volatile i32
+ %2 = load volatile i32, i32* %1, align 4
+; CHECK: 4 = MemoryDef(3)
+; CHECK-NEXT: %3 = load volatile i32
+ %3 = load volatile i32, i32* %1, align 4
+ %4 = add i32 %3, %2
+ ret i32 %4
+}
diff --git a/test/Transforms/Util/simplify-dbg-declare-load.ll b/test/Transforms/Util/simplify-dbg-declare-load.ll
index 0357a5e6facb..21d305450860 100644
--- a/test/Transforms/Util/simplify-dbg-declare-load.ll
+++ b/test/Transforms/Util/simplify-dbg-declare-load.ll
@@ -19,9 +19,9 @@ fail: ; preds = %top
unreachable
idxend: ; preds = %top
-; CHECK-NOT call void @llvm.dbg.value(metadata %foo* %cp, i64 0, metadata !1, metadata !16), !dbg !17
+; CHECK-NOT call void @llvm.dbg.value(metadata %foo* %cp,
%0 = load volatile %foo, %foo* %cp, align 8
-; CHECK: call void @llvm.dbg.value(metadata %foo %0, i64 0, metadata !1, metadata !16), !dbg !17
+; CHECK: call void @llvm.dbg.value(metadata %foo %0,
store volatile %foo %0, %foo* undef, align 8
ret void
}
@@ -30,11 +30,11 @@ attributes #0 = { nounwind readnone }
attributes #1 = { sspreq }
!llvm.module.flags = !{!0}
-!llvm.dbg.cu = !{}
+!llvm.dbg.cu = !{!18}
!0 = !{i32 1, !"Debug Info Version", i32 3}
!1 = !DILocalVariable(name: "cp", scope: !2, file: !3, line: 106, type: !12)
-!2 = distinct !DISubprogram(name: "fastshortest", linkageName: "julia_fastshortest_6256", scope: null, file: !3, type: !4, isLocal: false, isDefinition: true, isOptimized: true, variables: !11)
+!2 = distinct !DISubprogram(name: "fastshortest", linkageName: "julia_fastshortest_6256", scope: null, file: !3, type: !4, isLocal: false, isDefinition: true, isOptimized: true, unit: !18, variables: !11)
!3 = !DIFile(filename: "grisu/fastshortest.jl", directory: ".")
!4 = !DISubroutineType(types: !5)
!5 = !{!6, !7}
@@ -50,3 +50,4 @@ attributes #1 = { sspreq }
!15 = !DIBasicType(name: "Int32", size: 32, align: 32, encoding: DW_ATE_unsigned)
!16 = !DIExpression()
!17 = !DILocation(line: 106, scope: !2)
+!18 = distinct !DICompileUnit(language: DW_LANG_Julia, file: !3)
diff --git a/test/Transforms/Util/split-bit-piece.ll b/test/Transforms/Util/split-bit-piece.ll
index 6945beca84b1..9343214cd991 100644
--- a/test/Transforms/Util/split-bit-piece.ll
+++ b/test/Transforms/Util/split-bit-piece.ll
@@ -29,7 +29,7 @@ attributes #0 = { nounwind readnone }
!llvm.module.flags = !{!7}
!llvm.ident = !{!8}
-!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 3.8.0 (trunk 256979) (llvm/trunk 257107)", isOptimized: false, runtimeVersion: 0, emissionKind: 1, retainedTypes: !2)
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 3.8.0 (trunk 256979) (llvm/trunk 257107)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, retainedTypes: !2)
!1 = !DIFile(filename: "tsan_shadow_test.cc", directory: "/tmp")
!2 = !{!3, !5}
!3 = !DICompositeType(tag: DW_TAG_class_type, name: "FastState", file: !4, line: 91, size: 64, align: 64, identifier: "_ZTSN6__tsan9FastStateE")
@@ -40,6 +40,6 @@ attributes #0 = { nounwind readnone }
!8 = !{!"clang version 3.8.0 (trunk 256979) (llvm/trunk 257107)"}
!9 = !DILocalVariable(name: "v1", scope: !10, file: !4, line: 136, type: !5)
!10 = distinct !DILexicalBlock(scope: !11, file: !4, line: 136, column: 5)
-!11 = distinct !DISubprogram(name: "SetHistorySize", linkageName: "_ZN6__tsan9FastState14SetHistorySizeEi", scope: !"_ZTSN6__tsan9FastStateE", file: !4, line: 135, isLocal: false, isDefinition: true, scopeLine: 135, flags: DIFlagPrototyped, isOptimized: false)
+!11 = distinct !DISubprogram(name: "SetHistorySize", linkageName: "_ZN6__tsan9FastState14SetHistorySizeEi", scope: !3, file: !4, line: 135, isLocal: false, isDefinition: true, scopeLine: 135, flags: DIFlagPrototyped, isOptimized: false, unit: !0)
!12 = !DIExpression()
!13 = !DILocation(line: 136, column: 5, scope: !10)
diff --git a/test/Transforms/Util/store-first-op.ll b/test/Transforms/Util/store-first-op.ll
new file mode 100644
index 000000000000..08efbe47ccfe
--- /dev/null
+++ b/test/Transforms/Util/store-first-op.ll
@@ -0,0 +1,36 @@
+; RUN: opt -instcombine -S %s | FileCheck %s
+
+%foo = type { i8 }
+
+; Function Attrs: nounwind uwtable
+define void @_ZN4llvm13ScaledNumbers10multiply64Emm() {
+entry:
+ %getU = alloca %foo, align 1
+; This is supposed to make sure that the declare conversion, does not accidentally think the store OF
+; %getU is a store TO %getU. There are valid reasons to have an llvm.dbg.value here, but if the pass
+; is changed to emit such, a more specific check should be added to make sure that any llvm.dbg.value
+; is correct.
+; CHECK-NOT: @llvm.dbg.value(metadata %foo* %getU
+ call void @llvm.dbg.declare(metadata %foo* %getU, metadata !3, metadata !6), !dbg !7
+ store %foo* %getU, %foo** undef, align 8, !tbaa !8
+ unreachable
+}
+
+; Function Attrs: nounwind readnone
+declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
+
+attributes #1 = { nounwind readnone }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 3.8.0 (https://github.com/llvm-mirror/clang 89dda3855cda574f355e6defa1d77bdae5053994) (llvm/trunk 257597)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug)
+!1 = !DIFile(filename: "none", directory: ".")
+!2 = !{i32 2, !"Debug Info Version", i32 3}
+!3 = !DILocalVariable(name: "getU", scope: !4, file: !1, line: 25, type: !5)
+!4 = distinct !DISubprogram(name: "multiply64", linkageName: "_ZN4llvm13ScaledNumbers10multiply64Emm", scope: null, file: !1, line: 22, isLocal: false, isDefinition: true, scopeLine: 23, flags: DIFlagPrototyped, isOptimized: true, unit: !0)
+!5 = !DICompositeType(tag: DW_TAG_class_type, scope: !4, file: !1, line: 25, size: 8, align: 8)
+!6 = !DIExpression()
+!7 = !DILocation(line: 25, column: 8, scope: !4)
+!8 = !{!9, !9, i64 0}
+!9 = !{i64 0}