15#include "mlir/Dialect/Func/IR/FuncOps.h"
16#include "mlir/IR/Builders.h"
17#include "mlir/IR/BuiltinOps.h"
18#include "mlir/IR/BuiltinTypes.h"
19#include "mlir/IR/Value.h"
20#include "mlir/Pass/Pass.h"
21#include "mlir/Support/LogicalResult.h"
22#include "mlir/Transforms/DialectConversion.h"
26#define GEN_PASS_DEF_REMOVEI0TYPES
27#include "circt/Dialect/Arc/ArcPasses.h.inc"
36struct RemoveI0TypesPass
37 :
public arc::impl::RemoveI0TypesBase<RemoveI0TypesPass> {
38 using RemoveI0TypesBase::RemoveI0TypesBase;
39 void runOnOperation()
override;
43 auto intType = dyn_cast<IntegerType>(type);
44 return intType && intType.getWidth() == 0;
48SmallVector<Value> flatten(ArrayRef<ValueRange> ranges) {
49 SmallVector<Value> flat;
50 for (
auto range : ranges) {
51 flat.insert(flat.end(), range.begin(), range.end());
60 using OpConversionPattern<T>::OpConversionPattern;
61 using OneToNOpAdaptor =
typename OpConversionPattern<T>::OneToNOpAdaptor;
64 matchAndRewrite(T op, OneToNOpAdaptor adaptor,
65 ConversionPatternRewriter &rewriter)
const override {
66 const TypeConverter &converter = *this->getTypeConverter();
67 auto result = convertOpResultTypes(op, flatten(adaptor.getOperands()),
74 Operation *newOp = *result;
75 auto newOpResultIt = newOp->result_begin();
76 SmallVector<Value> results;
77 for (
auto oldType : op->getResultTypes()) {
78 if (!converter.convertType(oldType)) {
79 results.push_back(
nullptr);
81 results.push_back(*newOpResultIt++);
84 assert(newOpResultIt == newOp->result_end() &&
"Didn't map all results!");
85 rewriter.replaceOp(op, results);
95 ConvertGeneric(TypeConverter &converter, MLIRContext *
context)
96 : ConversionPattern(converter, MatchAnyOpTypeTag{},
100 matchAndRewrite(Operation *op, ArrayRef<ValueRange> operands,
101 ConversionPatternRewriter &rewriter)
const override {
102 const TypeConverter &converter = *getTypeConverter();
105 for (ValueRange range : operands) {
107 rewriter.eraseOp(op);
113 SmallVector<Type> resultTypes;
114 if (failed(converter.convertTypes(op->getResultTypes(), resultTypes)))
116 if (resultTypes.size() != op->getNumResults()) {
117 rewriter.eraseOp(op);
122 convertOpResultTypes(op, flatten(operands), converter, rewriter);
125 rewriter.replaceOp(op, *result);
133 using OpConversionPattern<hw::ArrayGetOp>::OpConversionPattern;
135 matchAndRewrite(hw::ArrayGetOp op, OneToNOpAdaptor adaptor,
136 ConversionPatternRewriter &rewriter)
const override {
137 if (adaptor.getIndex().empty()) {
138 assert(adaptor.getInput().size() == 1);
139 rewriter.replaceOp(op, adaptor.getInput().front());
149 using OpConversionPattern<hw::ArrayCreateOp>::OpConversionPattern;
151 matchAndRewrite(hw::ArrayCreateOp op, OneToNOpAdaptor adaptor,
152 ConversionPatternRewriter &rewriter)
const override {
153 if (adaptor.getInputs().size() == 1) {
154 rewriter.replaceOp(op, adaptor.getInputs().front());
164 using OpConversionPattern<hw::ArrayInjectOp>::OpConversionPattern;
166 matchAndRewrite(hw::ArrayInjectOp op, OneToNOpAdaptor adaptor,
167 ConversionPatternRewriter &rewriter)
const override {
168 if (adaptor.getIndex().empty()) {
169 rewriter.replaceOp(op, adaptor.getElement());
178struct ConvertAggregateConstant
180 using OpConversionPattern<hw::AggregateConstantOp>::OpConversionPattern;
182 matchAndRewrite(hw::AggregateConstantOp op, OpAdaptor adaptor,
183 ConversionPatternRewriter &rewriter)
const override {
184 Type resultType = getTypeConverter()->convertType(op.getResult().getType());
187 Attribute newFields =
188 rewriteArrayAttr(op.getFields(), op.getResult().getType());
190 if (!isa<ArrayAttr>(newFields)) {
192 IntegerAttr attr = cast<IntegerAttr>(newFields);
195 rewriter.replaceOp(op, result);
200 auto newOp = hw::AggregateConstantOp::create(
201 rewriter, op.getLoc(), resultType, cast<ArrayAttr>(newFields));
202 rewriter.replaceOp(op, newOp);
207 Attribute rewriteArrayAttr(ArrayAttr array, Type type)
const {
210 if (
auto arrayType = dyn_cast<hw::ArrayType>(type);
211 arrayType && arrayType.getNumElements() == 1) {
212 return *array.begin();
217 auto fieldIdInterface = cast<hw::FieldIDTypeInterface>(type);
218 SmallVector<Attribute>
attrs;
219 for (
auto [index, attr] : llvm::enumerate(array)) {
220 uint64_t fieldId = fieldIdInterface.getFieldID(index);
221 Type subType = fieldIdInterface.getSubTypeByFieldID(fieldId).first;
222 if (
auto subArrayAttr = dyn_cast<ArrayAttr>(attr))
223 attrs.push_back(rewriteArrayAttr(subArrayAttr, subType));
225 attrs.push_back(attr);
227 return ArrayAttr::get(array.getContext(),
attrs);
233void RemoveI0TypesPass::runOnOperation() {
234 TypeConverter converter;
235 ConversionTarget target(getContext());
236 RewritePatternSet patterns(&getContext());
239 converter.addConversion([](Type type, SmallVectorImpl<Type> &types) {
241 types.push_back(type);
246 converter.addConversion([&converter](hw::ArrayType type,
247 SmallVectorImpl<Type> &types) {
249 if (type.getNumElements() == 1) {
250 if (Type converted = converter.convertType(type.getElementType()))
251 types.push_back(converted);
255 types.push_back(hw::ArrayType::get(
256 converter.convertType(type.getElementType()), type.getNumElements()));
259 converter.addConversion([&converter](hw::StructType type) -> Type {
260 SmallVector<hw::StructType::FieldInfo> newMembers;
262 for (
auto &field : type.getElements()) {
263 SmallVector<Type> convertedTypes;
264 if (failed(converter.convertType(field.type, convertedTypes)))
266 if (!convertedTypes.empty()) {
267 assert(convertedTypes.size() == 1);
268 newMembers.push_back({field.name, convertedTypes[0]});
271 return hw::StructType::get(type.getContext(), newMembers);
273 converter.addConversion([&converter](hw::UnionType type) -> Type {
274 SmallVector<hw::UnionType::FieldInfo> newMembers;
276 for (
auto &field : type.getElements()) {
277 SmallVector<Type> convertedTypes;
278 if (failed(converter.convertType(field.type, convertedTypes)))
280 if (!convertedTypes.empty()) {
281 assert(convertedTypes.size() == 1);
282 newMembers.push_back({field.name, convertedTypes[0], field.offset});
285 return hw::UnionType::get(type.getContext(), newMembers);
287 converter.addConversion(
288 [&converter](hw::TypeAliasType type, SmallVectorImpl<Type> &types) {
289 return converter.convertType(type.getCanonicalType(), types);
291 converter.addConversion(
292 [&converter](arc::StateType type, SmallVectorImpl<Type> &types) {
293 SmallVector<Type> innerTypes;
294 if (failed(converter.convertType(type.getType(), innerTypes)))
298 if (innerTypes.empty())
300 assert(innerTypes.size() == 1);
301 types.push_back(arc::StateType::get(innerTypes[0]));
305 target.markUnknownOpDynamicallyLegal(
306 [&](Operation *op) {
return converter.isLegal(op); });
307 target.addDynamicallyLegalOp<func::FuncOp>([&](func::FuncOp func) {
308 FunctionType fty = func.getFunctionType();
309 return converter.isLegal(fty.getInputs()) &&
310 converter.isLegal(fty.getResults());
313 populateFunctionOpInterfaceTypeConversionPattern<func::FuncOp>(patterns,
316 patterns.add<LegalizeGeneric<func::ReturnOp>, LegalizeGeneric<func::CallOp>,
317 LegalizeGeneric<hw::StructCreateOp>, ConvertArrayGet,
318 ConvertArrayCreate, ConvertArrayInject, ConvertGeneric,
319 ConvertAggregateConstant>(converter, &getContext());
320 ConversionConfig config;
321 config.allowPatternRollback =
false;
322 if (failed(applyFullConversion(getOperation(), target, std::move(patterns),
324 return signalPassFailure();
assert(baseType &&"element must be base type")
static std::unique_ptr< Context > context
static FIRRTLBaseType convertType(FIRRTLBaseType type)
Returns null type if no conversion is needed.
false return failure()
Parse an optional keyword or string and set instance into 'result'.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.