[RewriteStatepointsForGC] Add additional tests around relocation
[oota-llvm.git] / test / Transforms / RewriteStatepointsForGC / relocation.ll
1 ; RUN: opt %s -rewrite-statepoints-for-gc -S 2>&1 | FileCheck %s
2
3
4 declare void @foo()
5
6 define i64 addrspace(1)* @test1(i64 addrspace(1)* %obj, i64 addrspace(1)* %obj2, i1 %condition) gc "statepoint-example" {
7 entry:
8 ; CHECK-LABEL: @test1
9 ; CHECK-DAG: %obj.relocated
10 ; CHECK-DAG: %obj2.relocated
11   %safepoint_token = call i32 (void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0)
12   br label %joint
13
14 joint:
15 ; CHECK-LABEL: joint:
16 ; CHECK: %phi1 = phi i64 addrspace(1)* [ %obj.relocated, %entry ], [ %obj3, %joint2 ]
17   %phi1 = phi i64 addrspace(1)* [ %obj, %entry ], [ %obj3, %joint2 ]
18   br i1 %condition, label %use, label %joint2
19
20 use:
21   br label %joint2
22
23 joint2:
24 ; CHECK-LABEL: joint2:
25 ; CHECK: %phi2 = phi i64 addrspace(1)* [ %obj.relocated, %use ], [ %obj2.relocated, %joint ]
26 ; CHECK: %obj3 = getelementptr i64, i64 addrspace(1)* %obj2.relocated, i32 1
27   %phi2 = phi i64 addrspace(1)* [ %obj, %use ], [ %obj2, %joint ]
28   %obj3 = getelementptr i64, i64 addrspace(1)* %obj2, i32 1
29   br label %joint
30 }
31
32 declare i64 addrspace(1)* @generate_obj()
33
34 declare void @consume_obj(i64 addrspace(1)*)
35
36 declare i1 @rt()
37
38 define void @test2() gc "statepoint-example" {
39 ; CHECK-LABEL: @test2
40 entry:
41   %obj_init = call i64 addrspace(1)* @generate_obj()
42   %obj = getelementptr i64, i64 addrspace(1)* %obj_init, i32 42
43   br label %loop
44
45 loop:
46 ; CHECK: loop:
47 ; CHECK-DAG: [ %obj_init.relocated, %loop.backedge ]
48 ; CHECK-DAG: [ %obj_init, %entry ]
49 ; CHECK-DAG: [ %obj.relocated, %loop.backedge ]
50 ; CHECK-DAG: [ %obj, %entry ]
51   %index = phi i32 [ 0, %entry ], [ %index.inc, %loop.backedge ]
52 ; CHECK-NOT: %location = getelementptr i64, i64 addrspace(1)* %obj, i32 %index
53   %location = getelementptr i64, i64 addrspace(1)* %obj, i32 %index
54   call void @consume_obj(i64 addrspace(1)* %location)
55   %index.inc = add i32 %index, 1
56   %condition = call i1 @rt()
57   br i1 %condition, label %loop_x, label %loop_y
58
59 loop_x:
60   br label %loop.backedge
61
62 loop.backedge:
63   %safepoint_token = call i32 (void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 0)
64   br label %loop
65
66 loop_y:
67   br label %loop.backedge
68 }
69
70 declare void @some_call(i8 addrspace(1)*)
71
72 define void @relocate_merge(i1 %cnd, i8 addrspace(1)* %arg) gc "statepoint-example" {
73 ; CHECK-LABEL: @relocate_merge
74 bci_0:
75   br i1 %cnd, label %if_branch, label %else_branch
76
77 if_branch:
78 ; CHECK-LABEL: if_branch:
79 ; CHECK: gc.statepoint
80 ; CHECK: gc.relocate
81   %safepoint_token = call i32 (void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0)
82   br label %join
83
84 else_branch:
85 ; CHECK-LABEL: else_branch:
86 ; CHECK: gc.statepoint
87 ; CHECK: gc.relocate
88   %safepoint_token1 = call i32 (void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0)
89   br label %join
90
91 join:
92 ; We need to end up with a single relocation phi updated from both paths 
93 ; CHECK-LABEL: join:
94 ; CHECK: phi i8 addrspace(1)*
95 ; CHECK-DAG: [ %arg.relocated, %if_branch ]
96 ; CHECK-DAG: [ %arg.relocated4, %else_branch ]
97 ; CHECK-NOT: phi
98   call void (i8 addrspace(1)*)* @some_call(i8 addrspace(1)* %arg)
99   ret void
100 }
101
102 ; Make sure a use in a statepoint gets properly relocated at a previous one.  
103 ; This is basically just making sure that statepoints aren't accidentally 
104 ; treated specially.
105 define void @test3(i64 addrspace(1)* %obj) gc "statepoint-example" {
106 entry:
107 ; CHECK-LABEL: @test3
108 ; CHECK: gc.statepoint
109 ; CHECK-NEXT: gc.relocate
110 ; CHECK-NEXT: gc.statepoint
111   %safepoint_token = call i32 (void (i64)*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidi64f(void (i64)* undef, i32 1, i32 0, i64 undef, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
112   %safepoint_token1 = call i32 (i32 (i64 addrspace(1)*)*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_i32p1i64f(i32 (i64 addrspace(1)*)* undef, i32 1, i32 0, i64 addrspace(1)* %obj, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
113   ret void
114 }
115
116 declare i32 @llvm.experimental.gc.statepoint.p0f_isVoidi64f(void (i64)*, i32, i32, ...)
117
118 declare i32 @llvm.experimental.gc.statepoint.p0f_i32p1i64f(i32 (i64 addrspace(1)*)*, i32, i32, ...)
119
120
121 declare void @do_safepoint()
122
123 declare i32 @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()*, i32, i32, ...)