Skip to content

perf(ast): memoize top-level constant function calls - #2

Merged
vbtcl merged 2 commits into
boson-basefrom
perf/const-call-memo
Oct 19, 2026
Merged

vbtcl merged 2 commits into
boson-basefrom
perf/const-call-memo

Conversation

@vbtcl

@vbtcl vbtcl commented Oct 16, 2026 •

Copy link
Copy Markdown

A constant function called from a parameter initializer is evaluated once per instance of the enclosing module, even when every instance passes the same arguments. On the PULP astral SoC, hsiao_ecc_pkg::hsiao_matrix(DataWidth, ProtWidth) is called 108 times with 6 distinct argument sets. It accounts for 145 s of a 148 s elaboration. The value is needed for each instance's instance-cache key, so the evaluation can't be skipped.

This change memoizes top-level constant function calls on the Compilation. The key is the subroutine, the eval flags, the AST flags and the exact argument values: integers compare width, sign and X/Z bits, and reals compare bit patterns, so +0.0 and -0.0 are different keys. A result is recorded only when the evaluation:

  • took at least 64 steps,
  • added no diagnostics to the EvalContext, and
  • did not depend on the call site. NamedValueExpression::checkConstant flags any non-package parameter checked against the outermost frame's lookup location.

Calls made from inside a package, calls with a queue target or lvalues on the stack, class methods, tasks and subroutines with output arguments are never memoized. On a hit, the original step count is added to the context. If the hit would cross maxConstexprSteps, the call is evaluated for real so that it fails exactly as it would have. The memo is mutex-guarded and holds at most 65,536 entries.

Measured with the boson native-elab driver setup, getAllDiagnostics, 1 thread:

design before after
astral (carfield top) 112.3 s 8.6 s
carfield 27.5 s 4.4 s

The rendered diagnostics are byte-identical on both designs.

New tests in ParameterTests.cpp cover values across instances and generate blocks, +0.0/-0.0 arguments, the step limit with memo hits, and call-site-dependent diagnostics (ConstEvalIdUsedInCEBeforeDecl). The full unittests pass: 22082 assertions in 2204 test cases, with #3 applied too.

Ships to boson as scripts/patches/slang/0010-memoize-top-level-constant-function-calls.patch (partcleda/boson#13187).

🤖 Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

A constant function called from a parameter initializer is evaluated once
per instance of the enclosing module, even when every instance passes the
same arguments. Designs that compute large tables in package functions
(e.g. Hsiao ECC matrices) spend most of their elaboration time redoing
identical evaluations.

Top-level calls are now memoized on the compilation, keyed on the
subroutine, the evaluation and AST flags, and the exact argument values.
A result is only recorded when the evaluation took enough steps to be
worth it, produced no diagnostics, and did not depend on its call site
(a non-package parameter checked against the call's lookup location).
Calls made from within a package are never memoized. On a hit the
original step count is replayed, and a call that would exceed the step
limit is evaluated for real so that it fails exactly as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e arguments

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@vbtcl

vbtcl commented Oct 16, 2026

Copy link
Copy Markdown
Author

Pushed 6b20f34: std::unique_lock<std::mutex> instead of CTAD (clang -Wctad-maybe-unsupported under -Werror, which upstream CI hit), plus a test that calls a memoized function with array, string, queue, associative-array and shortreal arguments. Unit tests: 22084 assertions in 2205 test cases, all pass (with #3). boson's 0010 differs from this branch only in that lock spelling: gcc builds both the same way.

@vbtcl
vbtcl merged commit b1b5cf9 into boson-base Oct 19, 2026
12 of 15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant