Skip to content

Transform.runProgram return an extra updated bool result, add analysis cache, and updates to ProcedureInlining#377

Open
aqjune-aws wants to merge 21 commits intomainfrom
jlee/inline-planner
Open

Transform.runProgram return an extra updated bool result, add analysis cache, and updates to ProcedureInlining#377
aqjune-aws wants to merge 21 commits intomainfrom
jlee/inline-planner

Conversation

@aqjune-aws
Copy link
Contributor

@aqjune-aws aqjune-aws commented Feb 3, 2026

Description of changes:

  1. The definition of Transform.runProgram now returns (updated, new program), and receives an extra optional arg allowProcList : Option (List String) that makes the transformation only run on specific procedures.

The goal of this change is to allow the user iteratively apply the transformation to the specific procedure (e.g., the "main" function) until there is no change anymore.

  1. Add doInline fn to Procedure Inlining, let CoreTransformState cache the result of expensive analysis like CallGraph construction.

In this patch, ProcedureInlining.inlineCallCmd takes a more generic lambda function doInline that receives the calling procedure name as well as the CallGraph data structure and decide whether to inline or not.
Since building CallGraph every time is expensive, CallGraph is incrementally updated after each inlining.
To keep the latest status of CallGraph, we have a new CoreTransformState datatype which tracks analyses cache, and it is the transformation's responsibility that must invalidate or correctly update the cache. This mimics what LLVM's passes do.
From the CallGraph, you can check whether e.g., there is only one caller of some procedure or not.

Also, since we have CoreTransformState, more cleaups to the signatures of transformation functions were possible. The transformation passes were originally taking an extra source Program argument that was being transformed, but this was awkward because transformations are defined at the Statement level. This removes the extra argument, and makes CoreTransformState track the currently modifying Program and Procedure.

  1. The Program.filterProcedures function is extracted out as a new transformation called FilterProcedure.

The new Program.filterProcedures introduced in #375 was extracted out to FilterProcedure because I thought that the correctness of this FilterProcedure can be very nicely described. :) To address the comment that I left in the pull request, I made FilterProcedure a standalone transform that is not parameteric to other transformations.
Also, there is performance win - combined with the AnalysisCache, now CallGraph is calculated inside FilterProcedure once, reused in ProcedureInlining, then reused in the second FilterProcedure!

Also, the proofs in CallElimCorrect is commentized even more.

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

@thanhnguyen-aws

@aqjune-aws aqjune-aws marked this pull request as ready for review February 4, 2026 19:29
@aqjune-aws aqjune-aws requested a review from a team as a code owner February 4, 2026 19:29
@aqjune-aws aqjune-aws changed the title Add a bool function to ProcedureInlining that determines whether to inline the call or not Transform.runProgram return an extra updated bool result, add analysis cache, and updates to ProcedureInlining Feb 4, 2026
Copy link
Contributor

@shigoel shigoel left a comment

Choose a reason for hiding this comment

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

Looks great, in general! Thank you.

@@ -418,7 +420,13 @@ def verify (smtsolver : String) (program : Program)
-- Verify specific procedures. By default, we apply the call elimination
-- transform to the targeted procedures to inline the contracts of any
-- callees.
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we clarify "apply call elim"? Specifically, I could imagine it's applied once, vs until fixpoint vs until we reach a procedure not in this list vs max N.

def CachedAnalyses.emp : CachedAnalyses := {}

/-- Define the state of transformation in Strata Core.
It is the duty of the transformation to keep the analysis cache keep the
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
It is the duty of the transformation to keep the analysis cache keep the
It is the duty of the transformation to update the analysis cache to keep the

Visit all procedures and run f
NOTE: please use runProgram if possible since CoreTransformState might result
in an inconsistent state. This function is for partial implementation.
-/
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe document that the Bool in Bool \times List Decl corresponds to changed (or better make a struct for the return value)?

return ({ c with body := new_body, header := new_header }, var_map)


/-- Update the call graph after inlining one f(caller) -> g(callee) invocation. -/
Copy link
Contributor

@andrewmwells-amazon andrewmwells-amazon Feb 6, 2026

Choose a reason for hiding this comment

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

Is this correct for a recursive function (or do we prevent constructing CGs for/inlining recursive functions)?

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