Skip to content

Commit 868d7cf

Browse files
hunhoffeclaude
andcommitted
[dyn-seq] Trim dma_bd SSA comments per review
Apply Andrej's review suggestions (AIE.td arith dependency, dma_bd offset/len docs, buildWithConstants) and give the sibling comments the same concise treatment: drop the internal cross-references and upstream-op name-drops, keep the load-bearing "why". Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 9c63091 commit 868d7cf

5 files changed

Lines changed: 46 additions & 85 deletions

File tree

include/aie/Dialect/AIE/IR/AIE.td

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,9 @@ def AIE_Dialect : Dialect {
2626
}];
2727
let useDefaultTypePrinterParser = 1;
2828
let useDefaultAttributePrinterParser = 1;
29-
// Several AIE constructs materialize arith ops via the builder API (e.g. the
30-
// Python wrappers in dialects/aie.py build arith.constant for runtime scalar
31-
// operands, and AIEX lowerings emit arith into runtime_sequence bodies). MLIR
32-
// requires dependent dialects to be pre-loaded before ops referencing them may
33-
// be built, so declaring the dependency at dialect level is the safe placement.
29+
// Python wrappers in dialects/aie.py and AIEX lowerings emit arith.constant
30+
// and other operations, so this dialect depends on arith being available.
3431
let dependentDialects = ["::mlir::arith::ArithDialect"];
3532
}
3633

37-
#endif // AIE_BASE
34+
#endif // AIE_BASE

include/aie/Dialect/AIE/IR/AIEOps.td

