1; RUN: opt -S %s -verify | FileCheck %s 2 3declare void @use(...) 4declare i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token, i32, i32) 5declare i64 addrspace(1)* @llvm.experimental.gc.relocate.p1i64(token, i32, i32) 6declare token @llvm.experimental.gc.statepoint.p0f_isVoidf(i64, i32, void ()*, i32, i32, ...) 7declare token @llvm.experimental.gc.statepoint.p0f_isVoidp0s_structsf(i64, i32, void (%struct*)*, i32, i32, ...) 8declare i32 @"personality_function"() 9 10;; Basic usage 11define i64 addrspace(1)* @test1(i8 addrspace(1)* %arg) gc "statepoint-example" { 12entry: 13 %cast = bitcast i8 addrspace(1)* %arg to i64 addrspace(1)* 14 %safepoint_token = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* undef, i32 0, i32 0, i32 0, i32 0) ["gc-live" (i8 addrspace(1)* %arg, i64 addrspace(1)* %cast, i8 addrspace(1)* %arg, i8 addrspace(1)* %arg), "deopt" (i32 0, i32 0, i32 0, i32 10, i32 0)] 15 %reloc = call i64 addrspace(1)* @llvm.experimental.gc.relocate.p1i64(token %safepoint_token, i32 0, i32 1) 16 ;; It is perfectly legal to relocate the same value multiple times... 17 %reloc2 = call i64 addrspace(1)* @llvm.experimental.gc.relocate.p1i64(token %safepoint_token, i32 0, i32 1) 18 %reloc3 = call i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %safepoint_token, i32 1, i32 0) 19 ret i64 addrspace(1)* %reloc 20; CHECK-LABEL: test1 21; CHECK: statepoint 22; CHECK: gc.relocate 23; CHECK: gc.relocate 24; CHECK: gc.relocate 25; CHECK: ret i64 addrspace(1)* %reloc 26} 27 28; This test catches two cases where the verifier was too strict: 29; 1) A base doesn't need to be relocated if it's never used again 30; 2) A value can be replaced by one which is known equal. This 31; means a potentially derived pointer can be known base and that 32; we can't check that derived pointer are never bases. 33define void @test2(i8 addrspace(1)* %arg, i64 addrspace(1)* %arg2) gc "statepoint-example" { 34entry: 35 %cast = bitcast i8 addrspace(1)* %arg to i64 addrspace(1)* 36 %c = icmp eq i64 addrspace(1)* %cast, %arg2 37 br i1 %c, label %equal, label %notequal 38 39notequal: 40 ret void 41 42equal: 43 %safepoint_token = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* undef, i32 0, i32 0, i32 0, i32 0) ["gc-live" (i8 addrspace(1)* %arg, i64 addrspace(1)* %cast, i8 addrspace(1)* %arg, i8 addrspace(1)* %arg), "deopt" (i32 0, i32 0, i32 0, i32 10, i32 0)] 44 %reloc = call i64 addrspace(1)* @llvm.experimental.gc.relocate.p1i64(token %safepoint_token, i32 0, i32 0) 45 call void undef(i64 addrspace(1)* %reloc) 46 ret void 47; CHECK-LABEL: test2 48; CHECK-LABEL: equal 49; CHECK: statepoint 50; CHECK-NEXT: %reloc = call 51; CHECK-NEXT: call 52; CHECK-NEXT: ret voi 53} 54 55; Basic test for invoke statepoints 56define i8 addrspace(1)* @test3(i8 addrspace(1)* %obj, i8 addrspace(1)* %obj1) gc "statepoint-example" personality i32 ()* @"personality_function" { 57; CHECK-LABEL: test3 58entry: 59 ; CHECK-LABEL: entry 60 ; CHECK: statepoint 61 %0 = invoke token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* undef, i32 0, i32 0, i32 0, i32 0) ["gc-live" (i8 addrspace(1)* %obj, i8 addrspace(1)* %obj1), "deopt" (i32 0, i32 -1, i32 0, i32 0, i32 0)] 62 to label %normal_dest unwind label %exceptional_return 63 64normal_dest: 65 ; CHECK-LABEL: normal_dest: 66 ; CHECK: gc.relocate 67 ; CHECK: gc.relocate 68 ; CHECK: ret 69 %obj.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %0, i32 0, i32 0) 70 %obj1.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %0, i32 1, i32 1) 71 ret i8 addrspace(1)* %obj.relocated 72 73exceptional_return: 74 ; CHECK-LABEL: exceptional_return 75 ; CHECK: gc.relocate 76 ; CHECK: gc.relocate 77 %landing_pad = landingpad token 78 cleanup 79 %obj.relocated1 = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %landing_pad, i32 0, i32 0) 80 %obj1.relocated1 = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %landing_pad, i32 1, i32 1) 81 ret i8 addrspace(1)* %obj1.relocated1 82} 83 84; Test for statepoint with sret attribute. 85; This should be allowed as long as the wrapped function is not vararg. 86%struct = type { i64, i64, i64 } 87 88declare void @fn_sret(%struct* sret(%struct)) 89 90define void @test_sret() gc "statepoint-example" { 91 %x = alloca %struct 92 %statepoint_token = call token (i64, i32, void (%struct*)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidp0s_structsf(i64 0, i32 0, void (%struct*)* @fn_sret, i32 1, i32 0, %struct* sret(%struct) %x, i32 0, i32 0) 93 ret void 94 ; CHECK-LABEL: test_sret 95 ; CHECK: alloca 96 ; CHECK: statepoint 97 ; CHECK-SAME: sret 98 ; CHECK: ret 99} 100