D108 - An operand the encoding does not carry is recorded, not omitted

Status: decided (2026-08-21) - the discrimination is measured now, not asserted

SlotKind::Implicit describes an operand that occupies no bits. The 32-bit comparison forms write the condition mask and nothing else, so vcc is printed by the reference and encoded nowhere.

Leaving it out of the layout was the alternative, and it would have made a decoded comparison not mention the register it writes - which is the operand that matters most about it. A report reading v_cmp_lt_f32 v0, v1 hides the whole effect.

The claim is evidenced rather than assumed. Two things look identical to a solver: an operand the encoding does not carry, and one the probes never varied. It emits implicit only when no field anywhere explains the operand and the text is identical in every sample. The 64-bit form of the same comparison does encode a destination, and does solve one.

The part of that which was prose, and now is not

The original entry justified the discrimination by saying the assembler refuses any other value in that position for these opcodes. That was never checked. It was an assertion of exactly the kind D128's width reconciliation made - and D128 turned out to be wrong, in the direction that sends someone to fix a probe that cannot be fixed.

So it is asked rather than asserted, by the same technique: substitute a different value into the operand, assemble, and compare the encoded words. Three outcomes, and the third is the one the prose did not allow for.

assembler says reading
refused nothing else is legal there. The operand is fixed.
accepted, words identical it carries no bits, because changing it changed no bit.
accepted, words differ there is a field, and the probes missed it.

The third case is why this is worth the round trip. Recording it as implicit would file an operand as un-encoded while the encoding carries it, and every decode of that opcode would print the sample's value in place of the real one - a wrong answer that looks like a right one, which is the failure this project's third principle exists to prevent. The solver now refuses to solve rather than guessing, which is the same response it already gives to every other unexplained operand.

Measured, and the strongest branch is the one that fired. For the four comparison opcodes that carry an implicit vcc:

v_cmp_lt_f32_e32 vcc,      v0, v1  ->  0x7c020300
v_cmp_lt_f32_e32 exec,     v0, v1  ->  refused
v_cmp_lt_f32_e32 s[0:1],   v0, v1  ->  refused
v_cmp_lt_f32_e32 s[10:11], v0, v1  ->  refused
v_cmp_lt_f32_e32 vcc_lo,   v0, v1  ->  0x7c020300   <- accepted, bit-identical

Not merely "nothing else is legal", which would leave open that the field exists and has one legal value. A different spelling was accepted and produced the same word, so the operand demonstrably occupies no bits. The four rows in opcode-operands.toml survive the check unchanged, which is the outcome that was expected - the point is that it is now an outcome rather than an expectation.

It also settles the two-spellings note below from the other direction: the assembler accepts both vcc and vcc_lo for the same un-encoded operand, so the disagreement really is about naming and not about which register is meant.

The same register arrives under two spellings. A source field holding code 106 decodes through the operand table, which names codes as 32-bit registers, so it reads vcc_lo. The implicit destination carries the text the reference printed, which is vcc. Neither is wrong and neither carries the width - the width comes from the opcode - so model::lane_mask_name normalises at the point of use rather than either table being rewritten to agree with the other.