-
Notifications
You must be signed in to change notification settings - Fork 5.4k
Trivially encoded types #7488
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Trivially encoded types #7488
Conversation
CodSpeed Performance ReportMerging #7488 will not alter performanceComparing Summary
|
d8b0301 to
b5bed35
Compare
9c8145a to
7e43c6a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This PR is being reviewed by Cursor Bugbot
Details
Your team is on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle for each member of your team.
To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.
Description
This PR will slice #7419 into multiple PRS, being the first one.
To start optimising encoding/decoding we will introduce the concept of "trivially encoded/decoded types". A type is trivially encoded or decoded if the encoding memory representation is the same as the runtime memory representation.
PR #7419 introduced an intrinsic that would return a
boolif both representations match. For this PR I decided to expose these memory representations directly. For that we have two new intrinsics:__runtime_mem_idand__encoding_mem_id.I am not 100% sure if they are going to be useful in other scenarios, but given that the optimiser is able to optimise them away, I think exposing them like this is better than what #7419 does.
These
idsare opaque numbers that do not convey anything about the type or their representation. They can only be compared for equality, and when a type does not have an encoding representation the intrinsic returns zero.With this in mind, the
encodefunction now checks if a type is "trivially encoded" or not. If it is, we just allocate and memcopy its bytes. As this function should not return an aliased pointer.On top of that, we also have an
encode_and_returnfunction that avoids creating tuples and other stuff, given that the optimiser still generates somemem_copys in these cases.A simple example of the benefit is the test
main_args_empty, where the binary size went from 96 bytes to 64 bytes.Before
After
Next PR will introduce this concept into the
AbiEncodetrait, allowing the type itself to control if it wants to be trivially encoded or not.Missing optimizations
If we look at the test
main_args_various_types, after themainis called we see that IR is still not optimal.Ideally, IR would be
Gas Usage Diff
Checklist
Breaking*orNew Featurelabels where relevant.Note
Introduce
__runtime_mem_id/__encoding_mem_idintrinsics and use them to trivially encode/return values, updating ABI entry tonever, improving gas/binary size, and adjusting docs, IR, and tests.__runtime_mem_id<T>() -> u64and__encoding_mem_id<T>() -> u64(AST, semantic, IR gen, const-eval).get_memory_representation,get_memory_id,get_encoding_representation/id).neverand use directretd.never.codec.sw):encode<T>: detect trivially-encodable types (matching IDs) andmemcpybytes; otherwise fallback to normal encoding.encode_and_return<T>() -> !using__contract_retfor fast returns.__transmute,__runtime_mem_id, and__encoding_mem_idin the Sway book; include constraints/semantics.main_args_emptyshrinks (e.g., 96→64 B) and many gas wins.Written by Cursor Bugbot for commit 2caf44c. This will update automatically on new commits. Configure here.