Skip to content

booster: configurable HS-only symbols before LLVM simplify#4140

Closed
Stevengre wants to merge 6 commits into
masterfrom
steven/pr853-hs-only-tdd
Closed

booster: configurable HS-only symbols before LLVM simplify#4140
Stevengre wants to merge 6 commits into
masterfrom
steven/pr853-hs-only-tdd

Conversation

@Stevengre
Copy link
Copy Markdown

@Stevengre Stevengre commented Mar 10, 2026

Behavior Delta

Before After
Trigger LLVM simplification runs unconditionally on all candidate terms, regardless of whether they contain symbols that should only be handled by the Haskell backend. Users pass --hs-only-symbol LABEL (repeatable) to kore-rpc-booster; any term containing a listed symbol skips LLVM simplification and stays on the Haskell path.
Observable effect Terms with Haskell-only helper symbols could be sent to LLVM, producing incorrect results or crashes when the LLVM backend does not understand those symbols. llvmSimplify, simplifyConstraint', and simplifyCeil now check for HS-only symbols before dispatching to LLVM, falling back to the Haskell evaluator when a match is found.
Affected inputs kore-rpc-booster CLI, ServerState, equation/rewrite/ceil evaluation paths, dev-tools (booster-dev, parsetest). Same components, plus a new --hs-only-symbol flag, containsSymbolName helper, and unit tests covering CLI parsing and symbol matching.
flowchart TD
  CLI["--hs-only-symbol LABEL (CLI)"] --> CLOptions["CLOptions.hsOnlySymbols :: HashSet ByteString"]
  CLOptions --> ServerState["ServerState / EquationConfig / RewriteConfig"]
  ServerState --> Guard{"Term contains HS-only symbol?"}
  Guard -- Yes --> Haskell["Haskell evaluator (no LLVM)"]
  Guard -- No --> LLVM["LLVM simplification (unchanged)"]
Loading

Invariants / Non-goals

  • Must still hold: When no --hs-only-symbol flags are passed, the empty set propagates everywhere and all existing behavior is unchanged (zero-cost guard).
  • Explicitly unchanged: LLVM simplification logic itself is not modified; only the dispatch decision is guarded.
  • Out of scope: Automatic detection of which symbols should be HS-only; this is left to the user via CLI configuration.

Validation

Risk point Evidence Link
CLI flag parsing (plain & K-encoded Lbl'Hash'... names) Test.Booster.CLOptions unit tests booster/unit-tests/Test/Booster/CLOptions.hs
containsSymbolName correctly scans nested terms Test.Booster.Pattern.ApplyEquations unit tests booster/unit-tests/Test/Booster/Pattern/ApplyEquations.hs
Dev-tools still compile with new computeCeilsDefinition arity cabal build booster-dev parsetest local build
LLVM integration not regressed cabal test llvm-integration (10/10 pass) local run
Predicate integration not regressed cabal test predicates-integration (13/13 pass) local run
CI fully green GitHub Actions run 22986242999 CI run

Risk / Blast Radius / Rollback

  • Most likely failure: A symbol label is passed in the wrong encoding (e.g., missing Lbl prefix), causing the guard to silently miss matches — terms still go to LLVM.
  • Blast radius: Only affects kore-rpc-booster users who explicitly opt-in via --hs-only-symbol; default behavior (empty set) is unchanged.
  • How to detect: Booster logs will show LLVM simplification still being called for terms that should have been kept on the Haskell path; unit tests cover both plain and encoded symbol names.
  • How to rollback: Remove the --hs-only-symbol flag from the launch command; the empty HashSet causes all guards to pass through to LLVM as before.

Review Focus

  1. Verify that containsSymbolName in Booster/Pattern/Util.hs recursively scans all term constructors (especially Injection, KMap, KList, KSet internal structures).
  2. Confirm that hsOnlySymbols is threaded correctly through ServerStateEquationConfig / RewriteConfigsimplifyCeil without any path dropping the set.
  3. Check that readHsOnlySymbol in CLOptions.hs validates and encodes labels correctly (ASCII-printable check, Lbl prefix addition).
Architecture Trace

Context (C4-L1)

No L1 change — this PR does not alter external system interactions. The kore-rpc-booster JSON-RPC interface is unchanged.

Container (C4-L2)

Single-container change within kore-rpc-booster. The LLVM backend shared library and the Haskell Kore evaluator are both unchanged; only the dispatch logic in front of LLVM is modified.

Component (C4-L3)

