1 ; RUN: opt -safepoint-ir-verifier-print-only -verify-safepoint-ir -S %s 2>&1 | FileCheck %s 2 3 define i8 addrspace(1)* @test.not.ok.0(i8 addrspace(1)* %arg) gc "statepoint-example" { 4 ; CHECK-LABEL: Verifying gc pointers in function: test.not.ok.0 5 bci_0: 6 br i1 undef, label %left, label %right 7 8 left: 9 %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 -1, i32 0, i32 0, i32 0) 10 br label %merge 11 12 right: 13 br label %merge 14 15 merge: 16 ; CHECK: Illegal use of unrelocated value found! 17 ; CHECK-NEXT: Def: %val = phi i8 addrspace(1)* [ %arg, %left ], [ %arg, %right ] 18 ; CHECK-NEXT: Use: ret i8 addrspace(1)* %val 19 %val = phi i8 addrspace(1)* [ %arg, %left ], [ %arg, %right ] 20 ret i8 addrspace(1)* %val 21 } 22 23 define i8 addrspace(1)* @test.not.ok.1(i8 addrspace(1)* %arg) gc "statepoint-example" { 24 ; CHECK-LABEL: Verifying gc pointers in function: test.not.ok.1 25 bci_0: 26 br i1 undef, label %left, label %right 27 28 left: 29 %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 -1, i32 0, i32 0, i32 0) 30 br label %merge 31 32 right: 33 br label %merge 34 35 merge: 36 ; CHECK: Illegal use of unrelocated value found! 37 ; CHECK-NEXT: Def: %val = phi i8 addrspace(1)* [ %arg, %left ], [ null, %right ] 38 ; CHECK-NEXT: Use: ret i8 addrspace(1)* %val 39 %val = phi i8 addrspace(1)* [ %arg, %left ], [ null, %right ] 40 ret i8 addrspace(1)* %val 41 } 42 43 define i8 addrspace(1)* @test.ok.0(i8 addrspace(1)* %arg) gc "statepoint-example" { 44 ; CHECK: No illegal uses found by SafepointIRVerifier in: test.ok.0 45 bci_0: 46 br i1 undef, label %left, label %right 47 48 left: 49 %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 -1, i32 0, i32 0, i32 0) 50 br label %merge 51 52 right: 53 br label %merge 54 55 merge: 56 %val = phi i8 addrspace(1)* [ null, %left ], [ null, %right] 57 ret i8 addrspace(1)* %val 58 } 59 60 define i8 addrspace(1)* @test.ok.1(i8 addrspace(1)* %arg) gc "statepoint-example" { 61 ; CHECK: No illegal uses found by SafepointIRVerifier in: test.ok.1 62 bci_0: 63 br i1 undef, label %left, label %right 64 65 left: 66 call void @not_statepoint() 67 br label %merge 68 69 right: 70 br label %merge 71 72 merge: 73 %val = phi i8 addrspace(1)* [ %arg, %left ], [ %arg, %right] 74 ret i8 addrspace(1)* %val 75 } 76 77 ; It should be allowed to compare poisoned ptr with null. 78 define void @test.poisoned.cmp.ok(i8 addrspace(1)* %arg) gc "statepoint-example" { 79 ; CHECK-LABEL: Verifying gc pointers in function: test.poisoned.cmp.ok 80 bci_0: 81 br i1 undef, label %left, label %right 82 83 left: 84 %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, i8 addrspace(1)* %arg , i32 -1, i32 0, i32 0, i32 0) 85 %arg.relocated = call i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %safepoint_token, i32 7, i32 7) ; arg, arg 86 br label %merge 87 88 right: 89 %safepoint_token2 = 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, i8 addrspace(1)* %arg , i32 -1, i32 0, i32 0, i32 0) 90 br label %merge 91 92 merge: 93 ; CHECK: No illegal uses found by SafepointIRVerifier in: test.poisoned.cmp.ok 94 %val.poisoned = phi i8 addrspace(1)* [ %arg.relocated, %left ], [ %arg, %right ] 95 %c = icmp eq i8 addrspace(1)* %val.poisoned, null 96 ret void 97 } 98 99 ; It is illegal to compare poisoned ptr and relocated. 100 define void @test.poisoned.cmp.fail.0(i8 addrspace(1)* %arg) gc "statepoint-example" { 101 ; CHECK-LABEL: Verifying gc pointers in function: test.poisoned.cmp.fail.0 102 bci_0: 103 br i1 undef, label %left, label %right 104 105 left: 106 %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, i8 addrspace(1)* %arg , i32 -1, i32 0, i32 0, i32 0) 107 %arg.relocated = call i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %safepoint_token, i32 7, i32 7) ; arg, arg 108 br label %merge 109 110 right: 111 %safepoint_token2 = 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, i8 addrspace(1)* %arg , i32 -1, i32 0, i32 0, i32 0) 112 %arg.relocated2 = call i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %safepoint_token2, i32 7, i32 7) ; arg, arg 113 br label %merge 114 115 merge: 116 ; CHECK: Illegal use of unrelocated value found! 117 ; CHECK-NEXT: Def: %val.poisoned = phi i8 addrspace(1)* [ %arg.relocated, %left ], [ %arg, %right ] 118 ; CHECK-NEXT: Use: %c = icmp eq i8 addrspace(1)* %val.poisoned, %val 119 %val.poisoned = phi i8 addrspace(1)* [ %arg.relocated, %left ], [ %arg, %right ] 120 %val = phi i8 addrspace(1)* [ %arg.relocated, %left ], [ %arg.relocated2, %right ] 121 %c = icmp eq i8 addrspace(1)* %val.poisoned, %val 122 ret void 123 } 124 125 ; It is illegal to compare poisoned ptr and unrelocated. 126 define void @test.poisoned.cmp.fail.1(i8 addrspace(1)* %arg) gc "statepoint-example" { 127 ; CHECK-LABEL: Verifying gc pointers in function: test.poisoned.cmp.fail.1 128 bci_0: 129 br i1 undef, label %left, label %right 130 131 left: 132 %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, i8 addrspace(1)* %arg , i32 -1, i32 0, i32 0, i32 0) 133 %arg.relocated = call i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %safepoint_token, i32 7, i32 7) ; arg, arg 134 br label %merge 135 136 right: 137 %safepoint_token2 = 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, i8 addrspace(1)* %arg , i32 -1, i32 0, i32 0, i32 0) 138 %arg.relocated2 = call i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %safepoint_token2, i32 7, i32 7) ; arg, arg 139 br label %merge 140 141 merge: 142 ; CHECK: Illegal use of unrelocated value found! 143 ; CHECK-NEXT: Def: %val.poisoned = phi i8 addrspace(1)* [ %arg.relocated, %left ], [ %arg, %right ] 144 ; CHECK-NEXT: Use: %c = icmp eq i8 addrspace(1)* %val.poisoned, %arg 145 %val.poisoned = phi i8 addrspace(1)* [ %arg.relocated, %left ], [ %arg, %right ] 146 %c = icmp eq i8 addrspace(1)* %val.poisoned, %arg 147 ret void 148 } 149 150 ; It should be allowed to compare unrelocated phi with unrelocated value. 151 define void @test.unrelocated-phi.cmp.ok(i8 addrspace(1)* %arg) gc "statepoint-example" { 152 ; CHECK-LABEL: Verifying gc pointers in function: test.unrelocated-phi.cmp.ok 153 bci_0: 154 br i1 undef, label %left, label %right 155 156 left: 157 %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 -1, i32 0, i32 0, i32 0) 158 br label %merge 159 160 right: 161 br label %merge 162 163 merge: 164 ; CHECK: No illegal uses found by SafepointIRVerifier in: test.unrelocated-phi.cmp.ok 165 %val.unrelocated = phi i8 addrspace(1)* [ %arg, %left ], [ null, %right ] 166 %c = icmp eq i8 addrspace(1)* %val.unrelocated, %arg 167 ret void 168 } 169 170 declare token @llvm.experimental.gc.statepoint.p0f_isVoidf(i64, i32, void ()*, i32, i32, ...) 171 declare i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token, i32, i32) 172 declare void @not_statepoint() 173