Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
86 commits
Select commit Hold shift + click to select a range
89946e7
Rotom layout alignment, assignment, and lowering
edwjchen May 21, 2026
a6ef15e
update
edwjchen May 21, 2026
42b39b4
Mask remap outputs in Rotom lowering, interpret tensor_ext.remap, add…
edwjchen Jun 11, 2026
617f6da
Merge remote-tracking branch 'upstream/main' into rotom_layout
edwjchen Jun 11, 2026
80f647f
Update Rotom tests to new dim/layout attribute syntax from upstream
edwjchen Jun 11, 2026
3bf9565
Rotom: enumerate slot-side single-roll layout variants
edwjchen Jun 13, 2026
d304d15
Rotom: end-to-end execution tests for rolled layouts
edwjchen Jun 13, 2026
fe55d54
Rotom: rotate-multiply-accumulate matmul kernel
edwjchen Jun 13, 2026
1378065
Rotom: ciphertext-axis diagonal/BSGS matvec + dense packing, e2e to M…
edwjchen Jun 21, 2026
19a5274
Rotom: normalize x.W^T matmuls so the diagonal kernel handles NN layers
edwjchen Jun 21, 2026
3c66bda
Rotom: address code-review findings (correctness + cleanup)
edwjchen Jun 22, 2026
93b5624
Rotom: straddle-aware ciphertext count; dedup layout-equality guard
edwjchen Jun 22, 2026
0febd46
Rotom: hoist matvec mask creation ahead of the rotation chain
edwjchen Jun 22, 2026
0e397ba
Rotom: route materializer func-arg propagation through AttributeUtils
edwjchen Jun 22, 2026
ec050e9
Rotom: extract row-vector matmul normalization into its own pass
edwjchen Jun 22, 2026
0329fd7
Rotom: share the diagonal BSGS schedule between the two matvec kernels
edwjchen Jun 22, 2026
dc9d27a
Rotom: return CtPrefix struct from inferCtPrefixLen
edwjchen Jun 22, 2026
7fb176d
Rotom: replace straddle role with a mixed-radix digit descriptor (ref…
edwjchen Jun 22, 2026
719775e
Rotom: stride is the within-axis mixed-radix divisor; getDim is the t…
edwjchen Jun 22, 2026
ce43e2e
Rotom: remove matmul/diagonal lowering, assignment, and normalize-mat…
edwjchen Jun 22, 2026
bb8cd8a
Rotom: drop straddle auto-split from inferCtPrefixLen
edwjchen Jun 22, 2026
7cb6d1b
Rotom: document preprocessLayoutData
edwjchen Jun 22, 2026
235e79b
Rotom: tighten preprocessLayoutData docstring
edwjchen Jun 22, 2026
62ed5d3
Rotom: require equal extents for roll pairs
edwjchen Jun 22, 2026
b3fe1e5
Rotom: trim roll equal-extent comment
edwjchen Jun 22, 2026
c19915c
Rotom: rename piece digit descriptor to pieceStride/pieceExtent
edwjchen Jun 22, 2026
1be6d49
Rotom: keep pieceDivBy/pieceModBy names; note Rotom stride/extent equ…
edwjchen Jun 22, 2026
7694ceb
Rotom: drop two stale inline comments in RotomAttributes
edwjchen Jun 22, 2026
18b8c88
Rotom: order pieceModBy before pieceDivBy to match [extent:stride]
edwjchen Jun 22, 2026
3aaccda
Rotom: add conversionMoves (slot-bit alignment diff) for elementwise
edwjchen Jun 22, 2026
4a817e6
Rotom: elementwise kernels via conversionMoves; drop dim-component al…
edwjchen Jun 22, 2026
eda2ea1
Rotom: drop dead Matmul KernelKind from layout assignment
edwjchen Jun 22, 2026
cb7dcad
Rotom: split layout assignment into generation and search phases
edwjchen Jun 22, 2026
f3ccfc5
Rotom: make the LayoutAttr inferCtPrefixLen adapter file-local
edwjchen Jun 22, 2026
e26e91c
Rotom: add shiftNetworkConversionCost (real VVE cost via tensor_ext b…
edwjchen Jun 22, 2026
5dedfd7
Rotom: use real shift-network conversion cost in elementwise layout s…
edwjchen Jun 22, 2026
c5848bc
Rotom: remove unverified roll enumeration; note per-op alignment TODO
edwjchen Jun 22, 2026
2497f20
Rotom: trim tests to the pipeline-related set
edwjchen Jun 22, 2026
7b98bb2
Rotom: emit convert-then-compute (convert_layout) for elementwise
edwjchen Jun 22, 2026
8bf3927
Rotom: restore foundational tests over-removed in cleanup
edwjchen Jun 22, 2026
fcbec81
Rotom: split LayoutAssignment.cpp into Candidate + DimMaps (refactor …
edwjchen Jun 22, 2026
05dbd22
Rotom: support subtraction in the elementwise lowering path
edwjchen Jun 22, 2026
7608ee1
Rotom: DAG-aware layout assignment via dedup'd accumulated cost
edwjchen Jun 22, 2026
5e6d999
Rotom: rename layout-assignment "cone" to "assignment"/"accumulated c…
edwjchen Jun 22, 2026
1e1dac2
Rotom: drop redundant anonymous namespace in RotomAttributes.cpp
edwjchen Jun 22, 2026
f57d686
Rotom: use mlir::debugString for candidate tie-key stringification
edwjchen Jun 22, 2026
dd1d674
Rotom: real conversion cost + op cost model (rotation/mul/add weights)
edwjchen Jun 22, 2026
f97e550
Rotom: cost reductions from the aligned input layout; clarify op-cost…
edwjchen Jun 22, 2026
bd2739f
Rotom: drop the ROTOM_COST_MODEL env hook and the conversion-cost fal…
edwjchen Jun 22, 2026
61aedfb
Rotom: drop dynamic-shape guards in DimMaps
edwjchen Jun 22, 2026
c24cf56
Rotom: de-optionalize remapLayoutDims
edwjchen Jun 23, 2026
6c79f1d
Rotom: tight per-function docstrings on the DimMaps dim-map helpers
edwjchen Jun 23, 2026
6525f28
Rotom: drop the verbose _comment from cost_model.json
edwjchen Jun 23, 2026
004afe6
Rotom: remove cost_model.json; the RotomCostModel struct is the sourc…
edwjchen Jun 23, 2026
43e6fbd
Rotom: drop redundant anonymous namespace in DimMaps.cpp
edwjchen Jun 23, 2026
59d339b
Rotom: prefer static over anonymous namespaces for file-local helpers
edwjchen Jun 23, 2026
c6aacdb
Rotom: fix rolled_tiled test to use the layout's true 4x4 shape
edwjchen Jun 24, 2026
4cca55a
Rotom: stop tracking the per-worktree bazel symlink
edwjchen Jun 24, 2026
6179a5e
Revert layout-equality guard: restore direct isEqual in the pattern m…
edwjchen Jun 24, 2026
5b36623
Rotom: route per-op layout generators through an AssignmentContext
edwjchen Jun 24, 2026
658d0f3
Rotom: extract layout value-type helpers into ValueUtils
edwjchen Jun 24, 2026
5ac78c2
Rotom: move per-op layout generators into per-category gen/ files
edwjchen Jun 24, 2026
6ecd614
Rotom: inline the single-caller inferCtPrefixLen(LayoutAttr) adapter
edwjchen Jun 28, 2026
9d5eaa0
Rotom: add ContractionAlignment, roll-free matmul plan enumeration (M1)
edwjchen Jul 2, 2026
3bd6ea6
Rotom: assign roll-free matmul layouts via generateMatmul (M2)
edwjchen Jul 2, 2026
da3932b
Rotom: lower roll-free matmul from assigned layouts (M3)
edwjchen Jul 2, 2026
bea6cbd
Rotom: canonicalize LayoutData traversal dims to ascending dim id
edwjchen Jul 2, 2026
a87c36a
Rotom: numerically verify roll-free matmul; fix the summed-k claim (M4)
edwjchen Jul 2, 2026
4e79888
Rotom: outline layout-assigned kernels into deduplicated functions
edwjchen Jul 2, 2026
a50e9df
Rotom: outline elementwise kernels; generalize the outliner
edwjchen Jul 2, 2026
ca55bcc
Rotom: price ciphertext-count-changing expansions instead of gating them
edwjchen Jul 2, 2026
f41f606
Rotom: allow rolling a traversal dim by a replication dim (R1 start)
edwjchen Jul 2, 2026
29e28bb
Rotom: allow rolling by a gap dim; rolled-by gaps claim their blocks
edwjchen Jul 5, 2026
c3b82f5
Rotom: wire ct-count-changing conversions into general search and low…
edwjchen Jul 5, 2026
cc8b962
Rotom: enumerate rolled ct-diagonal matmul plans (R1)
edwjchen Jul 5, 2026
2ff262f
Rotom: source-aware matmul operand pricing (R2)
edwjchen Jul 5, 2026
df551c6
Rotom: ciphertext-count carrying cost; validate replicate-then-roll (…
edwjchen Jul 5, 2026
9a29172
Rotom: spell replication/gap dims as R/G in the dim assembly form
edwjchen Jul 5, 2026
2d840cf
Rotom: enumerate slot-diagonal (Halevi-Shoup) rolled matmul plans
edwjchen Jul 5, 2026
fdc8292
Rotom: offer single-roll seed variants as general search candidates
edwjchen Jul 5, 2026
ab652aa
Rotom: route same-count conversions through explicit steps when cheaper
edwjchen Jul 6, 2026
eb94212
Rotom: roll-preserving hosting and free-swap diagonal results for matmul
edwjchen Jul 6, 2026
207cd21
Rotom: relax roll extents to mod-from semantics (non-square k)
edwjchen Jul 6, 2026
37e2a3d
Rotom: scaled and split-dim roll semantics (BSGS packing infrastructure)
edwjchen Jul 6, 2026
66efb7c
Rotom: baby-step/giant-step matmul plans (2*sqrt(D) rotations)
edwjchen Jul 6, 2026
9ef077a
Rotom: dense diagonal packing via slot-slack densified footprints
edwjchen Jul 6, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
# macOS
.DS_Store

# bazel output symlinks
bazel-bin
bazel-heir
bazel-out
bazel-testlogs
# bazel output symlinks (bazel-bin, bazel-out, bazel-testlogs, and the
# per-workspace/worktree bazel-<dir> convenience symlink)
/bazel-*

# default cmake output directory
build/
Expand Down
234 changes: 203 additions & 31 deletions lib/Dialect/Rotom/IR/RotomAttributes.cpp

Large diffs are not rendered by default.

15 changes: 15 additions & 0 deletions lib/Dialect/Rotom/IR/RotomAttributes.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,26 @@ struct LayoutData {
llvm::SmallVector<DimAttr> gapDims;
llvm::SmallVector<LayoutPieceKind> pieces;
llvm::SmallVector<int64_t> pieceIndex;
// pieceModBy and pieceDivBy are a piece's Rotom extent and stride (from
// [dim:extent:stride]), named for how the emitter consumes them: the mixed-
// radix digit of tensor index i is (i / pieceDivBy) mod pieceModBy. pieceModBy
// is 0 on the most-significant digit of an axis -- there i / pieceDivBy is
// already below the extent, so the modulus is redundant and dropped. A whole
// dim packed as one piece uses pieceModBy 0 and pieceDivBy 1 => digit == i;
// the same holds for non-traversal pieces.
llvm::SmallVector<int64_t> pieceModBy;
llvm::SmallVector<int64_t> pieceDivBy;
};

/// Preprocess a Rotom layout.
FailureOr<LayoutData> preprocessLayoutAttr(LayoutAttr attr);

/// Computes how many leading entries of `dims` (read left-to-right) fall on the
/// ciphertext axis for a ciphertext of `n` slots: the prefix that does not fit
/// into the remaining slot budget. Shared so attribute preprocessing and the
/// layout cost utilities derive the ct/slot split identically.
size_t inferCtPrefixLen(llvm::ArrayRef<DimAttr> dims, int64_t n);

} // namespace mlir::heir::rotom

#endif // LIB_DIALECT_ROTOM_IR_ROTOMATTRIBUTES_H_
27 changes: 23 additions & 4 deletions lib/Dialect/Rotom/IR/RotomAttributes.td
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ def Rotom_DimAttr : Rotom_Attr<"Dim", "dim"> {
* `-1`: replication (logical fill along this layout piece)
* `-2`: gap (padding / unused slots; constrained to zero in materialization)

Non-negative `dim` values index into the logical tensor shape.
Non-negative `dim` values index into the logical tensor shape. In the
assembly form the sentinels are spelled `R` (replication) and `G` (gap),
e.g. `[R:4:1]`; the numeric ids are also accepted on input.
}];

let parameters = (ins
Expand Down Expand Up @@ -57,14 +59,27 @@ def Rotom_LayoutAttr : Rotom_Attr<"Layout", "layout"> {

Optional **rolls** encode a `roll(i,j)` metadata object: each pair `(i, j)`
indexes into the `dims` array (the flattened `ct_dims + slot_dims` list) and
uses modular addition to modify the indices of `dims[i]` by the indices of
`dims[j]`.
rewrites `dims[i]`'s index to `(idx_i - s * idx_j) mod extent(dims[i])`,
where the scale `s` defaults to 1 and may be spelled as a third tuple
element `(i, j, s)`. The two extents need not match: the shift reduces
modulo the rolled dim's extent, so a smaller partner covers a prefix of the
rotations and a larger one wraps.

When a traversal dim is packed as several mixed-radix pieces, a roll FROM
any of its pieces rewrites the whole dim's index (each piece then takes its
digit of the rolled index), and a roll BY one of its pieces shifts by that
piece's digit -- together with a scale this expresses baby-step/giant-step
diagonal packings.

Optional **rollScales** stores one scale per roll pair; it must be omitted
when every scale is 1 (the canonical form the parser and builders produce).
}];

let parameters = (ins
"::mlir::ArrayAttr":$dims,
"int64_t":$n,
OptionalParameter<"::mlir::DenseI64ArrayAttr">:$rolls
OptionalParameter<"::mlir::DenseI64ArrayAttr">:$rolls,
OptionalParameter<"::mlir::DenseI64ArrayAttr">:$rollScales
);

let genVerifyDecl = 1;
Expand All @@ -74,6 +89,10 @@ def Rotom_LayoutAttr : Rotom_Attr<"Layout", "layout"> {
/// Layout with no `roll(i,j)` metadata (empty rolls storage).
static ::mlir::heir::rotom::LayoutAttr get(::mlir::MLIRContext *context,
::mlir::ArrayAttr dims, int64_t n);
/// Layout with unit-scale rolls (empty scale storage).
static ::mlir::heir::rotom::LayoutAttr get(::mlir::MLIRContext *context,
::mlir::ArrayAttr dims, int64_t n,
::mlir::DenseI64ArrayAttr rolls);
}];
}

