Minor refactoring of GEP handling in isDereferenceablePointer
[oota-llvm.git] / test / Analysis / ValueTracking / memory-dereferenceable.ll
1 ; RUN: opt -print-memderefs -analyze -S <%s | FileCheck %s
2
3 ; Uses the print-deref (+ analyze to print) pass to run
4 ; isDereferenceablePointer() on many load instruction operands
5
6 target datalayout = "e"
7
8 declare zeroext i1 @return_i1()
9
10 @globalstr = global [6 x i8] c"hello\00"
11 @globali32ptr = external global i32*
12
13 %struct.A = type { [8 x i8], [5 x i8] }
14 @globalstruct = external global %struct.A
15
16 define void @test(i32 addrspace(1)* dereferenceable(8) %dparam) gc "statepoint-example" {
17 ; CHECK: The following are dereferenceable:
18 ; CHECK: %globalptr
19 ; CHECK: %alloca
20 ; CHECK: %dparam
21 ; CHECK: %relocate
22 ; CHECK-NOT: %nparam
23 ; CHECK-NOT: %nd_load
24 ; CHECK: %d4_load
25 ; CHECK-NOT: %d2_load
26 ; CHECK-NOT: %d_or_null_load
27 ; CHECK: %d_or_null_non_null_load
28 ; CHECK: %within_allocation
29 ; CHECK-NOT: %outside_allocation
30 entry:
31     %globalptr = getelementptr inbounds [6 x i8], [6 x i8]* @globalstr, i32 0, i32 0
32     %load1 = load i8, i8* %globalptr
33     %alloca = alloca i1
34     %load2 = load i1, i1* %alloca
35     %load3 = load i32, i32 addrspace(1)* %dparam
36     %tok = tail call i32 (i64, i32, i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i64 0, i32 0, i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0, i32 addrspace(1)* %dparam)
37     %relocate = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %tok, i32 7, i32 7)
38     %load4 = load i32, i32 addrspace(1)* %relocate
39     %nparam = getelementptr i32, i32 addrspace(1)* %dparam, i32 5
40     %load5 = load i32, i32 addrspace(1)* %nparam
41
42     ; Load from a non-dereferenceable load
43     %nd_load = load i32*, i32** @globali32ptr
44     %load6 = load i32, i32* %nd_load
45
46     ; Load from a dereferenceable load
47     %d4_load = load i32*, i32** @globali32ptr, !dereferenceable !0
48     %load7 = load i32, i32* %d4_load
49
50     ; Load from an offset not covered by the dereferenceable portion
51     %d2_load = load i32*, i32** @globali32ptr, !dereferenceable !1
52     %load8 = load i32, i32* %d2_load
53
54     ; Load from a potentially null pointer with dereferenceable_or_null
55     %d_or_null_load = load i32*, i32** @globali32ptr, !dereferenceable_or_null !0
56     %load9 = load i32, i32* %d_or_null_load
57
58     ; Load from a non-null pointer with dereferenceable_or_null
59     %d_or_null_non_null_load = load i32*, i32** @globali32ptr, !nonnull !2, !dereferenceable_or_null !0
60     %load10 = load i32, i32* %d_or_null_non_null_load
61
62     ; It's OK to overrun static array size as long as we stay within underlying object size
63     %within_allocation = getelementptr inbounds %struct.A, %struct.A* @globalstruct, i64 0, i32 0, i64 10
64     %load11 = load i8, i8* %within_allocation
65
66     ; GEP is outside the underlying object size
67     %outside_allocation = getelementptr inbounds %struct.A, %struct.A* @globalstruct, i64 0, i32 1, i64 10
68     %load12 = load i8, i8* %outside_allocation
69
70     ret void
71 }
72
73 declare i32 @llvm.experimental.gc.statepoint.p0f_i1f(i64, i32, i1 ()*, i32, i32, ...)
74 declare i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32, i32, i32)
75
76 !0 = !{i64 4}
77 !1 = !{i64 2}
78 !2 = !{}