Philip Reames | 204e21b | 2014-12-01 21:18:12 +0000 | [diff] [blame] | 1 | ; RUN: opt -S %s -verify | FileCheck %s |
| 2 | |
| 3 | declare void @use(...) |
Chen Li | 955318d | 2015-12-26 07:54:32 +0000 | [diff] [blame] | 4 | declare i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token, i32, i32) |
| 5 | declare i64 addrspace(1)* @llvm.experimental.gc.relocate.p1i64(token, i32, i32) |
| 6 | declare token @llvm.experimental.gc.statepoint.p0f_isVoidf(i64, i32, void ()*, i32, i32, ...) |
Than McIntosh | afce114 | 2018-11-16 14:28:05 +0000 | [diff] [blame] | 7 | declare token @llvm.experimental.gc.statepoint.p0f_isVoidp0s_structsf(i64, i32, void (%struct*)*, i32, i32, ...) |
Philip Reames | 24173bd | 2015-01-30 23:18:42 +0000 | [diff] [blame] | 8 | declare i32 @"personality_function"() |
Philip Reames | 204e21b | 2014-12-01 21:18:12 +0000 | [diff] [blame] | 9 | |
| 10 | ;; Basic usage |
Igor Laevsky | 05be69f | 2015-02-19 11:28:47 +0000 | [diff] [blame] | 11 | define i64 addrspace(1)* @test1(i8 addrspace(1)* %arg) gc "statepoint-example" { |
Philip Reames | 204e21b | 2014-12-01 21:18:12 +0000 | [diff] [blame] | 12 | entry: |
| 13 | %cast = bitcast i8 addrspace(1)* %arg to i64 addrspace(1)* |
Chen Li | 955318d | 2015-12-26 07:54:32 +0000 | [diff] [blame] | 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 5, i32 0, i32 0, i32 0, i32 10, i32 0, i8 addrspace(1)* %arg, i64 addrspace(1)* %cast, i8 addrspace(1)* %arg, i8 addrspace(1)* %arg) |
| 15 | %reloc = call i64 addrspace(1)* @llvm.experimental.gc.relocate.p1i64(token %safepoint_token, i32 12, i32 13) |
Philip Reames | 204e21b | 2014-12-01 21:18:12 +0000 | [diff] [blame] | 16 | ;; It is perfectly legal to relocate the same value multiple times... |
Chen Li | 955318d | 2015-12-26 07:54:32 +0000 | [diff] [blame] | 17 | %reloc2 = call i64 addrspace(1)* @llvm.experimental.gc.relocate.p1i64(token %safepoint_token, i32 12, i32 13) |
| 18 | %reloc3 = call i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %safepoint_token, i32 13, i32 12) |
Philip Reames | 24173bd | 2015-01-30 23:18:42 +0000 | [diff] [blame] | 19 | ret i64 addrspace(1)* %reloc |
Philip Reames | 204e21b | 2014-12-01 21:18:12 +0000 | [diff] [blame] | 20 | ; CHECK-LABEL: test1 |
| 21 | ; CHECK: statepoint |
| 22 | ; CHECK: gc.relocate |
| 23 | ; CHECK: gc.relocate |
| 24 | ; CHECK: gc.relocate |
Philip Reames | 24173bd | 2015-01-30 23:18:42 +0000 | [diff] [blame] | 25 | ; CHECK: ret i64 addrspace(1)* %reloc |
Philip Reames | 204e21b | 2014-12-01 21:18:12 +0000 | [diff] [blame] | 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. |
Igor Laevsky | 05be69f | 2015-02-19 11:28:47 +0000 | [diff] [blame] | 33 | define void @test2(i8 addrspace(1)* %arg, i64 addrspace(1)* %arg2) gc "statepoint-example" { |
Philip Reames | 204e21b | 2014-12-01 21:18:12 +0000 | [diff] [blame] | 34 | entry: |
| 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 | |
| 39 | notequal: |
| 40 | ret void |
| 41 | |
| 42 | equal: |
Chen Li | 955318d | 2015-12-26 07:54:32 +0000 | [diff] [blame] | 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 5, i32 0, i32 0, i32 0, i32 10, i32 0, i8 addrspace(1)* %arg, i64 addrspace(1)* %cast, i8 addrspace(1)* %arg, i8 addrspace(1)* %arg) |
| 44 | %reloc = call i64 addrspace(1)* @llvm.experimental.gc.relocate.p1i64(token %safepoint_token, i32 12, i32 13) |
Philip Reames | 24173bd | 2015-01-30 23:18:42 +0000 | [diff] [blame] | 45 | call void undef(i64 addrspace(1)* %reloc) |
Philip Reames | 204e21b | 2014-12-01 21:18:12 +0000 | [diff] [blame] | 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 | } |
Igor Laevsky | 5d27960 | 2015-02-18 09:11:50 +0000 | [diff] [blame] | 54 | |
Igor Laevsky | 05be69f | 2015-02-19 11:28:47 +0000 | [diff] [blame] | 55 | ; Basic test for invoke statepoints |
David Majnemer | cc714e2 | 2015-06-17 20:52:32 +0000 | [diff] [blame] | 56 | define i8 addrspace(1)* @test3(i8 addrspace(1)* %obj, i8 addrspace(1)* %obj1) gc "statepoint-example" personality i32 ()* @"personality_function" { |
Igor Laevsky | 05be69f | 2015-02-19 11:28:47 +0000 | [diff] [blame] | 57 | ; CHECK-LABEL: test3 |
| 58 | entry: |
| 59 | ; CHECK-LABEL: entry |
| 60 | ; CHECK: statepoint |
Chen Li | 955318d | 2015-12-26 07:54:32 +0000 | [diff] [blame] | 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 5, i32 0, i32 -1, i32 0, i32 0, i32 0, i8 addrspace(1)* %obj, i8 addrspace(1)* %obj1) |
Igor Laevsky | 05be69f | 2015-02-19 11:28:47 +0000 | [diff] [blame] | 62 | to label %normal_dest unwind label %exceptional_return |
| 63 | |
| 64 | normal_dest: |
| 65 | ; CHECK-LABEL: normal_dest: |
| 66 | ; CHECK: gc.relocate |
| 67 | ; CHECK: gc.relocate |
| 68 | ; CHECK: ret |
Chen Li | 955318d | 2015-12-26 07:54:32 +0000 | [diff] [blame] | 69 | %obj.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %0, i32 12, i32 12) |
| 70 | %obj1.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %0, i32 12, i32 12) |
Igor Laevsky | 05be69f | 2015-02-19 11:28:47 +0000 | [diff] [blame] | 71 | ret i8 addrspace(1)* %obj.relocated |
| 72 | |
| 73 | exceptional_return: |
| 74 | ; CHECK-LABEL: exceptional_return |
| 75 | ; CHECK: gc.relocate |
| 76 | ; CHECK: gc.relocate |
Chen Li | 955318d | 2015-12-26 07:54:32 +0000 | [diff] [blame] | 77 | %landing_pad = landingpad token |
Igor Laevsky | 05be69f | 2015-02-19 11:28:47 +0000 | [diff] [blame] | 78 | cleanup |
Chen Li | 955318d | 2015-12-26 07:54:32 +0000 | [diff] [blame] | 79 | %obj.relocated1 = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %landing_pad, i32 12, i32 12) |
| 80 | %obj1.relocated1 = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %landing_pad, i32 12, i32 12) |
Igor Laevsky | 05be69f | 2015-02-19 11:28:47 +0000 | [diff] [blame] | 81 | ret i8 addrspace(1)* %obj1.relocated1 |
| 82 | } |
Than McIntosh | afce114 | 2018-11-16 14:28:05 +0000 | [diff] [blame] | 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 | |
| 88 | declare void @fn_sret(%struct* sret) |
| 89 | |
| 90 | define 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 %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 | } |