MLIR-AIE
AIECoreToStandard.cpp
Go to the documentation of this file.
1//===- AIECoreToStandard.cpp ------------------------------------*- C++ -*-===//
2//
3// This file is licensed under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7// (c) Copyright 2019 Xilinx Inc.
8//
9//===----------------------------------------------------------------------===//
10
13
14#include "mlir/Conversion/FuncToLLVM/ConvertFuncToLLVM.h"
15#include "mlir/Conversion/FuncToLLVM/ConvertFuncToLLVMPass.h"
16#include "mlir/Dialect/Arith/IR/Arith.h"
17#include "mlir/Dialect/ControlFlow/IR/ControlFlow.h"
18#include "mlir/Dialect/Index/IR/IndexDialect.h"
19#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
20#include "mlir/Dialect/Math/IR/Math.h"
21#include "mlir/Dialect/Vector/IR/VectorOps.h"
22#include "mlir/IR/Attributes.h"
23#include "mlir/IR/IRMapping.h"
24#include "mlir/IR/PatternMatch.h"
25#include "mlir/Pass/Pass.h"
26#include "mlir/Tools/mlir-translate/MlirTranslateMain.h"
27#include "mlir/Transforms/DialectConversion.h"
28
29using namespace mlir;
30using namespace mlir::vector;
31using namespace xilinx;
32using namespace xilinx::AIE;
33
34static StringRef getArchIntrinsicString(AIEArch arch) {
35 switch (arch) {
36 case AIEArch::AIE1:
37 return "aie";
38 case AIEArch::AIE2:
39 return "aie2";
40 case AIEArch::AIE2p:
41 return "aie2p";
42 }
43 llvm::report_fatal_error("unsupported arch");
44}
45
46typedef std::tuple<const char *, std::vector<Type>, std::vector<Type>>
48typedef std::vector<IntrinsicDecl> IntrinsicDecls;
49
50static auto getAIE1Intrinsics(OpBuilder &builder) {
51 Type int32Type = IntegerType::get(builder.getContext(), 32);
52 Type int128Type = IntegerType::get(builder.getContext(), 128);
53 Type int384Type = IntegerType::get(builder.getContext(), 384);
54 Type floatType = Float32Type::get(builder.getContext());
55
56 // Note that not all of these are valid for a particular design, or needed.
57 // For right now, we will just accept the noise.
58 IntrinsicDecls functions = {
59 {"debug_i32", {int32Type}, {}},
60 {"llvm.aie.event0", {}, {}},
61 {"llvm.aie.event1", {}, {}},
62 {"llvm.aie.put.ms",
63 {int32Type, int32Type},
64 {}}, //(%channel, %value) -> ()
65 {"llvm.aie.put.wms",
66 {int32Type, int128Type},
67 {}}, //(%channel, %value) -> ()
68 {"llvm.aie.put.fms",
69 {int32Type, floatType},
70 {}}, //(%channel, %value) -> ()
71 {"llvm.aie.get.ss", {int32Type}, {int32Type}}, //(%channel, %value) -> ()
72 {"llvm.aie.get.wss",
73 {int32Type},
74 {int128Type}}, //(%channel, %value) -> ()
75 {"llvm.aie.get.fss", {int32Type}, {floatType}}, //(%channel, %value) -> ()
76 {"llvm.aie.put.mcd", {int384Type}, {}},
77 {"llvm.aie.get.scd", {}, {int384Type}},
78 {"llvm.aie.lock.acquire.reg",
79 {int32Type, int32Type},
80 {}}, //(%lock_id, %lock_val) -> ()
81 {"llvm.aie.lock.release.reg",
82 {int32Type, int32Type},
83 {}}, //(%lock_id, %lock_val) -> ()
84 };
85 return functions;
86}
87
88static auto getAIE2Intrinsics(OpBuilder &builder) {
89 Type int32Type = IntegerType::get(builder.getContext(), 32);
90 Type accType = VectorType::get({16}, int32Type);
91 IntrinsicDecls functions = {
92 {"debug_i32", {int32Type}, {}},
93 {"llvm.aie2.put.ms", {int32Type, int32Type}, {}}, //(%value, %tlast) -> ()
94 {"llvm.aie2.get.ss", {}, {int32Type, int32Type}}, //() -> (%value, %tlast)
95 {"llvm.aie2.mcd.write.vec",
96 {accType, int32Type},
97 {}}, // (%value, %enable) -> ()
98 {"llvm.aie2.scd.read.vec",
99 {int32Type},
100 {accType}}, // (%enable) -> (%value)
101 {"llvm.aie2.acquire",
102 {int32Type, int32Type},
103 {}}, //(%lock_id, %lock_val) -> ()
104 {"llvm.aie2.release",
105 {int32Type, int32Type},
106 {}}, //(%lock_id, %lock_val) -> ()
107 };
108 return functions;
109}
110
111static auto getAIE2pIntrinsics(OpBuilder &builder) {
112 Type int32Type = IntegerType::get(builder.getContext(), 32);
113 Type accType = VectorType::get({16}, int32Type);
114 IntrinsicDecls functions = {
115 {"debug_i32", {int32Type}, {}},
116 {"llvm.aie2p.put.ms",
117 {int32Type, int32Type},
118 {}}, //(%value, %tlast) -> ()
119 {"llvm.aie2p.get.ss",
120 {},
121 {int32Type, int32Type}}, //() -> (%value, %tlast)
122 {"llvm.aie2p.mcd.write.vec",
123 {accType, int32Type},
124 {}}, // (%value, %enable) -> ()
125 {"llvm.aie2p.scd.read.vec",
126 {int32Type},
127 {accType}}, // (%enable) -> (%value)
128 {"llvm.aie2p.acquire",
129 {int32Type, int32Type},
130 {}}, //(%lock_id, %lock_val) -> ()
131 {"llvm.aie2p.release",
132 {int32Type, int32Type},
133 {}}, //(%lock_id, %lock_val) -> ()
134 };
135 return functions;
136}
137
138static void declareAIEIntrinsics(AIEArch arch, OpBuilder &builder) {
139 auto registerIntrinsics = [&builder](IntrinsicDecls functions) {
140 for (auto &i : functions) {
141 auto [name, argTypes, retTypes] = i;
142 builder
143 .create<func::FuncOp>(
144 builder.getUnknownLoc(), name,
145 FunctionType::get(builder.getContext(), argTypes, retTypes))
146 .setPrivate();
147 }
148 };
149 switch (arch) {
150 case AIEArch::AIE1:
151 registerIntrinsics(getAIE1Intrinsics(builder));
152 return;
153 case AIEArch::AIE2:
154 registerIntrinsics(getAIE2Intrinsics(builder));
155 return;
156 case AIEArch::AIE2p:
157 registerIntrinsics(getAIE2pIntrinsics(builder));
158 return;
159 }
160 llvm::report_fatal_error("unsupported arch");
161}
162
163template <typename MyAIEOp>
166 using OpAdaptor = typename MyAIEOp::Adaptor;
167 ModuleOp &module;
168
169 AIEOpRemoval(MLIRContext *context, ModuleOp &m, PatternBenefit benefit = 1)
170 : OpConversionPattern<MyAIEOp>(context, benefit), module(m) {}
171
172 LogicalResult
173 matchAndRewrite(MyAIEOp op, OpAdaptor adaptor,
174 ConversionPatternRewriter &rewriter) const override {
175 rewriter.eraseOp(op);
176 return success();
177 }
178};
179
181 using OpConversionPattern::OpConversionPattern;
182 ModuleOp &module;
183
184 AIEDebugOpToStdLowering(MLIRContext *context, ModuleOp &m,
185 PatternBenefit benefit = 1)
186 : OpConversionPattern(context, benefit), module(m) {}
187
188 LogicalResult
189 matchAndRewrite(DebugOp op, OpAdaptor adaptor,
190 ConversionPatternRewriter &rewriter) const override {
191 std::string funcName = "debug_i32";
192 auto func = module.lookupSymbol<func::FuncOp>(funcName);
193 if (!func)
194 return op.emitOpError("Could not find the intrinsic function ")
195 << funcName;
196 SmallVector<Value, 1> args;
197 args.push_back(op.getArg());
198 rewriter.create<func::CallOp>(rewriter.getUnknownLoc(), func, args);
199 rewriter.eraseOp(op);
200 return success();
201 }
202};
203
205 using OpConversionPattern::OpConversionPattern;
206 ModuleOp &module;
207
208 AIEPutStreamToStdLowering(MLIRContext *context, ModuleOp &m,
209 PatternBenefit benefit = 1)
210 : OpConversionPattern(context, benefit), module(m) {}
211
212 LogicalResult
213 matchAndRewrite(PutStreamOp op, OpAdaptor adaptor,
214 ConversionPatternRewriter &rewriter) const override {
215 auto device = op->getParentOfType<DeviceOp>();
216 const auto &targetModel = device.getTargetModel();
217 std::string funcName;
218 if (targetModel.getTargetArch() == AIEArch::AIE1)
219 funcName = "llvm.aie.put.";
220 else if (targetModel.getTargetArch() == AIEArch::AIE2)
221 funcName = "llvm.aie2.put.";
222 else
223 funcName = "llvm.aie2p.put.";
224
225 if (op.isWideStream())
226 funcName += "wms";
227 else if (op.isFloatStream())
228 funcName += "fms";
229 else
230 funcName += "ms";
231
232 auto putMSFunc = module.lookupSymbol<func::FuncOp>(funcName);
233 if (!putMSFunc)
234 return op.emitOpError("Could not find the intrinsic function ")
235 << funcName;
236 SmallVector<Value, 2> args;
237 if (targetModel.getTargetArch() == AIEArch::AIE1) {
238 args.push_back(op.getChannel());
239 args.push_back(op.getStreamValue());
240 } else {
241 args.push_back(op.getStreamValue());
242 args.push_back(rewriter.create<arith::ConstantOp>(
243 op.getLoc(), IntegerType::get(rewriter.getContext(), 32),
244 rewriter.getI32IntegerAttr(0))); // tlast
245 }
246 rewriter.create<func::CallOp>(rewriter.getUnknownLoc(), putMSFunc, args);
247 rewriter.eraseOp(op);
248 return success();
249 }
250};
251
253 using OpConversionPattern::OpConversionPattern;
254 ModuleOp &module;
255
256 AIEGetStreamToStdLowering(MLIRContext *context, ModuleOp &m,
257 PatternBenefit benefit = 1)
258 : OpConversionPattern(context, benefit), module(m) {}
259
260 LogicalResult
261 matchAndRewrite(GetStreamOp op, OpAdaptor adaptor,
262 ConversionPatternRewriter &rewriter) const override {
263 auto device = op->getParentOfType<DeviceOp>();
264 const auto &targetModel = device.getTargetModel();
265 std::string funcName;
266 if (targetModel.getTargetArch() == AIEArch::AIE1)
267 funcName = "llvm.aie.get.";
268 else if (targetModel.getTargetArch() == AIEArch::AIE2)
269 funcName = "llvm.aie2.get.";
270 else
271 funcName = "llvm.aie2p.get.";
272
273 if (op.isWideStream())
274 funcName += "wss";
275 else if (op.isFloatStream())
276 funcName += "fss";
277 else
278 funcName += "ss";
279
280 auto getSSFunc = module.lookupSymbol<func::FuncOp>(funcName);
281 if (!getSSFunc)
282 return op.emitOpError("Could not find the intrinsic function ")
283 << funcName;
284 SmallVector<Value, 2> args;
285 if (targetModel.getTargetArch() == AIEArch::AIE1)
286 args.push_back(op.getChannel());
287 auto getSSCall = rewriter.create<func::CallOp>(rewriter.getUnknownLoc(),
288 getSSFunc, args);
289 rewriter.replaceOp(op, getSSCall.getResult(0));
290 // Capture TLAST in AIEv2?
291 return success();
292 }
293};
294
296 using OpConversionPattern::OpConversionPattern;
297 ModuleOp &module;
298
299 AIEPutCascadeToStdLowering(MLIRContext *context, ModuleOp &m,
300 PatternBenefit benefit = 1)
301 : OpConversionPattern(context, benefit), module(m) {}
302
303 LogicalResult
304 matchAndRewrite(PutCascadeOp op, OpAdaptor adaptor,
305 ConversionPatternRewriter &rewriter) const override {
306 auto device = op->getParentOfType<DeviceOp>();
307 const auto &targetModel = device.getTargetModel();
308 std::string funcName;
309 if (targetModel.getTargetArch() == AIEArch::AIE1)
310 funcName = "llvm.aie.put.mcd";
311 else if (targetModel.getTargetArch() == AIEArch::AIE2)
312 funcName = "llvm.aie2.mcd.write.vec";
313 else
314 funcName = "llvm.aie2p.mcd.write.vec";
315 auto putMCDFunc = module.lookupSymbol<func::FuncOp>(funcName);
316 if (!putMCDFunc)
317 return op.emitOpError("Could not find the intrinsic function ")
318 << funcName;
319 SmallVector<Value, 2> args;
320 args.push_back(op.getCascadeValue());
321 if (isa<AIE2TargetModel>(targetModel))
322 args.push_back(rewriter.create<arith::ConstantOp>(
323 op.getLoc(), IntegerType::get(rewriter.getContext(), 32),
324 rewriter.getI32IntegerAttr(1))); // enable
325
326 rewriter.create<func::CallOp>(rewriter.getUnknownLoc(), putMCDFunc, args);
327 rewriter.eraseOp(op);
328 return success();
329 }
330};
331
333 using OpConversionPattern::OpConversionPattern;
334 ModuleOp &module;
335
336 AIEGetCascadeToStdLowering(MLIRContext *context, ModuleOp &m,
337 PatternBenefit benefit = 1)
338 : OpConversionPattern(context, benefit), module(m) {}
339
340 LogicalResult
341 matchAndRewrite(GetCascadeOp op, OpAdaptor adaptor,
342 ConversionPatternRewriter &rewriter) const override {
343 auto device = op->getParentOfType<DeviceOp>();
344 const auto &targetModel = device.getTargetModel();
345 std::string funcName;
346 if (targetModel.getTargetArch() == AIEArch::AIE1)
347 funcName = "llvm.aie.get.scd";
348 else if (targetModel.getTargetArch() == AIEArch::AIE2)
349 funcName = "llvm.aie2.scd.read.vec";
350 else
351 funcName = "llvm.aie2p.scd.read.vec";
352 auto getSCDFunc = module.lookupSymbol<func::FuncOp>(funcName);
353 if (!getSCDFunc)
354 return op.emitOpError("Could not find the intrinsic function ")
355 << funcName;
356 SmallVector<Value, 2> args;
357 if (isa<AIE2TargetModel>(targetModel))
358 args.push_back(rewriter.create<arith::ConstantOp>(
359 op.getLoc(), IntegerType::get(rewriter.getContext(), 32),
360 rewriter.getI32IntegerAttr(1))); // enable
361
362 auto getSCDCall = rewriter.create<func::CallOp>(rewriter.getUnknownLoc(),
363 getSCDFunc, args);
364 rewriter.replaceOp(op, getSCDCall.getResult(0));
365 return success();
366 }
367};
368
370 using OpConversionPattern::OpConversionPattern;
371 ModuleOp &module;
372
373 AIEUseLockToStdLowering(MLIRContext *context, ModuleOp &m,
374 PatternBenefit benefit = 1)
375 : OpConversionPattern(context, benefit), module(m) {}
376 LogicalResult
377 matchAndRewrite(UseLockOp useLock, OpAdaptor adaptor,
378 ConversionPatternRewriter &rewriter) const override {
379 if (!isa<DeviceOp>(useLock->getParentOp())) {
380 auto device = useLock->getParentOfType<DeviceOp>();
381 if (!device) {
382 return module.emitOpError("Device Not found!");
383 }
384 const auto &targetModel = device.getTargetModel();
385
386 // Generate the intrinsic name
387 std::string funcName;
388 if (targetModel.getTargetArch() == AIEArch::AIE1)
389 funcName = "llvm.aie.lock.";
390 else if (targetModel.getTargetArch() == AIEArch::AIE2)
391 funcName = "llvm.aie2.";
392 else
393 funcName = "llvm.aie2p.";
394 if (useLock.acquire() || useLock.acquireGE())
395 funcName += "acquire";
396 else if (useLock.release())
397 funcName += "release";
398 if (targetModel.getTargetArch() == AIEArch::AIE1)
399 funcName += ".reg";
400
401 auto useLockFunc = module.lookupSymbol<func::FuncOp>(funcName);
402 if (!useLockFunc)
403 return useLock.emitOpError("Could not find the intrinsic function!");
404
405 SmallVector<Value, 2> args;
406 auto lockValue = useLock.getLockValue();
407
408 // AIE2 acquire greater equal is encoded as a negative value.
409 if (useLock.acquireGE()) {
410 lockValue = -lockValue;
411 }
412 args.push_back(rewriter.create<arith::IndexCastOp>(
413 useLock.getLoc(), IntegerType::get(rewriter.getContext(), 32),
414 useLock.getLock()));
415 args.push_back(rewriter.create<arith::ConstantOp>(
416 useLock.getLoc(), IntegerType::get(rewriter.getContext(), 32),
417 rewriter.getI32IntegerAttr(lockValue)));
418
419 rewriter.create<func::CallOp>(rewriter.getUnknownLoc(), useLockFunc,
420 args);
421 }
422 rewriter.eraseOp(useLock);
423 return success();
424 }
425};
426
428 using OpConversionPattern::OpConversionPattern;
429 ModuleOp &module;
430 int tileCol = 0;
431 int tileRow = 0;
432 AIEBufferToStandard(MLIRContext *context, ModuleOp &m,
433 PatternBenefit benefit = 1, int tileCol = -1,
434 int tileRow = -1)
435 : OpConversionPattern(context, benefit), module(m), tileCol(tileCol),
436 tileRow(tileRow) {}
437 LogicalResult
438 matchAndRewrite(BufferOp buffer, OpAdaptor adaptor,
439 ConversionPatternRewriter &rewriter) const override {
440 rewriter.setInsertionPointToStart(module.getBody());
441 auto t = llvm::cast<MemRefType>(buffer.getType());
442 int col = llvm::cast<TileOp>(buffer.getTile().getDefiningOp()).getCol();
443 int row = llvm::cast<TileOp>(buffer.getTile().getDefiningOp()).getRow();
444 auto symName = buffer.name().getValue();
445 mlir::ElementsAttr initValue = buffer.getInitialValueAttr();
446 // Don't emit initialization for cores that don't "own" the buffer (to
447 // prevent duplication in the data section of the elf/object file)
448 if ((tileRow != row && tileRow != -1) || (tileCol != col && tileCol != -1))
449 initValue = nullptr;
450 rewriter.create<memref::GlobalOp>(
451 rewriter.getUnknownLoc(), symName, rewriter.getStringAttr("public"),
452 buffer.getType(), initValue, /*constant*/ false,
453 /*alignment*/ nullptr);
454
455 for (auto &use : make_early_inc_range(buffer.getResult().getUses())) {
456 Operation *user = use.getOwner();
457 rewriter.setInsertionPoint(user);
458 auto allocated = rewriter.create<memref::GetGlobalOp>(
459 rewriter.getUnknownLoc(), t, symName);
460 // Assume that buffers are aligned so they can be vectorized.
461 rewriter.create<memref::AssumeAlignmentOp>(rewriter.getUnknownLoc(),
462 allocated, 32);
463
464 use.set(allocated.getResult());
465 }
466
467 rewriter.eraseOp(buffer);
468 return success();
469 }
470};
471
473 using OpConversionPattern::OpConversionPattern;
474 ModuleOp &module;
475 IRMapping &mapper;
476 DenseMap<Operation *, SmallVector<BufferOp, 4>> &tileToBuffers;
477 int tileCol = 0;
478 int tileRow = 0;
479
481 MLIRContext *context, ModuleOp &m, IRMapping &mapper,
482 DenseMap<Operation *, SmallVector<BufferOp, 4>> &tileToBuffers,
483 PatternBenefit benefit = 1, int tileCol = 1, int tileRow = 1)
484 : OpConversionPattern(context, benefit), module(m), mapper(mapper),
486
487 LogicalResult
488 matchAndRewrite(CoreOp op, OpAdaptor adaptor,
489 ConversionPatternRewriter &rewriter) const override {
490
491 int col = op.colIndex();
492 int row = op.rowIndex();
493
494 // Only pull code for the indicated function
495 if ((tileRow != row && tileRow != -1) ||
496 (tileCol != col && tileCol != -1)) {
497 rewriter.eraseOp(op);
498 return success();
499 }
500
501 // The parent should be an AIE.device op.
502 rewriter.setInsertionPointAfter(op->getParentOp());
503
504 std::string coreName("core_" + std::to_string(col) + "_" +
505 std::to_string(row));
506 auto coreFunc = rewriter.create<func::FuncOp>(
507 rewriter.getUnknownLoc(), coreName,
508 FunctionType::get(rewriter.getContext(), {}, {}));
509
510 rewriter.cloneRegionBefore(op.getBody(), coreFunc.getBody(),
511 coreFunc.getBody().begin(), mapper);
512
513 // Rewrite the AIE.end() op
514 coreFunc.getBody().walk([&](Operation *childOp) {
515 rewriter.setInsertionPointAfter(childOp);
516
517 if (isa<EndOp>(childOp)) {
518 rewriter.create<func::ReturnOp>(rewriter.getUnknownLoc(),
519 ValueRange({}));
520 rewriter.eraseOp(childOp);
521 }
522 });
523
524 rewriter.eraseOp(op);
525 return success();
526 }
527};
528
529// Move all the ops with OpTy inside device, to just before the device.
530template <typename OpTy>
531void outlineOps(DeviceOp device) {
532 SmallVector<OpTy, 16> ops;
533 for (const auto &op : device.getOps<OpTy>())
534 ops.push_back(op);
535
536 for (const auto &op : ops)
537 op->moveBefore(device);
538}
539
540// Lower AIE.event to llvm.aie.event intrinsic
542 using OpConversionPattern::OpConversionPattern;
543 ModuleOp &module;
544
545 AIEEventOpToStdLowering(MLIRContext *context, ModuleOp &m,
546 PatternBenefit benefit = 1)
547 : OpConversionPattern(context, benefit), module(m) {}
548
549 LogicalResult
550 matchAndRewrite(EventOp op, OpAdaptor adaptor,
551 ConversionPatternRewriter &rewriter) const override {
552 std::string funcName = "llvm.aie.event" + std::to_string(op.getVal());
553 auto eventFunc = module.lookupSymbol<func::FuncOp>(funcName);
554 if (!eventFunc)
555 return op.emitOpError("Could not find the intrinsic function ")
556 << funcName;
557 rewriter.create<func::CallOp>(rewriter.getUnknownLoc(), eventFunc,
558 ValueRange({}));
559 rewriter.eraseOp(op);
560 return success();
561 }
562};
563
564struct AIECoreToStandardPass : AIECoreToStandardBase<AIECoreToStandardPass> {
565 void runOnOperation() override {
566
567 ModuleOp m = getOperation();
568 OpBuilder builder = OpBuilder::atBlockEnd(m.getBody());
569
570 if (m.getOps<DeviceOp>().empty()) {
571 m.emitOpError("expected AIE.device operation at toplevel");
572 return signalPassFailure();
573 }
574 DeviceOp device = *m.getOps<DeviceOp>().begin();
575 const auto &targetModel = device.getTargetModel();
576
577 // Ensure that we don't have an incorrect target triple. This may override
578 // some bogus target triple in the original mlir.
579 m->setAttr(LLVM::LLVMDialect::getTargetTripleAttrName(),
580 builder.getStringAttr(
581 getArchIntrinsicString(targetModel.getTargetArch())));
582
583 DenseMap<Operation *, SmallVector<BufferOp, 4>> tileToBuffers;
584
585 // Populate intrinsic functions
586 // Intrinsic information:
587 // peano/llvm-project/llvm/lib/Target/AIE/AIEInstrInfo.td Also take a look
588 // at the tests: peano/llvm-project/llvm/test/CodeGen/AIE
589 builder.setInsertionPointToStart(m.getBody());
590 declareAIEIntrinsics(targetModel.getTargetArch(), builder);
591
592 IRMapping mapper;
593 ConversionTarget target(getContext());
594 target.addLegalDialect<func::FuncDialect>();
595 target.addLegalDialect<cf::ControlFlowDialect>();
596 target.addLegalDialect<memref::MemRefDialect>();
597 target.addLegalDialect<VectorDialect>();
598 target.addLegalDialect<arith::ArithDialect>();
599 target.addLegalDialect<math::MathDialect>();
600 target.addLegalDialect<index::IndexDialect>();
601 target.addLegalOp<func::FuncOp, ModuleOp>();
602
603 RewritePatternSet patterns(&getContext());
607 AIEEventOpToStdLowering>(m.getContext(), m);
608
609 patterns.add<AIEBufferToStandard>(m.getContext(), m, /*benefit*/ 1, tileCol,
610 tileRow);
611 if (failed(applyPartialConversion(m, target, std::move(patterns))))
612 return signalPassFailure();
613
614 RewritePatternSet outlinePatterns(&getContext());
615 outlinePatterns.add<AIECoreToStandardFunc>(m.getContext(), m, mapper,
616 tileToBuffers, /*benefit*/ 1,
617 tileCol, tileRow);
618 if (failed(applyPartialConversion(m, target, std::move(outlinePatterns))))
619 return signalPassFailure();
620
621 // Move all the func.func ops and memref.globals from the device to the
622 // module
623 outlineOps<memref::GlobalOp>(device);
624 outlineOps<func::FuncOp>(device);
625
626 RewritePatternSet removepatterns(&getContext());
627 removepatterns.add<
633 m.getContext(), m);
634
635 if (failed(applyPartialConversion(m, target, std::move(removepatterns))))
636 return signalPassFailure();
637 }
638};
639
640std::unique_ptr<OperationPass<ModuleOp>> AIE::createAIECoreToStandardPass() {
641 return std::make_unique<AIECoreToStandardPass>();
642}
std::vector< IntrinsicDecl > IntrinsicDecls
void outlineOps(DeviceOp device)
std::tuple< const char *, std::vector< Type >, std::vector< Type > > IntrinsicDecl
Include the generated interface declarations.
std::unique_ptr< mlir::OperationPass< mlir::ModuleOp > > createAIECoreToStandardPass()
AIEArch
Definition Passes.h:21
LogicalResult matchAndRewrite(BufferOp buffer, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
AIEBufferToStandard(MLIRContext *context, ModuleOp &m, PatternBenefit benefit=1, int tileCol=-1, int tileRow=-1)
ModuleOp &IRMapping & mapper
LogicalResult matchAndRewrite(CoreOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
AIECoreToStandardFunc(MLIRContext *context, ModuleOp &m, IRMapping &mapper, DenseMap< Operation *, SmallVector< BufferOp, 4 > > &tileToBuffers, PatternBenefit benefit=1, int tileCol=1, int tileRow=1)
DenseMap< Operation *, SmallVector< BufferOp, 4 > > & tileToBuffers
ModuleOp & AIEDebugOpToStdLowering(MLIRContext *context, ModuleOp &m, PatternBenefit benefit=1)
LogicalResult matchAndRewrite(DebugOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
ModuleOp & AIEEventOpToStdLowering(MLIRContext *context, ModuleOp &m, PatternBenefit benefit=1)
LogicalResult matchAndRewrite(EventOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
LogicalResult matchAndRewrite(GetCascadeOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
ModuleOp & AIEGetCascadeToStdLowering(MLIRContext *context, ModuleOp &m, PatternBenefit benefit=1)
LogicalResult matchAndRewrite(GetStreamOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
ModuleOp & AIEGetStreamToStdLowering(MLIRContext *context, ModuleOp &m, PatternBenefit benefit=1)
ModuleOp & AIEOpRemoval(MLIRContext *context, ModuleOp &m, PatternBenefit benefit=1)
typename MyAIEOp::Adaptor OpAdaptor
LogicalResult matchAndRewrite(MyAIEOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
LogicalResult matchAndRewrite(PutCascadeOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
ModuleOp & AIEPutCascadeToStdLowering(MLIRContext *context, ModuleOp &m, PatternBenefit benefit=1)
LogicalResult matchAndRewrite(PutStreamOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
ModuleOp & AIEPutStreamToStdLowering(MLIRContext *context, ModuleOp &m, PatternBenefit benefit=1)
ModuleOp & AIEUseLockToStdLowering(MLIRContext *context, ModuleOp &m, PatternBenefit benefit=1)
LogicalResult matchAndRewrite(UseLockOp useLock, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override