1; RUN: opt -print-memderefs -analyze -S < %s -enable-new-pm=0 | FileCheck %s 2; RUN: opt -passes=print-memderefs -S < %s -disable-output 2>&1 | FileCheck %s 3 4; Uses the print-deref (+ analyze to print) pass to run 5; isDereferenceablePointer() on many load instruction operands 6 7target datalayout = "e-i32:32:64" 8 9%TypeOpaque = type opaque 10 11declare zeroext i1 @return_i1() 12 13declare i32* @foo() 14@globalstr = global [6 x i8] c"hello\00" 15@globali32ptr = external global i32* 16 17%struct.A = type { [8 x i8], [5 x i8] } 18@globalstruct = external global %struct.A 19 20@globalptr.align1 = external global i8, align 1 21@globalptr.align16 = external global i8, align 16 22 23; CHECK-LABEL: 'test' 24define void @test(%struct.A* sret(%struct.A) %result, 25 i32 addrspace(1)* dereferenceable(8) %dparam, 26 i8 addrspace(1)* dereferenceable(32) align 1 %dparam.align1, 27 i8 addrspace(1)* dereferenceable(32) align 16 %dparam.align16, 28 i8* byval(i8) %i8_byval, 29 %struct.A* byval(%struct.A) %A_byval) 30 gc "statepoint-example" { 31; CHECK: The following are dereferenceable: 32entry: 33; CHECK: %globalptr{{.*}}(aligned) 34 %globalptr = getelementptr inbounds [6 x i8], [6 x i8]* @globalstr, i32 0, i32 0 35 %load1 = load i8, i8* %globalptr 36 37; CHECK: %alloca{{.*}}(aligned) 38 %alloca = alloca i1 39 %load2 = load i1, i1* %alloca 40 41 ; Load from empty array alloca 42; CHECK-NOT: %empty_alloca 43 %empty_alloca = alloca i8, i64 0 44 %empty_load = load i8, i8* %empty_alloca 45 46 ; Loads from sret arguments 47; CHECK: %sret_gep{{.*}}(aligned) 48 %sret_gep = getelementptr inbounds %struct.A, %struct.A* %result, i64 0, i32 1, i64 2 49 load i8, i8* %sret_gep 50 51; CHECK-NOT: %sret_gep_outside 52 %sret_gep_outside = getelementptr %struct.A, %struct.A* %result, i64 0, i32 1, i64 7 53 load i8, i8* %sret_gep_outside 54 55; CHECK: %dparam{{.*}}(unaligned) 56 %load3 = load i32, i32 addrspace(1)* %dparam 57 58; CHECK: %relocate{{.*}}(unaligned) 59 %tok = tail call token (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) ["gc-live" (i32 addrspace(1)* %dparam)] 60 %relocate = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %tok, i32 0, i32 0) 61 %load4 = load i32, i32 addrspace(1)* %relocate 62 63; CHECK-NOT: %nparam 64 %dpa = call i32 addrspace(1)* @func1(i32 addrspace(1)* %dparam) 65 %nparam = getelementptr i32, i32 addrspace(1)* %dpa, i32 5 66 %load5 = load i32, i32 addrspace(1)* %nparam 67 68 ; Load from a non-dereferenceable load 69; CHECK-NOT: %nd_load 70 %nd_load = load i32*, i32** @globali32ptr 71 %load6 = load i32, i32* %nd_load 72 73 ; Load from a dereferenceable load 74; CHECK: %d4_load{{.*}}(unaligned) 75 %d4_load = load i32*, i32** @globali32ptr, !dereferenceable !0 76 %load7 = load i32, i32* %d4_load 77 78 ; Load from an offset not covered by the dereferenceable portion 79; CHECK-NOT: %d2_load 80 %d2_load = load i32*, i32** @globali32ptr, !dereferenceable !1 81 %load8 = load i32, i32* %d2_load 82 83 ; Load from a potentially null pointer with dereferenceable_or_null 84; CHECK-NOT: %d_or_null_load 85 %d_or_null_load = load i32*, i32** @globali32ptr, !dereferenceable_or_null !0 86 %load9 = load i32, i32* %d_or_null_load 87 88 ; Load from a non-null pointer with dereferenceable_or_null 89; CHECK: %d_or_null_non_null_load{{.*}}(unaligned) 90 %d_or_null_non_null_load = load i32*, i32** @globali32ptr, !nonnull !2, !dereferenceable_or_null !0 91 %load10 = load i32, i32* %d_or_null_non_null_load 92 93 ; It's OK to overrun static array size as long as we stay within underlying object size 94; CHECK: %within_allocation{{.*}}(aligned) 95 %within_allocation = getelementptr inbounds %struct.A, %struct.A* @globalstruct, i64 0, i32 0, i64 10 96 %load11 = load i8, i8* %within_allocation 97 98 ; GEP is outside the underlying object size 99; CHECK-NOT: %outside_allocation 100 %outside_allocation = getelementptr inbounds %struct.A, %struct.A* @globalstruct, i64 0, i32 1, i64 10 101 %load12 = load i8, i8* %outside_allocation 102 103 ; Loads from aligned globals 104; CHECK: @globalptr.align1{{.*}}(unaligned) 105; CHECK: @globalptr.align16{{.*}}(aligned) 106 %load13 = load i8, i8* @globalptr.align1, align 16 107 %load14 = load i8, i8* @globalptr.align16, align 16 108 109 ; Loads from aligned arguments 110; CHECK: %dparam.align1{{.*}}(unaligned) 111; CHECK: %dparam.align16{{.*}}(aligned) 112 %load15 = load i8, i8 addrspace(1)* %dparam.align1, align 16 113 %load16 = load i8, i8 addrspace(1)* %dparam.align16, align 16 114 115 ; Loads from byval arguments 116; CHECK: %i8_byval{{.*}}(aligned) 117 %i8_byval_load = load i8, i8* %i8_byval 118 119; CHECK-NOT: %byval_cast 120 %byval_cast = bitcast i8* %i8_byval to i32* 121 %bad_byval_load = load i32, i32* %byval_cast 122 123; CHECK: %byval_gep{{.*}}(aligned) 124 %byval_gep = getelementptr inbounds %struct.A, %struct.A* %A_byval, i64 0, i32 1, i64 2 125 load i8, i8* %byval_gep 126 127 ; Loads from aligned allocas 128; CHECK: %alloca.align1{{.*}}(unaligned) 129; CHECK: %alloca.align16{{.*}}(aligned) 130 %alloca.align1 = alloca i1, align 1 131 %alloca.align16 = alloca i1, align 16 132 %load17 = load i1, i1* %alloca.align1, align 16 133 %load18 = load i1, i1* %alloca.align16, align 16 134 135 ; Loads from GEPs 136; CHECK: %gep.align1.offset1{{.*}}(unaligned) 137; CHECK: %gep.align16.offset1{{.*}}(unaligned) 138; CHECK: %gep.align1.offset16{{.*}}(unaligned) 139; CHECK: %gep.align16.offset16{{.*}}(aligned) 140 %gep.align1.offset1 = getelementptr inbounds i8, i8 addrspace(1)* %dparam.align1, i32 1 141 %gep.align16.offset1 = getelementptr inbounds i8, i8 addrspace(1)* %dparam.align16, i32 1 142 %gep.align1.offset16 = getelementptr inbounds i8, i8 addrspace(1)* %dparam.align1, i32 16 143 %gep.align16.offset16 = getelementptr inbounds i8, i8 addrspace(1)* %dparam.align16, i32 16 144 %load19 = load i8, i8 addrspace(1)* %gep.align1.offset1, align 16 145 %load20 = load i8, i8 addrspace(1)* %gep.align16.offset1, align 16 146 %load21 = load i8, i8 addrspace(1)* %gep.align1.offset16, align 16 147 %load22 = load i8, i8 addrspace(1)* %gep.align16.offset16, align 16 148 149; CHECK-NOT: %no_deref_return 150; CHECK: %deref_return{{.*}}(unaligned) 151; CHECK: %deref_and_aligned_return{{.*}}(aligned) 152 %no_deref_return = call i32* @foo() 153 %deref_return = call dereferenceable(32) i32* @foo() 154 %deref_and_aligned_return = call dereferenceable(32) align 16 i32* @foo() 155 %load23 = load i32, i32* %no_deref_return 156 %load24 = load i32, i32* %deref_return, align 16 157 %load25 = load i32, i32* %deref_and_aligned_return, align 16 158 159 ; Load from a dereferenceable and aligned load 160; CHECK: %d4_unaligned_load{{.*}}(unaligned) 161; CHECK: %d4_aligned_load{{.*}}(aligned) 162 %d4_unaligned_load = load i32*, i32** @globali32ptr, !dereferenceable !0 163 %d4_aligned_load = load i32*, i32** @globali32ptr, !dereferenceable !0, !align !{i64 16} 164 %load26 = load i32, i32* %d4_unaligned_load, align 16 165 %load27 = load i32, i32* %d4_aligned_load, align 16 166 167 ; Alloca with no explicit alignment is aligned to preferred alignment of 168 ; the type (specified by datalayout string). 169; CHECK: %alloca.noalign{{.*}}(aligned) 170 %alloca.noalign = alloca i32 171 %load28 = load i32, i32* %alloca.noalign, align 8 172 173 ret void 174} 175 176; CHECK: The following are dereferenceable: 177; CHECK: %ptr = inttoptr i32 %val to i32*, !dereferenceable !0 178define i32 @f_0(i32 %val) { 179 %ptr = inttoptr i32 %val to i32*, !dereferenceable !0 180 %load29 = load i32, i32* %ptr, align 8 181 ret i32 %load29 182} 183 184; Just check that we don't crash. 185; CHECK-LABEL: 'opaque_type_crasher' 186define void @opaque_type_crasher(%TypeOpaque* dereferenceable(16) %a) { 187entry: 188 %bc = bitcast %TypeOpaque* %a to i8* 189 %ptr8 = getelementptr inbounds i8, i8* %bc, i32 8 190 %ptr32 = bitcast i8* %ptr8 to i32* 191 br i1 undef, label %if.then, label %if.end 192 193if.then: 194 %res = load i32, i32* %ptr32, align 4 195 br label %if.end 196 197if.end: 198 ret void 199} 200 201declare token @llvm.experimental.gc.statepoint.p0f_i1f(i64, i32, i1 ()*, i32, i32, ...) 202declare i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token, i32, i32) 203 204declare i32 addrspace(1)* @func1(i32 addrspace(1)* returned) nounwind argmemonly 205 206!0 = !{i64 4} 207!1 = !{i64 2} 208!2 = !{} 209