diff options
| author | Jack Koenig | 2021-05-18 14:54:59 -0700 |
|---|---|---|
| committer | GitHub | 2021-05-18 14:54:59 -0700 |
| commit | e0844966cbd2eb44b66c8bf341fa26370e3b4f1c (patch) | |
| tree | ae71ed0eb031e5b292c493c67aa01b1ec85afd3d /src/main | |
| parent | 97273bff5718cbcbce2673d57bce1a76ec909977 (diff) | |
Improve performance of RenameMap in LowerTypes (#2233)
LowerTypes creates a lot of mappings for the RenameMap. The built-in
.distinct of renames becomes a performance program for designs with
deeply nested Aggregates. Because LowerTypes does not create duplicate
renames, it can safely eschew the safety of using .distinct via a
private internal API.
Diffstat (limited to 'src/main')
| -rw-r--r-- | src/main/scala/firrtl/RenameMap.scala | 16 | ||||
| -rw-r--r-- | src/main/scala/firrtl/passes/LowerTypes.scala | 7 |
2 files changed, 20 insertions, 3 deletions
diff --git a/src/main/scala/firrtl/RenameMap.scala b/src/main/scala/firrtl/RenameMap.scala index 82c00ca5..d39d8106 100644 --- a/src/main/scala/firrtl/RenameMap.scala +++ b/src/main/scala/firrtl/RenameMap.scala @@ -78,6 +78,11 @@ object RenameMap { /** Initialize a new RenameMap */ def apply(): RenameMap = new RenameMap + // This is a private internal API for transforms where the .distinct operation is very expensive + // (eg. LowerTypes). The onus is on the user of this API to be very careful and not inject + // duplicates. This is a bad, hacky API that no one should use + private[firrtl] def noDistinct(): RenameMap = new RenameMap(doDistinct = false) + abstract class RenameTargetException(reason: String) extends Exception(reason) case class IllegalRenameException(reason: String) extends RenameTargetException(reason) case class CircularRenameException(reason: String) extends RenameTargetException(reason) @@ -94,7 +99,11 @@ object RenameMap { final class RenameMap private ( val underlying: mutable.HashMap[CompleteTarget, Seq[CompleteTarget]] = mutable.HashMap[CompleteTarget, Seq[CompleteTarget]](), - val chained: Option[RenameMap] = None) { + val chained: Option[RenameMap] = None, + // This is a private internal API for transforms where the .distinct operation is very expensive + // (eg. LowerTypes). The onus is on the user of this API to be very careful and not inject + // duplicates. This is a bad, hacky API that no one should use + doDistinct: Boolean = true) { /** Chain a [[RenameMap]] with this [[RenameMap]] * @param next the map to chain with this map @@ -662,7 +671,10 @@ final class RenameMap private ( private def completeRename(from: CompleteTarget, tos: Seq[CompleteTarget]): Unit = { tos.foreach { recordSensitivity(from, _) } val existing = underlying.getOrElse(from, Vector.empty) - val updated = (existing ++ tos).distinct + val updated = { + val all = (existing ++ tos) + if (doDistinct) all.distinct else all + } underlying(from) = updated traverseTokensCache.clear() traverseHierarchyCache.clear() diff --git a/src/main/scala/firrtl/passes/LowerTypes.scala b/src/main/scala/firrtl/passes/LowerTypes.scala index 0bd44a8c..7ba320d0 100644 --- a/src/main/scala/firrtl/passes/LowerTypes.scala +++ b/src/main/scala/firrtl/passes/LowerTypes.scala @@ -75,7 +75,12 @@ object LowerTypes extends Transform with DependencyAPIMigration { val memInitByModule = memInitAnnos.map(_.asInstanceOf[MemoryInitAnnotation]).groupBy(_.target.encapsulatingModule) val c = CircuitTarget(state.circuit.main) - val refRenameMap = RenameMap() + // By default, the RenameMap enforces a .distinct invariant for renames. This helps transform + // writers not mess up because violating that invariant can cause problems for transform + // writers. Unfortunately, when you have lots of renames, this is very expensive + // performance-wise. We use a private internal API that does not run .distinct to improve + // performance, but we must be careful to not insert any duplicates. + val refRenameMap = RenameMap.noDistinct() val resultAndRenames = state.circuit.modules.map(m => onModule(c, m, memInitByModule.getOrElse(m.name, Seq()), refRenameMap)) val result = state.circuit.copy(modules = resultAndRenames.map(_._1)) |
