754 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals2; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,TUNIT3; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,CGSCC4 5; FIXME: amdgpu doesn't claim malloc is a thing, so the test is somewhat6; useless except the __kmpc_alloc_shared part which now also covers the important7; part this test was initially designed for, make sure the "is freed" check is8; not sufficient on a GPU.9target triple = "amdgcn-amd-amdhsa"10target datalayout = "A5"11 12declare noalias ptr @malloc(i64)13 14declare void @nocapture_func_frees_pointer(ptr nocapture)15 16declare void @func_throws(...)17 18declare void @sync_func(ptr %p)19 20declare void @sync_will_return(ptr %p) willreturn nounwind21 22declare void @no_sync_func(ptr nocapture %p) nofree nosync willreturn23 24declare void @nofree_func(ptr nocapture %p) nofree nosync willreturn25 26declare void @usei8(ptr %p)27declare void @foo(ptr %p)28 29declare void @foo_nounw(ptr %p) nounwind nofree30 31declare i32 @no_return_call() noreturn32 33declare void @free(ptr nocapture)34 35declare void @llvm.lifetime.start.p0(ptr nocapture) nounwind36 37;.38; CHECK: @G = internal global ptr undef, align 439; CHECK: @Gtl = internal thread_local global ptr undef, align 440;.41define void @nofree_arg_only(ptr %p1, ptr %p2) {42; CHECK-LABEL: define {{[^@]+}}@nofree_arg_only43; CHECK-SAME: (ptr nofree captures(none) [[P1:%.*]], ptr captures(none) [[P2:%.*]]) {44; CHECK-NEXT: bb:45; CHECK-NEXT: tail call void @free(ptr captures(none) [[P2]])46; CHECK-NEXT: tail call void @nofree_func(ptr nofree captures(none) [[P1]])47; CHECK-NEXT: ret void48;49bb:50 tail call void @free(ptr %p2)51 tail call void @nofree_func(ptr %p1)52 ret void53}54 55; TEST 1 - negative, pointer freed in another function.56 57define void @test1() {58; CHECK-LABEL: define {{[^@]+}}@test1() {59; CHECK-NEXT: bb:60; CHECK-NEXT: [[I:%.*]] = tail call noalias ptr @malloc(i64 noundef 4)61; CHECK-NEXT: tail call void @nocapture_func_frees_pointer(ptr noalias captures(none) [[I]])62; CHECK-NEXT: tail call void (...) @func_throws()63; CHECK-NEXT: tail call void @free(ptr noalias captures(none) [[I]])64; CHECK-NEXT: ret void65;66bb:67 %i = tail call noalias ptr @malloc(i64 4)68 tail call void @nocapture_func_frees_pointer(ptr %i)69 tail call void (...) @func_throws()70 tail call void @free(ptr %i)71 ret void72}73 74; TEST 2 - negative, call to a sync function.75 76define void @test2() {77; CHECK-LABEL: define {{[^@]+}}@test2() {78; CHECK-NEXT: bb:79; CHECK-NEXT: [[I:%.*]] = tail call noalias ptr @malloc(i64 noundef 4)80; CHECK-NEXT: tail call void @sync_func(ptr [[I]])81; CHECK-NEXT: tail call void @free(ptr captures(none) [[I]])82; CHECK-NEXT: ret void83;84bb:85 %i = tail call noalias ptr @malloc(i64 4)86 tail call void @sync_func(ptr %i)87 tail call void @free(ptr %i)88 ret void89}90 91; TEST 3 - 1 malloc, 1 free92 93define void @test3() {94; CHECK-LABEL: define {{[^@]+}}@test3() {95; CHECK-NEXT: bb:96; CHECK-NEXT: [[I:%.*]] = tail call noalias ptr @malloc(i64 noundef 4)97; CHECK-NEXT: tail call void @no_sync_func(ptr noalias nofree captures(none) [[I]])98; CHECK-NEXT: tail call void @free(ptr noalias captures(none) [[I]])99; CHECK-NEXT: ret void100;101bb:102 %i = tail call noalias ptr @malloc(i64 4)103 tail call void @no_sync_func(ptr %i)104 tail call void @free(ptr %i)105 ret void106}107 108define void @test3a(ptr %p) {109; CHECK-LABEL: define {{[^@]+}}@test3a110; CHECK-SAME: (ptr captures(none) [[P:%.*]]) {111; CHECK-NEXT: bb:112; CHECK-NEXT: [[I:%.*]] = tail call noalias ptr @malloc(i64 noundef 4)113; CHECK-NEXT: tail call void @nofree_arg_only(ptr noalias nofree captures(none) [[I]], ptr captures(none) [[P]])114; CHECK-NEXT: tail call void @free(ptr noalias captures(none) [[I]])115; CHECK-NEXT: ret void116;117bb:118 %i = tail call noalias ptr @malloc(i64 4)119 tail call void @nofree_arg_only(ptr %i, ptr %p)120 tail call void @free(ptr %i)121 ret void122}123 124declare noalias ptr @aligned_alloc(i64, i64)125 126define void @test3b(ptr %p) {127; CHECK-LABEL: define {{[^@]+}}@test3b128; CHECK-SAME: (ptr captures(none) [[P:%.*]]) {129; CHECK-NEXT: bb:130; CHECK-NEXT: [[I:%.*]] = tail call noalias ptr @aligned_alloc(i64 noundef 32, i64 noundef 128)131; CHECK-NEXT: tail call void @nofree_arg_only(ptr noalias nofree captures(none) [[I]], ptr captures(none) [[P]])132; CHECK-NEXT: tail call void @free(ptr noalias captures(none) [[I]])133; CHECK-NEXT: ret void134;135bb:136 %i = tail call noalias ptr @aligned_alloc(i64 32, i64 128)137 tail call void @nofree_arg_only(ptr %i, ptr %p)138 tail call void @free(ptr %i)139 ret void140}141 142; leave alone non-constant alignments.143define void @test3c(i64 %alignment) {144; CHECK-LABEL: define {{[^@]+}}@test3c145; CHECK-SAME: (i64 [[ALIGNMENT:%.*]]) {146; CHECK-NEXT: bb:147; CHECK-NEXT: [[I:%.*]] = tail call noalias ptr @aligned_alloc(i64 [[ALIGNMENT]], i64 noundef 128)148; CHECK-NEXT: tail call void @free(ptr noalias captures(none) [[I]])149; CHECK-NEXT: ret void150;151bb:152 %i = tail call noalias ptr @aligned_alloc(i64 %alignment, i64 128)153 tail call void @free(ptr %i)154 ret void155}156 157declare noalias ptr @calloc(i64, i64)158 159define void @test0() {160; CHECK-LABEL: define {{[^@]+}}@test0() {161; CHECK-NEXT: bb:162; CHECK-NEXT: [[I:%.*]] = tail call noalias ptr @calloc(i64 noundef 2, i64 noundef 4)163; CHECK-NEXT: tail call void @no_sync_func(ptr noalias nofree captures(none) [[I]])164; CHECK-NEXT: tail call void @free(ptr noalias captures(none) [[I]])165; CHECK-NEXT: ret void166;167bb:168 %i = tail call noalias ptr @calloc(i64 2, i64 4)169 tail call void @no_sync_func(ptr %i)170 tail call void @free(ptr %i)171 ret void172}173 174; TEST 4175define void @test4() {176; CHECK-LABEL: define {{[^@]+}}@test4() {177; CHECK-NEXT: bb:178; CHECK-NEXT: [[I:%.*]] = tail call noalias ptr @malloc(i64 noundef 4)179; CHECK-NEXT: tail call void @nofree_func(ptr noalias nofree captures(none) [[I]])180; CHECK-NEXT: ret void181;182bb:183 %i = tail call noalias ptr @malloc(i64 4)184 tail call void @nofree_func(ptr %i)185 ret void186}187 188; TEST 5 - not all exit paths have a call to free, but all uses of malloc189; are in nofree functions and are not captured190 191define void @test5(i32 %arg, ptr %p) {192; CHECK-LABEL: define {{[^@]+}}@test5193; CHECK-SAME: (i32 [[ARG:%.*]], ptr captures(none) [[P:%.*]]) {194; CHECK-NEXT: bb:195; CHECK-NEXT: [[I:%.*]] = tail call noalias ptr @malloc(i64 noundef 4)196; CHECK-NEXT: [[I1:%.*]] = icmp eq i32 [[ARG]], 0197; CHECK-NEXT: br i1 [[I1]], label [[BB3:%.*]], label [[BB2:%.*]]198; CHECK: bb2:199; CHECK-NEXT: tail call void @nofree_func(ptr noalias nofree captures(none) [[I]])200; CHECK-NEXT: br label [[BB4:%.*]]201; CHECK: bb3:202; CHECK-NEXT: tail call void @nofree_arg_only(ptr noalias nofree captures(none) [[I]], ptr captures(none) [[P]])203; CHECK-NEXT: tail call void @free(ptr noalias captures(none) [[I]])204; CHECK-NEXT: br label [[BB4]]205; CHECK: bb4:206; CHECK-NEXT: ret void207;208bb:209 %i = tail call noalias ptr @malloc(i64 4)210 %i1 = icmp eq i32 %arg, 0211 br i1 %i1, label %bb3, label %bb2212 213bb2:214 tail call void @nofree_func(ptr %i)215 br label %bb4216 217bb3:218 tail call void @nofree_arg_only(ptr %i, ptr %p)219 tail call void @free(ptr %i)220 br label %bb4221 222bb4:223 ret void224}225 226; TEST 6 - all exit paths have a call to free227 228define void @test6(i32 %arg) {229; CHECK-LABEL: define {{[^@]+}}@test6230; CHECK-SAME: (i32 [[ARG:%.*]]) {231; CHECK-NEXT: bb:232; CHECK-NEXT: [[I:%.*]] = tail call noalias ptr @malloc(i64 noundef 4)233; CHECK-NEXT: [[I1:%.*]] = icmp eq i32 [[ARG]], 0234; CHECK-NEXT: br i1 [[I1]], label [[BB3:%.*]], label [[BB2:%.*]]235; CHECK: bb2:236; CHECK-NEXT: tail call void @nofree_func(ptr noalias nofree captures(none) [[I]])237; CHECK-NEXT: tail call void @free(ptr noalias captures(none) [[I]])238; CHECK-NEXT: br label [[BB4:%.*]]239; CHECK: bb3:240; CHECK-NEXT: tail call void @free(ptr noalias captures(none) [[I]])241; CHECK-NEXT: br label [[BB4]]242; CHECK: bb4:243; CHECK-NEXT: ret void244;245bb:246 %i = tail call noalias ptr @malloc(i64 4)247 %i1 = icmp eq i32 %arg, 0248 br i1 %i1, label %bb3, label %bb2249 250bb2:251 tail call void @nofree_func(ptr %i)252 tail call void @free(ptr %i)253 br label %bb4254 255bb3:256 tail call void @free(ptr %i)257 br label %bb4258 259bb4:260 ret void261}262 263; TEST 7 - free is dead.264 265define void @test7() {266; CHECK-LABEL: define {{[^@]+}}@test7() {267; CHECK-NEXT: bb:268; CHECK-NEXT: [[I:%.*]] = tail call noalias ptr @malloc(i64 noundef 4)269; CHECK-NEXT: [[I1:%.*]] = tail call i32 @no_return_call() #[[ATTR3:[0-9]+]]270; CHECK-NEXT: unreachable271;272bb:273 %i = tail call noalias ptr @malloc(i64 4)274 %i1 = tail call i32 @no_return_call()275 tail call void @free(ptr %i)276 ret void277}278 279; TEST 8 - Negative: bitcast pointer used in capture function280 281define void @test8() {282; CHECK-LABEL: define {{[^@]+}}@test8() {283; CHECK-NEXT: bb:284; CHECK-NEXT: [[I:%.*]] = tail call noalias ptr @malloc(i64 noundef 4)285; CHECK-NEXT: tail call void @no_sync_func(ptr nofree captures(none) [[I]])286; CHECK-NEXT: store i32 10, ptr [[I]], align 4287; CHECK-NEXT: tail call void @foo(ptr nonnull align 4 dereferenceable(4) [[I]])288; CHECK-NEXT: tail call void @free(ptr nonnull align 4 captures(none) dereferenceable(4) [[I]])289; CHECK-NEXT: ret void290;291bb:292 %i = tail call noalias ptr @malloc(i64 4)293 tail call void @no_sync_func(ptr %i)294 store i32 10, ptr %i, align 4295 %i2 = load i32, ptr %i, align 4296 tail call void @foo(ptr %i)297 tail call void @free(ptr %i)298 ret void299}300 301; TEST 9 - FIXME: malloc should be converted.302define void @test9() {303; CHECK-LABEL: define {{[^@]+}}@test9() {304; CHECK-NEXT: bb:305; CHECK-NEXT: [[I:%.*]] = tail call noalias ptr @malloc(i64 noundef 4)306; CHECK-NEXT: tail call void @no_sync_func(ptr nofree captures(none) [[I]])307; CHECK-NEXT: store i32 10, ptr [[I]], align 4308; CHECK-NEXT: tail call void @foo_nounw(ptr nofree nonnull align 4 dereferenceable(4) [[I]]) #[[ATTR6:[0-9]+]]309; CHECK-NEXT: tail call void @free(ptr nonnull align 4 captures(none) dereferenceable(4) [[I]])310; CHECK-NEXT: ret void311;312bb:313 %i = tail call noalias ptr @malloc(i64 4)314 tail call void @no_sync_func(ptr %i)315 store i32 10, ptr %i, align 4316 %i2 = load i32, ptr %i, align 4317 tail call void @foo_nounw(ptr %i)318 tail call void @free(ptr %i)319 ret void320}321 322; TEST 10 - 1 malloc, 1 free323 324define i32 @test10() {325; CHECK-LABEL: define {{[^@]+}}@test10() {326; CHECK-NEXT: bb:327; CHECK-NEXT: [[I:%.*]] = tail call noalias ptr @malloc(i64 noundef 4)328; CHECK-NEXT: tail call void @no_sync_func(ptr noalias nofree captures(none) [[I]])329; CHECK-NEXT: store i32 10, ptr [[I]], align 4330; CHECK-NEXT: [[I2:%.*]] = load i32, ptr [[I]], align 4331; CHECK-NEXT: tail call void @free(ptr noalias nonnull align 4 captures(none) dereferenceable(4) [[I]])332; CHECK-NEXT: ret i32 [[I2]]333;334bb:335 %i = tail call noalias ptr @malloc(i64 4)336 tail call void @no_sync_func(ptr %i)337 store i32 10, ptr %i, align 4338 %i2 = load i32, ptr %i, align 4339 tail call void @free(ptr %i)340 ret i32 %i2341}342 343; TEST 11344 345define void @test11() {346; CHECK-LABEL: define {{[^@]+}}@test11() {347; CHECK-NEXT: bb:348; CHECK-NEXT: [[I:%.*]] = tail call noalias ptr @malloc(i64 noundef 4)349; CHECK-NEXT: tail call void @sync_will_return(ptr [[I]]) #[[ATTR6]]350; CHECK-NEXT: tail call void @free(ptr captures(none) [[I]])351; CHECK-NEXT: ret void352;353bb:354 %i = tail call noalias ptr @malloc(i64 4)355 tail call void @sync_will_return(ptr %i)356 tail call void @free(ptr %i)357 ret void358}359 360; TEST 12361define i32 @irreducible_cfg(i32 %arg) {362; CHECK-LABEL: define {{[^@]+}}@irreducible_cfg363; CHECK-SAME: (i32 [[ARG:%.*]]) {364; CHECK-NEXT: bb:365; CHECK-NEXT: [[I:%.*]] = call noalias ptr @malloc(i64 noundef 4)366; CHECK-NEXT: store i32 10, ptr [[I]], align 4367; CHECK-NEXT: [[I2:%.*]] = icmp eq i32 [[ARG]], 1368; CHECK-NEXT: br i1 [[I2]], label [[BB3:%.*]], label [[BB5:%.*]]369; CHECK: bb3:370; CHECK-NEXT: [[I4:%.*]] = add nsw i32 [[ARG]], 5371; CHECK-NEXT: br label [[BB11:%.*]]372; CHECK: bb5:373; CHECK-NEXT: br label [[BB6:%.*]]374; CHECK: bb6:375; CHECK-NEXT: [[DOT0:%.*]] = phi i32 [ [[I12:%.*]], [[BB11]] ], [ 1, [[BB5]] ]376; CHECK-NEXT: [[I7:%.*]] = load i32, ptr [[I]], align 4377; CHECK-NEXT: [[I8:%.*]] = add nsw i32 [[I7]], -1378; CHECK-NEXT: store i32 [[I8]], ptr [[I]], align 4379; CHECK-NEXT: [[I9:%.*]] = icmp ne i32 [[I7]], 0380; CHECK-NEXT: br i1 [[I9]], label [[BB10:%.*]], label [[BB13:%.*]]381; CHECK: bb10:382; CHECK-NEXT: br label [[BB11]]383; CHECK: bb11:384; CHECK-NEXT: [[DOT1:%.*]] = phi i32 [ [[I4]], [[BB3]] ], [ [[DOT0]], [[BB10]] ]385; CHECK-NEXT: [[I12]] = add nsw i32 [[DOT1]], 1386; CHECK-NEXT: br label [[BB6]]387; CHECK: bb13:388; CHECK-NEXT: call void @free(ptr noalias noundef nonnull align 4 captures(none) dereferenceable(4) [[I]])389; CHECK-NEXT: [[I16:%.*]] = load i32, ptr [[I]], align 4390; CHECK-NEXT: ret i32 [[I16]]391;392bb:393 %i = call noalias ptr @malloc(i64 4)394 store i32 10, ptr %i, align 4395 %i2 = icmp eq i32 %arg, 1396 br i1 %i2, label %bb3, label %bb5397 398bb3:399 %i4 = add nsw i32 %arg, 5400 br label %bb11401 402bb5:403 br label %bb6404 405bb6:406 %.0 = phi i32 [ %i12, %bb11 ], [ 1, %bb5 ]407 %i7 = load i32, ptr %i, align 4408 %i8 = add nsw i32 %i7, -1409 store i32 %i8, ptr %i, align 4410 %i9 = icmp ne i32 %i7, 0411 br i1 %i9, label %bb10, label %bb13412 413bb10:414 br label %bb11415 416bb11:417 %.1 = phi i32 [ %i4, %bb3 ], [ %.0, %bb10 ]418 %i12 = add nsw i32 %.1, 1419 br label %bb6420 421bb13:422 %i14 = load i32, ptr %i, align 4423 call void @free(ptr %i)424 %i16 = load i32, ptr %i, align 4425 ret i32 %i16426}427 428 429define i32 @malloc_in_loop(i32 %arg) {430; CHECK-LABEL: define {{[^@]+}}@malloc_in_loop431; CHECK-SAME: (i32 [[ARG:%.*]]) {432; CHECK-NEXT: bb:433; CHECK-NEXT: [[I:%.*]] = alloca i32, align 4, addrspace(5)434; CHECK-NEXT: [[I1:%.*]] = alloca ptr, align 8, addrspace(5)435; CHECK-NEXT: [[I11:%.*]] = alloca i8, i32 0, align 8, addrspace(5)436; CHECK-NEXT: store i32 [[ARG]], ptr addrspace(5) [[I]], align 4437; CHECK-NEXT: br label [[BB2:%.*]]438; CHECK: bb2:439; CHECK-NEXT: [[I3:%.*]] = load i32, ptr addrspace(5) [[I]], align 4440; CHECK-NEXT: [[I4:%.*]] = add nsw i32 [[I3]], -1441; CHECK-NEXT: store i32 [[I4]], ptr addrspace(5) [[I]], align 4442; CHECK-NEXT: [[I5:%.*]] = icmp sgt i32 [[I4]], 0443; CHECK-NEXT: br i1 [[I5]], label [[BB6:%.*]], label [[BB9:%.*]]444; CHECK: bb6:445; CHECK-NEXT: [[I7:%.*]] = call noalias ptr @malloc(i64 noundef 4)446; CHECK-NEXT: br label [[BB2]]447; CHECK: bb9:448; CHECK-NEXT: ret i32 5449;450bb:451 %i = alloca i32, align 4, addrspace(5)452 %i1 = alloca ptr, align 8, addrspace(5)453 store i32 %arg, ptr addrspace(5) %i, align 4454 br label %bb2455 456bb2:457 %i3 = load i32, ptr addrspace(5) %i, align 4458 %i4 = add nsw i32 %i3, -1459 store i32 %i4, ptr addrspace(5) %i, align 4460 %i5 = icmp sgt i32 %i4, 0461 br i1 %i5, label %bb6, label %bb9462 463bb6:464 %i7 = call noalias ptr @malloc(i64 4)465 store i32 1, ptr %i7, align 8466 br label %bb2467 468bb9:469 ret i32 5470}471 472; Malloc/Calloc too large473define i32 @test13() {474; CHECK-LABEL: define {{[^@]+}}@test13() {475; CHECK-NEXT: bb:476; CHECK-NEXT: [[I:%.*]] = tail call noalias ptr @malloc(i64 noundef 256)477; CHECK-NEXT: tail call void @no_sync_func(ptr noalias nofree captures(none) [[I]])478; CHECK-NEXT: store i32 10, ptr [[I]], align 4479; CHECK-NEXT: [[I2:%.*]] = load i32, ptr [[I]], align 4480; CHECK-NEXT: tail call void @free(ptr noalias nonnull align 4 captures(none) dereferenceable(4) [[I]])481; CHECK-NEXT: ret i32 [[I2]]482;483bb:484 %i = tail call noalias ptr @malloc(i64 256)485 tail call void @no_sync_func(ptr %i)486 store i32 10, ptr %i, align 4487 %i2 = load i32, ptr %i, align 4488 tail call void @free(ptr %i)489 ret i32 %i2490}491 492define i32 @test_sle() {493; CHECK-LABEL: define {{[^@]+}}@test_sle() {494; CHECK-NEXT: bb:495; CHECK-NEXT: [[I:%.*]] = tail call noalias ptr @malloc(i64 noundef -1)496; CHECK-NEXT: tail call void @no_sync_func(ptr noalias nofree captures(none) [[I]])497; CHECK-NEXT: store i32 10, ptr [[I]], align 4498; CHECK-NEXT: [[I2:%.*]] = load i32, ptr [[I]], align 4499; CHECK-NEXT: tail call void @free(ptr noalias nonnull align 4 captures(none) dereferenceable(4) [[I]])500; CHECK-NEXT: ret i32 [[I2]]501;502bb:503 %i = tail call noalias ptr @malloc(i64 -1)504 tail call void @no_sync_func(ptr %i)505 store i32 10, ptr %i, align 4506 %i2 = load i32, ptr %i, align 4507 tail call void @free(ptr %i)508 ret i32 %i2509}510 511define i32 @test_overflow() {512; CHECK-LABEL: define {{[^@]+}}@test_overflow() {513; CHECK-NEXT: bb:514; CHECK-NEXT: [[I:%.*]] = tail call noalias ptr @calloc(i64 noundef 65537, i64 noundef 65537)515; CHECK-NEXT: tail call void @no_sync_func(ptr noalias nofree captures(none) [[I]])516; CHECK-NEXT: store i32 10, ptr [[I]], align 4517; CHECK-NEXT: [[I2:%.*]] = load i32, ptr [[I]], align 4518; CHECK-NEXT: tail call void @free(ptr noalias nonnull align 4 captures(none) dereferenceable(4) [[I]])519; CHECK-NEXT: ret i32 [[I2]]520;521bb:522 %i = tail call noalias ptr @calloc(i64 65537, i64 65537)523 tail call void @no_sync_func(ptr %i)524 store i32 10, ptr %i, align 4525 %i2 = load i32, ptr %i, align 4526 tail call void @free(ptr %i)527 ret i32 %i2528}529 530define void @test14() {531; CHECK-LABEL: define {{[^@]+}}@test14() {532; CHECK-NEXT: bb:533; CHECK-NEXT: [[I:%.*]] = tail call noalias ptr @calloc(i64 noundef 64, i64 noundef 4)534; CHECK-NEXT: tail call void @no_sync_func(ptr noalias nofree captures(none) [[I]])535; CHECK-NEXT: tail call void @free(ptr noalias captures(none) [[I]])536; CHECK-NEXT: ret void537;538bb:539 %i = tail call noalias ptr @calloc(i64 64, i64 4)540 tail call void @no_sync_func(ptr %i)541 tail call void @free(ptr %i)542 ret void543}544 545define void @test15(i64 %S) {546; CHECK-LABEL: define {{[^@]+}}@test15547; CHECK-SAME: (i64 [[S:%.*]]) {548; CHECK-NEXT: bb:549; CHECK-NEXT: [[I:%.*]] = tail call noalias ptr @malloc(i64 [[S]])550; CHECK-NEXT: tail call void @no_sync_func(ptr noalias nofree captures(none) [[I]])551; CHECK-NEXT: tail call void @free(ptr noalias captures(none) [[I]])552; CHECK-NEXT: ret void553;554bb:555 %i = tail call noalias ptr @malloc(i64 %S)556 tail call void @no_sync_func(ptr %i)557 tail call void @free(ptr %i)558 ret void559}560 561define void @test16a(i8 %v, ptr %P) {562; CHECK-LABEL: define {{[^@]+}}@test16a563; CHECK-SAME: (i8 [[V:%.*]], ptr nofree readnone captures(none) [[P:%.*]]) {564; CHECK-NEXT: bb:565; CHECK-NEXT: [[I:%.*]] = tail call noalias ptr @malloc(i64 noundef 4)566; CHECK-NEXT: store i8 [[V]], ptr [[I]], align 1567; CHECK-NEXT: tail call void @no_sync_func(ptr noalias nofree noundef nonnull captures(none) dereferenceable(1) [[I]])568; CHECK-NEXT: tail call void @free(ptr noalias noundef nonnull captures(none) dereferenceable(1) [[I]])569; CHECK-NEXT: ret void570;571bb:572 %i = tail call noalias ptr @malloc(i64 4)573 store i8 %v, ptr %i, align 1574 tail call void @no_sync_func(ptr %i)575 tail call void @free(ptr nonnull dereferenceable(1) %i)576 ret void577}578 579define void @test16b(i8 %v, ptr %P) {580; CHECK-LABEL: define {{[^@]+}}@test16b581; CHECK-SAME: (i8 [[V:%.*]], ptr nofree writeonly captures(none) [[P:%.*]]) {582; CHECK-NEXT: bb:583; CHECK-NEXT: [[I:%.*]] = tail call noalias ptr @malloc(i64 noundef 4)584; CHECK-NEXT: store ptr [[I]], ptr [[P]], align 8585; CHECK-NEXT: tail call void @no_sync_func(ptr nofree captures(none) [[I]])586; CHECK-NEXT: tail call void @free(ptr captures(none) [[I]])587; CHECK-NEXT: ret void588;589bb:590 %i = tail call noalias ptr @malloc(i64 4)591 store ptr %i, ptr %P, align 8592 tail call void @no_sync_func(ptr %i)593 tail call void @free(ptr %i)594 ret void595}596 597define void @test16c(i8 %v, ptr %P) {598; CHECK-LABEL: define {{[^@]+}}@test16c599; CHECK-SAME: (i8 [[V:%.*]], ptr nofree writeonly captures(none) [[P:%.*]]) {600; CHECK-NEXT: bb:601; CHECK-NEXT: [[I:%.*]] = tail call noalias ptr @malloc(i64 noundef 4)602; CHECK-NEXT: store ptr [[I]], ptr [[P]], align 8603; CHECK-NEXT: tail call void @no_sync_func(ptr nofree captures(none) [[I]]) #[[ATTR6]]604; CHECK-NEXT: tail call void @free(ptr captures(none) [[I]])605; CHECK-NEXT: ret void606;607bb:608 %i = tail call noalias ptr @malloc(i64 4)609 store ptr %i, ptr %P, align 8610 tail call void @no_sync_func(ptr %i) nounwind611 tail call void @free(ptr %i)612 ret void613}614 615define void @test16d(i8 %v, ptr %P) {616; CHECK-LABEL: define {{[^@]+}}@test16d617; CHECK-SAME: (i8 [[V:%.*]], ptr nofree writeonly captures(none) [[P:%.*]]) {618; CHECK-NEXT: bb:619; CHECK-NEXT: [[I:%.*]] = tail call noalias ptr @malloc(i64 noundef 4)620; CHECK-NEXT: store ptr [[I]], ptr [[P]], align 8621; CHECK-NEXT: ret void622;623bb:624 %i = tail call noalias ptr @malloc(i64 4)625 store ptr %i, ptr %P, align 8626 ret void627}628 629declare ptr @__kmpc_alloc_shared(i64)630declare void @__kmpc_free_shared(ptr nocapture, i64)631 632define void @test17() {633; CHECK-LABEL: define {{[^@]+}}@test17() {634; CHECK-NEXT: bb:635; CHECK-NEXT: [[I_H2S:%.*]] = alloca i8, i64 4, align 1, addrspace(5)636; CHECK-NEXT: [[MALLOC_CAST:%.*]] = addrspacecast ptr addrspace(5) [[I_H2S]] to ptr637; CHECK-NEXT: tail call void @usei8(ptr noalias nofree captures(none) [[MALLOC_CAST]]) #[[ATTR7:[0-9]+]]638; CHECK-NEXT: ret void639;640bb:641 %i = tail call noalias ptr @__kmpc_alloc_shared(i64 4)642 tail call void @usei8(ptr nocapture nofree %i) nosync nounwind willreturn643 tail call void @__kmpc_free_shared(ptr %i, i64 4)644 ret void645}646 647define void @test17b() {648; CHECK-LABEL: define {{[^@]+}}@test17b() {649; CHECK-NEXT: bb:650; CHECK-NEXT: [[I:%.*]] = tail call noalias ptr @__kmpc_alloc_shared(i64 noundef 4)651; CHECK-NEXT: tail call void @usei8(ptr nofree [[I]]) #[[ATTR7]]652; CHECK-NEXT: tail call void @__kmpc_free_shared(ptr captures(none) [[I]], i64 noundef 4)653; CHECK-NEXT: ret void654;655bb:656 %i = tail call noalias ptr @__kmpc_alloc_shared(i64 4)657 tail call void @usei8(ptr nofree %i) nosync nounwind willreturn658 tail call void @__kmpc_free_shared(ptr %i, i64 4)659 ret void660}661 662define void @move_alloca() {663; CHECK-LABEL: define {{[^@]+}}@move_alloca() {664; CHECK-NEXT: entry:665; CHECK-NEXT: [[I_H2S:%.*]] = alloca i8, i64 4, align 1, addrspace(5)666; CHECK-NEXT: br label [[NOT_ENTRY:%.*]]667; CHECK: not_entry:668; CHECK-NEXT: [[MALLOC_CAST:%.*]] = addrspacecast ptr addrspace(5) [[I_H2S]] to ptr669; CHECK-NEXT: tail call void @usei8(ptr noalias nofree captures(none) [[MALLOC_CAST]]) #[[ATTR7]]670; CHECK-NEXT: ret void671;672entry:673 br label %not_entry674 675not_entry:676 %i = tail call noalias ptr @__kmpc_alloc_shared(i64 4)677 tail call void @usei8(ptr nocapture nofree %i) nosync nounwind willreturn678 tail call void @__kmpc_free_shared(ptr %i, i64 4)679 ret void680}681 682@G = internal global ptr undef, align 4683define void @test16e(i8 %v) norecurse {684; CHECK: Function Attrs: norecurse685; CHECK-LABEL: define {{[^@]+}}@test16e686; CHECK-SAME: (i8 [[V:%.*]]) #[[ATTR5:[0-9]+]] {687; CHECK-NEXT: bb:688; CHECK-NEXT: [[I:%.*]] = tail call noalias ptr @__kmpc_alloc_shared(i64 noundef 4)689; CHECK-NEXT: store ptr [[I]], ptr @G, align 8690; CHECK-NEXT: call void @usei8(ptr nofree captures(none) [[I]]) #[[ATTR8:[0-9]+]]691; CHECK-NEXT: tail call void @__kmpc_free_shared(ptr noalias captures(none) [[I]], i64 noundef 4)692; CHECK-NEXT: ret void693;694bb:695 %i = tail call noalias ptr @__kmpc_alloc_shared(i64 4)696 store ptr %i, ptr @G, align 8697 %i1 = load ptr, ptr @G, align 8698 call void @usei8(ptr nocapture nofree %i1) nocallback nosync nounwind willreturn699 tail call void @__kmpc_free_shared(ptr %i, i64 4)700 ret void701}702 703@Gtl = internal thread_local global ptr undef, align 4704define void @test16f(i8 %v) norecurse {705; CHECK: Function Attrs: norecurse706; CHECK-LABEL: define {{[^@]+}}@test16f707; CHECK-SAME: (i8 [[V:%.*]]) #[[ATTR5]] {708; CHECK-NEXT: bb:709; CHECK-NEXT: [[I_H2S:%.*]] = alloca i8, i64 4, align 1, addrspace(5)710; CHECK-NEXT: [[MALLOC_CAST:%.*]] = addrspacecast ptr addrspace(5) [[I_H2S]] to ptr711; CHECK-NEXT: store ptr [[MALLOC_CAST]], ptr @Gtl, align 8712; CHECK-NEXT: call void @usei8(ptr nofree captures(none) [[MALLOC_CAST]]) #[[ATTR8]]713; CHECK-NEXT: ret void714;715bb:716 %i = tail call noalias ptr @__kmpc_alloc_shared(i64 4)717 store ptr %i, ptr @Gtl, align 8718 %i1 = load ptr, ptr @Gtl, align 8719 call void @usei8(ptr nocapture nofree %i1) nocallback nosync nounwind willreturn720 tail call void @__kmpc_free_shared(ptr %i, i64 4)721 ret void722}723 724define void @convert_large_kmpc_alloc_shared() {725; CHECK-LABEL: define {{[^@]+}}@convert_large_kmpc_alloc_shared() {726; CHECK-NEXT: bb:727; CHECK-NEXT: [[I_H2S:%.*]] = alloca i8, i64 256, align 1, addrspace(5)728; CHECK-NEXT: [[MALLOC_CAST:%.*]] = addrspacecast ptr addrspace(5) [[I_H2S]] to ptr729; CHECK-NEXT: tail call void @usei8(ptr noalias nofree captures(none) [[MALLOC_CAST]]) #[[ATTR7]]730; CHECK-NEXT: ret void731;732bb:733 %i = tail call noalias ptr @__kmpc_alloc_shared(i64 256)734 tail call void @usei8(ptr nocapture nofree %i) nosync nounwind willreturn735 tail call void @__kmpc_free_shared(ptr %i, i64 256)736 ret void737}738 739 740;.741; CHECK: attributes #[[ATTR0:[0-9]+]] = { nounwind willreturn }742; CHECK: attributes #[[ATTR1:[0-9]+]] = { nofree nosync willreturn }743; CHECK: attributes #[[ATTR2:[0-9]+]] = { nofree nounwind }744; CHECK: attributes #[[ATTR3]] = { noreturn }745; CHECK: attributes #[[ATTR4:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }746; CHECK: attributes #[[ATTR5]] = { norecurse }747; CHECK: attributes #[[ATTR6]] = { nounwind }748; CHECK: attributes #[[ATTR7]] = { nosync nounwind willreturn }749; CHECK: attributes #[[ATTR8]] = { nocallback nosync nounwind willreturn }750;.751;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:752; CGSCC: {{.*}}753; TUNIT: {{.*}}754