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