Imported Upstream version 5.18.0.205

Former-commit-id: 7f59f7e792705db773f1caecdaa823092f4e2927
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2018-11-16 08:20:38 +00:00
parent 5cd5df71cc
commit 8e12397d70
28486 changed files with 3867013 additions and 66 deletions

View File

@ -0,0 +1,23 @@
; RUN: opt -safepoint-ir-verifier-print-only -verify-safepoint-ir -S %s 2>&1 | FileCheck %s
; This test checks that if a value is used immediately after a
; safepoint without using the relocated value that the verifier
; catches this.
%jObject = type { [8 x i8] }
; Function Attrs: nounwind
define %jObject addrspace(1)* @test(%jObject addrspace(1)* %arg) gc "statepoint-example" {
bci_0:
%safepoint_token3 = tail call token (i64, i32, double (double)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_f64f64f(i64 0, i32 0, double (double)* undef, i32 1, i32 0, double undef, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0, %jObject addrspace(1)* %arg)
%arg2.relocated4 = call coldcc %jObject addrspace(1)* @llvm.experimental.gc.relocate.p1jObject(token %safepoint_token3, i32 13, i32 13)
ret %jObject addrspace(1)* %arg
; CHECK: Illegal use of unrelocated value found!
; CHECK-NEXT: Def: %jObject addrspace(1)* %arg
; CHECK-NEXT: Use: ret %jObject addrspace(1)* %arg
}
; Function Attrs: nounwind
declare %jObject addrspace(1)* @llvm.experimental.gc.relocate.p1jObject(token, i32, i32) #3
declare token @llvm.experimental.gc.statepoint.p0f_f64f64f(i64, i32, double (double)*, i32, i32, ...)

View File

@ -0,0 +1,85 @@
; RUN: opt -safepoint-ir-verifier-print-only -verify-safepoint-ir -S %s 2>&1 | FileCheck %s
; In some cases, it is valid to have unrelocated pointers used as compare
; operands. Make sure the verifier knows to spot these exceptions.
; comparison against null.
define i8 addrspace(1)* @test1(i64 %arg, i8 addrspace(1)* %addr) gc "statepoint-example" {
; CHECK: No illegal uses found by SafepointIRVerifier in: test1
entry:
%load_addr = getelementptr i8, i8 addrspace(1)* %addr, i64 %arg
%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)
%cmp = icmp eq i8 addrspace(1)* %load_addr, null
ret i8 addrspace(1)* null
}
; comparison against exclusively derived null.
define void @test2(i64 %arg, i1 %cond, i8 addrspace(1)* %addr) gc "statepoint-example" {
; CHECK: No illegal uses found by SafepointIRVerifier in: test2
%load_addr = getelementptr i8, i8 addrspace(1)* null, i64 %arg
%load_addr_sel = select i1 %cond, i8 addrspace(1)* null, i8 addrspace(1)* %load_addr
%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)
%cmp = icmp eq i8 addrspace(1)* %addr, %load_addr_sel
ret void
}
; comparison against a constant non-null pointer. This is unrelocated use, since
; that pointer bits may mean something in a VM.
define void @test3(i64 %arg, i32 addrspace(1)* %addr) gc "statepoint-example" {
; CHECK-LABEL: Verifying gc pointers in function: test3
; CHECK: Illegal use of unrelocated value found!
entry:
%load_addr = getelementptr i32, i32 addrspace(1)* %addr, i64 %arg
%load_addr_const = getelementptr i32, i32 addrspace(1)* inttoptr (i64 15 to i32 addrspace(1)*), i64 %arg
%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)
%cmp = icmp eq i32 addrspace(1)* %load_addr, %load_addr_const
ret void
}
; comparison against a derived pointer that is *not* exclusively derived from
; null. An unrelocated use since the derived pointer could be from the constant
; non-null pointer (load_addr.2).
define void @test4(i64 %arg, i1 %cond, i8 addrspace(1)* %base) gc "statepoint-example" {
; CHECK-LABEL: Verifying gc pointers in function: test4
; CHECK: Illegal use of unrelocated value found!
entry:
%load_addr.1 = getelementptr i8, i8 addrspace(1)* null, i64 %arg
br i1 %cond, label %split, label %join
split:
%load_addr.2 = getelementptr i8, i8 addrspace(1)* inttoptr (i64 30 to i8 addrspace(1)*), i64 %arg
br label %join
join:
%load_addr = phi i8 addrspace(1)* [%load_addr.1, %entry], [%load_addr.2, %split]
%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)
%cmp = icmp eq i8 addrspace(1)* %load_addr, %base
ret void
}
; comparison between 2 unrelocated base pointers.
; Since the cmp can be reordered legally before the safepoint, these are correct
; unrelocated uses of the pointers.
define void @test5(i64 %arg, i8 addrspace(1)* %base1, i8 addrspace(1)* %base2) gc "statepoint-example" {
; CHECK: No illegal uses found by SafepointIRVerifier in: test5
%load_addr1 = getelementptr i8, i8 addrspace(1)* %base1, i64 %arg
%load_addr2 = getelementptr i8, i8 addrspace(1)* %base2, i64 %arg
%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)
%cmp = icmp eq i8 addrspace(1)* %load_addr1, %load_addr2
ret void
}
; comparison between a relocated and an unrelocated pointer.
; this is invalid use of the unrelocated pointer.
define void @test6(i64 %arg, i8 addrspace(1)* %base1, i8 addrspace(1)* %base2) gc "statepoint-example" {
; CHECK-LABEL: Verifying gc pointers in function: test6
; CHECK: Illegal use of unrelocated value found!
%load_addr1 = getelementptr i8, i8 addrspace(1)* %base1, i64 %arg
%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)* %base2 , i32 -1, i32 0, i32 0, i32 0)
%ptr2.relocated = call i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %safepoint_token, i32 7, i32 7) ; base2, base2
%cmp = icmp eq i8 addrspace(1)* %load_addr1, %ptr2.relocated
ret void
}
declare token @llvm.experimental.gc.statepoint.p0f_isVoidf(i64, i32, void ()*, i32, i32, ...)
declare i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token, i32, i32)

