1; RUN: opt -print-memderefs -analyze -S < %s -enable-new-pm=0 -use-dereferenceable-at-point-semantics=0 | FileCheck %s --check-prefixes=CHECK,GLOBAL 2; RUN: opt -passes=print-memderefs -S < %s -disable-output -use-dereferenceable-at-point-semantics=0 2>&1 | FileCheck %s --check-prefixes=CHECK,GLOBAL 3; RUN: opt -print-memderefs -analyze -S < %s -enable-new-pm=0 -use-dereferenceable-at-point-semantics=1 | FileCheck %s --check-prefixes=CHECK,POINT 4; RUN: opt -passes=print-memderefs -S < %s -disable-output -use-dereferenceable-at-point-semantics=1 2>&1 | FileCheck %s --check-prefixes=CHECK,POINT 5 6 7; Uses the print-deref (+ analyze to print) pass to run 8; isDereferenceablePointer() on many load instruction operands 9 10target datalayout = "e-i32:32:64" 11 12%TypeOpaque = type opaque 13 14declare zeroext i1 @return_i1() 15 16declare i32* @foo() 17@globalstr = global [6 x i8] c"hello\00" 18@globali32ptr = external global i32* 19 20%struct.A = type { [8 x i8], [5 x i8] } 21@globalstruct = external global %struct.A 22 23@globalptr.align1 = external global i8, align 1 24@globalptr.align16 = external global i8, align 16 25 26; Loads from sret arguments 27; CHECK-LABEL: 'test_sret' 28; GLOBAL: %sret_gep{{.*}}(aligned) 29; POINT-NOT: %sret_gep{{.*}}(aligned) 30; CHECK-NOT: %sret_gep_outside 31define void @test_sret(%struct.A* sret(%struct.A) %result) { 32 %sret_gep = getelementptr inbounds %struct.A, %struct.A* %result, i64 0, i32 1, i64 2 33 load i8, i8* %sret_gep 34 35 %sret_gep_outside = getelementptr %struct.A, %struct.A* %result, i64 0, i32 1, i64 7 36 load i8, i8* %sret_gep_outside 37 ret void 38} 39 40; CHECK-LABEL: 'test' 41define void @test(i32 addrspace(1)* dereferenceable(8) %dparam, 42 i8 addrspace(1)* dereferenceable(32) align 1 %dparam.align1, 43 i8 addrspace(1)* dereferenceable(32) align 16 %dparam.align16) 44 gc "statepoint-example" { 45; CHECK: The following are dereferenceable: 46entry: 47 call void @mayfree() 48 49; GLOBAL: %dparam{{.*}}(unaligned) 50; POINT-NOT: %dparam{{.*}}(unaligned) 51 %load3 = load i32, i32 addrspace(1)* %dparam 52 53; GLOBAL: %relocate{{.*}}(unaligned) 54; POINT-NOT: %relocate{{.*}}(unaligned) 55 %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)] 56 %relocate = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %tok, i32 0, i32 0) 57 %load4 = load i32, i32 addrspace(1)* %relocate 58 59; CHECK-NOT: %nparam 60 %dpa = call i32 addrspace(1)* @func1(i32 addrspace(1)* %dparam) 61 %nparam = getelementptr i32, i32 addrspace(1)* %dpa, i32 5 62 %load5 = load i32, i32 addrspace(1)* %nparam 63 64 ; Load from a non-dereferenceable load 65; CHECK-NOT: %nd_load 66 %nd_load = load i32*, i32** @globali32ptr 67 %load6 = load i32, i32* %nd_load 68 69 ; Load from a dereferenceable load 70; GLOBAL: %d4_load{{.*}}(unaligned) 71; POINT-NOT: %d4_load{{.*}}(unaligned) 72 %d4_load = load i32*, i32** @globali32ptr, !dereferenceable !0 73 %load7 = load i32, i32* %d4_load 74 75 ; Load from an offset not covered by the dereferenceable portion 76; CHECK-NOT: %d2_load 77 %d2_load = load i32*, i32** @globali32ptr, !dereferenceable !1 78 %load8 = load i32, i32* %d2_load 79 80 ; Load from a potentially null pointer with dereferenceable_or_null 81; CHECK-NOT: %d_or_null_load 82 %d_or_null_load = load i32*, i32** @globali32ptr, !dereferenceable_or_null !0 83 %load9 = load i32, i32* %d_or_null_load 84 85 ; Load from a non-null pointer with dereferenceable_or_null 86; GLOBAL: %d_or_null_non_null_load{{.*}}(unaligned) 87; POINT-NOT: %d_or_null_non_null_load{{.*}}(unaligned) 88 %d_or_null_non_null_load = load i32*, i32** @globali32ptr, !nonnull !2, !dereferenceable_or_null !0 89 %load10 = load i32, i32* %d_or_null_non_null_load 90 91 ; Loads from aligned arguments 92; GLOBAL: %dparam.align1{{.*}}(unaligned) 93; POINT-NOT: %dparam.align1{{.*}}(unaligned) 94; POINT-NOT: %dparam.align16{{.*}}(aligned) 95; GLOBAL: %dparam.align16{{.*}}(aligned) 96 %load15 = load i8, i8 addrspace(1)* %dparam.align1, align 16 97 %load16 = load i8, i8 addrspace(1)* %dparam.align16, align 16 98 99 ; Loads from GEPs 100; GLOBAL: %gep.align1.offset1{{.*}}(unaligned) 101; GLOBAL: %gep.align16.offset1{{.*}}(unaligned) 102; GLOBAL: %gep.align1.offset16{{.*}}(unaligned) 103; GLOBAL: %gep.align16.offset16{{.*}}(aligned) 104; POINT-NOT: %gep.align1.offset1{{.*}}(unaligned) 105; POINT-NOT: %gep.align16.offset1{{.*}}(unaligned) 106; POINT-NOT: %gep.align1.offset16{{.*}}(unaligned) 107; POINT-NOT: %gep.align16.offset16{{.*}}(aligned) 108 %gep.align1.offset1 = getelementptr inbounds i8, i8 addrspace(1)* %dparam.align1, i32 1 109 %gep.align16.offset1 = getelementptr inbounds i8, i8 addrspace(1)* %dparam.align16, i32 1 110 %gep.align1.offset16 = getelementptr inbounds i8, i8 addrspace(1)* %dparam.align1, i32 16 111 %gep.align16.offset16 = getelementptr inbounds i8, i8 addrspace(1)* %dparam.align16, i32 16 112 %load19 = load i8, i8 addrspace(1)* %gep.align1.offset1, align 16 113 %load20 = load i8, i8 addrspace(1)* %gep.align16.offset1, align 16 114 %load21 = load i8, i8 addrspace(1)* %gep.align1.offset16, align 16 115 %load22 = load i8, i8 addrspace(1)* %gep.align16.offset16, align 16 116 117; CHECK-NOT: %no_deref_return 118; GLOBAL: %deref_return{{.*}}(unaligned) 119; GLOBAL: %deref_and_aligned_return{{.*}}(aligned) 120; POINT-NOT: %deref_return{{.*}}(unaligned) 121; POINT-NOT: %deref_and_aligned_return{{.*}}(aligned) 122 %no_deref_return = call i32* @foo() 123 %deref_return = call dereferenceable(32) i32* @foo() 124 %deref_and_aligned_return = call dereferenceable(32) align 16 i32* @foo() 125 %load23 = load i32, i32* %no_deref_return 126 %load24 = load i32, i32* %deref_return, align 16 127 %load25 = load i32, i32* %deref_and_aligned_return, align 16 128 129 ; Load from a dereferenceable and aligned load 130; GLOBAL: %d4_unaligned_load{{.*}}(unaligned) 131; GLOBAL: %d4_aligned_load{{.*}}(aligned) 132; POINT-NOT: %d4_unaligned_load{{.*}}(unaligned) 133; POINT-NOT: %d4_aligned_load{{.*}}(aligned) 134 %d4_unaligned_load = load i32*, i32** @globali32ptr, !dereferenceable !0 135 %d4_aligned_load = load i32*, i32** @globali32ptr, !dereferenceable !0, !align !{i64 16} 136 %load26 = load i32, i32* %d4_unaligned_load, align 16 137 %load27 = load i32, i32* %d4_aligned_load, align 16 138 ret void 139} 140 141; Loads from aligned allocas 142; CHECK-LABEL: 'alloca_aligned' 143; CHECK: %alloca.align1{{.*}}(unaligned) 144; CHECK: %alloca.align16{{.*}}(aligned) 145define void @alloca_aligned() { 146 %alloca.align1 = alloca i1, align 1 147 %alloca.align16 = alloca i1, align 16 148 call void @mayfree() 149 %load17 = load i1, i1* %alloca.align1, align 16 150 %load18 = load i1, i1* %alloca.align16, align 16 151 ret void 152} 153 154; CHECK-LABEL: 'alloca_basic' 155; CHECK: %alloca{{.*}}(aligned) 156define void @alloca_basic() { 157 %alloca = alloca i1 158 call void @mayfree() 159 %load2 = load i1, i1* %alloca 160 ret void 161} 162 163; Load from empty array alloca 164; CHECK-LABEL: 'alloca_empty' 165; CHECK-NOT: %empty_alloca 166define void @alloca_empty() { 167 %empty_alloca = alloca i8, i64 0 168 call void @mayfree() 169 %empty_load = load i8, i8* %empty_alloca 170 ret void 171} 172 173; Alloca with no explicit alignment is aligned to preferred alignment of 174; the type (specified by datalayout string). 175; CHECK-LABEL: 'alloca_perfalign' 176; CHECK: %alloca.noalign{{.*}}(aligned) 177define void @alloca_perfalign() { 178 %alloca.noalign = alloca i32 179 call void @mayfree() 180 %load28 = load i32, i32* %alloca.noalign, align 8 181 ret void 182} 183 184; CHECK-LABEL: 'global' 185; CHECK: @globalptr.align1{{.*}}(unaligned) 186; CHECK: @globalptr.align16{{.*}}(aligned) 187; CHECK: %globalptr{{.*}}(aligned) 188define void @global() { 189 %load13 = load i8, i8* @globalptr.align1, align 16 190 %load14 = load i8, i8* @globalptr.align16, align 16 191 192 %globalptr = getelementptr inbounds [6 x i8], [6 x i8]* @globalstr, i32 0, i32 0 193 %load1 = load i8, i8* %globalptr 194 ret void 195} 196 197; It's OK to overrun static array size as long as we stay within underlying 198; object size 199; CHECK-LABEL: 'global_allocationsize' 200; CHECK: %within_allocation{{.*}}(aligned) 201; CHECK-NOT: %outside_allocation 202define void @global_allocationsize() { 203 %within_allocation = getelementptr inbounds %struct.A, %struct.A* @globalstruct, i64 0, i32 0, i64 10 204 %load11 = load i8, i8* %within_allocation 205 206 %outside_allocation = getelementptr inbounds %struct.A, %struct.A* @globalstruct, i64 0, i32 1, i64 10 207 %load12 = load i8, i8* %outside_allocation 208 ret void 209} 210 211; Loads from byval arguments 212; CHECK-LABEL: 'byval' 213; GLOBAL: %i8_byval{{.*}}(aligned) 214; POINT-NOT: %i8_byval{{.*}}(aligned) 215; CHECK-NOT: %byval_cast 216; GLOBAL: %byval_gep{{.*}}(aligned) 217; POINT-NOT: %byval_gep{{.*}}(aligned) 218; FIXME: Should hold in the point semantics case too 219define void @byval(i8* byval(i8) %i8_byval, 220 %struct.A* byval(%struct.A) %A_byval) { 221 call void @mayfree() 222 %i8_byval_load = load i8, i8* %i8_byval 223 224 %byval_cast = bitcast i8* %i8_byval to i32* 225 %bad_byval_load = load i32, i32* %byval_cast 226 227 %byval_gep = getelementptr inbounds %struct.A, %struct.A* %A_byval, i64 0, i32 1, i64 2 228 load i8, i8* %byval_gep 229 ret void 230} 231 232; CHECK-LABEL: 'f_0' 233; GLOBAL: %ptr = inttoptr i32 %val to i32*, !dereferenceable !0 234; POINT-NOT: %ptr = inttoptr i32 %val to i32*, !dereferenceable !0 235define i32 @f_0(i32 %val) { 236 %ptr = inttoptr i32 %val to i32*, !dereferenceable !0 237 call void @mayfree() 238 %load29 = load i32, i32* %ptr, align 8 239 ret i32 %load29 240} 241 242 243; The most basic case showing the difference between legacy global deref 244; attribute semantics and the new point-in-time semantics. 245; CHECK-LABEL: 'negative' 246; GLOBAL: %p 247; POINT-NOT: %p 248define void @negative(i32* dereferenceable(8) %p) nofree nosync { 249 call void @mayfree() 250 %v = load i32, i32* %p 251 ret void 252} 253 254; CHECK-LABEL: 'infer_func_attrs1' 255; GLOBAL: %p 256; POINT-NOT: %p 257; FIXME: Can be inferred from attributes 258define void @infer_func_attrs1(i32* dereferenceable(8) %p) nofree nosync { 259 call void @mayfree() 260 %v = load i32, i32* %p 261 ret void 262} 263 264; CHECK-LABEL: 'infer_func_attrs2' 265; GLOBAL: %p 266; POINT-NOT: %p 267; FIXME: Can be inferred from attributes 268define void @infer_func_attrs2(i32* dereferenceable(8) %p) readonly { 269 call void @mayfree() 270 %v = load i32, i32* %p 271 ret void 272} 273 274; CHECK-LABEL: 'infer_noalias1' 275; GLOBAL: %p 276; POINT-NOT: %p 277; FIXME: Can be inferred from attributes 278define void @infer_noalias1(i32* dereferenceable(8) noalias nofree %p) { 279 call void @mayfree() 280 %v = load i32, i32* %p 281 ret void 282} 283 284; CHECK-LABEL: 'infer_noalias2' 285; GLOBAL: %p 286; POINT-NOT: %p 287; FIXME: Can be inferred from attributes 288define void @infer_noalias2(i32* dereferenceable(8) noalias readonly %p) nosync { 289 call void @mayfree() 290 %v = load i32, i32* %p 291 ret void 292} 293 294 295; Just check that we don't crash. 296; CHECK-LABEL: 'opaque_type_crasher' 297define void @opaque_type_crasher(%TypeOpaque* dereferenceable(16) %a) { 298entry: 299 %bc = bitcast %TypeOpaque* %a to i8* 300 %ptr8 = getelementptr inbounds i8, i8* %bc, i32 8 301 %ptr32 = bitcast i8* %ptr8 to i32* 302 br i1 undef, label %if.then, label %if.end 303 304if.then: 305 %res = load i32, i32* %ptr32, align 4 306 br label %if.end 307 308if.end: 309 ret void 310} 311 312declare token @llvm.experimental.gc.statepoint.p0f_i1f(i64, i32, i1 ()*, i32, i32, ...) 313declare i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token, i32, i32) 314 315declare i32 addrspace(1)* @func1(i32 addrspace(1)* returned) nounwind argmemonly 316 317; Can free any object accessible in memory 318declare void @mayfree() 319 320!0 = !{i64 4} 321!1 = !{i64 2} 322!2 = !{} 323