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