157 lines · plain
1; A collection of liveness test cases to ensure we're reporting the2; correct live values at statepoints3; RUN: opt -passes=rewrite-statepoints-for-gc -spp-rematerialization-threshold=0 -S < %s | FileCheck %s4 5; Tests to make sure we consider %obj live in both the taken and untaken6; predeccessor of merge.7 8define ptr addrspace(1) @test1(i1 %cmp, ptr addrspace(1) %obj) gc "statepoint-example" {9; CHECK-LABEL: @test110entry:11 br i1 %cmp, label %taken, label %untaken12 13taken: ; preds = %entry14; CHECK-LABEL: taken:15; CHECK-NEXT: gc.statepoint16; CHECK-NEXT: %obj.relocated = call coldcc ptr addrspace(1)17; CHECK-NEXT: br label %merge18 call void @foo() [ "deopt"() ]19 br label %merge20 21untaken: ; preds = %entry22; CHECK-LABEL: untaken:23; CHECK-NEXT: gc.statepoint24; CHECK-NEXT: %obj.relocated2 = call coldcc ptr addrspace(1)25; CHECK-NEXT: br label %merge26 call void @foo() [ "deopt"() ]27 br label %merge28 29merge: ; preds = %untaken, %taken30; CHECK-LABEL: merge:31; CHECK-NEXT: %.0 = phi ptr addrspace(1) [ %obj.relocated, %taken ], [ %obj.relocated2, %untaken ]32; CHECK-NEXT: ret ptr addrspace(1) %.033; A local kill should not effect liveness in predecessor block34 ret ptr addrspace(1) %obj35}36 37define ptr addrspace(1) @test2(i1 %cmp, ptr %loc) gc "statepoint-example" {38; CHECK-LABEL: @test239entry:40; CHECK-LABEL: entry:41; CHECK-NEXT: gc.statepoint42; CHECK-NEXT: br43 call void @foo() [ "deopt"() ]44 br i1 %cmp, label %taken, label %untaken45 46taken: ; preds = %entry47; CHECK-LABEL: taken:48; CHECK-NEXT: %obj = load49; CHECK-NEXT: gc.statepoint50; CHECK-NEXT: gc.relocate51; CHECK-NEXT: ret ptr addrspace(1) %obj.relocated52; A local kill should effect values live from a successor phi. Also, we53; should only propagate liveness from a phi to the appropriate predecessors.54 %obj = load ptr addrspace(1), ptr %loc55 call void @foo() [ "deopt"() ]56 ret ptr addrspace(1) %obj57 58untaken: ; preds = %entry59 ret ptr addrspace(1) null60}61 62define ptr addrspace(1) @test3(i1 %cmp, ptr %loc) gc "statepoint-example" {63; CHECK-LABEL: @test364entry:65 br i1 %cmp, label %taken, label %untaken66 67taken: ; preds = %entry68; CHECK-LABEL: taken:69; CHECK-NEXT: gc.statepoint70; CHECK-NEXT: %obj = load71; CHECK-NEXT: gc.statepoint72; CHECK-NEXT: %obj.relocated = call coldcc ptr addrspace(1)73; CHECK-NEXT: br label %merge74 call void @foo() [ "deopt"() ]75 %obj = load ptr addrspace(1), ptr %loc76 call void @foo() [ "deopt"() ]77 br label %merge78 79untaken: ; preds = %entry80; CHECK-LABEL: taken:81; CHECK-NEXT: gc.statepoint82; CHECK-NEXT: br label %merge83; A base pointer must be live if it is needed at a later statepoint,84; even if the base pointer is otherwise unused.85 call void @foo() [ "deopt"() ]86 br label %merge87 88merge: ; preds = %untaken, %taken89 %phi = phi ptr addrspace(1) [ %obj, %taken ], [ null, %untaken ]90 ret ptr addrspace(1) %phi91}92 93define ptr addrspace(1) @test4(i1 %cmp, ptr addrspace(1) %obj) gc "statepoint-example" {94; CHECK-LABEL: @test495entry:96; CHECK-LABEL: entry:97; CHECK-NEXT: %derived = getelementptr98; CHECK-NEXT: gc.statepoint99; CHECK-NEXT: %derived.relocated =100; CHECK-NEXT: %obj.relocated =101; CHECK-NEXT: gc.statepoint102; CHECK-NEXT: %derived.relocated2 =103 104; Note: It's legal to relocate obj again, but not strictly needed105; CHECK-NEXT: %obj.relocated3 =106; CHECK-NEXT: ret ptr addrspace(1) %derived.relocated2107;108; Make sure that a phi def visited during iteration is considered a kill.109; Also, liveness after base pointer analysis can change based on new uses,110; not just new defs.111 %derived = getelementptr i64, ptr addrspace(1) %obj, i64 8112 call void @foo() [ "deopt"() ]113 call void @foo() [ "deopt"() ]114 ret ptr addrspace(1) %derived115}116 117declare void @consume(...) readonly "gc-leaf-function"118 119define ptr addrspace(1) @test5(i1 %cmp, ptr addrspace(1) %obj) gc "statepoint-example" {120; CHECK-LABEL: @test5121entry:122 br i1 %cmp, label %taken, label %untaken123 124taken: ; preds = %entry125; CHECK-LABEL: taken:126; CHECK-NEXT: gc.statepoint127; CHECK-NEXT: %obj.relocated = call coldcc ptr addrspace(1)128; CHECK-NEXT: br label %merge129 call void @foo() [ "deopt"() ]130 br label %merge131 132untaken: ; preds = %entry133; CHECK-LABEL: untaken:134; CHECK-NEXT: br label %merge135 br label %merge136 137merge: ; preds = %untaken, %taken138; CHECK-LABEL: merge:139; CHECK-NEXT: %.0 = phi ptr addrspace(1)140; CHECK-NEXT: %obj2a = phi141; CHECK-NEXT: @consume142; CHECK-NEXT: br label %final143 %obj2a = phi ptr addrspace(1) [ %obj, %taken ], [ null, %untaken ]144 call void (...) @consume(ptr addrspace(1) %obj2a)145 br label %final146 147final: ; preds = %merge148; CHECK-LABEL: final:149; CHECK-NEXT: @consume150; CHECK-NEXT: ret ptr addrspace(1) %.0151 call void (...) @consume(ptr addrspace(1) %obj2a)152 ret ptr addrspace(1) %obj153}154 155declare void @foo()156 157