Expand Down
92 changes: 91 additions & 1 deletion lib/Dialect/Rotom/Transforms/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,62 @@ package(
default_visibility = ["//visibility:public"],
)

add_heir_transforms(
generated_target_name = "layout_assignment_pass_inc_gen",
header_filename = "LayoutAssignment/LayoutAssignment.h.inc",
pass_name = "LayoutAssignment",
registration_name = "RotomLayoutAssignment",
td_file = "LayoutAssignment/LayoutAssignment.td",
)

cc_library(
name = "LayoutAssignment",
srcs = [
"LayoutAssignment/Candidate.cpp",
"LayoutAssignment/CostModel.cpp",
"LayoutAssignment/DimMaps.cpp",
"LayoutAssignment/LayoutAssignment.cpp",
"LayoutAssignment/ValueUtils.cpp",
"LayoutAssignment/gen/Contraction.cpp",
"LayoutAssignment/gen/Elementwise.cpp",
"LayoutAssignment/gen/ReduceTranspose.cpp",
"LayoutAssignment/gen/Reshape.cpp",
"LayoutAssignment/gen/Structural.cpp",
],
hdrs = [
"LayoutAssignment/AssignmentContext.h",
"LayoutAssignment/Candidate.h",
"LayoutAssignment/CostModel.h",
"LayoutAssignment/DimMaps.h",
"LayoutAssignment/Generators.h",
"LayoutAssignment/LayoutAssignment.h",
"LayoutAssignment/ValueUtils.h",
],
deps = [
":layout_assignment_pass_inc_gen",
"@heir//lib/Dialect/Rotom/IR:Dialect",
"@heir//lib/Dialect/Rotom/Utils:ContractionAlignment",
"@heir//lib/Dialect/Rotom/Utils:LayoutAlignment",
"@heir//lib/Dialect/Rotom/Utils:RotomTensorExtLayoutLowering",
"@heir//lib/Dialect/Secret/IR:SecretPatterns",
"@heir//lib/Dialect/TensorExt/IR:Dialect",
"@heir//lib/Kernel",
"@heir//lib/Utils:AttributeUtils",
"@heir//lib/Utils/Layout:IslConversion",
"@heir//lib/Utils/Layout:Utils",
"@heir//lib/Utils:MathUtils",
"@llvm-project//llvm:Support",
"@llvm-project//mlir:ArithDialect",
"@llvm-project//mlir:DialectUtils",
"@llvm-project//mlir:FuncDialect",
"@llvm-project//mlir:IR",
"@llvm-project//mlir:LinalgDialect",
"@llvm-project//mlir:Pass",
"@llvm-project//mlir:Support",
"@llvm-project//mlir:TensorDialect",
],
)

