An interface-typed *field* inside a struct (`Scene { IMat m; ... }`), with n implementations selected at runtime through a switch. Unlike `dynamic_dispatch` (a bare local existential), boxing the existential in an aggregate forces `legalizeExistentialTypeLayout` to float the existential field out and recompute the parent layout, and feeds specializeModule a witness-table-per-case blowup. Stresses specializeModule + legalizeExistentialTypeLayout + the downstream simplifyIR. Scales by breadth (number of implementations / switch cases). Scaling null: n scales cases, each an O(1) body; ideal specialization cost is O(n).
bucket: dynamic_dispatch · compile mode: target · flags: -target spirv -emit-spirv-directly · default N: 100
Full sub-counter decomposition of compileInner — named leaf timers plus (self) residuals (a parent's time not covered by a named child, e.g. the autodiff transform in linkAndOptimizeIR (self)). Topmost band traces compileInner; hover a band for its phase.
Overall compileInner: 80.4 → 78.1 ms -2.9% (2026-07-30 7c58a326b → 2026-08-29 28c755b09)
Contributors — the mutually-exclusive phase buckets (named leaves + (self) residuals) that tile compileInner; the pp column sums to the overall %. Buckets moving the total by ≥0.2% are listed, the rest fold into the remainder row. Below them, every other reported counter (nested/overlapping, e.g. serialized-module reads — own change only):
| counter | Δ | own % | of total |
|---|---|---|---|
| linkAndOptimizeIR (self) | -1.1 ms | -12.3% | -1.3pp |
| generateOutput (self) | -0.7 ms | -5.1% | -0.9pp |
| SemanticChecking | +0.6 ms | +4.2% | +0.7pp |
| compileInner (self) | -0.3 ms | -73.2% | -0.4pp |
| generateIR | -0.3 ms | -4.4% | -0.4pp |
| legalizeExistentialTypeLayout | -0.3 ms | -19.0% | -0.4pp |
| legalizeResourceTypes | -0.2 ms | -22.2% | -0.3pp |
| simplifyIR | -0.2 ms | -1.6% | -0.2pp |
| (remaining 7 buckets) | +0.1 ms | – | +0.2pp |
Largest day steps (≥5% of the previous day, both directions; bisect with git log <c0>..<c1> -- source/):
| boundary | % vs prev day | commits | top buckets (own %) |
|---|---|---|---|
| none | |||
Run from the slang repo root. This regenerates the sources below and re-runs this workload's measurement; --gen-dir keeps the generated files (they go to a tempdir and are deleted otherwise).
python3 tools/compile-perf/bench.py --slangc /path/to/slangc --only existential_aggregate --label repro --gen-dir repro-existential_aggregate
the complete compiled source (N = 100), shown in full
// AUTO-GENERATED by perf-suite/workloads.py - do not edit by hand.
RWStructuredBuffer<float> outBuf;
[anyValueSize(16)]
interface IMat { float shade(float x); }
struct M0 : IMat { float shade(float x) { return x * 1.0 + 0.0 + sin(x * 1.0); } }
struct M1 : IMat { float shade(float x) { return x * 2.0 + 1.0 + sin(x * 2.0); } }
struct M2 : IMat { float shade(float x) { return x * 3.0 + 2.0 + sin(x * 3.0); } }
struct M3 : IMat { float shade(float x) { return x * 4.0 + 3.0 + sin(x * 4.0); } }
struct M4 : IMat { float shade(float x) { return x * 5.0 + 4.0 + sin(x * 5.0); } }
struct M5 : IMat { float shade(float x) { return x * 6.0 + 5.0 + sin(x * 6.0); } }
struct M6 : IMat { float shade(float x) { return x * 7.0 + 6.0 + sin(x * 7.0); } }
struct M7 : IMat { float shade(float x) { return x * 8.0 + 7.0 + sin(x * 1.0); } }
struct M8 : IMat { float shade(float x) { return x * 9.0 + 8.0 + sin(x * 2.0); } }
struct M9 : IMat { float shade(float x) { return x * 10.0 + 9.0 + sin(x * 3.0); } }
struct M10 : IMat { float shade(float x) { return x * 11.0 + 10.0 + sin(x * 4.0); } }
struct M11 : IMat { float shade(float x) { return x * 12.0 + 11.0 + sin(x * 5.0); } }
struct M12 : IMat { float shade(float x) { return x * 13.0 + 12.0 + sin(x * 6.0); } }
struct M13 : IMat { float shade(float x) { return x * 14.0 + 13.0 + sin(x * 7.0); } }
struct M14 : IMat { float shade(float x) { return x * 15.0 + 14.0 + sin(x * 1.0); } }
struct M15 : IMat { float shade(float x) { return x * 16.0 + 15.0 + sin(x * 2.0); } }
struct M16 : IMat { float shade(float x) { return x * 17.0 + 16.0 + sin(x * 3.0); } }
struct M17 : IMat { float shade(float x) { return x * 18.0 + 17.0 + sin(x * 4.0); } }
struct M18 : IMat { float shade(float x) { return x * 19.0 + 18.0 + sin(x * 5.0); } }
struct M19 : IMat { float shade(float x) { return x * 20.0 + 19.0 + sin(x * 6.0); } }
struct M20 : IMat { float shade(float x) { return x * 21.0 + 20.0 + sin(x * 7.0); } }
struct M21 : IMat { float shade(float x) { return x * 22.0 + 21.0 + sin(x * 1.0); } }
struct M22 : IMat { float shade(float x) { return x * 23.0 + 22.0 + sin(x * 2.0); } }
struct M23 : IMat { float shade(float x) { return x * 24.0 + 23.0 + sin(x * 3.0); } }
struct M24 : IMat { float shade(float x) { return x * 25.0 + 24.0 + sin(x * 4.0); } }
struct M25 : IMat { float shade(float x) { return x * 26.0 + 25.0 + sin(x * 5.0); } }
struct M26 : IMat { float shade(float x) { return x * 27.0 + 26.0 + sin(x * 6.0); } }
struct M27 : IMat { float shade(float x) { return x * 28.0 + 27.0 + sin(x * 7.0); } }
struct M28 : IMat { float shade(float x) { return x * 29.0 + 28.0 + sin(x * 1.0); } }
struct M29 : IMat { float shade(float x) { return x * 30.0 + 29.0 + sin(x * 2.0); } }
struct M30 : IMat { float shade(float x) { return x * 31.0 + 30.0 + sin(x * 3.0); } }
struct M31 : IMat { float shade(float x) { return x * 32.0 + 31.0 + sin(x * 4.0); } }
struct M32 : IMat { float shade(float x) { return x * 33.0 + 32.0 + sin(x * 5.0); } }
struct M33 : IMat { float shade(float x) { return x * 34.0 + 33.0 + sin(x * 6.0); } }
struct M34 : IMat { float shade(float x) { return x * 35.0 + 34.0 + sin(x * 7.0); } }
struct M35 : IMat { float shade(float x) { return x * 36.0 + 35.0 + sin(x * 1.0); } }
struct M36 : IMat { float shade(float x) { return x * 37.0 + 36.0 + sin(x * 2.0); } }
struct M37 : IMat { float shade(float x) { return x * 38.0 + 37.0 + sin(x * 3.0); } }
struct M38 : IMat { float shade(float x) { return x * 39.0 + 38.0 + sin(x * 4.0); } }
struct M39 : IMat { float shade(float x) { return x * 40.0 + 39.0 + sin(x * 5.0); } }
struct M40 : IMat { float shade(float x) { return x * 41.0 + 40.0 + sin(x * 6.0); } }
struct M41 : IMat { float shade(float x) { return x * 42.0 + 41.0 + sin(x * 7.0); } }
struct M42 : IMat { float shade(float x) { return x * 43.0 + 42.0 + sin(x * 1.0); } }
struct M43 : IMat { float shade(float x) { return x * 44.0 + 43.0 + sin(x * 2.0); } }
struct M44 : IMat { float shade(float x) { return x * 45.0 + 44.0 + sin(x * 3.0); } }
struct M45 : IMat { float shade(float x) { return x * 46.0 + 45.0 + sin(x * 4.0); } }
struct M46 : IMat { float shade(float x) { return x * 47.0 + 46.0 + sin(x * 5.0); } }
struct M47 : IMat { float shade(float x) { return x * 48.0 + 47.0 + sin(x * 6.0); } }
struct M48 : IMat { float shade(float x) { return x * 49.0 + 48.0 + sin(x * 7.0); } }
struct M49 : IMat { float shade(float x) { return x * 50.0 + 49.0 + sin(x * 1.0); } }
struct M50 : IMat { float shade(float x) { return x * 51.0 + 50.0 + sin(x * 2.0); } }
struct M51 : IMat { float shade(float x) { return x * 52.0 + 51.0 + sin(x * 3.0); } }
struct M52 : IMat { float shade(float x) { return x * 53.0 + 52.0 + sin(x * 4.0); } }
struct M53 : IMat { float shade(float x) { return x * 54.0 + 53.0 + sin(x * 5.0); } }
struct M54 : IMat { float shade(float x) { return x * 55.0 + 54.0 + sin(x * 6.0); } }
struct M55 : IMat { float shade(float x) { return x * 56.0 + 55.0 + sin(x * 7.0); } }
struct M56 : IMat { float shade(float x) { return x * 57.0 + 56.0 + sin(x * 1.0); } }
struct M57 : IMat { float shade(float x) { return x * 58.0 + 57.0 + sin(x * 2.0); } }
struct M58 : IMat { float shade(float x) { return x * 59.0 + 58.0 + sin(x * 3.0); } }
struct M59 : IMat { float shade(float x) { return x * 60.0 + 59.0 + sin(x * 4.0); } }
struct M60 : IMat { float shade(float x) { return x * 61.0 + 60.0 + sin(x * 5.0); } }
struct M61 : IMat { float shade(float x) { return x * 62.0 + 61.0 + sin(x * 6.0); } }
struct M62 : IMat { float shade(float x) { return x * 63.0 + 62.0 + sin(x * 7.0); } }
struct M63 : IMat { float shade(float x) { return x * 64.0 + 63.0 + sin(x * 1.0); } }
struct M64 : IMat { float shade(float x) { return x * 65.0 + 64.0 + sin(x * 2.0); } }
struct M65 : IMat { float shade(float x) { return x * 66.0 + 65.0 + sin(x * 3.0); } }
struct M66 : IMat { float shade(float x) { return x * 67.0 + 66.0 + sin(x * 4.0); } }
struct M67 : IMat { float shade(float x) { return x * 68.0 + 67.0 + sin(x * 5.0); } }
struct M68 : IMat { float shade(float x) { return x * 69.0 + 68.0 + sin(x * 6.0); } }
struct M69 : IMat { float shade(float x) { return x * 70.0 + 69.0 + sin(x * 7.0); } }
struct M70 : IMat { float shade(float x) { return x * 71.0 + 70.0 + sin(x * 1.0); } }
struct M71 : IMat { float shade(float x) { return x * 72.0 + 71.0 + sin(x * 2.0); } }
struct M72 : IMat { float shade(float x) { return x * 73.0 + 72.0 + sin(x * 3.0); } }
struct M73 : IMat { float shade(float x) { return x * 74.0 + 73.0 + sin(x * 4.0); } }
struct M74 : IMat { float shade(float x) { return x * 75.0 + 74.0 + sin(x * 5.0); } }
struct M75 : IMat { float shade(float x) { return x * 76.0 + 75.0 + sin(x * 6.0); } }
struct M76 : IMat { float shade(float x) { return x * 77.0 + 76.0 + sin(x * 7.0); } }
struct M77 : IMat { float shade(float x) { return x * 78.0 + 77.0 + sin(x * 1.0); } }
struct M78 : IMat { float shade(float x) { return x * 79.0 + 78.0 + sin(x * 2.0); } }
struct M79 : IMat { float shade(float x) { return x * 80.0 + 79.0 + sin(x * 3.0); } }
struct M80 : IMat { float shade(float x) { return x * 81.0 + 80.0 + sin(x * 4.0); } }
struct M81 : IMat { float shade(float x) { return x * 82.0 + 81.0 + sin(x * 5.0); } }
struct M82 : IMat { float shade(float x) { return x * 83.0 + 82.0 + sin(x * 6.0); } }
struct M83 : IMat { float shade(float x) { return x * 84.0 + 83.0 + sin(x * 7.0); } }
struct M84 : IMat { float shade(float x) { return x * 85.0 + 84.0 + sin(x * 1.0); } }
struct M85 : IMat { float shade(float x) { return x * 86.0 + 85.0 + sin(x * 2.0); } }
struct M86 : IMat { float shade(float x) { return x * 87.0 + 86.0 + sin(x * 3.0); } }
struct M87 : IMat { float shade(float x) { return x * 88.0 + 87.0 + sin(x * 4.0); } }
struct M88 : IMat { float shade(float x) { return x * 89.0 + 88.0 + sin(x * 5.0); } }
struct M89 : IMat { float shade(float x) { return x * 90.0 + 89.0 + sin(x * 6.0); } }
struct M90 : IMat { float shade(float x) { return x * 91.0 + 90.0 + sin(x * 7.0); } }
struct M91 : IMat { float shade(float x) { return x * 92.0 + 91.0 + sin(x * 1.0); } }
struct M92 : IMat { float shade(float x) { return x * 93.0 + 92.0 + sin(x * 2.0); } }
struct M93 : IMat { float shade(float x) { return x * 94.0 + 93.0 + sin(x * 3.0); } }
struct M94 : IMat { float shade(float x) { return x * 95.0 + 94.0 + sin(x * 4.0); } }
struct M95 : IMat { float shade(float x) { return x * 96.0 + 95.0 + sin(x * 5.0); } }
struct M96 : IMat { float shade(float x) { return x * 97.0 + 96.0 + sin(x * 6.0); } }
struct M97 : IMat { float shade(float x) { return x * 98.0 + 97.0 + sin(x * 7.0); } }
struct M98 : IMat { float shade(float x) { return x * 99.0 + 98.0 + sin(x * 1.0); } }
struct M99 : IMat { float shade(float x) { return x * 100.0 + 99.0 + sin(x * 2.0); } }
struct Scene { IMat m; float w; }
float shadeScene(Scene sc, float x) { return sc.m.shade(x) * sc.w; }
[shader("compute")]
[numthreads(64,1,1)]
void computeMain(uint3 tid : SV_DispatchThreadID)
{
float acc = 0.0;
int base = int(tid.x);
for (int i = 0; i < 100; ++i)
{
Scene sc;
switch ((base + i) % 100)
{
case 0: sc.m = M0(); break;
case 1: sc.m = M1(); break;
case 2: sc.m = M2(); break;
case 3: sc.m = M3(); break;
case 4: sc.m = M4(); break;
case 5: sc.m = M5(); break;
case 6: sc.m = M6(); break;
case 7: sc.m = M7(); break;
case 8: sc.m = M8(); break;
case 9: sc.m = M9(); break;
case 10: sc.m = M10(); break;
case 11: sc.m = M11(); break;
case 12: sc.m = M12(); break;
case 13: sc.m = M13(); break;
case 14: sc.m = M14(); break;
case 15: sc.m = M15(); break;
case 16: sc.m = M16(); break;
case 17: sc.m = M17(); break;
case 18: sc.m = M18(); break;
case 19: sc.m = M19(); break;
case 20: sc.m = M20(); break;
case 21: sc.m = M21(); break;
case 22: sc.m = M22(); break;
case 23: sc.m = M23(); break;
case 24: sc.m = M24(); break;
case 25: sc.m = M25(); break;
case 26: sc.m = M26(); break;
case 27: sc.m = M27(); break;
case 28: sc.m = M28(); break;
case 29: sc.m = M29(); break;
case 30: sc.m = M30(); break;
case 31: sc.m = M31(); break;
case 32: sc.m = M32(); break;
case 33: sc.m = M33(); break;
case 34: sc.m = M34(); break;
case 35: sc.m = M35(); break;
case 36: sc.m = M36(); break;
case 37: sc.m = M37(); break;
case 38: sc.m = M38(); break;
case 39: sc.m = M39(); break;
case 40: sc.m = M40(); break;
case 41: sc.m = M41(); break;
case 42: sc.m = M42(); break;
case 43: sc.m = M43(); break;
case 44: sc.m = M44(); break;
case 45: sc.m = M45(); break;
case 46: sc.m = M46(); break;
case 47: sc.m = M47(); break;
case 48: sc.m = M48(); break;
case 49: sc.m = M49(); break;
case 50: sc.m = M50(); break;
case 51: sc.m = M51(); break;
case 52: sc.m = M52(); break;
case 53: sc.m = M53(); break;
case 54: sc.m = M54(); break;
case 55: sc.m = M55(); break;
case 56: sc.m = M56(); break;
case 57: sc.m = M57(); break;
case 58: sc.m = M58(); break;
case 59: sc.m = M59(); break;
case 60: sc.m = M60(); break;
case 61: sc.m = M61(); break;
case 62: sc.m = M62(); break;
case 63: sc.m = M63(); break;
case 64: sc.m = M64(); break;
case 65: sc.m = M65(); break;
case 66: sc.m = M66(); break;
case 67: sc.m = M67(); break;
case 68: sc.m = M68(); break;
case 69: sc.m = M69(); break;
case 70: sc.m = M70(); break;
case 71: sc.m = M71(); break;
case 72: sc.m = M72(); break;
case 73: sc.m = M73(); break;
case 74: sc.m = M74(); break;
case 75: sc.m = M75(); break;
case 76: sc.m = M76(); break;
case 77: sc.m = M77(); break;
case 78: sc.m = M78(); break;
case 79: sc.m = M79(); break;
case 80: sc.m = M80(); break;
case 81: sc.m = M81(); break;
case 82: sc.m = M82(); break;
case 83: sc.m = M83(); break;
case 84: sc.m = M84(); break;
case 85: sc.m = M85(); break;
case 86: sc.m = M86(); break;
case 87: sc.m = M87(); break;
case 88: sc.m = M88(); break;
case 89: sc.m = M89(); break;
case 90: sc.m = M90(); break;
case 91: sc.m = M91(); break;
case 92: sc.m = M92(); break;
case 93: sc.m = M93(); break;
case 94: sc.m = M94(); break;
case 95: sc.m = M95(); break;
case 96: sc.m = M96(); break;
case 97: sc.m = M97(); break;
case 98: sc.m = M98(); break;
case 99: sc.m = M99(); break;
default: sc.m = M0(); break;
}
sc.w = float(i);
acc += shadeScene(sc, outBuf[0] + float(i));
}
outBuf[0] = acc;
}