1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes 2; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=4 -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-disable=false -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=4 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM 4; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-disable=false -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM 5; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-disable=false -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 6 7target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" 8declare void @f(i32) 9 10; Test1: Replace argument with constant 11define internal void @test1(i32 %a) { 12; CHECK-LABEL: define {{[^@]+}}@test1() 13; CHECK-NEXT: tail call void @f(i32 1) 14; CHECK-NEXT: ret void 15; 16 tail call void @f(i32 %a) 17 ret void 18} 19 20define void @test1_helper() { 21; CHECK-LABEL: define {{[^@]+}}@test1_helper() 22; CHECK-NEXT: tail call void @test1() 23; CHECK-NEXT: ret void 24; 25 tail call void @test1(i32 1) 26 ret void 27} 28 29; TEST 2 : Simplify return value 30define i32 @return0() { 31; CHECK-LABEL: define {{[^@]+}}@return0() 32; CHECK-NEXT: ret i32 0 33; 34 ret i32 0 35} 36 37define i32 @return1() { 38; CHECK-LABEL: define {{[^@]+}}@return1() 39; CHECK-NEXT: ret i32 1 40; 41 ret i32 1 42} 43 44define i32 @test2_1(i1 %c) { 45; CHECK-LABEL: define {{[^@]+}}@test2_1 46; CHECK-SAME: (i1 [[C:%.*]]) 47; CHECK-NEXT: br i1 [[C]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]] 48; CHECK: if.true: 49; CHECK-NEXT: [[RET0:%.*]] = add i32 0, 1 50; CHECK-NEXT: br label [[END:%.*]] 51; CHECK: if.false: 52; CHECK-NEXT: br label [[END]] 53; CHECK: end: 54; CHECK-NEXT: [[RET:%.*]] = phi i32 [ [[RET0]], [[IF_TRUE]] ], [ 1, [[IF_FALSE]] ] 55; CHECK-NEXT: ret i32 1 56; 57 br i1 %c, label %if.true, label %if.false 58if.true: 59 %call = tail call i32 @return0() 60 %ret0 = add i32 %call, 1 61 br label %end 62if.false: 63 %ret1 = tail call i32 @return1() 64 br label %end 65end: 66 67 %ret = phi i32 [ %ret0, %if.true ], [ %ret1, %if.false ] 68 69 ret i32 1 70} 71 72 73 74define i32 @test2_2(i1 %c) { 75; CHECK-LABEL: define {{[^@]+}}@test2_2 76; CHECK-SAME: (i1 [[C:%.*]]) 77; CHECK-NEXT: ret i32 1 78; 79 %ret = tail call i32 @test2_1(i1 %c) 80 ret i32 %ret 81} 82 83declare void @use(i32) 84define void @test3(i1 %c) { 85; CHECK-LABEL: define {{[^@]+}}@test3 86; CHECK-SAME: (i1 [[C:%.*]]) 87; CHECK-NEXT: br i1 [[C]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]] 88; CHECK: if.true: 89; CHECK-NEXT: br label [[END:%.*]] 90; CHECK: if.false: 91; CHECK-NEXT: br label [[END]] 92; CHECK: end: 93; CHECK-NEXT: [[R:%.*]] = phi i32 [ 1, [[IF_TRUE]] ], [ 1, [[IF_FALSE]] ] 94; CHECK-NEXT: tail call void @use(i32 1) 95; CHECK-NEXT: ret void 96; 97 br i1 %c, label %if.true, label %if.false 98if.true: 99 br label %end 100if.false: 101 %ret1 = tail call i32 @return1() 102 br label %end 103end: 104 105 %r = phi i32 [ 1, %if.true ], [ %ret1, %if.false ] 106 107 tail call void @use(i32 %r) 108 ret void 109} 110 111define void @test-select-phi(i1 %c) { 112; CHECK-LABEL: define {{[^@]+}}@test-select-phi 113; CHECK-SAME: (i1 [[C:%.*]]) 114; CHECK-NEXT: tail call void @use(i32 1) 115; CHECK-NEXT: [[SELECT_NOT_SAME:%.*]] = select i1 [[C]], i32 1, i32 0 116; CHECK-NEXT: tail call void @use(i32 [[SELECT_NOT_SAME]]) 117; CHECK-NEXT: br i1 [[C]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]] 118; CHECK: if-true: 119; CHECK-NEXT: br label [[END:%.*]] 120; CHECK: if-false: 121; CHECK-NEXT: br label [[END]] 122; CHECK: end: 123; CHECK-NEXT: [[PHI_SAME:%.*]] = phi i32 [ 1, [[IF_TRUE]] ], [ 1, [[IF_FALSE]] ] 124; CHECK-NEXT: [[PHI_NOT_SAME:%.*]] = phi i32 [ 0, [[IF_TRUE]] ], [ 1, [[IF_FALSE]] ] 125; CHECK-NEXT: [[PHI_SAME_PROP:%.*]] = phi i32 [ 1, [[IF_TRUE]] ], [ 1, [[IF_FALSE]] ] 126; CHECK-NEXT: [[PHI_SAME_UNDEF:%.*]] = phi i32 [ 1, [[IF_TRUE]] ], [ undef, [[IF_FALSE]] ] 127; CHECK-NEXT: [[SELECT_NOT_SAME_UNDEF:%.*]] = select i1 [[C]], i32 [[PHI_NOT_SAME]], i32 undef 128; CHECK-NEXT: tail call void @use(i32 1) 129; CHECK-NEXT: tail call void @use(i32 [[PHI_NOT_SAME]]) 130; CHECK-NEXT: tail call void @use(i32 1) 131; CHECK-NEXT: tail call void @use(i32 1) 132; CHECK-NEXT: tail call void @use(i32 [[SELECT_NOT_SAME_UNDEF]]) 133; CHECK-NEXT: ret void 134; 135 %select-same = select i1 %c, i32 1, i32 1 136 tail call void @use(i32 %select-same) 137 138 %select-not-same = select i1 %c, i32 1, i32 0 139 tail call void @use(i32 %select-not-same) 140 br i1 %c, label %if-true, label %if-false 141if-true: 142 br label %end 143if-false: 144 br label %end 145end: 146 %phi-same = phi i32 [ 1, %if-true ], [ 1, %if-false ] 147 %phi-not-same = phi i32 [ 0, %if-true ], [ 1, %if-false ] 148 %phi-same-prop = phi i32 [ 1, %if-true ], [ %select-same, %if-false ] 149 %phi-same-undef = phi i32 [ 1, %if-true ], [ undef, %if-false ] 150 %select-not-same-undef = select i1 %c, i32 %phi-not-same, i32 undef 151 152 153 tail call void @use(i32 %phi-same) 154 155 tail call void @use(i32 %phi-not-same) 156 157 tail call void @use(i32 %phi-same-prop) 158 159 tail call void @use(i32 %phi-same-undef) 160 161 tail call void @use(i32 %select-not-same-undef) 162 163 ret void 164 165} 166 167define i32 @ipccp1(i32 %a) { 168; CHECK-LABEL: define {{[^@]+}}@ipccp1 169; CHECK-SAME: (i32 returned [[A:%.*]]) 170; CHECK-NEXT: br i1 true, label [[T:%.*]], label [[F:%.*]] 171; CHECK: t: 172; CHECK-NEXT: ret i32 [[A]] 173; CHECK: f: 174; CHECK-NEXT: unreachable 175; 176 br i1 true, label %t, label %f 177t: 178 ret i32 %a 179f: 180 %r = call i32 @ipccp1(i32 5) 181 ret i32 %r 182} 183 184define internal i1 @ipccp2i(i1 %a) { 185; IS__CGSCC____-LABEL: define {{[^@]+}}@ipccp2i() 186; IS__CGSCC____-NEXT: br label [[T:%.*]] 187; IS__CGSCC____: t: 188; IS__CGSCC____-NEXT: ret i1 true 189; IS__CGSCC____: f: 190; IS__CGSCC____-NEXT: unreachable 191; 192 br i1 %a, label %t, label %f 193t: 194 ret i1 %a 195f: 196 %r = call i1 @ipccp2i(i1 false) 197 ret i1 %r 198} 199 200define i1 @ipccp2() { 201; IS__TUNIT____-LABEL: define {{[^@]+}}@ipccp2() 202; IS__TUNIT____-NEXT: ret i1 true 203; 204; IS__CGSCC____-LABEL: define {{[^@]+}}@ipccp2() 205; IS__CGSCC____-NEXT: [[R:%.*]] = call i1 @ipccp2i() 206; IS__CGSCC____-NEXT: ret i1 [[R]] 207; 208 %r = call i1 @ipccp2i(i1 true) 209 ret i1 %r 210} 211 212define internal i1 @ipccp2ib(i1 %a) { 213; IS__CGSCC____-LABEL: define {{[^@]+}}@ipccp2ib() 214; IS__CGSCC____-NEXT: br label [[T:%.*]] 215; IS__CGSCC____: t: 216; IS__CGSCC____-NEXT: ret i1 true 217; IS__CGSCC____: f: 218; IS__CGSCC____-NEXT: unreachable 219; 220 br i1 %a, label %t, label %f 221t: 222 ret i1 true 223f: 224 %r = call i1 @ipccp2ib(i1 false) 225 ret i1 %r 226} 227 228define i1 @ipccp2b() { 229; CHECK-LABEL: define {{[^@]+}}@ipccp2b() 230; CHECK-NEXT: ret i1 true 231; 232 %r = call i1 @ipccp2ib(i1 true) 233 ret i1 %r 234} 235 236define internal i32 @ipccp3i(i32 %a) { 237; IS__CGSCC____-LABEL: define {{[^@]+}}@ipccp3i() 238; IS__CGSCC____-NEXT: br label [[T:%.*]] 239; IS__CGSCC____: t: 240; IS__CGSCC____-NEXT: ret i32 7 241; IS__CGSCC____: f: 242; IS__CGSCC____-NEXT: unreachable 243; 244 %c = icmp eq i32 %a, 7 245 br i1 %c, label %t, label %f 246t: 247 ret i32 %a 248f: 249 %r = call i32 @ipccp3i(i32 5) 250 ret i32 %r 251} 252 253define i32 @ipccp3() { 254; IS__TUNIT____-LABEL: define {{[^@]+}}@ipccp3() 255; IS__TUNIT____-NEXT: ret i32 7 256; 257; IS__CGSCC____-LABEL: define {{[^@]+}}@ipccp3() 258; IS__CGSCC____-NEXT: [[R:%.*]] = call i32 @ipccp3i() 259; IS__CGSCC____-NEXT: ret i32 [[R]] 260; 261 %r = call i32 @ipccp3i(i32 7) 262 ret i32 %r 263} 264 265; Do not touch complicated arguments (for now) 266%struct.X = type { i8* } 267define internal i32* @test_inalloca(i32* inalloca %a) { 268; IS__TUNIT____-LABEL: define {{[^@]+}}@test_inalloca 269; IS__TUNIT____-SAME: (i32* inalloca noalias nofree returned writeonly align 536870912 "no-capture-maybe-returned" [[A:%.*]]) 270; IS__TUNIT____-NEXT: ret i32* [[A]] 271; 272; IS__CGSCC____-LABEL: define {{[^@]+}}@test_inalloca 273; IS__CGSCC____-SAME: (i32* inalloca noalias nofree returned writeonly "no-capture-maybe-returned" [[A:%.*]]) 274; IS__CGSCC____-NEXT: ret i32* [[A]] 275; 276 ret i32* %a 277} 278define i32* @complicated_args_inalloca() { 279; CHECK-LABEL: define {{[^@]+}}@complicated_args_inalloca() 280; CHECK-NEXT: [[CALL:%.*]] = call i32* @test_inalloca(i32* noalias nofree writeonly align 536870912 null) 281; CHECK-NEXT: ret i32* [[CALL]] 282; 283 %call = call i32* @test_inalloca(i32* null) 284 ret i32* %call 285} 286 287define internal void @test_sret(%struct.X* sret %a, %struct.X** %b) { 288; 289; IS__TUNIT____-LABEL: define {{[^@]+}}@test_sret 290; IS__TUNIT____-SAME: (%struct.X* noalias nofree sret writeonly align 536870912 [[A:%.*]], %struct.X** nocapture nofree nonnull writeonly align 8 dereferenceable(8) [[B:%.*]]) 291; IS__TUNIT____-NEXT: store %struct.X* [[A]], %struct.X** [[B]], align 8 292; IS__TUNIT____-NEXT: ret void 293; 294; IS__CGSCC____-LABEL: define {{[^@]+}}@test_sret 295; IS__CGSCC____-SAME: (%struct.X* noalias nofree sret writeonly [[A:%.*]], %struct.X** nocapture nofree nonnull writeonly align 8 dereferenceable(8) [[B:%.*]]) 296; IS__CGSCC____-NEXT: store %struct.X* [[A]], %struct.X** [[B]], align 8 297; IS__CGSCC____-NEXT: ret void 298; 299 store %struct.X* %a, %struct.X** %b 300 ret void 301} 302; FIXME: Alignment and dereferenceability are not propagated to the argument 303define void @complicated_args_sret(%struct.X** %b) { 304; 305; IS__TUNIT____-LABEL: define {{[^@]+}}@complicated_args_sret 306; IS__TUNIT____-SAME: (%struct.X** nocapture nofree writeonly [[B:%.*]]) 307; IS__TUNIT____-NEXT: call void @test_sret(%struct.X* noalias nofree writeonly align 536870912 null, %struct.X** nocapture nofree writeonly align 8 [[B]]) 308; IS__TUNIT____-NEXT: ret void 309; 310; IS__CGSCC____-LABEL: define {{[^@]+}}@complicated_args_sret 311; IS__CGSCC____-SAME: (%struct.X** nocapture nofree nonnull writeonly align 8 dereferenceable(8) [[B:%.*]]) 312; IS__CGSCC____-NEXT: call void @test_sret(%struct.X* noalias nofree writeonly align 536870912 null, %struct.X** nocapture nofree nonnull writeonly align 8 dereferenceable(8) [[B]]) 313; IS__CGSCC____-NEXT: ret void 314; 315 call void @test_sret(%struct.X* null, %struct.X** %b) 316 ret void 317} 318 319define internal %struct.X* @test_nest(%struct.X* nest %a) { 320; IS__TUNIT____-LABEL: define {{[^@]+}}@test_nest 321; IS__TUNIT____-SAME: (%struct.X* nest noalias nofree readnone returned align 536870912 "no-capture-maybe-returned" [[A:%.*]]) 322; IS__TUNIT____-NEXT: ret %struct.X* [[A]] 323; 324; IS__CGSCC____-LABEL: define {{[^@]+}}@test_nest 325; IS__CGSCC____-SAME: (%struct.X* nest noalias nofree readnone returned "no-capture-maybe-returned" [[A:%.*]]) 326; IS__CGSCC____-NEXT: ret %struct.X* [[A]] 327; 328 ret %struct.X* %a 329} 330define %struct.X* @complicated_args_nest() { 331; CHECK-LABEL: define {{[^@]+}}@complicated_args_nest() 332; CHECK-NEXT: [[CALL:%.*]] = call %struct.X* @test_nest(%struct.X* noalias nofree readnone align 536870912 null) 333; CHECK-NEXT: ret %struct.X* [[CALL]] 334; 335 %call = call %struct.X* @test_nest(%struct.X* null) 336 ret %struct.X* %call 337} 338 339@S = external global %struct.X 340define internal void @test_byval(%struct.X* byval %a) { 341; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@test_byval 342; IS__CGSCC_OPM-SAME: (%struct.X* noalias nocapture nofree nonnull writeonly byval align 8 dereferenceable(8) [[A:%.*]]) 343; IS__CGSCC_OPM-NEXT: [[G0:%.*]] = getelementptr [[STRUCT_X:%.*]], %struct.X* [[A]], i32 0, i32 0 344; IS__CGSCC_OPM-NEXT: store i8* null, i8** [[G0]], align 8 345; IS__CGSCC_OPM-NEXT: ret void 346; 347; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@test_byval 348; IS__CGSCC_NPM-SAME: (i8* nocapture nofree readnone [[TMP0:%.*]]) 349; IS__CGSCC_NPM-NEXT: [[A_PRIV:%.*]] = alloca [[STRUCT_X:%.*]] 350; IS__CGSCC_NPM-NEXT: [[A_PRIV_CAST:%.*]] = bitcast %struct.X* [[A_PRIV]] to i8** 351; IS__CGSCC_NPM-NEXT: store i8* [[TMP0]], i8** [[A_PRIV_CAST]] 352; IS__CGSCC_NPM-NEXT: [[G0:%.*]] = getelementptr [[STRUCT_X]], %struct.X* [[A_PRIV]], i32 0, i32 0 353; IS__CGSCC_NPM-NEXT: store i8* null, i8** [[G0]], align 8 354; IS__CGSCC_NPM-NEXT: ret void 355; 356 %g0 = getelementptr %struct.X, %struct.X* %a, i32 0, i32 0 357 store i8* null, i8** %g0 358 ret void 359} 360define void @complicated_args_byval() { 361; CHECK-LABEL: define {{[^@]+}}@complicated_args_byval() 362; CHECK-NEXT: ret void 363; 364 call void @test_byval(%struct.X* @S) 365 ret void 366} 367 368define internal i8*@test_byval2(%struct.X* byval %a) { 369; CHECK-LABEL: define {{[^@]+}}@test_byval2() 370; CHECK-NEXT: [[G0:%.*]] = getelementptr [[STRUCT_X:%.*]], %struct.X* @S, i32 0, i32 0 371; CHECK-NEXT: [[L:%.*]] = load i8*, i8** [[G0]], align 8 372; CHECK-NEXT: ret i8* [[L]] 373; 374 %g0 = getelementptr %struct.X, %struct.X* %a, i32 0, i32 0 375 %l = load i8*, i8** %g0 376 ret i8* %l 377} 378define i8* @complicated_args_byval2() { 379; CHECK-LABEL: define {{[^@]+}}@complicated_args_byval2() 380; CHECK-NEXT: [[C:%.*]] = call i8* @test_byval2() 381; CHECK-NEXT: ret i8* [[C]] 382; 383 %c = call i8* @test_byval2(%struct.X* @S) 384 ret i8* %c 385} 386 387define void @fixpoint_changed(i32* %p) { 388; CHECK-LABEL: define {{[^@]+}}@fixpoint_changed 389; CHECK-SAME: (i32* nocapture nofree writeonly [[P:%.*]]) 390; CHECK-NEXT: entry: 391; CHECK-NEXT: br label [[FOR_COND:%.*]] 392; CHECK: for.cond: 393; CHECK-NEXT: [[J_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[SW_EPILOG:%.*]] ] 394; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[J_0]], 30 395; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]] 396; CHECK: for.body: 397; CHECK-NEXT: switch i32 [[J_0]], label [[SW_EPILOG]] [ 398; CHECK-NEXT: i32 1, label [[SW_BB:%.*]] 399; CHECK-NEXT: ] 400; CHECK: sw.bb: 401; CHECK-NEXT: br label [[SW_EPILOG]] 402; CHECK: sw.epilog: 403; CHECK-NEXT: [[X_0:%.*]] = phi i32 [ 255, [[FOR_BODY]] ], [ 253, [[SW_BB]] ] 404; CHECK-NEXT: store i32 [[X_0]], i32* [[P]] 405; CHECK-NEXT: [[INC]] = add nsw i32 [[J_0]], 1 406; CHECK-NEXT: br label [[FOR_COND]] 407; CHECK: for.end: 408; CHECK-NEXT: ret void 409; 410entry: 411 br label %for.cond 412 413for.cond: 414 %j.0 = phi i32 [ 0, %entry ], [ %inc, %sw.epilog ] 415 %cmp = icmp slt i32 %j.0, 30 416 br i1 %cmp, label %for.body, label %for.end 417 418for.body: 419 switch i32 %j.0, label %sw.epilog [ 420 i32 1, label %sw.bb 421 ] 422 423sw.bb: 424 br label %sw.epilog 425 426sw.epilog: 427 %x.0 = phi i32 [ 255, %for.body ], [ 253, %sw.bb ] 428 store i32 %x.0, i32* %p 429 %inc = add nsw i32 %j.0, 1 430 br label %for.cond 431 432for.end: 433 ret void 434} 435 436; Check we merge undef and a constant properly. 437; FIXME fold the addition and return the constant. 438define i8 @caller0() { 439; CHECK-LABEL: define {{[^@]+}}@caller0() 440; CHECK-NEXT: [[C:%.*]] = call i8 @callee() 441; CHECK-NEXT: ret i8 [[C]] 442; 443 %c = call i8 @callee(i8 undef) 444 ret i8 %c 445} 446define i8 @caller1() { 447; CHECK-LABEL: define {{[^@]+}}@caller1() 448; CHECK-NEXT: [[C:%.*]] = call i8 @callee() 449; CHECK-NEXT: ret i8 [[C]] 450; 451 %c = call i8 @callee(i8 undef) 452 ret i8 %c 453} 454define i8 @caller2() { 455; CHECK-LABEL: define {{[^@]+}}@caller2() 456; CHECK-NEXT: [[C:%.*]] = call i8 @callee() 457; CHECK-NEXT: ret i8 [[C]] 458; 459 %c = call i8 @callee(i8 undef) 460 ret i8 %c 461} 462define i8 @caller_middle() { 463; CHECK-LABEL: define {{[^@]+}}@caller_middle() 464; CHECK-NEXT: [[C:%.*]] = call i8 @callee() 465; CHECK-NEXT: ret i8 [[C]] 466; 467 %c = call i8 @callee(i8 42) 468 ret i8 %c 469} 470define i8 @caller3() { 471; CHECK-LABEL: define {{[^@]+}}@caller3() 472; CHECK-NEXT: [[C:%.*]] = call i8 @callee() 473; CHECK-NEXT: ret i8 [[C]] 474; 475 %c = call i8 @callee(i8 undef) 476 ret i8 %c 477} 478define i8 @caller4() { 479; CHECK-LABEL: define {{[^@]+}}@caller4() 480; CHECK-NEXT: [[C:%.*]] = call i8 @callee() 481; CHECK-NEXT: ret i8 [[C]] 482; 483 %c = call i8 @callee(i8 undef) 484 ret i8 %c 485} 486define internal i8 @callee(i8 %a) { 487; CHECK-LABEL: define {{[^@]+}}@callee() 488; CHECK-NEXT: [[C:%.*]] = add i8 42, 7 489; CHECK-NEXT: ret i8 [[C]] 490; 491 %c = add i8 %a, 7 492 ret i8 %c 493} 494 495