View File

@ -0,0 +1,70 @@
; RUN: opt -safepoint-ir-verifier-print-only -verify-safepoint-ir -S %s 2>&1 | FileCheck %s
define i8 addrspace(1)* @test1(i64 %arg) gc "statepoint-example" {
; CHECK: No illegal uses found by SafepointIRVerifier in: test1
entry:
%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)
ret i8 addrspace(1)* null
}
define i8 addrspace(1)* @test2(i64 %arg) gc "statepoint-example" {
; CHECK: No illegal uses found by SafepointIRVerifier in: test2
entry:
%load_addr = getelementptr i8, i8 addrspace(1)* inttoptr (i64 15 to i8 addrspace(1)*), i64 %arg
%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)
ret i8 addrspace(1)* %load_addr
}
define i8 addrspace(1)* @test3(i64 %arg) gc "statepoint-example" {
; CHECK: No illegal uses found by SafepointIRVerifier in: test3
entry:
%load_addr = getelementptr i32, i32 addrspace(1)* inttoptr (i64 15 to i32 addrspace(1)*), i64 %arg
%load_addr.cast = bitcast i32 addrspace(1)* %load_addr to i8 addrspace(1)*
%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)
ret i8 addrspace(1)* %load_addr.cast
}
define i8 addrspace(1)* @test4(i64 %arg, i1 %cond) gc "statepoint-example" {
; CHECK: No illegal uses found by SafepointIRVerifier in: test4
entry:
%load_addr.1 = getelementptr i8, i8 addrspace(1)* inttoptr (i64 15 to i8 addrspace(1)*), i64 %arg
br i1 %cond, label %split, label %join
split:
%load_addr.2 = getelementptr i8, i8 addrspace(1)* inttoptr (i64 30 to i8 addrspace(1)*), i64 %arg
br label %join
join:
%load_addr = phi i8 addrspace(1)* [%load_addr.1, %entry], [%load_addr.2, %split]
%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)
ret i8 addrspace(1)* %load_addr
}
define i8 addrspace(1)* @test5(i64 %arg, i1 %cond) gc "statepoint-example" {
; CHECK: No illegal uses found by SafepointIRVerifier in: test5
entry:
%load_addr.1 = getelementptr i8, i8 addrspace(1)* inttoptr (i64 15 to i8 addrspace(1)*), i64 %arg
%load_addr.2 = getelementptr i8, i8 addrspace(1)* inttoptr (i64 30 to i8 addrspace(1)*), i64 %arg
%load_addr = select i1 %cond, i8 addrspace(1)* %load_addr.1, i8 addrspace(1)* %load_addr.2
%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)
ret i8 addrspace(1)* %load_addr
}
define i8 addrspace(1)* @test6(i64 %arg, i1 %cond, i8 addrspace(1)* %base) gc "statepoint-example" {
; CHECK-LABEL: Verifying gc pointers in function: test6
; CHECK: Illegal use of unrelocated value found!
entry:
%load_addr.1 = getelementptr i8, i8 addrspace(1)* %base, i64 %arg
br i1 %cond, label %split, label %join
split:
%load_addr.2 = getelementptr i8, i8 addrspace(1)* inttoptr (i64 30 to i8 addrspace(1)*), i64 %arg
br label %join
join:
%load_addr = phi i8 addrspace(1)* [%load_addr.1, %entry], [%load_addr.2, %split]
%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)
ret i8 addrspace(1)* %load_addr
}
declare token @llvm.experimental.gc.statepoint.p0f_isVoidf(i64, i32, void ()*, i32, i32, ...)