add_heir_transforms(
generated_target_name = "materialize_tensor_ext_layout_pass_inc_gen",
header_filename = "MaterializeTensorExtLayout/MaterializeTensorExtLayout.h.inc",
Expand All @@ -24,16 +80,47 @@ cc_library(
":materialize_tensor_ext_layout_pass_inc_gen",
"@heir//lib/Dialect/Rotom/IR:Dialect",
"@heir//lib/Dialect/Rotom/Utils:RotomTensorExtLayoutLowering",
"@heir//lib/Dialect/Secret/IR:Dialect",
"@heir//lib/Dialect/TensorExt/IR:Dialect",
"@heir//lib/Utils",
"@heir//lib/Utils:AttributeUtils",
"@llvm-project//llvm:Support",
"@llvm-project//mlir:FuncDialect",
"@llvm-project//mlir:IR",
"@llvm-project//mlir:Pass",
"@llvm-project//mlir:Support",
],
)

add_heir_transforms(
generated_target_name = "outline_kernels_pass_inc_gen",
header_filename = "OutlineKernels/OutlineKernels.h.inc",
pass_name = "OutlineKernels",
registration_name = "RotomOutlineKernels",
td_file = "OutlineKernels/OutlineKernels.td",
)

cc_library(
name = "OutlineKernels",
srcs = ["OutlineKernels/OutlineKernels.cpp"],
hdrs = ["OutlineKernels/OutlineKernels.h"],
deps = [
":outline_kernels_pass_inc_gen",
"@heir//lib/Dialect/Rotom/IR:Dialect",
"@heir//lib/Dialect/Rotom/Utils:ContractionAlignment",
"@heir//lib/Dialect/Secret/IR:Dialect",
"@heir//lib/Utils:AttributeUtils",
"@llvm-project//llvm:Support",
"@llvm-project//mlir:ArithDialect",
"@llvm-project//mlir:FuncDialect",
"@llvm-project//mlir:IR",
"@llvm-project//mlir:LinalgDialect",
"@llvm-project//mlir:Pass",
"@llvm-project//mlir:Support",
"@llvm-project//mlir:TensorDialect",
],
)

