aboutsummaryrefslogtreecommitdiff
path: root/test/Transforms/NewGVN/refine-stores.ll
diff options
context:
space:
mode:
Diffstat (limited to 'test/Transforms/NewGVN/refine-stores.ll')
-rw-r--r--test/Transforms/NewGVN/refine-stores.ll189
1 files changed, 189 insertions, 0 deletions
diff --git a/test/Transforms/NewGVN/refine-stores.ll b/test/Transforms/NewGVN/refine-stores.ll
new file mode 100644
index 000000000000..a48f2fe7fdb6
--- /dev/null
+++ b/test/Transforms/NewGVN/refine-stores.ll
@@ -0,0 +1,189 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s
+;; Now that we do store refinement, we have to verify that we add fake uses
+;; when we skip existing stores.
+;; We also are testing that various variations that cause stores to move classes
+;; have the right class movement happen
+;; All of these tests result in verification failures if it does not.
+%struct.eggs = type {}
+
+define void @spam(i32 *%a) {
+; CHECK-LABEL: @spam(
+; CHECK-NEXT: bb:
+; CHECK-NEXT: [[FOO:%.*]] = bitcast i32* [[A:%.*]] to %struct.eggs**
+; CHECK-NEXT: store %struct.eggs* null, %struct.eggs** [[FOO]]
+; CHECK-NEXT: br label [[BB1:%.*]]
+; CHECK: bb1:
+; CHECK-NEXT: br i1 undef, label [[BB3:%.*]], label [[BB2:%.*]]
+; CHECK: bb2:
+; CHECK-NEXT: call void @baz()
+; CHECK-NEXT: br label [[BB1]]
+; CHECK: bb3:
+; CHECK-NEXT: store i32 0, i32* undef
+; CHECK-NEXT: store %struct.eggs* null, %struct.eggs** [[FOO]]
+; CHECK-NEXT: unreachable
+;
+bb:
+ %foo = bitcast i32 *%a to %struct.eggs**
+ store %struct.eggs* null, %struct.eggs** %foo
+ br label %bb1
+
+bb1: ; preds = %bb2, %bb
+ br i1 undef, label %bb3, label %bb2
+
+bb2: ; preds = %bb1
+ call void @baz()
+ br label %bb1
+
+bb3: ; preds = %bb1
+ store i32 0, i32* undef
+;; This store is defined by a memoryphi of the call and the first store
+;; At first, we will prove it equivalent to the first store above.
+;; Then the call will become reachable, and the equivalence will be removed
+;; Without it being a use of the first store, we will not update the store
+;; to reflect this.
+ store %struct.eggs* null, %struct.eggs** %foo
+ unreachable
+}
+
+declare void @baz()
+
+
+define void @a() {
+; CHECK-LABEL: @a(
+; CHECK-NEXT: b:
+; CHECK-NEXT: br label [[C:%.*]]
+; CHECK: c:
+; CHECK-NEXT: store i64 undef, i64* null
+; CHECK-NEXT: br label [[E:%.*]]
+; CHECK: e:
+; CHECK-NEXT: [[G:%.*]] = load i64*, i64** null
+; CHECK-NEXT: store i64* undef, i64** null
+; CHECK-NEXT: br i1 undef, label [[C]], label [[E]]
+;
+b:
+ br label %c
+
+c: ; preds = %e, %b
+ %d = phi i64* [ undef, %b ], [ null, %e ]
+ store i64 undef, i64* %d
+ br label %e
+
+e: ; preds = %e, %c
+;; The memory for this load starts out equivalent to just the store in c, we later discover the store after us, and
+;; need to make sure the right set of values get marked as changed after memory leaders change
+ %g = load i64*, i64** null
+ %0 = bitcast i64* %g to i64*
+ store i64* undef, i64** null
+ br i1 undef, label %c, label %e
+}
+
+; ModuleID = 'bugpoint-reduced-simplified.bc'
+source_filename = "bugpoint-output-daef094.bc"
+target triple = "x86_64-apple-darwin16.5.0"
+
+%struct.hoge = type {}
+
+define void @widget(%struct.hoge* %arg) {
+; CHECK-LABEL: @widget(
+; CHECK-NEXT: bb:
+; CHECK-NEXT: br label [[BB1:%.*]]
+; CHECK: bb1:
+; CHECK-NEXT: [[TMP:%.*]] = phi %struct.hoge* [ [[ARG:%.*]], [[BB:%.*]] ], [ null, [[BB1]] ]
+; CHECK-NEXT: store %struct.hoge* [[TMP]], %struct.hoge** undef
+; CHECK-NEXT: br i1 undef, label [[BB1]], label [[BB2:%.*]]
+; CHECK: bb2:
+; CHECK-NEXT: [[TMP3:%.*]] = phi i64 [ [[TMP8:%.*]], [[BB7:%.*]] ], [ 0, [[BB1]] ]
+; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i64 [[TMP3]], 0
+; CHECK-NEXT: br i1 [[TMP4]], label [[BB7]], label [[BB5:%.*]]
+; CHECK: bb5:
+; CHECK-NEXT: [[TMP6:%.*]] = load i64, i64* null
+; CHECK-NEXT: call void @quux()
+; CHECK-NEXT: store i64 [[TMP6]], i64* undef
+; CHECK-NEXT: br label [[BB7]]
+; CHECK: bb7:
+; CHECK-NEXT: [[TMP8]] = add i64 [[TMP3]], 1
+; CHECK-NEXT: br label [[BB2]]
+;
+bb:
+ br label %bb1
+
+bb1: ; preds = %bb1, %bb
+ %tmp = phi %struct.hoge* [ %arg, %bb ], [ null, %bb1 ]
+ store %struct.hoge* %tmp, %struct.hoge** undef
+ br i1 undef, label %bb1, label %bb2
+
+bb2: ; preds = %bb7, %bb1
+ %tmp3 = phi i64 [ %tmp8, %bb7 ], [ 0, %bb1 ]
+ %tmp4 = icmp eq i64 %tmp3, 0
+ br i1 %tmp4, label %bb7, label %bb5
+
+bb5: ; preds = %bb2
+ ;; Originally thought equal to the store that comes after it until the phi edges
+ ;; are completely traversed
+ %tmp6 = load i64, i64* null
+ call void @quux()
+ store i64 %tmp6, i64* undef
+ br label %bb7
+
+bb7: ; preds = %bb5, %bb2
+ %tmp8 = add i64 %tmp3, 1
+ br label %bb2
+}
+
+declare void @quux()
+; ModuleID = 'short.ll'
+source_filename = "short.ll"
+
+%struct.a = type {}
+
+define void @b() {
+; CHECK-LABEL: @b(
+; CHECK-NEXT: [[C:%.*]] = alloca [[STRUCT_A:%.*]]
+; CHECK-NEXT: br label [[D:%.*]]
+; CHECK: m:
+; CHECK-NEXT: unreachable
+; CHECK: d:
+; CHECK-NEXT: [[G:%.*]] = bitcast %struct.a* [[C]] to i8*
+; CHECK-NEXT: [[F:%.*]] = bitcast i8* [[G]] to i32*
+; CHECK-NEXT: [[E:%.*]] = load i32, i32* [[F]]
+; CHECK-NEXT: br i1 undef, label [[I:%.*]], label [[J:%.*]]
+; CHECK: i:
+; CHECK-NEXT: br i1 undef, label [[K:%.*]], label [[M:%.*]]
+; CHECK: k:
+; CHECK-NEXT: br label [[L:%.*]]
+; CHECK: l:
+; CHECK-NEXT: unreachable
+; CHECK: j:
+; CHECK-NEXT: br label [[M]]
+;
+ %c = alloca %struct.a
+ br label %d
+
+m: ; preds = %j, %i
+ store i32 %e, i32* %f
+ unreachable
+
+d: ; preds = %0
+ %g = bitcast %struct.a* %c to i8*
+ %h = getelementptr i8, i8* %g
+ %f = bitcast i8* %h to i32*
+ %e = load i32, i32* %f
+ br i1 undef, label %i, label %j
+
+i: ; preds = %d
+ br i1 undef, label %k, label %m
+
+k: ; preds = %i
+ br label %l
+
+l: ; preds = %k
+ %n = phi i32 [ %e, %k ]
+ ;; Becomes equal and then not equal to the other store, and
+ ;; along the way, the load.
+ store i32 %n, i32* %f
+ unreachable
+
+j: ; preds = %d
+ br label %m
+}