1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes 2; RUN: opt < %s -passes=function-attrs -S | FileCheck --check-prefixes=COMMON,FNATTRS %s 3; RUN: opt < %s -passes=attributor-light -S | FileCheck --check-prefixes=COMMON,ATTRIBUTOR %s 4; RUN: opt < %s -passes=attributor-light-cgscc -S | FileCheck --check-prefixes=COMMON,ATTRIBUTOR-CGSCC %s 5 6@x = global i32 0 7 8declare void @test1_1(ptr %x1_1, ptr nocapture readonly %y1_1, ...) 9 10define void @test1_2(ptr %x1_2, ptr %y1_2, ptr %z1_2) { 11; FNATTRS-LABEL: define {{[^@]+}}@test1_2 12; FNATTRS-SAME: (ptr [[X1_2:%.*]], ptr readonly captures(none) [[Y1_2:%.*]], ptr [[Z1_2:%.*]]) { 13; FNATTRS-NEXT: call void (ptr, ptr, ...) @test1_1(ptr [[X1_2]], ptr [[Y1_2]], ptr [[Z1_2]]) 14; FNATTRS-NEXT: store i32 0, ptr @x, align 4 15; FNATTRS-NEXT: ret void 16; 17; ATTRIBUTOR-LABEL: define {{[^@]+}}@test1_2 18; ATTRIBUTOR-SAME: (ptr [[X1_2:%.*]], ptr nofree readonly captures(none) [[Y1_2:%.*]], ptr [[Z1_2:%.*]]) { 19; ATTRIBUTOR-NEXT: call void (ptr, ptr, ...) @test1_1(ptr [[X1_2]], ptr nofree readonly captures(none) [[Y1_2]], ptr [[Z1_2]]) 20; ATTRIBUTOR-NEXT: store i32 0, ptr @x, align 4 21; ATTRIBUTOR-NEXT: ret void 22; 23; ATTRIBUTOR-CGSCC-LABEL: define {{[^@]+}}@test1_2 24; ATTRIBUTOR-CGSCC-SAME: (ptr [[X1_2:%.*]], ptr nofree readonly captures(none) [[Y1_2:%.*]], ptr [[Z1_2:%.*]]) { 25; ATTRIBUTOR-CGSCC-NEXT: call void (ptr, ptr, ...) @test1_1(ptr [[X1_2]], ptr nofree readonly captures(none) [[Y1_2]], ptr [[Z1_2]]) 26; ATTRIBUTOR-CGSCC-NEXT: store i32 0, ptr @x, align 4 27; ATTRIBUTOR-CGSCC-NEXT: ret void 28; 29 call void (ptr, ptr, ...) @test1_1(ptr %x1_2, ptr %y1_2, ptr %z1_2) 30 store i32 0, ptr @x 31 ret void 32} 33 34; TODO: Missing with attributor-light: argmem: none, inaccessiblemem: none 35define ptr @test2(ptr %p) { 36; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write, argmem: none, inaccessiblemem: none) 37; FNATTRS-LABEL: define {{[^@]+}}@test2 38; FNATTRS-SAME: (ptr readnone returned [[P:%.*]]) #[[ATTR0:[0-9]+]] { 39; FNATTRS-NEXT: store i32 0, ptr @x, align 4 40; FNATTRS-NEXT: ret ptr [[P]] 41; 42; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write) 43; ATTRIBUTOR-LABEL: define {{[^@]+}}@test2 44; ATTRIBUTOR-SAME: (ptr nofree readnone [[P:%.*]]) #[[ATTR0:[0-9]+]] { 45; ATTRIBUTOR-NEXT: store i32 0, ptr @x, align 4 46; ATTRIBUTOR-NEXT: ret ptr [[P]] 47; 48; ATTRIBUTOR-CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write) 49; ATTRIBUTOR-CGSCC-LABEL: define {{[^@]+}}@test2 50; ATTRIBUTOR-CGSCC-SAME: (ptr nofree readnone [[P:%.*]]) #[[ATTR0:[0-9]+]] { 51; ATTRIBUTOR-CGSCC-NEXT: store i32 0, ptr @x, align 4 52; ATTRIBUTOR-CGSCC-NEXT: ret ptr [[P]] 53; 54 store i32 0, ptr @x 55 ret ptr %p 56} 57 58define i1 @test3(ptr %p, ptr %q) { 59; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 60; FNATTRS-LABEL: define {{[^@]+}}@test3 61; FNATTRS-SAME: (ptr readnone [[P:%.*]], ptr readnone [[Q:%.*]]) #[[ATTR1:[0-9]+]] { 62; FNATTRS-NEXT: [[A:%.*]] = icmp ult ptr [[P]], [[Q]] 63; FNATTRS-NEXT: ret i1 [[A]] 64; 65; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 66; ATTRIBUTOR-LABEL: define {{[^@]+}}@test3 67; ATTRIBUTOR-SAME: (ptr nofree readnone [[P:%.*]], ptr nofree readnone [[Q:%.*]]) #[[ATTR1:[0-9]+]] { 68; ATTRIBUTOR-NEXT: [[A:%.*]] = icmp ult ptr [[P]], [[Q]] 69; ATTRIBUTOR-NEXT: ret i1 [[A]] 70; 71; ATTRIBUTOR-CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 72; ATTRIBUTOR-CGSCC-LABEL: define {{[^@]+}}@test3 73; ATTRIBUTOR-CGSCC-SAME: (ptr nofree readnone [[P:%.*]], ptr nofree readnone [[Q:%.*]]) #[[ATTR1:[0-9]+]] { 74; ATTRIBUTOR-CGSCC-NEXT: [[A:%.*]] = icmp ult ptr [[P]], [[Q]] 75; ATTRIBUTOR-CGSCC-NEXT: ret i1 [[A]] 76; 77 %A = icmp ult ptr %p, %q 78 ret i1 %A 79} 80 81declare void @test4_1(ptr nocapture) readonly 82 83define void @test4_2(ptr %p) { 84; FNATTRS: Function Attrs: nofree memory(read) 85; FNATTRS-LABEL: define {{[^@]+}}@test4_2 86; FNATTRS-SAME: (ptr readonly captures(none) [[P:%.*]]) #[[ATTR3:[0-9]+]] { 87; FNATTRS-NEXT: call void @test4_1(ptr [[P]]) 88; FNATTRS-NEXT: ret void 89; 90; ATTRIBUTOR: Function Attrs: nosync memory(read) 91; ATTRIBUTOR-LABEL: define {{[^@]+}}@test4_2 92; ATTRIBUTOR-SAME: (ptr readonly captures(none) [[P:%.*]]) #[[ATTR3:[0-9]+]] { 93; ATTRIBUTOR-NEXT: call void @test4_1(ptr readonly captures(none) [[P]]) #[[ATTR3]] 94; ATTRIBUTOR-NEXT: ret void 95; 96; ATTRIBUTOR-CGSCC: Function Attrs: nosync memory(read) 97; ATTRIBUTOR-CGSCC-LABEL: define {{[^@]+}}@test4_2 98; ATTRIBUTOR-CGSCC-SAME: (ptr readonly captures(none) [[P:%.*]]) #[[ATTR3:[0-9]+]] { 99; ATTRIBUTOR-CGSCC-NEXT: call void @test4_1(ptr readonly captures(none) [[P]]) #[[ATTR3]] 100; ATTRIBUTOR-CGSCC-NEXT: ret void 101; 102 call void @test4_1(ptr %p) 103 ret void 104} 105 106; Missed optz'n: we could make %q readnone, but don't break test6! 107define void @test5(ptr %p, ptr %q) { 108; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) 109; FNATTRS-LABEL: define {{[^@]+}}@test5 110; FNATTRS-SAME: (ptr writeonly captures(none) initializes((0, 8)) [[P:%.*]], ptr [[Q:%.*]]) #[[ATTR4:[0-9]+]] { 111; FNATTRS-NEXT: store ptr [[Q]], ptr [[P]], align 8 112; FNATTRS-NEXT: ret void 113; 114; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) 115; ATTRIBUTOR-LABEL: define {{[^@]+}}@test5 116; ATTRIBUTOR-SAME: (ptr nofree nonnull writeonly captures(none) [[P:%.*]], ptr nofree writeonly [[Q:%.*]]) #[[ATTR4:[0-9]+]] { 117; ATTRIBUTOR-NEXT: store ptr [[Q]], ptr [[P]], align 8 118; ATTRIBUTOR-NEXT: ret void 119; 120; ATTRIBUTOR-CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) 121; ATTRIBUTOR-CGSCC-LABEL: define {{[^@]+}}@test5 122; ATTRIBUTOR-CGSCC-SAME: (ptr nofree nonnull writeonly captures(none) [[P:%.*]], ptr nofree writeonly [[Q:%.*]]) #[[ATTR4:[0-9]+]] { 123; ATTRIBUTOR-CGSCC-NEXT: store ptr [[Q]], ptr [[P]], align 8 124; ATTRIBUTOR-CGSCC-NEXT: ret void 125; 126 store ptr %q, ptr %p 127 ret void 128} 129 130declare void @test6_1() 131 132; This is not a missed optz'n. 133define void @test6_2(ptr %p, ptr %q) { 134; FNATTRS-LABEL: define {{[^@]+}}@test6_2 135; FNATTRS-SAME: (ptr writeonly captures(none) initializes((0, 8)) [[P:%.*]], ptr [[Q:%.*]]) { 136; FNATTRS-NEXT: store ptr [[Q]], ptr [[P]], align 8 137; FNATTRS-NEXT: call void @test6_1() 138; FNATTRS-NEXT: ret void 139; 140; ATTRIBUTOR-LABEL: define {{[^@]+}}@test6_2 141; ATTRIBUTOR-SAME: (ptr nofree nonnull writeonly captures(none) [[P:%.*]], ptr nofree [[Q:%.*]]) { 142; ATTRIBUTOR-NEXT: store ptr [[Q]], ptr [[P]], align 8 143; ATTRIBUTOR-NEXT: call void @test6_1() 144; ATTRIBUTOR-NEXT: ret void 145; 146; ATTRIBUTOR-CGSCC-LABEL: define {{[^@]+}}@test6_2 147; ATTRIBUTOR-CGSCC-SAME: (ptr nofree nonnull writeonly captures(none) [[P:%.*]], ptr nofree [[Q:%.*]]) { 148; ATTRIBUTOR-CGSCC-NEXT: store ptr [[Q]], ptr [[P]], align 8 149; ATTRIBUTOR-CGSCC-NEXT: call void @test6_1() 150; ATTRIBUTOR-CGSCC-NEXT: ret void 151; 152 store ptr %q, ptr %p 153 call void @test6_1() 154 ret void 155} 156 157; inalloca parameters are always considered written 158define void @test7_1(ptr inalloca(i32) %a) { 159; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) 160; FNATTRS-LABEL: define {{[^@]+}}@test7_1 161; FNATTRS-SAME: (ptr inalloca(i32) captures(none) [[A:%.*]]) #[[ATTR5:[0-9]+]] { 162; FNATTRS-NEXT: ret void 163; 164; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 165; ATTRIBUTOR-LABEL: define {{[^@]+}}@test7_1 166; ATTRIBUTOR-SAME: (ptr nofree nonnull writeonly inalloca(i32) captures(none) [[A:%.*]]) #[[ATTR1]] { 167; ATTRIBUTOR-NEXT: ret void 168; 169; ATTRIBUTOR-CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 170; ATTRIBUTOR-CGSCC-LABEL: define {{[^@]+}}@test7_1 171; ATTRIBUTOR-CGSCC-SAME: (ptr nofree nonnull writeonly inalloca(i32) captures(none) [[A:%.*]]) #[[ATTR1]] { 172; ATTRIBUTOR-CGSCC-NEXT: ret void 173; 174 ret void 175} 176 177; preallocated parameters are always considered written 178define void @test7_2(ptr preallocated(i32) %a) { 179; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) 180; FNATTRS-LABEL: define {{[^@]+}}@test7_2 181; FNATTRS-SAME: (ptr preallocated(i32) captures(none) [[A:%.*]]) #[[ATTR5]] { 182; FNATTRS-NEXT: ret void 183; 184; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 185; ATTRIBUTOR-LABEL: define {{[^@]+}}@test7_2 186; ATTRIBUTOR-SAME: (ptr nofree nonnull writeonly preallocated(i32) captures(none) [[A:%.*]]) #[[ATTR1]] { 187; ATTRIBUTOR-NEXT: ret void 188; 189; ATTRIBUTOR-CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 190; ATTRIBUTOR-CGSCC-LABEL: define {{[^@]+}}@test7_2 191; ATTRIBUTOR-CGSCC-SAME: (ptr nofree nonnull writeonly preallocated(i32) captures(none) [[A:%.*]]) #[[ATTR1]] { 192; ATTRIBUTOR-CGSCC-NEXT: ret void 193; 194 ret void 195} 196 197define ptr @test8_1(ptr %p) { 198; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 199; FNATTRS-LABEL: define {{[^@]+}}@test8_1 200; FNATTRS-SAME: (ptr readnone returned [[P:%.*]]) #[[ATTR1]] { 201; FNATTRS-NEXT: entry: 202; FNATTRS-NEXT: ret ptr [[P]] 203; 204; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 205; ATTRIBUTOR-LABEL: define {{[^@]+}}@test8_1 206; ATTRIBUTOR-SAME: (ptr nofree readnone [[P:%.*]]) #[[ATTR1]] { 207; ATTRIBUTOR-NEXT: entry: 208; ATTRIBUTOR-NEXT: ret ptr [[P]] 209; 210; ATTRIBUTOR-CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 211; ATTRIBUTOR-CGSCC-LABEL: define {{[^@]+}}@test8_1 212; ATTRIBUTOR-CGSCC-SAME: (ptr nofree readnone [[P:%.*]]) #[[ATTR1]] { 213; ATTRIBUTOR-CGSCC-NEXT: entry: 214; ATTRIBUTOR-CGSCC-NEXT: ret ptr [[P]] 215; 216entry: 217 ret ptr %p 218} 219 220define void @test8_2(ptr %p) { 221; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) 222; FNATTRS-LABEL: define {{[^@]+}}@test8_2 223; FNATTRS-SAME: (ptr writeonly [[P:%.*]]) #[[ATTR4]] { 224; FNATTRS-NEXT: entry: 225; FNATTRS-NEXT: [[CALL:%.*]] = call ptr @test8_1(ptr [[P]]) 226; FNATTRS-NEXT: store i32 10, ptr [[CALL]], align 4 227; FNATTRS-NEXT: ret void 228; 229; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write) 230; ATTRIBUTOR-LABEL: define {{[^@]+}}@test8_2 231; ATTRIBUTOR-SAME: (ptr nofree writeonly captures(none) [[P:%.*]]) #[[ATTR0]] { 232; ATTRIBUTOR-NEXT: entry: 233; ATTRIBUTOR-NEXT: [[CALL:%.*]] = call ptr @test8_1(ptr nofree readnone [[P]]) #[[ATTR14:[0-9]+]] 234; ATTRIBUTOR-NEXT: store i32 10, ptr [[CALL]], align 4 235; ATTRIBUTOR-NEXT: ret void 236; 237; ATTRIBUTOR-CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(write) 238; ATTRIBUTOR-CGSCC-LABEL: define {{[^@]+}}@test8_2 239; ATTRIBUTOR-CGSCC-SAME: (ptr nofree writeonly [[P:%.*]]) #[[ATTR5:[0-9]+]] { 240; ATTRIBUTOR-CGSCC-NEXT: entry: 241; ATTRIBUTOR-CGSCC-NEXT: [[CALL:%.*]] = call ptr @test8_1(ptr nofree readnone [[P]]) #[[ATTR14:[0-9]+]] 242; ATTRIBUTOR-CGSCC-NEXT: store i32 10, ptr [[CALL]], align 4 243; ATTRIBUTOR-CGSCC-NEXT: ret void 244; 245entry: 246 %call = call ptr @test8_1(ptr %p) 247 store i32 10, ptr %call, align 4 248 ret void 249} 250 251declare void @llvm.masked.scatter.v4i32.v4p0(<4 x i32>%val, <4 x ptr>, i32, <4 x i1>) 252 253define void @test9(<4 x ptr> %ptrs, <4 x i32>%val) { 254; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write) 255; FNATTRS-LABEL: define {{[^@]+}}@test9 256; FNATTRS-SAME: (<4 x ptr> [[PTRS:%.*]], <4 x i32> [[VAL:%.*]]) #[[ATTR7:[0-9]+]] { 257; FNATTRS-NEXT: call void @llvm.masked.scatter.v4i32.v4p0(<4 x i32> [[VAL]], <4 x ptr> [[PTRS]], i32 4, <4 x i1> <i1 true, i1 false, i1 true, i1 false>) 258; FNATTRS-NEXT: ret void 259; 260; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write) 261; ATTRIBUTOR-LABEL: define {{[^@]+}}@test9 262; ATTRIBUTOR-SAME: (<4 x ptr> [[PTRS:%.*]], <4 x i32> [[VAL:%.*]]) #[[ATTR0]] { 263; ATTRIBUTOR-NEXT: call void @llvm.masked.scatter.v4i32.v4p0(<4 x i32> [[VAL]], <4 x ptr> [[PTRS]], i32 4, <4 x i1> <i1 true, i1 false, i1 true, i1 false>) #[[ATTR15:[0-9]+]] 264; ATTRIBUTOR-NEXT: ret void 265; 266; ATTRIBUTOR-CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write) 267; ATTRIBUTOR-CGSCC-LABEL: define {{[^@]+}}@test9 268; ATTRIBUTOR-CGSCC-SAME: (<4 x ptr> [[PTRS:%.*]], <4 x i32> [[VAL:%.*]]) #[[ATTR0]] { 269; ATTRIBUTOR-CGSCC-NEXT: call void @llvm.masked.scatter.v4i32.v4p0(<4 x i32> [[VAL]], <4 x ptr> [[PTRS]], i32 4, <4 x i1> <i1 true, i1 false, i1 true, i1 false>) #[[ATTR15:[0-9]+]] 270; ATTRIBUTOR-CGSCC-NEXT: ret void 271; 272 call void @llvm.masked.scatter.v4i32.v4p0(<4 x i32>%val, <4 x ptr> %ptrs, i32 4, <4 x i1><i1 true, i1 false, i1 true, i1 false>) 273 ret void 274} 275 276declare <4 x i32> @llvm.masked.gather.v4i32.v4p0(<4 x ptr>, i32, <4 x i1>, <4 x i32>) 277define <4 x i32> @test10(<4 x ptr> %ptrs) { 278; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(read) 279; FNATTRS-LABEL: define {{[^@]+}}@test10 280; FNATTRS-SAME: (<4 x ptr> [[PTRS:%.*]]) #[[ATTR9:[0-9]+]] { 281; FNATTRS-NEXT: [[RES:%.*]] = call <4 x i32> @llvm.masked.gather.v4i32.v4p0(<4 x ptr> [[PTRS]], i32 4, <4 x i1> <i1 true, i1 false, i1 true, i1 false>, <4 x i32> undef) 282; FNATTRS-NEXT: ret <4 x i32> [[RES]] 283; 284; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(read) 285; ATTRIBUTOR-LABEL: define {{[^@]+}}@test10 286; ATTRIBUTOR-SAME: (<4 x ptr> [[PTRS:%.*]]) #[[ATTR7:[0-9]+]] { 287; ATTRIBUTOR-NEXT: [[RES:%.*]] = call <4 x i32> @llvm.masked.gather.v4i32.v4p0(<4 x ptr> [[PTRS]], i32 4, <4 x i1> <i1 true, i1 false, i1 true, i1 false>, <4 x i32> undef) #[[ATTR16:[0-9]+]] 288; ATTRIBUTOR-NEXT: ret <4 x i32> [[RES]] 289; 290; ATTRIBUTOR-CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(read) 291; ATTRIBUTOR-CGSCC-LABEL: define {{[^@]+}}@test10 292; ATTRIBUTOR-CGSCC-SAME: (<4 x ptr> [[PTRS:%.*]]) #[[ATTR8:[0-9]+]] { 293; ATTRIBUTOR-CGSCC-NEXT: [[RES:%.*]] = call <4 x i32> @llvm.masked.gather.v4i32.v4p0(<4 x ptr> [[PTRS]], i32 4, <4 x i1> <i1 true, i1 false, i1 true, i1 false>, <4 x i32> undef) #[[ATTR16:[0-9]+]] 294; ATTRIBUTOR-CGSCC-NEXT: ret <4 x i32> [[RES]] 295; 296 %res = call <4 x i32> @llvm.masked.gather.v4i32.v4p0(<4 x ptr> %ptrs, i32 4, <4 x i1><i1 true, i1 false, i1 true, i1 false>, <4 x i32>undef) 297 ret <4 x i32> %res 298} 299 300declare <4 x i32> @test11_1(<4 x ptr>) argmemonly nounwind readonly 301define <4 x i32> @test11_2(<4 x ptr> %ptrs) { 302; FNATTRS: Function Attrs: nofree nounwind memory(argmem: read) 303; FNATTRS-LABEL: define {{[^@]+}}@test11_2 304; FNATTRS-SAME: (<4 x ptr> [[PTRS:%.*]]) #[[ATTR11:[0-9]+]] { 305; FNATTRS-NEXT: [[RES:%.*]] = call <4 x i32> @test11_1(<4 x ptr> [[PTRS]]) 306; FNATTRS-NEXT: ret <4 x i32> [[RES]] 307; 308; ATTRIBUTOR: Function Attrs: nosync nounwind memory(argmem: read) 309; ATTRIBUTOR-LABEL: define {{[^@]+}}@test11_2 310; ATTRIBUTOR-SAME: (<4 x ptr> [[PTRS:%.*]]) #[[ATTR9:[0-9]+]] { 311; ATTRIBUTOR-NEXT: [[RES:%.*]] = call <4 x i32> @test11_1(<4 x ptr> [[PTRS]]) #[[ATTR3]] 312; ATTRIBUTOR-NEXT: ret <4 x i32> [[RES]] 313; 314; ATTRIBUTOR-CGSCC: Function Attrs: nosync nounwind memory(argmem: read) 315; ATTRIBUTOR-CGSCC-LABEL: define {{[^@]+}}@test11_2 316; ATTRIBUTOR-CGSCC-SAME: (<4 x ptr> [[PTRS:%.*]]) #[[ATTR10:[0-9]+]] { 317; ATTRIBUTOR-CGSCC-NEXT: [[RES:%.*]] = call <4 x i32> @test11_1(<4 x ptr> [[PTRS]]) #[[ATTR3]] 318; ATTRIBUTOR-CGSCC-NEXT: ret <4 x i32> [[RES]] 319; 320 %res = call <4 x i32> @test11_1(<4 x ptr> %ptrs) 321 ret <4 x i32> %res 322} 323 324declare <4 x i32> @test12_1(<4 x ptr>) argmemonly nounwind 325define <4 x i32> @test12_2(<4 x ptr> %ptrs) { 326; FNATTRS: Function Attrs: nounwind memory(argmem: readwrite) 327; FNATTRS-LABEL: define {{[^@]+}}@test12_2 328; FNATTRS-SAME: (<4 x ptr> [[PTRS:%.*]]) #[[ATTR12:[0-9]+]] { 329; FNATTRS-NEXT: [[RES:%.*]] = call <4 x i32> @test12_1(<4 x ptr> [[PTRS]]) 330; FNATTRS-NEXT: ret <4 x i32> [[RES]] 331; 332; ATTRIBUTOR: Function Attrs: nounwind memory(argmem: readwrite) 333; ATTRIBUTOR-LABEL: define {{[^@]+}}@test12_2 334; ATTRIBUTOR-SAME: (<4 x ptr> [[PTRS:%.*]]) #[[ATTR10:[0-9]+]] { 335; ATTRIBUTOR-NEXT: [[RES:%.*]] = call <4 x i32> @test12_1(<4 x ptr> [[PTRS]]) 336; ATTRIBUTOR-NEXT: ret <4 x i32> [[RES]] 337; 338; ATTRIBUTOR-CGSCC: Function Attrs: nounwind memory(argmem: readwrite) 339; ATTRIBUTOR-CGSCC-LABEL: define {{[^@]+}}@test12_2 340; ATTRIBUTOR-CGSCC-SAME: (<4 x ptr> [[PTRS:%.*]]) #[[ATTR11:[0-9]+]] { 341; ATTRIBUTOR-CGSCC-NEXT: [[RES:%.*]] = call <4 x i32> @test12_1(<4 x ptr> [[PTRS]]) 342; ATTRIBUTOR-CGSCC-NEXT: ret <4 x i32> [[RES]] 343; 344 %res = call <4 x i32> @test12_1(<4 x ptr> %ptrs) 345 ret <4 x i32> %res 346} 347 348define i32 @volatile_load(ptr %p) { 349; FNATTRS: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite, inaccessiblemem: readwrite) 350; FNATTRS-LABEL: define {{[^@]+}}@volatile_load 351; FNATTRS-SAME: (ptr [[P:%.*]]) #[[ATTR13:[0-9]+]] { 352; FNATTRS-NEXT: [[LOAD:%.*]] = load volatile i32, ptr [[P]], align 4 353; FNATTRS-NEXT: ret i32 [[LOAD]] 354; 355; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) 356; ATTRIBUTOR-LABEL: define {{[^@]+}}@volatile_load 357; ATTRIBUTOR-SAME: (ptr nofree [[P:%.*]]) #[[ATTR11:[0-9]+]] { 358; ATTRIBUTOR-NEXT: [[LOAD:%.*]] = load volatile i32, ptr [[P]], align 4 359; ATTRIBUTOR-NEXT: ret i32 [[LOAD]] 360; 361; ATTRIBUTOR-CGSCC: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) 362; ATTRIBUTOR-CGSCC-LABEL: define {{[^@]+}}@volatile_load 363; ATTRIBUTOR-CGSCC-SAME: (ptr nofree [[P:%.*]]) #[[ATTR12:[0-9]+]] { 364; ATTRIBUTOR-CGSCC-NEXT: [[LOAD:%.*]] = load volatile i32, ptr [[P]], align 4 365; ATTRIBUTOR-CGSCC-NEXT: ret i32 [[LOAD]] 366; 367 %load = load volatile i32, ptr %p 368 ret i32 %load 369} 370 371declare void @escape_readnone_ptr(ptr %addr, ptr readnone %ptr) 372declare void @escape_readonly_ptr(ptr %addr, ptr readonly %ptr) 373 374; The argument pointer %escaped_then_written cannot be marked readnone/only even 375; though the only direct use, in @escape_readnone_ptr/@escape_readonly_ptr, 376; is marked as readnone/only. However, the functions can write the pointer into 377; %addr, causing the store to write to %escaped_then_written. 378define void @unsound_readnone(ptr %ignored, ptr %escaped_then_written) { 379; FNATTRS-LABEL: define {{[^@]+}}@unsound_readnone 380; FNATTRS-SAME: (ptr readnone captures(none) [[IGNORED:%.*]], ptr [[ESCAPED_THEN_WRITTEN:%.*]]) { 381; FNATTRS-NEXT: [[ADDR:%.*]] = alloca ptr, align 8 382; FNATTRS-NEXT: call void @escape_readnone_ptr(ptr [[ADDR]], ptr [[ESCAPED_THEN_WRITTEN]]) 383; FNATTRS-NEXT: [[ADDR_LD:%.*]] = load ptr, ptr [[ADDR]], align 8 384; FNATTRS-NEXT: store i8 0, ptr [[ADDR_LD]], align 1 385; FNATTRS-NEXT: ret void 386; 387; ATTRIBUTOR-LABEL: define {{[^@]+}}@unsound_readnone 388; ATTRIBUTOR-SAME: (ptr nofree readnone captures(none) [[IGNORED:%.*]], ptr nofree [[ESCAPED_THEN_WRITTEN:%.*]]) { 389; ATTRIBUTOR-NEXT: [[ADDR:%.*]] = alloca ptr, align 8 390; ATTRIBUTOR-NEXT: call void @escape_readnone_ptr(ptr [[ADDR]], ptr nofree [[ESCAPED_THEN_WRITTEN]]) 391; ATTRIBUTOR-NEXT: [[ADDR_LD:%.*]] = load ptr, ptr [[ADDR]], align 8 392; ATTRIBUTOR-NEXT: store i8 0, ptr [[ADDR_LD]], align 1 393; ATTRIBUTOR-NEXT: ret void 394; 395; ATTRIBUTOR-CGSCC-LABEL: define {{[^@]+}}@unsound_readnone 396; ATTRIBUTOR-CGSCC-SAME: (ptr nofree readnone captures(none) [[IGNORED:%.*]], ptr nofree [[ESCAPED_THEN_WRITTEN:%.*]]) { 397; ATTRIBUTOR-CGSCC-NEXT: [[ADDR:%.*]] = alloca ptr, align 8 398; ATTRIBUTOR-CGSCC-NEXT: call void @escape_readnone_ptr(ptr [[ADDR]], ptr nofree [[ESCAPED_THEN_WRITTEN]]) 399; ATTRIBUTOR-CGSCC-NEXT: [[ADDR_LD:%.*]] = load ptr, ptr [[ADDR]], align 8 400; ATTRIBUTOR-CGSCC-NEXT: store i8 0, ptr [[ADDR_LD]], align 1 401; ATTRIBUTOR-CGSCC-NEXT: ret void 402; 403 %addr = alloca ptr 404 call void @escape_readnone_ptr(ptr %addr, ptr %escaped_then_written) 405 %addr.ld = load ptr, ptr %addr 406 store i8 0, ptr %addr.ld 407 ret void 408} 409 410define void @unsound_readonly(ptr %ignored, ptr %escaped_then_written) { 411; FNATTRS-LABEL: define {{[^@]+}}@unsound_readonly 412; FNATTRS-SAME: (ptr readnone captures(none) [[IGNORED:%.*]], ptr [[ESCAPED_THEN_WRITTEN:%.*]]) { 413; FNATTRS-NEXT: [[ADDR:%.*]] = alloca ptr, align 8 414; FNATTRS-NEXT: call void @escape_readonly_ptr(ptr [[ADDR]], ptr [[ESCAPED_THEN_WRITTEN]]) 415; FNATTRS-NEXT: [[ADDR_LD:%.*]] = load ptr, ptr [[ADDR]], align 8 416; FNATTRS-NEXT: store i8 0, ptr [[ADDR_LD]], align 1 417; FNATTRS-NEXT: ret void 418; 419; ATTRIBUTOR-LABEL: define {{[^@]+}}@unsound_readonly 420; ATTRIBUTOR-SAME: (ptr nofree readnone captures(none) [[IGNORED:%.*]], ptr nofree [[ESCAPED_THEN_WRITTEN:%.*]]) { 421; ATTRIBUTOR-NEXT: [[ADDR:%.*]] = alloca ptr, align 8 422; ATTRIBUTOR-NEXT: call void @escape_readonly_ptr(ptr [[ADDR]], ptr nofree [[ESCAPED_THEN_WRITTEN]]) 423; ATTRIBUTOR-NEXT: [[ADDR_LD:%.*]] = load ptr, ptr [[ADDR]], align 8 424; ATTRIBUTOR-NEXT: store i8 0, ptr [[ADDR_LD]], align 1 425; ATTRIBUTOR-NEXT: ret void 426; 427; ATTRIBUTOR-CGSCC-LABEL: define {{[^@]+}}@unsound_readonly 428; ATTRIBUTOR-CGSCC-SAME: (ptr nofree readnone captures(none) [[IGNORED:%.*]], ptr nofree [[ESCAPED_THEN_WRITTEN:%.*]]) { 429; ATTRIBUTOR-CGSCC-NEXT: [[ADDR:%.*]] = alloca ptr, align 8 430; ATTRIBUTOR-CGSCC-NEXT: call void @escape_readonly_ptr(ptr [[ADDR]], ptr nofree [[ESCAPED_THEN_WRITTEN]]) 431; ATTRIBUTOR-CGSCC-NEXT: [[ADDR_LD:%.*]] = load ptr, ptr [[ADDR]], align 8 432; ATTRIBUTOR-CGSCC-NEXT: store i8 0, ptr [[ADDR_LD]], align 1 433; ATTRIBUTOR-CGSCC-NEXT: ret void 434; 435 %addr = alloca ptr 436 call void @escape_readonly_ptr(ptr %addr, ptr %escaped_then_written) 437 %addr.ld = load ptr, ptr %addr 438 store i8 0, ptr %addr.ld 439 ret void 440} 441 442define void @fptr_test1a(ptr %p, ptr %f) { 443; FNATTRS-LABEL: define {{[^@]+}}@fptr_test1a 444; FNATTRS-SAME: (ptr readnone captures(none) [[P:%.*]], ptr readonly captures(none) [[F:%.*]]) { 445; FNATTRS-NEXT: call void [[F]](ptr readnone captures(none) [[P]]) 446; FNATTRS-NEXT: ret void 447; 448; ATTRIBUTOR-LABEL: define {{[^@]+}}@fptr_test1a 449; ATTRIBUTOR-SAME: (ptr nofree captures(none) [[P:%.*]], ptr nofree nonnull captures(none) [[F:%.*]]) { 450; ATTRIBUTOR-NEXT: call void [[F]](ptr nofree readnone captures(none) [[P]]) 451; ATTRIBUTOR-NEXT: ret void 452; 453; ATTRIBUTOR-CGSCC-LABEL: define {{[^@]+}}@fptr_test1a 454; ATTRIBUTOR-CGSCC-SAME: (ptr nofree captures(none) [[P:%.*]], ptr nofree nonnull captures(none) [[F:%.*]]) { 455; ATTRIBUTOR-CGSCC-NEXT: call void [[F]](ptr nofree readnone captures(none) [[P]]) 456; ATTRIBUTOR-CGSCC-NEXT: ret void 457; 458 call void %f(ptr nocapture readnone %p) 459 ret void 460} 461 462; Can't infer readnone here because call might capture %p 463define void @fptr_test1b(ptr %p, ptr %f) { 464; FNATTRS-LABEL: define {{[^@]+}}@fptr_test1b 465; FNATTRS-SAME: (ptr [[P:%.*]], ptr readonly captures(none) [[F:%.*]]) { 466; FNATTRS-NEXT: call void [[F]](ptr readnone [[P]]) 467; FNATTRS-NEXT: ret void 468; 469; ATTRIBUTOR-LABEL: define {{[^@]+}}@fptr_test1b 470; ATTRIBUTOR-SAME: (ptr nofree [[P:%.*]], ptr nofree nonnull captures(none) [[F:%.*]]) { 471; ATTRIBUTOR-NEXT: call void [[F]](ptr nofree readnone [[P]]) 472; ATTRIBUTOR-NEXT: ret void 473; 474; ATTRIBUTOR-CGSCC-LABEL: define {{[^@]+}}@fptr_test1b 475; ATTRIBUTOR-CGSCC-SAME: (ptr nofree [[P:%.*]], ptr nofree nonnull captures(none) [[F:%.*]]) { 476; ATTRIBUTOR-CGSCC-NEXT: call void [[F]](ptr nofree readnone [[P]]) 477; ATTRIBUTOR-CGSCC-NEXT: ret void 478; 479 call void %f(ptr readnone %p) 480 ret void 481} 482 483define void @fptr_test1c(ptr %p, ptr %f) { 484; FNATTRS: Function Attrs: nofree memory(read) 485; FNATTRS-LABEL: define {{[^@]+}}@fptr_test1c 486; FNATTRS-SAME: (ptr readnone [[P:%.*]], ptr readonly captures(none) [[F:%.*]]) #[[ATTR3]] { 487; FNATTRS-NEXT: call void [[F]](ptr readnone [[P]]) #[[ATTR2:[0-9]+]] 488; FNATTRS-NEXT: ret void 489; 490; ATTRIBUTOR: Function Attrs: memory(read) 491; ATTRIBUTOR-LABEL: define {{[^@]+}}@fptr_test1c 492; ATTRIBUTOR-SAME: (ptr nofree readonly [[P:%.*]], ptr nofree nonnull readonly captures(none) [[F:%.*]]) #[[ATTR2:[0-9]+]] { 493; ATTRIBUTOR-NEXT: call void [[F]](ptr nofree readnone [[P]]) #[[ATTR2]] 494; ATTRIBUTOR-NEXT: ret void 495; 496; ATTRIBUTOR-CGSCC: Function Attrs: memory(read) 497; ATTRIBUTOR-CGSCC-LABEL: define {{[^@]+}}@fptr_test1c 498; ATTRIBUTOR-CGSCC-SAME: (ptr nofree readonly [[P:%.*]], ptr nofree nonnull readonly captures(none) [[F:%.*]]) #[[ATTR2:[0-9]+]] { 499; ATTRIBUTOR-CGSCC-NEXT: call void [[F]](ptr nofree readnone [[P]]) #[[ATTR2]] 500; ATTRIBUTOR-CGSCC-NEXT: ret void 501; 502 call void %f(ptr readnone %p) readonly 503 ret void 504} 505 506define void @fptr_test2a(ptr %p, ptr %f) { 507; FNATTRS-LABEL: define {{[^@]+}}@fptr_test2a 508; FNATTRS-SAME: (ptr readonly captures(none) [[P:%.*]], ptr readonly captures(none) [[F:%.*]]) { 509; FNATTRS-NEXT: call void [[F]](ptr readonly captures(none) [[P]]) 510; FNATTRS-NEXT: ret void 511; 512; ATTRIBUTOR-LABEL: define {{[^@]+}}@fptr_test2a 513; ATTRIBUTOR-SAME: (ptr nofree captures(none) [[P:%.*]], ptr nofree nonnull captures(none) [[F:%.*]]) { 514; ATTRIBUTOR-NEXT: call void [[F]](ptr nofree readonly captures(none) [[P]]) 515; ATTRIBUTOR-NEXT: ret void 516; 517; ATTRIBUTOR-CGSCC-LABEL: define {{[^@]+}}@fptr_test2a 518; ATTRIBUTOR-CGSCC-SAME: (ptr nofree captures(none) [[P:%.*]], ptr nofree nonnull captures(none) [[F:%.*]]) { 519; ATTRIBUTOR-CGSCC-NEXT: call void [[F]](ptr nofree readonly captures(none) [[P]]) 520; ATTRIBUTOR-CGSCC-NEXT: ret void 521; 522 call void %f(ptr nocapture readonly %p) 523 ret void 524} 525 526define void @fptr_test2b(ptr %p, ptr %f) { 527 ; Can't infer readonly here because call might capture %p 528; FNATTRS-LABEL: define {{[^@]+}}@fptr_test2b 529; FNATTRS-SAME: (ptr [[P:%.*]], ptr readonly captures(none) [[F:%.*]]) { 530; FNATTRS-NEXT: call void [[F]](ptr readonly [[P]]) 531; FNATTRS-NEXT: ret void 532; 533; ATTRIBUTOR-LABEL: define {{[^@]+}}@fptr_test2b 534; ATTRIBUTOR-SAME: (ptr nofree [[P:%.*]], ptr nofree nonnull captures(none) [[F:%.*]]) { 535; ATTRIBUTOR-NEXT: call void [[F]](ptr nofree readonly [[P]]) 536; ATTRIBUTOR-NEXT: ret void 537; 538; ATTRIBUTOR-CGSCC-LABEL: define {{[^@]+}}@fptr_test2b 539; ATTRIBUTOR-CGSCC-SAME: (ptr nofree [[P:%.*]], ptr nofree nonnull captures(none) [[F:%.*]]) { 540; ATTRIBUTOR-CGSCC-NEXT: call void [[F]](ptr nofree readonly [[P]]) 541; ATTRIBUTOR-CGSCC-NEXT: ret void 542; 543 call void %f(ptr readonly %p) 544 ret void 545} 546 547define void @fptr_test2c(ptr %p, ptr %f) { 548; FNATTRS: Function Attrs: nofree memory(read) 549; FNATTRS-LABEL: define {{[^@]+}}@fptr_test2c 550; FNATTRS-SAME: (ptr readonly [[P:%.*]], ptr readonly captures(none) [[F:%.*]]) #[[ATTR3]] { 551; FNATTRS-NEXT: call void [[F]](ptr readonly [[P]]) #[[ATTR2]] 552; FNATTRS-NEXT: ret void 553; 554; ATTRIBUTOR: Function Attrs: memory(read) 555; ATTRIBUTOR-LABEL: define {{[^@]+}}@fptr_test2c 556; ATTRIBUTOR-SAME: (ptr nofree readonly [[P:%.*]], ptr nofree nonnull readonly captures(none) [[F:%.*]]) #[[ATTR2]] { 557; ATTRIBUTOR-NEXT: call void [[F]](ptr nofree readonly [[P]]) #[[ATTR2]] 558; ATTRIBUTOR-NEXT: ret void 559; 560; ATTRIBUTOR-CGSCC: Function Attrs: memory(read) 561; ATTRIBUTOR-CGSCC-LABEL: define {{[^@]+}}@fptr_test2c 562; ATTRIBUTOR-CGSCC-SAME: (ptr nofree readonly [[P:%.*]], ptr nofree nonnull readonly captures(none) [[F:%.*]]) #[[ATTR2]] { 563; ATTRIBUTOR-CGSCC-NEXT: call void [[F]](ptr nofree readonly [[P]]) #[[ATTR2]] 564; ATTRIBUTOR-CGSCC-NEXT: ret void 565; 566 call void %f(ptr readonly %p) readonly 567 ret void 568} 569 570define void @alloca_recphi() { 571; FNATTRS: Function Attrs: nofree norecurse nosync nounwind memory(none) 572; FNATTRS-LABEL: define {{[^@]+}}@alloca_recphi 573; FNATTRS-SAME: () #[[ATTR14:[0-9]+]] { 574; FNATTRS-NEXT: entry: 575; FNATTRS-NEXT: [[A:%.*]] = alloca [8 x i32], align 4 576; FNATTRS-NEXT: [[A_END:%.*]] = getelementptr i32, ptr [[A]], i64 8 577; FNATTRS-NEXT: br label [[LOOP:%.*]] 578; FNATTRS: loop: 579; FNATTRS-NEXT: [[P:%.*]] = phi ptr [ [[A]], [[ENTRY:%.*]] ], [ [[P_NEXT:%.*]], [[LOOP]] ] 580; FNATTRS-NEXT: store i32 0, ptr [[P]], align 4 581; FNATTRS-NEXT: [[TMP0:%.*]] = load i32, ptr [[P]], align 4 582; FNATTRS-NEXT: [[P_NEXT]] = getelementptr i32, ptr [[P]], i64 1 583; FNATTRS-NEXT: [[C:%.*]] = icmp ne ptr [[P_NEXT]], [[A_END]] 584; FNATTRS-NEXT: br i1 [[C]], label [[LOOP]], label [[EXIT:%.*]] 585; FNATTRS: exit: 586; FNATTRS-NEXT: ret void 587; 588; ATTRIBUTOR: Function Attrs: nofree norecurse nosync nounwind memory(none) 589; ATTRIBUTOR-LABEL: define {{[^@]+}}@alloca_recphi 590; ATTRIBUTOR-SAME: () #[[ATTR12:[0-9]+]] { 591; ATTRIBUTOR-NEXT: entry: 592; ATTRIBUTOR-NEXT: [[A:%.*]] = alloca [8 x i32], align 4 593; ATTRIBUTOR-NEXT: [[A_END:%.*]] = getelementptr i32, ptr [[A]], i64 8 594; ATTRIBUTOR-NEXT: br label [[LOOP:%.*]] 595; ATTRIBUTOR: loop: 596; ATTRIBUTOR-NEXT: [[P:%.*]] = phi ptr [ [[A]], [[ENTRY:%.*]] ], [ [[P_NEXT:%.*]], [[LOOP]] ] 597; ATTRIBUTOR-NEXT: store i32 0, ptr [[P]], align 4 598; ATTRIBUTOR-NEXT: [[TMP0:%.*]] = load i32, ptr [[P]], align 4 599; ATTRIBUTOR-NEXT: [[P_NEXT]] = getelementptr i32, ptr [[P]], i64 1 600; ATTRIBUTOR-NEXT: [[C:%.*]] = icmp ne ptr [[P_NEXT]], [[A_END]] 601; ATTRIBUTOR-NEXT: br i1 [[C]], label [[LOOP]], label [[EXIT:%.*]] 602; ATTRIBUTOR: exit: 603; ATTRIBUTOR-NEXT: ret void 604; 605; ATTRIBUTOR-CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 606; ATTRIBUTOR-CGSCC-LABEL: define {{[^@]+}}@alloca_recphi 607; ATTRIBUTOR-CGSCC-SAME: () #[[ATTR1]] { 608; ATTRIBUTOR-CGSCC-NEXT: entry: 609; ATTRIBUTOR-CGSCC-NEXT: [[A:%.*]] = alloca [8 x i32], align 4 610; ATTRIBUTOR-CGSCC-NEXT: [[A_END:%.*]] = getelementptr i32, ptr [[A]], i64 8 611; ATTRIBUTOR-CGSCC-NEXT: br label [[LOOP:%.*]] 612; ATTRIBUTOR-CGSCC: loop: 613; ATTRIBUTOR-CGSCC-NEXT: [[P:%.*]] = phi ptr [ [[A]], [[ENTRY:%.*]] ], [ [[P_NEXT:%.*]], [[LOOP]] ] 614; ATTRIBUTOR-CGSCC-NEXT: store i32 0, ptr [[P]], align 4 615; ATTRIBUTOR-CGSCC-NEXT: [[TMP0:%.*]] = load i32, ptr [[P]], align 4 616; ATTRIBUTOR-CGSCC-NEXT: [[P_NEXT]] = getelementptr i32, ptr [[P]], i64 1 617; ATTRIBUTOR-CGSCC-NEXT: [[C:%.*]] = icmp ne ptr [[P_NEXT]], [[A_END]] 618; ATTRIBUTOR-CGSCC-NEXT: br i1 [[C]], label [[LOOP]], label [[EXIT:%.*]] 619; ATTRIBUTOR-CGSCC: exit: 620; ATTRIBUTOR-CGSCC-NEXT: ret void 621; 622entry: 623 %a = alloca [8 x i32] 624 %a.end = getelementptr i32, ptr %a, i64 8 625 br label %loop 626 627loop: 628 %p = phi ptr [ %a, %entry ], [ %p.next, %loop ] 629 store i32 0, ptr %p 630 load i32, ptr %p 631 %p.next = getelementptr i32, ptr %p, i64 1 632 %c = icmp ne ptr %p.next, %a.end 633 br i1 %c, label %loop, label %exit 634 635exit: 636 ret void 637} 638 639declare void @readnone_param(ptr nocapture readnone %p) 640declare void @readonly_param(ptr nocapture readonly %p) 641 642; FIXME: While this can't be readnone, this could be readonly. 643define void @op_bundle_readnone_deopt(ptr %p) { 644; FNATTRS-LABEL: define {{[^@]+}}@op_bundle_readnone_deopt 645; FNATTRS-SAME: (ptr captures(none) [[P:%.*]]) { 646; FNATTRS-NEXT: call void @readnone_param(ptr [[P]]) [ "deopt"() ] 647; FNATTRS-NEXT: ret void 648; 649; ATTRIBUTOR-LABEL: define {{[^@]+}}@op_bundle_readnone_deopt 650; ATTRIBUTOR-SAME: (ptr nofree captures(none) [[P:%.*]]) { 651; ATTRIBUTOR-NEXT: call void @readnone_param(ptr nofree captures(none) [[P]]) [ "deopt"() ] 652; ATTRIBUTOR-NEXT: ret void 653; 654; ATTRIBUTOR-CGSCC-LABEL: define {{[^@]+}}@op_bundle_readnone_deopt 655; ATTRIBUTOR-CGSCC-SAME: (ptr nofree captures(none) [[P:%.*]]) { 656; ATTRIBUTOR-CGSCC-NEXT: call void @readnone_param(ptr nofree captures(none) [[P]]) [ "deopt"() ] 657; ATTRIBUTOR-CGSCC-NEXT: ret void 658; 659 call void @readnone_param(ptr %p) ["deopt"()] 660 ret void 661} 662 663define void @op_bundle_readnone_unknown(ptr %p) { 664; FNATTRS-LABEL: define {{[^@]+}}@op_bundle_readnone_unknown 665; FNATTRS-SAME: (ptr captures(none) [[P:%.*]]) { 666; FNATTRS-NEXT: call void @readnone_param(ptr [[P]]) [ "unknown"() ] 667; FNATTRS-NEXT: ret void 668; 669; ATTRIBUTOR-LABEL: define {{[^@]+}}@op_bundle_readnone_unknown 670; ATTRIBUTOR-SAME: (ptr nofree captures(none) [[P:%.*]]) { 671; ATTRIBUTOR-NEXT: call void @readnone_param(ptr nofree captures(none) [[P]]) [ "unknown"() ] 672; ATTRIBUTOR-NEXT: ret void 673; 674; ATTRIBUTOR-CGSCC-LABEL: define {{[^@]+}}@op_bundle_readnone_unknown 675; ATTRIBUTOR-CGSCC-SAME: (ptr nofree captures(none) [[P:%.*]]) { 676; ATTRIBUTOR-CGSCC-NEXT: call void @readnone_param(ptr nofree captures(none) [[P]]) [ "unknown"() ] 677; ATTRIBUTOR-CGSCC-NEXT: ret void 678; 679 call void @readnone_param(ptr %p) ["unknown"()] 680 ret void 681} 682 683define void @op_bundle_readonly_deopt(ptr %p) { 684; FNATTRS-LABEL: define {{[^@]+}}@op_bundle_readonly_deopt 685; FNATTRS-SAME: (ptr readonly captures(none) [[P:%.*]]) { 686; FNATTRS-NEXT: call void @readonly_param(ptr [[P]]) [ "deopt"() ] 687; FNATTRS-NEXT: ret void 688; 689; ATTRIBUTOR-LABEL: define {{[^@]+}}@op_bundle_readonly_deopt 690; ATTRIBUTOR-SAME: (ptr nofree captures(none) [[P:%.*]]) { 691; ATTRIBUTOR-NEXT: call void @readonly_param(ptr nofree captures(none) [[P]]) [ "deopt"() ] 692; ATTRIBUTOR-NEXT: ret void 693; 694; ATTRIBUTOR-CGSCC-LABEL: define {{[^@]+}}@op_bundle_readonly_deopt 695; ATTRIBUTOR-CGSCC-SAME: (ptr nofree captures(none) [[P:%.*]]) { 696; ATTRIBUTOR-CGSCC-NEXT: call void @readonly_param(ptr nofree captures(none) [[P]]) [ "deopt"() ] 697; ATTRIBUTOR-CGSCC-NEXT: ret void 698; 699 call void @readonly_param(ptr %p) ["deopt"()] 700 ret void 701} 702 703define void @op_bundle_readonly_unknown(ptr %p) { 704; FNATTRS-LABEL: define {{[^@]+}}@op_bundle_readonly_unknown 705; FNATTRS-SAME: (ptr captures(none) [[P:%.*]]) { 706; FNATTRS-NEXT: call void @readonly_param(ptr [[P]]) [ "unknown"() ] 707; FNATTRS-NEXT: ret void 708; 709; ATTRIBUTOR-LABEL: define {{[^@]+}}@op_bundle_readonly_unknown 710; ATTRIBUTOR-SAME: (ptr nofree captures(none) [[P:%.*]]) { 711; ATTRIBUTOR-NEXT: call void @readonly_param(ptr nofree captures(none) [[P]]) [ "unknown"() ] 712; ATTRIBUTOR-NEXT: ret void 713; 714; ATTRIBUTOR-CGSCC-LABEL: define {{[^@]+}}@op_bundle_readonly_unknown 715; ATTRIBUTOR-CGSCC-SAME: (ptr nofree captures(none) [[P:%.*]]) { 716; ATTRIBUTOR-CGSCC-NEXT: call void @readonly_param(ptr nofree captures(none) [[P]]) [ "unknown"() ] 717; ATTRIBUTOR-CGSCC-NEXT: ret void 718; 719 call void @readonly_param(ptr %p) ["unknown"()] 720 ret void 721} 722 723define i32 @writable_readonly(ptr writable dereferenceable(4) %p) { 724; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) 725; FNATTRS-LABEL: define {{[^@]+}}@writable_readonly 726; FNATTRS-SAME: (ptr readonly captures(none) dereferenceable(4) [[P:%.*]]) #[[ATTR15:[0-9]+]] { 727; FNATTRS-NEXT: [[V:%.*]] = load i32, ptr [[P]], align 4 728; FNATTRS-NEXT: ret i32 [[V]] 729; 730; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) 731; ATTRIBUTOR-LABEL: define {{[^@]+}}@writable_readonly 732; ATTRIBUTOR-SAME: (ptr nofree nonnull readonly captures(none) dereferenceable(4) [[P:%.*]]) #[[ATTR13:[0-9]+]] { 733; ATTRIBUTOR-NEXT: [[V:%.*]] = load i32, ptr [[P]], align 4 734; ATTRIBUTOR-NEXT: ret i32 [[V]] 735; 736; ATTRIBUTOR-CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) 737; ATTRIBUTOR-CGSCC-LABEL: define {{[^@]+}}@writable_readonly 738; ATTRIBUTOR-CGSCC-SAME: (ptr nofree nonnull readonly captures(none) dereferenceable(4) [[P:%.*]]) #[[ATTR13:[0-9]+]] { 739; ATTRIBUTOR-CGSCC-NEXT: [[V:%.*]] = load i32, ptr [[P]], align 4 740; ATTRIBUTOR-CGSCC-NEXT: ret i32 [[V]] 741; 742 %v = load i32, ptr %p 743 ret i32 %v 744} 745 746define void @writable_readnone(ptr writable dereferenceable(4) %p) { 747; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 748; FNATTRS-LABEL: define {{[^@]+}}@writable_readnone 749; FNATTRS-SAME: (ptr readnone captures(none) dereferenceable(4) [[P:%.*]]) #[[ATTR1]] { 750; FNATTRS-NEXT: ret void 751; 752; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 753; ATTRIBUTOR-LABEL: define {{[^@]+}}@writable_readnone 754; ATTRIBUTOR-SAME: (ptr nofree nonnull readnone captures(none) dereferenceable(4) [[P:%.*]]) #[[ATTR1]] { 755; ATTRIBUTOR-NEXT: ret void 756; 757; ATTRIBUTOR-CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 758; ATTRIBUTOR-CGSCC-LABEL: define {{[^@]+}}@writable_readnone 759; ATTRIBUTOR-CGSCC-SAME: (ptr nofree nonnull readnone captures(none) dereferenceable(4) [[P:%.*]]) #[[ATTR1]] { 760; ATTRIBUTOR-CGSCC-NEXT: ret void 761; 762 ret void 763} 764 765declare void @byval_param(ptr byval(i32) %p) 766 767define void @call_byval_param(ptr %p) { 768; FNATTRS-LABEL: define {{[^@]+}}@call_byval_param 769; FNATTRS-SAME: (ptr readonly captures(none) [[P:%.*]]) { 770; FNATTRS-NEXT: call void @byval_param(ptr byval(i32) [[P]]) 771; FNATTRS-NEXT: ret void 772; 773; ATTRIBUTOR-LABEL: define {{[^@]+}}@call_byval_param 774; ATTRIBUTOR-SAME: (ptr readonly captures(none) [[P:%.*]]) { 775; ATTRIBUTOR-NEXT: call void @byval_param(ptr readonly byval(i32) captures(none) [[P]]) 776; ATTRIBUTOR-NEXT: ret void 777; 778; ATTRIBUTOR-CGSCC-LABEL: define {{[^@]+}}@call_byval_param 779; ATTRIBUTOR-CGSCC-SAME: (ptr readonly captures(none) [[P:%.*]]) { 780; ATTRIBUTOR-CGSCC-NEXT: call void @byval_param(ptr readonly byval(i32) captures(none) [[P]]) 781; ATTRIBUTOR-CGSCC-NEXT: ret void 782; 783 call void @byval_param(ptr byval(i32) %p) 784 ret void 785} 786 787;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: 788; COMMON: {{.*}} 789