[AIG][LongestPathAnalysis] Fix a bug in deduplicatePathsImpl (#8746)

This commit fixes a bug in deduplicatePathsImpl within the AIG LongestPathAnalysis.

Close https://github.com/llvm/circt/issues/8745
This commit is contained in:
Hideto Ueno 2025-07-19 20:51:17 -07:00 committed by GitHub
parent 24bd19e3cc
commit dc524e9ea0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 26 additions and 14 deletions

View File

@ -41,7 +41,7 @@ with Context() as ctx, Location.unknown():
# CHECK-LABEL: LongestPathAnalysis created successfully!
print("LongestPathAnalysis created successfully!")
# CHECK: Total paths: 96
# CHECK: Total paths: 128
# CHECK-NEXT: Max delay: 2
# CHECK-NEXT: Min delay: 1
# CHECK-NEXT: 50th percentile delay: 1
@ -62,17 +62,17 @@ with Context() as ctx, Location.unknown():
DataflowPath.from_json_string(
collection.collection.get_path(5)) == collection[5])
# Check that len and get_size are the same
# CHECK-NEXT: 96 96
# CHECK-NEXT: 128 128
print(len(collection), collection.collection.get_size())
try:
print(collection[96])
print(collection[128])
except IndexError:
# CHECK-NEXT: IndexError correctly raised
print("IndexError correctly raised")
# Check that iterator works
# CHECK-NEXT: sum: 128
# CHECK-NEXT: sum: 192
print("sum: ", sum(p.delay for p in collection))
for p in collection[:2]:

View File

@ -87,19 +87,24 @@ deduplicatePathsImpl(SmallVectorImpl<T> &results, size_t startIndex,
llvm::function_ref<Key(const T &)> keyFn,
llvm::function_ref<int64_t(const T &)> delayFn) {
// Take only maximum for each path destination.
DenseMap<Key, size_t> saved;
for (auto [i, path] :
llvm::enumerate(ArrayRef(results).drop_front(startIndex))) {
auto &slot = saved[keyFn(path)];
if (slot == 0) {
slot = startIndex + i + 1;
DenseMap<Key, size_t> keyToIndex;
for (size_t i = startIndex; i < results.size(); ++i) {
auto &path = results[i];
auto key = keyFn(path);
auto delay = delayFn(path);
auto it = keyToIndex.find(key);
if (it == keyToIndex.end()) {
// Insert a new entry.
size_t newIndex = keyToIndex.size() + startIndex;
keyToIndex[key] = newIndex;
results[newIndex] = std::move(results[i]);
continue;
}
if (delayFn(results[slot - 1]) < delayFn(path))
results[slot - 1] = path;
if (delay > delayFn(results[it->second]))
results[it->second] = std::move(results[i]);
}
results.resize(saved.size() + startIndex);
results.resize(keyToIndex.size() + startIndex);
}
static void deduplicatePaths(SmallVectorImpl<OpenPath> &results,

View File

@ -103,3 +103,10 @@ hw.module private @comb(in %cond : i1, in %a : i1, in %b : i1, out x : i1) {
%r = comb.mux %cond, %a, %b : i1
hw.output %r : i1
}
// expected-remark-re @below {{fanOut=Object($root.x[0]), fanIn=Object($root.a[0], delay=2, history=[{{.+}}])}}
// expected-remark-re @below {{fanOut=Object($root.x[0]), fanIn=Object($root.b[0], delay=2, history=[{{.+}}])}}
hw.module private @fix_duplication(in %a : i1, in %b : i1, out x : i1) {
%0 = aig.and_inv %a, %a, %b : i1
hw.output %0 : i1
}

View File

@ -2,7 +2,7 @@
// RUN: circt-synth %s -output-longest-path=- -top counter -output-longest-path-json | FileCheck %s --check-prefix JSON
// CHECK-LABEL: # Longest Path Analysis result for "counter"
// CHECK-NEXT: Found 189 paths
// CHECK-NEXT: Found 288 paths
// CHECK-NEXT: Found 32 unique fanout points
// CHECK-NEXT: Maximum path delay: 48
// Don't test detailed reports as they are not stable.