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 5 6; Tests to make sure we consider %obj live in both the taken and untaken 7; predeccessor of merge. 8define i64 addrspace(1)* @test1(i1 %cmp, i64 addrspace(1)* %obj) gc "statepoint-example" { 9; CHECK-LABEL: @test1 10entry: 11 br i1 %cmp, label %taken, label %untaken 12 13taken: 14; CHECK-LABEL: taken: 15; CHECK-NEXT: gc.statepoint 16; CHECK-NEXT: %obj.relocated = call coldcc i8 addrspace(1)* 17; CHECK-NEXT: bitcast 18; CHECK-NEXT: br label %merge 19 call i32 (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @foo, i32 0, i32 0, i32 0, i32 0) 20 br label %merge 21 22untaken: 23; CHECK-LABEL: untaken: 24; CHECK-NEXT: gc.statepoint 25; CHECK-NEXT: %obj.relocated1 = call coldcc i8 addrspace(1)* 26; CHECK-NEXT: bitcast 27; CHECK-NEXT: br label %merge 28 call i32 (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @foo, i32 0, i32 0, i32 0, i32 0) 29 br label %merge 30 31merge: 32; CHECK-LABEL: merge: 33; CHECK-NEXT: %.0 = phi i64 addrspace(1)* [ %obj.relocated.casted, %taken ], [ %obj.relocated1.casted, %untaken ] 34; CHECK-NEXT: ret i64 addrspace(1)* %.0 35 ret i64 addrspace(1)* %obj 36} 37 38; A local kill should not effect liveness in predecessor block 39define i64 addrspace(1)* @test2(i1 %cmp, i64 addrspace(1)** %loc) gc "statepoint-example" { 40; CHECK-LABEL: @test2 41entry: 42; CHECK-LABEL: entry: 43; CHECK-NEXT: gc.statepoint 44; CHECK-NEXT: br 45 call i32 (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @foo, i32 0, i32 0, i32 0, i32 0) 46 br i1 %cmp, label %taken, label %untaken 47 48taken: 49; CHECK-LABEL: taken: 50; CHECK-NEXT: %obj = load 51; CHECK-NEXT: gc.statepoint 52; CHECK-NEXT: gc.relocate 53; CHECK-NEXT: bitcast 54; CHECK-NEXT: ret i64 addrspace(1)* %obj.relocated.casted 55 56 %obj = load i64 addrspace(1)*, i64 addrspace(1)** %loc 57 call i32 (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @foo, i32 0, i32 0, i32 0, i32 0) 58 ret i64 addrspace(1)* %obj 59 60untaken: 61 ret i64 addrspace(1)* null 62} 63 64; A local kill should effect values live from a successor phi. Also, we 65; should only propagate liveness from a phi to the appropriate predecessors. 66define i64 addrspace(1)* @test3(i1 %cmp, i64 addrspace(1)** %loc) gc "statepoint-example" { 67; CHECK-LABEL: @test3 68entry: 69 br i1 %cmp, label %taken, label %untaken 70 71taken: 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 i32 (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @foo, i32 0, i32 0, i32 0, i32 0) 80 %obj = load i64 addrspace(1)*, i64 addrspace(1)** %loc 81 call i32 (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @foo, i32 0, i32 0, i32 0, i32 0) 82 br label %merge 83 84untaken: 85; CHECK-LABEL: taken: 86; CHECK-NEXT: gc.statepoint 87; CHECK-NEXT: br label %merge 88 call i32 (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @foo, i32 0, i32 0, i32 0, i32 0) 89 br label %merge 90 91merge: 92 %phi = phi i64 addrspace(1)* [ %obj, %taken ], [ null, %untaken ] 93 ret i64 addrspace(1)* %phi 94} 95 96; A base pointer must be live if it is needed at a later statepoint, 97; even if the base pointer is otherwise unused. 98define i64 addrspace(1)* @test4(i1 %cmp, i64 addrspace(1)* %obj) gc "statepoint-example" { 99; CHECK-LABEL: @test4 100entry: 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.relocated1 = 110; CHECK-NEXT: bitcast 111; Note: It's legal to relocate obj again, but not strictly needed 112; CHECK-NEXT: %obj.relocated2 = 113; CHECK-NEXT: bitcast 114; CHECK-NEXT: ret i64 addrspace(1)* %derived.relocated1.casted 115; 116 %derived = getelementptr i64, i64 addrspace(1)* %obj, i64 8 117 call i32 (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @foo, i32 0, i32 0, i32 0, i32 0) 118 119 call i32 (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @foo, i32 0, i32 0, i32 0, i32 0) 120 ret i64 addrspace(1)* %derived 121} 122 123declare void @consume(...) readonly 124 125; Make sure that a phi def visited during iteration is considered a kill. 126; Also, liveness after base pointer analysis can change based on new uses, 127; not just new defs. 128define i64 addrspace(1)* @test5(i1 %cmp, i64 addrspace(1)* %obj) gc "statepoint-example" { 129; CHECK-LABEL: @test5 130entry: 131 br i1 %cmp, label %taken, label %untaken 132 133taken: 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 i32 (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @foo, i32 0, i32 0, i32 0, i32 0) 140 br label %merge 141 142untaken: 143; CHECK-LABEL: untaken: 144; CHECK-NEXT: br label %merge 145 br label %merge 146 147merge: 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 156final: 157; CHECK-LABEL: final: 158; CHECK-NEXT: @consume 159; CHECK-NEXT: ret i64 addrspace(1)* %.0 160 call void (...) @consume(i64 addrspace(1)* %obj2a) 161 ret i64 addrspace(1)* %obj 162} 163 164declare void @foo() 165 166declare i32 @llvm.experimental.gc.statepoint.p0f_isVoidf(i64, i32, void ()*, i32, i32, ...) 167