@@ -226,36 +226,46 @@ static InstancePath empty{};
226226
227227ArrayRef<InstancePath>
228228InstancePathCache::getAbsolutePaths (ModuleOpInterface op) {
229- return getAbsolutePaths (op, instanceGraph.getTopLevelNode ());
229+ return getPaths (op, instanceGraph.getTopLevelNode (), absolutePathsCache );
230230}
231231
232- // NOLINTBEGIN(misc-no-recursion)
233232ArrayRef<InstancePath>
234- InstancePathCache::getAbsolutePaths (ModuleOpInterface op,
235- InstanceGraphNode *top) {
233+ InstancePathCache::getRelativePaths (ModuleOpInterface op,
234+ InstanceGraphNode *node) {
235+ if (node == instanceGraph.getTopLevelNode ())
236+ return getAbsolutePaths (op);
237+ return getPaths (op, node, relativePathsCache[node]);
238+ }
239+
240+ // NOLINTBEGIN(misc-no-recursion)
241+ ArrayRef<InstancePath> InstancePathCache::getPaths (ModuleOpInterface op,
242+ InstanceGraphNode *top,
243+ PathsCache &cache) {
236244 InstanceGraphNode *node = instanceGraph[op];
237245
238246 if (node == top) {
239247 return empty;
240248 }
241249
242250 // Fast path: hit the cache.
243- auto cached = absolutePathsCache .find (op);
244- if (cached != absolutePathsCache .end ())
251+ auto cached = cache .find (op);
252+ if (cached != cache .end ())
245253 return cached->second ;
246254
247255 // For each instance, collect the instance paths to its parent and append the
248256 // instance itself to each.
249257 SmallVector<InstancePath, 8 > extendedPaths;
250258 for (auto *inst : node->uses ()) {
251259 if (auto module = inst->getParent ()->getModule ()) {
252- auto instPaths = getAbsolutePaths (module );
260+ auto instPaths = getPaths (module , top, cache );
253261 extendedPaths.reserve (instPaths.size ());
254262 for (auto path : instPaths) {
255263 extendedPaths.push_back (appendInstance (
256264 path, cast<InstanceOpInterface>(*inst->getInstance ())));
257265 }
258- } else {
266+ } else if (inst->getParent () == top) {
267+ // Special case when `inst` is a top-level instance and
268+ // `inst->getParent()` is a pseudo top-level node.
259269 extendedPaths.emplace_back (empty);
260270 }
261271 }
@@ -267,7 +277,7 @@ InstancePathCache::getAbsolutePaths(ModuleOpInterface op,
267277 std::copy (extendedPaths.begin (), extendedPaths.end (), paths);
268278 pathList = ArrayRef<InstancePath>(paths, extendedPaths.size ());
269279 }
270- absolutePathsCache .insert ({op, pathList});
280+ cache .insert ({op, pathList});
271281 return pathList;
272282}
273283// NOLINTEND(misc-no-recursion)
@@ -331,29 +341,33 @@ void InstancePathCache::replaceInstance(InstanceOpInterface oldOp,
331341 return llvm::any_of (
332342 paths, [&](InstancePath p) { return llvm::is_contained (p, oldOp); });
333343 };
334-
335- for (auto &iter : absolutePathsCache) {
336- if (!instanceExists (iter.getSecond ()))
337- continue ;
338- SmallVector<InstancePath, 8 > updatedPaths;
339- for (auto path : iter.getSecond ()) {
340- const auto *iter = llvm::find (path, oldOp);
341- if (iter == path.end ()) {
342- // path does not contain the oldOp, just copy it as is.
343- updatedPaths.push_back (path);
344+ auto updateCache = [&](PathsCache &cache) {
345+ for (auto &iter : cache) {
346+ if (!instanceExists (iter.getSecond ()))
344347 continue ;
348+ SmallVector<InstancePath, 8 > updatedPaths;
349+ for (auto path : iter.getSecond ()) {
350+ const auto *iter = llvm::find (path, oldOp);
351+ if (iter == path.end ()) {
352+ // path does not contain the oldOp, just copy it as is.
353+ updatedPaths.push_back (path);
354+ continue ;
355+ }
356+ auto *newPath = allocator.Allocate <InstanceOpInterface>(path.size ());
357+ llvm::copy (path, newPath);
358+ newPath[iter - path.begin ()] = newOp;
359+ updatedPaths.push_back (InstancePath (ArrayRef (newPath, path.size ())));
345360 }
346- auto *newPath = allocator.Allocate <InstanceOpInterface>(path.size ());
347- llvm::copy (path, newPath);
348- newPath[iter - path.begin ()] = newOp;
349- updatedPaths.push_back (InstancePath (ArrayRef (newPath, path.size ())));
361+ // Move the list of paths into the bump allocator for later quick
362+ // retrieval.
363+ auto *paths = allocator.Allocate <InstancePath>(updatedPaths.size ());
364+ llvm::copy (updatedPaths, paths);
365+ iter.getSecond () = ArrayRef<InstancePath>(paths, updatedPaths.size ());
350366 }
351- // Move the list of paths into the bump allocator for later quick
352- // retrieval.
353- auto *paths = allocator.Allocate <InstancePath>(updatedPaths.size ());
354- llvm::copy (updatedPaths, paths);
355- iter.getSecond () = ArrayRef<InstancePath>(paths, updatedPaths.size ());
356- }
367+ };
368+ updateCache (absolutePathsCache);
369+ for (auto &iter : relativePathsCache)
370+ updateCache (iter.getSecond ());
357371}
358372
359373#include " circt/Support/InstanceGraphInterface.cpp.inc"
0 commit comments