aboutsummaryrefslogtreecommitdiff
path: root/test/Transforms/RewriteStatepointsForGC
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-01-02 19:17:04 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-01-02 19:17:04 +0000
commitb915e9e0fc85ba6f398b3fab0db6a81a8913af94 (patch)
tree98b8f811c7aff2547cab8642daf372d6c59502fb /test/Transforms/RewriteStatepointsForGC
parent6421cca32f69ac849537a3cff78c352195e99f1b (diff)
Notes
Diffstat (limited to 'test/Transforms/RewriteStatepointsForGC')
-rw-r--r--test/Transforms/RewriteStatepointsForGC/base-vector.ll79
-rw-r--r--test/Transforms/RewriteStatepointsForGC/deopt-lowering-attrs.ll34
-rw-r--r--test/Transforms/RewriteStatepointsForGC/rematerialize-derived-pointers.ll69
-rw-r--r--test/Transforms/RewriteStatepointsForGC/statepoint-attrs.ll16
4 files changed, 198 insertions, 0 deletions
diff --git a/test/Transforms/RewriteStatepointsForGC/base-vector.ll b/test/Transforms/RewriteStatepointsForGC/base-vector.ll
index 39a78d725977..9026275cf682 100644
--- a/test/Transforms/RewriteStatepointsForGC/base-vector.ll
+++ b/test/Transforms/RewriteStatepointsForGC/base-vector.ll
@@ -165,4 +165,83 @@ next: ; preds = %merge
ret i64 addrspace(1)* %objb
}
+; identify base for shufflevector
+define void @test8(i64 addrspace(1)* %obj, i64 %idx) gc "statepoint-example" {
+; CHECK-LABEL: @test8
+; CHECK: %gep = getelementptr i64, i64 addrspace(1)* %obj, i64 1
+; CHECK: %gep2 = getelementptr i64, i64 addrspace(1)* %obj, i64 2
+; CHECK: %vec1.base = insertelement <4 x i64 addrspace(1)*> zeroinitializer, i64 addrspace(1)* %obj, i32 0, !is_base_value !0
+; CHECK: %vec1 = insertelement <4 x i64 addrspace(1)*> undef, i64 addrspace(1)* %gep, i32 0
+; CHECK: %vec2.base = insertelement <4 x i64 addrspace(1)*> zeroinitializer, i64 addrspace(1)* %obj, i32 2, !is_base_value !0
+; CHECK: %vec2 = insertelement <4 x i64 addrspace(1)*> undef, i64 addrspace(1)* %gep2, i32 2
+; CHECK: %vec.base = shufflevector <4 x i64 addrspace(1)*> %vec1.base, <4 x i64 addrspace(1)*> %vec2.base, <2 x i32> <i32 0, i32 2>, !is_base_value !0
+; CHECK: %vec = shufflevector <4 x i64 addrspace(1)*> %vec1, <4 x i64 addrspace(1)*> %vec2, <2 x i32> <i32 0, i32 2>
+; CHECK: %bdv.base = extractelement <2 x i64 addrspace(1)*> %vec.base, i64 %idx, !is_base_value !0
+; CHECK: %bdv = extractelement <2 x i64 addrspace(1)*> %vec, i64 %idx
+; CHECK: gc.statepoint
+; CHECK: gc.relocate
+; CHECK-DAG: (%bdv.base, %bdv)
+entry:
+ %gep = getelementptr i64, i64 addrspace(1)* %obj, i64 1
+ %gep2 = getelementptr i64, i64 addrspace(1)* %obj, i64 2
+ %vec1 = insertelement <4 x i64 addrspace(1)*> undef, i64 addrspace(1)* %gep, i32 0
+ %vec2 = insertelement <4 x i64 addrspace(1)*> undef, i64 addrspace(1)* %gep2, i32 2
+ %vec = shufflevector <4 x i64 addrspace(1)*> %vec1, <4 x i64 addrspace(1)*> %vec2, <2 x i32> <i32 0, i32 2>
+ %bdv = extractelement <2 x i64 addrspace(1)*> %vec, i64 %idx
+ call void @do_safepoint() [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0) ]
+ call void @use(i64 addrspace(1)* %bdv)
+ ret void
+}
+
+; Since the same 'base' vector is used in the shuffle operands, we do not need
+; create a shufflevector base.
+define void @test9(<4 x i64 addrspace(1)*> %vec1, i64 %idx) gc "statepoint-example" {
+; CHECK-LABEL: @test9
+; CHECK: %vec = shufflevector <4 x i64 addrspace(1)*> %vec1, <4 x i64 addrspace(1)*> %vec1, <2 x i32> <i32 0, i32 2>
+; CHECK: %base_ee = extractelement <4 x i64 addrspace(1)*> %vec1, i64 %idx, !is_base_value !0
+; CHECK: %bdv = extractelement <2 x i64 addrspace(1)*> %vec, i64 %idx
+; CHECK: gc.statepoint
+; CHECK: gc.relocate
+; CHECK-DAG: (%base_ee, %bdv)
+entry:
+ ; shrinking vec1 into vec
+ %vec = shufflevector <4 x i64 addrspace(1)*> %vec1, <4 x i64 addrspace(1)*> %vec1, <2 x i32> <i32 0, i32 2>
+ %bdv = extractelement <2 x i64 addrspace(1)*> %vec, i64 %idx
+ call void @do_safepoint() [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0) ]
+ call void @use(i64 addrspace(1)* %bdv)
+ ret void
+}
+
+; vector operand of shufflevector is a phi
+define i64 addrspace(1)* @test10(i1 %cnd, i64 addrspace(1)* %obj, i64 addrspace(1)* %obj2) gc "statepoint-example" {
+; CHECK-LABEL: @test10
+entry:
+ %vec1 = insertelement <4 x i64 addrspace(1)*> undef, i64 addrspace(1)* %obj, i32 0
+ br i1 %cnd, label %here, label %merge
+
+here:
+ %vec2 = insertelement <4 x i64 addrspace(1)*> undef, i64 addrspace(1)* %obj2, i32 2
+ br label %merge
+
+merge: ; preds = %merge, %entry, %here
+; CHECK-LABEL: merge:
+; CHECK: %vec.base = phi <4 x i64 addrspace(1)*> [ %vec1.base, %entry ], [ %vec2.base, %here ], [ %vec3.base, %merge ], !is_base_value !0
+; CHECK: vec
+; CHECK: vec3.base = shufflevector <4 x i64 addrspace(1)*> %vec.base, <4 x i64 addrspace(1)*> %vec.base
+; CHECK: vec3
+; CHECK: bdv.base
+; CHECK: bdv
+ %vec = phi <4 x i64 addrspace(1)*> [ %vec1, %entry ], [ %vec2, %here], [ %vec3, %merge]
+ %vec3 = shufflevector <4 x i64 addrspace(1)*> %vec, <4 x i64 addrspace(1)*> %vec, <4 x i32> <i32 2, i32 0, i32 1, i32 3>
+ %bdv = extractelement <4 x i64 addrspace(1)*> %vec3, i32 0
+ br i1 %cnd, label %merge, label %next
+
+next:
+; CHECK-LABEL: next:
+; CHECK: gc.statepoint
+; CHECK: gc.relocate
+; CHECK-DAG: (%bdv.base, %bdv)
+ call void @do_safepoint() [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0) ]
+ ret i64 addrspace(1)* %bdv
+}
declare void @do_safepoint()
diff --git a/test/Transforms/RewriteStatepointsForGC/deopt-lowering-attrs.ll b/test/Transforms/RewriteStatepointsForGC/deopt-lowering-attrs.ll
new file mode 100644
index 000000000000..bbf10714e5e1
--- /dev/null
+++ b/test/Transforms/RewriteStatepointsForGC/deopt-lowering-attrs.ll
@@ -0,0 +1,34 @@
+; RUN: opt -rewrite-statepoints-for-gc -S < %s | FileCheck %s
+; Check that the "deopt-lowering" function attribute gets transcoded into
+; flags on the resulting statepoint
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.11.0"
+
+declare void @foo()
+declare void @bar() "deopt-lowering"="live-in"
+declare void @baz() "deopt-lowering"="live-through"
+
+define void @test1() gc "statepoint-example" {
+; CHECK-LABEL: @test1(
+; CHECK: @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @foo, i32 0, i32 0, i32 0, i32 1, i32 57)
+; CHECK: @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @bar, i32 0, i32 2, i32 0, i32 1, i32 42)
+; CHECK: @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @baz, i32 0, i32 0, i32 0, i32 1, i32 13)
+
+entry:
+ call void @foo() [ "deopt"(i32 57) ]
+ call void @bar() [ "deopt"(i32 42) ]
+ call void @baz() [ "deopt"(i32 13) ]
+ ret void
+}
+
+; add deopt-lowering attribute as part of callsite
+define void @test2() gc "statepoint-example" {
+; CHECK-LABEL: @test2(
+; CHECK: @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @foo, i32 0, i32 2, i32 0, i32 1, i32 57)
+
+entry:
+ call void @foo() "deopt-lowering"="live-in" [ "deopt"(i32 57) ]
+ ret void
+}
+
diff --git a/test/Transforms/RewriteStatepointsForGC/rematerialize-derived-pointers.ll b/test/Transforms/RewriteStatepointsForGC/rematerialize-derived-pointers.ll
index c4ec2ce5bf77..6372c9b80de5 100644
--- a/test/Transforms/RewriteStatepointsForGC/rematerialize-derived-pointers.ll
+++ b/test/Transforms/RewriteStatepointsForGC/rematerialize-derived-pointers.ll
@@ -259,3 +259,72 @@ entry:
call void @use_obj32(i32 addrspace(1)* %ptr.gep11)
ret void
}
+
+
+declare i32 addrspace(1)* @new_instance() nounwind "gc-leaf-function"
+
+; remat the gep in presence of base pointer which is a phi node.
+; FIXME: We should remove the extra basephi.base as well.
+define void @contains_basephi(i1 %cond) gc "statepoint-example" {
+; CHECK-LABEL: contains_basephi
+entry:
+ %base1 = call i32 addrspace(1)* @new_instance()
+ %base2 = call i32 addrspace(1)* @new_instance()
+ br i1 %cond, label %here, label %there
+
+here:
+ br label %merge
+
+there:
+ br label %merge
+
+merge:
+ ; CHECK: %basephi.base = phi i32 addrspace(1)* [ %base1, %here ], [ %base2, %there ], !is_base_value !0
+ ; CHECK: %basephi = phi i32 addrspace(1)* [ %base1, %here ], [ %base2, %there ]
+ ; CHECK: %ptr.gep = getelementptr i32, i32 addrspace(1)* %basephi, i32 15
+ ; CHECK: %statepoint_token = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint
+ ; CHECK: %basephi.base.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %statepoint_token, i32 7, i32 7) ; (%basephi.base, %basephi.base)
+ ; CHECK: %basephi.base.relocated.casted = bitcast i8 addrspace(1)* %basephi.base.relocated to i32 addrspace(1)*
+ ; CHECK: %ptr.gep.remat = getelementptr i32, i32 addrspace(1)* %basephi.base.relocated.casted, i32 15
+ ; CHECK: call void @use_obj32(i32 addrspace(1)* %ptr.gep.remat)
+
+
+
+ %basephi = phi i32 addrspace(1)* [ %base1, %here ], [ %base2, %there ]
+ %ptr.gep = getelementptr i32, i32 addrspace(1)* %basephi, i32 15
+ call void @do_safepoint() ["deopt"() ]
+ call void @use_obj32(i32 addrspace(1)* %ptr.gep)
+ ret void
+}
+
+
+define void @test_intersecting_chains_with_phi(i1 %cond) gc "statepoint-example" {
+; CHECK-LABEL: test_intersecting_chains_with_phi
+entry:
+ %base1 = call i32 addrspace(1)* @new_instance()
+ %base2 = call i32 addrspace(1)* @new_instance()
+ br i1 %cond, label %here, label %there
+
+here:
+ br label %merge
+
+there:
+ br label %merge
+
+merge:
+ %basephi = phi i32 addrspace(1)* [ %base1, %here ], [ %base2, %there ]
+ %ptr.gep = getelementptr i32, i32 addrspace(1)* %basephi, i32 15
+ %ptr.cast = bitcast i32 addrspace(1)* %ptr.gep to i64 addrspace(1)*
+ %ptr.cast2 = bitcast i32 addrspace(1)* %ptr.gep to i16 addrspace(1)*
+ call void @do_safepoint() [ "deopt"() ]
+ ; CHECK: statepoint
+ ; CHECK: %ptr.gep.remat1 = getelementptr i32, i32 addrspace(1)* %basephi.base.relocated.casted, i32 15
+ ; CHECK: %ptr.cast.remat = bitcast i32 addrspace(1)* %ptr.gep.remat1 to i64 addrspace(1)*
+ ; CHECK: %ptr.gep.remat = getelementptr i32, i32 addrspace(1)* %basephi.base.relocated.casted, i32 15
+ ; CHECK: %ptr.cast2.remat = bitcast i32 addrspace(1)* %ptr.gep.remat to i16 addrspace(1)*
+ ; CHECK: call void @use_obj64(i64 addrspace(1)* %ptr.cast.remat)
+ ; CHECK: call void @use_obj16(i16 addrspace(1)* %ptr.cast2.remat)
+ call void @use_obj64(i64 addrspace(1)* %ptr.cast)
+ call void @use_obj16(i16 addrspace(1)* %ptr.cast2)
+ ret void
+}
diff --git a/test/Transforms/RewriteStatepointsForGC/statepoint-attrs.ll b/test/Transforms/RewriteStatepointsForGC/statepoint-attrs.ll
new file mode 100644
index 000000000000..38ad79e887f7
--- /dev/null
+++ b/test/Transforms/RewriteStatepointsForGC/statepoint-attrs.ll
@@ -0,0 +1,16 @@
+; RUN: opt -S -rewrite-statepoints-for-gc < %s | FileCheck %s
+; Ensure statepoints copy (valid) attributes from callsites.
+
+declare void @f(i8 addrspace(1)* %obj)
+
+; copy over norecurse noimplicitfloat to statepoint call
+define void @test1(i8 addrspace(1)* %arg) gc "statepoint-example" {
+; CHECK-LABEL: test1(
+; CHECK: call token (i64, i32, void (i8 addrspace(1)*)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidp1i8f(i64 2882400000, i32 0, void (i8 addrspace(1)*)* @f, i32 1, i32 0, i8 addrspace(1)* %arg, i32 0, i32 0, i8 addrspace(1)* %arg) #1
+
+ call void @f(i8 addrspace(1)* %arg) #1
+ ret void
+}
+
+
+attributes #1 = { norecurse noimplicitfloat }