MLIR-AIE 1.4.5.dev
AIELocalizeLocks.cpp
Go to the documentation of this file.
1//===- AIELocalizeLocks.cpp ---------------------------------------*- C++
2//-*-===//
3//
4// Copyright (C) 2019-2022 Xilinx, Inc.
5// Copyright (C) 2022-2026 Advanced Micro Devices, Inc.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7//
8//===----------------------------------------------------------------------===//
9
12
13#include "mlir/Dialect/Arith/IR/Arith.h"
14#include "mlir/Pass/Pass.h"
15
16namespace xilinx::AIE {
17#define GEN_PASS_DEF_AIELOCALIZELOCKS
18#include "aie/Dialect/AIE/Transforms/AIEPasses.h.inc"
19} // namespace xilinx::AIE
20
21#define DEBUG_TYPE "aie-localize-locks"
22
23using namespace mlir;
24using namespace xilinx;
25using namespace xilinx::AIE;
26
28 : xilinx::AIE::impl::AIELocalizeLocksBase<AIELocalizeLocksPass> {
29 void getDependentDialects(DialectRegistry &registry) const override {
30 registry.insert<arith::ArithDialect>();
31 }
32 void runOnOperation() override {
33
34 DeviceOp deviceOp = getOperation();
35
36 for (auto coreOp : deviceOp.getOps<CoreOp>()) {
37 // Collect the locks used in this core.
38 const auto &targetModel = getTargetModel(coreOp);
39
40 auto thisTile = cast<TileOp>(coreOp.getTile().getDefiningOp());
41 int col = thisTile.colIndex();
42 int row = thisTile.rowIndex();
43
44 // Find the neighboring tiles
45 SmallVector<TileOp, 4> accessibleTiles;
46 for (auto tile : deviceOp.getOps<TileOp>())
47 if (int dstRow = tile.rowIndex();
48 targetModel.isLegalMemAffinity(col, row, tile.colIndex(), dstRow))
49 accessibleTiles.push_back(tile);
50
51 for (auto tile : accessibleTiles) {
52 int dstCol = tile.colIndex();
53 int dstRow = tile.rowIndex();
54
55 const auto &targetModel = getTargetModel(tile);
56 for (auto *user : tile.getResult().getUsers())
57 if (auto lock = dyn_cast<LockOp>(user)) {
58 // At this point, we are iterating over all locks that are
59 // accessible from within the current core coreOp. We only need to
60 // localize the current lock if it is used within the core. Note
61 // that this pass is to be applied after the scf-to-cf lowering, so
62 // it suffices to check if the parent of a UseLockOp is coreOp.
63 if (llvm::none_of(lock.getResult().getUsers(),
64 [&](Operation *user) {
65 return user->getParentOp() == coreOp;
66 }))
67 continue;
68
69 auto lockIndexOffset =
70 targetModel.getLockLocalBaseIndex(col, row, dstCol, dstRow);
71 if (!lockIndexOffset)
72 llvm_unreachable("Found illegal lock user!");
73
74 int localLockIndex =
75 lockIndexOffset.value() + lock.getLockIDValue();
76
77 OpBuilder builder =
78 OpBuilder::atBlockBegin(&coreOp.getBody().front());
79
80 Value coreLockIDValue = arith::ConstantIndexOp::create(
81 builder, lock.getLoc(), localLockIndex);
82 lock.getResult().replaceUsesWithIf(
83 coreLockIDValue, [&](OpOperand &opOperand) {
84 return opOperand.getOwner()->getParentOp() == coreOp;
85 });
86 }
87 }
88 }
89 }
90};
91
92std::unique_ptr<OperationPass<DeviceOp>> AIE::createAIELocalizeLocksPass() {
93 return std::make_unique<AIELocalizeLocksPass>();
94}
const AIETargetModel & getTargetModel(mlir::Operation *op)
std::unique_ptr< mlir::OperationPass< DeviceOp > > createAIELocalizeLocksPass()
void runOnOperation() override
void getDependentDialects(DialectRegistry &registry) const override