Lines changed: 14 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -982,12 +982,10 @@ def AIE_DMABDOp: AIE_Op<"dma_bd", [AttrSizedOperandSegments]> {
982982

983983
let arguments = (
984984
ins AnyRankedOrUnrankedMemRef:$buffer,
985-
// offset/len are denominated in element width (not bytes). Like the
986-
// sizes/strides DynamicIndexList below (and aiex.npu.dma_memcpy_nd's
987-
// static_offsets), a compile-time constant lands in the
988-
// $static_offset/$static_len attribute while a runtime value becomes the
989-
// $offset/$len SSA operand. Absent operand AND attr means offset 0 /
990-
// full-buffer len.
985+
// offset/len are denominated in element width (not bytes).
986+
// Can be given as a static attribute or a runtime SSA value. If neither
987+
// are given, we assume zero for the offset and the memref's full buffer
988+
// length for the length.
991989
Optional<I32>:$offset,
992990
Optional<I32>:$len,
993991
OptionalAttr<AIEI32Attr>:$static_offset,
@@ -1032,20 +1030,17 @@ def AIE_DMABDOp: AIE_Op<"dma_bd", [AttrSizedOperandSegments]> {
10321030
// constant offset/len to the static_offset/static_len attributes (no
10331031
// arith.constant materialized) and decomposes a BDDimLayoutArrayAttr
10341032
// (outermost-first) into all-static static_sizes / static_strides arrays (no
1035-
// dynamic operands). Keeps every historical int-argument producer call site
1036-
// source-compatible.
1033+
// dynamic operands).
10371034
static void buildWithConstants(
10381035
::mlir::OpBuilder &builder, ::mlir::OperationState &state,
10391036
::mlir::Value buffer, int32_t offset, int32_t len,
10401037
BDDimLayoutArrayAttr dims, BDPadLayoutArrayAttr padDims,
10411038
PacketInfoAttr packet);
10421039

10431040
// Mixed static/dynamic builder: splits offset/len and each sizes/strides
1044-
// entry (a constant attribute or an SSA Value) into the operand + static
1045-
// attribute pair via the upstream dispatchIndexOpFoldResults helper, exactly
1046-
// like tensor.extract_slice. An empty sizes/strides list leaves the
1047-
// corresponding static array unset so it elides; a null offset/len leaves
1048-
// both its operand and attribute unset.
1041+
// entry into the operand + static attribute pair via the upstream
1042+
// dispatchIndexOpFoldResults helper. An empty sizes/strides list leaves the
1043+
// corresponding static array unset so it elides.
10491044
static void buildMixed(
10501045
::mlir::OpBuilder &builder, ::mlir::OperationState &state,
10511046
::mlir::Value buffer, ::mlir::OpFoldResult offset,
@@ -1061,12 +1056,9 @@ def AIE_DMABDOp: AIE_Op<"dma_bd", [AttrSizedOperandSegments]> {
10611056
return dataLayout.getTypeSize(bufferType.getElementType());
10621057
}
10631058

1064-
// The offset/len as compile-time constants. A constant lives in the
1065-
// static_offset/static_len attribute; if instead a runtime operand is
1066-
// present, fold it (a constant-valued operand still resolves). Returns
1067-
// nullopt when neither is present or the operand is a genuine runtime value
1068-
// (callers on the static lowering path treat that as an error via
1069-
// getFoldedDimensions' sibling diagnostics).
1059+
// The offset/len as a compile-time constant: the static_offset/static_len
1060+
// attribute, or a constant-valued operand folded down. Returns nullopt for a
1061+
// genuine runtime value.
10701062
std::optional<int32_t> getConstantOffset() {
10711063
if (auto attr = getStaticOffset())
10721064
return static_cast<int32_t>(*attr);
@@ -1084,9 +1076,9 @@ def AIE_DMABDOp: AIE_Op<"dma_bd", [AttrSizedOperandSegments]> {
10841076
return std::nullopt;
10851077
}
10861078

1087-
// True when the BD carries an explicit length (a runtime operand or the
1088-
// static_len attribute). Distinct from getConstantLen(), which is nullopt
1089-
// for a runtime len even though a length IS present.
1079+
// True when the BD carries an explicit length (runtime operand or
1080+
// static_len attribute), even a runtime one for which getConstantLen() is
1081+
// nullopt.
10901082
bool hasLen() { return getLen() || getStaticLen().has_value(); }
10911083
bool hasOffset() { return getOffset() || getStaticOffset().has_value(); }
10921084

lib/Dialect/AIE/IR/AIEDialect.cpp

Lines changed: 22 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2033,11 +2033,8 @@ BufferOp DMABDOp::getBufferOp() {
20332033

20342034
// Parse/print hooks for the custom<DynamicScalar>($operand, $static_attr)
20352035
// directive: a single scalar that is either an SSA value (runtime, %v) or a
2036-
// compile-time integer constant (folded into the attribute). Mirrors
2037-
// custom<DynamicIndexList> but for one scalar rather than a list, so a constant
2038-
// never materializes an operand. The generated code binds the Optional<I32>
2039-
// operand as std::optional<UnresolvedOperand> and the OptionalAttr<AIEI32Attr>
2040-
// as IntegerAttr, exactly like upstream transform.tune AlternativesOp.
2036+
// compile-time integer constant (folded into the attribute), so a constant
2037+
// never materializes an operand. The scalar analog of custom<DynamicIndexList>.
20412038
static ParseResult
20422039
parseDynamicScalar(OpAsmParser &parser,
20432040
std::optional<OpAsmParser::UnresolvedOperand> &operand,
@@ -2068,9 +2065,7 @@ static void printDynamicScalar(OpAsmPrinter &printer, Operation *,
20682065
}
20692066

20702067
// Split a scalar OpFoldResult into an operand (runtime value) or an i32
2071-
// attribute (compile-time constant), mirroring how sizes/strides split a
2072-
// constant into static_* and a runtime value into an operand. An absent (null)
2073-
// OpFoldResult leaves both unset.
2068+
// attribute (compile-time constant). A null OpFoldResult leaves both unset.
20742069
static void splitScalarOfr(mlir::OpBuilder &builder, mlir::OpFoldResult ofr,
20752070
mlir::Value &operand, mlir::IntegerAttr &attr) {
20762071
operand = nullptr;
@@ -2092,15 +2087,15 @@ void DMABDOp::buildMixed(mlir::OpBuilder &builder, mlir::OperationState &state,
20922087
llvm::ArrayRef<mlir::OpFoldResult> sizes,
20932088
llvm::ArrayRef<mlir::OpFoldResult> strides,
20942089
BDPadLayoutArrayAttr padDims, PacketInfoAttr packet) {
2095-
// Split each mixed list into its dynamic operands + static array with the
2096-
// ShapedType::kDynamic sentinel, exactly as tensor.extract_slice does.
2090+
// Split each mixed list into its dynamic operands + static array (with the
2091+
// ShapedType::kDynamic sentinel for the runtime entries).
20972092
llvm::SmallVector<int64_t> staticSizes, staticStrides;
20982093
llvm::SmallVector<mlir::Value> dynSizes, dynStrides;
20992094
mlir::dispatchIndexOpFoldResults(sizes, dynSizes, staticSizes);
21002095
mlir::dispatchIndexOpFoldResults(strides, dynStrides, staticStrides);
21012096

21022097
// Leave the static arrays unset when there is no ND layout so they elide
2103-
// from the printed form (a plain linear transfer has no sizes/strides).
2098+
// from the printed form.
21042099
DenseI64ArrayAttr staticSizesAttr =
21052100
staticSizes.empty() ? DenseI64ArrayAttr{}
21062101
: builder.getDenseI64ArrayAttr(staticSizes);
@@ -2137,13 +2132,13 @@ void DMABDOp::buildWithConstants(mlir::OpBuilder &builder,
21372132
BDPadLayoutArrayAttr padDims,
21382133
PacketInfoAttr packet) {
21392134
// Constant offset/len flow to the static_offset/static_len attributes (no
2140-
// arith.constant materialized). Use i32 to match the AIEI32Attr type so
2141-
// splitScalarOfr's cast stays sign-exact for negative offsets.
2135+
// arith.constant materialized). i32 matches AIEI32Attr, keeping the cast
2136+
// sign-exact for negative offsets.
21422137
mlir::OpFoldResult offsetOfr = builder.getI32IntegerAttr(offset);
21432138
mlir::OpFoldResult lenOfr = builder.getI32IntegerAttr(len);
21442139

21452140
// Turn the outermost-first BDDimLayoutArrayAttr into all-constant
2146-
// OpFoldResults and let buildMixed handle the decomposition.
2141+
// OpFoldResults for buildMixed.
21472142
llvm::SmallVector<mlir::OpFoldResult> sizes, strides;
21482143
if (dims) {
21492144
for (BDDimLayoutAttr d : dims) {
@@ -2261,11 +2256,9 @@ LogicalResult DMABDOp::verify() {
22612256
if (std::optional<int32_t> nextBdId = getNextBdId();
22622257
nextBdId.has_value() && static_cast<uint32_t>(*nextBdId) >= maxBds)
22632258
return emitOpError("nextBdId attribute exceeds max: ") << maxBds - 1;
2264-
// Guard the mixed static/dynamic invariant before any consumer counts
2265-
// sentinels against operands: the number of ShapedType::kDynamic entries in
2266-
// each static array must equal the number of dynamic operands, and sizes and
2267-
// strides must agree in rank. Skips the crash in getMixedValues when the two
2268-
// are inconsistent (llvm #179401).
2259+
// The dynamic-operand count must match the kDynamic-sentinel count in each
2260+
// static array, and sizes/strides must agree in rank. Checked before any
2261+
// consumer calls getMixedValues, which crashes on a mismatch (llvm #179401).
22692262
llvm::ArrayRef<int64_t> staticSizes =
22702263
getStaticSizes().value_or(llvm::ArrayRef<int64_t>{});
22712264
llvm::ArrayRef<int64_t> staticStrides =
@@ -2282,9 +2275,7 @@ LogicalResult DMABDOp::verify() {
22822275
<< ")";
22832276

22842277
// Fold the mixed sizes/strides to a constant BDDimLayoutAttr list for
2285-
// verification. A runtime size/stride yields nullopt + a diagnostic; on the
2286-
// static verification path that is an error. `dims` mirrors the historical
2287-
// std::optional<ArrayRef> shape so the checks below are unchanged.
2278+
// verification; a runtime size/stride yields nullopt plus a diagnostic.
22882279
std::optional<llvm::SmallVector<BDDimLayoutAttr>> dims;
22892280
if (!getMixedSizes().empty()) {
22902281
dims = getConstantDimensions();
@@ -2403,10 +2394,10 @@ LogicalResult DMABDOp::verify() {
24032394
return emitOpError("Packet ID field can only hold 5 bits.");
24042395
}
24052396

2397+
// A runtime len operand or the static_len attribute both count as having a
2398+
// length here.
24062399
if (!hasLen() && !getBuffer().getType().hasStaticShape())
24072400
return emitOpError() << "buffer with dynamic shape requires static length.";
2408-
// Either a runtime operand or the static_len attribute satisfies the "has a
2409-
// length" requirement.
24102401

24112402
if (getBurstLength() != 0 && !parentTile.isShimNOCTile())
24122403
return emitOpError("Burst length is only supported in Shim NOC tiles that "
@@ -2511,12 +2502,11 @@ struct LinearizeContiguousBDTransfer : public mlir::OpRewritePattern<DMABDOp> {
25112502
if (!bufferIsExternal && !parentIsShim && !inShimDMA)
25122503
return mlir::failure();
25132504

2514-
// Only when ND dimensions are present and all-constant. Runtime-valued
2515-
// sizes can't be folded/linearized; decline silently (no diagnostic) so
2516-
// valid IR with runtime sizes doesn't produce a spurious error.
2505+
// Only ND dimensions that are present and all-constant can be linearized;
2506+
// decline silently on runtime-valued sizes/strides so valid dynamic IR
2507+
// doesn't get a spurious diagnostic.
25172508
if (op.getMixedSizes().empty())
25182509
return mlir::failure();
2519-
// Check all sizes/strides are constants before attempting to fold.
25202510
for (mlir::OpFoldResult s : op.getMixedSizes())
25212511
if (!mlir::getConstantIntValue(s))
25222512
return mlir::failure();
@@ -2548,17 +2538,13 @@ struct LinearizeContiguousBDTransfer : public mlir::OpRewritePattern<DMABDOp> {
25482538
return mlir::failure();
25492539
int32_t len = static_cast<int32_t>(product);
25502540

2551-
// Rewrite to a linear BD: set len as the static_len attribute (a constant,
2552-
// so no arith.constant operand) and clear the sizes/strides (both operands
2553-
// and static arrays). All other attributes (offset, packet, burst_length,
2554-
// bd_id, etc.) are preserved automatically.
2541+
// Rewrite to a linear BD: len as the static_len attribute, sizes/strides
2542+
// cleared. Other attributes are preserved.
25552543
rewriter.modifyOpInPlace(op, [&]() {
25562544
op.getLenMutable().clear();
25572545
op.setStaticLen(len);
25582546
op.getSizesMutable().clear();
25592547
op.getStridesMutable().clear();
2560-
// Drop the static arrays entirely so the linear BD prints without any
2561-
// sizes/strides clause (the attributes are optional).
25622548
op.setStaticSizes(std::nullopt);
25632549
op.setStaticStrides(std::nullopt);
25642550
});
@@ -2568,10 +2554,7 @@ struct LinearizeContiguousBDTransfer : public mlir::OpRewritePattern<DMABDOp> {
25682554
} // namespace
25692555

25702556
// Canonicalization pattern for DMABDOp: fold a constant offset/len/size/stride
2571-
// operand back into the corresponding static attribute (removing the operand),
2572-
// via the upstream foldDynamicIndexList helper for the lists and
2573-
// getConstantIntValue for the scalars. Mirrors the constant-argument folding
2574-
// tensor.extract_slice performs for its offsets/sizes/strides.
2557+
// operand back into the corresponding static_* attribute, removing the operand.
25752558
namespace {
25762559
struct FoldConstantBDDimList : public mlir::OpRewritePattern<DMABDOp> {
25772560
using OpRewritePattern::OpRewritePattern;
@@ -2606,8 +2589,7 @@ struct FoldConstantBDDimList : public mlir::OpRewritePattern<DMABDOp> {
26062589
rewriter.modifyOpInPlace(op, [&]() {
26072590
op.getSizesMutable().assign(dynSizes);
26082591
op.getStridesMutable().assign(dynStrides);
2609-
// Leave the static arrays unset (not empty) when there is no ND layout so
2610-
// they elide from the printed form (a plain linear transfer).
2592+
// Leave the static arrays unset when there is no ND layout so they elide.
26112593
if (staticSizes.empty())
26122594
op.removeStaticSizesAttr();
26132595
else

python/dialects/aie.py

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -109,14 +109,9 @@ def _as_i32(v):
109109

110110
def _split_i32_scalar(v):
111111
"""Split a dma_bd offset/len argument into (operand, static_attr): a Python
112-
int becomes a compile-time attribute (no arith.constant materialized), an SSA
113-
Value becomes the runtime operand, and None leaves both unset. Mirrors the
114-
operand-vs-attribute split sizes/strides already use.
115-
116-
Contrast with ``_as_i32``: that helper always emits an ``arith.constant``
117-
for integer inputs, which is correct for scalar ops whose operand IS an SSA
118-
i32. Here a constant lands in the static_offset/static_len attribute instead,
119-
so no constant op is materialized."""
112+
int becomes the static attribute, an SSA Value becomes the runtime operand,
113+
and None leaves both unset. Unlike ``_as_i32``, an int stays an attribute
114+
rather than being materialized as an arith.constant operand."""
120115
if v is None:
121116
return None, None
122117
if isinstance(v, (int, np.integer)):
@@ -154,8 +149,7 @@ def dma_bd(
154149
offset_operand, static_offset = _split_i32_scalar(offset)
155150
len_operand, static_len = _split_i32_scalar(transfer_len)
156151

157-
# Leave the static arrays unset (not empty) when there is no ND layout so
158-
# the optional attributes elide from the printed op.
152+
# Leave the static arrays unset when there is no ND layout so they elide.
159153
return _DMABDOp(
160154
buffer,
161155
sizes=dyn_sizes,

python/iron/dataflow/tile_dma.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -95,11 +95,9 @@ class Bd:
9595
# ``(pkt_type, pkt_id)``. Pairs with a :class:`PacketFlow` that uses
9696
# the same ``pkt_id`` so the routing fabric dispatches correctly.
9797
packet: tuple[int, int] | None = None
98-
# Multi-dimensional (strided) access pattern, given as parallel lists
99-
# matching ``aie.dma_bd``'s ``sizes``/``strides`` operands (outermost
100-
# dimension first). Each entry may be a Python int (constant) or an SSA
101-
# ``Value`` (runtime). Empty lists (default) emit a plain contiguous
102-
# transfer. ``sizes`` and ``strides`` must have the same length.
98+
# Strided access pattern, outermost dimension first; each entry is a
99+
# constant int or a runtime Value. Empty (default) emits a contiguous
100+
# transfer. sizes and strides must have equal length.
103101
sizes: list = field(default_factory=list)
104102
strides: list = field(default_factory=list)
105103

@@ -244,8 +242,6 @@ def _body(block):
244242
with block[bd_block_idx[bd_pos]]:
245243
for acq in bd.acquires:
246244
acq.emit()
247-
# dma_bd takes sizes/strides directly (matches
248-
# npu.dma_memcpy_nd's DynamicIndexList operands).
249245
bd_kwargs: dict[str, Any] = dict(
250246
sizes=bd.sizes, strides=bd.strides
251247
)

0 commit comments

Comments
 (0)