1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals 2; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,TUNIT 3; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,CGSCC 4 5; TEST 1 - negative. 6 7; void *G; 8; void *foo(){ 9; void *V = malloc(4); 10; G = V; 11; return V; 12; } 13 14@G = external global ptr 15 16;. 17; CHECK: @G = external global ptr 18; CHECK: @alias_of_p = external global ptr 19;. 20define ptr @foo() { 21; CHECK-LABEL: define {{[^@]+}}@foo() { 22; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias ptr @malloc(i64 noundef 4) 23; CHECK-NEXT: store ptr [[TMP1]], ptr @G, align 8 24; CHECK-NEXT: ret ptr [[TMP1]] 25; 26 %1 = tail call noalias ptr @malloc(i64 4) 27 store ptr %1, ptr @G, align 8 28 ret ptr %1 29} 30 31declare noalias ptr @malloc(i64) 32 33; TEST 2 34; call noalias function in return instruction. 35 36define ptr @return_noalias(){ 37; CHECK-LABEL: define {{[^@]+}}@return_noalias() { 38; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias ptr @malloc(i64 noundef 4) 39; CHECK-NEXT: ret ptr [[TMP1]] 40; 41 %1 = tail call noalias ptr @malloc(i64 4) 42 ret ptr %1 43} 44 45define void @nocapture(ptr %a){ 46; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 47; CHECK-LABEL: define {{[^@]+}}@nocapture 48; CHECK-SAME: (ptr nofree readnone captures(none) [[A:%.*]]) #[[ATTR0:[0-9]+]] { 49; CHECK-NEXT: ret void 50; 51 ret void 52} 53 54define ptr @return_noalias_looks_like_capture(){ 55; CHECK-LABEL: define {{[^@]+}}@return_noalias_looks_like_capture() { 56; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias ptr @malloc(i64 noundef 4) 57; CHECK-NEXT: ret ptr [[TMP1]] 58; 59 %1 = tail call noalias ptr @malloc(i64 4) 60 call void @nocapture(ptr %1) 61 ret ptr %1 62} 63 64define ptr @return_noalias_casted(){ 65; CHECK-LABEL: define {{[^@]+}}@return_noalias_casted() { 66; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias ptr @malloc(i64 noundef 4) 67; CHECK-NEXT: ret ptr [[TMP1]] 68; 69 %1 = tail call noalias ptr @malloc(i64 4) 70 ret ptr %1 71} 72 73declare ptr @alias() 74 75; TEST 3 76define ptr @call_alias(){ 77; CHECK-LABEL: define {{[^@]+}}@call_alias() { 78; CHECK-NEXT: [[TMP1:%.*]] = tail call ptr @alias() 79; CHECK-NEXT: ret ptr [[TMP1]] 80; 81 %1 = tail call ptr @alias() 82 ret ptr %1 83} 84 85; TEST 4 86; void *baz(); 87; void *foo(int a); 88; 89; void *bar() { 90; foo(0); 91; return baz(); 92; } 93; 94; void *foo(int a) { 95; if (a) 96; bar(); 97; return malloc(4); 98; } 99 100define ptr @bar() nounwind uwtable { 101; TUNIT: Function Attrs: nounwind uwtable 102; TUNIT-LABEL: define {{[^@]+}}@bar 103; TUNIT-SAME: () #[[ATTR1:[0-9]+]] { 104; TUNIT-NEXT: [[TMP1:%.*]] = tail call ptr (...) @baz() #[[ATTR2:[0-9]+]] 105; TUNIT-NEXT: ret ptr [[TMP1]] 106; 107; CGSCC: Function Attrs: nounwind uwtable 108; CGSCC-LABEL: define {{[^@]+}}@bar 109; CGSCC-SAME: () #[[ATTR1:[0-9]+]] { 110; CGSCC-NEXT: [[TMP1:%.*]] = tail call ptr (...) @baz() #[[ATTR3:[0-9]+]] 111; CGSCC-NEXT: ret ptr [[TMP1]] 112; 113 %1 = tail call ptr (...) @baz() 114 ret ptr %1 115} 116 117define ptr @foo1(i32 %0) nounwind uwtable { 118; TUNIT: Function Attrs: nounwind uwtable 119; TUNIT-LABEL: define {{[^@]+}}@foo1 120; TUNIT-SAME: (i32 [[TMP0:%.*]]) #[[ATTR1]] { 121; TUNIT-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP0]], 0 122; TUNIT-NEXT: br i1 [[TMP2]], label [[TMP5:%.*]], label [[TMP3:%.*]] 123; TUNIT: 3: 124; TUNIT-NEXT: [[TMP4:%.*]] = tail call ptr (...) @baz() #[[ATTR2]] 125; TUNIT-NEXT: br label [[TMP5]] 126; TUNIT: 5: 127; TUNIT-NEXT: [[TMP6:%.*]] = tail call noalias ptr @malloc(i64 noundef 4) 128; TUNIT-NEXT: ret ptr [[TMP6]] 129; 130; CGSCC: Function Attrs: nounwind uwtable 131; CGSCC-LABEL: define {{[^@]+}}@foo1 132; CGSCC-SAME: (i32 [[TMP0:%.*]]) #[[ATTR1]] { 133; CGSCC-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP0]], 0 134; CGSCC-NEXT: br i1 [[TMP2]], label [[TMP5:%.*]], label [[TMP3:%.*]] 135; CGSCC: 3: 136; CGSCC-NEXT: [[TMP4:%.*]] = tail call ptr (...) @baz() #[[ATTR3]] 137; CGSCC-NEXT: br label [[TMP5]] 138; CGSCC: 5: 139; CGSCC-NEXT: [[TMP6:%.*]] = tail call noalias ptr @malloc(i64 noundef 4) 140; CGSCC-NEXT: ret ptr [[TMP6]] 141; 142 %2 = icmp eq i32 %0, 0 143 br i1 %2, label %5, label %3 144 1453: ; preds = %1 146 %4 = tail call ptr (...) @baz() 147 br label %5 148 1495: ; preds = %1, %3 150 %6 = tail call noalias ptr @malloc(i64 4) 151 ret ptr %6 152} 153 154declare ptr @baz(...) nounwind uwtable 155 156; TEST 5 157 158; Returning global pointer. Should not be noalias. 159define ptr @getter() { 160; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 161; CHECK-LABEL: define {{[^@]+}}@getter 162; CHECK-SAME: () #[[ATTR0]] { 163; CHECK-NEXT: ret ptr @G 164; 165 ret ptr @G 166} 167 168; Returning global pointer. Should not be noalias. 169define ptr @calle1(){ 170; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 171; TUNIT-LABEL: define {{[^@]+}}@calle1 172; TUNIT-SAME: () #[[ATTR0]] { 173; TUNIT-NEXT: ret ptr @G 174; 175; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none) 176; CGSCC-LABEL: define {{[^@]+}}@calle1 177; CGSCC-SAME: () #[[ATTR2:[0-9]+]] { 178; CGSCC-NEXT: [[TMP1:%.*]] = call noundef nonnull align 8 dereferenceable(8) ptr @getter() #[[ATTR12:[0-9]+]] 179; CGSCC-NEXT: ret ptr [[TMP1]] 180; 181 %1 = call ptr @getter() 182 ret ptr %1 183} 184 185; TEST 6 186declare noalias ptr @strdup(ptr nocapture) nounwind 187 188define ptr @test6() nounwind uwtable ssp { 189; TUNIT: Function Attrs: nounwind ssp uwtable 190; TUNIT-LABEL: define {{[^@]+}}@test6 191; TUNIT-SAME: () #[[ATTR3:[0-9]+]] { 192; TUNIT-NEXT: [[X:%.*]] = alloca [2 x i8], align 1 193; TUNIT-NEXT: store i8 97, ptr [[X]], align 1 194; TUNIT-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds [2 x i8], ptr [[X]], i64 0, i64 1 195; TUNIT-NEXT: store i8 0, ptr [[ARRAYIDX1]], align 1 196; TUNIT-NEXT: [[CALL:%.*]] = call noalias ptr @strdup(ptr noalias noundef nonnull captures(none) dereferenceable(2) [[X]]) #[[ATTR2]] 197; TUNIT-NEXT: ret ptr [[CALL]] 198; 199; CGSCC: Function Attrs: nounwind ssp uwtable 200; CGSCC-LABEL: define {{[^@]+}}@test6 201; CGSCC-SAME: () #[[ATTR4:[0-9]+]] { 202; CGSCC-NEXT: [[X:%.*]] = alloca [2 x i8], align 1 203; CGSCC-NEXT: store i8 97, ptr [[X]], align 1 204; CGSCC-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds [2 x i8], ptr [[X]], i64 0, i64 1 205; CGSCC-NEXT: store i8 0, ptr [[ARRAYIDX1]], align 1 206; CGSCC-NEXT: [[CALL:%.*]] = call noalias ptr @strdup(ptr noalias noundef nonnull captures(none) dereferenceable(2) [[X]]) #[[ATTR3]] 207; CGSCC-NEXT: ret ptr [[CALL]] 208; 209 %x = alloca [2 x i8], align 1 210 store i8 97, ptr %x, align 1 211 %arrayidx1 = getelementptr inbounds [2 x i8], ptr %x, i64 0, i64 1 212 store i8 0, ptr %arrayidx1, align 1 213 %call = call noalias ptr @strdup(ptr %x) nounwind 214 ret ptr %call 215} 216 217; TEST 7 218 219define ptr @test7() nounwind { 220; TUNIT: Function Attrs: nounwind 221; TUNIT-LABEL: define {{[^@]+}}@test7 222; TUNIT-SAME: () #[[ATTR2]] { 223; TUNIT-NEXT: entry: 224; TUNIT-NEXT: [[A:%.*]] = call noalias ptr @malloc(i64 noundef 4) #[[ATTR2]] 225; TUNIT-NEXT: [[TOBOOL:%.*]] = icmp eq ptr [[A]], null 226; TUNIT-NEXT: br i1 [[TOBOOL]], label [[RETURN:%.*]], label [[IF_END:%.*]] 227; TUNIT: if.end: 228; TUNIT-NEXT: store i8 7, ptr [[A]], align 1 229; TUNIT-NEXT: br label [[RETURN]] 230; TUNIT: return: 231; TUNIT-NEXT: [[RETVAL_0:%.*]] = phi ptr [ [[A]], [[IF_END]] ], [ null, [[ENTRY:%.*]] ] 232; TUNIT-NEXT: ret ptr [[RETVAL_0]] 233; 234; CGSCC: Function Attrs: nounwind 235; CGSCC-LABEL: define {{[^@]+}}@test7 236; CGSCC-SAME: () #[[ATTR3]] { 237; CGSCC-NEXT: entry: 238; CGSCC-NEXT: [[A:%.*]] = call noalias ptr @malloc(i64 noundef 4) #[[ATTR3]] 239; CGSCC-NEXT: [[TOBOOL:%.*]] = icmp eq ptr [[A]], null 240; CGSCC-NEXT: br i1 [[TOBOOL]], label [[RETURN:%.*]], label [[IF_END:%.*]] 241; CGSCC: if.end: 242; CGSCC-NEXT: store i8 7, ptr [[A]], align 1 243; CGSCC-NEXT: br label [[RETURN]] 244; CGSCC: return: 245; CGSCC-NEXT: [[RETVAL_0:%.*]] = phi ptr [ [[A]], [[IF_END]] ], [ null, [[ENTRY:%.*]] ] 246; CGSCC-NEXT: ret ptr [[RETVAL_0]] 247; 248entry: 249 %A = call noalias ptr @malloc(i64 4) nounwind 250 %tobool = icmp eq ptr %A, null 251 br i1 %tobool, label %return, label %if.end 252 253if.end: 254 store i8 7, ptr %A 255 br label %return 256 257return: 258 %retval.0 = phi ptr [ %A, %if.end ], [ null, %entry ] 259 ret ptr %retval.0 260} 261 262; TEST 8 263 264define ptr @test8(ptr %0) nounwind uwtable { 265; CHECK: Function Attrs: nounwind uwtable 266; CHECK-LABEL: define {{[^@]+}}@test8 267; CHECK-SAME: (ptr [[TMP0:%.*]]) #[[ATTR1:[0-9]+]] { 268; CHECK-NEXT: [[TMP2:%.*]] = tail call noalias ptr @malloc(i64 noundef 4) 269; CHECK-NEXT: [[TMP3:%.*]] = icmp ne ptr [[TMP0]], null 270; CHECK-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP5:%.*]] 271; CHECK: 4: 272; CHECK-NEXT: store i8 10, ptr [[TMP2]], align 1 273; CHECK-NEXT: br label [[TMP5]] 274; CHECK: 5: 275; CHECK-NEXT: ret ptr [[TMP2]] 276; 277 %2 = tail call noalias ptr @malloc(i64 4) 278 %3 = icmp ne ptr %0, null 279 br i1 %3, label %4, label %5 280 2814: ; preds = %1 282 store i8 10, ptr %2 283 br label %5 284 2855: ; preds = %1, %4 286 ret ptr %2 287} 288 289; TEST 9 290; Simple Argument Test 291declare void @use_i8(ptr nocapture) 292define internal void @test9a(ptr %a, ptr %b) { 293; TUNIT: Function Attrs: memory(readwrite, argmem: none) 294; TUNIT-LABEL: define {{[^@]+}}@test9a 295; TUNIT-SAME: () #[[ATTR4:[0-9]+]] { 296; TUNIT-NEXT: call void @use_i8(ptr noundef align 4294967296 null) 297; TUNIT-NEXT: ret void 298; 299; CGSCC: Function Attrs: memory(readwrite, argmem: none) 300; CGSCC-LABEL: define {{[^@]+}}@test9a 301; CGSCC-SAME: () #[[ATTR5:[0-9]+]] { 302; CGSCC-NEXT: call void @use_i8(ptr noundef align 4294967296 null) 303; CGSCC-NEXT: ret void 304; 305 call void @use_i8(ptr null) 306 ret void 307} 308define internal void @test9b(ptr %a, ptr %b) { 309; FIXME: %b should be noalias 310; CHECK-LABEL: define {{[^@]+}}@test9b 311; CHECK-SAME: (ptr noalias captures(none) [[A:%.*]], ptr captures(none) [[B:%.*]]) { 312; CHECK-NEXT: call void @use_i8(ptr noalias captures(none) [[A]]) 313; CHECK-NEXT: call void @use_i8(ptr captures(none) [[B]]) 314; CHECK-NEXT: ret void 315; 316 call void @use_i8(ptr %a) 317 call void @use_i8(ptr %b) 318 ret void 319} 320define internal void @test9c(ptr %a, ptr %b, ptr %c) { 321; CHECK-LABEL: define {{[^@]+}}@test9c 322; CHECK-SAME: (ptr noalias captures(none) [[A:%.*]], ptr captures(none) [[B:%.*]], ptr captures(none) [[C:%.*]]) { 323; CHECK-NEXT: call void @use_i8(ptr noalias captures(none) [[A]]) 324; CHECK-NEXT: call void @use_i8(ptr captures(none) [[B]]) 325; CHECK-NEXT: call void @use_i8(ptr captures(none) [[C]]) 326; CHECK-NEXT: ret void 327; 328 call void @use_i8(ptr %a) 329 call void @use_i8(ptr %b) 330 call void @use_i8(ptr %c) 331 ret void 332} 333define void @test9_helper(ptr %a, ptr %b) { 334; CHECK-LABEL: define {{[^@]+}}@test9_helper 335; CHECK-SAME: (ptr captures(none) [[A:%.*]], ptr captures(none) [[B:%.*]]) { 336; CHECK-NEXT: tail call void @test9a() 337; CHECK-NEXT: tail call void @test9a() 338; CHECK-NEXT: tail call void @test9b(ptr noalias captures(none) [[A]], ptr captures(none) [[B]]) 339; CHECK-NEXT: tail call void @test9b(ptr noalias captures(none) [[B]], ptr noalias captures(none) [[A]]) 340; CHECK-NEXT: tail call void @test9c(ptr noalias captures(none) [[A]], ptr captures(none) [[B]], ptr captures(none) [[B]]) 341; CHECK-NEXT: tail call void @test9c(ptr noalias captures(none) [[B]], ptr noalias captures(none) [[A]], ptr noalias captures(none) [[A]]) 342; CHECK-NEXT: ret void 343; 344 tail call void @test9a(ptr noalias %a, ptr %b) 345 tail call void @test9a(ptr noalias %b, ptr noalias %a) 346 tail call void @test9b(ptr noalias %a, ptr %b) 347 tail call void @test9b(ptr noalias %b, ptr noalias %a) 348 tail call void @test9c(ptr noalias %a, ptr %b, ptr %b) 349 tail call void @test9c(ptr noalias %b, ptr noalias %a, ptr noalias %a) 350 ret void 351} 352 353 354; TEST 10 355; Simple CallSite Test 356 357declare void @test10_helper_1(ptr %a) 358define void @test10_helper_2(ptr noalias %a) { 359; CHECK-LABEL: define {{[^@]+}}@test10_helper_2 360; CHECK-SAME: (ptr noalias [[A:%.*]]) { 361; CHECK-NEXT: tail call void @test10_helper_1(ptr [[A]]) 362; CHECK-NEXT: ret void 363; 364 tail call void @test10_helper_1(ptr %a) 365 ret void 366} 367define void @test10(ptr noalias %a) { 368; CHECK-LABEL: define {{[^@]+}}@test10 369; CHECK-SAME: (ptr noalias [[A:%.*]]) { 370; CHECK-NEXT: tail call void @test10_helper_1(ptr [[A]]) 371; CHECK-NEXT: tail call void @test10_helper_2(ptr [[A]]) 372; CHECK-NEXT: ret void 373; 374; FIXME: missing noalias 375 tail call void @test10_helper_1(ptr %a) 376 377 tail call void @test10_helper_2(ptr %a) 378 ret void 379} 380 381; TEST 11 382; CallSite Test 383 384declare void @test11_helper(ptr %a, ptr %b) 385define void @test11(ptr noalias %a) { 386; CHECK-LABEL: define {{[^@]+}}@test11 387; CHECK-SAME: (ptr noalias [[A:%.*]]) { 388; CHECK-NEXT: tail call void @test11_helper(ptr [[A]], ptr [[A]]) 389; CHECK-NEXT: ret void 390; 391 tail call void @test11_helper(ptr %a, ptr %a) 392 ret void 393} 394 395 396; TEST 12 397; CallSite Argument 398declare void @use_nocapture(ptr nocapture) 399declare void @use(ptr) 400define void @test12_1() { 401; CHECK-LABEL: define {{[^@]+}}@test12_1() { 402; CHECK-NEXT: [[A:%.*]] = alloca i8, align 4 403; CHECK-NEXT: [[B:%.*]] = tail call noalias ptr @malloc(i64 noundef 4) 404; CHECK-NEXT: tail call void @use_nocapture(ptr noalias noundef nonnull align 4 captures(none) dereferenceable(1) [[A]]) 405; CHECK-NEXT: tail call void @use_nocapture(ptr noalias noundef nonnull align 4 captures(none) dereferenceable(1) [[A]]) 406; CHECK-NEXT: tail call void @use_nocapture(ptr noalias captures(none) [[B]]) 407; CHECK-NEXT: tail call void @use_nocapture(ptr noalias captures(none) [[B]]) 408; CHECK-NEXT: ret void 409; 410 %A = alloca i8, align 4 411 %B = tail call noalias ptr @malloc(i64 4) 412 tail call void @use_nocapture(ptr %A) 413 tail call void @use_nocapture(ptr %A) 414 tail call void @use_nocapture(ptr %B) 415 tail call void @use_nocapture(ptr %B) 416 ret void 417} 418 419define void @test12_2(){ 420; CHECK-LABEL: define {{[^@]+}}@test12_2() { 421; CHECK-NEXT: [[A:%.*]] = tail call noalias ptr @malloc(i64 noundef 4) 422; CHECK-NEXT: tail call void @use_nocapture(ptr captures(none) [[A]]) 423; CHECK-NEXT: tail call void @use_nocapture(ptr captures(none) [[A]]) 424; CHECK-NEXT: tail call void @use(ptr [[A]]) 425; CHECK-NEXT: tail call void @use_nocapture(ptr captures(none) [[A]]) 426; CHECK-NEXT: ret void 427; 428; FIXME: This should be @use_nocapture(ptr noalias [[A]]) 429; FIXME: This should be @use_nocapture(ptr noalias nocapture [[A]]) 430 %A = tail call noalias ptr @malloc(i64 4) 431 tail call void @use_nocapture(ptr %A) 432 tail call void @use_nocapture(ptr %A) 433 tail call void @use(ptr %A) 434 tail call void @use_nocapture(ptr %A) 435 ret void 436} 437 438declare void @two_args(ptr nocapture , ptr nocapture) 439define void @test12_3(){ 440; CHECK-LABEL: define {{[^@]+}}@test12_3() { 441; CHECK-NEXT: [[A:%.*]] = tail call noalias ptr @malloc(i64 noundef 4) 442; CHECK-NEXT: tail call void @two_args(ptr captures(none) [[A]], ptr captures(none) [[A]]) 443; CHECK-NEXT: ret void 444; 445 %A = tail call noalias ptr @malloc(i64 4) 446 tail call void @two_args(ptr %A, ptr %A) 447 ret void 448} 449 450define void @test12_4(){ 451; CHECK-LABEL: define {{[^@]+}}@test12_4() { 452; CHECK-NEXT: [[A:%.*]] = tail call noalias ptr @malloc(i64 noundef 4) 453; CHECK-NEXT: [[B:%.*]] = tail call noalias ptr @malloc(i64 noundef 4) 454; CHECK-NEXT: [[A_1:%.*]] = getelementptr i8, ptr [[A]], i64 1 455; CHECK-NEXT: tail call void @two_args(ptr noalias captures(none) [[A]], ptr noalias captures(none) [[B]]) 456; CHECK-NEXT: tail call void @two_args(ptr captures(none) [[A]], ptr captures(none) [[A]]) 457; CHECK-NEXT: tail call void @two_args(ptr captures(none) [[A]], ptr captures(none) [[A_1]]) 458; CHECK-NEXT: tail call void @two_args(ptr noalias captures(none) [[A]], ptr noalias captures(none) [[B]]) 459; CHECK-NEXT: ret void 460; 461 %A = tail call noalias ptr @malloc(i64 4) 462 %B = tail call noalias ptr @malloc(i64 4) 463 %A_1 = getelementptr i8, ptr %A, i64 1 464 465 tail call void @two_args(ptr %A, ptr %B) 466 467 tail call void @two_args(ptr %A, ptr %A) 468 469 tail call void @two_args(ptr %A, ptr %A_1) 470 471; FIXME: This should be @two_args(ptr noalias nocapture %A, ptr noalias nocapture %B) 472 tail call void @two_args(ptr %A, ptr %B) 473 ret void 474} 475 476; TEST 13 477define void @use_i8_internal(ptr %a) { 478; CHECK-LABEL: define {{[^@]+}}@use_i8_internal 479; CHECK-SAME: (ptr captures(none) [[A:%.*]]) { 480; CHECK-NEXT: call void @use_i8(ptr captures(none) [[A]]) 481; CHECK-NEXT: ret void 482; 483 call void @use_i8(ptr %a) 484 ret void 485} 486 487define void @test13_use_noalias(){ 488; CHECK-LABEL: define {{[^@]+}}@test13_use_noalias() { 489; CHECK-NEXT: [[M1:%.*]] = tail call noalias ptr @malloc(i64 noundef 4) 490; CHECK-NEXT: call void @use_i8_internal(ptr noalias captures(none) [[M1]]) 491; CHECK-NEXT: ret void 492; 493; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@test13_use_noalias() 494; IS__CGSCC_OPM-NEXT: [[M1:%.*]] = tail call noalias ptr @malloc(i64 4) 495; IS__CGSCC_OPM-NEXT: call void @use_i8_internal(ptr noalias [[M1]]) 496; IS__CGSCC_OPM-NEXT: ret void 497 %m1 = tail call noalias ptr @malloc(i64 4) 498 call void @use_i8_internal(ptr %m1) 499 ret void 500} 501 502define void @test13_use_alias(){ 503; CHECK-LABEL: define {{[^@]+}}@test13_use_alias() { 504; CHECK-NEXT: [[M1:%.*]] = tail call noalias ptr @malloc(i64 noundef 4) 505; CHECK-NEXT: call void @use_i8_internal(ptr noalias captures(none) [[M1]]) 506; CHECK-NEXT: call void @use_i8_internal(ptr noalias captures(none) [[M1]]) 507; CHECK-NEXT: ret void 508; 509 %m1 = tail call noalias ptr @malloc(i64 4) 510 call void @use_i8_internal(ptr %m1) 511 call void @use_i8_internal(ptr %m1) 512 ret void 513} 514 515; TEST 14 i2p casts 516define internal i32 @p2i(ptr %arg) { 517; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 518; CHECK-LABEL: define {{[^@]+}}@p2i 519; CHECK-SAME: (ptr noalias nofree readnone [[ARG:%.*]]) #[[ATTR0]] { 520; CHECK-NEXT: [[P2I:%.*]] = ptrtoint ptr [[ARG]] to i32 521; CHECK-NEXT: ret i32 [[P2I]] 522; 523 %p2i = ptrtoint ptr %arg to i32 524 ret i32 %p2i 525} 526 527define i32 @i2p(ptr %arg) { 528; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(read) 529; TUNIT-LABEL: define {{[^@]+}}@i2p 530; TUNIT-SAME: (ptr nofree readonly [[ARG:%.*]]) #[[ATTR5:[0-9]+]] { 531; TUNIT-NEXT: [[C:%.*]] = call i32 @p2i(ptr noalias nofree readnone [[ARG]]) #[[ATTR11:[0-9]+]] 532; TUNIT-NEXT: [[I2P:%.*]] = inttoptr i32 [[C]] to ptr 533; TUNIT-NEXT: [[CALL:%.*]] = call i32 @ret(ptr nofree noundef readonly align 4 captures(none) [[I2P]]) #[[ATTR12:[0-9]+]] 534; TUNIT-NEXT: ret i32 [[CALL]] 535; 536; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(read) 537; CGSCC-LABEL: define {{[^@]+}}@i2p 538; CGSCC-SAME: (ptr nofree readonly [[ARG:%.*]]) #[[ATTR6:[0-9]+]] { 539; CGSCC-NEXT: [[C:%.*]] = call i32 @p2i(ptr noalias nofree readnone [[ARG]]) #[[ATTR12]] 540; CGSCC-NEXT: [[I2P:%.*]] = inttoptr i32 [[C]] to ptr 541; CGSCC-NEXT: [[CALL:%.*]] = call i32 @ret(ptr nofree noundef nonnull readonly align 4 captures(none) dereferenceable(4) [[I2P]]) #[[ATTR13:[0-9]+]] 542; CGSCC-NEXT: ret i32 [[CALL]] 543; 544 %c = call i32 @p2i(ptr %arg) 545 %i2p = inttoptr i32 %c to ptr 546 %call = call i32 @ret(ptr %i2p) 547 ret i32 %call 548} 549define internal i32 @ret(ptr %arg) { 550; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) 551; TUNIT-LABEL: define {{[^@]+}}@ret 552; TUNIT-SAME: (ptr nofree noundef nonnull readonly align 4 captures(none) dereferenceable(4) [[ARG:%.*]]) #[[ATTR6:[0-9]+]] { 553; TUNIT-NEXT: [[L:%.*]] = load i32, ptr [[ARG]], align 4 554; TUNIT-NEXT: ret i32 [[L]] 555; 556; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) 557; CGSCC-LABEL: define {{[^@]+}}@ret 558; CGSCC-SAME: (ptr nofree noundef nonnull readonly align 4 captures(none) dereferenceable(4) [[ARG:%.*]]) #[[ATTR7:[0-9]+]] { 559; CGSCC-NEXT: [[L:%.*]] = load i32, ptr [[ARG]], align 4 560; CGSCC-NEXT: ret i32 [[L]] 561; 562 %l = load i32, ptr %arg 563 ret i32 %l 564} 565 566; Test to propagate noalias where value is assumed to be no-capture in all the 567; uses possibly executed before this callsite. 568; IR referred from musl/src/strtod.c file 569 570%struct._IO_FILE = type { i32, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, i32, ptr, ptr, i32, i32, i32, i16, i8, i8, i32, i32, ptr, i64, ptr, ptr, ptr, [4 x i8], i64, i64, ptr, ptr, ptr, [4 x i8] } 571%struct.__locale_struct = type { [6 x ptr] } 572%struct.__locale_map = type opaque 573 574; Function Attrs: nounwind optsize 575define internal fastcc double @strtox(ptr %s, ptr %p, i32 %prec) unnamed_addr { 576; TUNIT-LABEL: define {{[^@]+}}@strtox 577; TUNIT-SAME: (ptr [[S:%.*]]) unnamed_addr { 578; TUNIT-NEXT: entry: 579; TUNIT-NEXT: [[F:%.*]] = alloca [[STRUCT__IO_FILE:%.*]], align 8 580; TUNIT-NEXT: call void @llvm.lifetime.start.p0(i64 noundef 144, ptr nofree noundef nonnull align 8 captures(none) dereferenceable(240) [[F]]) #[[ATTR13:[0-9]+]] 581; TUNIT-NEXT: [[CALL:%.*]] = call i32 @sh_fromstring(ptr noundef nonnull align 8 dereferenceable(240) [[F]], ptr [[S]]) 582; TUNIT-NEXT: call void @__shlim(ptr noundef nonnull align 8 dereferenceable(240) [[F]], i64 noundef 0) 583; TUNIT-NEXT: [[CALL1:%.*]] = call double @__floatscan(ptr noundef nonnull align 8 dereferenceable(240) [[F]], i32 noundef 1, i32 noundef 1) 584; TUNIT-NEXT: call void @llvm.lifetime.end.p0(i64 noundef 144, ptr nofree noundef nonnull align 8 captures(none) dereferenceable(240) [[F]]) 585; TUNIT-NEXT: ret double [[CALL1]] 586; 587; CGSCC-LABEL: define {{[^@]+}}@strtox 588; CGSCC-SAME: (ptr [[S:%.*]]) unnamed_addr { 589; CGSCC-NEXT: entry: 590; CGSCC-NEXT: [[F:%.*]] = alloca [[STRUCT__IO_FILE:%.*]], align 8 591; CGSCC-NEXT: call void @llvm.lifetime.start.p0(i64 noundef 144, ptr nofree noundef nonnull align 8 captures(none) dereferenceable(240) [[F]]) #[[ATTR14:[0-9]+]] 592; CGSCC-NEXT: [[CALL:%.*]] = call i32 @sh_fromstring(ptr noundef nonnull align 8 dereferenceable(240) [[F]], ptr [[S]]) 593; CGSCC-NEXT: call void @__shlim(ptr noundef nonnull align 8 dereferenceable(240) [[F]], i64 noundef 0) 594; CGSCC-NEXT: [[CALL1:%.*]] = call double @__floatscan(ptr noundef nonnull align 8 dereferenceable(240) [[F]], i32 noundef 1, i32 noundef 1) 595; CGSCC-NEXT: call void @llvm.lifetime.end.p0(i64 noundef 144, ptr nofree noundef nonnull align 8 captures(none) dereferenceable(240) [[F]]) 596; CGSCC-NEXT: ret double [[CALL1]] 597; 598entry: 599 %f = alloca %struct._IO_FILE, align 8 600 call void @llvm.lifetime.start.p0(i64 144, ptr nonnull %f) 601 %call = call i32 @sh_fromstring(ptr nonnull %f, ptr %s) 602 call void @__shlim(ptr nonnull %f, i64 0) 603 %call1 = call double @__floatscan(ptr nonnull %f, i32 %prec, i32 1) 604 call void @llvm.lifetime.end.p0(i64 144, ptr nonnull %f) 605 606 ret double %call1 607} 608 609; Function Attrs: nounwind optsize 610define dso_local double @strtod(ptr noalias %s, ptr noalias %p) { 611; CHECK-LABEL: define {{[^@]+}}@strtod 612; CHECK-SAME: (ptr noalias [[S:%.*]], ptr noalias nofree readnone captures(none) [[P:%.*]]) { 613; CHECK-NEXT: entry: 614; CHECK-NEXT: [[CALL:%.*]] = tail call fastcc double @strtox(ptr [[S]]) 615; CHECK-NEXT: ret double [[CALL]] 616; 617entry: 618 %call = tail call fastcc double @strtox(ptr %s, ptr %p, i32 1) 619 ret double %call 620} 621 622; Function Attrs: argmemonly nounwind willreturn 623declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) 624 625; Function Attrs: optsize 626declare dso_local i32 @sh_fromstring(...) local_unnamed_addr 627 628; Function Attrs: optsize 629declare dso_local void @__shlim(ptr, i64) local_unnamed_addr 630 631; Function Attrs: optsize 632declare dso_local double @__floatscan(ptr, i32, i32) local_unnamed_addr 633 634; Function Attrs: argmemonly nounwind willreturn 635declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) 636 637; Test 15 638; propagate noalias to some callsite arguments that there is no possibly reachable capture before it 639 640@alias_of_p = external global ptr 641 642define void @make_alias(ptr %p) { 643; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write) 644; TUNIT-LABEL: define {{[^@]+}}@make_alias 645; TUNIT-SAME: (ptr nofree writeonly [[P:%.*]]) #[[ATTR8:[0-9]+]] { 646; TUNIT-NEXT: store ptr [[P]], ptr @alias_of_p, align 8 647; TUNIT-NEXT: ret void 648; 649; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write) 650; CGSCC-LABEL: define {{[^@]+}}@make_alias 651; CGSCC-SAME: (ptr nofree writeonly [[P:%.*]]) #[[ATTR9:[0-9]+]] { 652; CGSCC-NEXT: store ptr [[P]], ptr @alias_of_p, align 8 653; CGSCC-NEXT: ret void 654; 655 store ptr %p, ptr @alias_of_p 656 ret void 657} 658 659define void @only_store(ptr %p) { 660; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) 661; TUNIT-LABEL: define {{[^@]+}}@only_store 662; TUNIT-SAME: (ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[P:%.*]]) #[[ATTR9:[0-9]+]] { 663; TUNIT-NEXT: store i32 0, ptr [[P]], align 4 664; TUNIT-NEXT: ret void 665; 666; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) 667; CGSCC-LABEL: define {{[^@]+}}@only_store 668; CGSCC-SAME: (ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[P:%.*]]) #[[ATTR10:[0-9]+]] { 669; CGSCC-NEXT: store i32 0, ptr [[P]], align 4 670; CGSCC-NEXT: ret void 671; 672 store i32 0, ptr %p 673 ret void 674} 675 676define void @test15_caller(ptr noalias %p, i32 %c) { 677; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write) 678; TUNIT-LABEL: define {{[^@]+}}@test15_caller 679; TUNIT-SAME: (ptr noalias nofree writeonly [[P:%.*]], i32 [[C:%.*]]) #[[ATTR8]] { 680; TUNIT-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[C]], 0 681; TUNIT-NEXT: br i1 [[TOBOOL]], label [[IF_END:%.*]], label [[IF_THEN:%.*]] 682; TUNIT: if.then: 683; TUNIT-NEXT: tail call void @only_store(ptr noalias nofree noundef writeonly align 4 captures(none) [[P]]) #[[ATTR14:[0-9]+]] 684; TUNIT-NEXT: br label [[IF_END]] 685; TUNIT: if.end: 686; TUNIT-NEXT: tail call void @make_alias(ptr nofree writeonly [[P]]) #[[ATTR14]] 687; TUNIT-NEXT: ret void 688; 689; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(write) 690; CGSCC-LABEL: define {{[^@]+}}@test15_caller 691; CGSCC-SAME: (ptr noalias nofree writeonly [[P:%.*]], i32 [[C:%.*]]) #[[ATTR11:[0-9]+]] { 692; CGSCC-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[C]], 0 693; CGSCC-NEXT: br i1 [[TOBOOL]], label [[IF_END:%.*]], label [[IF_THEN:%.*]] 694; CGSCC: if.then: 695; CGSCC-NEXT: tail call void @only_store(ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[P]]) #[[ATTR15:[0-9]+]] 696; CGSCC-NEXT: br label [[IF_END]] 697; CGSCC: if.end: 698; CGSCC-NEXT: tail call void @make_alias(ptr nofree writeonly [[P]]) #[[ATTR15]] 699; CGSCC-NEXT: ret void 700; 701 %tobool = icmp eq i32 %c, 0 702 br i1 %tobool, label %if.end, label %if.then 703 704 705if.then: 706 tail call void @only_store(ptr %p) 707 br label %if.end 708 709if.end: 710 tail call void @make_alias(ptr %p) 711 ret void 712} 713 714; Test 16 715; 716; __attribute__((noinline)) static void test16_sub(int * restrict p, int c1, int c2) { 717; if (c1) { 718; only_store(p); 719; make_alias(p); 720; } 721; if (!c2) { 722; only_store(p); 723; } 724; } 725; void test16_caller(int * restrict p, int c) { 726; test16_sub(p, c, c); 727; } 728; 729; FIXME: this should be tail @only_store(ptr noalias %p) 730; when test16_caller is called, c1 always equals to c2. (Note that linkage is internal) 731; Therefore, only one of the two conditions of if statementes will be fulfilled. 732 733define internal void @test16_sub(ptr noalias %p, i32 %c1, i32 %c2) { 734; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write) 735; TUNIT-LABEL: define {{[^@]+}}@test16_sub 736; TUNIT-SAME: (ptr noalias nofree writeonly [[P:%.*]], i32 [[C1:%.*]], i32 [[C2:%.*]]) #[[ATTR8]] { 737; TUNIT-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[C1]], 0 738; TUNIT-NEXT: br i1 [[TOBOOL]], label [[IF_END:%.*]], label [[IF_THEN:%.*]] 739; TUNIT: if.then: 740; TUNIT-NEXT: tail call void @only_store(ptr nofree noundef writeonly align 4 captures(none) [[P]]) #[[ATTR14]] 741; TUNIT-NEXT: tail call void @make_alias(ptr nofree writeonly align 4 [[P]]) #[[ATTR14]] 742; TUNIT-NEXT: br label [[IF_END]] 743; TUNIT: if.end: 744; TUNIT-NEXT: [[TOBOOL1:%.*]] = icmp eq i32 [[C2]], 0 745; TUNIT-NEXT: br i1 [[TOBOOL1]], label [[IF_THEN2:%.*]], label [[IF_END3:%.*]] 746; TUNIT: if.then2: 747; TUNIT-NEXT: tail call void @only_store(ptr nofree noundef writeonly align 4 captures(none) [[P]]) #[[ATTR14]] 748; TUNIT-NEXT: br label [[IF_END3]] 749; TUNIT: if.end3: 750; TUNIT-NEXT: ret void 751; 752; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(write) 753; CGSCC-LABEL: define {{[^@]+}}@test16_sub 754; CGSCC-SAME: (ptr noalias nofree writeonly [[P:%.*]], i32 [[C1:%.*]], i32 [[C2:%.*]]) #[[ATTR11]] { 755; CGSCC-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[C1]], 0 756; CGSCC-NEXT: br i1 [[TOBOOL]], label [[IF_END:%.*]], label [[IF_THEN:%.*]] 757; CGSCC: if.then: 758; CGSCC-NEXT: tail call void @only_store(ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[P]]) #[[ATTR15]] 759; CGSCC-NEXT: tail call void @make_alias(ptr nofree nonnull writeonly align 4 dereferenceable(4) [[P]]) #[[ATTR15]] 760; CGSCC-NEXT: br label [[IF_END]] 761; CGSCC: if.end: 762; CGSCC-NEXT: [[TOBOOL1:%.*]] = icmp eq i32 [[C2]], 0 763; CGSCC-NEXT: br i1 [[TOBOOL1]], label [[IF_THEN2:%.*]], label [[IF_END3:%.*]] 764; CGSCC: if.then2: 765; CGSCC-NEXT: tail call void @only_store(ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[P]]) #[[ATTR15]] 766; CGSCC-NEXT: br label [[IF_END3]] 767; CGSCC: if.end3: 768; CGSCC-NEXT: ret void 769; 770 %tobool = icmp eq i32 %c1, 0 771 br i1 %tobool, label %if.end, label %if.then 772 773if.then: 774 tail call void @only_store(ptr %p) 775 tail call void @make_alias(ptr %p) 776 br label %if.end 777if.end: 778 779 %tobool1 = icmp eq i32 %c2, 0 780 br i1 %tobool1, label %if.then2, label %if.end3 781 782if.then2: 783 tail call void @only_store(ptr %p) 784 br label %if.end3 785if.end3: 786 787 ret void 788} 789 790define void @test16_caller(ptr %p, i32 %c) { 791; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write) 792; TUNIT-LABEL: define {{[^@]+}}@test16_caller 793; TUNIT-SAME: (ptr nofree writeonly [[P:%.*]], i32 [[C:%.*]]) #[[ATTR8]] { 794; TUNIT-NEXT: tail call void @test16_sub(ptr nofree writeonly [[P]], i32 [[C]], i32 [[C]]) #[[ATTR14]] 795; TUNIT-NEXT: ret void 796; 797; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(write) 798; CGSCC-LABEL: define {{[^@]+}}@test16_caller 799; CGSCC-SAME: (ptr nofree writeonly [[P:%.*]], i32 [[C:%.*]]) #[[ATTR11]] { 800; CGSCC-NEXT: tail call void @test16_sub(ptr nofree writeonly [[P]], i32 [[C]], i32 [[C]]) #[[ATTR15]] 801; CGSCC-NEXT: ret void 802; 803 tail call void @test16_sub(ptr %p, i32 %c, i32 %c) 804 ret void 805} 806 807; test 17 808; 809; only_store is not called after make_alias is called. 810; 811; void test17_caller(int* p, int c) { 812; if(c) { 813; make_alias(p); 814; if(0 == 0) { 815; goto l3; 816; } else { 817; goto l2; 818; } 819; } 820; l2: 821; only_store(p); 822; l3: 823; return; 824; } 825 826define void @test17_caller(ptr noalias %p, i32 %c) { 827; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write) 828; TUNIT-LABEL: define {{[^@]+}}@test17_caller 829; TUNIT-SAME: (ptr noalias nofree writeonly [[P:%.*]], i32 [[C:%.*]]) #[[ATTR8]] { 830; TUNIT-NEXT: entry: 831; TUNIT-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[C]], 0 832; TUNIT-NEXT: br i1 [[TOBOOL]], label [[L1:%.*]], label [[L2:%.*]] 833; TUNIT: l1: 834; TUNIT-NEXT: tail call void @make_alias(ptr nofree writeonly [[P]]) #[[ATTR14]] 835; TUNIT-NEXT: br label [[L3:%.*]] 836; TUNIT: l2: 837; TUNIT-NEXT: tail call void @only_store(ptr noalias nofree noundef writeonly align 4 captures(none) [[P]]) #[[ATTR14]] 838; TUNIT-NEXT: br label [[L3]] 839; TUNIT: l3: 840; TUNIT-NEXT: ret void 841; 842; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(write) 843; CGSCC-LABEL: define {{[^@]+}}@test17_caller 844; CGSCC-SAME: (ptr noalias nofree writeonly [[P:%.*]], i32 [[C:%.*]]) #[[ATTR11]] { 845; CGSCC-NEXT: entry: 846; CGSCC-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[C]], 0 847; CGSCC-NEXT: br i1 [[TOBOOL]], label [[L1:%.*]], label [[L2:%.*]] 848; CGSCC: l1: 849; CGSCC-NEXT: tail call void @make_alias(ptr nofree writeonly [[P]]) #[[ATTR15]] 850; CGSCC-NEXT: br label [[L3:%.*]] 851; CGSCC: l2: 852; CGSCC-NEXT: tail call void @only_store(ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[P]]) #[[ATTR15]] 853; CGSCC-NEXT: br label [[L3]] 854; CGSCC: l3: 855; CGSCC-NEXT: ret void 856; 857entry: 858 %tobool = icmp eq i32 %c, 0 859 br i1 %tobool, label %l1, label %l2 860 861l1: 862 tail call void @make_alias(ptr %p) 863 %tobool2 = icmp eq i32 0, 0 864 br i1 %tobool2, label %l3, label %l2 865 866l2: 867 tail call void @only_store(ptr %p) 868 br label %l3 869 870l3: 871 ret void 872} 873 874; test 18 875; void test18_caller(int* p, int c) { 876; if(c) { 877; make_alias(p); 878; noreturn(); 879; } 880; only_store(p); 881; return; 882; } 883 884define void @noreturn() { 885; TUNIT: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none) 886; TUNIT-LABEL: define {{[^@]+}}@noreturn 887; TUNIT-SAME: () #[[ATTR10:[0-9]+]] { 888; TUNIT-NEXT: ret void 889; 890; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none) 891; CGSCC-LABEL: define {{[^@]+}}@noreturn 892; CGSCC-SAME: () #[[ATTR2]] { 893; CGSCC-NEXT: ret void 894; 895 call void @noreturn() 896 ret void 897} 898 899define void @test18_caller(ptr noalias %p, i32 %c) { 900; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write) 901; TUNIT-LABEL: define {{[^@]+}}@test18_caller 902; TUNIT-SAME: (ptr noalias nofree writeonly [[P:%.*]], i32 [[C:%.*]]) #[[ATTR8]] { 903; TUNIT-NEXT: entry: 904; TUNIT-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[C]], 0 905; TUNIT-NEXT: br i1 [[TOBOOL]], label [[L1:%.*]], label [[L2:%.*]] 906; TUNIT: l1: 907; TUNIT-NEXT: tail call void @make_alias(ptr nofree writeonly [[P]]) #[[ATTR14]] 908; TUNIT-NEXT: br label [[L2]] 909; TUNIT: l2: 910; TUNIT-NEXT: tail call void @only_store(ptr nofree noundef writeonly align 4 captures(none) [[P]]) #[[ATTR14]] 911; TUNIT-NEXT: ret void 912; 913; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(write) 914; CGSCC-LABEL: define {{[^@]+}}@test18_caller 915; CGSCC-SAME: (ptr noalias nofree nonnull writeonly align 4 dereferenceable(4) [[P:%.*]], i32 [[C:%.*]]) #[[ATTR11]] { 916; CGSCC-NEXT: entry: 917; CGSCC-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[C]], 0 918; CGSCC-NEXT: br i1 [[TOBOOL]], label [[L1:%.*]], label [[L2:%.*]] 919; CGSCC: l1: 920; CGSCC-NEXT: tail call void @make_alias(ptr nofree nonnull writeonly align 4 dereferenceable(4) [[P]]) #[[ATTR15]] 921; CGSCC-NEXT: br label [[L2]] 922; CGSCC: l2: 923; CGSCC-NEXT: tail call void @only_store(ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[P]]) #[[ATTR15]] 924; CGSCC-NEXT: ret void 925; 926entry: 927 %tobool = icmp eq i32 %c, 0 928 br i1 %tobool, label %l1, label %l2 929 930l1: 931 tail call void @make_alias(ptr %p) 932 tail call void @noreturn() 933 br label %l2 934 935l2: 936 tail call void @only_store(ptr %p) 937 ret void 938} 939;. 940; TUNIT: attributes #[[ATTR0]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) } 941; TUNIT: attributes #[[ATTR1]] = { nounwind uwtable } 942; TUNIT: attributes #[[ATTR2]] = { nounwind } 943; TUNIT: attributes #[[ATTR3]] = { nounwind ssp uwtable } 944; TUNIT: attributes #[[ATTR4]] = { memory(readwrite, argmem: none) } 945; TUNIT: attributes #[[ATTR5]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(read) } 946; TUNIT: attributes #[[ATTR6]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) } 947; TUNIT: attributes #[[ATTR7:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) } 948; TUNIT: attributes #[[ATTR8]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(write) } 949; TUNIT: attributes #[[ATTR9]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) } 950; TUNIT: attributes #[[ATTR10]] = { mustprogress nofree nosync nounwind willreturn memory(none) } 951; TUNIT: attributes #[[ATTR11]] = { nofree nosync nounwind willreturn memory(none) } 952; TUNIT: attributes #[[ATTR12]] = { nofree nosync nounwind willreturn memory(read) } 953; TUNIT: attributes #[[ATTR13]] = { nofree willreturn memory(readwrite) } 954; TUNIT: attributes #[[ATTR14]] = { nofree nosync nounwind willreturn memory(write) } 955;. 956; CGSCC: attributes #[[ATTR0]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) } 957; CGSCC: attributes #[[ATTR1]] = { nounwind uwtable } 958; CGSCC: attributes #[[ATTR2]] = { mustprogress nofree nosync nounwind willreturn memory(none) } 959; CGSCC: attributes #[[ATTR3]] = { nounwind } 960; CGSCC: attributes #[[ATTR4]] = { nounwind ssp uwtable } 961; CGSCC: attributes #[[ATTR5]] = { memory(readwrite, argmem: none) } 962; CGSCC: attributes #[[ATTR6]] = { mustprogress nofree nosync nounwind willreturn memory(read) } 963; CGSCC: attributes #[[ATTR7]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) } 964; CGSCC: attributes #[[ATTR8:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) } 965; CGSCC: attributes #[[ATTR9]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(write) } 966; CGSCC: attributes #[[ATTR10]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) } 967; CGSCC: attributes #[[ATTR11]] = { mustprogress nofree nosync nounwind willreturn memory(write) } 968; CGSCC: attributes #[[ATTR12]] = { nofree nosync willreturn } 969; CGSCC: attributes #[[ATTR13]] = { nofree willreturn memory(read) } 970; CGSCC: attributes #[[ATTR14]] = { nofree willreturn memory(readwrite) } 971; CGSCC: attributes #[[ATTR15]] = { nofree nounwind willreturn memory(write) } 972;. 973