mirror of https://github.com/llvm/circt.git
130 lines
4.8 KiB
C++
130 lines
4.8 KiB
C++
//===- ESIFolds.cpp - ESI op folders ----------------------------*- C++ -*-===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "circt/Dialect/ESI/ESIOps.h"
|
|
#include "circt/Support/LLVM.h"
|
|
|
|
#include "mlir/IR/BuiltinAttributes.h"
|
|
#include "mlir/IR/PatternMatch.h"
|
|
|
|
using namespace circt;
|
|
using namespace circt::esi;
|
|
|
|
LogicalResult WrapValidReadyOp::fold(FoldAdaptor,
|
|
SmallVectorImpl<OpFoldResult> &results) {
|
|
if (!getChanOutput().getUsers().empty())
|
|
return failure();
|
|
OpBuilder builder(getContext());
|
|
results.push_back(
|
|
builder.create<NullSourceOp>(getLoc(), getChanOutput().getType())
|
|
.getOut());
|
|
results.push_back(IntegerAttr::get(IntegerType::get(getContext(), 1), 1));
|
|
return success();
|
|
}
|
|
|
|
LogicalResult UnwrapFIFOOp::mergeAndErase(UnwrapFIFOOp unwrap, WrapFIFOOp wrap,
|
|
PatternRewriter &rewriter) {
|
|
if (unwrap && wrap) {
|
|
rewriter.replaceOp(unwrap, {wrap.getData(), wrap.getEmpty()});
|
|
rewriter.replaceOp(wrap, {{}, unwrap.getRden()});
|
|
return success();
|
|
}
|
|
return failure();
|
|
}
|
|
LogicalResult UnwrapFIFOOp::canonicalize(UnwrapFIFOOp op,
|
|
PatternRewriter &rewriter) {
|
|
auto wrap = dyn_cast_or_null<WrapFIFOOp>(op.getChanInput().getDefiningOp());
|
|
if (succeeded(UnwrapFIFOOp::mergeAndErase(op, wrap, rewriter)))
|
|
return success();
|
|
return failure();
|
|
}
|
|
|
|
LogicalResult WrapFIFOOp::fold(FoldAdaptor,
|
|
SmallVectorImpl<OpFoldResult> &results) {
|
|
if (!getChanOutput().getUsers().empty())
|
|
return failure();
|
|
|
|
OpBuilder builder(getContext());
|
|
results.push_back(
|
|
builder.create<NullSourceOp>(getLoc(), getChanOutput().getType())
|
|
.getOut());
|
|
results.push_back(IntegerAttr::get(
|
|
IntegerType::get(getContext(), 1, IntegerType::Signless), 0));
|
|
return success();
|
|
}
|
|
|
|
LogicalResult WrapFIFOOp::canonicalize(WrapFIFOOp op,
|
|
PatternRewriter &rewriter) {
|
|
|
|
if (!op.getChanOutput().hasOneUse())
|
|
return rewriter.notifyMatchFailure(
|
|
op, "channel output doesn't have exactly one use");
|
|
auto unwrap = dyn_cast_or_null<UnwrapFIFOOp>(
|
|
op.getChanOutput().getUses().begin()->getOwner());
|
|
if (succeeded(UnwrapFIFOOp::mergeAndErase(unwrap, op, rewriter)))
|
|
return success();
|
|
return rewriter.notifyMatchFailure(
|
|
op, "could not find corresponding unwrap for wrap");
|
|
}
|
|
|
|
OpFoldResult WrapWindow::fold(FoldAdaptor) {
|
|
if (auto unwrap = dyn_cast_or_null<UnwrapWindow>(getFrame().getDefiningOp()))
|
|
return unwrap.getWindow();
|
|
return {};
|
|
}
|
|
OpFoldResult UnwrapWindow::fold(FoldAdaptor) {
|
|
if (auto wrap = dyn_cast_or_null<WrapWindow>(getWindow().getDefiningOp()))
|
|
return wrap.getFrame();
|
|
return {};
|
|
}
|
|
|
|
LogicalResult PackBundleOp::canonicalize(PackBundleOp pack,
|
|
PatternRewriter &rewriter) {
|
|
Value bundle = pack.getBundle();
|
|
// This condition should be caught by the verifier, but we don't want to
|
|
// crash if we assume it since canonicalize can get run on IR in a broken
|
|
// state.
|
|
if (!bundle.hasOneUse())
|
|
return rewriter.notifyMatchFailure(pack,
|
|
"bundle has zero or more than one user");
|
|
|
|
// unpack(pack(x)) -> x
|
|
auto unpack = dyn_cast<UnpackBundleOp>(*bundle.getUsers().begin());
|
|
if (unpack) {
|
|
for (auto [a, b] :
|
|
llvm::zip_equal(pack.getToChannels(), unpack.getToChannels()))
|
|
rewriter.replaceAllUsesWith(b, a);
|
|
for (auto [a, b] :
|
|
llvm::zip_equal(unpack.getFromChannels(), pack.getFromChannels()))
|
|
rewriter.replaceAllUsesWith(b, a);
|
|
rewriter.eraseOp(unpack);
|
|
rewriter.eraseOp(pack);
|
|
return success();
|
|
}
|
|
return rewriter.notifyMatchFailure(pack,
|
|
"could not find corresponding unpack");
|
|
}
|
|
|
|
LogicalResult UnpackBundleOp::canonicalize(UnpackBundleOp unpack,
|
|
PatternRewriter &rewriter) {
|
|
Value bundle = unpack.getBundle();
|
|
// This condition should be caught by the verifier, but we don't want to
|
|
// crash if we assume it since canonicalize can get run on IR in a broken
|
|
// state.
|
|
if (!bundle.hasOneUse())
|
|
return rewriter.notifyMatchFailure(unpack,
|
|
"bundle has zero or more than one user");
|
|
|
|
// Reuse pack's canonicalizer.
|
|
auto pack = dyn_cast_or_null<PackBundleOp>(bundle.getDefiningOp());
|
|
if (pack)
|
|
return PackBundleOp::canonicalize(pack, rewriter);
|
|
return rewriter.notifyMatchFailure(unpack,
|
|
"could not find corresponding pack");
|
|
}
|