MLIR-AIE 1.4.5.dev
AIEResolveAddressPatchBuffers.cpp
Go to the documentation of this file.
1//===- AIEResolveAddressPatchBuffers.cpp ------------------------*- C++ -*-===//
2//
3// Copyright (C) 2026 Advanced Micro Devices, Inc.
4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5//
6//===----------------------------------------------------------------------===//
7
12
13#include "mlir/Dialect/Arith/IR/Arith.h"
14#include "mlir/IR/PatternMatch.h"
15#include "mlir/Pass/Pass.h"
16#include "mlir/Transforms/WalkPatternRewriteDriver.h"
17
18namespace xilinx::AIEX {
19#define GEN_PASS_DEF_AIERESOLVEADDRESSPATCHBUFFERS
20#include "aie/Dialect/AIEX/Transforms/AIEXPasses.h.inc"
21} // namespace xilinx::AIEX
22
23using namespace mlir;
24using namespace xilinx;
25using namespace xilinx::AIEX;
26
27namespace {
28
29struct ResolveBufferOperand : OpRewritePattern<NpuAddressPatchOp> {
30 using OpRewritePattern::OpRewritePattern;
31
32 LogicalResult matchAndRewrite(NpuAddressPatchOp op,
33 PatternRewriter &rewriter) const override {
34 if (!op.getBuffer()) {
35 return failure();
36 }
37
38 auto seq = op->getParentOfType<AIE::RuntimeSequenceOp>();
39 if (!seq) {
40 return rewriter.notifyMatchFailure(
41 op, "must be inside a runtime sequence to resolve its host buffer");
42 }
43 std::optional<SubviewTraceResult> traced =
44 traceSubviewToBlockArgument(op.getBuffer());
45 if (!traced || traced->rootArg.getOwner() != &seq.getBody().front()) {
46 return rewriter.notifyMatchFailure(
47 op, "buffer must be an argument of the enclosing runtime sequence, "
48 "or a static contiguous view of one");
49 }
50 std::optional<unsigned> argIdx = getHostBufferArgIndex(traced->rootArg);
51 if (!argIdx) {
52 return rewriter.notifyMatchFailure(
53 op, "buffer must resolve to a memref argument");
54 }
55
56 Value argPlus = op.getArgPlus();
57 if (traced->offsetInBytes != 0) {
58 // Sum at 64 bits; see createConstantArgPlus for the width choice.
59 if (std::optional<uint64_t> base = getConstantInt64Operand(argPlus)) {
60 argPlus = createConstantArgPlus(
61 rewriter, op.getLoc(),
62 *base + static_cast<uint64_t>(traced->offsetInBytes));
63 } else {
64 // Widen the runtime value only when the offset outgrows its width.
65 Type ty = argPlus.getType();
66 if (ty.getIntOrFloatBitWidth() < 64 &&
67 traced->offsetInBytes > std::numeric_limits<uint32_t>::max()) {
68 ty = rewriter.getIntegerType(64);
69 argPlus = arith::ExtUIOp::create(rewriter, op.getLoc(), ty, argPlus);
70 }
71 Value shift = arith::ConstantOp::create(
72 rewriter, op.getLoc(),
73 IntegerAttr::get(ty, static_cast<int64_t>(traced->offsetInBytes)));
74 argPlus = arith::AddIOp::create(rewriter, op.getLoc(), argPlus, shift);
75 }
76 }
77
78 rewriter.replaceOpWithNewOp<NpuAddressPatchOp>(
79 op, op.getAddr(), op.getAddrVal(), static_cast<int32_t>(*argIdx),
80 argPlus);
81 return success();
82 }
83};
84
85struct AIEResolveAddressPatchBuffersPass
86 : xilinx::AIEX::impl::AIEResolveAddressPatchBuffersBase<
87 AIEResolveAddressPatchBuffersPass> {
88
89 void runOnOperation() override {
90 RewritePatternSet patterns(&getContext());
91 patterns.add<ResolveBufferOperand>(&getContext());
92 walkAndApplyPatterns(getOperation(), std::move(patterns));
93
94 // A pattern that declines to match leaves the operand in place. The targets
95 // cannot emit that, so report it here instead.
96 WalkResult unresolved = getOperation().walk([&](NpuAddressPatchOp op) {
97 if (op.getBuffer()) {
98 op.emitOpError("could not resolve its buffer operand to a host buffer "
99 "index of the enclosing runtime sequence");
100 return WalkResult::interrupt();
101 }
102 return WalkResult::advance();
103 });
104 if (unresolved.wasInterrupted()) {
105 signalPassFailure();
106 }
107 }
108};
109
110} // namespace
111
112std::unique_ptr<OperationPass<AIE::DeviceOp>>
114 return std::make_unique<AIEResolveAddressPatchBuffersPass>();
115}
std::unique_ptr< mlir::OperationPass< AIE::DeviceOp > > createAIEResolveAddressPatchBuffersPass()
std::optional< SubviewTraceResult > traceSubviewToBlockArgument(Value value)
Definition AIEUtils.cpp:18
std::optional< uint64_t > getConstantInt64Operand(mlir::Value v)
mlir::Value createConstantArgPlus(mlir::OpBuilder &builder, mlir::Location loc, uint64_t value)
std::optional< unsigned > getHostBufferArgIndex(BlockArgument arg)
Definition AIEUtils.cpp:142