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