brintos

brintos / llvm-project-archived public Read only

0
0
Text · 22.6 KiB · 52129e8 Raw
574 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals2; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal  -attributor-annotate-decl-cs  -S < %s | FileCheck %s --check-prefixes=CHECK,TUNIT3; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal  -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,CGSCC4 5; Determine dereference-ability before unused loads get deleted:6; https://bugs.llvm.org/show_bug.cgi?id=217807 8define <4 x double> @PR21780(ptr %ptr) {9; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read)10; CHECK-LABEL: define {{[^@]+}}@PR2178011; CHECK-SAME: (ptr nofree noundef nonnull readonly align 8 captures(none) dereferenceable(32) [[PTR:%.*]]) #[[ATTR0:[0-9]+]] {12; CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds double, ptr [[PTR]], i64 113; CHECK-NEXT:    [[ARRAYIDX2:%.*]] = getelementptr inbounds double, ptr [[PTR]], i64 214; CHECK-NEXT:    [[ARRAYIDX3:%.*]] = getelementptr inbounds double, ptr [[PTR]], i64 315; CHECK-NEXT:    [[T0:%.*]] = load double, ptr [[PTR]], align 816; CHECK-NEXT:    [[T1:%.*]] = load double, ptr [[ARRAYIDX1]], align 817; CHECK-NEXT:    [[T2:%.*]] = load double, ptr [[ARRAYIDX2]], align 818; CHECK-NEXT:    [[T3:%.*]] = load double, ptr [[ARRAYIDX3]], align 819; CHECK-NEXT:    [[VECINIT0:%.*]] = insertelement <4 x double> undef, double [[T0]], i32 020; CHECK-NEXT:    [[VECINIT1:%.*]] = insertelement <4 x double> [[VECINIT0]], double [[T1]], i32 121; CHECK-NEXT:    [[VECINIT2:%.*]] = insertelement <4 x double> [[VECINIT1]], double [[T2]], i32 222; CHECK-NEXT:    [[VECINIT3:%.*]] = insertelement <4 x double> [[VECINIT2]], double [[T3]], i32 323; CHECK-NEXT:    [[SHUFFLE:%.*]] = shufflevector <4 x double> [[VECINIT3]], <4 x double> [[VECINIT3]], <4 x i32> <i32 0, i32 0, i32 2, i32 2>24; CHECK-NEXT:    ret <4 x double> [[SHUFFLE]]25;26 27  ; GEP of index 0 is simplified away.28  %arrayidx1 = getelementptr inbounds double, ptr %ptr, i64 129  %arrayidx2 = getelementptr inbounds double, ptr %ptr, i64 230  %arrayidx3 = getelementptr inbounds double, ptr %ptr, i64 331 32  %t0 = load double, ptr %ptr, align 833  %t1 = load double, ptr %arrayidx1, align 834  %t2 = load double, ptr %arrayidx2, align 835  %t3 = load double, ptr %arrayidx3, align 836 37  %vecinit0 = insertelement <4 x double> undef, double %t0, i32 038  %vecinit1 = insertelement <4 x double> %vecinit0, double %t1, i32 139  %vecinit2 = insertelement <4 x double> %vecinit1, double %t2, i32 240  %vecinit3 = insertelement <4 x double> %vecinit2, double %t3, i32 341  %shuffle = shufflevector <4 x double> %vecinit3, <4 x double> %vecinit3, <4 x i32> <i32 0, i32 0, i32 2, i32 2>42  ret <4 x double> %shuffle43}44 45 46define double @PR21780_only_access3_with_inbounds(ptr %ptr) {47; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read)48; CHECK-LABEL: define {{[^@]+}}@PR21780_only_access3_with_inbounds49; CHECK-SAME: (ptr nofree nonnull readonly align 8 captures(none) dereferenceable(32) [[PTR:%.*]]) #[[ATTR0]] {50; CHECK-NEXT:    [[ARRAYIDX3:%.*]] = getelementptr inbounds double, ptr [[PTR]], i64 351; CHECK-NEXT:    [[T3:%.*]] = load double, ptr [[ARRAYIDX3]], align 852; CHECK-NEXT:    ret double [[T3]]53;54 55  %arrayidx3 = getelementptr inbounds double, ptr %ptr, i64 356  %t3 = load double, ptr %arrayidx3, align 857  ret double %t358}59 60define double @PR21780_only_access3_without_inbounds(ptr %ptr) {61; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read)62; CHECK-LABEL: define {{[^@]+}}@PR21780_only_access3_without_inbounds63; CHECK-SAME: (ptr nofree readonly align 8 captures(none) [[PTR:%.*]]) #[[ATTR0]] {64; CHECK-NEXT:    [[ARRAYIDX3:%.*]] = getelementptr double, ptr [[PTR]], i64 365; CHECK-NEXT:    [[T3:%.*]] = load double, ptr [[ARRAYIDX3]], align 866; CHECK-NEXT:    ret double [[T3]]67;68  %arrayidx3 = getelementptr double, ptr %ptr, i64 369  %t3 = load double, ptr %arrayidx3, align 870  ret double %t371}72 73define double @PR21780_without_inbounds(ptr %ptr) {74; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read)75; CHECK-LABEL: define {{[^@]+}}@PR21780_without_inbounds76; CHECK-SAME: (ptr nofree noundef nonnull readonly align 8 captures(none) dereferenceable(32) [[PTR:%.*]]) #[[ATTR0]] {77; CHECK-NEXT:    [[ARRAYIDX3:%.*]] = getelementptr double, ptr [[PTR]], i64 378; CHECK-NEXT:    [[T3:%.*]] = load double, ptr [[ARRAYIDX3]], align 879; CHECK-NEXT:    ret double [[T3]]80;81 82  %arrayidx1 = getelementptr double, ptr %ptr, i64 183  %arrayidx2 = getelementptr double, ptr %ptr, i64 284  %arrayidx3 = getelementptr double, ptr %ptr, i64 385 86  %t0 = load double, ptr %ptr, align 887  %t1 = load double, ptr %arrayidx1, align 888  %t2 = load double, ptr %arrayidx2, align 889  %t3 = load double, ptr %arrayidx3, align 890 91  ret double %t392}93 94; Unsimplified, but still valid. Also, throw in some bogus arguments.95 96define void @gep0(ptr %unused, ptr %other, ptr %ptr) {97; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite)98; CHECK-LABEL: define {{[^@]+}}@gep099; CHECK-SAME: (ptr nofree readnone captures(none) [[UNUSED:%.*]], ptr nofree noundef nonnull writeonly captures(none) dereferenceable(1) [[OTHER:%.*]], ptr nofree nonnull readonly captures(none) dereferenceable(3) [[PTR:%.*]]) #[[ATTR1:[0-9]+]] {100; CHECK-NEXT:    [[ARRAYIDX2:%.*]] = getelementptr i8, ptr [[PTR]], i64 2101; CHECK-NEXT:    [[T2:%.*]] = load i8, ptr [[ARRAYIDX2]], align 1102; CHECK-NEXT:    store i8 [[T2]], ptr [[OTHER]], align 1103; CHECK-NEXT:    ret void104;105  %arrayidx0 = getelementptr i8, ptr %ptr, i64 0106  %arrayidx1 = getelementptr i8, ptr %ptr, i64 1107  %arrayidx2 = getelementptr i8, ptr %ptr, i64 2108  %t0 = load i8, ptr %arrayidx0109  %t1 = load i8, ptr %arrayidx1110  %t2 = load i8, ptr %arrayidx2111  store i8 %t2, ptr %other112  ret void113}114 115; Order of accesses does not change computation.116; Multiple arguments may be dereferenceable.117 118define void @ordering(ptr %ptr1, ptr %ptr2) {119; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)120; CHECK-LABEL: define {{[^@]+}}@ordering121; CHECK-SAME: (ptr nofree noundef nonnull readnone captures(none) dereferenceable(3) [[PTR1:%.*]], ptr nofree nonnull readnone align 4 captures(none) dereferenceable(8) [[PTR2:%.*]]) #[[ATTR2:[0-9]+]] {122; CHECK-NEXT:    ret void123;124  %a20 = getelementptr i32, ptr %ptr2, i64 0125  %a12 = getelementptr i8, ptr %ptr1, i64 2126  %t12 = load i8, ptr %a12127  %a11 = getelementptr i8, ptr %ptr1, i64 1128  %t20 = load i32, ptr %a20129  %t10 = load i8, ptr %ptr1130  %t11 = load i8, ptr %a11131  %a21 = getelementptr i32, ptr %ptr2, i64 1132  %t21 = load i32, ptr %a21133  ret void134}135 136; Not in entry block.137 138define void @not_entry_but_guaranteed_to_execute(ptr %ptr) {139; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)140; CHECK-LABEL: define {{[^@]+}}@not_entry_but_guaranteed_to_execute141; CHECK-SAME: (ptr nofree nonnull readnone captures(none) dereferenceable(3) [[PTR:%.*]]) #[[ATTR2]] {142; CHECK-NEXT:  entry:143; CHECK-NEXT:    br label [[EXIT:%.*]]144; CHECK:       exit:145; CHECK-NEXT:    ret void146;147entry:148  br label %exit149exit:150  %arrayidx1 = getelementptr i8, ptr %ptr, i64 1151  %arrayidx2 = getelementptr i8, ptr %ptr, i64 2152  %t0 = load i8, ptr %ptr153  %t1 = load i8, ptr %arrayidx1154  %t2 = load i8, ptr %arrayidx2155  ret void156}157 158; Not in entry block and not guaranteed to execute.159 160define void @not_entry_not_guaranteed_to_execute(ptr %ptr, i1 %cond) {161; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)162; CHECK-LABEL: define {{[^@]+}}@not_entry_not_guaranteed_to_execute163; CHECK-SAME: (ptr nofree readnone captures(none) [[PTR:%.*]], i1 noundef [[COND:%.*]]) #[[ATTR2]] {164; CHECK-NEXT:  entry:165; CHECK-NEXT:    br i1 [[COND]], label [[LOADS:%.*]], label [[EXIT:%.*]]166; CHECK:       loads:167; CHECK-NEXT:    ret void168; CHECK:       exit:169; CHECK-NEXT:    ret void170;171entry:172  br i1 %cond, label %loads, label %exit173loads:174  %arrayidx1 = getelementptr i8, ptr %ptr, i64 1175  %arrayidx2 = getelementptr i8, ptr %ptr, i64 2176  %t0 = load i8, ptr %ptr177  %t1 = load i8, ptr %arrayidx1178  %t2 = load i8, ptr %arrayidx2179  ret void180exit:181  ret void182}183 184; The last load may not execute, so derefenceable bytes only covers the 1st two loads.185 186define void @partial_in_entry(ptr %ptr, i1 %cond) {187; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)188; CHECK-LABEL: define {{[^@]+}}@partial_in_entry189; CHECK-SAME: (ptr nofree noundef nonnull readnone align 2 captures(none) dereferenceable(4) [[PTR:%.*]], i1 noundef [[COND:%.*]]) #[[ATTR2]] {190; CHECK-NEXT:  entry:191; CHECK-NEXT:    br i1 [[COND]], label [[LOADS:%.*]], label [[EXIT:%.*]]192; CHECK:       loads:193; CHECK-NEXT:    ret void194; CHECK:       exit:195; CHECK-NEXT:    ret void196;197entry:198  %arrayidx1 = getelementptr i16, ptr %ptr, i64 1199  %arrayidx2 = getelementptr i16, ptr %ptr, i64 2200  %t0 = load i16, ptr %ptr201  %t1 = load i16, ptr %arrayidx1202  br i1 %cond, label %loads, label %exit203loads:204  %t2 = load i16, ptr %arrayidx2205  ret void206exit:207  ret void208}209 210; The volatile load can't be used to prove a non-volatile access is allowed.211; The 2nd and 3rd loads may never execute.212 213define void @volatile_is_not_dereferenceable(ptr %ptr) {214; CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite)215; CHECK-LABEL: define {{[^@]+}}@volatile_is_not_dereferenceable216; CHECK-SAME: (ptr nofree align 2 [[PTR:%.*]]) #[[ATTR3:[0-9]+]] {217; CHECK-NEXT:    [[T0:%.*]] = load volatile i16, ptr [[PTR]], align 2218; CHECK-NEXT:    ret void219;220  %arrayidx0 = getelementptr i16, ptr %ptr, i64 0221  %arrayidx1 = getelementptr i16, ptr %ptr, i64 1222  %arrayidx2 = getelementptr i16, ptr %ptr, i64 2223  %t0 = load volatile i16, ptr %arrayidx0224  %t1 = load i16, ptr %arrayidx1225  %t2 = load i16, ptr %arrayidx2226  ret void227}228 229; TODO: We should allow inference for atomic (but not volatile) ops.230 231define void @atomic_is_alright(ptr %ptr) {232; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)233; CHECK-LABEL: define {{[^@]+}}@atomic_is_alright234; CHECK-SAME: (ptr nofree nonnull readnone align 2 captures(none) dereferenceable(6) [[PTR:%.*]]) #[[ATTR2]] {235; CHECK-NEXT:    ret void236;237  %arrayidx0 = getelementptr i16, ptr %ptr, i64 0238  %arrayidx1 = getelementptr i16, ptr %ptr, i64 1239  %arrayidx2 = getelementptr i16, ptr %ptr, i64 2240  %t0 = load atomic i16, ptr %arrayidx0 unordered, align 2241  %t1 = load i16, ptr %arrayidx1242  %t2 = load i16, ptr %arrayidx2243  ret void244}245 246declare void @may_not_return()247 248define void @not_guaranteed_to_transfer_execution(ptr %ptr) {249; CHECK-LABEL: define {{[^@]+}}@not_guaranteed_to_transfer_execution250; CHECK-SAME: (ptr nofree nonnull readnone align 2 captures(none) dereferenceable(2) [[PTR:%.*]]) {251; CHECK-NEXT:    call void @may_not_return()252; CHECK-NEXT:    ret void253;254  %arrayidx0 = getelementptr i16, ptr %ptr, i64 0255  %arrayidx1 = getelementptr i16, ptr %ptr, i64 1256  %arrayidx2 = getelementptr i16, ptr %ptr, i64 2257  %t0 = load i16, ptr %arrayidx0258  call void @may_not_return()259  %t1 = load i16, ptr %arrayidx1260  %t2 = load i16, ptr %arrayidx2261  ret void262}263 264; We must have consecutive accesses.265 266define void @variable_gep_index(ptr %unused, ptr %ptr, i64 %variable_index) {267; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)268; CHECK-LABEL: define {{[^@]+}}@variable_gep_index269; CHECK-SAME: (ptr nofree readnone captures(none) [[UNUSED:%.*]], ptr nofree noundef nonnull readnone captures(none) dereferenceable(1) [[PTR:%.*]], i64 [[VARIABLE_INDEX:%.*]]) #[[ATTR2]] {270; CHECK-NEXT:    ret void271;272  %arrayidx1 = getelementptr i8, ptr %ptr, i64 %variable_index273  %arrayidx2 = getelementptr i8, ptr %ptr, i64 2274  %t0 = load i8, ptr %ptr275  %t1 = load i8, ptr %arrayidx1276  %t2 = load i8, ptr %arrayidx2277  ret void278}279 280; Deal with >1 GEP index.281 282define void @multi_index_gep(ptr %ptr) {283; FIXME: %ptr should be dereferenceable(4)284; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)285; CHECK-LABEL: define {{[^@]+}}@multi_index_gep286; CHECK-SAME: (ptr nofree nonnull readnone captures(none) dereferenceable(1) [[PTR:%.*]]) #[[ATTR2]] {287; CHECK-NEXT:    ret void288;289  %arrayidx00 = getelementptr <4 x i8>, ptr %ptr, i64 0, i64 0290  %t0 = load i8, ptr %arrayidx00291  ret void292}293 294; Could round weird bitwidths down?295 296define void @not_byte_multiple(ptr %ptr) {297; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)298; CHECK-LABEL: define {{[^@]+}}@not_byte_multiple299; CHECK-SAME: (ptr nofree nonnull readnone align 2 captures(none) dereferenceable(2) [[PTR:%.*]]) #[[ATTR2]] {300; CHECK-NEXT:    ret void301;302  %arrayidx0 = getelementptr i9, ptr %ptr, i64 0303  %t0 = load i9, ptr %arrayidx0304  ret void305}306 307; Missing direct access from the pointer.308 309define void @no_pointer_deref(ptr %ptr) {310; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)311; CHECK-LABEL: define {{[^@]+}}@no_pointer_deref312; CHECK-SAME: (ptr nofree readnone align 2 captures(none) [[PTR:%.*]]) #[[ATTR2]] {313; CHECK-NEXT:    ret void314;315  %arrayidx1 = getelementptr i16, ptr %ptr, i64 1316  %arrayidx2 = getelementptr i16, ptr %ptr, i64 2317  %t1 = load i16, ptr %arrayidx1318  %t2 = load i16, ptr %arrayidx2319  ret void320}321 322; Out-of-order is ok, but missing access concludes dereferenceable range.323 324define void @non_consecutive(ptr %ptr) {325; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)326; CHECK-LABEL: define {{[^@]+}}@non_consecutive327; CHECK-SAME: (ptr nofree noundef nonnull readnone align 4 captures(none) dereferenceable(8) [[PTR:%.*]]) #[[ATTR2]] {328; CHECK-NEXT:    ret void329;330  %arrayidx1 = getelementptr i32, ptr %ptr, i64 1331  %arrayidx3 = getelementptr i32, ptr %ptr, i64 3332  %t1 = load i32, ptr %arrayidx1333  %t0 = load i32, ptr %ptr334  %t3 = load i32, ptr %arrayidx3335  ret void336}337 338; Improve on existing dereferenceable attribute.339 340define void @more_bytes(ptr dereferenceable(8) %ptr) {341; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)342; CHECK-LABEL: define {{[^@]+}}@more_bytes343; CHECK-SAME: (ptr nofree noundef nonnull readnone align 4 captures(none) dereferenceable(16) [[PTR:%.*]]) #[[ATTR2]] {344; CHECK-NEXT:    ret void345;346  %arrayidx3 = getelementptr i32, ptr %ptr, i64 3347  %arrayidx1 = getelementptr i32, ptr %ptr, i64 1348  %arrayidx2 = getelementptr i32, ptr %ptr, i64 2349  %t3 = load i32, ptr %arrayidx3350  %t1 = load i32, ptr %arrayidx1351  %t2 = load i32, ptr %arrayidx2352  %t0 = load i32, ptr %ptr353  ret void354}355 356; Improve on existing dereferenceable_or_null attribute.357 358define void @more_bytes_and_not_null(ptr dereferenceable_or_null(8) %ptr) {359; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)360; CHECK-LABEL: define {{[^@]+}}@more_bytes_and_not_null361; CHECK-SAME: (ptr nofree noundef nonnull readnone align 4 captures(none) dereferenceable(16) [[PTR:%.*]]) #[[ATTR2]] {362; CHECK-NEXT:    ret void363;364  %arrayidx3 = getelementptr i32, ptr %ptr, i64 3365  %arrayidx1 = getelementptr i32, ptr %ptr, i64 1366  %arrayidx2 = getelementptr i32, ptr %ptr, i64 2367  %t3 = load i32, ptr %arrayidx3368  %t1 = load i32, ptr %arrayidx1369  %t2 = load i32, ptr %arrayidx2370  %t0 = load i32, ptr %ptr371  ret void372}373 374; But don't pessimize existing dereferenceable attribute.375 376define void @better_bytes(ptr dereferenceable(100) %ptr) {377; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)378; CHECK-LABEL: define {{[^@]+}}@better_bytes379; CHECK-SAME: (ptr nofree noundef nonnull readnone align 4 captures(none) dereferenceable(100) [[PTR:%.*]]) #[[ATTR2]] {380; CHECK-NEXT:    ret void381;382  %arrayidx3 = getelementptr i32, ptr %ptr, i64 3383  %arrayidx1 = getelementptr i32, ptr %ptr, i64 1384  %arrayidx2 = getelementptr i32, ptr %ptr, i64 2385  %t3 = load i32, ptr %arrayidx3386  %t1 = load i32, ptr %arrayidx1387  %t2 = load i32, ptr %arrayidx2388  %t0 = load i32, ptr %ptr389  ret void390}391 392define void @bitcast(ptr %arg) {393; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)394; CHECK-LABEL: define {{[^@]+}}@bitcast395; CHECK-SAME: (ptr nofree nonnull readnone align 4 captures(none) dereferenceable(8) [[ARG:%.*]]) #[[ATTR2]] {396; CHECK-NEXT:    ret void397;398  %ptr = bitcast ptr %arg to ptr399  %arrayidx1 = getelementptr float, ptr %ptr, i64 1400  %t0 = load float, ptr %ptr401  %t1 = load float, ptr %arrayidx1402  ret void403}404 405define void @bitcast_different_sizes(ptr %arg1, ptr %arg2) {406; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)407; CHECK-LABEL: define {{[^@]+}}@bitcast_different_sizes408; CHECK-SAME: (ptr nofree nonnull readnone align 4 captures(none) dereferenceable(12) [[ARG1:%.*]], ptr nofree noundef nonnull readnone align 4 captures(none) dereferenceable(16) [[ARG2:%.*]]) #[[ATTR2]] {409; CHECK-NEXT:    ret void410;411  %ptr1 = bitcast ptr %arg1 to ptr412  %a11 = getelementptr float, ptr %ptr1, i64 1413  %a12 = getelementptr float, ptr %ptr1, i64 2414  %ld10 = load float, ptr %ptr1415  %ld11 = load float, ptr %a11416  %ld12 = load float, ptr %a12417 418  %a21 = getelementptr i64, ptr %arg2, i64 1419  %ld20 = load i64, ptr %arg2420  %ld21 = load i64, ptr %a21421  ret void422}423 424define void @negative_offset(ptr %arg) {425; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)426; CHECK-LABEL: define {{[^@]+}}@negative_offset427; CHECK-SAME: (ptr nofree nonnull readnone align 4 captures(none) dereferenceable(4) [[ARG:%.*]]) #[[ATTR2]] {428; CHECK-NEXT:    ret void429;430  %ptr = bitcast ptr %arg to ptr431  %arrayidx1 = getelementptr float, ptr %ptr, i64 -1432  %t0 = load float, ptr %ptr433  %t1 = load float, ptr %arrayidx1434  ret void435}436 437define void @stores(ptr %arg) {438; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)439; CHECK-LABEL: define {{[^@]+}}@stores440; CHECK-SAME: (ptr nofree nonnull writeonly align 4 captures(none) dereferenceable(8) [[ARG:%.*]]) #[[ATTR4:[0-9]+]] {441; CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr float, ptr [[ARG]], i64 1442; CHECK-NEXT:    store float 1.000000e+00, ptr [[ARG]], align 4443; CHECK-NEXT:    store float 2.000000e+00, ptr [[ARRAYIDX1]], align 4444; CHECK-NEXT:    ret void445;446  %ptr = bitcast ptr %arg to ptr447  %arrayidx1 = getelementptr float, ptr %ptr, i64 1448  store float 1.0, ptr %ptr449  store float 2.0, ptr %arrayidx1450  ret void451}452 453define void @load_store(ptr %arg) {454; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)455; CHECK-LABEL: define {{[^@]+}}@load_store456; CHECK-SAME: (ptr nofree nonnull writeonly align 4 captures(none) dereferenceable(8) [[ARG:%.*]]) #[[ATTR4]] {457; CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr float, ptr [[ARG]], i64 1458; CHECK-NEXT:    store float 2.000000e+00, ptr [[ARRAYIDX1]], align 4459; CHECK-NEXT:    ret void460;461  %ptr = bitcast ptr %arg to ptr462  %arrayidx1 = getelementptr float, ptr %ptr, i64 1463  %t1 = load float, ptr %ptr464  store float 2.0, ptr %arrayidx1465  ret void466}467 468define void @different_size1(ptr %arg) {469; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)470; CHECK-LABEL: define {{[^@]+}}@different_size1471; CHECK-SAME: (ptr nofree noundef nonnull writeonly align 8 captures(none) dereferenceable(8) [[ARG:%.*]]) #[[ATTR4]] {472; CHECK-NEXT:    store double 0.000000e+00, ptr [[ARG]], align 8473; CHECK-NEXT:    store i32 0, ptr [[ARG]], align 8474; CHECK-NEXT:    ret void475;476  %arg-cast = bitcast ptr %arg to ptr477  store double 0.000000e+00, ptr %arg-cast478  store i32 0, ptr %arg479  ret void480}481 482define void @different_size2(ptr %arg) {483; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)484; CHECK-LABEL: define {{[^@]+}}@different_size2485; CHECK-SAME: (ptr nofree noundef nonnull writeonly align 8 captures(none) dereferenceable(8) [[ARG:%.*]]) #[[ATTR4]] {486; CHECK-NEXT:    store i32 0, ptr [[ARG]], align 8487; CHECK-NEXT:    store double 0.000000e+00, ptr [[ARG]], align 8488; CHECK-NEXT:    ret void489;490  store i32 0, ptr %arg491  store double 0.000000e+00, ptr %arg492  ret void493}494 495; Make use of MustBeExecuted Explorer496;497; [CFG]498; entry499;  / \500; l1 l2501; | X |502; l3 l4503;  \ /504;  l5505;  / \506; l6 l7507;  \ /508;  end509; According to the above CFG, we can see that instructions in l5 Block must be executed.510; Therefore, %p must be dereferenced.511;512; ATTRIBUTOR_CGSCC_NPM-LABEL: define i32 @require_cfg_analysis(i32 %c, ptr {{.*}} dereferenceable(4) %p)513define i32 @require_cfg_analysis(i32 %c, ptr %p) {514; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)515; CHECK-LABEL: define {{[^@]+}}@require_cfg_analysis516; CHECK-SAME: (i32 [[C:%.*]], ptr nofree nonnull writeonly align 4 captures(none) dereferenceable(4) [[P:%.*]]) #[[ATTR4]] {517; CHECK-NEXT:    [[TOBOOL1:%.*]] = icmp eq i32 [[C]], 0518; CHECK-NEXT:    br i1 [[TOBOOL1]], label [[L1:%.*]], label [[L2:%.*]]519; CHECK:       l1:520; CHECK-NEXT:    br label [[L4:%.*]]521; CHECK:       l2:522; CHECK-NEXT:    [[TOBOOL3:%.*]] = icmp eq i32 [[C]], 2523; CHECK-NEXT:    br i1 [[TOBOOL3]], label [[L3:%.*]], label [[L4]]524; CHECK:       l3:525; CHECK-NEXT:    br label [[L5:%.*]]526; CHECK:       l4:527; CHECK-NEXT:    br label [[L5]]528; CHECK:       l5:529; CHECK-NEXT:    [[TOBOOL4:%.*]] = icmp eq i32 [[C]], 4530; CHECK-NEXT:    br i1 [[TOBOOL4]], label [[L6:%.*]], label [[L7:%.*]]531; CHECK:       l6:532; CHECK-NEXT:    store i32 0, ptr [[P]], align 4533; CHECK-NEXT:    br label [[END:%.*]]534; CHECK:       l7:535; CHECK-NEXT:    store i32 1, ptr [[P]], align 4536; CHECK-NEXT:    br label [[END]]537; CHECK:       end:538; CHECK-NEXT:    ret i32 1539;540  %tobool1 = icmp eq i32 %c, 0541  br i1 %tobool1, label %l1, label %l2542l1:543  %tobool2 = icmp eq i32 %c, 1544  br i1 %tobool2, label %l3, label %l4545l2:546  %tobool3 = icmp eq i32 %c, 2547  br i1 %tobool3, label %l3, label %l4548l3:549  br label %l5550l4:551  br label %l5552l5:553  %tobool4 = icmp eq i32 %c, 4554  br i1 %tobool4, label %l6, label %l7555l6:556  store i32 0, ptr %p557  br label %end558l7:559  store i32 1, ptr %p560  br label %end561end:562  ret i32 1563}564;.565; CHECK: attributes #[[ATTR0]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) }566; CHECK: attributes #[[ATTR1]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) }567; CHECK: attributes #[[ATTR2]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }568; CHECK: attributes #[[ATTR3]] = { mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) }569; CHECK: attributes #[[ATTR4]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) }570;.571;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:572; CGSCC: {{.*}}573; TUNIT: {{.*}}574