Optimizer: Eliminate dead mstore instructions from memoryguard-derived struct allocations - #16936
Open
OminduD wants to merge 2 commits into
Open
Optimizer: Eliminate dead mstore instructions from memoryguard-derived struct allocations#16936OminduD wants to merge 2 commits into
OminduD wants to merge 2 commits into
Conversation
r0qs
self-requested a review
August 24, 2026 13:42
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Fixes #16927
Fixes a missed optimisation in the IR pipeline where accessing a single member of an
abi.decode-d struct leaves several deadmstoreinstructions that theUnusedStoreEliminatorshould remove.Reproducer:
The IR optimizer generates a scratch region at
_1 = memoryguard(0x80), writes all four struct members into it, and then — becauseLoadResolveralready forwards the.tokenIdvalue directly — the fourmstores are dead. However,UnusedStoreEliminatorwas unable to remove them becauseKnowledgeBase::explore()did not recognisememoryguard(N)as the constantN. Without that knowledge, no non-overlap between the scratch slots (0x80–0xfe) and the return target (newFreePtr = 0x100) could be proved, so all four stores were conservatively kept.Fix:
Teach
KnowledgeBase::explore(Expression const&)to foldmemoryguard(literal)to its argument value, exactly like a plainLiteralnode.memoryguardalways takes a single literal operand (enforced by the builtin'sliteralArgumentsmetadata), so this is always safe.Changes:
libyul/optimiser/KnowledgeBase.h— addstd::optional<BuiltinHandle> m_memoryGuardBuiltinHandleand initialise it in both constructors (same pattern asm_addBuiltinHandle/m_subBuiltinHandle).libyul/optimiser/KnowledgeBase.cpp— add a newelse ifbranch inexplore(Expression const&)that returnsVariableOffset{YulName{}, literal->value.value()}when the callee ismemoryguard. Also adds the missing braces around thesubbranch to keep theelse ifchain well-formed.test/libyul/yulOptimizerTests/unusedStoreEliminator/memoryguard_dead_store.yul— new regression test directly modelling the IR pattern from the bug report; asserts that all four dead stores are eliminated.Checklist
AI Disclosure
Antigravity (Claude Sonnet 4.6) was used to navigate the codebase, cross-reference the interaction between
KnowledgeBase,UnusedStoreEliminator, andUnusedStoreBase, and to draft this PR description. All code changes were authored, reviewed, and tested by the contributor.