Skip to content

Remove old layout code#2199

Merged
copybara-service[bot] merged 1 commit intogoogle:mainfrom
j2kun:remove-old-layout
Oct 10, 2025
Merged

Remove old layout code#2199
copybara-service[bot] merged 1 commit intogoogle:mainfrom
j2kun:remove-old-layout

Conversation

@j2kun
Copy link
Collaborator

@j2kun j2kun commented Sep 8, 2025

This PR removes the old layout code (based on plain affine maps and alignment attributes) and migrates all existing code paths to the new layout system based on integer relations.

I will attempt to summarize the many changes that went into this. The short version is: I had to clean up a lot of technical debt from our prior lack of support for multi-packed ciphertexts, and this impacted pretty much every part of the arithmetic pipelines.

Pipeline changes

  • Following from Make BGV/CKKS ops elementwise-mappable, and add ElementwiseByOperandOpInterface #2277, now that most scheme-level ops are elementwise mappable, the central mlir-to-rlwe pipeline now has a elementwise-to-affine step that converts batch scheme ops to loops.
  • implement-shift-network has been added to the mlir-to-secret-arithmetic subpipeline
  • As the new layout system uses the new implement-rotate-and-reduce baby-step giant-step optimization, this can produce rotations of server-side constant plaintexts, and those are not lowered in secret-to-scheme because they have no secret operands or results. So the arithmetic pipelines now have a step of tensor-ext-to-tensor after all secret tensor-ext ops are lowered.
  • Similarly, a new canonicalization pattern, FoldRotateOfConst, was added to fold a rotated dense constant (e.g., a plaintext mask) to the corresponding pre-rotated dense constant.
  • Minor: a new step for fold-constant-tensors was added to help simplify extract_slice of tensor.splat which occurred as an edge case of the cmux test; the then/else branches were dynamically-valued cleartext scalars but the test was a ciphertext, so the then/else values got layouts implemented as a splat, and then were immediately slice-extracted for plaintext-ciphertext ops. So this pattern folds that to another splat and removes the original splat.

Pass changes

General

  • Most conversion passes needed extra support in their type converters for tensors-of-secret things to accommodate the new elementwise versions of each op.
  • Many places in the codebase assumed a type was a scalar ciphertext/plaintext type, and needed to have some version of getElementTypeOrSelf to replace it.
  • Various validations checked the shape of a tensor was exactly {numSlots} and this was changed to check the trailing axis.
  • Patterns for various tensor ops (insert/insert_slice, extract/extract_slice, empty, splat, from_elements) were added in many lowerings. This is needed mainly because some APIs weren't sensible to make elementwise (e.g., openfhe make_packed_plaintext can't be elementwise because the OpenFHE API doesn't support this)
  • Some analysis passes required slight tweaks to support tensor operations that had no impact on noise.
  • addTensorConversionPatterns was added to generically type-convert operands and results of "blind" tensor ops in lowerings like lwe-to-lattigo.
  • Many llvm_runner tests were using StridedMemRefType<int64_t> for the C API, which defaults to a rank-1 tensor, and so for multi-packed ciphertexts these were updated to StridedMemRefType<int64_t, 2> or similar.
  • A variety of tests were reorganized and renamed to better match the lib/ structure.

