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=11 -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=11 -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 6target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" 7 8@G = external dso_local global i32, align 4 9 10; CHECK: Function Attrs: inaccessiblememonly 11declare noalias i8* @malloc(i64) inaccessiblememonly 12 13define dso_local i8* @internal_only(i32 %arg) { 14; CHECK: Function Attrs: inaccessiblememonly 15; CHECK-LABEL: define {{[^@]+}}@internal_only 16; CHECK-SAME: (i32 [[ARG:%.*]]) [[ATTR0:#.*]] { 17; CHECK-NEXT: entry: 18; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[ARG]] to i64 19; CHECK-NEXT: [[CALL:%.*]] = call noalias i8* @malloc(i64 [[CONV]]) 20; CHECK-NEXT: ret i8* [[CALL]] 21; 22entry: 23 %conv = sext i32 %arg to i64 24 %call = call i8* @malloc(i64 %conv) 25 ret i8* %call 26} 27 28define dso_local i8* @internal_only_rec(i32 %arg) { 29; CHECK: Function Attrs: inaccessiblememonly 30; CHECK-LABEL: define {{[^@]+}}@internal_only_rec 31; CHECK-SAME: (i32 [[ARG:%.*]]) [[ATTR0]] { 32; CHECK-NEXT: entry: 33; CHECK-NEXT: [[REM:%.*]] = srem i32 [[ARG]], 2 34; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[REM]], 1 35; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 36; CHECK: if.then: 37; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[ARG]], 2 38; CHECK-NEXT: [[CALL:%.*]] = call noalias i8* @internal_only_rec(i32 [[DIV]]) 39; CHECK-NEXT: br label [[RETURN:%.*]] 40; CHECK: if.end: 41; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[ARG]] to i64 42; CHECK-NEXT: [[CALL1:%.*]] = call noalias i8* @malloc(i64 [[CONV]]) 43; CHECK-NEXT: br label [[RETURN]] 44; CHECK: return: 45; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i8* [ [[CALL]], [[IF_THEN]] ], [ [[CALL1]], [[IF_END]] ] 46; CHECK-NEXT: ret i8* [[RETVAL_0]] 47; 48entry: 49 %rem = srem i32 %arg, 2 50 %cmp = icmp eq i32 %rem, 1 51 br i1 %cmp, label %if.then, label %if.end 52 53if.then: ; preds = %entry 54 %div = sdiv i32 %arg, 2 55 %call = call i8* @internal_only_rec(i32 %div) 56 br label %return 57 58if.end: ; preds = %entry 59 %conv = sext i32 %arg to i64 60 %call1 = call i8* @malloc(i64 %conv) 61 br label %return 62 63return: ; preds = %if.end, %if.then 64 %retval.0 = phi i8* [ %call, %if.then ], [ %call1, %if.end ] 65 ret i8* %retval.0 66} 67 68define dso_local i8* @internal_only_rec_static_helper(i32 %arg) { 69; CHECK: Function Attrs: inaccessiblememonly 70; CHECK-LABEL: define {{[^@]+}}@internal_only_rec_static_helper 71; CHECK-SAME: (i32 [[ARG:%.*]]) [[ATTR0]] { 72; CHECK-NEXT: entry: 73; CHECK-NEXT: [[CALL:%.*]] = call noalias i8* @internal_only_rec_static(i32 [[ARG]]) 74; CHECK-NEXT: ret i8* [[CALL]] 75; 76entry: 77 %call = call i8* @internal_only_rec_static(i32 %arg) 78 ret i8* %call 79} 80 81define internal i8* @internal_only_rec_static(i32 %arg) { 82; CHECK: Function Attrs: inaccessiblememonly 83; CHECK-LABEL: define {{[^@]+}}@internal_only_rec_static 84; CHECK-SAME: (i32 [[ARG:%.*]]) [[ATTR0]] { 85; CHECK-NEXT: entry: 86; CHECK-NEXT: [[REM:%.*]] = srem i32 [[ARG]], 2 87; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[REM]], 1 88; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 89; CHECK: if.then: 90; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[ARG]], 2 91; CHECK-NEXT: [[CALL:%.*]] = call noalias i8* @internal_only_rec(i32 [[DIV]]) 92; CHECK-NEXT: br label [[RETURN:%.*]] 93; CHECK: if.end: 94; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[ARG]] to i64 95; CHECK-NEXT: [[CALL1:%.*]] = call noalias i8* @malloc(i64 [[CONV]]) 96; CHECK-NEXT: br label [[RETURN]] 97; CHECK: return: 98; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i8* [ [[CALL]], [[IF_THEN]] ], [ [[CALL1]], [[IF_END]] ] 99; CHECK-NEXT: ret i8* [[RETVAL_0]] 100; 101entry: 102 %rem = srem i32 %arg, 2 103 %cmp = icmp eq i32 %rem, 1 104 br i1 %cmp, label %if.then, label %if.end 105 106if.then: ; preds = %entry 107 %div = sdiv i32 %arg, 2 108 %call = call i8* @internal_only_rec(i32 %div) 109 br label %return 110 111if.end: ; preds = %entry 112 %conv = sext i32 %arg to i64 113 %call1 = call i8* @malloc(i64 %conv) 114 br label %return 115 116return: ; preds = %if.end, %if.then 117 %retval.0 = phi i8* [ %call, %if.then ], [ %call1, %if.end ] 118 ret i8* %retval.0 119} 120 121define dso_local i8* @internal_only_rec_static_helper_malloc_noescape(i32 %arg) { 122; FIXME: This is actually inaccessiblememonly because the malloced memory does not escape 123; CHECK-LABEL: define {{[^@]+}}@internal_only_rec_static_helper_malloc_noescape 124; CHECK-SAME: (i32 [[ARG:%.*]]) { 125; CHECK-NEXT: entry: 126; CHECK-NEXT: [[CALL:%.*]] = call noalias i8* @internal_only_rec_static_malloc_noescape(i32 [[ARG]]) 127; CHECK-NEXT: ret i8* [[CALL]] 128; 129entry: 130 %call = call i8* @internal_only_rec_static_malloc_noescape(i32 %arg) 131 ret i8* %call 132} 133 134define internal i8* @internal_only_rec_static_malloc_noescape(i32 %arg) { 135; FIXME: This is actually inaccessiblememonly because the malloced memory does not escape 136; CHECK-LABEL: define {{[^@]+}}@internal_only_rec_static_malloc_noescape 137; CHECK-SAME: (i32 [[ARG:%.*]]) { 138; CHECK-NEXT: entry: 139; CHECK-NEXT: [[REM:%.*]] = srem i32 [[ARG]], 2 140; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[REM]], 1 141; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 142; CHECK: if.then: 143; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[ARG]], 2 144; CHECK-NEXT: [[CALL:%.*]] = call noalias i8* @internal_only_rec(i32 [[DIV]]) 145; CHECK-NEXT: br label [[RETURN:%.*]] 146; CHECK: if.end: 147; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[ARG]] to i64 148; CHECK-NEXT: [[CALL1:%.*]] = call noalias i8* @malloc(i64 [[CONV]]) 149; CHECK-NEXT: store i8 0, i8* [[CALL1]], align 1 150; CHECK-NEXT: br label [[RETURN]] 151; CHECK: return: 152; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i8* [ [[CALL]], [[IF_THEN]] ], [ null, [[IF_END]] ] 153; CHECK-NEXT: ret i8* [[RETVAL_0]] 154; 155entry: 156 %rem = srem i32 %arg, 2 157 %cmp = icmp eq i32 %rem, 1 158 br i1 %cmp, label %if.then, label %if.end 159 160if.then: ; preds = %entry 161 %div = sdiv i32 %arg, 2 162 %call = call i8* @internal_only_rec(i32 %div) 163 br label %return 164 165if.end: ; preds = %entry 166 %conv = sext i32 %arg to i64 167 %call1 = call i8* @malloc(i64 %conv) 168 store i8 0, i8* %call1 169 br label %return 170 171return: ; preds = %if.end, %if.then 172 %retval.0 = phi i8* [ %call, %if.then ], [ null, %if.end ] 173 ret i8* %retval.0 174} 175 176define dso_local i8* @internal_argmem_only_read(i32* %arg) { 177; CHECK: Function Attrs: inaccessiblemem_or_argmemonly 178; CHECK-LABEL: define {{[^@]+}}@internal_argmem_only_read 179; CHECK-SAME: (i32* nocapture nonnull readonly align 4 dereferenceable(4) [[ARG:%.*]]) [[ATTR1:#.*]] { 180; CHECK-NEXT: entry: 181; CHECK-NEXT: [[TMP:%.*]] = load i32, i32* [[ARG]], align 4 182; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP]] to i64 183; CHECK-NEXT: [[CALL:%.*]] = call noalias i8* @malloc(i64 [[CONV]]) 184; CHECK-NEXT: ret i8* [[CALL]] 185; 186entry: 187 %tmp = load i32, i32* %arg, align 4 188 %conv = sext i32 %tmp to i64 189 %call = call i8* @malloc(i64 %conv) 190 ret i8* %call 191} 192 193define dso_local i8* @internal_argmem_only_write(i32* %arg) { 194; CHECK: Function Attrs: inaccessiblemem_or_argmemonly 195; CHECK-LABEL: define {{[^@]+}}@internal_argmem_only_write 196; CHECK-SAME: (i32* nocapture nonnull writeonly align 4 dereferenceable(4) [[ARG:%.*]]) [[ATTR1]] { 197; CHECK-NEXT: entry: 198; CHECK-NEXT: store i32 10, i32* [[ARG]], align 4 199; CHECK-NEXT: [[CALL:%.*]] = call noalias dereferenceable_or_null(10) i8* @malloc(i64 noundef 10) 200; CHECK-NEXT: ret i8* [[CALL]] 201; 202entry: 203 store i32 10, i32* %arg, align 4 204 %call = call dereferenceable_or_null(10) i8* @malloc(i64 10) 205 ret i8* %call 206} 207 208define dso_local i8* @internal_argmem_only_rec(i32* %arg) { 209; IS__TUNIT____: Function Attrs: inaccessiblemem_or_argmemonly 210; IS__TUNIT____-LABEL: define {{[^@]+}}@internal_argmem_only_rec 211; IS__TUNIT____-SAME: (i32* nocapture [[ARG:%.*]]) [[ATTR1:#.*]] { 212; IS__TUNIT____-NEXT: entry: 213; IS__TUNIT____-NEXT: [[CALL:%.*]] = call noalias i8* @internal_argmem_only_rec_1(i32* nocapture align 4 [[ARG]]) 214; IS__TUNIT____-NEXT: ret i8* [[CALL]] 215; 216; IS__CGSCC____: Function Attrs: inaccessiblemem_or_argmemonly 217; IS__CGSCC____-LABEL: define {{[^@]+}}@internal_argmem_only_rec 218; IS__CGSCC____-SAME: (i32* nocapture nonnull align 4 dereferenceable(4) [[ARG:%.*]]) [[ATTR1:#.*]] { 219; IS__CGSCC____-NEXT: entry: 220; IS__CGSCC____-NEXT: [[CALL:%.*]] = call noalias i8* @internal_argmem_only_rec_1(i32* nocapture nonnull align 4 dereferenceable(4) [[ARG]]) 221; IS__CGSCC____-NEXT: ret i8* [[CALL]] 222; 223entry: 224 %call = call i8* @internal_argmem_only_rec_1(i32* %arg) 225 ret i8* %call 226} 227 228define internal i8* @internal_argmem_only_rec_1(i32* %arg) { 229; CHECK: Function Attrs: inaccessiblemem_or_argmemonly 230; CHECK-LABEL: define {{[^@]+}}@internal_argmem_only_rec_1 231; CHECK-SAME: (i32* nocapture nonnull align 4 dereferenceable(4) [[ARG:%.*]]) [[ATTR1]] { 232; CHECK-NEXT: entry: 233; CHECK-NEXT: [[TMP:%.*]] = load i32, i32* [[ARG]], align 4 234; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP]], 0 235; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 236; CHECK: if.then: 237; CHECK-NEXT: br label [[RETURN:%.*]] 238; CHECK: if.end: 239; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[ARG]], align 4 240; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[TMP1]], 1 241; CHECK-NEXT: br i1 [[CMP1]], label [[IF_THEN2:%.*]], label [[IF_END3:%.*]] 242; CHECK: if.then2: 243; CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARG]], i64 -1 244; CHECK-NEXT: [[CALL:%.*]] = call noalias i8* @internal_argmem_only_rec_2(i32* nocapture nonnull align 4 dereferenceable(4) [[ADD_PTR]]) 245; CHECK-NEXT: br label [[RETURN]] 246; CHECK: if.end3: 247; CHECK-NEXT: [[TMP2:%.*]] = load i32, i32* [[ARG]], align 4 248; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP2]] to i64 249; CHECK-NEXT: [[CALL4:%.*]] = call noalias i8* @malloc(i64 [[CONV]]) 250; CHECK-NEXT: br label [[RETURN]] 251; CHECK: return: 252; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i8* [ null, [[IF_THEN]] ], [ [[CALL]], [[IF_THEN2]] ], [ [[CALL4]], [[IF_END3]] ] 253; CHECK-NEXT: ret i8* [[RETVAL_0]] 254; 255entry: 256 %tmp = load i32, i32* %arg, align 4 257 %cmp = icmp eq i32 %tmp, 0 258 br i1 %cmp, label %if.then, label %if.end 259 260if.then: ; preds = %entry 261 br label %return 262 263if.end: ; preds = %entry 264 %tmp1 = load i32, i32* %arg, align 4 265 %cmp1 = icmp eq i32 %tmp1, 1 266 br i1 %cmp1, label %if.then2, label %if.end3 267 268if.then2: ; preds = %if.end 269 %add.ptr = getelementptr inbounds i32, i32* %arg, i64 -1 270 %call = call i8* @internal_argmem_only_rec_2(i32* nonnull %add.ptr) 271 br label %return 272 273if.end3: ; preds = %if.end 274 %tmp2 = load i32, i32* %arg, align 4 275 %conv = sext i32 %tmp2 to i64 276 %call4 = call i8* @malloc(i64 %conv) 277 br label %return 278 279return: ; preds = %if.end3, %if.then2, %if.then 280 %retval.0 = phi i8* [ null, %if.then ], [ %call, %if.then2 ], [ %call4, %if.end3 ] 281 ret i8* %retval.0 282} 283 284define internal i8* @internal_argmem_only_rec_2(i32* %arg) { 285; CHECK: Function Attrs: inaccessiblemem_or_argmemonly 286; CHECK-LABEL: define {{[^@]+}}@internal_argmem_only_rec_2 287; CHECK-SAME: (i32* nocapture nonnull align 4 dereferenceable(4) [[ARG:%.*]]) [[ATTR1]] { 288; CHECK-NEXT: entry: 289; CHECK-NEXT: store i32 0, i32* [[ARG]], align 4 290; CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARG]], i64 -1 291; CHECK-NEXT: [[CALL:%.*]] = call noalias i8* @internal_argmem_only_rec_1(i32* nocapture nonnull align 4 dereferenceable(4) [[ADD_PTR]]) 292; CHECK-NEXT: ret i8* [[CALL]] 293; 294entry: 295 store i32 0, i32* %arg, align 4 296 %add.ptr = getelementptr inbounds i32, i32* %arg, i64 -1 297 %call = call i8* @internal_argmem_only_rec_1(i32* nonnull %add.ptr) 298 ret i8* %call 299} 300 301declare i8* @unknown_ptr() readnone 302declare i8* @argmem_only(i8* %arg) argmemonly 303declare i8* @inaccesible_argmem_only_decl(i8* %arg) inaccessiblemem_or_argmemonly 304declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) nounwind argmemonly willreturn 305 306define void @callerA1(i8* %arg) { 307; CHECK: Function Attrs: argmemonly 308; CHECK-LABEL: define {{[^@]+}}@callerA1 309; CHECK-SAME: (i8* [[ARG:%.*]]) [[ATTR3:#.*]] { 310; CHECK-NEXT: [[TMP1:%.*]] = call i8* @argmem_only(i8* [[ARG]]) 311; CHECK-NEXT: ret void 312; 313 call i8* @argmem_only(i8* %arg) 314 ret void 315} 316define void @callerA2(i8* %arg) { 317; CHECK: Function Attrs: inaccessiblemem_or_argmemonly 318; CHECK-LABEL: define {{[^@]+}}@callerA2 319; CHECK-SAME: (i8* [[ARG:%.*]]) [[ATTR1]] { 320; CHECK-NEXT: [[TMP1:%.*]] = call i8* @inaccesible_argmem_only_decl(i8* [[ARG]]) 321; CHECK-NEXT: ret void 322; 323 call i8* @inaccesible_argmem_only_decl(i8* %arg) 324 ret void 325} 326define void @callerB1() { 327; CHECK: Function Attrs: readnone 328; CHECK-LABEL: define {{[^@]+}}@callerB1 329; CHECK-SAME: () [[ATTR2:#.*]] { 330; CHECK-NEXT: [[STACK:%.*]] = alloca i8, align 1 331; CHECK-NEXT: [[TMP1:%.*]] = call i8* @argmem_only(i8* noundef nonnull dereferenceable(1) [[STACK]]) 332; CHECK-NEXT: ret void 333; 334 %stack = alloca i8 335 call i8* @argmem_only(i8* %stack) 336 ret void 337} 338define void @callerB2() { 339; CHECK: Function Attrs: inaccessiblememonly 340; CHECK-LABEL: define {{[^@]+}}@callerB2 341; CHECK-SAME: () [[ATTR0]] { 342; CHECK-NEXT: [[STACK:%.*]] = alloca i8, align 1 343; CHECK-NEXT: [[TMP1:%.*]] = call i8* @inaccesible_argmem_only_decl(i8* noundef nonnull dereferenceable(1) [[STACK]]) 344; CHECK-NEXT: ret void 345; 346 %stack = alloca i8 347 call i8* @inaccesible_argmem_only_decl(i8* %stack) 348 ret void 349} 350define void @callerC1() { 351; CHECK-LABEL: define {{[^@]+}}@callerC1() { 352; CHECK-NEXT: [[UNKNOWN:%.*]] = call i8* @unknown_ptr() 353; CHECK-NEXT: [[TMP1:%.*]] = call i8* @argmem_only(i8* [[UNKNOWN]]) 354; CHECK-NEXT: ret void 355; 356 %unknown = call i8* @unknown_ptr() 357 call i8* @argmem_only(i8* %unknown) 358 ret void 359} 360define void @callerC2() { 361; CHECK-LABEL: define {{[^@]+}}@callerC2() { 362; CHECK-NEXT: [[UNKNOWN:%.*]] = call i8* @unknown_ptr() 363; CHECK-NEXT: [[TMP1:%.*]] = call i8* @inaccesible_argmem_only_decl(i8* [[UNKNOWN]]) 364; CHECK-NEXT: ret void 365; 366 %unknown = call i8* @unknown_ptr() 367 call i8* @inaccesible_argmem_only_decl(i8* %unknown) 368 ret void 369} 370define void @callerD1() { 371; CHECK-LABEL: define {{[^@]+}}@callerD1() { 372; CHECK-NEXT: [[UNKNOWN:%.*]] = call i8* @argmem_only(i8* noalias nocapture noundef align 536870912 null) 373; CHECK-NEXT: store i8 0, i8* [[UNKNOWN]], align 1 374; CHECK-NEXT: ret void 375; 376 %unknown = call i8* @argmem_only(i8* null) 377 store i8 0, i8* %unknown 378 ret void 379} 380define void @callerD2() { 381; CHECK-LABEL: define {{[^@]+}}@callerD2() { 382; CHECK-NEXT: [[UNKNOWN:%.*]] = call i8* @inaccesible_argmem_only_decl(i8* noalias nocapture noundef align 536870912 null) 383; CHECK-NEXT: store i8 0, i8* [[UNKNOWN]], align 1 384; CHECK-NEXT: ret void 385; 386 %unknown = call i8* @inaccesible_argmem_only_decl(i8* null) 387 store i8 0, i8* %unknown 388 ret void 389} 390 391define void @callerE(i8* %arg) { 392; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn 393; IS__TUNIT____-LABEL: define {{[^@]+}}@callerE 394; IS__TUNIT____-SAME: (i8* nocapture nofree readnone [[ARG:%.*]]) [[ATTR5:#.*]] { 395; IS__TUNIT____-NEXT: ret void 396; 397; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 398; IS__CGSCC____-LABEL: define {{[^@]+}}@callerE 399; IS__CGSCC____-SAME: (i8* nocapture nofree readnone [[ARG:%.*]]) [[ATTR5:#.*]] { 400; IS__CGSCC____-NEXT: ret void 401; 402 call void @llvm.lifetime.start.p0i8(i64 4, i8* %arg) 403 ret void 404} 405 406 407define void @write_global() { 408; IS__TUNIT____: Function Attrs: nofree nosync nounwind willreturn writeonly 409; IS__TUNIT____-LABEL: define {{[^@]+}}@write_global 410; IS__TUNIT____-SAME: () [[ATTR6:#.*]] { 411; IS__TUNIT____-NEXT: store i32 0, i32* @G, align 4 412; IS__TUNIT____-NEXT: ret void 413; 414; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly 415; IS__CGSCC____-LABEL: define {{[^@]+}}@write_global 416; IS__CGSCC____-SAME: () [[ATTR6:#.*]] { 417; IS__CGSCC____-NEXT: store i32 0, i32* @G, align 4 418; IS__CGSCC____-NEXT: ret void 419; 420 store i32 0, i32* @G, align 4 421 ret void 422} 423define void @write_global_via_arg(i32* %GPtr) { 424; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly 425; IS__TUNIT____-LABEL: define {{[^@]+}}@write_global_via_arg 426; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[GPTR:%.*]]) [[ATTR7:#.*]] { 427; IS__TUNIT____-NEXT: store i32 0, i32* [[GPTR]], align 4 428; IS__TUNIT____-NEXT: ret void 429; 430; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly 431; IS__CGSCC____-LABEL: define {{[^@]+}}@write_global_via_arg 432; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[GPTR:%.*]]) [[ATTR7:#.*]] { 433; IS__CGSCC____-NEXT: store i32 0, i32* [[GPTR]], align 4 434; IS__CGSCC____-NEXT: ret void 435; 436 store i32 0, i32* %GPtr, align 4 437 ret void 438} 439define internal void @write_global_via_arg_internal(i32* %GPtr) { 440; IS__TUNIT____: Function Attrs: nofree nosync nounwind willreturn writeonly 441; IS__TUNIT____-LABEL: define {{[^@]+}}@write_global_via_arg_internal 442; IS__TUNIT____-SAME: () [[ATTR6]] { 443; IS__TUNIT____-NEXT: store i32 0, i32* @G, align 4 444; IS__TUNIT____-NEXT: ret void 445; 446; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly 447; IS__CGSCC____-LABEL: define {{[^@]+}}@write_global_via_arg_internal 448; IS__CGSCC____-SAME: () [[ATTR6]] { 449; IS__CGSCC____-NEXT: store i32 0, i32* @G, align 4 450; IS__CGSCC____-NEXT: ret void 451; 452 store i32 0, i32* %GPtr, align 4 453 ret void 454} 455 456define void @writeonly_global() { 457; IS__TUNIT____: Function Attrs: nofree nosync nounwind willreturn writeonly 458; IS__TUNIT____-LABEL: define {{[^@]+}}@writeonly_global 459; IS__TUNIT____-SAME: () [[ATTR6]] { 460; IS__TUNIT____-NEXT: call void @write_global() [[ATTR6]] 461; IS__TUNIT____-NEXT: ret void 462; 463; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly 464; IS__CGSCC____-LABEL: define {{[^@]+}}@writeonly_global 465; IS__CGSCC____-SAME: () [[ATTR6]] { 466; IS__CGSCC____-NEXT: call void @write_global() [[ATTR10:#.*]] 467; IS__CGSCC____-NEXT: ret void 468; 469 call void @write_global() 470 ret void 471} 472define void @writeonly_global_via_arg() { 473; IS__TUNIT____: Function Attrs: nofree nosync nounwind willreturn writeonly 474; IS__TUNIT____-LABEL: define {{[^@]+}}@writeonly_global_via_arg 475; IS__TUNIT____-SAME: () [[ATTR6]] { 476; IS__TUNIT____-NEXT: call void @write_global_via_arg(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) @G) [[ATTR6]] 477; IS__TUNIT____-NEXT: ret void 478; 479; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly 480; IS__CGSCC____-LABEL: define {{[^@]+}}@writeonly_global_via_arg 481; IS__CGSCC____-SAME: () [[ATTR6]] { 482; IS__CGSCC____-NEXT: call void @write_global_via_arg(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) @G) [[ATTR10]] 483; IS__CGSCC____-NEXT: ret void 484; 485 call void @write_global_via_arg(i32* @G) 486 ret void 487} 488 489define void @writeonly_global_via_arg_internal() { 490; 491; IS__TUNIT____: Function Attrs: nofree nosync nounwind willreturn writeonly 492; IS__TUNIT____-LABEL: define {{[^@]+}}@writeonly_global_via_arg_internal 493; IS__TUNIT____-SAME: () [[ATTR6]] { 494; IS__TUNIT____-NEXT: call void @write_global_via_arg_internal() [[ATTR6]] 495; IS__TUNIT____-NEXT: ret void 496; 497; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly 498; IS__CGSCC____-LABEL: define {{[^@]+}}@writeonly_global_via_arg_internal 499; IS__CGSCC____-SAME: () [[ATTR6]] { 500; IS__CGSCC____-NEXT: call void @write_global_via_arg_internal() [[ATTR10]] 501; IS__CGSCC____-NEXT: ret void 502; 503 call void @write_global_via_arg_internal(i32* @G) 504 ret void 505} 506 507define i8 @recursive_not_readnone(i8* %ptr, i1 %c) { 508; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind 509; IS__TUNIT____-LABEL: define {{[^@]+}}@recursive_not_readnone 510; IS__TUNIT____-SAME: (i8* nocapture nofree writeonly [[PTR:%.*]], i1 [[C:%.*]]) [[ATTR8:#.*]] { 511; IS__TUNIT____-NEXT: [[ALLOC:%.*]] = alloca i8, align 1 512; IS__TUNIT____-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] 513; IS__TUNIT____: t: 514; IS__TUNIT____-NEXT: [[TMP1:%.*]] = call i8 @recursive_not_readnone(i8* noalias nocapture nofree noundef nonnull writeonly dereferenceable(1) [[ALLOC]], i1 noundef false) [[ATTR10:#.*]] 515; IS__TUNIT____-NEXT: [[R:%.*]] = load i8, i8* [[ALLOC]], align 1 516; IS__TUNIT____-NEXT: ret i8 [[R]] 517; IS__TUNIT____: f: 518; IS__TUNIT____-NEXT: store i8 1, i8* [[PTR]], align 1 519; IS__TUNIT____-NEXT: ret i8 0 520; 521; IS__CGSCC____: Function Attrs: argmemonly nofree nosync nounwind 522; IS__CGSCC____-LABEL: define {{[^@]+}}@recursive_not_readnone 523; IS__CGSCC____-SAME: (i8* nocapture nofree writeonly [[PTR:%.*]], i1 [[C:%.*]]) [[ATTR8:#.*]] { 524; IS__CGSCC____-NEXT: [[ALLOC:%.*]] = alloca i8, align 1 525; IS__CGSCC____-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] 526; IS__CGSCC____: t: 527; IS__CGSCC____-NEXT: [[TMP1:%.*]] = call i8 @recursive_not_readnone(i8* noalias nocapture nofree noundef nonnull writeonly dereferenceable(1) [[ALLOC]], i1 noundef false) [[ATTR11:#.*]] 528; IS__CGSCC____-NEXT: [[R:%.*]] = load i8, i8* [[ALLOC]], align 1 529; IS__CGSCC____-NEXT: ret i8 [[R]] 530; IS__CGSCC____: f: 531; IS__CGSCC____-NEXT: store i8 1, i8* [[PTR]], align 1 532; IS__CGSCC____-NEXT: ret i8 0 533; 534 %alloc = alloca i8 535 br i1 %c, label %t, label %f 536t: 537 call i8 @recursive_not_readnone(i8* %alloc, i1 false) 538 %r = load i8, i8* %alloc 539 ret i8 %r 540f: 541 store i8 1, i8* %ptr 542 ret i8 0 543} 544 545define internal i8 @recursive_not_readnone_internal(i8* %ptr, i1 %c) { 546; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind 547; IS__TUNIT____-LABEL: define {{[^@]+}}@recursive_not_readnone_internal 548; IS__TUNIT____-SAME: (i8* noalias nocapture nofree noundef nonnull writeonly dereferenceable(1) [[PTR:%.*]], i1 [[C:%.*]]) [[ATTR8]] { 549; IS__TUNIT____-NEXT: [[ALLOC:%.*]] = alloca i8, align 1 550; IS__TUNIT____-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] 551; IS__TUNIT____: t: 552; IS__TUNIT____-NEXT: [[TMP1:%.*]] = call i8 @recursive_not_readnone_internal(i8* noalias nocapture nofree noundef nonnull writeonly dereferenceable(1) [[ALLOC]], i1 noundef false) [[ATTR10]] 553; IS__TUNIT____-NEXT: [[R:%.*]] = load i8, i8* [[ALLOC]], align 1 554; IS__TUNIT____-NEXT: ret i8 [[R]] 555; IS__TUNIT____: f: 556; IS__TUNIT____-NEXT: store i8 1, i8* [[PTR]], align 1 557; IS__TUNIT____-NEXT: ret i8 0 558; 559; IS__CGSCC____: Function Attrs: argmemonly nofree nosync nounwind 560; IS__CGSCC____-LABEL: define {{[^@]+}}@recursive_not_readnone_internal 561; IS__CGSCC____-SAME: (i8* noalias nocapture nofree noundef nonnull writeonly dereferenceable(1) [[PTR:%.*]], i1 [[C:%.*]]) [[ATTR8]] { 562; IS__CGSCC____-NEXT: [[ALLOC:%.*]] = alloca i8, align 1 563; IS__CGSCC____-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] 564; IS__CGSCC____: t: 565; IS__CGSCC____-NEXT: [[TMP1:%.*]] = call i8 @recursive_not_readnone_internal(i8* noalias nocapture nofree noundef nonnull writeonly dereferenceable(1) [[ALLOC]], i1 noundef false) [[ATTR11]] 566; IS__CGSCC____-NEXT: [[R:%.*]] = load i8, i8* [[ALLOC]], align 1 567; IS__CGSCC____-NEXT: ret i8 [[R]] 568; IS__CGSCC____: f: 569; IS__CGSCC____-NEXT: store i8 1, i8* [[PTR]], align 1 570; IS__CGSCC____-NEXT: ret i8 0 571; 572 %alloc = alloca i8 573 br i1 %c, label %t, label %f 574t: 575 call i8 @recursive_not_readnone_internal(i8* %alloc, i1 false) 576 %r = load i8, i8* %alloc 577 ret i8 %r 578f: 579 store i8 1, i8* %ptr 580 ret i8 0 581} 582 583define i8 @readnone_caller(i1 %c) { 584; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone 585; IS__TUNIT____-LABEL: define {{[^@]+}}@readnone_caller 586; IS__TUNIT____-SAME: (i1 [[C:%.*]]) [[ATTR9:#.*]] { 587; IS__TUNIT____-NEXT: [[A:%.*]] = alloca i8, align 1 588; IS__TUNIT____-NEXT: [[R:%.*]] = call i8 @recursive_not_readnone_internal(i8* noalias nocapture nofree noundef nonnull writeonly dereferenceable(1) [[A]], i1 [[C]]) [[ATTR10]] 589; IS__TUNIT____-NEXT: ret i8 [[R]] 590; 591; IS__CGSCC____: Function Attrs: nofree nosync nounwind readnone 592; IS__CGSCC____-LABEL: define {{[^@]+}}@readnone_caller 593; IS__CGSCC____-SAME: (i1 [[C:%.*]]) [[ATTR9:#.*]] { 594; IS__CGSCC____-NEXT: [[A:%.*]] = alloca i8, align 1 595; IS__CGSCC____-NEXT: [[R:%.*]] = call i8 @recursive_not_readnone_internal(i8* noalias nocapture nofree noundef nonnull writeonly dereferenceable(1) [[A]], i1 [[C]]) [[ATTR12:#.*]] 596; IS__CGSCC____-NEXT: ret i8 [[R]] 597; 598 %a = alloca i8 599 %r = call i8 @recursive_not_readnone_internal(i8* %a, i1 %c) 600 ret i8 %r 601} 602 603define internal i8 @recursive_not_readnone_internal2(i8* %ptr, i1 %c) { 604; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind 605; IS__TUNIT____-LABEL: define {{[^@]+}}@recursive_not_readnone_internal2 606; IS__TUNIT____-SAME: (i8* nocapture nofree nonnull writeonly [[PTR:%.*]], i1 [[C:%.*]]) [[ATTR8]] { 607; IS__TUNIT____-NEXT: [[ALLOC:%.*]] = alloca i8, align 1 608; IS__TUNIT____-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] 609; IS__TUNIT____: t: 610; IS__TUNIT____-NEXT: [[TMP1:%.*]] = call i8 @recursive_not_readnone_internal2(i8* noalias nocapture nofree noundef nonnull writeonly dereferenceable(1) [[ALLOC]], i1 noundef false) [[ATTR10]] 611; IS__TUNIT____-NEXT: [[R:%.*]] = load i8, i8* [[ALLOC]], align 1 612; IS__TUNIT____-NEXT: ret i8 [[R]] 613; IS__TUNIT____: f: 614; IS__TUNIT____-NEXT: store i8 1, i8* [[PTR]], align 1 615; IS__TUNIT____-NEXT: ret i8 0 616; 617; IS__CGSCC____: Function Attrs: argmemonly nofree nosync nounwind 618; IS__CGSCC____-LABEL: define {{[^@]+}}@recursive_not_readnone_internal2 619; IS__CGSCC____-SAME: (i8* nocapture nofree nonnull writeonly [[PTR:%.*]], i1 [[C:%.*]]) [[ATTR8]] { 620; IS__CGSCC____-NEXT: [[ALLOC:%.*]] = alloca i8, align 1 621; IS__CGSCC____-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] 622; IS__CGSCC____: t: 623; IS__CGSCC____-NEXT: [[TMP1:%.*]] = call i8 @recursive_not_readnone_internal2(i8* noalias nocapture nofree noundef nonnull writeonly dereferenceable(1) [[ALLOC]], i1 noundef false) [[ATTR11]] 624; IS__CGSCC____-NEXT: [[R:%.*]] = load i8, i8* [[ALLOC]], align 1 625; IS__CGSCC____-NEXT: ret i8 [[R]] 626; IS__CGSCC____: f: 627; IS__CGSCC____-NEXT: store i8 1, i8* [[PTR]], align 1 628; IS__CGSCC____-NEXT: ret i8 0 629; 630 %alloc = alloca i8 631 br i1 %c, label %t, label %f 632t: 633 call i8 @recursive_not_readnone_internal2(i8* %alloc, i1 false) 634 %r = load i8, i8* %alloc 635 ret i8 %r 636f: 637 store i8 1, i8* %ptr 638 ret i8 0 639} 640 641define i8 @readnone_caller2(i1 %c) { 642; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone 643; IS__TUNIT____-LABEL: define {{[^@]+}}@readnone_caller2 644; IS__TUNIT____-SAME: (i1 [[C:%.*]]) [[ATTR9]] { 645; IS__TUNIT____-NEXT: [[R:%.*]] = call i8 @recursive_not_readnone_internal2(i8* undef, i1 [[C]]) [[ATTR10]] 646; IS__TUNIT____-NEXT: ret i8 [[R]] 647; 648; IS__CGSCC____: Function Attrs: nofree nosync nounwind readnone 649; IS__CGSCC____-LABEL: define {{[^@]+}}@readnone_caller2 650; IS__CGSCC____-SAME: (i1 [[C:%.*]]) [[ATTR9]] { 651; IS__CGSCC____-NEXT: [[R:%.*]] = call i8 @recursive_not_readnone_internal2(i8* undef, i1 [[C]]) [[ATTR12]] 652; IS__CGSCC____-NEXT: ret i8 [[R]] 653; 654 %r = call i8 @recursive_not_readnone_internal2(i8* undef, i1 %c) 655 ret i8 %r 656} 657 658define internal void @argmemonly_before_ipconstprop(i32* %p) argmemonly { 659; IS__TUNIT____: Function Attrs: nofree nosync nounwind willreturn writeonly 660; IS__TUNIT____-LABEL: define {{[^@]+}}@argmemonly_before_ipconstprop 661; IS__TUNIT____-SAME: () [[ATTR6]] { 662; IS__TUNIT____-NEXT: store i32 0, i32* @G, align 4 663; IS__TUNIT____-NEXT: ret void 664; 665; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly 666; IS__CGSCC____-LABEL: define {{[^@]+}}@argmemonly_before_ipconstprop 667; IS__CGSCC____-SAME: () [[ATTR6]] { 668; IS__CGSCC____-NEXT: store i32 0, i32* @G, align 4 669; IS__CGSCC____-NEXT: ret void 670; 671 store i32 0, i32* %p 672 ret void 673} 674 675define void @argmemonky_caller() { 676; IS__TUNIT____: Function Attrs: nofree nosync nounwind willreturn writeonly 677; IS__TUNIT____-LABEL: define {{[^@]+}}@argmemonky_caller 678; IS__TUNIT____-SAME: () [[ATTR6]] { 679; IS__TUNIT____-NEXT: call void @argmemonly_before_ipconstprop() [[ATTR6]] 680; IS__TUNIT____-NEXT: ret void 681; 682; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly 683; IS__CGSCC____-LABEL: define {{[^@]+}}@argmemonky_caller 684; IS__CGSCC____-SAME: () [[ATTR6]] { 685; IS__CGSCC____-NEXT: call void @argmemonly_before_ipconstprop() [[ATTR10]] 686; IS__CGSCC____-NEXT: ret void 687; 688 call void @argmemonly_before_ipconstprop(i32* @G) 689 ret void 690} 691