feat: add more peephole optimisations - #458
Conversation
Add optimisations for increments and decrements of a variable deeper in the stack (e.g. x = x + 1 inside a branch), scope cleanup of deeper items, stack shuffles that OP_TUCK, OP_3DUP or OP_2SWAP express shorter, and OP_SIZE on a duplicated value. The increment and decrement rules come before the deeper drop rules, which would otherwise match the end of their patterns first. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## next #458 +/- ##
==========================================
- Coverage 89.34% 89.33% -0.01%
==========================================
Files 61 61
Lines 5048 5053 +5
Branches 942 946 +4
==========================================
+ Hits 4510 4514 +4
Misses 413 413
- Partials 125 126 +1 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
On behalf of Mathieu G. (mr-zwets), written by Claude Opus 5.5. A note for later, not for this PR:
This PR writes its families out like the existing ones, so the file stays one consistent list. A single regex can't express A generator would also rule out gaps, and there is already one: the Happy to add the |
Added a note about the need for dynamic optimisations in future versions.
Consolidate multiple optimization entries and fix various bugs related to literals and bytecode.
Opened on behalf of Mathieu G. (mr-zwets), written by Claude Opus 5.5.
Follow-up to #451, with peephole optimisations found in the pre-release audit of 0.14.0. The
cashctest contracts get 59 bytes smaller in total (3,067 to 3,008), and randomly generated loop-heavy contracts about 3.6%.Changes
New rules, appended to
optimisations.tsin four groups:x = x + 1inside a branch):OP_OVER OP_1ADD OP_ROT OP_DROP→OP_SWAP OP_1ADD, andOP_n OP_PICK OP_1ADD OP_(n+1) OP_ROLL OP_DROP→OP_n OP_ROLL OP_1ADDfor n = 2 to 15, with the same rules forOP_1SUB. These come before the drop rules below, which would otherwise match the end of these patterns first.OP_ROT OP_DROP OP_NIP→OP_NIP OP_NIP,OP_3 OP_ROLL OP_DROP OP_ROT→OP_2SWAP OP_NIP, thenOP_ROT OP_ROT OP_DROP→OP_NIP OP_SWAP, andOP_3 OP_ROLL OP_DROP OP_NIP OP_NIP→OP_NIP OP_NIP OP_NIP.OP_SWAP OP_OVER→OP_TUCK,OP_2 OP_PICK OP_2 OP_PICK→OP_3DUP OP_DROP,OP_2 OP_PICK OP_OVER→OP_3DUP OP_NIP(with a note thatOP_3DUPcopies one more item, which raises the operation cost when that item is large),OP_2 OP_PICK OP_NIP→OP_DROP OP_OVER,OP_TOALTSTACK OP_ROT OP_ROT OP_FROMALTSTACK→OP_2SWAP OP_ROT, andOP_DUP OP_ROT OP_NUMEQUALVERIFY→OP_TUCK OP_NUMEQUALVERIFY(the operands end up swapped, so only for this order-independent comparison).OP_DUP:OP_DUP OP_SIZE OP_NIP→OP_SIZE.Not included:
OP_DUP OP_VERIFY OP_DROP→OP_VERIFYis VM-equivalent, but itsOP_DROPis a scope cleanup. Merging that location into theOP_VERIFYmakes the SDK report a failingrequire(x)as the whole enclosing block, and moves a laterconsole.logbefore the check.Release notes updated.
Tests
optimiseBytecodeon 6 stacks each: no difference apart from stack-underflow cases and the documentedOP_NOTandOP_CAT OP_DROPrelaxations of existing rules. Every new rule shortens the script, so no new optimisation cycles are possible.cashctest contracts and for 4,500 generated contracts.deep_increment_decrement.cashfixture for decrements and deeper variables, which no existing test contract reached: it exercises theOP_1SUBrules at depths 1, 2 and 5, theOP_1ADDrule at depth 4, and bothOP_2SWAPrules (90 to 74 bytes).yarn build,yarn test,yarn lintandyarn spellcheckpass.🤖 Generated with Claude Code