java-topology/defects/llvm/unit/LlvmAliasSetTest.java
russell@unturf.com db29a08762 undefect. CWE-407 — 92 sites, 42 ecosystems
B&W print-friendly diagrams + tinkerpop-0001 + wave-3 proof sections.
Squash of 94 local commits onto remote master.
2026-03-26 19:48:18 -04:00

177 lines
6.8 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package unit;
import java.util.ArrayList;
import java.util.HashSet;
/**
* Unit tests modelling CWE-407 defects in LLVM:
*
* llvm-0002 — AliasSet::MemoryLocs: SmallVector + is_contained O(N)
* vs DenseSet::count O(1).
* Modelled as: outer loop over N memory accesses, inner
* ArrayList.contains() for dedup vs HashSet.contains().
*
* llvm-0003 — LCSSA isExitBlock: SmallVectorImpl + is_contained O(X)
* vs SmallPtrSet::count O(1).
* Modelled as: worklist of U uses, each calls
* ArrayList.contains() for X exit blocks vs HashSet.contains().
*
* Pure Java stdlib, instrumented operation counts.
*/
public class LlvmAliasSetTest {
// -----------------------------------------------------------------------
// llvm-0002 helpers
// -----------------------------------------------------------------------
/** Simulate defective path: N accesses, dedup via ArrayList.contains(). */
static long aliasSetDefective(int nAccesses, int maxLocs) {
ArrayList<Long> memoryLocs = new ArrayList<>();
long ops = 0;
for (int i = 0; i < nAccesses; i++) {
long loc = i % maxLocs;
// O(current size) scan — mirrors is_contained(MemoryLocs, MemLoc)
boolean found = false;
for (int j = 0; j < memoryLocs.size(); j++) {
ops++;
if (memoryLocs.get(j).equals(loc)) { found = true; break; }
}
if (!found) memoryLocs.add(loc);
}
return ops;
}
/** Simulate fixed path: N accesses, dedup via HashSet.contains(). */
static long aliasSetFixed(int nAccesses, int maxLocs) {
HashSet<Long> memoryLocs = new HashSet<>();
long ops = 0;
for (int i = 0; i < nAccesses; i++) {
long loc = i % maxLocs;
// O(1) — mirrors DenseSet::count(MemLoc)
ops++;
memoryLocs.add(loc);
}
return ops;
}
// -----------------------------------------------------------------------
// llvm-0003 helpers
// -----------------------------------------------------------------------
/** Simulate defective LCSSA: U uses × X exit blocks, ArrayList scan. */
static long lcssaDefective(int nUses, int nExitBlocks) {
ArrayList<Integer> exitBlocks = new ArrayList<>();
for (int i = 0; i < nExitBlocks; i++) exitBlocks.add(i);
long ops = 0;
for (int u = 0; u < nUses; u++) {
int userBB = u % nExitBlocks;
// O(X) per use — mirrors is_contained(ExitBlocks, UserBB)
for (int j = 0; j < exitBlocks.size(); j++) {
ops++;
if (exitBlocks.get(j).equals(userBB)) break;
}
}
return ops;
}
/** Simulate fixed LCSSA: U uses × X exit blocks, HashSet lookup. */
static long lcssaFixed(int nUses, int nExitBlocks) {
HashSet<Integer> exitBlockSet = new HashSet<>();
for (int i = 0; i < nExitBlocks; i++) exitBlockSet.add(i);
long ops = 0;
for (int u = 0; u < nUses; u++) {
int userBB = u % nExitBlocks;
// O(1) — mirrors SmallPtrSet::count(UserBB)
ops++;
exitBlockSet.contains(userBB);
}
return ops;
}
// -----------------------------------------------------------------------
// Test methods
// -----------------------------------------------------------------------
/**
* llvm-0002: defective op count must grow quadratically with saturation.
* At N=200 accesses, maxLocs=250: defective scans accumulate O(N×locs).
*/
static void testAliasSetDefectiveCountGrows() {
long opsSmall = aliasSetDefective(50, 250);
long opsFull = aliasSetDefective(200, 250);
// Quadratic growth: opsFull should be >> 4× opsSmall
assert opsFull > opsSmall * 4
: "llvm-0002: expected quadratic growth, got opsSmall=" + opsSmall
+ " opsFull=" + opsFull;
System.out.printf("PASS testAliasSetDefectiveCountGrows: opsSmall=%d opsFull=%d ratio=%.1fx%n",
opsSmall, opsFull, (double) opsFull / opsSmall);
}
/**
* llvm-0002: fixed op count must be O(N) (one op per access).
* At N=200 accesses: ops == N.
*/
static void testAliasSetFixedCountLinear() {
int n = 200;
long ops = aliasSetFixed(n, 250);
assert ops == n
: "llvm-0002: expected ops==" + n + " got " + ops;
System.out.printf("PASS testAliasSetFixedCountLinear: ops=%d (expected %d)%n", ops, n);
}
/**
* llvm-0002: speedup ratio defective/fixed must exceed 10× at N=200.
*/
static void testAliasSetSpeedupRatio() {
int n = 200, maxLocs = 250;
long defOps = aliasSetDefective(n, maxLocs);
long fixOps = aliasSetFixed(n, maxLocs);
double ratio = (double) defOps / fixOps;
assert ratio > 10.0
: "llvm-0002: speedup ratio " + ratio + " not > 10x";
System.out.printf("PASS testAliasSetSpeedupRatio: defective=%d fixed=%d ratio=%.1fx%n",
defOps, fixOps, ratio);
}
/**
* llvm-0003: LCSSA defective op count grows as U×X.
* At U=100 uses, X=20 exit blocks: ops ≈ U×(X/2) on average.
*/
static void testLcssaDefectiveCountGrows() {
long opsSmall = lcssaDefective(25, 20);
long opsFull = lcssaDefective(100, 20);
assert opsFull > opsSmall * 3
: "llvm-0003: expected super-linear growth, got opsSmall=" + opsSmall
+ " opsFull=" + opsFull;
System.out.printf("PASS testLcssaDefectiveCountGrows: opsSmall=%d opsFull=%d ratio=%.1fx%n",
opsSmall, opsFull, (double) opsFull / opsSmall);
}
/**
* llvm-0003: speedup ratio defective/fixed must exceed 5× at U=100, X=20.
*/
static void testLcssaSpeedupRatio() {
int nUses = 100, nExitBlocks = 20;
long defOps = lcssaDefective(nUses, nExitBlocks);
long fixOps = lcssaFixed(nUses, nExitBlocks);
double ratio = (double) defOps / fixOps;
assert ratio > 5.0
: "llvm-0003: speedup ratio " + ratio + " not > 5x";
System.out.printf("PASS testLcssaSpeedupRatio: defective=%d fixed=%d ratio=%.1fx%n",
defOps, fixOps, ratio);
}
// -----------------------------------------------------------------------
// Main
// -----------------------------------------------------------------------
public static void main(String[] args) {
System.out.println("=== LlvmAliasSetTest ===");
testAliasSetDefectiveCountGrows();
testAliasSetFixedCountLinear();
testAliasSetSpeedupRatio();
testLcssaDefectiveCountGrows();
testLcssaSpeedupRatio();
System.out.println("All tests passed.");
}
}