16#include "mlir/IR/Builders.h"
17#include "mlir/IR/PatternMatch.h"
18#include "llvm/ADT/APSInt.h"
25#include "circt/Dialect/HWArith/HWArithCanonicalizations.h.inc"
34LogicalResult CastOp::verify() {
35 auto inType = getIn().getType();
36 auto outType = getOut().getType();
40 if (isInSignless && isOutSignless)
41 return emitError(
"at least one type needs to carry sign semantics (ui/si)");
44 unsigned inBitWidth = inType.getIntOrFloatBitWidth();
45 unsigned outBitWidth = outType.getIntOrFloatBitWidth();
46 if (inBitWidth < outBitWidth)
47 return emitError(
"bit extension is undefined for a signless type");
53void CastOp::getCanonicalizationPatterns(RewritePatternSet &results,
55 results.insert<EliminateCast>(
context);
62APSInt ConstantOp::getConstantValue() {
return getRawValueAttr().getAPSInt(); }
64OpFoldResult ConstantOp::fold(FoldAdaptor adaptor) {
65 assert(adaptor.getOperands().empty() &&
"constant has no operands");
66 return getRawValueAttr();
69void ConstantOp::print(OpAsmPrinter &p) {
71 if (getType() == getRawValueAttr().getType()) {
72 p.printAttribute(getRawValueAttr());
75 p.printAttributeWithoutType(getRawValueAttr());
76 p <<
" : " << getType();
78 p.printOptionalAttrDict(getOperation()->getAttrs(),
79 {getRawValueAttrName()});
82ParseResult ConstantOp::parse(OpAsmParser &parser, OperationState &result) {
83 auto loc = parser.getCurrentLocation();
86 if (parser.parseInteger(value) || parser.parseColonType(type) ||
87 parser.parseOptionalAttrDict(result.attributes))
92 auto intType = hw::type_dyn_cast<IntegerType>(type);
94 return parser.emitError(loc,
"expected an integer type, but got ") << type;
95 unsigned width = intType.getWidth();
96 bool fits = value.isNegative()
97 ? !intType.isUnsigned() && value.getSignificantBits() <= width
98 : value.getActiveBits() + intType.isSigned() <= width;
100 return parser.emitError(loc,
"constant out of range for type ") << type;
102 result.addAttribute(getRawValueAttrName(result.name),
103 IntegerAttr::get(intType, value.sextOrTrunc(width)));
104 result.addTypes(type);
108LogicalResult ConstantOp::verify() {
110 if (getRawValueAttr().getType() != hw::getCanonicalType(getType()))
111 return emitOpError(
"value type ")
112 << getRawValueAttr().getType()
113 <<
" doesn't match the canonical result type "
114 << hw::getCanonicalType(getType());
122LogicalResult AddOp::inferReturnTypes(MLIRContext *
context,
123 std::optional<Location> loc,
124 ValueRange operands, DictionaryAttr attrs,
125 mlir::PropertyRef properties,
126 mlir::RegionRange regions,
127 SmallVectorImpl<Type> &results) {
128 auto lhs = cast<IntegerType>(operands[0].getType());
129 auto rhs = cast<IntegerType>(operands[1].getType());
130 IntegerType::SignednessSemantics signedness;
133 results.push_back(IntegerType::get(
context, resultWidth, signedness));
141LogicalResult SubOp::inferReturnTypes(MLIRContext *
context,
142 std::optional<Location> loc,
143 ValueRange operands, DictionaryAttr attrs,
144 mlir::PropertyRef properties,
145 mlir::RegionRange regions,
146 SmallVectorImpl<Type> &results) {
147 auto lhs = cast<IntegerType>(operands[0].getType());
148 auto rhs = cast<IntegerType>(operands[1].getType());
151 IntegerType::SignednessSemantics signedness;
153 signedness = IntegerType::Signed;
155 results.push_back(IntegerType::get(
context, resultWidth, signedness));
163static IntegerType::SignednessSemantics
166 if (lhs.getSignedness() == rhs.getSignedness()) {
168 return lhs.getSignedness();
171 return IntegerType::Signed;
175LogicalResult MulOp::inferReturnTypes(MLIRContext *
context,
176 std::optional<Location> loc,
177 ValueRange operands, DictionaryAttr attrs,
178 mlir::PropertyRef properties,
179 mlir::RegionRange regions,
180 SmallVectorImpl<Type> &results) {
181 auto lhs = cast<IntegerType>(operands[0].getType());
182 auto rhs = cast<IntegerType>(operands[1].getType());
184 unsigned resultWidth = lhs.getWidth() + rhs.getWidth();
185 IntegerType::SignednessSemantics signedness =
188 results.push_back(IntegerType::get(
context, resultWidth, signedness));
196LogicalResult DivOp::inferReturnTypes(MLIRContext *
context,
197 std::optional<Location> loc,
198 ValueRange operands, DictionaryAttr attrs,
199 mlir::PropertyRef properties,
200 mlir::RegionRange regions,
201 SmallVectorImpl<Type> &results) {
202 auto lhs = cast<IntegerType>(operands[0].getType());
203 auto rhs = cast<IntegerType>(operands[1].getType());
205 unsigned resultWidth = lhs.getWidth();
211 IntegerType::SignednessSemantics signedness =
214 results.push_back(IntegerType::get(
context, resultWidth, signedness));
226 IntegerType lhs, IntegerType rhs) {
228 unsigned resultWidth = std::max(lhs.getWidth(), rhs.getWidth()) + 1;
230 if (lhs.getSignedness() == rhs.getSignedness()) {
233 signedness = lhs.getSignedness();
236 signedness = IntegerType::Signed;
239 if ((lhs.isUnsigned() && lhs.getWidth() >= rhs.getWidth()) ||
240 (rhs.isUnsigned() && rhs.getWidth() >= lhs.getWidth())) {
252 auto ops = binOp->getOperands();
254 return binOp->emitError() <<
"expected 2 operands but got " << ops.size();
267#define GET_OP_CLASSES
268#include "circt/Dialect/HWArith/HWArith.cpp.inc"
assert(baseType &&"element must be base type")
static std::unique_ptr< Context > context
static IntegerType::SignednessSemantics getSignedInheritedSignedness(IntegerType lhs, IntegerType rhs)
static LogicalResult verifyBinOp(Operation *binOp)
bool isHWArithIntegerType(::mlir::Type type)
unsigned inferAddResultType(IntegerType::SignednessSemantics &signedness, IntegerType lhs, IntegerType rhs)
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.