[DAGCombiner] Add target hook function to decide folding (mul (add x, c1), c2)
[llvm-project.git] / llvm / test / Transforms / RewriteStatepointsForGC / constants.ll
blob7e493fe24081a2ff0f1b40c66997d53d60641c67
1 ; RUN: opt -S -rewrite-statepoints-for-gc < %s | FileCheck %s
2 ; RUN: opt -S -passes=rewrite-statepoints-for-gc < %s | FileCheck %s
4 target datalayout = "e-ni:1:6"
6 ; constants don't get relocated.
7 @G = addrspace(1) global i8 5
9 declare void @foo()
11 define i8 @test() gc "statepoint-example" {
12 ; CHECK-LABEL: @test
13 ; CHECK: gc.statepoint
14 ; CHECK-NEXT: load i8, i8 addrspace(1)* inttoptr (i64 15 to i8 addrspace(1)*)
15 ; Mostly just here to show reasonable code test can come from.  
16 entry:
17   call void @foo() [ "deopt"() ]
18   %res = load i8, i8 addrspace(1)* inttoptr (i64 15 to i8 addrspace(1)*)
19   ret i8 %res
22 define i8 @test2(i8 addrspace(1)* %p) gc "statepoint-example" {
23 ; CHECK-LABEL: @test2
24 ; CHECK: gc.statepoint
25 ; CHECK-NEXT: gc.relocate
26 ; CHECK-NEXT: icmp
27 ; Globals don't move and thus don't get relocated
28 entry:
29   call void @foo() [ "deopt"() ]
30   %cmp = icmp eq i8 addrspace(1)* %p, null
31   br i1 %cmp, label %taken, label %not_taken
33 taken:                                            ; preds = %not_taken, %entry
34   ret i8 0
36 not_taken:                                        ; preds = %entry
37   %cmp2 = icmp ne i8 addrspace(1)* %p, null
38   br i1 %cmp2, label %taken, label %dead
40 dead:                                             ; preds = %not_taken
41   %addr = getelementptr i8, i8 addrspace(1)* %p, i32 15
42   %res = load i8, i8 addrspace(1)* %addr
43   ret i8 %res
46 define i8 @test3(i1 %always_true) gc "statepoint-example" {
47 ; CHECK-LABEL: @test3
48 ; CHECK: gc.statepoint
49 ; CHECK-NEXT: load i8, i8 addrspace(1)* @G
50 entry:
51   call void @foo() [ "deopt"() ]
52   %res = load i8, i8 addrspace(1)* @G, align 1
53   ret i8 %res
56 ; Even for source languages without constant references, we can
57 ; see constants can show up along paths where the value is dead.
58 ; This is particular relevant when computing bases of PHIs.  
59 define i8 addrspace(1)* @test4(i8 addrspace(1)* %p) gc "statepoint-example" {
60 ; CHECK-LABEL: @test4
61 entry:
62   %is_null = icmp eq i8 addrspace(1)* %p, null
63   br i1 %is_null, label %split, label %join
65 split:
66   call void @foo()
67   %arg_value_addr.i = getelementptr inbounds i8, i8 addrspace(1)* %p, i64 8
68   %arg_value_addr_casted.i = bitcast i8 addrspace(1)* %arg_value_addr.i to i8 addrspace(1)* addrspace(1)*
69   br label %join
71 join:
72 ; CHECK-LABEL: join
73 ; CHECK: %addr2.base =
74   %addr2 = phi i8 addrspace(1)* addrspace(1)* [ %arg_value_addr_casted.i, %split ], [ inttoptr (i64 8 to i8 addrspace(1)* addrspace(1)*), %entry ]
75   ;; NOTE: This particular example can be jump-threaded, but in general,
76   ;; we can't, and have to deal with the resulting IR.
77   br i1 %is_null, label %early-exit, label %use
79 early-exit:
80   ret i8 addrspace(1)* null
82 use:
83 ; CHECK-LABEL: use:
84 ; CHECK: gc.statepoint
85 ; CHECK: gc.relocate
86   call void @foo()
87   %res = load i8 addrspace(1)*, i8 addrspace(1)* addrspace(1)* %addr2, align 1
88   ret i8 addrspace(1)* %res
91 ; Globals don't move and thus don't get relocated
92 define i8 addrspace(1)* @test5(i1 %always_true) gc "statepoint-example" {
93 ; CHECK-LABEL: @test5
94 ; CHECK: gc.statepoint
95 ; CHECK-NEXT: %res = extractelement <2 x i8 addrspace(1)*> <i8 addrspace(1)* @G, i8 addrspace(1)* @G>, i32 0
96 entry:
97   call void @foo()
98   %res = extractelement <2 x i8 addrspace(1)*> <i8 addrspace(1)* @G, i8 addrspace(1)* @G>, i32 0
99   ret i8 addrspace(1)* %res
102 define i8 addrspace(1)* @test6(i64 %arg) gc "statepoint-example" {
103 entry:
104   ; Don't fail any assertions and don't record null as a live value
105   ; CHECK-LABEL: test6
106   ; CHECK: gc.statepoint
107   ; CHECK-NOT: call {{.*}}gc.relocate
108   %load_addr = getelementptr i8, i8 addrspace(1)* null, i64 %arg
109   call void @foo() [ "deopt"() ]
110   ret i8 addrspace(1)* %load_addr
113 define i8 addrspace(1)* @test7(i64 %arg) gc "statepoint-example" {
114 entry:
115   ; Same as test7 but use regular constant instead of a null
116   ; CHECK-LABEL: test7
117   ; CHECK: gc.statepoint
118   ; CHECK-NOT: call {{.*}}gc.relocate
119   %load_addr = getelementptr i8, i8 addrspace(1)* inttoptr (i64 15 to i8 addrspace(1)*), i64 %arg
120   call void @foo() [ "deopt"() ]
121   ret i8 addrspace(1)* %load_addr
124 define i8 @test8(i8 addrspace(1)* %p) gc "statepoint-example" {
125 ; Checks that base( phi(gep null, oop) ) = phi(null, base(oop)) and that we
126 ; correctly relocate this value
127 ; CHECK-LABEL: @test8
128 entry:
129   %is_null = icmp eq i8 addrspace(1)* %p, null
130   br i1 %is_null, label %null.crit-edge, label %not-null
132 not-null:
133   %load_addr = getelementptr inbounds i8, i8 addrspace(1)* %p, i64 8
134   br label %join
136 null.crit-edge:
137   %load_addr.const = getelementptr inbounds i8, i8 addrspace(1)* null, i64 8
138   br label %join
140 join:
141   %addr = phi i8 addrspace(1)* [ %load_addr, %not-null ], [%load_addr.const, %null.crit-edge]
142   ; CHECK: %addr.base = phi i8 addrspace(1)*
143   ; CHECK-DAG: [ %p, %not-null ]
144   ; CHECK-DAG: [ null, %null.crit-edge ]
145   ; CHECK: gc.statepoint
146   call void @foo() [ "deopt"() ]
147   ; CHECK-DAG: call {{.*}}gc.relocate{{.*}}(%addr.base, %addr.base)
148   ; CHECK-DAG: call {{.*}}gc.relocate{{.*}}(%addr.base, %addr)
149   br i1 %is_null, label %early-exit, label %use
151 early-exit:
152   ret i8 0
154 use:
155   %res = load i8, i8 addrspace(1)* %addr, align 1
156   ret i8 %res
159 define i8 @test9(i8 addrspace(1)* %p) gc "statepoint-example" {
160 ; Checks that base( phi(inttoptr, oop) ) = phi(null, base(oop)) and that we
161 ; correctly relocate this value
162 ; CHECK-LABEL: @test9
163 entry:
164   %is_null = icmp eq i8 addrspace(1)* %p, null
165   br i1 %is_null, label %null.crit-edge, label %not-null
167 not-null:
168   %load_addr = getelementptr inbounds i8, i8 addrspace(1)* %p, i64 8
169   br label %join
171 null.crit-edge:
172   br label %join
174 join:
175   %addr = phi i8 addrspace(1)* [ %load_addr, %not-null ], [inttoptr (i64 8 to i8 addrspace(1)*), %null.crit-edge]
176   ; CHECK: %addr.base = phi i8 addrspace(1)*
177   ; CHECK-DAG: [ %p, %not-null ]
178   ; CHECK-DAG: [ null, %null.crit-edge ]
179   ; CHECK: gc.statepoint
180   call void @foo() [ "deopt"() ]
181   ; CHECK-DAG: call {{.*}}gc.relocate{{.*}}(%addr.base, %addr.base)
182   ; CHECK-DAG: call {{.*}}gc.relocate{{.*}}(%addr.base, %addr)
183   br i1 %is_null, label %early-exit, label %use
185 early-exit:
186   ret i8 0
188 use:
189   %res = load i8, i8 addrspace(1)* %addr, align 1
190   ret i8 %res
193 define i8 @test10(i8 addrspace(1)* %p) gc "statepoint-example" {
194 ; Checks that base( phi(const gep, oop) ) = phi(null, base(oop)) and that we
195 ; correctly relocate this value
196 ; CHECK-LABEL: @test10
197 entry:
198   %is_null = icmp eq i8 addrspace(1)* %p, null
199   br i1 %is_null, label %null.crit-edge, label %not-null
201 not-null:
202   %load_addr = getelementptr inbounds i8, i8 addrspace(1)* %p, i64 8
203   br label %join
205 null.crit-edge:
206   br label %join
208 join:
209   %addr = phi i8 addrspace(1)* [ %load_addr, %not-null ], [getelementptr (i8, i8 addrspace(1)* null, i64 8), %null.crit-edge]
210   ; CHECK: %addr.base = phi i8 addrspace(1)*
211   ; CHECK-DAG: [ %p, %not-null ]
212   ; CHECK-DAG: [ null, %null.crit-edge ]
213   ; CHECK: gc.statepoint
214   call void @foo() [ "deopt"() ]
215   ; CHECK-DAG: call {{.*}}gc.relocate{{.*}}(%addr.base, %addr.base)
216   ; CHECK-DAG: call {{.*}}gc.relocate{{.*}}(%addr.base, %addr)
217   br i1 %is_null, label %early-exit, label %use
219 early-exit:
220   ret i8 0
222 use:
223   %res = load i8, i8 addrspace(1)* %addr, align 1
224   ret i8 %res
227 define i32 addrspace(1)* @test11(i1 %c) gc "statepoint-example" {
228 ; CHECK-LABEL: @test11
229 ; Checks that base( select(const1, const2) ) == null and that we don't record
230 ; such value in the oop map
231 entry:
232   %val = select i1 %c, i32 addrspace(1)* inttoptr (i64 8 to i32 addrspace(1)*), i32 addrspace(1)* inttoptr (i64 15 to i32 addrspace(1)*)
233   ; CHECK: gc.statepoint
234   ; CHECK-NOT: call {{.*}}gc.relocate
235   call void @foo() [ "deopt"() ]
236   ret i32 addrspace(1)* %val
240 define <2 x i32 addrspace(1)*> @test12(i1 %c) gc "statepoint-example" {
241 ; CHECK-LABEL: @test12
242 ; Same as test11 but with vectors
243 entry:
244   %val = select i1 %c, <2 x i32 addrspace(1)*> <i32 addrspace(1)* inttoptr (i64 5 to i32 addrspace(1)*), 
245                                                 i32 addrspace(1)* inttoptr (i64 15 to i32 addrspace(1)*)>, 
246                        <2 x i32 addrspace(1)*> <i32 addrspace(1)* inttoptr (i64 30 to i32 addrspace(1)*), 
247                                                 i32 addrspace(1)* inttoptr (i64 60 to i32 addrspace(1)*)>
248   ; CHECK: gc.statepoint
249   ; CHECK-NOT: call {{.*}}gc.relocate
250   call void @foo() [ "deopt"() ]
251   ret <2 x i32 addrspace(1)*> %val
254 define <2 x i32 addrspace(1)*> @test13(i1 %c, <2 x i32 addrspace(1)*> %ptr) gc "statepoint-example" {
255 ; CHECK-LABEL: @test13
256 ; Similar to test8, test9 and test10 but with vectors
257 entry:
258   %val = select i1 %c, <2 x i32 addrspace(1)*> %ptr, 
259                        <2 x i32 addrspace(1)*> <i32 addrspace(1)* inttoptr (i64 30 to i32 addrspace(1)*), i32 addrspace(1)* inttoptr (i64 60 to i32 addrspace(1)*)>
260   ; CHECK: %val.base = select i1 %c, <2 x i32 addrspace(1)*> %ptr, <2 x i32 addrspace(1)*> zeroinitializer, !is_base_value !0
261   ; CHECK: gc.statepoint
262   call void @foo() [ "deopt"() ]
263   ; CHECK-DAG: call {{.*}}gc.relocate{{.*}}(%val.base, %val.base)
264   ; CHECK-DAG: call {{.*}}gc.relocate{{.*}}(%val.base, %val)
265   ret <2 x i32 addrspace(1)*> %val