273 lines · plain
1; RUN: opt < %s -passes='cgscc(inline)' -inline-threshold=0 -S | FileCheck %s2 3; The 'test1_' prefixed functions test the basic 'last callsite' inline4; threshold adjustment where we specifically inline the last call site of an5; internal function regardless of cost.6 7define internal void @test1_f() {8entry:9 %p = alloca i3210 store volatile i32 0, ptr %p11 store volatile i32 0, ptr %p12 store volatile i32 0, ptr %p13 store volatile i32 0, ptr %p14 store volatile i32 0, ptr %p15 store volatile i32 0, ptr %p16 store volatile i32 0, ptr %p17 store volatile i32 0, ptr %p18 ret void19}20 21; Identical to @test1_f but doesn't get inlined because there is more than one22; call. If this *does* get inlined, the body used both here and in @test1_f23; isn't a good test for different threshold based on the last call.24define internal void @test1_g() {25entry:26 %p = alloca i3227 store volatile i32 0, ptr %p28 store volatile i32 0, ptr %p29 store volatile i32 0, ptr %p30 store volatile i32 0, ptr %p31 store volatile i32 0, ptr %p32 store volatile i32 0, ptr %p33 store volatile i32 0, ptr %p34 store volatile i32 0, ptr %p35 ret void36}37 38define void @test1() {39; CHECK-LABEL: define void @test1()40entry:41 call void @test1_f()42; CHECK-NOT: @test1_f43 44 call void @test1_g()45 call void @test1_g()46; CHECK: call void @test1_g()47; CHECK: call void @test1_g()48 49 ret void50}51 52 53; The 'test2_' prefixed functions test that we can discover the last callsite54; bonus after having inlined the prior call site. For this to work, we need55; a callsite dependent cost so we have a trivial predicate guarding all the56; cost, and set that in a particular direction.57 58define internal void @test2_f(i1 %b) {59entry:60 %p = alloca i3261 br i1 %b, label %then, label %exit62 63then:64 store volatile i32 0, ptr %p65 store volatile i32 0, ptr %p66 store volatile i32 0, ptr %p67 store volatile i32 0, ptr %p68 store volatile i32 0, ptr %p69 store volatile i32 0, ptr %p70 store volatile i32 0, ptr %p71 store volatile i32 0, ptr %p72 br label %exit73 74exit:75 ret void76}77 78; Identical to @test2_f but doesn't get inlined because there is more than one79; call. If this *does* get inlined, the body used both here and in @test2_f80; isn't a good test for different threshold based on the last call.81define internal void @test2_g(i1 %b) {82entry:83 %p = alloca i3284 br i1 %b, label %then, label %exit85 86then:87 store volatile i32 0, ptr %p88 store volatile i32 0, ptr %p89 store volatile i32 0, ptr %p90 store volatile i32 0, ptr %p91 store volatile i32 0, ptr %p92 store volatile i32 0, ptr %p93 store volatile i32 0, ptr %p94 store volatile i32 0, ptr %p95 br label %exit96 97exit:98 ret void99}100 101define void @test2() {102; CHECK-LABEL: define void @test2()103entry:104 ; The first call is trivial to inline due to the argument.105 call void @test2_f(i1 false)106; CHECK-NOT: @test2_f107 108 ; The second call is too expensive to inline unless we update the number of109 ; calls after inlining the second.110 call void @test2_f(i1 true)111; CHECK-NOT: @test2_f112 113 ; Check that two calls with the hard predicate remain uninlined.114 call void @test2_g(i1 true)115 call void @test2_g(i1 true)116; CHECK: call void @test2_g(i1 true)117; CHECK: call void @test2_g(i1 true)118 119 ret void120}121 122 123; The 'test3_' prefixed functions are similar to the 'test2_' functions but the124; relative order of the trivial and hard to inline callsites is reversed. This125; checks that the order of calls isn't significant to whether we observe the126; "last callsite" threshold difference because the next-to-last gets inlined.127; FIXME: We don't currently catch this case.128 129define internal void @test3_f(i1 %b) {130entry:131 %p = alloca i32132 br i1 %b, label %then, label %exit133 134then:135 store volatile i32 0, ptr %p136 store volatile i32 0, ptr %p137 store volatile i32 0, ptr %p138 store volatile i32 0, ptr %p139 store volatile i32 0, ptr %p140 store volatile i32 0, ptr %p141 store volatile i32 0, ptr %p142 store volatile i32 0, ptr %p143 br label %exit144 145exit:146 ret void147}148 149; Identical to @test3_f but doesn't get inlined because there is more than one150; call. If this *does* get inlined, the body used both here and in @test3_f151; isn't a good test for different threshold based on the last call.152define internal void @test3_g(i1 %b) {153entry:154 %p = alloca i32155 br i1 %b, label %then, label %exit156 157then:158 store volatile i32 0, ptr %p159 store volatile i32 0, ptr %p160 store volatile i32 0, ptr %p161 store volatile i32 0, ptr %p162 store volatile i32 0, ptr %p163 store volatile i32 0, ptr %p164 store volatile i32 0, ptr %p165 store volatile i32 0, ptr %p166 br label %exit167 168exit:169 ret void170}171 172define void @test3() {173; CHECK-LABEL: define void @test3()174entry:175 ; The first call is too expensive to inline unless we update the number of176 ; calls after inlining the second.177 call void @test3_f(i1 true)178; FIXME: We should inline this call without iteration.179; CHECK: call void @test3_f(i1 true)180 181 ; But the second call is trivial to inline due to the argument.182 call void @test3_f(i1 false)183; CHECK-NOT: @test3_f184 185 ; Check that two calls with the hard predicate remain uninlined.186 call void @test3_g(i1 true)187 call void @test3_g(i1 true)188; CHECK: call void @test3_g(i1 true)189; CHECK: call void @test3_g(i1 true)190 191 ret void192}193 194 195; The 'test4_' prefixed functions are similar to the 'test2_' prefixed196; functions but include unusual constant expressions that make discovering that197; a function is dead harder.198 199define internal void @test4_f(i64 %a, i64 %b) {200entry:201 %p = alloca i32202 %cmp = icmp ne i64 %a, %b203 br i1 %cmp, label %then, label %exit204 205then:206 store volatile i32 0, ptr %p207 store volatile i32 0, ptr %p208 store volatile i32 0, ptr %p209 store volatile i32 0, ptr %p210 store volatile i32 0, ptr %p211 store volatile i32 0, ptr %p212 store volatile i32 0, ptr %p213 store volatile i32 0, ptr %p214 br label %exit215 216exit:217 ret void218}219 220; Identical to @test4_f but doesn't get inlined because there is more than one221; call. If this *does* get inlined, the body used both here and in @test4_f222; isn't a good test for different threshold based on the last call.223define internal void @test4_g(i1 %b) {224entry:225 %p = alloca i32226 br i1 %b, label %then, label %exit227 228then:229 store volatile i32 0, ptr %p230 store volatile i32 0, ptr %p231 store volatile i32 0, ptr %p232 store volatile i32 0, ptr %p233 store volatile i32 0, ptr %p234 store volatile i32 0, ptr %p235 store volatile i32 0, ptr %p236 store volatile i32 0, ptr %p237 br label %exit238 239exit:240 ret void241}242 243define void @test4() {244; CHECK-LABEL: define void @test4()245entry:246 ; The first call is trivial to inline due to the argument. However this247 ; argument also uses the function being called as part of a complex248 ; constant expression. Merely inlining and deleting the call isn't enough to249 ; drop the use count here, we need to GC the dead constant expression as250 ; well.251 call void @test4_f(i64 ptrtoint (ptr @test4_f to i64), i64 ptrtoint(ptr @test4_f to i64))252; CHECK-NOT: @test4_f253 254 ; The second call is too expensive to inline unless we update the number of255 ; calls after inlining the second.256 call void @test4_f(i64 0, i64 1)257; CHECK-NOT: @test4_f258 259 ; And check that a single call to a function which is used by a complex260 ; constant expression cannot be inlined because the constant expression forms261 ; a second use. If this part starts failing we need to use more complex262 ; constant expressions to reference a particular function with them.263 %sink = alloca i64264 %mul = mul i64 ptrtoint (ptr @test4_g to i64), ptrtoint(ptr @test4_g to i64)265 store volatile i64 %mul, ptr %sink266 call void @test4_g(i1 true)267; CHECK: %mul = mul i64 ptrtoint (ptr @test4_g to i64), ptrtoint (ptr @test4_g to i64)268; CHECK: store volatile i64 %mul, ptr %sink269; CHECK: call void @test4_g(i1 true)270 271 ret void272}273