llvm-project/llvm/test/Transforms/Inline/inline-recursive-fn2.ll
Arthur Eubanks 82505fbfc8
[Inliner] Put inline history into IR as !inline_history metadata (#190700)
(Reland of #190092 with verifier change to look through GlobalAliases)

So that it's preserved across all inline invocations rather than just
one inliner pass run.

This prevents cases where devirtualization in the simplification
pipeline uncovers inlining opportunities that should be discarded due to
inline history, but we dropped the inline history between inliner pass
runs, causing code size to blow up, sometimes exponentially.

For compile time reasons, we want to limit this to only call sites that
have the potential to inline through SCCs, potentially with the help of
devirtualization. This means that the callee is in a non-trivial
(Ref)SCC, or the call site was previously an indirect call, which can
potentially be devirtualized to call any function.

The CGSCCUpdater::InlinedInternalEdges logic still seems to be relevant
even with this change, as monster_scc.ll blows up if I remove that code.


http://llvm-compile-time-tracker.com/compare.php?from=e830d88e8ae5f44a97cc76136a0a4e83aa9157c0&to=ed535e732fc41b79ab8efda2417886cbd0812f7f&stat=instructions:u

Fixes #186926.
2026-04-06 17:31:43 -07:00

50 lines
2.3 KiB
LLVM

; REQUIRES: asserts
; RUN: opt -passes='cgscc(inline),instcombine,cgscc(inline)' -S -debug-only=inline -disable-output < %s 2>&1 | FileCheck %s
; This test shows that the recursive function will not get simplified
; unless the caller is the function itself, not another different caller.
; CHECK: Inlining calls in: test
; CHECK: Function size: 2
; CHECK: NOT Inlining (cost=never): recursive, Call: %call = tail call float @inline_rec_true_successor(float %x, float %scale)
; CHECK: Inlining calls in: inline_rec_true_successor
; CHECK: Function size: 10
; CHECK: Inlining (cost=-35, threshold=337), Call: %call = tail call float @inline_rec_true_successor(float %fneg, float %scale)
; CHECK: Size after inlining: 17
; CHECK: NOT Inlining (cost=never): noinline function attribute, Call: %call_test = tail call float @test(float %fneg, float %common.ret18.op.i)
; CHECK: NOT Inlining (cost=never): noinline function attribute, Call: %call_test.i = tail call float @test(float %x, float %call.i)
; CHECK: NOT Inlining (cost=never): recursive, Call: %call.i = tail call float @inline_rec_true_successor(float %x, float %scale)
; CHECK: Updated inlining SCC: (test, inline_rec_true_successor)
; CHECK: Inlining calls in: test
; CHECK: Function size: 2
; CHECK: Inlining (cost=25, threshold=225), Call: %call = tail call float @inline_rec_true_successor(float %x, float %scale)
; CHECK: Size after inlining: 10
define float @test(float %x, float %scale) noinline {
entry:
%call = tail call float @inline_rec_true_successor(float %x, float %scale)
ret float %call
}
define float @inline_rec_true_successor(float %x, float %scale) {
entry:
%cmp = fcmp olt float %x, 0.000000e+00
br i1 %cmp, label %if.then, label %if.end
common.ret18: ; preds = %if.then, %if.end
%common.ret18.op = phi float [ %call_test, %if.then ], [ %mul, %if.end ]
ret float %common.ret18.op
if.then: ; preds = %entry
%fneg = fneg float %x
%call = tail call float @inline_rec_true_successor(float %fneg, float %scale)
%call_test = tail call float @test(float %fneg, float %call)
br label %common.ret18
if.end: ; preds = %entry
%mul = fmul float %x, %scale
br label %common.ret18
}