summaryrefslogtreecommitdiff
path: root/test/Transforms/Util
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-04-16 16:01:22 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-04-16 16:01:22 +0000
commit71d5a2540a98c81f5bcaeb48805e0e2881f530ef (patch)
tree5343938942df402b49ec7300a1c25a2d4ccd5821 /test/Transforms/Util
parent31bbf64f3a4974a2d6c8b3b27ad2f519caf74057 (diff)
Diffstat (limited to 'test/Transforms/Util')
-rw-r--r--test/Transforms/Util/MemorySSA/assume.ll19
-rw-r--r--test/Transforms/Util/MemorySSA/atomic-clobber.ll119
-rw-r--r--test/Transforms/Util/MemorySSA/basicaa-memcpy.ll16
-rw-r--r--test/Transforms/Util/MemorySSA/constant-memory.ll41
-rw-r--r--test/Transforms/Util/MemorySSA/cyclicphi.ll123
-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/invariant-groups.ll30
-rw-r--r--test/Transforms/Util/MemorySSA/lifetime-simple.ll30
-rw-r--r--test/Transforms/Util/MemorySSA/load-invariant.ll41
-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.ll181
-rw-r--r--test/Transforms/Util/MemorySSA/pr28880.ll51
-rw-r--r--test/Transforms/Util/MemorySSA/volatile-clobber.ll94
-rw-r--r--test/Transforms/Util/PredicateInfo/condprop.ll471
-rw-r--r--test/Transforms/Util/PredicateInfo/diamond.ll68
-rw-r--r--test/Transforms/Util/PredicateInfo/edge.ll242
-rw-r--r--test/Transforms/Util/PredicateInfo/testandor.ll211
-rw-r--r--test/Transforms/Util/clone-dicompileunit.ll66
-rw-r--r--test/Transforms/Util/simplify-dbg-declare-load.ll2
-rw-r--r--test/Transforms/Util/strip-nonlinetable-debuginfo-loops.ll71
28 files changed, 1130 insertions, 1236 deletions
diff --git a/test/Transforms/Util/MemorySSA/assume.ll b/test/Transforms/Util/MemorySSA/assume.ll
deleted file mode 100644
index d771c78eb1cf..000000000000
--- a/test/Transforms/Util/MemorySSA/assume.ll
+++ /dev/null
@@ -1,19 +0,0 @@
-; 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
deleted file mode 100644
index acd819a89351..000000000000
--- a/test/Transforms/Util/MemorySSA/atomic-clobber.ll
+++ /dev/null
@@ -1,119 +0,0 @@
-; 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
-
-; CHECK-LABEL: define i32 @foo
-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
-}
-
-; CHECK-LABEL: define void @bar
-define void @bar(i32* %a) {
-; CHECK: MemoryUse(liveOnEntry)
-; CHECK-NEXT: load atomic i32, i32* %a unordered, align 4
- load atomic i32, i32* %a unordered, align 4
-; CHECK: 1 = MemoryDef(liveOnEntry)
-; CHECK-NEXT: load atomic i32, i32* %a monotonic, align 4
- load atomic i32, i32* %a monotonic, align 4
-; CHECK: 2 = MemoryDef(1)
-; CHECK-NEXT: load atomic i32, i32* %a acquire, align 4
- load atomic i32, i32* %a acquire, align 4
-; CHECK: 3 = MemoryDef(2)
-; CHECK-NEXT: load atomic i32, i32* %a seq_cst, align 4
- load atomic i32, i32* %a seq_cst, align 4
- ret void
-}
-
-; CHECK-LABEL: define void @baz
-define void @baz(i32* %a) {
-; CHECK: 1 = MemoryDef(liveOnEntry)
-; CHECK-NEXT: %1 = load atomic i32
- %1 = load atomic i32, i32* %a acquire, align 4
-; CHECK: MemoryUse(1)
-; CHECK-NEXT: %2 = load atomic i32, i32* %a unordered, align 4
- %2 = load atomic i32, i32* %a unordered, align 4
-; CHECK: 2 = MemoryDef(1)
-; CHECK-NEXT: %3 = load atomic i32, i32* %a monotonic, align 4
- %3 = load atomic i32, i32* %a monotonic, align 4
- ret void
-}
-
-; CHECK-LABEL: define void @fences
-define void @fences(i32* %a) {
-; CHECK: 1 = MemoryDef(liveOnEntry)
-; CHECK-NEXT: fence acquire
- fence acquire
-; CHECK: MemoryUse(1)
-; CHECK-NEXT: %1 = load i32, i32* %a
- %1 = load i32, i32* %a
-
-; CHECK: 2 = MemoryDef(1)
-; CHECK-NEXT: fence release
- fence release
-; CHECK: MemoryUse(2)
-; CHECK-NEXT: %2 = load i32, i32* %a
- %2 = load i32, i32* %a
-
-; CHECK: 3 = MemoryDef(2)
-; CHECK-NEXT: fence acq_rel
- fence acq_rel
-; CHECK: MemoryUse(3)
-; CHECK-NEXT: %3 = load i32, i32* %a
- %3 = load i32, i32* %a
-
-; CHECK: 4 = MemoryDef(3)
-; CHECK-NEXT: fence seq_cst
- fence seq_cst
-; CHECK: MemoryUse(4)
-; CHECK-NEXT: %4 = load i32, i32* %a
- %4 = load i32, i32* %a
- ret void
-}
-
-; CHECK-LABEL: define void @seq_cst_clobber
-define void @seq_cst_clobber(i32* noalias %a, i32* noalias %b) {
-; CHECK: 1 = MemoryDef(liveOnEntry)
-; CHECK-NEXT: %1 = load atomic i32, i32* %a monotonic, align 4
- load atomic i32, i32* %a monotonic, align 4
-
-; CHECK: 2 = MemoryDef(1)
-; CHECK-NEXT: %2 = load atomic i32, i32* %a seq_cst, align 4
- load atomic i32, i32* %a seq_cst, align 4
-
-; CHECK: 3 = MemoryDef(2)
-; CHECK-NEXT: load atomic i32, i32* %a monotonic, align 4
- load atomic i32, i32* %a monotonic, align 4
-
- ret void
-}
-
-; Ensure that AA hands us MRI_Mod on unreorderable atomic ops.
-;
-; This test is a bit implementation-specific. In particular, it depends on that
-; we pass cmpxchg-load queries to AA, without trying to reason about them on
-; our own.
-;
-; If AA gets more aggressive, we can find another way.
-;
-; CHECK-LABEL: define void @check_aa_is_sane
-define void @check_aa_is_sane(i32* noalias %a, i32* noalias %b) {
-; CHECK: 1 = MemoryDef(liveOnEntry)
-; CHECK-NEXT: cmpxchg i32* %a, i32 0, i32 1 acquire acquire
- cmpxchg i32* %a, i32 0, i32 1 acquire acquire
-; CHECK: MemoryUse(1)
-; CHECK-NEXT: load i32, i32* %b, align 4
- load i32, i32* %b, align 4
-
- ret void
-}
diff --git a/test/Transforms/Util/MemorySSA/basicaa-memcpy.ll b/test/Transforms/Util/MemorySSA/basicaa-memcpy.ll
deleted file mode 100644
index bfd7c899b59a..000000000000
--- a/test/Transforms/Util/MemorySSA/basicaa-memcpy.ll
+++ /dev/null
@@ -1,16 +0,0 @@
-; RUN: opt -disable-output -basicaa -print-memoryssa %s 2>&1 | FileCheck %s
-
-declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i32, i1) nounwind
-
-define void @source_clobber(i8* %a, i8* %b) {
-; CHECK-LABEL: @source_clobber(
-; CHECK-NEXT: ; 1 = MemoryDef(liveOnEntry)
-; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %a, i8* %b, i64 128, i32 1, i1 false)
-; CHECK-NEXT: ; MemoryUse(liveOnEntry)
-; CHECK-NEXT: [[X:%.*]] = load i8, i8* %b
-; CHECK-NEXT: ret void
-;
- call void @llvm.memcpy.p0i8.p0i8.i64(i8* %a, i8* %b, i64 128, i32 1, i1 false)
- %x = load i8, i8* %b
- ret void
-}
diff --git a/test/Transforms/Util/MemorySSA/constant-memory.ll b/test/Transforms/Util/MemorySSA/constant-memory.ll
deleted file mode 100644
index bc970e72fc4d..000000000000
--- a/test/Transforms/Util/MemorySSA/constant-memory.ll
+++ /dev/null
@@ -1,41 +0,0 @@
-; RUN: opt -basicaa -print-memoryssa -verify-memoryssa -analyze < %s 2>&1 | FileCheck %s
-;
-; Things that BasicAA can prove points to constant memory should be
-; liveOnEntry, as well.
-
-declare void @clobberAllTheThings()
-
-@str = private unnamed_addr constant [2 x i8] c"hi"
-
-define i8 @foo() {
-; CHECK: 1 = MemoryDef(liveOnEntry)
-; CHECK-NEXT: call void @clobberAllTheThings()
- call void @clobberAllTheThings()
- %1 = getelementptr [2 x i8], [2 x i8]* @str, i64 0, i64 0
-; CHECK: MemoryUse(liveOnEntry)
-; CHECK-NEXT: %2 = load i8
- %2 = load i8, i8* %1, align 1
- %3 = getelementptr [2 x i8], [2 x i8]* @str, i64 0, i64 1
-; CHECK: MemoryUse(liveOnEntry)
-; CHECK-NEXT: %4 = load i8
- %4 = load i8, i8* %3, align 1
- %5 = add i8 %2, %4
- ret i8 %5
-}
-
-define i8 @select(i1 %b) {
- %1 = alloca i8, align 1
-; CHECK: 1 = MemoryDef(liveOnEntry)
-; CHECK-NEXT: store i8 0
- store i8 0, i8* %1, align 1
-
-; CHECK: 2 = MemoryDef(1)
-; CHECK-NEXT: call void @clobberAllTheThings()
- call void @clobberAllTheThings()
- %2 = getelementptr [2 x i8], [2 x i8]* @str, i64 0, i64 0
- %3 = select i1 %b, i8* %2, i8* %1
-; CHECK: MemoryUse(2)
-; CHECK-NEXT: %4 = load i8
- %4 = load i8, i8* %3, align 1
- ret i8 %4
-}
diff --git a/test/Transforms/Util/MemorySSA/cyclicphi.ll b/test/Transforms/Util/MemorySSA/cyclicphi.ll
deleted file mode 100644
index 6e91db959e4c..000000000000
--- a/test/Transforms/Util/MemorySSA/cyclicphi.ll
+++ /dev/null
@@ -1,123 +0,0 @@
-; 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: 2 = MemoryPhi({%0,liveOnEntry},{bb77,3})
-; 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(2)
-; CHECK-NEXT: store i64 %tmp69, i64* %tmp, align 8
- store i64 %tmp69, i64* %tmp, align 8
- br label %bb77
-
-bb77: ; preds = %bb68, %bb26
-; CHECK: 3 = MemoryPhi({bb26,2},{bb68,1})
-; CHECK: MemoryUse(3)
-; 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: 2 = MemoryPhi({%0,liveOnEntry},{bb77,3})
-; CHECK-NEXT: br i1 undef, label %bb68, label %bb77
- br i1 undef, label %bb68, label %bb77
-
-bb68: ; preds = %bb26
-; CHECK: MemoryUse(2)
-; CHECK-NEXT: %tmp69 = load i64, i64* %g, align 8
- %tmp69 = load i64, i64* %g, align 8
-; CHECK: 1 = MemoryDef(2)
-; 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,2},{bb68,1})
-; CHECK: MemoryUse(liveOnEntry)
-; 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: 3 = MemoryPhi({%0,liveOnEntry},{bb77,2})
-; CHECK: MemoryUse(3)
-; 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: 4 = MemoryPhi({bb26,3},{bb68,1})
-; CHECK: 2 = MemoryDef(4)
-; 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: 2 = MemoryPhi({%0,liveOnEntry},{bb77,3})
-; 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(2)
-; CHECK-NEXT: %tmp69 = load i64, i64* %g, align 8
- %tmp69 = load i64, i64* %g, align 8
-; CHECK: 1 = MemoryDef(2)
-; 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,2},{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
deleted file mode 100644
index 2bbf399daae4..000000000000
--- a/test/Transforms/Util/MemorySSA/forward-unreachable.ll
+++ /dev/null
@@ -1,23 +0,0 @@
-; 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
deleted file mode 100644
index a01893a5b954..000000000000
--- a/test/Transforms/Util/MemorySSA/function-clobber.ll
+++ /dev/null
@@ -1,54 +0,0 @@
-; 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
deleted file mode 100644
index 11383771a413..000000000000
--- a/test/Transforms/Util/MemorySSA/function-mem-attrs.ll
+++ /dev/null
@@ -1,59 +0,0 @@
-; 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/invariant-groups.ll b/test/Transforms/Util/MemorySSA/invariant-groups.ll
deleted file mode 100644
index 57247fe3b2b5..000000000000
--- a/test/Transforms/Util/MemorySSA/invariant-groups.ll
+++ /dev/null
@@ -1,30 +0,0 @@
-; RUN: opt -basicaa -print-memoryssa -verify-memoryssa -analyze < %s 2>&1 | FileCheck %s
-;
-; Currently, MemorySSA doesn't support invariant groups. So, we should ignore
-; invariant.group.barrier intrinsics entirely. We'll need to pay attention to
-; them when/if we decide to support invariant groups.
-
-@g = external global i32
-
-define i32 @foo(i32* %a) {
-; CHECK: 1 = MemoryDef(liveOnEntry)
-; CHECK-NEXT: store i32 0
- store i32 0, i32* %a, align 4, !llvm.invariant.group !0
-
-; CHECK: 2 = MemoryDef(1)
-; CHECK-NEXT: store i32 1
- store i32 1, i32* @g, align 4
-
- %1 = bitcast i32* %a to i8*
- %a8 = call i8* @llvm.invariant.group.barrier(i8* %1)
- %a32 = bitcast i8* %a8 to i32*
-
-; CHECK: MemoryUse(2)
-; CHECK-NEXT: %2 = load i32
- %2 = load i32, i32* %a32, align 4, !llvm.invariant.group !0
- ret i32 %2
-}
-
-declare i8* @llvm.invariant.group.barrier(i8*)
-
-!0 = !{!"group1"}
diff --git a/test/Transforms/Util/MemorySSA/lifetime-simple.ll b/test/Transforms/Util/MemorySSA/lifetime-simple.ll
deleted file mode 100644
index cdb36e31eb96..000000000000
--- a/test/Transforms/Util/MemorySSA/lifetime-simple.ll
+++ /dev/null
@@ -1,30 +0,0 @@
-; 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 checks a number of things:
-; First, the lifetime markers should not clobber any uses of Q or P.
-; Second, the loads of P are MemoryUse(LiveOnEntry) due to the placement of the markers vs the loads.
-
-define i8 @test(i8* %P, i8* %Q) {
-entry:
-; CHECK: 1 = MemoryDef(liveOnEntry)
-; CHECK-NEXT: call void @llvm.lifetime.start(i64 32, i8* %P)
- call void @llvm.lifetime.start(i64 32, i8* %P)
-; CHECK: MemoryUse(liveOnEntry)
-; CHECK-NEXT: %0 = load i8, i8* %P
- %0 = load i8, i8* %P
-; CHECK: 2 = MemoryDef(1)
-; CHECK-NEXT: store i8 1, i8* %P
- store i8 1, i8* %P
-; CHECK: 3 = MemoryDef(2)
-; CHECK-NEXT: call void @llvm.lifetime.end(i64 32, i8* %P)
- call void @llvm.lifetime.end(i64 32, i8* %P)
-; CHECK: MemoryUse(liveOnEntry)
-; CHECK-NEXT: %1 = load i8, i8* %P
- %1 = load i8, i8* %P
-; CHECK: MemoryUse(2)
-; CHECK-NEXT: %2 = load i8, i8* %Q
- %2 = load i8, i8* %Q
- ret i8 %1
-}
-declare void @llvm.lifetime.start(i64 %S, i8* nocapture %P) readonly
-declare void @llvm.lifetime.end(i64 %S, i8* nocapture %P)
diff --git a/test/Transforms/Util/MemorySSA/load-invariant.ll b/test/Transforms/Util/MemorySSA/load-invariant.ll
deleted file mode 100644
index 3c55db11597b..000000000000
--- a/test/Transforms/Util/MemorySSA/load-invariant.ll
+++ /dev/null
@@ -1,41 +0,0 @@
-; 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()
-
-; CHECK-LABEL: define i32 @foo
-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
-}
-
-; CHECK-LABEL: define i32 @bar
-define i32 @bar(i32* %a) {
-; CHECK: 1 = MemoryDef(liveOnEntry)
-; CHECK-NEXT: call void @clobberAllTheThings()
- call void @clobberAllTheThings()
-
-; CHECK: 2 = MemoryDef(1)
-; CHECK-NEXT: %1 = load atomic i32
- %1 = load atomic i32, i32* %a acquire, align 4, !invariant.load !0
-
-; CHECK: MemoryUse(2)
-; CHECK-NEXT: %2 = load i32
- %2 = load i32, i32* %a, align 4
- ret i32 %2
-}
-
-!0 = !{}
diff --git a/test/Transforms/Util/MemorySSA/many-dom-backedge.ll b/test/Transforms/Util/MemorySSA/many-dom-backedge.ll
deleted file mode 100644
index c2216a47bb20..000000000000
--- a/test/Transforms/Util/MemorySSA/many-dom-backedge.ll
+++ /dev/null
@@ -1,77 +0,0 @@
-; 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: 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: 9 = MemoryPhi({loopbegin,8},{sw.almostexit,6})
-; CHECK: 4 = MemoryDef(9)
-; 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: 10 = MemoryPhi({sw.default,5},{sw.bb3,4},{sw.bb,1},{sw.bb1,2},{sw.bb2,3})
-; CHECK-NEXT: MemoryUse(10)
-; CHECK-NEXT: %0 =
- %0 = load i32, i32* %m, align 4
-; CHECK: 6 = MemoryDef(10)
-; 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
deleted file mode 100644
index 1f57cbf1c4df..000000000000
--- a/test/Transforms/Util/MemorySSA/many-doms.ll
+++ /dev/null
@@ -1,67 +0,0 @@
-; 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: 7 = 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(7)
-; CHECK-NEXT: store i32 1
- store i32 1, i32* %m, align 4
- br label %sw.epilog
-
-sw.bb1:
-; CHECK: 2 = MemoryDef(7)
-; CHECK-NEXT: store i32 2
- store i32 2, i32* %m, align 4
- br label %sw.epilog
-
-sw.bb2:
-; CHECK: 3 = MemoryDef(7)
-; CHECK-NEXT: store i32 3
- store i32 3, i32* %m, align 4
- br label %sw.epilog
-
-sw.bb3:
-; CHECK: 4 = MemoryDef(7)
-; CHECK-NEXT: store i32 4
- store i32 4, i32* %m, align 4
- br label %sw.epilog
-
-sw.default:
-; CHECK: 5 = MemoryDef(7)
-; 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.bb,1},{sw.bb1,2},{sw.bb2,3},{sw.bb3,4})
-; 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 %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
deleted file mode 100644
index 5d47728d6f5a..000000000000
--- a/test/Transforms/Util/MemorySSA/multi-edges.ll
+++ /dev/null
@@ -1,32 +0,0 @@
-; 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: 3 = MemoryPhi({entry,1},{Loop.End,4})
-; CHECK-NEXT: 2 = MemoryDef(3)
-; 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: 4 = MemoryPhi({entry,1},{Loop.Body,2},{Loop.Body,2})
-; CHECK-NEXT: MemoryUse(4)
-; 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
deleted file mode 100644
index 005a37c9add2..000000000000
--- a/test/Transforms/Util/MemorySSA/multiple-backedges-hal.ll
+++ /dev/null
@@ -1,73 +0,0 @@
-; 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: 4 = MemoryPhi({Entry,1},{InnerLoop.Tail,3})
-; CHECK-NEXT: %Val.Outer =
- %Val.Outer = call i8 @getValue()
-; CHECK: 2 = MemoryDef(4)
-; CHECK-NEXT: store i8 %Val.Outer
- store i8 %Val.Outer, i8* %Arg
- call void @doThingWithoutReading()
- br label %InnerLoop
-
-InnerLoop:
-; CHECK: 5 = MemoryPhi({OuterLoop,2},{InnerLoop,3})
-; CHECK-NEXT: ; MemoryUse(5)
-; CHECK-NEXT: %StartingAccess = load
- %StartingAccess = load i8, i8* %Arg, align 4
- %Val.Inner = call i8 @getValue()
-; CHECK: 3 = MemoryDef(5)
-; 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
deleted file mode 100644
index 9a3e87e4ab6d..000000000000
--- a/test/Transforms/Util/MemorySSA/multiple-locations.ll
+++ /dev/null
@@ -1,25 +0,0 @@
-; 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
deleted file mode 100644
index d1dcb15893ad..000000000000
--- a/test/Transforms/Util/MemorySSA/no-disconnected.ll
+++ /dev/null
@@ -1,43 +0,0 @@
-; 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
deleted file mode 100644
index 8a8f2dd50959..000000000000
--- a/test/Transforms/Util/MemorySSA/optimize-use.ll
+++ /dev/null
@@ -1,37 +0,0 @@
-; 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
deleted file mode 100644
index c91faf2ac20b..000000000000
--- a/test/Transforms/Util/MemorySSA/phi-translation.ll
+++ /dev/null
@@ -1,181 +0,0 @@
-; 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: 5 = MemoryPhi({entry,1},{if.then,2})
-; CHECK: 3 = MemoryDef(5)
-; CHECK-NEXT: store i8 3, i8* %local2
- store i8 3, i8* %local2
- br i1 %val3, label %phi.2, label %phi.1
-
-phi.2:
-; CHECK: 6 = MemoryPhi({if.then,2},{phi.3,3})
-; CHECK: 4 = MemoryDef(6)
-; 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: 5 = MemoryPhi({%0,1},{loop.3,4})
-; CHECK: 2 = MemoryDef(5)
-; 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: 7 = MemoryPhi({loop.1,2},{loop.2,3})
-; CHECK: 4 = MemoryDef(7)
-; CHECK-NEXT: store i8 2, i8* %p2
- store i8 2, i8* %p2
-; CHECK: MemoryUse(1)
-; 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: 4 = 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(4)
-; 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: 5 = MemoryPhi({while.cond,4},{if.then,1},{if.then2,2})
-; CHECK: MemoryUse(5)
-; CHECK-NEXT: load i8, i8* %p1
- load i8, i8* %p1
-; CHECK: 3 = MemoryDef(5)
-; CHECK-NEXT: store i8 2, i8* %p2
- store i8 2, i8* %p2
-; CHECK: MemoryUse(5)
-; CHECK-NEXT: load i8, i8* %p1
- load i8, i8* %p1
- br label %while.cond
-}
-
diff --git a/test/Transforms/Util/MemorySSA/pr28880.ll b/test/Transforms/Util/MemorySSA/pr28880.ll
deleted file mode 100644
index ae64c0c5d73e..000000000000
--- a/test/Transforms/Util/MemorySSA/pr28880.ll
+++ /dev/null
@@ -1,51 +0,0 @@
-; 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 testcase is reduced from SingleSource/Benchmarks/Misc/fbench.c
-; It is testing to make sure that the MemorySSA use optimizer
-; comes up with right answers when dealing with multiple MemoryLocations
-; over different blocks. See PR28880 for more details.
-@global = external hidden unnamed_addr global double, align 8
-@global.1 = external hidden unnamed_addr global double, align 8
-
-; Function Attrs: nounwind ssp uwtable
-define hidden fastcc void @hoge() unnamed_addr #0 {
-bb:
- br i1 undef, label %bb1, label %bb2
-
-bb1: ; preds = %bb
-; These accesses should not conflict.
-; CHECK: 1 = MemoryDef(liveOnEntry)
-; 1 = MemoryDef(liveOnEntry)
-; CHECK-NEXT: store double undef, double* @global, align 8
- store double undef, double* @global, align 8
-; CHECK: MemoryUse(liveOnEntry)
-; MemoryUse(liveOnEntry)
-; CHECK-NEXT: %tmp = load double, double* @global.1, align 8
- %tmp = load double, double* @global.1, align 8
- unreachable
-
-bb2: ; preds = %bb
- br label %bb3
-
-bb3: ; preds = %bb2
- br i1 undef, label %bb4, label %bb6
-
-bb4: ; preds = %bb3
-; These accesses should conflict.
-; CHECK: 2 = MemoryDef(liveOnEntry)
-; 2 = MemoryDef(liveOnEntry)
-; CHECK-NEXT: store double 0.000000e+00, double* @global.1, align 8
- store double 0.000000e+00, double* @global.1, align 8
-; CHECK: MemoryUse(2)
-; MemoryUse(2)
-; CHECK-NEXT: %tmp5 = load double, double* @global.1, align 8
- %tmp5 = load double, double* @global.1, align 8
- unreachable
-
-bb6: ; preds = %bb3
- unreachable
-}
-
-attributes #0 = { nounwind ssp uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="core2" "target-features"="+cx16,+fxsr,+mmx,+sse,+sse2,+sse3,+ssse3" "unsafe-fp-math"="false" "use-soft-float"="false" }
-
diff --git a/test/Transforms/Util/MemorySSA/volatile-clobber.ll b/test/Transforms/Util/MemorySSA/volatile-clobber.ll
deleted file mode 100644
index d6f960f3e382..000000000000
--- a/test/Transforms/Util/MemorySSA/volatile-clobber.ll
+++ /dev/null
@@ -1,94 +0,0 @@
-; 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
-
-; CHECK-LABEL: define i32 @foo
-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
-}
-
-; Ensuring that we don't automatically hoist nonvolatile loads around volatile
-; loads
-; CHECK-LABEL define void @volatile_only
-define void @volatile_only(i32* %arg1, i32* %arg2) {
- ; Trivially NoAlias/MustAlias
- %a = alloca i32
- %b = alloca i32
-
-; CHECK: 1 = MemoryDef(liveOnEntry)
-; CHECK-NEXT: load volatile i32, i32* %a
- load volatile i32, i32* %a
-; CHECK: MemoryUse(liveOnEntry)
-; CHECK-NEXT: load i32, i32* %b
- load i32, i32* %b
-; CHECK: MemoryUse(1)
-; CHECK-NEXT: load i32, i32* %a
- load i32, i32* %a
-
- ; MayAlias
-; CHECK: 2 = MemoryDef(1)
-; CHECK-NEXT: load volatile i32, i32* %arg1
- load volatile i32, i32* %arg1
-; CHECK: MemoryUse(2)
-; CHECK-NEXT: load i32, i32* %arg2
- load i32, i32* %arg2
-
- ret void
-}
-
-; Ensuring that volatile atomic operations work properly.
-; CHECK-LABEL define void @volatile_atomics
-define void @volatile_atomics(i32* %arg1, i32* %arg2) {
- %a = alloca i32
- %b = alloca i32
-
- ; Trivially NoAlias/MustAlias
-
-; CHECK: 1 = MemoryDef(liveOnEntry)
-; CHECK-NEXT: load atomic volatile i32, i32* %a acquire, align 4
- load atomic volatile i32, i32* %a acquire, align 4
-; CHECK: MemoryUse(1)
-; CHECK-NEXT: load i32, i32* %b
- load i32, i32* %b
-
-; CHECK: 2 = MemoryDef(1)
-; CHECK-NEXT: load atomic volatile i32, i32* %a monotonic, align 4
- load atomic volatile i32, i32* %a monotonic, align 4
-; CHECK: MemoryUse(1)
-; CHECK-NEXT: load i32, i32* %b
- load i32, i32* %b
-; CHECK: MemoryUse(1)
-; CHECK-NEXT: load atomic i32, i32* %b unordered, align 4
- load atomic i32, i32* %b unordered, align 4
-; CHECK: MemoryUse(2)
-; CHECK-NEXT: load atomic i32, i32* %a unordered, align 4
- load atomic i32, i32* %a unordered, align 4
-; CHECK: MemoryUse(2)
-; CHECK-NEXT: load i32, i32* %a
- load i32, i32* %a
-
- ; MayAlias
-; CHECK: 3 = MemoryDef(2)
-; CHECK-NEXT: load atomic volatile i32, i32* %arg1 monotonic, align 4
- load atomic volatile i32, i32* %arg1 monotonic, align 4
-; CHECK: MemoryUse(3)
-; CHECK-NEXT: load i32, i32* %arg2
- load i32, i32* %arg2
-
- ret void
-}
diff --git a/test/Transforms/Util/PredicateInfo/condprop.ll b/test/Transforms/Util/PredicateInfo/condprop.ll
new file mode 100644
index 000000000000..79c76baa6f61
--- /dev/null
+++ b/test/Transforms/Util/PredicateInfo/condprop.ll
@@ -0,0 +1,471 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -print-predicateinfo -analyze < %s 2>&1 | FileCheck %s
+
+@a = external global i32 ; <i32*> [#uses=7]
+
+define i32 @test1() nounwind {
+; CHECK-LABEL: @test1(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4
+; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 4
+; CHECK-NEXT: br i1 [[TMP1]], label [[BB:%.*]], label [[BB1:%.*]]
+; CHECK: bb:
+; CHECK-NEXT: br label [[BB8:%.*]]
+; CHECK: bb1:
+; CHECK-NEXT: [[TMP2:%.*]] = load i32, i32* @a, align 4
+; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 5
+; CHECK-NEXT: br i1 [[TMP3]], label [[BB2:%.*]], label [[BB3:%.*]]
+; CHECK: bb2:
+; CHECK-NEXT: br label [[BB8]]
+; CHECK: bb3:
+; CHECK-NEXT: [[TMP4:%.*]] = load i32, i32* @a, align 4
+; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[TMP4]], 4
+; CHECK-NEXT: br i1 [[TMP5]], label [[BB4:%.*]], label [[BB5:%.*]]
+; CHECK: bb4:
+; CHECK-NEXT: [[TMP6:%.*]] = load i32, i32* @a, align 4
+; CHECK-NEXT: [[TMP7:%.*]] = add i32 [[TMP6]], 5
+; CHECK-NEXT: br label [[BB8]]
+; CHECK: bb5:
+; CHECK-NEXT: [[TMP8:%.*]] = load i32, i32* @a, align 4
+; CHECK-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], 5
+; CHECK-NEXT: br i1 [[TMP9]], label [[BB6:%.*]], label [[BB7:%.*]]
+; CHECK: bb6:
+; CHECK-NEXT: [[TMP10:%.*]] = load i32, i32* @a, align 4
+; CHECK-NEXT: [[TMP11:%.*]] = add i32 [[TMP10]], 4
+; CHECK-NEXT: br label [[BB8]]
+; CHECK: bb7:
+; CHECK-NEXT: [[TMP12:%.*]] = load i32, i32* @a, align 4
+; CHECK-NEXT: br label [[BB8]]
+; CHECK: bb8:
+; CHECK-NEXT: [[DOT0:%.*]] = phi i32 [ [[TMP12]], [[BB7]] ], [ [[TMP11]], [[BB6]] ], [ [[TMP7]], [[BB4]] ], [ 4, [[BB2]] ], [ 5, [[BB]] ]
+; CHECK-NEXT: br label [[RETURN:%.*]]
+; CHECK: return:
+; CHECK-NEXT: ret i32 [[DOT0]]
+;
+entry:
+ %0 = load i32, i32* @a, align 4
+ %1 = icmp eq i32 %0, 4
+ br i1 %1, label %bb, label %bb1
+
+bb: ; preds = %entry
+ br label %bb8
+
+bb1: ; preds = %entry
+ %2 = load i32, i32* @a, align 4
+ %3 = icmp eq i32 %2, 5
+ br i1 %3, label %bb2, label %bb3
+
+bb2: ; preds = %bb1
+ br label %bb8
+
+bb3: ; preds = %bb1
+ %4 = load i32, i32* @a, align 4
+ %5 = icmp eq i32 %4, 4
+ br i1 %5, label %bb4, label %bb5
+
+bb4: ; preds = %bb3
+ %6 = load i32, i32* @a, align 4
+ %7 = add i32 %6, 5
+ br label %bb8
+
+bb5: ; preds = %bb3
+ %8 = load i32, i32* @a, align 4
+ %9 = icmp eq i32 %8, 5
+ br i1 %9, label %bb6, label %bb7
+
+bb6: ; preds = %bb5
+ %10 = load i32, i32* @a, align 4
+ %11 = add i32 %10, 4
+ br label %bb8
+
+bb7: ; preds = %bb5
+ %12 = load i32, i32* @a, align 4
+ br label %bb8
+
+bb8: ; preds = %bb7, %bb6, %bb4, %bb2, %bb
+ %.0 = phi i32 [ %12, %bb7 ], [ %11, %bb6 ], [ %7, %bb4 ], [ 4, %bb2 ], [ 5, %bb ]
+ br label %return
+
+return: ; preds = %bb8
+ ret i32 %.0
+}
+
+declare void @foo(i1)
+declare void @bar(i32)
+
+define void @test3(i32 %x, i32 %y) {
+; CHECK-LABEL: @test3(
+; CHECK-NEXT: [[XZ:%.*]] = icmp eq i32 [[X:%.*]], 0
+; CHECK-NEXT: [[YZ:%.*]] = icmp eq i32 [[Y:%.*]], 0
+; CHECK-NEXT: [[Z:%.*]] = and i1 [[XZ]], [[YZ]]
+; CHECK: [[XZ_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[XZ]])
+; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
+; CHECK: [[YZ_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[YZ]])
+; CHECK: [[Y_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[Y]])
+; CHECK: [[Z_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[Z]])
+; CHECK-NEXT: br i1 [[Z]], label [[BOTH_ZERO:%.*]], label [[NOPE:%.*]]
+; CHECK: both_zero:
+; CHECK-NEXT: call void @foo(i1 [[XZ_0]])
+; CHECK-NEXT: call void @foo(i1 [[YZ_0]])
+; CHECK-NEXT: call void @bar(i32 [[X_0]])
+; CHECK-NEXT: call void @bar(i32 [[Y_0]])
+; CHECK-NEXT: ret void
+; CHECK: nope:
+; CHECK-NEXT: call void @foo(i1 [[Z_0]])
+; CHECK-NEXT: ret void
+;
+ %xz = icmp eq i32 %x, 0
+ %yz = icmp eq i32 %y, 0
+ %z = and i1 %xz, %yz
+ br i1 %z, label %both_zero, label %nope
+both_zero:
+ call void @foo(i1 %xz)
+ call void @foo(i1 %yz)
+ call void @bar(i32 %x)
+ call void @bar(i32 %y)
+ ret void
+nope:
+ call void @foo(i1 %z)
+ ret void
+}
+
+define void @test4(i1 %b, i32 %x) {
+; CHECK-LABEL: @test4(
+; CHECK-NEXT: br i1 [[B:%.*]], label [[SW:%.*]], label [[CASE3:%.*]]
+; CHECK: sw:
+; CHECK: i32 0, label [[CASE0:%.*]]
+; CHECK-NEXT: i32 1, label [[CASE1:%.*]]
+; CHECK-NEXT: i32 2, label [[CASE0]]
+; CHECK-NEXT: i32 3, label [[CASE3]]
+; CHECK-NEXT: i32 4, label [[DEFAULT:%.*]]
+; CHECK-NEXT: ] Edge: [label [[SW]],label %case1] }
+; CHECK-NEXT: [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X:%.*]])
+; CHECK-NEXT: switch i32 [[X]], label [[DEFAULT]] [
+; CHECK-NEXT: i32 0, label [[CASE0]]
+; CHECK-NEXT: i32 1, label [[CASE1]]
+; CHECK-NEXT: i32 2, label [[CASE0]]
+; CHECK-NEXT: i32 3, label [[CASE3]]
+; CHECK-NEXT: i32 4, label [[DEFAULT]]
+; CHECK-NEXT: ]
+; CHECK: default:
+; CHECK-NEXT: call void @bar(i32 [[X]])
+; CHECK-NEXT: ret void
+; CHECK: case0:
+; CHECK-NEXT: call void @bar(i32 [[X]])
+; CHECK-NEXT: ret void
+; CHECK: case1:
+; CHECK-NEXT: call void @bar(i32 [[X_0]])
+; CHECK-NEXT: ret void
+; CHECK: case3:
+; CHECK-NEXT: call void @bar(i32 [[X]])
+; CHECK-NEXT: ret void
+;
+ br i1 %b, label %sw, label %case3
+sw:
+ switch i32 %x, label %default [
+ i32 0, label %case0
+ i32 1, label %case1
+ i32 2, label %case0
+ i32 3, label %case3
+ i32 4, label %default
+ ]
+default:
+ call void @bar(i32 %x)
+ ret void
+case0:
+ call void @bar(i32 %x)
+ ret void
+case1:
+ call void @bar(i32 %x)
+ ret void
+case3:
+ call void @bar(i32 %x)
+ ret void
+}
+
+define i1 @test5(i32 %x, i32 %y) {
+; CHECK-LABEL: @test5(
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]]
+; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
+; CHECK: [[X_1:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
+; CHECK: [[Y_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[Y]])
+; CHECK: [[Y_1:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[Y]])
+; CHECK-NEXT: br i1 [[CMP]], label [[SAME:%.*]], label [[DIFFERENT:%.*]]
+; CHECK: same:
+; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i32 [[X_0]], [[Y_0]]
+; CHECK-NEXT: ret i1 [[CMP2]]
+; CHECK: different:
+; CHECK-NEXT: [[CMP3:%.*]] = icmp eq i32 [[X_1]], [[Y_1]]
+; CHECK-NEXT: ret i1 [[CMP3]]
+;
+ %cmp = icmp eq i32 %x, %y
+ br i1 %cmp, label %same, label %different
+
+same:
+ %cmp2 = icmp ne i32 %x, %y
+ ret i1 %cmp2
+
+different:
+ %cmp3 = icmp eq i32 %x, %y
+ ret i1 %cmp3
+}
+
+define i1 @test6(i32 %x, i32 %y) {
+; CHECK-LABEL: @test6(
+; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X]], [[Y]]
+; CHECK-NEXT: [[CMP3:%.*]] = icmp eq i32 [[X]], [[Y]]
+; CHECK-NEXT: br i1 [[CMP]], label [[SAME:%.*]], label [[DIFFERENT:%.*]]
+; CHECK: same:
+; CHECK-NEXT: ret i1 [[CMP2]]
+; CHECK: different:
+; CHECK-NEXT: ret i1 [[CMP3]]
+;
+ %cmp2 = icmp ne i32 %x, %y
+ %cmp = icmp eq i32 %x, %y
+ %cmp3 = icmp eq i32 %x, %y
+ br i1 %cmp, label %same, label %different
+
+same:
+ ret i1 %cmp2
+
+different:
+ ret i1 %cmp3
+}
+
+define i1 @test6_fp(float %x, float %y) {
+; CHECK-LABEL: @test6_fp(
+; CHECK-NEXT: [[CMP2:%.*]] = fcmp une float [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float [[X]], [[Y]]
+; CHECK-NEXT: [[CMP3:%.*]] = fcmp oeq float [[X]], [[Y]]
+; CHECK-NEXT: br i1 [[CMP]], label [[SAME:%.*]], label [[DIFFERENT:%.*]]
+; CHECK: same:
+; CHECK-NEXT: ret i1 [[CMP2]]
+; CHECK: different:
+; CHECK-NEXT: ret i1 [[CMP3]]
+;
+ %cmp2 = fcmp une float %x, %y
+ %cmp = fcmp oeq float %x, %y
+ %cmp3 = fcmp oeq float %x, %y
+ br i1 %cmp, label %same, label %different
+
+same:
+ ret i1 %cmp2
+
+different:
+ ret i1 %cmp3
+}
+
+define i1 @test7(i32 %x, i32 %y) {
+; CHECK-LABEL: @test7(
+; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[X:%.*]], [[Y:%.*]]
+; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
+; CHECK: [[X_1:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
+; CHECK: [[Y_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[Y]])
+; CHECK: [[Y_1:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[Y]])
+; CHECK-NEXT: br i1 [[CMP]], label [[SAME:%.*]], label [[DIFFERENT:%.*]]
+; CHECK: same:
+; CHECK-NEXT: [[CMP2:%.*]] = icmp sle i32 [[X_0]], [[Y_0]]
+; CHECK-NEXT: ret i1 [[CMP2]]
+; CHECK: different:
+; CHECK-NEXT: [[CMP3:%.*]] = icmp sgt i32 [[X_1]], [[Y_1]]
+; CHECK-NEXT: ret i1 [[CMP3]]
+;
+ %cmp = icmp sgt i32 %x, %y
+ br i1 %cmp, label %same, label %different
+
+same:
+ %cmp2 = icmp sle i32 %x, %y
+ ret i1 %cmp2
+
+different:
+ %cmp3 = icmp sgt i32 %x, %y
+ ret i1 %cmp3
+}
+
+define i1 @test7_fp(float %x, float %y) {
+; CHECK-LABEL: @test7_fp(
+; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float [[X:%.*]], [[Y:%.*]]
+; CHECK: [[X_0:%.*]] = call float @llvm.ssa.copy.f32(float [[X]])
+; CHECK: [[X_1:%.*]] = call float @llvm.ssa.copy.f32(float [[X]])
+; CHECK: [[Y_0:%.*]] = call float @llvm.ssa.copy.f32(float [[Y]])
+; CHECK: [[Y_1:%.*]] = call float @llvm.ssa.copy.f32(float [[Y]])
+; CHECK-NEXT: br i1 [[CMP]], label [[SAME:%.*]], label [[DIFFERENT:%.*]]
+; CHECK: same:
+; CHECK-NEXT: [[CMP2:%.*]] = fcmp ule float [[X_0]], [[Y_0]]
+; CHECK-NEXT: ret i1 [[CMP2]]
+; CHECK: different:
+; CHECK-NEXT: [[CMP3:%.*]] = fcmp ogt float [[X_1]], [[Y_1]]
+; CHECK-NEXT: ret i1 [[CMP3]]
+;
+ %cmp = fcmp ogt float %x, %y
+ br i1 %cmp, label %same, label %different
+
+same:
+ %cmp2 = fcmp ule float %x, %y
+ ret i1 %cmp2
+
+different:
+ %cmp3 = fcmp ogt float %x, %y
+ ret i1 %cmp3
+}
+
+define i1 @test8(i32 %x, i32 %y) {
+; CHECK-LABEL: @test8(
+; CHECK-NEXT: [[CMP2:%.*]] = icmp sle i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[X]], [[Y]]
+; CHECK-NEXT: [[CMP3:%.*]] = icmp sgt i32 [[X]], [[Y]]
+; CHECK-NEXT: br i1 [[CMP]], label [[SAME:%.*]], label [[DIFFERENT:%.*]]
+; CHECK: same:
+; CHECK-NEXT: ret i1 [[CMP2]]
+; CHECK: different:
+; CHECK-NEXT: ret i1 [[CMP3]]
+;
+ %cmp2 = icmp sle i32 %x, %y
+ %cmp = icmp sgt i32 %x, %y
+ %cmp3 = icmp sgt i32 %x, %y
+ br i1 %cmp, label %same, label %different
+
+same:
+ ret i1 %cmp2
+
+different:
+ ret i1 %cmp3
+}
+
+define i1 @test8_fp(float %x, float %y) {
+; CHECK-LABEL: @test8_fp(
+; CHECK-NEXT: [[CMP2:%.*]] = fcmp ule float [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float [[X]], [[Y]]
+; CHECK-NEXT: [[CMP3:%.*]] = fcmp ogt float [[X]], [[Y]]
+; CHECK-NEXT: br i1 [[CMP]], label [[SAME:%.*]], label [[DIFFERENT:%.*]]
+; CHECK: same:
+; CHECK-NEXT: ret i1 [[CMP2]]
+; CHECK: different:
+; CHECK-NEXT: ret i1 [[CMP3]]
+;
+ %cmp2 = fcmp ule float %x, %y
+ %cmp = fcmp ogt float %x, %y
+ %cmp3 = fcmp ogt float %x, %y
+ br i1 %cmp, label %same, label %different
+
+same:
+ ret i1 %cmp2
+
+different:
+ ret i1 %cmp3
+}
+
+define i32 @test9(i32 %i, i32 %j) {
+; CHECK-LABEL: @test9(
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I:%.*]], [[J:%.*]]
+; CHECK: [[I_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[I]])
+; CHECK: [[J_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[J]])
+; CHECK-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[RET:%.*]]
+; CHECK: cond_true:
+; CHECK-NEXT: [[DIFF:%.*]] = sub i32 [[I_0]], [[J_0]]
+; CHECK-NEXT: ret i32 [[DIFF]]
+; CHECK: ret:
+; CHECK-NEXT: ret i32 5
+;
+ %cmp = icmp eq i32 %i, %j
+ br i1 %cmp, label %cond_true, label %ret
+
+cond_true:
+ %diff = sub i32 %i, %j
+ ret i32 %diff
+
+ret:
+ ret i32 5
+}
+
+define i32 @test10(i32 %j, i32 %i) {
+; CHECK-LABEL: @test10(
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I:%.*]], [[J:%.*]]
+; CHECK: [[I_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[I]])
+; CHECK: [[J_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[J]])
+; CHECK-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[RET:%.*]]
+; CHECK: cond_true:
+; CHECK-NEXT: [[DIFF:%.*]] = sub i32 [[I_0]], [[J_0]]
+; CHECK-NEXT: ret i32 [[DIFF]]
+; CHECK: ret:
+; CHECK-NEXT: ret i32 5
+;
+ %cmp = icmp eq i32 %i, %j
+ br i1 %cmp, label %cond_true, label %ret
+
+cond_true:
+ %diff = sub i32 %i, %j
+ ret i32 %diff
+
+ret:
+ ret i32 5
+}
+
+declare i32 @yogibar()
+
+define i32 @test11(i32 %x) {
+; CHECK-LABEL: @test11(
+; CHECK-NEXT: [[V0:%.*]] = call i32 @yogibar()
+; CHECK-NEXT: [[V1:%.*]] = call i32 @yogibar()
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[V0]], [[V1]]
+; CHECK: [[V0_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[V0]])
+; CHECK: [[V1_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[V1]])
+; CHECK-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[NEXT:%.*]]
+; CHECK: cond_true:
+; CHECK-NEXT: ret i32 [[V1_0]]
+; CHECK: next:
+; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 [[X:%.*]], [[V0_0]]
+; CHECK: [[V0_0_1:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[V0_0]])
+; CHECK-NEXT: br i1 [[CMP2]], label [[COND_TRUE2:%.*]], label [[NEXT2:%.*]]
+; CHECK: cond_true2:
+; CHECK-NEXT: ret i32 [[V0_0_1]]
+; CHECK: next2:
+; CHECK-NEXT: ret i32 0
+;
+ %v0 = call i32 @yogibar()
+ %v1 = call i32 @yogibar()
+ %cmp = icmp eq i32 %v0, %v1
+ br i1 %cmp, label %cond_true, label %next
+
+cond_true:
+ ret i32 %v1
+
+next:
+ %cmp2 = icmp eq i32 %x, %v0
+ br i1 %cmp2, label %cond_true2, label %next2
+
+cond_true2:
+ ret i32 %v0
+
+next2:
+ ret i32 0
+}
+
+define i32 @test12(i32 %x) {
+; CHECK-LABEL: @test12(
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], 0
+; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
+; CHECK: [[X_1:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
+; CHECK-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
+; CHECK: cond_true:
+; CHECK-NEXT: br label [[RET:%.*]]
+; CHECK: cond_false:
+; CHECK-NEXT: br label [[RET]]
+; CHECK: ret:
+; CHECK-NEXT: [[RES:%.*]] = phi i32 [ [[X_0]], [[COND_TRUE]] ], [ [[X_1]], [[COND_FALSE]] ]
+; CHECK-NEXT: ret i32 [[RES]]
+;
+ %cmp = icmp eq i32 %x, 0
+ br i1 %cmp, label %cond_true, label %cond_false
+
+cond_true:
+ br label %ret
+
+cond_false:
+ br label %ret
+
+ret:
+ %res = phi i32 [ %x, %cond_true ], [ %x, %cond_false ]
+ ret i32 %res
+}
diff --git a/test/Transforms/Util/PredicateInfo/diamond.ll b/test/Transforms/Util/PredicateInfo/diamond.ll
new file mode 100644
index 000000000000..e3f56d88caf0
--- /dev/null
+++ b/test/Transforms/Util/PredicateInfo/diamond.ll
@@ -0,0 +1,68 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -print-predicateinfo < %s 2>&1 | FileCheck %s
+define i1 @f(i32 %x, i1 %y) {
+; CHECK-LABEL: @f(
+; CHECK-NEXT: br i1 [[Y:%.*]], label [[BB0:%.*]], label [[BB1:%.*]]
+; CHECK: bb0:
+; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[X:%.*]], 0
+; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
+; CHECK-NEXT: br i1 [[CMP]], label [[BB2:%.*]], label [[BB3:%.*]]
+; CHECK: bb1:
+; CHECK-NEXT: [[X2:%.*]] = add nuw nsw i32 [[X]], 1
+; CHECK-NEXT: [[CMP2:%.*]] = icmp sge i32 [[X2]], 2
+; CHECK: [[X2_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X2]])
+; CHECK-NEXT: br i1 [[CMP2]], label [[BB2]], label [[BB3]]
+; CHECK: bb2:
+; CHECK-NEXT: [[X3:%.*]] = phi i32 [ [[X_0]], [[BB0]] ], [ [[X2_0]], [[BB1]] ]
+; CHECK-NEXT: br label [[BB3]]
+; CHECK: bb3:
+; CHECK-NEXT: ret i1 false
+;
+ br i1 %y, label %bb0, label %bb1
+ bb0:
+ %cmp = icmp sge i32 %x, 0 ; x > 0
+ br i1 %cmp, label %bb2, label %bb3
+ bb1:
+ %x2 = add nsw nuw i32 %x, 1
+ %cmp2 = icmp sge i32 %x2, 2 ; x+1 > 2 / x > 1
+ br i1 %cmp2, label %bb2, label %bb3
+ bb2:
+ %x3 = phi i32 [ %x, %bb0 ], [ %x2, %bb1 ]
+ br label %bb3
+ bb3:
+ ret i1 0
+}
+
+define i1 @g(i32 %x, i1 %y) {
+; CHECK-LABEL: @g(
+; CHECK-NEXT: br i1 [[Y:%.*]], label [[BB0:%.*]], label [[BB1:%.*]]
+; CHECK: bb0:
+; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[X:%.*]], 0
+; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
+; CHECK-NEXT: br i1 [[CMP]], label [[BB3:%.*]], label [[BB2:%.*]]
+; CHECK: bb1:
+; CHECK-NEXT: [[X2:%.*]] = add nuw nsw i32 [[X]], 1
+; CHECK-NEXT: [[CMP2:%.*]] = icmp sge i32 [[X2]], 2
+; CHECK: [[X2_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X2]])
+; CHECK-NEXT: br i1 [[CMP2]], label [[BB3]], label [[BB2]]
+; CHECK: bb2:
+; CHECK-NEXT: [[X3:%.*]] = phi i32 [ [[X_0]], [[BB0]] ], [ [[X2_0]], [[BB1]] ]
+; CHECK-NEXT: br label [[BB3]]
+; CHECK: bb3:
+; CHECK-NEXT: ret i1 false
+;
+ br i1 %y, label %bb0, label %bb1
+ bb0:
+ %cmp = icmp sge i32 %x, 0 ; x > 0
+ br i1 %cmp, label %bb3, label %bb2
+ bb1:
+ %x2 = add nsw nuw i32 %x, 1
+ %cmp2 = icmp sge i32 %x2, 2 ; x+1 > 2 / x > 1
+ br i1 %cmp2, label %bb3, label %bb2
+ bb2:
+ %x3 = phi i32 [ %x, %bb0 ], [ %x2, %bb1 ]
+ br label %bb3
+ bb3:
+ ret i1 0
+}
+
diff --git a/test/Transforms/Util/PredicateInfo/edge.ll b/test/Transforms/Util/PredicateInfo/edge.ll
new file mode 100644
index 000000000000..6c58540e1050
--- /dev/null
+++ b/test/Transforms/Util/PredicateInfo/edge.ll
@@ -0,0 +1,242 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -print-predicateinfo -analyze < %s 2>&1 | FileCheck %s
+
+define i32 @f1(i32 %x) {
+; CHECK-LABEL: @f1(
+; CHECK-NEXT: bb0:
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], 0
+; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
+; CHECK-NEXT: br i1 [[CMP]], label [[BB2:%.*]], label [[BB1:%.*]]
+; CHECK: bb1:
+; CHECK-NEXT: br label [[BB2]]
+; CHECK: bb2:
+; CHECK-NEXT: [[COND:%.*]] = phi i32 [ [[X_0]], [[BB0:%.*]] ], [ 0, [[BB1]] ]
+; CHECK-NEXT: [[FOO:%.*]] = add i32 [[COND]], [[X]]
+; CHECK-NEXT: ret i32 [[FOO]]
+;
+bb0:
+ %cmp = icmp eq i32 %x, 0
+ br i1 %cmp, label %bb2, label %bb1
+bb1:
+ br label %bb2
+bb2:
+ %cond = phi i32 [ %x, %bb0 ], [ 0, %bb1 ]
+ %foo = add i32 %cond, %x
+ ret i32 %foo
+}
+
+define i32 @f2(i32 %x) {
+; CHECK-LABEL: @f2(
+; CHECK-NEXT: bb0:
+; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[X:%.*]], 0
+; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
+; CHECK-NEXT: br i1 [[CMP]], label [[BB1:%.*]], label [[BB2:%.*]]
+; CHECK: bb1:
+; CHECK-NEXT: br label [[BB2]]
+; CHECK: bb2:
+; CHECK-NEXT: [[COND:%.*]] = phi i32 [ [[X_0]], [[BB0:%.*]] ], [ 0, [[BB1]] ]
+; CHECK-NEXT: [[FOO:%.*]] = add i32 [[COND]], [[X]]
+; CHECK-NEXT: ret i32 [[FOO]]
+;
+bb0:
+ %cmp = icmp ne i32 %x, 0
+ br i1 %cmp, label %bb1, label %bb2
+bb1:
+ br label %bb2
+bb2:
+ %cond = phi i32 [ %x, %bb0 ], [ 0, %bb1 ]
+ %foo = add i32 %cond, %x
+ ret i32 %foo
+}
+
+define i32 @f3(i32 %x) {
+; CHECK-LABEL: @f3(
+; CHECK-NEXT: bb0:
+; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X:%.*]])
+; CHECK-NEXT: switch i32 [[X]], label [[BB1:%.*]] [
+; CHECK-NEXT: i32 0, label [[BB2:%.*]]
+; CHECK-NEXT: ]
+; CHECK: bb1:
+; CHECK-NEXT: br label [[BB2]]
+; CHECK: bb2:
+; CHECK-NEXT: [[COND:%.*]] = phi i32 [ [[X_0]], [[BB0:%.*]] ], [ 0, [[BB1]] ]
+; CHECK-NEXT: [[FOO:%.*]] = add i32 [[COND]], [[X]]
+; CHECK-NEXT: ret i32 [[FOO]]
+;
+bb0:
+ switch i32 %x, label %bb1 [ i32 0, label %bb2]
+bb1:
+ br label %bb2
+bb2:
+ %cond = phi i32 [ %x, %bb0 ], [ 0, %bb1 ]
+ %foo = add i32 %cond, %x
+ ret i32 %foo
+}
+
+
+define double @fcmp_oeq_not_zero(double %x, double %y) {
+; CHECK-LABEL: @fcmp_oeq_not_zero(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq double [[Y:%.*]], 2.000000e+00
+; CHECK: [[Y_0:%.*]] = call double @llvm.ssa.copy.f64(double [[Y]])
+; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[RETURN:%.*]]
+; CHECK: if:
+; CHECK-NEXT: [[DIV:%.*]] = fdiv double [[X:%.*]], [[Y_0]]
+; CHECK-NEXT: br label [[RETURN]]
+; CHECK: return:
+; CHECK-NEXT: [[RETVAL:%.*]] = phi double [ [[DIV]], [[IF]] ], [ [[X]], [[ENTRY:%.*]] ]
+; CHECK-NEXT: ret double [[RETVAL]]
+;
+entry:
+ %cmp = fcmp oeq double %y, 2.0
+ br i1 %cmp, label %if, label %return
+
+if:
+ %div = fdiv double %x, %y
+ br label %return
+
+return:
+ %retval = phi double [ %div, %if ], [ %x, %entry ]
+ ret double %retval
+
+}
+
+define double @fcmp_une_not_zero(double %x, double %y) {
+; CHECK-LABEL: @fcmp_une_not_zero(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[CMP:%.*]] = fcmp une double [[Y:%.*]], 2.000000e+00
+; CHECK: [[Y_0:%.*]] = call double @llvm.ssa.copy.f64(double [[Y]])
+; CHECK-NEXT: br i1 [[CMP]], label [[RETURN:%.*]], label [[ELSE:%.*]]
+; CHECK: else:
+; CHECK-NEXT: [[DIV:%.*]] = fdiv double [[X:%.*]], [[Y_0]]
+; CHECK-NEXT: br label [[RETURN]]
+; CHECK: return:
+; CHECK-NEXT: [[RETVAL:%.*]] = phi double [ [[DIV]], [[ELSE]] ], [ [[X]], [[ENTRY:%.*]] ]
+; CHECK-NEXT: ret double [[RETVAL]]
+;
+entry:
+ %cmp = fcmp une double %y, 2.0
+ br i1 %cmp, label %return, label %else
+
+else:
+ %div = fdiv double %x, %y
+ br label %return
+
+return:
+ %retval = phi double [ %div, %else ], [ %x, %entry ]
+ ret double %retval
+
+}
+
+define double @fcmp_oeq_zero(double %x, double %y) {
+; CHECK-LABEL: @fcmp_oeq_zero(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq double [[Y:%.*]], 0.000000e+00
+; CHECK: [[Y_0:%.*]] = call double @llvm.ssa.copy.f64(double [[Y]])
+; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[RETURN:%.*]]
+; CHECK: if:
+; CHECK-NEXT: [[DIV:%.*]] = fdiv double [[X:%.*]], [[Y_0]]
+; CHECK-NEXT: br label [[RETURN]]
+; CHECK: return:
+; CHECK-NEXT: [[RETVAL:%.*]] = phi double [ [[DIV]], [[IF]] ], [ [[X]], [[ENTRY:%.*]] ]
+; CHECK-NEXT: ret double [[RETVAL]]
+;
+entry:
+ %cmp = fcmp oeq double %y, 0.0
+ br i1 %cmp, label %if, label %return
+
+if:
+ %div = fdiv double %x, %y
+ br label %return
+
+return:
+ %retval = phi double [ %div, %if ], [ %x, %entry ]
+ ret double %retval
+
+}
+
+define double @fcmp_une_zero(double %x, double %y) {
+; CHECK-LABEL: @fcmp_une_zero(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[CMP:%.*]] = fcmp une double [[Y:%.*]], -0.000000e+00
+; CHECK: [[Y_0:%.*]] = call double @llvm.ssa.copy.f64(double [[Y]])
+; CHECK-NEXT: br i1 [[CMP]], label [[RETURN:%.*]], label [[ELSE:%.*]]
+; CHECK: else:
+; CHECK-NEXT: [[DIV:%.*]] = fdiv double [[X:%.*]], [[Y_0]]
+; CHECK-NEXT: br label [[RETURN]]
+; CHECK: return:
+; CHECK-NEXT: [[RETVAL:%.*]] = phi double [ [[DIV]], [[ELSE]] ], [ [[X]], [[ENTRY:%.*]] ]
+; CHECK-NEXT: ret double [[RETVAL]]
+;
+entry:
+ %cmp = fcmp une double %y, -0.0
+ br i1 %cmp, label %return, label %else
+
+else:
+ %div = fdiv double %x, %y
+ br label %return
+
+return:
+ %retval = phi double [ %div, %else ], [ %x, %entry ]
+ ret double %retval
+
+}
+
+
+define double @fcmp_oeq_maybe_zero(double %x, double %y, double %z1, double %z2) {
+; CHECK-LABEL: @fcmp_oeq_maybe_zero(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[Z:%.*]] = fadd double [[Z1:%.*]], [[Z2:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq double [[Y:%.*]], [[Z]]
+; CHECK: [[Z_0:%.*]] = call double @llvm.ssa.copy.f64(double [[Z]])
+; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[RETURN:%.*]]
+; CHECK: if:
+; CHECK-NEXT: [[DIV:%.*]] = fdiv double [[X:%.*]], [[Z_0]]
+; CHECK-NEXT: br label [[RETURN]]
+; CHECK: return:
+; CHECK-NEXT: [[RETVAL:%.*]] = phi double [ [[DIV]], [[IF]] ], [ [[X]], [[ENTRY:%.*]] ]
+; CHECK-NEXT: ret double [[RETVAL]]
+;
+entry:
+ %z = fadd double %z1, %z2
+ %cmp = fcmp oeq double %y, %z
+ br i1 %cmp, label %if, label %return
+
+if:
+ %div = fdiv double %x, %z
+ br label %return
+
+return:
+ %retval = phi double [ %div, %if ], [ %x, %entry ]
+ ret double %retval
+
+}
+
+define double @fcmp_une_maybe_zero(double %x, double %y, double %z1, double %z2) {
+; CHECK-LABEL: @fcmp_une_maybe_zero(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[Z:%.*]] = fadd double [[Z1:%.*]], [[Z2:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = fcmp une double [[Y:%.*]], [[Z]]
+; CHECK: [[Z_0:%.*]] = call double @llvm.ssa.copy.f64(double [[Z]])
+; CHECK-NEXT: br i1 [[CMP]], label [[RETURN:%.*]], label [[ELSE:%.*]]
+; CHECK: else:
+; CHECK-NEXT: [[DIV:%.*]] = fdiv double [[X:%.*]], [[Z_0]]
+; CHECK-NEXT: br label [[RETURN]]
+; CHECK: return:
+; CHECK-NEXT: [[RETVAL:%.*]] = phi double [ [[DIV]], [[ELSE]] ], [ [[X]], [[ENTRY:%.*]] ]
+; CHECK-NEXT: ret double [[RETVAL]]
+;
+entry:
+ %z = fadd double %z1, %z2
+ %cmp = fcmp une double %y, %z
+ br i1 %cmp, label %return, label %else
+
+else:
+ %div = fdiv double %x, %z
+ br label %return
+
+return:
+ %retval = phi double [ %div, %else ], [ %x, %entry ]
+ ret double %retval
+
+}
diff --git a/test/Transforms/Util/PredicateInfo/testandor.ll b/test/Transforms/Util/PredicateInfo/testandor.ll
new file mode 100644
index 000000000000..5942ed155318
--- /dev/null
+++ b/test/Transforms/Util/PredicateInfo/testandor.ll
@@ -0,0 +1,211 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -print-predicateinfo < %s 2>&1 | FileCheck %s
+
+declare void @foo(i1)
+declare void @bar(i32)
+declare void @llvm.assume(i1)
+
+define void @testor(i32 %x, i32 %y) {
+; CHECK-LABEL: @testor(
+; CHECK-NEXT: [[XZ:%.*]] = icmp eq i32 [[X:%.*]], 0
+; CHECK-NEXT: [[YZ:%.*]] = icmp eq i32 [[Y:%.*]], 0
+; CHECK-NEXT: [[Z:%.*]] = or i1 [[XZ]], [[YZ]]
+; CHECK: [[XZ_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[XZ]])
+; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
+; CHECK: [[YZ_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[YZ]])
+; CHECK: [[Y_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[Y]])
+; CHECK: [[Z_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[Z]])
+; CHECK-NEXT: br i1 [[Z]], label [[ONEOF:%.*]], label [[NEITHER:%.*]]
+; CHECK: oneof:
+; CHECK-NEXT: call void @foo(i1 [[XZ]])
+; CHECK-NEXT: call void @foo(i1 [[YZ]])
+; CHECK-NEXT: call void @bar(i32 [[X]])
+; CHECK-NEXT: call void @bar(i32 [[Y]])
+; CHECK-NEXT: ret void
+; CHECK: neither:
+; CHECK-NEXT: call void @foo(i1 [[XZ_0]])
+; CHECK-NEXT: call void @foo(i1 [[YZ_0]])
+; CHECK-NEXT: call void @bar(i32 [[X_0]])
+; CHECK-NEXT: call void @bar(i32 [[Y_0]])
+; CHECK-NEXT: call void @foo(i1 [[Z_0]])
+; CHECK-NEXT: ret void
+;
+ %xz = icmp eq i32 %x, 0
+ %yz = icmp eq i32 %y, 0
+ %z = or i1 %xz, %yz
+ br i1 %z, label %oneof, label %neither
+oneof:
+;; Should not insert on the true edge for or
+ call void @foo(i1 %xz)
+ call void @foo(i1 %yz)
+ call void @bar(i32 %x)
+ call void @bar(i32 %y)
+ ret void
+neither:
+ call void @foo(i1 %xz)
+ call void @foo(i1 %yz)
+ call void @bar(i32 %x)
+ call void @bar(i32 %y)
+ call void @foo(i1 %z)
+ ret void
+}
+define void @testand(i32 %x, i32 %y) {
+; CHECK-LABEL: @testand(
+; CHECK-NEXT: [[XZ:%.*]] = icmp eq i32 [[X:%.*]], 0
+; CHECK-NEXT: [[YZ:%.*]] = icmp eq i32 [[Y:%.*]], 0
+; CHECK-NEXT: [[Z:%.*]] = and i1 [[XZ]], [[YZ]]
+; CHECK: [[XZ_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[XZ]])
+; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
+; CHECK: [[YZ_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[YZ]])
+; CHECK: [[Y_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[Y]])
+; CHECK: [[Z_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[Z]])
+; CHECK-NEXT: br i1 [[Z]], label [[BOTH:%.*]], label [[NOPE:%.*]]
+; CHECK: both:
+; CHECK-NEXT: call void @foo(i1 [[XZ_0]])
+; CHECK-NEXT: call void @foo(i1 [[YZ_0]])
+; CHECK-NEXT: call void @bar(i32 [[X_0]])
+; CHECK-NEXT: call void @bar(i32 [[Y_0]])
+; CHECK-NEXT: ret void
+; CHECK: nope:
+; CHECK-NEXT: call void @foo(i1 [[XZ]])
+; CHECK-NEXT: call void @foo(i1 [[YZ]])
+; CHECK-NEXT: call void @bar(i32 [[X]])
+; CHECK-NEXT: call void @bar(i32 [[Y]])
+; CHECK-NEXT: call void @foo(i1 [[Z_0]])
+; CHECK-NEXT: ret void
+;
+ %xz = icmp eq i32 %x, 0
+ %yz = icmp eq i32 %y, 0
+ %z = and i1 %xz, %yz
+ br i1 %z, label %both, label %nope
+both:
+ call void @foo(i1 %xz)
+ call void @foo(i1 %yz)
+ call void @bar(i32 %x)
+ call void @bar(i32 %y)
+ ret void
+nope:
+;; Should not insert on the false edge for and
+ call void @foo(i1 %xz)
+ call void @foo(i1 %yz)
+ call void @bar(i32 %x)
+ call void @bar(i32 %y)
+ call void @foo(i1 %z)
+ ret void
+}
+define void @testandsame(i32 %x, i32 %y) {
+; CHECK-LABEL: @testandsame(
+; CHECK-NEXT: [[XGT:%.*]] = icmp sgt i32 [[X:%.*]], 0
+; CHECK-NEXT: [[XLT:%.*]] = icmp slt i32 [[X]], 100
+; CHECK-NEXT: [[Z:%.*]] = and i1 [[XGT]], [[XLT]]
+; CHECK: [[XGT_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[XGT]])
+; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
+; CHECK: [[X_0_1:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X_0]])
+; CHECK: [[XLT_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[XLT]])
+; CHECK: [[Z_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[Z]])
+; CHECK-NEXT: br i1 [[Z]], label [[BOTH:%.*]], label [[NOPE:%.*]]
+; CHECK: both:
+; CHECK-NEXT: call void @foo(i1 [[XGT_0]])
+; CHECK-NEXT: call void @foo(i1 [[XLT_0]])
+; CHECK-NEXT: call void @bar(i32 [[X_0_1]])
+; CHECK-NEXT: ret void
+; CHECK: nope:
+; CHECK-NEXT: call void @foo(i1 [[XGT]])
+; CHECK-NEXT: call void @foo(i1 [[XLT]])
+; CHECK-NEXT: call void @foo(i1 [[Z_0]])
+; CHECK-NEXT: ret void
+;
+ %xgt = icmp sgt i32 %x, 0
+ %xlt = icmp slt i32 %x, 100
+ %z = and i1 %xgt, %xlt
+ br i1 %z, label %both, label %nope
+both:
+ call void @foo(i1 %xgt)
+ call void @foo(i1 %xlt)
+ call void @bar(i32 %x)
+ ret void
+nope:
+ call void @foo(i1 %xgt)
+ call void @foo(i1 %xlt)
+ call void @foo(i1 %z)
+ ret void
+}
+
+define void @testandassume(i32 %x, i32 %y) {
+; CHECK-LABEL: @testandassume(
+; CHECK-NEXT: [[XZ:%.*]] = icmp eq i32 [[X:%.*]], 0
+; CHECK-NEXT: [[YZ:%.*]] = icmp eq i32 [[Y:%.*]], 0
+; CHECK-NEXT: [[Z:%.*]] = and i1 [[XZ]], [[YZ]]
+; CHECK: [[TMP1:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[XZ]])
+; CHECK: [[TMP2:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
+; CHECK: [[TMP3:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[YZ]])
+; CHECK: [[TMP4:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[Y]])
+; CHECK: [[TMP5:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[Z]])
+; CHECK-NEXT: call void @llvm.assume(i1 [[TMP5]])
+; CHECK: [[DOT0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[TMP1]])
+; CHECK: [[DOT01:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[TMP2]])
+; CHECK: [[DOT02:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[TMP3]])
+; CHECK: [[DOT03:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[TMP4]])
+; CHECK: [[DOT04:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[TMP5]])
+; CHECK-NEXT: br i1 [[TMP5]], label [[BOTH:%.*]], label [[NOPE:%.*]]
+; CHECK: both:
+; CHECK-NEXT: call void @foo(i1 [[DOT0]])
+; CHECK-NEXT: call void @foo(i1 [[DOT02]])
+; CHECK-NEXT: call void @bar(i32 [[DOT01]])
+; CHECK-NEXT: call void @bar(i32 [[DOT03]])
+; CHECK-NEXT: ret void
+; CHECK: nope:
+; CHECK-NEXT: call void @foo(i1 [[DOT04]])
+; CHECK-NEXT: ret void
+;
+ %xz = icmp eq i32 %x, 0
+ %yz = icmp eq i32 %y, 0
+ %z = and i1 %xz, %yz
+ call void @llvm.assume(i1 %z)
+ br i1 %z, label %both, label %nope
+both:
+ call void @foo(i1 %xz)
+ call void @foo(i1 %yz)
+ call void @bar(i32 %x)
+ call void @bar(i32 %y)
+ ret void
+nope:
+ call void @foo(i1 %z)
+ ret void
+}
+
+;; Unlike and/or for branches, assume is *always* true, so we only match and for it
+define void @testorassume(i32 %x, i32 %y) {
+;
+; CHECK-LABEL: @testorassume(
+; CHECK-NEXT: [[XZ:%.*]] = icmp eq i32 [[X:%.*]], 0
+; CHECK-NEXT: [[YZ:%.*]] = icmp eq i32 [[Y:%.*]], 0
+; CHECK-NEXT: [[Z:%.*]] = or i1 [[XZ]], [[YZ]]
+; CHECK-NEXT: call void @llvm.assume(i1 [[Z]])
+; CHECK: [[Z_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[Z]])
+; CHECK-NEXT: br i1 [[Z]], label [[BOTH:%.*]], label [[NOPE:%.*]]
+; CHECK: both:
+; CHECK-NEXT: call void @foo(i1 [[XZ]])
+; CHECK-NEXT: call void @foo(i1 [[YZ]])
+; CHECK-NEXT: call void @bar(i32 [[X]])
+; CHECK-NEXT: call void @bar(i32 [[Y]])
+; CHECK-NEXT: ret void
+; CHECK: nope:
+; CHECK-NEXT: call void @foo(i1 [[Z_0]])
+; CHECK-NEXT: ret void
+;
+ %xz = icmp eq i32 %x, 0
+ %yz = icmp eq i32 %y, 0
+ %z = or i1 %xz, %yz
+ call void @llvm.assume(i1 %z)
+ br i1 %z, label %both, label %nope
+both:
+ call void @foo(i1 %xz)
+ call void @foo(i1 %yz)
+ call void @bar(i32 %x)
+ call void @bar(i32 %y)
+ ret void
+nope:
+ call void @foo(i1 %z)
+ ret void
+}
diff --git a/test/Transforms/Util/clone-dicompileunit.ll b/test/Transforms/Util/clone-dicompileunit.ll
new file mode 100644
index 000000000000..3f7b5981752d
--- /dev/null
+++ b/test/Transforms/Util/clone-dicompileunit.ll
@@ -0,0 +1,66 @@
+; RUN: opt -run-twice -verify -disable-debug-info-type-map -S -o - %s | FileCheck %s
+
+; Generated using:
+; $ cat p.cpp
+; void sink(void *);
+; class A {
+; public:
+; template <typename> void m_fn2() { static int a; }
+; virtual void m_fn1();
+; };
+; void foo() {
+; class B : public A {
+; public:
+; B() { m_fn2<B>(); }
+; };
+; sink(new B);
+; }
+; $ clang++ -target x86_64-unknown-linux -fvisibility=hidden -O2 -g2 -flto -S p.cpp -o p.ll
+; # then manually removed function/gv definitions
+
+; Test that when the module is cloned it does not contain a reference to
+; the original DICompileUnit as a result of a collision between the cloned
+; DISubprogram for m_fn2<B> (which refers to the non-ODR entity B via
+; template parameters) and the original DISubprogram.
+
+; CHECK: DICompileUnit
+; CHECK-NOT: DICompileUnit
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux"
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!28, !29}
+!llvm.ident = !{!30}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 5.0.0 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, globals: !3)
+!1 = !DIFile(filename: "p.cpp", directory: "/usr/local/google/home/pcc/b682773-2-repro/small2")
+!2 = !{}
+!3 = !{!4}
+!4 = !DIGlobalVariableExpression(var: !5)
+!5 = distinct !DIGlobalVariable(name: "a", scope: !6, file: !1, line: 5, type: !27, isLocal: true, isDefinition: true)
+!6 = distinct !DISubprogram(name: "m_fn2<B>", linkageName: "_ZN1A5m_fn2IZ3foovE1BEEvv", scope: !7, file: !1, line: 5, type: !8, isLocal: true, isDefinition: true, scopeLine: 5, flags: DIFlagPrototyped, isOptimized: true, unit: !0, templateParams: !11, declaration: !23, variables: !24)
+!7 = !DICompositeType(tag: DW_TAG_class_type, name: "A", file: !1, line: 3, flags: DIFlagFwdDecl, identifier: "_ZTS1A")
+!8 = !DISubroutineType(types: !9)
+!9 = !{null, !10}
+!10 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
+!11 = !{!12}
+!12 = !DITemplateTypeParameter(type: !13)
+!13 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "B", scope: !14, file: !1, line: 10, size: 64, elements: !17, vtableHolder: !7)
+!14 = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov", scope: !1, file: !1, line: 9, type: !15, isLocal: false, isDefinition: true, scopeLine: 9, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !2)
+!15 = !DISubroutineType(types: !16)
+!16 = !{null}
+!17 = !{!18, !19}
+!18 = !DIDerivedType(tag: DW_TAG_inheritance, scope: !13, baseType: !7, flags: DIFlagPublic)
+!19 = !DISubprogram(name: "B", scope: !13, file: !1, line: 12, type: !20, isLocal: false, isDefinition: false, scopeLine: 12, flags: DIFlagPublic | DIFlagPrototyped, isOptimized: true)
+!20 = !DISubroutineType(types: !21)
+!21 = !{null, !22}
+!22 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !13, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
+!23 = !DISubprogram(name: "m_fn2<B>", linkageName: "_ZN1A5m_fn2IZ3foovE1BEEvv", scope: !7, file: !1, line: 5, type: !8, isLocal: false, isDefinition: false, scopeLine: 5, flags: DIFlagPublic | DIFlagPrototyped, isOptimized: true, templateParams: !11)
+!24 = !{!25}
+!25 = !DILocalVariable(name: "this", arg: 1, scope: !6, type: !26, flags: DIFlagArtificial | DIFlagObjectPointer)
+!26 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64)
+!27 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!28 = !{i32 2, !"Dwarf Version", i32 4}
+!29 = !{i32 2, !"Debug Info Version", i32 3}
+!30 = !{!"clang version 5.0.0 "}
diff --git a/test/Transforms/Util/simplify-dbg-declare-load.ll b/test/Transforms/Util/simplify-dbg-declare-load.ll
index 21d305450860..4ea88fa81e05 100644
--- a/test/Transforms/Util/simplify-dbg-declare-load.ll
+++ b/test/Transforms/Util/simplify-dbg-declare-load.ll
@@ -19,7 +19,7 @@ fail: ; preds = %top
unreachable
idxend: ; preds = %top
-; CHECK-NOT call void @llvm.dbg.value(metadata %foo* %cp,
+; 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,
store volatile %foo %0, %foo* undef, align 8
diff --git a/test/Transforms/Util/strip-nonlinetable-debuginfo-loops.ll b/test/Transforms/Util/strip-nonlinetable-debuginfo-loops.ll
new file mode 100644
index 000000000000..5f88e31da9fc
--- /dev/null
+++ b/test/Transforms/Util/strip-nonlinetable-debuginfo-loops.ll
@@ -0,0 +1,71 @@
+; RUN: opt -S -strip-nonlinetable-debuginfo %s -o %t
+; RUN: cat %t | FileCheck %s
+; RUN: cat %t | FileCheck %s --check-prefix=NEGATIVE
+; void f(volatile int *i) {
+; while (--*i) {}
+; }
+source_filename = "/tmp/loop.c"
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.12.0"
+
+define void @f(i32* %i) local_unnamed_addr #0 !dbg !7 {
+entry:
+ tail call void @llvm.dbg.value(metadata i32* %i, i64 0, metadata !14, metadata !15), !dbg !16
+ br label %while.cond, !dbg !17
+
+while.cond: ; preds = %while.cond, %entry
+ %0 = load volatile i32, i32* %i, align 4, !dbg !18, !tbaa !19
+ %dec = add nsw i32 %0, -1, !dbg !18
+ store volatile i32 %dec, i32* %i, align 4, !dbg !18, !tbaa !19
+ %tobool = icmp eq i32 %dec, 0, !dbg !17
+ ; CHECK: !llvm.loop ![[LOOP:[0-9]+]]
+ br i1 %tobool, label %while.end, label %while.cond, !dbg !17, !llvm.loop !23
+
+while.end: ; preds = %while.cond
+ ret void, !dbg !25
+}
+
+; Function Attrs: nounwind readnone
+declare void @llvm.dbg.value(metadata, i64, metadata, metadata) #1
+
+attributes #0 = { nounwind ssp uwtable }
+attributes #1 = { nounwind readnone }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4, !5}
+!llvm.ident = !{!6}
+
+; CHECK: ![[CU:.*]] = distinct !DICompileUnit(language: DW_LANG_C99,
+; CHECK-SAME: emissionKind: LineTablesOnly
+; NEGATIVE-NOT: !DICompileUnit({{.*}} emissionKind: FullDebug
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 5.0.0 (trunk 298880) (llvm/trunk 298875)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
+!1 = !DIFile(filename: "/tmp/loop.c", directory: "/")
+!2 = !{}
+!3 = !{i32 2, !"Dwarf Version", i32 4}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!5 = !{i32 1, !"PIC Level", i32 2}
+!6 = !{!"clang version 5.0.0 (trunk 298880) (llvm/trunk 298875)"}
+; CHECK: ![[F:[0-9]]] = distinct !DISubprogram(name: "f", scope: !1
+!7 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 1, type: !8, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !13)
+!8 = !DISubroutineType(types: !9)
+!9 = !{null, !10}
+!10 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !11, size: 64)
+!11 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !12)
+; NEGATIVE-NOT: !DIBasicType(name: "int",
+!12 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!13 = !{!14}
+!14 = !DILocalVariable(name: "i", arg: 1, scope: !7, file: !1, line: 1, type: !10)
+!15 = !DIExpression()
+!16 = !DILocation(line: 1, column: 22, scope: !7)
+; CHECK: ![[BEGIN:[0-9]+]] = !DILocation(line: 2, column: 3, scope: ![[F]])
+!17 = !DILocation(line: 2, column: 3, scope: !7)
+!18 = !DILocation(line: 2, column: 10, scope: !7)
+!19 = !{!20, !20, i64 0}
+!20 = !{!"int", !21, i64 0}
+!21 = !{!"omnipotent char", !22, i64 0}
+!22 = !{!"Simple C/C++ TBAA"}
+; CHECK: ![[LOOP]] = distinct !{![[LOOP]], ![[BEGIN]], ![[END:[0-9]+]]}
+!23 = distinct !{!23, !17, !24}
+; CHECK: ![[END]] = !DILocation(line: 3, column: 3, scope: ![[F]])
+!24 = !DILocation(line: 3, column: 3, scope: !7)
+!25 = !DILocation(line: 4, column: 1, scope: !7)