From c423d1ecad2ddb70062fa357f6d99a0edb60aaab Mon Sep 17 00:00:00 2001 From: mingzheTerapines Date: Thu, 18 Jul 2024 17:50:36 +0800 Subject: [PATCH 01/11] Using pass canonicalizers to lower variableOp to structCreateOp --- lib/Dialect/Moore/MooreOps.cpp | 24 ++++++++++++++++++++++++ test/Dialect/Moore/canonicalizers.mlir | 16 ++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/lib/Dialect/Moore/MooreOps.cpp b/lib/Dialect/Moore/MooreOps.cpp index fb9001a82dde..bedd69ce6612 100644 --- a/lib/Dialect/Moore/MooreOps.cpp +++ b/lib/Dialect/Moore/MooreOps.cpp @@ -286,6 +286,30 @@ VariableOp::handlePromotionComplete(const MemorySlot &slot, Value defaultValue, LogicalResult VariableOp::canonicalize(VariableOp op, ::mlir::PatternRewriter &rewriter) { + if (auto initial = op.getInitial()) { + return TypeSwitch(op.getType().getNestedType()) + .Case([&op, &rewriter, + &initial](auto &type) { + SmallVector createFields; + unsigned bit = 0; + auto i32 = moore::IntType::getInt(op->getContext(), 32); + for (const auto &member : type.getMembers()) { + auto memberType = cast(member.type); + if (auto width = memberType.getBitSize()) { + auto lowBit = rewriter.create(op.getLoc(), i32, bit); + bit += width.value(); + auto field = rewriter.create(op->getLoc(), member.type, + initial, lowBit); + createFields.push_back(field); + } + } + rewriter.replaceOpWithNewOp(op, op.getType(), + createFields); + return success(); + }) + .Default([](auto &) { return failure(); }); + } + Value initial; for (auto *user : op->getUsers()) if (isa(user) && diff --git a/test/Dialect/Moore/canonicalizers.mlir b/test/Dialect/Moore/canonicalizers.mlir index a59d9872a22a..3639fb82f2e3 100644 --- a/test/Dialect/Moore/canonicalizers.mlir +++ b/test/Dialect/Moore/canonicalizers.mlir @@ -100,3 +100,19 @@ moore.module @structCreateFold(in %a : !moore.i1, out b : !moore.i1) { // CHECK: moore.output %a : !moore.i1 moore.output %1 : !moore.i1 } + +// CHECK-LABEL: moore.module @Conversion +moore.module @Conversion(out a : !moore.ref>) { + // CHECK: %0 = moore.constant 0 : i64 + // CHECK: %1 = moore.conversion %0 : !moore.i64 -> !moore.struct<{a: i32, b: i32}> + // CHECK: %2 = moore.constant 0 : i32 + // CHECK: %3 = moore.extract %1 from %2 : struct<{a: i32, b: i32}>, i32 -> i32 + // CHECK: %4 = moore.constant 32 : i32 + // CHECK: %5 = moore.extract %1 from %4 : struct<{a: i32, b: i32}>, i32 -> i32 + // CHECK: %6 = moore.struct_create %3, %5 : !moore.i32, !moore.i32 -> > + // CHECK: moore.output %6 : !moore.ref> + %0 = moore.constant 0 : i64 + %1 = moore.conversion %0 : !moore.i64 -> !moore.struct<{a: i32, b: i32}> + %f = moore.variable %1 : > + moore.output %f : !moore.ref> +} From d4612895d9b09f8d7bab1b6bf9fec63630d1f044 Mon Sep 17 00:00:00 2001 From: mingzheTerapines Date: Thu, 25 Jul 2024 14:13:01 +0800 Subject: [PATCH 02/11] Lower to structCreatOp and structInjectOp --- include/circt/Dialect/Moore/MooreOps.td | 17 ++++++ lib/Conversion/ImportVerilog/Expressions.cpp | 9 ---- lib/Dialect/Moore/MooreOps.cpp | 57 +++++++++++++------- test/Conversion/ImportVerilog/basic.sv | 7 +-- test/Dialect/Moore/canonicalizers.mlir | 25 ++++++--- 5 files changed, 78 insertions(+), 37 deletions(-) diff --git a/include/circt/Dialect/Moore/MooreOps.td b/include/circt/Dialect/Moore/MooreOps.td index f8ca29324071..f32d79406fa8 100644 --- a/include/circt/Dialect/Moore/MooreOps.td +++ b/include/circt/Dialect/Moore/MooreOps.td @@ -293,6 +293,22 @@ def ReadOp : MooreOp<"read", [ }]; } +def AddressOp : MooreOp<"address", [ + TypesMatchWith<"input and result types match", + "result", "input", "cast($_self).getNestedType()"> +]> { + let summary = "Read the current value of a declaration"; + let description = [{ + Creates an SSA value containing a pointer to a variable or constant. + It's similar to llvm.mlir.addressof. + }]; + let arguments = (ins UnpackedType:$input); + let results = (outs Arg:$result); + let assemblyFormat = [{ + $input attr-dict `:` type($result) + }]; +} + //===----------------------------------------------------------------------===// // Assignments //===----------------------------------------------------------------------===// @@ -332,6 +348,7 @@ def BlockingAssignOp : AssignOpBase<"blocking_assign", [ Arg:$dst, UnpackedType:$src ); + let hasCanonicalizeMethod = true; } def NonBlockingAssignOp : AssignOpBase<"nonblocking_assign"> { diff --git a/lib/Conversion/ImportVerilog/Expressions.cpp b/lib/Conversion/ImportVerilog/Expressions.cpp index bbb1b1a664fd..9ed814411843 100644 --- a/lib/Conversion/ImportVerilog/Expressions.cpp +++ b/lib/Conversion/ImportVerilog/Expressions.cpp @@ -113,15 +113,6 @@ struct RvalueExprVisitor { return {}; } - if (auto refOp = lhs.getDefiningOp()) { - auto input = refOp.getInput(); - if (isa(input.getDefiningOp()->getParentOp())) { - builder.create(loc, input.getType(), input, - refOp.getFieldNameAttr(), rhs); - refOp->erase(); - return rhs; - } - } if (expr.isNonBlocking()) builder.create(loc, lhs, rhs); else diff --git a/lib/Dialect/Moore/MooreOps.cpp b/lib/Dialect/Moore/MooreOps.cpp index 638235972fad..302a053e27ee 100644 --- a/lib/Dialect/Moore/MooreOps.cpp +++ b/lib/Dialect/Moore/MooreOps.cpp @@ -289,25 +289,22 @@ LogicalResult VariableOp::canonicalize(VariableOp op, ::mlir::PatternRewriter &rewriter) { if (auto initial = op.getInitial()) { return TypeSwitch(op.getType().getNestedType()) - .Case([&op, &rewriter, - &initial](auto &type) { - SmallVector createFields; - unsigned bit = 0; - auto i32 = moore::IntType::getInt(op->getContext(), 32); - for (const auto &member : type.getMembers()) { - auto memberType = cast(member.type); - if (auto width = memberType.getBitSize()) { - auto lowBit = rewriter.create(op.getLoc(), i32, bit); - bit += width.value(); - auto field = rewriter.create(op->getLoc(), member.type, - initial, lowBit); - createFields.push_back(field); - } - } - rewriter.replaceOpWithNewOp(op, op.getType(), - createFields); - return success(); - }) + .Case( + [&op, &rewriter, &initial](auto &type) { + auto addressOp = rewriter.create( + op.getLoc(), + RefType::get(cast(initial.getType())), initial); + SmallVector createFields; + for (const auto &member : type.getMembers()) { + auto field = rewriter.create( + op->getLoc(), cast(member.type), member.name, + addressOp); + createFields.push_back(field); + } + rewriter.replaceOpWithNewOp(op, op.getType(), + createFields); + return success(); + }) .Default([](auto &) { return failure(); }); } @@ -1000,6 +997,28 @@ DeletionKind BlockingAssignOp::removeBlockingUses( return DeletionKind::Delete; } +LogicalResult BlockingAssignOp::canonicalize(BlockingAssignOp op, + PatternRewriter &rewriter) { + if (auto refOp = op.getDst().getDefiningOp()) { + auto input = refOp.getInput(); + if (isa(input.getDefiningOp()->getParentOp())) { + auto newOp = rewriter.create( + op->getLoc(), input.getType(), input, refOp.getFieldNameAttr(), + op.getSrc()); + rewriter.replaceOpUsesWithIf( + input.getDefiningOp(), newOp->getResults(), + [&op](OpOperand &operand) { + return !operand.getOwner()->isBeforeInBlock(op); + }); + op.getDstMutable(); + op.erase(); + refOp.erase(); + return success(); + } + } + return failure(); +} + //===----------------------------------------------------------------------===// // ReadOp //===----------------------------------------------------------------------===// diff --git a/test/Conversion/ImportVerilog/basic.sv b/test/Conversion/ImportVerilog/basic.sv index bb22b3f32495..bd4754e6d2f6 100644 --- a/test/Conversion/ImportVerilog/basic.sv +++ b/test/Conversion/ImportVerilog/basic.sv @@ -995,14 +995,15 @@ module Expressions; // CHECK: moore.blocking_assign %a, [[TMP2]] a += (a *= a--); - // CHECK: [[TMP1:%.+]] = moore.read %a - // CHECK: [[TMP2:%.+]] = moore.struct_inject %struct0, "a", [[TMP1]] : !moore.ref> + // CHECK: [[TMP1:%.+]] = moore.struct_extract_ref %struct0, "a" : > -> + // CHECK: [[TMP2:%.+]] = moore.read %a + // CHECK: moore.blocking_assign [[TMP1]], [[TMP2]] : i32 struct0.a = a; // CHECK: [[TMP3:%.+]] = moore.struct_extract %struct0, "b" : > -> i32 // CHECK: moore.blocking_assign %b, [[TMP3]] : i32 b = struct0.b; - + //===------------------------------------------------------------------===// // Builtin Functions diff --git a/test/Dialect/Moore/canonicalizers.mlir b/test/Dialect/Moore/canonicalizers.mlir index 0976631d51f9..fad3bf2549b9 100644 --- a/test/Dialect/Moore/canonicalizers.mlir +++ b/test/Dialect/Moore/canonicalizers.mlir @@ -66,6 +66,20 @@ moore.module @structAssign(out a : !moore.ref>) { moore.output %6 : !moore.ref> } +// CHECK-LABEL: moore.module @structExtractRefLower2Inject +moore.module @structExtractRefLower2Inject(out a : !moore.ref>) { + // CHECK: %ii = moore.variable : > + // CHECK: %0 = moore.constant 1 : i32 + // CHECK: %1 = moore.struct_inject %ii, "a", %0 : !moore.ref> + // CHECK: moore.output %1 : !moore.ref> + %ii = moore.variable : > + %0 = moore.struct_extract_ref %ii, "a" : > -> + %1 = moore.constant 1 : i32 + %2 = moore.conversion %1 : !moore.i32 -> !moore.i32 + moore.blocking_assign %0, %2 : i32 + moore.output %ii : !moore.ref> +} + // CHECK-LABEL: moore.module @structInjectFold moore.module @structInjectFold(out a : !moore.ref>) { %x = moore.variable : @@ -105,12 +119,11 @@ moore.module @structCreateFold(in %a : !moore.i1, out b : !moore.i1) { moore.module @Conversion(out a : !moore.ref>) { // CHECK: %0 = moore.constant 0 : i64 // CHECK: %1 = moore.conversion %0 : !moore.i64 -> !moore.struct<{a: i32, b: i32}> - // CHECK: %2 = moore.constant 0 : i32 - // CHECK: %3 = moore.extract %1 from %2 : struct<{a: i32, b: i32}>, i32 -> i32 - // CHECK: %4 = moore.constant 32 : i32 - // CHECK: %5 = moore.extract %1 from %4 : struct<{a: i32, b: i32}>, i32 -> i32 - // CHECK: %6 = moore.struct_create %3, %5 : !moore.i32, !moore.i32 -> > - // CHECK: moore.output %6 : !moore.ref> + // CHECK: %2 = moore.address %1 : > + // CHECK: %3 = moore.struct_extract %2, "a" : > -> i32 + // CHECK: %4 = moore.struct_extract %2, "b" : > -> i32 + // CHECK: %5 = moore.struct_create %3, %4 : !moore.i32, !moore.i32 -> > + // CHECK: moore.output %5 : !moore.ref> %0 = moore.constant 0 : i64 %1 = moore.conversion %0 : !moore.i64 -> !moore.struct<{a: i32, b: i32}> %f = moore.variable %1 : > From 05aacc17d5294416e28a3090efd1989d640f3407 Mon Sep 17 00:00:00 2001 From: mingzheTerapines Date: Fri, 26 Jul 2024 16:18:45 +0800 Subject: [PATCH 03/11] Modify structCreateOp result type to unpacked type --- include/circt/Dialect/Moore/MooreOps.td | 2 +- lib/Dialect/Moore/MooreOps.cpp | 32 +++++++++++++++---------- test/Dialect/Moore/canonicalizers.mlir | 17 +++++++------ 3 files changed, 31 insertions(+), 20 deletions(-) diff --git a/include/circt/Dialect/Moore/MooreOps.td b/include/circt/Dialect/Moore/MooreOps.td index f32d79406fa8..384cd597caa2 100644 --- a/include/circt/Dialect/Moore/MooreOps.td +++ b/include/circt/Dialect/Moore/MooreOps.td @@ -1039,7 +1039,7 @@ def StructCreateOp : MooreOp<"struct_create", [Pure]> { See IEEE 1800-2017 ยง 7.2. "Structures". }]; let arguments = (ins Variadic:$input); - let results = (outs RefType:$result); + let results = (outs UnpackedType:$result); let assemblyFormat = [{ $input attr-dict `:` type($input) `->` type($result) }]; diff --git a/lib/Dialect/Moore/MooreOps.cpp b/lib/Dialect/Moore/MooreOps.cpp index 302a053e27ee..a540927d8546 100644 --- a/lib/Dialect/Moore/MooreOps.cpp +++ b/lib/Dialect/Moore/MooreOps.cpp @@ -301,8 +301,10 @@ LogicalResult VariableOp::canonicalize(VariableOp op, addressOp); createFields.push_back(field); } - rewriter.replaceOpWithNewOp(op, op.getType(), - createFields); + auto value = rewriter.create( + op->getLoc(), op.getType().getNestedType(), createFields); + rewriter.replaceOpWithNewOp( + op, RefType::get(value.getType()), value); return success(); }) .Default([](auto &) { return failure(); }); @@ -531,7 +533,7 @@ LogicalResult ConcatRefOp::inferReturnTypes( LogicalResult StructCreateOp::verify() { /// checks if the types of the inputs are exactly equal to the types of the /// result struct fields - return TypeSwitch(getType().getNestedType()) + return TypeSwitch(getType()) .Case([this](auto &type) { auto members = type.getMembers(); auto inputs = getInput(); @@ -634,14 +636,17 @@ OpFoldResult StructExtractOp::fold(FoldAdaptor adaptor) { return structInject.getFieldNameAttr() == getFieldNameAttr() ? structInject.getNewValue() : Value(); - if (auto structCreate = getInput().getDefiningOp()) { - auto ind = TypeSwitch>( - getInput().getType().getNestedType()) - .Case([this](auto &type) { - return type.getFieldIndex(getFieldNameAttr()); - }) - .Default([](auto &) { return std::nullopt; }); - return ind.has_value() ? structCreate->getOperand(ind.value()) : Value(); + if (auto addressOp = getInput().getDefiningOp()) { + if (auto structCreate = + addressOp.getInput().getDefiningOp()) { + auto ind = TypeSwitch>( + getInput().getType().getNestedType()) + .Case([this](auto &type) { + return type.getFieldIndex(getFieldNameAttr()); + }) + .Default([](auto &) { return std::nullopt; }); + return ind.has_value() ? structCreate->getOperand(ind.value()) : Value(); + } } return {}; } @@ -822,7 +827,10 @@ LogicalResult StructInjectOp::canonicalize(StructInjectOp op, createFields.push_back(it->second); } op.getInputMutable(); - rewriter.replaceOpWithNewOp(op, op.getType(), createFields); + auto value = rewriter.create( + op->getLoc(), op.getType().getNestedType(), createFields); + rewriter.replaceOpWithNewOp(op, RefType::get(value.getType()), + value); return success(); } diff --git a/test/Dialect/Moore/canonicalizers.mlir b/test/Dialect/Moore/canonicalizers.mlir index fad3bf2549b9..1750414a48c3 100644 --- a/test/Dialect/Moore/canonicalizers.mlir +++ b/test/Dialect/Moore/canonicalizers.mlir @@ -47,7 +47,8 @@ moore.module @structAssign(out a : !moore.ref>) { // CHECK: %1 = moore.read %x // CHECK: %2 = moore.constant 1 : i32 // CHECK: %3 = moore.add %1, %2 : i32 - // CHECK: %4 = moore.struct_create %3, %0 : !moore.i32, !moore.i32 -> > + // CHECK: %4 = moore.struct_create %3, %0 : !moore.i32, !moore.i32 -> struct<{a: i32, b: i32}> + // CHECK: %5 = moore.address %4 : > %ii = moore.variable : > %0 = moore.constant 4 : i32 %1 = moore.conversion %0 : !moore.i32 -> !moore.i32 @@ -62,7 +63,7 @@ moore.module @structAssign(out a : !moore.ref>) { %8 = moore.struct_extract %6, "a" : > -> i32 // CHECK: moore.assign %z, %3 : i32 moore.assign %z, %8 : i32 - // CHECK: moore.output %4 : !moore.ref> + // CHECK: moore.output %5 : !moore.ref> moore.output %6 : !moore.ref> } @@ -109,10 +110,11 @@ moore.module @structInjectFold(out a : !moore.ref>) { // CHECK-LABEL: moore.module @structCreateFold moore.module @structCreateFold(in %a : !moore.i1, out b : !moore.i1) { - %0 = moore.struct_create %a : !moore.i1 -> > - %1 = moore.struct_extract %0, "a" : > -> i1 + %0 = moore.struct_create %a : !moore.i1 -> struct<{a: i1}> + %1 = moore.address %0 : > + %2 = moore.struct_extract %1, "a" : > -> i1 // CHECK: moore.output %a : !moore.i1 - moore.output %1 : !moore.i1 + moore.output %2 : !moore.i1 } // CHECK-LABEL: moore.module @Conversion @@ -122,8 +124,9 @@ moore.module @Conversion(out a : !moore.ref>) { // CHECK: %2 = moore.address %1 : > // CHECK: %3 = moore.struct_extract %2, "a" : > -> i32 // CHECK: %4 = moore.struct_extract %2, "b" : > -> i32 - // CHECK: %5 = moore.struct_create %3, %4 : !moore.i32, !moore.i32 -> > - // CHECK: moore.output %5 : !moore.ref> + // CHECK: %5 = moore.struct_create %3, %4 : !moore.i32, !moore.i32 -> struct<{a: i32, b: i32}> + // CHECK: %6 = moore.address %5 : > + // CHECK: moore.output %6 : !moore.ref> %0 = moore.constant 0 : i64 %1 = moore.conversion %0 : !moore.i64 -> !moore.struct<{a: i32, b: i32}> %f = moore.variable %1 : > From a6e507b1792c1a2c571bb628862388172df66ffd Mon Sep 17 00:00:00 2001 From: mingzheTerapines Date: Fri, 26 Jul 2024 17:08:52 +0800 Subject: [PATCH 04/11] Add default constant value 0 for structCreateOp --- lib/Dialect/Moore/MooreOps.cpp | 83 ++++++++++++++------------ test/Dialect/Moore/canonicalizers.mlir | 29 +++++---- 2 files changed, 63 insertions(+), 49 deletions(-) diff --git a/lib/Dialect/Moore/MooreOps.cpp b/lib/Dialect/Moore/MooreOps.cpp index a540927d8546..e7f209bb3ecd 100644 --- a/lib/Dialect/Moore/MooreOps.cpp +++ b/lib/Dialect/Moore/MooreOps.cpp @@ -287,47 +287,54 @@ VariableOp::handlePromotionComplete(const MemorySlot &slot, Value defaultValue, LogicalResult VariableOp::canonicalize(VariableOp op, ::mlir::PatternRewriter &rewriter) { - if (auto initial = op.getInitial()) { - return TypeSwitch(op.getType().getNestedType()) - .Case( - [&op, &rewriter, &initial](auto &type) { - auto addressOp = rewriter.create( - op.getLoc(), - RefType::get(cast(initial.getType())), initial); - SmallVector createFields; - for (const auto &member : type.getMembers()) { - auto field = rewriter.create( - op->getLoc(), cast(member.type), member.name, - addressOp); - createFields.push_back(field); - } - auto value = rewriter.create( - op->getLoc(), op.getType().getNestedType(), createFields); - rewriter.replaceOpWithNewOp( - op, RefType::get(value.getType()), value); - return success(); - }) - .Default([](auto &) { return failure(); }); - } - Value initial; - for (auto *user : op->getUsers()) - if (isa(user) && - (user->getOperand(0) == op.getResult())) { - // Don't canonicalize the multiple continuous assignment to the same - // variable. - if (initial) - return failure(); - initial = user->getOperand(1); - } + return TypeSwitch(op.getType().getNestedType()) + .Case([&op, &rewriter](auto &type) { + SmallVector createFields; + if (auto initial = op.getInitial()) { + auto addressOp = rewriter.create( + op.getLoc(), RefType::get(cast(initial.getType())), + initial); + for (const auto &member : type.getMembers()) { + auto field = rewriter.create( + op->getLoc(), cast(member.type), member.name, + addressOp); + createFields.push_back(field); + } + } else { + for (const auto &member : type.getMembers()) { + // todo: support 4-domain value + auto field = rewriter.create( + op->getLoc(), cast(member.type), 0); + createFields.push_back(field); + } + } + auto value = rewriter.create( + op->getLoc(), op.getType().getNestedType(), createFields); + rewriter.replaceOpWithNewOp( + op, RefType::get(value.getType()), value); + return success(); + }) + .Default([&op, &rewriter](auto &) { + Value initial; + for (auto *user : op->getUsers()) + if (isa(user) && + (user->getOperand(0) == op.getResult())) { + // Don't canonicalize the multiple continuous assignment to the same + // variable. + if (initial) + return failure(); + initial = user->getOperand(1); + } - if (initial) { - rewriter.replaceOpWithNewOp(op, op.getType(), - op.getNameAttr(), initial); - return success(); - } + if (initial) { + rewriter.replaceOpWithNewOp(op, op.getType(), + op.getNameAttr(), initial); + return success(); + } - return failure(); + return failure(); + }); } SmallVector VariableOp::getDestructurableSlots() { diff --git a/test/Dialect/Moore/canonicalizers.mlir b/test/Dialect/Moore/canonicalizers.mlir index 1750414a48c3..7f77fbb75d16 100644 --- a/test/Dialect/Moore/canonicalizers.mlir +++ b/test/Dialect/Moore/canonicalizers.mlir @@ -69,10 +69,13 @@ moore.module @structAssign(out a : !moore.ref>) { // CHECK-LABEL: moore.module @structExtractRefLower2Inject moore.module @structExtractRefLower2Inject(out a : !moore.ref>) { - // CHECK: %ii = moore.variable : > - // CHECK: %0 = moore.constant 1 : i32 - // CHECK: %1 = moore.struct_inject %ii, "a", %0 : !moore.ref> - // CHECK: moore.output %1 : !moore.ref> + // CHECK: %0 = moore.constant 0 : i32 + // CHECK: %1 = moore.constant 0 : i32 + // CHECK: %2 = moore.struct_create %0, %1 : !moore.i32, !moore.i32 -> struct<{a: i32, b: i32}> + // CHECK: %3 = moore.address %2 : > + // CHECK: %4 = moore.constant 1 : i32 + // CHECK: %5 = moore.struct_inject %3, "a", %4 : !moore.ref> + // CHECK: moore.output %5 : !moore.ref> %ii = moore.variable : > %0 = moore.struct_extract_ref %ii, "a" : > -> %1 = moore.constant 1 : i32 @@ -86,11 +89,15 @@ moore.module @structInjectFold(out a : !moore.ref>) { %x = moore.variable : %y = moore.variable : %z = moore.variable : + // CHECK: %0 = moore.constant 0 : i32 + // CHECK: %1 = moore.constant 0 : i32 + // CHECK: %2 = moore.struct_create %0, %1 : !moore.i32, !moore.i32 -> struct<{a: i32, b: i32}> + // CHECK: %3 = moore.address %2 : > %ii = moore.variable : > - // CHECK: %0 = moore.read %x - // CHECK: %1 = moore.constant 1 : i32 - // CHECK: %2 = moore.add %0, %1 : i32 - // CHECK: %3 = moore.struct_inject %ii, "a", %2 : !moore.ref> + // CHECK: %4 = moore.read %x : + // CHECK: %5 = moore.constant 1 : i32 + // CHECK: %6 = moore.add %4, %5 : i32 + // CHECK: %7 = moore.struct_inject %3, "a", %6 : !moore.ref> %0 = moore.constant 4 : i32 %1 = moore.conversion %0 : !moore.i32 -> !moore.i32 %2 = moore.struct_inject %ii, "a", %1 : !moore.ref> @@ -99,12 +106,12 @@ moore.module @structInjectFold(out a : !moore.ref>) { %5 = moore.add %3, %4 : i32 %6 = moore.struct_inject %2, "a", %5 : !moore.ref> %7 = moore.struct_extract %6, "a" : > -> i32 - // CHECK: moore.assign %y, %2 : i32 + // CHECK: moore.assign %y, %6 : i32 moore.assign %y, %7 : i32 %8 = moore.struct_extract %6, "a" : > -> i32 - // CHECK: moore.assign %z, %2 : i32 + // CHECK: moore.assign %z, %6 : i32 moore.assign %z, %8 : i32 - // CHECK: moore.output %3 : !moore.ref> + // CHECK: moore.output %7 : !moore.ref> moore.output %6 : !moore.ref> } From 3b4ab1234cfb24e576ee2930308f15a7762f2492 Mon Sep 17 00:00:00 2001 From: mingzheTerapines Date: Wed, 31 Jul 2024 09:26:04 +0800 Subject: [PATCH 05/11] Merge main --- include/circt/Dialect/Moore/MooreOps.td | 4 ---- 1 file changed, 4 deletions(-) diff --git a/include/circt/Dialect/Moore/MooreOps.td b/include/circt/Dialect/Moore/MooreOps.td index 03f8f4f27b33..5f48cc72a824 100644 --- a/include/circt/Dialect/Moore/MooreOps.td +++ b/include/circt/Dialect/Moore/MooreOps.td @@ -1043,10 +1043,6 @@ def DynExtractRefOp : MooreOp<"dyn_extract_ref", [Pure]> { // Struct Manipulation //===----------------------------------------------------------------------===// -//===----------------------------------------------------------------------===// -// Struct Manipulation -//===----------------------------------------------------------------------===// - def StructCreateOp : MooreOp<"struct_create", [Pure]> { let summary = "Create a struct value from individual fields"; let arguments = (ins Variadic:$fields); From ab3ed8fa92dd113c98d240235b66a7e778c229c5 Mon Sep 17 00:00:00 2001 From: mingzheTerapines Date: Wed, 31 Jul 2024 11:15:58 +0800 Subject: [PATCH 06/11] Fit new version of struct --- include/circt/Dialect/Moore/MooreOps.td | 1 + lib/Dialect/Moore/MooreOps.cpp | 18 ++++++++++++++++-- test/Dialect/Moore/canonicalizers.mlir | 17 +++++++---------- 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/include/circt/Dialect/Moore/MooreOps.td b/include/circt/Dialect/Moore/MooreOps.td index 5f48cc72a824..a9e3f926d466 100644 --- a/include/circt/Dialect/Moore/MooreOps.td +++ b/include/circt/Dialect/Moore/MooreOps.td @@ -291,6 +291,7 @@ def ReadOp : MooreOp<"read", [ let assemblyFormat = [{ $input attr-dict `:` type($input) }]; + let hasCanonicalizeMethod = true; } def AddressOp : MooreOp<"address", [ diff --git a/lib/Dialect/Moore/MooreOps.cpp b/lib/Dialect/Moore/MooreOps.cpp index 6e6cd538688d..7b32f031e850 100644 --- a/lib/Dialect/Moore/MooreOps.cpp +++ b/lib/Dialect/Moore/MooreOps.cpp @@ -909,11 +909,15 @@ LogicalResult BlockingAssignOp::canonicalize(BlockingAssignOp op, if (auto refOp = op.getDst().getDefiningOp()) { auto input = refOp.getInput(); if (isa(input.getDefiningOp()->getParentOp())) { + auto value = rewriter.create( + op->getLoc(), cast(input.getType()).getNestedType(), input); auto newOp = rewriter.create( - op->getLoc(), input.getType(), input, refOp.getFieldNameAttr(), + op->getLoc(), value.getType(), value, refOp.getFieldNameAttr(), op.getSrc()); + auto newOpAddress = rewriter.create( + op.getLoc(), RefType::get(newOp.getType()), newOp); rewriter.replaceOpUsesWithIf( - input.getDefiningOp(), newOp->getResults(), + input.getDefiningOp(), newOpAddress->getResults(), [&op](OpOperand &operand) { return !operand.getOwner()->isBeforeInBlock(op); }); @@ -962,6 +966,16 @@ ReadOp::removeBlockingUses(const MemorySlot &slot, return DeletionKind::Delete; } +LogicalResult ReadOp::canonicalize(ReadOp op, PatternRewriter &rewriter) { + if (auto addr = op.getInput().getDefiningOp()) { + auto value = addr.getInput(); + op.replaceAllUsesWith(value); + op.erase(); + return success(); + } + return failure(); +} + //===----------------------------------------------------------------------===// // TableGen generated logic. //===----------------------------------------------------------------------===// diff --git a/test/Dialect/Moore/canonicalizers.mlir b/test/Dialect/Moore/canonicalizers.mlir index 1d2207093467..ad0e90639e09 100644 --- a/test/Dialect/Moore/canonicalizers.mlir +++ b/test/Dialect/Moore/canonicalizers.mlir @@ -70,20 +70,17 @@ func.func @StructInjectFold1(%arg0: !moore.struct<{a: i32, b: i32}>) -> (!moore. } // CHECK-LABEL: moore.module @structExtractRefLower2Inject -moore.module @structExtractRefLower2Inject(out a : !moore.ref>) { +moore.module @structExtractRefLower2Inject(out a : !moore.struct<{a: i32, b: i32}>) { // CHECK: %0 = moore.constant 0 : i32 - // CHECK: %1 = moore.constant 0 : i32 - // CHECK: %2 = moore.struct_create %0, %1 : !moore.i32, !moore.i32 -> struct<{a: i32, b: i32}> - // CHECK: %3 = moore.address %2 : > - // CHECK: %4 = moore.constant 1 : i32 - // CHECK: %5 = moore.struct_inject %3, "a", %4 : !moore.ref> - // CHECK: moore.output %5 : !moore.ref> + // CHECK: %1 = moore.constant 1 : i32 + // CHECK: %2 = moore.struct_create %1, %0 : !moore.i32, !moore.i32 -> struct<{a: i32, b: i32}> + // CHECK: moore.output %2 : !moore.struct<{a: i32, b: i32}> %ii = moore.variable : > %0 = moore.struct_extract_ref %ii, "a" : > -> %1 = moore.constant 1 : i32 - %2 = moore.conversion %1 : !moore.i32 -> !moore.i32 - moore.blocking_assign %0, %2 : i32 - moore.output %ii : !moore.ref> + moore.blocking_assign %0, %1 : i32 + %2 = moore.read %ii : > + moore.output %2 : !moore.struct<{a: i32, b: i32}> } // CHECK-LABEL: func.func @StructInjectFold2 From db8f16b8ba11a2432a3cef8ea9237821019a5514 Mon Sep 17 00:00:00 2001 From: mingzheTerapines Date: Fri, 2 Aug 2024 13:31:28 +0800 Subject: [PATCH 07/11] Remove typeswitch Add func.func Dialect Disable caonicalize function for local variable --- include/circt/Dialect/Moore/MooreDialect.td | 2 +- include/circt/Dialect/Moore/MooreOps.h | 1 + lib/Dialect/Moore/CMakeLists.txt | 1 + lib/Dialect/Moore/MooreDialect.cpp | 1 + lib/Dialect/Moore/MooreOps.cpp | 107 +++++++++++--------- 5 files changed, 63 insertions(+), 49 deletions(-) diff --git a/include/circt/Dialect/Moore/MooreDialect.td b/include/circt/Dialect/Moore/MooreDialect.td index 84f57a5285f4..ffec56edd9c1 100644 --- a/include/circt/Dialect/Moore/MooreDialect.td +++ b/include/circt/Dialect/Moore/MooreDialect.td @@ -35,7 +35,7 @@ def MooreDialect : Dialect { void printType(Type, DialectAsmPrinter &) const override; }]; let useDefaultTypePrinterParser = 0; - let dependentDialects = ["hw::HWDialect"]; + let dependentDialects = ["hw::HWDialect", "mlir::func::FuncDialect"]; } #endif // CIRCT_DIALECT_MOORE_MOOREDIALECT diff --git a/include/circt/Dialect/Moore/MooreOps.h b/include/circt/Dialect/Moore/MooreOps.h index 5a27457159d8..626174184dbd 100644 --- a/include/circt/Dialect/Moore/MooreOps.h +++ b/include/circt/Dialect/Moore/MooreOps.h @@ -16,6 +16,7 @@ #include "circt/Dialect/HW/HWTypes.h" #include "circt/Dialect/Moore/MooreDialect.h" #include "circt/Dialect/Moore/MooreTypes.h" +#include "mlir/Dialect/Func/IR/FuncOps.h" #include "mlir/IR/RegionKindInterface.h" #include "mlir/Interfaces/ControlFlowInterfaces.h" #include "mlir/Interfaces/InferTypeOpInterface.h" diff --git a/lib/Dialect/Moore/CMakeLists.txt b/lib/Dialect/Moore/CMakeLists.txt index bda0ea7713cc..4cb49c6d18a2 100644 --- a/lib/Dialect/Moore/CMakeLists.txt +++ b/lib/Dialect/Moore/CMakeLists.txt @@ -18,6 +18,7 @@ add_circt_dialect_library(CIRCTMoore CIRCTHW CIRCTSupport MLIRIR + MLIRFuncDialect MLIRInferTypeOpInterface MLIRMemorySlotInterfaces ) diff --git a/lib/Dialect/Moore/MooreDialect.cpp b/lib/Dialect/Moore/MooreDialect.cpp index 902fbb27e730..3aa3a6e37bfd 100644 --- a/lib/Dialect/Moore/MooreDialect.cpp +++ b/lib/Dialect/Moore/MooreDialect.cpp @@ -12,6 +12,7 @@ #include "circt/Dialect/HW/HWDialect.h" #include "circt/Dialect/Moore/MooreOps.h" +#include "mlir/Dialect/Func/IR/FuncOps.h" using namespace circt; using namespace circt::moore; diff --git a/lib/Dialect/Moore/MooreOps.cpp b/lib/Dialect/Moore/MooreOps.cpp index 7b32f031e850..5a638f012581 100644 --- a/lib/Dialect/Moore/MooreOps.cpp +++ b/lib/Dialect/Moore/MooreOps.cpp @@ -22,6 +22,8 @@ using namespace circt; using namespace circt::moore; using namespace mlir; +static ArrayRef getStructMembers(Type type); + //===----------------------------------------------------------------------===// // SVModuleOp //===----------------------------------------------------------------------===// @@ -289,54 +291,55 @@ VariableOp::handlePromotionComplete(const MemorySlot &slot, Value defaultValue, LogicalResult VariableOp::canonicalize(VariableOp op, ::mlir::PatternRewriter &rewriter) { + if (!(isa(op->getParentOp()) || + isa(op->getParentOp()))) + return failure(); + auto members = getStructMembers(op.getType().getNestedType()); + if (!members.empty()) { + SmallVector createFields; + if (auto initial = op.getInitial()) { + auto addressOp = rewriter.create( + op.getLoc(), RefType::get(cast(initial.getType())), + initial); + for (const auto &member : members) { + auto field = rewriter.create( + op->getLoc(), cast(member.type), member.name, + addressOp); + createFields.push_back(field); + } + } else { + for (const auto &member : members) { + // todo: support 4-domain value + auto field = rewriter.create(op->getLoc(), + cast(member.type), 0); + createFields.push_back(field); + } + } + auto value = rewriter.create( + op->getLoc(), op.getType().getNestedType(), createFields); + rewriter.replaceOpWithNewOp(op, RefType::get(value.getType()), + value); + return success(); + } - return TypeSwitch(op.getType().getNestedType()) - .Case([&op, &rewriter](auto &type) { - SmallVector createFields; - if (auto initial = op.getInitial()) { - auto addressOp = rewriter.create( - op.getLoc(), RefType::get(cast(initial.getType())), - initial); - for (const auto &member : type.getMembers()) { - auto field = rewriter.create( - op->getLoc(), cast(member.type), member.name, - addressOp); - createFields.push_back(field); - } - } else { - for (const auto &member : type.getMembers()) { - // todo: support 4-domain value - auto field = rewriter.create( - op->getLoc(), cast(member.type), 0); - createFields.push_back(field); - } - } - auto value = rewriter.create( - op->getLoc(), op.getType().getNestedType(), createFields); - rewriter.replaceOpWithNewOp( - op, RefType::get(value.getType()), value); - return success(); - }) - .Default([&op, &rewriter](auto &) { - Value initial; - for (auto *user : op->getUsers()) - if (isa(user) && - (user->getOperand(0) == op.getResult())) { - // Don't canonicalize the multiple continuous assignment to the same - // variable. - if (initial) - return failure(); - initial = user->getOperand(1); - } - - if (initial) { - rewriter.replaceOpWithNewOp(op, op.getType(), - op.getNameAttr(), initial); - return success(); - } - + Value initial; + for (auto *user : op->getUsers()) + if (isa(user) && + (user->getOperand(0) == op.getResult())) { + // Don't canonicalize the multiple continuous assignment to the same + // variable. + if (initial) return failure(); - }); + initial = user->getOperand(1); + } + + if (initial) { + rewriter.replaceOpWithNewOp(op, op.getType(), + op.getNameAttr(), initial); + return success(); + } + + return failure(); } SmallVector VariableOp::getDestructurableSlots() { @@ -560,7 +563,6 @@ static ArrayRef getStructMembers(Type type) { return structType.getMembers(); if (auto structType = dyn_cast(type)) return structType.getMembers(); - assert(0 && "expected StructType or UnpackedStructType"); return {}; } @@ -708,6 +710,9 @@ OpFoldResult StructInjectOp::fold(FoldAdaptor adaptor) { LogicalResult StructInjectOp::canonicalize(StructInjectOp op, PatternRewriter &rewriter) { + if (!(isa(op->getParentOp()) || + isa(op->getParentOp()))) + return failure(); auto members = getStructMembers(op.getType()); // Chase a chain of `struct_inject` ops, with an optional final @@ -906,9 +911,12 @@ DeletionKind BlockingAssignOp::removeBlockingUses( LogicalResult BlockingAssignOp::canonicalize(BlockingAssignOp op, PatternRewriter &rewriter) { + if (!(isa(op->getParentOp()) || + isa(op->getParentOp()))) + return failure(); if (auto refOp = op.getDst().getDefiningOp()) { auto input = refOp.getInput(); - if (isa(input.getDefiningOp()->getParentOp())) { + if (isa(input.getDefiningOp()->getParentOp())) { auto value = rewriter.create( op->getLoc(), cast(input.getType()).getNestedType(), input); auto newOp = rewriter.create( @@ -967,6 +975,9 @@ ReadOp::removeBlockingUses(const MemorySlot &slot, } LogicalResult ReadOp::canonicalize(ReadOp op, PatternRewriter &rewriter) { + if (!(isa(op->getParentOp()) || + isa(op->getParentOp()))) + return failure(); if (auto addr = op.getInput().getDefiningOp()) { auto value = addr.getInput(); op.replaceAllUsesWith(value); From 732a4126fb73cd4f873a7075cf133b4666877267 Mon Sep 17 00:00:00 2001 From: mingzheTerapines Date: Fri, 2 Aug 2024 14:28:52 +0800 Subject: [PATCH 08/11] Support union type --- lib/Dialect/Moore/MooreOps.cpp | 95 +++++++++++++++------------------- 1 file changed, 43 insertions(+), 52 deletions(-) diff --git a/lib/Dialect/Moore/MooreOps.cpp b/lib/Dialect/Moore/MooreOps.cpp index 5a638f012581..22ee8911d082 100644 --- a/lib/Dialect/Moore/MooreOps.cpp +++ b/lib/Dialect/Moore/MooreOps.cpp @@ -554,7 +554,11 @@ static std::optional getStructFieldIndex(Type type, StringAttr name) { return structType.getFieldIndex(name); if (auto structType = dyn_cast(type)) return structType.getFieldIndex(name); - assert(0 && "expected StructType or UnpackedStructType"); + if (auto unionType = dyn_cast(type)) + return unionType.getFieldIndex(name); + if (auto unionType = dyn_cast(type)) + return unionType.getFieldIndex(name); + assert(0 && "expected Struct-Like Type"); return {}; } @@ -563,6 +567,10 @@ static ArrayRef getStructMembers(Type type) { return structType.getMembers(); if (auto structType = dyn_cast(type)) return structType.getMembers(); + if (auto unionType = dyn_cast(type)) + return unionType.getMembers(); + if (auto unionType = dyn_cast(type)) + return unionType.getMembers(); return {}; } @@ -760,23 +768,18 @@ LogicalResult StructInjectOp::canonicalize(StructInjectOp op, //===----------------------------------------------------------------------===// LogicalResult UnionCreateOp::verify() { - /// checks if the types of the input is exactly equal to the union field + auto type = getStructFieldType(getType(), getFieldNameAttr()); + + /// checks if the type of the input is exactly equal to the union field /// type - return TypeSwitch(getType()) - .Case([this](auto &type) { - auto members = type.getMembers(); - auto resultType = getType(); - auto fieldName = getFieldName(); - for (const auto &member : members) - if (member.name == fieldName && member.type == resultType) - return success(); - emitOpError("input type must match the union field type"); - return failure(); - }) - .Default([this](auto &) { - emitOpError("input type must be UnionType or UnpackedUnionType"); - return failure(); - }); + + if (!type) + return emitOpError() << "union field " << getFieldNameAttr() + << " which does not exist in " << getInput().getType(); + if (type != getType()) + return emitOpError() << "result type " << getType() + << " must match union field type " << type; + return success(); } //===----------------------------------------------------------------------===// @@ -784,47 +787,35 @@ LogicalResult UnionCreateOp::verify() { //===----------------------------------------------------------------------===// LogicalResult UnionExtractOp::verify() { - /// checks if the types of the input is exactly equal to the one of the - /// types of the result union fields - return TypeSwitch(getInput().getType()) - .Case([this](auto &type) { - auto members = type.getMembers(); - auto fieldName = getFieldName(); - auto resultType = getType(); - for (const auto &member : members) - if (member.name == fieldName && member.type == resultType) - return success(); - emitOpError("result type must match the union field type"); - return failure(); - }) - .Default([this](auto &) { - emitOpError("input type must be UnionType or UnpackedUnionType"); - return failure(); - }); + auto type = getStructFieldType(getInput().getType(), getFieldNameAttr()); + + /// checks if the type of the input is exactly equal to the type of the result + /// union fields + if (!type) + return emitOpError() << "union field " << getFieldNameAttr() + << " which does not exist in " << getInput().getType(); + if (type != getType()) + return emitOpError() << "result type " << getType() + << " must match union field type " << type; + return success(); } //===----------------------------------------------------------------------===// -// UnionExtractOp +// UnionExtractRefOp //===----------------------------------------------------------------------===// LogicalResult UnionExtractRefOp::verify() { - /// checks if the types of the result is exactly equal to the type of the - /// refe union field - return TypeSwitch(getInput().getType().getNestedType()) - .Case([this](auto &type) { - auto members = type.getMembers(); - auto fieldName = getFieldName(); - auto resultType = getType().getNestedType(); - for (const auto &member : members) - if (member.name == fieldName && member.type == resultType) - return success(); - emitOpError("result type must match the union field type"); - return failure(); - }) - .Default([this](auto &) { - emitOpError("input type must be UnionType or UnpackedUnionType"); - return failure(); - }); + auto type = getStructFieldType(getInput().getType().getNestedType(), + getFieldNameAttr()); + /// checks if the type of the result is exactly equal to the type of the + /// referring union field + if (!type) + return emitOpError() << "union field " << getFieldNameAttr() + << " which does not exist in " << getInput().getType(); + if (type != getType()) + return emitOpError() << "result type " << getType() + << " must match union field type " << type; + return success(); } //===----------------------------------------------------------------------===// From 0729f70cded77cfff85fcce9f6e44f787cf4c48b Mon Sep 17 00:00:00 2001 From: mingzheTerapines Date: Fri, 2 Aug 2024 14:29:05 +0800 Subject: [PATCH 09/11] support uniont type2 --- lib/Dialect/Moore/MooreOps.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/Dialect/Moore/MooreOps.cpp b/lib/Dialect/Moore/MooreOps.cpp index 22ee8911d082..4897e3ff2916 100644 --- a/lib/Dialect/Moore/MooreOps.cpp +++ b/lib/Dialect/Moore/MooreOps.cpp @@ -16,7 +16,6 @@ #include "circt/Support/CustomDirectiveImpl.h" #include "mlir/IR/Builders.h" #include "llvm/ADT/SmallString.h" -#include "llvm/ADT/TypeSwitch.h" using namespace circt; using namespace circt::moore; From 5b91dc806301cf7c145636200f697c8bb286b5d0 Mon Sep 17 00:00:00 2001 From: mingzheTerapines Date: Fri, 23 Aug 2024 09:26:28 +0800 Subject: [PATCH 10/11] Revert some codes. --- include/circt/Dialect/Moore/MooreOps.td | 18 ----- lib/Dialect/Moore/MooreOps.cpp | 97 +------------------------ test/Dialect/Moore/canonicalizers.mlir | 14 ---- 3 files changed, 1 insertion(+), 128 deletions(-) diff --git a/include/circt/Dialect/Moore/MooreOps.td b/include/circt/Dialect/Moore/MooreOps.td index b6b222d586ac..b0ca268ec8c1 100644 --- a/include/circt/Dialect/Moore/MooreOps.td +++ b/include/circt/Dialect/Moore/MooreOps.td @@ -298,23 +298,6 @@ def ReadOp : MooreOp<"read", [ let assemblyFormat = [{ $input attr-dict `:` type($input) }]; - let hasCanonicalizeMethod = true; -} - -def AddressOp : MooreOp<"address", [ - TypesMatchWith<"input and result types match", - "result", "input", "cast($_self).getNestedType()"> -]> { - let summary = "Read the current value of a declaration"; - let description = [{ - Creates an SSA value containing a pointer to a variable or constant. - It's similar to llvm.mlir.addressof. - }]; - let arguments = (ins UnpackedType:$input); - let results = (outs Arg:$result); - let assemblyFormat = [{ - $input attr-dict `:` type($result) - }]; } //===----------------------------------------------------------------------===// @@ -356,7 +339,6 @@ def BlockingAssignOp : AssignOpBase<"blocking_assign", [ Arg:$dst, UnpackedType:$src ); - let hasCanonicalizeMethod = true; } def NonBlockingAssignOp : AssignOpBase<"nonblocking_assign"> { diff --git a/lib/Dialect/Moore/MooreOps.cpp b/lib/Dialect/Moore/MooreOps.cpp index b04d13d3d517..89b337b4f1d7 100644 --- a/lib/Dialect/Moore/MooreOps.cpp +++ b/lib/Dialect/Moore/MooreOps.cpp @@ -360,60 +360,7 @@ VariableOp::handlePromotionComplete(const MemorySlot &slot, Value defaultValue, if (defaultValue && defaultValue.use_empty()) defaultValue.getDefiningOp()->erase(); this->erase(); - return std::nullopt; -} - -LogicalResult VariableOp::canonicalize(VariableOp op, - ::mlir::PatternRewriter &rewriter) { - if (!(isa(op->getParentOp()) || - isa(op->getParentOp()))) - return failure(); - auto members = getStructMembers(op.getType().getNestedType()); - if (!members.empty()) { - SmallVector createFields; - if (auto initial = op.getInitial()) { - auto addressOp = rewriter.create( - op.getLoc(), RefType::get(cast(initial.getType())), - initial); - for (const auto &member : members) { - auto field = rewriter.create( - op->getLoc(), cast(member.type), member.name, - addressOp); - createFields.push_back(field); - } - } else { - for (const auto &member : members) { - // todo: support 4-domain value - auto field = rewriter.create(op->getLoc(), - cast(member.type), 0); - createFields.push_back(field); - } - } - auto value = rewriter.create( - op->getLoc(), op.getType().getNestedType(), createFields); - rewriter.replaceOpWithNewOp(op, RefType::get(value.getType()), - value); - return success(); - } - - Value initial; - for (auto *user : op->getUsers()) - if (isa(user) && - (user->getOperand(0) == op.getResult())) { - // Don't canonicalize the multiple continuous assignment to the same - // variable. - if (initial) - return failure(); - initial = user->getOperand(1); - } - - if (initial) { - rewriter.replaceOpWithNewOp(op, op.getType(), - op.getNameAttr(), initial); - return success(); - } - - return failure(); + return {}; } SmallVector VariableOp::getDestructurableSlots() { @@ -1139,35 +1086,6 @@ DeletionKind BlockingAssignOp::removeBlockingUses( return DeletionKind::Delete; } -LogicalResult BlockingAssignOp::canonicalize(BlockingAssignOp op, - PatternRewriter &rewriter) { - if (!(isa(op->getParentOp()) || - isa(op->getParentOp()))) - return failure(); - if (auto refOp = op.getDst().getDefiningOp()) { - auto input = refOp.getInput(); - if (isa(input.getDefiningOp()->getParentOp())) { - auto value = rewriter.create( - op->getLoc(), cast(input.getType()).getNestedType(), input); - auto newOp = rewriter.create( - op->getLoc(), value.getType(), value, refOp.getFieldNameAttr(), - op.getSrc()); - auto newOpAddress = rewriter.create( - op.getLoc(), RefType::get(newOp.getType()), newOp); - rewriter.replaceOpUsesWithIf( - input.getDefiningOp(), newOpAddress->getResults(), - [&op](OpOperand &operand) { - return !operand.getOwner()->isBeforeInBlock(op); - }); - op.getDstMutable(); - op.erase(); - refOp.erase(); - return success(); - } - } - return failure(); -} - //===----------------------------------------------------------------------===// // ReadOp //===----------------------------------------------------------------------===// @@ -1204,19 +1122,6 @@ ReadOp::removeBlockingUses(const MemorySlot &slot, return DeletionKind::Delete; } -LogicalResult ReadOp::canonicalize(ReadOp op, PatternRewriter &rewriter) { - if (!(isa(op->getParentOp()) || - isa(op->getParentOp()))) - return failure(); - if (auto addr = op.getInput().getDefiningOp()) { - auto value = addr.getInput(); - op.replaceAllUsesWith(value); - op.erase(); - return success(); - } - return failure(); -} - //===----------------------------------------------------------------------===// // PowSOp //===----------------------------------------------------------------------===// diff --git a/test/Dialect/Moore/canonicalizers.mlir b/test/Dialect/Moore/canonicalizers.mlir index 590dbbfbe581..2754fcef860c 100644 --- a/test/Dialect/Moore/canonicalizers.mlir +++ b/test/Dialect/Moore/canonicalizers.mlir @@ -206,20 +206,6 @@ func.func @StructInjectFold1(%arg0: !moore.struct<{a: i32, b: i32}>) -> (!moore. return %4 : !moore.struct<{a: i32, b: i32}> } -// CHECK-LABEL: moore.module @structExtractRefLower2Inject -moore.module @structExtractRefLower2Inject(out a : !moore.struct<{a: i32, b: i32}>) { - // CHECK: %0 = moore.constant 0 : i32 - // CHECK: %1 = moore.constant 1 : i32 - // CHECK: %2 = moore.struct_create %1, %0 : !moore.i32, !moore.i32 -> struct<{a: i32, b: i32}> - // CHECK: moore.output %2 : !moore.struct<{a: i32, b: i32}> - %ii = moore.variable : > - %0 = moore.struct_extract_ref %ii, "a" : > -> - %1 = moore.constant 1 : i32 - moore.blocking_assign %0, %1 : i32 - %2 = moore.read %ii : > - moore.output %2 : !moore.struct<{a: i32, b: i32}> -} - // CHECK-LABEL: func.func @StructInjectFold2 func.func @StructInjectFold2() -> (!moore.struct<{a: i32, b: i32}>) { // CHECK-NEXT: [[C42:%.+]] = moore.constant 42 From 6027b9de2d597fd0dd34c3cdaf6b6e43c654da41 Mon Sep 17 00:00:00 2001 From: mingzheTerapines Date: Fri, 23 Aug 2024 14:43:22 +0800 Subject: [PATCH 11/11] Lower strcutextractref to structinject --- include/circt/Dialect/Moore/MooreOps.td | 1 + lib/Dialect/Moore/MooreOps.cpp | 19 ++++++++++++++----- test/Dialect/Moore/canonicalizers.mlir | 13 +++++++++++++ 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/include/circt/Dialect/Moore/MooreOps.td b/include/circt/Dialect/Moore/MooreOps.td index b0ca268ec8c1..bed29e873d2d 100644 --- a/include/circt/Dialect/Moore/MooreOps.td +++ b/include/circt/Dialect/Moore/MooreOps.td @@ -339,6 +339,7 @@ def BlockingAssignOp : AssignOpBase<"blocking_assign", [ Arg:$dst, UnpackedType:$src ); + let hasCanonicalizeMethod = true; } def NonBlockingAssignOp : AssignOpBase<"nonblocking_assign"> { diff --git a/lib/Dialect/Moore/MooreOps.cpp b/lib/Dialect/Moore/MooreOps.cpp index 89b337b4f1d7..6c503e4bb8e7 100644 --- a/lib/Dialect/Moore/MooreOps.cpp +++ b/lib/Dialect/Moore/MooreOps.cpp @@ -22,8 +22,6 @@ using namespace circt; using namespace circt::moore; using namespace mlir; -static ArrayRef getStructMembers(Type type); - //===----------------------------------------------------------------------===// // SVModuleOp //===----------------------------------------------------------------------===// @@ -888,9 +886,6 @@ OpFoldResult StructInjectOp::fold(FoldAdaptor adaptor) { LogicalResult StructInjectOp::canonicalize(StructInjectOp op, PatternRewriter &rewriter) { - if (!(isa(op->getParentOp()) || - isa(op->getParentOp()))) - return failure(); auto members = getStructMembers(op.getType()); // Chase a chain of `struct_inject` ops, with an optional final @@ -1086,6 +1081,20 @@ DeletionKind BlockingAssignOp::removeBlockingUses( return DeletionKind::Delete; } +LogicalResult BlockingAssignOp::canonicalize(BlockingAssignOp op, + PatternRewriter &rewriter) { + if (auto refOp = op.getDst().getDefiningOp()) { + auto input = refOp.getInput(); + auto read = rewriter.create(op->getLoc(), input); + auto value = op.getSrc(); + auto inject = rewriter.create( + op->getLoc(), read, refOp.getFieldNameAttr(), value); + op->setOperands({input, inject}); + return success(); + } + return failure(); +} + //===----------------------------------------------------------------------===// // ReadOp //===----------------------------------------------------------------------===// diff --git a/test/Dialect/Moore/canonicalizers.mlir b/test/Dialect/Moore/canonicalizers.mlir index 2754fcef860c..9ed309fe7383 100644 --- a/test/Dialect/Moore/canonicalizers.mlir +++ b/test/Dialect/Moore/canonicalizers.mlir @@ -192,6 +192,19 @@ func.func @StructExtractFold2(%arg0: !moore.i17, %arg1: !moore.i42) -> (!moore.i return %1, %2 : !moore.i17, !moore.i42 } +// CHECK-LABEL: func.func @structExtractRefLower2Inject +func.func @structExtractRefLower2Inject(%arg0: !moore.ref>) -> (!moore.ref>) { + // CHECK-NEXT: [[C42:%.+]] = moore.constant 42 + // CHECK-NEXT: [[TMP1:%.+]] = moore.read %arg0 : > + // CHECK-NEXT: [[TMP2:%.+]] = moore.struct_inject [[TMP1]], "a", [[C42]] : struct<{a: i32, b: i32}>, i32 + // CHECK-NEXT: moore.blocking_assign %arg0, [[TMP2]] : struct<{a: i32, b: i32}> + // CHECK-NEXT: return %arg0 : !moore.ref> + %0 = moore.constant 42 : i32 + %1 = moore.struct_extract_ref %arg0, "a" : > -> + moore.blocking_assign %1, %0 : i32 + return %arg0 : !moore.ref> +} + // CHECK-LABEL: func.func @StructInjectFold1 func.func @StructInjectFold1(%arg0: !moore.struct<{a: i32, b: i32}>) -> (!moore.struct<{a: i32, b: i32}>) { // CHECK-NEXT: [[C42:%.+]] = moore.constant 42