Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / test / Transforms / RewriteStatepointsForGC / rematerialize-derived-pointers-at-uses.ll
blobdbf7a2b2e3f3c108582207f69ff31c1ae315331c
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes='rewrite-statepoints-for-gc,verify<safepoint-ir>' -S | FileCheck %s
4 declare void @use_obj(ptr addrspace(1)) "gc-leaf-function"
5 declare void @do_safepoint()
8 ; Profitable test
9 define i32 @test_remat(ptr addrspace(1) %base, i1 %cond) gc "statepoint-example" {
10 ; CHECK-LABEL: @test_remat(
11 ; CHECK-NEXT:  entry:
12 ; CHECK-NEXT:    [[DERIVED:%.*]] = getelementptr i32, ptr addrspace(1) [[BASE:%.*]], i32 16
13 ; CHECK-NEXT:    [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 2882400000, i32 0, ptr elementtype(void ()) @do_safepoint, i32 0, i32 0, i32 0, i32 0) [ "deopt"(), "gc-live"(ptr addrspace(1) [[BASE]]) ]
14 ; CHECK-NEXT:    [[BASE_RELOCATED:%.*]] = call coldcc ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token [[STATEPOINT_TOKEN]], i32 0, i32 0)
15 ; CHECK-NEXT:    br i1 [[COND:%.*]], label [[HERE:%.*]], label [[THERE:%.*]]
16 ; CHECK:       here:
17 ; CHECK-NEXT:    [[STATEPOINT_TOKEN1:%.*]] = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 2882400000, i32 0, ptr elementtype(void ()) @do_safepoint, i32 0, i32 0, i32 0, i32 0) [ "deopt"(), "gc-live"(ptr addrspace(1) [[BASE_RELOCATED]]) ]
18 ; CHECK-NEXT:    [[BASE_RELOCATED2:%.*]] = call coldcc ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token [[STATEPOINT_TOKEN1]], i32 0, i32 0)
19 ; CHECK-NEXT:    br label [[MERGE:%.*]]
20 ; CHECK:       there:
21 ; CHECK-NEXT:    [[STATEPOINT_TOKEN3:%.*]] = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 2882400000, i32 0, ptr elementtype(void ()) @do_safepoint, i32 0, i32 0, i32 0, i32 0) [ "deopt"(), "gc-live"(ptr addrspace(1) [[BASE_RELOCATED]]) ]
22 ; CHECK-NEXT:    [[BASE_RELOCATED4:%.*]] = call coldcc ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token [[STATEPOINT_TOKEN3]], i32 0, i32 0)
23 ; CHECK-NEXT:    br label [[MERGE]]
24 ; CHECK:       merge:
25 ; CHECK-NEXT:    [[DOT0:%.*]] = phi ptr addrspace(1) [ [[BASE_RELOCATED2]], [[HERE]] ], [ [[BASE_RELOCATED4]], [[THERE]] ]
26 ; CHECK-NEXT:    [[DERIVED_REMAT:%.*]] = getelementptr i32, ptr addrspace(1) [[DOT0]], i32 16
27 ; CHECK-NEXT:    [[RET:%.*]] = load i32, ptr addrspace(1) [[DERIVED_REMAT]], align 4
28 ; CHECK-NEXT:    ret i32 [[RET]]
30 entry:
31   %derived = getelementptr i32, ptr addrspace(1) %base, i32 16
32   call void @do_safepoint() [ "deopt"() ]
33   br i1 %cond, label %here, label %there
35 here:
36   call void @do_safepoint() [ "deopt"() ]
37   br label %merge
39 there:
40   call void @do_safepoint() [ "deopt"() ]
41   br label %merge
43 merge:
44   %ret = load i32, ptr addrspace(1) %derived
45   ret i32 %ret
48 ; Unprofitable test
49 define i32 @test_many_uses(ptr addrspace(1) %base, i1 %cond) gc "statepoint-example" {
50 ; CHECK-LABEL: @test_many_uses(
51 ; CHECK-NEXT:  entry:
52 ; CHECK-NEXT:    [[DERIVED:%.*]] = getelementptr i32, ptr addrspace(1) [[BASE:%.*]], i32 16
53 ; CHECK-NEXT:    [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 2882400000, i32 0, ptr elementtype(void ()) @do_safepoint, i32 0, i32 0, i32 0, i32 0) [ "deopt"(), "gc-live"(ptr addrspace(1) [[BASE]]) ]
54 ; CHECK-NEXT:    [[BASE_RELOCATED:%.*]] = call coldcc ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token [[STATEPOINT_TOKEN]], i32 0, i32 0)
55 ; CHECK-NEXT:    [[DERIVED_REMAT:%.*]] = getelementptr i32, ptr addrspace(1) [[BASE_RELOCATED]], i32 16
56 ; CHECK-NEXT:    br i1 [[COND:%.*]], label [[HERE:%.*]], label [[THERE:%.*]]
57 ; CHECK:       here:
58 ; CHECK-NEXT:    [[STATEPOINT_TOKEN3:%.*]] = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 2882400000, i32 0, ptr elementtype(void ()) @do_safepoint, i32 0, i32 0, i32 0, i32 0) [ "deopt"(), "gc-live"(ptr addrspace(1) [[BASE_RELOCATED]]) ]
59 ; CHECK-NEXT:    [[BASE_RELOCATED4:%.*]] = call coldcc ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token [[STATEPOINT_TOKEN3]], i32 0, i32 0)
60 ; CHECK-NEXT:    [[DERIVED_REMAT1:%.*]] = getelementptr i32, ptr addrspace(1) [[BASE_RELOCATED4]], i32 16
61 ; CHECK-NEXT:    call void @use_obj(ptr addrspace(1) [[DERIVED_REMAT1]])
62 ; CHECK-NEXT:    br label [[MERGE:%.*]]
63 ; CHECK:       there:
64 ; CHECK-NEXT:    call void @use_obj(ptr addrspace(1) [[DERIVED_REMAT]])
65 ; CHECK-NEXT:    [[STATEPOINT_TOKEN5:%.*]] = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 2882400000, i32 0, ptr elementtype(void ()) @do_safepoint, i32 0, i32 0, i32 0, i32 0) [ "deopt"(), "gc-live"(ptr addrspace(1) [[BASE_RELOCATED]]) ]
66 ; CHECK-NEXT:    [[BASE_RELOCATED6:%.*]] = call coldcc ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token [[STATEPOINT_TOKEN5]], i32 0, i32 0)
67 ; CHECK-NEXT:    [[DERIVED_REMAT2:%.*]] = getelementptr i32, ptr addrspace(1) [[BASE_RELOCATED6]], i32 16
68 ; CHECK-NEXT:    br label [[MERGE]]
69 ; CHECK:       merge:
70 ; CHECK-NEXT:    [[DOT0:%.*]] = phi ptr addrspace(1) [ [[DERIVED_REMAT1]], [[HERE]] ], [ [[DERIVED_REMAT2]], [[THERE]] ]
71 ; CHECK-NEXT:    call void @use_obj(ptr addrspace(1) [[DOT0]])
72 ; CHECK-NEXT:    [[RET:%.*]] = load i32, ptr addrspace(1) [[DOT0]], align 4
73 ; CHECK-NEXT:    ret i32 [[RET]]
75 entry:
76   %derived = getelementptr i32, ptr addrspace(1) %base, i32 16
77   call void @do_safepoint() [ "deopt" () ]
78   br i1 %cond, label %here, label %there
80 here:
81   call void @do_safepoint() [ "deopt"() ]
82   call void @use_obj(ptr addrspace(1) %derived)
83   br label %merge
85 there:
86   call void @use_obj(ptr addrspace(1) %derived)
87   call void @do_safepoint() [ "deopt"() ]
88   br label %merge
90 merge:
91   call void @use_obj(ptr addrspace(1) %derived)
92   %ret = load i32, ptr addrspace(1) %derived
93   ret i32 %ret
96 ; Remat before phi - not implemented
97 define i32 @test_phi(ptr addrspace(1) %base, i1 %cond) gc "statepoint-example" {
98 ; CHECK-LABEL: @test_phi(
99 ; CHECK-NEXT:  entry:
100 ; CHECK-NEXT:    [[DERIVED1:%.*]] = getelementptr i32, ptr addrspace(1) [[BASE:%.*]], i32 16
101 ; CHECK-NEXT:    [[DERIVED2:%.*]] = getelementptr i32, ptr addrspace(1) [[BASE]], i32 32
102 ; CHECK-NEXT:    [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 2882400000, i32 0, ptr elementtype(void ()) @do_safepoint, i32 0, i32 0, i32 0, i32 0) [ "deopt"(), "gc-live"(ptr addrspace(1) [[BASE]]) ]
103 ; CHECK-NEXT:    [[BASE_RELOCATED:%.*]] = call coldcc ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token [[STATEPOINT_TOKEN]], i32 0, i32 0)
104 ; CHECK-NEXT:    [[DERIVED2_REMAT:%.*]] = getelementptr i32, ptr addrspace(1) [[BASE_RELOCATED]], i32 32
105 ; CHECK-NEXT:    [[DERIVED1_REMAT:%.*]] = getelementptr i32, ptr addrspace(1) [[BASE_RELOCATED]], i32 16
106 ; CHECK-NEXT:    br i1 [[COND:%.*]], label [[HERE:%.*]], label [[THERE:%.*]]
107 ; CHECK:       here:
108 ; CHECK-NEXT:    br label [[MERGE:%.*]]
109 ; CHECK:       there:
110 ; CHECK-NEXT:    br label [[MERGE]]
111 ; CHECK:       merge:
112 ; CHECK-NEXT:    [[PHI1:%.*]] = phi ptr addrspace(1) [ [[DERIVED1_REMAT]], [[HERE]] ], [ [[DERIVED2_REMAT]], [[THERE]] ]
113 ; CHECK-NEXT:    [[RET:%.*]] = load i32, ptr addrspace(1) [[PHI1]], align 4
114 ; CHECK-NEXT:    ret i32 [[RET]]
116 entry:
117   %derived1 = getelementptr i32, ptr addrspace(1) %base, i32 16
118   %derived2 = getelementptr i32, ptr addrspace(1) %base, i32 32
119   call void @do_safepoint() [ "deopt"() ]
120   br i1 %cond, label %here, label %there
122 here:
123   br label %merge
125 there:
126   br label %merge
128 merge:
129   %phi1 = phi ptr addrspace(1) [ %derived1, %here ], [ %derived2, %there ]
130   %ret = load i32, ptr addrspace(1) %phi1
131   ret i32 %ret
134 ; Several uses per block
135 ; TODO: We could rematerialize once per block for several uses if there is not statepoint between
136 define i32 @test_same_block_with_statepoint(ptr addrspace(1) %base, i1 %cond) gc "statepoint-example" {
137 ; CHECK-LABEL: @test_same_block_with_statepoint(
138 ; CHECK-NEXT:  entry:
139 ; CHECK-NEXT:    [[DERIVED:%.*]] = getelementptr i32, ptr addrspace(1) [[BASE:%.*]], i32 16
140 ; CHECK-NEXT:    [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 2882400000, i32 0, ptr elementtype(void ()) @do_safepoint, i32 0, i32 0, i32 0, i32 0) [ "deopt"(), "gc-live"(ptr addrspace(1) [[BASE]]) ]
141 ; CHECK-NEXT:    [[BASE_RELOCATED:%.*]] = call coldcc ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token [[STATEPOINT_TOKEN]], i32 0, i32 0)
142 ; CHECK-NEXT:    br i1 [[COND:%.*]], label [[HERE:%.*]], label [[THERE:%.*]]
143 ; CHECK:       here:
144 ; CHECK-NEXT:    [[DERIVED_REMAT3:%.*]] = getelementptr i32, ptr addrspace(1) [[BASE_RELOCATED]], i32 16
145 ; CHECK-NEXT:    call void @use_obj(ptr addrspace(1) [[DERIVED_REMAT3]])
146 ; CHECK-NEXT:    [[STATEPOINT_TOKEN4:%.*]] = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 2882400000, i32 0, ptr elementtype(void ()) @do_safepoint, i32 0, i32 0, i32 0, i32 0) [ "deopt"(), "gc-live"(ptr addrspace(1) [[BASE_RELOCATED]]) ]
147 ; CHECK-NEXT:    [[BASE_RELOCATED5:%.*]] = call coldcc ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token [[STATEPOINT_TOKEN4]], i32 0, i32 0)
148 ; CHECK-NEXT:    [[DERIVED_REMAT2:%.*]] = getelementptr i32, ptr addrspace(1) [[BASE_RELOCATED5]], i32 16
149 ; CHECK-NEXT:    call void @use_obj(ptr addrspace(1) [[DERIVED_REMAT2]])
150 ; CHECK-NEXT:    [[DERIVED_REMAT1:%.*]] = getelementptr i32, ptr addrspace(1) [[BASE_RELOCATED5]], i32 16
151 ; CHECK-NEXT:    [[DUMMY:%.*]] = load i32, ptr addrspace(1) [[DERIVED_REMAT1]], align 4
152 ; CHECK-NEXT:    [[STATEPOINT_TOKEN6:%.*]] = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 2882400000, i32 0, ptr elementtype(void ()) @do_safepoint, i32 0, i32 0, i32 0, i32 0) [ "deopt"(), "gc-live"(ptr addrspace(1) [[BASE_RELOCATED5]]) ]
153 ; CHECK-NEXT:    [[BASE_RELOCATED7:%.*]] = call coldcc ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token [[STATEPOINT_TOKEN6]], i32 0, i32 0)
154 ; CHECK-NEXT:    br label [[MERGE:%.*]]
155 ; CHECK:       there:
156 ; CHECK-NEXT:    [[STATEPOINT_TOKEN8:%.*]] = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 2882400000, i32 0, ptr elementtype(void ()) @do_safepoint, i32 0, i32 0, i32 0, i32 0) [ "deopt"(), "gc-live"(ptr addrspace(1) [[BASE_RELOCATED]]) ]
157 ; CHECK-NEXT:    [[BASE_RELOCATED9:%.*]] = call coldcc ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token [[STATEPOINT_TOKEN8]], i32 0, i32 0)
158 ; CHECK-NEXT:    br label [[MERGE]]
159 ; CHECK:       merge:
160 ; CHECK-NEXT:    [[DOT0:%.*]] = phi ptr addrspace(1) [ [[BASE_RELOCATED7]], [[HERE]] ], [ [[BASE_RELOCATED9]], [[THERE]] ]
161 ; CHECK-NEXT:    [[DERIVED_REMAT:%.*]] = getelementptr i32, ptr addrspace(1) [[DOT0]], i32 16
162 ; CHECK-NEXT:    [[RET:%.*]] = load i32, ptr addrspace(1) [[DERIVED_REMAT]], align 4
163 ; CHECK-NEXT:    ret i32 [[RET]]
165 entry:
166   %derived = getelementptr i32, ptr addrspace(1) %base, i32 16
167   call void @do_safepoint() [ "deopt" () ]
168   br i1 %cond, label %here, label %there
170 here:
171   call void @use_obj(ptr addrspace(1) %derived)
172   call void @do_safepoint() [ "deopt"() ]
173   call void @use_obj(ptr addrspace(1) %derived)
174   %dummy = load i32, ptr addrspace(1) %derived
175   call void @do_safepoint() [ "deopt" () ]
176   br label %merge
178 there:
179   call void @do_safepoint() [ "deopt"() ]
180   br label %merge
182 merge:
183   %ret = load i32, ptr addrspace(1) %derived
184   ret i32 %ret
187 ; Test long chain with sub-chain rematerialized
188 ; TODO: If we rematerialized longer chain first (%v4), then shorter on (%v0) would become dead
189 define void @test_chain(ptr addrspace(1) %base, i1 %cond1) gc "statepoint-example" {
190 ; CHECK-LABEL: @test_chain(
191 ; CHECK-NEXT:  entry:
192 ; CHECK-NEXT:    [[V0:%.*]] = getelementptr i8, ptr addrspace(1) [[BASE:%.*]], i64 16
193 ; CHECK-NEXT:    [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 2882400000, i32 0, ptr elementtype(void ()) @do_safepoint, i32 0, i32 0, i32 0, i32 0) [ "deopt"(ptr addrspace(1) [[BASE]]), "gc-live"(ptr addrspace(1) [[BASE]]) ]
194 ; CHECK-NEXT:    [[BASE_RELOCATED:%.*]] = call coldcc ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token [[STATEPOINT_TOKEN]], i32 0, i32 0)
195 ; CHECK-NEXT:    br i1 [[COND1:%.*]], label [[BLOCK3:%.*]], label [[COMMON_RET:%.*]]
196 ; CHECK:       block3:
197 ; CHECK-NEXT:    [[V0_REMAT:%.*]] = getelementptr i8, ptr addrspace(1) [[BASE_RELOCATED]], i64 16
198 ; CHECK-NEXT:    [[V4:%.*]] = getelementptr i8, ptr addrspace(1) [[V0_REMAT]], i64 70
199 ; CHECK-NEXT:    [[STATEPOINT_TOKEN1:%.*]] = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 2882400000, i32 0, ptr elementtype(void ()) @do_safepoint, i32 0, i32 0, i32 0, i32 0) [ "deopt"(ptr addrspace(1) [[BASE_RELOCATED]]), "gc-live"(ptr addrspace(1) [[BASE_RELOCATED]]) ]
200 ; CHECK-NEXT:    [[BASE_RELOCATED2:%.*]] = call coldcc ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token [[STATEPOINT_TOKEN1]], i32 0, i32 0)
201 ; CHECK-NEXT:    [[V0_REMAT_REMAT:%.*]] = getelementptr i8, ptr addrspace(1) [[BASE_RELOCATED2]], i64 16
202 ; CHECK-NEXT:    [[V4_REMAT:%.*]] = getelementptr i8, ptr addrspace(1) [[V0_REMAT_REMAT]], i64 70
203 ; CHECK-NEXT:    [[V5:%.*]] = load atomic i8, ptr addrspace(1) [[V4_REMAT]] unordered, align 2
204 ; CHECK-NEXT:    br label [[COMMON_RET]]
205 ; CHECK:       common.ret:
206 ; CHECK-NEXT:    ret void
208 entry:
209   %v0 = getelementptr i8, ptr addrspace(1) %base, i64 16
210   call void @do_safepoint() [ "deopt"(ptr addrspace(1) %base) ]
211   br i1 %cond1, label %block3, label %common.ret
213 block3:
214   %v4 = getelementptr i8, ptr addrspace(1) %v0, i64 70
215   call void @do_safepoint() [ "deopt"(ptr addrspace(1) %base) ]
216   %v5 = load atomic i8, ptr addrspace(1) %v4 unordered, align 2
217   br label %common.ret
219 common.ret:
220   ret void