1; RUN: opt < %s -rewrite-statepoints-for-gc -S 2>&1 | FileCheck %s
2; RUN: opt < %s -passes=rewrite-statepoints-for-gc -S 2>&1 | FileCheck %s
3
4; The rewriting needs to make %obj loop variant by inserting a phi
5; of the original value and it's relocation.
6
7declare i64 addrspace(1)* @generate_obj() "gc-leaf-function"
8
9declare void @use_obj(i64 addrspace(1)*) "gc-leaf-function"
10
11define void @def_use_safepoint() gc "statepoint-example" {
12; CHECK-LABEL: def_use_safepoint
13; CHECK: phi i64 addrspace(1)*
14; CHECK-DAG: [ %obj.relocated.casted, %loop ]
15; CHECK-DAG: [ %obj, %entry ]
16entry:
17  %obj = call i64 addrspace(1)* @generate_obj()
18  br label %loop
19
20loop:                                             ; preds = %loop, %entry
21  call void @use_obj(i64 addrspace(1)* %obj)
22  call void @do_safepoint() [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0) ]
23  br label %loop
24}
25
26declare void @do_safepoint()
27
28declare void @parse_point(i64 addrspace(1)*)
29
30define i64 addrspace(1)* @test1(i32 %caller, i8 addrspace(1)* %a, i8 addrspace(1)* %b, i32 %unknown) gc "statepoint-example" {
31; CHECK-LABEL: test1
32entry:
33  br i1 undef, label %left, label %right
34
35left:                                             ; preds = %entry
36; CHECK: left:
37; CHECK-NEXT: %a.cast = bitcast i8 addrspace(1)* %a to i64 addrspace(1)*
38; CHECK-NEXT: [[CAST_L:%.*]] = bitcast i8 addrspace(1)* %a to i64 addrspace(1)*
39; Our safepoint placement pass calls removeUnreachableBlocks, which does a bunch
40; of simplifications to branch instructions.  This bug is visible only when
41; there are multiple branches into the same block from the same predecessor, and
42; the following ceremony is to make that artefact survive a call to
43; removeUnreachableBlocks.  As an example, "br i1 undef, label %merge, label %merge"
44; will get simplified to "br label %merge" by removeUnreachableBlocks.
45  %a.cast = bitcast i8 addrspace(1)* %a to i64 addrspace(1)*
46  switch i32 %unknown, label %right [
47    i32 0, label %merge
48    i32 1, label %merge
49    i32 5, label %merge
50    i32 3, label %right
51  ]
52
53right:                                            ; preds = %left, %left, %entry
54; CHECK: right:
55; CHECK-NEXT: %b.cast = bitcast i8 addrspace(1)* %b to i64 addrspace(1)*
56; CHECK-NEXT: [[CAST_R:%.*]] = bitcast i8 addrspace(1)* %b to i64 addrspace(1)*
57  %b.cast = bitcast i8 addrspace(1)* %b to i64 addrspace(1)*
58  br label %merge
59
60merge:                                            ; preds = %right, %left, %left, %left
61; CHECK: merge:
62; CHECK-NEXT: %value.base = phi i64 addrspace(1)* [ [[CAST_L]], %left ], [ [[CAST_L]], %left ], [ [[CAST_L]], %left ], [ [[CAST_R]], %right ], !is_base_value !0
63  %value = phi i64 addrspace(1)* [ %a.cast, %left ], [ %a.cast, %left ], [ %a.cast, %left ], [ %b.cast, %right ]
64  call void @parse_point(i64 addrspace(1)* %value) [ "deopt"(i32 0, i32 0, i32 0, i32 0, i32 0) ]
65  ret i64 addrspace(1)* %value
66}
67
68;; The purpose of this test is to ensure that when two live values share a
69;;  base defining value with inherent conflicts, we end up with a *single*
70;;  base phi/select per such node.  This is testing an optimization, not a
71;;  fundemental correctness criteria
72define void @test2(i1 %cnd, i64 addrspace(1)* %base_obj, i64 addrspace(1)* %base_arg2) gc "statepoint-example" {
73; CHECK-LABEL: @test2
74entry:
75  %obj = getelementptr i64, i64 addrspace(1)* %base_obj, i32 1
76  br label %loop
77; CHECK-LABEL: loop
78; CHECK:   %current.base = phi i64 addrspace(1)*
79; CHECK-DAG: [ %base_obj, %entry ]
80
81; Given the two selects are equivelent, so are their base phis - ideally,
82; we'd have commoned these, but that's a missed optimization, not correctness.
83; CHECK-DAG: [ [[DISCARD:%.*.base.relocated.casted]], %loop ]
84; CHECK-NOT: extra.base
85; CHECK: next.base = select
86; CHECK: next = select
87; CHECK: extra2.base = select
88; CHECK: extra2 = select
89; CHECK: statepoint
90;; Both 'next' and 'extra2' are live across the backedge safepoint...
91
92loop:                                             ; preds = %loop, %entry
93  %current = phi i64 addrspace(1)* [ %obj, %entry ], [ %next, %loop ]
94  %extra = phi i64 addrspace(1)* [ %obj, %entry ], [ %extra2, %loop ]
95  %nexta = getelementptr i64, i64 addrspace(1)* %current, i32 1
96  %next = select i1 %cnd, i64 addrspace(1)* %nexta, i64 addrspace(1)* %base_arg2
97  %extra2 = select i1 %cnd, i64 addrspace(1)* %nexta, i64 addrspace(1)* %base_arg2
98  call void @foo() [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0) ]
99  br label %loop
100}
101
102define i64 addrspace(1)* @test3(i1 %cnd, i64 addrspace(1)* %obj, i64 addrspace(1)* %obj2) gc "statepoint-example" {
103; CHECK-LABEL: @test3
104entry:
105  br i1 %cnd, label %merge, label %taken
106
107taken:                                            ; preds = %entry
108  br label %merge
109
110merge:                                            ; preds = %taken, %entry
111; CHECK-LABEL: merge:
112; CHECK-NEXT: phi
113; CHECK-NEXT: phi
114; CHECK-NEXT: gc.statepoint
115  %bdv = phi i64 addrspace(1)* [ %obj, %entry ], [ %obj2, %taken ]
116  call void @foo() [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0) ]
117  ret i64 addrspace(1)* %bdv
118}
119
120define i64 addrspace(1)* @test4(i1 %cnd, i64 addrspace(1)* %obj, i64 addrspace(1)* %obj2) gc "statepoint-example" {
121; CHECK-LABEL: @test4
122entry:
123  br i1 %cnd, label %merge, label %taken
124
125taken:                                            ; preds = %entry
126  br label %merge
127
128merge:                                            ; preds = %taken, %entry
129; CHECK-LABEL: merge:
130; CHECK-NEXT: phi
131; CHECK-NEXT: gc.statepoint
132  %bdv = phi i64 addrspace(1)* [ %obj, %entry ], [ %obj, %taken ]
133  call void @foo() [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0) ]
134  ret i64 addrspace(1)* %bdv
135}
136
137define i64 addrspace(1)* @test5(i1 %cnd, i64 addrspace(1)* %obj, i64 addrspace(1)* %obj2) gc "statepoint-example" {
138; CHECK-LABEL: @test5
139entry:
140  br label %merge
141
142merge:                                            ; preds = %merge, %entry
143; CHECK-LABEL: merge:
144; CHECK-NEXT: phi
145; CHECK-NEXT: phi
146; CHECK-NEXT: br i1
147  %bdv = phi i64 addrspace(1)* [ %obj, %entry ], [ %obj2, %merge ]
148  br i1 %cnd, label %merge, label %next
149
150next:                                             ; preds = %merge
151  call void @foo() [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0) ]
152  ret i64 addrspace(1)* %bdv
153}
154
155declare void @foo()
156