View File

@ -0,0 +1,26 @@
; XFAIL: *
; RUN: opt -safepoint-ir-verifier-print-only -verify-safepoint-ir -S %s 2>&1 | FileCheck %s
; In %merge %val.unrelocated, %ptr and %arg should be unrelocated.
; FIXME: if this test fails it is a false-positive alarm. IR is correct.
define void @test.unrelocated-phi.ok(i8 addrspace(1)* %arg) gc "statepoint-example" {
; CHECK-LABEL: Verifying gc pointers in function: test.unrelocated-phi.ok
bci_0:
%ptr = getelementptr i8, i8 addrspace(1)* %arg, i64 4
br i1 undef, label %left, label %right
left:
%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)
br label %merge
right:
br label %merge
merge:
; CHECK: No illegal uses found by SafepointIRVerifier in: test.unrelocated-phi.ok
%val.unrelocated = phi i8 addrspace(1)* [ %arg, %left ], [ %ptr, %right ]
%c = icmp eq i8 addrspace(1)* %val.unrelocated, %arg
ret void
}
declare token @llvm.experimental.gc.statepoint.p0f_isVoidf(i64, i32, void ()*, i32, i32, ...)

View File

@ -0,0 +1,72 @@
; RUN: opt %s -safepoint-ir-verifier-print-only -verify-safepoint-ir -S 2>&1 | FileCheck %s
; CHECK: Illegal use of unrelocated value found!
; CHECK-NEXT: Def: %base_phi4 = phi %jObject addrspace(1)* addrspace(1)* [ %addr98.relocated, %not_zero146 ], [ %cast6, %bci_37-aload ], !is_base_value !0
; CHECK-NEXT: Use: %safepoint_token = tail call token (i64, i32, i32 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i32f(i64 0, i32 0, i32 ()* undef, i32 0, i32 0, i32 0, i32 5, i32 0, i32 0, i32 0, i32 0, i32 0, %jObject addrspace(1)* %base_phi1, %jObject addrspace(1)* addrspace(1)* %base_phi4, %jObject addrspace(1)* addrspace(1)* %relocated4, %jObject addrspace(1)* %relocated7)
%jObject = type { [8 x i8] }
declare %jObject addrspace(1)* @generate_obj1() #1
declare %jObject addrspace(1)* addrspace(1)* @generate_obj2() #1
declare %jObject addrspace(1)* @generate_obj3() #1
; Function Attrs: nounwind
define void @test(%jObject addrspace(1)*, %jObject addrspace(1)*, i32) #3 gc "statepoint-example" {
bci_0:
%result608 = call %jObject addrspace(1)* @generate_obj3()
%obj609 = bitcast %jObject addrspace(1)* %result608 to %jObject addrspace(1)*
%cast = bitcast %jObject addrspace(1)* %result608 to %jObject addrspace(1)*
%cast5 = bitcast %jObject addrspace(1)* %result608 to %jObject addrspace(1)*
br label %bci_37-aload
bci_37-aload: ; preds = %not_zero179, %bci_0
%base_phi = phi %jObject addrspace(1)* [ %base_phi1.relocated, %not_zero179 ], [ %cast, %bci_0 ], !is_base_value !0
%base_phi2 = phi %jObject addrspace(1)* [ %base_phi3, %not_zero179 ], [ %cast5, %bci_0 ], !is_base_value !0
%relocated8 = phi %jObject addrspace(1)* [ %relocated7.relocated, %not_zero179 ], [ %obj609, %bci_0 ]
%tmp3 = getelementptr inbounds %jObject, %jObject addrspace(1)* %relocated8, i64 0, i32 0, i64 32
%addr98 = bitcast i8 addrspace(1)* %tmp3 to %jObject addrspace(1)* addrspace(1)*
%cast6 = bitcast %jObject addrspace(1)* %base_phi2 to %jObject addrspace(1)* addrspace(1)*
br i1 undef, label %not_zero179, label %not_zero146
not_zero146: ; preds = %bci_37-aload
%addr98.relocated = call %jObject addrspace(1)* addrspace(1)* @generate_obj2() #1
%obj609.relocated = call %jObject addrspace(1)* @generate_obj1() #1
br label %not_zero179
not_zero179: ; preds = %not_zero146, %bci_37-aload
%base_phi1 = phi %jObject addrspace(1)* [ %obj609.relocated, %not_zero146 ], [ %base_phi, %bci_37-aload ], !is_base_value !0
%base_phi3 = phi %jObject addrspace(1)* [ %obj609.relocated, %not_zero146 ], [ %base_phi2, %bci_37-aload ], !is_base_value !0
%relocated7 = phi %jObject addrspace(1)* [ %obj609.relocated, %not_zero146 ], [ %relocated8, %bci_37-aload ]
%base_phi4 = phi %jObject addrspace(1)* addrspace(1)* [ %addr98.relocated, %not_zero146 ], [ %cast6, %bci_37-aload ], !is_base_value !0
%relocated4 = phi %jObject addrspace(1)* addrspace(1)* [ %addr98.relocated, %not_zero146 ], [ %addr98, %bci_37-aload ]
%safepoint_token = tail call token (i64, i32, i32 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i32f(i64 0, i32 0, i32 ()* undef, i32 0, i32 0, i32 0, i32 5, i32 0, i32 0, i32 0, i32 0, i32 0, %jObject addrspace(1)* %base_phi1, %jObject addrspace(1)* addrspace(1)* %base_phi4, %jObject addrspace(1)* addrspace(1)* %relocated4, %jObject addrspace(1)* %relocated7)
%tmp4 = call i32 @llvm.experimental.gc.result.i32(token %safepoint_token)
%base_phi1.relocated = call coldcc %jObject addrspace(1)* @llvm.experimental.gc.relocate.p1jObject(token %safepoint_token, i32 12, i32 12)
%base_phi4.relocated = call coldcc %jObject addrspace(1)* addrspace(1)* @llvm.experimental.gc.relocate.p1p1jObject(token %safepoint_token, i32 13, i32 13)
%relocated4.relocated = call coldcc %jObject addrspace(1)* addrspace(1)* @llvm.experimental.gc.relocate.p1p1jObject(token %safepoint_token, i32 13, i32 14)
%relocated7.relocated = call coldcc %jObject addrspace(1)* @llvm.experimental.gc.relocate.p1jObject(token %safepoint_token, i32 12, i32 15)
%addr636 = bitcast %jObject addrspace(1)* addrspace(1)* %relocated4.relocated to %jObject addrspace(1)* addrspace(1)*
br label %bci_37-aload
}
declare token @llvm.experimental.gc.statepoint.p0f_i32f(i64, i32, i32 ()*, i32, i32, ...)
; Function Attrs: nounwind
declare i32 @llvm.experimental.gc.result.i32(token) #4
; Function Attrs: nounwind
declare %jObject addrspace(1)* @llvm.experimental.gc.relocate.p1jObject(token, i32, i32) #4
; Function Attrs: nounwind
declare %jObject addrspace(1)* addrspace(1)* @llvm.experimental.gc.relocate.p1p1jObject(token, i32, i32) #4
attributes #0 = { noinline nounwind "gc-leaf-function"="true" }
attributes #1 = { "gc-leaf-function"="true" }
attributes #2 = { nounwind readonly "gc-leaf-function"="true" }
attributes #3 = { nounwind }
attributes #4 = { nounwind }
!0 = !{i32 1}

View File

@ -0,0 +1,149 @@
; RUN: opt -safepoint-ir-verifier-print-only -verify-safepoint-ir -S %s 2>&1 | FileCheck %s
; Checking if verifier accepts chain of GEPs/bitcasts.
define void @test.deriving.ok(i32, i8 addrspace(1)* %base1, i8 addrspace(1)* %base2) gc "statepoint-example" {
; CHECK-LABEL: Verifying gc pointers in function: test.deriving.ok
; CHECK-NEXT: No illegal uses found by SafepointIRVerifier in: test.deriving.ok
%ptr = getelementptr i8, i8 addrspace(1)* %base1, i64 4
%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)* %base1)
%ptr2 = getelementptr i8, i8 addrspace(1)* %base2, i64 8
%ptr.i32 = bitcast i8 addrspace(1)* %ptr to i32 addrspace(1)*
%ptr2.i32 = bitcast i8 addrspace(1)* %ptr2 to i32 addrspace(1)*
ret void
}
; Checking if verifier accepts cmp of two derived pointers when one defined
; before safepoint and one after and both have unrelocated base.
define void @test.cmp.ok(i32, i8 addrspace(1)* %base1, i8 addrspace(1)* %base2) gc "statepoint-example" {
; CHECK-LABEL: Verifying gc pointers in function: test.cmp.ok
; CHECK-NEXT: No illegal uses found by SafepointIRVerifier in: test.cmp.ok
%ptr = getelementptr i8, i8 addrspace(1)* %base1, i64 4
%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)* %base1)
%ptr2 = getelementptr i8, i8 addrspace(1)* %base2, i64 8
%c2 = icmp sgt i8 addrspace(1)* %ptr2, %ptr
ret void
}
; Checking if verifier accepts cmp of two derived pointers when one defined
; before safepoint and one after and both have unrelocated base. One of pointers
; defined as a long chain of geps/bitcasts.
define void @test.cmp-long_chain.ok(i32, i8 addrspace(1)* %base1, i8 addrspace(1)* %base2) gc "statepoint-example" {
; CHECK-LABEL: Verifying gc pointers in function: test.cmp-long_chain.ok
; CHECK-NEXT: No illegal uses found by SafepointIRVerifier in: test.cmp-long_chain.ok
%ptr = getelementptr i8, i8 addrspace(1)* %base1, i64 4
%ptr.i32 = bitcast i8 addrspace(1)* %ptr to i32 addrspace(1)*
%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)* %base1)
%ptr2 = getelementptr i8, i8 addrspace(1)* %base2, i64 8
%ptr2.i32 = bitcast i8 addrspace(1)* %ptr2 to i32 addrspace(1)*
%ptr2.i32.2 = getelementptr i32, i32 addrspace(1)* %ptr2.i32, i64 4
%ptr2.i32.3 = getelementptr i32, i32 addrspace(1)* %ptr2.i32.2, i64 8
%ptr2.i32.4 = getelementptr i32, i32 addrspace(1)* %ptr2.i32.3, i64 8
%ptr2.i32.5 = getelementptr i32, i32 addrspace(1)* %ptr2.i32.4, i64 8
%ptr2.i32.6 = getelementptr i32, i32 addrspace(1)* %ptr2.i32.5, i64 8
%ptr2.i32.6.i8 = bitcast i32 addrspace(1)* %ptr2.i32.6 to i8 addrspace(1)*
%ptr2.i32.6.i8.i32 = bitcast i8 addrspace(1)* %ptr2.i32.6.i8 to i32 addrspace(1)*
%ptr2.i32.6.i8.i32.2 = getelementptr i32, i32 addrspace(1)* %ptr2.i32.6.i8.i32, i64 8
%c2 = icmp sgt i32 addrspace(1)* %ptr2.i32.6.i8.i32.2, %ptr.i32
ret void
}
; GEP and bitcast of unrelocated pointer is acceptable, but load by resulting
; pointer should be reported.
define void @test.load.fail(i32, i8 addrspace(1)* %base) gc "statepoint-example" {
; CHECK-LABEL: Verifying gc pointers in function: test.load.fail
%ptr = getelementptr i8, i8 addrspace(1)* %base, i64 4
%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)* %base)
%ptr.i32 = bitcast i8 addrspace(1)* %ptr to i32 addrspace(1)* ; it's ok
; CHECK-NEXT: Illegal use of unrelocated value found!
; CHECK-NEXT: Def: %ptr.i32 = bitcast i8 addrspace(1)* %ptr to i32 addrspace(1)*
; CHECK-NEXT: Use: %ptr.val = load i32, i32 addrspace(1)* %ptr.i32
%ptr.val = load i32, i32 addrspace(1)* %ptr.i32
ret void
}
; Comparison between pointer derived from unrelocated one (though defined after
; safepoint) and relocated pointer should be reported.
define void @test.cmp.fail(i64 %arg, i8 addrspace(1)* %base1, i8 addrspace(1)* %base2) gc "statepoint-example" {
; CHECK-LABEL: Verifying gc pointers in function: test.cmp.fail
%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)* %base2 , i32 -1, i32 0, i32 0, i32 0)
%base2.relocated = call i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %safepoint_token, i32 7, i32 7) ; base2, base2
%addr1 = getelementptr i8, i8 addrspace(1)* %base1, i64 %arg
; CHECK-NEXT: Illegal use of unrelocated value found!
; CHECK-NEXT: Def: %addr1 = getelementptr i8, i8 addrspace(1)* %base1, i64 %arg
; CHECK-NEXT: Use: %cmp = icmp eq i8 addrspace(1)* %addr1, %base2.relocated
%cmp = icmp eq i8 addrspace(1)* %addr1, %base2.relocated
ret void
}
; Same as test.cmp.fail but splitted into two BBs.
define void @test.cmp2.fail(i64 %arg, i8 addrspace(1)* %base1, i8 addrspace(1)* %base2) gc "statepoint-example" {
.b0:
; CHECK-LABEL: Verifying gc pointers in function: test.cmp2.fail
%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)* %base2 , i32 -1, i32 0, i32 0, i32 0)
%base2.relocated = call i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %safepoint_token, i32 7, i32 7) ; base2, base2
%addr1 = getelementptr i8, i8 addrspace(1)* %base1, i64 %arg
br label %.b1
.b1:
; CHECK-NEXT: Illegal use of unrelocated value found!
; CHECK-NEXT: Def: %addr1 = getelementptr i8, i8 addrspace(1)* %base1, i64 %arg
; CHECK-NEXT: Use: %cmp = icmp eq i8 addrspace(1)* %addr1, %base2.relocated
%cmp = icmp eq i8 addrspace(1)* %addr1, %base2.relocated
ret void
}
; Checking that cmp of two unrelocated pointers is OK and load is not.
define void @test.cmp-load.fail(i64 %arg, i8 addrspace(1)* %base1, i8 addrspace(1)* %base2) gc "statepoint-example" {
; CHECK-LABEL: Verifying gc pointers in function: test.cmp-load.fail
%addr1 = getelementptr i8, i8 addrspace(1)* %base1, i64 %arg
%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)* %base2 , i32 -1, i32 0, i32 0, i32 0)
%addr2 = getelementptr i8, i8 addrspace(1)* %base2, i64 8
%cmp = icmp eq i8 addrspace(1)* %addr1, %addr2
; CHECK-NEXT: Illegal use of unrelocated value found!
; CHECK-NEXT: Def: %addr2 = getelementptr i8, i8 addrspace(1)* %base2, i64 8
; CHECK-NEXT: Use: %val = load i8, i8 addrspace(1)* %addr2
%val = load i8, i8 addrspace(1)* %addr2
ret void
}
; Same as test.cmp-load.fail but splitted into thee BBs.
define void @test.cmp-load2.fail(i64 %arg, i8 addrspace(1)* %base1, i8 addrspace(1)* %base2) gc "statepoint-example" {
.b0:
; CHECK-LABEL: Verifying gc pointers in function: test.cmp-load2.fail
%addr1 = getelementptr i8, i8 addrspace(1)* %base1, i64 %arg
%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)* %base2 , i32 -1, i32 0, i32 0, i32 0)
br label %.b1
.b1:
%addr2 = getelementptr i8, i8 addrspace(1)* %base2, i64 8
br label %.b2
.b2:
%cmp = icmp eq i8 addrspace(1)* %addr1, %addr2
; CHECK-NEXT: Illegal use of unrelocated value found!
; CHECK-NEXT: Def: %addr2 = getelementptr i8, i8 addrspace(1)* %base2, i64 8
; CHECK-NEXT: Use: %val = load i8, i8 addrspace(1)* %addr2
%val = load i8, i8 addrspace(1)* %addr2
ret void
}
; Same as test.cmp.ok but with multiple safepoints within one BB. And the last
; one is in the very end of BB so that Contribution of this BB is empty.
define void @test.cmp.multi-sp.ok(i64 %arg, i8 addrspace(1)* %base1, i8 addrspace(1)* %base2) gc "statepoint-example" {
; CHECK-LABEL: Verifying gc pointers in function: test.cmp.multi-sp.ok
; CHECK-NEXT: No illegal uses found by SafepointIRVerifier in: test.cmp.multi-sp.ok
%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)* %base2 , i32 -1, i32 0, i32 0, i32 0)
%base2.relocated = call i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %safepoint_token, i32 7, i32 7) ; base2, base2
%addr1 = getelementptr i8, i8 addrspace(1)* %base1, i64 %arg
%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)* %base2.relocated, i32 -1, i32 0, i32 0, i32 0)
%base2.relocated2 = call i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %safepoint_token2, i32 7, i32 7) ; base2.relocated, base2.relocated
%addr2 = getelementptr i8, i8 addrspace(1)* %base2, i64 %arg
%cmp = icmp eq i8 addrspace(1)* %addr1, %addr2
%safepoint_token3 = 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)* %base2.relocated2, i32 -1, i32 0, i32 0, i32 0)
ret void
}
; Function Attrs: nounwind
declare token @llvm.experimental.gc.statepoint.p0f_isVoidf(i64, i32, void ()*, i32, i32, ...)
declare i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token, i32, i32)

