1; RUN: opt < %s -inferattrs -S | FileCheck %s 2 3 4 5; Determine dereference-ability before unused loads get deleted: 6; https://bugs.llvm.org/show_bug.cgi?id=21780 7 8define <4 x double> @PR21780(double* %ptr) { 9; CHECK-LABEL: @PR21780(double* %ptr) 10 11 ; GEP of index 0 is simplified away. 12 %arrayidx1 = getelementptr inbounds double, double* %ptr, i64 1 13 %arrayidx2 = getelementptr inbounds double, double* %ptr, i64 2 14 %arrayidx3 = getelementptr inbounds double, double* %ptr, i64 3 15 16 %t0 = load double, double* %ptr, align 8 17 %t1 = load double, double* %arrayidx1, align 8 18 %t2 = load double, double* %arrayidx2, align 8 19 %t3 = load double, double* %arrayidx3, align 8 20 21 %vecinit0 = insertelement <4 x double> undef, double %t0, i32 0 22 %vecinit1 = insertelement <4 x double> %vecinit0, double %t1, i32 1 23 %vecinit2 = insertelement <4 x double> %vecinit1, double %t2, i32 2 24 %vecinit3 = insertelement <4 x double> %vecinit2, double %t3, i32 3 25 %shuffle = shufflevector <4 x double> %vecinit3, <4 x double> %vecinit3, <4 x i32> <i32 0, i32 0, i32 2, i32 2> 26 ret <4 x double> %shuffle 27} 28 29 30define double @PR21780_only_access3_with_inbounds(double* %ptr) { 31; CHECK-LABEL: @PR21780_only_access3_with_inbounds(double* %ptr) 32 33 %arrayidx3 = getelementptr inbounds double, double* %ptr, i64 3 34 %t3 = load double, double* %arrayidx3, align 8 35 ret double %t3 36} 37 38define double @PR21780_only_access3_without_inbounds(double* %ptr) { 39; CHECK-LABEL: @PR21780_only_access3_without_inbounds(double* %ptr) 40 %arrayidx3 = getelementptr double, double* %ptr, i64 3 41 %t3 = load double, double* %arrayidx3, align 8 42 ret double %t3 43} 44 45define double @PR21780_without_inbounds(double* %ptr) { 46; CHECK-LABEL: @PR21780_without_inbounds(double* %ptr) 47 48 %arrayidx1 = getelementptr double, double* %ptr, i64 1 49 %arrayidx2 = getelementptr double, double* %ptr, i64 2 50 %arrayidx3 = getelementptr double, double* %ptr, i64 3 51 52 %t0 = load double, double* %ptr, align 8 53 %t1 = load double, double* %arrayidx1, align 8 54 %t2 = load double, double* %arrayidx2, align 8 55 %t3 = load double, double* %arrayidx3, align 8 56 57 ret double %t3 58} 59 60; Unsimplified, but still valid. Also, throw in some bogus arguments. 61 62define void @gep0(i8* %unused, i8* %other, i8* %ptr) { 63; CHECK-LABEL: @gep0(i8* %unused, i8* %other, i8* %ptr) 64 %arrayidx0 = getelementptr i8, i8* %ptr, i64 0 65 %arrayidx1 = getelementptr i8, i8* %ptr, i64 1 66 %arrayidx2 = getelementptr i8, i8* %ptr, i64 2 67 %t0 = load i8, i8* %arrayidx0 68 %t1 = load i8, i8* %arrayidx1 69 %t2 = load i8, i8* %arrayidx2 70 store i8 %t2, i8* %other 71 ret void 72} 73 74; Order of accesses does not change computation. 75; Multiple arguments may be dereferenceable. 76 77define void @ordering(i8* %ptr1, i32* %ptr2) { 78; CHECK-LABEL: @ordering(i8* %ptr1, i32* %ptr2) 79 %a20 = getelementptr i32, i32* %ptr2, i64 0 80 %a12 = getelementptr i8, i8* %ptr1, i64 2 81 %t12 = load i8, i8* %a12 82 %a11 = getelementptr i8, i8* %ptr1, i64 1 83 %t20 = load i32, i32* %a20 84 %a10 = getelementptr i8, i8* %ptr1, i64 0 85 %t10 = load i8, i8* %a10 86 %t11 = load i8, i8* %a11 87 %a21 = getelementptr i32, i32* %ptr2, i64 1 88 %t21 = load i32, i32* %a21 89 ret void 90} 91 92; Not in entry block. 93 94define void @not_entry_but_guaranteed_to_execute(i8* %ptr) { 95; CHECK-LABEL: @not_entry_but_guaranteed_to_execute(i8* %ptr) 96entry: 97 br label %exit 98exit: 99 %arrayidx0 = getelementptr i8, i8* %ptr, i64 0 100 %arrayidx1 = getelementptr i8, i8* %ptr, i64 1 101 %arrayidx2 = getelementptr i8, i8* %ptr, i64 2 102 %t0 = load i8, i8* %arrayidx0 103 %t1 = load i8, i8* %arrayidx1 104 %t2 = load i8, i8* %arrayidx2 105 ret void 106} 107 108; Not in entry block and not guaranteed to execute. 109 110define void @not_entry_not_guaranteed_to_execute(i8* %ptr, i1 %cond) { 111; CHECK-LABEL: @not_entry_not_guaranteed_to_execute(i8* %ptr, i1 %cond) 112entry: 113 br i1 %cond, label %loads, label %exit 114loads: 115 %arrayidx0 = getelementptr i8, i8* %ptr, i64 0 116 %arrayidx1 = getelementptr i8, i8* %ptr, i64 1 117 %arrayidx2 = getelementptr i8, i8* %ptr, i64 2 118 %t0 = load i8, i8* %arrayidx0 119 %t1 = load i8, i8* %arrayidx1 120 %t2 = load i8, i8* %arrayidx2 121 ret void 122exit: 123 ret void 124} 125 126; The last load may not execute, so derefenceable bytes only covers the 1st two loads. 127 128define void @partial_in_entry(i16* %ptr, i1 %cond) { 129; CHECK-LABEL: @partial_in_entry(i16* %ptr, i1 %cond) 130entry: 131 %arrayidx0 = getelementptr i16, i16* %ptr, i64 0 132 %arrayidx1 = getelementptr i16, i16* %ptr, i64 1 133 %arrayidx2 = getelementptr i16, i16* %ptr, i64 2 134 %t0 = load i16, i16* %arrayidx0 135 %t1 = load i16, i16* %arrayidx1 136 br i1 %cond, label %loads, label %exit 137loads: 138 %t2 = load i16, i16* %arrayidx2 139 ret void 140exit: 141 ret void 142} 143 144; The volatile load can't be used to prove a non-volatile access is allowed. 145; The 2nd and 3rd loads may never execute. 146 147define void @volatile_is_not_dereferenceable(i16* %ptr) { 148; CHECK-LABEL: @volatile_is_not_dereferenceable(i16* %ptr) 149 %arrayidx0 = getelementptr i16, i16* %ptr, i64 0 150 %arrayidx1 = getelementptr i16, i16* %ptr, i64 1 151 %arrayidx2 = getelementptr i16, i16* %ptr, i64 2 152 %t0 = load volatile i16, i16* %arrayidx0 153 %t1 = load i16, i16* %arrayidx1 154 %t2 = load i16, i16* %arrayidx2 155 ret void 156} 157 158; TODO: We should allow inference for atomic (but not volatile) ops. 159 160define void @atomic_is_alright(i16* %ptr) { 161; CHECK-LABEL: @atomic_is_alright(i16* %ptr) 162 %arrayidx0 = getelementptr i16, i16* %ptr, i64 0 163 %arrayidx1 = getelementptr i16, i16* %ptr, i64 1 164 %arrayidx2 = getelementptr i16, i16* %ptr, i64 2 165 %t0 = load atomic i16, i16* %arrayidx0 unordered, align 2 166 %t1 = load i16, i16* %arrayidx1 167 %t2 = load i16, i16* %arrayidx2 168 ret void 169} 170 171declare void @may_not_return() 172 173define void @not_guaranteed_to_transfer_execution(i16* %ptr) { 174; CHECK-LABEL: @not_guaranteed_to_transfer_execution(i16* %ptr) 175 %arrayidx0 = getelementptr i16, i16* %ptr, i64 0 176 %arrayidx1 = getelementptr i16, i16* %ptr, i64 1 177 %arrayidx2 = getelementptr i16, i16* %ptr, i64 2 178 %t0 = load i16, i16* %arrayidx0 179 call void @may_not_return() 180 %t1 = load i16, i16* %arrayidx1 181 %t2 = load i16, i16* %arrayidx2 182 ret void 183} 184 185; We must have consecutive accesses. 186 187define void @variable_gep_index(i8* %unused, i8* %ptr, i64 %variable_index) { 188; CHECK-LABEL: @variable_gep_index(i8* %unused, i8* %ptr, i64 %variable_index) 189 %arrayidx1 = getelementptr i8, i8* %ptr, i64 %variable_index 190 %arrayidx2 = getelementptr i8, i8* %ptr, i64 2 191 %t0 = load i8, i8* %ptr 192 %t1 = load i8, i8* %arrayidx1 193 %t2 = load i8, i8* %arrayidx2 194 ret void 195} 196 197; Deal with >1 GEP index. 198 199define void @multi_index_gep(<4 x i8>* %ptr) { 200; CHECK-LABEL: @multi_index_gep(<4 x i8>* %ptr) 201; FIXME: %ptr should be dereferenceable(4) 202 %arrayidx00 = getelementptr <4 x i8>, <4 x i8>* %ptr, i64 0, i64 0 203 %t0 = load i8, i8* %arrayidx00 204 ret void 205} 206 207; Could round weird bitwidths down? 208 209define void @not_byte_multiple(i9* %ptr) { 210; CHECK-LABEL: @not_byte_multiple(i9* %ptr) 211 %arrayidx0 = getelementptr i9, i9* %ptr, i64 0 212 %t0 = load i9, i9* %arrayidx0 213 ret void 214} 215 216; Missing direct access from the pointer. 217 218define void @no_pointer_deref(i16* %ptr) { 219; CHECK-LABEL: @no_pointer_deref(i16* %ptr) 220 %arrayidx1 = getelementptr i16, i16* %ptr, i64 1 221 %arrayidx2 = getelementptr i16, i16* %ptr, i64 2 222 %t1 = load i16, i16* %arrayidx1 223 %t2 = load i16, i16* %arrayidx2 224 ret void 225} 226 227; Out-of-order is ok, but missing access concludes dereferenceable range. 228 229define void @non_consecutive(i32* %ptr) { 230; CHECK-LABEL: @non_consecutive(i32* %ptr) 231 %arrayidx1 = getelementptr i32, i32* %ptr, i64 1 232 %arrayidx0 = getelementptr i32, i32* %ptr, i64 0 233 %arrayidx3 = getelementptr i32, i32* %ptr, i64 3 234 %t1 = load i32, i32* %arrayidx1 235 %t0 = load i32, i32* %arrayidx0 236 %t3 = load i32, i32* %arrayidx3 237 ret void 238} 239 240; Improve on existing dereferenceable attribute. 241 242define void @more_bytes(i32* dereferenceable(8) %ptr) { 243; CHECK-LABEL: @more_bytes(i32* dereferenceable(8) %ptr) 244 %arrayidx3 = getelementptr i32, i32* %ptr, i64 3 245 %arrayidx1 = getelementptr i32, i32* %ptr, i64 1 246 %arrayidx0 = getelementptr i32, i32* %ptr, i64 0 247 %arrayidx2 = getelementptr i32, i32* %ptr, i64 2 248 %t3 = load i32, i32* %arrayidx3 249 %t1 = load i32, i32* %arrayidx1 250 %t2 = load i32, i32* %arrayidx2 251 %t0 = load i32, i32* %arrayidx0 252 ret void 253} 254 255; Improve on existing dereferenceable_or_null attribute. 256 257define void @more_bytes_and_not_null(i32* dereferenceable_or_null(8) %ptr) { 258; CHECK-LABEL: @more_bytes_and_not_null(i32* dereferenceable_or_null(8) %ptr) 259 %arrayidx3 = getelementptr i32, i32* %ptr, i64 3 260 %arrayidx1 = getelementptr i32, i32* %ptr, i64 1 261 %arrayidx0 = getelementptr i32, i32* %ptr, i64 0 262 %arrayidx2 = getelementptr i32, i32* %ptr, i64 2 263 %t3 = load i32, i32* %arrayidx3 264 %t1 = load i32, i32* %arrayidx1 265 %t2 = load i32, i32* %arrayidx2 266 %t0 = load i32, i32* %arrayidx0 267 ret void 268} 269 270; But don't pessimize existing dereferenceable attribute. 271 272define void @better_bytes(i32* dereferenceable(100) %ptr) { 273; CHECK-LABEL: @better_bytes(i32* dereferenceable(100) %ptr) 274 %arrayidx3 = getelementptr i32, i32* %ptr, i64 3 275 %arrayidx1 = getelementptr i32, i32* %ptr, i64 1 276 %arrayidx0 = getelementptr i32, i32* %ptr, i64 0 277 %arrayidx2 = getelementptr i32, i32* %ptr, i64 2 278 %t3 = load i32, i32* %arrayidx3 279 %t1 = load i32, i32* %arrayidx1 280 %t2 = load i32, i32* %arrayidx2 281 %t0 = load i32, i32* %arrayidx0 282 ret void 283} 284 285define void @bitcast(i32* %arg) { 286; CHECK-LABEL: @bitcast(i32* %arg) 287 %ptr = bitcast i32* %arg to float* 288 %arrayidx0 = getelementptr float, float* %ptr, i64 0 289 %arrayidx1 = getelementptr float, float* %ptr, i64 1 290 %t0 = load float, float* %arrayidx0 291 %t1 = load float, float* %arrayidx1 292 ret void 293} 294 295define void @bitcast_different_sizes(double* %arg1, i8* %arg2) { 296; CHECK-LABEL: @bitcast_different_sizes(double* %arg1, i8* %arg2) 297 %ptr1 = bitcast double* %arg1 to float* 298 %a10 = getelementptr float, float* %ptr1, i64 0 299 %a11 = getelementptr float, float* %ptr1, i64 1 300 %a12 = getelementptr float, float* %ptr1, i64 2 301 %ld10 = load float, float* %a10 302 %ld11 = load float, float* %a11 303 %ld12 = load float, float* %a12 304 305 %ptr2 = bitcast i8* %arg2 to i64* 306 %a20 = getelementptr i64, i64* %ptr2, i64 0 307 %a21 = getelementptr i64, i64* %ptr2, i64 1 308 %ld20 = load i64, i64* %a20 309 %ld21 = load i64, i64* %a21 310 ret void 311} 312 313define void @negative_offset(i32* %arg) { 314; CHECK-LABEL: @negative_offset(i32* %arg) 315 %ptr = bitcast i32* %arg to float* 316 %arrayidx0 = getelementptr float, float* %ptr, i64 0 317 %arrayidx1 = getelementptr float, float* %ptr, i64 -1 318 %t0 = load float, float* %arrayidx0 319 %t1 = load float, float* %arrayidx1 320 ret void 321} 322 323define void @stores(i32* %arg) { 324; CHECK-LABEL: @stores(i32* %arg) 325 %ptr = bitcast i32* %arg to float* 326 %arrayidx0 = getelementptr float, float* %ptr, i64 0 327 %arrayidx1 = getelementptr float, float* %ptr, i64 1 328 store float 1.0, float* %arrayidx0 329 store float 2.0, float* %arrayidx1 330 ret void 331} 332 333define void @load_store(i32* %arg) { 334; CHECK-LABEL: @load_store(i32* %arg) 335 %ptr = bitcast i32* %arg to float* 336 %arrayidx0 = getelementptr float, float* %ptr, i64 0 337 %arrayidx1 = getelementptr float, float* %ptr, i64 1 338 %t1 = load float, float* %arrayidx0 339 store float 2.0, float* %arrayidx1 340 ret void 341} 342 343define void @different_size1(i32* %arg) { 344; CHECK-LABEL: @different_size1(i32* %arg) 345 %arg-cast = bitcast i32* %arg to double* 346 store double 0.000000e+00, double* %arg-cast 347 store i32 0, i32* %arg 348 ret void 349} 350 351define void @different_size2(i32* %arg) { 352; CHECK-LABEL: @different_size2(i32* %arg) 353 store i32 0, i32* %arg 354 %arg-cast = bitcast i32* %arg to double* 355 store double 0.000000e+00, double* %arg-cast 356 ret void 357} 358