1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes 2; RUN: opt -attributor -enable-new-pm=0 -attributor-manifest-internal -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-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 -enable-new-pm=0 -attributor-manifest-internal -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-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; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind readonly willreturn 12; IS__TUNIT____-LABEL: define {{[^@]+}}@PR21780 13; IS__TUNIT____-SAME: (double* nocapture nofree nonnull readonly align 8 dereferenceable(32) [[PTR:%.*]]) [[ATTR0:#.*]] { 14; IS__TUNIT____-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds double, double* [[PTR]], i64 1 15; IS__TUNIT____-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds double, double* [[PTR]], i64 2 16; IS__TUNIT____-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds double, double* [[PTR]], i64 3 17; IS__TUNIT____-NEXT: [[T0:%.*]] = load double, double* [[PTR]], align 8 18; IS__TUNIT____-NEXT: [[T1:%.*]] = load double, double* [[ARRAYIDX1]], align 8 19; IS__TUNIT____-NEXT: [[T2:%.*]] = load double, double* [[ARRAYIDX2]], align 8 20; IS__TUNIT____-NEXT: [[T3:%.*]] = load double, double* [[ARRAYIDX3]], align 8 21; IS__TUNIT____-NEXT: [[VECINIT0:%.*]] = insertelement <4 x double> undef, double [[T0]], i32 0 22; IS__TUNIT____-NEXT: [[VECINIT1:%.*]] = insertelement <4 x double> [[VECINIT0]], double [[T1]], i32 1 23; IS__TUNIT____-NEXT: [[VECINIT2:%.*]] = insertelement <4 x double> [[VECINIT1]], double [[T2]], i32 2 24; IS__TUNIT____-NEXT: [[VECINIT3:%.*]] = insertelement <4 x double> [[VECINIT2]], double [[T3]], i32 3 25; IS__TUNIT____-NEXT: [[SHUFFLE:%.*]] = shufflevector <4 x double> [[VECINIT3]], <4 x double> [[VECINIT3]], <4 x i32> <i32 0, i32 0, i32 2, i32 2> 26; IS__TUNIT____-NEXT: ret <4 x double> [[SHUFFLE]] 27; 28; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn 29; IS__CGSCC____-LABEL: define {{[^@]+}}@PR21780 30; IS__CGSCC____-SAME: (double* nocapture nofree nonnull readonly align 8 dereferenceable(32) [[PTR:%.*]]) [[ATTR0:#.*]] { 31; IS__CGSCC____-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds double, double* [[PTR]], i64 1 32; IS__CGSCC____-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds double, double* [[PTR]], i64 2 33; IS__CGSCC____-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds double, double* [[PTR]], i64 3 34; IS__CGSCC____-NEXT: [[T0:%.*]] = load double, double* [[PTR]], align 8 35; IS__CGSCC____-NEXT: [[T1:%.*]] = load double, double* [[ARRAYIDX1]], align 8 36; IS__CGSCC____-NEXT: [[T2:%.*]] = load double, double* [[ARRAYIDX2]], align 8 37; IS__CGSCC____-NEXT: [[T3:%.*]] = load double, double* [[ARRAYIDX3]], align 8 38; IS__CGSCC____-NEXT: [[VECINIT0:%.*]] = insertelement <4 x double> undef, double [[T0]], i32 0 39; IS__CGSCC____-NEXT: [[VECINIT1:%.*]] = insertelement <4 x double> [[VECINIT0]], double [[T1]], i32 1 40; IS__CGSCC____-NEXT: [[VECINIT2:%.*]] = insertelement <4 x double> [[VECINIT1]], double [[T2]], i32 2 41; IS__CGSCC____-NEXT: [[VECINIT3:%.*]] = insertelement <4 x double> [[VECINIT2]], double [[T3]], i32 3 42; IS__CGSCC____-NEXT: [[SHUFFLE:%.*]] = shufflevector <4 x double> [[VECINIT3]], <4 x double> [[VECINIT3]], <4 x i32> <i32 0, i32 0, i32 2, i32 2> 43; IS__CGSCC____-NEXT: ret <4 x double> [[SHUFFLE]] 44; 45 46 ; GEP of index 0 is simplified away. 47 %arrayidx1 = getelementptr inbounds double, double* %ptr, i64 1 48 %arrayidx2 = getelementptr inbounds double, double* %ptr, i64 2 49 %arrayidx3 = getelementptr inbounds double, double* %ptr, i64 3 50 51 %t0 = load double, double* %ptr, align 8 52 %t1 = load double, double* %arrayidx1, align 8 53 %t2 = load double, double* %arrayidx2, align 8 54 %t3 = load double, double* %arrayidx3, align 8 55 56 %vecinit0 = insertelement <4 x double> undef, double %t0, i32 0 57 %vecinit1 = insertelement <4 x double> %vecinit0, double %t1, i32 1 58 %vecinit2 = insertelement <4 x double> %vecinit1, double %t2, i32 2 59 %vecinit3 = insertelement <4 x double> %vecinit2, double %t3, i32 3 60 %shuffle = shufflevector <4 x double> %vecinit3, <4 x double> %vecinit3, <4 x i32> <i32 0, i32 0, i32 2, i32 2> 61 ret <4 x double> %shuffle 62} 63 64 65define double @PR21780_only_access3_with_inbounds(double* %ptr) { 66; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind readonly willreturn 67; IS__TUNIT____-LABEL: define {{[^@]+}}@PR21780_only_access3_with_inbounds 68; IS__TUNIT____-SAME: (double* nocapture nofree nonnull readonly align 8 dereferenceable(32) [[PTR:%.*]]) [[ATTR0]] { 69; IS__TUNIT____-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds double, double* [[PTR]], i64 3 70; IS__TUNIT____-NEXT: [[T3:%.*]] = load double, double* [[ARRAYIDX3]], align 8 71; IS__TUNIT____-NEXT: ret double [[T3]] 72; 73; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn 74; IS__CGSCC____-LABEL: define {{[^@]+}}@PR21780_only_access3_with_inbounds 75; IS__CGSCC____-SAME: (double* nocapture nofree nonnull readonly align 8 dereferenceable(32) [[PTR:%.*]]) [[ATTR0]] { 76; IS__CGSCC____-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds double, double* [[PTR]], i64 3 77; IS__CGSCC____-NEXT: [[T3:%.*]] = load double, double* [[ARRAYIDX3]], align 8 78; IS__CGSCC____-NEXT: ret double [[T3]] 79; 80 81 %arrayidx3 = getelementptr inbounds double, double* %ptr, i64 3 82 %t3 = load double, double* %arrayidx3, align 8 83 ret double %t3 84} 85 86define double @PR21780_only_access3_without_inbounds(double* %ptr) { 87; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind readonly willreturn 88; IS__TUNIT____-LABEL: define {{[^@]+}}@PR21780_only_access3_without_inbounds 89; IS__TUNIT____-SAME: (double* nocapture nofree readonly align 8 [[PTR:%.*]]) [[ATTR0]] { 90; IS__TUNIT____-NEXT: [[ARRAYIDX3:%.*]] = getelementptr double, double* [[PTR]], i64 3 91; IS__TUNIT____-NEXT: [[T3:%.*]] = load double, double* [[ARRAYIDX3]], align 8 92; IS__TUNIT____-NEXT: ret double [[T3]] 93; 94; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn 95; IS__CGSCC____-LABEL: define {{[^@]+}}@PR21780_only_access3_without_inbounds 96; IS__CGSCC____-SAME: (double* nocapture nofree readonly align 8 [[PTR:%.*]]) [[ATTR0]] { 97; IS__CGSCC____-NEXT: [[ARRAYIDX3:%.*]] = getelementptr double, double* [[PTR]], i64 3 98; IS__CGSCC____-NEXT: [[T3:%.*]] = load double, double* [[ARRAYIDX3]], align 8 99; IS__CGSCC____-NEXT: ret double [[T3]] 100; 101 %arrayidx3 = getelementptr double, double* %ptr, i64 3 102 %t3 = load double, double* %arrayidx3, align 8 103 ret double %t3 104} 105 106define double @PR21780_without_inbounds(double* %ptr) { 107; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind readonly willreturn 108; IS__TUNIT____-LABEL: define {{[^@]+}}@PR21780_without_inbounds 109; IS__TUNIT____-SAME: (double* nocapture nofree nonnull readonly align 8 dereferenceable(32) [[PTR:%.*]]) [[ATTR0]] { 110; IS__TUNIT____-NEXT: [[ARRAYIDX3:%.*]] = getelementptr double, double* [[PTR]], i64 3 111; IS__TUNIT____-NEXT: [[T3:%.*]] = load double, double* [[ARRAYIDX3]], align 8 112; IS__TUNIT____-NEXT: ret double [[T3]] 113; 114; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn 115; IS__CGSCC____-LABEL: define {{[^@]+}}@PR21780_without_inbounds 116; IS__CGSCC____-SAME: (double* nocapture nofree nonnull readonly align 8 dereferenceable(32) [[PTR:%.*]]) [[ATTR0]] { 117; IS__CGSCC____-NEXT: [[ARRAYIDX3:%.*]] = getelementptr double, double* [[PTR]], i64 3 118; IS__CGSCC____-NEXT: [[T3:%.*]] = load double, double* [[ARRAYIDX3]], align 8 119; IS__CGSCC____-NEXT: ret double [[T3]] 120; 121 122 %arrayidx1 = getelementptr double, double* %ptr, i64 1 123 %arrayidx2 = getelementptr double, double* %ptr, i64 2 124 %arrayidx3 = getelementptr double, double* %ptr, i64 3 125 126 %t0 = load double, double* %ptr, align 8 127 %t1 = load double, double* %arrayidx1, align 8 128 %t2 = load double, double* %arrayidx2, align 8 129 %t3 = load double, double* %arrayidx3, align 8 130 131 ret double %t3 132} 133 134; Unsimplified, but still valid. Also, throw in some bogus arguments. 135 136define void @gep0(i8* %unused, i8* %other, i8* %ptr) { 137; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind willreturn 138; IS__TUNIT____-LABEL: define {{[^@]+}}@gep0 139; IS__TUNIT____-SAME: (i8* nocapture nofree readnone [[UNUSED:%.*]], i8* nocapture nofree nonnull writeonly dereferenceable(1) [[OTHER:%.*]], i8* nocapture nofree nonnull readonly dereferenceable(3) [[PTR:%.*]]) [[ATTR1:#.*]] { 140; IS__TUNIT____-NEXT: [[ARRAYIDX2:%.*]] = getelementptr i8, i8* [[PTR]], i64 2 141; IS__TUNIT____-NEXT: [[T2:%.*]] = load i8, i8* [[ARRAYIDX2]], align 1 142; IS__TUNIT____-NEXT: store i8 [[T2]], i8* [[OTHER]], align 1 143; IS__TUNIT____-NEXT: ret void 144; 145; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn 146; IS__CGSCC____-LABEL: define {{[^@]+}}@gep0 147; IS__CGSCC____-SAME: (i8* nocapture nofree readnone [[UNUSED:%.*]], i8* nocapture nofree nonnull writeonly dereferenceable(1) [[OTHER:%.*]], i8* nocapture nofree nonnull readonly dereferenceable(3) [[PTR:%.*]]) [[ATTR1:#.*]] { 148; IS__CGSCC____-NEXT: [[ARRAYIDX2:%.*]] = getelementptr i8, i8* [[PTR]], i64 2 149; IS__CGSCC____-NEXT: [[T2:%.*]] = load i8, i8* [[ARRAYIDX2]], align 1 150; IS__CGSCC____-NEXT: store i8 [[T2]], i8* [[OTHER]], align 1 151; IS__CGSCC____-NEXT: ret void 152; 153 %arrayidx0 = getelementptr i8, i8* %ptr, i64 0 154 %arrayidx1 = getelementptr i8, i8* %ptr, i64 1 155 %arrayidx2 = getelementptr i8, i8* %ptr, i64 2 156 %t0 = load i8, i8* %arrayidx0 157 %t1 = load i8, i8* %arrayidx1 158 %t2 = load i8, i8* %arrayidx2 159 store i8 %t2, i8* %other 160 ret void 161} 162 163; Order of accesses does not change computation. 164; Multiple arguments may be dereferenceable. 165 166define void @ordering(i8* %ptr1, i32* %ptr2) { 167; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn 168; IS__TUNIT____-LABEL: define {{[^@]+}}@ordering 169; IS__TUNIT____-SAME: (i8* nocapture nofree nonnull readnone dereferenceable(3) [[PTR1:%.*]], i32* nocapture nofree nonnull readnone align 4 dereferenceable(8) [[PTR2:%.*]]) [[ATTR2:#.*]] { 170; IS__TUNIT____-NEXT: ret void 171; 172; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 173; IS__CGSCC____-LABEL: define {{[^@]+}}@ordering 174; IS__CGSCC____-SAME: (i8* nocapture nofree nonnull readnone dereferenceable(3) [[PTR1:%.*]], i32* nocapture nofree nonnull readnone align 4 dereferenceable(8) [[PTR2:%.*]]) [[ATTR2:#.*]] { 175; IS__CGSCC____-NEXT: ret void 176; 177 %a20 = getelementptr i32, i32* %ptr2, i64 0 178 %a12 = getelementptr i8, i8* %ptr1, i64 2 179 %t12 = load i8, i8* %a12 180 %a11 = getelementptr i8, i8* %ptr1, i64 1 181 %t20 = load i32, i32* %a20 182 %a10 = getelementptr i8, i8* %ptr1, i64 0 183 %t10 = load i8, i8* %a10 184 %t11 = load i8, i8* %a11 185 %a21 = getelementptr i32, i32* %ptr2, i64 1 186 %t21 = load i32, i32* %a21 187 ret void 188} 189 190; Not in entry block. 191 192define void @not_entry_but_guaranteed_to_execute(i8* %ptr) { 193; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn 194; IS__TUNIT____-LABEL: define {{[^@]+}}@not_entry_but_guaranteed_to_execute 195; IS__TUNIT____-SAME: (i8* nocapture nofree nonnull readnone dereferenceable(3) [[PTR:%.*]]) [[ATTR2]] { 196; IS__TUNIT____-NEXT: entry: 197; IS__TUNIT____-NEXT: br label [[EXIT:%.*]] 198; IS__TUNIT____: exit: 199; IS__TUNIT____-NEXT: ret void 200; 201; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 202; IS__CGSCC____-LABEL: define {{[^@]+}}@not_entry_but_guaranteed_to_execute 203; IS__CGSCC____-SAME: (i8* nocapture nofree nonnull readnone dereferenceable(3) [[PTR:%.*]]) [[ATTR2]] { 204; IS__CGSCC____-NEXT: entry: 205; IS__CGSCC____-NEXT: br label [[EXIT:%.*]] 206; IS__CGSCC____: exit: 207; IS__CGSCC____-NEXT: ret void 208; 209entry: 210 br label %exit 211exit: 212 %arrayidx0 = getelementptr i8, i8* %ptr, i64 0 213 %arrayidx1 = getelementptr i8, i8* %ptr, i64 1 214 %arrayidx2 = getelementptr i8, i8* %ptr, i64 2 215 %t0 = load i8, i8* %arrayidx0 216 %t1 = load i8, i8* %arrayidx1 217 %t2 = load i8, i8* %arrayidx2 218 ret void 219} 220 221; Not in entry block and not guaranteed to execute. 222 223define void @not_entry_not_guaranteed_to_execute(i8* %ptr, i1 %cond) { 224; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn 225; IS__TUNIT____-LABEL: define {{[^@]+}}@not_entry_not_guaranteed_to_execute 226; IS__TUNIT____-SAME: (i8* nocapture nofree readnone [[PTR:%.*]], i1 [[COND:%.*]]) [[ATTR2]] { 227; IS__TUNIT____-NEXT: entry: 228; IS__TUNIT____-NEXT: br i1 [[COND]], label [[LOADS:%.*]], label [[EXIT:%.*]] 229; IS__TUNIT____: loads: 230; IS__TUNIT____-NEXT: ret void 231; IS__TUNIT____: exit: 232; IS__TUNIT____-NEXT: ret void 233; 234; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 235; IS__CGSCC____-LABEL: define {{[^@]+}}@not_entry_not_guaranteed_to_execute 236; IS__CGSCC____-SAME: (i8* nocapture nofree readnone [[PTR:%.*]], i1 [[COND:%.*]]) [[ATTR2]] { 237; IS__CGSCC____-NEXT: entry: 238; IS__CGSCC____-NEXT: br i1 [[COND]], label [[LOADS:%.*]], label [[EXIT:%.*]] 239; IS__CGSCC____: loads: 240; IS__CGSCC____-NEXT: ret void 241; IS__CGSCC____: exit: 242; IS__CGSCC____-NEXT: ret void 243; 244entry: 245 br i1 %cond, label %loads, label %exit 246loads: 247 %arrayidx0 = getelementptr i8, i8* %ptr, i64 0 248 %arrayidx1 = getelementptr i8, i8* %ptr, i64 1 249 %arrayidx2 = getelementptr i8, i8* %ptr, i64 2 250 %t0 = load i8, i8* %arrayidx0 251 %t1 = load i8, i8* %arrayidx1 252 %t2 = load i8, i8* %arrayidx2 253 ret void 254exit: 255 ret void 256} 257 258; The last load may not execute, so derefenceable bytes only covers the 1st two loads. 259 260define void @partial_in_entry(i16* %ptr, i1 %cond) { 261; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn 262; IS__TUNIT____-LABEL: define {{[^@]+}}@partial_in_entry 263; IS__TUNIT____-SAME: (i16* nocapture nofree nonnull readnone align 2 dereferenceable(4) [[PTR:%.*]], i1 [[COND:%.*]]) [[ATTR2]] { 264; IS__TUNIT____-NEXT: entry: 265; IS__TUNIT____-NEXT: br i1 [[COND]], label [[LOADS:%.*]], label [[EXIT:%.*]] 266; IS__TUNIT____: loads: 267; IS__TUNIT____-NEXT: ret void 268; IS__TUNIT____: exit: 269; IS__TUNIT____-NEXT: ret void 270; 271; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 272; IS__CGSCC____-LABEL: define {{[^@]+}}@partial_in_entry 273; IS__CGSCC____-SAME: (i16* nocapture nofree nonnull readnone align 2 dereferenceable(4) [[PTR:%.*]], i1 [[COND:%.*]]) [[ATTR2]] { 274; IS__CGSCC____-NEXT: entry: 275; IS__CGSCC____-NEXT: br i1 [[COND]], label [[LOADS:%.*]], label [[EXIT:%.*]] 276; IS__CGSCC____: loads: 277; IS__CGSCC____-NEXT: ret void 278; IS__CGSCC____: exit: 279; IS__CGSCC____-NEXT: ret void 280; 281entry: 282 %arrayidx0 = getelementptr i16, i16* %ptr, i64 0 283 %arrayidx1 = getelementptr i16, i16* %ptr, i64 1 284 %arrayidx2 = getelementptr i16, i16* %ptr, i64 2 285 %t0 = load i16, i16* %arrayidx0 286 %t1 = load i16, i16* %arrayidx1 287 br i1 %cond, label %loads, label %exit 288loads: 289 %t2 = load i16, i16* %arrayidx2 290 ret void 291exit: 292 ret void 293} 294 295; The volatile load can't be used to prove a non-volatile access is allowed. 296; The 2nd and 3rd loads may never execute. 297 298define void @volatile_is_not_dereferenceable(i16* %ptr) { 299; IS__TUNIT____: Function Attrs: argmemonly nofree nounwind willreturn 300; IS__TUNIT____-LABEL: define {{[^@]+}}@volatile_is_not_dereferenceable 301; IS__TUNIT____-SAME: (i16* nofree align 2 [[PTR:%.*]]) [[ATTR3:#.*]] { 302; IS__TUNIT____-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i16, i16* [[PTR]], i64 0 303; IS__TUNIT____-NEXT: [[T0:%.*]] = load volatile i16, i16* [[ARRAYIDX0]], align 2 304; IS__TUNIT____-NEXT: ret void 305; 306; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nounwind willreturn 307; IS__CGSCC____-LABEL: define {{[^@]+}}@volatile_is_not_dereferenceable 308; IS__CGSCC____-SAME: (i16* nofree align 2 [[PTR:%.*]]) [[ATTR3:#.*]] { 309; IS__CGSCC____-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i16, i16* [[PTR]], i64 0 310; IS__CGSCC____-NEXT: [[T0:%.*]] = load volatile i16, i16* [[ARRAYIDX0]], align 2 311; IS__CGSCC____-NEXT: ret void 312; 313 %arrayidx0 = getelementptr i16, i16* %ptr, i64 0 314 %arrayidx1 = getelementptr i16, i16* %ptr, i64 1 315 %arrayidx2 = getelementptr i16, i16* %ptr, i64 2 316 %t0 = load volatile i16, i16* %arrayidx0 317 %t1 = load i16, i16* %arrayidx1 318 %t2 = load i16, i16* %arrayidx2 319 ret void 320} 321 322; TODO: We should allow inference for atomic (but not volatile) ops. 323 324define void @atomic_is_alright(i16* %ptr) { 325; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn 326; IS__TUNIT____-LABEL: define {{[^@]+}}@atomic_is_alright 327; IS__TUNIT____-SAME: (i16* nocapture nofree nonnull readnone align 2 dereferenceable(6) [[PTR:%.*]]) [[ATTR2]] { 328; IS__TUNIT____-NEXT: ret void 329; 330; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 331; IS__CGSCC____-LABEL: define {{[^@]+}}@atomic_is_alright 332; IS__CGSCC____-SAME: (i16* nocapture nofree nonnull readnone align 2 dereferenceable(6) [[PTR:%.*]]) [[ATTR2]] { 333; IS__CGSCC____-NEXT: ret void 334; 335 %arrayidx0 = getelementptr i16, i16* %ptr, i64 0 336 %arrayidx1 = getelementptr i16, i16* %ptr, i64 1 337 %arrayidx2 = getelementptr i16, i16* %ptr, i64 2 338 %t0 = load atomic i16, i16* %arrayidx0 unordered, align 2 339 %t1 = load i16, i16* %arrayidx1 340 %t2 = load i16, i16* %arrayidx2 341 ret void 342} 343 344declare void @may_not_return() 345 346define void @not_guaranteed_to_transfer_execution(i16* %ptr) { 347; CHECK-LABEL: define {{[^@]+}}@not_guaranteed_to_transfer_execution 348; CHECK-SAME: (i16* nocapture nofree nonnull readnone align 2 dereferenceable(2) [[PTR:%.*]]) { 349; CHECK-NEXT: call void @may_not_return() 350; CHECK-NEXT: ret void 351; 352 %arrayidx0 = getelementptr i16, i16* %ptr, i64 0 353 %arrayidx1 = getelementptr i16, i16* %ptr, i64 1 354 %arrayidx2 = getelementptr i16, i16* %ptr, i64 2 355 %t0 = load i16, i16* %arrayidx0 356 call void @may_not_return() 357 %t1 = load i16, i16* %arrayidx1 358 %t2 = load i16, i16* %arrayidx2 359 ret void 360} 361 362; We must have consecutive accesses. 363 364define void @variable_gep_index(i8* %unused, i8* %ptr, i64 %variable_index) { 365; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn 366; IS__TUNIT____-LABEL: define {{[^@]+}}@variable_gep_index 367; IS__TUNIT____-SAME: (i8* nocapture nofree readnone [[UNUSED:%.*]], i8* nocapture nofree nonnull readnone dereferenceable(1) [[PTR:%.*]], i64 [[VARIABLE_INDEX:%.*]]) [[ATTR2]] { 368; IS__TUNIT____-NEXT: ret void 369; 370; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 371; IS__CGSCC____-LABEL: define {{[^@]+}}@variable_gep_index 372; IS__CGSCC____-SAME: (i8* nocapture nofree readnone [[UNUSED:%.*]], i8* nocapture nofree nonnull readnone dereferenceable(1) [[PTR:%.*]], i64 [[VARIABLE_INDEX:%.*]]) [[ATTR2]] { 373; IS__CGSCC____-NEXT: ret void 374; 375 %arrayidx1 = getelementptr i8, i8* %ptr, i64 %variable_index 376 %arrayidx2 = getelementptr i8, i8* %ptr, i64 2 377 %t0 = load i8, i8* %ptr 378 %t1 = load i8, i8* %arrayidx1 379 %t2 = load i8, i8* %arrayidx2 380 ret void 381} 382 383; Deal with >1 GEP index. 384 385define void @multi_index_gep(<4 x i8>* %ptr) { 386; FIXME: %ptr should be dereferenceable(4) 387; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn 388; IS__TUNIT____-LABEL: define {{[^@]+}}@multi_index_gep 389; IS__TUNIT____-SAME: (<4 x i8>* nocapture nofree nonnull readnone dereferenceable(1) [[PTR:%.*]]) [[ATTR2]] { 390; IS__TUNIT____-NEXT: ret void 391; 392; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 393; IS__CGSCC____-LABEL: define {{[^@]+}}@multi_index_gep 394; IS__CGSCC____-SAME: (<4 x i8>* nocapture nofree nonnull readnone dereferenceable(1) [[PTR:%.*]]) [[ATTR2]] { 395; IS__CGSCC____-NEXT: ret void 396; 397 %arrayidx00 = getelementptr <4 x i8>, <4 x i8>* %ptr, i64 0, i64 0 398 %t0 = load i8, i8* %arrayidx00 399 ret void 400} 401 402; Could round weird bitwidths down? 403 404define void @not_byte_multiple(i9* %ptr) { 405; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn 406; IS__TUNIT____-LABEL: define {{[^@]+}}@not_byte_multiple 407; IS__TUNIT____-SAME: (i9* nocapture nofree nonnull readnone align 2 dereferenceable(2) [[PTR:%.*]]) [[ATTR2]] { 408; IS__TUNIT____-NEXT: ret void 409; 410; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 411; IS__CGSCC____-LABEL: define {{[^@]+}}@not_byte_multiple 412; IS__CGSCC____-SAME: (i9* nocapture nofree nonnull readnone align 2 dereferenceable(2) [[PTR:%.*]]) [[ATTR2]] { 413; IS__CGSCC____-NEXT: ret void 414; 415 %arrayidx0 = getelementptr i9, i9* %ptr, i64 0 416 %t0 = load i9, i9* %arrayidx0 417 ret void 418} 419 420; Missing direct access from the pointer. 421 422define void @no_pointer_deref(i16* %ptr) { 423; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn 424; IS__TUNIT____-LABEL: define {{[^@]+}}@no_pointer_deref 425; IS__TUNIT____-SAME: (i16* nocapture nofree readnone align 2 [[PTR:%.*]]) [[ATTR2]] { 426; IS__TUNIT____-NEXT: ret void 427; 428; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 429; IS__CGSCC____-LABEL: define {{[^@]+}}@no_pointer_deref 430; IS__CGSCC____-SAME: (i16* nocapture nofree readnone align 2 [[PTR:%.*]]) [[ATTR2]] { 431; IS__CGSCC____-NEXT: ret void 432; 433 %arrayidx1 = getelementptr i16, i16* %ptr, i64 1 434 %arrayidx2 = getelementptr i16, i16* %ptr, i64 2 435 %t1 = load i16, i16* %arrayidx1 436 %t2 = load i16, i16* %arrayidx2 437 ret void 438} 439 440; Out-of-order is ok, but missing access concludes dereferenceable range. 441 442define void @non_consecutive(i32* %ptr) { 443; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn 444; IS__TUNIT____-LABEL: define {{[^@]+}}@non_consecutive 445; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(8) [[PTR:%.*]]) [[ATTR2]] { 446; IS__TUNIT____-NEXT: ret void 447; 448; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 449; IS__CGSCC____-LABEL: define {{[^@]+}}@non_consecutive 450; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(8) [[PTR:%.*]]) [[ATTR2]] { 451; IS__CGSCC____-NEXT: ret void 452; 453 %arrayidx1 = getelementptr i32, i32* %ptr, i64 1 454 %arrayidx0 = getelementptr i32, i32* %ptr, i64 0 455 %arrayidx3 = getelementptr i32, i32* %ptr, i64 3 456 %t1 = load i32, i32* %arrayidx1 457 %t0 = load i32, i32* %arrayidx0 458 %t3 = load i32, i32* %arrayidx3 459 ret void 460} 461 462; Improve on existing dereferenceable attribute. 463 464define void @more_bytes(i32* dereferenceable(8) %ptr) { 465; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn 466; IS__TUNIT____-LABEL: define {{[^@]+}}@more_bytes 467; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(16) [[PTR:%.*]]) [[ATTR2]] { 468; IS__TUNIT____-NEXT: ret void 469; 470; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 471; IS__CGSCC____-LABEL: define {{[^@]+}}@more_bytes 472; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(16) [[PTR:%.*]]) [[ATTR2]] { 473; IS__CGSCC____-NEXT: ret void 474; 475 %arrayidx3 = getelementptr i32, i32* %ptr, i64 3 476 %arrayidx1 = getelementptr i32, i32* %ptr, i64 1 477 %arrayidx0 = getelementptr i32, i32* %ptr, i64 0 478 %arrayidx2 = getelementptr i32, i32* %ptr, i64 2 479 %t3 = load i32, i32* %arrayidx3 480 %t1 = load i32, i32* %arrayidx1 481 %t2 = load i32, i32* %arrayidx2 482 %t0 = load i32, i32* %arrayidx0 483 ret void 484} 485 486; Improve on existing dereferenceable_or_null attribute. 487 488define void @more_bytes_and_not_null(i32* dereferenceable_or_null(8) %ptr) { 489; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn 490; IS__TUNIT____-LABEL: define {{[^@]+}}@more_bytes_and_not_null 491; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(16) [[PTR:%.*]]) [[ATTR2]] { 492; IS__TUNIT____-NEXT: ret void 493; 494; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 495; IS__CGSCC____-LABEL: define {{[^@]+}}@more_bytes_and_not_null 496; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(16) [[PTR:%.*]]) [[ATTR2]] { 497; IS__CGSCC____-NEXT: ret void 498; 499 %arrayidx3 = getelementptr i32, i32* %ptr, i64 3 500 %arrayidx1 = getelementptr i32, i32* %ptr, i64 1 501 %arrayidx0 = getelementptr i32, i32* %ptr, i64 0 502 %arrayidx2 = getelementptr i32, i32* %ptr, i64 2 503 %t3 = load i32, i32* %arrayidx3 504 %t1 = load i32, i32* %arrayidx1 505 %t2 = load i32, i32* %arrayidx2 506 %t0 = load i32, i32* %arrayidx0 507 ret void 508} 509 510; But don't pessimize existing dereferenceable attribute. 511 512define void @better_bytes(i32* dereferenceable(100) %ptr) { 513; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn 514; IS__TUNIT____-LABEL: define {{[^@]+}}@better_bytes 515; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(100) [[PTR:%.*]]) [[ATTR2]] { 516; IS__TUNIT____-NEXT: ret void 517; 518; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 519; IS__CGSCC____-LABEL: define {{[^@]+}}@better_bytes 520; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(100) [[PTR:%.*]]) [[ATTR2]] { 521; IS__CGSCC____-NEXT: ret void 522; 523 %arrayidx3 = getelementptr i32, i32* %ptr, i64 3 524 %arrayidx1 = getelementptr i32, i32* %ptr, i64 1 525 %arrayidx0 = getelementptr i32, i32* %ptr, i64 0 526 %arrayidx2 = getelementptr i32, i32* %ptr, i64 2 527 %t3 = load i32, i32* %arrayidx3 528 %t1 = load i32, i32* %arrayidx1 529 %t2 = load i32, i32* %arrayidx2 530 %t0 = load i32, i32* %arrayidx0 531 ret void 532} 533 534define void @bitcast(i32* %arg) { 535; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn 536; IS__TUNIT____-LABEL: define {{[^@]+}}@bitcast 537; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(8) [[ARG:%.*]]) [[ATTR2]] { 538; IS__TUNIT____-NEXT: ret void 539; 540; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 541; IS__CGSCC____-LABEL: define {{[^@]+}}@bitcast 542; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(8) [[ARG:%.*]]) [[ATTR2]] { 543; IS__CGSCC____-NEXT: ret void 544; 545 %ptr = bitcast i32* %arg to float* 546 %arrayidx0 = getelementptr float, float* %ptr, i64 0 547 %arrayidx1 = getelementptr float, float* %ptr, i64 1 548 %t0 = load float, float* %arrayidx0 549 %t1 = load float, float* %arrayidx1 550 ret void 551} 552 553define void @bitcast_different_sizes(double* %arg1, i8* %arg2) { 554; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn 555; IS__TUNIT____-LABEL: define {{[^@]+}}@bitcast_different_sizes 556; IS__TUNIT____-SAME: (double* nocapture nofree nonnull readnone align 4 dereferenceable(12) [[ARG1:%.*]], i8* nocapture nofree nonnull readnone align 4 dereferenceable(16) [[ARG2:%.*]]) [[ATTR2]] { 557; IS__TUNIT____-NEXT: ret void 558; 559; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 560; IS__CGSCC____-LABEL: define {{[^@]+}}@bitcast_different_sizes 561; IS__CGSCC____-SAME: (double* nocapture nofree nonnull readnone align 4 dereferenceable(12) [[ARG1:%.*]], i8* nocapture nofree nonnull readnone align 4 dereferenceable(16) [[ARG2:%.*]]) [[ATTR2]] { 562; IS__CGSCC____-NEXT: ret void 563; 564 %ptr1 = bitcast double* %arg1 to float* 565 %a10 = getelementptr float, float* %ptr1, i64 0 566 %a11 = getelementptr float, float* %ptr1, i64 1 567 %a12 = getelementptr float, float* %ptr1, i64 2 568 %ld10 = load float, float* %a10 569 %ld11 = load float, float* %a11 570 %ld12 = load float, float* %a12 571 572 %ptr2 = bitcast i8* %arg2 to i64* 573 %a20 = getelementptr i64, i64* %ptr2, i64 0 574 %a21 = getelementptr i64, i64* %ptr2, i64 1 575 %ld20 = load i64, i64* %a20 576 %ld21 = load i64, i64* %a21 577 ret void 578} 579 580define void @negative_offset(i32* %arg) { 581; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn 582; IS__TUNIT____-LABEL: define {{[^@]+}}@negative_offset 583; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(4) [[ARG:%.*]]) [[ATTR2]] { 584; IS__TUNIT____-NEXT: ret void 585; 586; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 587; IS__CGSCC____-LABEL: define {{[^@]+}}@negative_offset 588; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(4) [[ARG:%.*]]) [[ATTR2]] { 589; IS__CGSCC____-NEXT: ret void 590; 591 %ptr = bitcast i32* %arg to float* 592 %arrayidx0 = getelementptr float, float* %ptr, i64 0 593 %arrayidx1 = getelementptr float, float* %ptr, i64 -1 594 %t0 = load float, float* %arrayidx0 595 %t1 = load float, float* %arrayidx1 596 ret void 597} 598 599define void @stores(i32* %arg) { 600; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly 601; IS__TUNIT____-LABEL: define {{[^@]+}}@stores 602; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull writeonly align 4 dereferenceable(8) [[ARG:%.*]]) [[ATTR4:#.*]] { 603; IS__TUNIT____-NEXT: [[PTR:%.*]] = bitcast i32* [[ARG]] to float* 604; IS__TUNIT____-NEXT: [[ARRAYIDX0:%.*]] = getelementptr float, float* [[PTR]], i64 0 605; IS__TUNIT____-NEXT: [[ARRAYIDX1:%.*]] = getelementptr float, float* [[PTR]], i64 1 606; IS__TUNIT____-NEXT: store float 1.000000e+00, float* [[ARRAYIDX0]], align 4 607; IS__TUNIT____-NEXT: store float 2.000000e+00, float* [[ARRAYIDX1]], align 4 608; IS__TUNIT____-NEXT: ret void 609; 610; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly 611; IS__CGSCC____-LABEL: define {{[^@]+}}@stores 612; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull writeonly align 4 dereferenceable(8) [[ARG:%.*]]) [[ATTR4:#.*]] { 613; IS__CGSCC____-NEXT: [[PTR:%.*]] = bitcast i32* [[ARG]] to float* 614; IS__CGSCC____-NEXT: [[ARRAYIDX0:%.*]] = getelementptr float, float* [[PTR]], i64 0 615; IS__CGSCC____-NEXT: [[ARRAYIDX1:%.*]] = getelementptr float, float* [[PTR]], i64 1 616; IS__CGSCC____-NEXT: store float 1.000000e+00, float* [[ARRAYIDX0]], align 4 617; IS__CGSCC____-NEXT: store float 2.000000e+00, float* [[ARRAYIDX1]], align 4 618; IS__CGSCC____-NEXT: ret void 619; 620 %ptr = bitcast i32* %arg to float* 621 %arrayidx0 = getelementptr float, float* %ptr, i64 0 622 %arrayidx1 = getelementptr float, float* %ptr, i64 1 623 store float 1.0, float* %arrayidx0 624 store float 2.0, float* %arrayidx1 625 ret void 626} 627 628define void @load_store(i32* %arg) { 629; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly 630; IS__TUNIT____-LABEL: define {{[^@]+}}@load_store 631; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull writeonly align 4 dereferenceable(8) [[ARG:%.*]]) [[ATTR4]] { 632; IS__TUNIT____-NEXT: [[PTR:%.*]] = bitcast i32* [[ARG]] to float* 633; IS__TUNIT____-NEXT: [[ARRAYIDX1:%.*]] = getelementptr float, float* [[PTR]], i64 1 634; IS__TUNIT____-NEXT: store float 2.000000e+00, float* [[ARRAYIDX1]], align 4 635; IS__TUNIT____-NEXT: ret void 636; 637; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly 638; IS__CGSCC____-LABEL: define {{[^@]+}}@load_store 639; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull writeonly align 4 dereferenceable(8) [[ARG:%.*]]) [[ATTR4]] { 640; IS__CGSCC____-NEXT: [[PTR:%.*]] = bitcast i32* [[ARG]] to float* 641; IS__CGSCC____-NEXT: [[ARRAYIDX1:%.*]] = getelementptr float, float* [[PTR]], i64 1 642; IS__CGSCC____-NEXT: store float 2.000000e+00, float* [[ARRAYIDX1]], align 4 643; IS__CGSCC____-NEXT: ret void 644; 645 %ptr = bitcast i32* %arg to float* 646 %arrayidx0 = getelementptr float, float* %ptr, i64 0 647 %arrayidx1 = getelementptr float, float* %ptr, i64 1 648 %t1 = load float, float* %arrayidx0 649 store float 2.0, float* %arrayidx1 650 ret void 651} 652 653define void @different_size1(i32* %arg) { 654; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly 655; IS__TUNIT____-LABEL: define {{[^@]+}}@different_size1 656; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull writeonly align 8 dereferenceable(8) [[ARG:%.*]]) [[ATTR4]] { 657; IS__TUNIT____-NEXT: [[ARG_CAST:%.*]] = bitcast i32* [[ARG]] to double* 658; IS__TUNIT____-NEXT: store double 0.000000e+00, double* [[ARG_CAST]], align 8 659; IS__TUNIT____-NEXT: store i32 0, i32* [[ARG]], align 8 660; IS__TUNIT____-NEXT: ret void 661; 662; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly 663; IS__CGSCC____-LABEL: define {{[^@]+}}@different_size1 664; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull writeonly align 8 dereferenceable(8) [[ARG:%.*]]) [[ATTR4]] { 665; IS__CGSCC____-NEXT: [[ARG_CAST:%.*]] = bitcast i32* [[ARG]] to double* 666; IS__CGSCC____-NEXT: store double 0.000000e+00, double* [[ARG_CAST]], align 8 667; IS__CGSCC____-NEXT: store i32 0, i32* [[ARG]], align 8 668; IS__CGSCC____-NEXT: ret void 669; 670 %arg-cast = bitcast i32* %arg to double* 671 store double 0.000000e+00, double* %arg-cast 672 store i32 0, i32* %arg 673 ret void 674} 675 676define void @different_size2(i32* %arg) { 677; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly 678; IS__TUNIT____-LABEL: define {{[^@]+}}@different_size2 679; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull writeonly align 8 dereferenceable(8) [[ARG:%.*]]) [[ATTR4]] { 680; IS__TUNIT____-NEXT: store i32 0, i32* [[ARG]], align 8 681; IS__TUNIT____-NEXT: [[ARG_CAST:%.*]] = bitcast i32* [[ARG]] to double* 682; IS__TUNIT____-NEXT: store double 0.000000e+00, double* [[ARG_CAST]], align 8 683; IS__TUNIT____-NEXT: ret void 684; 685; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly 686; IS__CGSCC____-LABEL: define {{[^@]+}}@different_size2 687; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull writeonly align 8 dereferenceable(8) [[ARG:%.*]]) [[ATTR4]] { 688; IS__CGSCC____-NEXT: store i32 0, i32* [[ARG]], align 8 689; IS__CGSCC____-NEXT: [[ARG_CAST:%.*]] = bitcast i32* [[ARG]] to double* 690; IS__CGSCC____-NEXT: store double 0.000000e+00, double* [[ARG_CAST]], align 8 691; IS__CGSCC____-NEXT: ret void 692; 693 store i32 0, i32* %arg 694 %arg-cast = bitcast i32* %arg to double* 695 store double 0.000000e+00, double* %arg-cast 696 ret void 697} 698 699; Make use of MustBeExecuted Explorer 700; 701; [CFG] 702; entry 703; / \ 704; l1 l2 705; | X | 706; l3 l4 707; \ / 708; l5 709; / \ 710; l6 l7 711; \ / 712; end 713; According to the above CFG, we can see that instructions in l5 Block must be executed. 714; Therefore, %p must be dereferenced. 715; 716; ATTRIBUTOR_CGSCC_NPM-LABEL: define i32 @require_cfg_analysis(i32 %c, i32* {{.*}} dereferenceable(4) %p) 717define i32 @require_cfg_analysis(i32 %c, i32* %p) { 718; IS__TUNIT_OPM: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly 719; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@require_cfg_analysis 720; IS__TUNIT_OPM-SAME: (i32 [[C:%.*]], i32* nocapture nofree writeonly [[P:%.*]]) [[ATTR4:#.*]] { 721; IS__TUNIT_OPM-NEXT: [[TOBOOL1:%.*]] = icmp eq i32 [[C]], 0 722; IS__TUNIT_OPM-NEXT: br i1 [[TOBOOL1]], label [[L1:%.*]], label [[L2:%.*]] 723; IS__TUNIT_OPM: l1: 724; IS__TUNIT_OPM-NEXT: [[TOBOOL2:%.*]] = icmp eq i32 [[C]], 1 725; IS__TUNIT_OPM-NEXT: br i1 [[TOBOOL2]], label [[L3:%.*]], label [[L4:%.*]] 726; IS__TUNIT_OPM: l2: 727; IS__TUNIT_OPM-NEXT: [[TOBOOL3:%.*]] = icmp eq i32 [[C]], 2 728; IS__TUNIT_OPM-NEXT: br i1 [[TOBOOL3]], label [[L3]], label [[L4]] 729; IS__TUNIT_OPM: l3: 730; IS__TUNIT_OPM-NEXT: br label [[L5:%.*]] 731; IS__TUNIT_OPM: l4: 732; IS__TUNIT_OPM-NEXT: br label [[L5]] 733; IS__TUNIT_OPM: l5: 734; IS__TUNIT_OPM-NEXT: [[TOBOOL4:%.*]] = icmp eq i32 [[C]], 4 735; IS__TUNIT_OPM-NEXT: br i1 [[TOBOOL4]], label [[L6:%.*]], label [[L7:%.*]] 736; IS__TUNIT_OPM: l6: 737; IS__TUNIT_OPM-NEXT: store i32 0, i32* [[P]], align 4 738; IS__TUNIT_OPM-NEXT: br label [[END:%.*]] 739; IS__TUNIT_OPM: l7: 740; IS__TUNIT_OPM-NEXT: store i32 1, i32* [[P]], align 4 741; IS__TUNIT_OPM-NEXT: br label [[END]] 742; IS__TUNIT_OPM: end: 743; IS__TUNIT_OPM-NEXT: ret i32 1 744; 745; IS__TUNIT_NPM: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly 746; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@require_cfg_analysis 747; IS__TUNIT_NPM-SAME: (i32 [[C:%.*]], i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[P:%.*]]) [[ATTR4:#.*]] { 748; IS__TUNIT_NPM-NEXT: [[TOBOOL1:%.*]] = icmp eq i32 [[C]], 0 749; IS__TUNIT_NPM-NEXT: br i1 [[TOBOOL1]], label [[L1:%.*]], label [[L2:%.*]] 750; IS__TUNIT_NPM: l1: 751; IS__TUNIT_NPM-NEXT: br label [[L4:%.*]] 752; IS__TUNIT_NPM: l2: 753; IS__TUNIT_NPM-NEXT: [[TOBOOL3:%.*]] = icmp eq i32 [[C]], 2 754; IS__TUNIT_NPM-NEXT: br i1 [[TOBOOL3]], label [[L3:%.*]], label [[L4]] 755; IS__TUNIT_NPM: l3: 756; IS__TUNIT_NPM-NEXT: br label [[L5:%.*]] 757; IS__TUNIT_NPM: l4: 758; IS__TUNIT_NPM-NEXT: br label [[L5]] 759; IS__TUNIT_NPM: l5: 760; IS__TUNIT_NPM-NEXT: [[TOBOOL4:%.*]] = icmp eq i32 [[C]], 4 761; IS__TUNIT_NPM-NEXT: br i1 [[TOBOOL4]], label [[L6:%.*]], label [[L7:%.*]] 762; IS__TUNIT_NPM: l6: 763; IS__TUNIT_NPM-NEXT: store i32 0, i32* [[P]], align 4 764; IS__TUNIT_NPM-NEXT: br label [[END:%.*]] 765; IS__TUNIT_NPM: l7: 766; IS__TUNIT_NPM-NEXT: store i32 1, i32* [[P]], align 4 767; IS__TUNIT_NPM-NEXT: br label [[END]] 768; IS__TUNIT_NPM: end: 769; IS__TUNIT_NPM-NEXT: ret i32 1 770; 771; IS__CGSCC_OPM: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly 772; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@require_cfg_analysis 773; IS__CGSCC_OPM-SAME: (i32 [[C:%.*]], i32* nocapture nofree writeonly [[P:%.*]]) [[ATTR4:#.*]] { 774; IS__CGSCC_OPM-NEXT: [[TOBOOL1:%.*]] = icmp eq i32 [[C]], 0 775; IS__CGSCC_OPM-NEXT: br i1 [[TOBOOL1]], label [[L1:%.*]], label [[L2:%.*]] 776; IS__CGSCC_OPM: l1: 777; IS__CGSCC_OPM-NEXT: [[TOBOOL2:%.*]] = icmp eq i32 [[C]], 1 778; IS__CGSCC_OPM-NEXT: br i1 [[TOBOOL2]], label [[L3:%.*]], label [[L4:%.*]] 779; IS__CGSCC_OPM: l2: 780; IS__CGSCC_OPM-NEXT: [[TOBOOL3:%.*]] = icmp eq i32 [[C]], 2 781; IS__CGSCC_OPM-NEXT: br i1 [[TOBOOL3]], label [[L3]], label [[L4]] 782; IS__CGSCC_OPM: l3: 783; IS__CGSCC_OPM-NEXT: br label [[L5:%.*]] 784; IS__CGSCC_OPM: l4: 785; IS__CGSCC_OPM-NEXT: br label [[L5]] 786; IS__CGSCC_OPM: l5: 787; IS__CGSCC_OPM-NEXT: [[TOBOOL4:%.*]] = icmp eq i32 [[C]], 4 788; IS__CGSCC_OPM-NEXT: br i1 [[TOBOOL4]], label [[L6:%.*]], label [[L7:%.*]] 789; IS__CGSCC_OPM: l6: 790; IS__CGSCC_OPM-NEXT: store i32 0, i32* [[P]], align 4 791; IS__CGSCC_OPM-NEXT: br label [[END:%.*]] 792; IS__CGSCC_OPM: l7: 793; IS__CGSCC_OPM-NEXT: store i32 1, i32* [[P]], align 4 794; IS__CGSCC_OPM-NEXT: br label [[END]] 795; IS__CGSCC_OPM: end: 796; IS__CGSCC_OPM-NEXT: ret i32 1 797; 798; IS__CGSCC_NPM: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly 799; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@require_cfg_analysis 800; IS__CGSCC_NPM-SAME: (i32 [[C:%.*]], i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[P:%.*]]) [[ATTR4:#.*]] { 801; IS__CGSCC_NPM-NEXT: [[TOBOOL1:%.*]] = icmp eq i32 [[C]], 0 802; IS__CGSCC_NPM-NEXT: br i1 [[TOBOOL1]], label [[L1:%.*]], label [[L2:%.*]] 803; IS__CGSCC_NPM: l1: 804; IS__CGSCC_NPM-NEXT: br label [[L4:%.*]] 805; IS__CGSCC_NPM: l2: 806; IS__CGSCC_NPM-NEXT: [[TOBOOL3:%.*]] = icmp eq i32 [[C]], 2 807; IS__CGSCC_NPM-NEXT: br i1 [[TOBOOL3]], label [[L3:%.*]], label [[L4]] 808; IS__CGSCC_NPM: l3: 809; IS__CGSCC_NPM-NEXT: br label [[L5:%.*]] 810; IS__CGSCC_NPM: l4: 811; IS__CGSCC_NPM-NEXT: br label [[L5]] 812; IS__CGSCC_NPM: l5: 813; IS__CGSCC_NPM-NEXT: [[TOBOOL4:%.*]] = icmp eq i32 [[C]], 4 814; IS__CGSCC_NPM-NEXT: br i1 [[TOBOOL4]], label [[L6:%.*]], label [[L7:%.*]] 815; IS__CGSCC_NPM: l6: 816; IS__CGSCC_NPM-NEXT: store i32 0, i32* [[P]], align 4 817; IS__CGSCC_NPM-NEXT: br label [[END:%.*]] 818; IS__CGSCC_NPM: l7: 819; IS__CGSCC_NPM-NEXT: store i32 1, i32* [[P]], align 4 820; IS__CGSCC_NPM-NEXT: br label [[END]] 821; IS__CGSCC_NPM: end: 822; IS__CGSCC_NPM-NEXT: ret i32 1 823; 824 %tobool1 = icmp eq i32 %c, 0 825 br i1 %tobool1, label %l1, label %l2 826l1: 827 %tobool2 = icmp eq i32 %c, 1 828 br i1 %tobool2, label %l3, label %l4 829l2: 830 %tobool3 = icmp eq i32 %c, 2 831 br i1 %tobool3, label %l3, label %l4 832l3: 833 br label %l5 834l4: 835 br label %l5 836l5: 837 %tobool4 = icmp eq i32 %c, 4 838 br i1 %tobool4, label %l6, label %l7 839l6: 840 store i32 0, i32* %p 841 br label %end 842l7: 843 store i32 1, i32* %p 844 br label %end 845end: 846 ret i32 1 847} 848