Skip to content

Implementation of loop support in PolyMulToNTT - #3295

Draft
crockeea wants to merge 1 commit into
google:mainfrom
crockeea:regionbranchopiface
Draft

Implementation of loop support in PolyMulToNTT#3295
crockeea wants to merge 1 commit into
google:mainfrom
crockeea:regionbranchopiface

Conversation

@crockeea

@crockeea crockeea commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator

Fixes #2685
This PR adds support for RegionBranchOpInterface to PolyMulToNTT, enabling NTT optimization inside things like for loops, if statements, and while loops.

Assisted by AI.

@crockeea
crockeea force-pushed the regionbranchopiface branch from ae099e6 to 04feed0 Compare August 4, 2026 21:34
@crockeea
crockeea force-pushed the regionbranchopiface branch from 43b5865 to 37803c5 Compare August 4, 2026 21:54

@j2kun j2kun left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[edit]: looks mostly good! I see one issue that I think would have a big impact on the solver's output optimality.

module {
// Covers: an scf.for iter_arg that needs both forms -- coeff to match its
// entry operand/loop result (consumed by to_tensor, coeff-only) and eval to
// feed the eval-only MulOp in the loop body. The NTT/INTT pair is hoisted

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Wouldn't it be more optimal to apply NTT once before the loop even begins, and then INTT once after the loop ends, rather than in each loop iteration?

// CHECK: [[t2:%.+]] = polynomial.to_tensor [[x2]] : [[poly_ty_1]] -> tensor<1024x[[RNS]]>
// CHECK: [[m2:%.+]] = polynomial.mul [[r2]], [[r2]] : [[ntt_poly_ty_1]]
// CHECK: return [[t2]], [[m2]] : tensor<1024x[[RNS]]>, [[ntt_poly_ty_1]]
func.func @if_yields_both_branches(%cond: i1, %x: !poly_ty_1) -> (tensor<1024x!rns.rns<!Zq0>>, !poly_ty_1) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think it would be useful to have a test case where an if statement requires two different forms in the two different branches.

// forwarding operands that feed it to match.
llvm::DenseMap<Value, Form> successorNativeForm;
for (Value target : polySuccessorInputs) {
Form f = soln.needsForm(target, Form::COEFF) ? Form::COEFF : Form::EVAL;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I feel like this is what's making the for_iter_arg_needs_both_forms test feel incorrect to me.

In my view, it's not that the successor input must have COEFF form if it has uses of both in different branches, but that all region successor operands and all corresponding successor inputs must have the same form (you can't change form during a control flow branch), and then allow the solver to choose which form it is based on the implied cost of changing form before/after the branch.

In the for_iter_arg_needs_both_forms test, it would require x, acc, sq and r to all have the same form. If they're all coeff, the ntt/intt would be in the loop and have cost given by the lb/ub (which I guess is the default 1k iterations in that example?), and if they're all eval, then it would have to insert conversions for x and for r.

@crockeea
crockeea marked this pull request as draft August 7, 2026 16:49
@crockeea

crockeea commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator Author

Your review exposed some major gaps (thank you!) which will take some time to fix. I'll let you know when I'm ready again.

@j2kun

j2kun commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator

Given that the gaps are optimizations, we could merge what you have and follow up with the improvements in a second PR. Up to you.

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.

Add region support in PolyMulToNTT

2 participants