diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2017-04-16 16:01:22 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2017-04-16 16:01:22 +0000 |
| commit | 71d5a2540a98c81f5bcaeb48805e0e2881f530ef (patch) | |
| tree | 5343938942df402b49ec7300a1c25a2d4ccd5821 /test/Transforms/Util | |
| parent | 31bbf64f3a4974a2d6c8b3b27ad2f519caf74057 (diff) | |
Diffstat (limited to 'test/Transforms/Util')
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) |
