MLIR-AIE 1.4.5.dev
AIESplitLongRepeats.cpp
Go to the documentation of this file.
1//===- AIESplitLongRepeats.cpp ----------------------------------*- C++ -*-===//
2//
3// Copyright (C) 2026 Advanced Micro Devices, Inc.
4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5//
6//===----------------------------------------------------------------------===//
7//
8// A queue push carries its repeat count in a narrow field, but a task start may
9// ask for more. This pass issues such a start as several starts of the same
10// task, so that every start after it is exactly one push.
11//
12//===----------------------------------------------------------------------===//
13
18
19#include "mlir/Dialect/Utils/StaticValueUtils.h"
20#include "mlir/Pass/Pass.h"
21
22namespace xilinx::AIEX {
23#define GEN_PASS_DEF_AIESPLITLONGREPEATS
24#include "aie/Dialect/AIEX/Transforms/AIEXPasses.h.inc"
25} // namespace xilinx::AIEX
26
27using namespace mlir;
28using namespace xilinx;
29using namespace xilinx::AIEX;
30
31namespace {
32
33struct AIESplitLongRepeatsPass
34 : xilinx::AIEX::impl::AIESplitLongRepeatsBase<AIESplitLongRepeatsPass> {
35 void runOnOperation() override {
36 AIE::DeviceOp device = getOperation();
37 uint32_t maxRepeat = device.getTargetModel().getMaxRepeatCount();
38 int64_t queueDepth = device.getTargetModel().getDmaTaskQueueDepth();
39 // A target without a repeat field has nothing to split into; its push
40 // verifier reports the count instead.
41 if (maxRepeat == 0)
42 return;
43 SmallVector<DMAStartTaskOp> starts;
44 device.walk([&](DMAStartTaskOp start) { starts.push_back(start); });
45 for (DMAStartTaskOp start : starts) {
46 // A start's own count needs no configure. Otherwise the count is the
47 // task's, read through any control flow that carries the task.
48 std::optional<int64_t> rc;
49 if (start.hasRepeatParameter()) {
50 // The task's count is the parameter's maximum, and the host's value
51 // reaches the queue as one push.
52 DMAConfigureTaskOp cfg = start.getTaskOp();
53 if (cfg && cfg.getRepeatCount() > maxRepeat) {
54 start.emitOpError("takes its repeat count from a scratchpad "
55 "parameter, which reaches one queue push, but its "
56 "task's repeat count, the parameter's maximum, is ")
57 << cfg.getRepeatCount() << ", past the target's " << maxRepeat;
58 return signalPassFailure();
59 }
60 continue;
61 }
62 if (std::optional<uint32_t> own = start.getRepeatCount()) {
63 rc = *own;
64 } else if (Value ownVal = start.getRepeatCountVal()) {
65 rc = getConstantIntValue(ownVal);
66 } else {
67 DMAConfigureTaskOp cfg = start.getTaskOp();
68 if (!cfg)
69 cfg = getUniqueReachableConfigure(start.getTask());
70 if (!cfg)
71 continue;
72 rc = getConstantIntValue(start.getPushRepeatCount(cfg));
73 }
74 if (!rc || *rc <= maxRepeat)
75 continue;
76 int64_t pushes = (*rc + maxRepeat + 1) / (maxRepeat + 1);
77 if (pushes > static_cast<int64_t>(maxPushes)) {
78 start.emitOpError("repeat count ")
79 << *rc << " needs " << pushes
80 << " queue pushes, more than max-pushes (" << maxPushes.getValue()
81 << ")";
82 return signalPassFailure();
83 }
84 if (queueDepth > 0 && pushes > queueDepth)
85 start.emitWarning("repeat count ")
86 << *rc << " needs " << pushes << " queue pushes, more than the "
87 << queueDepth
88 << " the channel's queue holds, so the sequence waits for this "
89 "channel to drain before going on. A transfer this one waits "
90 "on must be started before it, or the wait never ends.";
91 // Leading starts withhold the token, so an await on the task still
92 // returns only after the last pass.
93 OpBuilder b(start);
94 int64_t runs = *rc + 1;
95 for (; runs > maxRepeat + 1; runs -= maxRepeat + 1)
96 DMAStartTaskOp::create(b, start.getLoc(), start.getTask(),
97 b.getI32IntegerAttr(maxRepeat),
98 /*repeat_count_val=*/nullptr,
99 /*no_token=*/b.getUnitAttr(),
100 /*repeat_parameter=*/nullptr,
101 /*repeat_state_table_idx=*/nullptr);
102 start.setRepeatCountAttr(b.getI32IntegerAttr(runs - 1));
103 start.getRepeatCountValMutable().clear();
104 }
105 }
106};
107
108} // namespace
109
110std::unique_ptr<mlir::OperationPass<AIE::DeviceOp>>
112 return std::make_unique<AIESplitLongRepeatsPass>();
113}
DMAConfigureTaskOp getUniqueReachableConfigure(Value task)
Definition AIEUtils.cpp:354
std::unique_ptr< mlir::OperationPass< AIE::DeviceOp > > createAIESplitLongRepeatsPass()