Merge remote-tracking branch 'origin/topic/vern/ZAM-inlining'

* origin/topic/vern/ZAM-inlining:
  speed up ZAM compilation by capping function size when inlining
This commit is contained in:
Tim Wojtulewicz 2022-05-19 11:45:38 -07:00
commit 73273fc87b
15 changed files with 85 additions and 15 deletions

View file

@ -2329,6 +2329,10 @@ ExprPtr CallExpr::Inline(Inliner* inl)
{
auto new_me = inl->CheckForInlining({NewRef{}, this});
if ( ! new_me )
// All done with inlining.
return ThisPtr();
if ( new_me.get() != this )
return new_me;

View file

@ -5,10 +5,13 @@
#include "zeek/Desc.h"
#include "zeek/script_opt/ProfileFunc.h"
#include "zeek/script_opt/ScriptOpt.h"
#include "zeek/script_opt/StmtOptInfo.h"
namespace zeek::detail
{
constexpr int MAX_INLINE_SIZE = 1000;
void Inliner::Analyze()
{
// Locate self- and indirectly recursive functions.
@ -139,8 +142,15 @@ void Inliner::InlineFunction(FuncInfo* f)
// particular body.
curr_frame_size = f->Scope()->Length();
auto oi = f->Body()->GetOptInfo();
num_stmts = oi->num_stmts;
num_exprs = oi->num_exprs;
f->Body()->Inline(this);
oi->num_stmts = num_stmts;
oi->num_exprs = num_exprs;
int new_frame_size = curr_frame_size + max_inlined_frame_size;
if ( new_frame_size > f->Func()->FrameSize() )
@ -175,9 +185,19 @@ ExprPtr Inliner::CheckForInlining(CallExprPtr c)
if ( inline_ables.count(func_vf) == 0 )
return c;
ListExprPtr args = {NewRef{}, c->Args()};
// We're going to inline the body, unless it's too large.
auto body = func_vf->GetBodies()[0].stmts; // there's only 1 body
auto t = c->GetType();
auto oi = body->GetOptInfo();
if ( num_stmts + oi->num_stmts + num_exprs + oi->num_exprs > MAX_INLINE_SIZE )
return nullptr;
num_stmts += oi->num_stmts;
num_exprs += oi->num_exprs;
auto body_dup = body->Duplicate();
body_dup->GetOptInfo()->num_stmts = oi->num_stmts;
body_dup->GetOptInfo()->num_exprs = oi->num_exprs;
// Getting the names of the parameters is tricky. It's tempting
// to take them from the function's type declaration, but alas
@ -198,8 +218,6 @@ ExprPtr Inliner::CheckForInlining(CallExprPtr c)
for ( int i = 0; i < nparam; ++i )
params.emplace_back(vars[i]);
auto body_dup = body->Duplicate();
// Recursively inline the body. This is safe to do because we've
// ensured there are no recursive loops ... but we have to be
// careful in accounting for the frame sizes.
@ -221,6 +239,8 @@ ExprPtr Inliner::CheckForInlining(CallExprPtr c)
else
max_inlined_frame_size = hold_max_inlined_frame_size;
ListExprPtr args = {NewRef{}, c->Args()};
auto t = c->GetType();
auto ie = make_intrusive<InlineExpr>(args, std::move(params), body_dup, curr_frame_size, t);
ie->SetOriginal(c);

View file

@ -27,8 +27,8 @@ public:
Analyze();
}
// Either returns the original CallExpr if it's not inline-able,
// or an InlineExpr if it is.
// Either returns the original CallExpr if it's not inline-able;
// or an InlineExpr if it is; or nil if further inlining should stop.
ExprPtr CheckForInlining(CallExprPtr c);
// True if the given function has been inlined.
@ -57,6 +57,12 @@ protected:
// prior to increasing it to accommodate inlining.
int curr_frame_size;
// The number of statements and expressions in the function being
// inlined. Dynamically updated as the inlining proceeds. Used
// to cap inlining complexity.
int num_stmts;
int num_exprs;
// Whether to generate a report about functions either directly and
// indirectly recursive.
bool report_recursive;

View file

@ -26,6 +26,10 @@ public:
// Whether this statement is free of the possible influence
// of conditional code.
bool is_free_of_conditionals = true;
// Number of statements and expressions in a function body.
int num_stmts = 0;
int num_exprs = 0;
};
} // namespace zeek::detail