1; RUN: opt -safepoint-ir-verifier-print-only -verify-safepoint-ir -S %s 2>&1 | FileCheck %s 2 3define 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 23define 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 43define 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 60define 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. 78define 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. 100define 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. 126define 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. 151define 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 170declare token @llvm.experimental.gc.statepoint.p0f_isVoidf(i64, i32, void ()*, i32, i32, ...) 171declare i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token, i32, i32) 172declare void @not_statepoint() 173