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=2 -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=2 -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 8@x = global i32 0 9 10declare void @test1_1(i8* %x1_1, i8* readonly %y1_1, ...) 11 12; NOTE: readonly for %y1_2 would be OK here but not for the similar situation in test13. 13; 14define void @test1_2(i8* %x1_2, i8* %y1_2, i8* %z1_2) { 15; CHECK-LABEL: define {{[^@]+}}@test1_2 16; CHECK-SAME: (i8* [[X1_2:%.*]], i8* [[Y1_2:%.*]], i8* [[Z1_2:%.*]]) { 17; CHECK-NEXT: call void (i8*, i8*, ...) @test1_1(i8* [[X1_2]], i8* readonly [[Y1_2]], i8* [[Z1_2]]) 18; CHECK-NEXT: store i32 0, i32* @x, align 4 19; CHECK-NEXT: ret void 20; 21 call void (i8*, i8*, ...) @test1_1(i8* %x1_2, i8* %y1_2, i8* %z1_2) 22 store i32 0, i32* @x 23 ret void 24} 25 26define i8* @test2(i8* %p) { 27; IS__TUNIT____: Function Attrs: nofree nosync nounwind willreturn writeonly 28; IS__TUNIT____-LABEL: define {{[^@]+}}@test2 29; IS__TUNIT____-SAME: (i8* nofree readnone returned "no-capture-maybe-returned" [[P:%.*]]) [[ATTR0:#.*]] { 30; IS__TUNIT____-NEXT: store i32 0, i32* @x, align 4 31; IS__TUNIT____-NEXT: ret i8* [[P]] 32; 33; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly 34; IS__CGSCC____-LABEL: define {{[^@]+}}@test2 35; IS__CGSCC____-SAME: (i8* nofree readnone returned "no-capture-maybe-returned" [[P:%.*]]) [[ATTR0:#.*]] { 36; IS__CGSCC____-NEXT: store i32 0, i32* @x, align 4 37; IS__CGSCC____-NEXT: ret i8* [[P]] 38; 39 store i32 0, i32* @x 40 ret i8* %p 41} 42 43define i1 @test3(i8* %p, i8* %q) { 44; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn 45; IS__TUNIT____-LABEL: define {{[^@]+}}@test3 46; IS__TUNIT____-SAME: (i8* nofree readnone [[P:%.*]], i8* nofree readnone [[Q:%.*]]) [[ATTR1:#.*]] { 47; IS__TUNIT____-NEXT: [[A:%.*]] = icmp ult i8* [[P]], [[Q]] 48; IS__TUNIT____-NEXT: ret i1 [[A]] 49; 50; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 51; IS__CGSCC____-LABEL: define {{[^@]+}}@test3 52; IS__CGSCC____-SAME: (i8* nofree readnone [[P:%.*]], i8* nofree readnone [[Q:%.*]]) [[ATTR1:#.*]] { 53; IS__CGSCC____-NEXT: [[A:%.*]] = icmp ult i8* [[P]], [[Q]] 54; IS__CGSCC____-NEXT: ret i1 [[A]] 55; 56 %A = icmp ult i8* %p, %q 57 ret i1 %A 58} 59 60declare void @test4_1(i8* nocapture) readonly 61 62define void @test4_2(i8* %p) { 63; CHECK: Function Attrs: readonly 64; CHECK-LABEL: define {{[^@]+}}@test4_2 65; CHECK-SAME: (i8* nocapture readonly [[P:%.*]]) [[ATTR2:#.*]] { 66; CHECK-NEXT: call void @test4_1(i8* nocapture readonly [[P]]) [[ATTR2]] 67; CHECK-NEXT: ret void 68; 69 call void @test4_1(i8* %p) 70 ret void 71} 72 73; Missed optz'n: we could make %q readnone, but don't break test6! 74define void @test5(i8** %p, i8* %q) { 75; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly 76; IS__TUNIT____-LABEL: define {{[^@]+}}@test5 77; IS__TUNIT____-SAME: (i8** nocapture nofree nonnull writeonly align 8 dereferenceable(8) [[P:%.*]], i8* nofree writeonly [[Q:%.*]]) [[ATTR3:#.*]] { 78; IS__TUNIT____-NEXT: store i8* [[Q]], i8** [[P]], align 8 79; IS__TUNIT____-NEXT: ret void 80; 81; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly 82; IS__CGSCC____-LABEL: define {{[^@]+}}@test5 83; IS__CGSCC____-SAME: (i8** nocapture nofree nonnull writeonly align 8 dereferenceable(8) [[P:%.*]], i8* nofree writeonly [[Q:%.*]]) [[ATTR3:#.*]] { 84; IS__CGSCC____-NEXT: store i8* [[Q]], i8** [[P]], align 8 85; IS__CGSCC____-NEXT: ret void 86; 87 store i8* %q, i8** %p 88 ret void 89} 90 91declare void @test6_1() 92; This is not a missed optz'n. 93define void @test6_2(i8** %p, i8* %q) { 94; CHECK-LABEL: define {{[^@]+}}@test6_2 95; CHECK-SAME: (i8** nocapture nonnull writeonly align 8 dereferenceable(8) [[P:%.*]], i8* [[Q:%.*]]) { 96; CHECK-NEXT: store i8* [[Q]], i8** [[P]], align 8 97; CHECK-NEXT: call void @test6_1() 98; CHECK-NEXT: ret void 99; 100 store i8* %q, i8** %p 101 call void @test6_1() 102 ret void 103} 104 105; inalloca parameters are always considered written 106define void @test7_1(i32* inalloca %a) { 107; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn 108; IS__TUNIT____-LABEL: define {{[^@]+}}@test7_1 109; IS__TUNIT____-SAME: (i32* inalloca nocapture nofree nonnull writeonly dereferenceable(4) [[A:%.*]]) [[ATTR1]] { 110; IS__TUNIT____-NEXT: ret void 111; 112; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 113; IS__CGSCC____-LABEL: define {{[^@]+}}@test7_1 114; IS__CGSCC____-SAME: (i32* inalloca nocapture nofree nonnull writeonly dereferenceable(4) [[A:%.*]]) [[ATTR1]] { 115; IS__CGSCC____-NEXT: ret void 116; 117 ret void 118} 119 120define i32* @test8_1(i32* %p) { 121; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn 122; IS__TUNIT____-LABEL: define {{[^@]+}}@test8_1 123; IS__TUNIT____-SAME: (i32* nofree readnone returned "no-capture-maybe-returned" [[P:%.*]]) [[ATTR1]] { 124; IS__TUNIT____-NEXT: entry: 125; IS__TUNIT____-NEXT: ret i32* [[P]] 126; 127; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 128; IS__CGSCC____-LABEL: define {{[^@]+}}@test8_1 129; IS__CGSCC____-SAME: (i32* nofree readnone returned "no-capture-maybe-returned" [[P:%.*]]) [[ATTR1]] { 130; IS__CGSCC____-NEXT: entry: 131; IS__CGSCC____-NEXT: ret i32* [[P]] 132; 133entry: 134 ret i32* %p 135} 136 137define void @test8_2(i32* %p) { 138; IS__TUNIT____: Function Attrs: nofree nosync nounwind willreturn writeonly 139; IS__TUNIT____-LABEL: define {{[^@]+}}@test8_2 140; IS__TUNIT____-SAME: (i32* nocapture nofree writeonly [[P:%.*]]) [[ATTR0]] { 141; IS__TUNIT____-NEXT: entry: 142; IS__TUNIT____-NEXT: [[CALL:%.*]] = call i32* @test8_1(i32* noalias nofree readnone "no-capture-maybe-returned" [[P]]) [[ATTR1]] 143; IS__TUNIT____-NEXT: store i32 10, i32* [[CALL]], align 4 144; IS__TUNIT____-NEXT: ret void 145; 146; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly 147; IS__CGSCC____-LABEL: define {{[^@]+}}@test8_2 148; IS__CGSCC____-SAME: (i32* nocapture nofree writeonly [[P:%.*]]) [[ATTR3]] { 149; IS__CGSCC____-NEXT: entry: 150; IS__CGSCC____-NEXT: [[CALL:%.*]] = call align 4 i32* @test8_1(i32* noalias nofree readnone "no-capture-maybe-returned" [[P]]) [[ATTR11:#.*]] 151; IS__CGSCC____-NEXT: store i32 10, i32* [[CALL]], align 4 152; IS__CGSCC____-NEXT: ret void 153; 154entry: 155 %call = call i32* @test8_1(i32* %p) 156 store i32 10, i32* %call, align 4 157 ret void 158} 159 160; CHECK: declare void @llvm.masked.scatter 161declare void @llvm.masked.scatter.v4i32.v4p0i32(<4 x i32>%val, <4 x i32*>, i32, <4 x i1>) 162 163; CHECK-NOT: readnone 164; CHECK-NOT: readonly 165define void @test9(<4 x i32*> %ptrs, <4 x i32>%val) { 166; IS__TUNIT____: Function Attrs: nofree nosync nounwind willreturn writeonly 167; IS__TUNIT____-LABEL: define {{[^@]+}}@test9 168; IS__TUNIT____-SAME: (<4 x i32*> [[PTRS:%.*]], <4 x i32> [[VAL:%.*]]) [[ATTR0]] { 169; IS__TUNIT____-NEXT: call void @llvm.masked.scatter.v4i32.v4p0i32(<4 x i32> [[VAL]], <4 x i32*> [[PTRS]], i32 noundef 4, <4 x i1> noundef <i1 true, i1 false, i1 true, i1 false>) [[ATTR10:#.*]] 170; IS__TUNIT____-NEXT: ret void 171; 172; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn writeonly 173; IS__CGSCC____-LABEL: define {{[^@]+}}@test9 174; IS__CGSCC____-SAME: (<4 x i32*> [[PTRS:%.*]], <4 x i32> [[VAL:%.*]]) [[ATTR4:#.*]] { 175; IS__CGSCC____-NEXT: call void @llvm.masked.scatter.v4i32.v4p0i32(<4 x i32> [[VAL]], <4 x i32*> [[PTRS]], i32 noundef 4, <4 x i1> noundef <i1 true, i1 false, i1 true, i1 false>) [[ATTR12:#.*]] 176; IS__CGSCC____-NEXT: ret void 177; 178 call void @llvm.masked.scatter.v4i32.v4p0i32(<4 x i32>%val, <4 x i32*> %ptrs, i32 4, <4 x i1><i1 true, i1 false, i1 true, i1 false>) 179 ret void 180} 181 182; CHECK: declare <4 x i32> @llvm.masked.gather 183declare <4 x i32> @llvm.masked.gather.v4i32.v4p0i32(<4 x i32*>, i32, <4 x i1>, <4 x i32>) 184define <4 x i32> @test10(<4 x i32*> %ptrs) { 185; IS__TUNIT____: Function Attrs: nofree nosync nounwind readonly willreturn 186; IS__TUNIT____-LABEL: define {{[^@]+}}@test10 187; IS__TUNIT____-SAME: (<4 x i32*> [[PTRS:%.*]]) [[ATTR4:#.*]] { 188; IS__TUNIT____-NEXT: [[RES:%.*]] = call <4 x i32> @llvm.masked.gather.v4i32.v4p0i32(<4 x i32*> [[PTRS]], i32 noundef 4, <4 x i1> noundef <i1 true, i1 false, i1 true, i1 false>, <4 x i32> undef) [[ATTR11:#.*]] 189; IS__TUNIT____-NEXT: ret <4 x i32> [[RES]] 190; 191; IS__CGSCC____: Function Attrs: nofree nosync nounwind readonly willreturn 192; IS__CGSCC____-LABEL: define {{[^@]+}}@test10 193; IS__CGSCC____-SAME: (<4 x i32*> [[PTRS:%.*]]) [[ATTR5:#.*]] { 194; IS__CGSCC____-NEXT: [[RES:%.*]] = call <4 x i32> @llvm.masked.gather.v4i32.v4p0i32(<4 x i32*> [[PTRS]], i32 noundef 4, <4 x i1> noundef <i1 true, i1 false, i1 true, i1 false>, <4 x i32> undef) [[ATTR13:#.*]] 195; IS__CGSCC____-NEXT: ret <4 x i32> [[RES]] 196; 197 %res = call <4 x i32> @llvm.masked.gather.v4i32.v4p0i32(<4 x i32*> %ptrs, i32 4, <4 x i1><i1 true, i1 false, i1 true, i1 false>, <4 x i32>undef) 198 ret <4 x i32> %res 199} 200 201; CHECK: declare <4 x i32> @test11_1 202declare <4 x i32> @test11_1(<4 x i32*>) argmemonly nounwind readonly 203define <4 x i32> @test11_2(<4 x i32*> %ptrs) { 204; CHECK: Function Attrs: argmemonly nounwind readonly 205; CHECK-LABEL: define {{[^@]+}}@test11_2 206; CHECK-SAME: (<4 x i32*> [[PTRS:%.*]]) [[ATTR6:#.*]] { 207; CHECK-NEXT: [[RES:%.*]] = call <4 x i32> @test11_1(<4 x i32*> [[PTRS]]) [[ATTR2]] 208; CHECK-NEXT: ret <4 x i32> [[RES]] 209; 210 %res = call <4 x i32> @test11_1(<4 x i32*> %ptrs) 211 ret <4 x i32> %res 212} 213 214declare <4 x i32> @test12_1(<4 x i32*>) argmemonly nounwind 215; CHECK-NOT: readnone 216define <4 x i32> @test12_2(<4 x i32*> %ptrs) { 217; IS__TUNIT____: Function Attrs: argmemonly nounwind 218; IS__TUNIT____-LABEL: define {{[^@]+}}@test12_2 219; IS__TUNIT____-SAME: (<4 x i32*> [[PTRS:%.*]]) [[ATTR6:#.*]] { 220; IS__TUNIT____-NEXT: [[RES:%.*]] = call <4 x i32> @test12_1(<4 x i32*> [[PTRS]]) [[ATTR12:#.*]] 221; IS__TUNIT____-NEXT: ret <4 x i32> [[RES]] 222; 223; IS__CGSCC____: Function Attrs: argmemonly nounwind 224; IS__CGSCC____-LABEL: define {{[^@]+}}@test12_2 225; IS__CGSCC____-SAME: (<4 x i32*> [[PTRS:%.*]]) [[ATTR7:#.*]] { 226; IS__CGSCC____-NEXT: [[RES:%.*]] = call <4 x i32> @test12_1(<4 x i32*> [[PTRS]]) [[ATTR14:#.*]] 227; IS__CGSCC____-NEXT: ret <4 x i32> [[RES]] 228; 229 %res = call <4 x i32> @test12_1(<4 x i32*> %ptrs) 230 ret <4 x i32> %res 231} 232 233define i32 @volatile_load(i32* %p) { 234; IS__TUNIT____: Function Attrs: argmemonly nofree nounwind willreturn 235; IS__TUNIT____-LABEL: define {{[^@]+}}@volatile_load 236; IS__TUNIT____-SAME: (i32* nofree align 4 [[P:%.*]]) [[ATTR7:#.*]] { 237; IS__TUNIT____-NEXT: [[LOAD:%.*]] = load volatile i32, i32* [[P]], align 4 238; IS__TUNIT____-NEXT: ret i32 [[LOAD]] 239; 240; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nounwind willreturn 241; IS__CGSCC____-LABEL: define {{[^@]+}}@volatile_load 242; IS__CGSCC____-SAME: (i32* nofree align 4 [[P:%.*]]) [[ATTR8:#.*]] { 243; IS__CGSCC____-NEXT: [[LOAD:%.*]] = load volatile i32, i32* [[P]], align 4 244; IS__CGSCC____-NEXT: ret i32 [[LOAD]] 245; 246 %load = load volatile i32, i32* %p 247 ret i32 %load 248} 249 250declare void @escape_readnone_ptr(i8** %addr, i8* readnone %ptr) 251declare void @escape_readonly_ptr(i8** %addr, i8* readonly %ptr) 252 253; The argument pointer %escaped_then_written cannot be marked readnone/only even 254; though the only direct use, in @escape_readnone_ptr/@escape_readonly_ptr, 255; is marked as readnone/only. However, the functions can write the pointer into 256; %addr, causing the store to write to %escaped_then_written. 257; 258define void @unsound_readnone(i8* %ignored, i8* %escaped_then_written) { 259; CHECK-LABEL: define {{[^@]+}}@unsound_readnone 260; CHECK-SAME: (i8* nocapture nofree readnone [[IGNORED:%.*]], i8* [[ESCAPED_THEN_WRITTEN:%.*]]) { 261; CHECK-NEXT: [[ADDR:%.*]] = alloca i8*, align 8 262; CHECK-NEXT: call void @escape_readnone_ptr(i8** noundef nonnull align 8 dereferenceable(8) [[ADDR]], i8* noalias readnone [[ESCAPED_THEN_WRITTEN]]) 263; CHECK-NEXT: [[ADDR_LD:%.*]] = load i8*, i8** [[ADDR]], align 8 264; CHECK-NEXT: store i8 0, i8* [[ADDR_LD]], align 1 265; CHECK-NEXT: ret void 266; 267 %addr = alloca i8* 268 call void @escape_readnone_ptr(i8** %addr, i8* %escaped_then_written) 269 %addr.ld = load i8*, i8** %addr 270 store i8 0, i8* %addr.ld 271 ret void 272} 273 274define void @unsound_readonly(i8* %ignored, i8* %escaped_then_written) { 275; CHECK-LABEL: define {{[^@]+}}@unsound_readonly 276; CHECK-SAME: (i8* nocapture nofree readnone [[IGNORED:%.*]], i8* [[ESCAPED_THEN_WRITTEN:%.*]]) { 277; CHECK-NEXT: [[ADDR:%.*]] = alloca i8*, align 8 278; CHECK-NEXT: call void @escape_readonly_ptr(i8** noundef nonnull align 8 dereferenceable(8) [[ADDR]], i8* readonly [[ESCAPED_THEN_WRITTEN]]) 279; CHECK-NEXT: [[ADDR_LD:%.*]] = load i8*, i8** [[ADDR]], align 8 280; CHECK-NEXT: store i8 0, i8* [[ADDR_LD]], align 1 281; CHECK-NEXT: ret void 282; 283 %addr = alloca i8* 284 call void @escape_readonly_ptr(i8** %addr, i8* %escaped_then_written) 285 %addr.ld = load i8*, i8** %addr 286 store i8 0, i8* %addr.ld 287 ret void 288} 289 290; Byval but not readonly/none tests 291; 292;{ 293declare void @escape_i8(i8* %ptr) 294 295define void @byval_not_readonly_1(i8* byval(i8) %written) readonly { 296; CHECK: Function Attrs: readonly 297; CHECK-LABEL: define {{[^@]+}}@byval_not_readonly_1 298; CHECK-SAME: (i8* noalias nonnull byval(i8) dereferenceable(1) [[WRITTEN:%.*]]) [[ATTR2]] { 299; CHECK-NEXT: call void @escape_i8(i8* nonnull dereferenceable(1) [[WRITTEN]]) 300; CHECK-NEXT: ret void 301; 302 call void @escape_i8(i8* %written) 303 ret void 304} 305 306define void @byval_not_readonly_2(i8* byval(i8) %written) readonly { 307; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn 308; IS__TUNIT____-LABEL: define {{[^@]+}}@byval_not_readonly_2 309; IS__TUNIT____-SAME: (i8* noalias nocapture nofree nonnull writeonly byval(i8) dereferenceable(1) [[WRITTEN:%.*]]) [[ATTR1]] { 310; IS__TUNIT____-NEXT: store i8 0, i8* [[WRITTEN]], align 1 311; IS__TUNIT____-NEXT: ret void 312; 313; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 314; IS__CGSCC____-LABEL: define {{[^@]+}}@byval_not_readonly_2 315; IS__CGSCC____-SAME: (i8* noalias nocapture nofree nonnull writeonly byval(i8) dereferenceable(1) [[WRITTEN:%.*]]) [[ATTR1]] { 316; IS__CGSCC____-NEXT: store i8 0, i8* [[WRITTEN]], align 1 317; IS__CGSCC____-NEXT: ret void 318; 319 store i8 0, i8* %written 320 ret void 321} 322 323define void @byval_not_readnone_1(i8* byval(i8) %written) readnone { 324; CHECK: Function Attrs: readnone 325; CHECK-LABEL: define {{[^@]+}}@byval_not_readnone_1 326; CHECK-SAME: (i8* noalias nonnull byval(i8) dereferenceable(1) [[WRITTEN:%.*]]) [[ATTR9:#.*]] { 327; CHECK-NEXT: call void @escape_i8(i8* nonnull dereferenceable(1) [[WRITTEN]]) 328; CHECK-NEXT: ret void 329; 330 call void @escape_i8(i8* %written) 331 ret void 332} 333 334define void @byval_not_readnone_2(i8* byval(i8) %written) readnone { 335; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn 336; IS__TUNIT____-LABEL: define {{[^@]+}}@byval_not_readnone_2 337; IS__TUNIT____-SAME: (i8* noalias nocapture nofree nonnull writeonly byval(i8) dereferenceable(1) [[WRITTEN:%.*]]) [[ATTR1]] { 338; IS__TUNIT____-NEXT: store i8 0, i8* [[WRITTEN]], align 1 339; IS__TUNIT____-NEXT: ret void 340; 341; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 342; IS__CGSCC____-LABEL: define {{[^@]+}}@byval_not_readnone_2 343; IS__CGSCC____-SAME: (i8* noalias nocapture nofree nonnull writeonly byval(i8) dereferenceable(1) [[WRITTEN:%.*]]) [[ATTR1]] { 344; IS__CGSCC____-NEXT: store i8 0, i8* [[WRITTEN]], align 1 345; IS__CGSCC____-NEXT: ret void 346; 347 store i8 0, i8* %written 348 ret void 349} 350 351define void @byval_no_fnarg(i8* byval(i8) %written) { 352; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn 353; IS__TUNIT____-LABEL: define {{[^@]+}}@byval_no_fnarg 354; IS__TUNIT____-SAME: (i8* noalias nocapture nofree nonnull writeonly byval(i8) dereferenceable(1) [[WRITTEN:%.*]]) [[ATTR1]] { 355; IS__TUNIT____-NEXT: store i8 0, i8* [[WRITTEN]], align 1 356; IS__TUNIT____-NEXT: ret void 357; 358; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 359; IS__CGSCC____-LABEL: define {{[^@]+}}@byval_no_fnarg 360; IS__CGSCC____-SAME: (i8* noalias nocapture nofree nonnull writeonly byval(i8) dereferenceable(1) [[WRITTEN:%.*]]) [[ATTR1]] { 361; IS__CGSCC____-NEXT: store i8 0, i8* [[WRITTEN]], align 1 362; IS__CGSCC____-NEXT: ret void 363; 364 store i8 0, i8* %written 365 ret void 366} 367 368define void @testbyval(i8* %read_only) { 369; IS__TUNIT____-LABEL: define {{[^@]+}}@testbyval 370; IS__TUNIT____-SAME: (i8* nocapture readonly [[READ_ONLY:%.*]]) { 371; IS__TUNIT____-NEXT: call void @byval_not_readonly_1(i8* nocapture readonly [[READ_ONLY]]) [[ATTR2:#.*]] 372; IS__TUNIT____-NEXT: call void @byval_not_readnone_1(i8* noalias nocapture readnone [[READ_ONLY]]) 373; IS__TUNIT____-NEXT: ret void 374; 375; IS__CGSCC____: Function Attrs: readonly 376; IS__CGSCC____-LABEL: define {{[^@]+}}@testbyval 377; IS__CGSCC____-SAME: (i8* nocapture nonnull readonly dereferenceable(1) [[READ_ONLY:%.*]]) [[ATTR2:#.*]] { 378; IS__CGSCC____-NEXT: call void @byval_not_readonly_1(i8* noalias nocapture nonnull readonly dereferenceable(1) [[READ_ONLY]]) [[ATTR2]] 379; IS__CGSCC____-NEXT: call void @byval_not_readnone_1(i8* noalias nocapture nonnull readnone dereferenceable(1) [[READ_ONLY]]) 380; IS__CGSCC____-NEXT: ret void 381; 382 call void @byval_not_readonly_1(i8* %read_only) 383 call void @byval_not_readonly_2(i8* %read_only) 384 call void @byval_not_readnone_1(i8* %read_only) 385 call void @byval_not_readnone_2(i8* %read_only) 386 call void @byval_no_fnarg(i8* %read_only) 387 ret void 388} 389;} 390 391declare i8* @maybe_returned_ptr(i8* readonly %ptr) readonly nounwind 392declare i8 @maybe_returned_val(i8* %ptr) readonly nounwind 393declare void @val_use(i8 %ptr) readonly nounwind 394 395define void @ptr_uses(i8* %ptr) { 396; CHECK: Function Attrs: nounwind readonly 397; CHECK-LABEL: define {{[^@]+}}@ptr_uses 398; CHECK-SAME: (i8* nocapture readonly [[PTR:%.*]]) [[ATTR10:#.*]] { 399; CHECK-NEXT: ret void 400; 401 %call_ptr = call i8* @maybe_returned_ptr(i8* %ptr) 402 %call_val = call i8 @maybe_returned_val(i8* %call_ptr) 403 call void @val_use(i8 %call_val) 404 ret void 405} 406 407define void @ptr_use_chain(i8* %ptr) { 408; CHECK-LABEL: define {{[^@]+}}@ptr_use_chain 409; CHECK-SAME: (i8* [[PTR:%.*]]) { 410; CHECK-NEXT: [[BC0:%.*]] = bitcast i8* [[PTR]] to i32* 411; CHECK-NEXT: [[BC1:%.*]] = bitcast i32* [[BC0]] to i8* 412; CHECK-NEXT: [[BC2:%.*]] = bitcast i8* [[BC1]] to i32* 413; CHECK-NEXT: [[BC3:%.*]] = bitcast i32* [[BC2]] to i8* 414; CHECK-NEXT: [[BC4:%.*]] = bitcast i8* [[BC3]] to i32* 415; CHECK-NEXT: [[BC5:%.*]] = bitcast i32* [[BC4]] to i8* 416; CHECK-NEXT: [[BC6:%.*]] = bitcast i8* [[BC5]] to i32* 417; CHECK-NEXT: [[BC7:%.*]] = bitcast i32* [[BC6]] to i8* 418; CHECK-NEXT: [[BC8:%.*]] = bitcast i8* [[BC7]] to i32* 419; CHECK-NEXT: [[BC9:%.*]] = bitcast i32* [[BC8]] to i8* 420; CHECK-NEXT: [[ABC2:%.*]] = bitcast i8* [[BC9]] to i32* 421; CHECK-NEXT: [[ABC3:%.*]] = bitcast i32* [[ABC2]] to i8* 422; CHECK-NEXT: [[ABC4:%.*]] = bitcast i8* [[ABC3]] to i32* 423; CHECK-NEXT: [[ABC5:%.*]] = bitcast i32* [[ABC4]] to i8* 424; CHECK-NEXT: [[ABC6:%.*]] = bitcast i8* [[ABC5]] to i32* 425; CHECK-NEXT: [[ABC7:%.*]] = bitcast i32* [[ABC6]] to i8* 426; CHECK-NEXT: [[ABC8:%.*]] = bitcast i8* [[ABC7]] to i32* 427; CHECK-NEXT: [[ABC9:%.*]] = bitcast i32* [[ABC8]] to i8* 428; CHECK-NEXT: call void @escape_i8(i8* [[ABC9]]) 429; CHECK-NEXT: ret void 430; 431 %bc0 = bitcast i8* %ptr to i32* 432 %bc1 = bitcast i32* %bc0 to i8* 433 %bc2 = bitcast i8* %bc1 to i32* 434 %bc3 = bitcast i32* %bc2 to i8* 435 %bc4 = bitcast i8* %bc3 to i32* 436 %bc5 = bitcast i32* %bc4 to i8* 437 %bc6 = bitcast i8* %bc5 to i32* 438 %bc7 = bitcast i32* %bc6 to i8* 439 %bc8 = bitcast i8* %bc7 to i32* 440 %bc9 = bitcast i32* %bc8 to i8* 441 %abc2 = bitcast i8* %bc9 to i32* 442 %abc3 = bitcast i32* %abc2 to i8* 443 %abc4 = bitcast i8* %abc3 to i32* 444 %abc5 = bitcast i32* %abc4 to i8* 445 %abc6 = bitcast i8* %abc5 to i32* 446 %abc7 = bitcast i32* %abc6 to i8* 447 %abc8 = bitcast i8* %abc7 to i32* 448 %abc9 = bitcast i32* %abc8 to i8* 449 call void @escape_i8(i8* %abc9) 450 ret void 451} 452 453@constant_mem = external dso_local constant i32, align 4 454define i32 @read_only_constant_mem() { 455; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn 456; IS__TUNIT____-LABEL: define {{[^@]+}}@read_only_constant_mem 457; IS__TUNIT____-SAME: () [[ATTR1]] { 458; IS__TUNIT____-NEXT: [[L:%.*]] = load i32, i32* @constant_mem, align 4 459; IS__TUNIT____-NEXT: ret i32 [[L]] 460; 461; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 462; IS__CGSCC____-LABEL: define {{[^@]+}}@read_only_constant_mem 463; IS__CGSCC____-SAME: () [[ATTR1]] { 464; IS__CGSCC____-NEXT: [[L:%.*]] = load i32, i32* @constant_mem, align 4 465; IS__CGSCC____-NEXT: ret i32 [[L]] 466; 467 %l = load i32, i32* @constant_mem 468 ret i32 %l 469} 470