[DAGCombiner] Add target hook function to decide folding (mul (add x, c1), c2)
[llvm-project.git] / llvm / test / Transforms / RewriteStatepointsForGC / liveness-basics.ll
blob457a5b2044672ef49473e610bbc81b193ff90997
1 ; A collection of liveness test cases to ensure we're reporting the
2 ; correct live values at statepoints
3 ; RUN: opt -rewrite-statepoints-for-gc -spp-rematerialization-threshold=0 -S < %s | FileCheck %s
4 ; RUN: opt -passes=rewrite-statepoints-for-gc -spp-rematerialization-threshold=0 -S < %s | FileCheck %s
6 ; Tests to make sure we consider %obj live in both the taken and untaken 
7 ; predeccessor of merge.
9 define i64 addrspace(1)* @test1(i1 %cmp, i64 addrspace(1)* %obj) gc "statepoint-example" {
10 ; CHECK-LABEL: @test1
11 entry:
12   br i1 %cmp, label %taken, label %untaken
14 taken:                                            ; preds = %entry
15 ; CHECK-LABEL: taken:
16 ; CHECK-NEXT: gc.statepoint
17 ; CHECK-NEXT: %obj.relocated = call coldcc i8 addrspace(1)*
18 ; CHECK-NEXT: bitcast
19 ; CHECK-NEXT: br label %merge
20   call void @foo() [ "deopt"() ]
21   br label %merge
23 untaken:                                          ; preds = %entry
24 ; CHECK-LABEL: untaken:
25 ; CHECK-NEXT: gc.statepoint
26 ; CHECK-NEXT: %obj.relocated2 = call coldcc i8 addrspace(1)*
27 ; CHECK-NEXT: bitcast
28 ; CHECK-NEXT: br label %merge
29   call void @foo() [ "deopt"() ]
30   br label %merge
32 merge:                                            ; preds = %untaken, %taken
33 ; CHECK-LABEL: merge:
34 ; CHECK-NEXT: %.0 = phi i64 addrspace(1)* [ %obj.relocated.casted, %taken ], [ %obj.relocated2.casted, %untaken ]
35 ; CHECK-NEXT: ret i64 addrspace(1)* %.0
36 ; A local kill should not effect liveness in predecessor block
37   ret i64 addrspace(1)* %obj
40 define i64 addrspace(1)* @test2(i1 %cmp, i64 addrspace(1)** %loc) gc "statepoint-example" {
41 ; CHECK-LABEL: @test2
42 entry:
43 ; CHECK-LABEL: entry:
44 ; CHECK-NEXT:  gc.statepoint
45 ; CHECK-NEXT:  br
46   call void @foo() [ "deopt"() ]
47   br i1 %cmp, label %taken, label %untaken
49 taken:                                            ; preds = %entry
50 ; CHECK-LABEL: taken:
51 ; CHECK-NEXT:  %obj = load
52 ; CHECK-NEXT:  gc.statepoint
53 ; CHECK-NEXT:  gc.relocate
54 ; CHECK-NEXT: bitcast
55 ; CHECK-NEXT:  ret i64 addrspace(1)* %obj.relocated.casted
56 ; A local kill should effect values live from a successor phi.  Also, we
57 ; should only propagate liveness from a phi to the appropriate predecessors.
58   %obj = load i64 addrspace(1)*, i64 addrspace(1)** %loc
59   call void @foo() [ "deopt"() ]
60   ret i64 addrspace(1)* %obj
62 untaken:                                          ; preds = %entry
63   ret i64 addrspace(1)* null
66 define i64 addrspace(1)* @test3(i1 %cmp, i64 addrspace(1)** %loc) gc "statepoint-example" {
67 ; CHECK-LABEL: @test3
68 entry:
69   br i1 %cmp, label %taken, label %untaken
71 taken:                                            ; preds = %entry
72 ; CHECK-LABEL: taken:
73 ; CHECK-NEXT: gc.statepoint
74 ; CHECK-NEXT: %obj = load
75 ; CHECK-NEXT: gc.statepoint
76 ; CHECK-NEXT: %obj.relocated = call coldcc i8 addrspace(1)*
77 ; CHECK-NEXT: bitcast
78 ; CHECK-NEXT: br label %merge
79   call void @foo() [ "deopt"() ]
80   %obj = load i64 addrspace(1)*, i64 addrspace(1)** %loc
81   call void @foo() [ "deopt"() ]
82   br label %merge
84 untaken:                                          ; preds = %entry
85 ; CHECK-LABEL: taken:
86 ; CHECK-NEXT: gc.statepoint
87 ; CHECK-NEXT: br label %merge
88 ; A base pointer must be live if it is needed at a later statepoint,
89 ; even if the base pointer is otherwise unused.
90   call void @foo() [ "deopt"() ]
91   br label %merge
93 merge:                                            ; preds = %untaken, %taken
94   %phi = phi i64 addrspace(1)* [ %obj, %taken ], [ null, %untaken ]
95   ret i64 addrspace(1)* %phi
98 define i64 addrspace(1)* @test4(i1 %cmp, i64 addrspace(1)* %obj) gc "statepoint-example" {
99 ; CHECK-LABEL: @test4
100 entry:
101 ; CHECK-LABEL: entry:
102 ; CHECK-NEXT:  %derived = getelementptr
103 ; CHECK-NEXT:  gc.statepoint
104 ; CHECK-NEXT:  %derived.relocated =
105 ; CHECK-NEXT:  bitcast 
106 ; CHECK-NEXT:  %obj.relocated =
107 ; CHECK-NEXT:  bitcast
108 ; CHECK-NEXT:  gc.statepoint
109 ; CHECK-NEXT:  %derived.relocated2 =
110 ; CHECK-NEXT:  bitcast 
112 ; Note: It's legal to relocate obj again, but not strictly needed
113 ; CHECK-NEXT:  %obj.relocated3 =
114 ; CHECK-NEXT:  bitcast
115 ; CHECK-NEXT:  ret i64 addrspace(1)* %derived.relocated2.casted
117 ; Make sure that a phi def visited during iteration is considered a kill.
118 ; Also, liveness after base pointer analysis can change based on new uses,
119 ; not just new defs.
120   %derived = getelementptr i64, i64 addrspace(1)* %obj, i64 8
121   call void @foo() [ "deopt"() ]
122   call void @foo() [ "deopt"() ]
123   ret i64 addrspace(1)* %derived
126 declare void @consume(...) readonly "gc-leaf-function"
128 define i64 addrspace(1)* @test5(i1 %cmp, i64 addrspace(1)* %obj) gc "statepoint-example" {
129 ; CHECK-LABEL: @test5
130 entry:
131   br i1 %cmp, label %taken, label %untaken
133 taken:                                            ; preds = %entry
134 ; CHECK-LABEL: taken:
135 ; CHECK-NEXT: gc.statepoint
136 ; CHECK-NEXT: %obj.relocated = call coldcc i8 addrspace(1)*
137 ; CHECK-NEXT: bitcast
138 ; CHECK-NEXT: br label %merge
139   call void @foo() [ "deopt"() ]
140   br label %merge
142 untaken:                                          ; preds = %entry
143 ; CHECK-LABEL: untaken:
144 ; CHECK-NEXT: br label %merge
145   br label %merge
147 merge:                                            ; preds = %untaken, %taken
148 ; CHECK-LABEL: merge:
149 ; CHECK-NEXT: %.0 = phi i64 addrspace(1)*
150 ; CHECK-NEXT: %obj2a = phi
151 ; CHECK-NEXT: @consume
152 ; CHECK-NEXT: br label %final
153   %obj2a = phi i64 addrspace(1)* [ %obj, %taken ], [ null, %untaken ]
154   call void (...) @consume(i64 addrspace(1)* %obj2a)
155   br label %final
157 final:                                            ; preds = %merge
158 ; CHECK-LABEL: final:
159 ; CHECK-NEXT: @consume
160 ; CHECK-NEXT: ret i64 addrspace(1)* %.0
161   call void (...) @consume(i64 addrspace(1)* %obj2a)
162   ret i64 addrspace(1)* %obj
165 declare void @foo()