CIRCT 22.0.0git
Loading...
Searching...
No Matches
ESIFolds.cpp
Go to the documentation of this file.
1//===- ESIFolds.cpp - ESI op folders ----------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, 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//===----------------------------------------------------------------------===//
8
10#include "circt/Support/LLVM.h"
11
12#include "mlir/IR/BuiltinAttributes.h"
13#include "mlir/IR/PatternMatch.h"
14
15using namespace circt;
16using namespace circt::esi;
17
18LogicalResult WrapValidReadyOp::canonicalize(WrapValidReadyOp op,
19 PatternRewriter &rewriter) {
20 // If the channel has no consumers but the ready signal does, replace ready
21 // with a constant true (always ready to accept data).
22 if (op.getChanOutput().use_empty() && !op.getReady().use_empty()) {
23 auto trueConst =
24 hw::ConstantOp::create(rewriter, op.getLoc(), rewriter.getI1Type(), 1);
25 rewriter.replaceAllUsesWith(op.getReady(), trueConst);
26 rewriter.eraseOp(op);
27 return success();
28 }
29
30 // If the wrap has no users at all, just erase it.
31 if (op->use_empty()) {
32 rewriter.eraseOp(op);
33 return success();
34 }
35 return failure();
36}
37
38LogicalResult UnwrapFIFOOp::mergeAndErase(UnwrapFIFOOp unwrap, WrapFIFOOp wrap,
39 PatternRewriter &rewriter) {
40 if (unwrap && wrap) {
41 rewriter.replaceOp(unwrap, {wrap.getData(), wrap.getEmpty()});
42 rewriter.replaceOp(wrap, {{}, unwrap.getRden()});
43 return success();
44 }
45 return failure();
46}
47LogicalResult UnwrapFIFOOp::canonicalize(UnwrapFIFOOp op,
48 PatternRewriter &rewriter) {
49 auto wrap = dyn_cast_or_null<WrapFIFOOp>(op.getChanInput().getDefiningOp());
50 if (succeeded(UnwrapFIFOOp::mergeAndErase(op, wrap, rewriter)))
51 return success();
52 return failure();
53}
54
55LogicalResult WrapFIFOOp::canonicalize(WrapFIFOOp op,
56 PatternRewriter &rewriter) {
57 // If the channel has no consumers but the rden signal does, replace rden
58 // with a constant false (not reading since there's no consumer).
59 if (op.getChanOutput().use_empty() && !op.getRden().use_empty()) {
60 auto falseConst =
61 hw::ConstantOp::create(rewriter, op.getLoc(), rewriter.getI1Type(), 0);
62 rewriter.replaceAllUsesWith(op.getRden(), falseConst);
63 rewriter.eraseOp(op);
64 return success();
65 }
66
67 // If the wrap has no users at all, just erase it.
68 if (op->use_empty()) {
69 rewriter.eraseOp(op);
70 return success();
71 }
72
73 // Existing wrap-unwrap canonicalization logic
74 if (!op.getChanOutput().hasOneUse())
75 return rewriter.notifyMatchFailure(
76 op, "channel output doesn't have exactly one use");
77 auto unwrap = dyn_cast_or_null<UnwrapFIFOOp>(
78 op.getChanOutput().getUses().begin()->getOwner());
79 if (succeeded(UnwrapFIFOOp::mergeAndErase(unwrap, op, rewriter)))
80 return success();
81 return rewriter.notifyMatchFailure(
82 op, "could not find corresponding unwrap for wrap");
83}
84
85OpFoldResult WrapWindow::fold(FoldAdaptor) {
86 if (auto unwrap = dyn_cast_or_null<UnwrapWindow>(getFrame().getDefiningOp()))
87 return unwrap.getWindow();
88 return {};
89}
90LogicalResult WrapWindow::canonicalize(WrapWindow op,
91 PatternRewriter &rewriter) {
92 // Loop over all users and replace the frame of all UnwrapWindow users. Delete
93 // op if no users remain.
94 bool edited = false;
95 bool allUsersAreUnwraps = true;
96 for (auto &use : llvm::make_early_inc_range(op.getWindow().getUses())) {
97 if (auto unwrap = dyn_cast<UnwrapWindow>(use.getOwner())) {
98 rewriter.replaceOp(unwrap, op.getFrame());
99 edited = true;
100 } else {
101 allUsersAreUnwraps = false;
102 }
103 }
104 if (allUsersAreUnwraps || op.getWindow().getUses().empty()) {
105 rewriter.eraseOp(op);
106 edited = true;
107 }
108 return success(edited);
109}
110OpFoldResult UnwrapWindow::fold(FoldAdaptor) {
111 if (auto wrap = dyn_cast_or_null<WrapWindow>(getWindow().getDefiningOp()))
112 return wrap.getFrame();
113 return {};
114}
115
116LogicalResult PackBundleOp::canonicalize(PackBundleOp pack,
117 PatternRewriter &rewriter) {
118 Value bundle = pack.getBundle();
119 // This condition should be caught by the verifier, but we don't want to
120 // crash if we assume it since canonicalize can get run on IR in a broken
121 // state.
122 if (!bundle.hasOneUse())
123 return rewriter.notifyMatchFailure(pack,
124 "bundle has zero or more than one user");
125
126 // unpack(pack(x)) -> x
127 auto unpack = dyn_cast<UnpackBundleOp>(*bundle.getUsers().begin());
128 if (unpack) {
129 for (auto [a, b] :
130 llvm::zip_equal(pack.getToChannels(), unpack.getToChannels()))
131 rewriter.replaceAllUsesWith(b, a);
132 for (auto [a, b] :
133 llvm::zip_equal(unpack.getFromChannels(), pack.getFromChannels()))
134 rewriter.replaceAllUsesWith(b, a);
135 rewriter.eraseOp(unpack);
136 rewriter.eraseOp(pack);
137 return success();
138 }
139 return rewriter.notifyMatchFailure(pack,
140 "could not find corresponding unpack");
141}
142
143LogicalResult UnpackBundleOp::canonicalize(UnpackBundleOp unpack,
144 PatternRewriter &rewriter) {
145 Value bundle = unpack.getBundle();
146 // This condition should be caught by the verifier, but we don't want to
147 // crash if we assume it since canonicalize can get run on IR in a broken
148 // state.
149 if (!bundle.hasOneUse())
150 return rewriter.notifyMatchFailure(unpack,
151 "bundle has zero or more than one user");
152
153 // Reuse pack's canonicalizer.
154 auto pack = dyn_cast_or_null<PackBundleOp>(bundle.getDefiningOp());
155 if (pack)
156 return PackBundleOp::canonicalize(pack, rewriter);
157 return rewriter.notifyMatchFailure(unpack,
158 "could not find corresponding pack");
159}
return wrap(CMemoryType::get(unwrap(ctx), baseType, numElements))
static EvaluatorValuePtr unwrap(OMEvaluatorValue c)
Definition OM.cpp:111
create(data_type, value)
Definition hw.py:433
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.