flowchart LR
  CLI["CLOptions parser"] --> Server["Server.hs (ServerState)"]
  Server --> AE["ApplyEquations (llvmSimplify, simplifyConstraint')"]
  Server --> Ceil["Definition.Ceil (simplifyCeil)"]
  AE --> Util["Pattern.Util (containsSymbolName)"]
  Ceil --> Util
Loading

Code Trace (C4-L4)

  • CLI flag definition → Booster.CLOptionsbooster/library/Booster/CLOptions.hs
  • Term scanning helper → Booster.Pattern.Util.containsSymbolNamebooster/library/Booster/Pattern/Util.hs
  • LLVM dispatch guard (equations) → Booster.Pattern.ApplyEquationsbooster/library/Booster/Pattern/ApplyEquations.hs
  • LLVM dispatch guard (ceil) → Booster.Definition.Ceilbooster/library/Booster/Definition/Ceil.hs
  • Server state threading → booster/tools/booster/Server.hs, Booster.JsonRpc
  • Dev-tools fixup → dev-tools/booster-dev/Server.hs, dev-tools/parsetest/Parsetest.hs
  • Unit tests → booster/unit-tests/Test/Booster/CLOptions.hs, booster/unit-tests/Test/Booster/Pattern/ApplyEquations.hs

Decision Record

  • Decision: Add a CLI-configurable symbol set that guards LLVM simplification entry points, keeping flagged terms on the Haskell evaluation path.
  • Alternatives considered: (1) Hard-code known HS-only symbols in the booster — rejected because the set varies per K definition. (2) Detect HS-only symbols automatically from the definition — deferred as it requires deeper definition analysis infrastructure.
  • Trade-offs: Requires users to know and pass the correct symbol labels; in exchange, zero runtime cost when unused and no changes to existing semantics.
  • Why chosen: Provides an immediate, low-risk mechanism to prevent incorrect LLVM evaluation of Haskell-only symbols without waiting for automatic detection infrastructure.

@Stevengre Stevengre self-assigned this Mar 16, 2026
@Stevengre
Copy link
Copy Markdown
Author

KEVM Performance test

