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 -S < %s | FileCheck %s 4 5 6 ; Tests to make sure we consider %obj live in both the taken and untaken 7 ; predeccessor of merge. 8 define i64 addrspace(1)* @test1(i1 %cmp, i64 addrspace(1)* %obj) gc "statepoint-example" { 9 ; CHECK-LABEL: @test1 10 entry: 11 br i1 %cmp, label %taken, label %untaken 12 13 taken: 14 ; CHECK-LABEL: taken: 15 ; CHECK-NEXT: gc.statepoint 16 ; CHECK-NEXT: %obj.relocated = call coldcc i64 addrspace(1)* 17 ; CHECK-NEXT: br label %merge 18 call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0) 19 br label %merge 20 21 untaken: 22 ; CHECK-LABEL: untaken: 23 ; CHECK-NEXT: gc.statepoint 24 ; CHECK-NEXT: %obj.relocated1 = call coldcc i64 addrspace(1)* 25 ; CHECK-NEXT: br label %merge 26 call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0) 27 br label %merge 28 29 merge: 30 ; CHECK-LABEL: merge: 31 ; CHECK-NEXT: %.0 = phi i64 addrspace(1)* [ %obj.relocated, %taken ], [ %obj.relocated1, %untaken ] 32 ; CHECK-NEXT: ret i64 addrspace(1)* %.0 33 ret i64 addrspace(1)* %obj 34 } 35 36 ; A local kill should not effect liveness in predecessor block 37 define i64 addrspace(1)* @test2(i1 %cmp, i64 addrspace(1)** %loc) gc "statepoint-example" { 38 ; CHECK-LABEL: @test2 39 entry: 40 ; CHECK-LABEL: entry: 41 ; CHECK-NEXT: gc.statepoint 42 ; CHECK-NEXT: br 43 call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0) 44 br i1 %cmp, label %taken, label %untaken 45 46 taken: 47 ; CHECK-LABEL: taken: 48 ; CHECK-NEXT: %obj = load 49 ; CHECK-NEXT: gc.statepoint 50 ; CHECK-NEXT: gc.relocate 51 ; CHECK-NEXT: ret i64 addrspace(1)* %obj.relocated 52 53 %obj = load i64 addrspace(1)*, i64 addrspace(1)** %loc 54 call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0) 55 ret i64 addrspace(1)* %obj 56 57 untaken: 58 ret i64 addrspace(1)* null 59 } 60 61 ; A local kill should effect values live from a successor phi. Also, we 62 ; should only propagate liveness from a phi to the appropriate predecessors. 63 define i64 addrspace(1)* @test3(i1 %cmp, i64 addrspace(1)** %loc) gc "statepoint-example" { 64 ; CHECK-LABEL: @test3 65 entry: 66 br i1 %cmp, label %taken, label %untaken 67 68 taken: 69 ; CHECK-LABEL: taken: 70 ; CHECK-NEXT: gc.statepoint 71 ; CHECK-NEXT: %obj = load 72 ; CHECK-NEXT: gc.statepoint 73 ; CHECK-NEXT: %obj.relocated = call coldcc i64 addrspace(1)* 74 ; CHECK-NEXT: br label %merge 75 call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0) 76 %obj = load i64 addrspace(1)*, i64 addrspace(1)** %loc 77 call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0) 78 br label %merge 79 80 untaken: 81 ; CHECK-LABEL: taken: 82 ; CHECK-NEXT: gc.statepoint 83 ; CHECK-NEXT: br label %merge 84 call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0) 85 br label %merge 86 87 merge: 88 %phi = phi i64 addrspace(1)* [ %obj, %taken ], [ null, %untaken ] 89 ret i64 addrspace(1)* %phi 90 } 91 92 ; A base pointer must be live if it is needed at a later statepoint, 93 ; even if the base pointer is otherwise unused. 94 define i64 addrspace(1)* @test4(i1 %cmp, i64 addrspace(1)* %obj) gc "statepoint-example" { 95 ; CHECK-LABEL: @test4 96 entry: 97 ; CHECK-LABEL: entry: 98 ; CHECK-NEXT: %derived = getelementptr 99 ; CHECK-NEXT: gc.statepoint 100 ; CHECK-NEXT: %derived.relocated = 101 ; CHECK-NEXT: %obj.relocated = 102 ; CHECK-NEXT: gc.statepoint 103 ; CHECK-NEXT: %derived.relocated1 = 104 ; Note: It's legal to relocate obj again, but not strictly needed 105 ; CHECK-NEXT: %obj.relocated2 = 106 ; CHECK-NEXT: ret i64 addrspace(1)* %derived.relocated1 107 ; 108 %derived = getelementptr i64, i64 addrspace(1)* %obj, i64 8 109 call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0) 110 111 call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0) 112 ret i64 addrspace(1)* %derived 113 } 114 115 declare void @consume(...) readonly 116 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 define i64 addrspace(1)* @test5(i1 %cmp, i64 addrspace(1)* %obj) gc "statepoint-example" { 121 ; CHECK-LABEL: @test5 122 entry: 123 br i1 %cmp, label %taken, label %untaken 124 125 taken: 126 ; CHECK-LABEL: taken: 127 ; CHECK-NEXT: gc.statepoint 128 ; CHECK-NEXT: %obj.relocated = call coldcc i64 addrspace(1)* 129 ; CHECK-NEXT: br label %merge 130 call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0) 131 br label %merge 132 133 untaken: 134 ; CHECK-LABEL: untaken: 135 ; CHECK-NEXT: br label %merge 136 br label %merge 137 138 merge: 139 ; CHECK-LABEL: merge: 140 ; CHECK-NEXT: %.0 = phi i64 addrspace(1)* 141 ; CHECK-NEXT: %obj2a = phi 142 ; CHECK-NEXT: @consume 143 ; CHECK-NEXT: br label %final 144 %obj2a = phi i64 addrspace(1)* [ %obj, %taken ], [null, %untaken] 145 call void (...) @consume(i64 addrspace(1)* %obj2a) 146 br label %final 147 final: 148 ; CHECK-LABEL: final: 149 ; CHECK-NEXT: @consume 150 ; CHECK-NEXT: ret i64 addrspace(1)* %.0 151 call void (...) @consume(i64 addrspace(1)* %obj2a) 152 ret i64 addrspace(1)* %obj 153 } 154 155 declare void @foo() 156 157 declare i32 @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()*, i32, i32, ...) 158 159