diff --git a/include/circt/Dialect/FIRRTL/FIRRTLExpressions.td b/include/circt/Dialect/FIRRTL/FIRRTLExpressions.td index 359e64d86571..5580cd6f0091 100644 --- a/include/circt/Dialect/FIRRTL/FIRRTLExpressions.td +++ b/include/circt/Dialect/FIRRTL/FIRRTLExpressions.td @@ -1265,6 +1265,21 @@ def IntegerShrOp : IntegerBinaryPrimOp<"integer.shr"> { }]; } +def IntegerShlOp : IntegerBinaryPrimOp<"integer.shl"> { + let summary = "Shift an FIntegerType value left by an FIntegerType value"; + let description = [{ + The shift left operation result is the arbitrary precision signed integer + shift left of the lhs operand by the rhs operand. The rhs operand must be + non-negative. + + Example: + ```mlir + %2 = firrtl.integer.shl %0, %1 : (!firrtl.integer, !firrtl.integer) -> + !firrtl.integer + ``` + }]; +} + //===----------------------------------------------------------------------===// // RefOperations: Operations on the RefType. // diff --git a/lib/Dialect/FIRRTL/FIRRTLFolds.cpp b/lib/Dialect/FIRRTL/FIRRTLFolds.cpp index 747a12b95031..ca4d8acf0d11 100644 --- a/lib/Dialect/FIRRTL/FIRRTLFolds.cpp +++ b/lib/Dialect/FIRRTL/FIRRTLFolds.cpp @@ -952,6 +952,23 @@ OpFoldResult IntegerShrOp::fold(FoldAdaptor adaptor) { return {}; } +OpFoldResult IntegerShlOp::fold(FoldAdaptor adaptor) { + if (auto rhsCst = getConstant(adaptor.getRhs())) { + // Constant folding + if (auto lhsCst = getConstant(adaptor.getLhs())) + + return IntegerAttr::get( + IntegerType::get(getContext(), lhsCst->getBitWidth()), + lhsCst->shl(*rhsCst)); + + // integer.shl(x, 0) -> x + if (rhsCst->isZero()) + return getLhs(); + } + + return {}; +} + //===----------------------------------------------------------------------===// // Unary Operators //===----------------------------------------------------------------------===// diff --git a/lib/Dialect/FIRRTL/FIRRTLOps.cpp b/lib/Dialect/FIRRTL/FIRRTLOps.cpp index 7f4de9f99459..5978ee8c2ce9 100644 --- a/lib/Dialect/FIRRTL/FIRRTLOps.cpp +++ b/lib/Dialect/FIRRTL/FIRRTLOps.cpp @@ -5980,6 +5980,9 @@ void IntegerMulOp::getAsmResultNames(OpAsmSetValueNameFn setNameFn) { void IntegerShrOp::getAsmResultNames(OpAsmSetValueNameFn setNameFn) { genericAsmResultNames(*this, setNameFn); } +void IntegerShlOp::getAsmResultNames(OpAsmSetValueNameFn setNameFn) { + genericAsmResultNames(*this, setNameFn); +} void IsTagOp::getAsmResultNames(OpAsmSetValueNameFn setNameFn) { genericAsmResultNames(*this, setNameFn); } diff --git a/test/Dialect/FIRRTL/canonicalization.mlir b/test/Dialect/FIRRTL/canonicalization.mlir index d98b13b368a2..388fbe9057d9 100644 --- a/test/Dialect/FIRRTL/canonicalization.mlir +++ b/test/Dialect/FIRRTL/canonicalization.mlir @@ -3640,4 +3640,19 @@ firrtl.module private @Issue7562(in %sel : !firrtl.uint<1>, in %a : !firrtl.cons firrtl.connect %out, %res : !firrtl.uint, !firrtl.uint<1> } +// CHECK-LABEL: firrtl.class @PropertyArithmetic +firrtl.class @PropertyArithmetic(in %in: !firrtl.integer, out %out0: !firrtl.integer, out %out1: !firrtl.integer) { + // CHECK: [[C4:%.+]] = firrtl.integer 4 + %0 = firrtl.integer 0 + %1 = firrtl.integer 1 + %2 = firrtl.integer 2 + + %3 = firrtl.integer.shl %1, %2 : (!firrtl.integer, !firrtl.integer) -> !firrtl.integer + %4 = firrtl.integer.shl %in, %0 : (!firrtl.integer, !firrtl.integer) -> !firrtl.integer + + // CHECK: firrtl.propassign %out0, [[C4]] + // CHECK: firrtl.propassign %out1, %in + firrtl.propassign %out0, %3 : !firrtl.integer + firrtl.propassign %out1, %4 : !firrtl.integer +} } diff --git a/test/Dialect/FIRRTL/round-trip.mlir b/test/Dialect/FIRRTL/round-trip.mlir index 1c6ae9434ed2..1bc65f4526c8 100644 --- a/test/Dialect/FIRRTL/round-trip.mlir +++ b/test/Dialect/FIRRTL/round-trip.mlir @@ -102,6 +102,9 @@ firrtl.module @PropertyArithmetic() { // CHECK: firrtl.integer.shr %0, %1 : (!firrtl.integer, !firrtl.integer) -> !firrtl.integer %4 = firrtl.integer.shr %0, %1 : (!firrtl.integer, !firrtl.integer) -> !firrtl.integer + + // CHECK: firrtl.integer.shl %0, %1 : (!firrtl.integer, !firrtl.integer) -> !firrtl.integer + %5 = firrtl.integer.shl %0, %1 : (!firrtl.integer, !firrtl.integer) -> !firrtl.integer } // CHECK-LABEL: firrtl.module @PropertyListOps