View File

@ -0,0 +1,172 @@
; RUN: opt -safepoint-ir-verifier-print-only -verify-safepoint-ir -S %s 2>&1 | FileCheck %s
define i8 addrspace(1)* @test.not.ok.0(i8 addrspace(1)* %arg) gc "statepoint-example" {
; CHECK-LABEL: Verifying gc pointers in function: test.not.ok.0
bci_0:
br i1 undef, label %left, label %right
left:
%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)
br label %merge
right:
br label %merge
merge:
; CHECK: Illegal use of unrelocated value found!
; CHECK-NEXT: Def: %val = phi i8 addrspace(1)* [ %arg, %left ], [ %arg, %right ]
; CHECK-NEXT: Use: ret i8 addrspace(1)* %val
%val = phi i8 addrspace(1)* [ %arg, %left ], [ %arg, %right ]
ret i8 addrspace(1)* %val
}
define i8 addrspace(1)* @test.not.ok.1(i8 addrspace(1)* %arg) gc "statepoint-example" {
; CHECK-LABEL: Verifying gc pointers in function: test.not.ok.1
bci_0:
br i1 undef, label %left, label %right
left:
%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)
br label %merge
right:
br label %merge
merge:
; CHECK: Illegal use of unrelocated value found!
; CHECK-NEXT: Def: %val = phi i8 addrspace(1)* [ %arg, %left ], [ null, %right ]
; CHECK-NEXT: Use: ret i8 addrspace(1)* %val
%val = phi i8 addrspace(1)* [ %arg, %left ], [ null, %right ]
ret i8 addrspace(1)* %val
}
define i8 addrspace(1)* @test.ok.0(i8 addrspace(1)* %arg) gc "statepoint-example" {
; CHECK: No illegal uses found by SafepointIRVerifier in: test.ok.0
bci_0:
br i1 undef, label %left, label %right
left:
%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)
br label %merge
right:
br label %merge
merge:
%val = phi i8 addrspace(1)* [ null, %left ], [ null, %right]
ret i8 addrspace(1)* %val
}
define i8 addrspace(1)* @test.ok.1(i8 addrspace(1)* %arg) gc "statepoint-example" {
; CHECK: No illegal uses found by SafepointIRVerifier in: test.ok.1
bci_0:
br i1 undef, label %left, label %right
left:
call void @not_statepoint()
br label %merge
right:
br label %merge
merge:
%val = phi i8 addrspace(1)* [ %arg, %left ], [ %arg, %right]
ret i8 addrspace(1)* %val
}
; It should be allowed to compare poisoned ptr with null.
define void @test.poisoned.cmp.ok(i8 addrspace(1)* %arg) gc "statepoint-example" {
; CHECK-LABEL: Verifying gc pointers in function: test.poisoned.cmp.ok
bci_0:
br i1 undef, label %left, label %right
left:
%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)
%arg.relocated = call i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %safepoint_token, i32 7, i32 7) ; arg, arg
br label %merge
right:
%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)
br label %merge
merge:
; CHECK: No illegal uses found by SafepointIRVerifier in: test.poisoned.cmp.ok
%val.poisoned = phi i8 addrspace(1)* [ %arg.relocated, %left ], [ %arg, %right ]
%c = icmp eq i8 addrspace(1)* %val.poisoned, null
ret void
}
; It is illegal to compare poisoned ptr and relocated.
define void @test.poisoned.cmp.fail.0(i8 addrspace(1)* %arg) gc "statepoint-example" {
; CHECK-LABEL: Verifying gc pointers in function: test.poisoned.cmp.fail.0
bci_0:
br i1 undef, label %left, label %right
left:
%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)
%arg.relocated = call i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %safepoint_token, i32 7, i32 7) ; arg, arg
br label %merge
right:
%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)
%arg.relocated2 = call i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %safepoint_token2, i32 7, i32 7) ; arg, arg
br label %merge
merge:
; CHECK: Illegal use of unrelocated value found!
; CHECK-NEXT: Def: %val.poisoned = phi i8 addrspace(1)* [ %arg.relocated, %left ], [ %arg, %right ]
; CHECK-NEXT: Use: %c = icmp eq i8 addrspace(1)* %val.poisoned, %val
%val.poisoned = phi i8 addrspace(1)* [ %arg.relocated, %left ], [ %arg, %right ]
%val = phi i8 addrspace(1)* [ %arg.relocated, %left ], [ %arg.relocated2, %right ]
%c = icmp eq i8 addrspace(1)* %val.poisoned, %val
ret void
}
; It is illegal to compare poisoned ptr and unrelocated.
define void @test.poisoned.cmp.fail.1(i8 addrspace(1)* %arg) gc "statepoint-example" {
; CHECK-LABEL: Verifying gc pointers in function: test.poisoned.cmp.fail.1
bci_0:
br i1 undef, label %left, label %right
left:
%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)
%arg.relocated = call i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %safepoint_token, i32 7, i32 7) ; arg, arg
br label %merge
right:
%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)
%arg.relocated2 = call i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %safepoint_token2, i32 7, i32 7) ; arg, arg
br label %merge
merge:
; CHECK: Illegal use of unrelocated value found!
; CHECK-NEXT: Def: %val.poisoned = phi i8 addrspace(1)* [ %arg.relocated, %left ], [ %arg, %right ]
; CHECK-NEXT: Use: %c = icmp eq i8 addrspace(1)* %val.poisoned, %arg
%val.poisoned = phi i8 addrspace(1)* [ %arg.relocated, %left ], [ %arg, %right ]
%c = icmp eq i8 addrspace(1)* %val.poisoned, %arg
ret void
}
; It should be allowed to compare unrelocated phi with unrelocated value.
define void @test.unrelocated-phi.cmp.ok(i8 addrspace(1)* %arg) gc "statepoint-example" {
; CHECK-LABEL: Verifying gc pointers in function: test.unrelocated-phi.cmp.ok
bci_0:
br i1 undef, label %left, label %right
left:
%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)
br label %merge
right:
br label %merge
merge:
; CHECK: No illegal uses found by SafepointIRVerifier in: test.unrelocated-phi.cmp.ok
%val.unrelocated = phi i8 addrspace(1)* [ %arg, %left ], [ null, %right ]
%c = icmp eq i8 addrspace(1)* %val.unrelocated, %arg
ret void
}
declare token @llvm.experimental.gc.statepoint.p0f_isVoidf(i64, i32, void ()*, i32, i32, ...)
declare i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token, i32, i32)
declare void @not_statepoint()