xref: /llvm-project/llvm/test/Transforms/CodeGenPrepare/X86/statepoint-relocate.ll (revision 8ea31db27211ed0c8207b4b4b0839e5cbe780c73)
1; RUN: opt -passes='require<profile-summary>,function(codegenprepare)' -S < %s | FileCheck %s
2
3target datalayout = "e-i64:64-f80:128-n8:16:32:64-S128"
4target triple = "x86_64-pc-linux-gnu"
5
6declare zeroext i1 @return_i1()
7
8define i32 @test_sor_basic(ptr addrspace(1) %base) gc "statepoint-example" {
9; CHECK: getelementptr i32, ptr addrspace(1) %base, i32 15
10; CHECK: getelementptr i32, ptr addrspace(1) %base-new, i32 15
11entry:
12       %ptr = getelementptr i32, ptr addrspace(1) %base, i32 15
13       %tok = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(i1 ()) @return_i1, i32 0, i32 0, i32 0, i32 0) ["gc-live"(ptr addrspace(1) %base, ptr addrspace(1) %ptr)]
14       %base-new = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 0)
15       %ptr-new = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 1)
16       %ret = load i32, ptr addrspace(1) %ptr-new
17       ret i32 %ret
18}
19
20define i32 @test_sor_two_derived(ptr addrspace(1) %base) gc "statepoint-example" {
21; CHECK-LABEL: @test_sor_two_derived(
22; CHECK: getelementptr i32, ptr addrspace(1) %base, i32 15
23; CHECK: getelementptr i32, ptr addrspace(1) %base, i32 12
24; CHECK: getelementptr i32, ptr addrspace(1) %base-new, i32 15
25; CHECK: getelementptr i32, ptr addrspace(1) %base-new, i32 12
26entry:
27       %ptr = getelementptr i32, ptr addrspace(1) %base, i32 15
28       %ptr2 = getelementptr i32, ptr addrspace(1) %base, i32 12
29       %tok = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(i1 ()) @return_i1, i32 0, i32 0, i32 0, i32 0) ["gc-live"(ptr addrspace(1) %base, ptr addrspace(1) %ptr, ptr addrspace(1) %ptr2)]
30       %base-new = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 0)
31       %ptr-new = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 1)
32       %ptr2-new = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 2)
33       %ret = load i32, ptr addrspace(1) %ptr-new
34       ret i32 %ret
35}
36
37define i32 @test_sor_ooo(ptr addrspace(1) %base) gc "statepoint-example" {
38; CHECK-LABEL: @test_sor_ooo(
39; CHECK: getelementptr i32, ptr addrspace(1) %base, i32 15
40; CHECK: getelementptr i32, ptr addrspace(1) %base-new, i32 15
41entry:
42       %ptr = getelementptr i32, ptr addrspace(1) %base, i32 15
43       %tok = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(i1 ()) @return_i1, i32 0, i32 0, i32 0, i32 0) ["gc-live"(ptr addrspace(1) %base, ptr addrspace(1) %ptr)]
44       %ptr-new = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 1)
45       %base-new = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 0)
46       %ret = load i32, ptr addrspace(1) %ptr-new
47       ret i32 %ret
48}
49
50define i32 @test_sor_gep_smallint(ptr addrspace(1) %base) gc "statepoint-example" {
51; CHECK: getelementptr [3 x i32], ptr addrspace(1) %base, i32 0, i32 2
52; CHECK: getelementptr [3 x i32], ptr addrspace(1) %base-new, i32 0, i32 2
53entry:
54       %ptr = getelementptr [3 x i32], ptr addrspace(1) %base, i32 0, i32 2
55       %tok = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(i1 ()) @return_i1, i32 0, i32 0, i32 0, i32 0) ["gc-live"(ptr addrspace(1) %base, ptr addrspace(1) %ptr)]
56       %base-new = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 0)
57       %ptr-new = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 1)
58       %ret = load i32, ptr addrspace(1) %ptr-new
59       ret i32 %ret
60}
61
62define i32 @test_sor_gep_largeint(ptr addrspace(1) %base) gc "statepoint-example" {
63; CHECK: getelementptr [3 x i32], ptr addrspace(1) %base, i32 0, i32 21
64; CHECK-NOT: getelementptr [3 x i32], ptr addrspace(1) %base-new, i32 0, i32 21
65entry:
66       %ptr = getelementptr [3 x i32], ptr addrspace(1) %base, i32 0, i32 21
67       %tok = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(i1 ()) @return_i1, i32 0, i32 0, i32 0, i32 0) ["gc-live"(ptr addrspace(1) %base, ptr addrspace(1) %ptr)]
68       %base-new = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 0)
69       %ptr-new = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 1)
70       %ret = load i32, ptr addrspace(1) %ptr-new
71       ret i32 %ret
72}
73
74define i32 @test_sor_noop(ptr addrspace(1) %base) gc "statepoint-example" {
75; CHECK: getelementptr i32, ptr addrspace(1) %base, i32 15
76; CHECK: call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 1)
77; CHECK: call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 2)
78entry:
79       %ptr = getelementptr i32, ptr addrspace(1) %base, i32 15
80       %ptr2 = getelementptr i32, ptr addrspace(1) %base, i32 12
81       %tok = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(i1 ()) @return_i1, i32 0, i32 0, i32 0, i32 0) ["gc-live"(ptr addrspace(1) %base, ptr addrspace(1) %ptr, ptr addrspace(1) %ptr2)]
82       %ptr-new = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 1)
83       %ptr2-new = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 2)
84       %ret = load i32, ptr addrspace(1) %ptr-new
85       ret i32 %ret
86}
87
88define i32 @test_sor_basic_wrong_order(ptr addrspace(1) %base) gc "statepoint-example" {
89; CHECK-LABEL: @test_sor_basic_wrong_order
90; Here we have base relocate inserted after derived. Make sure that we don't
91; produce uses of the relocated base pointer before it's definition.
92entry:
93       %ptr = getelementptr i32, ptr addrspace(1) %base, i32 15
94       ; CHECK: getelementptr i32, ptr addrspace(1) %base, i32 15
95       %tok = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(i1 ()) @return_i1, i32 0, i32 0, i32 0, i32 0) ["gc-live"(ptr addrspace(1) %base, ptr addrspace(1) %ptr)]
96       %ptr-new = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 1)
97       %base-new = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 0)
98       ; CHECK: %base-new = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 0)
99       ; CHECK-NEXT: getelementptr i32, ptr addrspace(1) %base-new, i32 15
100       %ret = load i32, ptr addrspace(1) %ptr-new
101       ret i32 %ret
102}
103
104define i32 @test_sor_noop_cross_bb(i1 %external-cond, ptr addrspace(1) %base) gc "statepoint-example" {
105; CHECK-LABEL: @test_sor_noop_cross_bb
106; Here base relocate doesn't dominate derived relocate. Make sure that we don't
107; produce undefined use of the relocated base pointer.
108entry:
109       %ptr = getelementptr i32, ptr addrspace(1) %base, i32 15
110       ; CHECK: getelementptr i32, ptr addrspace(1) %base, i32 15
111       %tok = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(i1 ()) @return_i1, i32 0, i32 0, i32 0, i32 0) ["gc-live"(ptr addrspace(1) %base, ptr addrspace(1) %ptr)]
112       br i1 %external-cond, label %left, label %right
113
114left:
115       %ptr-new = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 1)
116       ; CHECK: call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 1)
117       %ret-new = load i32, ptr addrspace(1) %ptr-new
118       ret i32 %ret-new
119
120right:
121       %ptr-base = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 0)
122       ; CHECK: call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 0)
123       %ret-base = load i32, ptr addrspace(1) %ptr-base
124       ret i32 %ret-base
125}
126
127define i32 @test_sor_noop_same_bb(i1 %external-cond, ptr addrspace(1) %base) gc "statepoint-example" {
128; CHECK-LABEL: @test_sor_noop_same_bb
129; Here base relocate doesn't dominate derived relocate. Make sure that we don't
130; produce undefined use of the relocated base pointer.
131entry:
132       %ptr1 = getelementptr i32, ptr addrspace(1) %base, i32 15
133       ; CHECK: getelementptr i32, ptr addrspace(1) %base, i32 15
134       %ptr2 = getelementptr i32, ptr addrspace(1) %base, i32 5
135       ; CHECK: getelementptr i32, ptr addrspace(1) %base, i32 5
136       %tok = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(i1 ()) @return_i1, i32 0, i32 0, i32 0, i32 0) ["gc-live"(ptr addrspace(1) %base, ptr addrspace(1) %ptr1, ptr addrspace(1) %ptr2)]
137       ; CHECK: call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 0)
138       %ptr2-new = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 2)
139       %ret2-new = load i32, ptr addrspace(1) %ptr2-new
140       ; CHECK: getelementptr i32, ptr addrspace(1) %base-new, i32 5
141       %ptr1-new = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 1)
142       %ret1-new = load i32, ptr addrspace(1) %ptr1-new
143       ; CHECK: getelementptr i32, ptr addrspace(1) %base-new, i32 15
144       %base-new = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 0)
145       %ret-new = add i32 %ret2-new, %ret1-new
146       ret i32 %ret-new
147}
148
149declare token @llvm.experimental.gc.statepoint.p0(i64, i32, ptr, i32, i32, ...)
150declare ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token, i32, i32)
151