mirror of https://github.com/llvm/circt.git
[AlwaysFusion] Fix merging in the presence of top-level #ifdefs.
This changes the pass to do a post-order walk of the region tree, in preparation for other changes.
This commit is contained in:
parent
334798e4a2
commit
20b04d2369
|
@ -83,39 +83,52 @@ static void mergeOperations(Operation *op1, Operation *op2) {
|
|||
namespace {
|
||||
struct AlwaysFusionPass : public AlwaysFusionBase<AlwaysFusionPass> {
|
||||
void runOnOperation() override;
|
||||
|
||||
void runOnRegionBlock(Block &body);
|
||||
|
||||
private:
|
||||
bool anythingChanged;
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
void AlwaysFusionPass::runOnOperation() {
|
||||
auto *moduleBody = getOperation().getBodyBlock();
|
||||
|
||||
// Keeps track if anything changed during this pass, used to determine if
|
||||
// the analyses were preserved.
|
||||
bool graphChanged = false;
|
||||
|
||||
// A set of operations in the current block which are mergable. Any
|
||||
// operation in this set is a candidate for another similar operation to
|
||||
// merge in to.
|
||||
DenseSet<Operation *, SimpleOperationInfo> foundOps;
|
||||
for (sv::AlwaysFFOp alwaysOp :
|
||||
llvm::make_early_inc_range(moduleBody->getOps<sv::AlwaysFFOp>())) {
|
||||
// Check if we have encountered an equivalent operation already. If we
|
||||
// have, merge them together and delete the old operation.
|
||||
auto itAndInserted = foundOps.insert(alwaysOp);
|
||||
if (!itAndInserted.second) {
|
||||
// Merge with a similar alwaysff
|
||||
mergeOperations(*itAndInserted.first, alwaysOp);
|
||||
alwaysOp.erase();
|
||||
graphChanged = true;
|
||||
}
|
||||
}
|
||||
anythingChanged = false;
|
||||
runOnRegionBlock(*getOperation().getBodyBlock());
|
||||
|
||||
// If we did not change anything in the graph mark all analysis as
|
||||
// preserved.
|
||||
if (!graphChanged)
|
||||
if (!anythingChanged)
|
||||
markAllAnalysesPreserved();
|
||||
}
|
||||
|
||||
void AlwaysFusionPass::runOnRegionBlock(Block &body) {
|
||||
// A set of operations in the current block which are mergable. Any
|
||||
// operation in this set is a candidate for another similar operation to
|
||||
// merge in to.
|
||||
DenseSet<Operation *, SimpleOperationInfo> alwaysFFOpsSeen;
|
||||
for (Operation &op : llvm::make_early_inc_range(body)) {
|
||||
// Recursively process any regions in the op before we visit it.
|
||||
for (size_t i = 0, e = op.getNumRegions(); i != e; ++i) {
|
||||
if (op.getRegion(i).getBlocks().size() == 1)
|
||||
runOnRegionBlock(op.getRegion(i).front());
|
||||
}
|
||||
|
||||
if (auto alwaysOp = dyn_cast<sv::AlwaysFFOp>(op)) {
|
||||
// Check if we have encountered an equivalent operation already. If we
|
||||
// have, merge them together and delete the old operation.
|
||||
auto itAndInserted = alwaysFFOpsSeen.insert(alwaysOp);
|
||||
if (!itAndInserted.second) {
|
||||
// Merge with a similar alwaysff if we already have one.
|
||||
mergeOperations(*itAndInserted.first, alwaysOp);
|
||||
alwaysOp.erase();
|
||||
anythingChanged = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<Pass> circt::sv::createAlwaysFusionPass() {
|
||||
return std::make_unique<AlwaysFusionPass>();
|
||||
}
|
||||
|
|
|
@ -97,3 +97,25 @@ rtl.module @alwaysff_different_reset(%arg0: i1, %arg1: i1) {
|
|||
}
|
||||
rtl.output
|
||||
}
|
||||
|
||||
//CHECK-LABEL: rtl.module @alwaysff_ifdef(%arg0: i1) {
|
||||
//CHECK-NEXT: sv.ifdef "FOO" {
|
||||
//CHECK-NEXT: sv.alwaysff(posedge %arg0) {
|
||||
//CHECK-NEXT: sv.fwrite "A1"
|
||||
//CHECK-NEXT: sv.fwrite "B1"
|
||||
//CHECK-NEXT: }
|
||||
//CHECK-NEXT: }
|
||||
//CHECK-NEXT: rtl.output
|
||||
//CHECK-NEXT: }
|
||||
|
||||
rtl.module @alwaysff_ifdef(%arg0: i1) {
|
||||
sv.ifdef "FOO" {
|
||||
sv.alwaysff(posedge %arg0) {
|
||||
sv.fwrite "A1"
|
||||
}
|
||||
sv.alwaysff(posedge %arg0) {
|
||||
sv.fwrite "B1"
|
||||
}
|
||||
}
|
||||
rtl.output
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue