brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.1 KiB · bb7592e Raw
365 lines · plain
1; The new pass manager doesn't re-use any threshold based infrastructure for2; the always inliner, but test that we get the correct result.3; RUN: opt < %s -inline-threshold=0 -passes=always-inline -S | FileCheck %s --check-prefix=CHECK4; RUN: opt < %s -inline-threshold=20000000 -passes=always-inline -S | FileCheck %s --check-prefix=CHECK5; RUN: opt < %s -inline-threshold=-20000000 -passes=always-inline -S | FileCheck %s --check-prefix=CHECK6 7define internal i32 @inner1() alwaysinline {8; CHECK-NOT: @inner1(9  ret i32 110}11define i32 @outer1() {12; CHECK-LABEL: @outer1(13; CHECK-NOT: call14; CHECK: ret15 16   %r = call i32 @inner1()17   ret i32 %r18}19 20; The always inliner can't DCE arbitrary internal functions. PR294521define internal i32 @pr2945() nounwind {22; CHECK-LABEL: @pr2945(23  ret i32 024}25 26define internal void @inner2(i32 %N) alwaysinline {27; CHECK-NOT: @inner2(28  %P = alloca i32, i32 %N29  ret void30}31define void @outer2(i32 %N) {32; The always inliner (unlike the normal one) should be willing to inline33; a function with a dynamic alloca into one without a dynamic alloca.34; rdar://665593235;36; CHECK-LABEL: @outer2(37; CHECK-NOT: call void @inner238; CHECK: ret void39 40  call void @inner2( i32 %N )41  ret void42}43 44declare i32 @a() returns_twice45declare i32 @b() returns_twice46 47; Cannot alwaysinline when that would introduce a returns_twice call.48define internal i32 @inner3() alwaysinline {49; CHECK-LABEL: @inner3(50entry:51  %call = call i32 @a() returns_twice52  %add = add nsw i32 1, %call53  ret i32 %add54}55define i32 @outer3() {56entry:57; CHECK-LABEL: @outer3(58; CHECK-NOT: call i32 @a59; CHECK: ret60 61  %call = call i32 @inner3()62  %add = add nsw i32 1, %call63  ret i32 %add64}65 66define internal i32 @inner4() alwaysinline returns_twice {67; CHECK-NOT: @inner4(68entry:69  %call = call i32 @b() returns_twice70  %add = add nsw i32 1, %call71  ret i32 %add72}73 74define i32 @outer4() {75entry:76; CHECK-LABEL: @outer4(77; CHECK: call i32 @b()78; CHECK: ret79 80  %call = call i32 @inner4() returns_twice81  %add = add nsw i32 1, %call82  ret i32 %add83}84 85; We can't inline this even though it has alwaysinline!86define internal i32 @inner5(ptr %addr) alwaysinline {87; CHECK-LABEL: @inner5(88entry:89  indirectbr ptr %addr, [ label %one, label %two ]90 91one:92  ret i32 4293 94two:95  ret i32 4496}97define i32 @outer5(i32 %x) {98; CHECK-LABEL: @outer5(99; CHECK: call i32 @inner5100; CHECK: ret101 102  %cmp = icmp slt i32 %x, 42103  %addr = select i1 %cmp, ptr blockaddress(@inner5, %one), ptr blockaddress(@inner5, %two)104  %call = call i32 @inner5(ptr %addr)105  ret i32 %call106}107 108; We never inline a function that calls itself recursively.109define internal void @inner6(i32 %x) alwaysinline {110; CHECK-LABEL: @inner6(111entry:112  %icmp = icmp slt i32 %x, 0113  br i1 %icmp, label %return, label %bb114 115bb:116  %sub = sub nsw i32 %x, 1117  call void @inner6(i32 %sub)118  ret void119 120return:121  ret void122}123define void @outer6() {124; CHECK-LABEL: @outer6(125; CHECK: call void @inner6(i32 42)126; CHECK: ret127 128entry:129  call void @inner6(i32 42)130  ret void131}132 133; This is not an alwaysinline function and is actually external.134define i32 @inner7() {135; CHECK-LABEL: @inner7(136  ret i32 1137}138define i32 @outer7() {139; CHECK-LABEL: @outer7(140; CHECK-NOT: call141; CHECK: ret142   %r = call i32 @inner7() alwaysinline143   ret i32 %r144}145 146define internal ptr @inner8(ptr nocapture align 128 %a) alwaysinline {147; CHECK-NOT: @inner8(148  ret ptr %a149}150define float @outer8(ptr nocapture %a) {151; CHECK-LABEL: @outer8(152; CHECK-NOT: call ptr @inner8153; CHECK: ret154 155  %inner_a = call ptr @inner8(ptr %a)156  %f = load float, ptr %inner_a, align 4157  ret float %f158}159 160 161; The 'inner9*' and 'outer9' functions are designed to check that we remove162; a function that is inlined by the always inliner even when it is used by163; a complex constant expression prior to being inlined.164 165; The 'a' function gets used in a complex constant expression that, despite166; being constant folded, means it isn't dead. As a consequence it shouldn't be167; deleted. If it is, then the constant expression needs to become more complex168; to accurately test this scenario.169define internal void @inner9a(i1 %b) alwaysinline {170; CHECK-LABEL: @inner9a(171entry:172  ret void173}174 175define internal void @inner9b(i64 %b) alwaysinline {176; CHECK-NOT: @inner9b(177entry:178  ret void179}180 181declare void @dummy9(i1 %b)182 183define void @outer9() {184; CHECK-LABEL: @outer9(185entry:186  ; First we use @inner9a in a complex constant expression that may get folded187  ; but won't get removed, and then we call it which will get inlined. Despite188  ; this the function can't be deleted because of the constant expression189  ; usage.190  %sink = alloca i1191  %cmp = icmp eq i64 ptrtoint (ptr @inner9a to i64), ptrtoint(ptr @dummy9 to i64)192  store volatile i1 %cmp, ptr %sink193; CHECK: store volatile194  call void @inner9a(i1 false)195; CHECK-NOT: call void @inner9a196 197  ; Next we call @inner9b passing in a constant expression. This constant198  ; expression will in fact be removed by inlining, so we should also be able199  ; to delete the function.200  call void @inner9b(i64 ptrtoint (ptr @inner9b to i64))201; CHECK-NOT: @inner9b202 203  ret void204; CHECK: ret void205}206 207; The 'inner10' and 'outer10' functions test a frustrating consequence of the208; current 'alwaysinline' semantic model. Because such functions are allowed to209; be external functions, it may be necessary to both inline all of their uses210; and leave them in the final output. These tests can be removed if and when211; we restrict alwaysinline further.212define void @inner10() alwaysinline {213; CHECK-LABEL: @inner10(214entry:215  ret void216}217 218define void @outer10() {219; CHECK-LABEL: @outer10(220entry:221  call void @inner10()222; CHECK-NOT: call void @inner10223 224  ret void225; CHECK: ret void226}227 228; The 'inner11' and 'outer11' functions test another dimension of non-internal229; functions with alwaysinline. These functions use external linkages that we can230; actually remove safely and so we should.231define linkonce void @inner11a() alwaysinline {232; CHECK-NOT: @inner11a(233entry:234  ret void235}236 237define available_externally void @inner11b() alwaysinline {238; CHECK-NOT: @inner11b(239entry:240  ret void241}242 243define void @outer11() {244; CHECK-LABEL: @outer11(245entry:246  call void @inner11a()247  call void @inner11b()248; CHECK-NOT: call void @inner11a249; CHECK-NOT: call void @inner11b250 251  ret void252; CHECK: ret void253}254 255; The 'inner12' and 'outer12' functions test that we don't remove functions256; which are part of a comdat group even if they otherwise seem dead.257$comdat12 = comdat any258 259define linkonce void @inner12() alwaysinline comdat($comdat12) {260; CHECK-LABEL: @inner12(261  ret void262}263 264define void @outer12() comdat($comdat12) {265; CHECK-LABEL: @outer12(266entry:267  call void @inner12()268; CHECK-NOT: call void @inner12269 270  ret void271; CHECK: ret void272}273 274; The 'inner13*' and 'outer13' functions test that we do remove functions275; which are part of a comdat group where all of the members are removed during276; always inlining.277$comdat13 = comdat any278 279define linkonce void @inner13a() alwaysinline comdat($comdat13) {280; CHECK-NOT: @inner13a(281  ret void282}283 284define linkonce void @inner13b() alwaysinline comdat($comdat13) {285; CHECK-NOT: @inner13b(286  ret void287}288 289define void @outer13() {290; CHECK-LABEL: @outer13(291entry:292  call void @inner13a()293  call void @inner13b()294; CHECK-NOT: call void @inner13a295; CHECK-NOT: call void @inner13b296 297  ret void298; CHECK: ret void299}300 301define void @inner14() readnone nounwind {302; CHECK: define void @inner14303  ret void304}305 306define void @outer14() {307; CHECK: call void @inner14308  call void @inner14()309  ret void310}311 312define internal i32 @inner15() {313; CHECK: @inner15(314  ret i32 1315}316 317define i32 @outer15() {318; CHECK-LABEL: @outer15(319; CHECK: call320 321   %r = call i32 @inner15() noinline322   ret i32 %r323}324 325define internal i32 @inner16() alwaysinline {326; CHECK: @inner16(327  ret i32 1328}329 330define i32 @outer16() {331; CHECK-LABEL: @outer16(332; CHECK: call333 334   %r = call i32 @inner16() noinline335   ret i32 %r336}337 338define i32 @inner17() alwaysinline {339; CHECK: @inner17(340  ret i32 1341}342 343define i32 @outer17() {344; CHECK-LABEL: @outer17(345; CHECK: call346 347   %r = call i32 @inner17() noinline348   ret i32 %r349}350 351define i32 @inner18() noinline {352; CHECK: @inner18(353  ret i32 1354}355 356define i32 @outer18() {357; CHECK-LABEL: @outer18(358; CHECK-NOT: call359; CHECK: ret360 361   %r = call i32 @inner18() alwaysinline362 363   ret i32 %r364}365