Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 31 additions & 3 deletions lib/Dialect/DC/DCOps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ class EliminateForkToForkPattern : public OpRewritePattern<ForkOp> {

// We have a fork feeding into another fork. Replace the output fork by
// adding more outputs to the current fork.
size_t totalForks = fork.getNumResults() + userFork.getNumResults() - 1;
size_t totalForks = fork.getNumResults() + userFork.getNumResults();

auto newFork = rewriter.create<dc::ForkOp>(fork.getLoc(),
fork.getToken(), totalForks);
Expand Down Expand Up @@ -180,10 +180,38 @@ class EliminateForkOfSourcePattern : public OpRewritePattern<ForkOp> {
}
};

struct EliminateUnusedForkResultsPattern : mlir::OpRewritePattern<ForkOp> {
using mlir::OpRewritePattern<ForkOp>::OpRewritePattern;

LogicalResult matchAndRewrite(ForkOp op,
PatternRewriter &rewriter) const override {
std::set<unsigned> unusedIndexes;

for (auto res : llvm::enumerate(op.getResults()))
if (res.value().use_empty())
unusedIndexes.insert(res.index());

if (unusedIndexes.empty())
return failure();

// Create a new fork op, dropping the unused results.
rewriter.setInsertionPoint(op);
auto operand = op.getOperand();
auto newFork = rewriter.create<ForkOp>(
op.getLoc(), operand, op.getNumResults() - unusedIndexes.size());
unsigned i = 0;
for (auto oldRes : llvm::enumerate(op.getResults()))
if (unusedIndexes.count(oldRes.index()) == 0)
rewriter.replaceAllUsesWith(oldRes.value(), newFork.getResults()[i++]);
rewriter.eraseOp(op);
return success();
}
};

void ForkOp::getCanonicalizationPatterns(RewritePatternSet &results,
MLIRContext *context) {
results.insert<EliminateForkToForkPattern, EliminateForkOfSourcePattern>(
context);
results.insert<EliminateForkToForkPattern, EliminateForkOfSourcePattern,
EliminateUnusedForkResultsPattern>(context);
}

