Skip to content

Deforestation mk4#406

Merged
LPTK merged 95 commits intohkust-taco:hkmc2from
ychenfo:hkmc2-deforest-new-new
Mar 15, 2026
Merged

Deforestation mk4#406
LPTK merged 95 commits intohkust-taco:hkmc2from
ychenfo:hkmc2-deforest-new-new

Conversation

@ychenfo
Copy link
Member

@ychenfo ychenfo commented Mar 8, 2026

Supersedes and closes #335

@LPTK LPTK force-pushed the hkmc2 branch 2 times, most recently from 46c5ce1 to 414cf0c Compare March 10, 2026 15:42
@ychenfo ychenfo force-pushed the hkmc2-deforest-new-new branch from 21b6e91 to a4b9fbf Compare March 12, 2026 20:30
@LPTK LPTK requested a review from Copilot March 13, 2026 10:58
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds a deforestation optimization pass to the hkmc2 compiler. Deforestation is an optimization that eliminates intermediate data structures by fusing producers (constructors) with consumers (pattern matches/selections). The PR supersedes PR #335.

Changes:

  • Adds a complete deforestation pipeline: pre-analysis, constraint collection, constraint solving, and rewriting phases
  • Integrates the deforestation pass into the lowering pipeline, controlled by a :deforest command
  • Fixes determinism in the SCC partitioning algorithm and adds supporting infrastructure changes

Reviewed changes

Copilot reviewed 27 out of 27 changed files in this pull request and generated no comments.

Show a summary per file
File Description
hkmc2/shared/src/main/scala/hkmc2/Config.scala Adds Deforest config case class and deforest field to Config
hkmc2DiffTests/src/test/scala/hkmc2/MLsDiffMaker.scala Adds :deforest command for test files
hkmc2/shared/src/main/scala/hkmc2/Uid.scala Adds Result and StratVar UID handlers for deforestation
hkmc2/shared/src/main/scala/hkmc2/codegen/Block.scala Sets tsym on BlockMemberSymbol in FunDefn.withFreshSymbol
hkmc2/shared/src/main/scala/hkmc2/codegen/LambdaRewriter.scala Refactors to use FunDefn.withFreshSymbol
hkmc2/shared/src/main/scala/utils/TraceLogger.scala Widens emitDbg visibility to protected[hkmc2]
core/shared/main/scala/utils/algorithms.scala Fixes nondeterminism in SCC by using LinkedHashSet
hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala Integrates deforestation pass into lowering pipeline
hkmc2/shared/src/main/scala/hkmc2/codegen/deforest/Deforest.scala Core types, extractors, and entry point for deforestation
hkmc2/shared/src/main/scala/hkmc2/codegen/deforest/Analyze.scala Pre-analysis, constraint collection, and constraint solving
hkmc2/shared/src/main/scala/hkmc2/codegen/deforest/Rewrite.scala Rewriting pass that applies deforestation transformations
hkmc2/shared/src/test/mlscript/deforest/*.mls Comprehensive test suite for deforestation (12 test files)

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Contributor

@LPTK LPTK left a comment

Choose a reason for hiding this comment

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

Ok, I don't have time to review everything in detail at this time, but I believe this is more or less ready to merge!

end DeforestConstraintsCollector


class DeforestConstrainSolver(val collector: DeforestConstraintsCollector):
Copy link
Contributor

Choose a reason for hiding this comment

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

Doesn't this belong in its own file?

Copy link
Member Author

Choose a reason for hiding this comment

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

I think maybe it's reasonable to keep them here for now, they are indeed both part of the analysis phase and the classes are not particularly large (~260 loc).

Copy link
Contributor

Choose a reason for hiding this comment

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

Ok, fair enough.

inline def exit() = indent -= 1

protected def emitDbg(str: Str): Unit = scala.Predef.println(str)
protected[hkmc2] def emitDbg(str: Str): Unit = scala.Predef.println(str)
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think this change is needed?

Copy link
Member Author

Choose a reason for hiding this comment

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

In Lowering.scala I make a new traceLogger to output fusion opportunities, and its emitDbg need to use the emitDbg from lowering traceLogger (not inherited), so I think I need protected[hkmc2] to widen access...

Copy link
Contributor

Choose a reason for hiding this comment

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

Why not pass the same TraceLogger as for lowering?

Copy link
Member Author

Choose a reason for hiding this comment

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

Oh, my intention is that deforest's tracelogger can be enabled independently of lowering tracing. If we reused the same tracelogger, we would have to enable lowering debug just to see deforest summary. The emitDbg calling the lowering tracelogger's emitDbg is just so the output still goes to the same place, prefixed by "deforest > ".

@LPTK LPTK merged commit 763d788 into hkust-taco:hkmc2 Mar 15, 2026
1 check passed
@LPTK LPTK deleted the hkmc2-deforest-new-new branch March 15, 2026 14:36
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.

3 participants