---
generated: true
model: claude-opus-4-7
generated_at: 2026-05-21T18:00:00+00:00
source_commit: 690f6a3084801386b77186394e0f6e8c120824a4
watched_paths_digest: a7b1c184243cc33ab7365f1e766ae76123f4e9039f529babd0a030cb03949933
source_doc: docs/generated/design/cross-cutting/ir-instructions.md
source_doc_digest: a0fb638618164f0a2ef326bfc1eda1d1f8d37d916fbe5842e1ae309d082169f9
warning: "Auto-generated. May drift from source. Do not edit by hand."
---

# Tests for cross-cutting/ir-instructions

## Intent
Tests verify the observable shape of the Slang IR described in
[`docs/generated/design/cross-cutting/ir-instructions.md`](../../../design/cross-cutting/ir-instructions.md):
that representative opcodes from each documented family
(`add`/`sub`/`mul`/`div` arithmetic, `cmpGT` comparison, `intCast`
conversion, `var`/`load`/`store`/`get_field_addr`/`swizzle` memory,
`ifElse`/`unconditionalBranch`/`loop`/`return_val` control-flow,
`func`/`struct`/`field`/`witness_table`/`witness_table_entry`/`global_param`
structure, `specialize` for generic instantiation, `entryPoint` /
`nameHint` decorations, `rwstructuredBufferGetElementPtr` /
`global_hashed_string_literals` resource and value opcodes,
`Vec(elementType, elementCount)` and `Array(elementType, elementCount)`
and `Ptr(valueType)` types) appear in the IR for the obvious source
construct that ought to produce them.