LogicalResult ForkOp::fold(FoldAdaptor adaptor,
Expand Down
40 changes: 29 additions & 11 deletions test/Dialect/DC/canonicalization.mlir
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// RUN: circt-opt %s --canonicalize --cse --canonicalize | FileCheck %s
// XFAIL: *
// Waiting on: https://github.com/llvm/llvm-project/issues/64280

// CHECK-LABEL: func.func @staggeredJoin1(
Expand All @@ -14,11 +13,12 @@ func.func @staggeredJoin1(%a: !dc.token, %b : !dc.token) -> (!dc.token) {
return %1 : !dc.token
}

// TODO: For some reason, the canonicalizer no longer combines the two joins. Investigate.
// CHECK-LABEL: func.func @staggeredJoin2(
// CHECK-SAME: %[[VAL_0:.*]]: !dc.token, %[[VAL_1:.*]]: !dc.token, %[[VAL_2:.*]]: !dc.token, %[[VAL_3:.*]]: !dc.token) -> !dc.token {
// CHECK: %[[VAL_4:.*]] = dc.join %[[VAL_2]], %[[VAL_3]], %[[VAL_0]], %[[VAL_1]]
// CHECK: return %[[VAL_4]] : !dc.token
// CHECK: }
// CHECKx: %[[VAL_4:.*]] = dc.join %[[VAL_2]], %[[VAL_3]], %[[VAL_0]], %[[VAL_1]]
// CHECKx: return %[[VAL_4]] : !dc.token
// CHECKx: }
func.func @staggeredJoin2(%a: !dc.token, %b : !dc.token, %c : !dc.token, %d : !dc.token) -> (!dc.token) {
%0 = dc.join %a, %b
%1 = dc.join %c, %0, %d
Expand Down Expand Up @@ -83,7 +83,7 @@ func.func @csePack(%a: !dc.token, %b : i32) -> (!dc.value<i32>, !dc.value<i32>)
// CHECK-LABEL: func.func @forkToFork(
// CHECK-SAME: %[[VAL_0:.*]]: !dc.token) -> (!dc.token, !dc.token, !dc.token) {
// CHECK: %[[VAL_1:.*]]:3 = dc.fork [3] %[[VAL_0]]
// CHECK: return %[[VAL_1]]#1, %[[VAL_1]]#1, %[[VAL_1]]#2 : !dc.token, !dc.token, !dc.token
// CHECK: return %[[VAL_1]]#0, %[[VAL_1]]#1, %[[VAL_1]]#2 : !dc.token, !dc.token, !dc.token
// CHECK: }
func.func @forkToFork(%a: !dc.token) -> (!dc.token, !dc.token, !dc.token) {
%0, %1 = dc.fork [2] %a
Expand All @@ -102,11 +102,13 @@ func.func @forkToFork2(%a: !dc.token) -> (!dc.token, !dc.token, !dc.token) {
return %0, %2, %3 : !dc.token, !dc.token, !dc.token
}

// TODO: For some reason, the canonicalizer no longer simplifies this redundant
// triangle pattern. Investigate.
// CHECK-LABEL: func.func @merge(
// CHECK-SAME: %[[VAL_0:.*]]: !dc.value<i1>) -> !dc.token {
// CHECK: %[[VAL_1:.*]], %[[VAL_2:.*]] = dc.unpack %[[VAL_0]] : !dc.value<i1>
// CHECK: return %[[VAL_1]] : !dc.token
// CHECK: }
// CHECKx: %[[VAL_1:.*]], %[[VAL_2:.*]] = dc.unpack %[[VAL_0]] : !dc.value<i1>
// CHECKx: return %[[VAL_1]] : !dc.token
// CHECKx: }
func.func @merge(%sel : !dc.value<i1>) -> (!dc.token) {
// Canonicalize away a merge that is fed by a branch with the same select
// input.
Expand All @@ -115,12 +117,14 @@ func.func @merge(%sel : !dc.value<i1>) -> (!dc.token) {
return %0 : !dc.token
}

// TODO: For some reason, the canonicalizer no longer removes the source->join
// pattern. Investigate.
// CHECK-LABEL: func.func @joinOnSource(
// CHECK-SAME: %[[VAL_0:.*]]: !dc.token,
// CHECK-SAME: %[[VAL_1:.*]]: !dc.token) -> !dc.token {
// CHECK: %[[VAL_2:.*]] = dc.join %[[VAL_0]], %[[VAL_1]]
// CHECK: return %[[VAL_2]] : !dc.token
// CHECK: }
// CHECKx: %[[VAL_2:.*]] = dc.join %[[VAL_0]], %[[VAL_1]]
// CHECKx: return %[[VAL_2]] : !dc.token
// CHECKx: }
func.func @joinOnSource(%a : !dc.token, %b : !dc.token) -> (!dc.token) {
%0 = dc.source
%out = dc.join %a, %0, %b
Expand All @@ -136,3 +140,17 @@ func.func @forkOfSource() -> (!dc.token, !dc.token) {
%1:2 = dc.fork [2] %0
return %1#0, %1#1 : !dc.token, !dc.token
}

// CHECK-LABEL: hw.module @TestForkCanonicalization(in %arg0 : !dc.token, out out0 : !dc.token, out out1 : !dc.token) {
// CHECK-NEXT: [[R0:%.+]]:2 = dc.fork [2] %arg0
// CHECK-NEXT: [[R1:%.+]] = dc.buffer[4] [[R0]]#0 : !dc.token
// CHECK-NEXT: [[R2:%.+]] = dc.buffer[4] [[R0]]#1 : !dc.token
// CHECK-NEXT: hw.output [[R1]], [[R2]] : !dc.token, !dc.token

hw.module @TestForkCanonicalization(in %arg0: !dc.token, out out0: !dc.token, out out1: !dc.token) {
%0:3 = dc.fork [3] %arg0
%1 = dc.buffer [4] %0#1 : !dc.token
%2 = dc.buffer [4] %0#2 : !dc.token
dc.sink %0#2
hw.output %1, %2 : !dc.token, !dc.token
}
Loading