add_heir_transforms(
generated_target_name = "seed_layout_pass_inc_gen",
header_filename = "SeedLayout/SeedLayout.h.inc",
Expand Down Expand Up @@ -63,17 +150,20 @@ cc_library(
"@llvm-project//mlir:IR",
"@llvm-project//mlir:Pass",
"@llvm-project//mlir:Support",
"@llvm-project//mlir:TensorDialect",
],
)

cc_library(
name = "Transforms",
hdrs = ["Passes.h"],
deps = [
":LayoutAssignment",
":MaterializeTensorExtLayout",
":OutlineKernels",
":SeedLayout",
":layout_assignment_pass_inc_gen",
":materialize_tensor_ext_layout_pass_inc_gen",
":outline_kernels_pass_inc_gen",
":seed_layout_pass_inc_gen",
"@heir//lib/Dialect/Rotom/IR:Dialect",
"@llvm-project//mlir:Pass",
Expand Down
55 changes: 55 additions & 0 deletions lib/Dialect/Rotom/Transforms/LayoutAssignment/AssignmentContext.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#ifndef LIB_DIALECT_ROTOM_TRANSFORMS_LAYOUTASSIGNMENT_ASSIGNMENTCONTEXT_H_
#define LIB_DIALECT_ROTOM_TRANSFORMS_LAYOUTASSIGNMENT_ASSIGNMENTCONTEXT_H_

#include <cstdint>
#include <optional>

#include "lib/Dialect/Rotom/IR/RotomAttributes.h"
#include "lib/Dialect/Rotom/Transforms/LayoutAssignment/Candidate.h"
#include "lib/Kernel/KernelName.h"
#include "mlir/include/mlir/IR/Operation.h" // from @llvm-project
#include "mlir/include/mlir/IR/Value.h" // from @llvm-project
#include "mlir/include/mlir/Support/LLVM.h" // from @llvm-project

namespace mlir::heir::rotom {

// The narrow interface the per-op candidate generators use to read and write
// the candidate map and query costs, so each generator depends only on this
// rather than on the LayoutAssignment pass struct. The pass implements it.
class AssignmentContext {
public:
virtual ~AssignmentContext() = default;

// Seed `value` from its rotom.seed attribute (no-op if already processed).
virtual void seedValue(Value value) = 0;

// The candidate layouts assigned to `value` (seeding it first if needed).
virtual SmallVector<Candidate> candidatesForValue(Value value) = 0;

// Record `newCandidates` as the candidates for `value`, after validating and
// folding each into its assignment.
virtual void setCandidates(Value value,
ArrayRef<Candidate> newCandidates) = 0;

// Set the chosen candidate set on every tensor result of `op`.
virtual void assignResultsFromCandidates(Operation* op,
ArrayRef<Candidate> chosen) = 0;

// Bring all of `op`'s operands onto a common result layout (the generic
// N-operand combiner).
virtual SmallVector<Candidate> chooseCommonOperandCandidates(
Operation* op, KernelKind kind) = 0;

// The specialized binary convert-then-compute combiner (add/sub/mul).
virtual SmallVector<Candidate> chooseElementwiseKernels(
ArrayRef<Value> operands, KernelKind kind,
function_ref<int64_t(LayoutAttr)> computeCostFn,
std::optional<KernelName> rotomKernel = std::nullopt) = 0;

// Real (cached) rotation cost of converting `from` onto `to`.
virtual int64_t cachedConversionCost(LayoutAttr from, LayoutAttr to) = 0;
};

} // namespace mlir::heir::rotom

#endif // LIB_DIALECT_ROTOM_TRANSFORMS_LAYOUTASSIGNMENT_ASSIGNMENTCONTEXT_H_
Loading