The primary observation mechanism is `-target spirv-asm -dump-ir -o
/dev/null` followed by a FileCheck against the IR dump (anchored at
the `### LOWER-TO-IR:` stage, the first dump where opcode spellings
match the doc's "Notes" column most directly). For claims that lower
predictably across text-emit targets (notably `add` → `+`), a
multi-backend test runs the same Slang source through each available
text target and FileChecks the per-target emit.

Implementation-internal claims — opcode-flag bits
(`Hoistable`/`Global`/`Parent`/`UseOther`), the IR-builder's
deduplication decision, the contiguous opcode-range layout that
underlies `as<IRBasicType>()`, the module-version-bump workflow, the
FIDDLE-generated `IROp` enum — are recorded under
`## Untested claims` because they are not observable
through any directive that `slang-test` runs on a CPU.


## Functional coverage
| Claim | Intent | Anchor | Tests |
| --- | --- | --- | --- |
| A `discard` statement in a pixel shader lowers to the `discard` IR terminator that the doc lists alongside `return_val` and `unreachable`. | boundary | [#control-flow-instructions](../../../design/cross-cutting/ir-instructions.md#control-flow-instructions) | [`control-flow-discard-ir.slang`](control-flow-discard-ir.slang) |
| A `for` loop lowers to the `loop` terminator and uses block `param`s to carry the SSA induction value. | functional | [#control-flow-instructions](../../../design/cross-cutting/ir-instructions.md#control-flow-instructions) | [`control-flow-loop-ir.slang`](control-flow-loop-ir.slang) |
| A function `return value;` statement lowers to the `return_val` terminator. | functional | [#control-flow-instructions](../../../design/cross-cutting/ir-instructions.md#control-flow-instructions) | [`control-flow-return-val-ir.slang`](control-flow-return-val-ir.slang) |
| A function whose every control-flow path ends in `return` produces an `unreachable` terminator in the synthesized join block, exercising the documented `unreachable` exit terminator. | boundary | [#control-flow-instructions](../../../design/cross-cutting/ir-instructions.md#control-flow-instructions) | [`control-flow-unreachable-ir.slang`](control-flow-unreachable-ir.slang) |
| An `if`/`else` statement lowers to the `ifElse` terminator plus an `unconditionalBranch` join. | functional | [#control-flow-instructions](../../../design/cross-cutting/ir-instructions.md#control-flow-instructions) | [`control-flow-ifelse-ir.slang`](control-flow-ifelse-ir.slang) |
| An `if`/`else` whose two arms each yield a value lowers to a join `block` with a `param` that receives the per-arm value via `unconditionalBranch(merge, value)` — the doc's "block parameters replace SSA `phi`" claim. | expansion | [#control-flow-instructions](../../../design/cross-cutting/ir-instructions.md#control-flow-instructions) | [`control-flow-block-with-param.slang`](control-flow-block-with-param.slang) |
| Boundary probe of the `block` family: an entry function with an empty body still produces a basic `block` ending in `return_val(void_constant)`. | boundary | [#control-flow-instructions](../../../design/cross-cutting/ir-instructions.md#control-flow-instructions) | [`control-flow-empty-body.slang`](control-flow-empty-body.slang) |
| Boundary probe of the documented `switch` terminator with multiple case values: the IR `switch(...)` instruction takes the scrutinee, a default block, a merge block, and per-case `(value, block)` pairs as variadic operands. | boundary | [#control-flow-instructions](../../../design/cross-cutting/ir-instructions.md#control-flow-instructions) | [`control-flow-switch-multi-case.slang`](control-flow-switch-multi-case.slang) |
| Stress probe of the documented `loop` terminator: two nested `for` loops produce two distinct `loop(...)` terminators in the IR, each with its own back-edge block parameters. | stress | [#control-flow-instructions](../../../design/cross-cutting/ir-instructions.md#control-flow-instructions) | [`control-flow-nested-loop.slang`](control-flow-nested-loop.slang) |
| A `[numthreads(X,Y,Z)]` attribute on a compute entry point lowers to a `numThreads` decoration on the IR `func`, exercising the documented `Decoration` family (member of the ~180 decorations the doc cites). | expansion | [#decorations](../../../design/cross-cutting/ir-instructions.md#decorations) | [`decoration-num-threads-ir.slang`](decoration-num-threads-ir.slang) |
| A function marked as a compute entry point carries an `entryPoint` decoration in the IR and emits a target-specific entry-point declaration. | functional | [#decorations](../../../design/cross-cutting/ir-instructions.md#decorations) | [`decoration-entry-point-ir.slang`](decoration-entry-point-ir.slang) |
| Each user-named declaration in source carries a `nameHint` decoration in the IR so the linker / debug output can render it. | functional | [#decorations](../../../design/cross-cutting/ir-instructions.md#decorations) | [`decoration-name-hint-ir.slang`](decoration-name-hint-ir.slang) |
| A call to a `void`-returning helper with an `out` parameter lowers to a `call` opcode whose first non-callee operand is the address of the local backing the `out` argument, exercising the documented call-site form of `func`. | expansion | [#function-and-module-structure](../../../design/cross-cutting/ir-instructions.md#function-and-module-structure) | [`structure-call-void-return.slang`](structure-call-void-return.slang) |
| A module-scope `uniform` declaration lowers to a `global_param` IR opcode. | functional | [#function-and-module-structure](../../../design/cross-cutting/ir-instructions.md#function-and-module-structure) | [`structure-global-param-ir.slang`](structure-global-param-ir.slang) |
| A mutable `static` module-scope variable lowers to the documented `global_var` IR opcode (sibling of `global_param` / `globalConstant`). | boundary | [#function-and-module-structure](../../../design/cross-cutting/ir-instructions.md#function-and-module-structure) | [`structure-global-var-ir.slang`](structure-global-var-ir.slang) |
| A type that conforms to an interface produces a `witness_table` with `witness_table_entry` children mapping interface requirements to satisfying values. | functional | [#function-and-module-structure](../../../design/cross-cutting/ir-instructions.md#function-and-module-structure) | [`structure-witness-table-ir.slang`](structure-witness-table-ir.slang) |
| A user-declared generic function lowers to the documented `generic` parent opcode (C++ wrapper `IRGeneric`) — "Type-level computation parent ending in `yield`". | expansion | [#function-and-module-structure](../../../design/cross-cutting/ir-instructions.md#function-and-module-structure) | [`structure-generic-ir.slang`](structure-generic-ir.slang) |
| A user-defined function lowers to a `func` opcode whose children are basic `block`s, and a call site lowers to `call`. | functional | [#function-and-module-structure](../../../design/cross-cutting/ir-instructions.md#function-and-module-structure) | [`structure-func-ir.slang`](structure-func-ir.slang) |
| Boundary probe of the documented `witness_table_entry(requirementKey, satisfyingVal)` opcode: an interface with multiple requirements produces one `witness_table_entry` per requirement in the table. | boundary | [#function-and-module-structure](../../../design/cross-cutting/ir-instructions.md#function-and-module-structure) | [`structure-witness-table-entry-ir.slang`](structure-witness-table-entry-ir.slang) |
| Boundary probe of the documented module-scope storage opcodes: a `static const` literal declaration lowers to a `globalConstant` IR opcode (sibling of `global_param`). | boundary | [#function-and-module-structure](../../../design/cross-cutting/ir-instructions.md#function-and-module-structure) | [`structure-global-constant.slang`](structure-global-constant.slang) |
| Negative probe of the documented `globalConstant` opcode: a `static const` declaration is read-only by definition, so assigning to it is rejected at type-check time before any IR is built. | negative | [#function-and-module-structure](../../../design/cross-cutting/ir-instructions.md#function-and-module-structure) | [`negative-write-to-static-const.slang`](negative-write-to-static-const.slang) |
| Stress probe of the documented `call` opcode (under the `func` family): a call to an 8-argument helper produces a single variadic `call` with all eight argument values. | stress | [#function-and-module-structure](../../../design/cross-cutting/ir-instructions.md#function-and-module-structure) | [`function-call-high-arity.slang`](function-call-high-arity.slang) |
| A `.wxyz` swizzle on a `double4` lowers to the documented `swizzle` opcode with indices `(3, 0, 1, 2)` and a `Vec(Double, 4)` result — double-precision probe of the swizzle element-type axis. | expansion | [#memory-instructions](../../../design/cross-cutting/ir-instructions.md#memory-instructions) | [`swizzle-double4-wxyz.slang`](swizzle-double4-wxyz.slang) |
| A `.xyz` swizzle on a `half4` lowers to the documented `swizzle` opcode collecting indices `(0, 1, 2)` and producing a `Vec(Half, 3)` result. | expansion | [#memory-instructions](../../../design/cross-cutting/ir-instructions.md#memory-instructions) | [`swizzle-half3-xyz.slang`](swizzle-half3-xyz.slang) |
| A `.yx` swap-swizzle on a `half2` lowers to the documented `swizzle` opcode with indices `(1, 0)` and a `Vec(Half, 2)` result — narrow-float length-2 reverse-order probe. | expansion | [#memory-instructions](../../../design/cross-cutting/ir-instructions.md#memory-instructions) | [`swizzle-half2-yx.slang`](swizzle-half2-yx.slang) |
| A local `var` produces a value whose IR type is `Ptr<T>`, as the doc states for the memory family. | functional | [#memory-instructions](../../../design/cross-cutting/ir-instructions.md#memory-instructions) | [`type-ptr-from-var-ir.slang`](type-ptr-from-var-ir.slang) |
| A local struct variable lowers to `var` and its field reads/writes lower to `store` / `load` / `get_field_addr` IR opcodes. | functional | [#memory-instructions](../../../design/cross-cutting/ir-instructions.md#memory-instructions) | [`memory-var-load-store-ir.slang`](memory-var-load-store-ir.slang) |
| A single-element extract `.w` on a `double4` lowers to the documented `swizzle` opcode with a `Double` result type and a single index `3 : Int` — double-precision probe at the length-1 swizzle edge. | expansion | [#memory-instructions](../../../design/cross-cutting/ir-instructions.md#memory-instructions) | [`swizzle-double4-single-w.slang`](swizzle-double4-single-w.slang) |
| A single-element extract `.x` on a `vector<uint8_t, 4>` lowers to the documented `swizzle` opcode with a `UInt8` result type — narrow-integer probe of the swizzle element-type axis at the length-1 edge. | expansion | [#memory-instructions](../../../design/cross-cutting/ir-instructions.md#memory-instructions) | [`swizzle-uint8-vec-single-element.slang`](swizzle-uint8-vec-single-element.slang) |
| A single-element extract `.y` on a `half3` vector lowers to the documented `swizzle` opcode with a `Half` result type — narrow-float probe of the swizzle-element-type axis. | expansion | [#memory-instructions](../../../design/cross-cutting/ir-instructions.md#memory-instructions) | [`swizzle-half3-single-element.slang`](swizzle-half3-single-element.slang) |
| Boundary probe of the `load` memory opcode: reading a whole struct value out of an `RWStructuredBuffer` emits a `load(ptr)` whose pointer is the result of `rwstructuredBufferGetElementPtr`. | boundary | [#memory-instructions](../../../design/cross-cutting/ir-instructions.md#memory-instructions) | [`memory-load-struct-from-buffer.slang`](memory-load-struct-from-buffer.slang) |
| Boundary probe of the documented `Ptr<T>` type operand: a `rwstructuredBufferGetElementPtr` result is typed `Ptr(Int)`, exercising the doc's `Ptr` type opcode with a scalar `valueType`. | boundary | [#memory-instructions](../../../design/cross-cutting/ir-instructions.md#memory-instructions) | [`memory-ptr-from-var-int.slang`](memory-ptr-from-var-int.slang) |
| Boundary probe of the documented `swizzle` opcode at the 2-element interior of the length axis: `v.xy` lowers to a `swizzle(%v, 0 : Int, 1 : Int)` IR opcode producing a `Vec(Float, 2 : Int)` result. | boundary | [#memory-instructions](../../../design/cross-cutting/ir-instructions.md#memory-instructions) | [`memory-swizzle-two-elements.slang`](memory-swizzle-two-elements.slang) |
| Boundary probe of the documented `swizzle` opcode at the length-1 edge: `v.x` lowers to `swizzle(%v, 0 : Int)` with a single index operand. | boundary | [#memory-instructions](../../../design/cross-cutting/ir-instructions.md#memory-instructions) | [`memory-swizzle-single-element.slang`](memory-swizzle-single-element.slang) |
| Boundary probe of the documented `swizzle` opcode at the maximum HLSL-vector-length edge: `v.wzyx` lowers to a 4-index `swizzle(%v, 3, 2, 1, 0)` in the IR. | boundary | [#memory-instructions](../../../design/cross-cutting/ir-instructions.md#memory-instructions) | [`memory-swizzle-full-reverse.slang`](memory-swizzle-full-reverse.slang) |
| Indexed access into a local fixed-size array with a runtime index lowers to the documented `getElement` memory opcode taking `(base, index)`. | boundary | [#memory-instructions](../../../design/cross-cutting/ir-instructions.md#memory-instructions) | [`memory-get-element-array.slang`](memory-get-element-array.slang) |
| Indexing into a vector or array value through a swizzle lowers to a `swizzle` IR opcode, the rvalue indexing operation the doc lists alongside `getElement` / `getElementPtr`. | functional | [#memory-instructions](../../../design/cross-cutting/ir-instructions.md#memory-instructions) | [`memory-getelement-ir.slang`](memory-getelement-ir.slang) |
| A read from a `StructuredBuffer<T>` lowers to the documented `structuredBufferLoad(base, index)` opcode (the read-only sibling of `rwstructuredBufferStore`). | expansion | [#resource-and-shader-io-opcodes](../../../design/cross-cutting/ir-instructions.md#resource-and-shader-io-opcodes) | [`resource-structured-buffer-load-ir.slang`](resource-structured-buffer-load-ir.slang) |
| An `Atomic<half>.add(v)` lowers to the documented `atomicAdd` opcode with a `Half` result type — narrow-float probe of the `AtomicOperation` family. | expansion | [#resource-and-shader-io-opcodes](../../../design/cross-cutting/ir-instructions.md#resource-and-shader-io-opcodes) | [`atomic-add-half.slang`](atomic-add-half.slang) |
| An `Atomic<int64_t>.add(1)` lowers to the documented `atomicAdd` opcode with an `Int64` result type — 64-bit signed companion of the `atomic-add-uint64` probe. | expansion | [#resource-and-shader-io-opcodes](../../../design/cross-cutting/ir-instructions.md#resource-and-shader-io-opcodes) | [`atomic-add-int64.slang`](atomic-add-int64.slang) |
| An `Atomic<int64_t>.compareExchange(expected, desired)` lowers to the documented `atomicCompareExchange` opcode of the `AtomicOperation` family on a 64-bit signed element. | expansion | [#resource-and-shader-io-opcodes](../../../design/cross-cutting/ir-instructions.md#resource-and-shader-io-opcodes) | [`atomic-compare-exchange-int64.slang`](atomic-compare-exchange-int64.slang) |
| An `Atomic<int64_t>.load()` lowers to the documented `atomicLoad` opcode of the `AtomicOperation` family on a 64-bit signed element. | expansion | [#resource-and-shader-io-opcodes](../../../design/cross-cutting/ir-instructions.md#resource-and-shader-io-opcodes) | [`atomic-load-int64.slang`](atomic-load-int64.slang) |
| An `Atomic<int64_t>.max(v)` lowers to the documented `atomicMax` opcode of the `AtomicOperation` family on a 64-bit signed element. | expansion | [#resource-and-shader-io-opcodes](../../../design/cross-cutting/ir-instructions.md#resource-and-shader-io-opcodes) | [`atomic-max-int64.slang`](atomic-max-int64.slang) |
| An `Atomic<int64_t>.min(1)` lowers to the documented `atomicMin` opcode (sibling of `atomicAdd` in the `AtomicOperation` family) on a 64-bit signed element. | expansion | [#resource-and-shader-io-opcodes](../../../design/cross-cutting/ir-instructions.md#resource-and-shader-io-opcodes) | [`atomic-min-int64.slang`](atomic-min-int64.slang) |
| An `Atomic<int64_t>.store(v)` lowers to the documented `atomicStore` opcode of the `AtomicOperation` family on a 64-bit signed element. | expansion | [#resource-and-shader-io-opcodes](../../../design/cross-cutting/ir-instructions.md#resource-and-shader-io-opcodes) | [`atomic-store-int64.slang`](atomic-store-int64.slang) |
| An `Atomic<uint64_t>.add(1)` lowers to the documented `atomicAdd` opcode with a `UInt64` result type — the 64-bit-unsigned probe of the `AtomicOperation` family. | expansion | [#resource-and-shader-io-opcodes](../../../design/cross-cutting/ir-instructions.md#resource-and-shader-io-opcodes) | [`atomic-add-uint64.slang`](atomic-add-uint64.slang) |
| An `Atomic<uint64_t>.exchange(v)` lowers to the documented `atomicExchange` opcode (read-modify-write sibling of `atomicAdd`) on a 64-bit unsigned element. | expansion | [#resource-and-shader-io-opcodes](../../../design/cross-cutting/ir-instructions.md#resource-and-shader-io-opcodes) | [`atomic-exchange-uint64.slang`](atomic-exchange-uint64.slang) |
| An `Atomic<uint64_t>.or(v)` lowers to the documented `atomicOr` opcode of the `AtomicOperation` family on a 64-bit unsigned element. | expansion | [#resource-and-shader-io-opcodes](../../../design/cross-cutting/ir-instructions.md#resource-and-shader-io-opcodes) | [`atomic-or-uint64.slang`](atomic-or-uint64.slang) |
| An `Atomic<uint64_t>.xor(v)` lowers to the documented `atomicXor` opcode of the `AtomicOperation` family on a 64-bit unsigned element. | expansion | [#resource-and-shader-io-opcodes](../../../design/cross-cutting/ir-instructions.md#resource-and-shader-io-opcodes) | [`atomic-xor-uint64.slang`](atomic-xor-uint64.slang) |
| An `Atomic<uint>.and(mask)` lowers to the documented `atomicAnd` opcode of the `AtomicOperation` family. | expansion | [#resource-and-shader-io-opcodes](../../../design/cross-cutting/ir-instructions.md#resource-and-shader-io-opcodes) | [`atomic-and-uint.slang`](atomic-and-uint.slang) |
| Boundary probe of `rwstructuredBufferGetElementPtr`: a runtime-bounded index (thread id, not a literal) still lowers to the same opcode with an SSA-value index instead of a literal. | boundary | [#resource-and-shader-io-opcodes](../../../design/cross-cutting/ir-instructions.md#resource-and-shader-io-opcodes) | [`buffer-write-runtime-index.slang`](buffer-write-runtime-index.slang) |
| Boundary probe of `rwstructuredBufferGetElementPtr`: writing to one index and reading from another in the same buffer emits two distinct `getElementPtr` instructions, plus paired `store` and `load`. | boundary | [#resource-and-shader-io-opcodes](../../../design/cross-cutting/ir-instructions.md#resource-and-shader-io-opcodes) | [`buffer-aliased-write-and-read.slang`](buffer-aliased-write-and-read.slang) |
| Boundary probe of `structuredBufferLoad` with a runtime (non-literal) index: the index operand survives in the IR as a use of the `uniform`-fed value rather than being folded. | boundary | [#resource-and-shader-io-opcodes](../../../design/cross-cutting/ir-instructions.md#resource-and-shader-io-opcodes) | [`resource-structured-buffer-load-runtime-index.slang`](resource-structured-buffer-load-runtime-index.slang) |
| Indexing into an `RWStructuredBuffer` lowers to a resource-family IR opcode that produces a pointer to the element. | functional | [#resource-and-shader-io-opcodes](../../../design/cross-cutting/ir-instructions.md#resource-and-shader-io-opcodes) | [`resource-buffer-getelementptr-ir.slang`](resource-buffer-getelementptr-ir.slang) |
| Stress probe of the documented `atomicAdd` family: 64 threads each calling `.add(1)` on a shared `Atomic<int>` produce an `atomicAdd` instruction in the per-thread IR body. | stress | [#resource-and-shader-io-opcodes](../../../design/cross-cutting/ir-instructions.md#resource-and-shader-io-opcodes) | [`atomic-add-stress.slang`](atomic-add-stress.slang) |
| `Atomic<int16_t>` is rejected at type-check time because `int16_t` does not conform to the `IAtomicable` interface — bounds the AtomicOperation element-type axis below 32 bits on the integer side. | negative | [#resource-and-shader-io-opcodes](../../../design/cross-cutting/ir-instructions.md#resource-and-shader-io-opcodes) | [`negative-atomic-int16-not-atomicable.slang`](negative-atomic-int16-not-atomicable.slang) |
| `RWStructuredBuffer<half3>.Load(idx)` lowers to the documented `rwstructuredBufferLoad` resource opcode returning a `Vec(Half, 3)` value — narrow-float vector element probe of the resource family. | expansion | [#resource-and-shader-io-opcodes](../../../design/cross-cutting/ir-instructions.md#resource-and-shader-io-opcodes) | [`rwbuffer-load-half3-element.slang`](rwbuffer-load-half3-element.slang) |
| `RWStructuredBuffer<int8_t>.Load(idx)` lowers to the documented `rwstructuredBufferLoad` resource opcode with an `Int8` result type — narrow-integer-element probe of the resource family. | expansion | [#resource-and-shader-io-opcodes](../../../design/cross-cutting/ir-instructions.md#resource-and-shader-io-opcodes) | [`rwbuffer-load-int8-element.slang`](rwbuffer-load-int8-element.slang) |
| `StructuredBuffer<int8_t>.Load(idx)` lowers to the documented `structuredBufferLoad` resource opcode with an `Int8` result type — narrow-integer probe of the read-only resource family. | expansion | [#resource-and-shader-io-opcodes](../../../design/cross-cutting/ir-instructions.md#resource-and-shader-io-opcodes) | [`sbuffer-load-int8-element.slang`](sbuffer-load-int8-element.slang) |
| Assigning a concrete type to an interface-typed local lowers to the documented `makeExistential(value, witness)` opcode that packs the value and its witness table. | expansion | [#specialization-and-existentials](../../../design/cross-cutting/ir-instructions.md#specialization-and-existentials) | [`specialization-make-existential-ir.slang`](specialization-make-existential-ir.slang) |
| Boundary probe of the variadic `args...` operand list on the documented `specialize` opcode: a 2-type-parameter generic call lowers to `specialize(%generic, Int, Float)`. | boundary | [#specialization-and-existentials](../../../design/cross-cutting/ir-instructions.md#specialization-and-existentials) | [`specialize-two-type-arguments.slang`](specialize-two-type-arguments.slang) |
| Calling a generic function with a concrete type argument lowers to a `specialize` IR opcode. | functional | [#specialization-and-existentials](../../../design/cross-cutting/ir-instructions.md#specialization-and-existentials) | [`specialization-specialize-ir.slang`](specialization-specialize-ir.slang) |
| Calling an interface method through an existential-typed value projects the value, type, and witness via the documented `extractExistentialValue` / `extractExistentialType` / `extractExistentialWitnessTable` opcodes. | expansion | [#specialization-and-existentials](../../../design/cross-cutting/ir-instructions.md#specialization-and-existentials) | [`specialization-extract-existential-ir.slang`](specialization-extract-existential-ir.slang) |
| Calling an interface-constrained generic on a concrete type lowers to the documented `lookupWitness(witnessTable, requirementKey)` opcode that resolves the interface requirement to the concrete method. | expansion | [#specialization-and-existentials](../../../design/cross-cutting/ir-instructions.md#specialization-and-existentials) | [`specialization-lookup-witness-ir.slang`](specialization-lookup-witness-ir.slang) |
| A `Texture2D<float4>` parameter is typed with the documented `Texture` type opcode in the IR, carrying its (elementType, shape, isArray, isMS, sampleCount, access, ...) operand row. | expansion | [#type-instructions](../../../design/cross-cutting/ir-instructions.md#type-instructions) | [`type-texture2d-ir.slang`](type-texture2d-ir.slang) |
| A `float3x3` matrix parameter is typed `Mat(elementType, rowCount, columnCount, layout)` in the IR — exercising the documented four-operand shape of the `matrix` type opcode (with the layout operand explicit). | boundary | [#type-instructions](../../../design/cross-cutting/ir-instructions.md#type-instructions) | [`type-matrix-layout-operand.slang`](type-matrix-layout-operand.slang) |
| A fixed-size array type appears in the IR as `Array(elementType, elementCount)`. | functional | [#type-instructions](../../../design/cross-cutting/ir-instructions.md#type-instructions) | [`type-array-ir.slang`](type-array-ir.slang) |
| A user `struct` declaration lowers to a parent `struct` IR opcode containing `field` children. | functional | [#type-instructions](../../../design/cross-cutting/ir-instructions.md#type-instructions) | [`structure-struct-field-ir.slang`](structure-struct-field-ir.slang) |
| A user-declared `class` lowers to the documented `class` parent type opcode (C++ wrapper `ClassType`), distinct from `struct`. | expansion | [#type-instructions](../../../design/cross-cutting/ir-instructions.md#type-instructions) | [`type-class-ir.slang`](type-class-ir.slang) |
| A user-declared `interface` lowers to the documented `interface` parent type opcode (C++ wrapper `InterfaceType`), whose children are `interface_req_entry` requirement rows. | expansion | [#type-instructions](../../../design/cross-cutting/ir-instructions.md#type-instructions) | [`type-interface-ir.slang`](type-interface-ir.slang) |
| A vector-typed parameter or value uses the `Vec` IR type with element-type and element-count operands. | functional | [#type-instructions](../../../design/cross-cutting/ir-instructions.md#type-instructions) | [`type-vector-ir.slang`](type-vector-ir.slang) |
| Boundary probe of the `Array` IR type at element-count `1`: a `data[1]` field lowers to `Array(Int, 1 : Int)`. | boundary | [#type-instructions](../../../design/cross-cutting/ir-instructions.md#type-instructions) | [`type-array-length-one.slang`](type-array-length-one.slang) |
| Boundary probe of the `struct` parent opcode at the empty-children edge: an empty `struct {}` still lowers to a `struct` IR opcode with no `field` children. | boundary | [#type-instructions](../../../design/cross-cutting/ir-instructions.md#type-instructions) | [`structure-empty-struct.slang`](structure-empty-struct.slang) |
| Boundary probe of the `vector` IR type at element-count `1`: `vector<int,1>` lowers to `Vec(Int, 1 : Int)` in the IR. | boundary | [#type-instructions](../../../design/cross-cutting/ir-instructions.md#type-instructions) | [`type-vector-length-one.slang`](type-vector-length-one.slang) |
| Boundary probe of the documented `matrix` type opcode: a `float4x4` parameter is typed `Mat(Float, 4 : Int, 4 : Int, ...)` in the IR with element-type, row-count, and column-count operands. | boundary | [#type-instructions](../../../design/cross-cutting/ir-instructions.md#type-instructions) | [`type-matrix-float-4x4.slang`](type-matrix-float-4x4.slang) |
| Negative probe of the documented `Array(elementType, elementCount)` type opcode: the `elementCount` operand must be a compile-time constant, so a runtime-sized local array is rejected before IR lowering. | negative | [#type-instructions](../../../design/cross-cutting/ir-instructions.md#type-instructions) | [`negative-runtime-sized-local-array.slang`](negative-runtime-sized-local-array.slang) |
| The basic-scalar `Bool` type appears in the IR for a `bool` parameter — the doc's "`Int`, `Float`, `Bool`, ..." basic-scalar row. | boundary | [#type-instructions](../../../design/cross-cutting/ir-instructions.md#type-instructions) | [`type-bool-ir.slang`](type-bool-ir.slang) |
| A `float4(a, b, c, d)` constructor lowers to the documented "aggregate constructors" value family — the `makeVector` opcode collecting per-element operands into a `Vec(Float, 4)` result. | expansion | [#value-instructions](../../../design/cross-cutting/ir-instructions.md#value-instructions) | [`value-make-vector-ir.slang`](value-make-vector-ir.slang) |
| A constructor-style float-to-int cast lowers to a conversion opcode (`castFloatToInt`) within the documented conversion family — distinct from same-domain `intCast` / `floatCast`. | expansion | [#value-instructions](../../../design/cross-cutting/ir-instructions.md#value-instructions) | [`conversion-float-to-int-cast-ir.slang`](conversion-float-to-int-cast-ir.slang) |
| A floating-point division expression lowers to the `div` IR opcode. | functional | [#value-instructions](../../../design/cross-cutting/ir-instructions.md#value-instructions) | [`arithmetic-div-ir.slang`](arithmetic-div-ir.slang) |
| A greater-than comparison expression lowers to the `cmpGT` IR opcode. | functional | [#value-instructions](../../../design/cross-cutting/ir-instructions.md#value-instructions) | [`comparison-cmpgt-ir.slang`](comparison-cmpgt-ir.slang) |
| A narrowing float-to-float cast (`double` -> `float`) lowers to the documented `floatCast` conversion opcode (same-domain precision cast). | boundary | [#value-instructions](../../../design/cross-cutting/ir-instructions.md#value-instructions) | [`conversion-floatcast-double-to-float.slang`](conversion-floatcast-double-to-float.slang) |
| A string-literal use lowers to a `StringLit` payload-carrying value, and the module records a `global_hashed_string_literals` entry for it. | functional | [#value-instructions](../../../design/cross-cutting/ir-instructions.md#value-instructions) | [`value-string-lit-hash-ir.slang`](value-string-lit-hash-ir.slang) |
| An explicit integer cast from a `uint` source value lowers to the `intCast` IR opcode. | functional | [#value-instructions](../../../design/cross-cutting/ir-instructions.md#value-instructions) | [`conversion-intcast-ir.slang`](conversion-intcast-ir.slang) |
| An integer addition expression lowers to the `add` IR opcode and emits as `+` on every C-like text-emit target. | functional | [#value-instructions](../../../design/cross-cutting/ir-instructions.md#value-instructions) | [`arithmetic-add-ir.slang`](arithmetic-add-ir.slang) |
| An integer multiplication expression lowers to the `mul` IR opcode and emits as `*` on every C-like text-emit target. | functional | [#value-instructions](../../../design/cross-cutting/ir-instructions.md#value-instructions) | [`arithmetic-mul-ir.slang`](arithmetic-mul-ir.slang) |
| An integer subtraction expression lowers to the `sub` IR opcode and emits as `-` on every C-like text-emit target. | functional | [#value-instructions](../../../design/cross-cutting/ir-instructions.md#value-instructions) | [`arithmetic-sub-ir.slang`](arithmetic-sub-ir.slang) |
| Bitwise `&` on `int8_t` operands lowers to the documented `and` arithmetic/logic opcode with an `Int8` result type — narrow-integer probe of the bit-op family. | expansion | [#value-instructions](../../../design/cross-cutting/ir-instructions.md#value-instructions) | [`bitwise-and-int8.slang`](bitwise-and-int8.slang) |
| Bitwise `&` on `uint64_t` operands lowers to the documented `and` opcode with a `UInt64` result type — 64-bit unsigned probe of the bit-op family. | expansion | [#value-instructions](../../../design/cross-cutting/ir-instructions.md#value-instructions) | [`bitwise-and-uint64.slang`](bitwise-and-uint64.slang) |
| Bitwise `&` on `uint8_t` operands lowers to the documented `and` opcode with a `UInt8` result type — unsigned-narrow probe of the bit-op family. | expansion | [#value-instructions](../../../design/cross-cutting/ir-instructions.md#value-instructions) | [`bitwise-and-uint8.slang`](bitwise-and-uint8.slang) |
| Bitwise `^` on `int64_t` operands lowers to the documented `xor` opcode with an `Int64` result type — upper-edge probe of the integer-width axis for the bit-op family. | expansion | [#value-instructions](../../../design/cross-cutting/ir-instructions.md#value-instructions) | [`bitwise-xor-int64.slang`](bitwise-xor-int64.slang) |
| Bitwise `\|` on `int16_t` operands lowers to the documented `or` opcode with an `Int16` result type — narrow-integer (16-bit signed) probe of the bit-op family. | expansion | [#value-instructions](../../../design/cross-cutting/ir-instructions.md#value-instructions) | [`bitwise-or-int16.slang`](bitwise-or-int16.slang) |
| Bitwise `\|` on `uint8_t` operands lowers to the documented `or` opcode with a `UInt8` result type — unsigned-narrow probe of the bit-op family. | expansion | [#value-instructions](../../../design/cross-cutting/ir-instructions.md#value-instructions) | [`bitwise-or-uint8.slang`](bitwise-or-uint8.slang) |
| Bitwise `~` (unary complement) on `int16_t` lowers to the documented `bitnot` opcode (the 1-operand bit-op family member) with an `Int16` result type. | expansion | [#value-instructions](../../../design/cross-cutting/ir-instructions.md#value-instructions) | [`bitwise-not-int16.slang`](bitwise-not-int16.slang) |
| Boundary probe of `intCast` in the opposite direction from the bootstrap test: a signed-to-unsigned cast of a `uniform int` lowers to `intCast(%a)` with the result typed `UInt`. | boundary | [#value-instructions](../../../design/cross-cutting/ir-instructions.md#value-instructions) | [`conversion-intcast-int-to-uint.slang`](conversion-intcast-int-to-uint.slang) |
| Boundary probe of the `add` opcode at `+inf`: a literal `1.0/0.0` folds to `inf : Float`, and `add(%a, inf : Float)` survives in the IR. | boundary | [#value-instructions](../../../design/cross-cutting/ir-instructions.md#value-instructions) | [`arithmetic-add-float-positive-inf.slang`](arithmetic-add-float-positive-inf.slang) |
| Boundary probe of the `add` opcode at `-inf`: a literal `-1.0/0.0` folds to `-inf : Float`, and the `add` survives in the IR. | boundary | [#value-instructions](../../../design/cross-cutting/ir-instructions.md#value-instructions) | [`arithmetic-add-float-negative-inf.slang`](arithmetic-add-float-negative-inf.slang) |
| Boundary probe of the `add` opcode at the `uint` MAX edge: `uint a + 0xFFFFFFFF` keeps an `add(%a, 4294967295 : UInt)` in the IR. | boundary | [#value-instructions](../../../design/cross-cutting/ir-instructions.md#value-instructions) | [`arithmetic-add-uint32-max-overflow.slang`](arithmetic-add-uint32-max-overflow.slang) |
| Boundary probe of the `cmpGT` opcode at the NaN-ordering edge: comparing a `uniform float` against itself emits a `cmpGT(%a, %a)` in the IR. | boundary | [#value-instructions](../../../design/cross-cutting/ir-instructions.md#value-instructions) | [`comparison-nan-greater-than-self.slang`](comparison-nan-greater-than-self.slang) |
| Boundary probe of the `div` opcode with a literal `0.0` divisor: `uniform / 0.0` still emits `div(%a, 0 : Float)` in the IR. | boundary | [#value-instructions](../../../design/cross-cutting/ir-instructions.md#value-instructions) | [`arithmetic-div-by-positive-zero-float.slang`](arithmetic-div-by-positive-zero-float.slang) |
| Boundary probe of the `mul` opcode with a literal `0` operand: a `uniform * 0` still emits `mul(%a, 0 : Float)` because constant folding does not strength-reduce a uniform operand. | boundary | [#value-instructions](../../../design/cross-cutting/ir-instructions.md#value-instructions) | [`arithmetic-mul-by-zero-literal.slang`](arithmetic-mul-by-zero-literal.slang) |
| Boundary probe of the `sub` opcode at the `int` MIN edge: subtracting `INT_MIN` from a uniform produces `sub(%a, -2147483648 : Int)` in the IR. | boundary | [#value-instructions](../../../design/cross-cutting/ir-instructions.md#value-instructions) | [`arithmetic-sub-int-min-literal.slang`](arithmetic-sub-int-min-literal.slang) |
| Boundary probe of the comparison family: `!=` lowers to the `cmpNE` IR opcode (sibling of `cmpEQ`). | boundary | [#value-instructions](../../../design/cross-cutting/ir-instructions.md#value-instructions) | [`comparison-cmpne-ir.slang`](comparison-cmpne-ir.slang) |
| Boundary probe of the comparison family: `<=` lowers to the `cmpLE` IR opcode (sibling of `cmpLT`). | boundary | [#value-instructions](../../../design/cross-cutting/ir-instructions.md#value-instructions) | [`comparison-cmple-ir.slang`](comparison-cmple-ir.slang) |
| Boundary probe of the comparison family: `<` lowers to the `cmpLT` IR opcode, the entry the doc explicitly cites as a sibling of `cmpEQ`. | boundary | [#value-instructions](../../../design/cross-cutting/ir-instructions.md#value-instructions) | [`comparison-cmplt-ir.slang`](comparison-cmplt-ir.slang) |
| Boundary probe of the comparison family: `==` lowers to the `cmpEQ` IR opcode named by the doc alongside `cmpLT`/`cmpGT`. | boundary | [#value-instructions](../../../design/cross-cutting/ir-instructions.md#value-instructions) | [`comparison-cmpeq-ir.slang`](comparison-cmpeq-ir.slang) |
| Boundary probe of the comparison family: `>=` lowers to the `cmpGE` IR opcode (sibling of `cmpGT`). | boundary | [#value-instructions](../../../design/cross-cutting/ir-instructions.md#value-instructions) | [`comparison-cmpge-ir.slang`](comparison-cmpge-ir.slang) |
| Boundary probe of the conversion family: `bit_cast<uint>(float)` lowers to the documented `bitCast` IR opcode (bit-pattern reinterpret, not numeric cast). | boundary | [#value-instructions](../../../design/cross-cutting/ir-instructions.md#value-instructions) | [`conversion-bitcast-float-to-uint.slang`](conversion-bitcast-float-to-uint.slang) |
| Boundary probe of the conversion family: `int(uniform float)` lowers to the `castFloatToInt` IR opcode (numeric float-to-int conversion). | boundary | [#value-instructions](../../../design/cross-cutting/ir-instructions.md#value-instructions) | [`conversion-floatcast-to-int.slang`](conversion-floatcast-to-int.slang) |
| Boundary probe of the documented arithmetic family at its 1-operand member: unary `-a` produces a `neg(%a)` IR instruction. | boundary | [#value-instructions](../../../design/cross-cutting/ir-instructions.md#value-instructions) | [`arithmetic-neg-int.slang`](arithmetic-neg-int.slang) |
| Boundary probe of the documented arithmetic family on a float operand: `-a` lowers to the unary `neg` opcode (sibling of the binary `add`/`sub`/`mul`/`div` set the doc names). | boundary | [#value-instructions](../../../design/cross-cutting/ir-instructions.md#value-instructions) | [`arithmetic-neg-float.slang`](arithmetic-neg-float.slang) |
| Comparing `int8_t < int16_t` lowers to an `intCast` promoting the narrower operand followed by `cmpLT` over the unified width — pins the mixed-narrow-type promotion path of the comparison family. | expansion | [#value-instructions](../../../design/cross-cutting/ir-instructions.md#value-instructions) | [`comparison-cmplt-mixed-int8-int16.slang`](comparison-cmplt-mixed-int8-int16.slang) |
| Left-shift `<<` on an `int64_t` lowers to the documented `shl` opcode with an `Int64` result type — upper-edge probe of the shift sibling of the bit-op family. | expansion | [#value-instructions](../../../design/cross-cutting/ir-instructions.md#value-instructions) | [`bitwise-shl-int64.slang`](bitwise-shl-int64.slang) |
| Left-shift `<<` on an `int8_t` lowers to the documented `shl` opcode with an `Int8` result type — narrow-integer shift probe. | expansion | [#value-instructions](../../../design/cross-cutting/ir-instructions.md#value-instructions) | [`bitwise-shl-int8.slang`](bitwise-shl-int8.slang) |
| Negative probe of the `bitCast` conversion opcode: `bit_cast<T>` from a value whose size does not match `T` is a documented conversion-family error, rejected by type checking before IR lowering. | negative | [#value-instructions](../../../design/cross-cutting/ir-instructions.md#value-instructions) | [`negative-bitcast-size-mismatch.slang`](negative-bitcast-size-mismatch.slang) |
| Negative probe of the documented arithmetic family: `+` is only defined for the numeric / arithmetic-interface types the doc's `add` opcode applies to; applying it to a user `struct` with no `+` overload fails type checking before IR lowering. | negative | [#value-instructions](../../../design/cross-cutting/ir-instructions.md#value-instructions) | [`negative-arithmetic-add-struct-no-overload.slang`](negative-arithmetic-add-struct-no-overload.slang) |
| Right-shift `>>` on a `uint64_t` lowers to the documented `shr` opcode with a `UInt64` result type — upper-edge of the integer-width axis for the shift sibling of the bit-op family. | expansion | [#value-instructions](../../../design/cross-cutting/ir-instructions.md#value-instructions) | [`bitwise-shr-uint64.slang`](bitwise-shr-uint64.slang) |
| Stress probe of the documented `IntLit` literal value (hoistable): six textual occurrences of `7` in source still resolve to the same `7 : Int` constant operand at every `add` use-site in the IR dump. | stress | [#value-instructions](../../../design/cross-cutting/ir-instructions.md#value-instructions) | [`value-int-lit-hoistable-stress.slang`](value-int-lit-hoistable-stress.slang) |
| `!=` on two `int16_t` operands lowers to the documented `cmpNE` opcode with a `Bool` result — 16-bit narrow-integer probe of the inequality comparison sibling. | expansion | [#value-instructions](../../../design/cross-cutting/ir-instructions.md#value-instructions) | [`comparison-cmpne-int16.slang`](comparison-cmpne-int16.slang) |
| `<=` on two `int8_t` operands lowers to the documented `cmpLE` opcode with a `Bool` result — narrow-integer probe of the inclusive-less-than comparison sibling. | expansion | [#value-instructions](../../../design/cross-cutting/ir-instructions.md#value-instructions) | [`comparison-cmple-int8.slang`](comparison-cmple-int8.slang) |
| `<` on two `uint64_t` operands lowers to the documented `cmpLT` opcode — 64-bit unsigned probe of the comparison family. | expansion | [#value-instructions](../../../design/cross-cutting/ir-instructions.md#value-instructions) | [`comparison-cmplt-uint64.slang`](comparison-cmplt-uint64.slang) |
| `==` on two `int8_t` operands lowers to the documented `cmpEQ` opcode — narrow-integer probe of the comparison family. | expansion | [#value-instructions](../../../design/cross-cutting/ir-instructions.md#value-instructions) | [`comparison-cmpeq-int8.slang`](comparison-cmpeq-int8.slang) |
| `>=` on two `int16_t` operands lowers to the documented `cmpGE` opcode — 16-bit narrow-integer probe of the comparison family. | expansion | [#value-instructions](../../../design/cross-cutting/ir-instructions.md#value-instructions) | [`comparison-cmpge-int16.slang`](comparison-cmpge-int16.slang) |
| `>` on two `uint64_t` operands lowers to the documented `cmpGT` opcode with a `Bool` result — 64-bit unsigned probe of the comparison family on its already-tested `cmpGT` member. | expansion | [#value-instructions](../../../design/cross-cutting/ir-instructions.md#value-instructions) | [`comparison-cmpgt-uint64.slang`](comparison-cmpgt-uint64.slang) |
| `float3(a, b, 1.0)` with `a : float`, `b : int` lowers to an explicit `castIntToFloat(%b)` followed by the documented `makeVector` aggregate-constructor opcode — pins mixed-precision vector composition. | expansion | [#value-instructions](../../../design/cross-cutting/ir-instructions.md#value-instructions) | [`makevec-float-from-int-and-float.slang`](makevec-float-from-int-and-float.slang) |


## Untested claims
| Claim | Reason | Anchor | Why untested |
| --- | --- | --- | --- |
| The contiguous opcode-range allocation that lets `as<IRBasicType>()` be a single integer comparison — entirely internal to FIDDLE-generated `slang-ir-insts-enum.h.fiddle`. | (unclassified) | (unspecified) | Reason and explanation to be refined by the next regeneration. |
| The module-version bump required when an opcode is inserted in the middle of an existing family range — a serialization invariant for `.slang-module` files. The user-facing consequences belong to `cross-cutting/serialization`. | (unclassified) | (unspecified) | Reason and explanation to be refined by the next regeneration. |
| The C++ wrapper-struct identity for each opcode (e.g. that `add` is an `IRAdd*` in C++) — internal API. | (unclassified) | [#add](../../../design/cross-cutting/ir-instructions.md#add) | Reason and explanation to be refined by the next regeneration. |
| Whether `Hoistable` instructions actually float to the outermost scope where their operands are available — observable only by inspecting the IR-dump position of an instruction relative to its defining scope, and the dump's textual order does not directly encode the scope tree. | (unclassified) | [#hoistable](../../../design/cross-cutting/ir-instructions.md#hoistable) | Reason and explanation to be refined by the next regeneration. |
| The flag-bit layout (`kIROpFlag_Parent`, `kIROpFlag_UseOther`, `kIROpFlag_Hoistable`, `kIROpFlag_Global`) — internal to the `IROpFlags` enum in `slang-ir.h`. Not surfaced in `-dump-ir` output. | (unclassified) | [#kiropflagparent](../../../design/cross-cutting/ir-instructions.md#kiropflagparent) | Reason and explanation to be refined by the next regeneration. |
| The opcode-bit packing (`kIROpMeta::kIROpMeta_OtherShift = 10`, high bits store auxiliary info for `UseOther` ops) — internal to `IRInst::m_op` layout. | (unclassified) | [#useother](../../../design/cross-cutting/ir-instructions.md#useother) | Reason and explanation to be refined by the next regeneration. |
| The `IRBuilder` emitter helper for each opcode — internal C++ API. | needs-unit-test | [#irbuilder](../../../design/cross-cutting/ir-instructions.md#irbuilder) | No slangc CLI surface reaches this. A C++ unit test in `tools/slang-unit-test/` could exercise the relevant compiler internals directly. |
| The IR builder's deduplication / hoisting decision for hoistable opcodes — the IR dump shows the post-hoist result, not the decision path. Two textually identical `vector(Int, 3)` types appearing once in the dump is observable; the *reason* (dedup) is not. | implementation-detail | (unspecified) | Internal compiler choice (pass ordering, hoistability decisions, deduplication) with no test-directive that reveals it. |
| The FIDDLE workflow for adding a new opcode — a developer guide ("Adding a new opcode" section in the source doc) rather than a user-observable behaviour. | process-doc | [#adding-a-new-opcode](../../../design/cross-cutting/ir-instructions.md#adding-a-new-opcode) | Contributor walkthrough / process documentation, not a compiler behavior. |


## Doc gaps observed
| Anchor | Kind | Gap | Suggested addition |
| --- | --- | --- | --- |
| [#representative-not-exhaustive](../../../design/cross-cutting/ir-instructions.md#representative-not-exhaustive) | undocumented-behavior | The doc's per-family tables are explicitly "representative, not exhaustive". Behaviors that the doc names but does not list a specific opcode for — e.g. the full set of comparison opcodes (`cmpEQ`/`cmpNE`/`cmpLE`/`cmpGE`), the full set of conversion ops (`floatCast`/`bitCast`/`uintCast`), the `matrix` type, the `Texture` type — are deferred to the family-specific bundles (`ir-reference/values`, `ir-reference/types`) where they belong. |  |
| [#alloca](../../../design/cross-cutting/ir-instructions.md#alloca) | ambiguous-claim | The doc cites `alloca` with operand `allocSize` but does not name a user-facing language surface that lowers to `alloca`. The Slang surface for dynamically-sized stack allocation is unclear from the doc alone; a one-line note on the source-level construct (`alloca` is currently used internally for some lowering paths) would let an agent anchor a test here. |  |
| [#other-control-flow-backend-hint-opcodes](../../../design/cross-cutting/ir-instructions.md#other-control-flow-backend-hint-opcodes) | undocumented-behavior | `RequirePrelude`, `RequireTargetExtension`, `Printf`, `StaticAssert` appear in the control-flow row but the doc does not state a user-observable consequence for each — only that they are "other control-flow / backend-hint opcodes". | A one-line "user surface" column would let the agent test these. |
| [#packs-a-value-plus-its-witness](../../../design/cross-cutting/ir-instructions.md#packs-a-value-plus-its-witness) | undocumented-behavior | The doc's `makeExistential` row lists "Packs a value plus its witness" but does not state the source-level construct that triggers it (assignment of a concrete type to an interface-typed variable). With the user surface stated, the test would be straightforward. |  |
| [#decorations](../../../design/cross-cutting/ir-instructions.md#decorations) | undocumented-behavior | The "Decorations" row says the family has "~180 decorations" but the doc itself names only four. Coverage of the long tail belongs in `ir-reference/decorations`. |  |
| [#block-or-function-parameter-replaces-ssa-phi](../../../design/cross-cutting/ir-instructions.md#block-or-function-parameter-replaces-ssa-phi) | undocumented-behavior | The doc says `param` is "Block or function parameter; replaces SSA `phi`." but does not give the surface-level construct that creates block params besides loop induction variables — e.g. that the back-edge of a `for` loop carries values via block parameters. The connection between source-level loops and IR `param`s is implicit. |  |
| [#add](../../../design/cross-cutting/ir-instructions.md#add) | undocumented-behavior | The arithmetic family is documented as `add`/`sub`/`mul`/`div` but the unary-negation member of the same family (`neg`) is not named, even though it is the natural 1-operand sibling of the binary operators. | Adding `neg` to the value-instructions row would let an agent anchor a boundary test for unary arithmetic directly. |
| [#intcast](../../../design/cross-cutting/ir-instructions.md#intcast) | drift-from-source | The doc's conversion-family entry names `intCast`, `floatCast`, and `bitCast` but does not enumerate the float-to-int and int-to-float numeric conversion opcodes (`castFloatToInt`, `castIntToFloat`) that the front end actually emits for `int(floatExpr)` and `float(intExpr)`. | A one-line note on the user surface for each conversion opcode would be a meaningful expansion. |
| [#swizzle](../../../design/cross-cutting/ir-instructions.md#swizzle) | undocumented-behavior | The doc's `swizzle` entry does not state the operand shape; the IR actually takes `(base, idx0, idx1, ...)` where the variadic-index arity equals the resulting vector length. | Stating this in the memory-instructions row would let agents pin down the lower- vs upper-edge of the swizzle-length axis. |
| [#globalconstant](../../../design/cross-cutting/ir-instructions.md#globalconstant) | undocumented-behavior | The doc cites `globalConstant` only in passing alongside `global_var` / `global_param` but does not name the surface-level construct (`static const`) that produces it. With the surface named, the `globalConstant` opcode could be tested directly. |  |
| [#no-overload](../../../design/cross-cutting/ir-instructions.md#no-overload) | undocumented-behavior | The doc does not document any error or warning text for invalid arithmetic / conversion operands; this restricts the bundle's negative tests to a small surface (struct-arithmetic, bit-cast size mismatch) that survives by general "no overload" / "type mismatch" diagnostics rather than by IR-instruction-specific rules. | Naming a few canonical diagnostic codes (e.g. for the bit-width-mismatch rule of `bitCast`) would let agents tie negative tests directly to documented behavior. |
| [#atomicoperation](../../../design/cross-cutting/ir-instructions.md#atomicoperation) | undocumented-behavior | The doc's `AtomicOperation` row names representative opcodes (`atomicLoad`, `atomicStore`, `atomicAdd`) but does not enumerate the admissible element-type axis. Empirically `Atomic<T>` requires `T : IAtomicable`, which is satisfied by `int32_t`/`uint32_t`/ `int64_t`/`uint64_t`/`half`/`float`/`double` (the doc admits `atomicAdd<half>` for example) but rejected for `int8_t`/`int16_t` /`uint8_t`/`uint16_t`. | A one-line note enumerating these element types — and the `IAtomicable` interface name — would let agents pin every member of the family at its admissible widths. |
| [#cmpeqcmpltcmpgt](../../../design/cross-cutting/ir-instructions.md#cmpeqcmpltcmpgt) | undocumented-behavior | The doc names the comparison family `cmpEQ/cmpLT/cmpGT/...` but does not state the promotion rule for mixed-precision operands. Empirically the front end emits an `intCast` on the narrower operand before the `cmp*` opcode. Calling this out — and naming the source-level rule that selects the unified width — would let an agent pin the conversion + comparison combination directly to a documented claim. |  |
| [#rwstructuredbufferstore](../../../design/cross-cutting/ir-instructions.md#rwstructuredbufferstore) | undocumented-behavior | The doc lists `rwstructuredBufferStore` and `structuredBufferLoad` but the read-back companion `rwstructuredBufferLoad` (emitted for `RWStructuredBuffer<T>.Load(idx)`) is not named. | A one-line entry in the resource family row would surface this opcode. |
| [#swizzle](../../../design/cross-cutting/ir-instructions.md#swizzle) | undocumented-behavior | The doc's `swizzle` entry does not state the result-type rule. Empirically the result type is `Vec(elemTy, indexCount)` when the index list has length > 1 and the bare scalar `elemTy` when the index list has length 1. | Naming this in the memory-instructions row would let agents pin the length-1 vs length-N boundary. |