Test steven-pr853-hs-only-tdd time master-00479fbdb time (steven-pr853-hs-only-tdd/master-00479fbdb) time
benchmarks/ecrecoverloop02-sigs-valid-spec.k 88.05 101.45 0.8679152291769344
mcd-structured/flopper-tick-pass-rough-spec.k 78.27 86.54 0.9044372544488097
mcd-structured/vow-flog-fail-rough-spec.k 93.02 102.8 0.904863813229572
benchmarks/storagevar00-spec.k 44.19 48.64 0.9085115131578947
examples/erc721-spec.md 122.83 134.21 0.9152075106176887
mcd-structured/flipper-tau-pass-spec.k 47.88 51.84 0.923611111111111
benchmarks/dynamicarray00-spec.k 45.21 48.86 0.9252967662709783
erc20/ds/transferFrom-success-1-spec.k 61.02 65.61 0.9300411522633746
benchmarks/requires01-a0le0-spec.k 44.57 47.88 0.9308688387635755
mcd-structured/flopper-cage-pass-spec.k 49.62 53.29 0.9311315443798086
examples/erc20-spec.md 124.59 133.26 0.934939216569113
benchmarks/storagevar03-spec.k 43.95 46.96 0.9359028960817718
mcd-structured/end-cash-pass-rough-spec.k 123.51 131.68 0.9379556500607533
mcd-structured/flopper-file-pass-rough-spec.k 18.86 20.1 0.9383084577114427
benchmarks/storagevar01-spec.k 44.4 47.14 0.9418752651675859
benchmarks/storagevar02-nooverflow-spec.k 45.01 47.73 0.9430127802220826
benchmarks/overflow00-overflow-spec.k 44.72 47.33 0.9448552714979929
examples/sum-to-n-spec.k 81.65 86.29 0.9462278363657434
examples/sum-to-n-foundry-spec.k 90.46 95.02 0.9520101031361818
benchmarks/encodepacked-keccak01-spec.k 45.86 47.98 0.9558149228845353
benchmarks/ecrecoverloop02-sig1-invalid-spec.k 86.95 90.9 0.9565456545654565
mcd-structured/pot-join-pass-rough-spec.k 153.3 159.99 0.9581848865554097
erc20/ds/transferFrom-failure-1-d-spec.k 53.2 55.38 0.9606356085229325
kontrol/test-allowchangestest-testallow_fail-0-spec.k 53.78 55.96 0.9610436025732666
erc20/ds/transfer-failure-2-b-spec.k 45.87 47.65 0.9626442812172088
mcd/end-subuu-pass-spec.k 55.51 57.52 0.9650556328233657
erc20/hkg/transfer-success-2-spec.k 50.07 48.36 1.0353598014888337
mcd/dsvalue-read-pass-summarize-spec.k 54.18 52.31 1.035748422863697
mcd-structured/dsvalue-read-pass-spec.k 49.47 47.73 1.0364550597108737
mcd/vow-flog-fail-rough-spec.k 107.3 103.52 1.0365146831530139
erc20/hkg/approve-spec.k 48.15 46.45 1.0365984930032293
benchmarks/staticarray00-spec.k 50.41 48.6 1.0372427983539094
erc20/hkg/transfer-success-1-spec.k 50.78 48.94 1.0375970576215776
mcd/cat-exhaustiveness-spec.k 116.7 112.33 1.0389032315498976
kontrol/test-expectcalltest-testexpectstaticcall-0-spec.k 53.76 51.73 1.0392422192151556
mcd/flipper-tau-pass-spec.k 53.16 51.13 1.0397027185605319
erc20/ds/approve-success-spec.k 52.06 50.04 1.0403677058353318
kontrol/test-countertest-testincrement-0-spec.k 89.93 86.44 1.0403748264692274
erc20/ds/transfer-failure-2-a-spec.k 63.26 60.75 1.0413168724279835
erc20/hkg/transfer-failure-2-spec.k 57.65 55.34 1.0417419588001444
kontrol/test-expectreverttest-test_expectrevert_message-0-spec.k 54.67 52.44 1.0425247902364607
kontrol/test-owneruponlytest-testincrementasowner-0-spec.k 75.03 71.93 1.0430974558598636
kontrol/test-expectreverttest-testfail_expectrevert_bytes4-0-spec.k 54.69 52.24 1.0468989280245022
erc20/hkg/transfer-failure-1-spec.k 59.12 56.45 1.0472984942426926
kontrol/test-emitcontracttest-testexpectemitcheckemitter-0-spec.k 54.3 51.83 1.0476557978005017
mcd/dsvalue-peek-pass-rough-spec.k 57.6 54.9 1.0491803278688525
erc20/hkg/transferFrom-success-1-spec.k 58.65 55.82 1.050698674310283
erc20/ds/allowance-spec.k 49.52 47.13 1.0507107999151284
kontrol/test-emitcontracttest-testexpectemitdonotcheckdata-0-spec.k 54.07 51.43 1.0513319074470153
mcd/vow-fess-fail-rough-spec.k 104.45 99.35 1.051333668847509
erc20/hkg/allowance-spec.k 48.23 45.87 1.0514497492914758
erc20/hkg/transferFrom-failure-1-spec.k 73.51 69.83 1.0526994128598024
erc20/hkg/transferFrom-success-2-spec.k 56.88 54.01 1.0531383077207925
erc20/hkg/transferFrom-failure-2-spec.k 68.36 64.83 1.0544501002622242
kontrol/test-arithmetictest-test_wdiv_rounding-uint256-uint256-0-spec.k 54.35 51.51 1.0551349252572317
mcd/dstoken-approve-fail-rough-spec.k 86.81 81.96 1.059175207418253
mcd/pot-join-pass-rough-spec.k 212.19 199.88 1.0615869521713028
kontrol/test-expectreverttest-testfail_expectrevert_failandsuccess-0-spec.k 55.41 51.89 1.067835806513779
mcd/flapper-yank-pass-rough-spec.k 177.51 166.21 1.0679862824138138
kontrol/test-emitcontracttest-testexpectemit-0-spec.k 55.77 51.9 1.0745664739884393
mcd-structured/end-subuu-pass-spec.k 56.97 52.66 1.0818458032662364
mcd/dai-adduu-fail-rough-spec.k 51.28 47.28 1.0846023688663282
kontrol/test-arithmetictest-test_wmul_weakly_increasing_positive-uint256-uint256-0-spec.k 72.87 66.74 1.0918489661372492
erc20/ds/transfer-success-2-spec.k 59.71 54.08 1.1041050295857988
mcd/flopper-cage-pass-spec.k 60.2 53.08 1.13413715146948
TOTAL 4495.31 4480.93 1.003209155242327

@Stevengre
Copy link
Copy Markdown
Author

Closing this PR. The functionality this aimed to implement is essentially the correct behavior of the non-evaluator, tracked in runtimeverification/k#4904.

@Stevengre Stevengre closed this Mar 17, 2026
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