java-topology/defects/llvm/patch/llvm-0005-assumptioncache-transfer-denseset.patch

64 lines
2.4 KiB
Diff

# UNDF: UNDF-2026-000000156
diff --git a/llvm/include/llvm/Analysis/AssumptionCache.h b/llvm/include/llvm/Analysis/AssumptionCache.h
index a1b2c3d..b8e7c2d 100644
--- a/llvm/include/llvm/Analysis/AssumptionCache.h
+++ b/llvm/include/llvm/Analysis/AssumptionCache.h
@@ -14,6 +14,7 @@
#define LLVM_ANALYSIS_ASSUMPTIONCACHE_H
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/ilist_node.h"
#include "llvm/IR/PassManager.h"
diff --git a/llvm/lib/Analysis/AssumptionCache.cpp b/llvm/lib/Analysis/AssumptionCache.cpp
index d2c3e4f..a8b9c1e 100644
--- a/llvm/lib/Analysis/AssumptionCache.cpp
+++ b/llvm/lib/Analysis/AssumptionCache.cpp
@@ -149,9 +149,22 @@ void AssumptionCache::transferAffectedValuesInCache(Value *OV, Value *NV) {
auto &NAVV = getOrInsertAffectedValues(NV);
auto AVI = AffectedValues.find(OV);
if (AVI == AffectedValues.end())
return;
- for (auto &A : AVI->second)
- if (!llvm::is_contained(NAVV, A))
- NAVV.push_back(A);
+ // CWE-407 fix: is_contained(NAVV, A) was O(|NAVV|) per element in
+ // AVI->second. If |NAVV|=M and |AVI->second|=N, the old code ran in
+ // O(N*M). Build a DenseSet from NAVV once for O(1) per lookup.
+ //
+ // ResultElem is a struct { WeakVH Assume; unsigned Index; }; use a
+ // SmallPtrSet keyed on the raw Assume pointer for O(1) membership.
+ SmallPtrSet<Value *, 16> NAVVSet;
+ for (auto &E : NAVV)
+ if (Value *V = E.Assume)
+ NAVVSet.insert(V);
+
+ for (auto &A : AVI->second) {
+ Value *V = A.Assume;
+ if (V && NAVVSet.insert(V).second)
+ NAVV.push_back(A); // O(1) amortized; O(N+M) total
+ }
AffectedValues.erase(OV);
}
# Ticket: llvm-0005
# File: llvm/lib/Analysis/AssumptionCache.cpp
# Line: 152-154 (transferAffectedValuesInCache)
# CWE: 407 — Inefficient Algorithmic Complexity
# Severity: MEDIUM
#
# Pattern:
# for (auto &A : AVI->second) // O(N) iterations
# if (!llvm::is_contained(NAVV, A)) // O(M) linear scan
# NAVV.push_back(A);
#
# NAVV is a SmallVector<ResultElem, 1>. is_contained() walks it linearly.
# When a value that many assumptions affect is replaced (e.g., during
# constant folding or inlining), OV's assumption list (size N) is merged
# into NV's list (size M), costing O(N*M).
#
# Fix: pre-build a SmallPtrSet from NAVV before the loop; O(N+M) total.
#
# Speedup: O(N*M) → O(N+M). For typical N=M=K: O(K^2) → O(K).