Skip to content

SSA CFG: stack to memory spilling#16767

Open
clonker wants to merge 6 commits into
developfrom
ssa-cfg-kiss-memspill
Open

SSA CFG: stack to memory spilling#16767
clonker wants to merge 6 commits into
developfrom
ssa-cfg-kiss-memspill

Conversation

@clonker
Copy link
Copy Markdown
Member

@clonker clonker commented May 22, 2026

Implements stack to memory spilling for the SSA CFG pipeline in a simple stupid version.

Adds:

  • ssa/spill/MemoryAddressing is a per-subobject owner of spill memory
    • sums numSpilled() across each CFGs SpillSet and bumps memory guard accordingly, allocates non-overlapping memory addresses for spilled values
  • ssa/spill/Emitter emits bytecode against the symbolic stack for spilled values
  • ssa/spill/SpillSet got a new method feasilize which will check for all spilled values whether they can be feasibly spilled at the point of origin, may add more things to spill accordingly

Modifies

  • ssa/StackLayoutGenerators generate() to return {layout, spillSet} instead of just the layout and also validates back-edges asserting that back-edge targets can be safely shuffled to
  • ssa/CodeTransform is reworked to first generate per-CFG layouts and spill sets (feasilize them), then build a single global MemoryAddressing to hand into the CodeTransform instance

Test

  • Adds SpillTest suite under test/libyul/ssa/spill which runs the generate -> feasilize -> address sequence and emits that plus a text representation of the input object. does not generate any code.

@clonker clonker marked this pull request as ready for review May 22, 2026 09:27
@clonker clonker requested a review from blishko May 22, 2026 10:00
{
public:
static std::unique_ptr<TestCase> create(Config const& _config);
explicit SpillTest(std::string const& _filename);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can/should this constructor be private?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not if we want to use make_unique in create, that can't access private ctors

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, that's true.
But you can change the implementation to

std::unique_ptr<frontend::test::TestCase> SpillTest::create(Config const& _config)
{
	return std::unique_ptr<SpillTest>(new SpillTest(_config.filename));
}

And then you can make it private.

I had another look at the codebase and I see that that you are just following the existing pattern.
It's just that I don't understand the purpose of the pattern.

Comment thread test/libyul/ssa/spill/phi_spilled_at_definition.yul
std::deque<InstId>& _workQueue)
{
// Leaf predicate = spill set minus the owner; the shuffle accumulates discovered culprits here.
SpillSet leafSpills = without(_value);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why leaf? I am not sure about the terminology.

Comment on lines +44 to +45
u256 const originalGuard = *_cfgs.memoryGuard;
*_cfgs.memoryGuard += u256(totalSlots) * 32;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updating the memory guard in the constructor of MemoryAddressing is a bit suspicious to me.
I understand the intent, I think maybe we should design this differently.
Can we discuss this further?

Comment on lines +110 to +114
MemoryAddressing const* m_addressing;
FunctionGraphID m_cfgIdx;
SpillSet const* m_spillSet;
SSACFG const* m_cfg;
AbstractAssembly* m_assembly;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are these pointers?

namespace solidity::yul::ssa::spill
{

class Emitter
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have to think somewhat more about this class.

@clonker clonker force-pushed the ssa-cfg-kiss-memspill branch from b93b4ac to 821b1df Compare June 2, 2026 08:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants