xref: /llvm-project/llvm/test/Transforms/RewriteStatepointsForGC/deref-pointers.ll (revision f01a3a893c147c1594b9a3fbd817456b209dabbf)
1; RUN: opt -S -passes=rewrite-statepoints-for-gc < %s | FileCheck %s
2
3; CHECK: declare ptr addrspace(1) @some_function_ret_deref()
4; CHECK: define ptr addrspace(1) @test_deref_arg(ptr addrspace(1) %a)
5; CHECK: define ptr addrspace(1) @test_deref_or_null_arg(ptr addrspace(1) %a)
6; CHECK: define ptr addrspace(1) @test_noalias_arg(ptr addrspace(1) %a)
7
8declare void @foo()
9
10declare ptr addrspace(1) @some_function() "gc-leaf-function"
11
12declare void @some_function_consumer(ptr addrspace(1)) "gc-leaf-function"
13
14declare dereferenceable(4) ptr addrspace(1) @some_function_ret_deref() "gc-leaf-function"
15declare noalias ptr addrspace(1) @some_function_ret_noalias() "gc-leaf-function"
16
17define ptr addrspace(1) @test_deref_arg(ptr addrspace(1) dereferenceable(4) %a) gc "statepoint-example" {
18entry:
19  call void @foo() [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0) ]
20  ret ptr addrspace(1) %a
21}
22
23define ptr addrspace(1) @test_deref_or_null_arg(ptr addrspace(1) dereferenceable_or_null(4) %a) gc "statepoint-example" {
24entry:
25  call void @foo() [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0) ]
26  ret ptr addrspace(1) %a
27}
28
29define ptr addrspace(1) @test_noalias_arg(ptr addrspace(1) noalias %a) gc "statepoint-example" {
30entry:
31  call void @foo() [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0) ]
32  ret ptr addrspace(1) %a
33}
34
35define ptr addrspace(1) @test_deref_retval() gc "statepoint-example" {
36; CHECK-LABEL: @test_deref_retval(
37; CHECK: %a = call ptr addrspace(1) @some_function()
38entry:
39  %a = call dereferenceable(4) ptr addrspace(1) @some_function()
40  call void @foo() [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0) ]
41  ret ptr addrspace(1) %a
42}
43
44define ptr addrspace(1) @test_deref_or_null_retval() gc "statepoint-example" {
45; CHECK-LABEL: @test_deref_or_null_retval(
46; CHECK: %a = call ptr addrspace(1) @some_function()
47entry:
48  %a = call dereferenceable_or_null(4) ptr addrspace(1) @some_function()
49  call void @foo() [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0) ]
50  ret ptr addrspace(1) %a
51}
52
53define ptr addrspace(1) @test_noalias_retval() gc "statepoint-example" {
54; CHECK-LABEL: @test_noalias_retval(
55; CHECK: %a = call ptr addrspace(1) @some_function()
56entry:
57  %a = call noalias ptr addrspace(1) @some_function()
58  call void @foo() [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0) ]
59  ret ptr addrspace(1) %a
60}
61
62define i8 @test_md(ptr addrspace(1) %ptr) gc "statepoint-example" {
63; CHECK-LABEL: @test_md(
64; CHECK: %tmp = load i8, ptr addrspace(1) %ptr, align 1, !tbaa [[TAG_old:!.*]]
65entry:
66  %tmp = load i8, ptr addrspace(1) %ptr, !tbaa !0
67  call void @foo() [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0) ]
68  ret i8 %tmp
69}
70
71; Same as test_md() above, but with new-format TBAA metadata.
72define i8 @test_md_new(ptr addrspace(1) %ptr) gc "statepoint-example" {
73; CHECK-LABEL: @test_md_new(
74; CHECK: %tmp = load i8, ptr addrspace(1) %ptr, align 1, !tbaa [[TAG_new:!.*]]
75entry:
76  %tmp = load i8, ptr addrspace(1) %ptr, !tbaa !4
77  call void @foo() [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0) ]
78  ret i8 %tmp
79}
80
81define ptr addrspace(1) @test_decl_only_attribute(ptr addrspace(1) %ptr) gc "statepoint-example" {
82; CHECK-LABEL: @test_decl_only_attribute(
83; No change here, but the prototype of some_function_ret_deref should have changed.
84; CHECK: call ptr addrspace(1) @some_function_ret_deref()
85entry:
86  %a = call ptr addrspace(1) @some_function_ret_deref()
87  call void @foo() [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0) ]
88  ret ptr addrspace(1) %a
89}
90
91define ptr addrspace(1) @test_decl_only_noalias(ptr addrspace(1) %ptr) gc "statepoint-example" {
92; CHECK-LABEL: @test_decl_only_noalias(
93; No change here, but the prototype of some_function_ret_noalias should have changed.
94; CHECK: call ptr addrspace(1) @some_function_ret_noalias()
95entry:
96  %a = call ptr addrspace(1) @some_function_ret_noalias()
97  call void @foo() [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0) ]
98  ret ptr addrspace(1) %a
99}
100
101define ptr addrspace(1) @test_callsite_arg_attribute(ptr addrspace(1) %ptr) gc "statepoint-example" {
102; CHECK-LABEL: @test_callsite_arg_attribute(
103; CHECK: call void @some_function_consumer(ptr addrspace(1) %ptr)
104entry:
105  call void @some_function_consumer(ptr addrspace(1) dereferenceable(4) noalias %ptr)
106  call void @foo() [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0) ]
107  ret ptr addrspace(1) %ptr
108}
109
110!0 = !{!1, !2, i64 0, i64 1}  ; TAG_old
111!1 = !{!"type_base_old", !2, i64 0}
112!2 = !{!"type_access_old", !3}
113!3 = !{!"root"}
114
115!4 = !{!5, !6, i64 0, i64 1, i64 1}  ; TAG_new
116!5 = !{!3, i64 1, !"type_base_new", !6, i64 0, i64 1}
117!6 = !{!3, i64 1, !"type_access_new"}
118
119; CHECK-DAG: [[ROOT:!.*]] = !{!"root"}
120; CHECK-DAG: [[TYPE_access_old:!.*]] = !{!"type_access_old", [[ROOT]]}
121; CHECK-DAG: [[TYPE_base_old:!.*]] = !{!"type_base_old", [[TYPE_access_old]], i64 0}
122; CHECK-DAG: [[TAG_old]] = !{[[TYPE_base_old]], [[TYPE_access_old]], i64 0}
123; CHECK-DAG: [[TYPE_access_new:!.*]] = !{[[ROOT]], i64 1, !"type_access_new"}
124; CHECK-DAG: [[TYPE_base_new:!.*]] = !{[[ROOT]], i64 1, !"type_base_new", [[TYPE_access_new]], i64 0, i64 1}
125; CHECK-DAG: [[TAG_new]] = !{[[TYPE_base_new]], [[TYPE_access_new]], i64 0, i64 1}
126