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