riscv-non-isa / rvv-intrinsic-doc

https://jira.riscv.org/browse/RVG-153
BSD 3-Clause "New" or "Revised" License
283 stars 89 forks source link

Clarify the definition of "tail/mask agnostic" for the intrinsic interface #236

Closed topperc closed 10 months ago

topperc commented 1 year ago

Tail/mask agnostic in the vector extension spec is defined as tail/mask undisturbed our or all ones. There's an additional special case for the tail of instructions that produce a mask.

Users are discouraged from relying on the value of the elements, but since it has a defined behavior they could rely on it. For example by preloading all ones using vlmax, and then using tail agnostic policy for some arithmetic, the tail elements would be guaranteed to be all ones no matter how hardware implements the tail agnostic policy.

Most of the unmasked "tail agnostic" intrinsics in the C API do not provide an operand for the tail elements. The user will have no control of what register is used for the destination and thus no control of the tail elements. They could be considered "tail undefined". Similar for masked intrinsics that are mask and tail agnostic.

There are some exceptions like fmadd/fmacc intrinsics that have a third source operand that must be allocated to the same register as the result. That operand could be used to also provide the tail elements. To implement "tail agnostic" as it is defined by the vector specification, the compiler would not be able to change vfmadd->vfmacc or vfmacc->vfmadd to avoid copies.

Clang is known to be treating "tail agnostic" as "tail undefined" in several places today. Some of these issues might get fixed, but that may limit optimization opportunities.

I propose that the intrinsic API treat "tail/mask agnostic" as "tail/mask undefined" and make no guarantees on the value of the tail or masked off elements.

CC: @eopXD @nick-knight @kito-cheng @reames

nick-knight commented 1 year ago

I've always supported this interpretation of agnosticism. In my proposal --- which eventually became the current (so-called) "policy intrinsics" --- I distinguished two behaviors (from C semantics perspective): "undisturbed" and "compiler-defined" (not "agnostic").

This is one of several corner-cases where the intrinsics API does not fully expose the ISA to the C programmer. I'm OK with it.

topperc commented 1 year ago

I see we do have this line in https://github.com/riscv-non-isa/rvv-intrinsic-doc/blob/5951cf64109e3c38b31efdf94341a0fd73afdf5a/rvv-intrinsic-rfc.md?plain=1#L434

Those it looks like the rest of that section wasn't updated for the current (so-called) "policy intrinsics".

eopXD commented 10 months ago

I believe we covered this with the note inside the specification now.

NOTE: When policy is set to "agnostic", there is no guarantee of what will be in the tail/masked-off elements. Under this policy, users should not assume the values within to be deterministic.