secret-to-<scheme>

  • Support for insert/extract slice in secret-to-scheme conversions are limited to operating on full ciphertexts (i.e., you can only extract a slice from a ciphertext-semantic tensor if you're extracting one or more full rows).
  • "encode" ops are not elementwise, so the way to handle encoding a multi-packed plaintext is to extract-slice all the rows, encode each one, and from_elements them back together.

secret-to-mod-arith

  • A bug was fixed in that, due to a namespace conflict, secret-to-mod-arith was using context-aware conversion patterns when it should not have been.

secret-to-ckks

This pass had a number of hard-coded handling of "multi-packed" ciphertexts that were added purely to make the initial halevi-shoup matvec demo work from Summer of 2024. This code is all removed and the corresponding ops are supported in generality.

tensor-ext-to-tensor

(submitted separately as #2291)

layout-propagation

  • OperandLayoutRequirementOpInterface got a new isSecret option because tensor.insert has two regimes: if it's inserting a cleartext scalar into a plaintext or ciphertext, the scalar does not require a layout. If it's inserting a ciphertext scalar, then the scalar does require a layout.
  • A hook for rectifyIncompatibleOperandLayouts was added for tensor.insert, which handles the case of inserting a secret scalar into a secret destination by layout-converting the scalar to the same layout as the dest tensor. This is bad but it's also bad to insert scalars into secret tensors so I don't expect this kernel to be used all that much. (It was in a test that did a manual matvec mul by a nested loop with inner body extract, mul, sum, insert)
  • The default layout for the result of a tensor.extract op now does not require replicating the scalar to all slots. This allows us to avoid some layout conversions that are unnecessary when the tensor.extract is the last operation in the IR, and in other cases where the result is used in a way that doesn't strictly require full replication of the scalar in every slot.

secret-insert-mgmt

All these passes now add mgmt.init ops for relevant tensor operations that have plaintext operands (e.g., insert_slice into a plaintext tensor.empty)

Emitter Changes

  • Lattigo and OpenFHE emitters are completely converted to "flattened" tensor types (e.g., all code-genned vector-like types are 1D and all access indices are code-genned in a flattened form). This brings both emitters in line, such that more codegen can be shared between the two. All restrictions on tensor shapes are removed.
  • SCF codegen was added to the lattigo emitter
  • A bug was fixed in the lattigo emitCopySlice where assignment done inside a loop was causing it to shadow (via lexical scope) the actual destination of the copy.

Issues

  • The debug logging mechanism is now unable to unpack, and so logged results are packed cleartexts Cf. Reconsider "application data" field on LWE ciphertext #2280 for places where this occurs.
  • To tests (matmul_loop.mlir and matmul_unrolled.mlir) were removed because, while they compiled successfully with the new code, the generated code was quite large and the tests became slow. Asra and I agreed we don't need these tests anymore.

@j2kun j2kun marked this pull request as draft September 8, 2025 17:38
@j2kun j2kun changed the title start removing old layout code Remove old layout code Sep 8, 2025
@j2kun j2kun force-pushed the remove-old-layout branch 7 times, most recently from 44ba3d9 to 6e983c4 Compare September 27, 2025 03:16
@j2kun j2kun force-pushed the remove-old-layout branch 4 times, most recently from 6c34244 to 3c6d4a2 Compare October 4, 2025 20:24
@j2kun j2kun force-pushed the remove-old-layout branch 2 times, most recently from a6d2649 to 1eeb9ea Compare October 5, 2025 03:21
@j2kun j2kun requested a review from asraa October 7, 2025 03:42
@j2kun j2kun force-pushed the remove-old-layout branch from 7bc3d56 to 9dd6e1a Compare October 7, 2025 03:52
@j2kun j2kun marked this pull request as ready for review October 7, 2025 04:20
@j2kun j2kun force-pushed the remove-old-layout branch 3 times, most recently from 1c874f3 to e674615 Compare October 7, 2025 17:19
j2kun referenced this pull request in google/github_workflows_playground Oct 8, 2025
Copy link
Collaborator

@asraa asraa left a comment

Choose a reason for hiding this comment

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

phew! appreciate so much how much the PR description helped here

This PR removes the old layout code (based on plain affine maps and
alignment attributes) and migrates all existing code paths to the new
layout system based on integer relations.

As a byproduct, this commit adds support for multi-packed ciphertexts
through the entire arithmetic pipeline of HEIR.

Co-authored-by: asraa <asraa@google.com>
@j2kun j2kun force-pushed the remove-old-layout branch from 15bbdfe to 49b6f20 Compare October 9, 2025 22:42
@j2kun j2kun added the pull_ready Indicates whether a PR is ready to pull. The copybara worker will import for internal testing label Oct 9, 2025
@copybara-service copybara-service bot merged commit b28cb06 into google:main Oct 10, 2025
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pull_ready Indicates whether a PR is ready to pull. The copybara worker will import for internal testing

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants