MLIR-AIE 1.4.5.dev
AIEMaterializeBDChains.cpp
Go to the documentation of this file.
1//===- AIEMaterializeBDChains.cpp -------------------------------*- C++ -*-===//
2//
3// Copyright (C) 2024 Advanced Micro Devices, Inc.
4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5//
6//===----------------------------------------------------------------------===//
7
11
12#include "mlir/Analysis/CallGraph.h"
13#include "mlir/IR/IRMapping.h"
14#include "mlir/IR/PatternMatch.h"
15#include "mlir/IR/SymbolTable.h"
16#include "mlir/Pass/Pass.h"
17#include "mlir/Pass/PassManager.h"
18#include "mlir/Transforms/DialectConversion.h"
19#include "mlir/Transforms/GreedyPatternRewriteDriver.h"
20
21namespace xilinx::AIEX {
22#define GEN_PASS_DEF_AIEMATERIALIZEBDCHAINS
23#include "aie/Dialect/AIEX/Transforms/AIEXPasses.h.inc"
24} // namespace xilinx::AIEX
25
26using namespace mlir;
27using namespace xilinx;
28using namespace xilinx::AIEX;
29
30struct DMAStartBdChainForOpPattern : RewritePattern {
31
32 // Symbol-lookup cache used for speedier `ShimDMAAllocationOp` lookups
33 const mlir::SymbolTable &symbolTable;
34
36 const mlir::SymbolTable &symbolTable)
37 : RewritePattern(DMAStartBdChainForOp::getOperationName(),
38 PatternBenefit(1), ctx),
40
41 LogicalResult matchAndRewrite(Operation *op_any,
42 PatternRewriter &rewriter) const override {
43 DMAStartBdChainForOp op = llvm::dyn_cast<DMAStartBdChainForOp>(op_any);
44 if (!op) {
45 return failure();
46 }
47
48 AIE::ShimDMAAllocationOp alloc_op =
49 symbolTable.lookup<AIE::ShimDMAAllocationOp>(op.getAlloc());
50 if (!alloc_op) {
51 return op.emitOpError("no shim DMA allocation found for symbol");
52 }
53
54 AIE::TileOp tile = alloc_op.getTileOp();
55 if (!tile) {
56 return op.emitOpError(
57 "shim DMA allocation must reference a valid TileOp");
58 }
59
60 DMAStartBdChainOp new_op = DMAStartBdChainOp::create(
61 rewriter, op.getLoc(), rewriter.getIndexType(), op.getSymbol(),
62 op.getArgs(), tile.getResult(), alloc_op.getChannelDir(),
63 (int32_t)alloc_op.getChannelIndex(), op.getIssueToken(),
64 op.getRepeatCount());
65 rewriter.replaceAllUsesWith(op.getResult(), new_op.getResult());
66 rewriter.eraseOp(op);
67 return success();
68 }
69};
70
71struct DMAInlineBDChainPattern : RewritePattern {
72
73 DMAInlineBDChainPattern(MLIRContext *ctx)
74 : RewritePattern(DMAStartBdChainOp::getOperationName(), PatternBenefit(1),
75 ctx) {}
76
77 LogicalResult matchAndRewrite(Operation *op,
78 PatternRewriter &rewriter) const override {
79 DMAStartBdChainOp start_op = llvm::dyn_cast<DMAStartBdChainOp>(op);
80 if (!start_op) { // Not a match.
81 return failure();
82 }
83 rewriter.setInsertionPointAfter(start_op);
84
85 // Get referenced abstract BD chain
86 AIE::BDChainOp chain_def = start_op.getBDChainOp();
87 assert(chain_def);
88 Region &source_region = chain_def.getBody();
89
90 // Create BD op into which the result will be inlined
91 DMAConfigureTaskOp configure_op = DMAConfigureTaskOp::create(
92 rewriter, start_op.getLoc(), rewriter.getIndexType(),
93 start_op.getTile(), start_op.getDirection(), start_op.getChannel(),
94 start_op.getIssueToken(), start_op.getRepeatCount());
95 Region &target_region = configure_op.getBody();
96
97 // Clone BD definition into usage site, replacing abstract SSA values with
98 // concrete ones
99 IRMapping arg_map;
100 ValueRange values = start_op.getArgs();
101 for (unsigned i = 0, n = source_region.getNumArguments(); i < n; i++) {
102 BlockArgument arg = source_region.getArgument(i);
103 Value val = values[i];
104 assert(arg.getType() == val.getType());
105 arg_map.map(arg, val);
106 }
107 source_region.cloneInto(&target_region, arg_map);
108
109 // Replace result of dma start task with result of bd chain configuration
110 rewriter.replaceAllUsesWith(start_op.getResult(), configure_op.getResult());
111
112 // Add a start BDs instruction
113 DMAStartTaskOp::create(rewriter, start_op.getLoc(),
114 configure_op.getResult());
115
116 // After fully inlining, remove the original instruction
117 rewriter.eraseOp(start_op);
118
119 return success();
120 }
121};
122
125 AIEMaterializeBDChainsPass> {
126
127 void runOnOperation() override {
128 MLIRContext *ctx = &getContext();
129 AIE::DeviceOp device = getOperation();
130 GreedyRewriteConfig rewriter_config = GreedyRewriteConfig();
131 rewriter_config.setRegionSimplificationLevel(
132 GreedySimplifyRegionLevel::Disabled);
133
134 mlir::SymbolTable symbolTable(device);
135
136 RewritePatternSet patterns_0(ctx);
137 patterns_0.insert<DMAStartBdChainForOpPattern>(ctx, symbolTable);
138 DMAConfigureTaskOp::getCanonicalizationPatterns(patterns_0, ctx);
139 if (failed(applyPatternsGreedily(device, std::move(patterns_0),
140 rewriter_config))) {
141 signalPassFailure();
142 }
143
144 RewritePatternSet patterns_1(ctx);
145 patterns_1.insert<DMAInlineBDChainPattern>(ctx);
146 rewriter_config.setRegionSimplificationLevel(
147 GreedySimplifyRegionLevel::Disabled);
148 DMAConfigureTaskOp::getCanonicalizationPatterns(patterns_1, ctx);
149 if (failed(applyPatternsGreedily(device, std::move(patterns_1),
150 rewriter_config))) {
151 signalPassFailure();
152 }
153 }
154};
155
156std::unique_ptr<OperationPass<AIE::DeviceOp>>
158 return std::make_unique<AIEMaterializeBDChainsPass>();
159}
std::unique_ptr< mlir::OperationPass< AIE::DeviceOp > > createAIEMaterializeBDChainsPass()
LogicalResult matchAndRewrite(Operation *op, PatternRewriter &rewriter) const override
DMAInlineBDChainPattern(MLIRContext *ctx)
LogicalResult matchAndRewrite(Operation *op_any, PatternRewriter &rewriter) const override
DMAStartBdChainForOpPattern(MLIRContext *ctx, const mlir::SymbolTable &symbolTable)
const mlir::SymbolTable & symbolTable