21
21
#include " circt/Dialect/OM/OMAttributes.h"
22
22
#include " circt/Dialect/OM/OMOps.h"
23
23
#include " mlir/IR/BuiltinOps.h"
24
- #include " mlir/IR/IRMapping.h"
25
24
#include " mlir/IR/PatternMatch.h"
26
25
#include " mlir/IR/Threading.h"
27
26
#include " mlir/Pass/Pass.h"
@@ -1105,9 +1104,6 @@ void LowerClassesPass::lowerClassLike(FModuleLike moduleLike,
1105
1104
1106
1105
void LowerClassesPass::lowerClass (om::ClassOp classOp, FModuleLike moduleLike,
1107
1106
const PathInfoTable &pathInfoTable) {
1108
- // Map from Values in the FIRRTL Class to Values in the OM Class.
1109
- IRMapping mapping;
1110
-
1111
1107
// Collect information about property ports.
1112
1108
SmallVector<Property> inputProperties;
1113
1109
BitVector portsToErase (moduleLike.getNumPorts ());
@@ -1132,6 +1128,7 @@ void LowerClassesPass::lowerClass(om::ClassOp classOp, FModuleLike moduleLike,
1132
1128
1133
1129
// Construct the OM Class body with block arguments for each input property,
1134
1130
// updating the mapping to map from the input property to the block argument.
1131
+ Block *moduleBody = &moduleLike->getRegion (0 ).front ();
1135
1132
Block *classBody = &classOp->getRegion (0 ).emplaceBlock ();
1136
1133
// Every class created from a module gets a base path as its first parameter.
1137
1134
auto basePathType = BasePathType::get (&getContext ());
@@ -1144,76 +1141,35 @@ void LowerClassesPass::lowerClass(om::ClassOp classOp, FModuleLike moduleLike,
1144
1141
for (size_t i = 0 ; i < nAltBasePaths; ++i)
1145
1142
classBody->addArgument (basePathType, unknownLoc);
1146
1143
1147
- // Mapping from block arguments or instance results to new values.
1148
- DenseMap<Value, Value> valueMapping;
1149
- for (auto inputProperty : inputProperties) {
1150
- BlockArgument parameterValue =
1151
- classBody->addArgument (inputProperty.type , inputProperty.loc );
1152
- BlockArgument inputValue =
1153
- moduleLike->getRegion (0 ).getArgument (inputProperty.index );
1154
-
1155
- valueMapping[inputValue] = parameterValue;
1156
- }
1157
-
1158
- // Helper to check if an op is a property op, which should be removed in the
1159
- // module like, or kept in the OM class.
1160
- auto isPropertyOp = [&](Operation &op) {
1161
- // Check if any operand is a property.
1162
- auto propertyOperands = llvm::any_of (op.getOperandTypes (), [](Type type) {
1163
- return isa<PropertyType>(type);
1164
- });
1165
- bool needsClone = false ;
1166
- if (auto instance = dyn_cast<InstanceOp>(op))
1167
- needsClone = shouldCreateClass (instance.getReferencedModuleNameAttr ());
1168
-
1169
- // Check if any result is a property.
1170
- auto propertyResults = llvm::any_of (
1171
- op.getResultTypes (), [](Type type) { return isa<PropertyType>(type); });
1172
-
1173
- return needsClone || propertyOperands || propertyResults;
1174
- };
1175
-
1176
- // Move operations from the module like to the OM class.
1177
- // We need to clone only instances and register their results to the value
1178
- // mapping. Operands must be remapped using the value mapping.
1179
- for (auto &op : llvm::make_early_inc_range (
1180
- moduleLike->getRegion (0 ).front ().getOperations ())) {
1181
- if (!isPropertyOp (op))
1144
+ // Move operations from the modulelike to the OM class.
1145
+ for (auto &op : llvm::make_early_inc_range (llvm::reverse (*moduleBody))) {
1146
+ if (auto instance = dyn_cast<InstanceOp>(op)) {
1147
+ if (!shouldCreateClass (instance.getReferencedModuleNameAttr ()))
1148
+ continue ;
1149
+ auto *clone = OpBuilder::atBlockBegin (classBody).clone (op);
1150
+ for (auto result : instance.getResults ()) {
1151
+ if (isa<PropertyType>(result.getType ()))
1152
+ result.replaceAllUsesWith (clone->getResult (result.getResultNumber ()));
1153
+ }
1182
1154
continue ;
1183
-
1184
- Operation *newOp = &op;
1185
-
1186
- bool needsMove = true ;
1187
-
1188
- // Clone instances and register their results to the value mapping.
1189
- if (isa<InstanceOp>(op)) {
1190
- newOp = op.clone ();
1191
- for (auto [oldResult, newResult] :
1192
- llvm::zip (op.getResults (), newOp->getResults ()))
1193
- valueMapping[oldResult] = newResult;
1194
- classBody->getOperations ().insert (classBody->end (), newOp);
1195
- needsMove = false ;
1196
1155
}
1197
1156
1198
- // Remap operands using the value mapping.
1199
- for (size_t i = 0 ; i < newOp->getNumOperands (); ++i) {
1200
- auto operand = newOp->getOperand (i);
1201
- auto it = valueMapping.find (operand);
1202
- if (it != valueMapping.end ())
1203
- newOp->setOperand (i, it->second );
1204
- }
1157
+ auto isProperty = [](auto x) { return isa<PropertyType>(x.getType ()); };
1158
+ if (llvm::any_of (op.getOperands (), isProperty) ||
1159
+ llvm::any_of (op.getResults (), isProperty))
1160
+ op.moveBefore (classBody, classBody->begin ());
1161
+ }
1205
1162
1206
- // Move the op into the OM class body.
1207
- if (needsMove)
1208
- newOp->moveBefore (classBody, classBody->end ());
1163
+ // Move property ports from the module to the class.
1164
+ for (auto input : inputProperties) {
1165
+ auto arg = classBody->addArgument (input.type , input.loc );
1166
+ moduleBody->getArgument (input.index ).replaceAllUsesWith (arg);
1209
1167
}
1210
1168
1211
1169
llvm::SmallVector<mlir::Location> fieldLocs;
1212
1170
llvm::SmallVector<mlir::Value> fieldValues;
1213
1171
for (Operation &op :
1214
1172
llvm::make_early_inc_range (classOp.getBodyBlock ()->getOperations ())) {
1215
- assert (isPropertyOp (op));
1216
-
1217
1173
if (auto propAssign = dyn_cast<PropAssignOp>(op)) {
1218
1174
if (auto blockArg = dyn_cast<BlockArgument>(propAssign.getDest ())) {
1219
1175
// Store any output property assignments into fields op inputs.
@@ -1238,16 +1194,6 @@ void LowerClassesPass::lowerClass(om::ClassOp classOp, FModuleLike moduleLike,
1238
1194
// If the module-like is a Class, it will be completely erased later.
1239
1195
// Otherwise, erase just the property ports and ops.
1240
1196
if (!isa<firrtl::ClassLike>(moduleLike.getOperation ())) {
1241
- // Erase ops in use before def order, thanks to FIRRTL's SSA regions.
1242
- for (auto &op :
1243
- llvm::make_early_inc_range (llvm::reverse (moduleLike.getOperation ()
1244
- ->getRegion (0 )
1245
- .getBlocks ()
1246
- .front ()
1247
- .getOperations ())))
1248
- if (isPropertyOp (op) && !isa<InstanceOp>(op))
1249
- op.erase ();
1250
-
1251
1197
// Erase property typed ports.
1252
1198
moduleLike.erasePorts (portsToErase);
1253
1199
}
0 commit comments