1 ; A collection of liveness test cases to ensure we're reporting the
2 ; correct live values at statepoints
3 ; RUN: opt -passes=rewrite-statepoints-for-gc -spp-rematerialization-threshold=0 -S < %s | FileCheck %s
5 ; Tests to make sure we consider %obj live in both the taken and untaken
6 ; predeccessor of merge.
8 define ptr addrspace(1) @test1(i1 %cmp, ptr addrspace(1) %obj) gc "statepoint-example" {
11 br i1 %cmp, label %taken, label %untaken
13 taken: ; preds = %entry
15 ; CHECK-NEXT: gc.statepoint
16 ; CHECK-NEXT: %obj.relocated = call coldcc ptr addrspace(1)
17 ; CHECK-NEXT: br label %merge
18 call void @foo() [ "deopt"() ]
21 untaken: ; preds = %entry
22 ; CHECK-LABEL: untaken:
23 ; CHECK-NEXT: gc.statepoint
24 ; CHECK-NEXT: %obj.relocated2 = call coldcc ptr addrspace(1)
25 ; CHECK-NEXT: br label %merge
26 call void @foo() [ "deopt"() ]
29 merge: ; preds = %untaken, %taken
31 ; CHECK-NEXT: %.0 = phi ptr addrspace(1) [ %obj.relocated, %taken ], [ %obj.relocated2, %untaken ]
32 ; CHECK-NEXT: ret ptr addrspace(1) %.0
33 ; A local kill should not effect liveness in predecessor block
34 ret ptr addrspace(1) %obj
37 define ptr addrspace(1) @test2(i1 %cmp, ptr %loc) gc "statepoint-example" {
41 ; CHECK-NEXT: gc.statepoint
43 call void @foo() [ "deopt"() ]
44 br i1 %cmp, label %taken, label %untaken
46 taken: ; preds = %entry
48 ; CHECK-NEXT: %obj = load
49 ; CHECK-NEXT: gc.statepoint
50 ; CHECK-NEXT: gc.relocate
51 ; CHECK-NEXT: ret ptr addrspace(1) %obj.relocated
52 ; A local kill should effect values live from a successor phi. Also, we
53 ; should only propagate liveness from a phi to the appropriate predecessors.
54 %obj = load ptr addrspace(1), ptr %loc
55 call void @foo() [ "deopt"() ]
56 ret ptr addrspace(1) %obj
58 untaken: ; preds = %entry
59 ret ptr addrspace(1) null
62 define ptr addrspace(1) @test3(i1 %cmp, ptr %loc) gc "statepoint-example" {
65 br i1 %cmp, label %taken, label %untaken
67 taken: ; preds = %entry
69 ; CHECK-NEXT: gc.statepoint
70 ; CHECK-NEXT: %obj = load
71 ; CHECK-NEXT: gc.statepoint
72 ; CHECK-NEXT: %obj.relocated = call coldcc ptr addrspace(1)
73 ; CHECK-NEXT: br label %merge
74 call void @foo() [ "deopt"() ]
75 %obj = load ptr addrspace(1), ptr %loc
76 call void @foo() [ "deopt"() ]
79 untaken: ; preds = %entry
81 ; CHECK-NEXT: gc.statepoint
82 ; CHECK-NEXT: br label %merge
83 ; A base pointer must be live if it is needed at a later statepoint,
84 ; even if the base pointer is otherwise unused.
85 call void @foo() [ "deopt"() ]
88 merge: ; preds = %untaken, %taken
89 %phi = phi ptr addrspace(1) [ %obj, %taken ], [ null, %untaken ]
90 ret ptr addrspace(1) %phi
93 define ptr addrspace(1) @test4(i1 %cmp, ptr addrspace(1) %obj) gc "statepoint-example" {
97 ; CHECK-NEXT: %derived = getelementptr
98 ; CHECK-NEXT: gc.statepoint
99 ; CHECK-NEXT: %derived.relocated =
100 ; CHECK-NEXT: %obj.relocated =
101 ; CHECK-NEXT: gc.statepoint
102 ; CHECK-NEXT: %derived.relocated2 =
104 ; Note: It's legal to relocate obj again, but not strictly needed
105 ; CHECK-NEXT: %obj.relocated3 =
106 ; CHECK-NEXT: ret ptr addrspace(1) %derived.relocated2
108 ; Make sure that a phi def visited during iteration is considered a kill.
109 ; Also, liveness after base pointer analysis can change based on new uses,
111 %derived = getelementptr i64, ptr addrspace(1) %obj, i64 8
112 call void @foo() [ "deopt"() ]
113 call void @foo() [ "deopt"() ]
114 ret ptr addrspace(1) %derived
117 declare void @consume(...) readonly "gc-leaf-function"
119 define ptr addrspace(1) @test5(i1 %cmp, ptr addrspace(1) %obj) gc "statepoint-example" {
120 ; CHECK-LABEL: @test5
122 br i1 %cmp, label %taken, label %untaken
124 taken: ; preds = %entry
125 ; CHECK-LABEL: taken:
126 ; CHECK-NEXT: gc.statepoint
127 ; CHECK-NEXT: %obj.relocated = call coldcc ptr addrspace(1)
128 ; CHECK-NEXT: br label %merge
129 call void @foo() [ "deopt"() ]
132 untaken: ; preds = %entry
133 ; CHECK-LABEL: untaken:
134 ; CHECK-NEXT: br label %merge
137 merge: ; preds = %untaken, %taken
138 ; CHECK-LABEL: merge:
139 ; CHECK-NEXT: %.0 = phi ptr addrspace(1)
140 ; CHECK-NEXT: %obj2a = phi
141 ; CHECK-NEXT: @consume
142 ; CHECK-NEXT: br label %final
143 %obj2a = phi ptr addrspace(1) [ %obj, %taken ], [ null, %untaken ]
144 call void (...) @consume(ptr addrspace(1) %obj2a)
147 final: ; preds = %merge
148 ; CHECK-LABEL: final:
149 ; CHECK-NEXT: @consume
150 ; CHECK-NEXT: ret ptr addrspace(1) %.0
151 call void (...) @consume(ptr addrspace(1) %obj2a)
152 ret ptr addrspace(1) %obj