1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes 2; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM 3; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-disable=false -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM 4; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-disable=false -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM 5; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-disable=false -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_OPM,IS__CGSCC____,IS________NPM,IS__CGSCC_NPM 6 7; Determine dereference-ability before unused loads get deleted: 8; https://bugs.llvm.org/show_bug.cgi?id=21780 9 10define <4 x double> @PR21780(double* %ptr) { 11; CHECK-LABEL: define {{[^@]+}}@PR21780 12; CHECK-SAME: (double* nocapture nofree nonnull readonly align 8 dereferenceable(32) [[PTR:%.*]]) 13; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds double, double* [[PTR]], i64 1 14; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds double, double* [[PTR]], i64 2 15; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds double, double* [[PTR]], i64 3 16; CHECK-NEXT: [[T0:%.*]] = load double, double* [[PTR]], align 8 17; CHECK-NEXT: [[T1:%.*]] = load double, double* [[ARRAYIDX1]], align 8 18; CHECK-NEXT: [[T2:%.*]] = load double, double* [[ARRAYIDX2]], align 8 19; CHECK-NEXT: [[T3:%.*]] = load double, double* [[ARRAYIDX3]], align 8 20; CHECK-NEXT: [[VECINIT0:%.*]] = insertelement <4 x double> undef, double [[T0]], i32 0 21; CHECK-NEXT: [[VECINIT1:%.*]] = insertelement <4 x double> [[VECINIT0]], double [[T1]], i32 1 22; CHECK-NEXT: [[VECINIT2:%.*]] = insertelement <4 x double> [[VECINIT1]], double [[T2]], i32 2 23; CHECK-NEXT: [[VECINIT3:%.*]] = insertelement <4 x double> [[VECINIT2]], double [[T3]], i32 3 24; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <4 x double> [[VECINIT3]], <4 x double> [[VECINIT3]], <4 x i32> <i32 0, i32 0, i32 2, i32 2> 25; CHECK-NEXT: ret <4 x double> [[SHUFFLE]] 26; 27 28 ; GEP of index 0 is simplified away. 29 %arrayidx1 = getelementptr inbounds double, double* %ptr, i64 1 30 %arrayidx2 = getelementptr inbounds double, double* %ptr, i64 2 31 %arrayidx3 = getelementptr inbounds double, double* %ptr, i64 3 32 33 %t0 = load double, double* %ptr, align 8 34 %t1 = load double, double* %arrayidx1, align 8 35 %t2 = load double, double* %arrayidx2, align 8 36 %t3 = load double, double* %arrayidx3, align 8 37 38 %vecinit0 = insertelement <4 x double> undef, double %t0, i32 0 39 %vecinit1 = insertelement <4 x double> %vecinit0, double %t1, i32 1 40 %vecinit2 = insertelement <4 x double> %vecinit1, double %t2, i32 2 41 %vecinit3 = insertelement <4 x double> %vecinit2, double %t3, i32 3 42 %shuffle = shufflevector <4 x double> %vecinit3, <4 x double> %vecinit3, <4 x i32> <i32 0, i32 0, i32 2, i32 2> 43 ret <4 x double> %shuffle 44} 45 46 47define double @PR21780_only_access3_with_inbounds(double* %ptr) { 48; CHECK-LABEL: define {{[^@]+}}@PR21780_only_access3_with_inbounds 49; CHECK-SAME: (double* nocapture nofree nonnull readonly align 8 dereferenceable(32) [[PTR:%.*]]) 50; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds double, double* [[PTR]], i64 3 51; CHECK-NEXT: [[T3:%.*]] = load double, double* [[ARRAYIDX3]], align 8 52; CHECK-NEXT: ret double [[T3]] 53; 54 55 %arrayidx3 = getelementptr inbounds double, double* %ptr, i64 3 56 %t3 = load double, double* %arrayidx3, align 8 57 ret double %t3 58} 59 60define double @PR21780_only_access3_without_inbounds(double* %ptr) { 61; CHECK-LABEL: define {{[^@]+}}@PR21780_only_access3_without_inbounds 62; CHECK-SAME: (double* nocapture nofree readonly align 8 [[PTR:%.*]]) 63; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr double, double* [[PTR]], i64 3 64; CHECK-NEXT: [[T3:%.*]] = load double, double* [[ARRAYIDX3]], align 8 65; CHECK-NEXT: ret double [[T3]] 66; 67 %arrayidx3 = getelementptr double, double* %ptr, i64 3 68 %t3 = load double, double* %arrayidx3, align 8 69 ret double %t3 70} 71 72define double @PR21780_without_inbounds(double* %ptr) { 73; CHECK-LABEL: define {{[^@]+}}@PR21780_without_inbounds 74; CHECK-SAME: (double* nocapture nofree nonnull readonly align 8 dereferenceable(32) [[PTR:%.*]]) 75; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr double, double* [[PTR]], i64 3 76; CHECK-NEXT: [[T3:%.*]] = load double, double* [[ARRAYIDX3]], align 8 77; CHECK-NEXT: ret double [[T3]] 78; 79 80 %arrayidx1 = getelementptr double, double* %ptr, i64 1 81 %arrayidx2 = getelementptr double, double* %ptr, i64 2 82 %arrayidx3 = getelementptr double, double* %ptr, i64 3 83 84 %t0 = load double, double* %ptr, align 8 85 %t1 = load double, double* %arrayidx1, align 8 86 %t2 = load double, double* %arrayidx2, align 8 87 %t3 = load double, double* %arrayidx3, align 8 88 89 ret double %t3 90} 91 92; Unsimplified, but still valid. Also, throw in some bogus arguments. 93 94define void @gep0(i8* %unused, i8* %other, i8* %ptr) { 95; CHECK-LABEL: define {{[^@]+}}@gep0 96; CHECK-SAME: (i8* nocapture nofree readnone [[UNUSED:%.*]], i8* nocapture nofree nonnull writeonly dereferenceable(1) [[OTHER:%.*]], i8* nocapture nofree nonnull readonly dereferenceable(3) [[PTR:%.*]]) 97; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr i8, i8* [[PTR]], i64 2 98; CHECK-NEXT: [[T2:%.*]] = load i8, i8* [[ARRAYIDX2]] 99; CHECK-NEXT: store i8 [[T2]], i8* [[OTHER]] 100; CHECK-NEXT: ret void 101; 102 %arrayidx0 = getelementptr i8, i8* %ptr, i64 0 103 %arrayidx1 = getelementptr i8, i8* %ptr, i64 1 104 %arrayidx2 = getelementptr i8, i8* %ptr, i64 2 105 %t0 = load i8, i8* %arrayidx0 106 %t1 = load i8, i8* %arrayidx1 107 %t2 = load i8, i8* %arrayidx2 108 store i8 %t2, i8* %other 109 ret void 110} 111 112; Order of accesses does not change computation. 113; Multiple arguments may be dereferenceable. 114 115define void @ordering(i8* %ptr1, i32* %ptr2) { 116; CHECK-LABEL: define {{[^@]+}}@ordering 117; CHECK-SAME: (i8* nocapture nofree nonnull readnone dereferenceable(3) [[PTR1:%.*]], i32* nocapture nofree nonnull readnone align 4 dereferenceable(8) [[PTR2:%.*]]) 118; CHECK-NEXT: ret void 119; 120 %a20 = getelementptr i32, i32* %ptr2, i64 0 121 %a12 = getelementptr i8, i8* %ptr1, i64 2 122 %t12 = load i8, i8* %a12 123 %a11 = getelementptr i8, i8* %ptr1, i64 1 124 %t20 = load i32, i32* %a20 125 %a10 = getelementptr i8, i8* %ptr1, i64 0 126 %t10 = load i8, i8* %a10 127 %t11 = load i8, i8* %a11 128 %a21 = getelementptr i32, i32* %ptr2, i64 1 129 %t21 = load i32, i32* %a21 130 ret void 131} 132 133; Not in entry block. 134 135define void @not_entry_but_guaranteed_to_execute(i8* %ptr) { 136; CHECK-LABEL: define {{[^@]+}}@not_entry_but_guaranteed_to_execute 137; CHECK-SAME: (i8* nocapture nofree nonnull readnone dereferenceable(3) [[PTR:%.*]]) 138; CHECK-NEXT: entry: 139; CHECK-NEXT: br label [[EXIT:%.*]] 140; CHECK: exit: 141; CHECK-NEXT: ret void 142; 143entry: 144 br label %exit 145exit: 146 %arrayidx0 = getelementptr i8, i8* %ptr, i64 0 147 %arrayidx1 = getelementptr i8, i8* %ptr, i64 1 148 %arrayidx2 = getelementptr i8, i8* %ptr, i64 2 149 %t0 = load i8, i8* %arrayidx0 150 %t1 = load i8, i8* %arrayidx1 151 %t2 = load i8, i8* %arrayidx2 152 ret void 153} 154 155; Not in entry block and not guaranteed to execute. 156 157define void @not_entry_not_guaranteed_to_execute(i8* %ptr, i1 %cond) { 158; CHECK-LABEL: define {{[^@]+}}@not_entry_not_guaranteed_to_execute 159; CHECK-SAME: (i8* nocapture nofree readnone [[PTR:%.*]], i1 [[COND:%.*]]) 160; CHECK-NEXT: entry: 161; CHECK-NEXT: br i1 [[COND]], label [[LOADS:%.*]], label [[EXIT:%.*]] 162; CHECK: loads: 163; CHECK-NEXT: ret void 164; CHECK: exit: 165; CHECK-NEXT: ret void 166; 167entry: 168 br i1 %cond, label %loads, label %exit 169loads: 170 %arrayidx0 = getelementptr i8, i8* %ptr, i64 0 171 %arrayidx1 = getelementptr i8, i8* %ptr, i64 1 172 %arrayidx2 = getelementptr i8, i8* %ptr, i64 2 173 %t0 = load i8, i8* %arrayidx0 174 %t1 = load i8, i8* %arrayidx1 175 %t2 = load i8, i8* %arrayidx2 176 ret void 177exit: 178 ret void 179} 180 181; The last load may not execute, so derefenceable bytes only covers the 1st two loads. 182 183define void @partial_in_entry(i16* %ptr, i1 %cond) { 184; CHECK-LABEL: define {{[^@]+}}@partial_in_entry 185; CHECK-SAME: (i16* nocapture nofree nonnull readnone align 2 dereferenceable(4) [[PTR:%.*]], i1 [[COND:%.*]]) 186; CHECK-NEXT: entry: 187; CHECK-NEXT: br i1 [[COND]], label [[LOADS:%.*]], label [[EXIT:%.*]] 188; CHECK: loads: 189; CHECK-NEXT: ret void 190; CHECK: exit: 191; CHECK-NEXT: ret void 192; 193entry: 194 %arrayidx0 = getelementptr i16, i16* %ptr, i64 0 195 %arrayidx1 = getelementptr i16, i16* %ptr, i64 1 196 %arrayidx2 = getelementptr i16, i16* %ptr, i64 2 197 %t0 = load i16, i16* %arrayidx0 198 %t1 = load i16, i16* %arrayidx1 199 br i1 %cond, label %loads, label %exit 200loads: 201 %t2 = load i16, i16* %arrayidx2 202 ret void 203exit: 204 ret void 205} 206 207; The volatile load can't be used to prove a non-volatile access is allowed. 208; The 2nd and 3rd loads may never execute. 209 210define void @volatile_is_not_dereferenceable(i16* %ptr) { 211; CHECK-LABEL: define {{[^@]+}}@volatile_is_not_dereferenceable 212; CHECK-SAME: (i16* nofree align 2 [[PTR:%.*]]) 213; CHECK-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i16, i16* [[PTR]], i64 0 214; CHECK-NEXT: [[T0:%.*]] = load volatile i16, i16* [[ARRAYIDX0]], align 2 215; CHECK-NEXT: ret void 216; 217 %arrayidx0 = getelementptr i16, i16* %ptr, i64 0 218 %arrayidx1 = getelementptr i16, i16* %ptr, i64 1 219 %arrayidx2 = getelementptr i16, i16* %ptr, i64 2 220 %t0 = load volatile i16, i16* %arrayidx0 221 %t1 = load i16, i16* %arrayidx1 222 %t2 = load i16, i16* %arrayidx2 223 ret void 224} 225 226; TODO: We should allow inference for atomic (but not volatile) ops. 227 228define void @atomic_is_alright(i16* %ptr) { 229; CHECK-LABEL: define {{[^@]+}}@atomic_is_alright 230; CHECK-SAME: (i16* nocapture nofree nonnull readnone align 2 dereferenceable(6) [[PTR:%.*]]) 231; CHECK-NEXT: ret void 232; 233 %arrayidx0 = getelementptr i16, i16* %ptr, i64 0 234 %arrayidx1 = getelementptr i16, i16* %ptr, i64 1 235 %arrayidx2 = getelementptr i16, i16* %ptr, i64 2 236 %t0 = load atomic i16, i16* %arrayidx0 unordered, align 2 237 %t1 = load i16, i16* %arrayidx1 238 %t2 = load i16, i16* %arrayidx2 239 ret void 240} 241 242declare void @may_not_return() 243 244define void @not_guaranteed_to_transfer_execution(i16* %ptr) { 245; CHECK-LABEL: define {{[^@]+}}@not_guaranteed_to_transfer_execution 246; CHECK-SAME: (i16* nocapture nofree nonnull readnone align 2 dereferenceable(2) [[PTR:%.*]]) 247; CHECK-NEXT: call void @may_not_return() 248; CHECK-NEXT: ret void 249; 250 %arrayidx0 = getelementptr i16, i16* %ptr, i64 0 251 %arrayidx1 = getelementptr i16, i16* %ptr, i64 1 252 %arrayidx2 = getelementptr i16, i16* %ptr, i64 2 253 %t0 = load i16, i16* %arrayidx0 254 call void @may_not_return() 255 %t1 = load i16, i16* %arrayidx1 256 %t2 = load i16, i16* %arrayidx2 257 ret void 258} 259 260; We must have consecutive accesses. 261 262define void @variable_gep_index(i8* %unused, i8* %ptr, i64 %variable_index) { 263; CHECK-LABEL: define {{[^@]+}}@variable_gep_index 264; CHECK-SAME: (i8* nocapture nofree readnone [[UNUSED:%.*]], i8* nocapture nofree nonnull readnone dereferenceable(1) [[PTR:%.*]], i64 [[VARIABLE_INDEX:%.*]]) 265; CHECK-NEXT: ret void 266; 267 %arrayidx1 = getelementptr i8, i8* %ptr, i64 %variable_index 268 %arrayidx2 = getelementptr i8, i8* %ptr, i64 2 269 %t0 = load i8, i8* %ptr 270 %t1 = load i8, i8* %arrayidx1 271 %t2 = load i8, i8* %arrayidx2 272 ret void 273} 274 275; Deal with >1 GEP index. 276 277define void @multi_index_gep(<4 x i8>* %ptr) { 278; FIXME: %ptr should be dereferenceable(4) 279; CHECK-LABEL: define {{[^@]+}}@multi_index_gep 280; CHECK-SAME: (<4 x i8>* nocapture nofree nonnull readnone dereferenceable(1) [[PTR:%.*]]) 281; CHECK-NEXT: ret void 282; 283 %arrayidx00 = getelementptr <4 x i8>, <4 x i8>* %ptr, i64 0, i64 0 284 %t0 = load i8, i8* %arrayidx00 285 ret void 286} 287 288; Could round weird bitwidths down? 289 290define void @not_byte_multiple(i9* %ptr) { 291; CHECK-LABEL: define {{[^@]+}}@not_byte_multiple 292; CHECK-SAME: (i9* nocapture nofree nonnull readnone align 2 dereferenceable(2) [[PTR:%.*]]) 293; CHECK-NEXT: ret void 294; 295 %arrayidx0 = getelementptr i9, i9* %ptr, i64 0 296 %t0 = load i9, i9* %arrayidx0 297 ret void 298} 299 300; Missing direct access from the pointer. 301 302define void @no_pointer_deref(i16* %ptr) { 303; CHECK-LABEL: define {{[^@]+}}@no_pointer_deref 304; CHECK-SAME: (i16* nocapture nofree readnone align 2 [[PTR:%.*]]) 305; CHECK-NEXT: ret void 306; 307 %arrayidx1 = getelementptr i16, i16* %ptr, i64 1 308 %arrayidx2 = getelementptr i16, i16* %ptr, i64 2 309 %t1 = load i16, i16* %arrayidx1 310 %t2 = load i16, i16* %arrayidx2 311 ret void 312} 313 314; Out-of-order is ok, but missing access concludes dereferenceable range. 315 316define void @non_consecutive(i32* %ptr) { 317; CHECK-LABEL: define {{[^@]+}}@non_consecutive 318; CHECK-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(8) [[PTR:%.*]]) 319; CHECK-NEXT: ret void 320; 321 %arrayidx1 = getelementptr i32, i32* %ptr, i64 1 322 %arrayidx0 = getelementptr i32, i32* %ptr, i64 0 323 %arrayidx3 = getelementptr i32, i32* %ptr, i64 3 324 %t1 = load i32, i32* %arrayidx1 325 %t0 = load i32, i32* %arrayidx0 326 %t3 = load i32, i32* %arrayidx3 327 ret void 328} 329 330; Improve on existing dereferenceable attribute. 331 332define void @more_bytes(i32* dereferenceable(8) %ptr) { 333; CHECK-LABEL: define {{[^@]+}}@more_bytes 334; CHECK-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(16) [[PTR:%.*]]) 335; CHECK-NEXT: ret void 336; 337 %arrayidx3 = getelementptr i32, i32* %ptr, i64 3 338 %arrayidx1 = getelementptr i32, i32* %ptr, i64 1 339 %arrayidx0 = getelementptr i32, i32* %ptr, i64 0 340 %arrayidx2 = getelementptr i32, i32* %ptr, i64 2 341 %t3 = load i32, i32* %arrayidx3 342 %t1 = load i32, i32* %arrayidx1 343 %t2 = load i32, i32* %arrayidx2 344 %t0 = load i32, i32* %arrayidx0 345 ret void 346} 347 348; Improve on existing dereferenceable_or_null attribute. 349 350define void @more_bytes_and_not_null(i32* dereferenceable_or_null(8) %ptr) { 351; CHECK-LABEL: define {{[^@]+}}@more_bytes_and_not_null 352; CHECK-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(16) [[PTR:%.*]]) 353; CHECK-NEXT: ret void 354; 355 %arrayidx3 = getelementptr i32, i32* %ptr, i64 3 356 %arrayidx1 = getelementptr i32, i32* %ptr, i64 1 357 %arrayidx0 = getelementptr i32, i32* %ptr, i64 0 358 %arrayidx2 = getelementptr i32, i32* %ptr, i64 2 359 %t3 = load i32, i32* %arrayidx3 360 %t1 = load i32, i32* %arrayidx1 361 %t2 = load i32, i32* %arrayidx2 362 %t0 = load i32, i32* %arrayidx0 363 ret void 364} 365 366; But don't pessimize existing dereferenceable attribute. 367 368define void @better_bytes(i32* dereferenceable(100) %ptr) { 369; CHECK-LABEL: define {{[^@]+}}@better_bytes 370; CHECK-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(100) [[PTR:%.*]]) 371; CHECK-NEXT: ret void 372; 373 %arrayidx3 = getelementptr i32, i32* %ptr, i64 3 374 %arrayidx1 = getelementptr i32, i32* %ptr, i64 1 375 %arrayidx0 = getelementptr i32, i32* %ptr, i64 0 376 %arrayidx2 = getelementptr i32, i32* %ptr, i64 2 377 %t3 = load i32, i32* %arrayidx3 378 %t1 = load i32, i32* %arrayidx1 379 %t2 = load i32, i32* %arrayidx2 380 %t0 = load i32, i32* %arrayidx0 381 ret void 382} 383 384define void @bitcast(i32* %arg) { 385; CHECK-LABEL: define {{[^@]+}}@bitcast 386; CHECK-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(8) [[ARG:%.*]]) 387; CHECK-NEXT: ret void 388; 389 %ptr = bitcast i32* %arg to float* 390 %arrayidx0 = getelementptr float, float* %ptr, i64 0 391 %arrayidx1 = getelementptr float, float* %ptr, i64 1 392 %t0 = load float, float* %arrayidx0 393 %t1 = load float, float* %arrayidx1 394 ret void 395} 396 397define void @bitcast_different_sizes(double* %arg1, i8* %arg2) { 398; CHECK-LABEL: define {{[^@]+}}@bitcast_different_sizes 399; CHECK-SAME: (double* nocapture nofree nonnull readnone align 4 dereferenceable(12) [[ARG1:%.*]], i8* nocapture nofree nonnull readnone align 4 dereferenceable(16) [[ARG2:%.*]]) 400; CHECK-NEXT: ret void 401; 402 %ptr1 = bitcast double* %arg1 to float* 403 %a10 = getelementptr float, float* %ptr1, i64 0 404 %a11 = getelementptr float, float* %ptr1, i64 1 405 %a12 = getelementptr float, float* %ptr1, i64 2 406 %ld10 = load float, float* %a10 407 %ld11 = load float, float* %a11 408 %ld12 = load float, float* %a12 409 410 %ptr2 = bitcast i8* %arg2 to i64* 411 %a20 = getelementptr i64, i64* %ptr2, i64 0 412 %a21 = getelementptr i64, i64* %ptr2, i64 1 413 %ld20 = load i64, i64* %a20 414 %ld21 = load i64, i64* %a21 415 ret void 416} 417 418define void @negative_offset(i32* %arg) { 419; CHECK-LABEL: define {{[^@]+}}@negative_offset 420; CHECK-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(4) [[ARG:%.*]]) 421; CHECK-NEXT: ret void 422; 423 %ptr = bitcast i32* %arg to float* 424 %arrayidx0 = getelementptr float, float* %ptr, i64 0 425 %arrayidx1 = getelementptr float, float* %ptr, i64 -1 426 %t0 = load float, float* %arrayidx0 427 %t1 = load float, float* %arrayidx1 428 ret void 429} 430 431define void @stores(i32* %arg) { 432; CHECK-LABEL: define {{[^@]+}}@stores 433; CHECK-SAME: (i32* nocapture nofree nonnull writeonly align 4 dereferenceable(8) [[ARG:%.*]]) 434; CHECK-NEXT: [[PTR:%.*]] = bitcast i32* [[ARG]] to float* 435; CHECK-NEXT: [[ARRAYIDX0:%.*]] = getelementptr float, float* [[PTR]], i64 0 436; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr float, float* [[PTR]], i64 1 437; CHECK-NEXT: store float 1.000000e+00, float* [[ARRAYIDX0]], align 4 438; CHECK-NEXT: store float 2.000000e+00, float* [[ARRAYIDX1]], align 4 439; CHECK-NEXT: ret void 440; 441 %ptr = bitcast i32* %arg to float* 442 %arrayidx0 = getelementptr float, float* %ptr, i64 0 443 %arrayidx1 = getelementptr float, float* %ptr, i64 1 444 store float 1.0, float* %arrayidx0 445 store float 2.0, float* %arrayidx1 446 ret void 447} 448 449define void @load_store(i32* %arg) { 450; CHECK-LABEL: define {{[^@]+}}@load_store 451; CHECK-SAME: (i32* nocapture nofree nonnull writeonly align 4 dereferenceable(8) [[ARG:%.*]]) 452; CHECK-NEXT: [[PTR:%.*]] = bitcast i32* [[ARG]] to float* 453; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr float, float* [[PTR]], i64 1 454; CHECK-NEXT: store float 2.000000e+00, float* [[ARRAYIDX1]], align 4 455; CHECK-NEXT: ret void 456; 457 %ptr = bitcast i32* %arg to float* 458 %arrayidx0 = getelementptr float, float* %ptr, i64 0 459 %arrayidx1 = getelementptr float, float* %ptr, i64 1 460 %t1 = load float, float* %arrayidx0 461 store float 2.0, float* %arrayidx1 462 ret void 463} 464 465define void @different_size1(i32* %arg) { 466; CHECK-LABEL: define {{[^@]+}}@different_size1 467; CHECK-SAME: (i32* nocapture nofree nonnull writeonly align 8 dereferenceable(8) [[ARG:%.*]]) 468; CHECK-NEXT: [[ARG_CAST:%.*]] = bitcast i32* [[ARG]] to double* 469; CHECK-NEXT: store double 0.000000e+00, double* [[ARG_CAST]], align 8 470; CHECK-NEXT: store i32 0, i32* [[ARG]], align 8 471; CHECK-NEXT: ret void 472; 473 %arg-cast = bitcast i32* %arg to double* 474 store double 0.000000e+00, double* %arg-cast 475 store i32 0, i32* %arg 476 ret void 477} 478 479define void @different_size2(i32* %arg) { 480; CHECK-LABEL: define {{[^@]+}}@different_size2 481; CHECK-SAME: (i32* nocapture nofree nonnull writeonly align 8 dereferenceable(8) [[ARG:%.*]]) 482; CHECK-NEXT: store i32 0, i32* [[ARG]], align 8 483; CHECK-NEXT: [[ARG_CAST:%.*]] = bitcast i32* [[ARG]] to double* 484; CHECK-NEXT: store double 0.000000e+00, double* [[ARG_CAST]], align 8 485; CHECK-NEXT: ret void 486; 487 store i32 0, i32* %arg 488 %arg-cast = bitcast i32* %arg to double* 489 store double 0.000000e+00, double* %arg-cast 490 ret void 491} 492 493; Make use of MustBeExecuted Explorer 494; 495; [CFG] 496; entry 497; / \ 498; l1 l2 499; | X | 500; l3 l4 501; \ / 502; l5 503; / \ 504; l6 l7 505; \ / 506; end 507; According to the above CFG, we can see that instructions in l5 Block must be executed. 508; Therefore, %p must be dereferenced. 509; 510; ATTRIBUTOR_CGSCC_NPM-LABEL: define i32 @require_cfg_analysis(i32 %c, i32* {{.*}} dereferenceable(4) %p) 511define i32 @require_cfg_analysis(i32 %c, i32* %p) { 512; IS________OPM-LABEL: define {{[^@]+}}@require_cfg_analysis 513; IS________OPM-SAME: (i32 [[C:%.*]], i32* nocapture nofree writeonly [[P:%.*]]) 514; IS________OPM-NEXT: [[TOBOOL1:%.*]] = icmp eq i32 [[C]], 0 515; IS________OPM-NEXT: br i1 [[TOBOOL1]], label [[L1:%.*]], label [[L2:%.*]] 516; IS________OPM: l1: 517; IS________OPM-NEXT: [[TOBOOL2:%.*]] = icmp eq i32 [[C]], 1 518; IS________OPM-NEXT: br i1 [[TOBOOL2]], label [[L3:%.*]], label [[L4:%.*]] 519; IS________OPM: l2: 520; IS________OPM-NEXT: [[TOBOOL3:%.*]] = icmp eq i32 [[C]], 2 521; IS________OPM-NEXT: br i1 [[TOBOOL3]], label [[L3]], label [[L4]] 522; IS________OPM: l3: 523; IS________OPM-NEXT: br label [[L5:%.*]] 524; IS________OPM: l4: 525; IS________OPM-NEXT: br label [[L5]] 526; IS________OPM: l5: 527; IS________OPM-NEXT: [[TOBOOL4:%.*]] = icmp eq i32 [[C]], 4 528; IS________OPM-NEXT: br i1 [[TOBOOL4]], label [[L6:%.*]], label [[L7:%.*]] 529; IS________OPM: l6: 530; IS________OPM-NEXT: store i32 0, i32* [[P]] 531; IS________OPM-NEXT: br label [[END:%.*]] 532; IS________OPM: l7: 533; IS________OPM-NEXT: store i32 1, i32* [[P]] 534; IS________OPM-NEXT: br label [[END]] 535; IS________OPM: end: 536; IS________OPM-NEXT: ret i32 1 537; 538; IS________NPM-LABEL: define {{[^@]+}}@require_cfg_analysis 539; IS________NPM-SAME: (i32 [[C:%.*]], i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[P:%.*]]) 540; IS________NPM-NEXT: [[TOBOOL1:%.*]] = icmp eq i32 [[C]], 0 541; IS________NPM-NEXT: br i1 [[TOBOOL1]], label [[L1:%.*]], label [[L2:%.*]] 542; IS________NPM: l1: 543; IS________NPM-NEXT: br label [[L4:%.*]] 544; IS________NPM: l2: 545; IS________NPM-NEXT: [[TOBOOL3:%.*]] = icmp eq i32 [[C]], 2 546; IS________NPM-NEXT: br i1 [[TOBOOL3]], label [[L3:%.*]], label [[L4]] 547; IS________NPM: l3: 548; IS________NPM-NEXT: br label [[L5:%.*]] 549; IS________NPM: l4: 550; IS________NPM-NEXT: br label [[L5]] 551; IS________NPM: l5: 552; IS________NPM-NEXT: [[TOBOOL4:%.*]] = icmp eq i32 [[C]], 4 553; IS________NPM-NEXT: br i1 [[TOBOOL4]], label [[L6:%.*]], label [[L7:%.*]] 554; IS________NPM: l6: 555; IS________NPM-NEXT: store i32 0, i32* [[P]], align 4 556; IS________NPM-NEXT: br label [[END:%.*]] 557; IS________NPM: l7: 558; IS________NPM-NEXT: store i32 1, i32* [[P]], align 4 559; IS________NPM-NEXT: br label [[END]] 560; IS________NPM: end: 561; IS________NPM-NEXT: ret i32 1 562; 563 %tobool1 = icmp eq i32 %c, 0 564 br i1 %tobool1, label %l1, label %l2 565l1: 566 %tobool2 = icmp eq i32 %c, 1 567 br i1 %tobool2, label %l3, label %l4 568l2: 569 %tobool3 = icmp eq i32 %c, 2 570 br i1 %tobool3, label %l3, label %l4 571l3: 572 br label %l5 573l4: 574 br label %l5 575l5: 576 %tobool4 = icmp eq i32 %c, 4 577 br i1 %tobool4, label %l6, label %l7 578l6: 579 store i32 0, i32* %p 580 br label %end 581l7: 582 store i32 1, i32* %p 583 br label %end 584end: 585 ret i32 1 586} 587