← back

existential_aggregate

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

Phase composition across releases

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.

Across releases

existential_aggregate — Across releases (median ms) existential_aggregate 0.81× 0.0 145 290 25.12 25.13 25.14 25.15 25.16 25.17 25.18 25.19 25.20 25.21 25.22 25.23 25.24 26.1 26.2 26.3 26.4 26.5 26.7 26.8 26.9 26.10 26.11 26.12 26.13 26.13.1 26.14 26.14.1 26.16 26.16.1 existential_aggregate — parseTranslationUnit existential_aggregate — SemanticChecking existential_aggregate — generateIR existential_aggregate — frontEndExecute (self) existential_aggregate — specializeModule existential_aggregate — simplifyIR existential_aggregate — linkIR existential_aggregate — unrollLoopsInModule existential_aggregate — legalizeResourceTypes existential_aggregate — legalizeExistentialTypeLayout existential_aggregate — performMandatoryEarlyInlining existential_aggregate — performForceInlining existential_aggregate — linkAndOptimizeIR (self) existential_aggregate — generateOutput (self) existential_aggregate — compileInner (self) phase buckets parseTranslationUnit SemanticChecking generateIR frontEndExecute (self) specializeModule simplifyIR linkIR unrollLoopsInModule legalizeResourceTypes legalizeExistentialTypeLayout performMandatoryEarlyInlining performForceInlining linkAndOptimizeIR (self) emitEntryPointsSourceFromIR generateOutput (self) compileInner (self)

Daily tip-of-tree (last 30 days)

existential_aggregate — Daily tip-of-tree (last 30 days) (median ms) existential_aggregate 0.97× 0.0 44 88 07-30 07-31 08-01 08-02 08-03 08-04 08-05 08-06 08-07 08-08 08-09 08-10 08-11 08-12 08-13 08-14 08-15 08-15 08-18 08-19 08-20 08-21 08-22 08-23 08-24 08-25 08-26 08-27 08-28 08-29 existential_aggregate — parseTranslationUnit existential_aggregate — SemanticChecking existential_aggregate — generateIR existential_aggregate — frontEndExecute (self) existential_aggregate — specializeModule existential_aggregate — simplifyIR existential_aggregate — linkIR existential_aggregate — unrollLoopsInModule existential_aggregate — legalizeResourceTypes existential_aggregate — legalizeExistentialTypeLayout existential_aggregate — performMandatoryEarlyInlining existential_aggregate — performForceInlining existential_aggregate — linkAndOptimizeIR (self) existential_aggregate — generateOutput (self) existential_aggregate — compileInner (self) phase buckets parseTranslationUnit SemanticChecking generateIR frontEndExecute (self) specializeModule simplifyIR linkIR unrollLoopsInModule legalizeResourceTypes legalizeExistentialTypeLayout performMandatoryEarlyInlining performForceInlining linkAndOptimizeIR (self) emitEntryPointsSourceFromIR generateOutput (self) compileInner (self)

Daily window progress

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 daycommitstop buckets (own %)
none

Reproduce

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

Compiled Slang source

the complete compiled source (N = 100), shown in full

existential_aggregate.slang (229 lines)

// 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;
}