32 llvm::function_ref<
bool(StringAttr)> shouldStripDomain) {
33 auto shouldStripType = [&](Type type) {
34 if (
auto domainType = dyn_cast<DomainType>(type))
35 return shouldStripDomain(domainType.getName().getAttr());
38 WalkResult result = op->walk<mlir::WalkOrder::PostOrder, ReverseIterator>(
39 [&](Operation *op) -> WalkResult {
40 return TypeSwitch<Operation *, WalkResult>(op)
41 .Case<FModuleLike>([&](FModuleLike op) {
42 BitVector erasures(op.getNumPorts());
43 for (
size_t i = 0, e = op.getNumPorts(); i < e; ++i)
44 if (shouldStripType(op.getPortType(i)))
47 op.erasePorts(erasures);
48 return WalkResult::advance();
50 .Case<DomainDefineOp>([&](DomainDefineOp op) {
51 if (shouldStripType(op.getDest().getType()) ||
52 shouldStripType(op.getSrc().getType()))
54 return WalkResult::advance();
56 .Case<DomainCreateOp>([&](DomainCreateOp op) {
57 if (shouldStripType(op.getType()))
59 return WalkResult::advance();
61 .Case<DomainCreateAnonOp>([&](DomainCreateAnonOp op) {
62 if (shouldStripType(op.getType()))
64 return WalkResult::advance();
66 .Case<DomainSubfieldOp>([&](DomainSubfieldOp op) {
69 if (shouldStripType(op.getInput().getType())) {
70 if (!op->use_empty()) {
71 OpBuilder builder(op);
72 op.replaceAllUsesWith(
73 UnknownValueOp::create(builder, op.getLoc(), op.getType())
78 return WalkResult::advance();
80 .Case<UnsafeDomainCastOp>([&](UnsafeDomainCastOp op) {
83 if (llvm::any_of(op.getDomains(), [&](Value domain) {
84 return shouldStripType(domain.getType());
86 op.replaceAllUsesWith(op.getInput());
89 return WalkResult::advance();
91 .Case<WireOp>([&](WireOp op) {
93 if (shouldStripType(op.getType(0))) {
95 return WalkResult::advance();
97 BitVector erasures(op.getDomains().size());
100 for (
int i = 0, e = op.getDomains().size(); i < e; ++i)
101 if (shouldStripType(op.getDomains()[i].getType()))
104 op->eraseOperands(erasures);
105 return WalkResult::advance();
107 .Case<FInstanceLike>([&](
auto op) {
108 auto n = op.getNumPorts();
109 BitVector erasures(n);
110 for (
size_t i = 0; i < n; ++i)
111 if (shouldStripType(op->getResult(i).getType()))
113 if (erasures.any()) {
114 op.cloneWithErasedPortsAndReplaceUses(erasures);
117 return WalkResult::advance();
119 .Default([&](Operation *op) {
124 concat<Type>(op->getOperandTypes(), op->getResultTypes())) {
125 if (isa<DomainType>(type)) {
126 op->emitOpError(
"cannot be stripped");
127 return WalkResult::interrupt();
130 return WalkResult::advance();
133 return failure(result.wasInterrupted());
137 CircuitOp circuit, llvm::function_ref<
bool(StringAttr)> shouldStripDomain) {
139 llvm::SmallVector<FModuleLike> modules;
140 for (Operation &op : make_early_inc_range(*circuit.getBodyBlock())) {
141 TypeSwitch<Operation *, void>(&op)
142 .Case<FModuleLike>([&](FModuleLike op) { modules.push_back(op); })
143 .Case<DomainOp>([&](DomainOp op) {
145 if (shouldStripDomain(op.getNameAttr()))
151 return failableParallelForEach(
152 circuit.getContext(), modules, [&](FModuleLike module) {
153 return stripModuleImpl(module, shouldStripDomain);
static LogicalResult stripModuleImpl(FModuleLike op, llvm::function_ref< bool(StringAttr)> shouldStripDomain)
A helper for stripping domains from a module based on a predicate.