Skip to content

Commit

Permalink
[Moore] Add constant materialization, fold constant conversions
Browse files Browse the repository at this point in the history
Implement the `materializeConstant` function for the Moore dialect and
mark the `ConstantOp` as a `ConstantLike` operation. This now allows us
to write constant folders for various operations. As a first example,
add a constant folder for `ConversionOp` that directly applies domain
conversions (e.g., `i42` to `l42` or vice versa) to constants.
  • Loading branch information
fabianschuiki committed Aug 9, 2024
1 parent 450c968 commit d4d6c0f
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 10 deletions.
1 change: 1 addition & 0 deletions include/circt/Dialect/Moore/MooreDialect.td
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ def MooreDialect : Dialect {
}];
let useDefaultAttributePrinterParser = 1;
let useDefaultTypePrinterParser = 0;
let hasConstantMaterializer = 1;
let dependentDialects = ["hw::HWDialect"];
}

Expand Down
2 changes: 1 addition & 1 deletion include/circt/Dialect/Moore/MooreOps.td
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,7 @@ def EventOp : MooreOp<"wait_event", [
// Expressions
//===----------------------------------------------------------------------===//

def ConstantOp : MooreOp<"constant", [Pure]> {
def ConstantOp : MooreOp<"constant", [Pure, ConstantLike]> {
let summary = "A constant integer value";
let arguments = (ins FVIntegerAttr:$value);
let results = (outs IntType:$result);
Expand Down
9 changes: 9 additions & 0 deletions lib/Dialect/Moore/MooreDialect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,13 @@ void MooreDialect::initialize() {
>();
}

Operation *MooreDialect::materializeConstant(OpBuilder &builder,
Attribute value, Type type,
Location loc) {
if (auto intType = dyn_cast<IntType>(type))
if (auto intValue = dyn_cast<FVIntegerAttr>(value))
return builder.create<ConstantOp>(loc, intType, intValue);
return nullptr;
}

#include "circt/Dialect/Moore/MooreDialect.cpp.inc"
17 changes: 17 additions & 0 deletions lib/Dialect/Moore/MooreOps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -998,6 +998,23 @@ OpFoldResult ConversionOp::fold(FoldAdaptor adaptor) {
// Fold away no-op casts.
if (getInput().getType() == getResult().getType())
return getInput();

// Convert domains of constant integer inputs.
auto intInput = dyn_cast_or_null<FVIntegerAttr>(adaptor.getInput());
auto fromIntType = dyn_cast<IntType>(getInput().getType());
auto toIntType = dyn_cast<IntType>(getResult().getType());
if (intInput && fromIntType && toIntType &&
fromIntType.getWidth() == toIntType.getWidth()) {
// If we are going *to* a four-valued type, simply pass through the
// constant.
if (toIntType.getDomain() == Domain::FourValued)
return intInput;

// Otherwise map all unknown bits to zero (the default in SystemVerilog) and
// return a new constant.
return FVIntegerAttr::get(getContext(), intInput.getValue().toAPInt(false));
}

return {};
}

Expand Down
5 changes: 2 additions & 3 deletions test/Conversion/MooreToCore/basic.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -296,10 +296,9 @@ moore.module @Variable() {
%b2 = moore.variable %0 : <i8>

// CHECK: %true = hw.constant true
%1 = moore.constant 1 : i1
%2 = moore.conversion %1 : !moore.i1 -> !moore.l1
%1 = moore.constant 1 : l1
// CHECK: llhd.sig "l" %true : i1
%l = moore.variable %2 : <l1>
%l = moore.variable %1 : <l1>

// CHECK: [[TMP2:%.+]] = hw.constant 10 : i32
%3 = moore.constant 10 : i32
Expand Down
33 changes: 27 additions & 6 deletions test/Dialect/Moore/canonicalizers.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,9 @@ func.func private @useRef(%arg0: !moore.ref<i42>)

// CHECK-LABEL: moore.module @DropRedundantVars
moore.module @DropRedundantVars(in %a : !moore.i42, out b : !moore.i42, out c : !moore.i42) {
// CHECK: [[C9001:%.+]] = moore.constant 9001 : i42
%c9001_i42 = moore.constant 9001 : i42

// Remove variables that shadow an input port of the same name.
// CHECK-NOT: moore.assigned_variable
// CHECK: dbg.variable "a", %a
Expand All @@ -164,13 +167,11 @@ moore.module @DropRedundantVars(in %a : !moore.i42, out b : !moore.i42, out c :

// Remove variables that shadow an output port of the same name. Variables
// that shadow an output port of a different name should remain.
// CHECK: [[TMP:%.+]] = moore.constant 9001 : i42
// CHECK-NOT: %b = moore.assigned_variable
// CHECK: %w = moore.assigned_variable [[TMP]]
// CHECK: moore.output [[TMP]], %w
%3 = moore.constant 9001 : i42
%b = moore.assigned_variable %3 : i42
%w = moore.assigned_variable %3 : i42
// CHECK: %w = moore.assigned_variable [[C9001]]
// CHECK: moore.output [[C9001]], %w
%b = moore.assigned_variable %c9001_i42 : i42
%w = moore.assigned_variable %c9001_i42 : i42
moore.output %b, %w : !moore.i42, !moore.i42
}

Expand Down Expand Up @@ -229,3 +230,23 @@ func.func @StructInjectFold3(%arg0: !moore.struct<{a: i32, b: i32}>) -> (!moore.
%3 = moore.struct_inject %2, "a", %1 : struct<{a: i32, b: i32}>, i32
return %3 : !moore.struct<{a: i32, b: i32}>
}

// CHECK-LABEL: func.func @ConvertConstantTwoToFourValued
func.func @ConvertConstantTwoToFourValued() -> (!moore.l42) {
// CHECK: [[TMP:%.+]] = moore.constant 9001 : l42
// CHECK-NOT: moore.conversion
// CHECK: return [[TMP]] :
%0 = moore.constant 9001 : i42
%1 = moore.conversion %0 : !moore.i42 -> !moore.l42
return %1 : !moore.l42
}

// CHECK-LABEL: func.func @ConvertConstantFourToTwoValued
func.func @ConvertConstantFourToTwoValued() -> (!moore.i42) {
// CHECK: [[TMP:%.+]] = moore.constant 8 : i42
// CHECK-NOT: moore.conversion
// CHECK: return [[TMP]] :
%0 = moore.constant b1XZ0 : l42
%1 = moore.conversion %0 : !moore.l42 -> !moore.i42
return %1 : !moore.i42
}

0 comments on commit d4d6c0f

Please sign in to comment.