1; RUN: opt %s -rewrite-statepoints-for-gc -rs4gc-use-deopt-bundles -S | FileCheck  %s
2
3
4define i64 addrspace(1)* @test(<2 x i64 addrspace(1)*> %vec, i32 %idx) gc "statepoint-example" {
5; CHECK-LABEL: @test
6; CHECK: extractelement
7; CHECK: extractelement
8; CHECK: statepoint
9; CHECK: gc.relocate
10; CHECK-DAG: ; (%base_ee, %base_ee)
11; CHECK: gc.relocate
12; CHECK-DAG: ; (%base_ee, %obj)
13; Note that the second extractelement is actually redundant here.  A correct output would
14; be to reuse the existing obj as a base since it is actually a base pointer.
15entry:
16  %obj = extractelement <2 x i64 addrspace(1)*> %vec, i32 %idx
17  call void @do_safepoint() [ "deopt"() ]
18  ret i64 addrspace(1)* %obj
19}
20
21define i64 addrspace(1)* @test2(<2 x i64 addrspace(1)*>* %ptr, i1 %cnd, i32 %idx1, i32 %idx2) gc "statepoint-example" {
22; CHECK-LABEL: test2
23entry:
24  br i1 %cnd, label %taken, label %untaken
25
26taken:                                            ; preds = %entry
27  %obja = load <2 x i64 addrspace(1)*>, <2 x i64 addrspace(1)*>* %ptr
28  br label %merge
29
30untaken:                                          ; preds = %entry
31  %objb = load <2 x i64 addrspace(1)*>, <2 x i64 addrspace(1)*>* %ptr
32  br label %merge
33
34merge:                                            ; preds = %untaken, %taken
35  %vec = phi <2 x i64 addrspace(1)*> [ %obja, %taken ], [ %objb, %untaken ]
36  br i1 %cnd, label %taken2, label %untaken2
37
38taken2:                                           ; preds = %merge
39  %obj0 = extractelement <2 x i64 addrspace(1)*> %vec, i32 %idx1
40  br label %merge2
41
42untaken2:                                         ; preds = %merge
43  %obj1 = extractelement <2 x i64 addrspace(1)*> %vec, i32 %idx2
44  br label %merge2
45
46merge2:                                           ; preds = %untaken2, %taken2
47; CHECK-LABEL: merge2:
48; CHECK-NEXT: %obj = phi i64 addrspace(1)*
49; CHECK-NEXT: statepoint
50; CHECK: gc.relocate
51; CHECK-DAG: ; (%obj, %obj)
52  %obj = phi i64 addrspace(1)* [ %obj0, %taken2 ], [ %obj1, %untaken2 ]
53  call void @do_safepoint() [ "deopt"() ]
54  ret i64 addrspace(1)* %obj
55}
56
57define i64 addrspace(1)* @test3(i64 addrspace(1)* %ptr) gc "statepoint-example" {
58; CHECK-LABEL: test3
59; CHECK: insertelement
60; CHECK: extractelement
61; CHECK: statepoint
62; CHECK: gc.relocate
63; CHECK-DAG: (%obj, %obj)
64entry:
65  %vec = insertelement <2 x i64 addrspace(1)*> undef, i64 addrspace(1)* %ptr, i32 0
66  %obj = extractelement <2 x i64 addrspace(1)*> %vec, i32 0
67  call void @do_safepoint() [ "deopt"() ]
68  ret i64 addrspace(1)* %obj
69}
70
71define i64 addrspace(1)* @test4(i64 addrspace(1)* %ptr) gc "statepoint-example" {
72; CHECK-LABEL: test4
73; CHECK: statepoint
74; CHECK: gc.relocate
75; CHECK-DAG: ; (%ptr, %obj)
76; CHECK: gc.relocate
77; CHECK-DAG: ; (%ptr, %ptr)
78; When we can optimize an extractelement from a known
79; index and avoid introducing new base pointer instructions
80entry:
81  %derived = getelementptr i64, i64 addrspace(1)* %ptr, i64 16
82  %veca = insertelement <2 x i64 addrspace(1)*> undef, i64 addrspace(1)* %derived, i32 0
83  %vec = insertelement <2 x i64 addrspace(1)*> %veca, i64 addrspace(1)* %ptr, i32 1
84  %obj = extractelement <2 x i64 addrspace(1)*> %vec, i32 0
85  call void @do_safepoint() [ "deopt"() ]
86  ret i64 addrspace(1)* %obj
87}
88
89declare void @use(i64 addrspace(1)*) "gc-leaf-function"
90
91define void @test5(i1 %cnd, i64 addrspace(1)* %obj) gc "statepoint-example" {
92; CHECK-LABEL: @test5
93; CHECK: gc.relocate
94; CHECK-DAG: (%obj, %bdv)
95; When we fundementally have to duplicate
96entry:
97  %gep = getelementptr i64, i64 addrspace(1)* %obj, i64 1
98  %vec = insertelement <2 x i64 addrspace(1)*> undef, i64 addrspace(1)* %gep, i32 0
99  %bdv = extractelement <2 x i64 addrspace(1)*> %vec, i32 0
100  call void @do_safepoint() [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0) ]
101  call void @use(i64 addrspace(1)* %bdv)
102  ret void
103}
104
105define void @test6(i1 %cnd, i64 addrspace(1)* %obj, i64 %idx) gc "statepoint-example" {
106; CHECK-LABEL: @test6
107; CHECK: %gep = getelementptr i64, i64 addrspace(1)* %obj, i64 1
108; CHECK: %vec.base = insertelement <2 x i64 addrspace(1)*> undef, i64 addrspace(1)* %obj, i32 0, !is_base_value !0
109; CHECK: %vec = insertelement <2 x i64 addrspace(1)*> undef, i64 addrspace(1)* %gep, i32 0
110; CHECK: %bdv.base = extractelement <2 x i64 addrspace(1)*> %vec.base, i64 %idx, !is_base_value !0
111; CHECK:  %bdv = extractelement <2 x i64 addrspace(1)*> %vec, i64 %idx
112; CHECK: gc.statepoint
113; CHECK: gc.relocate
114; CHECK-DAG: (%bdv.base, %bdv)
115; A more complicated example involving vector and scalar bases.
116; This is derived from a failing test case when we didn't have correct
117; insertelement handling.
118entry:
119  %gep = getelementptr i64, i64 addrspace(1)* %obj, i64 1
120  %vec = insertelement <2 x i64 addrspace(1)*> undef, i64 addrspace(1)* %gep, i32 0
121  %bdv = extractelement <2 x i64 addrspace(1)*> %vec, i64 %idx
122  call void @do_safepoint() [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0) ]
123  call void @use(i64 addrspace(1)* %bdv)
124  ret void
125}
126
127define i64 addrspace(1)* @test7(i1 %cnd, i64 addrspace(1)* %obj, i64 addrspace(1)* %obj2) gc "statepoint-example" {
128; CHECK-LABEL: @test7
129entry:
130  %vec = insertelement <2 x i64 addrspace(1)*> undef, i64 addrspace(1)* %obj2, i32 0
131  br label %merge1
132
133merge1:                                           ; preds = %merge1, %entry
134; CHECK-LABEL: merge1:
135; CHECK: vec2.base
136; CHECK: vec2
137; CHECK: gep
138; CHECK: vec3.base
139; CHECK: vec3
140  %vec2 = phi <2 x i64 addrspace(1)*> [ %vec, %entry ], [ %vec3, %merge1 ]
141  %gep = getelementptr i64, i64 addrspace(1)* %obj2, i64 1
142  %vec3 = insertelement <2 x i64 addrspace(1)*> undef, i64 addrspace(1)* %gep, i32 0
143  br i1 %cnd, label %merge1, label %next1
144
145next1:                                            ; preds = %merge1
146; CHECK-LABEL: next1:
147; CHECK: bdv.base =
148; CHECK: bdv =
149  %bdv = extractelement <2 x i64 addrspace(1)*> %vec2, i32 0
150  br label %merge
151
152merge:                                            ; preds = %merge, %next1
153; CHECK-LABEL: merge:
154; CHECK: %objb.base
155; CHECK: %objb
156; CHECK: gc.statepoint
157; CHECK: gc.relocate
158; CHECK-DAG: (%objb.base, %objb)
159  %objb = phi i64 addrspace(1)* [ %obj, %next1 ], [ %bdv, %merge ]
160  br i1 %cnd, label %merge, label %next
161
162next:                                             ; preds = %merge
163  call void @do_safepoint() [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0) ]
164  ret i64 addrspace(1)* %objb
165}
166
167declare void @do_safepoint()
168